summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2016-11-24 19:36:23 +0100
committerLiang Qi <liang.qi@qt.io>2016-11-24 19:36:23 +0100
commite2ece6d1283926c5a91362933719f3d10efa2ed5 (patch)
tree5fa62a28a909fd74dbbe31fcba29dc3c5f8e74bb /src
parentf0c46685091fade417f118bfdc8ccdcbb4e9b9ce (diff)
parent78c73ebf88fbb97ebb796fc71e76232af5c8f1d3 (diff)
downloadqtlocation-5.7.tar.gz
Merge remote-tracking branch 'origin/5.6' into 5.75.7
Change-Id: I49b1b3fc94819b5a7f2fd1ab2481a1d8ea41586b
Diffstat (limited to 'src')
-rw-r--r--src/imports/location/qdeclarativegeomap.cpp3
-rw-r--r--src/location/maps/qgeorouteparser_p_p.h11
-rw-r--r--src/plugins/geoservices/nokia/nokia.pro4
-rw-r--r--src/plugins/geoservices/nokia/qgeocodejsonparser.cpp413
-rw-r--r--src/plugins/geoservices/nokia/qgeocodejsonparser.h (renamed from src/plugins/geoservices/nokia/qgeocodexmlparser.h)33
-rw-r--r--src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp17
-rw-r--r--src/plugins/geoservices/nokia/qgeocodereply_nokia.h3
-rw-r--r--src/plugins/geoservices/nokia/qgeocodexmlparser.cpp573
-rw-r--r--src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp194
-rw-r--r--src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h5
-rw-r--r--src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp2
-rw-r--r--src/plugins/geoservices/nokia/uri_constants.cpp5
-rw-r--r--src/plugins/geoservices/nokia/uri_constants.h3
-rw-r--r--src/plugins/geoservices/osm/qgeoroutereplyosm.cpp7
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp21
15 files changed, 610 insertions, 684 deletions
diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp
index 53d607fb..dbea220f 100644
--- a/src/imports/location/qdeclarativegeomap.cpp
+++ b/src/imports/location/qdeclarativegeomap.cpp
@@ -890,6 +890,9 @@ void QDeclarativeGeoMap::fitViewportToGeoShape()
QGeoRectangle rect = m_region;
topLeft = rect.topLeft();
bottomRight = rect.bottomRight();
+ if (bottomRight.longitude() < topLeft.longitude())
+ bottomRight.setLongitude(bottomRight.longitude() + 360.0);
+
break;
}
case QGeoShape::CircleType:
diff --git a/src/location/maps/qgeorouteparser_p_p.h b/src/location/maps/qgeorouteparser_p_p.h
index 7bf41f87..63c773eb 100644
--- a/src/location/maps/qgeorouteparser_p_p.h
+++ b/src/location/maps/qgeorouteparser_p_p.h
@@ -37,6 +37,17 @@
#ifndef QGEOROUTEPARSER_P_P_H
#define QGEOROUTEPARSER_P_P_H
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
#include <QtCore/private/qobject_p.h>
#include <QtCore/QUrl>
#include <QtLocation/qgeoroutereply.h>
diff --git a/src/plugins/geoservices/nokia/nokia.pro b/src/plugins/geoservices/nokia/nokia.pro
index cd340f50..1aa31123 100644
--- a/src/plugins/geoservices/nokia/nokia.pro
+++ b/src/plugins/geoservices/nokia/nokia.pro
@@ -10,7 +10,7 @@ contains(QT_CONFIG, location-china-support) {
HEADERS += \
qgeocodereply_nokia.h \
- qgeocodexmlparser.h \
+ qgeocodejsonparser.h \
qgeocodingmanagerengine_nokia.h \
qgeotiledmappingmanagerengine_nokia.h \
qgeotilefetcher_nokia.h \
@@ -31,7 +31,7 @@ HEADERS += \
SOURCES += \
qgeocodereply_nokia.cpp \
- qgeocodexmlparser.cpp \
+ qgeocodejsonparser.cpp \
qgeocodingmanagerengine_nokia.cpp \
qgeotiledmappingmanagerengine_nokia.cpp \
qgeotilefetcher_nokia.cpp \
diff --git a/src/plugins/geoservices/nokia/qgeocodejsonparser.cpp b/src/plugins/geoservices/nokia/qgeocodejsonparser.cpp
new file mode 100644
index 00000000..128f7fd2
--- /dev/null
+++ b/src/plugins/geoservices/nokia/qgeocodejsonparser.cpp
@@ -0,0 +1,413 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgeocodejsonparser.h"
+
+#include <QtPositioning/QGeoShape>
+#include <QtPositioning/QGeoRectangle>
+#include <QtPositioning/QGeoAddress>
+#include <QtPositioning/QGeoCoordinate>
+
+#include <QtCore/QThreadPool>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonParseError>
+#include <QtCore/QVariantMap>
+
+#include <QtDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+/*
+ Checks that the given Location object contains the information
+ we need and is not malformed in any way. We expect a Location
+ object of the following form:
+
+ "Location": {
+ "Address": {
+ "AdditionalData": [
+ {
+ "key": "CountryName",
+ "value": "Australia"
+ },
+ {
+ "key": "StateName",
+ "value": "New South Wales"
+ }
+ ],
+ "City": "Sydney",
+ "Country": "AUS",
+ "District": "Casula",
+ "Label": "Casula, Sydney, NSW, Australia",
+ "PostalCode": "2170",
+ "State": "NSW"
+ },
+ "DisplayPosition": {
+ "Latitude": -33.949509999999997,
+ "Longitude": 150.90386000000001
+ },
+ "LocationId": "NT_5UQ89lKoiI4DIYbOrIR0-D",
+ "LocationType": "area",
+ "MapReference": {
+ "CityId": "1469266800",
+ "CountryId": "1469256839",
+ "DistrictId": "1469267758",
+ "MapId": "NXAM16130",
+ "MapReleaseDate": "2016-10-05",
+ "MapVersion": "Q1/2016",
+ "ReferenceId": "868383156",
+ "SideOfStreet": "neither",
+ "StateId": "1469256831"
+ },
+ "MapView": {
+ "BottomRight": {
+ "Latitude": -33.966839999999998,
+ "Longitude": 150.91875999999999
+ },
+ "TopLeft": {
+ "Latitude": -33.937440000000002,
+ "Longitude": 150.87457000000001
+ }
+ }
+ }
+
+*/
+bool checkLocation(const QJsonObject &loc, QString *errorString)
+{
+ QJsonObject::const_iterator ait = loc.constFind(QLatin1String("Address"));
+ if (ait == loc.constEnd()) {
+ *errorString = QLatin1String("Expected Address element within Location object");
+ return false;
+ } else if (!ait.value().isObject()) {
+ *errorString = QLatin1String("Expected Address object within Location object");
+ return false;
+ }
+
+ QJsonObject::const_iterator dpit = loc.constFind(QLatin1String("DisplayPosition"));
+ if (dpit == loc.constEnd()) {
+ *errorString = QLatin1String("Expected DisplayPosition element within Location object");
+ return false;
+ } else if (!dpit.value().isObject()) {
+ *errorString = QLatin1String("Expected DisplayPosition object within Location object");
+ return false;
+ }
+ QJsonObject displayPosition = dpit.value().toObject();
+ QJsonObject::const_iterator latit = displayPosition.constFind(QLatin1String("Latitude"));
+ if (latit == displayPosition.constEnd()) {
+ *errorString = QLatin1String("Expected Latitude element within Location.DisplayPosition object");
+ return false;
+ } else if (!latit.value().isDouble()) {
+ *errorString = QLatin1String("Expected Latitude double within Location.DisplayPosition object");
+ return false;
+ }
+ QJsonObject::const_iterator lonit = displayPosition.constFind(QLatin1String("Longitude"));
+ if (lonit == displayPosition.constEnd()) {
+ *errorString = QLatin1String("Expected Longitude element within Location.DisplayPosition object");
+ return false;
+ } else if (!lonit.value().isDouble()) {
+ *errorString = QLatin1String("Expected Longitude double within Location.DisplayPosition object");
+ return false;
+ }
+
+ QJsonObject::const_iterator mvit = loc.constFind(QLatin1String("MapView"));
+ if (mvit == loc.constEnd()) {
+ *errorString = QLatin1String("Expected MapView element within Location object");
+ return false;
+ } else if (!mvit.value().isObject()) {
+ *errorString = QLatin1String("Expected MapView object within Location object");
+ return false;
+ }
+ QJsonObject mapView = mvit.value().toObject();
+ QJsonObject::const_iterator brit = mapView.constFind(QLatin1String("BottomRight"));
+ if (brit == mapView.constEnd()) {
+ *errorString = QLatin1String("Expected BottomRight element within Location.MapView object");
+ return false;
+ } else if (!brit.value().isObject()) {
+ *errorString = QLatin1String("Expected BottomRight object within Location.MapView object");
+ return false;
+ }
+ QJsonObject bottomRight = brit.value().toObject();
+ QJsonObject::const_iterator brlatit = bottomRight.constFind(QLatin1String("Latitude"));
+ if (brlatit == bottomRight.constEnd()) {
+ *errorString = QLatin1String("Expected Latitude element within Location.MapView.BottomRight object");
+ return false;
+ } else if (!brlatit.value().isDouble()) {
+ *errorString = QLatin1String("Expected Latitude double within Location.MapView.BottomRight object");
+ return false;
+ }
+ QJsonObject::const_iterator brlonit = bottomRight.constFind(QLatin1String("Longitude"));
+ if (brlonit == bottomRight.constEnd()) {
+ *errorString = QLatin1String("Expected Longitude element within Location.MapView.BottomRight object");
+ return false;
+ } else if (!brlonit.value().isDouble()) {
+ *errorString = QLatin1String("Expected Longitude double within Location.MapView.BottomRight object");
+ return false;
+ }
+ QJsonObject::const_iterator tlit = mapView.constFind(QLatin1String("TopLeft"));
+ if (tlit == mapView.constEnd()) {
+ *errorString = QLatin1String("Expected TopLeft element within Location.MapView object");
+ return false;
+ } else if (!tlit.value().isObject()) {
+ *errorString = QLatin1String("Expected TopLeft object within Location.MapView object");
+ return false;
+ }
+ QJsonObject topLeft = tlit.value().toObject();
+ QJsonObject::const_iterator tllatit = topLeft.constFind(QLatin1String("Latitude"));
+ if (tllatit == topLeft.constEnd()) {
+ *errorString = QLatin1String("Expected Latitude element within Location.MapView.TopLeft object");
+ return false;
+ } else if (!tllatit.value().isDouble()) {
+ *errorString = QLatin1String("Expected Latitude double within Location.MapView.TopLeft object");
+ return false;
+ }
+ QJsonObject::const_iterator tllonit = topLeft.constFind(QLatin1String("Longitude"));
+ if (tllonit == bottomRight.constEnd()) {
+ *errorString = QLatin1String("Expected Longitude element within Location.MapView.TopLeft object");
+ return false;
+ } else if (!tllonit.value().isDouble()) {
+ *errorString = QLatin1String("Expected Longitude double within Location.MapView.TopLeft object");
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ Checks that the given document contains the required information
+ and is not malformed in any way. We expect a document like the
+ following:
+
+ {
+ "Response": {
+ "MetaInfo": {
+ "Timestamp": "2016-10-18T08:42:04.369+0000"
+ },
+ "View": [
+ {
+ "ViewId": 0,
+ "_type": "SearchResultsViewType",
+ "Result": [
+ {
+ "Direction": 72.099999999999994,
+ "Distance": -1885.2,
+ "Location": {
+ // OMITTED FOR BREVITY
+ },
+ "MatchLevel": "district",
+ "MatchQuality": {
+ "City": 1,
+ "Country": 1,
+ "District": 1,
+ "PostalCode": 1,
+ "State": 1
+ },
+ "Relevance": 1
+ }
+ ]
+ }
+ ]
+ }
+ }
+*/
+bool checkDocument(const QJsonDocument &doc, QString *errorString)
+{
+ if (!doc.isObject()) {
+ *errorString = QLatin1String("Expected JSON document containing object");
+ return false;
+ }
+
+ QJsonObject rootObject = doc.object();
+ QJsonObject::const_iterator it = rootObject.constFind(QLatin1String("Response"));
+ if (it == rootObject.constEnd()) {
+ *errorString = QLatin1String("Expected Response element within root object");
+ return false;
+ } else if (!it.value().isObject()) {
+ *errorString = QLatin1String("Expected Response object within root object");
+ return false;
+ }
+
+ QJsonObject response = it.value().toObject();
+ QJsonObject::const_iterator rit = response.constFind(QLatin1String("View"));
+ if (rit == response.constEnd()) {
+ *errorString = QLatin1String("Expected View element within Response object");
+ return false;
+ } else if (!rit.value().isArray()) {
+ *errorString = QLatin1String("Expected View array within Response object");
+ return false;
+ }
+
+ QJsonArray view = rit.value().toArray();
+ Q_FOREACH (const QJsonValue &viewElement, view) {
+ if (!viewElement.isObject()) {
+ *errorString = QLatin1String("Expected View array element to be object");
+ return false;
+ }
+
+ QJsonObject viewObject = viewElement.toObject();
+ QJsonObject::const_iterator voit = viewObject.constFind(QLatin1String("Result"));
+ if (voit == viewObject.constEnd()) {
+ *errorString = QLatin1String("Expected Result element within View array object element");
+ return false;
+ } else if (!voit.value().isArray()) {
+ *errorString = QLatin1String("Expected Result array within View array object element");
+ return false;
+ }
+
+ QJsonArray result = voit.value().toArray();
+ Q_FOREACH (const QJsonValue &resultElement, result) {
+ if (!resultElement.isObject()) {
+ *errorString = QLatin1String("Expected Result array element to be object");
+ return false;
+ }
+
+ QJsonObject resultObject = resultElement.toObject();
+ QJsonObject::const_iterator roit = resultObject.constFind("Location");
+ if (roit == resultObject.constEnd()) {
+ *errorString = QLatin1String("Expected Location element in Result array element object");
+ return false;
+ } else if (!roit.value().isObject()) {
+ *errorString = QLatin1String("Expected Location object in Result array element object");
+ return false;
+ }
+
+ QJsonObject location = roit.value().toObject();
+ if (!checkLocation(location, errorString)) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool parseLocation(const QJsonObject &obj, const QGeoShape &bounds, QGeoLocation *loc)
+{
+ QJsonObject displayPosition = obj.value("DisplayPosition").toObject();
+ QGeoCoordinate coordinate = QGeoCoordinate(displayPosition.value("Latitude").toDouble(), displayPosition.value("Longitude").toDouble());
+ if (bounds.isValid() && !bounds.contains(coordinate)) {
+ // manual bounds check failed, location can be omitted from results.
+ return false;
+ }
+
+ QGeoAddress address;
+ QJsonObject addr = obj.value("Address").toObject();
+ address.setCountryCode(addr.value("Country").toString());
+ address.setState(addr.value("State").toString());
+ address.setCounty(addr.value("County").toString());
+ address.setCity(addr.value("City").toString());
+ address.setDistrict(addr.value("District").toString());
+ QString houseNumber = addr.value("HouseNumber").toString();
+ QString street = addr.value("Street").toString();
+ address.setStreet(houseNumber.isEmpty() ? street : QString("%1 %2").arg(houseNumber, street));
+ address.setPostalCode(addr.value("PostalCode").toString());
+ QString label = addr.value("Label").toString().trimmed();
+ if (!label.isEmpty()) {
+ address.setText(label);
+ }
+ QJsonArray additionalData = addr.value("AdditionalData").toArray();
+ Q_FOREACH (const QJsonValue &adv, additionalData) {
+ if (adv.isObject()) {
+ const QJsonObject &ado(adv.toObject());
+ if (ado.value("key").toString() == QLatin1String("CountryName")) {
+ address.setCountry(ado.value("value").toString());
+ }
+ }
+ }
+
+ QGeoRectangle boundingBox;
+ QJsonObject mapView = obj.value("MapView").toObject();
+ QJsonObject bottomRight = mapView.value("BottomRight").toObject();
+ QJsonObject topLeft = mapView.value("TopLeft").toObject();
+ boundingBox.setBottomRight(QGeoCoordinate(bottomRight.value("Latitude").toDouble(), bottomRight.value("Longitude").toDouble()));
+ boundingBox.setTopLeft(QGeoCoordinate(topLeft.value("Latitude").toDouble(), topLeft.value("Longitude").toDouble()));
+
+ loc->setAddress(address);
+ loc->setCoordinate(coordinate);
+ loc->setBoundingBox(boundingBox);
+
+ return true;
+}
+
+void parseDocument(const QJsonDocument &doc, const QGeoShape &bounds, QList<QGeoLocation> *locs)
+{
+ QJsonArray view = doc.object().value("Response").toObject().value("View").toArray();
+ Q_FOREACH (const QJsonValue &viewElement, view) {
+ QJsonArray result = viewElement.toObject().value("Result").toArray();
+ Q_FOREACH (const QJsonValue &resultElement, result) {
+ QGeoLocation location;
+ if (parseLocation(resultElement.toObject().value("Location").toObject(), bounds, &location)) {
+ locs->append(location);
+ }
+ }
+ }
+}
+
+} // namespace
+
+void QGeoCodeJsonParser::setBounds(const QGeoShape &bounds)
+{
+ m_bounds = bounds;
+}
+
+void QGeoCodeJsonParser::parse(const QByteArray &data)
+{
+ m_data = data;
+ QThreadPool::globalInstance()->start(this);
+}
+
+void QGeoCodeJsonParser::run()
+{
+ // parse the document.
+ QJsonParseError perror;
+ m_document = QJsonDocument::fromJson(m_data, &perror);
+ if (perror.error != QJsonParseError::NoError) {
+ m_errorString = perror.errorString();
+ } else {
+ // ensure that the response is valid and contains the information we need.
+ if (checkDocument(m_document, &m_errorString)) {
+ // extract the location results from the response.
+ parseDocument(m_document, m_bounds, &m_results);
+ emit results(m_results);
+ return;
+ }
+ }
+
+ emit error(m_errorString);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia/qgeocodexmlparser.h b/src/plugins/geoservices/nokia/qgeocodejsonparser.h
index 83a4b598..03251775 100644
--- a/src/plugins/geoservices/nokia/qgeocodexmlparser.h
+++ b/src/plugins/geoservices/nokia/qgeocodejsonparser.h
@@ -34,31 +34,26 @@
**
****************************************************************************/
-#ifndef QGEOCODEXMLPARSER_H
-#define QGEOCODEXMLPARSER_H
+#ifndef QGEOCODEJSONPARSER_H
+#define QGEOCODEJSONPARSER_H
+
+#include <QtPositioning/QGeoShape>
+#include <QtPositioning/QGeoLocation>
#include <QtCore/QObject>
#include <QtCore/QRunnable>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QByteArray>
#include <QtCore/QString>
#include <QtCore/QList>
-#include <QtPositioning/QGeoShape>
QT_BEGIN_NAMESPACE
-class QGeoLocation;
-class QGeoAddress;
-class QGeoRectangle;
-class QGeoCoordinate;
-class QXmlStreamReader;
-
-class QGeoCodeXmlParser : public QObject, public QRunnable
+class QGeoCodeJsonParser : public QObject, public QRunnable
{
Q_OBJECT
public:
- QGeoCodeXmlParser();
- ~QGeoCodeXmlParser();
-
void setBounds(const QGeoShape &bounds);
void parse(const QByteArray &data);
void run();
@@ -68,17 +63,9 @@ signals:
void error(const QString &errorString);
private:
- bool parseRootElement();
- bool parsePlace(QGeoLocation *location);
- bool parseLocation(QGeoLocation *location);
- bool parseAddress(QGeoAddress *address);
- bool parseBoundingBox(QGeoRectangle *bounds);
- bool parseCoordinate(QGeoCoordinate *coordinate, const QString &elementName);
-
- QGeoShape m_bounds;
+ QJsonDocument m_document;
QByteArray m_data;
- QXmlStreamReader *m_reader;
-
+ QGeoShape m_bounds;
QList<QGeoLocation> m_results;
QString m_errorString;
};
diff --git a/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp b/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp
index 73d2d4c3..e99b9815 100644
--- a/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp
@@ -35,7 +35,7 @@
****************************************************************************/
#include "qgeocodereply_nokia.h"
-#include "qgeocodexmlparser.h"
+#include "qgeocodejsonparser.h"
#include "qgeoerror_messages.h"
#include <QtPositioning/QGeoShape>
@@ -45,9 +45,15 @@ Q_DECLARE_METATYPE(QList<QGeoLocation>)
QT_BEGIN_NAMESPACE
+// manualBoundsRequired will be true if the parser has to manually
+// check if a given result lies within the viewport bounds,
+// and false if the bounds information was able to be supplied
+// to the server in the request (so it should not return any
+// out-of-bounds results).
QGeoCodeReplyNokia::QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offset,
- const QGeoShape &viewport, QObject *parent)
-: QGeoCodeReply(parent), m_reply(reply), m_parsing(false)
+ const QGeoShape &viewport, bool manualBoundsRequired,
+ QObject *parent)
+: QGeoCodeReply(parent), m_reply(reply), m_parsing(false), m_manualBoundsRequired(manualBoundsRequired)
{
qRegisterMetaType<QList<QGeoLocation> >();
@@ -87,8 +93,9 @@ void QGeoCodeReplyNokia::networkFinished()
if (m_reply->error() != QNetworkReply::NoError)
return;
- QGeoCodeXmlParser *parser = new QGeoCodeXmlParser;
- parser->setBounds(viewport());
+ QGeoCodeJsonParser *parser = new QGeoCodeJsonParser; // QRunnable, autoDelete = true.
+ if (m_manualBoundsRequired)
+ parser->setBounds(viewport());
connect(parser, SIGNAL(results(QList<QGeoLocation>)),
this, SLOT(appendResults(QList<QGeoLocation>)));
connect(parser, SIGNAL(error(QString)), this, SLOT(parseError(QString)));
diff --git a/src/plugins/geoservices/nokia/qgeocodereply_nokia.h b/src/plugins/geoservices/nokia/qgeocodereply_nokia.h
index 85726fca..0d0c47d1 100644
--- a/src/plugins/geoservices/nokia/qgeocodereply_nokia.h
+++ b/src/plugins/geoservices/nokia/qgeocodereply_nokia.h
@@ -46,7 +46,7 @@ class QGeoCodeReplyNokia : public QGeoCodeReply
{
Q_OBJECT
public:
- QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offset, const QGeoShape &viewport, QObject *parent = 0);
+ QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offset, const QGeoShape &viewport, bool manualBoundsRequired, QObject *parent = 0);
~QGeoCodeReplyNokia();
void abort();
@@ -60,6 +60,7 @@ private Q_SLOTS:
private:
QNetworkReply *m_reply;
bool m_parsing;
+ bool m_manualBoundsRequired;
};
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp b/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp
deleted file mode 100644
index 89738869..00000000
--- a/src/plugins/geoservices/nokia/qgeocodexmlparser.cpp
+++ /dev/null
@@ -1,573 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtLocation module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later 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 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qgeocodexmlparser.h"
-
-#include <QtCore/QXmlStreamReader>
-#include <QtCore/QThreadPool>
-#include <QtPositioning/QGeoLocation>
-#include <QtPositioning/QGeoAddress>
-#include <QtPositioning/QGeoCoordinate>
-#include <QtPositioning/QGeoRectangle>
-
-QT_BEGIN_NAMESPACE
-
-QGeoCodeXmlParser::QGeoCodeXmlParser()
-{
-}
-
-QGeoCodeXmlParser::~QGeoCodeXmlParser()
-{
-}
-
-void QGeoCodeXmlParser::setBounds(const QGeoShape &bounds)
-{
- m_bounds = bounds;
-}
-
-void QGeoCodeXmlParser::parse(const QByteArray &data)
-{
- m_data = data;
- QThreadPool::globalInstance()->start(this);
-}
-
-void QGeoCodeXmlParser::run()
-{
- m_reader = new QXmlStreamReader(m_data);
-
- if (!parseRootElement())
- emit error(m_reader->errorString());
- else
- emit results(m_results);
-
- delete m_reader;
- m_reader = 0;
-}
-
-bool QGeoCodeXmlParser::parseRootElement()
-{
- /*
- <xsd:element name="places">
- <xsd:complexType>
- <xsd:sequence>
- <xsd:element minOccurs="0" maxOccurs="unbounded" name="place" type="gc:Place"/>
- </xsd:sequence>
- <xsd:attribute name="resultCode" type="gc:ResultCodes"/>
- <xsd:attribute name="resultDescription" type="xsd:string"/>
- <xsd:attribute name="resultsTotal" type="xsd:nonNegativeInteger"/>
- </xsd:complexType>
- </xsd:element>
-
- <xsd:simpleType name="ResultCodes">
- <xsd:restriction base="xsd:string">
- <xsd:enumeration value="OK"/>
- <xsd:enumeration value="FAILED"/>
- </xsd:restriction>
- </xsd:simpleType>
- */
-
- if (m_reader->readNextStartElement()) {
- if (m_reader->name() == "places") {
- if (m_reader->attributes().hasAttribute("resultCode")) {
- QStringRef result = m_reader->attributes().value("resultCode");
- if (result == "FAILED") {
- QString resultDesc = m_reader->attributes().value("resultDescription").toString();
- if (resultDesc.isEmpty())
- resultDesc = "The attribute \"resultCode\" of the element \"places\" indicates that the request failed.";
-
- m_reader->raiseError(resultDesc);
-
- return false;
- } else if (result != "OK") {
- m_reader->raiseError(QString("The attribute \"resultCode\" of the element \"places\" has an unknown value (value was %1).").arg(result.toString()));
- return false;
- }
- }
-
- while (m_reader->readNextStartElement()) {
- if (m_reader->name() == "place") {
- QGeoLocation location;
-
- if (!parsePlace(&location))
- return false;
-
- if (!m_bounds.isValid() || m_bounds.contains(location.coordinate()))
- m_results.append(location);
- } else {
- m_reader->raiseError(QString("The element \"places\" did not expect a child element named \"%1\".").arg(m_reader->name().toString()));
- return false;
- }
- }
- } else {
- m_reader->raiseError(QString("The root element is expected to have the name \"places\" (root element was named \"%1\").").arg(m_reader->name().toString()));
- return false;
- }
- } else {
- m_reader->raiseError("Expected a root element named \"places\" (no root element found).");
- return false;
- }
-
- if (m_reader->readNextStartElement()) {
- m_reader->raiseError(QString("A single root element named \"places\" was expected (second root element was named \"%1\")").arg(m_reader->name().toString()));
- return false;
- }
-
- return true;
-}
-
-
-//Note: the term Place here is semi-confusing since
-// the xml 'place' is actually a location ie coord + address
-bool QGeoCodeXmlParser::parsePlace(QGeoLocation *location)
-{
- /*
- <xsd:complexType name="Place">
- <xsd:all>
- <xsd:element name="location" type="gc:Location"/>
- <xsd:element minOccurs="0" name="address" type="gc:Address"/>
- <xsd:element minOccurs="0" name="alternatives" type="gc:Alternatives"/>
- </xsd:all>
- <xsd:attribute name="title" type="xsd:string" use="required"/>
- <xsd:attribute name="language" type="gc:LanguageCode" use="required"/>
- </xsd:complexType>
-
- <xsd:simpleType name="LanguageCode">
- <xsd:restriction base="xsd:string">
- <xsd:length value="3"/>
- </xsd:restriction>
- </xsd:simpleType>
- */
-
- Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "place");
-
- if (!m_reader->attributes().hasAttribute("title")) {
- m_reader->raiseError("The element \"place\" did not have the required attribute \"title\".");
- return false;
- }
-
- if (!m_reader->attributes().hasAttribute("language")) {
- //m_reader->raiseError("The element \"place\" did not have the required attribute \"language\".");
- //return false;
- } else {
- QString lang = m_reader->attributes().value("language").toString();
-
- if (lang.length() != 3) {
- m_reader->raiseError(QString("The attribute \"language\" of the element \"place\" was not of length 3 (length was %1).").arg(lang.length()));
- return false;
- }
- }
-
- bool parsedLocation = false;
- bool parsedAddress = false;
- bool parsedAlternatives = false;
-
- while (m_reader->readNextStartElement()) {
- QString name = m_reader->name().toString();
- if (name == "location") {
- if (parsedLocation) {
- m_reader->raiseError("The element \"place\" has multiple child elements named \"location\" (exactly one expected)");
- return false;
- }
-
- if (!parseLocation(location))
- return false;
-
- parsedLocation = true;
- } else if (name == "address") {
- if (parsedAddress) {
- m_reader->raiseError("The element \"place\" has multiple child elements named \"address\" (at most one expected)");
- return false;
- }
-
- QGeoAddress address;
- if (!parseAddress(&address))
- return false;
- else
- location->setAddress(address);
-
- location->setAddress(address);
-
- parsedAddress = true;
- } else if (name == "alternatives") {
- if (parsedAlternatives) {
- m_reader->raiseError("The element \"place\" has multiple child elements named \"alternatives\" (at most one expected)");
- return false;
- }
-
- // skip alternatives for now
- // need to work out if we have a use for them at all
- // and how to store them if we get them
- m_reader->skipCurrentElement();
-
- parsedAlternatives = true;
- } else {
- m_reader->raiseError(QString("The element \"place\" did not expect a child element named \"%1\".").arg(m_reader->name().toString()));
- return false;
- }
- }
-
- if (!parsedLocation) {
- m_reader->raiseError("The element \"place\" has no child elements named \"location\" (exactly one expected)");
- return false;
- }
-
- return true;
-}
-
-//Note: the term Place here is semi-confusing since
-// the xml 'location' is actually a parital location i.e coord
-// as opposed to coord + address
-bool QGeoCodeXmlParser::parseLocation(QGeoLocation *location)
-{
- /*
- <xsd:complexType name="Location">
- <xsd:all>
- <xsd:element name="position" type="gc:GeoCoord"/>
- <xsd:element minOccurs="0" name="boundingBox" type="gc:GeoBox"/>
- </xsd:all>
- </xsd:complexType>
-
- <xsd:complexType name="GeoBox">
- <xsd:sequence>
- <xsd:element name="topLeft" type="gc:GeoCoord"/>
- <xsd:element name="bottomRight" type="gc:GeoCoord"/>
- </xsd:sequence>
- </xsd:complexType>
- */
-
- Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "location");
-
- bool parsedPosition = false;
- bool parsedBounds = false;
-
- while (m_reader->readNextStartElement()) {
- QString name = m_reader->name().toString();
- if (name == "position") {
- if (parsedPosition) {
- m_reader->raiseError("The element \"location\" has multiple child elements named \"position\" (exactly one expected)");
- return false;
- }
-
- QGeoCoordinate coord;
- if (!parseCoordinate(&coord, "position"))
- return false;
-
- location->setCoordinate(coord);
-
- parsedPosition = true;
- } else if (name == "boundingBox") {
- if (parsedBounds) {
- m_reader->raiseError("The element \"location\" has multiple child elements named \"boundingBox\" (at most one expected)");
- return false;
- }
-
- QGeoRectangle bounds;
-
- if (!parseBoundingBox(&bounds))
- return false;
-
- location->setBoundingBox(bounds);
-
- parsedBounds = true;
- } else {
- m_reader->raiseError(QString("The element \"location\" did not expect a child element named \"%1\".").arg(m_reader->name().toString()));
- return false;
- }
- }
-
- if (!parsedPosition) {
- m_reader->raiseError("The element \"location\" has no child elements named \"position\" (exactly one expected)");
- return false;
- }
-
- return true;
-}
-
-bool QGeoCodeXmlParser::parseAddress(QGeoAddress *address)
-{
- /*
- <xsd:complexType name="Address">
- <xsd:sequence>
- <xsd:element minOccurs="0" maxOccurs="1" name="country" type="xsd:string"/>
- <xsd:element minOccurs="0" maxOccurs="1" name="countryCode" type="gc:CountryCode"/>
- <xsd:element minOccurs="0" maxOccurs="1" name="state" type="xsd:string"/>
- <xsd:element minOccurs="0" maxOccurs="1" name="county" type="xsd:string"/>
- <xsd:element minOccurs="0" maxOccurs="1" name="city" type="xsd:string"/>
- <xsd:element minOccurs="0" maxOccurs="1" name="district" type="xsd:string"/>
- <xsd:element minOccurs="0" maxOccurs="1" name="thoroughfare" type="gc:Thoroughfare"/>
- <xsd:element minOccurs="0" maxOccurs="1" name="postCode" type="xsd:string"/>
- </xsd:sequence>
- <xsd:attribute name="type" type="xsd:string"/>
- </xsd:complexType>
-
- <xsd:simpleType name="CountryCode">
- <xsd:restriction base="xsd:string">
- <xsd:length value="3" fixed="true"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <xsd:complexType name="Thoroughfare">
- <xsd:sequence>
- <xsd:element minOccurs="0" name="name" type="xsd:string"/>
- <xsd:element minOccurs="0" name="number" type="xsd:string"/>
- </xsd:sequence>
- </xsd:complexType>
- */
-
- Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "address");
-
- // currently ignoring the type of the address
-
- if (!m_reader->readNextStartElement())
- return true;
-
- if (m_reader->name() == "country") {
- address->setCountry(m_reader->readElementText());
- if (!m_reader->readNextStartElement())
- return true;
- }
-
- if (m_reader->name() == "countryCode") {
- address->setCountryCode(m_reader->readElementText());
-
- if (address->countryCode().length() != 3) {
- m_reader->raiseError(QString("The text of the element \"countryCode\" was not of length 3 (length was %1).").arg(address->countryCode().length()));
- return false;
- }
-
- if (!m_reader->readNextStartElement())
- return true;
- }
-
- if (m_reader->name() == "state") {
- address->setState(m_reader->readElementText());
- if (!m_reader->readNextStartElement())
- return true;
- }
-
- if (m_reader->name() == "county") {
- address->setCounty(m_reader->readElementText());
- if (!m_reader->readNextStartElement())
- return true;
- }
-
- if (m_reader->name() == "city") {
- address->setCity(m_reader->readElementText());
- if (!m_reader->readNextStartElement())
- return true;
- }
-
- if (m_reader->name() == "district") {
- address->setDistrict(m_reader->readElementText());
- if (!m_reader->readNextStartElement())
- return true;
- }
-
- bool inThoroughfare = false;
-
- if (m_reader->name() == "thoroughfare") {
- inThoroughfare = m_reader->readNextStartElement();
-
- if (inThoroughfare && (m_reader->name() == "name")) {
- address->setStreet(m_reader->readElementText());
- if (!m_reader->readNextStartElement())
- inThoroughfare = false;
- }
-
- if (inThoroughfare && (m_reader->name() == "number")) {
- address->setStreet(m_reader->readElementText() + ' ' + address->street());
- if (!m_reader->readNextStartElement())
- inThoroughfare = false;
- }
-
- if (inThoroughfare) {
- m_reader->raiseError(QString("The element \"thoroughFare\" did not expect the child element \"%1\" at this point (unknown child element or child element out of order).").arg(m_reader->name().toString()));
- return false;
- }
-
- if (!m_reader->readNextStartElement())
- return true;
- }
-
- if (m_reader->name() == "postCode") {
- address->setPostalCode(m_reader->readElementText());
- if (!m_reader->readNextStartElement())
- return true;
- }
-
- m_reader->raiseError(QString("The element \"address\" did not expect the child element \"%1\" at this point (unknown child element or child element out of order).").arg(m_reader->name().toString()));
- return false;
-}
-
-bool QGeoCodeXmlParser::parseBoundingBox(QGeoRectangle *bounds)
-{
- /*
- <xsd:complexType name="GeoBox">
- <xsd:sequence>
- <xsd:element name="topLeft" type="gc:GeoCoord"/>
- <xsd:element name="bottomRight" type="gc:GeoCoord"/>
- </xsd:sequence>
- </xsd:complexType>
- */
-
- Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "boundingBox");
-
- if (!m_reader->readNextStartElement()) {
- m_reader->raiseError("The element \"boundingBox\" was expected to have 2 child elements (0 found)");
- return false;
- }
-
- QGeoCoordinate nw;
-
- if (m_reader->name() == "topLeft") {
- if (!parseCoordinate(&nw, "topLeft"))
- return false;
- } else {
- m_reader->raiseError(QString("The element \"boundingBox\" expected this child element to be named \"topLeft\" (found an element named \"%1\")").arg(m_reader->name().toString()));
- return false;
- }
-
- if (!m_reader->readNextStartElement()) {
- m_reader->raiseError("The element \"boundingBox\" was expected to have 2 child elements (1 found)");
- return false;
- }
-
- QGeoCoordinate se;
-
- if (m_reader->name() == "bottomRight") {
- if (!parseCoordinate(&se, "bottomRight"))
- return false;
- } else {
- m_reader->raiseError(QString("The element \"boundingBox\" expected this child element to be named \"bottomRight\" (found an element named \"%1\")").arg(m_reader->name().toString()));
- return false;
- }
-
- if (m_reader->readNextStartElement()) {
- m_reader->raiseError("The element \"boundingBox\" was expected to have 2 child elements (more than 2 found)");
- return false;
- }
-
- *bounds = QGeoRectangle(nw, se);
-
- return true;
-}
-
-bool QGeoCodeXmlParser::parseCoordinate(QGeoCoordinate *coordinate, const QString &elementName)
-{
- /*
- <xsd:complexType name="GeoCoord">
- <xsd:sequence>
- <xsd:element name="latitude" type="gc:Latitude"/>
- <xsd:element name="longitude" type="gc:Longitude"/>
- </xsd:sequence>
- </xsd:complexType>
-
- <xsd:simpleType name="Latitude">
- <xsd:restriction base="xsd:float">
- <xsd:minInclusive value="-90.0"/>
- <xsd:maxInclusive value="90.0"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <xsd:simpleType name="Longitude">
- <xsd:restriction base="xsd:float">
- <xsd:minInclusive value="-180.0"/>
- <xsd:maxInclusive value="180.0"/>
- </xsd:restriction>
- </xsd:simpleType>
- */
-
- Q_ASSERT(m_reader->isStartElement() && m_reader->name() == elementName);
-
- if (!m_reader->readNextStartElement()) {
- m_reader->raiseError(QString("The element \"%1\" was expected to have 2 child elements (0 found)").arg(elementName));
- return false;
- }
-
- if (m_reader->name() == "latitude") {
- bool ok = false;
- QString s = m_reader->readElementText();
- double lat = s.toDouble(&ok);
-
- if (!ok) {
- m_reader->raiseError(QString("The element \"latitude\" expected a value convertable to type float (value was \"%1\")").arg(s));
- return false;
- }
-
- if (lat < -90.0 || 90.0 < lat) {
- m_reader->raiseError(QString("The element \"latitude\" expected a value between -90.0 and 90.0 inclusive (value was %1)").arg(lat));
- return false;
- }
-
- coordinate->setLatitude(lat);
- } else {
- m_reader->raiseError(QString("The element \"%1\" expected this child element to be named \"latitude\" (found an element named \"%2\")").arg(elementName).arg(m_reader->name().toString()));
- }
-
- if (!m_reader->readNextStartElement()) {
- m_reader->raiseError(QString("The element \"%1\" was expected to have 2 child elements (1 found)").arg(elementName));
- return false;
- }
-
- if (m_reader->name() == "longitude") {
- bool ok = false;
- QString s = m_reader->readElementText();
- double lng = s.toDouble(&ok);
-
- if (!ok) {
- m_reader->raiseError(QString("The element \"longitude\" expected a value convertable to type float (value was \"%1\")").arg(s));
- return false;
- }
-
- if (lng < -180.0 || 180.0 < lng) {
- m_reader->raiseError(QString("The element \"longitude\" expected a value between -180.0 and 180.0 inclusive (value was %1)").arg(lng));
- return false;
- }
-
- coordinate->setLongitude(lng);
- } else {
- m_reader->raiseError(QString("The element \"%1\" expected this child element to be named \"longitude\" (found an element named \"%2\")").arg(elementName).arg(m_reader->name().toString()));
- }
-
- if (m_reader->readNextStartElement()) {
- m_reader->raiseError(QString("The element \"%1\" was expected to have 2 child elements (more than 2 found)").arg(elementName));
- return false;
- }
-
- return true;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp
index 2e0eae42..b3c74a63 100644
--- a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.cpp
@@ -41,8 +41,12 @@
#include "qgeouriprovider.h"
#include "uri_constants.h"
-#include <qgeoaddress.h>
-#include <qgeocoordinate.h>
+#include <QtPositioning/QGeoAddress>
+#include <QtPositioning/QGeoCoordinate>
+#include <QtPositioning/QGeoCircle>
+#include <QtPositioning/QGeoRectangle>
+#include <QtPositioning/QGeoShape>
+
#include <QUrl>
#include <QMap>
#include <QStringList>
@@ -56,7 +60,8 @@ QGeoCodingManagerEngineNokia::QGeoCodingManagerEngineNokia(
QString *errorString)
: QGeoCodingManagerEngine(parameters)
, m_networkManager(networkManager)
- , m_uriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.geocoding.host"), GEOCODING_HOST, GEOCODING_HOST_CN))
+ , m_uriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.geocoding.host"), GEOCODING_HOST))
+ , m_reverseGeocodingUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.reversegeocoding.host"), REVERSE_GEOCODING_HOST))
{
Q_ASSERT(networkManager);
m_networkManager->setParent(this);
@@ -81,7 +86,7 @@ QString QGeoCodingManagerEngineNokia::getAuthenticationString() const
QString authenticationString;
if (!m_token.isEmpty() && !m_applicationId.isEmpty()) {
- authenticationString += "?token=";
+ authenticationString += "?app_code=";
authenticationString += m_token;
authenticationString += "&app_id=";
@@ -95,15 +100,43 @@ QString QGeoCodingManagerEngineNokia::getAuthenticationString() const
QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(const QGeoAddress &address,
const QGeoShape &bounds)
{
- QString requestString = "http://";
+ QString requestString = "https://";
requestString += m_uriProvider->getCurrentHost();
- requestString += "/geocoder/gc/2.0";
+ requestString += "/6.2/geocode.json";
requestString += getAuthenticationString();
+ requestString += "&gen=9";
- requestString += "&lg=";
+ requestString += "&language=";
requestString += languageToMarc(locale().language());
+ bool manualBoundsRequired = false;
+ if (bounds.type() == QGeoShape::RectangleType) {
+ QGeoRectangle rect(bounds);
+ if (rect.isValid()) {
+ requestString += "&bbox=";
+ requestString += trimDouble(rect.topLeft().latitude());
+ requestString += ",";
+ requestString += trimDouble(rect.topLeft().longitude());
+ requestString += ";";
+ requestString += trimDouble(rect.bottomRight().latitude());
+ requestString += ",";
+ requestString += trimDouble(rect.bottomRight().longitude());
+ }
+ } else if (bounds.type() == QGeoShape::CircleType) {
+ QGeoCircle circ(bounds);
+ if (circ.isValid()) {
+ requestString += "?prox=";
+ requestString += trimDouble(circ.center().latitude());
+ requestString += ",";
+ requestString += trimDouble(circ.center().longitude());
+ requestString += ",";
+ requestString += trimDouble(circ.radius());
+ }
+ } else {
+ manualBoundsRequired = true;
+ }
+
if (address.country().isEmpty()) {
QStringList parts;
@@ -119,8 +152,8 @@ QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(const QGeoAddress &address,
if (!address.street().isEmpty())
parts << address.street();
- requestString += "&obloc=";
- requestString += parts.join(" ");
+ requestString += "&searchtext=";
+ requestString += parts.join("+").replace(' ', '+');
} else {
requestString += "&country=";
requestString += address.country();
@@ -136,7 +169,7 @@ QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(const QGeoAddress &address,
}
if (!address.postalCode().isEmpty()) {
- requestString += "&zip=";
+ requestString += "&postalcode=";
requestString += address.postalCode();
}
@@ -146,39 +179,7 @@ QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(const QGeoAddress &address,
}
}
-
- // TODO?
- // street number has been removed from QGeoAddress
- // do we need to try to split it out from QGeoAddress::street
- // in order to geocode properly
-
- // Old code:
-// if (!address.streetNumber().isEmpty()) {
-// requestString += "&number=";
-// requestString += address.streetNumber();
-// }
-
- return geocode(requestString, bounds);
-}
-
-QGeoCodeReply *QGeoCodingManagerEngineNokia::reverseGeocode(const QGeoCoordinate &coordinate,
- const QGeoShape &bounds)
-{
- QString requestString = "http://";
- requestString += m_uriProvider->getCurrentHost();
- requestString += "/geocoder/rgc/2.0";
-
- requestString += getAuthenticationString();
-
- requestString += "&long=";
- requestString += trimDouble(coordinate.longitude());
- requestString += "&lat=";
- requestString += trimDouble(coordinate.latitude());
-
- requestString += "&lg=";
- requestString += languageToMarc(locale().language());
-
- return geocode(requestString, bounds);
+ return geocode(requestString, bounds, manualBoundsRequired);
}
QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(const QString &address,
@@ -186,52 +187,119 @@ QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(const QString &address,
int offset,
const QGeoShape &bounds)
{
- QString requestString = "http://";
+ QString requestString = "https://";
requestString += m_uriProvider->getCurrentHost();
- requestString += "/geocoder/gc/2.0";
+ requestString += "/6.2/geocode.json";
requestString += getAuthenticationString();
+ requestString += "&gen=9";
- requestString += "&lg=";
+ requestString += "&language=";
requestString += languageToMarc(locale().language());
- requestString += "&obloc=";
- requestString += address;
+ requestString += "&searchtext=";
+ requestString += QString(address).replace(' ', '+');
if (limit > 0) {
- requestString += "&total=";
+ requestString += "&maxresults=";
requestString += QString::number(limit);
}
-
if (offset > 0) {
- requestString += "&offset=";
- requestString += QString::number(offset);
+ // We cannot do this precisely, since HERE doesn't allow
+ // precise result-set offset to be supplied; instead, it
+ // returns "pages" of results at a time.
+ // So, we tell HERE which page of results we want, and the
+ // client has to filter out duplicates if they changed
+ // the limit param since the last call.
+ requestString += "&pageinformation=";
+ requestString += QString::number(offset/limit);
}
- return geocode(requestString, bounds, limit, offset);
+ bool manualBoundsRequired = false;
+ if (bounds.type() == QGeoShape::RectangleType) {
+ QGeoRectangle rect(bounds);
+ if (rect.isValid()) {
+ requestString += "&bbox=";
+ requestString += trimDouble(rect.topLeft().latitude());
+ requestString += ",";
+ requestString += trimDouble(rect.topLeft().longitude());
+ requestString += ";";
+ requestString += trimDouble(rect.bottomRight().latitude());
+ requestString += ",";
+ requestString += trimDouble(rect.bottomRight().longitude());
+ }
+ } else if (bounds.type() == QGeoShape::CircleType) {
+ QGeoCircle circ(bounds);
+ if (circ.isValid()) {
+ requestString += "?prox=";
+ requestString += trimDouble(circ.center().latitude());
+ requestString += ",";
+ requestString += trimDouble(circ.center().longitude());
+ requestString += ",";
+ requestString += trimDouble(circ.radius());
+ }
+ } else {
+ manualBoundsRequired = true;
+ }
+
+ return geocode(requestString, bounds, manualBoundsRequired, limit, offset);
}
QGeoCodeReply *QGeoCodingManagerEngineNokia::geocode(QString requestString,
const QGeoShape &bounds,
+ bool manualBoundsRequired,
int limit,
int offset)
{
- QNetworkReply *networkReply = m_networkManager->get(QNetworkRequest(QUrl(requestString)));
- QGeoCodeReplyNokia *reply = new QGeoCodeReplyNokia(networkReply, limit, offset, bounds, this);
+ QGeoCodeReplyNokia *reply = new QGeoCodeReplyNokia(
+ m_networkManager->get(QNetworkRequest(QUrl(requestString))),
+ limit, offset, bounds, manualBoundsRequired, this);
- connect(reply,
- SIGNAL(finished()),
- this,
- SLOT(placesFinished()));
+ connect(reply, &QGeoCodeReplyNokia::finished,
+ this, &QGeoCodingManagerEngineNokia::placesFinished);
- connect(reply,
- SIGNAL(error(QGeoCodeReply::Error,QString)),
- this,
- SLOT(placesError(QGeoCodeReply::Error,QString)));
+ connect(reply, static_cast<void (QGeoCodeReply::*)(QGeoCodeReply::Error, const QString &)>(&QGeoCodeReplyNokia::error),
+ this, &QGeoCodingManagerEngineNokia::placesError);
return reply;
}
+QGeoCodeReply *QGeoCodingManagerEngineNokia::reverseGeocode(const QGeoCoordinate &coordinate,
+ const QGeoShape &bounds)
+{
+ QString requestString = "https://";
+ requestString += m_reverseGeocodingUriProvider->getCurrentHost();
+ requestString += "/6.2/reversegeocode.json";
+
+ requestString += getAuthenticationString();
+ requestString += "&gen=9";
+
+ requestString += "&mode=retrieveAddresses";
+
+ requestString += "&prox=";
+ requestString += trimDouble(coordinate.latitude());
+ requestString += ",";
+ requestString += trimDouble(coordinate.longitude());
+
+ bool manualBoundsRequired = false;
+ if (bounds.type() == QGeoShape::CircleType) {
+ QGeoCircle circ(bounds);
+ if (circ.isValid() && circ.center() == coordinate) {
+ requestString += ",";
+ requestString += trimDouble(circ.radius());
+ } else {
+ manualBoundsRequired = true;
+ }
+ } else {
+ manualBoundsRequired = true;
+ }
+
+ requestString += "&language=";
+ requestString += languageToMarc(locale().language());
+
+ return geocode(requestString, bounds, manualBoundsRequired);
+}
+
QString QGeoCodingManagerEngineNokia::trimDouble(double degree, int decimalDigits)
{
QString sDegree = QString::number(degree, 'g', decimalDigits);
diff --git a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h
index baa91907..9e1564aa 100644
--- a/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h
+++ b/src/plugins/geoservices/nokia/qgeocodingmanagerengine_nokia.h
@@ -75,14 +75,15 @@ private Q_SLOTS:
private:
static QString trimDouble(double degree, int decimalDigits = 10);
- QGeoCodeReply *geocode(QString requestString, const QGeoShape &bounds, int limit = -1, int offset = 0);
+ QGeoCodeReply *geocode(QString requestString, const QGeoShape &bounds, bool manualBoundsRequired = true, int limit = -1, int offset = 0);
QString languageToMarc(QLocale::Language language);
QString getAuthenticationString() const;
QGeoNetworkAccessManager *m_networkManager;
+ QGeoUriProvider *m_uriProvider;
+ QGeoUriProvider *m_reverseGeocodingUriProvider;
QString m_token;
QString m_applicationId;
- QGeoUriProvider *m_uriProvider;
};
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp
index 6dcb28da..67b7e70f 100644
--- a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp
+++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp
@@ -200,7 +200,7 @@ QPlaceManagerEngineNokiaV2::QPlaceManagerEngineNokiaV2(
QString *errorString)
: QPlaceManagerEngine(parameters)
, m_manager(networkManager)
- , m_uriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.places.host"), PLACES_HOST, PLACES_HOST_CN))
+ , m_uriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.places.host"), PLACES_HOST))
{
Q_ASSERT(networkManager);
m_manager->setParent(this);
diff --git a/src/plugins/geoservices/nokia/uri_constants.cpp b/src/plugins/geoservices/nokia/uri_constants.cpp
index 8a075328..8db47beb 100644
--- a/src/plugins/geoservices/nokia/uri_constants.cpp
+++ b/src/plugins/geoservices/nokia/uri_constants.cpp
@@ -38,10 +38,9 @@
QT_BEGIN_NAMESPACE
const QString ROUTING_HOST = QLatin1String("route.api.here.com");
-const QString GEOCODING_HOST = QLatin1String("loc.desktop.maps.svc.ovi.com");
-const QString GEOCODING_HOST_CN = QLatin1String("pr.geo.maps.svc.nokia.com.cn");
+const QString GEOCODING_HOST = QLatin1String("geocoder.api.here.com");
+const QString REVERSE_GEOCODING_HOST = QLatin1String("reverse.geocoder.api.here.com");
const QString PLACES_HOST = QLatin1String("places.api.here.com");
-const QString PLACES_HOST_CN = QLatin1String("places.nlp.nokia.com.cn");
const QString MAP_TILES_HOST = QLatin1String("1-4.base.maps.api.here.com");
const QString MAP_TILES_HOST_AERIAL = QLatin1String("1-4.aerial.maps.api.here.com");
diff --git a/src/plugins/geoservices/nokia/uri_constants.h b/src/plugins/geoservices/nokia/uri_constants.h
index 151a4aa4..b2133fe3 100644
--- a/src/plugins/geoservices/nokia/uri_constants.h
+++ b/src/plugins/geoservices/nokia/uri_constants.h
@@ -43,9 +43,8 @@ QT_BEGIN_NAMESPACE
extern const QString ROUTING_HOST;
extern const QString GEOCODING_HOST;
-extern const QString GEOCODING_HOST_CN;
+extern const QString REVERSE_GEOCODING_HOST;
extern const QString PLACES_HOST;
-extern const QString PLACES_HOST_CN;
extern const QString MAP_TILES_HOST;
extern const QString MAP_TILES_HOST_AERIAL;
diff --git a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp
index da28317f..c640e595 100644
--- a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp
+++ b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp
@@ -80,13 +80,6 @@ void QGeoRouteReplyOsm::networkReplyFinished()
return;
}
- if (m_reply->error() != QNetworkReply::NoError) {
- setError(QGeoRouteReply::CommunicationError, m_reply->errorString());
- m_reply->deleteLater();
- m_reply = 0;
- return;
- }
-
QGeoRoutingManagerEngineOsm *engine = qobject_cast<QGeoRoutingManagerEngineOsm *>(parent());
const QGeoRouteParser *parser = engine->routeParser();
diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
index 245d855e..33523493 100644
--- a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
+++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
@@ -343,7 +343,7 @@ void QGeoPositionInfoSourceWinRT::virtualPositionUpdate()
// We can only do this if we received a valid position before
if (d->lastPosition.isValid()) {
QGeoPositionInfo sent = d->lastPosition;
- sent.setTimestamp(QDateTime::currentDateTime());
+ sent.setTimestamp(sent.timestamp().addMSecs(updateInterval()));
d->lastPosition = sent;
emit positionUpdated(sent);
}
@@ -486,7 +486,24 @@ HRESULT QGeoPositionInfoSourceWinRT::onPositionChanged(IGeolocator *locator, IPo
currentInfo.setAttribute(QGeoPositionInfo::GroundSpeed, value);
}
- currentInfo.setTimestamp(QDateTime::currentDateTime());
+ DateTime dateTime;
+ hr = coord->get_Timestamp(&dateTime);
+
+ if (dateTime.UniversalTime > 0) {
+ ULARGE_INTEGER uLarge;
+ uLarge.QuadPart = dateTime.UniversalTime;
+ FILETIME fileTime;
+ fileTime.dwHighDateTime = uLarge.HighPart;
+ fileTime.dwLowDateTime = uLarge.LowPart;
+ SYSTEMTIME systemTime;
+ if (FileTimeToSystemTime(&fileTime, &systemTime)) {
+ currentInfo.setTimestamp(QDateTime(QDate(systemTime.wYear, systemTime.wMonth,
+ systemTime.wDay),
+ QTime(systemTime.wHour, systemTime.wMinute,
+ systemTime.wSecond, systemTime.wMilliseconds),
+ Qt::UTC));
+ }
+ }
emit nativePositionUpdate(currentInfo);