From 43593f6d4b59904013f7b4f4a9d5eb4adad209e9 Mon Sep 17 00:00:00 2001 From: Niels Date: Mon, 21 Jun 2010 23:38:54 +0200 Subject: [PATCH] split painting code into layer classes add time and battery status display --- abstractlayer.cpp | 78 +++++++++++ abstractlayer.h | 64 +++++++++ batterylayer.cpp | 96 +++++++++++++ batterylayer.h | 48 +++++++ gpxlayer.cpp | 141 +++++++++++++++++++ gpxlayer.h | 47 +++++++ mainwidget.cpp | 55 +++++--- mainwidget.h | 3 - mapwidget.cpp | 338 ++++++++++++---------------------------------- mapwidget.h | 39 ++---- markerlayer.cpp | 126 +++++++++++++++++ markerlayer.h | 55 ++++++++ markerlist.h | 1 + nanomap.pro | 12 ++ projection.cpp | 54 ++++++++ projection.h | 35 +++++ timelayer.cpp | 53 ++++++++ timelayer.h | 45 ++++++ 18 files changed, 992 insertions(+), 298 deletions(-) create mode 100644 abstractlayer.cpp create mode 100644 abstractlayer.h create mode 100644 batterylayer.cpp create mode 100644 batterylayer.h create mode 100644 gpxlayer.cpp create mode 100644 gpxlayer.h create mode 100644 markerlayer.cpp create mode 100644 markerlayer.h create mode 100644 projection.cpp create mode 100644 projection.h create mode 100644 timelayer.cpp create mode 100644 timelayer.h diff --git a/abstractlayer.cpp b/abstractlayer.cpp new file mode 100644 index 0000000..bd3ef4d --- /dev/null +++ b/abstractlayer.cpp @@ -0,0 +1,78 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "abstractlayer.h" + +#include "mapwidget.h" + +AbstractLayer::AbstractLayer(MapWidget *map) : + QObject(map), + m_map(map), + m_visible(true) +{ +} + +void AbstractLayer::load(const QString &filename) +{ + Q_UNUSED(filename) +} + +void AbstractLayer::zoom(int level) +{ + Q_UNUSED(level) +} + +void AbstractLayer::pan(const QPoint &move) +{ + Q_UNUSED(move) +} + +void AbstractLayer::triggerAction() +{ +} + +void AbstractLayer::paintLayer(QPainter *painter) +{ + if (m_visible) { + painter->save(); + paint(painter); + painter->restore(); + } +} + +MapWidget *AbstractLayer::map() const +{ + return m_map; +} + +bool AbstractLayer::isVisible() const +{ + return m_visible; +} + +void AbstractLayer::setVisible(bool visible) +{ + m_visible = visible; +} + +void AbstractLayer::toggleVisibility() +{ + m_visible = !m_visible; +} + diff --git a/abstractlayer.h b/abstractlayer.h new file mode 100644 index 0000000..f9a08bb --- /dev/null +++ b/abstractlayer.h @@ -0,0 +1,64 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef ABSTRACT_LAYER_H +#define ABSTRACT_LAYER_H + +#include +#include + +class MapWidget; + +enum Layer +{ + Tracks, + Marker, + Time, + System, + User +}; + +class AbstractLayer : public QObject +{ + Q_OBJECT +public: + AbstractLayer(MapWidget *map); + + virtual void load(const QString &filename); + virtual void zoom(int level); + virtual void pan(const QPoint &move); + virtual void triggerAction(); + + void paintLayer(QPainter *painter); + + MapWidget *map() const; + bool isVisible() const; + void setVisible(bool visible = true); + void toggleVisibility(); + +protected: + virtual void paint(QPainter *painter) = 0; + +private: + MapWidget *m_map; + bool m_visible; + +}; + +#endif // ABSTRACT_LAYER_H diff --git a/batterylayer.cpp b/batterylayer.cpp new file mode 100644 index 0000000..824e2d1 --- /dev/null +++ b/batterylayer.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "batterylayer.h" + +#include "mapwidget.h" + +#include +#include +//#include +#include +#include + +BatteryLayer::BatteryLayer(MapWidget *map) : + AbstractLayer(map), + m_updateTimer(new QTimer(this)), + m_percent(0), + m_isCharging(false) +{ + m_updateTimer->setInterval(60 * 1000); + connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(repaint())); + m_updateTimer->start(); + +// QFileSystemWatcher *w = new QFileSystemWatcher(this); +// w->addPath("/sys/class/power_supply/battery/capacity"); +// w->addPath("/sys/class/power_supply/battery/status"); +// connect(w, SIGNAL(fileChanged(QString)), this, SLOT(fileChanged(QString))); + + repaint(); +} + +void BatteryLayer::paint(QPainter *painter) +{ + int w = map()->width(); + int h = map()->height(); + + painter->setBrush(QBrush(QColor(255, 255, 255, 210))); + painter->drawRoundedRect(w - 111, h - 17, 110, 16, 5, 5); + painter->drawText(w - 101, h - 15, 90, 14, Qt::AlignCenter, QString("%1%").arg(m_percent)); + if (m_isCharging) { + painter->setBrush(QBrush(QColor(0, 255, 0, 110))); + } else { + painter->setBrush(QBrush(QColor(0, 0, 255, 110))); + } + painter->drawRoundedRect(w - 111, h - 17, 10 + m_percent, 16, 5, 5); +} + +void BatteryLayer::repaint() +{ + if (isVisible()) { + int percent = m_percent; + QFile capacity("/sys/class/power_supply/battery/capacity"); + if (capacity.open(QFile::ReadOnly | QFile::Text)) { + QTextStream in(&capacity); + QString l = in.readLine(); + percent = l.toInt(); + } + + bool charging = m_isCharging; + QFile status("/sys/class/power_supply/battery/status"); + if (status.open(QFile::ReadOnly | QFile::Text)) { + QTextStream in(&status); + QString l = in.readLine().toLower(); + charging = (l == "charging"); + } + + if (charging != m_isCharging || percent != m_percent) { + m_percent = percent; + m_isCharging = charging; + map()->update(); + } + } +} + +void BatteryLayer::fileChanged(const QString &filename) +{ + qDebug() << filename; + repaint(); +} + diff --git a/batterylayer.h b/batterylayer.h new file mode 100644 index 0000000..e368f4c --- /dev/null +++ b/batterylayer.h @@ -0,0 +1,48 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef BATTERY_LAYER_H +#define BATTERY_LAYER_H + +#include "abstractlayer.h" + +#include +#include + +class BatteryLayer : public AbstractLayer +{ + Q_OBJECT +public: + BatteryLayer(MapWidget *map); + +protected: + virtual void paint(QPainter *painter); + +private slots: + void repaint(); + void fileChanged(const QString &filename); + +private: + QTimer *m_updateTimer; + int m_percent; + bool m_isCharging; + +}; + +#endif // BATTERY_LAYER_H diff --git a/gpxlayer.cpp b/gpxlayer.cpp new file mode 100644 index 0000000..ecd49e0 --- /dev/null +++ b/gpxlayer.cpp @@ -0,0 +1,141 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "gpxlayer.h" + +#include "mapwidget.h" +#include "projection.h" + +#include +#include +#include + +GpxLayer::GpxLayer(MapWidget *map) : + AbstractLayer(map) +{ +} + +void GpxLayer::load(const QString &filename) +{ + QFile file(filename); + if (file.open(QIODevice::ReadOnly)) { + QXmlStreamReader xml(&file); + + QPolygonF points; + QList elev; + QList time; + + QString tag, tag2; + QString name; + QPointF pos; + while (!xml.atEnd()) { + xml.readNext(); + if (xml.isStartElement()) { + if (xml.name() == "trkpt") { + tag = "trkpt"; + float lat = xml.attributes().value("lat").toString().toFloat(); + float lon = xml.attributes().value("lon").toString().toFloat(); + + points << QPointF(Projection::lon2rawx(lon), Projection::lat2rawy(lat)); + } else if (xml.name() == "ele") { + tag2 = "ele"; + } else if (xml.name() == "time") { + tag2 = "time"; + } else if (xml.name() == "wpt") { + tag = "wpt"; + float lat = xml.attributes().value("lat").toString().toFloat(); + float lon = xml.attributes().value("lon").toString().toFloat(); + + pos = QPointF(lon, lat); + } else if (xml.name() == "name") { + tag2 = "name"; + } else if (xml.name() == "trk" || + xml.name() == "trkseg") { + } else { + tag2.clear(); + } + } else if (xml.isEndElement()) { + if (xml.name() == "trkseg") { + if (!points.isEmpty()) { + m_track << points; + m_track << QPointF(); + } + points.clear(); + elev.clear(); + time.clear(); + } else if (xml.name() == "wpt") { + //addMarker(pos, name); + name.clear(); + } + } else if (xml.isCharacters() && !xml.isWhitespace()) { + if (tag == "trkpt") { + if (tag2 == "ele") { + elev << xml.text().toString().toFloat(); + } else if (tag2 == "time") { + QDateTime dt = QDateTime::fromString(xml.text().toString(), Qt::ISODate); + time << dt.toTime_t(); + } + } else if (tag == "wpt") { + if (tag2 == "name") { + name = xml.text().toString(); + } + } + } + } + zoom(0); + } +} + +void GpxLayer::zoom(int level) +{ + if (m_track.count() > 1) { + int scale = 1 << level; + m_trackOnScreen.clear(); + m_trackOffset = map()->raw2screen(m_track.first().x(), m_track.first().y(), scale); + m_trackOnScreen << QPoint(0, 0); + for (int i = 1; i < m_track.count(); ++i) { + QPointF p = m_track.at(i); + if (!p.isNull()) { + m_trackOnScreen << map()->raw2screen(p.x(), p.y(), scale) - m_trackOffset; + } else { + m_trackOnScreen << QPoint(); + } + } + } +} + +void GpxLayer::pan(const QPoint &move) +{ + m_trackOffset += move; +} + +void GpxLayer::paint(QPainter *painter) +{ + if (m_trackOnScreen.count() > 1) { + QPoint p1, p2 = m_trackOnScreen.first(); + for (int i = 1; i < m_trackOnScreen.count(); ++i) { + p1 = m_trackOnScreen.at(i); + if (!p1.isNull()) { + painter->drawLine(p1 + m_trackOffset, p2 + m_trackOffset); + p2 = p1; + } + } + } +} + diff --git a/gpxlayer.h b/gpxlayer.h new file mode 100644 index 0000000..c402d07 --- /dev/null +++ b/gpxlayer.h @@ -0,0 +1,47 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef GPX_LAYER_H +#define GPX_LAYER_H + +#include "abstractlayer.h" + +#include + +class GpxLayer : public AbstractLayer +{ + Q_OBJECT +public: + GpxLayer(MapWidget *map); + + virtual void load(const QString &filename); + virtual void zoom(int level); + virtual void pan(const QPoint &move); + +protected: + virtual void paint(QPainter *painter); + +private: + QPolygonF m_track; + QList m_trackOnScreen; + QPoint m_trackOffset; + +}; + +#endif // GPX_LAYER_H diff --git a/mainwidget.cpp b/mainwidget.cpp index fc10af1..f7ed106 100644 --- a/mainwidget.cpp +++ b/mainwidget.cpp @@ -23,6 +23,13 @@ #include "mapwidget.h" #include "markerlist.h" +#include "batterylayer.h" +#include "gpxlayer.h" +#include "markerlayer.h" +#include "timelayer.h" + +#include +#include #include MainWidget::MainWidget(QWidget *parent) @@ -32,19 +39,43 @@ MainWidget::MainWidget(QWidget *parent) m_markerList(new MarkerList(this)), m_dlWidget(new DownloadWidget(this)) { + QString fileName; + if (QApplication::arguments().count() > 1) { + fileName = QApplication::arguments().at(1); + } + QHBoxLayout *layout = new QHBoxLayout(this); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(m_stack); + AbstractLayer *l = new TimeLayer(m_map); + l->setVisible(false); + m_map->addLayer(Time, l); + + l = new BatteryLayer(m_map); + l->setVisible(false); + m_map->addLayer(System, l); + + l = new GpxLayer(m_map); + if (fileName.endsWith(".gpx")) { + l->load(fileName); + } + m_map->addLayer(Tracks, l); + + l = new MarkerLayer(m_map); + connect(l, SIGNAL(markerAdded(QString)), m_markerList, SLOT(addMarker(QString))); + connect(m_markerList, SIGNAL(centerOnMarker(int)), l, SLOT(centerOnMarker(int))); + connect(m_markerList, SIGNAL(removeMarker(int)), l, SLOT(removeMarker(int))); + connect(m_markerList, SIGNAL(markerRenamed(int, QString)), l, SLOT(renameMarker(int, QString))); + l->load(QDir::homePath()+"/Maps/marker.list"); + m_map->addLayer(Marker, l); + connect(m_map, SIGNAL(showMarkerList()), this, SLOT(showList())); - connect(m_map, SIGNAL(markerAdded(QString)), this, SLOT(markerAdded(QString))); connect(m_map, SIGNAL(downloadArea(int, QRectF)), this, SLOT(downloadArea(int, QRectF))); m_stack->insertWidget(0, m_map); connect(m_markerList, SIGNAL(back()), this, SLOT(showMap())); - connect(m_markerList, SIGNAL(centerOnMarker(int)), this, SLOT(centerOnMarker(int))); - connect(m_markerList, SIGNAL(removeMarker(int)), this, SLOT(removeMarker(int))); - connect(m_markerList, SIGNAL(markerRenamed(int, QString)), this, SLOT(markerRenamed(int, QString))); + connect(m_markerList, SIGNAL(centerOnMarker(int)), this, SLOT(showMap())); m_stack->insertWidget(1, m_markerList); connect(m_dlWidget, SIGNAL(back()), this, SLOT(showMap())); @@ -72,22 +103,6 @@ void MainWidget::showMap() m_stack->setCurrentIndex(0); } -void MainWidget::centerOnMarker(int row) -{ - m_map->centerOnMarker(row); - m_stack->setCurrentIndex(0); -} - -void MainWidget::removeMarker(int row) -{ - m_map->removeMarker(row); -} - -void MainWidget::markerRenamed(int index, const QString &name) -{ - m_map->renameMarker(index, name); -} - void MainWidget::downloadArea(int level, const QRectF &rect) { m_dlWidget->setStartLevel(level); diff --git a/mainwidget.h b/mainwidget.h index 32067ba..a1cf8e2 100644 --- a/mainwidget.h +++ b/mainwidget.h @@ -39,9 +39,6 @@ private slots: void showList(); void markerAdded(const QString &name); void showMap(); - void centerOnMarker(int row); - void removeMarker(int row); - void markerRenamed(int index, const QString &name); void downloadArea(int level, const QRectF &rect); private: diff --git a/mapwidget.cpp b/mapwidget.cpp index c0de5b6..0bc53a4 100644 --- a/mapwidget.cpp +++ b/mapwidget.cpp @@ -19,9 +19,10 @@ #include "mapwidget.h" +#include "projection.h" + #include -#include #include #include #include @@ -36,12 +37,11 @@ #include #include #include -#include MapWidget::MapWidget(QWidget *parent) : QWidget(parent), m_usage(false), - m_infos(true), + m_ui(true), m_zoomable(false), m_baseName(), m_xPadding(0), @@ -69,12 +69,7 @@ MapWidget::MapWidget(QWidget *parent) m_manager(new QNetworkAccessManager(this)), m_networkMode(false), m_copyright(), - m_markerPos(), - m_markerName(), - m_drawMarker(true), - m_track(), - m_trackOnScreen(), - m_trackOffset() + m_layer() { for (int x = 0; x < 100; ++x) { for (int y = 0; y < 100; ++y) { @@ -115,9 +110,6 @@ MapWidget::MapWidget(QWidget *parent) m_minIndexYList << 0; m_maxIndexYList << (1 << i) - 1; } - if (fileName.endsWith(".gpx")) { - loadGpx(fileName); - } m_baseName = QDir::homePath()+"/Maps/OSM/%z/%x/%y.png"; QTimer::singleShot(100, this, SLOT(loadConfig())); } @@ -139,30 +131,9 @@ MapWidget::~MapWidget() } } -void MapWidget::removeMarker(int index) +void MapWidget::addLayer(Layer l, AbstractLayer *layer) { - if (index >= 0 && m_markerPos.count() > index) { - m_markerPos.removeAt(index); - m_markerName.removeAt(index); - update(); - } -} - -void MapWidget::renameMarker(int index, const QString &name) -{ - if (index >= 0 && m_markerName.count() > index) { - m_markerName.replace(index, name); - } -} - -void MapWidget::centerOnMarker(int index) -{ - if (index >= 0 && m_markerPos.count() > index) { - qreal lon = m_markerPos.at(index).x(); - qreal lat = m_markerPos.at(index).y(); - - centerOnGeoPos(lon, lat); - } + m_layer.insert(l, layer); } void MapWidget::resizeEvent(QResizeEvent *event) @@ -190,7 +161,9 @@ void MapWidget::resizeEvent(QResizeEvent *event) void MapWidget::mouseMoveEvent(QMouseEvent *event) { if (m_isMoving) { - m_trackOffset += (event->pos() - m_startPos) - m_pos; + foreach (AbstractLayer *l, m_layer) { + l->pan((event->pos() - m_startPos) - m_pos); + } m_pos = event->pos() - m_startPos; updatePos(); } @@ -198,19 +171,17 @@ void MapWidget::mouseMoveEvent(QMouseEvent *event) void MapWidget::mousePressEvent(QMouseEvent *event) { - if (QRect(9, 14, 13, 13).contains(event->pos())) { + if (m_ui && QRect(9, 14, 13, 13).contains(event->pos())) { changeZoomLevel(1); - updateTrack(); reloadPixmaps(); updatePos(); m_isMoving = false; - } else if (QRect(9, 214, 13, 13).contains(event->pos())) { + } else if (m_ui && QRect(9, 214, 13, 13).contains(event->pos())) { changeZoomLevel(-1); - updateTrack(); reloadPixmaps(); updatePos(); m_isMoving = false; - } else if (!QRect(5, 10, 20, 220).contains(event->pos())) { + } else if (!m_ui || !QRect(5, 10, 20, 220).contains(event->pos())) { m_startPos = event->pos() - m_pos; m_isMoving = true; } @@ -227,11 +198,9 @@ void MapWidget::wheelEvent(QWheelEvent *event) { if (event->delta() < 0) { changeZoomLevel(-1); - updateTrack(); reloadPixmaps(); } else { changeZoomLevel(1); - updateTrack(); reloadPixmaps(); } updatePos(); @@ -243,6 +212,8 @@ void MapWidget::keyPressEvent(QKeyEvent *event) int width = 10; if (event->modifiers() & Qt::AltModifier) { width = 100; + } else if (event->modifiers() & Qt::ShiftModifier) { + width = 1; } switch (event->key()) { case Qt::Key_Tab: @@ -252,15 +223,13 @@ void MapWidget::keyPressEvent(QKeyEvent *event) } case Qt::Key_M: { - if (event->modifiers() & Qt::AltModifier) { - m_drawMarker = !m_drawMarker; - } else if (event->modifiers() == Qt::NoModifier) { - int n = 0; - if (!m_markerName.isEmpty()) { - n = m_markerName.last().toInt(); + AbstractLayer *l = m_layer.value(Marker); + if (l) { + if (event->modifiers() & Qt::AltModifier) { + l->toggleVisibility(); + } else if (event->modifiers() == Qt::NoModifier) { + l->triggerAction(); } - QString newName = QString::number(n+1); - addMarker(geoPos(), newName); } break; } @@ -296,14 +265,12 @@ void MapWidget::keyPressEvent(QKeyEvent *event) case Qt::Key_O: { changeZoomLevel(-1); - updateTrack(); reloadPixmaps(); break; } case Qt::Key_I: { changeZoomLevel(1); - updateTrack(); reloadPixmaps(); break; } @@ -314,7 +281,23 @@ void MapWidget::keyPressEvent(QKeyEvent *event) } case Qt::Key_U: { - m_infos = !m_infos; + m_ui = !m_ui; + break; + } + case Qt::Key_T: + { + AbstractLayer *l = m_layer.value(Time); + if (l) { + l->toggleVisibility(); + } + break; + } + case Qt::Key_B: + { + AbstractLayer *l = m_layer.value(System); + if (l) { + l->toggleVisibility(); + } break; } case Qt::Key_Q: @@ -331,7 +314,9 @@ void MapWidget::keyPressEvent(QKeyEvent *event) } } m_pos += move; - m_trackOffset += move; + foreach (AbstractLayer *l, m_layer) { + l->pan(move); + } updatePos(); } @@ -339,63 +324,48 @@ void MapWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event) + AbstractLayer *l = 0; + QPainter painter(this); - bool empty = true; for (int x = 0; x < m_cols; ++x) { for (int y = 0; y < m_rows; ++y) { QPixmap *pix = m_pix[x][y]; if (pix) { - empty = false; QRect rect(m_pos+QPoint(m_pixWidth*x, m_pixHeight*y), pix->size()); painter.drawPixmap(rect, *pix); } } } - if (empty) { - painter.drawText(0, 0, width(), height(), Qt::AlignCenter, "No Map Loaded"); + + l = m_layer.value(Tracks); + if (l) { + l->paintLayer(&painter); } - if (m_trackOnScreen.count() > 1) { - QPoint p1, p2 = m_trackOnScreen.first(); - for (int i = 1; i < m_trackOnScreen.count(); ++i) { - p1 = m_trackOnScreen.at(i); - if (!p1.isNull()) { - painter.drawLine(p1 + m_trackOffset, p2 + m_trackOffset); - p2 = p1; - } - } + + l = m_layer.value(Marker); + if (l) { + l->paintLayer(&painter); } - if (m_drawMarker) { - int i = 0; - painter.setBrush(QBrush(QColor(255, 237, 60))); - QFontMetrics fm(painter.font()); - int h = fm.height() / 2; - foreach (const QPointF &m, m_markerPos) { - QPoint pos = geo2screen(m.x(), m.y()); - int w = fm.width(m_markerName.at(i)) / 2; - QRect rect(pos.x() - w - 2, pos.y() - h - 11, 2*w + 4, 2*h); - QPolygon polygon; - polygon << pos; - polygon << pos + QPoint(-2, -5); - polygon << rect.bottomLeft(); - polygon << rect.topLeft(); - polygon << rect.topRight(); - polygon << rect.bottomRight(); - polygon << pos + QPoint(2, -5); - polygon << pos; - painter.drawPolygon(polygon); - painter.drawText(rect, Qt::AlignCenter, m_markerName.at(i)); - ++i; - } + + l = m_layer.value(Time); + if (l) { + l->paintLayer(&painter); } - if (m_infos) { + + l = m_layer.value(System); + if (l) { + l->paintLayer(&painter); + } + + if (m_ui) { painter.setBrush(QBrush(QColor(255, 255, 255, 210))); if (m_networkMode) { - painter.drawRoundedRect(30, height() - 20, width() - 35, 19, 10, 10); + painter.drawRoundedRect(30, height() - 17, width() - 145, 16, 5, 5); QPointF geo = geoPos(); QString lon = geo.x() > 0 ? QString("E %1").arg(geo.x()) : QString("W %1").arg(-geo.x()); QString lat = geo.y() > 0 ? QString("N %1").arg(geo.y()) : QString("S %1").arg(-geo.y()); - painter.drawText(35, height() - 18, width() - 45, 15, Qt::AlignCenter, lat+" "+lon); + painter.drawText(35, height() - 15, width() - 155, 14, Qt::AlignCenter, lat+" "+lon); } if (m_zoomable) { painter.drawRoundedRect(5, 10, 20, 220, 10, 10); @@ -416,6 +386,7 @@ void MapWidget::paintEvent(QPaintEvent *event) painter.drawLine(midX - 5, midY, midX + 5, midY); painter.drawLine(midX, midY - 5, midX, midY + 5); } + if (m_usage) { painter.setBrush(QBrush(QColor(255, 255, 255, 210))); painter.drawRoundedRect(20, 5, 280, 215, 10, 10); @@ -423,9 +394,8 @@ void MapWidget::paintEvent(QPaintEvent *event) QStringList usage; usage << "Esc: Quit application"; usage << "h: Show/hide this message"; - usage << "Arrows: Move map by 10 pixel"; - usage << "Alt+Arrows: Move map by 100 pixel"; - usage << "c: Move to the center of the map"; + usage << "Arrows: Move the map"; + //usage << "c: Move to the center of the map"; if (m_zoomable) { usage << "i: Zoom in"; usage << "o: Zoom out"; @@ -577,31 +547,6 @@ void MapWidget::reloadPixmaps() } } -void MapWidget::updateTrack() -{ - if (m_track.count() > 1) { - int scale = 1 << m_level; - m_trackOnScreen.clear(); - m_trackOffset = raw2screen(m_track.first().x(), m_track.first().y(), scale); - m_trackOnScreen << QPoint(0, 0); - for (int i = 1; i < m_track.count(); ++i) { - QPointF p = m_track.at(i); - if (!p.isNull()) { - m_trackOnScreen << raw2screen(p.x(), p.y(), scale) - m_trackOffset; - } else { - m_trackOnScreen << QPoint(); - } - } - } -} - -void MapWidget::addMarker(const QPointF &pos, const QString &name) -{ - m_markerPos << pos; - m_markerName << name; - emit markerAdded(name); -} - QString MapWidget::filename(int x, int y) { QString result; @@ -696,77 +641,6 @@ void MapWidget::loadMapFile(const QString &filename) } } -void MapWidget::loadGpx(const QString &filename) -{ - QFile file(filename); - if (file.open(QIODevice::ReadOnly)) { - QXmlStreamReader xml(&file); - - QPolygonF points; - QList elev; - QList time; - - QString tag, tag2; - QString name; - QPointF pos; - while (!xml.atEnd()) { - xml.readNext(); - if (xml.isStartElement()) { - if (xml.name() == "trkpt") { - tag = "trkpt"; - float lat = xml.attributes().value("lat").toString().toFloat(); - float lon = xml.attributes().value("lon").toString().toFloat(); - - points << QPointF(lon2rawx(lon), lat2rawy(lat)); - } else if (xml.name() == "ele") { - tag2 = "ele"; - } else if (xml.name() == "time") { - tag2 = "time"; - } else if (xml.name() == "wpt") { - tag = "wpt"; - float lat = xml.attributes().value("lat").toString().toFloat(); - float lon = xml.attributes().value("lon").toString().toFloat(); - - pos = QPointF(lon, lat); - } else if (xml.name() == "name") { - tag2 = "name"; - } else if (xml.name() == "trk" || - xml.name() == "trkseg") { - } else { - tag2.clear(); - } - } else if (xml.isEndElement()) { - if (xml.name() == "trkseg") { - if (!points.isEmpty()) { - m_track << points; - m_track << QPointF(); - } - points.clear(); - elev.clear(); - time.clear(); - } else if (xml.name() == "wpt") { - //addMarker(pos, name); - name.clear(); - } - } else if (xml.isCharacters() && !xml.isWhitespace()) { - if (tag == "trkpt") { - if (tag2 == "ele") { - elev << xml.text().toString().toFloat(); - } else if (tag2 == "time") { - QDateTime dt = QDateTime::fromString(xml.text().toString(), Qt::ISODate); - time << dt.toTime_t(); - } - } else if (tag == "wpt") { - if (tag2 == "name") { - name = xml.text().toString(); - } - } - } - } - updateTrack(); - } -} - void MapWidget::loadConfig() { QSettings set(QDir::homePath()+"/Maps/nanomap.conf", QSettings::NativeFormat); @@ -778,15 +652,6 @@ void MapWidget::loadConfig() m_usage = set.value("usage", true).toBool(); changeZoomLevel(level - m_level); centerOnGeoPos(lon, lat); - updateTrack(); - set.endGroup(); - - set.beginGroup("marker"); - QStringList m = set.childKeys(); - foreach (const QString &marker, m) { - QPointF pos = set.value(marker).toPointF(); - addMarker(pos, marker); - } set.endGroup(); } @@ -801,13 +666,6 @@ void MapWidget::saveConfig() set.setValue("level", m_level); set.setValue("usage", m_usage); set.endGroup(); - - set.beginGroup("marker"); - set.remove(""); - for (int i = 0; i < m_markerPos.count(); ++i) { - set.setValue(m_markerName.at(i), m_markerPos.at(i)); - } - set.endGroup(); } void MapWidget::downloadTile(int x, int y, int level) @@ -844,22 +702,35 @@ void MapWidget::changeZoomLevel(int diff) m_indexY = (int) floor(y); m_pos.setX(((m_indexX-x) * m_pixWidth) + w); m_pos.setY(((m_indexY-y) * m_pixHeight) + h); + + foreach (AbstractLayer *l, m_layer) { + l->zoom(m_level); + } } void MapWidget::centerOnGeoPos(qreal lon, qreal lat) { + QPoint oldPos = QPoint(m_pixWidth * m_indexX, m_pixHeight * m_indexY) - m_pos; + qreal w = width() / 2.0; qreal h = height() / 2.0; - qreal x = lon2tilex(lon, m_level); - qreal y = lat2tiley(lat, m_level); + qreal x = Projection::lon2tilex(lon, m_level); + qreal y = Projection::lat2tiley(lat, m_level); m_indexX = (int) floor(x); m_indexY = (int) floor(y); m_pos.setX(((m_indexX-x) * m_pixWidth) + w); m_pos.setY(((m_indexY-y) * m_pixHeight) + h); + QPoint newPos = QPoint(m_pixWidth * m_indexX, m_pixHeight * m_indexY) - m_pos; + reloadPixmaps(); + + foreach (AbstractLayer *l, m_layer) { + l->pan(oldPos - newPos); + } + updatePos(); } @@ -867,13 +738,13 @@ QRectF MapWidget::geoRect() const { qreal partX = (-m_pos.x()) / 256.0; qreal partY = (height() - m_pos.y()) / 256.0; - qreal minLon = tilex2lon(m_indexX + partX, m_level); - qreal minLat = tiley2lat(m_indexY + partY, m_level); + qreal minLon = Projection::tilex2lon(m_indexX + partX, m_level); + qreal minLat = Projection::tiley2lat(m_indexY + partY, m_level); partX = (width() - m_pos.x()) / 256.0; partY = (-m_pos.y()) / 256.0; - qreal maxLon = tilex2lon(m_indexX + partX, m_level); - qreal maxLat = tiley2lat(m_indexY + partY, m_level); + qreal maxLon = Projection::tilex2lon(m_indexX + partX, m_level); + qreal maxLat = Projection::tiley2lat(m_indexY + partY, m_level); return QRectF(QPointF(minLon, minLat), QPointF(maxLon, maxLat)); } @@ -884,16 +755,16 @@ QPointF MapWidget::geoPos() const qreal h = height() / 2.0; qreal partX = (w - m_pos.x()) / 256.0; qreal partY = (h - m_pos.y()) / 256.0; - qreal lon = tilex2lon(m_indexX + partX, m_level); - qreal lat = tiley2lat(m_indexY + partY, m_level); + qreal lon = Projection::tilex2lon(m_indexX + partX, m_level); + qreal lat = Projection::tiley2lat(m_indexY + partY, m_level); return QPointF(lon, lat); } QPoint MapWidget::geo2screen(qreal lon, qreal lat) const { - qreal tx = lon2tilex(lon, m_level); - qreal ty = lat2tiley(lat, m_level); + qreal tx = Projection::lon2tilex(lon, m_level); + qreal ty = Projection::lat2tiley(lat, m_level); int x = (tx * m_pixWidth) - ((m_indexX * m_pixWidth) - m_pos.x()); int y = (ty * m_pixHeight) - ((m_indexY * m_pixHeight) - m_pos.y()); @@ -912,34 +783,3 @@ QPoint MapWidget::raw2screen(qreal x, qreal y, int scale) const return QPoint(sx, sy); } -qreal MapWidget::lon2rawx(qreal lon) const -{ - return (lon + 180.0) / 360.0; -} - -qreal MapWidget::lat2rawy(qreal lat) const -{ - return (1.0 - log(tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0; -} - -qreal MapWidget::lon2tilex(qreal lon, int z) const -{ - return (lon + 180.0) / 360.0 * (1 << z); -} - -qreal MapWidget::lat2tiley(qreal lat, int z) const -{ - return (1.0 - log(tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * (1 << z); -} - -qreal MapWidget::tilex2lon(qreal x, int z) const -{ - return x / (1 << z) * 360.0 - 180; -} - -qreal MapWidget::tiley2lat(qreal y, int z) const -{ - qreal n = M_PI - 2.0 * M_PI * y / (1 << z); - return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); -} - diff --git a/mapwidget.h b/mapwidget.h index be63f95..55beef9 100644 --- a/mapwidget.h +++ b/mapwidget.h @@ -20,8 +20,11 @@ #ifndef MAPWIDGET_H #define MAPWIDGET_H -#include +#include "abstractlayer.h" + +#include #include +#include #include class MapWidget : public QWidget @@ -31,14 +34,17 @@ public: MapWidget(QWidget *parent = 0); ~MapWidget(); - void removeMarker(int index); - void renameMarker(int index, const QString &name); + void addLayer(Layer l, AbstractLayer *layer); + + QRectF geoRect() const; + QPointF geoPos() const; + QPoint geo2screen(qreal lon, qreal lat) const; + QPoint raw2screen(qreal x, qreal y, int scale) const; public slots: - void centerOnMarker(int index); + void centerOnGeoPos(qreal lon, qreal lat); signals: - void markerAdded(const QString &name); void showMarkerList(); void downloadArea(int level, const QRectF &rect); @@ -58,28 +64,14 @@ private slots: private: void updatePos(); void reloadPixmaps(); - void updateTrack(); - void addMarker(const QPointF &pos, const QString &name); QString filename(int x, int y); QPixmap *loadPixmap(int x, int y); void loadMapFile(const QString &filename); - void loadGpx(const QString &filename); void saveConfig(); void downloadTile(int x, int y, int level); void changeZoomLevel(int diff); - void centerOnGeoPos(qreal lon, qreal lat); - QRectF geoRect() const; - QPointF geoPos() const; - QPoint geo2screen(qreal lon, qreal lat) const; - QPoint raw2screen(qreal x, qreal y, int scale) const; - qreal lon2rawx(qreal lon) const; - qreal lat2rawy(qreal lat) const; - qreal lon2tilex(qreal lon, int z) const; - qreal lat2tiley(qreal lat, int z) const; - qreal tilex2lon(qreal x, int z) const; - qreal tiley2lat(qreal y, int z) const; - bool m_usage, m_infos, m_zoomable; + bool m_usage, m_ui, m_zoomable; QString m_baseName; int m_xPadding, m_yPadding; QPoint m_pos, m_startPos; @@ -97,12 +89,7 @@ private: QNetworkAccessManager *m_manager; bool m_networkMode; QString m_copyright; - QList m_markerPos; - QStringList m_markerName; - bool m_drawMarker; - QPolygonF m_track; - QList m_trackOnScreen; - QPoint m_trackOffset; + QHash m_layer; }; diff --git a/markerlayer.cpp b/markerlayer.cpp new file mode 100644 index 0000000..cea7e04 --- /dev/null +++ b/markerlayer.cpp @@ -0,0 +1,126 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "markerlayer.h" + +#include "mapwidget.h" + +#include + +MarkerLayer::MarkerLayer(MapWidget *map) : + AbstractLayer(map), + m_markerPos(), + m_markerName(), + m_filename() +{ +} + +MarkerLayer::~MarkerLayer() +{ + QSettings set(m_filename, QSettings::NativeFormat); + + set.beginGroup("marker"); + set.remove(""); + for (int i = 0; i < m_markerPos.count(); ++i) { + set.setValue(m_markerName.at(i), m_markerPos.at(i)); + } + set.endGroup(); +} + +void MarkerLayer::load(const QString &filename) +{ + m_filename = filename; + + QSettings set(filename, QSettings::NativeFormat); + + set.beginGroup("marker"); + QStringList m = set.childKeys(); + foreach (const QString &marker, m) { + QPointF pos = set.value(marker).toPointF(); + m_markerPos << pos; + m_markerName << marker; + emit markerAdded(marker); + } + set.endGroup(); +} + +void MarkerLayer::triggerAction() +{ + int n = 0; + if (!m_markerName.isEmpty()) { + n = m_markerName.last().toInt(); + } + QString newName = QString::number(n+1); + + m_markerPos << map()->geoPos(); + m_markerName << newName; + emit markerAdded(newName); +} + +void MarkerLayer::paint(QPainter *painter) +{ + int i = 0; + painter->setBrush(QBrush(QColor(255, 237, 60))); + QFontMetrics fm(painter->font()); + int h = fm.height() / 2; + foreach (const QPointF &m, m_markerPos) { + QPoint pos = map()->geo2screen(m.x(), m.y()); + int w = fm.width(m_markerName.at(i)) / 2; + QRect rect(pos.x() - w - 2, pos.y() - h - 11, 2*w + 4, 2*h); + QPolygon polygon; + polygon << pos; + polygon << pos + QPoint(-2, -5); + polygon << rect.bottomLeft(); + polygon << rect.topLeft(); + polygon << rect.topRight(); + polygon << rect.bottomRight(); + polygon << pos + QPoint(2, -5); + polygon << pos; + painter->drawPolygon(polygon); + painter->drawText(rect, Qt::AlignCenter, m_markerName.at(i)); + ++i; + } +} + +void MarkerLayer::removeMarker(int index) +{ + if (index >= 0 && m_markerPos.count() > index) { + m_markerPos.removeAt(index); + m_markerName.removeAt(index); + map()->update(); + } +} + +void MarkerLayer::renameMarker(int index, const QString &name) +{ + if (index >= 0 && m_markerName.count() > index) { + m_markerName.replace(index, name); + } +} + +void MarkerLayer::centerOnMarker(int index) +{ + if (index >= 0 && m_markerPos.count() > index) { + qreal lon = m_markerPos.at(index).x(); + qreal lat = m_markerPos.at(index).y(); + + map()->centerOnGeoPos(lon, lat); + } +} + diff --git a/markerlayer.h b/markerlayer.h new file mode 100644 index 0000000..3e64224 --- /dev/null +++ b/markerlayer.h @@ -0,0 +1,55 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef MARKER_LAYER_H +#define MARKER_LAYER_H + +#include "abstractlayer.h" + +#include + +class MarkerLayer : public AbstractLayer +{ + Q_OBJECT +public: + MarkerLayer(MapWidget *map); + ~MarkerLayer(); + + virtual void load(const QString &filename); + virtual void triggerAction(); + +protected: + virtual void paint(QPainter *painter); + +public slots: + void removeMarker(int index); + void renameMarker(int index, const QString &name); + void centerOnMarker(int index); + +signals: + void markerAdded(const QString &name); + +private: + QList m_markerPos; + QStringList m_markerName; + QString m_filename; + +}; + +#endif // MARKER_LAYER_H diff --git a/markerlist.h b/markerlist.h index 83b0e28..cc819d5 100644 --- a/markerlist.h +++ b/markerlist.h @@ -30,6 +30,7 @@ public: MarkerList(QWidget *parent = 0); ~MarkerList(); +public slots: void addMarker(const QString &name); signals: diff --git a/nanomap.pro b/nanomap.pro index 9b2e553..e5f6efa 100644 --- a/nanomap.pro +++ b/nanomap.pro @@ -5,12 +5,24 @@ QT += network SOURCES += main.cpp \ mainwidget.cpp \ + projection.cpp \ + abstractlayer.cpp \ + markerlayer.cpp \ + gpxlayer.cpp \ + timelayer.cpp \ + batterylayer.cpp \ mapwidget.cpp \ markerlist.cpp \ downloadwidget.cpp \ gpsclient.cpp HEADERS += mainwidget.h \ + projection.h \ + abstractlayer.h \ + markerlayer.h \ + gpxlayer.h \ + timelayer.h \ + batterylayer.h \ mapwidget.h \ markerlist.h \ downloadwidget.h \ diff --git a/projection.cpp b/projection.cpp new file mode 100644 index 0000000..c982c35 --- /dev/null +++ b/projection.cpp @@ -0,0 +1,54 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "projection.h" + +#include + +qreal Projection::lon2rawx(qreal lon) +{ + return (lon + 180.0) / 360.0; +} + +qreal Projection::lat2rawy(qreal lat) +{ + return (1.0 - log(tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0; +} + +qreal Projection::lon2tilex(qreal lon, int z) +{ + return (lon + 180.0) / 360.0 * (1 << z); +} + +qreal Projection::lat2tiley(qreal lat, int z) +{ + return (1.0 - log(tan(lat * M_PI/180.0) + 1.0 / cos(lat * M_PI/180.0)) / M_PI) / 2.0 * (1 << z); +} + +qreal Projection::tilex2lon(qreal x, int z) +{ + return x / (1 << z) * 360.0 - 180; +} + +qreal Projection::tiley2lat(qreal y, int z) +{ + qreal n = M_PI - 2.0 * M_PI * y / (1 << z); + return 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n))); +} + diff --git a/projection.h b/projection.h new file mode 100644 index 0000000..79bee69 --- /dev/null +++ b/projection.h @@ -0,0 +1,35 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef PROJECTION_H +#define PROJECTION_H + +#include + +namespace Projection +{ + qreal lon2rawx(qreal lon); + qreal lat2rawy(qreal lat); + qreal lon2tilex(qreal lon, int z); + qreal lat2tiley(qreal lat, int z); + qreal tilex2lon(qreal x, int z); + qreal tiley2lat(qreal y, int z); +}; + +#endif // PROJECTION_H diff --git a/timelayer.cpp b/timelayer.cpp new file mode 100644 index 0000000..20b8112 --- /dev/null +++ b/timelayer.cpp @@ -0,0 +1,53 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#include "timelayer.h" + +#include "mapwidget.h" + +#include + +TimeLayer::TimeLayer(MapWidget *map) : + AbstractLayer(map), + m_updateTimer(new QTimer(this)) +{ + m_updateTimer->setInterval(60 * 1000); + connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(repaint())); + int time = (60 - QTime::currentTime().second()) * 1000; + QTimer::singleShot(time, this, SLOT(repaint())); + QTimer::singleShot(time, m_updateTimer, SLOT(start())); +} + +void TimeLayer::paint(QPainter *painter) +{ + int w = map()->width(); + + painter->setBrush(QBrush(QColor(255, 255, 255, 210))); + painter->drawRoundedRect(w - 82, 1, 80, 16, 5, 5); + painter->drawText(w - 77, 3, 70, 14, Qt::AlignCenter, + QTime::currentTime().toString("h:mm")); +} + +void TimeLayer::repaint() +{ + if (isVisible()) { + map()->update(); + } +} + diff --git a/timelayer.h b/timelayer.h new file mode 100644 index 0000000..b9fbf9c --- /dev/null +++ b/timelayer.h @@ -0,0 +1,45 @@ +/* + * Copyright 2010 Niels Kummerfeldt + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA + */ + +#ifndef TIME_LAYER_H +#define TIME_LAYER_H + +#include "abstractlayer.h" + +#include +#include + +class TimeLayer : public AbstractLayer +{ + Q_OBJECT +public: + TimeLayer(MapWidget *map); + +protected: + virtual void paint(QPainter *painter); + +private slots: + void repaint(); + +private: + QTimer *m_updateTimer; + +}; + +#endif // TIME_LAYER_H