QT += maemo5 xml
TARGET = jspeed
TEMPLATE = app
+CONFIG += mobility
+MOBILITY += multimedia
SOURCES += src/main.cpp \
src/mainwindow.cpp \
src/mainwindowstack.cpp \
src/effect.cpp \
src/blureffect.cpp \
src/opacityeffect.cpp \
- src/dropshadoweffect.cpp
+ src/dropshadoweffect.cpp \
+ src/poialerts.cpp \
+ src/poireader.cpp \
+ src/poiascreader.cpp \
+ src/poisettings.cpp \
+ src/speedalarmsettings.cpp \
+ src/speedalarm.cpp \
+ src/fileselector.cpp \
+ src/themescheduler.cpp \
+ src/themeschedulersettings.cpp \
+ src/themepicker.cpp \
+ src/mediaplayer.cpp \
+ src/soundselector.cpp \
+ src/buttonbox.cpp
HEADERS += src/mainwindow.h \
src/mainwindowstack.h \
src/location.h \
src/effect.h \
src/blureffect.h \
src/opacityeffect.h \
- src/dropshadoweffect.h
+ src/dropshadoweffect.h \
+ src/poialerts.h \
+ src/poireader.h \
+ src/poiascreader.h \
+ src/poisettings.h \
+ src/speedalarmsettings.h \
+ src/speedalarm.h \
+ src/fileselector.h \
+ src/themescheduler.h \
+ src/themeschedulersettings.h \
+ src/themepicker.h \
+ src/mediaplayer.h \
+ src/soundselector.h \
+ src/buttonbox.h
RESOURCES = src/resources.qrc
CONFIG += link_pkgconfig
PKGCONFIG += liblocation libzip
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtGui/QPushButton>
+#include "buttonbox.h"
+
+ButtonBox::ButtonBox(QWidget* parent): QDialogButtonBox(parent)
+{
+ setCenterButtons(false);
+ setOrientation(Qt::Vertical);
+}
+
+QPushButton* ButtonBox::addButton(QString const& text,
+ const QObject* receiver,
+ const char* member,
+ QDialogButtonBox::ButtonRole role)
+{
+ QPushButton* button = new QPushButton(text);
+ connect(button, SLOT(clicked(bool)), receiver, member);
+ QDialogButtonBox::addButton(button, role);
+ return button;
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef BUTTONBOX_H
+#define BUTTONBOX_H
+
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPushButton>
+#include <QtCore/QString>
+
+class ButtonBox : public QDialogButtonBox
+{
+ Q_OBJECT
+
+public:
+ ButtonBox(QWidget* parent = 0);
+ QPushButton* addButton(QString const& text,
+ const QObject* receiver,
+ const char* member,
+ QDialogButtonBox::ButtonRole role = QDialogButtonBox::AcceptRole);
+};
+
+#endif
return model_->removeRow(index);
}
+int ButtonSelector::size() const
+{
+ return model_->rowCount();
+}
+
void ButtonSelector::onSelected(QString const& text)
{
emit selected(currentIndex(), text, value());
int indexOfValue(QVariant const& value) const;
bool selectByValue(QVariant const& value);
int currentIndex() const;
+ int size() const;
bool changeItem(unsigned int index, QString const& text);
bool changeItem(unsigned int index, QString const& text, QVariant const& value);
bool removeItem(unsigned int index);
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtGui/QFileDialog>
+#include <QtGui/QMessageBox>
+#include <QtCore/QString>
+#include <QtCore/QDir>
+#include <QtCore/QStringList>
+#include "fileselector.h"
+
+FileSelector::FileSelector(QString const& text, QWidget* parent): ButtonSelector(text, parent)
+{
+}
+
+bool FileSelector::loadFiles(QString const& dir, QString const& pattern)
+{
+ QDir directory(dir);
+
+ if(directory.exists() && directory.isReadable())
+ {
+ QStringList filters;
+ filters << pattern;
+ directory.setNameFilters(filters);
+ directory.setFilter(QDir::Files);
+ QStringList files = directory.entryList();
+
+ for(int i = 0; i < files.size(); i++)
+ {
+ addItem(files.at(i));
+ }
+
+ return true;
+ }
+
+ return false;
+}
+
+bool FileSelector::importFile(QString const& dir,
+ QString const& name,
+ QString const& pattern,
+ bool add,
+ QString* addedFile)
+{
+ QString filename = QFileDialog::getOpenFileName(this, tr("Open file"),
+ QDir::home().path(),
+ name + "(" + pattern + ")");
+
+ if(filename.isEmpty())
+ {
+ return true;
+ }
+
+ QString basename;
+
+ int i = filename.lastIndexOf(QDir::separator());
+
+ if(i == -1)
+ {
+ basename = filename;
+ }
+ else
+ {
+ basename = filename.mid(i + 1);
+ }
+
+ QString targetFile = dir + basename;
+
+ QDir targetDir(dir);
+
+ if(!targetDir.exists())
+ {
+ if(!targetDir.mkpath(dir))
+ {
+ return false;
+ }
+ }
+
+ bool ok = true;
+
+ if(QFile::exists(targetFile))
+ {
+ ok = confirmCopy(basename);
+
+ if(ok)
+ {
+ QFile::remove(targetFile);
+ }
+ }
+
+ if(ok)
+ {
+ if(!QFile::copy(filename, targetFile))
+ {
+ return false;
+ }
+
+ if(addedFile)
+ {
+ *addedFile = basename;
+ }
+
+ if(add)
+ {
+ addItem(basename);
+ selectByValue(basename);
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool FileSelector::confirmCopy(QString const& filename)
+{
+ QMessageBox::StandardButton result = QMessageBox::question(this, tr("File exists"),
+ tr("File %1 already exists in directory, overwrite?").arg(filename),
+ QMessageBox::Yes | QMessageBox::No);
+
+ return (result == QMessageBox::Yes);
+}
+
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef FILESELECTOR_H
+#define FILESELECTOR_H
+
+#include "buttonselector.h"
+
+class QString;
+
+class FileSelector : public ButtonSelector
+{
+ Q_OBJECT
+
+public:
+ FileSelector(QString const& text, QWidget* parent = 0);
+ bool loadFiles(QString const& dir, QString const& pattern);
+ bool importFile(QString const& dir, QString const& name,
+ QString const& pattern, bool add = true,
+ QString* addedFile = 0);
+
+private:
+ bool confirmCopy(QString const& filename);
+
+};
+
+#endif
public:
GraphicsScene(QRectF const& rect);
- static int const CLICK_MARGIN = 45;
+ static int const CLICK_MARGIN = 48;
signals:
void clicked();
#include <QtGui/QApplication>
#include "mainwindow.h"
+#include "poiascreader.h"
+#include <QtCore/QDebug>
+#include "poialerts.h"
+
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
+ /* PoiAscReader reader("/home/maemo/workspace/jspeed/test.asc");
+
+ QList<PoiAscReader::Poi> pois;
+
+ if(reader.read(pois))
+ {
+ qDebug() << "Kyl";
+
+ for(int i = 0; i < pois.size(); i++)
+ {
+ qDebug() << pois.at(i).latitude << pois.at(i).longitude << pois.at(i).name;
+ }
+ }
+ else
+ {
+ qDebug() << "Ei";
+ }*/
+
+ //PoiAlerts::instance().startTest();
+
MainWindow window;
QObject::connect(&window, SIGNAL(quit()), &app, SLOT(quit()));
#include "mainmenu.h"
#include "themeselector.h"
#include "unitselector.h"
+#include "poisettings.h"
+#include "speedalarmsettings.h"
MainMenu::MainMenu(QWidget* parent): QDialog(parent), itemCount_(0),
-currentRow_(0), themeSelector_(0), unitSelector_(0), aboutDialog_(0)
+currentRow_(0), themeSelector_(0), unitSelector_(0), poiSettings_(0),
+speedAlarmSettings_(0), aboutDialog_(0)
{
layout_ = new QVBoxLayout;
setLayout(layout_);
setWindowTitle(tr("Menu"));
addAction(tr("Reset trip"), this, SIGNAL(resetTrip()));
addAction(tr("Reset all"), this, SLOT(confirmReset()));
- addAction(tr("Select theme"), this, SLOT(selectTheme()));
+ addAction(tr("Theme"), this, SLOT(selectTheme()));
addAction(tr("Set unit"), this, SLOT(selectUnit()));
+ addAction(tr("Speed camera alerts"), this, SLOT(openPoiAlerts()));
+ addAction(tr("Speed alarm"), this, SLOT(openSpeedAlarm()));
addAction(tr("Flip screen"), this, SIGNAL(flip()));
addAction(tr("About"), this, SLOT(showAbout()));
}
themeSelector_->show();
}
+void MainMenu::openPoiAlerts()
+{
+ if(!poiSettings_)
+ {
+ poiSettings_ = new PoiSettings(this);
+ }
+
+ poiSettings_->show();
+}
+
+void MainMenu::openSpeedAlarm()
+{
+ if(!speedAlarmSettings_)
+ {
+ speedAlarmSettings_ = new SpeedAlarmSettings(this);
+ }
+
+ speedAlarmSettings_->show();
+}
+
void MainMenu::selectUnit()
{
if(!unitSelector_)
class QHBoxLayout;
class ThemeSelector;
class UnitSelector;
+class PoiSettings;
+class SpeedAlarmSettings;
class MainMenu : public QDialog
{
void selectUnit();
void showAbout();
void confirmReset();
+ void openPoiAlerts();
+ void openSpeedAlarm();
private:
QVBoxLayout* layout_;
QHBoxLayout* currentRow_;
ThemeSelector* themeSelector_;
UnitSelector* unitSelector_;
+ PoiSettings* poiSettings_;
+ SpeedAlarmSettings* speedAlarmSettings_;
QDialog* aboutDialog_;
};
#include "mainmenu.h"
#include "odometer.h"
#include "widgetscreen.h"
+#include "poialerts.h"
+#include "speedalarm.h"
MainWindow::MainWindow(): QMainWindow(0), menu_(0), themeLoader_(0), mainScreen_(0)
{
setWindowTitle(tr("jSpeed"));
showFullScreen();
Odometer::instance().start();
+ PoiAlerts::instance().start();
+ SpeedAlarm::instance().start();
addScreens();
startBacklight();
}
connect(menu_, SIGNAL(flip()), stack_, SLOT(flip()));
connect(menu_, SIGNAL(themeChanged()), this, SLOT(loadTheme()));
connect(menu_, SIGNAL(unitChanged()), &(Odometer::instance()), SLOT(updateUnit()));
+ connect(menu_, SIGNAL(poiSettingsChanged()), &(PoiAlerts::instance()), SLOT(loadConfig()));
+ connect(menu_, SIGNAL(speedAlarmSettingsChanged()), &(SpeedAlarm::instance()), SLOT(loadConfig()));
}
menu_->show();
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QUrl>
+#include <QtCore/QDir>
+#include <QMediaContent>
+#include "mediaplayer.h"
+#include "settings.h"
+
+namespace
+{
+ QString const FORMATS[MediaPlayer::FORMAT_COUNT] = {"mp3", "aac", "wav"};
+ QString const LOCAL_SOUND_DIR = ":/resources/sounds/";
+}
+
+QMediaPlayer MediaPlayer::player_;
+
+bool MediaPlayer::play(QString const& file)
+{
+ QMediaContent media(QUrl::fromLocalFile(file));
+
+ if(media.isNull())
+ {
+ return false;
+ }
+
+ player_.setMedia(media);
+ player_.play();
+ return true;
+}
+
+void MediaPlayer::getSupportedFormats(QList<QString>& formats)
+{
+ formats.clear();
+
+ for(int i = 0; i < FORMAT_COUNT; i++)
+ {
+ formats.push_back(FORMATS[i]);
+ }
+}
+
+QString MediaPlayer::getFormatPattern()
+{
+ QString result = "";
+
+ for(int i = 0; i < FORMAT_COUNT; i++)
+ {
+ result += "*." + FORMATS[i] + " ";
+ }
+
+ return result.trimmed();
+}
+
+QString MediaPlayer::getSoundDir()
+{
+ return Settings::getDir() + "sounds" + QDir::separator();
+}
+
+QString const& MediaPlayer::getLocalSoundDir()
+{
+ return LOCAL_SOUND_DIR;
+}
+
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef MEDIAPLAYER_H
+#define MEDIAPLAYER_H
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+#include <QMediaPlayer>
+
+class MediaPlayer
+{
+public:
+ enum Format {MP3, WAV, AAC, FORMAT_COUNT};
+ static bool play(QString const& file);
+ static void getSupportedFormats(QList<QString>& formats);
+ static QString getFormatPattern();
+ static QString getSoundDir();
+ static QString const& getLocalSoundDir();
+
+private:
+ static QMediaPlayer player_;
+};
+
+#endif
}
}
+double Odometer::getUnitMultiplier()
+{
+ return Location::getUnitMultiplier();
+}
+
void Odometer::updateUnit()
{
QString unit = Settings::instance().value("unit", "km").toString();
double getSignalStrength() const;
static QString const& getUnit();
static QString const& getSpeedUnit();
+ static double getUnitMultiplier();
signals:
void dataUpdated();
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QDir>
+#include <QtCore/QTimer>
+#include <QtCore/QFile>
+#include <QtCore/QDebug>
+#include <math.h>
+#include "poialerts.h"
+#include "odometer.h"
+#include "settings.h"
+#include "location.h"
+#include "mediaplayer.h"
+
+namespace
+{
+ static double const EARTH_MEAN_RADIUS = 6371.0072;
+ static double const PI = 3.14159265;
+}
+
+inline static double degToRad(double deg)
+{
+ return deg * PI / 180;
+}
+
+inline static double radToDeg(double rad)
+{
+ return rad * 180 / PI;
+}
+
+PoiAlerts::PoiAlerts(): QObject(0), enabled_(false), currentPoi_(0), loaded_(false)
+{
+}
+
+PoiAlerts::~PoiAlerts()
+{
+ end();
+}
+
+PoiAlerts& PoiAlerts::instance()
+{
+ static PoiAlerts instance;
+ return instance;
+}
+
+bool PoiAlerts::start()
+{
+ if(!loaded_)
+ {
+ if(!loadConfig())
+ {
+ return false;
+ }
+ }
+
+ if(enabled_)
+ {
+ connect(&(Odometer::instance()), SIGNAL(dataUpdated()), this, SLOT(onDataUpdated()));
+ }
+
+ return true;
+}
+
+void PoiAlerts::end()
+{
+ if(enabled_)
+ {
+ disconnect(&(Odometer::instance()), SIGNAL(dataUpdated()), this, SLOT(onDataUpdated()));
+ }
+
+ pois_.clear();
+ playedSounds_.clear();
+ travelled_ = 0;
+ enabled_ = false;
+ currentPoi_ = 0;
+}
+
+bool PoiAlerts::loadConfig()
+{
+ loaded_ = true;
+
+ bool enabled = Settings::instance().value("alert_enabled", false).toBool();
+
+ if(!enabled)
+ {
+ end();
+ enabled_ = false;
+ return true;
+ }
+
+ distance_ = Settings::instance().value("alert_distance", 300).toBool();
+ onlyOnRoute_ = Settings::instance().value("alert_only_on_route", true).toBool();
+
+ if(distance_ < 0)
+ {
+ distance_ = 0;
+ }
+
+ QString filename = Settings::instance().value("alert_sound", "").toString();
+
+ if(filename.isEmpty())
+ {
+ filename = "alert.wav";
+ }
+
+ QString soundDir = MediaPlayer::getSoundDir();
+ QString localDir = MediaPlayer::getLocalSoundDir();
+
+ if(!filename.isEmpty() && QFile::exists(soundDir + filename))
+ {
+ file_ = soundDir + filename;
+ }
+ else if(!filename.isEmpty() && QFile::exists(localDir + filename))
+ {
+ file_ = localDir + filename;
+ }
+ else
+ {
+ enabled_ = false;
+ return false;
+ }
+
+ if(!loadPois())
+ {
+ enabled_ = false;
+ return false;
+ }
+
+ if(!enabled_)
+ {
+ enabled_ = true;
+ start();
+ }
+
+ return true;
+}
+
+bool PoiAlerts::loadPois()
+{
+ QString filename = Settings::instance().value("alert_poi_file", "").toString();
+
+ QString poiFile = getPoiDir() + filename;
+
+ if(filename.isEmpty() || !QFile::exists(poiFile))
+ {
+ error_ = "Poi file doesn't exist";
+ return false;
+ }
+
+ PoiReader* reader = PoiReader::getReader(poiFile);
+
+ if(!reader)
+ {
+ error_ = "Unknown file format: " + poiFile;
+ return false;
+ }
+
+ if(!reader->read(pois_))
+ {
+ error_ = reader->error();
+ return false;
+ }
+
+ return true;
+}
+
+double PoiAlerts::getCurrentDistance() const
+{
+ if(!currentPoi_)
+ {
+ return 0.0;
+ }
+
+ return currentDistance_;
+}
+
+QString PoiAlerts::getCurrentPoi() const
+{
+ if(currentPoi_)
+ {
+ return currentPoi_->name;
+ }
+
+ return "";
+}
+
+bool PoiAlerts::poiInView() const
+{
+ return currentPoi_ != 0;
+}
+
+QString const& PoiAlerts::error() const
+{
+ return error_;
+}
+
+void PoiAlerts::onDataUpdated()
+{
+ qDebug() << "Data update";
+
+ static int i = 0;
+ i++;
+
+ double travelled = Odometer::instance().getTotal();
+ const Location::Fix* fix = &(Odometer::instance().getLatestFix());
+
+ if(fix->latitude < 0.01 || fix->longitude < 0.01 || fix->kmSpeed < 0.01)
+ {
+ return;
+ }
+ else
+ {
+ /*if(i < 5)
+ {
+ pois_[0].latitude = fix->latitude;
+ pois_[0].longitude = fix->longitude;
+ }*/
+ }
+
+ double distance;
+ double inRouteMargin = IN_ROUTE_MARGIN + (fix->eph / 1000.0);
+
+ qDebug() << "Eph: " << fix->eph;
+ qDebug() << "In route margin: " << inRouteMargin;
+
+ if(1 == 1 || abs(travelled - travelled_) > 0.03)
+ {
+ travelled_ = travelled;
+
+ for(int i = 0; i < pois_.size(); i++)
+ {
+ if((distance = calculateDistance(pois_.at(i).latitude, pois_.at(i).longitude,
+ fix->latitude, fix->longitude)) <= distance_)
+ {
+ qDebug() << "Distance: " << distance;
+
+ if(onlyOnRoute_)
+ {
+ double track = abs(calculateTrack(fix->latitude, fix->longitude,
+ pois_.at(i).latitude, pois_.at(i).longitude) - fix->track);
+
+ if(track > 180)
+ {
+ track = 360.0 - track;
+ }
+
+ qDebug() << "Real track: " << track;
+ qDebug() << "Epd: " << fix->epd;
+
+ double trackLimit;
+
+ if(distance < (inRouteMargin * 2.0))
+ {
+ trackLimit = 60.0;
+ }
+ else
+ {
+ trackLimit = 90.0 - radToDeg(acos((inRouteMargin + (distance * 0.15)) / distance));
+ }
+
+ qDebug() << "Tracklimit: " << trackLimit;
+
+ if(track < trackLimit)
+ {
+ currentPoi_ = &pois_[i];
+ currentDistance_ = distance;
+ playSound(i);
+ }
+ else
+ {
+ currentPoi_ = 0;
+ }
+
+ }
+ else
+ {
+ currentPoi_ = &pois_[i];
+ currentDistance_ = distance;
+ playSound(i);
+ }
+
+ break;
+ }
+ else
+ {
+ currentPoi_ = 0;
+ qDebug() << "Distance: " << distance;
+ }
+ }
+ }
+
+ qDebug() << '\n';
+}
+
+void PoiAlerts::startTest()
+{
+ Odometer::instance().start();
+ enabled_ = true;
+ distance_ = 100;
+ PoiReader::Poi poi;
+ poi.latitude = 0.0;
+ poi.longitude = 0.0;
+ poi.name = "Mokki";
+ pois_.push_back(poi);
+ onlyOnRoute_ = true;
+ start();
+}
+
+double PoiAlerts::calculateDistance(double latitude1, double longitude1,
+ double latitude2, double longitude2)
+{
+ double dlat = degToRad(latitude1 - latitude2);
+ double dlon = degToRad(longitude1 - longitude2);
+ double y = sin(dlat / 2.0) * sin(dlat / 2.0)
+ + cos(degToRad(latitude2))
+ * cos(degToRad(latitude1))
+ * sin(dlon / 2.0) * sin(dlon / 2.0);
+ double x = 2 * atan2(sqrt(y), sqrt(1 - y));
+ return x * EARTH_MEAN_RADIUS * 1000;
+}
+
+double PoiAlerts::calculateTrack(double latitude1, double longitude1,
+ double latitude2, double longitude2)
+{
+ double dlon = degToRad(longitude2 - longitude1);
+ double lat1Rad = degToRad(latitude1);
+ double lat2Rad = degToRad(latitude2);
+ double y = sin(dlon) * cos(lat2Rad);
+ double x = cos(lat1Rad) * sin(lat2Rad) - sin(lat1Rad) * cos(lat2Rad) * cos(dlon);
+ double whole;
+ double fraction = modf(radToDeg(atan2(y, x)), &whole);
+ return (int(whole + 360) % 360) + fraction;
+}
+
+void PoiAlerts::playSound(int poiIndex)
+{
+ qDebug() << "Almost play sound";
+
+ if(playedSounds_.indexOf(poiIndex) == -1)
+ {
+ playedSounds_.enqueue(poiIndex);
+
+ qDebug() << "Play sound";
+ MediaPlayer::play(file_);
+
+ QTimer::singleShot(POI_ALERT_INTERVAL * 1000, this, SLOT(removePlayed()));
+ }
+
+}
+
+void PoiAlerts::removePlayed()
+{
+ if(!playedSounds_.isEmpty())
+ {
+ int removed = playedSounds_.dequeue();
+ qDebug() << "Removed: " << removed;
+ }
+}
+
+QString PoiAlerts::getPoiDir()
+{
+ return Settings::getDir() + "pois" + QDir::separator();
+}
+
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef POIALERTS_H
+#define POIALERTS_H
+
+#include <QtCore/QList>
+#include <QtCore/QSet>
+#include <QtCore/QQueue>
+#include "poireader.h"
+
+class QString;
+
+class PoiAlerts : public QObject
+{
+ Q_OBJECT
+
+public:
+ static int const POI_ALERT_INTERVAL = 120;
+ static int const IN_ROUTE_MARGIN = 20;
+ static PoiAlerts& instance();
+ static QString getPoiDir();
+ ~PoiAlerts();
+ bool start();
+ void end();
+ void startTest();
+ double getCurrentDistance() const;
+ QString getCurrentPoi() const;
+ bool poiInView() const;
+ QString const& error() const;
+
+public slots:
+ bool loadConfig();
+
+private slots:
+ void onDataUpdated();
+ void removePlayed();
+
+private:
+ PoiAlerts();
+ bool loadPois();
+ void playSound(int poiIndex);
+ static double calculateDistance(double latitude1, double longitude1,
+ double latitude2, double longitude2);
+ static double calculateTrack(double latitude1, double longitude1,
+ double latitude2, double longitude2);
+ QString file_;
+ bool onlyOnRoute_;
+ QList<PoiReader::Poi> pois_;
+ QQueue<int> playedSounds_;
+ bool enabled_;
+ int distance_;
+ double travelled_;
+ PoiReader::Poi* currentPoi_;
+ double currentDistance_;
+ bool loaded_;
+ QString error_;
+
+};
+
+#endif
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QFile>
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
+#include <QtCore/QDebug>
+#include <QtCore/QRegExp>
+#include "poiascreader.h"
+
+PoiAscReader::PoiAscReader(QString filename): PoiReader(), filename_(filename)
+{
+}
+
+bool PoiAscReader::read(QList<Poi>& pois)
+{
+ QFile file(filename_);
+
+ if(!file.open(QIODevice::ReadOnly))
+ {
+ setError("Unable to open file (check permissions)");
+ return false;
+ }
+
+ QString data = QString(file.readAll());
+ static QRegExp matcher("([0-9]{1,3})\\.([0-9]+), ([0-9]{1,3})\\.([0-9]+), \"(.*)\"");
+ matcher.setMinimal(true);
+
+ int pos = 0;
+
+ while((pos = matcher.indexIn(data, pos)) != -1)
+ {
+ pos += matcher.matchedLength();
+
+ Poi poi;
+
+ bool ok;
+
+ QString latitude = matcher.cap(1) + "." + matcher.cap(2);
+ QString longitude = matcher.cap(3) + "." + matcher.cap(4);
+
+ double doubleLatitude = latitude.toDouble(&ok);
+
+ if(!ok)
+ {
+ continue;
+ }
+
+ double doubleLongitude = longitude.toDouble(&ok);
+
+ if(!ok)
+ {
+ continue;
+ }
+
+ poi.latitude = doubleLatitude;
+ poi.longitude = doubleLongitude;
+ poi.name = matcher.cap(5);
+
+ pois.push_back(poi);
+
+ }
+
+ if(pois.size() == 0)
+ {
+ setError("No valid poi data found from file");
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef POIASCREADER_H
+#define POIASCREADER_H
+
+#include "poireader.h"
+
+class PoiAscReader : public PoiReader
+{
+public:
+ PoiAscReader(QString filename);
+ virtual bool read(QList<Poi>& pois);
+
+private:
+ QString filename_;
+};
+
+#endif
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "poireader.h"
+#include "poiascreader.h"
+
+namespace
+{
+ QString const READER_FILETYPES[PoiReader::READER_COUNT] = {"asc"};
+}
+
+PoiReader::PoiReader()
+{
+}
+
+PoiReader* PoiReader::getReader(QString const& filename)
+{
+ QString lower = filename.toLower();
+ QString type;
+ Reader reader = READER_COUNT;
+
+ for(int i = 0; i < READER_COUNT; i++)
+ {
+ if(lower.right(READER_FILETYPES[i].size()) == READER_FILETYPES[i])
+ {
+ reader = static_cast<Reader>(i);
+ break;
+ }
+ }
+
+ switch(reader)
+ {
+ case ASCREADER:
+ return new PoiAscReader(filename);
+ break;
+ default:
+ return 0;
+ }
+}
+
+void PoiReader::setError(QString const& error)
+{
+ error_ = error;
+}
+
+QString const& PoiReader::error()
+{
+ return error_;
+}
+
+QString PoiReader::getFormatPattern()
+{
+ QString data = "";
+
+ for(int i = 0; i < READER_COUNT; i++)
+ {
+ data += "*." + READER_FILETYPES[i] + " ";
+ }
+
+ return data.trimmed();
+}
+
+void PoiReader::getSupportedFormats(QList<QString>& formats)
+{
+ formats.clear();
+
+ for(int i = 0; i < READER_COUNT; i++)
+ {
+ formats.push_back(READER_FILETYPES[i]);
+ }
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef POIREADER_H
+#define POIREADER_H
+
+#include <QtCore/QString>
+#include <QtCore/QList>
+
+class PoiReader
+{
+public:
+
+ struct Poi
+ {
+ double latitude;
+ double longitude;
+ QString name;
+ };
+
+ enum Reader {ASCREADER, READER_COUNT};
+
+ static PoiReader* getReader(QString const& filename);
+ PoiReader();
+ virtual bool read(QList<Poi>& pois) = 0;
+ QString const& error();
+ static QString getFormatPattern();
+ static void getSupportedFormats(QList<QString>& formats);
+
+protected:
+ void setError(QString const& error);
+
+private:
+ QString error_;
+
+};
+
+#endif
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtGui/QFileDialog>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QLabel>
+#include <QtGui/QCheckBox>
+#include <QtGui/QLineEdit>
+#include <QtGui/QIntValidator>
+#include <QMaemo5InformationBox>
+#include "poisettings.h"
+#include "fileselector.h"
+#include "poialerts.h"
+#include "settings.h"
+#include "mediaplayer.h"
+#include "poireader.h"
+#include "buttonbox.h"
+#include "soundselector.h"
+
+
+PoiSettings::PoiSettings(QWidget* parent): QDialog(parent)
+{
+ setWindowTitle(tr("Speed camera alerts"));
+ enabled_ = new QCheckBox(tr("Enabled"));
+ enabled_->setChecked(Settings::instance().value("alert_enabled", false).toBool());
+
+ QHBoxLayout* poiLayout = new QHBoxLayout;
+ poiFileSelector_ = new FileSelector(tr("Poi file (.asc)"));
+ QPushButton* importButton = new QPushButton(tr("Import"));
+ connect(importButton, SIGNAL(clicked(bool)), this, SLOT(importFile()));
+ poiLayout->addWidget(poiFileSelector_, Qt::AlignLeft);
+ poiLayout->addWidget(importButton);
+
+ soundSelector_ = new SoundSelector;
+
+ QLabel* distanceLabel = new QLabel(tr("Alert distance"));
+ distance_ = new QLineEdit;
+ distance_->setText(QString::number(Settings::instance().value("alert_distance", 300).toInt()));
+ distance_->setValidator(new QIntValidator(0, 5000, this));
+ QHBoxLayout* distance = new QHBoxLayout;
+ distance->addWidget(distanceLabel);
+ distance->addWidget(distance_);
+ onlyOnRoute_ = new QCheckBox(tr("Alert only if poi is in route"));
+ onlyOnRoute_->setChecked(Settings::instance().value("alert_only_on_route", true).toBool());
+
+ ButtonBox* buttons = new ButtonBox;
+ buttons->addButton(tr("Save"), this, SLOT(saveSettings()), QDialogButtonBox::AcceptRole);
+
+ QHBoxLayout* layout = new QHBoxLayout;
+ QVBoxLayout* left = new QVBoxLayout;
+
+ left->addWidget(enabled_);
+ left->addLayout(poiLayout);
+ left->addWidget(soundSelector_);
+ left->addLayout(distance);
+ left->addWidget(onlyOnRoute_);
+
+ layout->addLayout(left, Qt::AlignLeft);
+ layout->addWidget(buttons);
+
+ setLayout(layout);
+}
+
+
+void PoiSettings::importFile()
+{
+ if(!poiFileSelector_->importFile(PoiAlerts::getPoiDir(),
+ "Poi files",
+ PoiReader::getFormatPattern(),
+ true))
+ {
+ qDebug() << "Unable to import";
+ }
+}
+
+void PoiSettings::loadFiles()
+{
+ QDir poiDir(PoiAlerts::getPoiDir());
+
+ QString selectedSound = Settings::instance().value("alert_sound", "").toString();
+ soundSelector_->setValue(selectedSound);
+
+ poiFileSelector_->clear();
+ QString selectedPoi = Settings::instance().value("alert_poi_file", "").toString();
+ poiFileSelector_->loadFiles(PoiAlerts::getPoiDir(), PoiReader::getFormatPattern());
+ poiFileSelector_->selectByValue(selectedPoi);
+
+}
+
+void PoiSettings::setVisible(bool visible)
+{
+ if(visible)
+ {
+ loadFiles();
+ }
+
+ QDialog::setVisible(visible);
+}
+
+void PoiSettings::saveSettings()
+{
+ if(poiFileSelector_->currentIndex() < 0 && enabled_->isChecked())
+ {
+ QMaemo5InformationBox::information(this, tr("No poi file selected"));
+ return;
+ }
+
+ Settings::instance().setValue("alert_enabled", enabled_->isChecked());
+ Settings::instance().setValue("alert_only_on_route", onlyOnRoute_->isChecked());
+ Settings::instance().setValue("alert_distance", distance_->text().toInt());
+ Settings::instance().setValue("alert_sound", soundSelector_->value());
+ Settings::instance().setValue("alert_poi_file", poiFileSelector_->value());
+
+ hide();
+
+ if(!PoiAlerts::instance().loadConfig())
+ {
+ QMaemo5InformationBox::information(0, tr("Unable to load poi file: %1.").arg(PoiAlerts::instance().error()),
+ QMaemo5InformationBox::NoTimeout);
+ }
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef POISETTINGS_H
+#define POISETTINGS_H
+
+#include <QtGui/QDialog>
+
+class QLineEdit;
+class QCheckBox;
+class SoundSelector;
+class FileSelector;
+
+class PoiSettings : public QDialog
+{
+ Q_OBJECT
+
+public:
+ PoiSettings(QWidget* parent = 0);
+
+signals:
+ void saved();
+
+protected:
+ virtual void setVisible(bool visible);
+
+private slots:
+ void saveSettings();
+ void importFile();
+
+private:
+ void loadFiles();
+ void loadSounds(QString const& dir, QString const& selected);
+ QCheckBox* enabled_;
+ FileSelector* poiFileSelector_;
+ SoundSelector* soundSelector_;
+ QLineEdit* distance_;
+ QCheckBox* onlyOnRoute_;
+
+};
+
+#endif
<file>resources/signal_2.png</file>
<file>resources/signal_3.png</file>
<file>resources/signal_4.png</file>
+ <file>resources/sounds/beep.wav</file>
<file>resources/themes/default/theme.xml</file>
<file>resources/themes/default/digital7.ttf</file>
<file>resources/themes/default/background.png</file>
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QFile>
+#include <QtGui/QHBoxLayout>
+#include "soundselector.h"
+#include "fileselector.h"
+#include "mediaplayer.h"
+
+SoundSelector::SoundSelector(QWidget* parent): QWidget(parent)
+{
+ selector_ = new FileSelector(tr("Sound"));
+ QPushButton* playButton = new QPushButton(tr("Play"));
+ connect(playButton, SIGNAL(clicked(bool)), this, SLOT(playSound()));
+ QHBoxLayout* layout = new QHBoxLayout;
+ layout->addWidget(selector_, Qt::AlignLeft);
+ layout->addWidget(playButton);
+ setLayout(layout);
+}
+
+void SoundSelector::playSound()
+{
+ QString sound = selector_->value().toString();
+
+ if(sound.isEmpty())
+ {
+ return;
+ }
+
+ QString soundDir = MediaPlayer::getSoundDir();
+ QString localDir = MediaPlayer::getLocalSoundDir();
+
+ if(QFile::exists(soundDir + sound))
+ {
+ MediaPlayer::play(soundDir + sound);
+ }
+ else if(QFile::exists(localDir + sound))
+ {
+ MediaPlayer::play(localDir + sound);
+ }
+}
+
+void SoundSelector::setVisible(bool visible)
+{
+ if(visible)
+ {
+ QString currentValue = selector_->value().toString();
+ selector_->clear();
+ QString pattern = MediaPlayer::getFormatPattern();
+ selector_->loadFiles(MediaPlayer::getLocalSoundDir(), pattern);
+ selector_->loadFiles(MediaPlayer::getSoundDir(), pattern);
+ setValue(currentValue);
+ }
+
+ QWidget::setVisible(visible);
+}
+
+void SoundSelector::setValue(QString const& value)
+{
+ selector_->selectByValue(value);
+}
+
+QString SoundSelector::value() const
+{
+ return selector_->value().toString();
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SOUNDSELECTOR_H
+#define SOUNDSELECTOR_H
+
+#include <QtGui/QWidget>
+
+class FileSelector;
+
+class SoundSelector : public QWidget
+{
+ Q_OBJECT
+
+public:
+ SoundSelector(QWidget* parent = 0);
+
+public slots:
+ void setValue(QString const& value);
+ QString value() const;
+
+protected:
+ virtual void setVisible(bool visible);
+
+private slots:
+ void playSound();
+
+private:
+ FileSelector* selector_;
+};
+
+#endif
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QFile>
+#include <QMediaPlayer>
+#include "speedalarm.h"
+#include "settings.h"
+#include "odometer.h"
+#include "poialerts.h"
+#include "mediaplayer.h"
+
+SpeedAlarm::SpeedAlarm(): QObject(0), loaded_(false), enabled_(false), isOver_(false)
+{
+}
+
+SpeedAlarm& SpeedAlarm::instance()
+{
+ static SpeedAlarm instance;
+ return instance;
+}
+
+void SpeedAlarm::start()
+{
+ if(!loaded_)
+ {
+ loadConfig();
+ }
+
+ if(enabled_)
+ {
+ connect(&(Odometer::instance()), SIGNAL(dataUpdated()), this, SLOT(onDataUpdated()));
+ }
+
+}
+
+void SpeedAlarm::loadConfig()
+{
+ loaded_ = true;
+
+ bool enabled = Settings::instance().value("alarm_enabled", false).toBool();
+
+ if(enabled)
+ {
+ enabled_ = true;
+
+ QString sound = Settings::instance().value("alarm_sound", "").toString();
+
+ if(sound.isEmpty())
+ {
+ enabled_ = false;
+ return;
+ }
+
+ QString soundDir = MediaPlayer::getSoundDir();
+
+ if(QFile::exists(soundDir + sound))
+ {
+ soundFile_ = soundDir + sound;
+ }
+ else if(QFile::exists(MediaPlayer::getLocalSoundDir() + sound))
+ {
+ soundFile_ = MediaPlayer::getLocalSoundDir() + sound;
+ }
+ else
+ {
+ enabled_ = false;
+ return;
+ }
+
+ threshold_ = Settings::instance().value("alarm_threshold", 0).toInt();
+
+ start();
+ }
+ else
+ {
+ end();
+ enabled_ = false;
+ }
+}
+
+void SpeedAlarm::end()
+{
+ if(enabled_)
+ {
+ disconnect(&(Odometer::instance()), SIGNAL(dataUpdated()), this, SLOT(onDataUpdated()));
+ }
+}
+
+void SpeedAlarm::onDataUpdated()
+{
+ if(Odometer::instance().getLatestFix().kmSpeed > threshold_)
+ {
+ if(!isOver_)
+ {
+ MediaPlayer::play(soundFile_);
+ isOver_ = true;
+ }
+ }
+ else
+ {
+ isOver_ = false;
+ }
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SPEEDALARM_H
+#define SPEEDALARM_H
+
+#include <QtCore/QObject>
+
+class SpeedAlarm : public QObject
+{
+ Q_OBJECT
+
+public:
+ static SpeedAlarm& instance();
+ void start();
+ void end();
+
+public slots:
+ void loadConfig();
+
+private slots:
+ void onDataUpdated();
+
+private:
+ SpeedAlarm();
+ bool loaded_;
+ QString soundFile_;
+ int threshold_;
+ bool enabled_;
+ bool isOver_;
+};
+
+#endif
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QDir>
+#include <QtCore/QDebug>
+#include <QtGui/QLineEdit>
+#include <QtGui/QLabel>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QPushButton>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QCheckBox>
+#include <QtGui/QIntValidator>
+#include <math.h>
+#include "speedalarmsettings.h"
+#include "speedalarm.h"
+#include "odometer.h"
+#include "settings.h"
+#include "fileselector.h"
+#include "poialerts.h"
+#include "mediaplayer.h"
+#include "soundselector.h"
+#include "buttonbox.h"
+
+
+SpeedAlarmSettings::SpeedAlarmSettings(QWidget* parent): QDialog(parent)
+{
+ setWindowTitle(tr("Speed alarm"));
+
+ speedLabel_ = new QLabel;
+ speed_ = new QLineEdit;
+ speed_->setValidator(new QIntValidator(0, 999, this));
+
+ QPushButton* current = new QPushButton(tr("Current"));
+ connect(current, SIGNAL(clicked(bool)), this, SLOT(loadCurrentSpeed()));
+
+ QHBoxLayout* speedLayout = new QHBoxLayout;
+ speedLayout->addWidget(speedLabel_);
+ speedLayout->addWidget(speed_);
+ speedLayout->addWidget(current);
+
+ soundSelector_ = new SoundSelector;
+
+ enabled_ = new QCheckBox(tr("Enabled"));
+ enabled_->setChecked(Settings::instance().value("alarm_enabled", false).toBool());
+
+ ButtonBox* buttons = new ButtonBox;
+ buttons->addButton(tr("Save"), this, SLOT(saveSettings()), QDialogButtonBox::AcceptRole);
+
+ QHBoxLayout* layout = new QHBoxLayout;
+ QVBoxLayout* left = new QVBoxLayout;
+
+ left->addLayout(speedLayout);
+ left->addWidget(soundSelector_);
+ left->addWidget(enabled_);
+ layout->addLayout(left, Qt::AlignLeft);
+ layout->addWidget(buttons);
+
+ setLayout(layout);
+}
+
+
+void SpeedAlarmSettings::loadData()
+{
+ speedLabel_->setText(tr("Speed threshold (%1)").arg(Odometer::getSpeedUnit()));
+ int speedValue = round(Settings::instance().value("alarm_threshold", 100).toDouble() * Odometer::getUnitMultiplier());
+ speed_->setText(QString::number(static_cast<int>(speedValue)));
+
+ QString selected = Settings::instance().value("alarm_sound", "").toString();
+ soundSelector_->setValue(selected);
+}
+
+void SpeedAlarmSettings::loadCurrentSpeed()
+{
+ double speed = round(Odometer::instance().getLatestFix().speed);
+ speed_->setText(QString::number(static_cast<int>(speed)));
+}
+
+void SpeedAlarmSettings::saveSettings()
+{
+ double kmSpeed = speed_->text().toInt() / Odometer::getUnitMultiplier();
+
+ Settings::instance().setValue("alarm_threshold", kmSpeed);
+ Settings::instance().setValue("alarm_enabled", enabled_->isChecked());
+ Settings::instance().setValue("alarm_sound", soundSelector_->value());
+
+ SpeedAlarm::instance().loadConfig();
+
+ hide();
+}
+
+void SpeedAlarmSettings::setVisible(bool visible)
+{
+ if(visible)
+ {
+ loadData();
+ }
+
+ QDialog::setVisible(visible);
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef SPEEDALARMSETTINGS_H
+#define SPEEDALARMSETTINGS_H
+
+#include <QtGui/QDialog>
+
+class QLineEdit;
+class QLabel;
+class QCheckBox;
+class FileSelector;
+class SoundSelector;
+
+class SpeedAlarmSettings : public QDialog
+{
+ Q_OBJECT
+
+public:
+ SpeedAlarmSettings(QWidget* parent = 0);
+
+protected:
+ virtual void setVisible(bool visible);
+
+private slots:
+ void saveSettings();
+ void loadCurrentSpeed();
+
+private:
+ void loadData();
+ QLabel* speedLabel_;
+ QLineEdit* speed_;
+ SoundSelector* soundSelector_;
+ QCheckBox* enabled_;
+};
+
+#endif
#include "detailscreen.h"
#include "settings.h"
#include "widgetscreen.h"
+#include "themescheduler.h"
namespace
{
bool ThemeLoader::load()
{
- QString theme = Settings::instance().value("theme", "default").toString();
+ if(theme_.isEmpty())
+ {
+ connect(&(ThemeScheduler::instance()), SIGNAL(themeChanged()), this, SLOT(load()));
+ }
+
+ QString theme = ThemeScheduler::instance().currentTheme();
+
+ if(theme == theme_)
+ {
+ return true;
+ }
+
+ theme_ = theme;
QString themeDir = getThemeDir();
- if(QFile::exists(themeDir + theme + THEME_SUFFIX))
+ if(QFile::exists(themeDir + theme_ + THEME_SUFFIX))
{
- reader_ = new ZipReader(themeDir + theme + THEME_SUFFIX);
+ reader_ = new ZipReader(themeDir + theme_ + THEME_SUFFIX);
if(read())
{
}
}
- theme = "default";
- Settings::instance().setValue("theme", theme);
+ theme_ = ThemeScheduler::instance().getDefaultTheme();
+ Settings::instance().setValue("theme", theme_);
- if(QFile::exists(RESOURCE_DIR + theme))
+ if(QFile::exists(RESOURCE_DIR + theme_))
{
if(reader_)
{
delete reader_;
}
- reader_ = new FileReader(RESOURCE_DIR + theme);
+ reader_ = new FileReader(RESOURCE_DIR + theme_);
return read();
}
class ThemeLoader : public QObject
{
+ Q_OBJECT
+
public:
ThemeLoader(WidgetScreen* mainScreen, WidgetScreen* detailScreen, QObject* parent = 0);
~ThemeLoader();
- bool load();
QString const& error() const;
static QString getThemeDir();
static QString const& getThemeSuffix();
+public slots:
+ bool load();
+
private:
bool read();
bool loadScreen(QString const& tag, QDomDocument const& doc, WidgetScreen* screen);
+ QString theme_;
Reader* reader_;
QString error_;
WidgetScreen* mainScreen_;
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <QtCore/QDir>
+#include "themepicker.h"
+#include "themescheduler.h"
+#include "themeloader.h"
+#include "settings.h"
+
+ThemePicker::ThemePicker(QString const& text, QWidget* parent):
+FileSelector(text, parent)
+{
+}
+
+void ThemePicker::setVisible(bool visible)
+{
+ if(visible)
+ {
+ loadThemes();
+ }
+
+ FileSelector::setVisible(visible);
+}
+
+void ThemePicker::loadThemes()
+{
+ QString current = Settings::instance().value("theme", ThemeScheduler::getDefaultTheme()).toString();
+ clear();
+ addItem(tr("Default"), ThemeScheduler::getDefaultTheme());
+
+ QDir themeDir(ThemeLoader::getThemeDir());
+
+ if(!themeDir.exists() || !themeDir.isReadable())
+ {
+ qDebug() << "Warning: theme dir (" + ThemeLoader::getThemeDir() + ") doesn't exist or is read protected";
+ return;
+ }
+
+ QStringList filters;
+ filters << "*" + ThemeLoader::getThemeSuffix();
+ themeDir.setNameFilters(filters);
+ themeDir.setFilter(QDir::Files);
+ QStringList files = themeDir.entryList();
+
+ for(int i = 0; i < files.size(); i++)
+ {
+ QString name;
+ QString id;
+ getThemeDetails(files.at(i), name, id);
+ addItem(name, id);
+
+ if(id == current)
+ {
+ setCurrentIndex(i + 1);
+ }
+ }
+}
+
+bool ThemePicker::selectTheme(QString const& filename)
+{
+ QString name;
+ QString id;
+ getThemeDetails(filename, name, id);
+ return selectByValue(id);
+}
+
+void ThemePicker::getThemeDetails(QString filename,
+ QString& name,
+ QString& id)
+{
+ static QRegExp cleaner(QRegExp::escape(ThemeLoader::getThemeSuffix()) + "$");
+ filename = filename.replace(cleaner, "");
+
+ id = filename;
+ name = filename.at(0).toUpper() + filename.mid(1);
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef THEMEPICKER_H
+#define THEMEPICKER_H
+
+#include "fileselector.h"
+
+class ThemePicker : public FileSelector
+{
+ Q_OBJECT
+
+public:
+ ThemePicker(QString const& text = tr("Theme"), QWidget* parent = 0);
+ bool selectTheme(QString const& name);
+
+public slots:
+ void loadThemes();
+
+protected:
+ virtual void setVisible(bool visible);
+
+private:
+ void getThemeDetails(QString filename, QString& name, QString& id);
+ QString theme_;
+};
+
+#endif
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include "themescheduler.h"
+#include "settings.h"
+
+namespace
+{
+ QString const DEFAULT_THEME = "default";
+}
+
+ThemeScheduler::ThemeScheduler(): QObject(0), enabled_(false)
+{
+ loadConfig();
+}
+
+ThemeScheduler::~ThemeScheduler()
+{
+ store();
+ clear();
+}
+
+ThemeScheduler& ThemeScheduler::instance()
+{
+ static ThemeScheduler instance;
+ return instance;
+}
+
+void ThemeScheduler::addItem(QTime const& time, QString const& theme)
+{
+ removeItem(time);
+ ItemDetails* details = new ItemDetails;
+ details->time = time;
+ details->theme = theme;
+
+ int msecs = QTime::currentTime().msecsTo(time);
+
+ if(msecs < 0)
+ {
+ msecs += 86400000;
+ }
+
+ details->timer.setSingleShot(true);
+ details->timer.start(msecs + 500);
+ connect(&details->timer, SIGNAL(timeout()), this, SLOT(emitThemeChanged()));
+
+ for(int i = 0; i < items_.size(); i++)
+ {
+ if(items_.at(i)->time > time)
+ {
+ items_.insert(i, details);
+ return;
+ }
+ }
+
+ items_.push_back(details);
+}
+
+void ThemeScheduler::removeItem(QTime const& time)
+{
+ for(int i = 0; i < items_.size(); i++)
+ {
+ if(items_.at(i)->time == time)
+ {
+ delete items_.at(i);
+ items_.removeAt(i);
+ break;
+ }
+ }
+}
+
+void ThemeScheduler::store()
+{
+ if(items_.isEmpty())
+ {
+ Settings::instance().remove("theme_scheduler");
+ return;
+ }
+
+ QList<QVariant> list;
+
+ for(int i = 0; i < items_.size(); i++)
+ {
+ QMap<QString, QVariant> map;
+ map["time"] = items_.at(i)->time.toString();
+ map["theme"] = items_.at(i)->theme;
+ list.push_back(map);
+ }
+
+ Settings::instance().setValue("theme_scheduler", list);
+}
+
+void ThemeScheduler::loadConfig()
+{
+ enabled_ = Settings::instance().value("theme_scheduler_enabled", false).toBool();
+
+ QList<QVariant> list = Settings::instance().value("theme_scheduler").toList();
+
+ for(int i = 0; i < list.size(); i++)
+ {
+ QMap<QString, QVariant> map = list.at(i).toMap();
+ QTime time = QTime::fromString(map["time"].toString());
+ addItem(time, map["theme"].toString());
+ }
+}
+
+void ThemeScheduler::setEnabled(bool enabled)
+{
+ enabled_ = enabled;
+}
+
+bool ThemeScheduler::isEnabled() const
+{
+ return enabled_;
+}
+
+QString ThemeScheduler::currentTheme() const
+{
+ if(enabled_)
+ {
+ QTime time = QTime::currentTime();
+
+ for(int i = 0; i < items_.size(); i++)
+ {
+ if(items_.at(i)->time >= time)
+ {
+ int index = i - 1;
+
+ if(index < 0)
+ {
+ index = items_.size() - 1;
+ }
+
+ return items_.at(index)->theme;
+ }
+ }
+
+ if(items_.size() > 0)
+ {
+ return items_.at(items_.size() - 1)->theme;
+ }
+ }
+
+ QString theme = Settings::instance().value("theme", DEFAULT_THEME).toString();
+
+ if(theme.isEmpty())
+ {
+ return DEFAULT_THEME;
+ }
+
+ return theme;
+}
+
+QString const& ThemeScheduler::getDefaultTheme()
+{
+ return DEFAULT_THEME;
+}
+
+void ThemeScheduler::clear()
+{
+ for(int i = 0; i < items_.size(); i++)
+ {
+ delete items_.at(i);
+ }
+
+ items_.clear();
+}
+
+void ThemeScheduler::getItems(QList<SchedulerItem>& items)
+{
+ items.clear();
+
+ for(int i = 0; i < items_.size(); i++)
+ {
+ SchedulerItem item;
+ item.time = items_.at(i)->time;
+ item.theme = items_.at(i)->theme;
+ items.push_back(item);
+ }
+}
+
+void ThemeScheduler::emitThemeChanged()
+{
+ if(enabled_)
+ {
+ emit themeChanged();
+ }
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef THEMESCHEDULER_H
+#define THEMESCHEDULER_H
+
+#include <QtCore/QObject>
+#include <QtCore/QList>
+#include <QtCore/QTime>
+#include <QtCore/QTimer>
+
+class QString;
+
+class ThemeScheduler : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ struct SchedulerItem
+ {
+ QTime time;
+ QString theme;
+ };
+
+ ~ThemeScheduler();
+ static ThemeScheduler& instance();
+ static QString const& getDefaultTheme();
+ void addItem(QTime const& time, QString const& theme);
+ void removeItem(QTime const& time);
+ void setEnabled(bool enabled);
+ bool isEnabled() const;
+ QString currentTheme() const;
+ void clear();
+ void getItems(QList<SchedulerItem>& items);
+
+public slots:
+ void store();
+
+signals:
+ void themeChanged();
+
+private slots:
+ void emitThemeChanged();
+
+private:
+ struct ItemDetails
+ {
+ QTime time;
+ QString theme;
+ QTimer timer;
+ };
+
+ ThemeScheduler();
+ void loadConfig();
+ void sort();
+ bool enabled_;
+ QList<ItemDetails*> items_;
+
+
+};
+
+#endif
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <QtCore/QDebug>
+#include <QtGui/QMenu>
+#include <QtGui/QApplication>
+#include <QtGui/QHBoxLayout>
+#include <QtGui/QVBoxLayout>
+#include <QtGui/QCheckBox>
+#include <QtGui/QLabel>
+#include <QtGui/QScrollArea>
+#include <QtGui/QDialogButtonBox>
+#include <QtGui/QPushButton>
+#include <QtGui/QListWidget>
+#include <QMaemo5ValueButton>
+#include <QMaemo5TimePickSelector>
+#include "themeschedulersettings.h"
+#include "themescheduler.h"
+#include "themepicker.h"
+#include "buttonbox.h"
+
+namespace
+{
+ QString const TIME_FORMAT = "hh:mm";
+}
+
+ThemeSchedulerSettings::ThemeSchedulerSettings(QWidget* parent):
+QDialog(parent), currentWidget_(0), addDialog_(0), itemList_(0)
+{
+ setWindowTitle(tr("Theme scheduler"));
+
+ QHBoxLayout* layout = new QHBoxLayout;
+ layout_ = new QVBoxLayout;
+
+ enabled_ = new QCheckBox(tr("Enabled"));
+ enabled_->setChecked(ThemeScheduler::instance().isEnabled());
+
+ QLabel* info = new QLabel(tr("Scheduled themes:"));
+
+ layout_->addWidget(enabled_);
+ layout_->addWidget(info);
+
+ loadItems();
+
+ ButtonBox* buttons = new ButtonBox;
+ buttons->addButton(tr("Save"), this, SLOT(saveSettings()), QDialogButtonBox::AcceptRole);
+ buttons->addButton(tr("Add new theme"), this, SLOT(openAddDialog()), QDialogButtonBox::ActionRole);
+ buttons->addButton(tr("Clear scheduler"), this, SLOT(clearScheduler()), QDialogButtonBox::ActionRole);
+
+ layout->addLayout(layout_, Qt::AlignLeft);
+ layout->addWidget(buttons);
+
+ setLayout(layout);
+
+}
+
+void ThemeSchedulerSettings::openAddDialog()
+{
+ if(!addDialog_)
+ {
+ addDialog_ = new QDialog(this);
+ addDialog_->setWindowTitle("Add scheduled theme");
+ QHBoxLayout* layout = new QHBoxLayout;
+ QVBoxLayout* left = new QVBoxLayout;
+ timeButton_ = new QMaemo5ValueButton(tr("Start time"));
+ timeButton_->setValueLayout(QMaemo5ValueButton::ValueBesideText);
+ pickSelector_ = new QMaemo5TimePickSelector;
+ timeButton_->setPickSelector(pickSelector_);
+ themePicker_ = new ThemePicker(tr("Theme"));
+
+ ButtonBox* buttons = new ButtonBox;
+ buttons->addButton(tr("Add"), this, SLOT(addScheduledTheme()));
+
+ left->addWidget(timeButton_);
+ left->addWidget(themePicker_);
+
+ layout->addLayout(left);
+ layout->addWidget(buttons);
+
+ addDialog_->setLayout(layout);
+
+ }
+
+ pickSelector_->setCurrentTime(QTime::currentTime());
+ addDialog_->show();
+}
+
+void ThemeSchedulerSettings::addScheduledTheme()
+{
+ QTime time = QTime::fromString(timeButton_->valueText(), TIME_FORMAT);
+ QString theme = themePicker_->value().toString();
+ ThemeScheduler::instance().addItem(time, theme);
+ loadItems();
+ addDialog_->hide();
+}
+
+void ThemeSchedulerSettings::clearScheduler()
+{
+ ThemeScheduler::instance().clear();
+ loadItems();
+}
+
+void ThemeSchedulerSettings::loadItems()
+{
+ ThemeScheduler::instance().getItems(items_);
+ itemList_ = 0;
+
+ if(currentWidget_)
+ {
+ layout_->removeWidget(currentWidget_);
+ delete currentWidget_;
+ currentWidget_ = 0;
+ }
+
+ if(items_.isEmpty())
+ {
+ QLabel* label = new QLabel(tr("There are currently no scheduled themes."));
+ label->setWordWrap(true);
+ label->setAlignment(Qt::AlignLeft | Qt::AlignTop);
+ currentWidget_ = label;
+ layout_->addWidget(label);
+ }
+ else
+ {
+ itemList_ = new QListWidget;
+ itemList_->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(itemList_, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showContextMenu(const QPoint&)));
+
+ for(int i = 0; i < items_.size(); i++)
+ {
+ const QTime* endTime = 0;
+
+ if(i < items_.size() - 1)
+ {
+ endTime = &(items_.at(i + 1).time);
+ }
+ else
+ {
+ endTime = &(items_.at(0).time);
+ }
+
+ QString theme = items_.at(i).theme;
+ QString text = items_.at(i).time.toString(TIME_FORMAT) + " - " +
+ endTime->toString(TIME_FORMAT) + ": " +
+ theme.at(0).toUpper() + theme.mid(1);
+ QListWidgetItem* item = new QListWidgetItem(text);
+ item->setData(Qt::UserRole, items_.at(i).time.toString(TIME_FORMAT));
+ itemList_->addItem(item);
+ }
+
+ currentWidget_ = itemList_;
+ layout_->addWidget(itemList_);
+ }
+
+ QApplication::processEvents();
+ adjustSize();
+ QApplication::processEvents();
+
+}
+
+void ThemeSchedulerSettings::saveSettings()
+{
+ ThemeScheduler::instance().setEnabled(enabled_->isChecked());
+ hide();
+}
+
+void ThemeSchedulerSettings::showContextMenu(QPoint const& point)
+{
+ if(!itemList_)
+ {
+ return;
+ }
+
+ QMenu* menu = new QMenu(itemList_);
+ menu->addAction(tr("Remove"), this, SLOT(removeCurrent()));
+ connect(menu, SIGNAL(aboutToHide()), this, SLOT(removeSelection()));
+ menu->popup(itemList_->mapToGlobal(point));
+}
+
+void ThemeSchedulerSettings::removeCurrent()
+{
+ if(itemList_)
+ {
+ QListWidgetItem* item = itemList_->currentItem();
+
+ if(item)
+ {
+ ThemeScheduler::instance().removeItem(QTime::fromString(item->data(Qt::UserRole).toString(), TIME_FORMAT));
+ loadItems();
+ }
+ }
+}
+
+void ThemeSchedulerSettings::removeSelection()
+{
+ if(itemList_)
+ {
+ itemList_->clearSelection();
+ }
+}
--- /dev/null
+/*
+ * This file is part of jSpeed.
+ *
+ * jSpeed is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * jSpeed is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with jSpeed. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef THEMESCHEDULERSETTINGS_H
+#define THEMESCHEDULERSETTINGS_H
+
+#include <QtGui/QDialog>
+#include "themescheduler.h"
+
+class QCheckBox;
+class QScrollArea;
+class QMaemo5ValueButton;
+class QMaemo5TimePickSelector;
+class QVBoxLayout;
+class QListWidget;
+class ThemePicker;
+
+class ThemeSchedulerSettings : public QDialog
+{
+ Q_OBJECT
+
+public:
+ ThemeSchedulerSettings(QWidget* parent = 0);
+
+private slots:
+ void openAddDialog();
+ void addScheduledTheme();
+ void clearScheduler();
+ void saveSettings();
+ void showContextMenu(QPoint const& point);
+ void removeCurrent();
+ void removeSelection();
+
+private:
+ void loadItems();
+ QCheckBox* enabled_;
+ QVBoxLayout* layout_;
+ QWidget* currentWidget_;
+ QDialog* addDialog_;
+ QMaemo5TimePickSelector* pickSelector_;
+ QMaemo5ValueButton* timeButton_;
+ ThemePicker* themePicker_;
+ QList<ThemeScheduler::SchedulerItem> items_;
+ QListWidget* itemList_;
+};
+
+#endif
#include <QtGui/QVBoxLayout>
#include <QtGui/QMessageBox>
#include "themeselector.h"
-#include "buttonselector.h"
+#include "themepicker.h"
#include "themeloader.h"
#include "settings.h"
+#include "themeschedulersettings.h"
-ThemeSelector::ThemeSelector(QWidget* parent): QDialog(parent)
+ThemeSelector::ThemeSelector(QWidget* parent): QDialog(parent), themeScheduler_(0)
{
setWindowTitle(tr("Select theme"));
QHBoxLayout* layout = new QHBoxLayout;
- QHBoxLayout* left = new QHBoxLayout;
+ QVBoxLayout* left = new QVBoxLayout;
+ QHBoxLayout* first = new QHBoxLayout;
QPushButton* saveButton = new QPushButton(tr("Save"));
connect(saveButton, SIGNAL(clicked(bool)), this, SLOT(saveTheme()));
QDialogButtonBox* buttons = new QDialogButtonBox;
buttons->setCenterButtons(false);
+ buttons->setOrientation(Qt::Vertical);
buttons->addButton(saveButton, QDialogButtonBox::AcceptRole);
- selector_ = new ButtonSelector(tr("Theme"), this);
+ selector_ = new ThemePicker(tr("Theme"), this);
theme_ = Settings::instance().value("theme", "default").toString();
QPushButton* loadButton = new QPushButton(tr("Import"));
connect(loadButton, SIGNAL(clicked(bool)), this, SLOT(loadFromFile()));
- left->addWidget(selector_, Qt::AlignLeft);
- left->addWidget(loadButton);
+ QPushButton* scheduler = new QPushButton(tr("Theme scheduler"));
+ connect(scheduler, SIGNAL(clicked(bool)), this, SLOT(openScheduler()));
+
+ first->addWidget(selector_, Qt::AlignLeft);
+ first->addWidget(loadButton);
+
+ left->addLayout(first);
+ left->addWidget(scheduler);
layout->addLayout(left, Qt::AlignLeft);
layout->addWidget(buttons);
void ThemeSelector::loadFromFile()
{
- QString filename = QFileDialog::getOpenFileName(this, tr("Open file"),
- QDir::home().path(),
- tr("Theme files") + "(*" + ThemeLoader::getThemeSuffix() + ")");
-
- if(filename.isEmpty())
- {
- return;
- }
-
- qDebug() << filename;
-
- QString basename;
- int i = filename.lastIndexOf(QDir::separator());
-
- if(i == -1)
- {
- basename = filename;
- }
- else
- {
- basename = filename.mid(i + 1);
- }
-
- QString targetFile = ThemeLoader::getThemeDir() + basename;
-
- qDebug() << targetFile;
-
- bool ok = true;
-
- if(QFile::exists(targetFile))
- {
- ok = confirmCopy(basename);
-
- if(ok)
- {
- QFile::remove(targetFile);
- }
- }
-
- if(ok)
- {
- QFile::copy(filename, targetFile);
- QString name;
- QString id;
- getThemeDetails(basename, name, id);
- theme_ = id;
- loadThemes();
- }
-}
-
-void ThemeSelector::loadThemes()
-{
- selector_->clear();
- selector_->addItem(tr("Default"), "default");
- QDir themeDir(ThemeLoader::getThemeDir());
-
- if(!themeDir.exists() || !themeDir.isReadable())
- {
- qDebug() << "Warning: theme dir (" + ThemeLoader::getThemeDir() + ") doesn't exist or is read protected";
- return;
- }
+ QString file;
- QStringList filters;
- filters << "*" + ThemeLoader::getThemeSuffix();
- themeDir.setNameFilters(filters);
- themeDir.setFilter(QDir::Files);
- QStringList files = themeDir.entryList();
-
- for(int i = 0; i < files.size(); i++)
+ if(selector_->importFile(ThemeLoader::getThemeDir(),
+ "Theme files",
+ "*" + ThemeLoader::getThemeSuffix(),
+ false,
+ &file))
{
- QString name;
- QString id;
- getThemeDetails(files.at(i), name, id);
- selector_->addItem(name, id);
-
- if(id == theme_)
- {
- selector_->setCurrentIndex(i + 1);
- }
+ selector_->loadThemes();
+ selector_->selectTheme(file);
}
-
-}
-
-void ThemeSelector::getThemeDetails(QString filename,
- QString& name,
- QString& id)
-{
- static QRegExp cleaner(QRegExp::escape(ThemeLoader::getThemeSuffix()) + "$");
- filename = filename.replace(cleaner, "");
-
- id = filename;
- name = filename.at(0).toUpper() + filename.mid(1);
-}
-
-bool ThemeSelector::confirmCopy(QString const& filename)
-{
- QMessageBox::StandardButton result = QMessageBox::question(this, tr("File exists"),
- tr("Theme file %1 already exists in theme directory, overwrite?").arg(filename),
- QMessageBox::Yes | QMessageBox::No);
-
- return (result == QMessageBox::Yes);
}
-void ThemeSelector::setVisible(bool visible)
+void ThemeSelector::openScheduler()
{
- if(visible)
+ if(!themeScheduler_)
{
- loadThemes();
+ themeScheduler_ = new ThemeSchedulerSettings(this);
}
- QDialog::setVisible(visible);
+ themeScheduler_->show();
}
#include <QtGui/QDialog>
class QString;
-class ButtonSelector;
+class ThemePicker;
+class ThemeSchedulerSettings;
class ThemeSelector : public QDialog
{
private slots:
void saveTheme();
void loadFromFile();
-
-protected:
- virtual void setVisible(bool visible);
+ void openScheduler();
private:
- void loadThemes();
- void getThemeDetails(QString filename, QString& name, QString& id);
- bool confirmCopy(QString const& name);
- ButtonSelector* selector_;
+ ThemePicker* selector_;
QString theme_;
+ ThemeSchedulerSettings* themeScheduler_;
};
#include "unitselector.h"
#include "buttonselector.h"
#include "settings.h"
+#include "buttonbox.h"
UnitSelector::UnitSelector(QWidget* parent): QDialog(parent)
{
layout->addWidget(selector_, Qt::AlignLeft);
- QPushButton* button = new QPushButton(tr("Save"));
- connect(button, SIGNAL(clicked(bool)), this, SLOT(saveUnit()));
- QDialogButtonBox* buttons = new QDialogButtonBox;
- buttons->setCenterButtons(false);
- buttons->addButton(button, QDialogButtonBox::AcceptRole);
+ ButtonBox* buttons = new ButtonBox;
+ buttons->addButton(tr("Save"), this, SLOT(saveUnit()));
layout->addWidget(buttons);