[Marble-commits] KDE/kdeedu/marble/src/lib/routing

Dennis Nienhüser earthwings at gentoo.org
Thu Mar 18 21:39:40 CET 2010


SVN commit 1104896 by nienhueser:

Reverse geocoding via openstreetmap nominatim to show addresses instead of lat/lon pairs in input fields

 M  +69 -3     RoutingInputWidget.cpp  
 M  +8 -0      RoutingInputWidget.h  


--- trunk/KDE/kdeedu/marble/src/lib/routing/RoutingInputWidget.cpp #1104895:1104896
@@ -14,6 +14,8 @@
 #include "MarblePlacemarkModel.h"
 #include "MarbleDebug.h"
 #include "RouteSkeleton.h"
+#include "TinyWebBrowser.h"
+#include "MarbleLocale.h"
 
 #include <QtCore/QTimer>
 #include <QtGui/QLineEdit>
@@ -21,6 +23,10 @@
 #include <QtGui/QPushButton>
 #include <QtGui/QMovie>
 #include <QtGui/QIcon>
+#include <QtXml/QDomDocument>
+#include <QtNetwork/QNetworkAccessManager>
+#include <QtNetwork/QNetworkReply>
+#include <QtCore/QUrl>
 
 namespace Marble {
 
@@ -37,8 +43,6 @@
 
     MarbleRunnerManager *m_runnerManager;
 
-    RoutingInputWidgetPrivate(RouteSkeleton *skeleton, int index, QWidget *parent);
-
     MarblePlacemarkModel* m_placemarkModel;
 
     QMovie m_progress;
@@ -48,12 +52,22 @@
     RouteSkeleton* m_route;
 
     int m_index;
+
+    QNetworkAccessManager *m_manager;
+
+    QTimer m_nominatimTimer;
+
+    /** Constructor */
+    RoutingInputWidgetPrivate(RouteSkeleton *skeleton, int index, QWidget *parent);
+
+    /** Initiate reverse geocoding request to download address */
+    void adjustText();
 };
 
 RoutingInputWidgetPrivate::RoutingInputWidgetPrivate(RouteSkeleton *skeleton, int index, QWidget *parent) :
         m_lineEdit(0), m_runnerManager(new MarbleRunnerManager(parent)),
         m_placemarkModel(0), m_progress(":/data/bitmaps/progress.mng"),
-        m_route(skeleton), m_index(index)
+        m_route(skeleton), m_index(index), m_manager(new QNetworkAccessManager(parent))
 {
     m_stateButton = new QPushButton(parent);
     m_stateButton->setToolTip("Center Map here");
@@ -87,8 +101,15 @@
     m_pickButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
 
     m_progressTimer.setInterval(100);
+    m_nominatimTimer.setInterval(1000);
+    m_nominatimTimer.setSingleShot(true);
 }
 
+void RoutingInputWidgetPrivate::adjustText()
+{
+    m_nominatimTimer.start();
+}
+
 RoutingInputWidget::RoutingInputWidget(RouteSkeleton *skeleton, int index, QWidget *parent) :
         QWidget(parent), d(new RoutingInputWidgetPrivate(skeleton, index, this))
 {
@@ -120,6 +141,8 @@
             this, SLOT(finishSearch()));
     connect(skeleton, SIGNAL(positionChanged(int, GeoDataCoordinates)),
             this, SLOT(updatePosition(int, GeoDataCoordinates)));
+    connect(&d->m_nominatimTimer, SIGNAL(timeout()),
+            this, SLOT(startHttpRequest()));
 }
 
 RoutingInputWidget::~RoutingInputWidget()
@@ -127,6 +150,29 @@
     delete d;
 }
 
+void RoutingInputWidget::startHttpRequest()
+{
+    if (!hasTargetPosition())
+        return;
+
+    GeoDataCoordinates position = targetPosition();
+    QString base = "http://nominatim.openstreetmap.org/reverse?format=xml&addressdetails=0";
+    // @todo: Alternative URI with addressdetails=1 could be used for shorther placemark name
+    QString query = "&lon=%1&lat=%2&accept-language=%3";
+    double lon = position.longitude(GeoDataCoordinates::Degree);
+    double lat = position.latitude(GeoDataCoordinates::Degree);
+    QString url = QString(base + query).arg(lon).arg(lat).arg(MarbleLocale::languageCode());
+
+    QObject::connect(d->m_manager, SIGNAL(finished(QNetworkReply*)),
+            this, SLOT(handleHttpReply(QNetworkReply*)));
+
+    QNetworkRequest request;
+    request.setUrl(QUrl(url));
+    request.setRawHeader("User-Agent", TinyWebBrowser::userAgent("Browser", "RoutingInputWidget") );
+
+    d->m_manager->get(QNetworkRequest(request));
+}
+
 void RoutingInputWidget::setPlacemarkModel(MarblePlacemarkModel* model)
 {
     d->m_placemarkModel = model;
@@ -145,6 +191,7 @@
     if (!hasTargetPosition()) {
         d->m_route->setPosition(d->m_index, position);
         emit targetValidityChanged(true);
+        d->adjustText();
     }
 }
 
@@ -246,9 +293,28 @@
         d->m_stateButton->setEnabled(hasTargetPosition());
         d->m_stateButton->setIcon(d->m_route->pixmap(d->m_index));
         emit targetValidityChanged(hasTargetPosition());
+        d->adjustText();
     }
 }
 
+void RoutingInputWidget::handleHttpReply( QNetworkReply* reply )
+{
+    QDomDocument xml;
+    if (!xml.setContent(reply->readAll())) {
+        qWarning() << "Cannot parse osm nominatim result " << xml.toString();
+        return;
+    }
+
+    QVector<GeoDataPlacemark> placemarks;
+    QDomElement root = xml.documentElement();
+    QDomNodeList places = root.elementsByTagName("result");
+    if (places.size()==1) {
+        QString address = places.item(0).toElement().text();
+        d->m_lineEdit->setText(address);
+        d->m_lineEdit->setCursorPosition(0);
+    }
+}
+
 } // namespace Marble
 
 #include "RoutingInputWidget.moc"
--- trunk/KDE/kdeedu/marble/src/lib/routing/RoutingInputWidget.h #1104895:1104896
@@ -15,6 +15,8 @@
 
 #include <QtGui/QWidget>
 
+class QNetworkReply;
+
 namespace Marble {
 
 class RoutingInputWidgetPrivate;
@@ -129,6 +131,12 @@
     /** Set the target position (dragging) */
     void updatePosition(int index, const GeoDataCoordinates &position);
 
+    /** Start reverse geocoding request */
+    void startHttpRequest();
+
+    /** Http request with nominatim.openstreetmap.org done */
+    void handleHttpReply( QNetworkReply* );
+
 private:
     RoutingInputWidgetPrivate* const d;
 };


More information about the Marble-commits mailing list