summaryrefslogtreecommitdiff
path: root/src/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/geoservices/esri/esri.pro39
-rw-r--r--src/plugins/geoservices/esri/esri.qrc5
-rw-r--r--src/plugins/geoservices/esri/esri_plugin.json13
-rw-r--r--src/plugins/geoservices/esri/geocodereply_esri.cpp227
-rw-r--r--src/plugins/geoservices/esri/geocodereply_esri.h86
-rw-r--r--src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp186
-rw-r--r--src/plugins/geoservices/esri/geocodingmanagerengine_esri.h77
-rw-r--r--src/plugins/geoservices/esri/geomapsource.cpp107
-rw-r--r--src/plugins/geoservices/esri/geomapsource.h77
-rw-r--r--src/plugins/geoservices/esri/georoutejsonparser_esri.cpp246
-rw-r--r--src/plugins/geoservices/esri/georoutejsonparser_esri.h72
-rw-r--r--src/plugins/geoservices/esri/georoutereply_esri.cpp114
-rw-r--r--src/plugins/geoservices/esri/georoutereply_esri.h68
-rw-r--r--src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp190
-rw-r--r--src/plugins/geoservices/esri/georoutingmanagerengine_esri.h76
-rw-r--r--src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp86
-rw-r--r--src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h72
-rw-r--r--src/plugins/geoservices/esri/geotiledmap_esri.cpp73
-rw-r--r--src/plugins/geoservices/esri/geotiledmap_esri.h74
-rw-r--r--src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp284
-rw-r--r--src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h78
-rw-r--r--src/plugins/geoservices/esri/geotiledmapreply_esri.cpp129
-rw-r--r--src/plugins/geoservices/esri/geotiledmapreply_esri.h70
-rw-r--r--src/plugins/geoservices/esri/geotilefetcher_esri.cpp77
-rw-r--r--src/plugins/geoservices/esri/geotilefetcher_esri.h93
-rw-r--r--src/plugins/geoservices/esri/maps.json123
-rw-r--r--src/plugins/geoservices/geoservices.pro2
-rw-r--r--src/plugins/geoservices/mapbox/mapbox.pro10
-rw-r--r--src/plugins/geoservices/mapbox/mapbox_plugin.json3
-rw-r--r--src/plugins/geoservices/mapbox/qgeofiletilecachemapbox.cpp131
-rw-r--r--src/plugins/geoservices/mapbox/qgeofiletilecachemapbox.h63
-rw-r--r--src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp231
-rw-r--r--src/plugins/geoservices/mapbox/qgeoroutereplymapbox.h71
-rw-r--r--src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp122
-rw-r--r--src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.h76
-rw-r--r--src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.cpp25
-rw-r--r--src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp155
-rw-r--r--src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.h3
-rw-r--r--src/plugins/geoservices/mapbox/qgeotilefetchermapbox.cpp13
-rw-r--r--src/plugins/geoservices/mapbox/qgeotilefetchermapbox.h8
-rw-r--r--src/plugins/geoservices/nokia/nokia.pro12
-rw-r--r--src/plugins/geoservices/nokia/qgeofiletilecachenokia.cpp124
-rw-r--r--src/plugins/geoservices/nokia/qgeofiletilecachenokia.h60
-rw-r--r--src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp6
-rw-r--r--src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp4
-rw-r--r--src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp57
-rw-r--r--src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp28
-rw-r--r--src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h7
-rw-r--r--src/plugins/geoservices/nokia/qgeouriprovider.cpp37
-rw-r--r--src/plugins/geoservices/nokia/qgeouriprovider.h3
-rw-r--r--src/plugins/geoservices/osm/osm.pro4
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/cycle8
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/hiking9
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/night-transit9
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/satellite10
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/street10
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/street-hires9
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/terrain9
-rw-r--r--src/plugins/geoservices/osm/providers/5.8/transit9
-rw-r--r--src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp360
-rw-r--r--src/plugins/geoservices/osm/qgeofiletilecacheosm.h91
-rw-r--r--src/plugins/geoservices/osm/qgeotiledmaposm.cpp5
-rw-r--r--src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp255
-rw-r--r--src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h4
-rw-r--r--src/plugins/geoservices/osm/qgeotilefetcherosm.cpp39
-rw-r--r--src/plugins/geoservices/osm/qgeotilefetcherosm.h7
-rw-r--r--src/plugins/geoservices/osm/qgeotileproviderosm.cpp550
-rw-r--r--src/plugins/geoservices/osm/qgeotileproviderosm.h261
-rw-r--r--src/plugins/position/android/src/jnipositioning.cpp31
-rw-r--r--src/plugins/position/android/src/src.pro2
-rw-r--r--src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml2
-rw-r--r--src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml4
-rw-r--r--src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h18
-rw-r--r--src/plugins/position/gypsy/gypsy.pro5
-rw-r--r--src/plugins/position/position.pro6
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp16
76 files changed, 5239 insertions, 487 deletions
diff --git a/src/plugins/geoservices/esri/esri.pro b/src/plugins/geoservices/esri/esri.pro
new file mode 100644
index 00000000..3642ddaf
--- /dev/null
+++ b/src/plugins/geoservices/esri/esri.pro
@@ -0,0 +1,39 @@
+TARGET = qtgeoservices_esri
+
+QT += location-private positioning-private network
+
+HEADERS += \
+ geocodereply_esri.h \
+ geocodingmanagerengine_esri.h \
+ geomapsource.h \
+ georoutejsonparser_esri.h \
+ georoutereply_esri.h \
+ georoutingmanagerengine_esri.h \
+ geoserviceproviderfactory_esri.h \
+ geotiledmap_esri.h \
+ geotiledmappingmanagerengine_esri.h \
+ geotiledmapreply_esri.h \
+ geotilefetcher_esri.h
+
+SOURCES += \
+ geocodereply_esri.cpp \
+ geocodingmanagerengine_esri.cpp \
+ geomapsource.cpp \
+ georoutejsonparser_esri.cpp \
+ georoutereply_esri.cpp \
+ georoutingmanagerengine_esri.cpp \
+ geoserviceproviderfactory_esri.cpp \
+ geotiledmap_esri.cpp \
+ geotiledmappingmanagerengine_esri.cpp \
+ geotiledmapreply_esri.cpp \
+ geotilefetcher_esri.cpp
+
+RESOURCES += \
+ esri.qrc
+
+OTHER_FILES += \
+ esri_plugin.json
+
+PLUGIN_TYPE = geoservices
+PLUGIN_CLASS_NAME = GeoServiceProviderFactoryEsri
+load(qt_plugin)
diff --git a/src/plugins/geoservices/esri/esri.qrc b/src/plugins/geoservices/esri/esri.qrc
new file mode 100644
index 00000000..43b0857f
--- /dev/null
+++ b/src/plugins/geoservices/esri/esri.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>maps.json</file>
+ </qresource>
+</RCC>
diff --git a/src/plugins/geoservices/esri/esri_plugin.json b/src/plugins/geoservices/esri/esri_plugin.json
new file mode 100644
index 00000000..3398648e
--- /dev/null
+++ b/src/plugins/geoservices/esri/esri_plugin.json
@@ -0,0 +1,13 @@
+{
+ "Keys": ["esri"],
+ "Provider": "esri",
+ "Version": 100,
+ "Experimental": false,
+ "Features": [
+ "OnlineMappingFeature",
+ "OnlineGeocodingFeature",
+ "ReverseGeocodingFeature",
+ "OnlineRoutingFeature"
+ ],
+ "Priority": 1000
+}
diff --git a/src/plugins/geoservices/esri/geocodereply_esri.cpp b/src/plugins/geoservices/esri/geocodereply_esri.cpp
new file mode 100644
index 00000000..a7ad9368
--- /dev/null
+++ b/src/plugins/geoservices/esri/geocodereply_esri.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geocodereply_esri.h"
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+#include <QGeoCoordinate>
+#include <QGeoAddress>
+#include <QGeoLocation>
+#include <QGeoRectangle>
+
+QT_BEGIN_NAMESPACE
+
+GeoCodeReplyEsri::GeoCodeReplyEsri(QNetworkReply *reply, OperationType operationType,
+ QObject *parent) :
+ QGeoCodeReply(parent), m_reply(reply), m_operationType(operationType)
+{
+ connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished()));
+ connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
+ this, SLOT(networkReplyError(QNetworkReply::NetworkError)));
+
+ setLimit(1);
+ setOffset(0);
+}
+
+GeoCodeReplyEsri::~GeoCodeReplyEsri()
+{
+ if (m_reply)
+ m_reply->deleteLater();
+}
+
+void GeoCodeReplyEsri::abort()
+{
+ if (!m_reply)
+ return;
+
+ m_reply->abort();
+ QGeoCodeReply::abort();
+
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+}
+
+void GeoCodeReplyEsri::networkReplyError(QNetworkReply::NetworkError error)
+{
+ Q_UNUSED(error)
+
+ if (!m_reply)
+ return;
+
+ setError(QGeoCodeReply::CommunicationError, m_reply->errorString());
+
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+}
+
+void GeoCodeReplyEsri::networkReplyFinished()
+{
+ if (!m_reply)
+ return;
+
+ if (m_reply->error() != QNetworkReply::NoError)
+ {
+ setError(QGeoCodeReply::CommunicationError, m_reply->errorString());
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+ return;
+ }
+
+ QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll());
+
+ if (document.isObject()) {
+ QJsonObject object = document.object();
+
+ switch (operationType()) {
+ case Geocode:
+ {
+ QJsonArray candidates = object.value(QStringLiteral("candidates")).toArray();
+
+ QList<QGeoLocation> locations;
+
+ for (int i = 0; i < candidates.count(); i++) {
+ if (!candidates.at(i).isObject())
+ continue;
+
+ QJsonObject candidate = candidates.at(i).toObject();
+
+ QGeoLocation location = parseCandidate(candidate);
+ locations.append(location);
+ }
+
+ setLocations(locations);
+ setFinished(true);
+ }
+ break;
+
+ case ReverseGeocode:
+ {
+ QGeoLocation location = parseAddress(object);
+
+ QList<QGeoLocation> locations;
+ locations.append(location);
+
+ setLocations(locations);
+ setFinished(true);
+ }
+ break;
+ }
+
+ } else {
+ setError(QGeoCodeReply::CommunicationError, QStringLiteral("Unknown document"));
+ }
+
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+}
+
+QGeoLocation GeoCodeReplyEsri::parseAddress(const QJsonObject& object)
+{
+ QJsonObject addressObject = object.value(QStringLiteral("address")).toObject();
+
+ QGeoAddress address;
+
+ address.setCountryCode(addressObject.value(QStringLiteral("CountryCode")).toString());
+ address.setState(addressObject.value(QStringLiteral("Region")).toString());
+ address.setCity(addressObject.value(QStringLiteral("City")).toString());
+ address.setDistrict(addressObject.value(QStringLiteral("Subregion")).toString());
+ address.setPostalCode(addressObject.value(QStringLiteral("Postal")).toString());
+ address.setStreet(addressObject.value(QStringLiteral("Address")).toString());
+
+ QGeoCoordinate coordinate;
+
+ QJsonObject locationObject = object.value(QStringLiteral("location")).toObject();
+
+ coordinate.setLongitude(locationObject.value(QStringLiteral("x")).toDouble());
+ coordinate.setLatitude(locationObject.value(QStringLiteral("y")).toDouble());
+
+ QGeoLocation location;
+
+ location.setCoordinate(coordinate);
+ location.setAddress(address);
+
+ return location;
+}
+
+QGeoLocation GeoCodeReplyEsri::parseCandidate(const QJsonObject& candidate)
+{
+ QGeoCoordinate coordinate;
+
+ QJsonObject locationObject = candidate.value(QStringLiteral("location")).toObject();
+
+ coordinate.setLongitude(locationObject.value(QStringLiteral("x")).toDouble());
+ coordinate.setLatitude(locationObject.value(QStringLiteral("y")).toDouble());
+
+ QGeoRectangle extent;
+
+ if (candidate.contains(QStringLiteral("extent"))) {
+ QJsonObject extentObject = candidate.value(QStringLiteral("extent")).toObject();
+
+ extent.setTopLeft(QGeoCoordinate(extentObject.value(QStringLiteral("ymin")).toDouble(),
+ extentObject.value(QStringLiteral("xmin")).toDouble()));
+
+ extent.setBottomRight(QGeoCoordinate(extentObject.value(QStringLiteral("ymax")).toDouble(),
+ extentObject.value(QStringLiteral("xmax")).toDouble()));
+ }
+
+ QJsonObject attributesObject = candidate.value(QStringLiteral("attributes")).toObject();
+
+ QGeoAddress address;
+
+ address.setText(candidate.value(QStringLiteral("address")).toString());
+
+ address.setCountry(attributesObject.value(QStringLiteral("Country")).toString());
+ address.setCountryCode(attributesObject.value(QStringLiteral("Country")).toString());
+ address.setState(attributesObject.value(QStringLiteral("Region")).toString());
+ address.setCity(attributesObject.value(QStringLiteral("City")).toString());
+ address.setDistrict(attributesObject.value(QStringLiteral("Subregion")).toString());
+ address.setPostalCode(attributesObject.value(QStringLiteral("Postal")).toString());
+
+ QGeoLocation location;
+
+ location.setCoordinate(coordinate);
+ location.setBoundingBox(extent);
+ location.setAddress(address);
+
+ return location;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/geocodereply_esri.h b/src/plugins/geoservices/esri/geocodereply_esri.h
new file mode 100644
index 00000000..4434b7dc
--- /dev/null
+++ b/src/plugins/geoservices/esri/geocodereply_esri.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOCODEREPLYESRI_H
+#define GEOCODEREPLYESRI_H
+
+#include <QNetworkReply>
+#include <QGeoCodeReply>
+
+QT_BEGIN_NAMESPACE
+
+class GeoCodeReplyEsri : public QGeoCodeReply
+{
+ Q_OBJECT
+
+public:
+ enum OperationType
+ {
+ Geocode,
+ ReverseGeocode
+ };
+
+public:
+ GeoCodeReplyEsri(QNetworkReply *reply, OperationType operationType, QObject *parent = Q_NULLPTR);
+ virtual ~GeoCodeReplyEsri();
+
+ void abort() Q_DECL_OVERRIDE;
+
+ inline OperationType operationType() const;
+
+private Q_SLOTS:
+ void networkReplyFinished();
+ void networkReplyError(QNetworkReply::NetworkError error);
+
+ QGeoLocation parseAddress(const QJsonObject &object);
+ QGeoLocation parseCandidate(const QJsonObject &candidate);
+
+private:
+ QNetworkReply *m_reply;
+ OperationType m_operationType;
+};
+
+inline GeoCodeReplyEsri::OperationType GeoCodeReplyEsri::operationType() const
+{
+ return m_operationType;
+}
+
+QT_END_NAMESPACE
+
+#endif // GEOCODEREPLYESRI_H
diff --git a/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
new file mode 100644
index 00000000..fcdc5962
--- /dev/null
+++ b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geocodingmanagerengine_esri.h"
+#include "geocodereply_esri.h"
+
+#include <QVariantMap>
+#include <QUrl>
+#include <QUrlQuery>
+#include <QLocale>
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QGeoCoordinate>
+#include <QGeoAddress>
+#include <QGeoShape>
+#include <QGeoRectangle>
+
+QT_BEGIN_NAMESPACE
+
+// https://developers.arcgis.com/rest/geocode/api-reference/geocoding-find-address-candidates.htm
+// https://developers.arcgis.com/rest/geocode/api-reference/geocoding-reverse-geocode.htm
+
+static const QString kPrefixEsri(QStringLiteral("esri."));
+static const QString kParamUserAgent(kPrefixEsri + QStringLiteral("useragent"));
+
+static const QString kUrlGeocode(QStringLiteral("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates"));
+static const QString kUrlReverseGeocode(QStringLiteral("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode"));
+
+static QString addressToQuery(const QGeoAddress &address)
+{
+ return address.street() + QStringLiteral(", ")
+ + address.district() + QStringLiteral(", ")
+ + address.city() + QStringLiteral(", ")
+ + address.state() + QStringLiteral(", ")
+ + address.country();
+}
+
+static QString boundingBoxToLtrb(const QGeoRectangle &rect)
+{
+ return QString::number(rect.topLeft().longitude()) + QLatin1Char(',')
+ + QString::number(rect.topLeft().latitude()) + QLatin1Char(',')
+ + QString::number(rect.bottomRight().longitude()) + QLatin1Char(',')
+ + QString::number(rect.bottomRight().latitude());
+}
+
+GeoCodingManagerEngineEsri::GeoCodingManagerEngineEsri(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error,
+ QString *errorString)
+: QGeoCodingManagerEngine(parameters), m_networkManager(new QNetworkAccessManager(this))
+{
+ if (parameters.contains(kParamUserAgent))
+ m_userAgent = parameters.value(kParamUserAgent).toString().toLatin1();
+ else
+ m_userAgent = QByteArrayLiteral("Qt Location based application");
+
+ *error = QGeoServiceProvider::NoError;
+ errorString->clear();
+}
+
+GeoCodingManagerEngineEsri::~GeoCodingManagerEngineEsri()
+{
+}
+
+QGeoCodeReply *GeoCodingManagerEngineEsri::geocode(const QGeoAddress &address,
+ const QGeoShape &bounds)
+{
+ return geocode(addressToQuery(address), 1, -1, bounds);
+}
+
+QGeoCodeReply *GeoCodingManagerEngineEsri::geocode(const QString &address, int limit, int offset,
+ const QGeoShape &bounds)
+{
+ Q_UNUSED(offset)
+
+ QNetworkRequest request;
+ request.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent);
+
+ QUrl url(kUrlGeocode);
+
+ QUrlQuery query;
+ query.addQueryItem(QStringLiteral("singleLine"), address);
+ query.addQueryItem(QStringLiteral("f"), QStringLiteral("json"));
+ query.addQueryItem(QStringLiteral("outFields"), "*");
+
+ if (bounds.type() == QGeoShape::RectangleType)
+ query.addQueryItem(QStringLiteral("searchExtent"), boundingBoxToLtrb(bounds));
+
+ if (limit != -1)
+ query.addQueryItem(QStringLiteral("maxLocations"), QString::number(limit));
+
+ url.setQuery(query);
+ request.setUrl(url);
+
+ QNetworkReply *reply = m_networkManager->get(request);
+ GeoCodeReplyEsri *geocodeReply = new GeoCodeReplyEsri(reply, GeoCodeReplyEsri::Geocode, this);
+
+ connect(geocodeReply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ connect(geocodeReply, SIGNAL(error(QGeoCodeReply::Error,QString)),
+ this, SLOT(replyError(QGeoCodeReply::Error,QString)));
+
+ return geocodeReply;
+}
+
+QGeoCodeReply *GeoCodingManagerEngineEsri::reverseGeocode(const QGeoCoordinate &coordinate,
+ const QGeoShape &bounds)
+{
+ Q_UNUSED(bounds)
+
+ QNetworkRequest request;
+ request.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent);
+
+ QUrl url(kUrlReverseGeocode);
+
+ QUrlQuery query;
+
+ query.addQueryItem(QStringLiteral("f"), QStringLiteral("json"));
+ query.addQueryItem(QStringLiteral("langCode"), locale().name().left(2));
+ query.addQueryItem(QStringLiteral("location"), QString::number(coordinate.longitude()) + QLatin1Char(',')
+ + QString::number(coordinate.latitude()));
+
+ url.setQuery(query);
+ request.setUrl(url);
+
+ QNetworkReply *reply = m_networkManager->get(request);
+ GeoCodeReplyEsri *geocodeReply = new GeoCodeReplyEsri(reply, GeoCodeReplyEsri::ReverseGeocode,
+ this);
+
+ connect(geocodeReply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ connect(geocodeReply, SIGNAL(error(QGeoCodeReply::Error,QString)),
+ this, SLOT(replyError(QGeoCodeReply::Error,QString)));
+
+ return geocodeReply;
+}
+
+void GeoCodingManagerEngineEsri::replyFinished()
+{
+ QGeoCodeReply *reply = qobject_cast<QGeoCodeReply *>(sender());
+ if (reply)
+ emit finished(reply);
+}
+
+void GeoCodingManagerEngineEsri::replyError(QGeoCodeReply::Error errorCode,
+ const QString &errorString)
+{
+ QGeoCodeReply *reply = qobject_cast<QGeoCodeReply *>(sender());
+ if (reply)
+ emit error(reply, errorCode, errorString);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h
new file mode 100644
index 00000000..9ff246e0
--- /dev/null
+++ b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOCODINGMANAGERENGINEESRI_H
+#define GEOCODINGMANAGERENGINEESRI_H
+
+#include <QGeoServiceProvider>
+#include <QGeoCodingManagerEngine>
+#include <QGeoCodeReply>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkAccessManager;
+
+class GeoCodingManagerEngineEsri : public QGeoCodingManagerEngine
+{
+ Q_OBJECT
+
+public:
+ GeoCodingManagerEngineEsri(const QVariantMap &parameters, QGeoServiceProvider::Error *error,
+ QString *errorString);
+ virtual ~GeoCodingManagerEngineEsri();
+
+ QGeoCodeReply *geocode(const QGeoAddress &address, const QGeoShape &bounds) Q_DECL_OVERRIDE;
+ QGeoCodeReply *geocode(const QString &address, int limit, int offset,
+ const QGeoShape &bounds) Q_DECL_OVERRIDE;
+ QGeoCodeReply *reverseGeocode(const QGeoCoordinate &coordinate,
+ const QGeoShape &bounds) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void replyFinished();
+ void replyError(QGeoCodeReply::Error errorCode, const QString &errorString);
+
+private:
+ QNetworkAccessManager *m_networkManager;
+ QByteArray m_userAgent;
+};
+
+QT_END_NAMESPACE
+
+#endif // GEOCODINGMANAGERENGINEESRI_H
diff --git a/src/plugins/geoservices/esri/geomapsource.cpp b/src/plugins/geoservices/esri/geomapsource.cpp
new file mode 100644
index 00000000..32fe1899
--- /dev/null
+++ b/src/plugins/geoservices/esri/geomapsource.cpp
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geomapsource.h"
+
+#include <QUrl>
+
+QT_BEGIN_NAMESPACE
+
+static const QString kArcGISTileScheme(QStringLiteral("/tile/${z}/${y}/${x}"));
+
+struct MapStyleData
+{
+ QString name;
+ QGeoMapType::MapStyle style;
+};
+
+static const MapStyleData mapStyles[] =
+{
+ { QStringLiteral("StreetMap"), QGeoMapType::StreetMap },
+ { QStringLiteral("SatelliteMapDay"), QGeoMapType::SatelliteMapDay },
+ { QStringLiteral("SatelliteMapNight"), QGeoMapType::SatelliteMapNight },
+ { QStringLiteral("TerrainMap"), QGeoMapType::TerrainMap },
+ { QStringLiteral("HybridMap"), QGeoMapType::HybridMap },
+ { QStringLiteral("TransitMap"), QGeoMapType::TransitMap },
+ { QStringLiteral("GrayStreetMap"), QGeoMapType::GrayStreetMap },
+ { QStringLiteral("PedestrianMap"), QGeoMapType::PedestrianMap },
+ { QStringLiteral("CarNavigationMap"), QGeoMapType::CarNavigationMap },
+ { QStringLiteral("CustomMap"), QGeoMapType::CustomMap }
+};
+
+GeoMapSource::GeoMapSource(QGeoMapType::MapStyle style, const QString &name,
+ const QString &description, bool mobile, bool night, int mapId,
+ const QString &url, const QString &copyright) :
+ QGeoMapType(style, name, description, mobile, night, mapId),
+ m_url(url), m_copyright(copyright)
+{
+}
+
+QString GeoMapSource::toFormat(const QString &url)
+{
+ QString format = url;
+
+ if (!format.contains(QLatin1String("${")))
+ format += kArcGISTileScheme;
+
+ format.replace(QLatin1String("${z}"), QLatin1String("%1"));
+ format.replace(QLatin1String("${x}"), QLatin1String("%2"));
+ format.replace(QLatin1String("${y}"), QLatin1String("%3"));
+ format.replace(QLatin1String("${token}"), QLatin1String("%4"));
+
+ return format;
+}
+
+QGeoMapType::MapStyle GeoMapSource::mapStyle(const QString &styleString)
+{
+ for (unsigned int i = 0; i < sizeof(mapStyles)/sizeof(MapStyle); i++) {
+ const MapStyleData &mapStyle = mapStyles[i];
+
+ if (styleString.compare(mapStyle.name, Qt::CaseInsensitive) == 0)
+ return mapStyle.style;
+ }
+
+ QGeoMapType::MapStyle style = static_cast<QGeoMapType::MapStyle>(styleString.toInt());
+ if (style <= QGeoMapType::NoMap)
+ style = QGeoMapType::CustomMap;
+
+ return style;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/geomapsource.h b/src/plugins/geoservices/esri/geomapsource.h
new file mode 100644
index 00000000..8660e999
--- /dev/null
+++ b/src/plugins/geoservices/esri/geomapsource.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOMAPSOURCE_H
+#define GEOMAPSOURCE_H
+
+#include <QtLocation/private/qgeomaptype_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class GeoMapSource : public QGeoMapType
+{
+public:
+ GeoMapSource(QGeoMapType::MapStyle style, const QString &name,
+ const QString &description, bool mobile, bool night, int mapId,
+ const QString &url, const QString &copyright);
+
+ inline const QString &url() const;
+ inline const QString &copyright() const;
+
+ static QString toFormat(const QString &url);
+ static QGeoMapType::MapStyle mapStyle(const QString &styleString);
+
+private:
+ QString m_url;
+ QString m_copyright;
+};
+
+inline const QString &GeoMapSource::url() const
+{
+ return m_url;
+}
+
+inline const QString &GeoMapSource::copyright() const
+{
+ return m_copyright;
+}
+
+QT_END_NAMESPACE
+
+#endif // GEOMAPSOURCE_H
diff --git a/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp b/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
new file mode 100644
index 00000000..30db48f0
--- /dev/null
+++ b/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "georoutejsonparser_esri.h"
+
+#include <QJsonArray>
+#include <QGeoRectangle>
+#include <QGeoManeuver>
+#include <QGeoRouteSegment>
+
+QT_BEGIN_NAMESPACE
+
+// JSON reference: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
+
+static const QString kErrorMessage(QStringLiteral("Error %1: %2."));
+static const QString kErrorJson(QStringLiteral("Error: invalide JSON document."));
+
+static const QString kErrorKey(QStringLiteral("error"));
+static const QString kErrorCodeKey(QStringLiteral("code"));
+static const QString kErrorMessageKey(QStringLiteral("message"));
+static const QString kErrorDetailsKey(QStringLiteral("details"));
+static const QString kDirectionsKey(QStringLiteral("directions"));
+static const QString kRoutesKey(QStringLiteral("routes"));
+static const QString kBarriersKey(QStringLiteral("barriers"));
+static const QString kMessagesKey(QStringLiteral("messages"));
+static const QString kDirectionsRouteIdKey(QStringLiteral("routeId"));
+static const QString kDirectionsRouteNameKey(QStringLiteral("routeName"));
+static const QString kDirectionsSummaryKey(QStringLiteral("summary"));
+static const QString kDirectionsTotalLengthKey(QStringLiteral("totalLength"));
+static const QString kDirectionsTotalTimeKey(QStringLiteral("totalTime"));
+static const QString kDirectionsTotalDriveTimeKey(QStringLiteral("totalDriveTime"));
+static const QString kDirectionsEnvelopeKey(QStringLiteral("envelope"));
+static const QString kDirectionsEnvelopeXminKey(QStringLiteral("xmin"));
+static const QString kDirectionsEnvelopeYminKey(QStringLiteral("ymin"));
+static const QString kDirectionsEnvelopeXmaxKey(QStringLiteral("xmax"));
+static const QString kDirectionsEnvelopeYmaxKey(QStringLiteral("ymax"));
+static const QString kDirectionsFeaturesKey(QStringLiteral("features"));
+static const QString kDirectionsFeaturesAttributesKey(QStringLiteral("attributes"));
+static const QString kDirectionsFeaturesCompressedGeometryKey(QStringLiteral("compressedGeometry"));
+static const QString kDirectionsFeaturesAttributesLengthKey(QStringLiteral("length"));
+static const QString kDirectionsFeaturesAttributesTimeKey(QStringLiteral("time"));
+static const QString kDirectionsFeaturesAttributesTextKey(QStringLiteral("text"));
+static const QString kDirectionsFeaturesAttributesEtaKey(QStringLiteral("ETA"));
+static const QString kDirectionsFeaturesAttributesManeuverTypeKey(QStringLiteral("maneuverType"));
+static const QString kRoutesFeaturesKey(QStringLiteral("features"));
+static const QString kRoutesFeaturesAttributesKey(QStringLiteral("attributes"));
+static const QString kRoutesFeaturesObjectIdKey(QStringLiteral("ObjectID"));
+static const QString kRoutesFeaturesGeometryKey(QStringLiteral("geometry"));
+static const QString kRoutesFeaturesGeometryPathsKey(QStringLiteral("paths"));
+
+GeoRouteJsonParserEsri::GeoRouteJsonParserEsri(const QJsonDocument &document)
+{
+ if (!document.isObject())
+ {
+ m_error = kErrorJson;
+ return;
+ }
+
+ m_json = document.object();
+ if (m_json.contains(kErrorKey))
+ {
+ QJsonObject error = m_json.value(kErrorKey).toObject();
+ int code = error.value(kErrorCodeKey).toInt();
+ QString message = error.value(kErrorMessageKey).toString();
+
+ m_error = kErrorMessage.arg(code).arg(message);
+ return;
+ }
+
+ parseDirections();
+ parseRoutes();
+}
+
+QList<QGeoRoute> GeoRouteJsonParserEsri::routes() const
+{
+ return m_routes.values();
+}
+
+bool GeoRouteJsonParserEsri::isValid() const
+{
+ return (m_error.isEmpty());
+}
+
+QString GeoRouteJsonParserEsri::errorString() const
+{
+ return m_error;
+}
+
+void GeoRouteJsonParserEsri::parseDirections()
+{
+ QJsonArray directions = m_json.value(kDirectionsKey).toArray();
+ foreach (const QJsonValue &direction, directions)
+ parseDirection(direction.toObject());
+}
+
+void GeoRouteJsonParserEsri::parseDirection(const QJsonObject &direction)
+{
+ QGeoRoute &geoRoute = m_routes[direction.value(kDirectionsRouteIdKey).toInt()];
+
+ // parse summary
+ geoRoute.setRouteId(direction.value(kDirectionsRouteNameKey).toString());
+
+ QJsonObject summary = direction.value(kDirectionsSummaryKey).toObject();
+ geoRoute.setDistance(summary.value(kDirectionsTotalLengthKey).toDouble());
+
+ geoRoute.setTravelTime(summary.value(kDirectionsTotalTimeKey).toDouble() * 60);
+ // default units is minutes, see directionsTimeAttributeName param
+
+ geoRoute.setTravelMode(QGeoRouteRequest::CarTravel);
+ // default request is time for car, see directionsTimeAttributeName param
+
+ QJsonObject enveloppe = summary.value(kDirectionsEnvelopeKey).toObject();
+
+ QGeoCoordinate topLeft(enveloppe.value(kDirectionsEnvelopeXminKey).toDouble(),
+ enveloppe.value(kDirectionsEnvelopeYmaxKey).toDouble());
+ QGeoCoordinate bottomRight(enveloppe.value(kDirectionsEnvelopeXmaxKey).toDouble(),
+ enveloppe.value(kDirectionsEnvelopeYminKey).toDouble());
+ geoRoute.setBounds(QGeoRectangle(topLeft, bottomRight));
+
+ // parse features
+ QJsonArray features = direction.value(kDirectionsFeaturesKey).toArray();
+
+ static const QMap<QString, QGeoManeuver::InstructionDirection> esriDirectionsManeuverTypes
+ {
+ { QStringLiteral("esriDMTUnknown"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTStop"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTStraight"), QGeoManeuver::DirectionForward },
+ { QStringLiteral("esriDMTBearLeft"), QGeoManeuver::DirectionBearLeft },
+ { QStringLiteral("esriDMTBearRight"), QGeoManeuver::DirectionBearRight },
+ { QStringLiteral("esriDMTTurnLeft"), QGeoManeuver::DirectionLeft },
+ { QStringLiteral("esriDMTTurnRight"), QGeoManeuver::DirectionRight },
+ { QStringLiteral("esriDMTSharpLeft"), QGeoManeuver::DirectionLightLeft },
+ { QStringLiteral("esriDMTSharpRight"), QGeoManeuver::DirectionLightRight },
+ { QStringLiteral("esriDMTUTurn"), QGeoManeuver::DirectionUTurnRight },
+ { QStringLiteral("esriDMTFerry"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTRoundabout"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTHighwayMerge"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTHighwayExit"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTHighwayChange"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTForkCenter"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTForkLeft"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTForkRight"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTDepart"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTTripItem"), QGeoManeuver::NoDirection },
+ { QStringLiteral("esriDMTEndOfFerry"), QGeoManeuver::NoDirection }
+ };
+
+ QGeoRouteSegment firstSegment;
+ for (int i = features.size() - 1; i >= 0; --i)
+ {
+ QJsonObject feature = features.at(i).toObject();
+ QJsonObject attributes = feature.value(kDirectionsFeaturesAttributesKey).toObject();
+
+ QGeoRouteSegment segment;
+ double length = attributes.value(kDirectionsFeaturesAttributesLengthKey).toDouble();
+ segment.setDistance(length);
+
+ double time = attributes.value(kDirectionsFeaturesAttributesTimeKey).toDouble() * 60;
+ // default units is minutes, see directionsTimeAttributeName param
+ segment.setTravelTime(time);
+
+ QGeoManeuver maneuver;
+ QString type = attributes.value(kDirectionsFeaturesAttributesManeuverTypeKey).toString();
+ maneuver.setDirection(esriDirectionsManeuverTypes.value(type));
+
+ maneuver.setInstructionText(attributes.value(kDirectionsFeaturesAttributesTextKey).toString() + ".");
+ maneuver.setDistanceToNextInstruction(length);
+ maneuver.setTimeToNextInstruction(time);
+
+ segment.setManeuver(maneuver);
+
+ segment.setNextRouteSegment(firstSegment);
+ firstSegment = segment;
+ }
+ geoRoute.setFirstRouteSegment(firstSegment);
+}
+
+void GeoRouteJsonParserEsri::parseRoutes()
+{
+ QJsonObject routes = m_json.value(kRoutesKey).toObject();
+ QJsonArray features = routes.value(kRoutesFeaturesKey).toArray();
+ foreach (const QJsonValue &feature, features)
+ parseRoute(feature.toObject());
+}
+
+void GeoRouteJsonParserEsri::parseRoute(const QJsonObject &route)
+{
+ QJsonObject attributes = route.value(kRoutesFeaturesAttributesKey).toObject();
+ QGeoRoute &geoRoute = m_routes[attributes.value(kRoutesFeaturesObjectIdKey).toInt()];
+
+ QJsonObject geometry = route.value(kRoutesFeaturesGeometryKey).toObject();
+ QJsonArray paths = geometry.value(kRoutesFeaturesGeometryPathsKey).toArray();
+
+ if (!paths.isEmpty())
+ {
+ QList<QGeoCoordinate> geoCoordinates;
+ foreach (const QJsonValue &value, paths.first().toArray()) // only first polyline?
+ {
+ QJsonArray geoCoordinate = value.toArray();
+ if (geoCoordinate.size() == 2) // ignore 3rd coordinate
+ {
+ geoCoordinates.append(QGeoCoordinate(geoCoordinate[1].toDouble(),
+ geoCoordinate[0].toDouble()));
+ }
+ }
+ geoRoute.setPath(geoCoordinates);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/georoutejsonparser_esri.h b/src/plugins/geoservices/esri/georoutejsonparser_esri.h
new file mode 100644
index 00000000..0511cf4d
--- /dev/null
+++ b/src/plugins/geoservices/esri/georoutejsonparser_esri.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOROUTEJSONPARSERESRI_H
+#define GEOROUTEJSONPARSERESRI_H
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QGeoRoute>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+
+class GeoRouteJsonParserEsri
+{
+public:
+ GeoRouteJsonParserEsri(const QJsonDocument &document);
+
+ QList<QGeoRoute> routes() const;
+ bool isValid() const;
+ QString errorString() const;
+
+private:
+ void parseDirections();
+ void parseDirection(const QJsonObject &direction);
+ void parseRoutes();
+ void parseRoute(const QJsonObject &route);
+
+ QString m_error;
+ QMap<int, QGeoRoute> m_routes;
+ QJsonObject m_json;
+};
+
+QT_END_NAMESPACE
+
+#endif // GEOROUTEJSONPARSERESRI_H
diff --git a/src/plugins/geoservices/esri/georoutereply_esri.cpp b/src/plugins/geoservices/esri/georoutereply_esri.cpp
new file mode 100644
index 00000000..4a7d5c67
--- /dev/null
+++ b/src/plugins/geoservices/esri/georoutereply_esri.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "georoutereply_esri.h"
+#include "georoutejsonparser_esri.h"
+
+#include <QJsonDocument>
+
+QT_BEGIN_NAMESPACE
+
+// JSON reference: http://resources.arcgis.com/en/help/arcgis-rest-api/#/Route_service_with_synchronous_execution/02r300000036000000/
+
+GeoRouteReplyEsri::GeoRouteReplyEsri(QNetworkReply *reply, const QGeoRouteRequest &request,
+ QObject *parent) :
+ QGeoRouteReply(request, parent), m_reply(reply)
+{
+ connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished()));
+ connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
+ this, SLOT(networkReplyError(QNetworkReply::NetworkError)));
+}
+
+GeoRouteReplyEsri::~GeoRouteReplyEsri()
+{
+ if (m_reply)
+ m_reply->deleteLater();
+}
+
+void GeoRouteReplyEsri::abort()
+{
+ if (!m_reply)
+ return;
+
+ m_reply->abort();
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+}
+
+void GeoRouteReplyEsri::networkReplyFinished()
+{
+ if (!m_reply)
+ return;
+
+ if (m_reply->error() != QNetworkReply::NoError)
+ {
+ setError(QGeoRouteReply::CommunicationError, m_reply->errorString());
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+ return;
+ }
+
+ QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll());
+ GeoRouteJsonParserEsri parser(document);
+
+ if (parser.isValid())
+ {
+ setRoutes(parser.routes());
+ setFinished(true);
+ } else {
+ setError(QGeoRouteReply::ParseError, parser.errorString());
+ }
+
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+}
+
+void GeoRouteReplyEsri::networkReplyError(QNetworkReply::NetworkError error)
+{
+ Q_UNUSED(error)
+
+ if (!m_reply)
+ return;
+
+ setError(QGeoRouteReply::CommunicationError, m_reply->errorString());
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/georoutereply_esri.h b/src/plugins/geoservices/esri/georoutereply_esri.h
new file mode 100644
index 00000000..6e97ee9f
--- /dev/null
+++ b/src/plugins/geoservices/esri/georoutereply_esri.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOROUTEREPLYESRI_H
+#define GEOROUTEREPLYESRI_H
+
+#include <QNetworkReply>
+#include <QGeoRouteReply>
+
+QT_BEGIN_NAMESPACE
+
+class GeoRouteReplyEsri : public QGeoRouteReply
+{
+ Q_OBJECT
+
+public:
+ GeoRouteReplyEsri(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent = Q_NULLPTR);
+ virtual ~GeoRouteReplyEsri();
+
+ void abort() Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void networkReplyFinished();
+ void networkReplyError(QNetworkReply::NetworkError error);
+
+private:
+ QNetworkReply *m_reply;
+};
+
+QT_END_NAMESPACE
+
+#endif // GEOROUTEREPLYESRI_H
diff --git a/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
new file mode 100644
index 00000000..ae722e59
--- /dev/null
+++ b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "georoutingmanagerengine_esri.h"
+#include "georoutereply_esri.h"
+
+#include <QUrlQuery>
+
+QT_BEGIN_NAMESPACE
+
+static const QString kPrefixEsri(QStringLiteral("esri."));
+static const QString kParamUserAgent(kPrefixEsri + QStringLiteral("useragent"));
+static const QString kParamToken(kPrefixEsri + QStringLiteral("token"));
+
+static const QString kUrlRouting(QStringLiteral("http://route.arcgis.com/arcgis/rest/services/World/Route/NAServer/Route_World/solve"));
+
+GeoRoutingManagerEngineEsri::GeoRoutingManagerEngineEsri(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error,
+ QString *errorString) :
+ QGeoRoutingManagerEngine(parameters), m_networkManager(new QNetworkAccessManager(this))
+{
+ if (parameters.contains(kParamUserAgent))
+ m_userAgent = parameters.value(kParamUserAgent).toString().toLatin1();
+ else
+ m_userAgent = QByteArrayLiteral("Qt Location based application");
+
+ m_token = parameters.value(kParamToken).toString();
+
+ *error = QGeoServiceProvider::NoError;
+ errorString->clear();
+}
+
+GeoRoutingManagerEngineEsri::~GeoRoutingManagerEngineEsri()
+{
+}
+
+// REST reference: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
+
+QGeoRouteReply *GeoRoutingManagerEngineEsri::calculateRoute(const QGeoRouteRequest &request)
+{
+ QNetworkRequest networkRequest;
+ networkRequest.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent);
+
+ QUrl url(kUrlRouting);
+ QUrlQuery query;
+ QString stops;
+
+ foreach (const QGeoCoordinate &coordinate, request.waypoints())
+ {
+ if (!stops.isEmpty())
+ stops += "; ";
+
+ stops += QString::number(coordinate.longitude()) + QLatin1Char(',') +
+ QString::number(coordinate.latitude());
+ }
+
+ query.addQueryItem(QStringLiteral("stops"), stops);
+ query.addQueryItem(QStringLiteral("f"), QStringLiteral("json"));
+ query.addQueryItem(QStringLiteral("directionsLanguage"), preferedDirectionLangage());
+ query.addQueryItem(QStringLiteral("directionsLengthUnits"), preferedDirectionsLengthUnits());
+ query.addQueryItem(QStringLiteral("token"), m_token);
+
+ url.setQuery(query);
+ networkRequest.setUrl(url);
+
+ QNetworkReply *reply = m_networkManager->get(networkRequest);
+ GeoRouteReplyEsri *routeReply = new GeoRouteReplyEsri(reply, request, this);
+
+ connect(routeReply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ connect(routeReply, SIGNAL(error(QGeoRouteReply::Error,QString)), this, SLOT(replyError(QGeoRouteReply::Error,QString)));
+
+ return routeReply;
+}
+
+void GeoRoutingManagerEngineEsri::replyFinished()
+{
+ QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
+ if (reply)
+ emit finished(reply);
+}
+
+void GeoRoutingManagerEngineEsri::replyError(QGeoRouteReply::Error errorCode, const QString &errorString)
+{
+ QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
+ if (reply)
+ emit error(reply, errorCode, errorString);
+}
+
+QString GeoRoutingManagerEngineEsri::preferedDirectionLangage()
+{
+ // list of supported langages is defined in:
+ // http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000
+ const QStringList supportedLanguages = {
+ "ar", // Generate directions in Arabic
+ "cs", // Generate directions in Czech
+ "de", // Generate directions in German
+ "el", // Generate directions in Greek
+ "en", // Generate directions in English (default)
+ "es", // Generate directions in Spanish
+ "et", // Generate directions in Estonian
+ "fr", // Generate directions in French
+ "he", // Generate directions in Hebrew
+ "it", // Generate directions in Italian
+ "ja", // Generate directions in Japanese
+ "ko", // Generate directions in Korean
+ "lt", // Generate directions in Lithuanian
+ "lv", // Generate directions in Latvian
+ "nl", // Generate directions in Dutch
+ "pl", // Generate directions in Polish
+ "pt-BR", // Generate directions in Brazilian Portuguese
+ "pt-PT", // Generate directions in Portuguese (Portugal)
+ "ru", // Generate directions in Russian
+ "sv", // Generate directions in Swedish
+ "tr", // Generate directions in Turkish
+ "zh-CN" // Simplified Chinese
+ };
+
+ for (const QString &language: locale().uiLanguages())
+ {
+ if (language.startsWith("pt_BR")) // Portuguese (Brazilian)
+ return QStringLiteral("pt-BR");
+ if (language.startsWith("pt")) // Portuguese (Portugal)
+ return QStringLiteral("pt-PT");
+ if (language.startsWith("zh")) // Portuguese (Portugal)
+ return QStringLiteral("zh-CN");
+
+ const QString country = language.left(2);
+ if (supportedLanguages.contains(country))
+ return country;
+ }
+ return QStringLiteral("en"); // default value
+}
+
+QString GeoRoutingManagerEngineEsri::preferedDirectionsLengthUnits()
+{
+ switch (measurementSystem())
+ {
+ case QLocale::MetricSystem:
+ return QStringLiteral("esriNAUMeters");
+ break;
+ case QLocale::ImperialUSSystem:
+ return QStringLiteral( "esriNAUFeet");
+ break;
+ case QLocale::ImperialUKSystem:
+ return QStringLiteral("esriNAUFeet");
+ break;
+ default:
+ return QStringLiteral("esriNAUMeters");
+ break;
+ }
+ return QStringLiteral("esriNAUMeters");
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h
new file mode 100644
index 00000000..7387e25c
--- /dev/null
+++ b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOROUTINGMANAGERENGINEESRI_H
+#define GEOROUTINGMANAGERENGINEESRI_H
+
+#include <QGeoServiceProvider>
+#include <QGeoRoutingManagerEngine>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkAccessManager;
+
+class GeoRoutingManagerEngineEsri : public QGeoRoutingManagerEngine
+{
+ Q_OBJECT
+
+public:
+ GeoRoutingManagerEngineEsri(const QVariantMap &parameters, QGeoServiceProvider::Error *error,
+ QString *errorString);
+ virtual ~GeoRoutingManagerEngineEsri();
+
+ QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void replyFinished();
+ void replyError(QGeoRouteReply::Error errorCode, const QString &errorString);
+
+private:
+ QString preferedDirectionLangage();
+ QString preferedDirectionsLengthUnits();
+
+ QNetworkAccessManager *m_networkManager;
+ QByteArray m_userAgent;
+ QString m_token;
+};
+
+QT_END_NAMESPACE
+
+#endif // GEOROUTINGMANAGERENGINEESRI_H
diff --git a/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp
new file mode 100644
index 00000000..5277cde3
--- /dev/null
+++ b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geoserviceproviderfactory_esri.h"
+#include "geotiledmappingmanagerengine_esri.h"
+#include "geocodingmanagerengine_esri.h"
+#include "georoutingmanagerengine_esri.h"
+
+#include <QtLocation/private/qgeotiledmappingmanagerengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QGeoCodingManagerEngine *GeoServiceProviderFactoryEsri::createGeocodingManagerEngine(
+ const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString) const
+{
+ return new GeoCodingManagerEngineEsri(parameters, error, errorString);
+}
+
+QGeoMappingManagerEngine *GeoServiceProviderFactoryEsri::createMappingManagerEngine(
+ const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString) const
+{
+ return new GeoTiledMappingManagerEngineEsri(parameters, error, errorString);
+}
+
+QGeoRoutingManagerEngine *GeoServiceProviderFactoryEsri::createRoutingManagerEngine(
+ const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString) const
+{
+ const QString token = parameters.value(QStringLiteral("esri.token")).toString();
+
+ if (!token.isEmpty()) {
+ return new GeoRoutingManagerEngineEsri(parameters, error, errorString);
+ } else {
+ *error = QGeoServiceProvider::MissingRequiredParameterError;
+ *errorString = tr("Esri plugin requires a 'esri.token' parameter.\n"
+ "Please visit https://developers.arcgis.com/authentication/accessing-arcgis-online-services/");
+ return 0;
+ }
+}
+
+QPlaceManagerEngine *GeoServiceProviderFactoryEsri::createPlaceManagerEngine(
+ const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString) const
+{
+ Q_UNUSED(parameters)
+ Q_UNUSED(error)
+ Q_UNUSED(errorString)
+
+ return Q_NULLPTR;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h
new file mode 100644
index 00000000..d198c75a
--- /dev/null
+++ b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOSERVICEPROVIDERFACTORYESRI_H
+#define GEOSERVICEPROVIDERFACTORYESRI_H
+
+#include <QObject>
+#include <QGeoServiceProviderFactory>
+
+QT_BEGIN_NAMESPACE
+
+class GeoServiceProviderFactoryEsri: public QObject, public QGeoServiceProviderFactory
+{
+ Q_OBJECT
+ Q_INTERFACES(QGeoServiceProviderFactory)
+ Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0"
+ FILE "esri_plugin.json")
+
+public:
+ QGeoCodingManagerEngine *createGeocodingManagerEngine(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error,
+ QString *errorString) const Q_DECL_OVERRIDE;
+ QGeoMappingManagerEngine *createMappingManagerEngine(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error,
+ QString *errorString) const Q_DECL_OVERRIDE;
+ QGeoRoutingManagerEngine *createRoutingManagerEngine(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error,
+ QString *errorString) const Q_DECL_OVERRIDE;
+ QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error,
+ QString *errorString) const Q_DECL_OVERRIDE;
+};
+
+QT_END_NAMESPACE
+
+#endif // GEOSERVICEPROVIDERFACTORYESRI_H
diff --git a/src/plugins/geoservices/esri/geotiledmap_esri.cpp b/src/plugins/geoservices/esri/geotiledmap_esri.cpp
new file mode 100644
index 00000000..9171fc2b
--- /dev/null
+++ b/src/plugins/geoservices/esri/geotiledmap_esri.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geotiledmap_esri.h"
+#include "geotiledmappingmanagerengine_esri.h"
+
+#include <QtLocation/private/qgeotilespec_p.h>
+
+QT_BEGIN_NAMESPACE
+
+GeoTiledMapEsri::GeoTiledMapEsri(GeoTiledMappingManagerEngineEsri *engine, QObject *parent) :
+ QGeoTiledMap(engine, parent), m_engine(engine), m_mapId(-1)
+{
+}
+
+GeoTiledMapEsri::~GeoTiledMapEsri()
+{
+}
+
+void GeoTiledMapEsri::evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles)
+{
+ if (visibleTiles.isEmpty())
+ return;
+
+ QGeoTileSpec tile = *(visibleTiles.constBegin());
+ if (tile.mapId() == m_mapId)
+ return;
+
+ m_mapId = tile.mapId();
+
+ GeoMapSource *mapSource = engine()->mapSource(m_mapId);
+
+ if (mapSource)
+ emit copyrightsChanged(mapSource->copyright());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/geotiledmap_esri.h b/src/plugins/geoservices/esri/geotiledmap_esri.h
new file mode 100644
index 00000000..d9d9d0b7
--- /dev/null
+++ b/src/plugins/geoservices/esri/geotiledmap_esri.h
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOTILEDMAPESRI_H
+#define GEOTILEDMAPESRI_H
+
+#include <QtLocation/private/qgeotiledmap_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class GeoTiledMappingManagerEngineEsri;
+
+class GeoTiledMapEsri: public QGeoTiledMap
+{
+ Q_OBJECT
+
+public:
+ explicit GeoTiledMapEsri(GeoTiledMappingManagerEngineEsri *engine, QObject *parent = Q_NULLPTR);
+ virtual ~GeoTiledMapEsri();
+
+protected:
+ void evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles) Q_DECL_OVERRIDE;
+
+ inline GeoTiledMappingManagerEngineEsri *engine() const;
+
+private:
+ GeoTiledMappingManagerEngineEsri *m_engine;
+ int m_mapId;
+};
+
+inline GeoTiledMappingManagerEngineEsri *GeoTiledMapEsri::engine() const
+{
+ return m_engine;
+}
+
+QT_END_NAMESPACE
+
+#endif // GEOTILEDMAPESRI_H
diff --git a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
new file mode 100644
index 00000000..abcb3779
--- /dev/null
+++ b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geotiledmappingmanagerengine_esri.h"
+#include "geotiledmap_esri.h"
+#include "geotilefetcher_esri.h"
+
+#include <QtLocation/private/qgeocameracapabilities_p.h>
+#include <QtLocation/private/qgeomaptype_p.h>
+#include <QtLocation/private/qgeotiledmap_p.h>
+#include <QtLocation/private/qgeofiletilecache_p.h>
+
+#include <QFileInfo>
+#include <QDir>
+#include <QUrl>
+#include <QFile>
+#include <QJsonDocument>
+#include <QJsonObject>
+
+static void initResources()
+{
+ Q_INIT_RESOURCE(esri);
+}
+
+QT_BEGIN_NAMESPACE
+
+static const QString kPrefixEsri(QStringLiteral("esri."));
+static const QString kParamUserAgent(kPrefixEsri + QStringLiteral("useragent"));
+static const QString kParamToken(kPrefixEsri + QStringLiteral("token"));
+static const QString kPrefixMapping(kPrefixEsri + QStringLiteral("mapping."));
+static const QString kParamMinimumZoomLevel(kPrefixMapping + QStringLiteral("minimumZoomLevel"));
+static const QString kParamMaximumZoomLevel(kPrefixMapping + QStringLiteral("maximumZoomLevel"));
+
+static const QString kPropMapSources(QStringLiteral("mapSources"));
+static const QString kPropStyle(QStringLiteral("style"));
+static const QString kPropName(QStringLiteral("name"));
+static const QString kPropDescription(QStringLiteral("description"));
+static const QString kPropMobile(QStringLiteral("mobile"));
+static const QString kPropNight(QStringLiteral("night"));
+static const QString kPropUrl(QStringLiteral("url"));
+static const QString kPropMapId(QStringLiteral("mapId"));
+static const QString kPropCopyright(QStringLiteral("copyrightText"));
+
+GeoTiledMappingManagerEngineEsri::GeoTiledMappingManagerEngineEsri(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error,
+ QString *errorString) :
+ QGeoTiledMappingManagerEngine()
+{
+ QGeoCameraCapabilities cameraCaps;
+
+ double minimumZoomLevel = 0;
+ double maximumZoomLevel = 19;
+
+ if (parameters.contains(kParamMinimumZoomLevel))
+ minimumZoomLevel = parameters[kParamMinimumZoomLevel].toDouble();
+
+ if (parameters.contains(kParamMaximumZoomLevel))
+ maximumZoomLevel = parameters[kParamMaximumZoomLevel].toDouble();
+
+ cameraCaps.setMinimumZoomLevel(minimumZoomLevel);
+ cameraCaps.setMaximumZoomLevel(maximumZoomLevel);
+
+ setCameraCapabilities(cameraCaps);
+
+ setTileSize(QSize(256, 256));
+
+ if (!initializeMapSources(error, errorString))
+ return;
+
+ QList<QGeoMapType> mapTypes;
+
+ foreach (GeoMapSource *mapSource, m_mapSources) {
+ mapTypes << QGeoMapType(
+ mapSource->style(),
+ mapSource->name(),
+ mapSource->description(),
+ mapSource->mobile(),
+ mapSource->night(),
+ mapSource->mapId());
+ }
+
+ setSupportedMapTypes(mapTypes);
+
+ GeoTileFetcherEsri *tileFetcher = new GeoTileFetcherEsri(this);
+
+ if (parameters.contains(kParamUserAgent))
+ tileFetcher->setUserAgent(parameters.value(kParamUserAgent).toString().toLatin1());
+
+ if (parameters.contains(kParamToken))
+ tileFetcher->setToken(parameters.value(kParamToken).toString());
+
+ setTileFetcher(tileFetcher);
+
+ /* TILE CACHE */
+ QString cacheDirectory;
+ if (parameters.contains(QStringLiteral("esri.mapping.cache.directory"))) {
+ cacheDirectory = parameters.value(QStringLiteral("esri.mapping.cache.directory")).toString();
+ } else {
+ // managerName() is not yet set, we have to hardcode the plugin name below
+ cacheDirectory = QAbstractGeoTileCache::baseLocationCacheDirectory() + QLatin1String("esri");
+ }
+ QGeoFileTileCache *tileCache = new QGeoFileTileCache(cacheDirectory);
+
+ /*
+ * Disk cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("esri.mapping.cache.disk.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("esri.mapping.cache.disk.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize);
+ }
+ if (parameters.contains(QStringLiteral("esri.mapping.cache.disk.size"))) {
+ bool ok = false;
+ int cacheSize = parameters.value(QStringLiteral("esri.mapping.cache.disk.size")).toString().toInt(&ok);
+ if (ok)
+ tileCache->setMaxDiskUsage(cacheSize);
+ }
+
+ /*
+ * Memory cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("esri.mapping.cache.memory.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("esri.mapping.cache.memory.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
+ }
+ if (parameters.contains(QStringLiteral("esri.mapping.cache.memory.size"))) {
+ bool ok = false;
+ int cacheSize = parameters.value(QStringLiteral("esri.mapping.cache.memory.size")).toString().toInt(&ok);
+ if (ok)
+ tileCache->setMaxMemoryUsage(cacheSize);
+ }
+
+ /*
+ * Texture cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("esri.mapping.cache.texture.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("esri.mapping.cache.texture.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ }
+ if (parameters.contains(QStringLiteral("esri.mapping.cache.texture.size"))) {
+ bool ok = false;
+ int cacheSize = parameters.value(QStringLiteral("esri.mapping.cache.texture.size")).toString().toInt(&ok);
+ if (ok)
+ tileCache->setExtraTextureUsage(cacheSize);
+ }
+
+
+ setTileCache(tileCache);
+ *error = QGeoServiceProvider::NoError;
+ errorString->clear();
+}
+
+GeoTiledMappingManagerEngineEsri::~GeoTiledMappingManagerEngineEsri()
+{
+ qDeleteAll(m_mapSources);
+}
+
+QGeoMap *GeoTiledMappingManagerEngineEsri::createMap()
+{
+ return new GeoTiledMapEsri(this);
+}
+
+// ${z} = Zoom
+// ${x} = X
+// ${y} = Y
+// ${token} = Token
+
+// template = 'http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{{z}}/{{y}}/{{x}}.png'
+
+bool GeoTiledMappingManagerEngineEsri::initializeMapSources(QGeoServiceProvider::Error *error,
+ QString *errorString)
+{
+ initResources();
+ QFile mapsFile(":/maps.json");
+
+ if (!mapsFile.open(QIODevice::ReadOnly)) {
+ *error = QGeoServiceProvider::NotSupportedError;
+ *errorString = Q_FUNC_INFO + QStringLiteral("Unable to open: ") + mapsFile.fileName();
+
+ return false;
+ }
+
+ QByteArray mapsData = mapsFile.readAll();
+ mapsFile.close();
+
+ QJsonParseError parseError;
+
+ QJsonDocument mapsDocument = QJsonDocument::fromJson(mapsData, &parseError);
+
+ if (!mapsDocument.isObject()) {
+ *error = QGeoServiceProvider::NotSupportedError;
+ *errorString = Q_FUNC_INFO + QStringLiteral("JSON error: ") + (int)parseError.error
+ + ", offset: " + parseError.offset
+ + ", details: " + parseError.errorString();
+ return false;
+ }
+
+ QVariantMap maps = mapsDocument.object().toVariantMap();
+
+ QVariantList mapSources = maps["mapSources"].toList();
+
+ foreach (QVariant mapSourceElement, mapSources) {
+ QVariantMap mapSource = mapSourceElement.toMap();
+
+ int mapId = mapSource[kPropMapId].toInt();
+ if (mapId <= 0)
+ mapId = m_mapSources.count() + 1;
+
+ m_mapSources << new GeoMapSource(
+ GeoMapSource::mapStyle(mapSource[kPropStyle].toString()),
+ mapSource[kPropName].toString(),
+ mapSource[kPropDescription].toString(),
+ mapSource[kPropMobile].toBool(),
+ mapSource[kPropMapId].toBool(),
+ mapId,
+ GeoMapSource::toFormat(mapSource[kPropUrl].toString()),
+ mapSource[kPropCopyright].toString()
+ );
+ }
+
+ return true;
+}
+
+GeoMapSource *GeoTiledMappingManagerEngineEsri::mapSource(int mapId) const
+{
+ foreach (GeoMapSource *mapSource, mapSources()) {
+ if (mapSource->mapId() == mapId)
+ return mapSource;
+ }
+
+ return Q_NULLPTR;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h
new file mode 100644
index 00000000..a13ba05c
--- /dev/null
+++ b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOTILEDMAPPINGMANAGERENGINEESRI_H
+#define GEOTILEDMAPPINGMANAGERENGINEESRI_H
+
+#include <QGeoServiceProvider>
+
+#include <QtLocation/private/qgeotiledmappingmanagerengine_p.h>
+
+#include "geomapsource.h"
+
+QT_BEGIN_NAMESPACE
+
+class GeoTiledMappingManagerEngineEsri : public QGeoTiledMappingManagerEngine
+{
+ Q_OBJECT
+
+public:
+ GeoTiledMappingManagerEngineEsri(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error, QString *errorString);
+ virtual ~GeoTiledMappingManagerEngineEsri();
+
+ QGeoMap *createMap() Q_DECL_OVERRIDE;
+
+ inline const QList<GeoMapSource *>& mapSources() const;
+ GeoMapSource *mapSource(int mapId) const;
+
+private:
+ bool initializeMapSources(QGeoServiceProvider::Error *error, QString *errorString);
+
+ QList<GeoMapSource *> m_mapSources;
+};
+
+inline const QList<GeoMapSource *>& GeoTiledMappingManagerEngineEsri::mapSources() const
+{
+ return m_mapSources;
+}
+
+QT_END_NAMESPACE
+
+#endif // GEOTILEDMAPPINGMANAGERENGINEESRI_H
diff --git a/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp b/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp
new file mode 100644
index 00000000..e0816c15
--- /dev/null
+++ b/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geotiledmapreply_esri.h"
+
+#include <QtLocation/private/qgeotilespec_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static const unsigned char pngSignature[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00};
+static const unsigned char jpegSignature[] = {0xFF, 0xD8, 0xFF, 0x00};
+static const unsigned char gifSignature[] = {0x47, 0x49, 0x46, 0x38, 0x00};
+
+GeoTiledMapReplyEsri::GeoTiledMapReplyEsri(QNetworkReply *reply, const QGeoTileSpec &spec,
+ QObject *parent) :
+ QGeoTiledMapReply(spec, parent), m_reply(reply)
+{
+ connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished()));
+ connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
+ this, SLOT(networkReplyError(QNetworkReply::NetworkError)));
+ connect(m_reply, SIGNAL(destroyed()), this, SLOT(replyDestroyed()));
+}
+
+GeoTiledMapReplyEsri::~GeoTiledMapReplyEsri()
+{
+ if (m_reply) {
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+ }
+}
+
+void GeoTiledMapReplyEsri::abort()
+{
+ if (!m_reply)
+ return;
+
+ m_reply->abort();
+ QGeoTiledMapReply::abort();
+}
+
+void GeoTiledMapReplyEsri::replyDestroyed()
+{
+ m_reply = Q_NULLPTR;
+}
+
+void GeoTiledMapReplyEsri::networkReplyFinished()
+{
+ if (!m_reply)
+ return;
+
+ if (m_reply->error() != QNetworkReply::NoError)
+ {
+ setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString());
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+ return;
+ }
+
+ QByteArray const& imageData = m_reply->readAll();
+
+ bool validFormat = true;
+ if (imageData.startsWith(reinterpret_cast<const char*>(pngSignature)))
+ setMapImageFormat(QStringLiteral("png"));
+ else if (imageData.startsWith(reinterpret_cast<const char*>(jpegSignature)))
+ setMapImageFormat(QStringLiteral("jpg"));
+ else if (imageData.startsWith(reinterpret_cast<const char*>(gifSignature)))
+ setMapImageFormat(QStringLiteral("gif"));
+ else
+ validFormat = false;
+
+ if (validFormat)
+ setMapImageData(imageData);
+
+ setFinished(true);
+
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+}
+
+void GeoTiledMapReplyEsri::networkReplyError(QNetworkReply::NetworkError error)
+{
+ if (!m_reply)
+ return;
+
+ if (error != QNetworkReply::OperationCanceledError)
+ setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString());
+
+ setFinished(true);
+ m_reply->deleteLater();
+ m_reply = Q_NULLPTR;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/geotiledmapreply_esri.h b/src/plugins/geoservices/esri/geotiledmapreply_esri.h
new file mode 100644
index 00000000..32a35698
--- /dev/null
+++ b/src/plugins/geoservices/esri/geotiledmapreply_esri.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOTILEDMAPREPLYESRI_H
+#define GEOTILEDMAPREPLYESRI_H
+
+#include <QNetworkReply>
+
+#include <QtLocation/private/qgeotiledmapreply_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class GeoTiledMapReplyEsri : public QGeoTiledMapReply
+{
+ Q_OBJECT
+
+public:
+ GeoTiledMapReplyEsri(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent = Q_NULLPTR);
+ virtual ~GeoTiledMapReplyEsri();
+
+ void abort() Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void replyDestroyed();
+ void networkReplyFinished();
+ void networkReplyError(QNetworkReply::NetworkError error);
+
+private:
+ QNetworkReply *m_reply;
+};
+
+QT_END_NAMESPACE
+
+#endif // GEOTILEDMAPREPLYESRI_H
diff --git a/src/plugins/geoservices/esri/geotilefetcher_esri.cpp b/src/plugins/geoservices/esri/geotilefetcher_esri.cpp
new file mode 100644
index 00000000..62484bbb
--- /dev/null
+++ b/src/plugins/geoservices/esri/geotilefetcher_esri.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "geotilefetcher_esri.h"
+#include "geotiledmappingmanagerengine_esri.h"
+#include "geotiledmapreply_esri.h"
+
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+
+#include <QtLocation/private/qgeotilespec_p.h>
+
+QT_BEGIN_NAMESPACE
+
+GeoTileFetcherEsri::GeoTileFetcherEsri(QObject *parent) :
+ QGeoTileFetcher(parent), m_networkManager(new QNetworkAccessManager(this)),
+ m_userAgent(QByteArrayLiteral("Qt Location based application"))
+{
+}
+
+QGeoTiledMapReply *GeoTileFetcherEsri::getTileImage(const QGeoTileSpec &spec)
+{
+ QNetworkRequest request;
+ request.setHeader(QNetworkRequest::UserAgentHeader, userAgent());
+
+ GeoTiledMappingManagerEngineEsri *engine = qobject_cast<GeoTiledMappingManagerEngineEsri *>(
+ parent());
+
+ GeoMapSource *mapSource = engine->mapSource(spec.mapId());
+
+ if (!mapSource)
+ qWarning("Unknown mapId %d\n", spec.mapId());
+ else
+ request.setUrl(mapSource->url().arg(spec.zoom()).arg(spec.x()).arg(spec.y()));
+
+ QNetworkReply *reply = m_networkManager->get(request);
+
+ return new GeoTiledMapReplyEsri(reply, spec);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/geotilefetcher_esri.h b/src/plugins/geoservices/esri/geotilefetcher_esri.h
new file mode 100644
index 00000000..43dcfdfa
--- /dev/null
+++ b/src/plugins/geoservices/esri/geotilefetcher_esri.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef GEOTILEFETCHERESRI_H
+#define GEOTILEFETCHERESRI_H
+
+#include <QtLocation/private/qgeotilefetcher_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGeoTiledMappingManagerEngine;
+class QNetworkAccessManager;
+
+class GeoTileFetcherEsri : public QGeoTileFetcher
+{
+ Q_OBJECT
+
+public:
+ explicit GeoTileFetcherEsri(QObject *parent = Q_NULLPTR);
+
+ inline const QByteArray &userAgent() const;
+ inline void setUserAgent(const QByteArray &userAgent);
+
+ inline const QString &token() const;
+ inline void setToken(const QString &token);
+
+private:
+ QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec) Q_DECL_OVERRIDE;
+
+ QNetworkAccessManager *m_networkManager;
+ QByteArray m_userAgent;
+ QString m_token;
+};
+
+inline const QByteArray &GeoTileFetcherEsri::userAgent() const
+{
+ return m_userAgent;
+}
+
+inline void GeoTileFetcherEsri::setUserAgent(const QByteArray &userAgent)
+{
+ m_userAgent = userAgent;
+}
+
+inline const QString &GeoTileFetcherEsri::token() const
+{
+ return m_token;
+}
+
+inline void GeoTileFetcherEsri::setToken(const QString &token)
+{
+ m_token = token;
+}
+
+QT_END_NAMESPACE
+
+#endif // GEOTILEFETCHERESRI_H
diff --git a/src/plugins/geoservices/esri/maps.json b/src/plugins/geoservices/esri/maps.json
new file mode 100644
index 00000000..8167ae7d
--- /dev/null
+++ b/src/plugins/geoservices/esri/maps.json
@@ -0,0 +1,123 @@
+{
+ "mapSources": [
+ {
+ "style": "StreetMap",
+ "name": "World Street Map",
+ "description": "ArcGIS Online World Street Map",
+ "mobile": true,
+ "night": false,
+ "url": "http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=3b93337983e9436f8db950e38a8629af'>Esri</a> contributors"
+ },
+
+ {
+ "style": "SatelliteMapDay",
+ "name": "World Imagery",
+ "": "ArcGIS Online World Imagery",
+ "mobile": true,
+ "night": false,
+ "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9'>Esri</a> contributors"
+ },
+
+ {
+ "style": "TerrainMap",
+ "name": "World Terrain Base",
+ "description": "ArcGIS Online World Terrain Base",
+ "mobile": false,
+ "night": false,
+ "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Terrain_Base/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=c61ad8ab017d49e1a82f580ee1298931'>Esri</a> contributors"
+ },
+
+ {
+ "style": "CustomMap",
+ "name": "World Topography",
+ "description": "ArcGIS Online World Topography",
+ "mobile": true,
+ "night": false,
+ "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=30e5fe3149c34df1ba922e6f5bbf808f'>Esri</a> contributors"
+ },
+
+ {
+ "style": "CustomMap",
+ "name": "USA Topo Maps",
+ "description": "This map presents land cover and detailed topographic maps for the United States.",
+ "mobile": true,
+ "night": false,
+ "url": "http://services.arcgisonline.com/ArcGIS/rest/services/USA_Topo_Maps/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=99cd5fbd98934028802b4f797c4b1732'>Esri</a> contributors"
+ },
+
+ {
+ "style": "CustomMap",
+ "name": "National Geographic World Map",
+ "description": "National Geographic World Map",
+ "mobile": false,
+ "night": false,
+ "url": "http://services.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=b9b1b422198944fbbd5250b3241691b6'>Esri</a> contributors"
+ },
+
+ {
+ "style": "GrayStreetMap",
+ "name": "Light Gray Canvas",
+ "description": "Thematic content providing a neutral background with minimal colors",
+ "mobile": true,
+ "night": false,
+ "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=ed712cb1db3e4bae9e85329040fb9a49'>Esri</a> contributors"
+ },
+
+ {
+ "style": "CustomMap",
+ "name": "World Physical Map",
+ "description": "Natural Earth physical map for the world",
+ "mobile": false,
+ "night": false,
+ "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Physical_Map/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=c4ec722a1cd34cf0a23904aadf8923a0'>Esri</a> contributors"
+ },
+
+ {
+ "style": "CustomMap",
+ "name": "World Shaded Relief",
+ "description": "Portrays surface elevation as shaded relief",
+ "mobile": false,
+ "night": false,
+ "url": "http://server.arcgisonline.com/ArcGIS/rest/services/World_Shaded_Relief/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=9c5370d0b54f4de1b48a3792d7377ff2'>Esri</a> contributors"
+ },
+
+ {
+ "style": "CustomMap",
+ "name": "World Ocean Base",
+ "description": "This map is designed to be used as a basemap by marine GIS professionals and as a reference map by anyone interested in ocean data",
+ "mobile": false,
+ "night": false,
+ "url": "http://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Base/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=1e126e7520f9466c9ca28b8f28b5e500'>Esri</a> contributors"
+ },
+
+ {
+ "style": "GrayStreetMap",
+ "name": "Dark Gray Canvas",
+ "description": "Thematic content providing a neutral background with minimal colors",
+ "mobile": false,
+ "night": true,
+ "url": "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=a284a9b99b3446a3910d4144a50990f6'>Esri</a> contributors"
+ },
+
+ {
+ "style": "CustomMap",
+ "name": "DeLorme World Basemap",
+ "description": "DeLorme’s topographic basemap is a seamless global data set that portrays transportation, hydrography, jurisdiction boundaries, and major geographic features",
+ "mobile": false,
+ "night": false,
+ "url": "http://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer",
+ "copyrightText": "&copy; <a href='http://www.arcgis.com/home/item.html?id=b165c3df453e4be6b5ac4fdb241effbe'>Esri</a> contributors"
+ }
+ ]
+}
diff --git a/src/plugins/geoservices/geoservices.pro b/src/plugins/geoservices/geoservices.pro
index 3d0971f7..7a392b57 100644
--- a/src/plugins/geoservices/geoservices.pro
+++ b/src/plugins/geoservices/geoservices.pro
@@ -1,3 +1,3 @@
TEMPLATE = subdirs
-SUBDIRS = nokia osm mapbox
+SUBDIRS = nokia osm mapbox esri
diff --git a/src/plugins/geoservices/mapbox/mapbox.pro b/src/plugins/geoservices/mapbox/mapbox.pro
index d4797e37..ea011131 100644
--- a/src/plugins/geoservices/mapbox/mapbox.pro
+++ b/src/plugins/geoservices/mapbox/mapbox.pro
@@ -6,13 +6,19 @@ HEADERS += \
qgeoserviceproviderpluginmapbox.h \
qgeotiledmappingmanagerenginemapbox.h \
qgeotilefetchermapbox.h \
- qgeomapreplymapbox.h
+ qgeomapreplymapbox.h \
+ qgeofiletilecachemapbox.h \
+ qgeoroutingmanagerenginemapbox.h \
+ qgeoroutereplymapbox.h
SOURCES += \
qgeoserviceproviderpluginmapbox.cpp \
qgeotiledmappingmanagerenginemapbox.cpp \
qgeotilefetchermapbox.cpp \
- qgeomapreplymapbox.cpp
+ qgeomapreplymapbox.cpp \
+ qgeofiletilecachemapbox.cpp \
+ qgeoroutingmanagerenginemapbox.cpp \
+ qgeoroutereplymapbox.cpp
OTHER_FILES += \
mapbox_plugin.json
diff --git a/src/plugins/geoservices/mapbox/mapbox_plugin.json b/src/plugins/geoservices/mapbox/mapbox_plugin.json
index 0b8d08af..f886458f 100644
--- a/src/plugins/geoservices/mapbox/mapbox_plugin.json
+++ b/src/plugins/geoservices/mapbox/mapbox_plugin.json
@@ -4,6 +4,7 @@
"Version": 100,
"Experimental": false,
"Features": [
- "OnlineMappingFeature"
+ "OnlineMappingFeature",
+ "OnlineRoutingFeature"
]
}
diff --git a/src/plugins/geoservices/mapbox/qgeofiletilecachemapbox.cpp b/src/plugins/geoservices/mapbox/qgeofiletilecachemapbox.cpp
new file mode 100644
index 00000000..8cc3622b
--- /dev/null
+++ b/src/plugins/geoservices/mapbox/qgeofiletilecachemapbox.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 "qgeofiletilecachemapbox.h"
+#include <QtLocation/private/qgeotilespec_p.h>
+#include <QDir>
+
+QT_BEGIN_NAMESPACE
+
+QGeoFileTileCacheMapbox::QGeoFileTileCacheMapbox(const QList<QGeoMapType> &mapTypes, int scaleFactor, const QString &directory, QObject *parent)
+ :QGeoFileTileCache(directory, parent), m_mapTypes(mapTypes)
+{
+ m_scaleFactor = qBound(1, scaleFactor, 2);
+ for (int i=0; i < mapTypes.size(); i++)
+ m_mapNameToId.insert(mapTypes[i].name(), i);
+}
+
+QGeoFileTileCacheMapbox::~QGeoFileTileCacheMapbox()
+{
+
+}
+
+QString QGeoFileTileCacheMapbox::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const
+{
+ QString filename = spec.plugin();
+ filename += QLatin1String("-");
+ filename += m_mapTypes[spec.mapId()].name();
+ filename += QLatin1String("-");
+ filename += QString::number(spec.zoom());
+ filename += QLatin1String("-");
+ filename += QString::number(spec.x());
+ filename += QLatin1String("-");
+ filename += QString::number(spec.y());
+
+ //Append version if real version number to ensure backwards compatibility and eviction of old tiles
+ if (spec.version() != -1) {
+ filename += QLatin1String("-");
+ filename += QString::number(spec.version());
+ }
+
+ filename += QLatin1String("-@");
+ filename += QString::number(m_scaleFactor);
+ filename += QLatin1Char('x');
+
+ filename += QLatin1String(".");
+ filename += format;
+
+ QDir dir = QDir(directory);
+
+ return dir.filePath(filename);
+}
+
+QGeoTileSpec QGeoFileTileCacheMapbox::filenameToTileSpec(const QString &filename) const
+{
+ QStringList parts = filename.split('.');
+
+ if (parts.length() != 3)
+ return QGeoTileSpec();
+
+ QString name = parts.at(0) + parts.at(1);
+ QStringList fields = name.split('-');
+
+ int length = fields.length();
+ if (length != 6 && length != 7) {
+ return QGeoTileSpec();
+ } else {
+ int scaleIdx = fields.last().indexOf("@");
+ if (scaleIdx < 0 || fields.last().size() <= (scaleIdx + 2))
+ return QGeoTileSpec();
+ int scaleFactor = fields.last()[scaleIdx + 1].digitValue();
+ if (scaleFactor != m_scaleFactor)
+ return QGeoTileSpec();
+ }
+
+ QList<int> numbers;
+
+ bool ok = false;
+ for (int i = 2; i < length-1; ++i) { // skipping -@_X
+ ok = false;
+ int value = fields.at(i).toInt(&ok);
+ if (!ok)
+ return QGeoTileSpec();
+ numbers.append(value);
+ }
+
+ //File name without version, append default
+ if (numbers.length() < 4)
+ numbers.append(-1);
+
+ return QGeoTileSpec(fields.at(0),
+ m_mapNameToId[fields.at(1)],
+ numbers.at(0),
+ numbers.at(1),
+ numbers.at(2),
+ numbers.at(3));
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/mapbox/qgeofiletilecachemapbox.h b/src/plugins/geoservices/mapbox/qgeofiletilecachemapbox.h
new file mode 100644
index 00000000..faf9b2bf
--- /dev/null
+++ b/src/plugins/geoservices/mapbox/qgeofiletilecachemapbox.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef QGEOFILETILECACHEMAPBOX_H
+#define QGEOFILETILECACHEMAPBOX_H
+
+#include <QtLocation/private/qgeofiletilecache_p.h>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+
+class QGeoFileTileCacheMapbox : public QGeoFileTileCache
+{
+ Q_OBJECT
+public:
+ QGeoFileTileCacheMapbox(const QList<QGeoMapType> &mapTypes, int scaleFactor, const QString &directory = QString(), QObject *parent = 0);
+ ~QGeoFileTileCacheMapbox();
+
+protected:
+ QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const Q_DECL_OVERRIDE;
+ QGeoTileSpec filenameToTileSpec(const QString &filename) const Q_DECL_OVERRIDE;
+
+ QList<QGeoMapType> m_mapTypes;
+ QMap<QString, int> m_mapNameToId;
+ int m_scaleFactor;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOFILETILECACHEMAPBOX_H
diff --git a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp
new file mode 100644
index 00000000..4c98412b
--- /dev/null
+++ b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp
@@ -0,0 +1,231 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Vlad Seryakov <vseryakov@gmail.com>
+** Copyright (C) 2016 Aaron McCarthy <mccarthy.aaron@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgeoroutereplymapbox.h"
+
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QtCore/QJsonArray>
+#include <QtLocation/QGeoRouteSegment>
+#include <QtLocation/QGeoManeuver>
+
+QT_BEGIN_NAMESPACE
+
+static QList<QGeoCoordinate> parsePolyline(const QString &line)
+{
+ QList<QGeoCoordinate> path;
+ QByteArray data(line.toLocal8Bit());
+
+ int mode = 0, shift = 0, value = 0, coord[2] = {0, 0};
+ for (int i = 0; i < data.length(); ++i) {
+ int c = data.at(i) - 63;
+ value |= (c & 0x1f) << shift;
+ shift += 5;
+ if (c & 0x20) continue;
+ coord[mode] += (value & 1) ? ~(value >> 1) : (value >> 1);
+ if (mode) path.append(QGeoCoordinate((double)coord[0]/1e5, (double)coord[1]/1e5));
+ mode = 1 - mode;
+ value = shift = 0;
+ }
+ return path;
+}
+
+static QList<QGeoCoordinate> parseGeometry(const QJsonValue &geometry)
+{
+ QList<QGeoCoordinate> path;
+ if (geometry.isString()) path = parsePolyline(geometry.toString());
+ if (geometry.isObject()) {
+ QJsonArray coords = geometry.toObject().value(QStringLiteral("coordinates")).toArray();
+ for (int i = 0; i < coords.count(); i++) {
+ QJsonArray coord = coords.at(i).toArray();
+ if (coord.count() != 2) continue;
+ path.append(QGeoCoordinate(coord.at(1).toDouble(), coord.at(0).toDouble()));
+ }
+ }
+ return path;
+}
+
+QGeoRouteReplyMapbox::QGeoRouteReplyMapbox(QNetworkReply *reply, const QGeoRouteRequest &request,
+ QObject *parent)
+: QGeoRouteReply(request, parent), m_reply(reply)
+{
+ connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished()));
+ connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)),
+ this, SLOT(networkReplyError(QNetworkReply::NetworkError)));
+}
+
+QGeoRouteReplyMapbox::~QGeoRouteReplyMapbox()
+{
+ if (m_reply)
+ m_reply->deleteLater();
+}
+
+void QGeoRouteReplyMapbox::abort()
+{
+ if (!m_reply)
+ return;
+
+ m_reply->abort();
+
+ m_reply->deleteLater();
+ m_reply = 0;
+}
+
+static QGeoRoute constructRoute(const QJsonObject &obj)
+{
+ QGeoRoute route;
+ route.setDistance(obj.value(QStringLiteral("distance")).toDouble());
+ route.setTravelTime(obj.value(QStringLiteral("duration")).toDouble());
+
+ QList<QGeoCoordinate> path = parseGeometry(obj.value(QStringLiteral("geometry")));
+ route.setPath(path);
+
+ QGeoRouteSegment firstSegment, lastSegment;
+ QJsonArray legs = obj.value(QStringLiteral("legs")).toArray();
+
+ for (int i = 0; i < legs.count(); i++) {
+ QJsonObject leg = legs.at(i).toObject();
+ QJsonArray steps = leg.value("steps").toArray();
+
+ for (int j = 0; j < steps.count(); j++) {
+ QJsonObject step = steps.at(j).toObject();
+ QJsonObject stepManeuver = step.value("maneuver").toObject();
+
+ QGeoRouteSegment segment;
+ segment.setDistance(step.value("distance").toDouble());
+ segment.setTravelTime(step.value(QStringLiteral("duration")).toDouble());
+
+ QGeoManeuver maneuver;
+ maneuver.setDistanceToNextInstruction(step.value("distance").toDouble());
+ maneuver.setInstructionText(stepManeuver.value("instruction").toString());
+ maneuver.setTimeToNextInstruction(step.value(QStringLiteral("duration")).toDouble());
+ QJsonArray location = stepManeuver.value(QStringLiteral("location")).toArray();
+ if (location.count() > 1)
+ maneuver.setPosition(QGeoCoordinate(location.at(0).toDouble(), location.at(1).toDouble()));
+
+ QString modifier = stepManeuver.value("modifier").toString();
+ int bearing1 = stepManeuver.value("bearing_before").toInt();
+ int bearing2 = stepManeuver.value("bearing_after").toInt();
+
+ if (modifier == "straight")
+ maneuver.setDirection(QGeoManeuver::DirectionForward);
+ else if (modifier == "slight right")
+ maneuver.setDirection(QGeoManeuver::DirectionLightRight);
+ else if (modifier == "right")
+ maneuver.setDirection(QGeoManeuver::DirectionRight);
+ else if (modifier == "sharp right")
+ maneuver.setDirection(QGeoManeuver::DirectionHardRight);
+ else if (modifier == "uturn")
+ maneuver.setDirection(bearing2 - bearing1 > 180 ? QGeoManeuver::DirectionUTurnLeft : QGeoManeuver::DirectionUTurnRight);
+ else if (modifier == "sharp left")
+ maneuver.setDirection(QGeoManeuver::DirectionHardLeft);
+ else if (modifier == "left")
+ maneuver.setDirection(QGeoManeuver::DirectionLeft);
+ else if (modifier == "slight left")
+ maneuver.setDirection(QGeoManeuver::DirectionLightLeft);
+ else
+ maneuver.setDirection(QGeoManeuver::NoDirection);
+
+ segment.setManeuver(maneuver);
+ segment.setPath(parseGeometry(step.value(QStringLiteral("geometry"))));
+
+ if (!firstSegment.isValid()) firstSegment = segment;
+ if (lastSegment.isValid()) lastSegment.setNextRouteSegment(segment);
+ lastSegment = segment;
+ }
+ }
+ route.setFirstRouteSegment(firstSegment);
+ return route;
+}
+
+void QGeoRouteReplyMapbox::networkReplyFinished()
+{
+ if (!m_reply)
+ return;
+
+ if (m_reply->error() != QNetworkReply::NoError) {
+ setError(QGeoRouteReply::CommunicationError, m_reply->errorString());
+ m_reply->deleteLater();
+ m_reply = 0;
+ return;
+ }
+
+ QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll());
+ if (document.isObject()) {
+ QJsonObject object = document.object();
+
+ QString status = object.value(QStringLiteral("code")).toString();
+ if (status != QStringLiteral("Ok")) {
+ setError(QGeoRouteReply::UnknownError, object.value(QStringLiteral("message")).toString());
+ m_reply->deleteLater();
+ m_reply = 0;
+ return;
+ }
+
+ QList<QGeoRoute> list;
+ QJsonArray routes = object.value(QStringLiteral("routes")).toArray();
+ for (int i = 0; i < routes.count(); i++) {
+ QGeoRoute route = constructRoute(routes.at(i).toObject());
+ list.append(route);
+ }
+ setRoutes(list);
+ setFinished(true);
+ } else {
+ setError(QGeoRouteReply::ParseError, QStringLiteral("Couldn't parse json."));
+ }
+
+ m_reply->deleteLater();
+ m_reply = 0;
+}
+
+void QGeoRouteReplyMapbox::networkReplyError(QNetworkReply::NetworkError error)
+{
+ Q_UNUSED(error)
+
+ if (!m_reply)
+ return;
+
+ setError(QGeoRouteReply::CommunicationError, m_reply->errorString());
+
+ m_reply->deleteLater();
+ m_reply = 0;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.h b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.h
new file mode 100644
index 00000000..9df45ac4
--- /dev/null
+++ b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.h
@@ -0,0 +1,71 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Vlad Seryakov <vseryakov@gmail.com>
+** Copyright (C) 2016 Aaron McCarthy <mccarthy.aaron@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOROUTEREPLYMAPBOX_H
+#define QGEOROUTEREPLYMAPBOX_H
+
+#include <QtNetwork/QNetworkReply>
+#include <QtLocation/QGeoRouteReply>
+
+QT_BEGIN_NAMESPACE
+
+class QGeoRouteReplyMapbox : public QGeoRouteReply
+{
+ Q_OBJECT
+
+public:
+ explicit QGeoRouteReplyMapbox(QObject *parent = 0);
+ QGeoRouteReplyMapbox(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent = 0);
+ ~QGeoRouteReplyMapbox();
+
+ void abort() Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void networkReplyFinished();
+ void networkReplyError(QNetworkReply::NetworkError error);
+
+private:
+ QNetworkReply *m_reply;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOROUTEREPLYMAPBOX_H
+
diff --git a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp
new file mode 100644
index 00000000..d6ef8f0a
--- /dev/null
+++ b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Vlad Seryakov <vseryakov@gmail.com>
+** Copyright (C) 2016 Aaron McCarthy <mccarthy.aaron@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgeoroutingmanagerenginemapbox.h"
+#include "qgeoroutereplymapbox.h"
+
+#include <QtCore/QUrlQuery>
+#include <QtCore/QDebug>
+
+QT_BEGIN_NAMESPACE
+
+QGeoRoutingManagerEngineMapbox::QGeoRoutingManagerEngineMapbox(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error,
+ QString *errorString)
+ : QGeoRoutingManagerEngine(parameters),
+ m_networkManager(new QNetworkAccessManager(this)),
+ m_userAgent("Qt Location based application")
+{
+ if (parameters.contains(QStringLiteral("mapbox.useragent"))) {
+ m_userAgent = parameters.value(QStringLiteral("mapbox.useragent")).toString().toLatin1();
+ }
+
+ if (parameters.contains(QStringLiteral("mapbox.access_token"))) {
+ m_accessToken = parameters.value(QStringLiteral("mapbox.access_token")).toString();
+ }
+
+ *error = QGeoServiceProvider::NoError;
+ errorString->clear();
+}
+
+QGeoRoutingManagerEngineMapbox::~QGeoRoutingManagerEngineMapbox()
+{
+}
+
+QGeoRouteReply* QGeoRoutingManagerEngineMapbox::calculateRoute(const QGeoRouteRequest &request)
+{
+ QNetworkRequest networkRequest;
+ networkRequest.setRawHeader("User-Agent", m_userAgent);
+
+ QString url("https://api.mapbox.com/directions/v5/mapbox/");
+
+ QGeoRouteRequest::TravelModes travelModes = request.travelModes();
+ if (travelModes.testFlag(QGeoRouteRequest::PedestrianTravel))
+ url += "walking/";
+ else
+ if (travelModes.testFlag(QGeoRouteRequest::BicycleTravel))
+ url += "cycling/";
+ else
+ if (travelModes.testFlag(QGeoRouteRequest::CarTravel))
+ url += "driving/";
+
+ foreach (const QGeoCoordinate &c, request.waypoints()) {
+ url += QString("%1,%2;").arg(c.longitude()).arg(c.latitude());
+ }
+ if (url.right(1) == ";") url.chop(1);
+ url += QString("?steps=true&overview=full&geometries=geojson&access_token=%1").arg(m_accessToken);
+
+ networkRequest.setUrl(QUrl(url));
+
+ QNetworkReply *reply = m_networkManager->get(networkRequest);
+ QGeoRouteReplyMapbox *routeReply = new QGeoRouteReplyMapbox(reply, request, this);
+
+ connect(routeReply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ connect(routeReply, SIGNAL(error(QGeoRouteReply::Error,QString)),
+ this, SLOT(replyError(QGeoRouteReply::Error,QString)));
+
+ return routeReply;
+}
+
+void QGeoRoutingManagerEngineMapbox::replyFinished()
+{
+ QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
+ if (reply)
+ emit finished(reply);
+}
+
+void QGeoRoutingManagerEngineMapbox::replyError(QGeoRouteReply::Error errorCode,
+ const QString &errorString)
+{
+ QGeoRouteReply *reply = qobject_cast<QGeoRouteReply *>(sender());
+ if (reply)
+ emit error(reply, errorCode, errorString);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.h b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.h
new file mode 100644
index 00000000..5b440147
--- /dev/null
+++ b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Vlad Seryakov <vseryakov@gmail.com>
+** Copyright (C) 2016 Aaron McCarthy <mccarthy.aaron@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOROUTINGMANAGERENGINEMAPBOX_H
+#define QGEOROUTINGMANAGERENGINEMAPBOX_H
+
+#include <QtLocation/QGeoServiceProvider>
+#include <QtLocation/QGeoRoutingManagerEngine>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkAccessManager;
+
+class QGeoRoutingManagerEngineMapbox : public QGeoRoutingManagerEngine
+{
+ Q_OBJECT
+
+public:
+ QGeoRoutingManagerEngineMapbox(const QVariantMap &parameters,
+ QGeoServiceProvider::Error *error,
+ QString *errorString);
+ ~QGeoRoutingManagerEngineMapbox();
+
+ QGeoRouteReply *calculateRoute(const QGeoRouteRequest &request);
+
+private Q_SLOTS:
+ void replyFinished();
+ void replyError(QGeoRouteReply::Error errorCode, const QString &errorString);
+
+private:
+ QNetworkAccessManager *m_networkManager;
+ QByteArray m_userAgent;
+ QString m_accessToken;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOROUTINGMANAGERENGINEOSM_H
+
diff --git a/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.cpp b/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.cpp
index ec40716b..835f9d04 100644
--- a/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.cpp
+++ b/src/plugins/geoservices/mapbox/qgeoserviceproviderpluginmapbox.cpp
@@ -36,6 +36,7 @@
#include "qgeoserviceproviderpluginmapbox.h"
#include "qgeotiledmappingmanagerenginemapbox.h"
+#include "qgeoroutingmanagerenginemapbox.h"
#include <QtLocation/private/qgeotiledmappingmanagerengine_p.h>
@@ -51,18 +52,22 @@ QGeoCodingManagerEngine *QGeoServiceProviderFactoryMapbox::createGeocodingManage
return 0;
}
+static inline QString msgAccessTokenParameter()
+{
+ return QGeoServiceProviderFactoryMapbox::tr("Mapbox plugin requires a 'mapbox.access_token' parameter.\n"
+ "Please visit https://www.mapbox.com");
+}
+
QGeoMappingManagerEngine *QGeoServiceProviderFactoryMapbox::createMappingManagerEngine(
const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString) const
{
- const QString mapId = parameters.value(QStringLiteral("mapbox.map_id")).toString();
const QString accessToken = parameters.value(QStringLiteral("mapbox.access_token")).toString();
- if (!mapId.isEmpty() && !accessToken.isEmpty()) {
+ if (!accessToken.isEmpty()) {
return new QGeoTiledMappingManagerEngineMapbox(parameters, error, errorString);
} else {
*error = QGeoServiceProvider::MissingRequiredParameterError;
- *errorString = tr("Mapbox plugin requires 'mapbox.map_id' and 'mapbox.access_token' parameters.\n"
- "Please visit https://www.mapbox.com");
+ *errorString = msgAccessTokenParameter();
return 0;
}
}
@@ -70,11 +75,15 @@ QGeoMappingManagerEngine *QGeoServiceProviderFactoryMapbox::createMappingManager
QGeoRoutingManagerEngine *QGeoServiceProviderFactoryMapbox::createRoutingManagerEngine(
const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString) const
{
- Q_UNUSED(parameters)
- Q_UNUSED(error)
- Q_UNUSED(errorString)
+ const QString accessToken = parameters.value(QStringLiteral("mapbox.access_token")).toString();
- return 0;
+ if (!accessToken.isEmpty()) {
+ return new QGeoRoutingManagerEngineMapbox(parameters, error, errorString);
+ } else {
+ *error = QGeoServiceProvider::MissingRequiredParameterError;
+ *errorString = msgAccessTokenParameter();
+ return 0;
+ }
}
QPlaceManagerEngine *QGeoServiceProviderFactoryMapbox::createPlaceManagerEngine(
diff --git a/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp
index 4be5ac24..5404eb30 100644
--- a/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp
+++ b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp
@@ -40,6 +40,7 @@
#include <QtLocation/private/qgeocameracapabilities_p.h>
#include <QtLocation/private/qgeomaptype_p.h>
#include <QtLocation/private/qgeotiledmap_p.h>
+#include "qgeofiletilecachemapbox.h"
QT_BEGIN_NAMESPACE
@@ -54,19 +55,80 @@ QGeoTiledMappingManagerEngineMapbox::QGeoTiledMappingManagerEngineMapbox(const Q
setTileSize(QSize(256, 256));
QList<QGeoMapType> mapTypes;
- mapTypes << QGeoMapType(QGeoMapType::CustomMap, tr("Custom"), tr("Mapbox custom map"), false, false, 0);
+ // as index 0 to retain compatibility with the current API, that expects the passed map_id to be on by default.
+ if (parameters.contains(QStringLiteral("mapbox.mapping.map_id"))) {
+ const QString name = parameters.value(QStringLiteral("mapbox.mapping.map_id")).toString();
+ mapTypes << QGeoMapType(QGeoMapType::CustomMap, name, name, false, false, mapTypes.size());
+ } else if (parameters.contains(QStringLiteral("mapbox.map_id"))) { //deprecated
+ const QString name = parameters.value(QStringLiteral("mapbox.map_id")).toString();
+ mapTypes << QGeoMapType(QGeoMapType::CustomMap, name, name, false, false, mapTypes.size());
+ }
+
+ // As of 2016.06.15, valid mapbox map_ids are documented at https://www.mapbox.com/api-documentation/#maps
+ //: Noun describing map type 'Street map'
+ mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.streets"), tr("Street"), false, false, mapTypes.size());
+ //: Noun describing type of a map using light colors (weak contrast)
+ mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.light"), tr("Light"), false, false, mapTypes.size());
+ //: Noun describing type of a map using dark colors
+ mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.dark"), tr("Dark"), false, true, mapTypes.size());
+ //: Noun describing type of a map created by satellite
+ mapTypes << QGeoMapType(QGeoMapType::SatelliteMapDay, QStringLiteral("mapbox.satellite"), tr("Satellite"), false, false, mapTypes.size());
+ //: Noun describing type of a street map created by satellite
+ mapTypes << QGeoMapType(QGeoMapType::HybridMap, QStringLiteral("mapbox.streets-satellite"), tr("Streets Satellite"), false, false, mapTypes.size());
+ //: Noun describing type of a map using wheat paste colors
+ mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.wheatpaste"), tr("Wheatpaste"), false, false, mapTypes.size());
+ //: Noun describing type of a basic street map
+ mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.streets-basic"), tr("Streets Basic"), false, false, mapTypes.size());
+ //: Noun describing type of a map using cartoon-style fonts
+ mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.comic"), tr("Comic"), false, false, mapTypes.size());
+ //: Noun describing type of a map for outdoor activities
+ mapTypes << QGeoMapType(QGeoMapType::PedestrianMap, QStringLiteral("mapbox.outdoors"), tr("Outdoors"), false, false, mapTypes.size());
+ //: Noun describing type of a map for sports
+ mapTypes << QGeoMapType(QGeoMapType::CycleMap, QStringLiteral("mapbox.run-bike-hike"), tr("Run Bike Hike"), false, false, mapTypes.size());
+ //: Noun describing type of a map drawn by pencil
+ mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.pencil"), tr("Pencil"), false, false, mapTypes.size());
+ //: Noun describing type of a treasure map with pirate boat watermark
+ mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.pirates"), tr("Pirates"), false, false, mapTypes.size());
+ //: Noun describing type of a map using emerald colors
+ mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.emerald"), tr("Emerald"), false, false, mapTypes.size());
+ //: Noun describing type of a map with high contrast
+ mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.high-contrast"), tr("High Contrast"), false, false, mapTypes.size());
+
+ // New way to specify multiple customized map_ids via additional_map_ids
+ if (parameters.contains(QStringLiteral("mapbox.mapping.additional_map_ids"))) {
+ const QString ids = parameters.value(QStringLiteral("mapbox.mapping.additional_map_ids")).toString();
+ const QStringList idList = ids.split(',', QString::SkipEmptyParts);
+
+ for (const QString &name: idList) {
+ if (!name.isEmpty())
+ mapTypes << QGeoMapType(QGeoMapType::CustomMap, name, name, false, false, mapTypes.size());
+ }
+ }
+
+ QVector<QString> mapIds;
+ for (int i=0; i < mapTypes.size(); ++i)
+ mapIds.push_back(mapTypes[i].name());
+
setSupportedMapTypes(mapTypes);
- QGeoTileFetcherMapbox *tileFetcher = new QGeoTileFetcherMapbox(this);
+ int scaleFactor = 1;
+ if (parameters.contains(QStringLiteral("mapbox.mapping.highdpi_tiles"))) {
+ const QString param = parameters.value(QStringLiteral("mapbox.mapping.highdpi_tiles")).toString().toLower();
+ if (param == "true")
+ scaleFactor = 2;
+ }
+
+ QGeoTileFetcherMapbox *tileFetcher = new QGeoTileFetcherMapbox(scaleFactor, this);
+ tileFetcher->setMapIds(mapIds);
+
if (parameters.contains(QStringLiteral("useragent"))) {
const QByteArray ua = parameters.value(QStringLiteral("useragent")).toString().toLatin1();
tileFetcher->setUserAgent(ua);
}
- if (parameters.contains(QStringLiteral("mapbox.map_id"))) {
- const QString id = parameters.value(QStringLiteral("mapbox.map_id")).toString();
- tileFetcher->setMapId(id);
- }
- if (parameters.contains(QStringLiteral("mapbox.format"))) {
+ if (parameters.contains(QStringLiteral("mapbox.mapping.format"))) {
+ const QString format = parameters.value(QStringLiteral("mapbox.mapping.format")).toString();
+ tileFetcher->setFormat(format);
+ } else if (parameters.contains(QStringLiteral("mapbox.format"))) { //deprecated
const QString format = parameters.value(QStringLiteral("mapbox.format")).toString();
tileFetcher->setFormat(format);
}
@@ -77,6 +139,85 @@ QGeoTiledMappingManagerEngineMapbox::QGeoTiledMappingManagerEngineMapbox(const Q
setTileFetcher(tileFetcher);
+ // TODO: do this in a plugin-neutral way so that other tiled map plugins
+ // don't need this boilerplate or hardcode plugin name
+
+ if (parameters.contains(QStringLiteral("mapbox.mapping.cache.directory"))) {
+ m_cacheDirectory = parameters.value(QStringLiteral("mapbox.mapping.cache.directory")).toString();
+ } else {
+ // managerName() is not yet set, we have to hardcode the plugin name below
+ m_cacheDirectory = QAbstractGeoTileCache::baseLocationCacheDirectory() + QLatin1String("mapbox");
+ }
+
+ QGeoFileTileCache *tileCache = new QGeoFileTileCacheMapbox(mapTypes, scaleFactor, m_cacheDirectory);
+
+ /*
+ * Disk cache setup -- defaults to Unitary since:
+ *
+ * The Mapbox free plan allows for 6000 tiles to be stored for offline uses,
+ * As of 2016.06.15, according to https://www.mapbox.com/help/mobile-offline/ .
+ * Thus defaulting to Unitary strategy, and setting 6000 tiles as default cache disk size
+ */
+ if (parameters.contains(QStringLiteral("mapbox.mapping.cache.disk.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("mapbox.mapping.cache.disk.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::Unitary);
+ }
+ if (parameters.contains(QStringLiteral("mapbox.mapping.cache.disk.size"))) {
+ bool ok = false;
+ int cacheSize = parameters.value(QStringLiteral("mapbox.mapping.cache.disk.size")).toString().toInt(&ok);
+ if (ok)
+ tileCache->setMaxDiskUsage(cacheSize);
+ } else {
+ if (tileCache->costStrategyDisk() == QGeoFileTileCache::Unitary)
+ tileCache->setMaxDiskUsage(6000); // The maximum allowed with the free tier
+ }
+
+ /*
+ * Memory cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("mapbox.mapping.cache.memory.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("mapbox.mapping.cache.memory.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
+ }
+ if (parameters.contains(QStringLiteral("mapbox.mapping.cache.memory.size"))) {
+ bool ok = false;
+ int cacheSize = parameters.value(QStringLiteral("mapbox.mapping.cache.memory.size")).toString().toInt(&ok);
+ if (ok)
+ tileCache->setMaxMemoryUsage(cacheSize);
+ }
+
+ /*
+ * Texture cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("mapbox.mapping.cache.texture.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("mapbox.mapping.cache.texture.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ }
+ if (parameters.contains(QStringLiteral("mapbox.mapping.cache.texture.size"))) {
+ bool ok = false;
+ int cacheSize = parameters.value(QStringLiteral("mapbox.mapping.cache.texture.size")).toString().toInt(&ok);
+ if (ok)
+ tileCache->setExtraTextureUsage(cacheSize);
+ }
+
+
+ setTileCache(tileCache);
+
*error = QGeoServiceProvider::NoError;
errorString->clear();
}
diff --git a/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.h b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.h
index 379ca6b8..292e4211 100644
--- a/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.h
+++ b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.h
@@ -53,6 +53,9 @@ public:
~QGeoTiledMappingManagerEngineMapbox();
QGeoMap *createMap();
+
+private:
+ QString m_cacheDirectory;
};
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.cpp b/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.cpp
index 69a832df..062b4f89 100644
--- a/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.cpp
+++ b/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.cpp
@@ -44,14 +44,14 @@
QT_BEGIN_NAMESPACE
-QGeoTileFetcherMapbox::QGeoTileFetcherMapbox(QObject *parent)
+QGeoTileFetcherMapbox::QGeoTileFetcherMapbox(int scaleFactor, QObject *parent)
: QGeoTileFetcher(parent), m_networkManager(new QNetworkAccessManager(this)),
m_userAgent("Qt Location based application"),
- m_mapId(""),
m_format("png"),
m_replyFormat("png"),
m_accessToken("")
{
+ m_scaleFactor = qBound(1, scaleFactor, 2);
}
void QGeoTileFetcherMapbox::setUserAgent(const QByteArray &userAgent)
@@ -59,9 +59,9 @@ void QGeoTileFetcherMapbox::setUserAgent(const QByteArray &userAgent)
m_userAgent = userAgent;
}
-void QGeoTileFetcherMapbox::setMapId(const QString &mapId)
+void QGeoTileFetcherMapbox::setMapIds(const QVector<QString> &mapIds)
{
- m_mapId = mapId;
+ m_mapIds = mapIds;
}
void QGeoTileFetcherMapbox::setFormat(const QString &format)
@@ -87,10 +87,11 @@ QGeoTiledMapReply *QGeoTileFetcherMapbox::getTileImage(const QGeoTileSpec &spec)
request.setRawHeader("User-Agent", m_userAgent);
request.setUrl(QUrl(QStringLiteral("http://api.tiles.mapbox.com/v4/") +
- m_mapId + QLatin1Char('/') +
+ ((spec.mapId() >= m_mapIds.size()) ? QStringLiteral("mapbox.streets") : m_mapIds[spec.mapId()]) + QLatin1Char('/') +
QString::number(spec.zoom()) + QLatin1Char('/') +
QString::number(spec.x()) + QLatin1Char('/') +
- QString::number(spec.y()) + QLatin1Char('.') +
+ QString::number(spec.y()) +
+ ((m_scaleFactor > 1) ? (QLatin1Char('@') + QString::number(m_scaleFactor) + QLatin1String("x.")) : QLatin1String(".")) +
m_format + QLatin1Char('?') +
QStringLiteral("access_token=") + m_accessToken));
diff --git a/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.h b/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.h
index ddec2896..e52651e1 100644
--- a/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.h
+++ b/src/plugins/geoservices/mapbox/qgeotilefetchermapbox.h
@@ -37,6 +37,7 @@
#ifndef QGEOTILEFETCHERMAPBOX_H
#define QGEOTILEFETCHERMAPBOX_H
+#include <qvector.h>
#include <QtLocation/private/qgeotilefetcher_p.h>
QT_BEGIN_NAMESPACE
@@ -49,10 +50,10 @@ class QGeoTileFetcherMapbox : public QGeoTileFetcher
Q_OBJECT
public:
- QGeoTileFetcherMapbox(QObject *parent = 0);
+ QGeoTileFetcherMapbox(int scaleFactor = 2, QObject *parent = 0);
void setUserAgent(const QByteArray &userAgent);
- void setMapId(const QString &mapId);
+ void setMapIds(const QVector<QString> &mapIds);
void setFormat(const QString &format);
void setAccessToken(const QString &accessToken);
@@ -61,10 +62,11 @@ private:
QNetworkAccessManager *m_networkManager;
QByteArray m_userAgent;
- QString m_mapId;
QString m_format;
QString m_replyFormat;
QString m_accessToken;
+ QVector<QString> m_mapIds;
+ int m_scaleFactor;
};
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia/nokia.pro b/src/plugins/geoservices/nokia/nokia.pro
index 1aa31123..c60bc7af 100644
--- a/src/plugins/geoservices/nokia/nokia.pro
+++ b/src/plugins/geoservices/nokia/nokia.pro
@@ -2,12 +2,6 @@ TARGET = qtgeoservices_nokia
QT += location-private positioning-private network
-contains(QT_CONFIG, location-china-support) {
- # China support
- DEFINES += USE_CHINA_NETWORK_REGISTRATION
- QT += systeminfo
-}
-
HEADERS += \
qgeocodereply_nokia.h \
qgeocodejsonparser.h \
@@ -26,7 +20,8 @@ HEADERS += \
uri_constants.h \
qgeoerror_messages.h \
qgeomapversion.h \
- qgeotiledmap_nokia.h
+ qgeotiledmap_nokia.h \
+ qgeofiletilecachenokia.h
SOURCES += \
@@ -45,7 +40,8 @@ SOURCES += \
uri_constants.cpp \
qgeoerror_messages.cpp \
qgeomapversion.cpp \
- qgeotiledmap_nokia.cpp
+ qgeotiledmap_nokia.cpp \
+ qgeofiletilecachenokia.cpp
include(placesv2/placesv2.pri)
diff --git a/src/plugins/geoservices/nokia/qgeofiletilecachenokia.cpp b/src/plugins/geoservices/nokia/qgeofiletilecachenokia.cpp
new file mode 100644
index 00000000..8b795325
--- /dev/null
+++ b/src/plugins/geoservices/nokia/qgeofiletilecachenokia.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 "qgeofiletilecachenokia.h"
+#include <QtLocation/private/qgeotilespec_p.h>
+#include <QDir>
+
+QT_BEGIN_NAMESPACE
+
+QGeoFileTileCacheNokia::QGeoFileTileCacheNokia(int ppi, const QString &directory, QObject *parent)
+ :QGeoFileTileCache(directory, parent)
+{
+ m_ppi = QString::number(ppi) + QLatin1String("p");
+}
+
+QGeoFileTileCacheNokia::~QGeoFileTileCacheNokia()
+{
+
+}
+
+QString QGeoFileTileCacheNokia::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const
+{
+ QString filename = spec.plugin();
+ filename += QLatin1String("-");
+ filename += QString::number(spec.mapId());
+ filename += QLatin1String("-");
+ filename += QString::number(spec.zoom());
+ filename += QLatin1String("-");
+ filename += QString::number(spec.x());
+ filename += QLatin1String("-");
+ filename += QString::number(spec.y());
+
+ //Append version if real version number to ensure backwards compatibility and eviction of old tiles
+ if (spec.version() != -1) {
+ filename += QLatin1String("-");
+ filename += QString::number(spec.version());
+ }
+
+ filename += QLatin1String("-");
+ filename += m_ppi;
+
+ filename += QLatin1String(".");
+ filename += format;
+
+ QDir dir = QDir(directory);
+
+ return dir.filePath(filename);
+}
+
+QGeoTileSpec QGeoFileTileCacheNokia::filenameToTileSpec(const QString &filename) const
+{
+ QGeoTileSpec emptySpec;
+
+ QStringList parts = filename.split('.');
+
+ if (parts.length() != 2)
+ return emptySpec;
+
+ QString name = parts.at(0);
+ QStringList fields = name.split('-');
+
+ int length = fields.length();
+ if (length != 6 && length != 7)
+ return emptySpec;
+ else if (fields.last() != m_ppi)
+ return QGeoTileSpec();
+
+ QList<int> numbers;
+
+ bool ok = false;
+ for (int i = 1; i < length-1; ++i) { // skipping -<ppi>
+ ok = false;
+ int value = fields.at(i).toInt(&ok);
+ if (!ok)
+ return emptySpec;
+ numbers.append(value);
+ }
+
+ //File name without version, append default
+ if (numbers.length() < 5)
+ numbers.append(-1);
+
+ return QGeoTileSpec(fields.at(0),
+ numbers.at(0),
+ numbers.at(1),
+ numbers.at(2),
+ numbers.at(3),
+ numbers.at(4));
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia/qgeofiletilecachenokia.h b/src/plugins/geoservices/nokia/qgeofiletilecachenokia.h
new file mode 100644
index 00000000..aba232f5
--- /dev/null
+++ b/src/plugins/geoservices/nokia/qgeofiletilecachenokia.h
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef QGEOFILETILECACHENOKIA_H
+#define QGEOFILETILECACHENOKIA_H
+
+#include <QtLocation/private/qgeofiletilecache_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGeoFileTileCacheNokia : public QGeoFileTileCache
+{
+ Q_OBJECT
+public:
+ QGeoFileTileCacheNokia(int ppi, const QString &directory = QString(), QObject *parent = 0);
+ ~QGeoFileTileCacheNokia();
+
+protected:
+ virtual QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const Q_DECL_OVERRIDE;
+ virtual QGeoTileSpec filenameToTileSpec(const QString &filename) const Q_DECL_OVERRIDE;
+
+ QString m_ppi;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOFILETILECACHENOKIA_H
diff --git a/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp b/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp
index f6d05c36..4deac4ee 100644
--- a/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp
@@ -81,7 +81,11 @@ namespace
token = parameters.value(QStringLiteral("here.token")).toString();
if (isValidParameter(appId) && isValidParameter(token))
- return;
+ return;
+ else if (!isValidParameter(appId))
+ qWarning() << "Invalid here.app_id";
+ else
+ qWarning() << "Invalid here.token";
if (parameters.contains(QStringLiteral("app_id")) || parameters.contains(QStringLiteral("token")))
qWarning() << QStringLiteral("Please prefix 'app_id' and 'token' with prefix 'here' (e.g.: 'here.app_id')");
diff --git a/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp
index d83ad0f9..5179fff4 100644
--- a/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qgeotiledmap_nokia.cpp
@@ -72,13 +72,13 @@ void QGeoTiledMapNokia::evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTile
const QString copyrightsString = m_engine->evaluateCopyrightsText(activeMapType(), cameraData().zoomLevel(), visibleTiles);
- if (width() > 0 && height() > 0 && ((copyrightsString.isNull() && m_copyrightsSlab.isNull()) || copyrightsString != m_lastCopyrightsString)) {
+ if (viewportWidth() > 0 && viewportHeight() > 0 && ((copyrightsString.isNull() && m_copyrightsSlab.isNull()) || copyrightsString != m_lastCopyrightsString)) {
QFont font("Sans Serif");
font.setPixelSize(fontSize);
font.setStyleHint(QFont::SansSerif);
font.setWeight(QFont::Bold);
- QRect textBounds = QFontMetrics(font).boundingRect(0, 0, width(), height(), Qt::AlignBottom | Qt::AlignLeft | Qt::TextWordWrap, copyrightsString);
+ QRect textBounds = QFontMetrics(font).boundingRect(0, 0, viewportWidth(), viewportHeight(), Qt::AlignBottom | Qt::AlignLeft | Qt::TextWordWrap, copyrightsString);
m_copyrightsSlab = QImage(m_logo.width() + textBounds.width() + spaceToLogo + blurRate * 2,
qMax(m_logo.height(), textBounds.height() + blurRate * 2),
diff --git a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp
index 4f44e5fd..6548aa2b 100644
--- a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp
@@ -39,7 +39,7 @@
#include "qgeotiledmap_nokia.h"
#include "qgeotilefetcher_nokia.h"
#include "qgeotilespec_p.h"
-#include "qgeofiletilecache_p.h"
+#include "qgeofiletilecachenokia.h"
#include <QDebug>
#include <QDir>
@@ -95,22 +95,40 @@ QGeoTiledMappingManagerEngineNokia::QGeoTiledMappingManagerEngineNokia(
types << QGeoMapType(QGeoMapType::CarNavigationMap, tr("Car Navigation Map"), tr("Normal map view in daylight mode for car navigation"), false, false, 21);
setSupportedMapTypes(types);
- QGeoTileFetcherNokia *fetcher = new QGeoTileFetcherNokia(parameters, networkManager, this, tileSize());
+ int ppi = 72;
+ if (parameters.contains(QStringLiteral("here.mapping.highdpi_tiles"))) {
+ const QString param = parameters.value(QStringLiteral("here.mapping.highdpi_tiles")).toString().toLower();
+ if (param == "true")
+ ppi = 250;
+ }
+
+ QGeoTileFetcherNokia *fetcher = new QGeoTileFetcherNokia(parameters, networkManager, this, tileSize(), ppi);
setTileFetcher(fetcher);
+ /* TILE CACHE */
// TODO: do this in a plugin-neutral way so that other tiled map plugins
// don't need this boilerplate or hardcode plugin name
-
if (parameters.contains(QStringLiteral("here.mapping.cache.directory"))) {
m_cacheDirectory = parameters.value(QStringLiteral("here.mapping.cache.directory")).toString();
} else {
// managerName() is not yet set, we have to hardcode the plugin name below
- m_cacheDirectory = QAbstractGeoTileCache::baseCacheDirectory() + QLatin1String("here");
+ m_cacheDirectory = QAbstractGeoTileCache::baseLocationCacheDirectory() + QLatin1String("here");
}
- QAbstractGeoTileCache *tileCache = new QGeoFileTileCache(m_cacheDirectory);
- setTileCache(tileCache);
-
+ QGeoFileTileCache *tileCache = new QGeoFileTileCacheNokia(ppi, m_cacheDirectory);
+
+ /*
+ * Disk cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("here.mapping.cache.disk.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("here.mapping.cache.disk.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize);
+ }
if (parameters.contains(QStringLiteral("here.mapping.cache.disk.size"))) {
bool ok = false;
int cacheSize = parameters.value(QStringLiteral("here.mapping.cache.disk.size")).toString().toInt(&ok);
@@ -118,6 +136,18 @@ QGeoTiledMappingManagerEngineNokia::QGeoTiledMappingManagerEngineNokia(
tileCache->setMaxDiskUsage(cacheSize);
}
+ /*
+ * Memory cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("here.mapping.cache.memory.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("here.mapping.cache.memory.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
+ }
if (parameters.contains(QStringLiteral("here.mapping.cache.memory.size"))) {
bool ok = false;
int cacheSize = parameters.value(QStringLiteral("here.mapping.cache.memory.size")).toString().toInt(&ok);
@@ -125,6 +155,18 @@ QGeoTiledMappingManagerEngineNokia::QGeoTiledMappingManagerEngineNokia(
tileCache->setMaxMemoryUsage(cacheSize);
}
+ /*
+ * Texture cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("here.mapping.cache.texture.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("here.mapping.cache.texture.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ }
if (parameters.contains(QStringLiteral("here.mapping.cache.texture.size"))) {
bool ok = false;
int cacheSize = parameters.value(QStringLiteral("here.mapping.cache.texture.size")).toString().toInt(&ok);
@@ -132,6 +174,7 @@ QGeoTiledMappingManagerEngineNokia::QGeoTiledMappingManagerEngineNokia(
tileCache->setExtraTextureUsage(cacheSize);
}
+ setTileCache(tileCache);
populateMapSchemes();
loadMapVersion();
QMetaObject::invokeMethod(fetcher, "fetchCopyrightsData", Qt::QueuedConnection);
diff --git a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp
index 50acc2a0..a55f71c0 100644
--- a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.cpp
@@ -56,11 +56,11 @@ QT_BEGIN_NAMESPACE
namespace
{
- QString sizeToStr(const QSize &size)
+ QString sizeToStr(int size)
{
- if (size.height() >= 512 || size.width() >= 512)
+ if (size > 256)
return QStringLiteral("512");
- else if (size.height() >= 256 || size.width() >= 256)
+ else if (size > 128)
return QStringLiteral("256");
else
return QStringLiteral("128"); // 128 pixel tiles are deprecated.
@@ -74,13 +74,14 @@ namespace
QGeoTileFetcherNokia::QGeoTileFetcherNokia(const QVariantMap &parameters,
QGeoNetworkAccessManager *networkManager,
QGeoTiledMappingManagerEngineNokia *engine,
- const QSize &tileSize)
-: QGeoTileFetcher(engine), m_engineNokia(engine), m_networkManager(networkManager),
- m_tileSize(tileSize), m_copyrightsReply(0),
+ const QSize &tileSize,
+ int ppi)
+: QGeoTileFetcher(engine), m_engineNokia(engine), m_networkManager(networkManager), m_ppi(ppi), m_copyrightsReply(0),
m_baseUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.mapping.host"), MAP_TILES_HOST)),
m_aerialUriProvider(new QGeoUriProvider(this, parameters, QStringLiteral("here.mapping.host.aerial"), MAP_TILES_HOST_AERIAL))
{
Q_ASSERT(networkManager);
+ m_tileSize = qMax(tileSize.width(), tileSize.height());
m_networkManager->setParent(this);
m_applicationId = parameters.value(QStringLiteral("here.app_id")).toString();
@@ -94,7 +95,11 @@ QGeoTileFetcherNokia::~QGeoTileFetcherNokia()
QGeoTiledMapReply *QGeoTileFetcherNokia::getTileImage(const QGeoTileSpec &spec)
{
// TODO add error detection for if request.connectivityMode() != QGraphicsGeoMap::OnlineMode
- QString rawRequest = getRequestString(spec);
+ int ppi = m_ppi;
+ if ((spec.mapId() == 2) || (spec.mapId() == 12) || (spec.mapId() == 21))
+ ppi = 72; // HiDpi apparently not supported for these maps
+
+ QString rawRequest = getRequestString(spec, ppi);
if (rawRequest.isEmpty()) {
return new QGeoTiledMapReply(QGeoTiledMapReply::UnknownError,
tr("Mapping manager no longer exists"), this);
@@ -110,7 +115,7 @@ QGeoTiledMapReply *QGeoTileFetcherNokia::getTileImage(const QGeoTileSpec &spec)
return mapReply;
}
-QString QGeoTileFetcherNokia::getRequestString(const QGeoTileSpec &spec)
+QString QGeoTileFetcherNokia::getRequestString(const QGeoTileSpec &spec, int ppi)
{
if (!m_engineNokia)
return QString();
@@ -136,11 +141,11 @@ QString QGeoTileFetcherNokia::getRequestString(const QGeoTileSpec &spec)
requestString += slash;
requestString += QString::number(spec.y());
requestString += slash;
- requestString += sizeToStr(m_tileSize);
+ requestString += ((ppi > 72)) ? sizeToStr(m_tileSize * 2) : sizeToStr(m_tileSize);
static const QString slashpng("/png8");
requestString += slashpng;
- if (!m_token.isEmpty() && !m_applicationId.isEmpty()) {
+ if (!m_token.isEmpty() && !m_applicationId.isEmpty()) { // TODO: remove the if
requestString += "?token=";
requestString += m_token;
@@ -148,9 +153,10 @@ QString QGeoTileFetcherNokia::getRequestString(const QGeoTileSpec &spec)
requestString += m_applicationId;
}
+ requestString += "&ppi=" + QString::number(ppi);
+
requestString += "&lg=";
requestString += getLanguageString();
-
return requestString;
}
diff --git a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h
index 44f2ad07..06d1bba9 100644
--- a/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h
+++ b/src/plugins/geoservices/nokia/qgeotilefetcher_nokia.h
@@ -57,7 +57,7 @@ class QGeoTileFetcherNokia : public QGeoTileFetcher
public:
QGeoTileFetcherNokia(const QVariantMap &parameters, QGeoNetworkAccessManager *networkManager,
- QGeoTiledMappingManagerEngineNokia *engine, const QSize &tileSize);
+ QGeoTiledMappingManagerEngineNokia *engine, const QSize &tileSize, int ppi);
~QGeoTileFetcherNokia();
QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec);
@@ -74,13 +74,14 @@ public Q_SLOTS:
private:
Q_DISABLE_COPY(QGeoTileFetcherNokia)
- QString getRequestString(const QGeoTileSpec &spec);
+ QString getRequestString(const QGeoTileSpec &spec, int ppi=72);
QString getLanguageString() const;
QPointer<QGeoTiledMappingManagerEngineNokia> m_engineNokia;
QGeoNetworkAccessManager *m_networkManager;
- QSize m_tileSize;
+ int m_tileSize;
+ int m_ppi;
QString m_token;
QNetworkReply *m_copyrightsReply;
QNetworkReply *m_versionReply;
diff --git a/src/plugins/geoservices/nokia/qgeouriprovider.cpp b/src/plugins/geoservices/nokia/qgeouriprovider.cpp
index 05ace120..80b47f31 100644
--- a/src/plugins/geoservices/nokia/qgeouriprovider.cpp
+++ b/src/plugins/geoservices/nokia/qgeouriprovider.cpp
@@ -35,10 +35,6 @@
****************************************************************************/
#include "qgeouriprovider.h"
-#ifdef USE_CHINA_NETWORK_REGISTRATION
-#include <QNetworkInfo>
-#endif
-
#include <QMap>
#include <QVariant>
#include <QSet>
@@ -46,14 +42,6 @@
QT_BEGIN_NAMESPACE
-namespace
-{
- const QString CHINA_MCC = QLatin1String("460"); // China mobile country code
- const QString CHINA2_MCC = QLatin1String("461"); // China mobile country code
- const QString HONG_KONG_MCC = QLatin1String("454"); // Hong Kong mobile country code
- const QString MACAU_MCC = QLatin1String("455"); // Macau mobile country code
-}
-
QGeoUriProvider::QGeoUriProvider(
QObject *parent,
const QVariantMap &parameters,
@@ -61,17 +49,11 @@ QGeoUriProvider::QGeoUriProvider(
const QString &internationalHost,
const QString &localizedHost)
: QObject(parent)
-#ifdef USE_CHINA_NETWORK_REGISTRATION
- , m_networkInfo(new QNetworkInfo(this))
-#endif
, m_internationalHost(parameters.value(hostParameterName, internationalHost).toString())
, m_localizedHost(localizedHost)
, m_firstSubdomain(QChar::Null)
, m_maxSubdomains(0)
{
-#ifdef USE_CHINA_NETWORK_REGISTRATION
- QObject::connect(m_networkInfo, SIGNAL(currentMobileCountryCodeChanged(int,QString)), this, SLOT(mobileCountryCodeChanged(int,QString)));
-#endif
setCurrentHost(isInternationalNetwork() || m_localizedHost.isEmpty() ? m_internationalHost : m_localizedHost);
}
@@ -109,26 +91,7 @@ void QGeoUriProvider::mobileCountryCodeChanged(int interface, const QString& mcc
bool QGeoUriProvider::isInternationalNetwork() const
{
-#ifndef USE_CHINA_NETWORK_REGISTRATION
- return true;
-#else
- static QSet<QString> codes;
- if (codes.empty()) {
- codes.insert(CHINA_MCC);
- codes.insert(CHINA2_MCC);
- }
-
- QNetworkInfo::NetworkMode mode = m_networkInfo->currentNetworkMode();
-
- int interfaces = m_networkInfo->networkInterfaceCount(mode);
- for (int i = 0; i < interfaces; ++i) {
- QString mcc = m_networkInfo->currentMobileCountryCode(interfaces);
- if (codes.contains(mcc))
- return false;
- }
-
return true;
-#endif // USE_CHINA_NETWORK_REGISTRATION
}
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia/qgeouriprovider.h b/src/plugins/geoservices/nokia/qgeouriprovider.h
index 1bd30b52..e8d93a0f 100644
--- a/src/plugins/geoservices/nokia/qgeouriprovider.h
+++ b/src/plugins/geoservices/nokia/qgeouriprovider.h
@@ -64,9 +64,6 @@ private:
bool isInternationalNetwork() const;
void setCurrentHost(const QString &host);
-#ifdef USE_CHINA_NETWORK_REGISTRATION
- QNetworkInfo *m_networkInfo;
-#endif
const QString m_internationalHost;
const QString m_localizedHost;
QString m_currentHost;
diff --git a/src/plugins/geoservices/osm/osm.pro b/src/plugins/geoservices/osm/osm.pro
index 56f4cb33..86a62744 100644
--- a/src/plugins/geoservices/osm/osm.pro
+++ b/src/plugins/geoservices/osm/osm.pro
@@ -1,6 +1,6 @@
TARGET = qtgeoservices_osm
-QT += location-private positioning-private network
+QT += location-private positioning-private network concurrent
HEADERS += \
qgeoserviceproviderpluginosm.h \
@@ -15,6 +15,7 @@ HEADERS += \
qplacesearchreplyosm.h \
qplacecategoriesreplyosm.h \
qgeotiledmaposm.h \
+ qgeofiletilecacheosm.h \
qgeotileproviderosm.h
SOURCES += \
@@ -30,6 +31,7 @@ SOURCES += \
qplacesearchreplyosm.cpp \
qplacecategoriesreplyosm.cpp \
qgeotiledmaposm.cpp \
+ qgeofiletilecacheosm.cpp \
qgeotileproviderosm.cpp
diff --git a/src/plugins/geoservices/osm/providers/5.8/cycle b/src/plugins/geoservices/osm/providers/5.8/cycle
new file mode 100644
index 00000000..5e37aab2
--- /dev/null
+++ b/src/plugins/geoservices/osm/providers/5.8/cycle
@@ -0,0 +1,8 @@
+{
+ "UrlTemplate" : "http://a.tile.thunderforest.com/cycle/%z/%x/%y.png",
+ "ImageFormat" : "png",
+ "QImageFormat" : "Indexed8",
+ "ID" : "thf-cycle",
+ "MapCopyRight" : "<a href='http://www.thunderforest.com/'>Thunderforest</a>",
+ "DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
+}
diff --git a/src/plugins/geoservices/osm/providers/5.8/hiking b/src/plugins/geoservices/osm/providers/5.8/hiking
new file mode 100644
index 00000000..1bb182e4
--- /dev/null
+++ b/src/plugins/geoservices/osm/providers/5.8/hiking
@@ -0,0 +1,9 @@
+{
+ "UrlTemplate" : "http://b.tiles.wmflabs.org/hikebike/%z/%x/%y.png",
+ "ImageFormat" : "png",
+ "QImageFormat" : "Indexed8",
+ "ID" : "wmf-hike",
+ "MaximumZoomLevel" : 18,
+ "MapCopyRight" : "<a href='https://wikimediafoundation.org/wiki/Terms_of_Use'>WikiMedia Foundation</a>",
+ "DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
+}
diff --git a/src/plugins/geoservices/osm/providers/5.8/night-transit b/src/plugins/geoservices/osm/providers/5.8/night-transit
new file mode 100644
index 00000000..988a096a
--- /dev/null
+++ b/src/plugins/geoservices/osm/providers/5.8/night-transit
@@ -0,0 +1,9 @@
+{
+ "UrlTemplate" : "http://a.tile.thunderforest.com/transport-dark/%z/%x/%y.png",
+ "ImageFormat" : "png",
+ "QImageFormat" : "Indexed8",
+ "ID" : "thf-nighttransit",
+ "MaximumZoomLevel" : 19,
+ "MapCopyRight" : "<a href='http://www.thunderforest.com/'>Thunderforest</a>",
+ "DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
+}
diff --git a/src/plugins/geoservices/osm/providers/5.8/satellite b/src/plugins/geoservices/osm/providers/5.8/satellite
new file mode 100644
index 00000000..5c48a077
--- /dev/null
+++ b/src/plugins/geoservices/osm/providers/5.8/satellite
@@ -0,0 +1,10 @@
+{
+ "Enabled" : false,
+ "UrlTemplate" : "http://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer/tile/%z/%y/%x",
+ "ImageFormat" : "jpg",
+ "QImageFormat" : "RGB888",
+ "ID" : "usgs-l7",
+ "MaximumZoomLevel" : 8,
+ "MapCopyRight" : "<a href='http://basemap.nationalmap.gov/arcgis/rest/services/USGSImageryOnly/MapServer'>USGS The National Map: Orthoimagery</a>",
+ "DataCopyRight" : "<a href='http://landsat.gsfc.nasa.gov/?page_id=2339'>USGS/NASA Landsat</a>"
+}
diff --git a/src/plugins/geoservices/osm/providers/5.8/street b/src/plugins/geoservices/osm/providers/5.8/street
new file mode 100644
index 00000000..b3bccf1d
--- /dev/null
+++ b/src/plugins/geoservices/osm/providers/5.8/street
@@ -0,0 +1,10 @@
+{
+ "UrlTemplate" : "http://korona.geog.uni-heidelberg.de/tiles/roads/x=%x&y=%y&z=%z",
+ "ImageFormat" : "jpg",
+ "QImageFormat" : "Indexed8",
+ "ID" : "oms-street",
+ "MaximumZoomLevel" : 20,
+ "MapCopyRight" : "<a href='http://giscience.uni-hd.de/'>GIScience Research Group @ University of Heidelberg</a>",
+ "StyleCopyRight" : "<a href='http://www.geog.uni-heidelberg.de/personen/gis_rylov.html'>Maxim Rylov</a>",
+ "DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
+}
diff --git a/src/plugins/geoservices/osm/providers/5.8/street-hires b/src/plugins/geoservices/osm/providers/5.8/street-hires
new file mode 100644
index 00000000..9819f619
--- /dev/null
+++ b/src/plugins/geoservices/osm/providers/5.8/street-hires
@@ -0,0 +1,9 @@
+{
+ "UrlTemplate" : "https://maps.wikimedia.org/osm-intl/%z/%x/%y@2x.png",
+ "ImageFormat" : "png",
+ "QImageFormat" : "Indexed8",
+ "MaximumZoomLevel" : 18,
+ "ID" : "wmf-intl-2x",
+ "MapCopyRight" : "<a href='https://wikimediafoundation.org/wiki/Terms_of_Use'>WikiMedia Foundation</a>",
+ "DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
+}
diff --git a/src/plugins/geoservices/osm/providers/5.8/terrain b/src/plugins/geoservices/osm/providers/5.8/terrain
new file mode 100644
index 00000000..7fc6636c
--- /dev/null
+++ b/src/plugins/geoservices/osm/providers/5.8/terrain
@@ -0,0 +1,9 @@
+{
+ "UrlTemplate" : "http://a.tile.thunderforest.com/landscape/%z/%x/%y.png",
+ "ImageFormat" : "png",
+ "QImageFormat" : "Indexed8",
+ "ID" : "thf-landsc",
+ "MaximumZoomLevel" : 19,
+ "MapCopyRight" : "<a href='http://www.thunderforest.com/'>Thunderforest</a>",
+ "DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
+}
diff --git a/src/plugins/geoservices/osm/providers/5.8/transit b/src/plugins/geoservices/osm/providers/5.8/transit
new file mode 100644
index 00000000..ebf87b05
--- /dev/null
+++ b/src/plugins/geoservices/osm/providers/5.8/transit
@@ -0,0 +1,9 @@
+{
+ "UrlTemplate" : "http://a.tile.thunderforest.com/transport/%z/%x/%y.png",
+ "ImageFormat" : "png",
+ "QImageFormat" : "Indexed8",
+ "ID" : "thf-transit",
+ "MaximumZoomLevel" : 19,
+ "MapCopyRight" : "<a href='http://www.thunderforest.com/'>Thunderforest</a>",
+ "DataCopyRight" : "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
+}
diff --git a/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp b/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp
new file mode 100644
index 00000000..a563cced
--- /dev/null
+++ b/src/plugins/geoservices/osm/qgeofiletilecacheosm.cpp
@@ -0,0 +1,360 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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 "qgeofiletilecacheosm.h"
+#include <QtLocation/private/qgeotilespec_p.h>
+#include <QDir>
+#include <QDirIterator>
+#include <QPair>
+#include <QDateTime>
+#include <QtConcurrent>
+#include <QThread>
+
+QT_BEGIN_NAMESPACE
+
+QGeoFileTileCacheOsm::QGeoFileTileCacheOsm(const QVector<QGeoTileProviderOsm *> &providers,
+ const QString &offlineDirectory,
+ const QString &directory,
+ QObject *parent)
+: QGeoFileTileCache(directory, parent), m_offlineDirectory(offlineDirectory), m_requestCancel(0), m_providers(providers)
+{
+ m_highDpi.resize(providers.size());
+ for (int i = 0; i < providers.size(); i++) {
+ m_highDpi[i] = providers[i]->isHighDpi();
+ m_mapIdFutures[providers[i]->mapType().mapId()].isFinished(); // To construct a default future for this mapId
+ connect(providers[i], &QGeoTileProviderOsm::resolutionFinished, this, &QGeoFileTileCacheOsm::onProviderResolutionFinished);
+ connect(providers[i], &QGeoTileProviderOsm::resolutionError, this, &QGeoFileTileCacheOsm::onProviderResolutionFinished);
+ }
+}
+
+QGeoFileTileCacheOsm::~QGeoFileTileCacheOsm()
+{
+ m_requestCancel = 1;
+ m_future.waitForFinished();
+ for (const QGeoTileProviderOsm *p : m_providers)
+ m_mapIdFutures[p->mapType().mapId()].waitForFinished();
+}
+
+QSharedPointer<QGeoTileTexture> QGeoFileTileCacheOsm::get(const QGeoTileSpec &spec)
+{
+ QSharedPointer<QGeoTileTexture> tt = getFromMemory(spec);
+ if (tt)
+ return tt;
+ if ((tt = getFromOfflineStorage(spec)))
+ return tt;
+ return getFromDisk(spec);
+}
+
+void QGeoFileTileCacheOsm::onProviderResolutionFinished(const QGeoTileProviderOsm *provider)
+{
+ clearObsoleteTiles(provider);
+ Q_UNUSED(provider)
+ for (int i = 0; i < m_providers.size(); i++) {
+ if (m_providers[i]->isHighDpi() != m_highDpi[i]) { // e.g., HiDpi was requested but only LoDpi is available
+ int mapId = m_providers[i]->mapType().mapId();
+ m_highDpi[i] = m_providers[i]->isHighDpi();
+
+ // reload cache for mapId i
+ dropTiles(mapId);
+ loadTiles(mapId);
+
+ // reload offline registry for mapId i
+ m_mapIdFutures[mapId] = QtConcurrent::run(this, &QGeoFileTileCacheOsm::initOfflineRegistry, mapId);
+
+ // send signal to clear scene in all maps created through this provider that use the reloaded tiles
+ emit mapDataUpdated(mapId);
+ }
+ }
+}
+
+// On resolution error the provider is removed ONLY if there is no enabled hardcoded fallback.
+// Hardcoded fallbacks also have a timestamp, that can get updated with Qt releases.
+void QGeoFileTileCacheOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error)
+{
+ Q_UNUSED(error)
+ clearObsoleteTiles(provider); // this still removes tiles who happen to be older than qgeotileproviderosm.cpp defaultTs
+}
+
+void QGeoFileTileCacheOsm::init()
+{
+ if (directory_.isEmpty())
+ directory_ = baseLocationCacheDirectory();
+ QDir::root().mkpath(directory_);
+
+ // find max mapId
+ int max = 0;
+ for (auto p: m_providers)
+ if (p->mapType().mapId() > max)
+ max = p->mapType().mapId();
+ // Create a mapId to maxTimestamp LUT..
+ m_maxMapIdTimestamps.resize(max+1); // initializes to invalid QDateTime
+
+ // .. by finding the newest file in each tileset (tileset = mapId).
+ QDir dir(directory_);
+ QStringList formats;
+ formats << QLatin1String("*.*");
+ QStringList files = dir.entryList(formats, QDir::Files);
+
+ for (const QString &tileFileName : files) {
+ QGeoTileSpec spec = filenameToTileSpec(tileFileName);
+ if (spec.zoom() == -1)
+ continue;
+ QFileInfo fi(dir.filePath(tileFileName));
+ if (fi.lastModified() > m_maxMapIdTimestamps[spec.mapId()])
+ m_maxMapIdTimestamps[spec.mapId()] = fi.lastModified();
+ }
+
+ // Base class ::init()
+ QGeoFileTileCache::init();
+
+ for (QGeoTileProviderOsm * p: m_providers)
+ clearObsoleteTiles(p);
+
+ if (!m_offlineDirectory.isEmpty())
+ m_future = QtConcurrent::run(this, &QGeoFileTileCacheOsm::initOfflineRegistry, -1);
+}
+
+QSharedPointer<QGeoTileTexture> QGeoFileTileCacheOsm::getFromOfflineStorage(const QGeoTileSpec &spec)
+{
+ QMutexLocker locker(&storageLock);
+ if (m_tilespecToOfflineFilepath.contains(spec)) {
+ QFile file(m_tilespecToOfflineFilepath[spec]);
+ file.open(QIODevice::ReadOnly);
+ QByteArray bytes = file.readAll();
+ file.close();
+ locker.unlock();
+
+ QImage image;
+ if (!image.loadFromData(bytes)) {
+ handleError(spec, QLatin1String("Problem with tile image"));
+ return QSharedPointer<QGeoTileTexture>(0);
+ }
+
+ addToMemoryCache(spec, bytes, QString());
+ QSharedPointer<QGeoTileTexture> tt = addToTextureCache(spec, image);
+ if (tt)
+ return tt;
+ }
+
+ return QSharedPointer<QGeoTileTexture>();
+}
+
+void QGeoFileTileCacheOsm::dropTiles(int mapId)
+{
+ QList<QGeoTileSpec> keys;
+ keys = textureCache_.keys();
+ for (const QGeoTileSpec &k : keys)
+ if (k.mapId() == mapId)
+ textureCache_.remove(k);
+
+ keys = memoryCache_.keys();
+ for (const QGeoTileSpec &k : keys)
+ if (k.mapId() == mapId)
+ memoryCache_.remove(k);
+
+ keys = diskCache_.keys();
+ for (const QGeoTileSpec &k : keys)
+ if (k.mapId() == mapId)
+ diskCache_.remove(k);
+}
+
+void QGeoFileTileCacheOsm::loadTiles(int mapId)
+{
+ QStringList formats;
+ formats << QLatin1String("*.*");
+
+ QDir dir(directory_);
+ QStringList files = dir.entryList(formats, QDir::Files);
+
+ for (int i = 0; i < files.size(); ++i) {
+ QGeoTileSpec spec = filenameToTileSpec(files.at(i));
+ if (spec.zoom() == -1 || spec.mapId() != mapId)
+ continue;
+ QString filename = dir.filePath(files.at(i));
+ addToDiskCache(spec, filename);
+ }
+}
+
+void QGeoFileTileCacheOsm::initOfflineRegistry(int mapId)
+{
+ // Dealing with duplicates: picking the newest
+ QMap<QString, QPair<QString, QDateTime> > fileDates; // key is filename, value is <filepath, lastmodified>
+ QDirIterator it(m_offlineDirectory, QStringList() << "*.*", QDir::Files, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks );
+ while (it.hasNext()) {
+ const QString &path = it.next();
+ QFileInfo f(path);
+ if (!fileDates.contains(f.fileName()) || fileDates[f.fileName()].second < f.lastModified())
+ fileDates[f.fileName()] = QPair<QString, QDateTime>(f.filePath(), f.lastModified());
+ if (m_requestCancel)
+ return;
+ }
+
+ // Clear the content of the index. Entirely (at startup), or selectively (when a provider resolution changes the highDpi status).
+ if (mapId < 0) {
+ storageLock.lock();
+ m_tilespecToOfflineFilepath.clear();
+ storageLock.unlock();
+ } else {
+ QList<QGeoTileSpec> toRemove;
+ for (auto i = m_tilespecToOfflineFilepath.constBegin(); i != m_tilespecToOfflineFilepath.constEnd(); ++i) {
+ if (i.key().mapId() == mapId)
+ toRemove.append(i.key());
+ }
+ storageLock.lock();
+ for (const auto &i : toRemove)
+ m_tilespecToOfflineFilepath.remove(i);
+ storageLock.unlock();
+ }
+ if (m_requestCancel)
+ return;
+
+ // Fill the index entirely or selectively
+ int count = 0;
+ for (auto i= fileDates.constBegin(); i != fileDates.constEnd(); ++i) {
+ QGeoTileSpec spec = filenameToTileSpec(i.key());
+ if (spec.zoom() == -1)
+ continue;
+ if (mapId >= 0 && spec.mapId() != mapId) // if mapId != -1, pick up only those files with that mapId.
+ continue;
+ count++;
+ storageLock.lock();
+ m_tilespecToOfflineFilepath[spec] = i.value().first;
+ storageLock.unlock();
+ if (m_requestCancel)
+ return;
+ }
+ //qInfo() << "OSM plugin has found and is using "<< count <<" offline tiles";
+}
+
+QString QGeoFileTileCacheOsm::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const
+{
+ int providerId = spec.mapId() - 1;
+ if (providerId < 0 || providerId >= m_providers.size())
+ return QString();
+ QString filename = spec.plugin();
+ filename += QLatin1String("-");
+ filename += (m_providers[providerId]->isHighDpi()) ? QLatin1Char('h') : QLatin1Char('l');
+ filename += QLatin1String("-");
+ filename += QString::number(spec.mapId());
+ filename += QLatin1String("-");
+ filename += QString::number(spec.zoom());
+ filename += QLatin1String("-");
+ filename += QString::number(spec.x());
+ filename += QLatin1String("-");
+ filename += QString::number(spec.y());
+
+ //Append version if real version number to ensure backwards compatibility and eviction of old tiles
+ if (spec.version() != -1) {
+ filename += QLatin1String("-");
+ filename += QString::number(spec.version());
+ }
+
+ filename += QLatin1String(".");
+ filename += format;
+
+ QDir dir = QDir(directory);
+
+ return dir.filePath(filename);
+}
+
+QGeoTileSpec QGeoFileTileCacheOsm::filenameToTileSpec(const QString &filename) const
+{
+ QGeoTileSpec emptySpec;
+
+ QStringList parts = filename.split('.');
+
+ if (parts.length() != 2)
+ return emptySpec;
+
+ QString name = parts.at(0);
+ QStringList fields = name.split('-');
+
+ int length = fields.length();
+ if (length != 6 && length != 7)
+ return emptySpec;
+
+ QList<int> numbers;
+
+ bool ok = false;
+ for (int i = 2; i < length; ++i) {
+ ok = false;
+ int value = fields.at(i).toInt(&ok);
+ if (!ok)
+ return emptySpec;
+ numbers.append(value);
+ }
+
+ bool highDpi = m_providers[numbers.at(0) - 1]->isHighDpi();
+ if (highDpi && fields.at(1) != QLatin1Char('h'))
+ return emptySpec;
+ else if (!highDpi && fields.at(1) != QLatin1Char('l'))
+ return emptySpec;
+
+ //File name without version, append default
+ if (numbers.length() < 5)
+ numbers.append(-1);
+
+ return QGeoTileSpec(fields.at(0),
+ numbers.at(0),
+ numbers.at(1),
+ numbers.at(2),
+ numbers.at(3),
+ numbers.at(4));
+}
+
+void QGeoFileTileCacheOsm::clearObsoleteTiles(const QGeoTileProviderOsm *p)
+{
+ // process initialized providers, and connect the others
+
+ if (p->isResolved()) {
+ if (m_maxMapIdTimestamps[p->mapType().mapId()].isValid() && // there are tiles in the cache
+ p->timestamp() > m_maxMapIdTimestamps[p->mapType().mapId()]) { // and they are older than the provider
+ qInfo() << "provider for " << p->mapType().name() << " timestamp: " << p->timestamp()
+ << " -- data last modified: " << m_maxMapIdTimestamps[p->mapType().mapId()] << ". Clearing.";
+ clearMapId(p->mapType().mapId());
+ m_maxMapIdTimestamps[p->mapType().mapId()] = p->timestamp(); // don't do it again.
+ }
+ } else {
+ connect(p, &QGeoTileProviderOsm::resolutionFinished,
+ this, &QGeoFileTileCacheOsm::onProviderResolutionFinished);
+#if 0 // If resolution fails, better not try to remove anything. Beside, on error, resolutionFinished is also emitted.
+ connect(p, &QGeoTileProviderOsm::resolutionError,
+ this, &QGeoFileTileCacheOsm::onProviderResolutionError);
+#endif
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/osm/qgeofiletilecacheosm.h b/src/plugins/geoservices/osm/qgeofiletilecacheosm.h
new file mode 100644
index 00000000..d26cad4a
--- /dev/null
+++ b/src/plugins/geoservices/osm/qgeofiletilecacheosm.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+#ifndef QGEOFILETILECACHEOSM_H
+#define QGEOFILETILECACHEOSM_H
+
+#include "qgeotileproviderosm.h"
+#include <QtLocation/private/qgeofiletilecache_p.h>
+#include <QHash>
+#include <QtConcurrent>
+#include <qatomic.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGeoFileTileCacheOsm : public QGeoFileTileCache
+{
+ Q_OBJECT
+public:
+ QGeoFileTileCacheOsm(const QVector<QGeoTileProviderOsm *> &providers,
+ const QString &offlineDirectory = QString(),
+ const QString &directory = QString(),
+ QObject *parent = 0);
+ ~QGeoFileTileCacheOsm();
+
+ QSharedPointer<QGeoTileTexture> get(const QGeoTileSpec &spec) Q_DECL_OVERRIDE;
+
+Q_SIGNALS:
+ void mapDataUpdated(int mapId);
+
+protected Q_SLOTS:
+ void onProviderResolutionFinished(const QGeoTileProviderOsm *provider);
+ void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error);
+
+protected:
+ void init() Q_DECL_OVERRIDE;
+ QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const Q_DECL_OVERRIDE;
+ QGeoTileSpec filenameToTileSpec(const QString &filename) const Q_DECL_OVERRIDE;
+ QSharedPointer<QGeoTileTexture> getFromOfflineStorage(const QGeoTileSpec &spec);
+ void dropTiles(int mapId);
+ void loadTiles(int mapId);
+
+ void initOfflineRegistry(int mapId = -1);
+ void clearObsoleteTiles(const QGeoTileProviderOsm *p);
+
+ QString m_offlineDirectory;
+ QHash<QGeoTileSpec, QString> m_tilespecToOfflineFilepath;
+ QAtomicInt m_requestCancel;
+ QFuture<void> m_future;
+ QMap<int, QFuture<void>> m_mapIdFutures;
+ QMutex storageLock;
+ QVector<QGeoTileProviderOsm *> m_providers;
+ QVector<bool> m_highDpi;
+ QVector<QDateTime> m_maxMapIdTimestamps;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOFILETILECACHEOSM_H
diff --git a/src/plugins/geoservices/osm/qgeotiledmaposm.cpp b/src/plugins/geoservices/osm/qgeotiledmaposm.cpp
index f16e602a..d94a40a6 100644
--- a/src/plugins/geoservices/osm/qgeotiledmaposm.cpp
+++ b/src/plugins/geoservices/osm/qgeotiledmaposm.cpp
@@ -71,10 +71,13 @@ void QGeoTiledMapOsm::evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles)
return;
int providerId = tile.mapId() - 1;
- if (providerId < 0 || providerId >= m_engine->providers().size() || !m_engine->providers().at(providerId)->isValid())
+ if (providerId < 0 || providerId >= m_engine->providers().size())
return;
m_mapId = tile.mapId();
+ if (!m_engine->providers().at(providerId)->isValid())
+ return;
+
onProviderDataUpdated(m_engine->providers().at(providerId));
}
diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
index fba177f4..ff79c261 100644
--- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
+++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp
@@ -40,7 +40,7 @@
#include "qgeotiledmappingmanagerengineosm.h"
#include "qgeotilefetcherosm.h"
#include "qgeotiledmaposm.h"
-#include "qgeotileproviderosm.h"
+#include "qgeofiletilecacheosm.h"
#include <QtLocation/private/qgeocameracapabilities_p.h>
#include <QtLocation/private/qgeomaptype_p.h>
@@ -62,77 +62,120 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian
setTileSize(QSize(256, 256));
QNetworkAccessManager *nm = new QNetworkAccessManager();
- QString domain = QStringLiteral("http://maps-redirect.qt.io/osm/5.6/");
+ QString domain = QStringLiteral("http://maps-redirect.qt.io/osm/5.8/");
if (parameters.contains(QStringLiteral("osm.mapping.providersrepository.address"))) {
QString customAddress = parameters.value(QStringLiteral("osm.mapping.providersrepository.address")).toString();
- // Allowing some malformed addresses ( containing the suffix "/osm/5.6/"
+ // Allowing some malformed addresses
if (customAddress.indexOf(QStringLiteral(":")) < 0) // defaulting to http:// if no prefix is found
customAddress = QStringLiteral("http://") + customAddress;
if (customAddress[customAddress.length()-1] != QLatin1Char('/'))
customAddress += QLatin1Char('/');
- domain = customAddress;
+ if (QUrl(customAddress).isValid())
+ domain = customAddress;
+ else
+ qWarning() << "Invalid custom providers repository address: " << customAddress;
}
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "street",
- nm,
+ bool highdpi = false;
+ if (parameters.contains(QStringLiteral("osm.mapping.highdpi_tiles"))) {
+ const QString param = parameters.value(QStringLiteral("osm.mapping.highdpi_tiles")).toString().toLower();
+ if (param == "true")
+ highdpi = true;
+ }
+
+ /* TileProviders setup */
+ QVector<TileProvider *> providers_street;
+ QVector<TileProvider *> providers_satellite;
+ QVector<TileProvider *> providers_cycle;
+ QVector<TileProvider *> providers_transit;
+ QVector<TileProvider *> providers_nighttransit;
+ QVector<TileProvider *> providers_terrain;
+ QVector<TileProvider *> providers_hiking;
+ if (highdpi) {
+ providers_street.push_back(new TileProvider(domain + "street-hires", true));
+ providers_satellite.push_back(new TileProvider(domain + "satellite-hires", true));
+ providers_cycle.push_back(new TileProvider(domain + "cycle-hires", true));
+ providers_transit.push_back(new TileProvider(domain + "transit-hires", true));
+ providers_nighttransit.push_back(new TileProvider(domain + "night-transit-hires", true));
+ providers_terrain.push_back(new TileProvider(domain + "terrain-hires", true));
+ providers_hiking.push_back(new TileProvider(domain + "hiking-hires", true));
+ }
+ providers_street.push_back(new TileProvider(domain + "street"));
+ providers_satellite.push_back(new TileProvider(domain + "satellite"));
+ providers_cycle.push_back(new TileProvider(domain + "cycle"));
+ providers_transit.push_back(new TileProvider(domain + "transit"));
+ providers_nighttransit.push_back(new TileProvider(domain + "night-transit"));
+ providers_terrain.push_back(new TileProvider(domain + "terrain"));
+ providers_hiking.push_back(new TileProvider(domain + "hiking"));
+ // Backups
+ const QDateTime defaultTs = QDateTime::fromString(QStringLiteral("2016-06-01T00:00:00"), Qt::ISODate);
+ providers_street.push_back(
+ new TileProvider(QStringLiteral("http://c.tile.openstreetmap.org/%z/%x/%y.png"),
+ QStringLiteral("png"),
+ QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap.org</a>"),
+ QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
+ providers_street.back()->setTimestamp(defaultTs);
+
+ // No available open access satellite backup with satisfactory level of details at the present.
+
+ providers_cycle.push_back(
+ new TileProvider(QStringLiteral("http://c.tile.opencyclemap.org/cycle/%z/%x/%y.png"),
+ QStringLiteral("png"),
+ QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
+ QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
+ providers_cycle.back()->setTimestamp(defaultTs);
+
+ providers_transit.push_back(
+ new TileProvider(QStringLiteral("http://c.tile2.opencyclemap.org/transport/%z/%x/%y.png"),
+ QStringLiteral("png"),
+ QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
+ QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
+ providers_transit.back()->setTimestamp(defaultTs);
+
+ providers_nighttransit.push_back(
+ new TileProvider(QStringLiteral("http://a.tile.thunderforest.com/transport-dark/%z/%x/%y.png"),
+ QStringLiteral("png"),
+ QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
+ QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")) );
+ providers_nighttransit.back()->setTimestamp(defaultTs);
+
+ providers_terrain.push_back(
+ new TileProvider(QStringLiteral("http://a.tile.thunderforest.com/landscape/%z/%x/%y.png"),
+ QStringLiteral("png"),
+ QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
+ QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
+ providers_terrain.back()->setTimestamp(defaultTs);
+
+ providers_hiking.push_back(
+ new TileProvider(QStringLiteral("http://a.tile.thunderforest.com/outdoors/%z/%x/%y.png"),
+ QStringLiteral("png"),
+ QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
+ QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")));
+ providers_hiking.back()->setTimestamp(defaultTs);
+
+
+ /* QGeoTileProviderOsms setup */
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::StreetMap, tr("Street Map"), tr("Street map view in daylight mode"), false, false, 1),
- QGeoTileProviderOsm::TileProvider(QStringLiteral("http://c.tile.openstreetmap.org/%z/%x/%y.png"),
- QStringLiteral("png"),
- QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap.org</a>"),
- QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "satellite",
- nm,
+ providers_street ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::SatelliteMapDay, tr("Satellite Map"), tr("Satellite map view in daylight mode"), false, false, 2),
- QGeoTileProviderOsm::TileProvider()
- ));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "cycle",
- nm,
+ providers_satellite ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::CycleMap, tr("Cycle Map"), tr("Cycle map view in daylight mode"), false, false, 3),
- QGeoTileProviderOsm::TileProvider(QStringLiteral("http://c.tile.opencyclemap.org/cycle/%z/%x/%y.png"),
- QStringLiteral("png"),
- QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
- QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "transit",
- nm,
+ providers_cycle ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::TransitMap, tr("Transit Map"), tr("Public transit map view in daylight mode"), false, false, 4),
- QGeoTileProviderOsm::TileProvider(QStringLiteral("http://c.tile2.opencyclemap.org/transport/%z/%x/%y.png"),
- QStringLiteral("png"),
- QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
- QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "night-transit",
- nm,
+ providers_transit ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::TransitMap, tr("Night Transit Map"), tr("Public transit map view in night mode"), false, true, 5),
- QGeoTileProviderOsm::TileProvider(QStringLiteral("http://a.tile.thunderforest.com/transport-dark/%z/%x/%y.png"),
- QStringLiteral("png"),
- QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
- QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "terrain",
- nm,
+ providers_nighttransit ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::TerrainMap, tr("Terrain Map"), tr("Terrain map view"), false, false, 6),
- QGeoTileProviderOsm::TileProvider(QStringLiteral("http://a.tile.thunderforest.com/landscape/%z/%x/%y.png"),
- QStringLiteral("png"),
- QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
- QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")
- )));
- m_providers.push_back(
- new QGeoTileProviderOsm(domain + "hiking",
- nm,
+ providers_terrain ));
+ m_providers.push_back( new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::PedestrianMap, tr("Hiking Map"), tr("Hiking map view"), false, false, 7),
- QGeoTileProviderOsm::TileProvider(QStringLiteral("http://a.tile.thunderforest.com/outdoors/%z/%x/%y.png"),
- QStringLiteral("png"),
- QStringLiteral("<a href='http://www.thunderforest.com/'>Thunderforest</a>"),
- QStringLiteral("<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors")
- )));
+ providers_hiking ));
if (parameters.contains(QStringLiteral("osm.mapping.custom.host"))
|| parameters.contains(QStringLiteral("osm.mapping.host"))) {
@@ -154,14 +197,13 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian
m_customCopyright = parameters.value(QStringLiteral("osm.mapping.copyright")).toString();
m_providers.push_back(
- new QGeoTileProviderOsm("",
- nm,
+ new QGeoTileProviderOsm( nm,
QGeoMapType(QGeoMapType::CustomMap, tr("Custom URL Map"), tr("Custom url map view set via urlprefix parameter"), false, false, 8),
- QGeoTileProviderOsm::TileProvider(tmsServer + QStringLiteral("%z/%x/%y.png"),
+ { new TileProvider(tmsServer + QStringLiteral("%z/%x/%y.png"),
QStringLiteral("png"),
mapCopyright,
- dataCopyright
- )));
+ dataCopyright) }
+ ));
m_providers.last()->disableRedirection();
}
@@ -182,20 +224,87 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian
}
updateMapTypes();
+
+ /* TILE CACHE */
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.directory"))) {
+ m_cacheDirectory = parameters.value(QStringLiteral("osm.mapping.cache.directory")).toString();
+ } else {
+ // managerName() is not yet set, we have to hardcode the plugin name below
+ m_cacheDirectory = QAbstractGeoTileCache::baseLocationCacheDirectory() + QLatin1String("osm");
+ }
+ if (parameters.contains(QStringLiteral("osm.mapping.offline.directory")))
+ m_offlineDirectory = parameters.value(QStringLiteral("osm.mapping.offline.directory")).toString();
+ QGeoFileTileCacheOsm *tileCache = new QGeoFileTileCacheOsm(m_providers, m_offlineDirectory, m_cacheDirectory);
+
+ /*
+ * Disk cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.disk.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("osm.mapping.cache.disk.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyDisk(QGeoFileTileCache::ByteSize);
+ }
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.disk.size"))) {
+ bool ok = false;
+ int cacheSize = parameters.value(QStringLiteral("osm.mapping.cache.disk.size")).toString().toInt(&ok);
+ if (ok)
+ tileCache->setMaxDiskUsage(cacheSize);
+ }
+
+ /*
+ * Memory cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.memory.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("osm.mapping.cache.memory.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyMemory(QGeoFileTileCache::ByteSize);
+ }
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.memory.size"))) {
+ bool ok = false;
+ int cacheSize = parameters.value(QStringLiteral("osm.mapping.cache.memory.size")).toString().toInt(&ok);
+ if (ok)
+ tileCache->setMaxMemoryUsage(cacheSize);
+ }
+
+ /*
+ * Texture cache setup -- defaults to ByteSize (old behavior)
+ */
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.texture.cost_strategy"))) {
+ QString cacheStrategy = parameters.value(QStringLiteral("osm.mapping.cache.texture.cost_strategy")).toString().toLower();
+ if (cacheStrategy == QLatin1String("bytesize"))
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ else
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::Unitary);
+ } else {
+ tileCache->setCostStrategyTexture(QGeoFileTileCache::ByteSize);
+ }
+ if (parameters.contains(QStringLiteral("osm.mapping.cache.texture.size"))) {
+ bool ok = false;
+ int cacheSize = parameters.value(QStringLiteral("osm.mapping.cache.texture.size")).toString().toInt(&ok);
+ if (ok)
+ tileCache->setExtraTextureUsage(cacheSize);
+ }
+
+
+ setTileCache(tileCache);
+
+
+ /* TILE FETCHER */
QGeoTileFetcherOsm *tileFetcher = new QGeoTileFetcherOsm(m_providers, nm, this);
if (parameters.contains(QStringLiteral("osm.useragent"))) {
const QByteArray ua = parameters.value(QStringLiteral("osm.useragent")).toString().toLatin1();
tileFetcher->setUserAgent(ua);
}
-
-
setTileFetcher(tileFetcher);
- QAbstractGeoTileCache *tileCache = new QGeoFileTileCache(QAbstractGeoTileCache::baseCacheDirectory() + QStringLiteral("osm"));
- // 50mb of disk cache by default to minimize n. of accesses to public OSM servers
- tileCache->setMaxDiskUsage(50 * 1024 * 1024);
- setTileCache(tileCache);
-
*error = QGeoServiceProvider::NoError;
errorString->clear();
}
@@ -206,7 +315,10 @@ QGeoTiledMappingManagerEngineOsm::~QGeoTiledMappingManagerEngineOsm()
QGeoMap *QGeoTiledMappingManagerEngineOsm::createMap()
{
- return new QGeoTiledMapOsm(this);
+ QGeoTiledMap *map = new QGeoTiledMapOsm(this);
+ connect(qobject_cast<QGeoFileTileCacheOsm *>(tileCache()), &QGeoFileTileCacheOsm::mapDataUpdated
+ , map, &QGeoTiledMap::clearScene);
+ return map;
}
const QVector<QGeoTileProviderOsm *> &QGeoTiledMappingManagerEngineOsm::providers()
@@ -226,9 +338,8 @@ void QGeoTiledMappingManagerEngineOsm::onProviderResolutionFinished(const QGeoTi
updateMapTypes();
}
-void QGeoTiledMappingManagerEngineOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error)
+void QGeoTiledMappingManagerEngineOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider)
{
- Q_UNUSED(error)
if (!provider->isResolved())
return;
updateMapTypes();
diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h
index 247e4377..b1f0a13c 100644
--- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h
+++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h
@@ -65,7 +65,7 @@ public:
protected Q_SLOTS:
void onProviderResolutionFinished(const QGeoTileProviderOsm *provider);
- void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error);
+ void onProviderResolutionError(const QGeoTileProviderOsm *provider);
protected:
void updateMapTypes();
@@ -73,6 +73,8 @@ protected:
private:
QVector<QGeoTileProviderOsm *> m_providers;
QString m_customCopyright;
+ QString m_cacheDirectory;
+ QString m_offlineDirectory;
};
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp
index 98621411..f7c25d61 100644
--- a/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp
+++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.cpp
@@ -43,6 +43,7 @@
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtLocation/private/qgeotilespec_p.h>
+#include <QtLocation/private/qgeotilefetcher_p_p.h>
QT_BEGIN_NAMESPACE
@@ -55,10 +56,30 @@ static bool providersResolved(const QVector<QGeoTileProviderOsm *> &providers)
return true;
}
+class QGeoTileFetcherOsmPrivate : public QGeoTileFetcherPrivate
+{
+ Q_DECLARE_PUBLIC(QGeoTileFetcherOsm)
+public:
+ QGeoTileFetcherOsmPrivate();
+ virtual ~QGeoTileFetcherOsmPrivate();
+
+private:
+ Q_DISABLE_COPY(QGeoTileFetcherOsmPrivate)
+};
+
+QGeoTileFetcherOsmPrivate::QGeoTileFetcherOsmPrivate() : QGeoTileFetcherPrivate()
+{
+}
+
+QGeoTileFetcherOsmPrivate::~QGeoTileFetcherOsmPrivate()
+{
+}
+
+
QGeoTileFetcherOsm::QGeoTileFetcherOsm(const QVector<QGeoTileProviderOsm *> &providers,
QNetworkAccessManager *nm,
QObject *parent)
-: QGeoTileFetcher(parent), m_userAgent("Qt Location based application"),
+: QGeoTileFetcher(*new QGeoTileFetcherOsmPrivate(), parent), m_userAgent("Qt Location based application"),
m_providers(providers), m_nm(nm), m_ready(true)
{
m_nm->setParent(this);
@@ -69,6 +90,8 @@ QGeoTileFetcherOsm::QGeoTileFetcherOsm(const QVector<QGeoTileProviderOsm *> &pro
this, &QGeoTileFetcherOsm::onProviderResolutionFinished);
connect(provider, &QGeoTileProviderOsm::resolutionError,
this, &QGeoTileFetcherOsm::onProviderResolutionError);
+ connect(provider, &QGeoTileProviderOsm::resolutionRequired,
+ this, &QGeoTileFetcherOsm::restartTimer, Qt::QueuedConnection);
provider->resolveProvider();
}
}
@@ -100,9 +123,8 @@ void QGeoTileFetcherOsm::onProviderResolutionFinished(const QGeoTileProviderOsm
emit providerDataUpdated(provider);
}
-void QGeoTileFetcherOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error)
+void QGeoTileFetcherOsm::onProviderResolutionError(const QGeoTileProviderOsm *provider)
{
- Q_UNUSED(error)
if ((m_ready = providersResolved(m_providers))) {
qWarning("QGeoTileFetcherOsm: all providers resolved");
readyUpdated();
@@ -110,6 +132,14 @@ void QGeoTileFetcherOsm::onProviderResolutionError(const QGeoTileProviderOsm *pr
emit providerDataUpdated(provider);
}
+void QGeoTileFetcherOsm::restartTimer()
+{
+ Q_D(QGeoTileFetcherOsm);
+
+ if (!d->queue_.isEmpty())
+ d->timer_.start(0, this);
+}
+
QGeoTiledMapReply *QGeoTileFetcherOsm::getTileImage(const QGeoTileSpec &spec)
{
int id = spec.mapId();
@@ -122,6 +152,9 @@ QGeoTiledMapReply *QGeoTileFetcherOsm::getTileImage(const QGeoTileSpec &spec)
}
id -= 1; // TODO: make OSM map ids start from 0.
+ if (spec.zoom() > m_providers[id]->maximumZoomLevel() || spec.zoom() < m_providers[id]->minimumZoomLevel())
+ return Q_NULLPTR;
+
const QUrl url = m_providers[id]->tileAddress(spec.x(), spec.y(), spec.zoom());
QNetworkRequest request;
request.setHeader(QNetworkRequest::UserAgentHeader, m_userAgent);
diff --git a/src/plugins/geoservices/osm/qgeotilefetcherosm.h b/src/plugins/geoservices/osm/qgeotilefetcherosm.h
index 8d69cc56..a7b89bad 100644
--- a/src/plugins/geoservices/osm/qgeotilefetcherosm.h
+++ b/src/plugins/geoservices/osm/qgeotilefetcherosm.h
@@ -47,10 +47,12 @@
QT_BEGIN_NAMESPACE
class QNetworkAccessManager;
+class QGeoTileFetcherOsmPrivate;
class QGeoTileFetcherOsm : public QGeoTileFetcher
{
Q_OBJECT
+ Q_DECLARE_PRIVATE(QGeoTileFetcherOsm)
friend class QGeoMapReplyOsm;
friend class QGeoTiledMappingManagerEngineOsm;
@@ -69,10 +71,11 @@ protected:
protected Q_SLOTS:
void onProviderResolutionFinished(const QGeoTileProviderOsm *provider);
- void onProviderResolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error);
+ void onProviderResolutionError(const QGeoTileProviderOsm *provider);
+ void restartTimer();
private:
- QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec);
+ QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec) Q_DECL_OVERRIDE;
void readyUpdated();
QByteArray m_userAgent;
diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp
index 3d46a425..1989c44f 100644
--- a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp
+++ b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp
@@ -43,115 +43,89 @@
QT_BEGIN_NAMESPACE
static const int maxValidZoom = 30;
+static const QDateTime defaultTs = QDateTime::fromString(QStringLiteral("2016-06-01T00:00:00"), Qt::ISODate);
-QGeoTileProviderOsm::QGeoTileProviderOsm(const QString &urlRedir,
- QNetworkAccessManager *nm,
- const QGeoMapType &mapType,
- const QGeoTileProviderOsm::TileProvider &providerFallback)
- : m_nm(nm), m_urlRedirector(urlRedir),
- m_providerFallback(providerFallback),
- m_mapType(mapType), m_status(Idle)
+QGeoTileProviderOsm::QGeoTileProviderOsm(QNetworkAccessManager *nm,
+ const QGeoMapType &mapType,
+ const QVector<TileProvider *> &providers)
+: m_nm(nm), m_provider(nullptr), m_mapType(mapType), m_status(Idle)
{
- if (!m_urlRedirector.isValid())
- disableRedirection();
+ for (int i = 0; i < providers.size(); ++i) {
+ TileProvider *p = providers[i];
+ if (!m_provider)
+ m_providerId = i;
+ addProvider(p);
+ }
+
+ if (!m_provider || m_provider->isValid())
+ m_status = Resolved;
}
QGeoTileProviderOsm::~QGeoTileProviderOsm()
{
-
}
-void QGeoTileProviderOsm::resolveProvider()
+QUrl QGeoTileProviderOsm::tileAddress(int x, int y, int z) const
{
- switch (m_status) {
- case Resolving:
- case Invalid:
- case Valid:
- return;
- case Idle:
- m_status = Resolving;
- break;
- }
+ if (m_status != Resolved || !m_provider)
+ return QUrl();
+ return m_provider->tileAddress(x, y, z);
+}
- QNetworkRequest request;
- request.setHeader(QNetworkRequest::UserAgentHeader, QByteArrayLiteral("QGeoTileFetcherOsm"));
- request.setUrl(m_urlRedirector);
- QNetworkReply *reply = m_nm->get(request);
- connect(reply, SIGNAL(finished()), this, SLOT(onNetworkReplyFinished()));
- connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
- this, SLOT(onNetworkReplyError(QNetworkReply::NetworkError)));
+QString QGeoTileProviderOsm::mapCopyRight() const
+{
+ if (m_status != Resolved || !m_provider)
+ return QString();
+ return m_provider->mapCopyRight();
}
-void QGeoTileProviderOsm::disableRedirection()
+QString QGeoTileProviderOsm::dataCopyRight() const
{
- m_status = Invalid;
- m_provider.m_valid = false;
+ if (m_status != Resolved || !m_provider)
+ return QString();
+ return m_provider->dataCopyRight();
}
-void QGeoTileProviderOsm::handleError(QNetworkReply::NetworkError error)
+QString QGeoTileProviderOsm::styleCopyRight() const
{
- switch (error) {
- case QNetworkReply::ConnectionRefusedError:
- case QNetworkReply::TooManyRedirectsError:
- case QNetworkReply::InsecureRedirectError:
- case QNetworkReply::ContentAccessDenied:
- case QNetworkReply::ContentOperationNotPermittedError:
- case QNetworkReply::ContentNotFoundError:
- case QNetworkReply::AuthenticationRequiredError:
- case QNetworkReply::ContentGoneError:
- case QNetworkReply::OperationNotImplementedError:
- case QNetworkReply::ServiceUnavailableError:
- // Errors we don't expect to recover from in the near future, which
- // prevent accessing the redirection info but not the actual providers.
- m_status = Invalid;
- default:
- break;
- }
+ if (m_status != Resolved || !m_provider)
+ return QString();
+ return m_provider->styleCopyRight();
}
-QUrl QGeoTileProviderOsm::tileAddress(int x, int y, int z) const
+QString QGeoTileProviderOsm::format() const
{
- if (m_provider.isValid())
- return m_provider.tileAddress(x,y,z);
- if (m_providerFallback.isValid())
- return m_providerFallback.tileAddress(x,y,z);
- return QUrl();
+ if (m_status != Resolved || !m_provider)
+ return QString();
+ return m_provider->format();
}
-QString QGeoTileProviderOsm::mapCopyRight() const
+int QGeoTileProviderOsm::minimumZoomLevel() const
{
- if (m_provider.isValid())
- return m_provider.mapCopyRight();
- if (m_providerFallback.isValid())
- return m_providerFallback.mapCopyRight();
- return QString();
+ if (m_status != Resolved || !m_provider)
+ return 0;
+ return m_provider->minimumZoomLevel();
}
-QString QGeoTileProviderOsm::dataCopyRight() const
+int QGeoTileProviderOsm::maximumZoomLevel() const
{
- if (m_provider.isValid())
- return m_provider.dataCopyRight();
- if (m_providerFallback.isValid())
- return m_providerFallback.dataCopyRight();
- return QString();
+ if (m_status != Resolved || !m_provider)
+ return 20;
+ return m_provider->maximumZoomLevel();
}
-QString QGeoTileProviderOsm::styleCopyRight() const
+bool QGeoTileProviderOsm::isHighDpi() const
{
- if (m_provider.isValid())
- return m_provider.styleCopyRight();
- if (m_providerFallback.isValid())
- return m_providerFallback.styleCopyRight();
- return QString();
+ if (!m_provider)
+ return false;
+ return m_provider->isHighDpi();
}
-QString QGeoTileProviderOsm::format() const
+const QDateTime QGeoTileProviderOsm::timestamp() const
{
- if (m_provider.isValid())
- return m_provider.format();
- if (m_providerFallback.isValid())
- return m_providerFallback.format();
- return QString();
+ if (!m_provider)
+ return QDateTime();
+ return m_provider->timestamp();
}
const QGeoMapType &QGeoTileProviderOsm::mapType() const
@@ -161,33 +135,218 @@ const QGeoMapType &QGeoTileProviderOsm::mapType() const
bool QGeoTileProviderOsm::isValid() const
{
- return (m_provider.isValid() || m_providerFallback.isValid());
+ if (m_status != Resolved || !m_provider)
+ return false;
+ return m_provider->isValid();
}
bool QGeoTileProviderOsm::isResolved() const
{
- return (m_status == Valid || m_status == Invalid);
+ return (m_status == Resolved);
+}
+
+void QGeoTileProviderOsm::resolveProvider()
+{
+ if (m_status == Resolved || m_status == Resolving)
+ return;
+
+ m_status = Resolving;
+ // Provider can't be null while on Idle status.
+ connect(m_provider, &TileProvider::resolutionFinished, this, &QGeoTileProviderOsm::onResolutionFinished);
+ connect(m_provider, &TileProvider::resolutionError, this, &QGeoTileProviderOsm::onResolutionError);
+ m_provider->resolveProvider();
+}
+
+void QGeoTileProviderOsm::disableRedirection()
+{
+ if (m_provider && m_provider->isValid())
+ return;
+ bool found = false;
+ for (TileProvider *p: m_providerList) {
+ if (p->isValid() && !found) {
+ m_provider = p;
+ found = true;
+ }
+ p->disconnect(this);
+ }
+}
+
+void QGeoTileProviderOsm::onResolutionFinished(TileProvider *provider)
+{
+ Q_UNUSED(provider)
+ // provider and m_provider are the same, at this point. m_status is Resolving.
+ m_status = Resolved;
+ emit resolutionFinished(this);
+}
+
+void QGeoTileProviderOsm::onResolutionError(TileProvider *provider)
+{
+ Q_UNUSED(provider)
+ // provider and m_provider are the same at this point. m_status is Resolving.
+ if (m_provider->isInvalid()) {
+ m_provider = nullptr;
+ m_status = Resolved;
+ if (m_providerId >= m_providerList.size() -1) { // no hope left
+ emit resolutionError(this);
+ return;
+ }
+ // Advance the pointer in the provider list, and possibly start resolution on the next in the list.
+ for (int i = m_providerId + 1; i < m_providerList.size(); ++i) {
+ m_providerId = i;
+ TileProvider *p = m_providerList[m_providerId];
+ if (!p->isInvalid()) {
+ m_provider = p;
+ if (!p->isValid()) {
+ m_status = Idle;
+#if 0 // leaving triggering the retry to the tile fetcher, instead of constantly spinning it in here.
+ m_status = Resolving;
+ p->resolveProvider();
+#endif
+ emit resolutionRequired();
+ }
+ break;
+ }
+ }
+ if (!m_provider)
+ emit resolutionError(this);
+ } else if (m_provider->isValid()) {
+ m_status = Resolved;
+ emit resolutionFinished(this);
+ } else { // still not resolved. But network error is recoverable.
+ m_status = Idle;
+#if 0 // leaving triggering the retry to the tile fetcher
+ m_provider->resolveProvider();
+#endif
+ }
+}
+
+void QGeoTileProviderOsm::addProvider(TileProvider *provider)
+{
+ if (!provider)
+ return;
+ QScopedPointer<TileProvider> p(provider);
+ if (provider->status() == TileProvider::Invalid)
+ return; // if the provider is already resolved and invalid, no point in adding it.
+
+ provider = p.take();
+ provider->setNetworkManager(m_nm);
+ provider->setParent(this);
+ m_providerList.append(provider);
+ if (!m_provider)
+ m_provider = provider;
+}
+
+
+/*
+ Class TileProvder
+*/
+
+static void sort2(int &a, int &b)
+{
+ if (a > b) {
+ int temp=a;
+ a=b;
+ b=temp;
+ }
+}
+
+TileProvider::TileProvider() : m_status(Invalid), m_nm(nullptr), m_timestamp(defaultTs), m_highDpi(false)
+{
+
+}
+
+TileProvider::TileProvider(const QUrl &urlRedirector, bool highDpi)
+: m_status(Idle), m_urlRedirector(urlRedirector), m_nm(nullptr), m_timestamp(defaultTs), m_highDpi(highDpi)
+{
+ if (!m_urlRedirector.isValid())
+ m_status = Invalid;
+}
+
+TileProvider::TileProvider(const QString &urlTemplate,
+ const QString &format,
+ const QString &copyRightMap,
+ const QString &copyRightData,
+ bool highDpi,
+ int minimumZoomLevel,
+ int maximumZoomLevel)
+: m_status(Invalid), m_nm(nullptr), m_urlTemplate(urlTemplate),
+ m_format(format), m_copyRightMap(copyRightMap), m_copyRightData(copyRightData),
+ m_minimumZoomLevel(minimumZoomLevel), m_maximumZoomLevel(maximumZoomLevel), m_timestamp(defaultTs), m_highDpi(highDpi)
+{
+ setupProvider();
+}
+
+TileProvider::~TileProvider()
+{
+}
+
+void TileProvider::resolveProvider()
+{
+ if (!m_nm)
+ return;
+
+ switch (m_status) {
+ case Resolving:
+ case Invalid:
+ case Valid:
+ return;
+ case Idle:
+ m_status = Resolving;
+ break;
+ }
+
+ QNetworkRequest request;
+ request.setHeader(QNetworkRequest::UserAgentHeader, QByteArrayLiteral("QGeoTileFetcherOsm"));
+ request.setUrl(m_urlRedirector);
+ request.setAttribute(QNetworkRequest::BackgroundRequestAttribute, true);
+ QNetworkReply *reply = m_nm->get(request);
+ connect(reply, SIGNAL(finished()), this, SLOT(onNetworkReplyFinished()) );
+ connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onNetworkReplyError(QNetworkReply::NetworkError)));
+}
+
+void TileProvider::handleError(QNetworkReply::NetworkError error)
+{
+ switch (error) {
+ case QNetworkReply::ConnectionRefusedError:
+ case QNetworkReply::TooManyRedirectsError:
+ case QNetworkReply::InsecureRedirectError:
+ case QNetworkReply::ContentAccessDenied:
+ case QNetworkReply::ContentOperationNotPermittedError:
+ case QNetworkReply::ContentNotFoundError:
+ case QNetworkReply::AuthenticationRequiredError:
+ case QNetworkReply::ContentGoneError:
+ case QNetworkReply::OperationNotImplementedError:
+ case QNetworkReply::ServiceUnavailableError:
+ // Errors we don't expect to recover from in the near future, which
+ // prevent accessing the redirection info but not the actual providers.
+ m_status = Invalid;
+ default:
+ //qWarning() << "QGeoTileProviderOsm network error:" << error;
+ break;
+ }
}
-void QGeoTileProviderOsm::onNetworkReplyFinished()
+void TileProvider::onNetworkReplyFinished()
{
QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
reply->deleteLater();
switch (m_status) {
- case Resolving:
- m_status = Idle;
- case Idle: // should not happen
- case Invalid: // should not happen
- break;
- case Valid: // should not happen
- return;
+ case Resolving:
+ m_status = Idle;
+ case Idle: // should not happen
+ case Invalid: // should not happen
+ break;
+ case Valid: // should not happen
+ emit resolutionFinished(this);
+ return;
}
+ QObject errorEmitter;
+ QMetaObject::Connection errorEmitterConnection = connect(&errorEmitter, &QObject::destroyed, [this](){ this->resolutionError(this); });
+
if (reply->error() != QNetworkReply::NoError) {
handleError(reply->error());
- if (m_status == Invalid)
- emit resolutionError(this, reply->error());
return;
}
m_status = Invalid;
@@ -205,48 +364,51 @@ void QGeoTileProviderOsm::onNetworkReplyFinished()
* "StyleCopyRight" : "<copyright>", (optional)
* "MinimumZoomLevel" : <minimumZoomLevel>, (optional)
* "MaximumZoomLevel" : <maximumZoomLevel>, (optional)
+ * "Timestamp" : <timestamp>, (optional)
* }
*
* Enabled is optional, and allows to temporarily disable a tile provider if it becomes
* unavailable, without making the osm plugin fire requests to it. Default is true.
*
* MinimumZoomLevel and MaximumZoomLevel are also optional, and allow to prevent invalid tile
- * requests to the providers, if they do not support the specific ZL. Default is 0 and 19,
+ * requests to the providers, if they do not support the specific ZL. Default is 0 and 20,
* respectively.
*
- * <server address template> is required, and is the tile url template, with %x, %y and %z as
+ * UrlTemplate is required, and is the tile url template, with %x, %y and %z as
* placeholders for the actual parameters.
* Example:
* http://localhost:8080/maps/%z/%x/%y.png
*
- * <image format> is required, and is the format of the tile.
+ * ImageFormat is required, and is the format of the tile.
* Examples:
* "png", "jpg"
*
- * <MapCopyRight> is required and is the string that will be displayed in the "Map (c)" part
+ * MapCopyRight is required and is the string that will be displayed in the "Map (c)" part
* of the on-screen copyright notice. Can be an empty string.
* Example:
* "<a href='http://www.mapquest.com/'>MapQuest</a>"
*
- * <DataCopyRight> is required and is the string that will be displayed in the "Data (c)" part
+ * DataCopyRight is required and is the string that will be displayed in the "Data (c)" part
* of the on-screen copyright notice. Can be an empty string.
* Example:
* "<a href='http://www.openstreetmap.org/copyright'>OpenStreetMap</a> contributors"
*
- * <StyleCopyRight> is optional and is the string that will be displayed in the optional "Style (c)" part
+ * StyleCopyRight is optional and is the string that will be displayed in the optional "Style (c)" part
* of the on-screen copyright notice.
+ *
+ * Timestamp is optional, and if set will cause QtLocation to clear the content of the cache older
+ * than this timestamp. The purpose is to prevent mixing tiles from different providers in the cache
+ * upon provider change. The value must be a string in ISO 8601 format (see Qt::ISODate)
*/
QJsonParseError error;
QJsonDocument d = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qWarning() << "QGeoTileProviderOsm: Error parsing redirection data: "<<error.errorString() << "at "<<m_urlRedirector;
- emit resolutionFinished(this);
return;
}
if (!d.isObject()) {
qWarning() << "QGeoTileProviderOsm: Invalid redirection data" << "at "<<m_urlRedirector;
- emit resolutionFinished(this);
return;
}
const QJsonObject json = d.object();
@@ -263,56 +425,200 @@ void QGeoTileProviderOsm::onNetworkReplyFinished()
|| !copyRightMap.isString()
|| !copyRightData.isString()) {
qWarning() << "QGeoTileProviderOsm: Incomplete redirection data" << "at "<<m_urlRedirector;
- emit resolutionFinished(this);
return;
}
+ m_urlTemplate = urlTemplate.toString();
+ m_format = imageFormat.toString();
+ m_copyRightMap = copyRightMap.toString();
+ m_copyRightData = copyRightData.toString();
+
const QJsonValue enabled = json.value(QLatin1String("Enabled"));
if (enabled.isBool() && ! enabled.toBool()) {
qWarning() << "QGeoTileProviderOsm: Tileserver disabled" << "at "<<m_urlRedirector;
- emit resolutionFinished(this);
return;
}
- QString styleCopyRight;
const QJsonValue copyRightStyle = json.value(QLatin1String("StyleCopyRight"));
if (copyRightStyle != QJsonValue::Undefined && copyRightStyle.isString())
- styleCopyRight = copyRightStyle.toString();
+ m_copyRightStyle = copyRightStyle.toString();
- int minZL = 0;
- int maxZL = 19;
+ m_minimumZoomLevel = 0;
+ m_maximumZoomLevel = 20;
const QJsonValue minZoom = json.value(QLatin1String("MinimumZoomLevel"));
if (minZoom.isDouble())
- minZL = qBound(0, int(minZoom.toDouble()), maxValidZoom);
+ m_minimumZoomLevel = qBound(0, int(minZoom.toDouble()), maxValidZoom);
const QJsonValue maxZoom = json.value(QLatin1String("MaximumZoomLevel"));
if (maxZoom.isDouble())
- maxZL = qBound(0, int(maxZoom.toDouble()), maxValidZoom);
+ m_maximumZoomLevel = qBound(0, int(maxZoom.toDouble()), maxValidZoom);
- m_provider = TileProvider(urlTemplate.toString(),
- imageFormat.toString(),
- copyRightMap.toString(),
- copyRightData.toString(),
- minZL,
- maxZL);
- m_provider.setStyleCopyRight(styleCopyRight);
+ const QJsonValue ts = json.value(QLatin1String("Timestamp"));
+ if (ts.isString())
+ m_timestamp = QDateTime::fromString(ts.toString(), Qt::ISODate);
- if (m_provider.isValid())
- m_status = Valid;
-
- emit resolutionFinished(this);
+ setupProvider();
+ if (isValid()) {
+ QObject::disconnect(errorEmitterConnection);
+ emit resolutionFinished(this);
+ }
}
-void QGeoTileProviderOsm::onNetworkReplyError(QNetworkReply::NetworkError error)
+void TileProvider::onNetworkReplyError(QNetworkReply::NetworkError error)
{
if (m_status == Resolving)
m_status = Idle;
- qWarning() << "QGeoTileProviderOsm::onNetworkReplyError " << error;
handleError(error);
-
static_cast<QNetworkReply *>(sender())->deleteLater();
- if (m_status == Invalid)
- emit resolutionError(this, error);
+ emit resolutionError(this);
+}
+
+void TileProvider::setupProvider()
+{
+ if (m_urlTemplate.isEmpty())
+ return;
+
+ if (m_format.isEmpty())
+ return;
+
+ if (m_minimumZoomLevel < 0 || m_minimumZoomLevel > 30)
+ return;
+
+ if (m_maximumZoomLevel < 0 || m_maximumZoomLevel > 30 || m_maximumZoomLevel < m_minimumZoomLevel)
+ return;
+
+ // Currently supporting only %x, %y and &z
+ int offset[3];
+ offset[0] = m_urlTemplate.indexOf(QLatin1String("%x"));
+ if (offset[0] < 0)
+ return;
+
+ offset[1] = m_urlTemplate.indexOf(QLatin1String("%y"));
+ if (offset[1] < 0)
+ return;
+
+ offset[2] = m_urlTemplate.indexOf(QLatin1String("%z"));
+ if (offset[2] < 0)
+ return;
+
+ int sortedOffsets[3];
+ std::copy(offset, offset + 3, sortedOffsets);
+ sort2(sortedOffsets[0] ,sortedOffsets[1]);
+ sort2(sortedOffsets[1] ,sortedOffsets[2]);
+ sort2(sortedOffsets[0] ,sortedOffsets[1]);
+
+ int min = sortedOffsets[0];
+ int max = sortedOffsets[2];
+ int mid = sortedOffsets[1];
+
+ // Initing LUT
+ for (int i=0; i<3; i++) {
+ if (offset[0] == sortedOffsets[i])
+ paramsLUT[i] = 0;
+ else if (offset[1] == sortedOffsets[i])
+ paramsLUT[i] = 1;
+ else
+ paramsLUT[i] = 2;
+ }
+
+ m_urlPrefix = m_urlTemplate.mid(0 , min);
+ m_urlSuffix = m_urlTemplate.mid(max + 2, m_urlTemplate.size() - max - 2);
+
+ paramsSep[0] = m_urlTemplate.mid(min + 2, mid - min - 2);
+ paramsSep[1] = m_urlTemplate.mid(mid + 2, max - mid - 2);
+ m_status = Valid;
+}
+
+bool TileProvider::isValid() const
+{
+ return m_status == Valid;
+}
+
+bool TileProvider::isInvalid() const
+{
+ return m_status == Invalid;
+}
+
+bool TileProvider::isResolved() const
+{
+ return (m_status == Valid || m_status == Invalid);
+}
+
+QString TileProvider::mapCopyRight() const
+{
+ return m_copyRightMap;
+}
+
+QString TileProvider::dataCopyRight() const
+{
+ return m_copyRightData;
+}
+
+QString TileProvider::styleCopyRight() const
+{
+ return m_copyRightStyle;
+}
+
+QString TileProvider::format() const
+{
+ return m_format;
+}
+
+int TileProvider::minimumZoomLevel() const
+{
+ return m_minimumZoomLevel;
+}
+
+int TileProvider::maximumZoomLevel() const
+{
+ return m_maximumZoomLevel;
}
+const QDateTime &TileProvider::timestamp() const
+{
+ return m_timestamp;
+}
+
+bool TileProvider::isHighDpi() const
+{
+ return m_highDpi;
+}
+
+void TileProvider::setStyleCopyRight(const QString &copyright)
+{
+ m_copyRightStyle = copyright;
+}
+
+void TileProvider::setTimestamp(const QDateTime &timestamp)
+{
+ m_timestamp = timestamp;
+}
+
+QUrl TileProvider::tileAddress(int x, int y, int z) const
+{
+ if (z < m_minimumZoomLevel || z > m_maximumZoomLevel)
+ return QUrl();
+ int params[3] = { x, y, z};
+ QString url;
+ url += m_urlPrefix;
+ url += QString::number(params[paramsLUT[0]]);
+ url += paramsSep[0];
+ url += QString::number(params[paramsLUT[1]]);
+ url += paramsSep[1];
+ url += QString::number(params[paramsLUT[2]]);
+ url += m_urlSuffix;
+ return QUrl(url);
+}
+
+void TileProvider::setNetworkManager(QNetworkAccessManager *nm)
+{
+ m_nm = nm;
+}
+
+TileProvider::Status TileProvider::status() const
+{
+ return m_status;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.h b/src/plugins/geoservices/osm/qgeotileproviderosm.h
index f396b3b5..b8647244 100644
--- a/src/plugins/geoservices/osm/qgeotileproviderosm.h
+++ b/src/plugins/geoservices/osm/qgeotileproviderosm.h
@@ -40,215 +40,148 @@
#include <QtLocation/private/qgeomaptype_p.h>
#include <QtCore/QUrl>
+#include <QtCore/QVector>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtCore/QPointer>
#include <QTimer>
#include <algorithm>
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonObject>
+#include <QDateTime>
QT_BEGIN_NAMESPACE
-class QGeoTileProviderOsm: public QObject
+class TileProvider: public QObject
{
Q_OBJECT
-
- friend class QGeoTileFetcherOsm;
- friend class QGeoMapReplyOsm;
- friend class QGeoTiledMappingManagerEngineOsm;
public:
- struct TileProvider {
-
- static inline void sort2(int &a, int &b)
- {
- if (a > b) {
- int temp=a;
- a=b;
- b=temp;
- }
- }
-
- TileProvider() : m_valid(false)
- {
-
- }
-
- TileProvider(const QString &urlTemplate,
- const QString &format,
- const QString &copyRightMap,
- const QString &copyRightData,
- int minimumZoomLevel = 0,
- int maximumZoomLevel = 19) : m_valid(false)
- {
- if (urlTemplate.isEmpty())
- return;
- m_urlTemplate = urlTemplate;
-
- if (format.isEmpty())
- return;
- m_format = format;
-
- m_copyRightMap = copyRightMap;
- m_copyRightData = copyRightData;
-
- if (minimumZoomLevel < 0 || minimumZoomLevel > 30)
- return;
- m_minimumZoomLevel = minimumZoomLevel;
-
- if (maximumZoomLevel < 0 || maximumZoomLevel > 30 || maximumZoomLevel < minimumZoomLevel)
- return;
- m_maximumZoomLevel = maximumZoomLevel;
-
- // Currently supporting only %x, %y and &z
- int offset[3];
- offset[0] = m_urlTemplate.indexOf(QLatin1String("%x"));
- if (offset[0] < 0)
- return;
-
- offset[1] = m_urlTemplate.indexOf(QLatin1String("%y"));
- if (offset[1] < 0)
- return;
-
- offset[2] = m_urlTemplate.indexOf(QLatin1String("%z"));
- if (offset[2] < 0)
- return;
-
- int sortedOffsets[3];
- std::copy(offset, offset + 3, sortedOffsets);
- sort2(sortedOffsets[0] ,sortedOffsets[1]);
- sort2(sortedOffsets[1] ,sortedOffsets[2]);
- sort2(sortedOffsets[0] ,sortedOffsets[1]);
-
- int min = sortedOffsets[0];
- int max = sortedOffsets[2];
- int mid = sortedOffsets[1];
-
- // Initing LUT
- for (int i=0; i<3; i++) {
- if (offset[0] == sortedOffsets[i])
- paramsLUT[i] = 0;
- else if (offset[1] == sortedOffsets[i])
- paramsLUT[i] = 1;
- else
- paramsLUT[i] = 2;
- }
-
- m_urlPrefix = m_urlTemplate.mid(0 , min);
- m_urlSuffix = m_urlTemplate.mid(max + 2, m_urlTemplate.size() - max - 2);
-
- paramsSep[0] = m_urlTemplate.mid(min + 2, mid - min - 2);
- paramsSep[1] = m_urlTemplate.mid(mid + 2, max - mid - 2);
- m_valid = true;
- }
-
- ~TileProvider()
- {
- }
-
- inline bool isValid() const
- {
- return m_valid;
- }
+ enum Status {Idle,
+ Resolving,
+ Valid,
+ Invalid };
- inline QString mapCopyRight() const
- {
- return m_copyRightMap;
- }
+ TileProvider();
+ // "Online" constructor. Needs resolution to fetch the parameters
+ TileProvider(const QUrl &urlRedirector, bool highDpi = false);
+ // Offline constructor. Doesn't need URLRedirector and networkmanager
+ TileProvider(const QString &urlTemplate,
+ const QString &format,
+ const QString &copyRightMap,
+ const QString &copyRightData,
+ bool highDpi = false,
+ int minimumZoomLevel = 0,
+ int maximumZoomLevel = 19);
+
+ ~TileProvider();
+ void setNetworkManager(QNetworkAccessManager *nm);
- inline QString dataCopyRight() const
- {
- return m_copyRightData;
- }
+ void resolveProvider();
+ void handleError(QNetworkReply::NetworkError error);
+ void setupProvider();
+
+ inline bool isValid() const;
+ inline bool isInvalid() const;
+ inline bool isResolved() const;
+ inline Status status() const;
+
+ inline QString mapCopyRight() const;
+ inline QString dataCopyRight() const;
+ inline QString styleCopyRight() const;
+ inline QString format() const;
+ inline int minimumZoomLevel() const;
+ inline int maximumZoomLevel() const;
+ inline const QDateTime &timestamp() const;
+ inline bool isHighDpi() const;
+ QUrl tileAddress(int x, int y, int z) const;
- inline QString styleCopyRight() const
- {
- return m_copyRightStyle;
- }
+ // Optional properties, not needed to construct a provider
+ void setStyleCopyRight(const QString &copyright);
+ void setTimestamp(const QDateTime &timestamp);
- inline QString format() const
- {
- return m_format;
- }
+ Status m_status;
+ QUrl m_urlRedirector; // The URL from where to fetch the URL template in case of a provider to resolve.
+ QNetworkAccessManager *m_nm;
+ QString m_urlTemplate;
+ QString m_format;
+ QString m_copyRightMap;
+ QString m_copyRightData;
+ QString m_copyRightStyle;
+ QString m_urlPrefix;
+ QString m_urlSuffix;
+ int m_minimumZoomLevel;
+ int m_maximumZoomLevel;
+ QDateTime m_timestamp;
+ bool m_highDpi;
+
+ int paramsLUT[3]; //Lookup table to handle possibly shuffled x,y,z
+ QString paramsSep[2]; // what goes in between %x, %y and %z
- // Optional properties, not needed to construct a provider
- void setStyleCopyRight(const QString &copyright)
- {
- m_copyRightStyle = copyright;
- }
+Q_SIGNALS:
+ void resolutionFinished(TileProvider *provider);
+ void resolutionError(TileProvider *provider);
- QUrl tileAddress(int x, int y, int z) const
- {
- if (z < m_minimumZoomLevel || z > m_maximumZoomLevel)
- return QUrl();
- int params[3] = { x, y, z};
- QString url;
- url += m_urlPrefix;
- url += QString::number(params[paramsLUT[0]]);
- url += paramsSep[0];
- url += QString::number(params[paramsLUT[1]]);
- url += paramsSep[1];
- url += QString::number(params[paramsLUT[2]]);
- url += m_urlSuffix;
- return QUrl(url);
- }
+public Q_SLOTS:
+ void onNetworkReplyFinished();
+ void onNetworkReplyError(QNetworkReply::NetworkError error);
- bool m_valid;
- QString m_urlTemplate;
- QString m_format;
- QString m_copyRightMap;
- QString m_copyRightData;
- QString m_copyRightStyle;
- QString m_urlPrefix;
- QString m_urlSuffix;
- int m_minimumZoomLevel;
- int m_maximumZoomLevel;
+friend class QGeoTileProviderOsm;
+};
- int paramsLUT[3]; //Lookup table to handle possibly shuffled x,y,z
- QString paramsSep[2]; // what goes in between %x, %y and %z
- };
+class QGeoTileProviderOsm: public QObject
+{
+ Q_OBJECT
+ friend class QGeoTileFetcherOsm;
+ friend class QGeoMapReplyOsm;
+ friend class QGeoTiledMappingManagerEngineOsm;
+public:
enum Status {Idle,
Resolving,
- Valid,
- Invalid };
-
- QGeoTileProviderOsm(const QString &urlRedir,
- QNetworkAccessManager *nm,
- const QGeoMapType &mapType,
- const TileProvider &providerFallback);
+ Resolved };
+ QGeoTileProviderOsm(QNetworkAccessManager *nm,
+ const QGeoMapType &mapType,
+ const QVector<TileProvider *> &providers);
~QGeoTileProviderOsm();
-
-
QUrl tileAddress(int x, int y, int z) const;
QString mapCopyRight() const;
QString dataCopyRight() const;
QString styleCopyRight() const;
QString format() const;
+ int minimumZoomLevel() const;
+ int maximumZoomLevel() const;
+ bool isHighDpi() const;
const QGeoMapType &mapType() const;
bool isValid() const;
bool isResolved() const;
+ const QDateTime timestamp() const;
Q_SIGNALS:
void resolutionFinished(const QGeoTileProviderOsm *provider);
- void resolutionError(const QGeoTileProviderOsm *provider, QNetworkReply::NetworkError error);
+ void resolutionError(const QGeoTileProviderOsm *provider);
+ void resolutionRequired();
public Q_SLOTS:
- void onNetworkReplyFinished();
- void onNetworkReplyError(QNetworkReply::NetworkError error);
void resolveProvider();
+ void disableRedirection();
+
+protected Q_SLOTS:
+ void onResolutionFinished(TileProvider *provider);
+ void onResolutionError(TileProvider *provider);
protected:
- void disableRedirection();
- void handleError(QNetworkReply::NetworkError error);
+ void addProvider(TileProvider *provider);
+
+/* Data members */
QNetworkAccessManager *m_nm;
- QUrl m_urlRedirector; // The URL from where to fetch the URL template
- TileProvider m_provider;
- TileProvider m_providerFallback;
+ QVector<TileProvider *> m_providerList;
+ TileProvider *m_provider;
+ int m_providerId;
QGeoMapType m_mapType;
Status m_status;
- QTimer m_retryTimer;
};
QT_END_NAMESPACE
diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp
index e0124eb6..44d2fda4 100644
--- a/src/plugins/position/android/src/jnipositioning.cpp
+++ b/src/plugins/position/android/src/jnipositioning.cpp
@@ -41,6 +41,7 @@
#include <QDebug>
#include <QMap>
#include <QtGlobal>
+#include <QtCore/private/qjnihelpers_p.h>
#include <android/log.h>
#include <jni.h>
#include <QGeoPositionInfo>
@@ -99,7 +100,7 @@ namespace AndroidPositioning {
{
static bool firstInit = true;
if (firstInit) {
- qsrand( QDateTime::currentDateTime().toTime_t() );
+ qsrand( QDateTime::currentMSecsSinceEpoch() / 1000 );
firstInit = false;
}
@@ -367,6 +368,20 @@ namespace AndroidPositioning {
QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
if (source) {
+ // Android v23+ requires runtime permission check and requests
+ QString permission(QLatin1String("android.permission.ACCESS_FINE_LOCATION"));
+
+ if (QtAndroidPrivate::checkPermission(permission) == QtAndroidPrivate::PermissionsResult::Denied) {
+ const QHash<QString, QtAndroidPrivate::PermissionsResult> results =
+ QtAndroidPrivate::requestPermissionsSync(env.jniEnv, QStringList() << permission);
+ if (!results.contains(permission)
+ || results[permission] == QtAndroidPrivate::PermissionsResult::Denied)
+ {
+ qWarning() << "Position retrieval not possible due to missing permission (ACCESS_FINE_LOCATION)";
+ return QGeoPositionInfoSource::AccessError;
+ }
+ }
+
int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, startUpdatesMethodId,
androidClassKey,
positioningMethodToInt(source->preferredPositioningMethods()),
@@ -404,6 +419,20 @@ namespace AndroidPositioning {
QGeoPositionInfoSourceAndroid *source = AndroidPositioning::idToPosSource()->value(androidClassKey);
if (source) {
+ // Android v23+ requires runtime permission check and requests
+ QString permission(QLatin1String("android.permission.ACCESS_FINE_LOCATION"));
+
+ if (QtAndroidPrivate::checkPermission(permission) == QtAndroidPrivate::PermissionsResult::Denied) {
+ const QHash<QString, QtAndroidPrivate::PermissionsResult> results =
+ QtAndroidPrivate::requestPermissionsSync(env.jniEnv, QStringList() << permission);
+ if (!results.contains(permission)
+ || results[permission] == QtAndroidPrivate::PermissionsResult::Denied)
+ {
+ qWarning() << "Position update not possible due to missing permission (ACCESS_FINE_LOCATION)";
+ return QGeoPositionInfoSource::AccessError;
+ }
+ }
+
int errorCode = env.jniEnv->CallStaticIntMethod(positioningClass, requestUpdateMethodId,
androidClassKey,
positioningMethodToInt(source->preferredPositioningMethods()));
diff --git a/src/plugins/position/android/src/src.pro b/src/plugins/position/android/src/src.pro
index 3a19c85e..36facc55 100644
--- a/src/plugins/position/android/src/src.pro
+++ b/src/plugins/position/android/src/src.pro
@@ -1,6 +1,6 @@
TARGET = qtposition_android
-QT = core positioning
+QT = core core-private positioning
HEADERS = \
positionfactory_android.h \
diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml
index ce5c80de..8f7f70d4 100644
--- a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml
+++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Position.xml
@@ -18,7 +18,7 @@
<arg name="longitude" type="d"/>
<arg name="altitude" type="d"/>
<arg name="accuracy" type="(idd)"/>
- <annotation name="org.qtproject.QtDBus.QtTypeName.In5" value="Accuracy"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out5" value="Accuracy"/>
</signal>
</interface>
</node>
diff --git a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml
index 2ed112c9..b892e26f 100644
--- a/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml
+++ b/src/plugins/position/geoclue/org.freedesktop.Geoclue.Satellite.xml
@@ -26,8 +26,8 @@
<arg name="satelliteVisible" type="i" />
<arg name="usedPrn" type="ai" />
<arg name="satInfo" type="a(iiii)" />'
- <annotation name="org.qtproject.QtDBus.QtTypeName.In3" value="QList&lt;qint32&gt;"/>
- <annotation name="org.qtproject.QtDBus.QtTypeName.In4" value="QList&lt;QGeoSatelliteInfo&gt;"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out3" value="QList&lt;qint32&gt;"/>
+ <annotation name="org.qtproject.QtDBus.QtTypeName.Out4" value="QList&lt;QGeoSatelliteInfo&gt;"/>
</signal>
</interface>
</node>
diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h
index f2d817b1..b9c4774a 100644
--- a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h
+++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.h
@@ -65,17 +65,17 @@ public:
~QGeoPositionInfoSourceGeoclueMaster();
// From QGeoPositionInfoSource
- void setUpdateInterval(int msec);
- QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const;
- PositioningMethods supportedPositioningMethods() const;
- void setPreferredPositioningMethods(PositioningMethods methods);
- int minimumUpdateInterval() const;
+ void setUpdateInterval(int msec) override;
+ QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const override;
+ PositioningMethods supportedPositioningMethods() const override;
+ void setPreferredPositioningMethods(PositioningMethods methods) override;
+ int minimumUpdateInterval() const override;
- Error error() const;
+ Error error() const override;
- virtual void startUpdates() Q_DECL_OVERRIDE;
- virtual void stopUpdates() Q_DECL_OVERRIDE;
- virtual void requestUpdate(int timeout = 5000) Q_DECL_OVERRIDE;
+ void startUpdates() override;
+ void stopUpdates() override;
+ void requestUpdate(int timeout = 5000) override;
private slots:
void positionProviderChanged(const QString &name, const QString &description,
diff --git a/src/plugins/position/gypsy/gypsy.pro b/src/plugins/position/gypsy/gypsy.pro
index be65f183..c7b74325 100644
--- a/src/plugins/position/gypsy/gypsy.pro
+++ b/src/plugins/position/gypsy/gypsy.pro
@@ -1,6 +1,6 @@
TARGET = qtposition_gypsy
-QT = core positioning
+QT = core positioning-private
HEADERS += \
qgeosatelliteinfosource_gypsy_p.h \
@@ -10,8 +10,7 @@ SOURCES += \
qgeosatelliteinfosource_gypsy.cpp \
qgeopositioninfosourcefactory_gypsy.cpp
-CONFIG += link_pkgconfig
-PKGCONFIG += gypsy gconf-2.0
+QMAKE_USE_PRIVATE += gypsy
OTHER_FILES += \
plugin.json
diff --git a/src/plugins/position/position.pro b/src/plugins/position/position.pro
index df1930b3..1687a9d2 100644
--- a/src/plugins/position/position.pro
+++ b/src/plugins/position/position.pro
@@ -1,11 +1,13 @@
TEMPLATE = subdirs
+QT_FOR_CONFIG += positioning-private
+
qtHaveModule(dbus):SUBDIRS += geoclue
-config_gypsy:SUBDIRS += gypsy
+qtConfig(gypsy):SUBDIRS += gypsy
+qtConfig(winrt_geolocation):SUBDIRS += winrt
qtHaveModule(simulator):SUBDIRS += simulator
osx|ios|tvos:SUBDIRS += corelocation
android:SUBDIRS += android
-winrt:SUBDIRS += winrt
win32:qtHaveModule(serialport):SUBDIRS += serialnmea
SUBDIRS += \
diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
index 33523493..a8e5e201 100644
--- a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
+++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
@@ -62,10 +62,10 @@ typedef IAsyncOperationCompletedHandler<Geoposition*> PositionHandler;
typedef IAsyncOperationCompletedHandler<GeolocationAccessStatus> AccessHandler;
#endif
-QT_BEGIN_NAMESPACE
-
Q_DECLARE_METATYPE(QGeoPositionInfo)
+QT_BEGIN_NAMESPACE
+
#ifndef Q_OS_WINRT
namespace QEventDispatcherWinRT {
HRESULT runOnXamlThread(const std::function<HRESULT ()> &delegate, bool waitForRun = true)
@@ -486,6 +486,18 @@ HRESULT QGeoPositionInfoSourceWinRT::onPositionChanged(IGeolocator *locator, IPo
currentInfo.setAttribute(QGeoPositionInfo::GroundSpeed, value);
}
+ IReference<double> *heading;
+ hr = coord->get_Heading(&heading);
+ if (SUCCEEDED(hr) && heading) {
+ double value;
+ hr = heading->get_Value(&value);
+ double mod = 0;
+ value = modf(value, &mod);
+ value += static_cast<int>(mod) % 360;
+ if (value >=0 && value <= 359) // get_Value might return nan/-nan
+ currentInfo.setAttribute(QGeoPositionInfo::Direction, value);
+ }
+
DateTime dateTime;
hr = coord->get_Timestamp(&dateTime);