summaryrefslogtreecommitdiff
path: root/examples/maps/marker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/maps/marker.cpp')
-rw-r--r--examples/maps/marker.cpp326
1 files changed, 326 insertions, 0 deletions
diff --git a/examples/maps/marker.cpp b/examples/maps/marker.cpp
new file mode 100644
index 00000000..53efc908
--- /dev/null
+++ b/examples/maps/marker.cpp
@@ -0,0 +1,326 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Mobility Components.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "marker.h"
+#include "mapswidget.h"
+
+#include <QPixmap>
+
+#include "qlandmark.h"
+#include "qgeoboundingcircle.h"
+
+class MarkerPrivate
+{
+public:
+ Marker::MarkerType type;
+ QString name;
+ bool moveable;
+ QGeoAddress address;
+};
+
+Marker::Marker(MarkerType type) :
+ QGeoMapPixmapObject(),
+ d(new MarkerPrivate)
+{
+ setMarkerType(type);
+}
+
+void Marker::setMarkerType(MarkerType type)
+{
+ QString filename;
+ QPoint offset;
+ int scale;
+
+ d->type = type;
+
+ switch (d->type) {
+ case MyLocationMarker:
+ filename = ":/icons/mylocation.png";
+ break;
+ case SearchMarker:
+ filename = ":/icons/searchmarker.png";
+ break;
+ case WaypointMarker:
+ filename = ":/icons/waypointmarker.png";
+ break;
+ case StartMarker:
+ filename = ":/icons/startmarker.png";
+ break;
+ case EndMarker:
+ filename = ":/icons/endmarker.png";
+ break;
+ case PathMarker:
+ filename = ":/icons/pathmarker.png";
+ break;
+ }
+
+ if (d->type == MyLocationMarker) {
+ offset = QPoint(-13,-13);
+ scale = 25;
+ } else {
+ offset = QPoint(-15, -36);
+ scale = 30;
+ }
+
+ setOffset(offset);
+ setPixmap(QPixmap(filename).scaledToWidth(scale, Qt::SmoothTransformation));
+}
+
+void Marker::setAddress(QGeoAddress addr)
+{
+ if (d->address != addr) {
+ d->address = addr;
+ emit addressChanged(d->address);
+ }
+}
+
+Marker::MarkerType Marker::markerType() const
+{
+ return d->type;
+}
+
+QString Marker::name() const
+{
+ return d->name;
+}
+
+QGeoAddress Marker::address() const
+{
+ return d->address;
+}
+
+bool Marker::moveable() const
+{
+ return d->moveable;
+}
+
+void Marker::setName(QString name)
+{
+ if (d->name != name) {
+ d->name = name;
+ emit nameChanged(d->name);
+ }
+}
+
+void Marker::setMoveable(bool moveable)
+{
+ if (d->moveable != moveable) {
+ d->moveable = moveable;
+ emit moveableChanged(d->moveable);
+ }
+}
+
+
+class MarkerManagerPrivate
+{
+public:
+ Marker *myLocation;
+ QList<Marker*> searchMarkers;
+
+ // a reverse geocode request is currently running
+ bool revGeocodeRunning;
+ // a request is currently running, and my location has changed
+ // since it started (ie, the request is stale)
+ bool myLocHasMoved;
+
+ QGraphicsGeoMap *map;
+ StatusBarItem *status;
+ QGeoSearchManager *searchManager;
+
+ QSet<QGeoSearchReply*> forwardReplies;
+ QSet<QGeoSearchReply*> reverseReplies;
+};
+
+MarkerManager::MarkerManager(QGeoSearchManager *searchManager, QObject *parent) :
+ QObject(parent),
+ d(new MarkerManagerPrivate)
+{
+ d->searchManager = searchManager;
+ d->status = 0;
+ d->revGeocodeRunning = false;
+ d->myLocHasMoved = false;
+
+ d->myLocation = new Marker(Marker::MyLocationMarker);
+ d->myLocation->setName("Me");
+
+ // hook the coordinateChanged() signal for reverse geocoding
+ connect(d->myLocation, SIGNAL(coordinateChanged(QGeoCoordinate)),
+ this, SLOT(myLocationChanged(QGeoCoordinate)));
+
+ connect(d->searchManager, SIGNAL(finished(QGeoSearchReply*)),
+ this, SLOT(replyFinished(QGeoSearchReply*)));
+ connect(d->searchManager, SIGNAL(finished(QGeoSearchReply*)),
+ this, SLOT(reverseReplyFinished(QGeoSearchReply*)));
+}
+
+MarkerManager::~MarkerManager()
+{
+ d->map->removeMapObject(d->myLocation);
+ delete d->myLocation;
+ removeSearchMarkers();
+}
+
+void MarkerManager::setStatusBar(StatusBarItem *bar)
+{
+ d->status = bar;
+}
+
+void MarkerManager::setMap(QGraphicsGeoMap *map)
+{
+ d->map = map;
+ map->addMapObject(d->myLocation);
+}
+
+void MarkerManager::setMyLocation(QGeoCoordinate coord)
+{
+ d->myLocation->setCoordinate(coord);
+}
+
+void MarkerManager::search(QString query, qreal radius)
+{
+ QGeoSearchReply *reply;
+ if (radius > 0) {
+ QGeoBoundingCircle *boundingCircle = new QGeoBoundingCircle(
+ d->myLocation->coordinate(), radius);
+ reply = d->searchManager->search(query,
+ -1, 0,
+ boundingCircle);
+ } else {
+ reply = d->searchManager->search(query);
+ }
+
+ d->forwardReplies.insert(reply);
+
+ if (d->status) {
+ d->status->setText("Searching...");
+ d->status->show();
+ }
+
+ if (reply->isFinished()) {
+ replyFinished(reply);
+ } else {
+ connect(reply, SIGNAL(error(QGeoSearchReply::Error,QString)),
+ this, SIGNAL(searchError(QGeoSearchReply::Error,QString)));
+ }
+}
+
+void MarkerManager::removeSearchMarkers()
+{
+ foreach (Marker *m, d->searchMarkers) {
+ d->map->removeMapObject(m);
+ delete m;
+ }
+}
+
+QGeoCoordinate MarkerManager::myLocation() const
+{
+ return d->myLocation->coordinate();
+}
+
+void MarkerManager::myLocationChanged(QGeoCoordinate location)
+{
+ if (d->revGeocodeRunning) {
+ d->myLocHasMoved = true;
+ } else {
+ QGeoSearchReply *reply = d->searchManager->reverseGeocode(location);
+ d->reverseReplies.insert(reply);
+ d->myLocHasMoved = false;
+
+ if (reply->isFinished()) {
+ d->revGeocodeRunning = false;
+ reverseReplyFinished(reply);
+ } else {
+ d->revGeocodeRunning = true;
+ }
+ }
+}
+
+void MarkerManager::reverseReplyFinished(QGeoSearchReply *reply)
+{
+ if (!d->reverseReplies.contains(reply))
+ return;
+
+ if (!reply->locations().isEmpty()) {
+ QGeoLocation location = reply->locations().first();
+ d->myLocation->setAddress(location.address());
+ }
+
+ d->revGeocodeRunning = false;
+ if (d->myLocHasMoved)
+ myLocationChanged(d->myLocation->coordinate());
+
+ d->reverseReplies.remove(reply);
+ reply->deleteLater();
+}
+
+void MarkerManager::replyFinished(QGeoSearchReply *reply)
+{
+ if (!d->forwardReplies.contains(reply))
+ return;
+
+ // generate the markers and add them to the map
+ foreach (const QGeoLocation &location, reply->locations()) {
+ Marker *m = new Marker(Marker::SearchMarker);
+ m->setCoordinate(location.coordinate());
+
+ m->setName(QString("%1, %2").arg(location.address().street())
+ .arg(location.address().city()));
+ m->setAddress(location.address());
+ m->setMoveable(false);
+
+ d->searchMarkers.append(m);
+
+ if (d->map) {
+ d->map->addMapObject(m);
+ // also zoom out until marker is visible
+ while (!d->map->viewport().contains(location.coordinate()))
+ d->map->setZoomLevel(d->map->zoomLevel()-1);
+ }
+ }
+
+ d->forwardReplies.remove(reply);
+ reply->deleteLater();
+
+ emit searchFinished();
+
+ if (d->status)
+ d->status->hide();
+}