From: eshe Date: Sun, 25 Jul 2010 21:15:36 +0000 (+0100) Subject: Added theme scheduler, poi support and speed alarm features. X-Git-Url: http://git.maemo.org/git/?p=jspeed;a=commitdiff_plain;h=28cb8747756c4270e5bb6cd8585685e7ed234aef;ds=sidebyside Added theme scheduler, poi support and speed alarm features. --- diff --git a/jspeed.pro b/jspeed.pro index f3014b6..ad563e1 100644 --- a/jspeed.pro +++ b/jspeed.pro @@ -1,6 +1,8 @@ QT += maemo5 xml TARGET = jspeed TEMPLATE = app +CONFIG += mobility +MOBILITY += multimedia SOURCES += src/main.cpp \ src/mainwindow.cpp \ src/mainwindowstack.cpp \ @@ -30,7 +32,20 @@ SOURCES += src/main.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 \ @@ -59,7 +74,20 @@ HEADERS += src/mainwindow.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 diff --git a/src/buttonbox.cpp b/src/buttonbox.cpp new file mode 100644 index 0000000..4636aae --- /dev/null +++ b/src/buttonbox.cpp @@ -0,0 +1,37 @@ +/* + * 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 . + * + */ + +#include +#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; +} diff --git a/src/buttonbox.h b/src/buttonbox.h new file mode 100644 index 0000000..6a3771c --- /dev/null +++ b/src/buttonbox.h @@ -0,0 +1,38 @@ +/* + * 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 . + * + */ + +#ifndef BUTTONBOX_H +#define BUTTONBOX_H + +#include +#include +#include + +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 diff --git a/src/buttonselector.cpp b/src/buttonselector.cpp index c1adde3..22fa6d4 100644 --- a/src/buttonselector.cpp +++ b/src/buttonselector.cpp @@ -142,6 +142,11 @@ bool ButtonSelector::removeItem(unsigned int index) return model_->removeRow(index); } +int ButtonSelector::size() const +{ + return model_->rowCount(); +} + void ButtonSelector::onSelected(QString const& text) { emit selected(currentIndex(), text, value()); diff --git a/src/buttonselector.h b/src/buttonselector.h index e36c159..6b92b24 100644 --- a/src/buttonselector.h +++ b/src/buttonselector.h @@ -39,6 +39,7 @@ public: 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); diff --git a/src/fileselector.cpp b/src/fileselector.cpp new file mode 100644 index 0000000..e7e9887 --- /dev/null +++ b/src/fileselector.cpp @@ -0,0 +1,139 @@ +/* + * 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 . + * + */ + +#include +#include +#include +#include +#include +#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); +} + diff --git a/src/fileselector.h b/src/fileselector.h new file mode 100644 index 0000000..1a2ccb3 --- /dev/null +++ b/src/fileselector.h @@ -0,0 +1,42 @@ +/* + * 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 . + * + */ + +#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 diff --git a/src/graphicsscene.h b/src/graphicsscene.h index d5ac6d7..0a8733e 100644 --- a/src/graphicsscene.h +++ b/src/graphicsscene.h @@ -29,7 +29,7 @@ class GraphicsScene : public QGraphicsScene public: GraphicsScene(QRectF const& rect); - static int const CLICK_MARGIN = 45; + static int const CLICK_MARGIN = 48; signals: void clicked(); diff --git a/src/main.cpp b/src/main.cpp index cee1700..9838096 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,10 +20,34 @@ #include #include "mainwindow.h" +#include "poiascreader.h" +#include +#include "poialerts.h" + int main(int argc, char *argv[]) { QApplication app(argc, argv); + /* PoiAscReader reader("/home/maemo/workspace/jspeed/test.asc"); + + QList 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())); diff --git a/src/mainmenu.cpp b/src/mainmenu.cpp index a10d69b..da6af01 100644 --- a/src/mainmenu.cpp +++ b/src/mainmenu.cpp @@ -25,9 +25,12 @@ #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_); @@ -35,8 +38,10 @@ currentRow_(0), themeSelector_(0), unitSelector_(0), aboutDialog_(0) 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())); } @@ -52,6 +57,26 @@ void MainMenu::selectTheme() 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_) diff --git a/src/mainmenu.h b/src/mainmenu.h index 44e8b0c..39dbb5d 100644 --- a/src/mainmenu.h +++ b/src/mainmenu.h @@ -25,6 +25,8 @@ class QVBoxLayout; class QHBoxLayout; class ThemeSelector; class UnitSelector; +class PoiSettings; +class SpeedAlarmSettings; class MainMenu : public QDialog { @@ -46,6 +48,8 @@ private slots: void selectUnit(); void showAbout(); void confirmReset(); + void openPoiAlerts(); + void openSpeedAlarm(); private: QVBoxLayout* layout_; @@ -53,6 +57,8 @@ private: QHBoxLayout* currentRow_; ThemeSelector* themeSelector_; UnitSelector* unitSelector_; + PoiSettings* poiSettings_; + SpeedAlarmSettings* speedAlarmSettings_; QDialog* aboutDialog_; }; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 39b41b3..0d1294a 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -29,12 +29,16 @@ #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(); } @@ -115,6 +119,8 @@ void MainWindow::openMenu() 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(); diff --git a/src/mediaplayer.cpp b/src/mediaplayer.cpp new file mode 100644 index 0000000..3d09112 --- /dev/null +++ b/src/mediaplayer.cpp @@ -0,0 +1,78 @@ +/* + * 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 . + * + */ + +#include +#include +#include +#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& 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; +} + diff --git a/src/mediaplayer.h b/src/mediaplayer.h new file mode 100644 index 0000000..abd3303 --- /dev/null +++ b/src/mediaplayer.h @@ -0,0 +1,40 @@ +/* + * 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 . + * + */ + +#ifndef MEDIAPLAYER_H +#define MEDIAPLAYER_H + +#include +#include +#include + +class MediaPlayer +{ +public: + enum Format {MP3, WAV, AAC, FORMAT_COUNT}; + static bool play(QString const& file); + static void getSupportedFormats(QList& formats); + static QString getFormatPattern(); + static QString getSoundDir(); + static QString const& getLocalSoundDir(); + +private: + static QMediaPlayer player_; +}; + +#endif diff --git a/src/odometer.cpp b/src/odometer.cpp index d68fb1f..4d81136 100644 --- a/src/odometer.cpp +++ b/src/odometer.cpp @@ -284,6 +284,11 @@ QString const& Odometer::getSpeedUnit() } } +double Odometer::getUnitMultiplier() +{ + return Location::getUnitMultiplier(); +} + void Odometer::updateUnit() { QString unit = Settings::instance().value("unit", "km").toString(); diff --git a/src/odometer.h b/src/odometer.h index c68fee3..83116bb 100644 --- a/src/odometer.h +++ b/src/odometer.h @@ -44,6 +44,7 @@ public: double getSignalStrength() const; static QString const& getUnit(); static QString const& getSpeedUnit(); + static double getUnitMultiplier(); signals: void dataUpdated(); diff --git a/src/poialerts.cpp b/src/poialerts.cpp new file mode 100644 index 0000000..dcc847e --- /dev/null +++ b/src/poialerts.cpp @@ -0,0 +1,380 @@ +/* + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include +#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(); +} + diff --git a/src/poialerts.h b/src/poialerts.h new file mode 100644 index 0000000..8adc163 --- /dev/null +++ b/src/poialerts.h @@ -0,0 +1,76 @@ +/* + * 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 . + * + */ + +#ifndef POIALERTS_H +#define POIALERTS_H + +#include +#include +#include +#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 pois_; + QQueue playedSounds_; + bool enabled_; + int distance_; + double travelled_; + PoiReader::Poi* currentPoi_; + double currentDistance_; + bool loaded_; + QString error_; + +}; + +#endif diff --git a/src/poiascreader.cpp b/src/poiascreader.cpp new file mode 100644 index 0000000..0b44e7f --- /dev/null +++ b/src/poiascreader.cpp @@ -0,0 +1,86 @@ +/* + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include "poiascreader.h" + +PoiAscReader::PoiAscReader(QString filename): PoiReader(), filename_(filename) +{ +} + +bool PoiAscReader::read(QList& 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; +} diff --git a/src/poiascreader.h b/src/poiascreader.h new file mode 100644 index 0000000..237cf5d --- /dev/null +++ b/src/poiascreader.h @@ -0,0 +1,34 @@ +/* + * 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 . + * + */ + +#ifndef POIASCREADER_H +#define POIASCREADER_H + +#include "poireader.h" + +class PoiAscReader : public PoiReader +{ +public: + PoiAscReader(QString filename); + virtual bool read(QList& pois); + +private: + QString filename_; +}; + +#endif diff --git a/src/poireader.cpp b/src/poireader.cpp new file mode 100644 index 0000000..3078ec6 --- /dev/null +++ b/src/poireader.cpp @@ -0,0 +1,86 @@ +/* + * 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 . + * + */ + +#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(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& formats) +{ + formats.clear(); + + for(int i = 0; i < READER_COUNT; i++) + { + formats.push_back(READER_FILETYPES[i]); + } +} diff --git a/src/poireader.h b/src/poireader.h new file mode 100644 index 0000000..fced29e --- /dev/null +++ b/src/poireader.h @@ -0,0 +1,53 @@ +/* + * 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 . + * + */ + +#ifndef POIREADER_H +#define POIREADER_H + +#include +#include + +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& pois) = 0; + QString const& error(); + static QString getFormatPattern(); + static void getSupportedFormats(QList& formats); + +protected: + void setError(QString const& error); + +private: + QString error_; + +}; + +#endif diff --git a/src/poisettings.cpp b/src/poisettings.cpp new file mode 100644 index 0000000..09a4043 --- /dev/null +++ b/src/poisettings.cpp @@ -0,0 +1,143 @@ +/* + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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); + } +} diff --git a/src/poisettings.h b/src/poisettings.h new file mode 100644 index 0000000..67cfc7f --- /dev/null +++ b/src/poisettings.h @@ -0,0 +1,57 @@ +/* + * 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 . + * + */ + +#ifndef POISETTINGS_H +#define POISETTINGS_H + +#include + +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 diff --git a/src/resources.qrc b/src/resources.qrc index 24f58d4..a01fadf 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -12,6 +12,7 @@ resources/signal_2.png resources/signal_3.png resources/signal_4.png + resources/sounds/beep.wav resources/themes/default/theme.xml resources/themes/default/digital7.ttf resources/themes/default/background.png diff --git a/src/resources/sounds/beep.wav b/src/resources/sounds/beep.wav new file mode 100644 index 0000000..678fbec Binary files /dev/null and b/src/resources/sounds/beep.wav differ diff --git a/src/soundselector.cpp b/src/soundselector.cpp new file mode 100644 index 0000000..1d80dbf --- /dev/null +++ b/src/soundselector.cpp @@ -0,0 +1,81 @@ +/* + * 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 . + * + */ + +#include +#include +#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(); +} diff --git a/src/soundselector.h b/src/soundselector.h new file mode 100644 index 0000000..c9247e9 --- /dev/null +++ b/src/soundselector.h @@ -0,0 +1,47 @@ +/* + * 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 . + * + */ + +#ifndef SOUNDSELECTOR_H +#define SOUNDSELECTOR_H + +#include + +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 diff --git a/src/speedalarm.cpp b/src/speedalarm.cpp new file mode 100644 index 0000000..b4908e7 --- /dev/null +++ b/src/speedalarm.cpp @@ -0,0 +1,118 @@ +/* + * 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 . + * + */ + +#include +#include +#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; + } +} diff --git a/src/speedalarm.h b/src/speedalarm.h new file mode 100644 index 0000000..10e3581 --- /dev/null +++ b/src/speedalarm.h @@ -0,0 +1,48 @@ +/* + * 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 . + * + */ + +#ifndef SPEEDALARM_H +#define SPEEDALARM_H + +#include + +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 diff --git a/src/speedalarmsettings.cpp b/src/speedalarmsettings.cpp new file mode 100644 index 0000000..64e84c2 --- /dev/null +++ b/src/speedalarmsettings.cpp @@ -0,0 +1,115 @@ +/* + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(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(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); +} diff --git a/src/speedalarmsettings.h b/src/speedalarmsettings.h new file mode 100644 index 0000000..aa7d97e --- /dev/null +++ b/src/speedalarmsettings.h @@ -0,0 +1,52 @@ +/* + * 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 . + * + */ + +#ifndef SPEEDALARMSETTINGS_H +#define SPEEDALARMSETTINGS_H + +#include + +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 diff --git a/src/themeloader.cpp b/src/themeloader.cpp index b554088..768999b 100644 --- a/src/themeloader.cpp +++ b/src/themeloader.cpp @@ -33,6 +33,7 @@ #include "detailscreen.h" #include "settings.h" #include "widgetscreen.h" +#include "themescheduler.h" namespace { @@ -51,13 +52,25 @@ ThemeLoader::~ThemeLoader() 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()) { @@ -71,17 +84,17 @@ bool ThemeLoader::load() } } - 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(); } diff --git a/src/themeloader.h b/src/themeloader.h index bdf2ce2..f5797a2 100644 --- a/src/themeloader.h +++ b/src/themeloader.h @@ -28,17 +28,22 @@ class WidgetScreen; 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_; diff --git a/src/themepicker.cpp b/src/themepicker.cpp new file mode 100644 index 0000000..f7d3e44 --- /dev/null +++ b/src/themepicker.cpp @@ -0,0 +1,93 @@ +/* + * 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 . + * + */ + +#include +#include +#include +#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); +} diff --git a/src/themepicker.h b/src/themepicker.h new file mode 100644 index 0000000..5339faa --- /dev/null +++ b/src/themepicker.h @@ -0,0 +1,43 @@ +/* + * 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 . + * + */ + +#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 diff --git a/src/themescheduler.cpp b/src/themescheduler.cpp new file mode 100644 index 0000000..a09225f --- /dev/null +++ b/src/themescheduler.cpp @@ -0,0 +1,205 @@ +/* + * 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 . + * + */ + +#include +#include +#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 list; + + for(int i = 0; i < items_.size(); i++) + { + QMap 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 list = Settings::instance().value("theme_scheduler").toList(); + + for(int i = 0; i < list.size(); i++) + { + QMap 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& 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(); + } +} diff --git a/src/themescheduler.h b/src/themescheduler.h new file mode 100644 index 0000000..0501964 --- /dev/null +++ b/src/themescheduler.h @@ -0,0 +1,78 @@ +/* + * 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 . + * + */ + +#ifndef THEMESCHEDULER_H +#define THEMESCHEDULER_H + +#include +#include +#include +#include + +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& 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 items_; + + +}; + +#endif diff --git a/src/themeschedulersettings.cpp b/src/themeschedulersettings.cpp new file mode 100644 index 0000000..f736626 --- /dev/null +++ b/src/themeschedulersettings.cpp @@ -0,0 +1,215 @@ +/* + * 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 . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(); + } +} diff --git a/src/themeschedulersettings.h b/src/themeschedulersettings.h new file mode 100644 index 0000000..c4a4fcd --- /dev/null +++ b/src/themeschedulersettings.h @@ -0,0 +1,62 @@ +/* + * 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 . + * + */ + +#ifndef THEMESCHEDULERSETTINGS_H +#define THEMESCHEDULERSETTINGS_H + +#include +#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 items_; + QListWidget* itemList_; +}; + +#endif diff --git a/src/themeselector.cpp b/src/themeselector.cpp index e66d925..9f377ac 100644 --- a/src/themeselector.cpp +++ b/src/themeselector.cpp @@ -27,31 +27,40 @@ #include #include #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); @@ -78,115 +87,25 @@ void ThemeSelector::saveTheme() 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(); } diff --git a/src/themeselector.h b/src/themeselector.h index 7d29ac8..ec5f943 100644 --- a/src/themeselector.h +++ b/src/themeselector.h @@ -22,7 +22,8 @@ #include class QString; -class ButtonSelector; +class ThemePicker; +class ThemeSchedulerSettings; class ThemeSelector : public QDialog { @@ -37,16 +38,12 @@ signals: 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_; }; diff --git a/src/unitselector.cpp b/src/unitselector.cpp index 90cadfa..61a0fb8 100644 --- a/src/unitselector.cpp +++ b/src/unitselector.cpp @@ -23,6 +23,7 @@ #include "unitselector.h" #include "buttonselector.h" #include "settings.h" +#include "buttonbox.h" UnitSelector::UnitSelector(QWidget* parent): QDialog(parent) { @@ -44,11 +45,8 @@ 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);