summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--config.tests/gypsy/gypsy.pro4
-rw-r--r--config.tests/winrt/main.cpp49
-rw-r--r--config.tests/winrt/winrt.pro5
-rw-r--r--configure.json5
-rw-r--r--qtlocation.pro1
-rw-r--r--src/3rdparty/clip2tri/qt_attribution.json13
-rw-r--r--src/3rdparty/clip2tri_legal.qdoc32
-rw-r--r--src/3rdparty/clipper/LICENSE (renamed from src/3rdparty/clipper_legal.qdoc)13
-rw-r--r--src/3rdparty/clipper/qt_attribution.json13
-rw-r--r--src/3rdparty/poly2tri/qt_attribution.json13
-rw-r--r--src/3rdparty/poly2tri_legal.qdoc37
-rw-r--r--src/imports/location/location.cpp2
-rw-r--r--src/imports/location/qdeclarativecirclemapitem.cpp6
-rw-r--r--src/imports/location/qdeclarativegeomap.cpp65
-rw-r--r--src/imports/location/qdeclarativegeomap_p.h2
-rw-r--r--src/imports/location/qdeclarativegeomapitembase.cpp18
-rw-r--r--src/imports/location/qdeclarativegeomapitemview_p.h2
-rw-r--r--src/imports/location/qdeclarativepolygonmapitem.cpp6
-rw-r--r--src/imports/location/qdeclarativepolylinemapitem.cpp10
-rw-r--r--src/imports/location/qgeomapitemgeometry.cpp8
-rw-r--r--src/imports/location/qquickgeomapgesturearea.cpp23
-rw-r--r--src/imports/positioning/positioning.cpp2
-rw-r--r--src/location/doc/src/plugins/esri.qdoc239
-rw-r--r--src/location/doc/src/plugins/mapbox.qdoc67
-rw-r--r--src/location/doc/src/plugins/nokia.qdoc41
-rw-r--r--src/location/doc/src/plugins/osm.qdoc60
-rw-r--r--src/location/doc/src/qtlocation.qdoc12
-rw-r--r--src/location/location.pro8
-rw-r--r--src/location/maps/qabstractgeotilecache.cpp10
-rw-r--r--src/location/maps/qabstractgeotilecache_p.h15
-rw-r--r--src/location/maps/qcache3q_p.h18
-rw-r--r--src/location/maps/qgeocameratiles.cpp5
-rw-r--r--src/location/maps/qgeocameratiles_p.h1
-rw-r--r--src/location/maps/qgeofiletilecache.cpp211
-rw-r--r--src/location/maps/qgeofiletilecache_p.h23
-rw-r--r--src/location/maps/qgeomap.cpp20
-rw-r--r--src/location/maps/qgeomap_p.h18
-rw-r--r--src/location/maps/qgeomap_p_p.h16
-rw-r--r--src/location/maps/qgeoserviceprovider.cpp1
-rw-r--r--src/location/maps/qgeotiledmap.cpp35
-rw-r--r--src/location/maps/qgeotiledmap_p.h7
-rw-r--r--src/location/maps/qgeotiledmap_p_p.h4
-rw-r--r--src/location/maps/qgeotiledmappingmanagerengine.cpp4
-rw-r--r--src/location/maps/qgeotiledmapscene.cpp101
-rw-r--r--src/location/maps/qgeotilefetcher.cpp27
-rw-r--r--src/location/maps/qgeotilefetcher_p.h6
-rw-r--r--src/location/maps/qgeotilefetcher_p_p.h5
-rw-r--r--src/location/qlocationglobal_p.h63
-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
-rw-r--r--src/positioning/configure.json48
-rw-r--r--src/positioning/qgeosatelliteinfo.cpp2
-rw-r--r--tests/applications/positioning_backend/widget.cpp10
-rw-r--r--tests/applications/positioning_backend/widget.ui54
-rw-r--r--tests/auto/qgeocameracapabilities/qgeocameracapabilities.pro2
-rw-r--r--tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp14
-rw-r--r--tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp2
-rw-r--r--tests/plugins/declarativetestplugin/locationtest.cpp2
133 files changed, 6363 insertions, 845 deletions
diff --git a/.qmake.conf b/.qmake.conf
index a2a0d418..aefa1e70 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,3 +1,3 @@
load(qt_build_config)
-MODULE_VERSION = 5.7.1
+MODULE_VERSION = 5.8.0
diff --git a/config.tests/gypsy/gypsy.pro b/config.tests/gypsy/gypsy.pro
index f9dcffa9..93d56eb1 100644
--- a/config.tests/gypsy/gypsy.pro
+++ b/config.tests/gypsy/gypsy.pro
@@ -1,6 +1,2 @@
TEMPLATE = app
-unix {
- CONFIG += link_pkgconfig
- PKGCONFIG += gypsy gconf-2.0
-}
SOURCES += main.cpp
diff --git a/config.tests/winrt/main.cpp b/config.tests/winrt/main.cpp
new file mode 100644
index 00000000..e1b14959
--- /dev/null
+++ b/config.tests/winrt/main.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <functional>
+#include <windows.system.h>
+#include <windows.devices.geolocation.h>
+#include <windows.foundation.h>
+#include <wrl.h>
+
+using namespace Microsoft::WRL::Wrappers;
+using namespace ABI::Windows::Devices::Geolocation;
+using namespace ABI::Windows::Foundation;
+
+#if _MSC_VER >= 1900
+typedef IAsyncOperationCompletedHandler<GeolocationAccessStatus> AccessHandler;
+#endif
+
+int main(int, char**)
+{
+ IGeolocator *locator;
+ RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Devices_Geolocation_Geolocator).Get(),
+ reinterpret_cast<IInspectable**>(&locator));
+ return 0;
+}
diff --git a/config.tests/winrt/winrt.pro b/config.tests/winrt/winrt.pro
new file mode 100644
index 00000000..1476abc9
--- /dev/null
+++ b/config.tests/winrt/winrt.pro
@@ -0,0 +1,5 @@
+SOURCES += main.cpp
+win32-msvc201* {
+ LIBS += runtimeobject.lib
+ CONFIG += console
+}
diff --git a/configure.json b/configure.json
new file mode 100644
index 00000000..d54624af
--- /dev/null
+++ b/configure.json
@@ -0,0 +1,5 @@
+{
+ "subconfigs": [
+ "src/positioning"
+ ]
+}
diff --git a/qtlocation.pro b/qtlocation.pro
index 3104465f..53069981 100644
--- a/qtlocation.pro
+++ b/qtlocation.pro
@@ -1,4 +1,5 @@
load(configure)
qtCompileTest(gypsy)
+qtCompileTest(winrt)
load(qt_parts)
diff --git a/src/3rdparty/clip2tri/qt_attribution.json b/src/3rdparty/clip2tri/qt_attribution.json
new file mode 100644
index 00000000..1316f630
--- /dev/null
+++ b/src/3rdparty/clip2tri/qt_attribution.json
@@ -0,0 +1,13 @@
+{
+ "Id": "clip2tri",
+ "Name": "Clip2Tri Polygon Triangulation Library",
+ "QDocModule": "qtlocation",
+ "QtUsage": "Used in the QML plugin of Qt Location.",
+
+ "Description": "Clip2Tri can be used together with Clipper for robust triangulation.",
+ "Homepage": "https://github.com/raptor/clip2tri",
+ "LicenseId": "MIT",
+ "License": "MIT License",
+ "LicenseFile": "LICENSE",
+ "Copyright": "Copyright (c) 2014 Bitfighter developers"
+}
diff --git a/src/3rdparty/clip2tri_legal.qdoc b/src/3rdparty/clip2tri_legal.qdoc
deleted file mode 100644
index 65a5fa7f..00000000
--- a/src/3rdparty/clip2tri_legal.qdoc
+++ /dev/null
@@ -1,32 +0,0 @@
-/*!
-\page legal-clip2tri.html
-\title Clip2Tri Polygon Triangulation Library
-\ingroup licensing
-
-\legalese
-\code
-Clip2Tri Copyright (c) 2014 Bitfighter developers
-https://github.com/raptor/clip2tri
-
-The MIT License (MIT)
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-\endcode
-\endlegalese
-*/
diff --git a/src/3rdparty/clipper_legal.qdoc b/src/3rdparty/clipper/LICENSE
index 59b7f574..bc0d6b01 100644
--- a/src/3rdparty/clipper_legal.qdoc
+++ b/src/3rdparty/clipper/LICENSE
@@ -1,13 +1,3 @@
-/*!
-\page legal-clipper.html
-\title Clipper Polygon Clipping Library
-\ingroup licensing
-
-\legalese
-\code
-Clipper Copyright Angus Johnson 2010-2014
-http://www.angusj.com
-
Use, modification & distribution is subject to Boost Software License Ver 1.
http://www.boost.org/LICENSE_1_0.txt
@@ -29,6 +19,3 @@ ASME 2005 International Design Engineering Technical Conferences
and Computers and Information in Engineering Conference (IDETC/CIE2005)
September 24-28, 2005 , Long Beach, California, USA
http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf
-\endcode
-\endlegalese
-*/
diff --git a/src/3rdparty/clipper/qt_attribution.json b/src/3rdparty/clipper/qt_attribution.json
new file mode 100644
index 00000000..d64b091f
--- /dev/null
+++ b/src/3rdparty/clipper/qt_attribution.json
@@ -0,0 +1,13 @@
+{
+ "Id": "clipper",
+ "Name": "Clipper Polygon Clipping Library",
+ "QDocModule": "qtlocation",
+ "QtUsage": "Used in the QML plugin of Qt Location.",
+
+ "Description": "Clip2Tri can be used together with Clipper for robust triangulation.",
+ "Homepage": "http://www.angusj.com",
+ "LicenseId": "BSL-1.0",
+ "License": "Boost Software License 1.0",
+ "LicenseFile": "LICENSE",
+ "Copyright": "Copyright Angus Johnson 2010-2014"
+}
diff --git a/src/3rdparty/poly2tri/qt_attribution.json b/src/3rdparty/poly2tri/qt_attribution.json
new file mode 100644
index 00000000..fdc7c29e
--- /dev/null
+++ b/src/3rdparty/poly2tri/qt_attribution.json
@@ -0,0 +1,13 @@
+{
+ "Id": "poly2tri",
+ "Name": "Poly2Tri Polygon Triangulation Library",
+ "QDocModule": "qtlocation",
+ "QtUsage": "Used in the QML plugin of Qt Location.",
+
+ "Description": "Poly2Tri is a sweepline constrained Delaunay Polygon Triangulation Library.",
+ "Homepage": "http://code.google.com/p/poly2tri/",
+ "LicenseId": "BSD-3-Clause",
+ "License": "BSD 3-clause \"New\" or \"Revised\" License",
+ "LicenseFile": "LICENSE",
+ "Copyright": "Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors"
+}
diff --git a/src/3rdparty/poly2tri_legal.qdoc b/src/3rdparty/poly2tri_legal.qdoc
deleted file mode 100644
index acbb2646..00000000
--- a/src/3rdparty/poly2tri_legal.qdoc
+++ /dev/null
@@ -1,37 +0,0 @@
-/*!
-\page legal-poly2tri.html
-\title Poly2Tri Polygon Triangulation Library
-\ingroup licensing
-
-\legalese
-\code
-Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
-http://code.google.com/p/poly2tri/
-
-All rights reserved.
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-* Neither the name of Poly2Tri nor the names of its contributors may be
- used to endorse or promote products derived from this software without specific
- prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-\endcode
-\endlegalese
-*/
diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp
index b42933f0..6405313b 100644
--- a/src/imports/location/location.cpp
+++ b/src/imports/location/location.cpp
@@ -83,7 +83,7 @@ class QtLocationDeclarativeModule: public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0"
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid
FILE "plugin.json")
public:
diff --git a/src/imports/location/qdeclarativecirclemapitem.cpp b/src/imports/location/qdeclarativecirclemapitem.cpp
index f6b3c14f..6890703b 100644
--- a/src/imports/location/qdeclarativecirclemapitem.cpp
+++ b/src/imports/location/qdeclarativecirclemapitem.cpp
@@ -144,7 +144,7 @@ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QGeoMap &map)
if (!screenDirty_)
return;
- if (map.width() == 0 || map.height() == 0) {
+ if (map.viewportWidth() == 0 || map.viewportHeight() == 0) {
clear();
return;
}
@@ -176,7 +176,7 @@ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QGeoMap &map)
geoDistance += 360.0;
double mapWidth = 360.0 / geoDistance;
- qreal leftOffset = origin.x() - (map.width()/2.0 - mapWidth/2.0) - firstPointOffset_.x();
+ qreal leftOffset = origin.x() - (map.viewportWidth()/2.0 - mapWidth/2.0) - firstPointOffset_.x();
qreal topOffset = origin.y() - (midPoint.y() - mapWidth/2.0) - firstPointOffset_.y();
QPainterPath ppiBorder;
ppiBorder.moveTo(QPointF(-leftOffset, -topOffset));
@@ -613,7 +613,7 @@ void QDeclarativeCircleMapItem::updateCirclePathForRendering(QList<QGeoCoordinat
if ( geoDistance < 0 )
geoDistance += 360;
qreal mapWidth = 360.0 / geoDistance;
- mapWidth = qMin(static_cast<int>(mapWidth), map()->width());
+ mapWidth = qMin(static_cast<int>(mapWidth), map()->viewportWidth());
QDoubleVector2D prev = map()->coordinateToItemPosition(path.at(0), false);
// find the points in path where wrapping occurs
for (int i = 1; i <= path.count(); ++i) {
diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp
index dbea220f..0450bf56 100644
--- a/src/imports/location/qdeclarativegeomap.cpp
+++ b/src/imports/location/qdeclarativegeomap.cpp
@@ -45,7 +45,7 @@
#include <QtPositioning/QGeoCircle>
#include <QtPositioning/QGeoRectangle>
#include <QtQuick/QQuickWindow>
-#include <QtQuick/QSGSimpleRectNode>
+#include <QtQuick/QSGRectangleNode>
#include <QtQuick/private/qquickwindow_p.h>
#include <QtQml/qqmlinfo.h>
#include <cmath>
@@ -306,10 +306,10 @@ void QDeclarativeGeoMap::initialize()
// try to keep center change signal in the end
bool centerHasChanged = false;
- setMinimumZoomLevel(m_map->minimumZoomForMapSize(width(), height()));
+ setMinimumZoomLevel(m_map->minimumZoomAtViewportSize(width(), height()));
// set latitude bundary check
- m_maximumViewportLatitude = m_map->maximumLatitudeForZoom(m_cameraData.zoomLevel());
+ m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData.zoomLevel());
QGeoCoordinate center = m_cameraData.center();
center.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
@@ -393,7 +393,6 @@ void QDeclarativeGeoMap::mouseReleaseEvent(QMouseEvent *event)
{
if (isInteractive()) {
m_gestureArea->handleMouseReleaseEvent(event);
- ungrabMouse();
} else {
QQuickItem::mouseReleaseEvent(event);
}
@@ -476,13 +475,12 @@ QSGNode *QDeclarativeGeoMap::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
return 0;
}
- QSGSimpleRectNode *root = static_cast<QSGSimpleRectNode *>(oldNode);
+ QSGRectangleNode *root = static_cast<QSGRectangleNode *>(oldNode);
if (!root)
- root = new QSGSimpleRectNode(boundingRect(), m_color);
- else {
- root->setRect(boundingRect());
- root->setColor(m_color);
- }
+ root = window()->createRectangleNode();
+
+ root->setRect(boundingRect());
+ root->setColor(m_color);
QSGNode *content = root->childCount() ? root->firstChild() : 0;
content = m_map->updateSceneGraph(content, window());
@@ -561,7 +559,7 @@ void QDeclarativeGeoMap::mappingManagerInitialized()
// after this has been called at least once, after creation.
if (!m_initialized && width() > 0 && height() > 0) {
- m_map->setSize(QSize(width(), height()));
+ m_map->setViewportSize(QSize(width(), height()));
initialize();
}
@@ -617,7 +615,7 @@ void QDeclarativeGeoMap::setMinimumZoomLevel(qreal minimumZoomLevel)
if (m_map) {
minimumZoomLevel = qBound(qreal(m_map->cameraCapabilities().minimumZoomLevel()), minimumZoomLevel, maximumZoomLevel());
- double minimumViewportZoomLevel = m_map->minimumZoomForMapSize(width(),height());
+ double minimumViewportZoomLevel = m_map->minimumZoomAtViewportSize(width(),height());
if (minimumZoomLevel < minimumViewportZoomLevel)
minimumZoomLevel = minimumViewportZoomLevel;
}
@@ -716,7 +714,7 @@ void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel)
if (m_initialized) {
m_cameraData.setZoomLevel(qBound(minimumZoomLevel(), zoomLevel, maximumZoomLevel()));
- m_maximumViewportLatitude = m_map->maximumLatitudeForZoom(m_cameraData.zoomLevel());
+ m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData.zoomLevel());
QGeoCoordinate coord = m_cameraData.center();
coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
if (coord != m_cameraData.center()) {
@@ -1040,8 +1038,8 @@ void QDeclarativeGeoMap::pan(int dx, int dy)
if (dx == 0 && dy == 0)
return;
QGeoCoordinate coord = m_map->itemPositionToCoordinate(
- QDoubleVector2D(m_map->width() / 2 + dx,
- m_map->height() / 2 + dy));
+ QDoubleVector2D(m_map->viewportWidth() / 2 + dx,
+ m_map->viewportHeight() / 2 + dy));
setCenter(coord);
}
@@ -1115,10 +1113,6 @@ void QDeclarativeGeoMap::touchEvent(QTouchEvent *event)
{
if (isInteractive()) {
m_gestureArea->handleTouchEvent(event);
- if ( event->type() == QEvent::TouchEnd ||
- event->type() == QEvent::TouchCancel) {
- ungrabTouchPoints();
- }
} else {
//ignore event so sythesized event is generated;
QQuickItem::touchEvent(event);
@@ -1208,13 +1202,11 @@ void QDeclarativeGeoMap::addMapItem(QDeclarativeGeoMapItemBase *item)
{
if (!item || item->quickMap())
return;
- m_updateMutex.lock();
item->setParentItem(this);
if (m_map)
item->setMap(this, m_map);
m_mapItems.append(item);
emit mapItemsChanged();
- m_updateMutex.unlock();
}
/*!
@@ -1254,13 +1246,11 @@ void QDeclarativeGeoMap::removeMapItem(QDeclarativeGeoMapItemBase *ptr)
QPointer<QDeclarativeGeoMapItemBase> item(ptr);
if (!m_mapItems.contains(item))
return;
- m_updateMutex.lock();
item.data()->setParentItem(0);
item.data()->setMap(0, 0);
// these can be optimized for perf, as we already check the 'contains' above
m_mapItems.removeOne(item);
emit mapItemsChanged();
- m_updateMutex.unlock();
}
/*!
@@ -1274,7 +1264,6 @@ void QDeclarativeGeoMap::clearMapItems()
{
if (m_mapItems.isEmpty())
return;
- m_updateMutex.lock();
for (int i = 0; i < m_mapItems.count(); ++i) {
if (m_mapItems.at(i)) {
m_mapItems.at(i).data()->setParentItem(0);
@@ -1283,7 +1272,6 @@ void QDeclarativeGeoMap::clearMapItems()
}
m_mapItems.clear();
emit mapItemsChanged();
- m_updateMutex.unlock();
}
/*!
@@ -1322,12 +1310,12 @@ void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF
if (!m_map || !newGeometry.size().isValid())
return;
- m_map->setSize(newGeometry.size().toSize());
+ m_map->setViewportSize(newGeometry.size().toSize());
if (!m_initialized)
initialize();
else
- setMinimumZoomLevel(m_map->minimumZoomForMapSize(newGeometry.width(), newGeometry.height()));
+ setMinimumZoomLevel(m_map->minimumZoomAtViewportSize(newGeometry.width(), newGeometry.height()));
/*!
The fitViewportTo*() functions depend on a valid map geometry.
@@ -1495,19 +1483,21 @@ bool QDeclarativeGeoMap::sendMouseEvent(QMouseEvent *event)
}
}
- if (event->type() == QEvent::MouseButtonRelease) {
- if (win && win->mouseGrabberItem() == this)
- ungrabMouse();
- }
-
return false;
}
bool QDeclarativeGeoMap::sendTouchEvent(QTouchEvent *event)
{
- QQuickWindowPrivate *win = window() ? QQuickWindowPrivate::get(window()) : 0;
+ const QQuickPointerDevice *touchDevice = QQuickPointerDevice::touchDevice(event->device());
const QTouchEvent::TouchPoint &point = event->touchPoints().first();
- QQuickItem *grabber = win ? win->itemForTouchPointId.value(point.id()) : 0;
+
+ auto touchPointGrabberItem = [touchDevice](const QTouchEvent::TouchPoint &point) -> QQuickItem* {
+ if (QQuickEventPoint *eventPointer = touchDevice->pointerEvent()->pointById(point.id()))
+ return eventPointer->grabber();
+ return nullptr;
+ };
+
+ QQuickItem *grabber = touchPointGrabberItem(point);
bool stealEvent = m_gestureArea->isActive();
bool containsPoint = contains(mapFromScene(point.scenePos()));
@@ -1519,7 +1509,7 @@ bool QDeclarativeGeoMap::sendTouchEvent(QTouchEvent *event)
m_gestureArea->handleTouchEvent(touchEvent.data());
stealEvent = m_gestureArea->isActive();
- grabber = win ? win->itemForTouchPointId.value(point.id()) : 0;
+ grabber = touchPointGrabberItem(point);
if (grabber && stealEvent && !grabber->keepTouchGrab() && grabber != this) {
QVector<int> ids;
@@ -1540,11 +1530,6 @@ bool QDeclarativeGeoMap::sendTouchEvent(QTouchEvent *event)
}
}
- if (event->type() == QEvent::TouchEnd) {
- if (win && win->itemForTouchPointId.value(point.id()) == this) {
- ungrabTouchPoints();
- }
- }
return false;
}
diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h
index d1d69656..262314ed 100644
--- a/src/imports/location/qdeclarativegeomap_p.h
+++ b/src/imports/location/qdeclarativegeomap_p.h
@@ -54,7 +54,6 @@
#include "qgeocameradata_p.h"
#include <QtQuick/QQuickItem>
#include <QtCore/QPointer>
-#include <QtCore/QMutex>
#include <QtGui/QColor>
#include <QtPositioning/qgeoshape.h>
@@ -193,7 +192,6 @@ private:
QGeoMap *m_map;
QPointer<QDeclarativeGeoMapCopyrightNotice> m_copyrights;
QList<QPointer<QDeclarativeGeoMapItemBase> > m_mapItems;
- QMutex m_updateMutex;
QString m_errorString;
QGeoServiceProvider::Error m_error;
QGeoShape m_region;
diff --git a/src/imports/location/qdeclarativegeomapitembase.cpp b/src/imports/location/qdeclarativegeomapitembase.cpp
index 8e825f5b..1788f740 100644
--- a/src/imports/location/qdeclarativegeomapitembase.cpp
+++ b/src/imports/location/qdeclarativegeomapitembase.cpp
@@ -198,18 +198,14 @@ float QDeclarativeGeoMapItemBase::zoomLevelOpacity() const
bool QDeclarativeGeoMapItemBase::childMouseEventFilter(QQuickItem *item, QEvent *event)
{
Q_UNUSED(item)
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- case QEvent::MouseButtonRelease:
- if (contains(static_cast<QMouseEvent*>(event)->pos())) {
- return false;
- } else {
- event->setAccepted(false);
- return true;
- }
- default:
- return false;
+ if (event->type() == QEvent::MouseButtonPress && !contains(static_cast<QMouseEvent*>(event)->pos())) {
+ // This is an evil hack: in case of items that are not rectangles, we never accept the event.
+ // Instead the events are now delivered to QDeclarativeGeoMapItemBase which doesn't to anything with them.
+ // The map below it still works since it filters events and steals the events at some point.
+ event->setAccepted(false);
+ return true;
}
+ return false;
}
/*!
diff --git a/src/imports/location/qdeclarativegeomapitemview_p.h b/src/imports/location/qdeclarativegeomapitemview_p.h
index 6a4a2921..fefc63ba 100644
--- a/src/imports/location/qdeclarativegeomapitemview_p.h
+++ b/src/imports/location/qdeclarativegeomapitemview_p.h
@@ -139,7 +139,7 @@ private:
int m_readyIncubators;
bool m_repopulating;
- friend class QDeclarativeGeoMapItemViewItemData;
+ friend struct QDeclarativeGeoMapItemViewItemData;
friend class MapItemViewDelegateIncubator;
};
diff --git a/src/imports/location/qdeclarativepolygonmapitem.cpp b/src/imports/location/qdeclarativepolygonmapitem.cpp
index 3d981406..32dbb206 100644
--- a/src/imports/location/qdeclarativepolygonmapitem.cpp
+++ b/src/imports/location/qdeclarativepolygonmapitem.cpp
@@ -214,7 +214,7 @@ void QGeoMapPolygonGeometry::updateScreenPoints(const QGeoMap &map)
if (!screenDirty_)
return;
- if (map.width() == 0 || map.height() == 0) {
+ if (map.viewportWidth() == 0 || map.viewportHeight() == 0) {
clear();
return;
}
@@ -223,7 +223,7 @@ void QGeoMapPolygonGeometry::updateScreenPoints(const QGeoMap &map)
// Create the viewport rect in the same coordinate system
// as the actual points
- QRectF viewport(0, 0, map.width(), map.height());
+ QRectF viewport(0, 0, map.viewportWidth(), map.viewportHeight());
viewport.translate(-1 * origin.toPointF());
QPainterPath vpPath;
@@ -667,7 +667,7 @@ MapPolygonNode::MapPolygonNode() :
geometry_(QSGGeometry::defaultAttributes_Point2D(), 0),
blocked_(true)
{
- geometry_.setDrawingMode(GL_TRIANGLES);
+ geometry_.setDrawingMode(QSGGeometry::DrawTriangles);
QSGGeometryNode::setMaterial(&fill_material_);
QSGGeometryNode::setGeometry(&geometry_);
diff --git a/src/imports/location/qdeclarativepolylinemapitem.cpp b/src/imports/location/qdeclarativepolylinemapitem.cpp
index 3c29ad2b..2153b036 100644
--- a/src/imports/location/qdeclarativepolylinemapitem.cpp
+++ b/src/imports/location/qdeclarativepolylinemapitem.cpp
@@ -200,9 +200,9 @@ void QGeoMapPolylineGeometry::updateSourcePoints(const QGeoMap &map,
srcPointTypes_.clear();
srcPointTypes_.reserve(path.size());
- QDoubleVector2D origin, lastPoint, lastAddedPoint;
+ QDoubleVector2D origin, lastAddedPoint;
- const double mapWidthHalf = map.width()/2.0;
+ const double mapWidthHalf = map.viewportWidth()/2.0;
double unwrapBelowX = 0;
if (preserveGeometry_)
unwrapBelowX = map.coordinateToItemPosition(geoLeftBound_, false).x();
@@ -263,8 +263,6 @@ void QGeoMapPolylineGeometry::updateSourcePoints(const QGeoMap &map,
lastAddedPoint = point;
}
}
-
- lastPoint = point;
}
sourceBounds_ = QRectF(QPointF(minX, minY), QPointF(maxX, maxY));
@@ -402,7 +400,7 @@ void QGeoMapPolylineGeometry::updateScreenPoints(const QGeoMap &map,
// Create the viewport rect in the same coordinate system
// as the actual points
- QRectF viewport(0, 0, map.width(), map.height());
+ QRectF viewport(0, 0, map.viewportWidth(), map.viewportHeight());
viewport.adjust(-strokeWidth, -strokeWidth, strokeWidth, strokeWidth);
viewport.translate(-1 * origin);
@@ -965,7 +963,7 @@ MapPolylineNode::MapPolylineNode() :
geometry_(QSGGeometry::defaultAttributes_Point2D(),0),
blocked_(true)
{
- geometry_.setDrawingMode(GL_TRIANGLE_STRIP);
+ geometry_.setDrawingMode(QSGGeometry::DrawTriangleStrip);
QSGGeometryNode::setMaterial(&fill_material_);
QSGGeometryNode::setGeometry(&geometry_);
}
diff --git a/src/imports/location/qgeomapitemgeometry.cpp b/src/imports/location/qgeomapitemgeometry.cpp
index e9c490d5..a22be0af 100644
--- a/src/imports/location/qgeomapitemgeometry.cpp
+++ b/src/imports/location/qgeomapitemgeometry.cpp
@@ -70,11 +70,11 @@ void QGeoMapItemGeometry::allocateAndFill(QSGGeometry *geom) const
if (isIndexed()) {
geom->allocate(vx.size(), ix.size());
- if (geom->indexType() == GL_UNSIGNED_SHORT) {
+ if (geom->indexType() == QSGGeometry::UnsignedShortType) {
quint16 *its = geom->indexDataAsUShort();
for (int i = 0; i < ix.size(); ++i)
its[i] = ix[i];
- } else if (geom->indexType() == GL_UNSIGNED_INT) {
+ } else if (geom->indexType() == QSGGeometry::UnsignedIntType) {
quint32 *its = geom->indexDataAsUInt();
for (int i = 0; i < ix.size(); ++i)
its[i] = ix[i];
@@ -125,7 +125,7 @@ double QGeoMapItemGeometry::geoDistanceToScreenWidth(const QGeoMap &map,
// Do not wrap around half the globe
Q_ASSERT(!qFuzzyCompare(fromCoord.longitude(), toCoord.longitude()));
- QGeoCoordinate mapMid = map.itemPositionToCoordinate(QDoubleVector2D(map.width()/2.0, 0));
+ QGeoCoordinate mapMid = map.itemPositionToCoordinate(QDoubleVector2D(map.viewportWidth()/2.0, 0));
double halfGeoDist = toCoord.longitude() - fromCoord.longitude();
if (toCoord.longitude() < fromCoord.longitude())
halfGeoDist += 360;
@@ -133,7 +133,7 @@ double QGeoMapItemGeometry::geoDistanceToScreenWidth(const QGeoMap &map,
QGeoCoordinate geoDelta = QGeoCoordinate(0,
QLocationUtils::wrapLong(mapMid.longitude() + halfGeoDist));
QDoubleVector2D halfScreenDist = map.coordinateToItemPosition(geoDelta, false)
- - QDoubleVector2D(map.width()/2.0, 0);
+ - QDoubleVector2D(map.viewportWidth()/2.0, 0);
return halfScreenDist.x() * 2.0;
}
diff --git a/src/imports/location/qquickgeomapgesturearea.cpp b/src/imports/location/qquickgeomapgesturearea.cpp
index 1a3b3c16..0baaf98e 100644
--- a/src/imports/location/qquickgeomapgesturearea.cpp
+++ b/src/imports/location/qquickgeomapgesturearea.cpp
@@ -661,7 +661,7 @@ void QQuickGeoMapGestureArea::handleTouchUngrabEvent()
{
m_touchPoints.clear();
//this is needed since in some cases mouse release is not delivered
- //(second touch point brakes mouse synthesized events)
+ //(second touch point breaks mouse synthesized events)
m_mousePoint.reset();
update();
}
@@ -672,8 +672,13 @@ void QQuickGeoMapGestureArea::handleTouchUngrabEvent()
void QQuickGeoMapGestureArea::handleTouchEvent(QTouchEvent *event)
{
m_touchPoints.clear();
- for (int i = 0; i < event->touchPoints().count(); ++i)
- m_touchPoints << event->touchPoints().at(i);
+ m_mousePoint.reset();
+
+ for (int i = 0; i < event->touchPoints().count(); ++i) {
+ auto point = event->touchPoints().at(i);
+ if (point.state() != Qt::TouchPointReleased)
+ m_touchPoints << point;
+ }
if (event->touchPoints().count() >= 2)
event->accept();
else
@@ -697,7 +702,7 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event)
{
qreal dx = postZoomPoint.x() - preZoomPoint.x();
qreal dy = postZoomPoint.y() - preZoomPoint.y();
- QPointF mapCenterPoint(m_map->width() / 2.0 + dx, m_map->height() / 2.0 + dy);
+ QPointF mapCenterPoint(m_map->viewportWidth() / 2.0 + dx, m_map->viewportHeight() / 2.0 + dy);
QGeoCoordinate mapCenterCoordinate = m_map->itemPositionToCoordinate(QDoubleVector2D(mapCenterPoint), false);
m_declarativeMap->setCenter(mapCenterCoordinate);
@@ -1012,11 +1017,6 @@ void QQuickGeoMapGestureArea::updatePinch()
// Add to starting zoom level. Sign of (dist-pinchstartdist) takes care of zoom in / out
m_pinch.m_zoom.m_start;
}
- qreal da = m_pinch.m_lastAngle - m_twoTouchAngle;
- if (da > 180)
- da -= 360;
- else if (da < -180)
- da += 360;
m_pinch.m_event.setCenter(mapFromScene(m_sceneCenter));
m_pinch.m_event.setAngle(m_twoTouchAngle);
@@ -1148,8 +1148,8 @@ void QQuickGeoMapGestureArea::updatePan()
int dx = static_cast<int>(m_sceneCenter.x() - startPoint.x());
int dy = static_cast<int>(m_sceneCenter.y() - startPoint.y());
QPointF mapCenterPoint;
- mapCenterPoint.setY(m_map->height() / 2.0 - dy);
- mapCenterPoint.setX(m_map->width() / 2.0 - dx);
+ mapCenterPoint.setY(m_map->viewportHeight() / 2.0 - dy);
+ mapCenterPoint.setX(m_map->viewportWidth() / 2.0 - dx);
QGeoCoordinate animationStartCoordinate = m_map->itemPositionToCoordinate(QDoubleVector2D(mapCenterPoint), false);
m_declarativeMap->setCenter(animationStartCoordinate);
}
@@ -1277,6 +1277,7 @@ void QQuickGeoMapGestureArea::handleFlickAnimationStopped()
if (m_flickState == flickActive) {
m_flickState = flickInactive;
emit flickFinished();
+ emit panActiveChanged();
m_map->prefetchData();
}
}
diff --git a/src/imports/positioning/positioning.cpp b/src/imports/positioning/positioning.cpp
index 5137da22..4c54c211 100644
--- a/src/imports/positioning/positioning.cpp
+++ b/src/imports/positioning/positioning.cpp
@@ -506,7 +506,7 @@ class QtPositioningDeclarativeModule: public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0"
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid
FILE "plugin.json")
public:
diff --git a/src/location/doc/src/plugins/esri.qdoc b/src/location/doc/src/plugins/esri.qdoc
new file mode 100644
index 00000000..6ac65910
--- /dev/null
+++ b/src/location/doc/src/plugins/esri.qdoc
@@ -0,0 +1,239 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+/*!
+\page location-plugin-esri.html
+\title Qt Location Esri Plugin
+\ingroup QtLocation-plugins
+
+\brief Uses Esri for location services.
+
+\section1 Overview
+
+This geo services plugin allows applications to access
+\l {http://www.esri.com}{Esri} location based services using the Qt Location API.
+The use of these services is governed by the \l {http://www.esri.com/legal/terms-use}{Esri terms of use}.
+
+Data is provided by \l {http://www.esri.com/data/find-data}{many different content providers}.
+
+The Esri geoservices plugin can be loaded by using the plugin key "esri".
+
+To use the services provided by the Esri platform, a subscription is required. There are two kinds of subscriptions:
+
+\list
+ \li \l {https://developers.arcgis.com/plans/}{Developer Subscription}
+ \li \l {http://www.arcgis.com/features/plans/pricing.html}{ArcGIS Online Subscription}
+\endlist
+
+The Developer subscription offers a free-of-charge option for developing and testing your applications.
+With this, your applications can go to production under the following conditions:
+
+\list
+ \li The app can request up to one million maps per month, and one million geocodes per month.
+ \li The app does not directly generate revenue. That is, end users must be able to obtain it and to use it for free.
+\endlist
+
+If the above conditions cannot be met, the ArcGIS Online subscription is the correct choice, as it
+gives applications full access to the ArcGIS platform.
+
+\section1 Parameters
+
+\section2 Mandatory parameters
+
+\table
+\header
+ \li Parameter
+ \li Description
+\row
+ \li esri.token
+ \li Security token for using routing services only. Mapping and geocoding services do not require a token.
+\endtable
+
+To use the routing services hosted on ArcGIS Online with the Esri plugin, a token is required.
+You can \l{https://developers.arcgis.com/authentication/accessing-arcgis-online-services/#registering-your-application}{obtain a token for testing purposes},
+or you can sign up for an \l {http://www.arcgis.com/features/plans/pricing.html}{ArcGIS Online subscription}.
+
+\section2 Optional parameters
+
+\table
+\header
+ \li Parameter
+ \li Description
+\row
+ \li esri.useragent
+ \li User agent string sent when making network requests
+\row
+ \li esri.mapping.minimumZoomLevel
+ \li The minimum zoom level [double] at which the map is displayed
+\row
+ \li esri.mapping.maximumZoomLevel
+ \li The maximum level [double] at which the map is displayed
+\row
+ \li esri.mapping.cache.directory
+ \li Absolute path to map tile cache directory used as network disk cache.
+
+ The default place for the cache is \c{QtLocation/here} directory in
+ \l {QStandardPaths::writableLocation()} {QStandardPaths::writableLocation}(\l{QStandardPaths::GenericCacheLocation}).
+ On systems that have no concept of a shared cache, the application-specific
+ \l{QStandardPaths::CacheLocation} is used instead.
+\row
+ \li esri.mapping.cache.disk.cost_strategy
+ \li The cost strategy to use to cache map tiles on disk.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b esri.mapping.cache.disk.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
+ \li esri.mapping.cache.disk.size
+ \li Disk cache size for map tiles. The default size of the cache is 50 MiB when \b bytesize is the cost
+ strategy for this cache, or 1000 tiles, when \b unitary is the cost strategy.
+\row
+ \li esri.mapping.cache.memory.cost_strategy
+ \li The cost strategy to use to cache map tiles in memory.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b esri.mapping.cache.memory.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
+ \li esri.mapping.cache.memory.size
+ \li Memory cache size for map tiles. The default size of the cache is 3 MiB when \b bytesize is the cost
+ strategy for this cache, or 100 tiles, when \b unitary is the cost strategy.
+\row
+ \li esri.mapping.cache.texture.cost_strategy
+ \li The cost strategy to use to cache decompressed map tiles in memory.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b esri.mapping.cache.texture.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
+ \li esri.mapping.cache.texture.size
+ \li Texture cache size for map tiles. The default size of the cache is 6 MiB when \b bytesize is the cost
+ strategy for this cache, or 30 tiles, when \b unitary is the cost strategy.
+ Note that the texture cache has a hard minimum size which depends on the size of the map viewport
+ (it must contain enough data to display the tiles currently visible on the display).
+ This value is the amount of cache to be used in addition to the bare minimum.
+\endtable
+
+\section2 Directions language
+
+The service supports generating directions in the following languages:
+
+\table
+\header
+ \li Language
+ \li Description
+\row
+ \li ar
+ \li Generate directions in Arabic
+\row
+ \li cs
+ \li Generate directions in Czech
+\row
+ \li de
+ \li Generate directions in German
+\row
+ \li el
+ \li Generate directions in Greek
+\row
+ \li en
+ \li (default) Generate directions in English
+\row
+ \li es
+ \li Generate directions in Spanish
+\row
+ \li et
+ \li Generate directions in Estonian
+\row
+ \li fr
+ \li Generate directions in French
+\row
+ \li he
+ \li Generate directions in Hebrew
+\row
+ \li it
+ \li Generate directions in Italian
+\row
+ \li ja
+ \li Generate directions in Japanese
+\row
+ \li ko
+ \li Generate directions in Korean
+\row
+ \li lt
+ \li Generate directions in Lithuanian
+\row
+ \li lv
+ \li Generate directions in Latvian
+\row
+ \li nl
+ \li Generate directions in Dutch
+\row
+ \li pl
+ \li Generate directions in Polish
+\row
+ \li pt-BR
+ \li Generate directions in Brazilian Portuguese
+\row
+ \li pt-PT
+ \li Generate directions in Portuguese (Portugal)
+\row
+ \li ru
+ \li Generate directions in Russian
+\row
+ \li sv
+ \li Generate directions in Swedish
+\row
+ \li tr
+ \li Generate directions in Turkish
+\row
+ \li zh-CN
+ \li Simplified Chinese
+\endtable
+
+If only unsupported language codes are specified via the \l{http://doc.qt.io/qt-5/qml-qtlocation-plugin.html#locales-prop}
+{locales} property, the service returns the directions using the default language, English.
+
+\section2 Directions length units
+
+QLocale::MetricSystem (default) use meters, other values (QLocale::ImperialUSSystem, QLocale::ImperialUSSystem) use feet.
+
+*/
diff --git a/src/location/doc/src/plugins/mapbox.qdoc b/src/location/doc/src/plugins/mapbox.qdoc
index 6cd326ba..dfa83713 100644
--- a/src/location/doc/src/plugins/mapbox.qdoc
+++ b/src/location/doc/src/plugins/mapbox.qdoc
@@ -53,9 +53,6 @@ The following table lists mandatory parameters that \e must be passed to the Map
\row
\li mapbox.access_token
\li \l{https://www.mapbox.com/help/define-access-token/}{Access token} provided by Mapbox.
-\row
- \li mapbox.map_id
- \li \l{https://www.mapbox.com/help/define-map-id/}{ID} of the Mapbox map to show. An example ID is "examples.map-zr0njcqy".
\endtable
The Mapbox geo services plugin requires an access token and map ID to use the
@@ -69,13 +66,75 @@ The following table lists optional parameters that can be passed to the Mapbox p
\li Parameter
\li Description
\row
- \li mapbox.format
+ \li mapbox.mapping.map_id, mapbox.map_id (\b deprecated)
+ \li \l{https://www.mapbox.com/help/define-map-id/}{ID} of the Mapbox map to show. An example ID is "examples.map-zr0njcqy".
+ If this parameter is present, the specified map type will be used by default, unless another is selected.
+ If not present, the default Mapbox map ID is "mapbox.streets".
+\row
+ \li mapbox.mapping.additional_map_ids
+ \li Additional, comma separated, Mapbox map IDs to be added to the available map types.
+\row
+ \li mapbox.mapping.format, mapbox.format (\b deprecated)
\li Data format to download tiles in, available values are "png", "png32",
"png64", "png128", "png256", (PNG with full, 32, 64, 128 and 256 color palette)
"jpg70", "jpg80", "jpg90" (JPEG with 70%, 80% and 90% compression).
Defaults to "png".
\row
+ \li mapbox.mapping.highdpi_tiles
+ \li Whether or not to request high dpi tiles. Valid values are \b true and \b false. The default value is \b false.
+\row
\li useragent
\li User agent string set when making network requests.
+\row
+ \li mapbox.mapping.cache.directory
+ \li Absolute path to map tile cache directory used as network disk cache.
+
+ The default place for the cache is \c{QtLocation/mapbox} directory in \l {QStandardPaths::writableLocation()} {QStandardPaths::writableLocation}(\l{QStandardPaths::GenericCacheLocation}).
+ On systems that have no concept of a shared cache, the application-specific \l{QStandardPaths::CacheLocation} is used instead.
+\row
+ \li mapbox.mapping.cache.disk.cost_strategy
+ \li The cost strategy to use to cache map tiles on disk.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b mapbox.mapping.cache.disk.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b unitary.
+\row
+ \li mapbox.mapping.cache.disk.size
+ \li Disk cache size for map tiles.
+ The default size of this cache is 6000 if \b unitary is used as cost strategy,
+ or 50 MiB, if \b bytesize is used as cost strategy.
+ Note that 6000 is the maximum amount of tiles that the Mapbox free plan allows to cache.
+ Make sure to comply with Mapbox Terms of Service before increasing this value.
+\row
+ \li mapbox.mapping.cache.memory.cost_strategy
+ \li The cost strategy to use to cache map tiles in memory.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b mapbox.mapping.cache.memory.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
+ \li mapbox.mapping.cache.memory.size
+ \li Memory cache size for map tiles.
+ The Default size of this cache is 100 if \b unitary is used as cost strategy, or
+ 3 MiB, if \b bytesize is used as cost strategy.
+\row
+ \li mapbox.mapping.cache.texture.cost_strategy
+ \li The cost strategy to use to cache decompressed map tiles in memory.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b mapbox.mapping.cache.texture.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
+ \li mapbox.mapping.cache.texture.size
+ \li Texture cache size for map tiles.
+ The Default size of this cache is 30 if \b unitary is used as cost strategy, or
+ 6 MiB, if \b bytesize is used as cost strategy.
+ Note that the texture cache has a hard minimum size which depends on the size of the map
+ viewport (it must contain enough data to display the tiles currently visible on the
+ display).
+ This value is the amount of tiles to be cached in addition to the bare minimum.
\endtable
*/
diff --git a/src/location/doc/src/plugins/nokia.qdoc b/src/location/doc/src/plugins/nokia.qdoc
index 1ed5e6e1..7e2fa512 100644
--- a/src/location/doc/src/plugins/nokia.qdoc
+++ b/src/location/doc/src/plugins/nokia.qdoc
@@ -96,14 +96,47 @@ a prefix.
On systems that have no concept of a shared cache, the application-specific \l{QStandardPaths::CacheLocation} is used instead.
\row
+ \li here.mapping.cache.disk.cost_strategy
+ \li The cost strategy to use to cache map tiles on disk.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b here.mapping.cache.disk.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
\li here.mapping.cache.disk.size
- \li Map tile disk cache size in bytes. Default size of the cache is 20MB.
+ \li Disk cache size for map tiles. The default size of the cache is 50 MiB when \b bytesize is the cost
+ strategy for this cache, or 1000 tiles, when \b unitary is the cost strategy.
+\row
+ \li here.mapping.cache.memory.cost_strategy
+ \li The cost strategy to use to cache map tiles in memory.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b here.mapping.cache.memory.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
\row
\li here.mapping.cache.memory.size
- \li Map tile memory cache size in bytes. Default size of the cache is 3MB.
+ \li Memory cache size for map tiles. The default size of the cache is 3 MiB when \b bytesize is the cost
+ strategy for this cache, or 100 tiles, when \b unitary is the cost strategy.
+\row
+ \li here.mapping.cache.texture.cost_strategy
+ \li The cost strategy to use to cache decompressed map tiles in memory.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b here.mapping.cache.texture.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
+ \li osm.mapping.cache.texture.size
+ \li Texture cache size for map tiles. The default size of the cache is 6 MiB when \b bytesize is the cost
+ strategy for this cache, or 30 tiles, when \b unitary is the cost strategy.
+ Note that the texture cache has a hard minimum size which depends on the size of the map viewport
+ (it must contain enough data to display the tiles currently visible on the display).
+ This value is the amount of cache to be used in addition to the bare minimum.
\row
- \li here.mapping.cache.texture.size
- \li Map tile texture cache size in bytes. Default size of the cache is 6MB. Note that the texture cache has a hard minimum size which depends on the size of the map viewport (it must contain enough data to display the tiles currently visible on the display). This value is the amount of cache to be used in addition to the bare minimum.
+ \li here.mapping.highdpi_tiles
+ \li Whether or not to request high dpi tiles. Valid values are \b true and \b false. The default value is \b false.
\row
\li here.geocoding.host
\li Geocoding service URL used by geocoding manager.
diff --git a/src/location/doc/src/plugins/osm.qdoc b/src/location/doc/src/plugins/osm.qdoc
index a0f2bc2b..bb520601 100644
--- a/src/location/doc/src/plugins/osm.qdoc
+++ b/src/location/doc/src/plugins/osm.qdoc
@@ -92,6 +92,13 @@ a prefix.
The plugin, however, still contains fallback hardcoded provider data, in case the provider repository becomes unreachable.
Setting this parameter to \b true makes the plugin use the hardcoded urls only and therefore prevents the plugin from fetching provider data from the remote repository.
\row
+ \li osm.mapping.highdpi_tiles
+ \li Whether or not to request high dpi tiles. Valid values are \b true and \b false. The default value is \b false.
+ Please note that not all map types are available in high dpi. Setting this parameter to true might even have no effect if
+ no map type is available in high dpi at the moment. Provider information files for high dpi tiles are named
+ \tt{street-hires}, \tt{satellite-hires}, \tt{cycle-hires}, \tt{transit-hires}, \tt{night-transit-hires}, \tt{terrain-hires} and \tt{hiking-hires}.
+ These are fetched from the same location used for the low dpi counterparts.
+\row
\li osm.routing.host
\li Url string set when making network requests to the routing server. This parameter should be set to a
valid server url with the correct osrm API. If not specified the default \l {http://router.project-osrm.org/route/v1/driving/}{url} will be used.
@@ -114,6 +121,59 @@ a prefix.
If not specified the default \l {http://nominatim.openstreetmap.org/search}{url}
will be used.
\note The API documentation is available at \l {https://wiki.openstreetmap.org/wiki/Nominatim}{Project OSM Nominatim}.
+\row
+ \li osm.mapping.cache.directory
+ \li Absolute path to map tile cache directory used as network disk cache.
+
+ The default place for the cache is \c{QtLocation/osm} directory in \l {QStandardPaths::writableLocation()} {QStandardPaths::writableLocation}(\l{QStandardPaths::GenericCacheLocation}).
+ On systems that have no concept of a shared cache, the application-specific \l{QStandardPaths::CacheLocation} is used instead.
+\row
+ \li osm.mapping.offline.directory
+ \li Absolute path to a directory containing map tiles used as an offline storage. If specified, it will work together with the network disk cache, but tiles won't get automatically
+ inserted, removed or updated. The format of the tiles is the same used by the network disk cache.
+
+ There is no default value, and if this property is not set, no directory will be indexed and only the network disk cache will be used
+ to reduce network usage or to act as an offline storage for the currently cached tiles.
+\row
+ \li osm.mapping.cache.disk.cost_strategy
+ \li The cost strategy to use to cache map tiles on disk.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b osm.mapping.cache.disk.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
+ \li osm.mapping.cache.disk.size
+ \li Disk cache size for map tiles. The default size of the cache is 50 MiB when \b bytesize is the cost
+ strategy for this cache, or 1000 tiles, when \b unitary is the cost strategy.
+\row
+ \li osm.mapping.cache.memory.cost_strategy
+ \li The cost strategy to use to cache map tiles in memory.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b osm.mapping.cache.memory.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
+ \li osm.mapping.cache.memory.size
+ \li Memory cache size for map tiles. The default size of the cache is 3 MiB when \b bytesize is the cost
+ strategy for this cache, or 100 tiles, when \b unitary is the cost strategy.
+\row
+ \li osm.mapping.cache.texture.cost_strategy
+ \li The cost strategy to use to cache decompressed map tiles in memory.
+ Valid values are \b bytesize and \b unitary.
+ Using \b bytesize, the related size parameter (\b osm.mapping.cache.texture.size) will
+ be interpreted as bytes.
+ Using \b unitary, they will be interpreted as number of tiles.
+ The default value for this parameter is \b bytesize.
+\row
+ \li osm.mapping.cache.texture.size
+ \li Texture cache size for map tiles. The default size of the cache is 6 MiB when \b bytesize is the cost
+ strategy for this cache, or 30 tiles, when \b unitary is the cost strategy.
+ Note that the texture cache has a hard minimum size which depends on the size of the map viewport
+ (it must contain enough data to display the tiles currently visible on the display).
+ This value is the amount of cache to be used in addition to the bare minimum.
+
\endtable
\section1 Parameter Usage Example
diff --git a/src/location/doc/src/qtlocation.qdoc b/src/location/doc/src/qtlocation.qdoc
index 7979bbe5..5a3fb937 100644
--- a/src/location/doc/src/qtlocation.qdoc
+++ b/src/location/doc/src/qtlocation.qdoc
@@ -184,4 +184,16 @@ Qt Location available for a new platform.
\li Information about QML API changes since 5.4
\endtable
+ \section1 Licenses and Attributions
+
+ Qt Location is available under commercial licenses from \l{The Qt Company}.
+ In addition, it is available under the
+ \l{GNU Lesser General Public License, version 3}, or
+ the \l{GNU General Public License, version 2}.
+ See \l{Qt Licensing} for further details.
+
+ Furthermore Qt Location potentially contains third party
+ modules under following permissive licenses:
+
+ \generatelist{groupsbymodule attributions-qtlocation}
*/
diff --git a/src/location/location.pro b/src/location/location.pro
index 052a1970..225df556 100644
--- a/src/location/location.pro
+++ b/src/location/location.pro
@@ -1,6 +1,11 @@
TARGET = QtLocation
QT = core-private positioning-private
+android {
+ # adding qtconcurrent dependency here for the osm plugin
+ QT += concurrent
+}
+
MODULE_PLUGIN_TYPES = \
geoservices
@@ -11,6 +16,9 @@ PUBLIC_HEADERS += \
qlocation.h \
qlocationglobal.h
+PRIVATE_HEADERS += \
+ qlocationglobal_p.h
+
SOURCES += \
qlocation.cpp
diff --git a/src/location/maps/qabstractgeotilecache.cpp b/src/location/maps/qabstractgeotilecache.cpp
index 739123db..395206c8 100644
--- a/src/location/maps/qabstractgeotilecache.cpp
+++ b/src/location/maps/qabstractgeotilecache.cpp
@@ -139,9 +139,15 @@ QString QAbstractGeoTileCache::baseCacheDirectory()
if (!dir.endsWith(QLatin1Char('/')))
dir += QLatin1Char('/');
- dir += QLatin1String("QtLocation/");
-
return dir;
}
+QString QAbstractGeoTileCache::baseLocationCacheDirectory()
+{
+ // This scheme allows to have the "tiles" prefix hardcoded here
+ // NOTE: changing the Qt version here requires changing it also in QGeoFileTileCache::init,
+ // in the code that remove old version tiles !
+ return baseCacheDirectory() + QLatin1String("QtLocation/5.8/tiles/");
+}
+
QT_END_NAMESPACE
diff --git a/src/location/maps/qabstractgeotilecache_p.h b/src/location/maps/qabstractgeotilecache_p.h
index 141aa9b4..484bb8a5 100644
--- a/src/location/maps/qabstractgeotilecache_p.h
+++ b/src/location/maps/qabstractgeotilecache_p.h
@@ -87,6 +87,10 @@ class Q_LOCATION_EXPORT QAbstractGeoTileCache : public QObject
{
Q_OBJECT
public:
+ enum CostStrategy {
+ Unitary,
+ ByteSize
+ };
virtual ~QAbstractGeoTileCache();
virtual void setMaxDiskUsage(int diskUsage);
@@ -103,6 +107,12 @@ public:
virtual int minTextureUsage() const = 0;
virtual int textureUsage() const = 0;
virtual void clearAll() = 0;
+ virtual void setCostStrategyDisk(CostStrategy costStrategy) = 0;
+ virtual CostStrategy costStrategyDisk() const = 0;
+ virtual void setCostStrategyMemory(CostStrategy costStrategy) = 0;
+ virtual CostStrategy costStrategyMemory() const = 0;
+ virtual void setCostStrategyTexture(CostStrategy costStrategy) = 0;
+ virtual CostStrategy costStrategyTexture() const = 0;
virtual QSharedPointer<QGeoTileTexture> get(const QGeoTileSpec &spec) = 0;
@@ -113,11 +123,14 @@ public:
virtual void handleError(const QGeoTileSpec &spec, const QString &errorString);
static QString baseCacheDirectory();
+ static QString baseLocationCacheDirectory();
protected:
QAbstractGeoTileCache(QObject *parent = 0);
-
+ virtual void init() = 0;
virtual void printStats() = 0;
+
+ friend class QGeoTiledMappingManagerEngine;
};
QT_END_NAMESPACE
diff --git a/src/location/maps/qcache3q_p.h b/src/location/maps/qcache3q_p.h
index debce5d1..148c1f8b 100644
--- a/src/location/maps/qcache3q_p.h
+++ b/src/location/maps/qcache3q_p.h
@@ -145,7 +145,7 @@ private:
QHash<Key, Node *> lookup_;
public:
- explicit QCache3Q(int maxCost = 100, int minRecent = -1, int maxOldPopular = -1);
+ explicit QCache3Q(int maxCost = 0, int minRecent = -1, int maxOldPopular = -1);
inline ~QCache3Q() { clear(); delete q1_; delete q2_; delete q3_; delete q1_evicted_; }
inline int maxCost() const { return maxCost_; }
@@ -161,8 +161,8 @@ public:
QSharedPointer<T> object(const Key &key) const;
QSharedPointer<T> operator[](const Key &key) const;
- void remove(const Key &key);
-
+ void remove(const Key &key, bool force = false);
+ QList<Key> keys() const;
void printStats();
// Copy data directly into a queue. Designed for single use after construction
@@ -398,7 +398,7 @@ void QCache3Q<Key,T,EvPolicy>::rebalance()
} else {
Node *n = q2_->l;
unlink(n);
- if (n->pop > (q2_->pop / q2_->size)) {
+ if (q2_->size && n->pop > (q2_->pop / q2_->size)) {
link_front(n, q3_);
} else {
EvPolicy::aboutToBeEvicted(n->k, n->v);
@@ -411,20 +411,26 @@ void QCache3Q<Key,T,EvPolicy>::rebalance()
}
template <class Key, class T, class EvPolicy>
-void QCache3Q<Key,T,EvPolicy>::remove(const Key &key)
+void QCache3Q<Key,T,EvPolicy>::remove(const Key &key, bool force)
{
if (!lookup_.contains(key)) {
return;
}
Node *n = lookup_[key];
unlink(n);
- if (n->q != q1_evicted_)
+ if (n->q != q1_evicted_ && !force)
EvPolicy::aboutToBeRemoved(n->k, n->v);
lookup_.remove(key);
delete n;
}
template <class Key, class T, class EvPolicy>
+QList<Key> QCache3Q<Key,T,EvPolicy>::keys() const
+{
+ return lookup_.keys();
+}
+
+template <class Key, class T, class EvPolicy>
QSharedPointer<T> QCache3Q<Key,T,EvPolicy>::object(const Key &key) const
{
if (!lookup_.contains(key)) {
diff --git a/src/location/maps/qgeocameratiles.cpp b/src/location/maps/qgeocameratiles.cpp
index 5eae7c0b..f3a36adf 100644
--- a/src/location/maps/qgeocameratiles.cpp
+++ b/src/location/maps/qgeocameratiles.cpp
@@ -169,6 +169,11 @@ void QGeoCameraTiles::setMapType(const QGeoMapType &mapType)
d_ptr->m_mapType = mapType;
}
+QGeoMapType QGeoCameraTiles::activeMapType() const
+{
+ return d_ptr->m_mapType;
+}
+
void QGeoCameraTiles::setMapVersion(int mapVersion)
{
if (d_ptr->m_mapVersion == mapVersion)
diff --git a/src/location/maps/qgeocameratiles_p.h b/src/location/maps/qgeocameratiles_p.h
index d10895f8..8a26f28a 100644
--- a/src/location/maps/qgeocameratiles_p.h
+++ b/src/location/maps/qgeocameratiles_p.h
@@ -71,6 +71,7 @@ public:
void setViewExpansion(double viewExpansion);
void setPluginString(const QString &pluginString);
void setMapType(const QGeoMapType &mapType);
+ QGeoMapType activeMapType() const;
void setMapVersion(int mapVersion);
const QSet<QGeoTileSpec>& createTiles();
diff --git a/src/location/maps/qgeofiletilecache.cpp b/src/location/maps/qgeofiletilecache.cpp
index 3d381dc2..49e9dfff 100644
--- a/src/location/maps/qgeofiletilecache.cpp
+++ b/src/location/maps/qgeofiletilecache.cpp
@@ -86,32 +86,60 @@ QGeoCachedTileDisk::~QGeoCachedTileDisk()
}
QGeoFileTileCache::QGeoFileTileCache(const QString &directory, QObject *parent)
- : QAbstractGeoTileCache(parent), directory_(directory),
- minTextureUsage_(0), extraTextureUsage_(0)
+ : QAbstractGeoTileCache(parent), directory_(directory), minTextureUsage_(0), extraTextureUsage_(0)
+ ,costStrategyDisk_(ByteSize), costStrategyMemory_(ByteSize), costStrategyTexture_(ByteSize)
{
- const QString basePath = baseCacheDirectory();
- // delete old tiles from QtLocation 5.4 or prior
- // Newer version use plugin-specific subdirectories so those are not affected.
+}
+
+void QGeoFileTileCache::init()
+{
+ const QString basePath = baseCacheDirectory() + QLatin1String("QtLocation/");
+
+ // delete old tiles from QtLocation 5.7 or prior
+ // Newer version use plugin-specific subdirectories, versioned with qt version so those are not affected.
// TODO Remove cache cleanup in Qt 6
QDir baseDir(basePath);
if (baseDir.exists()) {
const QStringList oldCacheFiles = baseDir.entryList(QDir::Files);
foreach (const QString& file, oldCacheFiles)
baseDir.remove(file);
+ const QStringList oldCacheDirs = { QStringLiteral("osm"), QStringLiteral("mapbox"), QStringLiteral("here") };
+ foreach (const QString& d, oldCacheDirs) {
+ QDir oldCacheDir(basePath + QLatin1Char('/') + d);
+ if (oldCacheDir.exists())
+ oldCacheDir.removeRecursively();
+ }
}
if (directory_.isEmpty()) {
- directory_ = basePath;
+ directory_ = baseLocationCacheDirectory();
qWarning() << "Plugin uses uninitialized QGeoFileTileCache directory which was deleted during startup";
}
QDir::root().mkpath(directory_);
// default values
- setMaxDiskUsage(20 * 1024 * 1024);
- setMaxMemoryUsage(3 * 1024 * 1024);
- setExtraTextureUsage(6 * 1024 * 1024);
+ if (!diskCache_.maxCost()) { // If setMaxDiskUsage has not been called yet
+ if (costStrategyDisk_ == ByteSize)
+ setMaxDiskUsage(50 * 1024 * 1024);
+ else
+ setMaxDiskUsage(1000);
+ }
+
+ if (!memoryCache_.maxCost()) { // If setMaxMemoryUsage has not been called yet
+ if (costStrategyMemory_ == ByteSize)
+ setMaxMemoryUsage(3 * 1024 * 1024);
+ else
+ setMaxMemoryUsage(100);
+ }
+
+ if (!textureCache_.maxCost()) { // If setExtraTextureUsage has not been called yet
+ if (costStrategyTexture_ == ByteSize)
+ setExtraTextureUsage(6 * 1024 * 1024);
+ else
+ setExtraTextureUsage(30); // byte size of texture is >> compressed image, hence unitary cost should be lower
+ }
loadTiles();
}
@@ -150,7 +178,11 @@ void QGeoFileTileCache::loadTiles()
QFileInfo fi(tileDisk->filename);
specs.append(spec);
queue.append(tileDisk);
- costs.append(fi.size());
+ if (costStrategyDisk_ == ByteSize)
+ costs.append(fi.size());
+ else
+ costs.append(1);
+
}
}
@@ -274,45 +306,70 @@ void QGeoFileTileCache::clearAll()
}
}
-QSharedPointer<QGeoTileTexture> QGeoFileTileCache::get(const QGeoTileSpec &spec)
+void QGeoFileTileCache::clearMapId(const int mapId)
{
- QSharedPointer<QGeoTileTexture> tt = textureCache_.object(spec);
- if (tt)
- return tt;
-
- QSharedPointer<QGeoCachedTileMemory> tm = memoryCache_.object(spec);
- if (tm) {
- QImage image;
- if (!image.loadFromData(tm->bytes)) {
- handleError(spec, QLatin1String("Problem with tile image"));
- return QSharedPointer<QGeoTileTexture>(0);
- }
- QSharedPointer<QGeoTileTexture> tt = addToTextureCache(spec, image);
- if (tt)
- return tt;
+ for (const QGeoTileSpec &k : diskCache_.keys())
+ if (k.mapId() == mapId)
+ diskCache_.remove(k, true);
+ for (const QGeoTileSpec &k : memoryCache_.keys())
+ if (k.mapId() == mapId)
+ memoryCache_.remove(k);
+ for (const QGeoTileSpec &k : textureCache_.keys())
+ if (k.mapId() == mapId)
+ textureCache_.remove(k);
+
+ // TODO: It seems the cache leaves residues, like some tiles do not get picked up.
+ // After the above calls, files that shouldnt be left behind are still on disk.
+ // Do an additional pass and make sure what has to be deleted gets deleted.
+ QDir dir(directory_);
+ QStringList formats;
+ formats << QLatin1String("*.*");
+ QStringList files = dir.entryList(formats, QDir::Files);
+ qWarning() << "Old tile data detected. Cache eviction left out "<< files.size() << "tiles";
+ for (const QString &tileFileName : files) {
+ QGeoTileSpec spec = filenameToTileSpec(tileFileName);
+ if (spec.mapId() != mapId)
+ continue;
+ QFile::remove(dir.filePath(tileFileName));
}
+}
- QSharedPointer<QGeoCachedTileDisk> td = diskCache_.object(spec);
- if (td) {
- const QString format = QFileInfo(td->filename).suffix();
- QFile file(td->filename);
- file.open(QIODevice::ReadOnly);
- QByteArray bytes = file.readAll();
- file.close();
+void QGeoFileTileCache::setCostStrategyDisk(QAbstractGeoTileCache::CostStrategy costStrategy)
+{
+ costStrategyDisk_ = costStrategy;
+}
- QImage image;
- if (!image.loadFromData(bytes)) {
- handleError(spec, QLatin1String("Problem with tile image"));
- return QSharedPointer<QGeoTileTexture>(0);
- }
+QAbstractGeoTileCache::CostStrategy QGeoFileTileCache::costStrategyDisk() const
+{
+ return costStrategyDisk_;
+}
- addToMemoryCache(spec, bytes, format);
- QSharedPointer<QGeoTileTexture> tt = addToTextureCache(td->spec, image);
- if (tt)
- return tt;
- }
+void QGeoFileTileCache::setCostStrategyMemory(QAbstractGeoTileCache::CostStrategy costStrategy)
+{
+ costStrategyMemory_ = costStrategy;
+}
- return QSharedPointer<QGeoTileTexture>();
+QAbstractGeoTileCache::CostStrategy QGeoFileTileCache::costStrategyMemory() const
+{
+ return costStrategyMemory_;
+}
+
+void QGeoFileTileCache::setCostStrategyTexture(QAbstractGeoTileCache::CostStrategy costStrategy)
+{
+ costStrategyTexture_ = costStrategy;
+}
+
+QAbstractGeoTileCache::CostStrategy QGeoFileTileCache::costStrategyTexture() const
+{
+ return costStrategyTexture_;
+}
+
+QSharedPointer<QGeoTileTexture> QGeoFileTileCache::get(const QGeoTileSpec &spec)
+{
+ QSharedPointer<QGeoTileTexture> tt = getFromMemory(spec);
+ if (tt)
+ return tt;
+ return getFromDisk(spec);
}
void QGeoFileTileCache::insert(const QGeoTileSpec &spec,
@@ -358,9 +415,12 @@ QSharedPointer<QGeoCachedTileDisk> QGeoFileTileCache::addToDiskCache(const QGeoT
td->filename = filename;
td->cache = this;
- QFileInfo fi(filename);
- int diskCost = fi.size();
- diskCache_.insert(spec, td, diskCost);
+ int cost = 1;
+ if (costStrategyDisk_ == ByteSize) {
+ QFileInfo fi(filename);
+ cost = fi.size();
+ }
+ diskCache_.insert(spec, td, cost);
return td;
}
@@ -372,7 +432,9 @@ QSharedPointer<QGeoCachedTileMemory> QGeoFileTileCache::addToMemoryCache(const Q
tm->bytes = bytes;
tm->format = format;
- int cost = bytes.size();
+ int cost = 1;
+ if (costStrategyMemory_ == ByteSize)
+ cost = bytes.size();
memoryCache_.insert(spec, tm, cost);
return tm;
@@ -384,13 +446,60 @@ QSharedPointer<QGeoTileTexture> QGeoFileTileCache::addToTextureCache(const QGeoT
tt->spec = spec;
tt->image = image;
- int textureCost = image.width() * image.height() * image.depth() / 8;
- textureCache_.insert(spec, tt, textureCost);
+ int cost = 1;
+ if (costStrategyTexture_ == ByteSize)
+ cost = image.width() * image.height() * image.depth() / 8;
+ textureCache_.insert(spec, tt, cost);
return tt;
}
-QString QGeoFileTileCache::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory)
+QSharedPointer<QGeoTileTexture> QGeoFileTileCache::getFromMemory(const QGeoTileSpec &spec)
+{
+ QSharedPointer<QGeoTileTexture> tt = textureCache_.object(spec);
+ if (tt)
+ return tt;
+
+ QSharedPointer<QGeoCachedTileMemory> tm = memoryCache_.object(spec);
+ if (tm) {
+ QImage image;
+ if (!image.loadFromData(tm->bytes)) {
+ handleError(spec, QLatin1String("Problem with tile image"));
+ return QSharedPointer<QGeoTileTexture>(0);
+ }
+ QSharedPointer<QGeoTileTexture> tt = addToTextureCache(spec, image);
+ if (tt)
+ return tt;
+ }
+ return QSharedPointer<QGeoTileTexture>();
+}
+
+QSharedPointer<QGeoTileTexture> QGeoFileTileCache::getFromDisk(const QGeoTileSpec &spec)
+{
+ QSharedPointer<QGeoCachedTileDisk> td = diskCache_.object(spec);
+ if (td) {
+ const QString format = QFileInfo(td->filename).suffix();
+ QFile file(td->filename);
+ file.open(QIODevice::ReadOnly);
+ QByteArray bytes = file.readAll();
+ file.close();
+
+ QImage image;
+ if (!image.loadFromData(bytes)) {
+ handleError(spec, QLatin1String("Problem with tile image"));
+ return QSharedPointer<QGeoTileTexture>(0);
+ }
+
+ addToMemoryCache(spec, bytes, format);
+ QSharedPointer<QGeoTileTexture> tt = addToTextureCache(td->spec, image);
+ if (tt)
+ return tt;
+ }
+
+ return QSharedPointer<QGeoTileTexture>();
+}
+
+QString QGeoFileTileCache::tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const
{
QString filename = spec.plugin();
filename += QLatin1String("-");
@@ -416,7 +525,7 @@ QString QGeoFileTileCache::tileSpecToFilename(const QGeoTileSpec &spec, const QS
return dir.filePath(filename);
}
-QGeoTileSpec QGeoFileTileCache::filenameToTileSpec(const QString &filename)
+QGeoTileSpec QGeoFileTileCache::filenameToTileSpec(const QString &filename) const
{
QGeoTileSpec emptySpec;
diff --git a/src/location/maps/qgeofiletilecache_p.h b/src/location/maps/qgeofiletilecache_p.h
index bd3e684b..7d6df9fd 100644
--- a/src/location/maps/qgeofiletilecache_p.h
+++ b/src/location/maps/qgeofiletilecache_p.h
@@ -48,6 +48,7 @@
//
#include <QtLocation/qlocationglobal.h>
+#include <QtLocation/private/qlocationglobal_p.h>
#include <QObject>
#include <QCache>
@@ -88,7 +89,7 @@ public:
/* Custom eviction policy for the disk cache, to avoid deleting all the files
* when the application closes */
-class QCache3QTileEvictionPolicy : public QCache3QDefaultEvictionPolicy<QGeoTileSpec,QGeoCachedTileDisk>
+class Q_LOCATION_PRIVATE_EXPORT QCache3QTileEvictionPolicy : public QCache3QDefaultEvictionPolicy<QGeoTileSpec,QGeoCachedTileDisk>
{
protected:
void aboutToBeRemoved(const QGeoTileSpec &key, QSharedPointer<QGeoCachedTileDisk> obj);
@@ -116,6 +117,14 @@ public:
int minTextureUsage() const Q_DECL_OVERRIDE;
int textureUsage() const Q_DECL_OVERRIDE;
void clearAll() Q_DECL_OVERRIDE;
+ void clearMapId(const int mapId);
+ void setCostStrategyDisk(CostStrategy costStrategy) Q_DECL_OVERRIDE;
+ CostStrategy costStrategyDisk() const Q_DECL_OVERRIDE;
+ void setCostStrategyMemory(CostStrategy costStrategy) Q_DECL_OVERRIDE;
+ CostStrategy costStrategyMemory() const Q_DECL_OVERRIDE;
+ void setCostStrategyTexture(CostStrategy costStrategy) Q_DECL_OVERRIDE;
+ CostStrategy costStrategyTexture() const Q_DECL_OVERRIDE;
+
QSharedPointer<QGeoTileTexture> get(const QGeoTileSpec &spec) Q_DECL_OVERRIDE;
@@ -128,7 +137,8 @@ public:
const QString &format,
QGeoTiledMappingManagerEngine::CacheAreas areas = QGeoTiledMappingManagerEngine::AllCaches) Q_DECL_OVERRIDE;
-private:
+protected:
+ void init() Q_DECL_OVERRIDE;
void printStats() Q_DECL_OVERRIDE;
void loadTiles();
@@ -137,9 +147,11 @@ private:
QSharedPointer<QGeoCachedTileDisk> addToDiskCache(const QGeoTileSpec &spec, const QString &filename);
QSharedPointer<QGeoCachedTileMemory> addToMemoryCache(const QGeoTileSpec &spec, const QByteArray &bytes, const QString &format);
QSharedPointer<QGeoTileTexture> addToTextureCache(const QGeoTileSpec &spec, const QImage &image);
+ QSharedPointer<QGeoTileTexture> getFromMemory(const QGeoTileSpec &spec);
+ QSharedPointer<QGeoTileTexture> getFromDisk(const QGeoTileSpec &spec);
- static QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory);
- static QGeoTileSpec filenameToTileSpec(const QString &filename);
+ virtual QString tileSpecToFilename(const QGeoTileSpec &spec, const QString &format, const QString &directory) const;
+ virtual QGeoTileSpec filenameToTileSpec(const QString &filename) const;
QCache3Q<QGeoTileSpec, QGeoCachedTileDisk, QCache3QTileEvictionPolicy > diskCache_;
QCache3Q<QGeoTileSpec, QGeoCachedTileMemory > memoryCache_;
@@ -149,6 +161,9 @@ private:
int minTextureUsage_;
int extraTextureUsage_;
+ CostStrategy costStrategyDisk_;
+ CostStrategy costStrategyMemory_;
+ CostStrategy costStrategyTexture_;
};
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp
index c3b01a3e..0e0a2007 100644
--- a/src/location/maps/qgeomap.cpp
+++ b/src/location/maps/qgeomap.cpp
@@ -51,31 +51,31 @@ QGeoMap::~QGeoMap()
{
}
-void QGeoMap::setSize(const QSize& size)
+void QGeoMap::setViewportSize(const QSize& size)
{
Q_D(QGeoMap);
- if (size == d->m_size)
+ if (size == d->m_viewportSize)
return;
- d->m_size = size;
- d->changeMapSize(size);
+ d->m_viewportSize = size;
+ d->changeViewportSize(size);
}
-QSize QGeoMap::size() const
+QSize QGeoMap::viewportSize() const
{
Q_D(const QGeoMap);
- return d->m_size;
+ return d->m_viewportSize;
}
-int QGeoMap::width() const
+int QGeoMap::viewportWidth() const
{
Q_D(const QGeoMap);
- return d->m_size.width();
+ return d->m_viewportSize.width();
}
-int QGeoMap::height() const
+int QGeoMap::viewportHeight() const
{
Q_D(const QGeoMap);
- return d->m_size.height();
+ return d->m_viewportSize.height();
}
void QGeoMap::setCameraData(const QGeoCameraData &cameraData)
diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h
index 021c440b..ea4806c0 100644
--- a/src/location/maps/qgeomap_p.h
+++ b/src/location/maps/qgeomap_p.h
@@ -47,8 +47,8 @@
// We mean it.
//
-#include "qgeocameradata_p.h"
-#include "qgeomaptype_p.h"
+#include <QtLocation/private/qgeocameradata_p.h>
+#include <QtLocation/private/qgeomaptype_p.h>
#include <QtCore/QObject>
#include <QtPositioning/private/qdoublevector2d_p.h>
@@ -70,10 +70,11 @@ class Q_LOCATION_EXPORT QGeoMap : public QObject
public:
virtual ~QGeoMap();
- void setSize(const QSize& size);
- QSize size() const;
- int width() const;
- int height() const;
+ // Sets the display size
+ void setViewportSize(const QSize& viewportSize);
+ QSize viewportSize() const;
+ int viewportWidth() const;
+ int viewportHeight() const;
QGeoCameraData cameraData() const;
@@ -84,9 +85,8 @@ public:
virtual QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const = 0;
virtual QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const = 0;
-
- virtual double minimumZoomForMapSize(int width, int height) const = 0;
- virtual double maximumLatitudeForZoom(double zoomLevel) const = 0;
+ virtual double minimumZoomAtViewportSize(int viewportWidth, int viewportHeight) const = 0;
+ virtual double maximumCenterLatitudeAtZoom(double zoomLevel) const = 0;
virtual QDoubleVector2D referenceCoordinateToItemPosition(const QGeoCoordinate &coordinate) const = 0;
virtual QGeoCoordinate referenceItemPositionToCoordinate(const QDoubleVector2D &pos) const = 0;
diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h
index f09d55c2..b95c1dc7 100644
--- a/src/location/maps/qgeomap_p_p.h
+++ b/src/location/maps/qgeomap_p_p.h
@@ -47,8 +47,9 @@
// We mean it.
//
-#include "qgeocameradata_p.h"
-#include "qgeomaptype_p.h"
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qgeocameradata_p.h>
+#include <QtLocation/private/qgeomaptype_p.h>
#include <QtCore/private/qobject_p.h>
#include <QtCore/QSize>
@@ -59,7 +60,7 @@ class QGeoMappingManagerEngine;
class QGeoMap;
class QGeoMapController;
-class QGeoMapPrivate : public QObjectPrivate
+class Q_LOCATION_PRIVATE_EXPORT QGeoMapPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QGeoMap)
public:
@@ -67,12 +68,13 @@ public:
virtual ~QGeoMapPrivate();
protected:
- virtual void changeMapSize(const QSize &size) = 0;
- virtual void changeCameraData(const QGeoCameraData &oldCameraData) = 0;
- virtual void changeActiveMapType(const QGeoMapType mapType) = 0;
+ /* Hooks into the actual map implementations */
+ virtual void changeViewportSize(const QSize &size) = 0; // called by QGeoMap::setSize()
+ virtual void changeCameraData(const QGeoCameraData &oldCameraData) = 0; // called by QGeoMap::setCameraData()
+ virtual void changeActiveMapType(const QGeoMapType mapType) = 0; // called by QGeoMap::setActiveMapType()
protected:
- QSize m_size;
+ QSize m_viewportSize;
QPointer<QGeoMappingManagerEngine> m_engine;
QGeoMapController *m_controller;
QGeoCameraData m_cameraData;
diff --git a/src/location/maps/qgeoserviceprovider.cpp b/src/location/maps/qgeoserviceprovider.cpp
index 51b0de60..8a3dc144 100644
--- a/src/location/maps/qgeoserviceprovider.cpp
+++ b/src/location/maps/qgeoserviceprovider.cpp
@@ -104,6 +104,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
\li "mapbox" -> \l {Qt Location Mapbox Plugin}{Mapbox service}
\li "here" -> \l {Qt Location HERE Plugin}{HERE Services}
\li "osm" -> \l {Qt Location Open Street Map Plugin}{OpenStreetMap Services}
+ \li "esri" -> \l {Qt Location Esri Plugin}{ESRI Services}
\endlist
Each service provider must follow a naming convention for their service specific
diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp
index a6cbb294..04f9ad21 100644
--- a/src/location/maps/qgeotiledmap.cpp
+++ b/src/location/maps/qgeotiledmap.cpp
@@ -116,6 +116,13 @@ void QGeoTiledMap::clearData()
d->m_mapScene->clearTexturedTiles();
}
+void QGeoTiledMap::clearScene(int mapId)
+{
+ Q_D(QGeoTiledMap);
+ if (activeMapType().mapId() == mapId)
+ d->clearScene();
+}
+
void QGeoTiledMap::handleTileVersionChanged()
{
Q_D(QGeoTiledMap);
@@ -135,8 +142,8 @@ QGeoCoordinate QGeoTiledMap::itemPositionToCoordinate(const QDoubleVector2D &pos
{
Q_D(const QGeoTiledMap);
if (clipToViewport) {
- int w = width();
- int h = height();
+ int w = viewportWidth();
+ int h = viewportHeight();
if ((pos.x() < 0) || (w < pos.x()) || (pos.y() < 0) || (h < pos.y()))
return QGeoCoordinate();
@@ -151,8 +158,8 @@ QDoubleVector2D QGeoTiledMap::coordinateToItemPosition(const QGeoCoordinate &coo
QDoubleVector2D pos = d->coordinateToItemPosition(coordinate);
if (clipToViewport) {
- int w = width();
- int h = height();
+ int w = viewportWidth();
+ int h = viewportHeight();
double x = pos.x();
double y = pos.y();
if ((x < 0.0) || (x > w) || (y < 0) || (y > h) || qIsNaN(x) || qIsNaN(y))
@@ -164,7 +171,7 @@ QDoubleVector2D QGeoTiledMap::coordinateToItemPosition(const QGeoCoordinate &coo
// This method returns the minimum zoom level that this specific qgeomap type allows
// at a given canvas size (width,height) and for a given tile size (usually 256).
-double QGeoTiledMap::minimumZoomForMapSize(int width, int height) const
+double QGeoTiledMap::minimumZoomAtViewportSize(int width, int height) const
{
Q_D(const QGeoTiledMap);
double maxSize = qMax(width,height);
@@ -178,14 +185,14 @@ double QGeoTiledMap::minimumZoomForMapSize(int width, int height) const
// the amount of pixels between the center and the borders changes
// 2) when the zoom level changes, because the amount of pixels between the center
// and the borders stays the same, but the meters per pixel change
-double QGeoTiledMap::maximumLatitudeForZoom(double zoomLevel) const
+double QGeoTiledMap::maximumCenterLatitudeAtZoom(double zoomLevel) const
{
Q_D(const QGeoTiledMap);
double mapEdgeSize = std::pow(2.0,zoomLevel);
mapEdgeSize *= d->m_visibleTiles->tileSize();
// At init time weird things happen
- int clampedWindowHeight = (height() > mapEdgeSize) ? mapEdgeSize : height();
+ int clampedWindowHeight = (viewportHeight() > mapEdgeSize) ? mapEdgeSize : viewportHeight();
// Use the window height divided by 2 as the topmost allowed center, with respect to the map size in pixels
double mercatorTopmost = (clampedWindowHeight * 0.5) / mapEdgeSize ;
@@ -293,6 +300,11 @@ void QGeoTiledMapPrivate::prefetchTiles()
}
}
+QGeoMapType QGeoTiledMapPrivate::activeMapType()
+{
+ return m_visibleTiles->activeMapType();
+}
+
void QGeoTiledMapPrivate::changeCameraData(const QGeoCameraData &cameraData)
{
Q_Q(QGeoTiledMap);
@@ -356,7 +368,14 @@ void QGeoTiledMapPrivate::changeTileVersion(int version)
updateScene();
}
-void QGeoTiledMapPrivate::changeMapSize(const QSize& size)
+void QGeoTiledMapPrivate::clearScene()
+{
+ m_mapScene->clearTexturedTiles();
+ m_mapScene->setVisibleTiles(QSet<QGeoTileSpec>());
+ updateScene();
+}
+
+void QGeoTiledMapPrivate::changeViewportSize(const QSize& size)
{
Q_Q(QGeoTiledMap);
diff --git a/src/location/maps/qgeotiledmap_p.h b/src/location/maps/qgeotiledmap_p.h
index 813e342d..d00a1ed9 100644
--- a/src/location/maps/qgeotiledmap_p.h
+++ b/src/location/maps/qgeotiledmap_p.h
@@ -86,9 +86,9 @@ public:
QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const Q_DECL_OVERRIDE;
QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const Q_DECL_OVERRIDE;
+ double minimumZoomAtViewportSize(int viewportWidth, int viewportHeight) const Q_DECL_OVERRIDE;
+ double maximumCenterLatitudeAtZoom(double zoomLevel) const Q_DECL_OVERRIDE;
- double minimumZoomForMapSize(int width, int height) const Q_DECL_OVERRIDE;
- double maximumLatitudeForZoom(double zoomLevel) const Q_DECL_OVERRIDE;
QDoubleVector2D referenceCoordinateToItemPosition(const QGeoCoordinate &coordinate) const Q_DECL_OVERRIDE;
QGeoCoordinate referenceItemPositionToCoordinate(const QDoubleVector2D &pos) const Q_DECL_OVERRIDE;
@@ -96,6 +96,9 @@ public:
void prefetchData() Q_DECL_OVERRIDE;
void clearData() Q_DECL_OVERRIDE;
+public Q_SLOTS:
+ virtual void clearScene(int mapId);
+
protected:
QSGNode *updateSceneGraph(QSGNode *, QQuickWindow *window) Q_DECL_OVERRIDE;
virtual void evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles);
diff --git a/src/location/maps/qgeotiledmap_p_p.h b/src/location/maps/qgeotiledmap_p_p.h
index c1b190bf..01646d66 100644
--- a/src/location/maps/qgeotiledmap_p_p.h
+++ b/src/location/maps/qgeotiledmap_p_p.h
@@ -80,12 +80,14 @@ public:
void updateTile(const QGeoTileSpec &spec);
void prefetchTiles();
+ QGeoMapType activeMapType();
protected:
- void changeMapSize(const QSize& size) Q_DECL_OVERRIDE;
+ void changeViewportSize(const QSize& size) Q_DECL_OVERRIDE;
void changeCameraData(const QGeoCameraData &cameraData) Q_DECL_OVERRIDE;
void changeActiveMapType(const QGeoMapType mapType) Q_DECL_OVERRIDE;
void changeTileVersion(int version);
+ void clearScene();
private:
void updateScene();
diff --git a/src/location/maps/qgeotiledmappingmanagerengine.cpp b/src/location/maps/qgeotiledmappingmanagerengine.cpp
index dc5f1889..0ad37a1d 100644
--- a/src/location/maps/qgeotiledmappingmanagerengine.cpp
+++ b/src/location/maps/qgeotiledmappingmanagerengine.cpp
@@ -289,6 +289,7 @@ void QGeoTiledMappingManagerEngine::setTileCache(QAbstractGeoTileCache *cache)
Q_ASSERT_X(!d->tileCache_, Q_FUNC_INFO, "This should be called only once");
cache->setParent(this);
d->tileCache_ = cache;
+ d->tileCache_->init();
}
QAbstractGeoTileCache *QGeoTiledMappingManagerEngine::tileCache()
@@ -297,8 +298,9 @@ QAbstractGeoTileCache *QGeoTiledMappingManagerEngine::tileCache()
if (!d->tileCache_) {
QString cacheDirectory;
if (!managerName().isEmpty())
- cacheDirectory = QAbstractGeoTileCache::baseCacheDirectory() + managerName();
+ cacheDirectory = QAbstractGeoTileCache::baseLocationCacheDirectory() + managerName();
d->tileCache_ = new QGeoFileTileCache(cacheDirectory);
+ d->tileCache_->init();
}
return d->tileCache_;
}
diff --git a/src/location/maps/qgeotiledmapscene.cpp b/src/location/maps/qgeotiledmapscene.cpp
index 57750f4d..d859c2af 100644
--- a/src/location/maps/qgeotiledmapscene.cpp
+++ b/src/location/maps/qgeotiledmapscene.cpp
@@ -40,7 +40,7 @@
#include "qgeotilespec_p.h"
#include <QtPositioning/private/qdoublevector3d_p.h>
#include <QtCore/private/qobject_p.h>
-#include <QtQuick/QSGSimpleTextureNode>
+#include <QtQuick/QSGImageNode>
#include <QtQuick/QQuickWindow>
#include <cmath>
@@ -101,6 +101,8 @@ public:
bool m_verticalLock;
bool m_linearScaling;
+ bool m_dropTextures;
+
void addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture);
QDoubleVector2D itemPositionToMercator(const QDoubleVector2D &pos) const;
@@ -108,7 +110,7 @@ public:
void setVisibleTiles(const QSet<QGeoTileSpec> &tiles);
void removeTiles(const QSet<QGeoTileSpec> &oldTiles);
- bool buildGeometry(const QGeoTileSpec &spec, QSGGeometry::TexturedPoint2D *vertices);
+ bool buildGeometry(const QGeoTileSpec &spec, QSGImageNode *imageNode);
void setTileBounds(const QSet<QGeoTileSpec> &tiles);
void setupCamera();
};
@@ -200,6 +202,7 @@ void QGeoTiledMapScene::clearTexturedTiles()
{
Q_D(QGeoTiledMapScene);
d->m_textures.clear();
+ d->m_dropTextures = true;
}
QGeoTiledMapScenePrivate::QGeoTiledMapScenePrivate()
@@ -223,7 +226,8 @@ QGeoTiledMapScenePrivate::QGeoTiledMapScenePrivate()
m_screenHeight(0.0),
m_useVerticalLock(false),
m_verticalLock(false),
- m_linearScaling(false)
+ m_linearScaling(false),
+ m_dropTextures(false)
{
}
@@ -292,7 +296,7 @@ QDoubleVector2D QGeoTiledMapScenePrivate::mercatorToItemPosition(const QDoubleVe
return QDoubleVector2D(x + m_screenOffsetX, y + m_screenOffsetY);
}
-bool QGeoTiledMapScenePrivate::buildGeometry(const QGeoTileSpec &spec, QSGGeometry::TexturedPoint2D *vertices)
+bool QGeoTiledMapScenePrivate::buildGeometry(const QGeoTileSpec &spec, QSGImageNode *imageNode)
{
int x = spec.x();
@@ -320,11 +324,9 @@ bool QGeoTiledMapScenePrivate::buildGeometry(const QGeoTileSpec &spec, QSGGeomet
y1 *= edge;
y2 *= edge;
- //Texture coordinate order for veritcal flip of texture
- vertices[0].set(x1, y1, 0, 0);
- vertices[1].set(x1, y2, 0, 1);
- vertices[2].set(x2, y1, 1, 0);
- vertices[3].set(x2, y2, 1, 1);
+ imageNode->setRect(QRectF(QPointF(x1, y2), QPointF(x2, y1)));
+ imageNode->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically);
+ imageNode->setSourceRect(QRectF(QPointF(0,0), imageNode->texture()->textureSize()));
return true;
}
@@ -559,12 +561,12 @@ void QGeoTiledMapScenePrivate::setupCamera()
class QGeoTiledMapTileContainerNode : public QSGTransformNode
{
public:
- void addChild(const QGeoTileSpec &spec, QSGSimpleTextureNode *node)
+ void addChild(const QGeoTileSpec &spec, QSGImageNode *node)
{
tiles.insert(spec, node);
appendChildNode(node);
}
- QHash<QGeoTileSpec, QSGSimpleTextureNode *> tiles;
+ QHash<QGeoTileSpec, QSGImageNode *> tiles;
};
class QGeoTiledMapRootNode : public QSGClipNode
@@ -601,7 +603,10 @@ public:
}
}
- void updateTiles(QGeoTiledMapTileContainerNode *root, QGeoTiledMapScenePrivate *d, double camAdjust);
+ void updateTiles(QGeoTiledMapTileContainerNode *root,
+ QGeoTiledMapScenePrivate *d,
+ double camAdjust,
+ QQuickWindow *window);
bool isTextureLinear;
@@ -617,11 +622,9 @@ public:
QHash<QGeoTileSpec, QSGTexture *> textures;
};
-static bool qgeotiledmapscene_isTileInViewport(const QSGGeometry::TexturedPoint2D *tp, const QMatrix4x4 &matrix) {
- QPolygonF polygon; polygon.reserve(4);
- for (int i=0; i<4; ++i)
- polygon << matrix * QPointF(tp[i].x, tp[i].y);
- return QRectF(-1, -1, 2, 2).intersects(polygon.boundingRect());
+static bool qgeotiledmapscene_isTileInViewport(const QRectF &tileRect, const QMatrix4x4 &matrix) {
+ const QRectF boundingRect = QRectF(matrix * tileRect.topLeft(), matrix * tileRect.bottomRight());
+ return QRectF(-1, -1, 2, 2).intersects(boundingRect);
}
static QVector3D toVector3D(const QDoubleVector3D& in)
@@ -630,8 +633,9 @@ static QVector3D toVector3D(const QDoubleVector3D& in)
}
void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
- QGeoTiledMapScenePrivate *d,
- double camAdjust)
+ QGeoTiledMapScenePrivate *d,
+ double camAdjust,
+ QQuickWindow *window)
{
// Set up the matrix...
QDoubleVector3D eye = d->m_cameraEye;
@@ -649,30 +653,24 @@ void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
foreach (const QGeoTileSpec &s, toRemove)
delete root->tiles.take(s);
- for (QHash<QGeoTileSpec, QSGSimpleTextureNode *>::iterator it = root->tiles.begin();
+ for (QHash<QGeoTileSpec, QSGImageNode *>::iterator it = root->tiles.begin();
it != root->tiles.end(); ) {
- QSGGeometry visualGeometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4);
- QSGGeometry::TexturedPoint2D *v = visualGeometry.vertexDataAsTexturedPoint2D();
- bool ok = d->buildGeometry(it.key(), v) && qgeotiledmapscene_isTileInViewport(v, root->matrix());
- QSGSimpleTextureNode *node = it.value();
- QSGNode::DirtyState dirtyBits = 0;
+ QSGImageNode *node = it.value();
+ bool ok = d->buildGeometry(it.key(), node) && qgeotiledmapscene_isTileInViewport(node->rect(), root->matrix());
- // Check and handle changes to vertex data.
- if (ok && memcmp(node->geometry()->vertexData(), v, 4 * sizeof(QSGGeometry::TexturedPoint2D)) != 0) {
- if (v[0].x == v[3].x || v[0].y == v[3].y) { // top-left == bottom-right => invalid => remove
- ok = false;
- } else {
- memcpy(node->geometry()->vertexData(), v, 4 * sizeof(QSGGeometry::TexturedPoint2D));
- dirtyBits |= QSGNode::DirtyGeometry;
- }
- }
+ QSGNode::DirtyState dirtyBits = 0;
if (!ok) {
it = root->tiles.erase(it);
delete node;
} else {
if (isTextureLinear != d->m_linearScaling) {
- node->setFiltering(d->m_linearScaling ? QSGTexture::Linear : QSGTexture::Nearest);
+ if (node->texture()->textureSize().width() > d->m_tileSize) {
+ node->setFiltering(QSGTexture::Linear); // With mipmapping QSGTexture::Nearest generates artifacts
+ node->setMipmapFiltering(QSGTexture::Linear);
+ } else {
+ node->setFiltering(d->m_linearScaling ? QSGTexture::Linear : QSGTexture::Nearest);
+ }
dirtyBits |= QSGNode::DirtyMaterial;
}
if (dirtyBits != 0)
@@ -685,15 +683,16 @@ void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
QGeoTileTexture *tileTexture = d->m_textures.value(s).data();
if (!tileTexture || tileTexture->image.isNull())
continue;
- QSGSimpleTextureNode *tileNode = new QSGSimpleTextureNode();
+ QSGImageNode *tileNode = window->createImageNode();
// note: setTexture will update coordinates so do it here, before we buildGeometry
tileNode->setTexture(textures.value(s));
- Q_ASSERT(tileNode->geometry());
- Q_ASSERT(tileNode->geometry()->attributes() == QSGGeometry::defaultAttributes_TexturedPoint2D().attributes);
- Q_ASSERT(tileNode->geometry()->vertexCount() == 4);
- if (d->buildGeometry(s, tileNode->geometry()->vertexDataAsTexturedPoint2D())
- && qgeotiledmapscene_isTileInViewport(tileNode->geometry()->vertexDataAsTexturedPoint2D(), root->matrix())) {
- tileNode->setFiltering(d->m_linearScaling ? QSGTexture::Linear : QSGTexture::Nearest);
+ if (d->buildGeometry(s, tileNode) && qgeotiledmapscene_isTileInViewport(tileNode->rect(), root->matrix())) {
+ if (tileNode->texture()->textureSize().width() > d->m_tileSize) {
+ tileNode->setFiltering(QSGTexture::Linear); // with mipmapping QSGTexture::Nearest generates artifacts
+ tileNode->setMipmapFiltering(QSGTexture::Linear);
+ } else {
+ tileNode->setFiltering(d->m_linearScaling ? QSGTexture::Linear : QSGTexture::Nearest);
+ }
root->addChild(s, tileNode);
} else {
delete tileNode;
@@ -723,6 +722,18 @@ QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *win
itemSpaceMatrix.scale(1, -1);
mapRoot->root->setMatrix(itemSpaceMatrix);
+ if (d->m_dropTextures) {
+ foreach (const QGeoTileSpec &s, mapRoot->tiles->tiles.keys())
+ delete mapRoot->tiles->tiles.take(s);
+ foreach (const QGeoTileSpec &s, mapRoot->wrapLeft->tiles.keys())
+ delete mapRoot->wrapLeft->tiles.take(s);
+ foreach (const QGeoTileSpec &s, mapRoot->wrapRight->tiles.keys())
+ delete mapRoot->wrapRight->tiles.take(s);
+ foreach (const QGeoTileSpec &spec, mapRoot->textures.keys())
+ mapRoot->textures.take(spec)->deleteLater();
+ d->m_dropTextures = false;
+ }
+
QSet<QGeoTileSpec> textures = QSet<QGeoTileSpec>::fromList(mapRoot->textures.keys());
QSet<QGeoTileSpec> toRemove = textures - d->m_visibleTiles;
QSet<QGeoTileSpec> toAdd = d->m_visibleTiles - textures;
@@ -737,9 +748,9 @@ QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *win
}
double sideLength = d->m_scaleFactor * d->m_tileSize * d->m_sideLength;
- mapRoot->updateTiles(mapRoot->tiles, d, 0);
- mapRoot->updateTiles(mapRoot->wrapLeft, d, +sideLength);
- mapRoot->updateTiles(mapRoot->wrapRight, d, -sideLength);
+ mapRoot->updateTiles(mapRoot->tiles, d, 0, window);
+ mapRoot->updateTiles(mapRoot->wrapLeft, d, +sideLength, window);
+ mapRoot->updateTiles(mapRoot->wrapRight, d, -sideLength, window);
mapRoot->isTextureLinear = d->m_linearScaling;
diff --git a/src/location/maps/qgeotilefetcher.cpp b/src/location/maps/qgeotilefetcher.cpp
index 0e0e81ca..34bf686c 100644
--- a/src/location/maps/qgeotilefetcher.cpp
+++ b/src/location/maps/qgeotilefetcher.cpp
@@ -46,20 +46,28 @@
QT_BEGIN_NAMESPACE
QGeoTileFetcher::QGeoTileFetcher(QObject *parent)
-: QObject(parent), d_ptr(new QGeoTileFetcherPrivate)
+: QObject(*new QGeoTileFetcherPrivate(), parent)
{
Q_D(QGeoTileFetcher);
d->enabled_ = true;
- if (!d->queue_.isEmpty())
- d->timer_.start(0, this);
+// if (!d->queue_.isEmpty())
+// d->timer_.start(0, this);
}
-QGeoTileFetcher::~QGeoTileFetcher()
+QGeoTileFetcher::QGeoTileFetcher(QGeoTileFetcherPrivate &dd, QObject *parent)
+: QObject(dd,parent)
{
+ Q_D(QGeoTileFetcher);
+ d->enabled_ = true;
- delete d_ptr;
+// if (!d->queue_.isEmpty())
+// d->timer_.start(0, this);
+}
+
+QGeoTileFetcher::~QGeoTileFetcher()
+{
}
void QGeoTileFetcher::updateTileRequests(const QSet<QGeoTileSpec> &tilesAdded,
@@ -109,8 +117,12 @@ void QGeoTileFetcher::requestNextTile()
return;
QGeoTileSpec ts = d->queue_.takeFirst();
+ if (d->queue_.isEmpty())
+ d->timer_.stop();
QGeoTiledMapReply *reply = getTileImage(ts);
+ if (!reply)
+ return;
if (reply->isFinished()) {
handleReply(reply, ts);
@@ -123,9 +135,6 @@ void QGeoTileFetcher::requestNextTile()
d->invmap_.insert(ts, reply);
}
-
- if (d->queue_.isEmpty())
- d->timer_.stop();
}
void QGeoTileFetcher::finished()
@@ -193,7 +202,7 @@ void QGeoTileFetcher::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &
*******************************************************************************/
QGeoTileFetcherPrivate::QGeoTileFetcherPrivate()
-: enabled_(false)
+: QObjectPrivate(), enabled_(false)
{
}
diff --git a/src/location/maps/qgeotilefetcher_p.h b/src/location/maps/qgeotilefetcher_p.h
index cbd8b995..e3621d3d 100644
--- a/src/location/maps/qgeotilefetcher_p.h
+++ b/src/location/maps/qgeotilefetcher_p.h
@@ -65,6 +65,7 @@ class QGeoTileSpec;
class Q_LOCATION_EXPORT QGeoTileFetcher : public QObject
{
Q_OBJECT
+ Q_DECLARE_PRIVATE(QGeoTileFetcher)
public:
QGeoTileFetcher(QObject *parent = 0);
@@ -83,19 +84,18 @@ Q_SIGNALS:
void tileError(const QGeoTileSpec &spec, const QString &errorString);
protected:
+ QGeoTileFetcher(QGeoTileFetcherPrivate &dd, QObject *parent = 0);
+
void timerEvent(QTimerEvent *event);
QGeoTiledMappingManagerEngine::CacheAreas cacheHint() const;
virtual bool initialized() const;
private:
- QGeoTileFetcherPrivate *d_ptr;
virtual QGeoTiledMapReply *getTileImage(const QGeoTileSpec &spec) = 0;
void handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec);
- Q_DECLARE_PRIVATE(QGeoTileFetcher)
Q_DISABLE_COPY(QGeoTileFetcher)
-
friend class QGeoTiledMappingManagerEngine;
};
diff --git a/src/location/maps/qgeotilefetcher_p_p.h b/src/location/maps/qgeotilefetcher_p_p.h
index acd7288e..7e9db527 100644
--- a/src/location/maps/qgeotilefetcher_p_p.h
+++ b/src/location/maps/qgeotilefetcher_p_p.h
@@ -48,6 +48,8 @@
// We mean it.
//
+#include <QtCore/private/qobject_p.h>
+#include <QtLocation/private/qlocationglobal_p.h>
#include <QSize>
#include <QList>
#include <QMap>
@@ -64,8 +66,9 @@ class QGeoTileSpec;
class QGeoTiledMapReply;
class QGeoTiledMappingManagerEngine;
-class QGeoTileFetcherPrivate
+class Q_LOCATION_PRIVATE_EXPORT QGeoTileFetcherPrivate : public QObjectPrivate
{
+ Q_DECLARE_PUBLIC(QGeoTileFetcher)
public:
QGeoTileFetcherPrivate();
virtual ~QGeoTileFetcherPrivate();
diff --git a/src/location/qlocationglobal_p.h b/src/location/qlocationglobal_p.h
new file mode 100644
index 00000000..afc0760b
--- /dev/null
+++ b/src/location/qlocationglobal_p.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtPositioning 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 QLOCATIONGLOBAL_P_H
+#define QLOCATIONGLOBAL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qlocationglobal.h"
+
+QT_BEGIN_NAMESPACE
+
+#define Q_LOCATION_PRIVATE_EXPORT Q_LOCATION_EXPORT
+
+QT_END_NAMESPACE
+
+
+#endif // QLOCATIONGLOBAL_P_H
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);
diff --git a/src/positioning/configure.json b/src/positioning/configure.json
new file mode 100644
index 00000000..22b77be6
--- /dev/null
+++ b/src/positioning/configure.json
@@ -0,0 +1,48 @@
+{
+ "module": "positioning",
+ "testDir": "../../config.tests",
+
+ "libraries": {
+ "gypsy": {
+ "label": "Gypsy",
+ "test": "gypsy",
+ "sources": [
+ { "type": "pkgConfig", "args": "gypsy gconf-2.0" }
+ ]
+ }
+ },
+
+ "tests": {
+ "winrt_geolocation": {
+ "label": "WinRT Geolocation API",
+ "type": "compile",
+ "test": "winrt"
+ }
+ },
+
+ "features": {
+ "gypsy": {
+ "label": "Gypsy GPS Daemon",
+ "condition": "libs.gypsy",
+ "output": [ "privateFeature" ]
+ },
+ "winrt_geolocation": {
+ "label": "WinRT Geolocation API",
+ "condition": "tests.winrt_geolocation",
+ "output": [ "privateFeature" ]
+ }
+ },
+
+ "report": [
+ ],
+
+ "summary": [
+ {
+ "section": "Qt Location",
+ "entries": [
+ "gypsy",
+ "winrt_geolocation"
+ ]
+ }
+ ]
+}
diff --git a/src/positioning/qgeosatelliteinfo.cpp b/src/positioning/qgeosatelliteinfo.cpp
index 9168183e..79e39eff 100644
--- a/src/positioning/qgeosatelliteinfo.cpp
+++ b/src/positioning/qgeosatelliteinfo.cpp
@@ -283,7 +283,7 @@ QDataStream &operator<<(QDataStream &stream, const QGeoSatelliteInfo &info)
stream << info.d->signal;
stream << info.d->doubleAttribs;
stream << info.d->satId;
- stream << info.d->system;
+ stream << int(info.d->system);
return stream;
}
#endif
diff --git a/tests/applications/positioning_backend/widget.cpp b/tests/applications/positioning_backend/widget.cpp
index ecf9b7e8..93a42a80 100644
--- a/tests/applications/positioning_backend/widget.cpp
+++ b/tests/applications/positioning_backend/widget.cpp
@@ -71,6 +71,16 @@ void Widget::positionUpdated(QGeoPositionInfo gpsPos)
ui->labelVAccuracy->setText(QString::number(gpsPos.attribute(QGeoPositionInfo::VerticalAccuracy)));
else
ui->labelVAccuracy->setText(QStringLiteral("N/A"));
+
+ if (gpsPos.hasAttribute(QGeoPositionInfo::Direction))
+ ui->labelDirection->setText(QString::number(gpsPos.attribute(QGeoPositionInfo::Direction)));
+ else
+ ui->labelDirection->setText(QStringLiteral("N/A"));
+
+ if (gpsPos.hasAttribute(QGeoPositionInfo::GroundSpeed))
+ ui->labelSpeed->setText(QString::number(gpsPos.attribute(QGeoPositionInfo::GroundSpeed)));
+ else
+ ui->labelSpeed->setText(QStringLiteral("N/A"));
}
void Widget::positionTimedOut()
diff --git a/tests/applications/positioning_backend/widget.ui b/tests/applications/positioning_backend/widget.ui
index d19497d2..a96a83f6 100644
--- a/tests/applications/positioning_backend/widget.ui
+++ b/tests/applications/positioning_backend/widget.ui
@@ -61,56 +61,56 @@
</property>
</widget>
</item>
- <item row="3" column="0">
+ <item row="5" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<string>TimeStamp:</string>
</property>
</widget>
</item>
- <item row="3" column="1">
+ <item row="5" column="1">
<widget class="QLabel" name="labelTimeStamp">
<property name="text">
<string>N/A</string>
</property>
</widget>
</item>
- <item row="4" column="0">
+ <item row="7" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Horizontal Accuracy:</string>
</property>
</widget>
</item>
- <item row="4" column="1">
+ <item row="7" column="1">
<widget class="QLabel" name="labelHAccuracy">
<property name="text">
<string>N/A</string>
</property>
</widget>
</item>
- <item row="5" column="0">
+ <item row="8" column="0">
<widget class="QLabel" name="label_8">
<property name="text">
<string>Vertical Accuracy:</string>
</property>
</widget>
</item>
- <item row="5" column="1">
+ <item row="8" column="1">
<widget class="QLabel" name="labelVAccuracy">
<property name="text">
<string>N/A</string>
</property>
</widget>
</item>
- <item row="6" column="0">
+ <item row="9" column="0">
<widget class="QLabel" name="label_7">
<property name="text">
<string>TimeOut:</string>
</property>
</widget>
</item>
- <item row="6" column="1">
+ <item row="9" column="1">
<widget class="QLabel" name="labelTimeOut">
<property name="enabled">
<bool>true</bool>
@@ -120,28 +120,28 @@
</property>
</widget>
</item>
- <item row="7" column="0">
+ <item row="10" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Supported Methods:</string>
</property>
</widget>
</item>
- <item row="8" column="0">
+ <item row="11" column="0">
<widget class="QLabel" name="label_9">
<property name="text">
<string>Error State:</string>
</property>
</widget>
</item>
- <item row="8" column="1">
+ <item row="11" column="1">
<widget class="QLabel" name="labelErrorState">
<property name="text">
<string>N/A</string>
</property>
</widget>
</item>
- <item row="7" column="1">
+ <item row="10" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QLabel" name="labelSupported">
@@ -159,6 +159,34 @@
</item>
</layout>
</item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_11">
+ <property name="text">
+ <string>Direction:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLabel" name="labelDirection">
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="label_12">
+ <property name="text">
+ <string>Speed:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLabel" name="labelSpeed">
+ <property name="text">
+ <string>N/A</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
<item>
@@ -171,7 +199,7 @@
<rect>
<x>43</x>
<y>21</y>
- <width>243</width>
+ <width>251</width>
<height>71</height>
</rect>
</property>
diff --git a/tests/auto/qgeocameracapabilities/qgeocameracapabilities.pro b/tests/auto/qgeocameracapabilities/qgeocameracapabilities.pro
index f629a154..d061f18f 100644
--- a/tests/auto/qgeocameracapabilities/qgeocameracapabilities.pro
+++ b/tests/auto/qgeocameracapabilities/qgeocameracapabilities.pro
@@ -6,4 +6,4 @@ INCLUDEPATH += ../../../src/location/maps
SOURCES += tst_qgeocameracapabilities.cpp
-QT += location positioning-private testlib
+QT += location-private positioning-private testlib
diff --git a/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp b/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp
index e33dab39..121253fa 100644
--- a/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp
+++ b/tests/auto/qgeoserviceprovider/tst_qgeoserviceprovider.cpp
@@ -65,13 +65,14 @@ void tst_QGeoServiceProvider::tst_availableServiceProvider()
const QStringList provider = QGeoServiceProvider::availableServiceProviders();
// Currently provided plugins
- if (provider.count() != 7)
+ if (provider.count() != 8)
qWarning() << provider;
- QCOMPARE(provider.count(), 7);
+ QCOMPARE(provider.count(), 8);
// these providers are deployed
QVERIFY(provider.contains(QStringLiteral("mapbox")));
QVERIFY(provider.contains(QStringLiteral("here")));
QVERIFY(provider.contains(QStringLiteral("osm")));
+ QVERIFY(provider.contains(QStringLiteral("esri")));
// these providers exist for unit tests only
QVERIFY(provider.contains(QStringLiteral("geocode.test.plugin")));
QVERIFY(provider.contains(QStringLiteral("georoute.test.plugin")));
@@ -102,7 +103,7 @@ void tst_QGeoServiceProvider::tst_features_data()
QTest::newRow("mapbox") << QString("mapbox")
<< QGeoServiceProvider::MappingFeatures(QGeoServiceProvider::OnlineMappingFeature)
<< QGeoServiceProvider::GeocodingFeatures(QGeoServiceProvider::NoGeocodingFeatures)
- << QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::NoRoutingFeatures)
+ << QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::OnlineRoutingFeature)
<< QGeoServiceProvider::PlacesFeatures(QGeoServiceProvider::NoPlacesFeatures);
QTest::newRow("here") << QString("here")
@@ -124,6 +125,13 @@ void tst_QGeoServiceProvider::tst_features_data()
| QGeoServiceProvider::ReverseGeocodingFeature)
<< QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::OnlineRoutingFeature)
<< QGeoServiceProvider::PlacesFeatures(QGeoServiceProvider::OnlinePlacesFeature);
+
+ QTest::newRow("esri") << QString("esri")
+ << QGeoServiceProvider::MappingFeatures(QGeoServiceProvider::OnlineMappingFeature)
+ << QGeoServiceProvider::GeocodingFeatures(QGeoServiceProvider::OnlineGeocodingFeature
+ | QGeoServiceProvider::ReverseGeocodingFeature)
+ << QGeoServiceProvider::RoutingFeatures(QGeoServiceProvider::OnlineRoutingFeature)
+ << QGeoServiceProvider::PlacesFeatures(QGeoServiceProvider::NoPlacesFeatures);
}
void tst_QGeoServiceProvider::tst_features()
diff --git a/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp b/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp
index e7026cff..cc2672b2 100644
--- a/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp
+++ b/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp
@@ -109,7 +109,7 @@ void tst_QGeoTiledMap::initTestCase()
QVERIFY2(provider->error() == QGeoServiceProvider::NoError, "Could not load plugin: " + provider->errorString().toLatin1());
m_map.reset(static_cast<QGeoTiledMapTest*>(mappingManager->createMap(this)));
QVERIFY(m_map);
- m_map->setSize(QSize(16, 16));
+ m_map->setViewportSize(QSize(16, 16));
m_fetcher = static_cast<QGeoTileFetcherTest*>(m_map->m_engine->tileFetcher());
m_tilesCounter.reset(new FetchTileCounter());
connect(m_fetcher, SIGNAL(tileFetched(const QGeoTileSpec&)), m_tilesCounter.data(), SLOT(tileFetched(const QGeoTileSpec&)));
diff --git a/tests/plugins/declarativetestplugin/locationtest.cpp b/tests/plugins/declarativetestplugin/locationtest.cpp
index f0389d90..44e74e86 100644
--- a/tests/plugins/declarativetestplugin/locationtest.cpp
+++ b/tests/plugins/declarativetestplugin/locationtest.cpp
@@ -48,7 +48,7 @@ static QObject *helper_factory(QQmlEngine *engine, QJSEngine *scriptEngine)
class QLocationDeclarativeTestModule: public QQmlExtensionPlugin
{
Q_OBJECT
- Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
public:
virtual void registerTypes(const char* uri)
{