• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.14
  • kdeedu
  • marble
  • src
  • plugins
  • runner
  • nominatim-search
OsmNominatimSearchRunner.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2010 Dennis Nienhüser <earthwings@gentoo.org>
9 //
10 
11 #include "OsmNominatimSearchRunner.h"
12 
13 #include "MarbleDebug.h"
14 #include "MarbleLocale.h"
15 #include "GeoDataDocument.h"
16 #include "GeoDataPlacemark.h"
17 #include "GeoDataExtendedData.h"
18 #include "TinyWebBrowser.h"
19 
20 #include <QString>
21 #include <QVector>
22 #include <QUrl>
23 #include <QTimer>
24 #include <QNetworkAccessManager>
25 #include <QNetworkReply>
26 #include <QDomDocument>
27 
28 namespace Marble
29 {
30 
31 OsmNominatimRunner::OsmNominatimRunner( QObject *parent ) :
32  SearchRunner( parent ),
33  m_manager()
34 {
35  connect(&m_manager, SIGNAL(finished(QNetworkReply*)),
36  this, SLOT(handleResult(QNetworkReply*)));
37 }
38 
39 OsmNominatimRunner::~OsmNominatimRunner()
40 {
41  // nothing to do
42 }
43 
44 void OsmNominatimRunner::returnNoResults()
45 {
46  emit searchFinished( QVector<GeoDataPlacemark*>() );
47 }
48 
49 void OsmNominatimRunner::search( const QString &searchTerm, const GeoDataLatLonBox &preferred )
50 {
51  QString base = "http://nominatim.openstreetmap.org/search?";
52  QString query = "q=%1&format=xml&addressdetails=1&accept-language=%2";
53  QString url = QString(base + query).arg(searchTerm).arg(MarbleLocale::languageCode());
54  if( !preferred.isEmpty() ) {
55  GeoDataCoordinates::Unit deg = GeoDataCoordinates::Degree;
56  QString viewbox( "&viewbox=%1,%2,%3,%4&bounded=1" ); // left, top, right, bottom
57  url += viewbox.arg(preferred.west(deg))
58  .arg(preferred.north(deg))
59  .arg(preferred.east(deg))
60  .arg(preferred.south(deg));
61 
62  }
63  m_request.setUrl(QUrl(url));
64  m_request.setRawHeader("User-Agent", TinyWebBrowser::userAgent("Browser", "OsmNominatimRunner") );
65 
66  QEventLoop eventLoop;
67 
68  QTimer timer;
69  timer.setSingleShot( true );
70  timer.setInterval( 15000 );
71 
72  connect( &timer, SIGNAL(timeout()),
73  &eventLoop, SLOT(quit()));
74  connect( this, SIGNAL(searchFinished(QVector<GeoDataPlacemark*>)),
75  &eventLoop, SLOT(quit()) );
76 
77  // @todo FIXME Must currently be done in the main thread, see bug 257376
78  QTimer::singleShot( 0, this, SLOT(startSearch()) );
79  timer.start();
80 
81  eventLoop.exec();
82 }
83 
84 void OsmNominatimRunner::startSearch()
85 {
86  QNetworkReply *reply = m_manager.get( m_request );
87  connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
88  this, SLOT(returnNoResults()));
89 }
90 
91 
92 void OsmNominatimRunner::handleResult( QNetworkReply* reply )
93 {
94  QDomDocument xml;
95  if (!xml.setContent(reply->readAll())) {
96  qWarning() << "Cannot parse osm nominatim result";
97  returnNoResults();
98  return;
99  }
100 
101  QVector<GeoDataPlacemark*> placemarks;
102  QDomElement root = xml.documentElement();
103  QDomNodeList places = root.elementsByTagName("place");
104  for (int i=0; i<places.size(); ++i) {
105  QDomNode place = places.at(i);
106  QDomNamedNodeMap attributes = place.attributes();
107  QString lon = attributes.namedItem("lon").nodeValue();
108  QString lat = attributes.namedItem("lat").nodeValue();
109  QString desc = attributes.namedItem("display_name").nodeValue();
110  QString key = attributes.namedItem("class").nodeValue();
111  QString value = attributes.namedItem("type").nodeValue();
112 
113  QString name = place.firstChildElement(value).text();
114  QString road = place.firstChildElement("road").text();
115 
116  QString city = place.firstChildElement("city").text();
117  if( city.isEmpty() ) {
118  city = place.firstChildElement("town").text();
119  if( city.isEmpty() ) {
120  city = place.firstChildElement("village").text();
121  } if( city.isEmpty() ) {
122  city = place.firstChildElement("hamlet").text();
123  }
124  }
125 
126  QString administrative = place.firstChildElement("county").text();
127  if( administrative.isEmpty() ) {
128  administrative = place.firstChildElement("region").text();
129  if( administrative.isEmpty() ) {
130  administrative = place.firstChildElement("state").text();
131  }
132  }
133 
134  QString country = place.firstChildElement("country").text();
135 
136  QString description;
137  for (int i=0; i<place.childNodes().size(); ++i) {
138  QDomElement item = place.childNodes().at(i).toElement();
139  description += item.nodeName() + ':' + item.text() + '\n';
140  }
141  description += "Category: " + key + '/' + value;
142 
143  if (!lon.isEmpty() && !lat.isEmpty() && !desc.isEmpty()) {
144  QString placemarkName;
145  GeoDataPlacemark* placemark = new GeoDataPlacemark;
146  // try to provide 2 fields
147  if (!name.isEmpty()) {
148  placemarkName = name;
149  }
150  if (!road.isEmpty() && road != placemarkName ) {
151  if( !placemarkName.isEmpty() ) {
152  placemarkName += ", ";
153  }
154  placemarkName += road;
155  }
156  if (!city.isEmpty() && !placemarkName.contains(",") && city != placemarkName) {
157  if( !placemarkName.isEmpty() ) {
158  placemarkName += ", ";
159  }
160  placemarkName += city;
161  }
162  if (!administrative.isEmpty()&& !placemarkName.contains(",") && administrative != placemarkName) {
163  if( !placemarkName.isEmpty() ) {
164  placemarkName += ", ";
165  }
166  placemarkName += administrative;
167  }
168  if (!country.isEmpty()&& !placemarkName.contains(",") && country != placemarkName) {
169  if( !placemarkName.isEmpty() ) {
170  placemarkName += ", ";
171  }
172  placemarkName += country;
173  }
174  if (placemarkName.isEmpty()) {
175  placemarkName = desc;
176  }
177  placemark->setName( placemarkName );
178  placemark->setDescription(description);
179  placemark->setCoordinate( lon.toDouble(), lat.toDouble(), 0, GeoDataCoordinates::Degree );
180  GeoDataFeature::GeoDataVisualCategory category = GeoDataFeature::OsmVisualCategory( key + '=' + value );
181  placemark->setVisualCategory( category );
182  placemarks << placemark;
183  }
184  }
185 
186  emit searchFinished( placemarks );
187 }
188 
189 } // namespace Marble
190 
191 #include "OsmNominatimSearchRunner.moc"
Marble::GeoDataCoordinates::Unit
Unit
enum used constructor to specify the units used
Definition: GeoDataCoordinates.h:64
GeoDataDocument.h
QTimer::setInterval
void setInterval(int msec)
QDomElement::elementsByTagName
QDomNodeList elementsByTagName(const QString &tagname) const
Marble::GeoDataFeature::OsmVisualCategory
static GeoDataVisualCategory OsmVisualCategory(const QString &keyValue)
Convenience categorization of placemarks for Osm key=value pairs.
Definition: GeoDataFeature.cpp:875
Marble::MarbleLocale::languageCode
static QString languageCode()
Definition: MarbleLocale.cpp:50
Marble::GeoDataLatLonBox::isEmpty
virtual bool isEmpty() const
Indicates whether the bounding box is not initialised (and contains nothing).
Definition: GeoDataLatLonBox.cpp:768
TinyWebBrowser.h
QEventLoop
QNetworkRequest::setUrl
void setUrl(const QUrl &url)
QDomNode::nodeValue
QString nodeValue() const
QNetworkReply
QDomNodeList
Marble::SearchRunner::searchFinished
void searchFinished(QVector< GeoDataPlacemark * > result)
This is emitted to indicate that the runner has finished the placemark search.
QDomDocument::documentElement
QDomElement documentElement() const
QDomNode
GeoDataExtendedData.h
QString::toDouble
double toDouble(bool *ok) const
QDomNode::childNodes
QDomNodeList childNodes() const
MarbleDebug.h
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
QDomNode::toElement
QDomElement toElement() const
QDomNamedNodeMap
Marble::GeoDataLatLonBox::north
qreal north(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the northern boundary of the bounding box.
Definition: GeoDataLatLonBox.cpp:93
QObject::name
const char * name() const
Marble::GeoDataLatLonBox::east
qreal east(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the eastern boundary of the bounding box.
Definition: GeoDataLatLonBox.cpp:135
Marble::OsmNominatimRunner::~OsmNominatimRunner
~OsmNominatimRunner()
Definition: OsmNominatimReverseGeocodingRunner.cpp:39
QDomElement::text
QString text() const
QTimer
Marble::OsmNominatimRunner::search
void search(const QString &searchTerm, const GeoDataLatLonBox &preferred)
Start a placemark search.
Definition: OsmNominatimSearchRunner.cpp:49
QEventLoop::exec
int exec(QFlags< QEventLoop::ProcessEventsFlag > flags)
QObject
QDomNode::nodeName
QString nodeName() const
QString::isEmpty
bool isEmpty() const
QIODevice::readAll
QByteArray readAll()
QString
MarbleLocale.h
GeoDataPlacemark.h
QDomNamedNodeMap::namedItem
QDomNode namedItem(const QString &name) const
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QUrl
QDomDocument
OsmNominatimSearchRunner.h
Marble::GeoDataLatLonBox::west
qreal west(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the western boundary of the bounding box.
Definition: GeoDataLatLonBox.cpp:156
QVector
QNetworkRequest::setRawHeader
void setRawHeader(const QByteArray &headerName, const QByteArray &headerValue)
Marble::OsmNominatimRunner::OsmNominatimRunner
OsmNominatimRunner(QObject *parent=0)
Definition: OsmNominatimReverseGeocodingRunner.cpp:31
QDomNode::firstChildElement
QDomElement firstChildElement(const QString &tagName) const
Marble::GeoDataLatLonBox::south
qreal south(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
Get the southern boundary of the bounding box.
Definition: GeoDataLatLonBox.cpp:114
QTimer::start
void start(int msec)
Marble::TinyWebBrowser::userAgent
static QByteArray userAgent(const QString &platform, const QString &plugin)
Definition: TinyWebBrowser.cpp:106
Marble::GeoDataFeature::GeoDataVisualCategory
GeoDataVisualCategory
A categorization of a placemark as defined by ...FIXME.
Definition: GeoDataFeature.h:77
QNetworkAccessManager::get
QNetworkReply * get(const QNetworkRequest &request)
QDomNodeList::size
int size() const
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QDomElement
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QDomNode::attributes
QDomNamedNodeMap attributes() const
Marble::GeoDataLatLonBox
A class that defines a 2D bounding box for geographic data.
Definition: GeoDataLatLonBox.h:51
QDomNodeList::at
QDomNode at(int index) const
QDomDocument::setContent
bool setContent(const QByteArray &data, bool namespaceProcessing, QString *errorMsg, int *errorLine, int *errorColumn)
QTimer::setSingleShot
void setSingleShot(bool singleShot)
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:13:41 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal