From c64d7392c2e2ae51547788252e8c83ce5480fe49 Mon Sep 17 00:00:00 2001 From: "Javier S. Pedro" Date: Sun, 19 Aug 2012 03:50:04 +0200 Subject: add an arrow indicator to map watchlet --- qmapwatchlet/arrow.png | Bin 0 -> 2809 bytes qmapwatchlet/mapview.cc | 126 +++++++++++++++++++++++++++++++++++++----- qmapwatchlet/mapview.h | 22 +++++++- qmapwatchlet/qmapwatchlet.pro | 2 +- 4 files changed, 132 insertions(+), 18 deletions(-) create mode 100644 qmapwatchlet/arrow.png diff --git a/qmapwatchlet/arrow.png b/qmapwatchlet/arrow.png new file mode 100644 index 0000000..b0e4d0c Binary files /dev/null and b/qmapwatchlet/arrow.png differ diff --git a/qmapwatchlet/mapview.cc b/qmapwatchlet/mapview.cc index d647412..5972e07 100644 --- a/qmapwatchlet/mapview.cc +++ b/qmapwatchlet/mapview.cc @@ -3,6 +3,7 @@ #include #include #include +#include #include "qmapwatchletplugin.h" #include "mapview.h" @@ -12,8 +13,10 @@ using namespace sowatch; MapView::MapView(QDeclarativeItem *parent) : QDeclarativeItem(parent), _enabled(false), + _arrow(SOWATCH_QML_DIR "/qmapwatchlet/arrow.png"), _mapData(0), - _pos(QGeoPositionInfoSource::createDefaultSource(this)) + _posSource(QGeoPositionInfoSource::createDefaultSource(this)), + _searchArea(0), _searchReply(0) { QGeoServiceProvider *provider = QMapWatchletPlugin::geoServiceProvider(); if (!provider) { @@ -27,7 +30,7 @@ MapView::MapView(QDeclarativeItem *parent) : _mapData->init(); _mapData->setMapType(QGraphicsGeoMap::StreetMap); - _mapData->setZoomLevel(10); + _mapData->setZoomLevel(12); connect(_mapData, SIGNAL(zoomLevelChanged(qreal)), SIGNAL(zoomLevelChanged())); connect(_mapData, SIGNAL(updateMapDisplay(QRectF)), SLOT(handleMapChanged(QRectF))); @@ -35,10 +38,10 @@ MapView::MapView(QDeclarativeItem *parent) : qWarning() << "No mapdata!"; } - if (_pos) { - connect(_pos, SIGNAL(positionUpdated(QGeoPositionInfo)), + if (_posSource) { + connect(_posSource, SIGNAL(positionUpdated(QGeoPositionInfo)), SLOT(handlePositionUpdate(QGeoPositionInfo))); - _pos->lastKnownPosition(); + _posSource->lastKnownPosition(); } else { qWarning() << "No position source for moving map!"; } @@ -49,6 +52,8 @@ MapView::MapView(QDeclarativeItem *parent) : MapView::~MapView() { delete _mapData; + delete _searchReply; + delete _searchArea; } bool MapView::updateEnabled() const @@ -58,13 +63,13 @@ bool MapView::updateEnabled() const void MapView::setUpdateEnabled(bool enabled) { - if (_pos && _enabled != enabled) { + if (_posSource && _enabled != enabled) { if (enabled) { qDebug() << "Start position updates"; - _pos->startUpdates(); + _posSource->startUpdates(); } else { qDebug() << "Stop position updates"; - _pos->stopUpdates(); + _posSource->stopUpdates(); } _enabled = enabled; @@ -75,8 +80,8 @@ void MapView::setUpdateEnabled(bool enabled) int MapView::updateInterval() const { - if (_pos) { - return _pos->updateInterval(); + if (_posSource) { + return _posSource->updateInterval(); } else { return 0; } @@ -84,8 +89,8 @@ int MapView::updateInterval() const void MapView::setUpdateInterval(int msec) { - if (_pos) { - _pos->setUpdateInterval(msec); + if (_posSource) { + _posSource->setUpdateInterval(msec); emit updateIntervalChanged(); } } @@ -107,6 +112,11 @@ void MapView::setZoomLevel(qreal level) } } +QString MapView::currentLocationName() const +{ + return _posName; +} + void MapView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(widget); @@ -151,9 +161,54 @@ void MapView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, Q // And render into the watch painter->drawImage(0, 0, pixmap); + + // Now render the arrow indicator + const int centerX = size.width() / 2, centerY = size.height() / 2; + painter->save(); + painter->translate(centerX, centerY); + if (_pos.hasAttribute(QGeoPositionInfo::Direction)) { + painter->rotate(_pos.attribute(QGeoPositionInfo::Direction)); + } + painter->drawImage(-_arrow.width() / 2, -_arrow.height() / 2, _arrow); + painter->restore(); } } +void MapView::updateCurrentLocationName() +{ + if (_searchReply) { + qDebug() << "Search already in progress"; + return; + } + QGeoServiceProvider *provider = QMapWatchletPlugin::geoServiceProvider(); + if (!provider) { + qWarning() << "No geo service provider for map watchlet!"; + } + + // Lifetime of 'bounds' in call to reverseGeocode() is not specified anywhere. + // So we keep it "forever" until the next call to reverseGeocode(). + // which is ... now. + delete _searchArea; + + // Create the new bounds object. + if (_mapData) { + _searchArea = new QGeoBoundingBox(_mapData->viewport()); + } else { + _searchArea = 0; + } + + _posName.clear(); + + qDebug() << "Start request of current location"; + + QGeoSearchManager *manager = provider->searchManager(); + _searchReply = manager->reverseGeocode(_pos.coordinate(), _searchArea); + connect(_searchReply, SIGNAL(finished()), + SLOT(handleCurrentLocationNameSearchFinished())); + connect(_searchReply, SIGNAL(error(QGeoSearchReply::Error,QString)), + SLOT(handleCurrentLocationNameSearchError(QGeoSearchReply::Error,QString))); +} + void MapView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_UNUSED(oldGeometry); @@ -164,14 +219,55 @@ void MapView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeomet void MapView::handlePositionUpdate(const QGeoPositionInfo& info) { + _pos = info; if (_mapData) { - qDebug() << "Got pos for map"; _mapData->setCenter(info.coordinate()); } } void MapView::handleMapChanged(const QRectF &rect) { - Q_UNUSED(rect); - update(); // Always do full updates + update(rect); +} + +void MapView::handleCurrentLocationNameSearchFinished() +{ + if (_searchReply) { + if (_searchReply->error() == QGeoSearchReply::NoError) { + QList places = _searchReply->places(); + qDebug() << "Current location name search got " << places.size() << " results"; + foreach (const QGeoPlace& place, places) { + QGeoAddress address = place.address(); + qDebug() << " " << address.street() << " - " << address.district() << " - " << address.city(); + } + if (!places.isEmpty()) { + QGeoAddress address = places.first().address(); + if (!address.street().isEmpty()) { + _posName = address.street(); + } else if (!address.district().isEmpty()) { + _posName = address.district(); + } else if (!address.city().isEmpty()) { + _posName = address.city(); + } else { + _posName.clear(); + } + qDebug() << "Current location name search finished:" << _posName; + emit currentLocationNameChanged(); + } + } else { + qDebug() << "Current location name search finished with error:" + << _searchReply->error(); + } + _searchReply->deleteLater(); + _searchReply = 0; + } +} + +void MapView::handleCurrentLocationNameSearchError(QGeoSearchReply::Error error, const QString &errorString) +{ + qWarning() << "Current location name search error: " << errorString; + if (_searchReply) { + _searchReply->deleteLater(); + _searchReply = 0; + } } diff --git a/qmapwatchlet/mapview.h b/qmapwatchlet/mapview.h index f3e457f..efd4ea5 100644 --- a/qmapwatchlet/mapview.h +++ b/qmapwatchlet/mapview.h @@ -1,16 +1,20 @@ #ifndef MAPVIEW_H #define MAPVIEW_H +#include #include #include #include +#include namespace sowatch { -using QTM_PREPEND_NAMESPACE(QGeoPositionInfo); using QTM_PREPEND_NAMESPACE(QGeoMapData); using QTM_PREPEND_NAMESPACE(QGeoPositionInfoSource); +using QTM_PREPEND_NAMESPACE(QGeoPositionInfo); +using QTM_PREPEND_NAMESPACE(QGeoBoundingBox); +using QTM_PREPEND_NAMESPACE(QGeoSearchReply); class MapView : public QDeclarativeItem { @@ -18,6 +22,7 @@ class MapView : public QDeclarativeItem Q_PROPERTY(bool updateEnabled READ updateEnabled WRITE setUpdateEnabled NOTIFY updateEnabledChanged) Q_PROPERTY(int updateInterval READ updateInterval WRITE setUpdateInterval NOTIFY updateIntervalChanged) Q_PROPERTY(qreal zoomLevel READ zoomLevel WRITE setZoomLevel NOTIFY zoomLevelChanged) + Q_PROPERTY(QString currentLocationName READ currentLocationName NOTIFY currentLocationNameChanged) public: explicit MapView(QDeclarativeItem *parent = 0); @@ -32,12 +37,18 @@ public: qreal zoomLevel() const; void setZoomLevel(qreal level); + QString currentLocationName() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); +public slots: + void updateCurrentLocationName(); + signals: void updateEnabledChanged(); void updateIntervalChanged(); void zoomLevelChanged(); + void currentLocationNameChanged(); protected: void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); @@ -45,11 +56,18 @@ protected: private slots: void handlePositionUpdate(const QGeoPositionInfo& info); void handleMapChanged(const QRectF& rect); + void handleCurrentLocationNameSearchFinished(); + void handleCurrentLocationNameSearchError(QGeoSearchReply::Error error, const QString& errorString); private: bool _enabled; + QImage _arrow; QGeoMapData *_mapData; - QGeoPositionInfoSource *_pos; + QGeoPositionInfoSource *_posSource; + QGeoPositionInfo _pos; + QString _posName; + QGeoBoundingBox *_searchArea; + QGeoSearchReply *_searchReply; }; } diff --git a/qmapwatchlet/qmapwatchlet.pro b/qmapwatchlet/qmapwatchlet.pro index 72f588a..9bfb755 100644 --- a/qmapwatchlet/qmapwatchlet.pro +++ b/qmapwatchlet/qmapwatchlet.pro @@ -9,7 +9,7 @@ SOURCES += qmapwatchletplugin.cpp qmapwatchlet.cpp mapview.cc HEADERS += qmapwatchletplugin.h qmapwatchlet.h mapview.h -qml_files.files = metawatch-digital.qml icon.png +qml_files.files = metawatch-digital.qml icon.png arrow.png LIBS += -L$$OUT_PWD/../libsowatch/ -lsowatch INCLUDEPATH += $$PWD/../libsowatch -- cgit v1.2.3