src/imageelement.cpp \
src/rectangle.cpp \
src/pointer.cpp \
+ src/compass.cpp \
src/odometer.cpp \
src/themeloader.cpp \
src/themescreen.cpp \
src/blureffect.cpp \
src/opacityeffect.cpp \
src/dropshadoweffect.cpp \
+ src/flickereffect.cpp \
src/poialerts.cpp \
src/poireader.cpp \
src/poiascreader.cpp \
src/imageelement.h \
src/rectangle.h \
src/pointer.h \
+ src/compass.h \
src/odometer.h \
src/themeloader.h \
src/themescreen.h \
src/blureffect.h \
src/opacityeffect.h \
src/dropshadoweffect.h \
+ src/flickereffect.h \
src/poialerts.h \
src/poireader.h \
src/poiascreader.h \
BINDIR = $$PREFIX/bin
DATADIR =$$PREFIX/share
- THEMEDIR = /home/user/.jspeed/themes
+ APPDIR = /home/user/.jspeed
DEFINES += DATADIR=\\\"$$DATADIR\\\" PKGDATADIR=\\\"$$PKGDATADIR\\\"
#MAKE INSTALL
- INSTALLS += target desktop themes icon26 icon48 icon64
+ INSTALLS += target desktop themes sounds icon26 icon48 icon64
target.path =$$BINDIR
desktop.path = $$DATADIR/applications/hildon
desktop.files += src/data/$${TARGET}.desktop
- themes.path = $$THEMEDIR
- themes.files += src/data/themes/graphical.jspeed \
- src/data/themes/white.jspeed \
+ themes.path = $$APPDIR/themes
+ themes.files += src/data/themes/white.jspeed \
src/data/themes/dark.jspeed
+ sounds.path = $$APPDIR/sounds
+ sounds.files += src/data/sounds/beep.mp3 \
+ src/data/sounds/alert.mp3
+
icon26.path = $$DATADIR/icons/hicolor/26x26/apps
icon26.files += src/data/26x26/$${TARGET}.png
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;
-}
public:
ButtonBox(QWidget* parent = 0);
- QPushButton* addButton(QString const& text,
- const QObject* receiver,
- const char* member,
- QDialogButtonBox::ButtonRole role = QDialogButtonBox::AcceptRole);
};
#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 <QtGui/QGraphicsPixmapItem>
+#include <QtCore/QDebug>
+#include <QtCore/QTimeLine>
+#include <math.h>
+#include "compass.h"
+#include "reader.h"
+#include "graphicsscene.h"
+#include "odometer.h"
+
+namespace
+{
+ const GraphicsElement::AttributeDetails ATTRIBUTES[Compass::ATTRIBUTE_COUNT] =
+ {
+ {"xpos", true},
+ {"ypos", true},
+ {"zpos", true},
+ {"visiblewhen", false},
+ {"src", false},
+ {"xrotationpoint", true},
+ {"yrotationpoint", true}
+ };
+
+ int const ANIMATION_TIME = 700;
+ int const ANIMATION_FRAMES = 80;
+ int const ANIMATION_UPDATEINTERVAL = 20;
+ double const COMPASS_IGNORE_THRESHOLD = 90.0;
+}
+
+Compass::Compass(Reader* reader, bool animate): GraphicsElement(reader),
+xRotationPoint_(-1), yRotationPoint_(-1), x_(0), y_(0), targetAngle_(0),
+startAngle_(0), angle_(-1), width_(0), height_(0), imageSet_(false), animate_(animate), timer_(0)
+{
+ element_ = new QGraphicsPixmapItem();
+
+ if(animate_)
+ {
+ timer_ = new QTimeLine(ANIMATION_TIME);
+ timer_->setFrameRange(0, ANIMATION_FRAMES);
+ timer_->setUpdateInterval(ANIMATION_UPDATEINTERVAL);
+ connect(timer_, SIGNAL(frameChanged(int)), this, SLOT(setFrame(int)));
+ }
+
+}
+
+Compass::~Compass()
+{
+ delete timer_;
+}
+
+bool Compass::setAttribute(QString const& name, QString const& value)
+{
+ int intVal = 0;
+ int attrId = -1;
+
+ if((attrId = getAttribute(name, value, ATTRIBUTES, ATTRIBUTE_COUNT, intVal)) != -1)
+ {
+ Attribute attr = static_cast<Attribute>(attrId);
+
+ switch(attr)
+ {
+ case XPOS:
+ x_ = intVal;
+ break;
+ case YPOS:
+ y_ = intVal;
+ break;
+ case ZPOS:
+ element_->setZValue(intVal);
+ break;
+ case VISIBLEWHEN:
+ setVisibleWhen(strToVisibleWhen(value));
+ break;
+ case SRC:
+ return loadImage(value);
+ break;
+ case XROTATIONPOINT:
+ xRotationPoint_ = intVal;
+ break;
+ case YROTATIONPOINT:
+ yRotationPoint_ = intVal;
+ break;
+ default:
+ qDebug() << "Unknown attribute: " << attr;
+ return false;
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void Compass::addToScene(GraphicsScene* scene)
+{
+ if(!imageSet_)
+ {
+ return;
+ }
+
+ if(xRotationPoint_ < 0)
+ {
+ xRotationPoint_ = width_ / 2;
+ }
+ if(yRotationPoint_ < 0)
+ {
+ yRotationPoint_ = height_ / 2;
+ }
+
+ element_->setTransformOriginPoint(xRotationPoint_, yRotationPoint_);
+ element_->setX(x_ - xRotationPoint_);
+ element_->setY(y_ - yRotationPoint_);
+
+ bool animateVal = animate_;
+ animate_ = false;
+ update();
+ animate_ = animateVal;
+
+ scene->addItem(element_);
+}
+
+void Compass::update()
+{
+ if(Odometer::instance().getLatestFix().epd > COMPASS_IGNORE_THRESHOLD)
+ {
+ return;
+ }
+
+ double angle = Odometer::instance().getLatestFix().track * -1.0;
+
+ if(angle < -180)
+ {
+ angle += 360.0;
+ }
+
+ int rounded = static_cast<int>(round(angle));
+
+ if(rounded == angle_)
+ {
+ return;
+ }
+
+ angle_ = rounded;
+
+ if(!animate_)
+ {
+ element_->setRotation(rounded);
+ }
+ else
+ {
+ targetAngle_ = rounded;
+ startAngle_ = element_->rotation();
+
+ if(timer_->state() == QTimeLine::Running)
+ {
+ timer_->stop();
+ }
+
+ timer_->start();
+ }
+}
+
+void Compass::setFrame(int frame)
+{
+ element_->setRotation(startAngle_ + ((static_cast<double>(frame) / ANIMATION_FRAMES) * (targetAngle_ - startAngle_)));
+}
+
+bool Compass::loadImage(QString const& name)
+{
+ QPixmap pixmap;
+ QByteArray data;
+
+ if(!readFile(name, data))
+ {
+ return false;
+ }
+
+ if(!pixmap.loadFromData(data))
+ {
+ setError("Invalid image file: " + name);
+ return false;
+ }
+
+ width_ = pixmap.width();
+ height_ = pixmap.height();
+
+ element_->setPixmap(pixmap);
+ imageSet_ = true;
+
+ return true;
+}
+
+QGraphicsItem* Compass::getElement() const
+{
+ return element_;
+}
+
--- /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 COMPASS_H
+#define COMPASS_H
+
+#include <QtCore/QObject>
+#include "graphicselement.h"
+
+class QGraphicsPixmapItem;
+class QTimeLine;
+class QGraphicsItem;
+class GraphicsScene;
+class Reader;
+
+class Compass : public GraphicsElement
+{
+ Q_OBJECT
+
+public:
+ enum Attribute {XPOS, YPOS, ZPOS, VISIBLEWHEN, SRC, XROTATIONPOINT, YROTATIONPOINT, ATTRIBUTE_COUNT};
+ Compass(Reader* reader, bool animate);
+ ~Compass();
+ virtual bool setAttribute(QString const& name, QString const& value);
+ virtual void addToScene(GraphicsScene* scene);
+ virtual void update();
+ virtual QGraphicsItem* getElement() const;
+
+private slots:
+ void setFrame(int frame);
+
+private:
+ bool loadImage(QString const& name);
+ QGraphicsPixmapItem* element_;
+ int xRotationPoint_;
+ int yRotationPoint_;
+ int x_;
+ int y_;
+ int targetAngle_;
+ int startAngle_;
+ int angle_;
+ int width_;
+ int height_;
+ bool imageSet_;
+ bool animate_;
+ QTimeLine* timer_;
+};
+
+#endif
#include "dropshadoweffect.h"
#include "blureffect.h"
#include "opacityeffect.h"
+#include "flickereffect.h"
Effect::Effect()
{
return new OpacityEffect;
}
+ else if(name == "flicker")
+ {
+ return new FlickerEffect;
+ }
return 0;
}
{
}
-bool FileSelector::loadFiles(QString const& dir, QString const& pattern)
+bool FileSelector::loadFiles(QString const& dir, QStringList const& patterns)
{
QDir directory(dir);
if(directory.exists() && directory.isReadable())
{
- QStringList filters;
- filters << pattern;
- directory.setNameFilters(filters);
+ directory.setNameFilters(patterns);
directory.setFilter(QDir::Files);
QStringList files = directory.entryList();
return false;
}
+bool FileSelector::loadFiles(QString const& dir, QString const& pattern)
+{
+ return loadFiles(dir, QStringList() << pattern);
+}
+
bool FileSelector::importFile(QString const& dir,
QString const& name,
QString const& pattern,
public:
FileSelector(QString const& text, QWidget* parent = 0);
+ bool loadFiles(QString const& dir, QStringList const& patterns);
bool loadFiles(QString const& dir, QString const& pattern);
bool importFile(QString const& dir, QString const& name,
QString const& pattern, bool add = 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/>.
+ *
+ */
+
+#include <QtCore/QString>
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+#include <QtGui/QGraphicsItem>
+#include <math.h>
+#include "flickereffect.h"
+
+namespace
+{
+ Effect::AttributeDetails ATTRIBUTES[FlickerEffect::ATTRIBUTE_COUNT] =
+ {
+ {"interval", true}
+ };
+}
+
+FlickerEffect::FlickerEffect(): QObject(0), Effect(), interval_(500), timer_(0), item_(0)
+{
+}
+
+FlickerEffect::~FlickerEffect()
+{
+ delete timer_;
+}
+
+bool FlickerEffect::setAttribute(QString const& name, QString const& value)
+{
+ qreal realVal = 0;
+ int attrId = -1;
+
+ if((attrId = getAttribute(name, value, ATTRIBUTES, ATTRIBUTE_COUNT, realVal)) != -1)
+ {
+ Attribute attr = static_cast<Attribute>(attrId);
+
+ switch(attr)
+ {
+ case INTERVAL:
+ interval_ = round(realVal);
+ break;
+ default:
+ qDebug() << "Unknown attribute: " << attr;
+ return false;
+ }
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void FlickerEffect::apply(QGraphicsItem* item)
+{
+ if(interval_ > 0)
+ {
+ item_ = item;
+ timer_ = new QTimer;
+ timer_->setInterval(interval_);
+ connect(timer_, SIGNAL(timeout()), this, SLOT(updateVisibility()));
+ timer_->start();
+ }
+}
+
+void FlickerEffect::updateVisibility()
+{
+ if(item_)
+ {
+ item_->setVisible(!item_->isVisible());
+ }
+}
--- /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 FLICKEREFFECT_H
+#define FLICKEREFFECT_H
+
+#include <QtCore/QObject>
+#include "effect.h"
+
+class QString;
+class QGraphicsItem;
+class QTimer;
+
+class FlickerEffect : public QObject, public Effect
+{
+ Q_OBJECT
+
+public:
+ enum Attribute {INTERVAL, ATTRIBUTE_COUNT};
+ FlickerEffect();
+ ~FlickerEffect();
+ virtual bool setAttribute(QString const& name, QString const& value);
+ virtual void apply(QGraphicsItem* item);
+
+private slots:
+ void updateVisibility();
+
+private:
+ int interval_;
+ QTimer* timer_;
+ QGraphicsItem* item_;
+};
+
+#endif
#include "imageelement.h"
#include "rectangle.h"
#include "pointer.h"
+#include "compass.h"
#include "settings.h"
#include "effect.h"
+#include "poialerts.h"
+#include "speedalarm.h"
-GraphicsElement::GraphicsElement(Reader* reader): reader_(reader), error_(""), effect_(0)
+GraphicsElement::GraphicsElement(Reader* reader): QObject(0), reader_(reader), error_(""), effect_(0), visibleWhen_(ALWAYS)
{
}
return new Pointer(reader, animate);
}
+ if(name == "compass")
+ {
+ bool animate = Settings::instance().value("animate_pointer", true).toBool();
+ return new Compass(reader, animate);
+ }
+
qDebug() << "Element not found: " << name;
return 0;
}
bool GraphicsElement::setEffect(QString const& name)
{
- /* QGraphicsDropShadowEffect* eff = new QGraphicsDropShadowEffect;
- eff->setOffset(1);
- eff->setBlurRadius(3);
-
- getElement()->setGraphicsEffect(eff);
-
- return true;*/
-
effect_ = Effect::getEffect(name);
if(!effect_)
bool GraphicsElement::setEffectAttribute(QString const& name, QString const& value)
{
- //return true;
if(!effect_)
{
qDebug() << "Effect not set";
void GraphicsElement::applyEffect()
{
- //return;
effect_->apply(getElement());
}
+
+void GraphicsElement::setVisibleWhen(VisibleWhen when)
+{
+ if(when != visibleWhen_)
+ {
+ visibleWhen_ = when;
+
+ switch(when)
+ {
+ case POI_VISIBLE:
+ connect(&(PoiAlerts::instance()), SIGNAL(visibilityChanged(bool)), this, SLOT(updateVisibility(bool)));
+ break;
+ case SPEED_EXCEEDED:
+ connect(&(SpeedAlarm::instance()), SIGNAL(speedExceedChanged(bool)), this, SLOT(updateVisibility(bool)));
+ break;
+ case ALWAYS:
+ disconnect(&(PoiAlerts::instance()), SIGNAL(visibilityChanged(bool)), this, SLOT(updateVisibility(bool)));
+ disconnect(&(SpeedAlarm::instance()), SIGNAL(speedExceedChanged(bool)), this, SLOT(updateVisibility(bool)));
+ break;
+ }
+ }
+}
+
+GraphicsElement::VisibleWhen GraphicsElement::strToVisibleWhen(QString const& str) const
+{
+ if(str == "poivisible")
+ {
+ return POI_VISIBLE;
+ }
+ else if(str == "speedexceeded")
+ {
+ return SPEED_EXCEEDED;
+ }
+
+ return ALWAYS;
+}
+
+void GraphicsElement::updateVisibility(bool visible)
+{
+ QGraphicsItem* item = getElement();
+
+ if(item)
+ {
+ item->setVisible(visible);
+ }
+}
#ifndef GRAPHICSELEMENT_H
#define GRAPHICSELEMENT_H
+#include <QtCore/QObject>
#include <QtCore/QMap>
-#include "location.h"
class QString;
class QByteArray;
class Reader;
class Effect;
-class GraphicsElement
+class GraphicsElement : public QObject
{
+ Q_OBJECT
+
public:
struct AttributeDetails
void applyEffect();
protected:
+ enum VisibleWhen {ALWAYS, POI_VISIBLE, SPEED_EXCEEDED};
+
int getAttribute(QString const& name, QString const& value, const AttributeDetails details[], int count, int& intValue);
void setError(QString const& error);
bool readFile(QString const& name, QByteArray& data);
bool getFont(QString const& name, QFont& font);
+ void setVisibleWhen(VisibleWhen when);
+ VisibleWhen strToVisibleWhen(QString const& str) const;
+
+private slots:
+ void updateVisibility(bool visible);
private:
Reader* reader_;
QString error_;
Effect* effect_;
QMap<QString, QString> loadedFonts_;
+ VisibleWhen visibleWhen_;
};
#endif
namespace
{
int const PADDING = 6;
+ QString const BACKGROUND_COLOR = "#000";
}
GraphicsScreen::GraphicsScreen(QWidget* parent): QGraphicsView(parent),
scene_ = new GraphicsScene(QRect(QPoint(0, 0), rect.size()));
setScene(scene_);
+ setBackgroundBrush(QBrush(QColor(BACKGROUND_COLOR)));
+
connect(scene_, SIGNAL(clicked()), this, SIGNAL(clicked()));
minimizeButton_ = new ToolbarItem(":/resources/minimize.png", ":/resources/minimize_active.png");
{
QApplication::processEvents();
update();
+ viewport()->update();
QApplication::processEvents();
}
{"xpos", true},
{"ypos", true},
{"zpos", true},
+ {"visiblewhen", false},
{"src", false},
{"width", true},
{"height", true}
case ZPOS:
element_->setZValue(intVal);
break;
+ case VISIBLEWHEN:
+ setVisibleWhen(strToVisibleWhen(value));
+ break;
case SRC:
return loadImage(value);
break;
class ImageElement : public GraphicsElement
{
public:
- enum Attribute {XPOS, YPOS, ZPOS, SRC, WIDTH, HEIGHT, ATTRIBUTE_COUNT};
+ enum Attribute {XPOS, YPOS, ZPOS, VISIBLEWHEN, SRC, WIDTH, HEIGHT, ATTRIBUTE_COUNT};
ImageElement(Reader* reader);
virtual bool setAttribute(QString const& name, QString const& value);
virtual void addToScene(GraphicsScene* scene);
{
setWindowTitle(tr("jSpeed"));
showFullScreen();
- Odometer::instance().start();
- PoiAlerts::instance().start();
- SpeedAlarm::instance().start();
addScreens();
- startBacklight();
+ QTimer::singleShot(500, this, SLOT(loadServices()));
}
MainWindow::~MainWindow()
delete themeLoader_;
}
+void MainWindow::loadServices()
+{
+ Odometer::instance().start();
+ QApplication::processEvents();
+ PoiAlerts::instance().start();
+ QApplication::processEvents();
+ SpeedAlarm::instance().start();
+ QApplication::processEvents();
+ startBacklight();
+}
+
void MainWindow::addScreens()
{
stack_ = new MainWindowStack(this);
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();
void quit();
private slots:
+ void loadServices();
void minimize();
void openMenu();
void keepBacklightOn();
return result.trimmed();
}
+QStringList MediaPlayer::getFormatPatterns()
+{
+ QStringList result;
+
+ for(int i = 0; i < FORMAT_COUNT; i++)
+ {
+ result.push_back("*." + FORMATS[i]);
+ }
+
+ return result;
+}
+
QString MediaPlayer::getSoundDir()
{
return Settings::getDir() + "sounds" + QDir::separator();
#define MEDIAPLAYER_H
#include <QtCore/QString>
+#include <QtCore/QStringList>
#include <QtCore/QList>
#include <QMediaPlayer>
static bool play(QString const& file);
static void getSupportedFormats(QList<QString>& formats);
static QString getFormatPattern();
+ static QStringList getFormatPatterns();
static QString getSoundDir();
static QString const& getLocalSoundDir();
QString const MILE_UNIT = "mi";
QString const KM_SPEEDUNIT = "km/h";
QString const MILE_SPEEDUNIT = "mph";
+ QString const METER_UNIT = "m";
+ QString const FEET_UNIT = "feet";
+ double const FEET_MULTIPLIER = 3.2808399;
+ double const METER_MULTIPLIER = 1.0;
static const int FIX_TIMEOUT = 4000;
double const DEFAULT_SPEED_TRESHOLD = 8.0;
double const MIN_SPEED_TRESHOLD = 0.8;
return Location::getUnitMultiplier();
}
+double Odometer::getMeterMultiplier()
+{
+ if(Location::getUnit() == Location::KM)
+ {
+ return METER_MULTIPLIER;
+ }
+ else
+ {
+ return FEET_MULTIPLIER;
+ }
+}
+
+QString Odometer::getMeterUnit()
+{
+ if(Location::getUnit() == Location::KM)
+ {
+ return METER_UNIT;
+ }
+ else
+ {
+ return FEET_UNIT;
+ }
+}
+
void Odometer::updateUnit()
{
QString unit = Settings::instance().value("unit", "km").toString();
static QString const& getUnit();
static QString const& getSpeedUnit();
static double getUnitMultiplier();
+ static double getMeterMultiplier();
+ static QString getMeterUnit();
signals:
void dataUpdated();
return rad * 180 / PI;
}
+inline static double absValue(double value)
+{
+ if(value < 0.0)
+ {
+ return -value;
+ }
+
+ return value;
+}
+
PoiAlerts::PoiAlerts(): QObject(0), enabled_(false), currentPoi_(0), loaded_(false)
{
}
return true;
}
- distance_ = Settings::instance().value("alert_distance", 300).toBool();
+ distance_ = Settings::instance().value("alert_distance", 300).toDouble();
onlyOnRoute_ = Settings::instance().value("alert_only_on_route", true).toBool();
if(distance_ < 0)
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)
+ if(fix->latitude < 0.01 || fix->longitude < 0.01 ||
+ fix->kmSpeed < 0.01 || isnan(fix->eph))
{
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;
+ double travelled = Odometer::instance().getTotal();
- if(1 == 1 || abs(travelled - travelled_) > 0.03)
+ if(absValue(travelled - travelled_) > 0.02)
{
+ double distance;
+ double inRouteMargin = IN_ROUTE_MARGIN + (fix->eph / 1000.0);
+
+ bool found = false;
+
travelled_ = travelled;
for(int i = 0; i < pois_.size(); i++)
if(onlyOnRoute_)
{
- double track = abs(calculateTrack(fix->latitude, fix->longitude,
- pois_.at(i).latitude, pois_.at(i).longitude) - fix->track);
+ double track = absValue(calculateTrack(fix->latitude, fix->longitude,
+ pois_.at(i).latitude, pois_.at(i).longitude) - fix->track);
if(track > 180)
{
}
qDebug() << "Real track: " << track;
- qDebug() << "Epd: " << fix->epd;
double trackLimit;
}
else
{
- trackLimit = 90.0 - radToDeg(acos((inRouteMargin + (distance * 0.15)) / distance));
+ trackLimit = 90.0 - radToDeg(acos((inRouteMargin + (distance * 0.16)) / distance));
}
qDebug() << "Tracklimit: " << trackLimit;
if(track < trackLimit)
{
+ found = true;
currentPoi_ = &pois_[i];
currentDistance_ = distance;
+ emit visibilityChanged(true);
playSound(i);
}
else
{
currentPoi_ = 0;
+ emit visibilityChanged(false);
}
}
else
{
+ found = true;
currentPoi_ = &pois_[i];
currentDistance_ = distance;
+ emit visibilityChanged(true);
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();
+ if(!found && currentPoi_)
+ {
+ currentPoi_ = 0;
+ emit visibilityChanged(false);
+ }
+ }
}
double PoiAlerts::calculateDistance(double latitude1, double longitude1,
{
return Settings::getDir() + "pois" + QDir::separator();
}
-
~PoiAlerts();
bool start();
void end();
- void startTest();
double getCurrentDistance() const;
QString getCurrentPoi() const;
bool poiInView() const;
QString const& error() const;
+signals:
+ void visibilityChanged(bool visible);
+
public slots:
bool loadConfig();
QList<PoiReader::Poi> pois_;
QQueue<int> playedSounds_;
bool enabled_;
- int distance_;
+ double distance_;
double travelled_;
PoiReader::Poi* currentPoi_;
double currentDistance_;
bool ok;
- QString latitude = matcher.cap(1) + "." + matcher.cap(2);
- QString longitude = matcher.cap(3) + "." + matcher.cap(4);
+ QString latitude = matcher.cap(3) + "." + matcher.cap(4);
+ QString longitude = matcher.cap(1) + "." + matcher.cap(2);
double doubleLatitude = latitude.toDouble(&ok);
{"xpos", true},
{"ypos", true},
{"zpos", true},
+ {"visiblewhen", false},
{"src", false},
{"zeroangle", true},
{"fullangle", true},
int const ANIMATION_UPDATEINTERVAL = 20;
}
-Pointer::Pointer(Reader* reader, bool animate): QObject(0), GraphicsElement(reader),
+Pointer::Pointer(Reader* reader, bool animate): GraphicsElement(reader),
xRotationPoint_(0), yRotationPoint_(0), x_(0), y_(0), zeroAngle_(0),
fullAngle_(180), zeroSpeed_(0), fullSpeed_(220), targetAngle_(0),
startAngle_(0), angle_(-1), imageSet_(false), animate_(animate), timer_(0)
case ZPOS:
element_->setZValue(intVal);
break;
+ case VISIBLEWHEN:
+ setVisibleWhen(strToVisibleWhen(value));
+ break;
case SRC:
return loadImage(value);
break;
class GraphicsScene;
class Reader;
-class Pointer : public QObject, public GraphicsElement
+class Pointer : public GraphicsElement
{
Q_OBJECT
public:
- enum Attribute {XPOS, YPOS, ZPOS, SRC, ZEROANGLE, FULLANGLE, ZEROSPEED, FULLSPEED, XROTATIONPOINT, YROTATIONPOINT, ATTRIBUTE_COUNT};
+ enum Attribute {XPOS, YPOS, ZPOS, VISIBLEWHEN, SRC, ZEROANGLE, FULLANGLE, ZEROSPEED, FULLSPEED, XROTATIONPOINT, YROTATIONPOINT, ATTRIBUTE_COUNT};
Pointer(Reader* reader, bool animate);
~Pointer();
virtual bool setAttribute(QString const& name, QString const& value);
#include <QtGui/QLineEdit>
#include <QtGui/QIntValidator>
#include <QMaemo5InformationBox>
+#include <math.h>
#include "poisettings.h"
#include "fileselector.h"
#include "poialerts.h"
#include "poireader.h"
#include "buttonbox.h"
#include "soundselector.h"
+#include "odometer.h"
PoiSettings::PoiSettings(QWidget* parent): QDialog(parent)
soundSelector_ = new SoundSelector;
- QLabel* distanceLabel = new QLabel(tr("Alert distance"));
+ distanceLabel_ = new QLabel;
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(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);
+ connect(buttons->addButton(tr("Save"), QDialogButtonBox::AcceptRole), SIGNAL(clicked(bool)), this, SLOT(saveSettings()));
QHBoxLayout* layout = new QHBoxLayout;
QVBoxLayout* left = new QVBoxLayout;
left->addWidget(enabled_);
left->addLayout(poiLayout);
- left->addWidget(soundSelector_);
+ left->addLayout(soundSelector_);
left->addLayout(distance);
left->addWidget(onlyOnRoute_);
void PoiSettings::loadFiles()
{
+ distanceLabel_->setText((tr("Alert distance (%1)").arg(Odometer::getMeterUnit())));
+ int speedValue = round(Settings::instance().value("alert_distance", 300).toDouble() * Odometer::getMeterMultiplier());
+ distance_->setText(QString::number(speedValue));
+
QDir poiDir(PoiAlerts::getPoiDir());
QString selectedSound = Settings::instance().value("alert_sound", "").toString();
+ soundSelector_->load();
soundSelector_->setValue(selectedSound);
poiFileSelector_->clear();
return;
}
+ double distance = distance_->text().toInt() / Odometer::getMeterMultiplier();
+
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_distance", distance);
Settings::instance().setValue("alert_sound", soundSelector_->value());
Settings::instance().setValue("alert_poi_file", poiFileSelector_->value());
#include <QtGui/QDialog>
class QLineEdit;
+class QLabel;
class QCheckBox;
class SoundSelector;
class FileSelector;
FileSelector* poiFileSelector_;
SoundSelector* soundSelector_;
QLineEdit* distance_;
+ QLabel* distanceLabel_;
QCheckBox* onlyOnRoute_;
};
{"xpos", true},
{"ypos", true},
{"zpos", true},
+ {"visiblewhen", false},
{"width", true},
{"height", true},
{"color", false}
case ZPOS:
element_->setZValue(intVal);
break;
+ case VISIBLEWHEN:
+ setVisibleWhen(strToVisibleWhen(value));
+ break;
case WIDTH:
width_ = intVal;
break;
class Rectangle : public GraphicsElement
{
public:
- enum Attribute {XPOS, YPOS, ZPOS, WIDTH, HEIGHT, COLOR, ATTRIBUTE_COUNT};
+ enum Attribute {XPOS, YPOS, ZPOS, VISIBLEWHEN, WIDTH, HEIGHT, COLOR, ATTRIBUTE_COUNT};
Rectangle(Reader* reader);
virtual bool setAttribute(QString const& name, QString const& value);
virtual void addToScene(GraphicsScene* scene);
<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>
#include "fileselector.h"
#include "mediaplayer.h"
-SoundSelector::SoundSelector(QWidget* parent): QWidget(parent)
+SoundSelector::SoundSelector(QWidget* parent): QHBoxLayout(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);
+ addWidget(selector_, Qt::AlignLeft);
+ addWidget(playButton);
}
void SoundSelector::playSound()
}
}
-void SoundSelector::setVisible(bool visible)
+void SoundSelector::load()
{
- 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);
+ QString currentValue = selector_->value().toString();
+ selector_->clear();
+ QStringList patterns = MediaPlayer::getFormatPatterns();
+ selector_->loadFiles(MediaPlayer::getLocalSoundDir(), patterns);
+ selector_->loadFiles(MediaPlayer::getSoundDir(), patterns);
+ setValue(currentValue);
}
void SoundSelector::setValue(QString const& value)
#ifndef SOUNDSELECTOR_H
#define SOUNDSELECTOR_H
-#include <QtGui/QWidget>
+#include <QtGui/QHBoxLayout>
class FileSelector;
-class SoundSelector : public QWidget
+class SoundSelector : public QHBoxLayout
{
Q_OBJECT
public slots:
void setValue(QString const& value);
QString value() const;
-
-protected:
- virtual void setVisible(bool visible);
+ void load();
private slots:
void playSound();
*/
#include <QtCore/QFile>
-#include <QMediaPlayer>
+#include <QtCore/QTimer>
#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(): QObject(0), loaded_(false),
+enabled_(false), isOver_(false), timer_(0)
+{
+}
+
+SpeedAlarm::~SpeedAlarm()
{
+ delete timer_;
}
SpeedAlarm& SpeedAlarm::instance()
return;
}
- threshold_ = Settings::instance().value("alarm_threshold", 0).toInt();
+ threshold_ = Settings::instance().value("alarm_threshold", 0).toDouble();
start();
}
{
MediaPlayer::play(soundFile_);
isOver_ = true;
+ emit speedExceedChanged(true);
+ startAlarmTimer();
}
}
else
{
+ if(isOver_)
+ {
+ emit speedExceedChanged(false);
+ }
+
isOver_ = false;
}
}
+
+void SpeedAlarm::startAlarmTimer()
+{
+ if(timer_)
+ {
+ timer_->stop();
+ delete timer_;
+ timer_ = 0;
+ }
+
+ timer_ = new QTimer;
+ timer_->setInterval(ALARM_INTERVAL * 1000);
+ connect(timer_, SIGNAL(timeout()), this, SLOT(playAlarmSound()));
+ timer_->start();
+}
+
+void SpeedAlarm::playAlarmSound()
+{
+ if(isOver_)
+ {
+ MediaPlayer::play(soundFile_);
+ }
+ else
+ {
+ delete timer_;
+ timer_ = 0;
+ }
+}
#include <QtCore/QObject>
+class QTimer;
+
class SpeedAlarm : public QObject
{
Q_OBJECT
public:
+ ~SpeedAlarm();
+ static int const ALARM_INTERVAL = 15;
static SpeedAlarm& instance();
void start();
void end();
+signals:
+ void speedExceedChanged(bool exceeded);
+
public slots:
void loadConfig();
private slots:
void onDataUpdated();
+ void playAlarmSound();
private:
SpeedAlarm();
+ void startAlarmTimer();
bool loaded_;
QString soundFile_;
- int threshold_;
+ double threshold_;
bool enabled_;
bool isOver_;
+ QTimer* timer_;
};
#endif
enabled_->setChecked(Settings::instance().value("alarm_enabled", false).toBool());
ButtonBox* buttons = new ButtonBox;
- buttons->addButton(tr("Save"), this, SLOT(saveSettings()), QDialogButtonBox::AcceptRole);
+ connect(buttons->addButton(tr("Save"), QDialogButtonBox::AcceptRole), SIGNAL(clicked(bool)), this, SLOT(saveSettings()));
QHBoxLayout* layout = new QHBoxLayout;
QVBoxLayout* left = new QVBoxLayout;
left->addLayout(speedLayout);
- left->addWidget(soundSelector_);
+ left->addLayout(soundSelector_);
left->addWidget(enabled_);
layout->addLayout(left, Qt::AlignLeft);
layout->addWidget(buttons);
speed_->setText(QString::number(static_cast<int>(speedValue)));
QString selected = Settings::instance().value("alarm_sound", "").toString();
+ soundSelector_->load();
soundSelector_->setValue(selected);
}
#include "reader.h"
#include "odometer.h"
#include "graphicsscene.h"
+#include "poialerts.h"
namespace
{
{"xpos", true},
{"ypos", true},
{"zpos", true},
+ {"visiblewhen", false},
{"data", false},
{"format", false},
{"width", true},
const QString FIELDS[TextElement::FIELD_COUNT] = {"TRIP", "TOTAL", "SPEED",
"MAXSPEED", "AVGSPEED",
- "UNIT", "SPEEDUNIT", "TIME", "DATE"};
+ "UNIT", "SPEEDUNIT", "TIME", "DATE",
+ "POIDISTANCE", "ANGLE", "LATITUDE",
+ "LONGITUDE"};
}
TextElement::TextElement(Reader* reader): GraphicsElement(reader),
case ZPOS:
element_->setZValue(intVal);
break;
+ case VISIBLEWHEN:
+ setVisibleWhen(strToVisibleWhen(value));
+ break;
case DATA:
data_ = value;
break;
case DATE:
replaceValue(value, f, QDate::currentDate().toString(dateFormat_));
break;
+ case POIDISTANCE:
+ replaceValue(value, f, handleEmpty(PoiAlerts::instance().getCurrentDistance()));
+ break;
+ case ANGLE:
+ replaceValue(value, f, formatString(o->getLatestFix().track));
+ break;
+ case LATITUDE:
+ replaceValue(value, f, handleEmpty(o->getLatestFix().latitude));
+ break;
+ case LONGITUDE:
+ replaceValue(value, f, handleEmpty(o->getLatestFix().longitude));
+ break;
default:
qDebug() << "Unknown field: " << f;
}
}
}
+QString TextElement::handleEmpty(double value)
+{
+ if(value < 0.01)
+ {
+ return "";
+ }
+
+ return formatString(value);
+}
+
void TextElement::replaceValue(QString& value,
TextElement::Field field,
QString const& replace)
class TextElement : public GraphicsElement
{
public:
- enum Attribute {XPOS, YPOS, ZPOS, DATA, FORMAT, WIDTH, ALIGN, COLOR, SIZE, FONT, BOLD, ITALIC, UPPERCASE, LETTERSPACING, TIMEFORMAT, DATEFORMAT, ATTRIBUTE_COUNT};
- enum Field {TRIP, TOTAL, SPEED, MAXSPEED, AVGSPEED, UNIT, SPEEDUNIT, TIME, DATE, FIELD_COUNT};
+ enum Attribute {XPOS, YPOS, ZPOS, VISIBLEWHEN, DATA, FORMAT, WIDTH, ALIGN, COLOR, SIZE, FONT, BOLD, ITALIC, UPPERCASE, LETTERSPACING, TIMEFORMAT, DATEFORMAT, ATTRIBUTE_COUNT};
+ enum Field {TRIP, TOTAL, SPEED, MAXSPEED, AVGSPEED, UNIT, SPEEDUNIT, TIME, DATE, POIDISTANCE, ANGLE, LATITUDE, LONGITUDE, FIELD_COUNT};
TextElement(Reader* reader);
virtual bool setAttribute(QString const& name, QString const& value);
virtual void addToScene(GraphicsScene* scene);
virtual QGraphicsItem* getElement() const;
private:
+ QString handleEmpty(double value);
void updateHtml(QString data);
void replaceSpecialFields(QString& value);
void replaceValue(QString& value, Field field, QString const& replace);
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);
+ connect(buttons->addButton(tr("Save"), QDialogButtonBox::AcceptRole), SIGNAL(clicked(bool)), this, SLOT(saveSettings()));
+ connect(buttons->addButton(tr("Add new theme"), QDialogButtonBox::ActionRole), SIGNAL(clicked(bool)), this, SLOT(openAddDialog()));
+ connect(buttons->addButton(tr("Clear scheduler"), QDialogButtonBox::ActionRole), SIGNAL(clicked(bool)), this, SLOT(clearScheduler()));
layout->addLayout(layout_, Qt::AlignLeft);
layout->addWidget(buttons);
themePicker_ = new ThemePicker(tr("Theme"));
ButtonBox* buttons = new ButtonBox;
- buttons->addButton(tr("Add"), this, SLOT(addScheduledTheme()));
+ connect(buttons->addButton(tr("Add"), QDialogButtonBox::AcceptRole), SIGNAL(clicked(bool)), this, SLOT(addScheduledTheme()));
left->addWidget(timeButton_);
left->addWidget(themePicker_);
layout->addWidget(selector_, Qt::AlignLeft);
ButtonBox* buttons = new ButtonBox;
- buttons->addButton(tr("Save"), this, SLOT(saveUnit()));
+ connect(buttons->addButton(tr("Save"), QDialogButtonBox::AcceptRole), SIGNAL(clicked(bool)), this, SLOT(saveUnit()));
layout->addWidget(buttons);
currentOrientation_ = o;
setCurrentWidget(screens_[o]);
screens_[o]->reArrange();
-
- if(o == LANDSCAPE)
- {
- screens_[o]->forceRepaint();
- }
+ screens_[o]->forceRepaint();
}
}
}