summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
m---------src/3rdparty/mapbox-gl-native0
-rw-r--r--src/imports/location/location.cpp17
-rw-r--r--src/imports/location/plugins.qmltypes63
-rw-r--r--src/imports/locationlabs/locationlabs.cpp12
-rw-r--r--src/imports/locationlabs/locationlabs.pro2
-rw-r--r--src/imports/locationlabs/plugins.qmltypes104
-rw-r--r--src/imports/positioning/locationsingleton.cpp62
-rw-r--r--src/imports/positioning/locationsingleton.h5
-rw-r--r--src/imports/positioning/plugins.qmltypes26
-rw-r--r--src/imports/positioning/positioning.cpp11
-rw-r--r--src/location/configure.json2
-rw-r--r--src/location/declarativemaps/declarativemaps.pri108
-rw-r--r--src/location/declarativemaps/locationvaluetypehelper.cpp2
-rw-r--r--src/location/declarativemaps/qdeclarativecirclemapitem.cpp18
-rw-r--r--src/location/declarativemaps/qdeclarativecirclemapitem_p.h1
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap.cpp637
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap_p.h19
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitembase.cpp99
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitembase_p.h41
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp63
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h23
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager.cpp (renamed from src/locationlabs/qlocationlabsglobal_p.h)64
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h120
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemview.cpp270
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemview_p.h37
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapquickitem.cpp19
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapquickitem_p.h1
-rw-r--r--src/location/declarativemaps/qdeclarativegeoroute.cpp105
-rw-r--r--src/location/declarativemaps/qdeclarativegeoroute_p.h26
-rw-r--r--src/location/declarativemaps/qdeclarativegeoroutemodel.cpp2
-rw-r--r--src/location/declarativemaps/qdeclarativegeoroutesegment.cpp2
-rw-r--r--src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp1
-rw-r--r--src/location/declarativemaps/qdeclarativepolygonmapitem.cpp13
-rw-r--r--src/location/declarativemaps/qdeclarativepolygonmapitem_p.h4
-rw-r--r--src/location/declarativemaps/qdeclarativepolylinemapitem.cpp163
-rw-r--r--src/location/declarativemaps/qdeclarativepolylinemapitem_p.h12
-rw-r--r--src/location/declarativemaps/qdeclarativerectanglemapitem.cpp18
-rw-r--r--src/location/declarativemaps/qdeclarativerectanglemapitem_p.h1
-rw-r--r--src/location/declarativemaps/qquickgeomapgesturearea.cpp2
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchmodelbase.cpp6
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchmodelbase_p.h1
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp126
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h23
-rw-r--r--src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp29
-rw-r--r--src/location/doc/src/plugins/esri.qdoc14
-rw-r--r--src/location/doc/src/plugins/mapboxgl.qdoc5
-rw-r--r--src/location/doc/src/qtlocation-qml.qdoc138
-rw-r--r--src/location/doc/src/qtlocation.qdoc24
-rw-r--r--src/location/labs/qdeclarativenavigator.cpp85
-rw-r--r--src/location/labs/qdeclarativenavigator_p.h1
-rw-r--r--src/location/labs/qdeclarativenavigator_p_p.h24
-rw-r--r--src/location/maps/maps.pri3
-rw-r--r--src/location/maps/qgeocameratiles.cpp135
-rw-r--r--src/location/maps/qgeocameratiles_p.h4
-rw-r--r--src/location/maps/qgeocameratiles_p_p.h152
-rw-r--r--src/location/maps/qgeomap.cpp53
-rw-r--r--src/location/maps/qgeomap_p.h11
-rw-r--r--src/location/maps/qgeomap_p_p.h11
-rw-r--r--src/location/maps/qgeomapparameter.cpp6
-rw-r--r--src/location/maps/qgeomapparameter_p.h1
-rw-r--r--src/location/maps/qgeoprojection.cpp130
-rw-r--r--src/location/maps/qgeoprojection_p.h16
-rw-r--r--src/location/maps/qgeoroute.cpp175
-rw-r--r--src/location/maps/qgeoroute.h28
-rw-r--r--src/location/maps/qgeoroute_p.h24
-rw-r--r--src/location/maps/qgeorouteparserosrmv5.cpp60
-rw-r--r--src/location/maps/qgeoroutesegment.cpp48
-rw-r--r--src/location/maps/qgeoroutesegment.h3
-rw-r--r--src/location/maps/qgeoroutesegment_p.h8
-rw-r--r--src/location/maps/qgeoserviceprovider.cpp48
-rw-r--r--src/location/maps/qgeoserviceprovider.h5
-rw-r--r--src/location/maps/qgeoserviceprovider_p.h4
-rw-r--r--src/location/maps/qgeoserviceproviderfactory.cpp13
-rw-r--r--src/location/maps/qgeoserviceproviderfactory.h14
-rw-r--r--src/location/maps/qgeotiledmap.cpp28
-rw-r--r--src/location/maps/qgeotiledmap_p_p.h8
-rw-r--r--src/location/maps/qgeotiledmapscene.cpp184
-rw-r--r--src/location/maps/qgeotiledmapscene_p.h1
-rw-r--r--src/location/maps/qgeotiledmapscene_p_p.h193
-rw-r--r--src/location/maps/qnavigationmanager.cpp39
-rw-r--r--src/location/maps/qnavigationmanager_p.h26
-rw-r--r--src/location/maps/qnavigationmanagerengine.cpp71
-rw-r--r--src/location/maps/qnavigationmanagerengine_p.h49
-rw-r--r--src/location/places/places.pri1
-rw-r--r--src/location/places/qplacereply.cpp13
-rw-r--r--src/location/places/qplacereply.h1
-rw-r--r--src/location/places/qplacesearchrequest.cpp44
-rw-r--r--src/location/places/qplacesearchrequest.h2
-rw-r--r--src/location/places/qplacesearchrequest_p.h (renamed from src/location/declarativemaps/mapitemviewdelegateincubator_p.h)49
-rw-r--r--src/plugins/geoservices/esri/esri.pro10
-rw-r--r--src/plugins/geoservices/esri/esri_plugin.json3
-rw-r--r--src/plugins/geoservices/esri/geocodereply_esri.cpp2
-rw-r--r--src/plugins/geoservices/esri/geocodereply_esri.h2
-rw-r--r--src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp2
-rw-r--r--src/plugins/geoservices/esri/geocodingmanagerengine_esri.h2
-rw-r--r--src/plugins/geoservices/esri/geomapsource.cpp2
-rw-r--r--src/plugins/geoservices/esri/geomapsource.h2
-rw-r--r--src/plugins/geoservices/esri/georoutejsonparser_esri.cpp2
-rw-r--r--src/plugins/geoservices/esri/georoutejsonparser_esri.h2
-rw-r--r--src/plugins/geoservices/esri/georoutereply_esri.cpp2
-rw-r--r--src/plugins/geoservices/esri/georoutereply_esri.h2
-rw-r--r--src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp2
-rw-r--r--src/plugins/geoservices/esri/georoutingmanagerengine_esri.h2
-rw-r--r--src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp9
-rw-r--r--src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h2
-rw-r--r--src/plugins/geoservices/esri/geotiledmap_esri.cpp2
-rw-r--r--src/plugins/geoservices/esri/geotiledmap_esri.h2
-rw-r--r--src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp8
-rw-r--r--src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h2
-rw-r--r--src/plugins/geoservices/esri/geotiledmapreply_esri.cpp2
-rw-r--r--src/plugins/geoservices/esri/geotiledmapreply_esri.h2
-rw-r--r--src/plugins/geoservices/esri/geotilefetcher_esri.cpp2
-rw-r--r--src/plugins/geoservices/esri/geotilefetcher_esri.h2
-rw-r--r--src/plugins/geoservices/esri/placecategoriesreply_esri.cpp65
-rw-r--r--src/plugins/geoservices/esri/placecategoriesreply_esri.h61
-rw-r--r--src/plugins/geoservices/esri/placemanagerengine_esri.cpp369
-rw-r--r--src/plugins/geoservices/esri/placemanagerengine_esri.h109
-rw-r--r--src/plugins/geoservices/esri/placesearchreply_esri.cpp223
-rw-r--r--src/plugins/geoservices/esri/placesearchreply_esri.h78
-rw-r--r--src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp24
-rw-r--r--src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp7
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp49
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h2
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h13
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp65
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.h1
-rw-r--r--src/plugins/geoservices/mapboxgl/qgeoserviceproviderpluginmapboxgl.cpp6
-rw-r--r--src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp71
-rw-r--r--src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h13
-rw-r--r--src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp10
-rw-r--r--src/plugins/geoservices/nokia/qgeoroutexmlparser.cpp198
-rw-r--r--src/plugins/geoservices/nokia/qgeoroutexmlparser.h24
-rw-r--r--src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp29
-rw-r--r--src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp6
-rw-r--r--src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp10
-rw-r--r--src/plugins/geoservices/osm/qgeoroutereplyosm.cpp7
-rw-r--r--src/plugins/geoservices/osm/qplacemanagerengineosm.cpp2
-rw-r--r--src/plugins/geoservices/osm/qplacesearchreplyosm.cpp7
-rw-r--r--src/plugins/position/android/src/qgeopositioninfosource_android.cpp4
-rw-r--r--src/plugins/position/corelocation/qgeopositioninfosource_cl.mm71
-rw-r--r--src/plugins/position/geoclue2/geoclue2.pro30
-rw-r--r--src/plugins/position/geoclue2/geocluetypes.cpp62
-rw-r--r--src/plugins/position/geoclue2/geocluetypes.h63
-rw-r--r--src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Client.xml122
-rw-r--r--src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Location.xml96
-rw-r--r--src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Manager.xml60
-rw-r--r--src/plugins/position/geoclue2/plugin.json9
-rw-r--r--src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2.cpp443
-rw-r--r--src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2_p.h97
-rw-r--r--src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.cpp66
-rw-r--r--src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.h68
-rw-r--r--src/plugins/position/position.pro3
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp211
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h8
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp19
-rw-r--r--src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h4
-rw-r--r--src/positioning/doc/src/qtpositioning-qml.qdoc54
-rw-r--r--src/positioning/doc/src/qtpositioning.qdoc17
-rw-r--r--src/positioning/qgeopath.cpp84
-rw-r--r--src/positioning/qgeopath.h1
-rw-r--r--src/positioning/qgeopath_p.h8
-rw-r--r--src/positioning/qgeopolygon.cpp112
-rw-r--r--src/positioning/qgeopolygon.h14
-rw-r--r--src/positioning/qgeopositioninfosource.cpp8
-rw-r--r--src/positioning/qgeopositioninfosource.h1
-rw-r--r--src/positioningquick/qdeclarativepositionsource.cpp30
-rw-r--r--src/positioningquick/qdeclarativepositionsource_p.h1
-rw-r--r--src/positioningquick/qquickgeocoordinateanimation.cpp (renamed from src/imports/positioning/qquickgeocoordinateanimation.cpp)0
-rw-r--r--src/positioningquick/qquickgeocoordinateanimation_p.h (renamed from src/imports/positioning/qquickgeocoordinateanimation_p.h)5
-rw-r--r--src/positioningquick/qquickgeocoordinateanimation_p_p.h (renamed from src/imports/positioning/qquickgeocoordinateanimation_p_p.h)0
170 files changed, 6076 insertions, 1526 deletions
diff --git a/src/3rdparty/mapbox-gl-native b/src/3rdparty/mapbox-gl-native
-Subproject b59b0450c60b3df9e0852f62f6c8a6024889cd9
+Subproject 4b85252fbe811a786c6ee9eabedb7639b031dc5
diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp
index 183d11d3..2c2331bf 100644
--- a/src/imports/location/location.cpp
+++ b/src/imports/location/location.cpp
@@ -73,13 +73,6 @@
#include <QtCore/QDebug>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtLocation);
-#endif
-}
-
QT_BEGIN_NAMESPACE
@@ -91,7 +84,7 @@ class QtLocationDeclarativeModule: public QQmlExtensionPlugin
FILE "plugin.json")
public:
- QtLocationDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
+ QtLocationDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { }
virtual void registerTypes(const char *uri)
{
if (QLatin1String(uri) == QLatin1String("QtLocation")) {
@@ -193,6 +186,14 @@ public:
qmlRegisterType<QDeclarativeGeoServiceProvider, 11>(uri, major, minor, "Plugin");
qmlRegisterType<QDeclarativeGeoWaypoint>(uri, major, minor, "Waypoint");
+ // Register the 5.12 types
+ minor = 12;
+ qmlRegisterType<QDeclarativeGeoMapItemView, 12>(uri, major, minor, "MapItemView");
+ qmlRegisterType<QDeclarativeSearchResultModel, 12>(uri, major, minor, "PlaceSearchModel");
+ qmlRegisterType<QDeclarativeGeoMap, 12>(uri, major, minor, "Map");
+ qmlRegisterType<QDeclarativeGeoRoute, 12>(uri, major, minor, "Route");
+ qmlRegisterType<QDeclarativeGeoRouteLeg, 12>(uri, major, minor, "RouteLeg");
+
// Register the latest Qt version as QML type version
qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR);
diff --git a/src/imports/location/plugins.qmltypes b/src/imports/location/plugins.qmltypes
index d2d9030a..c7ab0e69 100644
--- a/src/imports/location/plugins.qmltypes
+++ b/src/imports/location/plugins.qmltypes
@@ -4,10 +4,10 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtLocation 5.11'
+// 'qmlplugindump -nonrelocatable QtLocation 5.12'
Module {
- dependencies: ["QtQuick 2.8"]
+ dependencies: ["QtQuick 2.12"]
Component {
name: "QDeclarativeCategory"
prototype: "QObject"
@@ -149,8 +149,12 @@ Module {
name: "QDeclarativeGeoMap"
defaultProperty: "data"
prototype: "QQuickItem"
- exports: ["QtLocation/Map 5.0", "QtLocation/Map 5.11"]
- exportMetaObjectRevisions: [0, 11]
+ exports: [
+ "QtLocation/Map 5.0",
+ "QtLocation/Map 5.11",
+ "QtLocation/Map 5.12"
+ ]
+ exportMetaObjectRevisions: [0, 11, 12]
Property { name: "gesture"; type: "QQuickGeoMapGestureArea"; isReadonly: true; isPointer: true }
Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true }
Property { name: "minimumZoomLevel"; type: "double" }
@@ -179,6 +183,7 @@ Module {
Property { name: "copyrightsVisible"; type: "bool" }
Property { name: "color"; type: "QColor" }
Property { name: "mapReady"; type: "bool"; isReadonly: true }
+ Property { name: "visibleArea"; revision: 12; type: "QRectF" }
Signal {
name: "pluginChanged"
Parameter { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true }
@@ -364,10 +369,10 @@ Module {
]
isCreatable: false
exportMetaObjectRevisions: [0, 11]
- Property { name: "geoShape"; type: "QGeoShape"; isReadonly: true }
+ Property { name: "geoShape"; type: "QGeoShape" }
Signal { name: "mapItemOpacityChanged" }
- Signal { name: "enterTransitionFinished"; revision: 11 }
- Signal { name: "exitTransitionFinished"; revision: 11 }
+ Signal { name: "addTransitionFinished"; revision: 12 }
+ Signal { name: "removeTransitionFinished"; revision: 12 }
}
Component {
name: "QDeclarativeGeoMapItemGroup"
@@ -375,15 +380,23 @@ Module {
prototype: "QQuickItem"
exports: ["QtLocation/MapItemGroup 5.9"]
exportMetaObjectRevisions: [0]
+ Signal { name: "mapItemOpacityChanged" }
+ Signal { name: "addTransitionFinished" }
+ Signal { name: "removeTransitionFinished" }
}
Component {
name: "QDeclarativeGeoMapItemView"
- prototype: "QObject"
- exports: ["QtLocation/MapItemView 5.0"]
- exportMetaObjectRevisions: [0]
+ defaultProperty: "data"
+ prototype: "QDeclarativeGeoMapItemGroup"
+ exports: ["QtLocation/MapItemView 5.0", "QtLocation/MapItemView 5.12"]
+ exportMetaObjectRevisions: [0, 12]
Property { name: "model"; type: "QVariant" }
Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
Property { name: "autoFitViewport"; type: "bool" }
+ Property { name: "add"; revision: 12; type: "QQuickTransition"; isPointer: true }
+ Property { name: "remove"; revision: 12; type: "QQuickTransition"; isPointer: true }
+ Property { name: "mapItems"; revision: 12; type: "QList<QQuickItem*>"; isReadonly: true }
+ Property { name: "incubateDelegates"; revision: 12; type: "bool" }
}
Component {
name: "QDeclarativeGeoMapParameter"
@@ -448,8 +461,12 @@ Module {
Component {
name: "QDeclarativeGeoRoute"
prototype: "QObject"
- exports: ["QtLocation/Route 5.0", "QtLocation/Route 5.11"]
- exportMetaObjectRevisions: [0, 11]
+ exports: [
+ "QtLocation/Route 5.0",
+ "QtLocation/Route 5.11",
+ "QtLocation/Route 5.12"
+ ]
+ exportMetaObjectRevisions: [0, 11, 12]
Property { name: "bounds"; type: "QGeoRectangle"; isReadonly: true }
Property { name: "travelTime"; type: "int"; isReadonly: true }
Property { name: "distance"; type: "double"; isReadonly: true }
@@ -462,6 +479,20 @@ Module {
isReadonly: true
isPointer: true
}
+ Property { name: "legs"; revision: 12; type: "QList<QObject*>"; isReadonly: true }
+ Method {
+ name: "equals"
+ type: "bool"
+ Parameter { name: "other"; type: "QDeclarativeGeoRoute"; isPointer: true }
+ }
+ }
+ Component {
+ name: "QDeclarativeGeoRouteLeg"
+ prototype: "QDeclarativeGeoRoute"
+ exports: ["QtLocation/RouteLeg 5.12"]
+ exportMetaObjectRevisions: [12]
+ Property { name: "legIndex"; type: "int"; isReadonly: true }
+ Property { name: "overallRoute"; type: "QObject"; isReadonly: true; isPointer: true }
}
Component {
name: "QDeclarativeGeoRouteModel"
@@ -1258,8 +1289,11 @@ Module {
Component {
name: "QDeclarativeSearchResultModel"
prototype: "QDeclarativeSearchModelBase"
- exports: ["QtLocation/PlaceSearchModel 5.0"]
- exportMetaObjectRevisions: [0]
+ exports: [
+ "QtLocation/PlaceSearchModel 5.0",
+ "QtLocation/PlaceSearchModel 5.12"
+ ]
+ exportMetaObjectRevisions: [0, 12]
Enum {
name: "SearchResultType"
values: {
@@ -1284,6 +1318,7 @@ Module {
Property { name: "count"; type: "int"; isReadonly: true }
Property { name: "favoritesPlugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true }
Property { name: "favoritesMatchParameters"; type: "QVariantMap" }
+ Property { name: "incremental"; revision: 12; type: "bool" }
Signal { name: "rowCountChanged" }
Signal { name: "dataChanged" }
Method {
diff --git a/src/imports/locationlabs/locationlabs.cpp b/src/imports/locationlabs/locationlabs.cpp
index c48fd7d9..cebdf0e4 100644
--- a/src/imports/locationlabs/locationlabs.cpp
+++ b/src/imports/locationlabs/locationlabs.cpp
@@ -46,13 +46,6 @@
#include <QtQml/qqml.h>
#include <QtCore/QDebug>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_Qt_labs_location);
-#endif
-}
-
QT_BEGIN_NAMESPACE
@@ -64,7 +57,7 @@ class QtLocationLabsDeclarativeModule: public QQmlExtensionPlugin
FILE "plugin.json")
public:
- QtLocationLabsDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
+ QtLocationLabsDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { }
virtual void registerTypes(const char *uri)
{
if (QLatin1String(uri) == QLatin1String("Qt.labs.location")) {
@@ -81,9 +74,6 @@ public:
qmlRegisterType<QMapPolygonObject>(uri, major, minor, "MapPolygonObject");
qmlRegisterType<QMapPolylineObject>(uri, major, minor, "MapPolylineObject");
qmlRegisterType<QDeclarativeNavigator>(uri, major, minor, "Navigator");
-
- // Register the latest Qt version as QML type version
- qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR);
} else {
qDebug() << "Unsupported URI given to load location QML plugin: " << QLatin1String(uri);
}
diff --git a/src/imports/locationlabs/locationlabs.pro b/src/imports/locationlabs/locationlabs.pro
index db7f5ec2..2fcc1adc 100644
--- a/src/imports/locationlabs/locationlabs.pro
+++ b/src/imports/locationlabs/locationlabs.pro
@@ -3,7 +3,7 @@ QT += quick-private network positioning-private location-private qml-private cor
TARGET = locationlabsplugin
CXX_MODULE = $$TARGET
TARGETPATH = Qt/labs/location
-IMPORT_VERSION = 5.11
+IMPORT_VERSION = 1.0
SOURCES += \
locationlabs.cpp
diff --git a/src/imports/locationlabs/plugins.qmltypes b/src/imports/locationlabs/plugins.qmltypes
index d5e30c38..e985e844 100644
--- a/src/imports/locationlabs/plugins.qmltypes
+++ b/src/imports/locationlabs/plugins.qmltypes
@@ -4,10 +4,43 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable Qt.labs.location 5.11'
+// 'qmlplugindump -nonrelocatable Qt.labs.location 1.0'
Module {
- dependencies: ["QtQuick 2.8"]
+ dependencies: ["QtQuick 2.11"]
+ Component {
+ name: "QDeclarativeNavigator"
+ defaultProperty: "quickChildren"
+ prototype: "QParameterizableObject"
+ exports: ["Qt.labs.location/Navigator 1.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "plugin"; type: "QDeclarativeGeoServiceProvider"; isPointer: true }
+ Property { name: "map"; type: "QDeclarativeGeoMap"; isPointer: true }
+ Property { name: "route"; type: "QDeclarativeGeoRoute"; isPointer: true }
+ Property { name: "positionSource"; type: "QDeclarativePositionSource"; isPointer: true }
+ Property { name: "active"; type: "bool" }
+ Property { name: "navigatorReady"; type: "bool"; isReadonly: true }
+ Property { name: "trackPositionSource"; type: "bool" }
+ Property { name: "currentRoute"; type: "QDeclarativeGeoRoute"; isReadonly: true; isPointer: true }
+ Property { name: "currentSegment"; type: "int"; isReadonly: true }
+ Signal {
+ name: "navigatorReadyChanged"
+ Parameter { name: "ready"; type: "bool" }
+ }
+ Signal {
+ name: "trackPositionSourceChanged"
+ Parameter { name: "trackPositionSource"; type: "bool" }
+ }
+ Signal {
+ name: "activeChanged"
+ Parameter { name: "active"; type: "bool" }
+ }
+ Signal {
+ name: "waypointReached"
+ Parameter { name: "pos"; type: "const QDeclarativeGeoWaypoint"; isPointer: true }
+ }
+ Signal { name: "destinationReached" }
+ }
Component {
name: "QGeoMapObject"
defaultProperty: "quickChildren"
@@ -32,10 +65,44 @@ Module {
Signal { name: "completed" }
}
Component {
+ name: "QMapCircleObject"
+ defaultProperty: "quickChildren"
+ prototype: "QGeoMapObject"
+ exports: ["Qt.labs.location/MapCircleObject 1.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "center"; type: "QGeoCoordinate" }
+ Property { name: "radius"; type: "double" }
+ Property { name: "color"; type: "QColor" }
+ Property {
+ name: "border"
+ type: "QDeclarativeMapLineProperties"
+ isReadonly: true
+ isPointer: true
+ }
+ }
+ Component {
+ name: "QMapIconObject"
+ defaultProperty: "quickChildren"
+ prototype: "QGeoMapObject"
+ exports: ["Qt.labs.location/MapIconObject 1.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "coordinate"; type: "QGeoCoordinate" }
+ Property { name: "content"; type: "QVariant" }
+ Property { name: "size"; type: "QSizeF" }
+ Signal {
+ name: "contentChanged"
+ Parameter { name: "content"; type: "QVariant" }
+ }
+ Signal {
+ name: "coordinateChanged"
+ Parameter { name: "coordinate"; type: "QGeoCoordinate" }
+ }
+ }
+ Component {
name: "QMapObjectView"
defaultProperty: "quickChildren"
prototype: "QGeoMapObject"
- exports: ["Qt.labs.location/MapObjectView 5.11"]
+ exports: ["Qt.labs.location/MapObjectView 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "model"; type: "QVariant" }
Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
@@ -57,10 +124,39 @@ Module {
}
}
Component {
+ name: "QMapPolygonObject"
+ defaultProperty: "quickChildren"
+ prototype: "QGeoMapObject"
+ exports: ["Qt.labs.location/MapPolygonObject 1.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "path"; type: "QVariantList" }
+ Property { name: "color"; type: "QColor" }
+ Property {
+ name: "border"
+ type: "QDeclarativeMapLineProperties"
+ isReadonly: true
+ isPointer: true
+ }
+ }
+ Component {
+ name: "QMapPolylineObject"
+ defaultProperty: "quickChildren"
+ prototype: "QGeoMapObject"
+ exports: ["Qt.labs.location/MapPolylineObject 1.0"]
+ exportMetaObjectRevisions: [0]
+ Property { name: "path"; type: "QVariantList" }
+ Property {
+ name: "line"
+ type: "QDeclarativeMapLineProperties"
+ isReadonly: true
+ isPointer: true
+ }
+ }
+ Component {
name: "QMapRouteObject"
defaultProperty: "quickChildren"
prototype: "QGeoMapObject"
- exports: ["Qt.labs.location/MapRouteObject 5.11"]
+ exports: ["Qt.labs.location/MapRouteObject 1.0"]
exportMetaObjectRevisions: [0]
Property { name: "route"; type: "QDeclarativeGeoRoute"; isPointer: true }
Signal {
diff --git a/src/imports/positioning/locationsingleton.cpp b/src/imports/positioning/locationsingleton.cpp
index 35b0d8d9..e355851e 100644
--- a/src/imports/positioning/locationsingleton.cpp
+++ b/src/imports/positioning/locationsingleton.cpp
@@ -38,6 +38,9 @@
****************************************************************************/
#include "locationsingleton.h"
+#include <QtPositioning/private/qwebmercator_p.h>
+#include <QtPositioning/private/qdoublevector2d_p.h>
+#include <QDebug>
static QGeoCoordinate parseCoordinate(const QJSValue &value, bool *ok)
{
@@ -265,6 +268,39 @@ QGeoPolygon LocationSingleton::polygon(const QVariantList &coordinates) const
}
/*!
+ \qmlmethod geopolygon QtPositioning::polygon(list<coordinate> perimeter, list<list<coordinate>> holes) const
+
+ Constructs a polygon from coordinates for perimeter and inner holes.
+
+ \sa {geopolygon}
+ \since 5.12
+*/
+QGeoPolygon LocationSingleton::polygon(const QVariantList &perimeter, const QVariantList &holes) const
+{
+ QList<QGeoCoordinate> internalCoordinates;
+ for (int i = 0; i < perimeter.size(); i++) {
+ if (perimeter.at(i).canConvert<QGeoCoordinate>())
+ internalCoordinates << perimeter.at(i).value<QGeoCoordinate>();
+ }
+ QGeoPolygon poly(internalCoordinates);
+
+ for (int i = 0; i < holes.size(); i++) {
+ if (holes.at(i).type() == QVariant::List) {
+ QList<QGeoCoordinate> hole;
+ const QVariantList &holeData = holes.at(i).toList();
+ for (int j = 0; j < holeData.size(); j++) {
+ if (holeData.at(j).canConvert<QGeoCoordinate>())
+ hole << holeData.at(j).value<QGeoCoordinate>();
+ }
+ if (hole.size())
+ poly.addHole(hole);
+ }
+ }
+
+ return poly;
+}
+
+/*!
\qmlmethod geocircle QtPositioning::shapeToCircle(geoshape shape) const
Converts \a shape to a geocircle.
@@ -315,3 +351,29 @@ QGeoPolygon LocationSingleton::shapeToPolygon(const QGeoShape &shape) const
{
return QGeoPolygon(shape);
}
+
+/*!
+ \qmlmethod coordinate QtPositioning::mercatorToCoord(point mercator) const
+
+ Converts a mercator coordinate into a latitude-longitude coordinate.
+
+ \sa {coordToMercator}
+ \since 5.12
+*/
+QGeoCoordinate LocationSingleton::mercatorToCoord(const QPointF &mercator) const
+{
+ return QWebMercator::mercatorToCoord(QDoubleVector2D(mercator.x(), mercator.y()));
+}
+
+/*!
+ \qmlmethod point QtPositioning::coordToMercator(coordinate coord) const
+
+ Converts a coordinate into a mercator coordinate.
+
+ \sa {mercatorToCoord}
+ \since 5.12
+*/
+QPointF LocationSingleton::coordToMercator(const QGeoCoordinate &coord) const
+{
+ return QWebMercator::coordToMercator(coord).toPointF();
+}
diff --git a/src/imports/positioning/locationsingleton.h b/src/imports/positioning/locationsingleton.h
index 56d35b70..9372b8f1 100644
--- a/src/imports/positioning/locationsingleton.h
+++ b/src/imports/positioning/locationsingleton.h
@@ -50,6 +50,7 @@
#include <QtPositioning/QGeoPolygon>
#include <QtQml/QJSValue>
#include <QVariant>
+#include <QPointF>
class LocationSingleton : public QObject
{
@@ -79,11 +80,15 @@ public:
Q_INVOKABLE QGeoPolygon polygon() const;
Q_INVOKABLE QGeoPolygon polygon(const QVariantList &value) const;
+ Q_INVOKABLE QGeoPolygon polygon(const QVariantList &perimeter, const QVariantList &holes) const;
Q_INVOKABLE QGeoCircle shapeToCircle(const QGeoShape &shape) const;
Q_INVOKABLE QGeoRectangle shapeToRectangle(const QGeoShape &shape) const;
Q_INVOKABLE QGeoPath shapeToPath(const QGeoShape &shape) const;
Q_INVOKABLE QGeoPolygon shapeToPolygon(const QGeoShape &shape) const;
+
+ Q_REVISION(12) Q_INVOKABLE QGeoCoordinate mercatorToCoord(const QPointF &mercator) const;
+ Q_REVISION(12) Q_INVOKABLE QPointF coordToMercator(const QGeoCoordinate &coord) const;
};
#endif // LOCATIONSINGLETON_H
diff --git a/src/imports/positioning/plugins.qmltypes b/src/imports/positioning/plugins.qmltypes
index dab72802..c599d841 100644
--- a/src/imports/positioning/plugins.qmltypes
+++ b/src/imports/positioning/plugins.qmltypes
@@ -4,10 +4,10 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -nonrelocatable QtPositioning 5.11'
+// 'qmlplugindump -nonrelocatable QtPositioning 5.12'
Module {
- dependencies: ["QtQuick 2.8"]
+ dependencies: ["QtQuick 2.12"]
Component {
name: "LocationSingleton"
prototype: "QObject"
@@ -73,13 +73,19 @@ Module {
type: "QGeoPath"
Parameter { name: "value"; type: "QJSValue" }
}
- Method { name: "polygon"; type: "QGeoPath" }
+ Method { name: "polygon"; type: "QGeoPolygon" }
Method {
name: "polygon"
- type: "QGeoPath"
+ type: "QGeoPolygon"
Parameter { name: "value"; type: "QVariantList" }
}
Method {
+ name: "polygon"
+ type: "QGeoPolygon"
+ Parameter { name: "perimeter"; type: "QVariantList" }
+ Parameter { name: "holes"; type: "QVariantList" }
+ }
+ Method {
name: "shapeToCircle"
type: "QGeoCircle"
Parameter { name: "shape"; type: "QGeoShape" }
@@ -99,6 +105,18 @@ Module {
type: "QGeoPolygon"
Parameter { name: "shape"; type: "QGeoShape" }
}
+ Method {
+ name: "mercatorToCoord"
+ revision: 12
+ type: "QGeoCoordinate"
+ Parameter { name: "mercator"; type: "QPointF" }
+ }
+ Method {
+ name: "coordToMercator"
+ revision: 12
+ type: "QPointF"
+ Parameter { name: "coord"; type: "QGeoCoordinate" }
+ }
}
Component {
name: "QDeclarativeGeoAddress"
diff --git a/src/imports/positioning/positioning.cpp b/src/imports/positioning/positioning.cpp
index 6af79b54..a3cb98fa 100644
--- a/src/imports/positioning/positioning.cpp
+++ b/src/imports/positioning/positioning.cpp
@@ -45,7 +45,7 @@
#include <QtPositioningQuick/private/qdeclarativepositionsource_p.h>
#include <QtPositioningQuick/private/qdeclarativeposition_p.h>
-#include "qquickgeocoordinateanimation_p.h"
+#include <QtPositioningQuick/private/qquickgeocoordinateanimation_p.h>
#include "locationsingleton.h"
#include <QtCore/QVariantAnimation>
@@ -62,13 +62,6 @@
#include <QtCore/QDebug>
-static void initResources()
-{
-#ifdef QT_STATIC
- Q_INIT_RESOURCE(qmake_QtPositioning);
-#endif
-}
-
QT_BEGIN_NAMESPACE
/*!
@@ -572,7 +565,7 @@ class QtPositioningDeclarativeModule: public QQmlExtensionPlugin
FILE "plugin.json")
public:
- QtPositioningDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); }
+ QtPositioningDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { }
virtual void registerTypes(const char *uri)
{
if (QLatin1String(uri) == QStringLiteral("QtPositioning")) {
diff --git a/src/location/configure.json b/src/location/configure.json
index bf15f0be..90565052 100644
--- a/src/location/configure.json
+++ b/src/location/configure.json
@@ -43,7 +43,7 @@
"condition": [
"features.opengl",
"features.c++14",
- "!config.qnx && !config.intel_icc && (!config.win32 || config.mingw)"
+ "!config.intel_icc && (!config.win32 || config.mingw)"
],
"output": [ "privateFeature" ]
},
diff --git a/src/location/declarativemaps/declarativemaps.pri b/src/location/declarativemaps/declarativemaps.pri
index 3cd7a529..54a0824b 100644
--- a/src/location/declarativemaps/declarativemaps.pri
+++ b/src/location/declarativemaps/declarativemaps.pri
@@ -1,63 +1,63 @@
-QT += quick-private network positioning-private qml-private core-private gui-private
+QT += quick-private network positioning-private positioningquick-private qml-private core-private gui-private
INCLUDEPATH += declarativemaps
PRIVATE_HEADERS += \
- declarativemaps/error_messages_p.h \
- declarativemaps/qdeclarativegeomapitemview_p.h \
- declarativemaps/qdeclarativegeoserviceprovider_p.h \
- declarativemaps/qdeclarativegeocodemodel_p.h \
- declarativemaps/qdeclarativegeoroutemodel_p.h \
- declarativemaps/qdeclarativegeoroute_p.h \
- declarativemaps/qdeclarativegeoroutesegment_p.h \
- declarativemaps/qdeclarativegeomaneuver_p.h \
- declarativemaps/qdeclarativegeomap_p.h \
- declarativemaps/qdeclarativegeomaptype_p.h \
- declarativemaps/qdeclarativegeomapitembase_p.h \
- declarativemaps/qdeclarativegeomapquickitem_p.h \
- declarativemaps/qdeclarativecirclemapitem_p.h \
- declarativemaps/qdeclarativerectanglemapitem_p.h \
- declarativemaps/qdeclarativepolygonmapitem_p.h \
- declarativemaps/qdeclarativepolylinemapitem_p.h \
- declarativemaps/qdeclarativeroutemapitem_p.h \
- declarativemaps/qdeclarativegeomapparameter_p.h \
- declarativemaps/qgeomapitemgeometry_p.h \
- declarativemaps/qdeclarativegeomapcopyrightsnotice_p.h \
- declarativemaps/locationvaluetypehelper_p.h \
- declarativemaps/qquickgeomapgesturearea_p.h \
- declarativemaps/qdeclarativegeomapitemgroup_p.h \
- declarativemaps/qparameterizableobject_p.h \
- declarativemaps/qgeomapobject_p.h \
- declarativemaps/qgeomapobject_p_p.h \
- ../imports/positioning/qquickgeocoordinateanimation_p.h
+ declarativemaps/error_messages_p.h \
+ declarativemaps/locationvaluetypehelper_p.h \
+ declarativemaps/qdeclarativecirclemapitem_p.h \
+ declarativemaps/qdeclarativegeocodemodel_p.h \
+ declarativemaps/qdeclarativegeomaneuver_p.h \
+ declarativemaps/qdeclarativegeomapcopyrightsnotice_p.h \
+ declarativemaps/qdeclarativegeomapitembase_p.h \
+ declarativemaps/qdeclarativegeomapitemgroup_p.h \
+ declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h \
+ declarativemaps/qdeclarativegeomapitemview_p.h \
+ declarativemaps/qdeclarativegeomapparameter_p.h \
+ declarativemaps/qdeclarativegeomap_p.h \
+ declarativemaps/qdeclarativegeomapquickitem_p.h \
+ declarativemaps/qdeclarativegeomaptype_p.h \
+ declarativemaps/qdeclarativegeoroutemodel_p.h \
+ declarativemaps/qdeclarativegeoroute_p.h \
+ declarativemaps/qdeclarativegeoroutesegment_p.h \
+ declarativemaps/qdeclarativegeoserviceprovider_p.h \
+ declarativemaps/qdeclarativepolygonmapitem_p.h \
+ declarativemaps/qdeclarativepolylinemapitem_p.h \
+ declarativemaps/qdeclarativerectanglemapitem_p.h \
+ declarativemaps/qdeclarativeroutemapitem_p.h \
+ declarativemaps/qgeomapitemgeometry_p.h \
+ declarativemaps/qgeomapobject_p.h \
+ declarativemaps/qgeomapobject_p_p.h \
+ declarativemaps/qparameterizableobject_p.h \
+ declarativemaps/qquickgeomapgesturearea_p.h
SOURCES += \
- declarativemaps/qdeclarativegeomapitemview.cpp \
- declarativemaps/qdeclarativegeoserviceprovider.cpp \
- declarativemaps/qdeclarativegeocodemodel.cpp \
- declarativemaps/qdeclarativegeoroutemodel.cpp \
- declarativemaps/qdeclarativegeoroute.cpp \
- declarativemaps/qdeclarativegeoroutesegment.cpp \
- declarativemaps/qdeclarativegeomaneuver.cpp \
- declarativemaps/qdeclarativegeomap.cpp \
- declarativemaps/qdeclarativegeomaptype.cpp \
- declarativemaps/qdeclarativegeomapitembase.cpp \
- declarativemaps/qdeclarativegeomapquickitem.cpp \
- declarativemaps/qdeclarativecirclemapitem.cpp \
- declarativemaps/qdeclarativerectanglemapitem.cpp \
- declarativemaps/qdeclarativepolygonmapitem.cpp \
- declarativemaps/qdeclarativepolylinemapitem.cpp \
- declarativemaps/qdeclarativeroutemapitem.cpp \
- declarativemaps/qdeclarativegeomapparameter.cpp \
- declarativemaps/qgeomapitemgeometry.cpp \
- declarativemaps/qdeclarativegeomapcopyrightsnotice.cpp \
- declarativemaps/error_messages.cpp \
- declarativemaps/locationvaluetypehelper.cpp \
- declarativemaps/qquickgeomapgesturearea.cpp \
- declarativemaps/qparameterizableobject.cpp \
- declarativemaps/qdeclarativegeomapitemgroup.cpp \
- declarativemaps/qgeomapobject.cpp \
- ../imports/positioning/qquickgeocoordinateanimation.cpp
+ declarativemaps/error_messages.cpp \
+ declarativemaps/locationvaluetypehelper.cpp \
+ declarativemaps/qdeclarativecirclemapitem.cpp \
+ declarativemaps/qdeclarativegeocodemodel.cpp \
+ declarativemaps/qdeclarativegeomaneuver.cpp \
+ declarativemaps/qdeclarativegeomapcopyrightsnotice.cpp \
+ declarativemaps/qdeclarativegeomap.cpp \
+ declarativemaps/qdeclarativegeomapitembase.cpp \
+ declarativemaps/qdeclarativegeomapitemgroup.cpp \
+ declarativemaps/qdeclarativegeomapitemtransitionmanager.cpp \
+ declarativemaps/qdeclarativegeomapitemview.cpp \
+ declarativemaps/qdeclarativegeomapparameter.cpp \
+ declarativemaps/qdeclarativegeomapquickitem.cpp \
+ declarativemaps/qdeclarativegeomaptype.cpp \
+ declarativemaps/qdeclarativegeoroute.cpp \
+ declarativemaps/qdeclarativegeoroutemodel.cpp \
+ declarativemaps/qdeclarativegeoroutesegment.cpp \
+ declarativemaps/qdeclarativegeoserviceprovider.cpp \
+ declarativemaps/qdeclarativepolygonmapitem.cpp \
+ declarativemaps/qdeclarativepolylinemapitem.cpp \
+ declarativemaps/qdeclarativerectanglemapitem.cpp \
+ declarativemaps/qdeclarativeroutemapitem.cpp \
+ declarativemaps/qgeomapitemgeometry.cpp \
+ declarativemaps/qgeomapobject.cpp \
+ declarativemaps/qparameterizableobject.cpp \
+ declarativemaps/qquickgeomapgesturearea.cpp
load(qt_build_paths)
LIBS_PRIVATE += -L$$MODULE_BASE_OUTDIR/lib -lpoly2tri$$qtPlatformTargetSuffix() -lclip2tri$$qtPlatformTargetSuffix()
diff --git a/src/location/declarativemaps/locationvaluetypehelper.cpp b/src/location/declarativemaps/locationvaluetypehelper.cpp
index cda37b5f..8c96c8e7 100644
--- a/src/location/declarativemaps/locationvaluetypehelper.cpp
+++ b/src/location/declarativemaps/locationvaluetypehelper.cpp
@@ -159,7 +159,7 @@ QJSValue fromList(const QObject *object, const QList<QGeoCoordinate> &list)
int i = 0;
for (const auto &val : list) {
QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(val)));
- pathArray->putIndexed(i++, cv);
+ pathArray->put(i++, cv);
}
return QJSValue(v4, pathArray.asReturnedValue());
diff --git a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp
index 608260cd..2727cc26 100644
--- a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp
@@ -606,6 +606,24 @@ const QGeoShape &QDeclarativeCircleMapItem::geoShape() const
return circle_;
}
+void QDeclarativeCircleMapItem::setGeoShape(const QGeoShape &shape)
+{
+ if (shape == circle_)
+ return;
+
+ const QGeoCircle circle(shape); // if shape isn't a circle, circle will be created as a default-constructed circle
+ const bool centerHasChanged = circle.center() != circle_.center();
+ const bool radiusHasChanged = circle.radius() != circle_.radius();
+ circle_ = circle;
+
+ updateCirclePath();
+ markSourceDirtyAndUpdate();
+ if (centerHasChanged)
+ emit centerChanged(circle_.center());
+ if (radiusHasChanged)
+ emit radiusChanged(circle_.radius());
+}
+
QGeoMap::ItemType QDeclarativeCircleMapItem::itemType() const
{
return QGeoMap::MapCircle;
diff --git a/src/location/declarativemaps/qdeclarativecirclemapitem_p.h b/src/location/declarativemaps/qdeclarativecirclemapitem_p.h
index 2e8c56f8..a5b92881 100644
--- a/src/location/declarativemaps/qdeclarativecirclemapitem_p.h
+++ b/src/location/declarativemaps/qdeclarativecirclemapitem_p.h
@@ -94,6 +94,7 @@ public:
bool contains(const QPointF &point) const override;
const QGeoShape &geoShape() const override;
+ void setGeoShape(const QGeoShape &shape) override;
QGeoMap::ItemType itemType() const override;
static bool crossEarthPole(const QGeoCoordinate &center, qreal distance);
diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp
index d8d01b66..63587efe 100644
--- a/src/location/declarativemaps/qdeclarativegeomap.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomap.cpp
@@ -240,10 +240,13 @@ QDeclarativeGeoMap::~QDeclarativeGeoMap()
for (QDeclarativeGeoMapItemView *v : qAsConst(m_mapViews)) {
if (!v)
continue;
- if (v->parent() == this)
+ if (v->parent() == this) {
delete v;
- else
- v->removeInstantiatedItems();
+ } else {
+ // FIXME: removeInstantiatedItems should abort, as well as exit transitions terminated
+ v->removeInstantiatedItems(false);
+ v->m_map = nullptr;
+ }
}
}
// remove any map items associations
@@ -251,19 +254,12 @@ QDeclarativeGeoMap::~QDeclarativeGeoMap()
if (m_mapItems.at(i))
m_mapItems.at(i).data()->setMap(0,0);
}
- m_mapItems.clear();
- for (auto g: qAsConst(m_mapItemGroups)) {
- if (!g)
- continue;
- const QList<QQuickItem *> quickKids = g->childItems();
- for (auto c: quickKids) {
- QDeclarativeGeoMapItemBase *itemBase = qobject_cast<QDeclarativeGeoMapItemBase *>(c);
- if (itemBase)
- itemBase->setMap(0,0);
- }
+ // remove any map item groups associations
+ for (int i = 0; i < m_mapItemGroups.count(); ++i) {
+ if (m_mapItemGroups.at(i))
+ m_mapItemGroups.at(i).data()->setQuickMap(nullptr);
}
- m_mapItemGroups.clear();
if (m_copyrights.data())
delete m_copyrights.data();
@@ -329,10 +325,7 @@ void QDeclarativeGeoMap::setError(QGeoServiceProvider::Error error, const QStrin
void QDeclarativeGeoMap::initialize()
{
// try to keep change signals in the end
- bool centerHasChanged = false;
- bool bearingHasChanged = false;
- bool tiltHasChanged = false;
- bool fovHasChanged = false;
+ bool visibleAreaHasChanged = false;
QGeoCoordinate center = m_cameraData.center();
@@ -344,50 +337,41 @@ void QDeclarativeGeoMap::initialize()
double bearing = m_cameraData.bearing();
double tilt = m_cameraData.tilt();
double fov = m_cameraData.fieldOfView(); // Must be 45.0
+ QGeoCameraData cameraData = m_cameraData;
- if (!m_cameraCapabilities.supportsBearing() && bearing != 0.0) {
- m_cameraData.setBearing(0);
- bearingHasChanged = true;
- }
- if (!m_cameraCapabilities.supportsTilting() && tilt != 0.0) {
- m_cameraData.setTilt(0);
- tiltHasChanged = true;
- }
+ if (!m_cameraCapabilities.supportsBearing() && bearing != 0.0)
+ cameraData.setBearing(0);
+
+ if (!m_cameraCapabilities.supportsTilting() && tilt != 0.0)
+ cameraData.setTilt(0);
- m_cameraData.setFieldOfView(qBound(m_cameraCapabilities.minimumFieldOfView(),
+ m_map->setVisibleArea(m_visibleArea);
+ if (m_map->visibleArea() != m_visibleArea)
+ visibleAreaHasChanged = true;
+
+ cameraData.setFieldOfView(qBound(m_cameraCapabilities.minimumFieldOfView(),
fov,
m_cameraCapabilities.maximumFieldOfView()));
- if (fov != m_cameraData.fieldOfView())
- fovHasChanged = true;
// set latitude boundary check
- m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
+ m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(cameraData);
+ m_minimumViewportLatitude = m_map->minimumCenterLatitudeAtZoom(cameraData);
- center.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
+ center.setLatitude(qBound(m_minimumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
+ cameraData.setCenter(center);
- if (center != m_cameraData.center()) {
- centerHasChanged = true;
- m_cameraData.setCenter(center);
- }
-
- m_map->setCameraData(m_cameraData);
+ connect(m_map.data(), &QGeoMap::cameraDataChanged,
+ this, &QDeclarativeGeoMap::onCameraDataChanged);
+ m_map->setCameraData(cameraData);
for (auto obj : qAsConst(m_pendingMapObjects))
obj->setMap(m_map);
m_initialized = true;
- if (centerHasChanged)
- emit centerChanged(m_cameraData.center());
-
- if (bearingHasChanged)
- emit bearingChanged(m_cameraData.bearing());
-
- if (tiltHasChanged)
- emit tiltChanged(m_cameraData.tilt());
-
- if (fovHasChanged)
- emit fieldOfViewChanged(m_cameraData.fieldOfView());
+ if (visibleAreaHasChanged)
+ emit visibleAreaChanged();
+ connect(m_map.data(), &QGeoMap::visibleAreaChanged, this, &QDeclarativeGeoMap::visibleAreaChanged);
emit mapReadyChanged(true);
@@ -460,28 +444,7 @@ void QDeclarativeGeoMap::populateMap()
kids.insert(ite);
for (QObject *k : qAsConst(kids)) {
- // dispatch items appropriately
- QDeclarativeGeoMapItemView *mapView = qobject_cast<QDeclarativeGeoMapItemView *>(k);
- if (mapView) {
- m_mapViews.append(mapView);
- setupMapView(mapView);
- continue;
- }
- QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(k);
- if (mapItem) {
- addMapItem(mapItem);
- continue;
- }
- // Allow to add to the map Map items contained inside a parent QQuickItem, but only those at one level of nesting.
- QDeclarativeGeoMapItemGroup *itemGroup = qobject_cast<QDeclarativeGeoMapItemGroup *>(k);
- if (itemGroup) {
- addMapItemGroup(itemGroup);
- continue;
- }
-
- QGeoMapObject *mapObject = qobject_cast<QGeoMapObject *>(k);
- if (mapObject)
- addMapObject(mapObject);
+ addMapChild(k);
}
}
@@ -741,15 +704,9 @@ void QDeclarativeGeoMap::mappingManagerInitialized()
}
// Any map item groups that were added before the plugin was ready
- // need to have setMap called again on their children map items
- for (auto g: qAsConst(m_mapItemGroups)) {
- const QList<QQuickItem *> quickKids = g->childItems();
- for (auto c: quickKids) {
- QDeclarativeGeoMapItemBase *itemBase = qobject_cast<QDeclarativeGeoMapItemBase *>(c);
- if (itemBase)
- itemBase->setMap(this, m_map);
- }
- }
+ // DO NOT need to have setMap called again on their children map items
+ // because they have been added to m_mapItems, which is processed right above.
+
// All map parameters that were added before the plugin was ready
// need to be added to m_map
@@ -903,37 +860,87 @@ void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel)
*/
void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel, bool overzoom)
{
- const qreal oldZoom = m_cameraData.zoomLevel();
- if (oldZoom == zoomLevel || zoomLevel < 0)
+ if (zoomLevel < 0)
return;
- //small optimization to avoid double setCameraData
- bool centerHasChanged = false;
-
if (m_initialized) {
- m_cameraData.setZoomLevel(qBound<qreal>(overzoom ? m_map->minimumZoom() : effectiveMinimumZoomLevel(),
+ QGeoCameraData cameraData = m_map->cameraData();
+ if (cameraData.zoomLevel() == zoomLevel)
+ return;
+
+ cameraData.setZoomLevel(qBound<qreal>(overzoom ? m_map->minimumZoom() : effectiveMinimumZoomLevel(),
zoomLevel,
overzoom ? 30 : maximumZoomLevel()));
- m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
- QGeoCoordinate coord = m_cameraData.center();
- coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
- if (coord != m_cameraData.center()) {
- centerHasChanged = true;
- m_cameraData.setCenter(coord);
- }
- m_map->setCameraData(m_cameraData);
+ m_maximumViewportLatitude = m_map->maximumCenterLatitudeAtZoom(cameraData);
+ m_minimumViewportLatitude = m_map->minimumCenterLatitudeAtZoom(cameraData);
+ QGeoCoordinate coord = cameraData.center();
+ coord.setLatitude(qBound(m_minimumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
+ cameraData.setCenter(coord);
+ m_map->setCameraData(cameraData);
} else {
+ const bool zlHasChanged = zoomLevel != m_cameraData.zoomLevel();
m_cameraData.setZoomLevel(zoomLevel);
+ if (zlHasChanged)
+ emit zoomLevelChanged(zoomLevel);
}
+}
- if (centerHasChanged)
- emit centerChanged(m_cameraData.center());
- if (oldZoom != m_cameraData.zoomLevel())
- emit zoomLevelChanged(m_cameraData.zoomLevel());
+bool QDeclarativeGeoMap::addMapChild(QObject *child)
+{
+ // dispatch items appropriately
+ QDeclarativeGeoMapItemView *mapView = qobject_cast<QDeclarativeGeoMapItemView *>(child);
+ if (mapView)
+ return addMapItemView_real(mapView);
+
+ QDeclarativeGeoMapItemGroup *itemGroup = qobject_cast<QDeclarativeGeoMapItemGroup *>(child);
+ if (itemGroup) // addMapItemView calls addMapItemGroup
+ return addMapItemGroup_real(itemGroup);
+
+ QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(child);
+ if (mapItem)
+ return addMapItem_real(mapItem);
+
+ QGeoMapObject *mapObject = qobject_cast<QGeoMapObject *>(child);
+ if (mapObject)
+ addMapObject(mapObject); // this emits mapObjectsChanged, != mapItemsChanged
+ return false;
+}
+
+bool QDeclarativeGeoMap::removeMapChild(QObject *child)
+{
+ // dispatch items appropriately
+ QDeclarativeGeoMapItemView *mapView = qobject_cast<QDeclarativeGeoMapItemView *>(child);
+ if (mapView)
+ return removeMapItemView_real(mapView);
+
+ QDeclarativeGeoMapItemGroup *itemGroup = qobject_cast<QDeclarativeGeoMapItemGroup *>(child);
+ if (itemGroup) // removeMapItemView calls removeMapItemGroup for itself.
+ return removeMapItemGroup_real(itemGroup);
+
+ QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(child);
+ if (mapItem)
+ return removeMapItem_real(mapItem);
+
+ QGeoMapObject *mapObject = qobject_cast<QGeoMapObject *>(child);
+ if (mapObject)
+ removeMapObject(mapObject); // this emits mapObjectsChanged, != mapItemsChanged
+ return false;
+}
+
+bool QDeclarativeGeoMap::isGroupNested(QDeclarativeGeoMapItemGroup *group)
+{
+ QObject *parent = group->parent();
+ // Nested groups have parent set in parent's componentComplete()
+ // Those instantiated by MapItemView's delegateModel, however, do not,
+ // but have setParentItem set.
+ return qobject_cast<QDeclarativeGeoMapItemGroup *>(parent)
+ || qobject_cast<QDeclarativeGeoMapItemGroup *>(group->parentItem());
}
qreal QDeclarativeGeoMap::zoomLevel() const
{
+ if (m_initialized)
+ return m_map->cameraData().zoomLevel();
return m_cameraData.zoomLevel();
}
@@ -950,13 +957,16 @@ qreal QDeclarativeGeoMap::zoomLevel() const
void QDeclarativeGeoMap::setBearing(qreal bearing)
{
bearing = sanitizeBearing(bearing);
- if (m_cameraData.bearing() == bearing)
- return;
-
- m_cameraData.setBearing(bearing);
- if (m_map)
- m_map->setCameraData(m_cameraData);
- emit bearingChanged(bearing);
+ if (m_initialized) {
+ QGeoCameraData cameraData = m_map->cameraData();
+ cameraData.setBearing(bearing);
+ m_map->setCameraData(cameraData);
+ } else {
+ const bool bearingHasChanged = bearing != m_cameraData.bearing();
+ m_cameraData.setBearing(bearing);
+ if (bearingHasChanged)
+ emit bearingChanged(bearing);
+ }
}
/*!
@@ -973,7 +983,7 @@ void QDeclarativeGeoMap::setBearing(qreal bearing)
*/
void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate)
{
- if (!m_map)
+ if (!m_initialized)
return;
const QGeoCoordinate currentCenter = center();
@@ -985,21 +995,14 @@ void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordin
|| (coordinate == currentCenter && bearing == currentBearing))
return;
- if (m_map->capabilities() & QGeoMap::SupportsSetBearing) {
- if (!m_map->setBearing(bearing, coordinate))
- return;
-
- m_cameraData = m_map->cameraData();
-
- if (m_cameraData.center() != currentCenter)
- emit centerChanged(m_cameraData.center());
- if (m_cameraData.bearing() != currentBearing)
- emit bearingChanged(bearing);
- }
+ if (m_map->capabilities() & QGeoMap::SupportsSetBearing)
+ m_map->setBearing(bearing, coordinate);
}
qreal QDeclarativeGeoMap::bearing() const
{
+ if (m_initialized)
+ return m_map->cameraData().bearing();
return m_cameraData.bearing();
}
@@ -1018,17 +1021,23 @@ qreal QDeclarativeGeoMap::bearing() const
void QDeclarativeGeoMap::setTilt(qreal tilt)
{
tilt = qBound(minimumTilt(), tilt, maximumTilt());
- if (m_cameraData.tilt() == tilt)
- return;
- m_cameraData.setTilt(tilt);
- if (m_map)
- m_map->setCameraData(m_cameraData);
- emit tiltChanged(tilt);
+ if (m_initialized) {
+ QGeoCameraData cameraData = m_map->cameraData();
+ cameraData.setTilt(tilt);
+ m_map->setCameraData(cameraData);
+ } else {
+ const bool tiltHasChanged = tilt != m_cameraData.tilt();
+ m_cameraData.setTilt(tilt);
+ if (tiltHasChanged)
+ emit tiltChanged(tilt);
+ }
}
qreal QDeclarativeGeoMap::tilt() const
{
+ if (m_initialized)
+ return m_map->cameraData().tilt();
return m_cameraData.tilt();
}
@@ -1039,9 +1048,9 @@ void QDeclarativeGeoMap::setMinimumTilt(qreal minimumTilt, bool userSet)
m_userMinimumTilt = minimumTilt;
qreal oldMinimumTilt = this->minimumTilt();
- m_minimumTilt = qBound(m_cameraCapabilities.minimumTilt(),
- minimumTilt,
- m_cameraCapabilities.maximumTilt());
+ m_minimumTilt = qBound<double>(m_cameraCapabilities.minimumTilt(),
+ minimumTilt,
+ m_cameraCapabilities.maximumTilt());
if (tilt() < m_minimumTilt)
setTilt(m_minimumTilt);
@@ -1070,17 +1079,23 @@ void QDeclarativeGeoMap::setMinimumTilt(qreal minimumTilt, bool userSet)
void QDeclarativeGeoMap::setFieldOfView(qreal fieldOfView)
{
fieldOfView = qBound(minimumFieldOfView(), fieldOfView, maximumFieldOfView());
- if (m_cameraData.fieldOfView() == fieldOfView)
- return;
- m_cameraData.setFieldOfView(fieldOfView);
- if (m_map)
- m_map->setCameraData(m_cameraData);
- emit fieldOfViewChanged(fieldOfView);
+ if (m_initialized) {
+ QGeoCameraData cameraData = m_map->cameraData();
+ cameraData.setFieldOfView(fieldOfView);
+ m_map->setCameraData(cameraData);
+ } else {
+ const bool fovChanged = fieldOfView != m_cameraData.fieldOfView();
+ m_cameraData.setFieldOfView(fieldOfView);
+ if (fovChanged)
+ emit fieldOfViewChanged(fieldOfView);
+ }
}
qreal QDeclarativeGeoMap::fieldOfView() const
{
+ if (m_initialized)
+ return m_map->cameraData().fieldOfView();
return m_cameraData.fieldOfView();
}
@@ -1091,9 +1106,9 @@ void QDeclarativeGeoMap::setMinimumFieldOfView(qreal minimumFieldOfView, bool us
m_userMinimumFieldOfView = minimumFieldOfView;
qreal oldMinimumFoV = this->minimumFieldOfView();
- m_minimumFieldOfView = qBound(m_cameraCapabilities.minimumFieldOfView(),
- minimumFieldOfView,
- m_cameraCapabilities.maximumFieldOfView());
+ m_minimumFieldOfView = qBound<double>(m_cameraCapabilities.minimumFieldOfView(),
+ minimumFieldOfView,
+ m_cameraCapabilities.maximumFieldOfView());
if (fieldOfView() < m_minimumFieldOfView)
setFieldOfView(m_minimumFieldOfView);
@@ -1128,9 +1143,9 @@ void QDeclarativeGeoMap::setMaximumFieldOfView(qreal maximumFieldOfView, bool us
m_userMaximumFieldOfView = maximumFieldOfView;
qreal oldMaximumFoV = this->maximumFieldOfView();
- m_maximumFieldOfView = qBound(m_cameraCapabilities.minimumFieldOfView(),
- maximumFieldOfView,
- m_cameraCapabilities.maximumFieldOfView());
+ m_maximumFieldOfView = qBound<double>(m_cameraCapabilities.minimumFieldOfView(),
+ maximumFieldOfView,
+ m_cameraCapabilities.maximumFieldOfView());
if (fieldOfView() > m_maximumFieldOfView)
setFieldOfView(m_maximumFieldOfView);
@@ -1167,6 +1182,8 @@ qreal QDeclarativeGeoMap::maximumFieldOfView() const
this property.
If the \l plugin property is not set or the plugin does not support mapping, this property is \c 0.
+ Since QtLocation 5.12, plugins can additionally restrict this value depending on the current zoom level.
+
\sa tilt, maximumTilt
\since QtLocation 5.9
@@ -1183,9 +1200,9 @@ void QDeclarativeGeoMap::setMaximumTilt(qreal maximumTilt, bool userSet)
m_userMaximumTilt = maximumTilt;
qreal oldMaximumTilt = this->maximumTilt();
- m_maximumTilt = qBound(m_cameraCapabilities.minimumTilt(),
- maximumTilt,
- m_cameraCapabilities.maximumTilt());
+ m_maximumTilt = qBound<double>(m_cameraCapabilities.minimumTilt(),
+ maximumTilt,
+ m_cameraCapabilities.maximumTilt());
if (tilt() > m_maximumTilt)
setTilt(m_maximumTilt);
@@ -1204,6 +1221,8 @@ void QDeclarativeGeoMap::setMaximumTilt(qreal maximumTilt, bool userSet)
this property.
If the \l plugin property is not set or the plugin does not support mapping, this property is \c 89.5.
+ Since QtLocation 5.12, plugins can additionally restrict this value depending on the current zoom level.
+
\sa tilt, minimumTilt
\since QtLocation 5.9
@@ -1223,26 +1242,27 @@ qreal QDeclarativeGeoMap::maximumTilt() const
*/
void QDeclarativeGeoMap::setCenter(const QGeoCoordinate &center)
{
- if (center == m_cameraData.center())
- return;
-
if (!center.isValid())
return;
if (m_initialized) {
QGeoCoordinate coord(center);
- coord.setLatitude(qBound(-m_maximumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
- m_cameraData.setCenter(coord);
- m_map->setCameraData(m_cameraData);
+ coord.setLatitude(qBound(m_minimumViewportLatitude, center.latitude(), m_maximumViewportLatitude));
+ QGeoCameraData cameraData = m_map->cameraData();
+ cameraData.setCenter(coord);
+ m_map->setCameraData(cameraData);
} else {
+ const bool centerHasChanged = center != m_cameraData.center();
m_cameraData.setCenter(center);
+ if (centerHasChanged)
+ emit centerChanged(center);
}
-
- emit centerChanged(m_cameraData.center());
}
QGeoCoordinate QDeclarativeGeoMap::center() const
{
+ if (m_initialized)
+ return m_map->cameraData().center();
return m_cameraData.center();
}
@@ -1364,6 +1384,42 @@ QColor QDeclarativeGeoMap::color() const
}
/*!
+ \qmlproperty rect QtLocation::Map::visibleArea
+
+ This property holds the visible area inside the Map QML element.
+ It is a rect whose coordinates are relative to the Map element.
+ Its size will be clamped to the size of the Map element.
+ A null visibleArea means that the whole Map is visible.
+
+ \since 5.12
+*/
+QRectF QDeclarativeGeoMap::visibleArea() const
+{
+ if (m_initialized)
+ return m_map->visibleArea();
+ return m_visibleArea;
+}
+
+void QDeclarativeGeoMap::setVisibleArea(const QRectF &visibleArea)
+{
+ const QRectF oldVisibleArea = QDeclarativeGeoMap::visibleArea();
+ if (visibleArea == oldVisibleArea)
+ return;
+
+ if (!visibleArea.isValid() && !visibleArea.isEmpty()) // values < 0
+ return;
+
+ if (m_initialized) {
+ m_map->setVisibleArea(visibleArea);
+ } else {
+ m_visibleArea = visibleArea;
+ const QRectF newVisibleArea = QDeclarativeGeoMap::visibleArea();
+ if (newVisibleArea != oldVisibleArea)
+ emit visibleAreaChanged();
+ }
+}
+
+/*!
\qmlproperty bool QtLocation::Map::mapReady
This property holds whether the map has been successfully initialized and is ready to be used.
@@ -1378,6 +1434,17 @@ bool QDeclarativeGeoMap::mapReady() const
return m_initialized;
}
+QMargins QDeclarativeGeoMap::mapMargins() const
+{
+ const QRectF va = m_map->visibleArea();
+ if (va.isEmpty())
+ return QMargins();
+ return QMargins( va.x()
+ , va.y()
+ , width() - va.width() - va.x()
+ , height() - va.height() - va.y());
+}
+
// TODO: offer the possibility to specify the margins.
void QDeclarativeGeoMap::fitViewportToGeoShape()
{
@@ -1385,48 +1452,28 @@ void QDeclarativeGeoMap::fitViewportToGeoShape()
// This case remains handled here, and not inside QGeoMap*::fitViewportToGeoRectangle,
// in order to honor animations on center and zoomLevel
const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
- const int margins = 10;
- if (!m_map || !m_visibleRegion.isValid() || width() <= margins || height() <= margins)
- return;
+ const int borderSize = 10;
+ const QMargins borders(borderSize, borderSize, borderSize, borderSize);
- QDoubleVector2D topLeftPoint = p.geoToMapProjection(m_visibleRegion.topLeft());
- QDoubleVector2D bottomRightPoint = p.geoToMapProjection(m_visibleRegion.bottomRight());
- if (bottomRightPoint.x() < topLeftPoint.x()) // crossing the dateline
- bottomRightPoint.setX(bottomRightPoint.x() + 1.0);
+ if (!m_map || !m_visibleRegion.isValid())
+ return;
- // find center of the bounding box
- QDoubleVector2D center = (topLeftPoint + bottomRightPoint) * 0.5;
- center.setX(center.x() > 1.0 ? center.x() - 1.0 : center.x());
- QGeoCoordinate centerCoordinate = p.mapProjectionToGeo(center);
+ const QMargins margins = borders + mapMargins();
+ const QPair<QGeoCoordinate, qreal> fitData = p.fitViewportToGeoRectangle(m_visibleRegion,
+ margins);
+ if (!fitData.first.isValid())
+ return;
// position camera to the center of bounding box
- setProperty("center", QVariant::fromValue(centerCoordinate)); // not using setCenter(centerCoordinate) to honor a possible animation set on the center property
+ setProperty("center", QVariant::fromValue(fitData.first)); // not using setCenter(centerCoordinate) to honor a possible animation set on the center property
- // if the shape is empty we just change center position, not zoom
- double bboxWidth = (bottomRightPoint.x() - topLeftPoint.x()) * m_map->mapWidth();
- double bboxHeight = (bottomRightPoint.y() - topLeftPoint.y()) * m_map->mapHeight();
-
- if (bboxHeight == 0.0 && bboxWidth == 0.0)
+ if (!qIsFinite(fitData.second))
return;
-
- double zoomRatio = qMax(bboxWidth / (width() - margins),
- bboxHeight / (height() - margins));
- zoomRatio = std::log(zoomRatio) / std::log(2.0);
- double newZoom = qMax<double>(minimumZoomLevel(), zoomLevel() - zoomRatio);
+ double newZoom = qMax<double>(minimumZoomLevel(), fitData.second);
setProperty("zoomLevel", QVariant::fromValue(newZoom)); // not using setZoomLevel(newZoom) to honor a possible animation set on the zoomLevel property
} else if (m_map->capabilities() & QGeoMap::SupportsFittingViewportToGeoRectangle) {
- // Animations cannot be honored in this case, as m_map act as a black box
- const QGeoCoordinate currentCenter = center();
- const qreal currentZoom = zoomLevel();
-
- if (!m_map->fitViewportToGeoRectangle(m_visibleRegion))
- return;
-
- m_cameraData = m_map->cameraData();
- if (m_cameraData.center() != currentCenter)
- emit centerChanged(m_cameraData.center());
- if (m_cameraData.zoomLevel() != currentZoom)
- emit zoomLevelChanged(m_cameraData.zoomLevel());
+ // Animations cannot be honored in this case, as m_map acts as a black box
+ m_map->fitViewportToGeoRectangle(m_visibleRegion);
}
}
@@ -1466,20 +1513,12 @@ void QDeclarativeGeoMap::alignCoordinateToPoint(const QGeoCoordinate &coordinate
if (!m_map || !(m_map->capabilities() & QGeoMap::SupportsAnchoringCoordinate))
return;
- const QGeoCoordinate currentCenter = center();
-
if (!coordinate.isValid()
|| !qIsFinite(point.x())
|| !qIsFinite(point.y()))
return;
- if (!m_map->anchorCoordinateToPoint(coordinate, point))
- return;
-
- m_cameraData = m_map->cameraData();
-
- if (m_cameraData.center() != currentCenter)
- emit centerChanged(m_cameraData.center());
+ m_map->anchorCoordinateToPoint(coordinate, point);
}
/*!
@@ -1659,37 +1698,26 @@ void QDeclarativeGeoMap::onAttachedCopyrightNoticeVisibilityChanged()
m_map->setCopyrightVisible(m_copyNoticesVisible > 0);
}
-/*!
- \qmlmethod void QtLocation::Map::addMapItem(MapItem item)
-
- Adds the given \a item to the Map (for example MapQuickItem, MapCircle). If the object
- already is on the Map, it will not be added again.
-
- As an example, consider the case where you have a MapCircle representing your current position:
-
- \snippet declarative/maps.qml QtQuick import
- \snippet declarative/maps.qml QtLocation import
- \codeline
- \snippet declarative/maps.qml Map addMapItem MapCircle at current position
-
- \note MapItemViews cannot be added with this method.
+void QDeclarativeGeoMap::onCameraDataChanged(const QGeoCameraData &cameraData)
+{
+ bool centerHasChanged = cameraData.center() != m_cameraData.center();
+ bool bearingHasChanged = cameraData.bearing() != m_cameraData.bearing();
+ bool tiltHasChanged = cameraData.tilt() != m_cameraData.tilt();
+ bool fovHasChanged = cameraData.fieldOfView() != m_cameraData.fieldOfView();
+ bool zoomHasChanged = cameraData.zoomLevel() != m_cameraData.zoomLevel();
- \sa mapItems, removeMapItem, clearMapItems
-*/
+ m_cameraData = cameraData;
-void QDeclarativeGeoMap::addMapItem(QDeclarativeGeoMapItemBase *item)
-{
- if (!item || item->quickMap())
- return;
- // If the item comes from a MapItemGroup, do not reparent it.
- if (!qobject_cast<QDeclarativeGeoMapItemGroup *>(item->parentItem()))
- item->setParentItem(this);
- m_mapItems.append(item);
- if (m_map) {
- item->setMap(this, m_map);
- m_map->addMapItem(item);
- }
- emit mapItemsChanged();
+ if (centerHasChanged)
+ emit centerChanged(m_cameraData.center());
+ if (zoomHasChanged)
+ emit zoomLevelChanged(m_cameraData.zoomLevel());
+ if (bearingHasChanged)
+ emit bearingChanged(m_cameraData.bearing());
+ if (tiltHasChanged)
+ emit tiltChanged(m_cameraData.tilt());
+ if (fovHasChanged)
+ emit fieldOfViewChanged(m_cameraData.fieldOfView());
}
/*!
@@ -1872,6 +1900,45 @@ QList<QObject *> QDeclarativeGeoMap::mapItems()
}
/*!
+ \qmlmethod void QtLocation::Map::addMapItem(MapItem item)
+
+ Adds the given \a item to the Map (for example MapQuickItem, MapCircle). If the object
+ already is on the Map, it will not be added again.
+
+ As an example, consider the case where you have a MapCircle representing your current position:
+
+ \snippet declarative/maps.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/maps.qml Map addMapItem MapCircle at current position
+
+ \note MapItemViews cannot be added with this method.
+
+ \sa mapItems, removeMapItem, clearMapItems
+*/
+
+void QDeclarativeGeoMap::addMapItem(QDeclarativeGeoMapItemBase *item)
+{
+ if (addMapItem_real(item))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::addMapItem_real(QDeclarativeGeoMapItemBase *item)
+{
+ if (!item || item->quickMap())
+ return false;
+ // If the item comes from a MapItemGroup, do not reparent it.
+ if (!qobject_cast<QDeclarativeGeoMapItemGroup *>(item->parentItem()))
+ item->setParentItem(this);
+ m_mapItems.append(item);
+ if (m_map) {
+ item->setMap(this, m_map);
+ m_map->addMapItem(item);
+ }
+ return true;
+}
+
+/*!
\qmlmethod void QtLocation::Map::removeMapItem(MapItem item)
Removes the given \a item from the Map (for example MapQuickItem, MapCircle). If
@@ -1882,18 +1949,25 @@ QList<QObject *> QDeclarativeGeoMap::mapItems()
*/
void QDeclarativeGeoMap::removeMapItem(QDeclarativeGeoMapItemBase *ptr)
{
- if (!ptr || !m_map)
- return;
- m_map->removeMapItem(ptr);
+ if (removeMapItem_real(ptr))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::removeMapItem_real(QDeclarativeGeoMapItemBase *ptr)
+{
+ if (!ptr)
+ return false;
QPointer<QDeclarativeGeoMapItemBase> item(ptr);
if (!m_mapItems.contains(item))
- return;
+ return false;
+ if (m_map)
+ m_map->removeMapItem(ptr);
if (item->parentItem() == this)
item->setParentItem(0);
item->setMap(0, 0);
// these can be optimized for perf, as we already check the 'contains' above
m_mapItems.removeOne(item);
- emit mapItemsChanged();
+ return true;
}
/*!
@@ -1907,18 +1981,25 @@ void QDeclarativeGeoMap::clearMapItems()
{
if (m_mapItems.isEmpty())
return;
- if (m_map)
- m_map->clearMapItems();
- for (auto i : qAsConst(m_mapItems)) {
- if (i) {
- i->setMap(0, 0);
- if (i->parentItem() == this)
- i->setParentItem(0);
- }
+
+ int removed = 0;
+ for (auto i : qAsConst(m_mapItemGroups)) {
+ // Processing only top-level groups (!views)
+ QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(i);
+ if (view)
+ continue;
+
+ if (i->parentItem() != this)
+ continue;
+
+ removed += removeMapItemGroup_real(i);
}
- m_mapItems.clear();
- m_mapItemGroups.clear();
- emit mapItemsChanged();
+
+ for (auto i : qAsConst(m_mapItems))
+ removed += removeMapItem_real(i);
+
+ if (removed)
+ emit mapItemsChanged();
}
/*!
@@ -1933,19 +2014,29 @@ void QDeclarativeGeoMap::clearMapItems()
*/
void QDeclarativeGeoMap::addMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup)
{
- if (!itemGroup || itemGroup->quickMap()) // || Already added to some map
- return;
+ if (addMapItemGroup_real(itemGroup))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::addMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup)
+{
+ if (!itemGroup || itemGroup->quickMap()) // Already added to some map
+ return false;
itemGroup->setQuickMap(this);
+
+ if (!isGroupNested(itemGroup))
+ itemGroup->setParentItem(this);
+
QPointer<QDeclarativeGeoMapItemGroup> g(itemGroup);
m_mapItemGroups.append(g);
- const QList<QQuickItem *> quickKids = g->childItems();
+
+ const QList<QQuickItem *> quickKids = itemGroup->childItems();
+ int count = 0;
for (auto c: quickKids) {
- QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(c);
- if (mapItem)
- addMapItem(mapItem);
+ count += addMapChild(c); // this calls addMapItemGroup recursively, if needed
}
- itemGroup->setParentItem(this);
+ return count;
}
/*!
@@ -1959,21 +2050,28 @@ void QDeclarativeGeoMap::addMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup)
*/
void QDeclarativeGeoMap::removeMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup)
{
+ if (removeMapItemGroup_real(itemGroup))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::removeMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup)
+{
if (!itemGroup || itemGroup->quickMap() != this) // cant remove an itemGroup added to another map
- return;
+ return false;
QPointer<QDeclarativeGeoMapItemGroup> g(itemGroup);
if (!m_mapItemGroups.removeOne(g))
- return;
+ return false;
const QList<QQuickItem *> quickKids = itemGroup->childItems();
+ int count = 0;
for (auto c: quickKids) {
- QDeclarativeGeoMapItemBase *mapItem = qobject_cast<QDeclarativeGeoMapItemBase *>(c);
- if (mapItem)
- removeMapItem(mapItem);
+ count += removeMapChild(c);
}
itemGroup->setQuickMap(nullptr);
- itemGroup->setParentItem(0);
+ if (itemGroup->parentItem() == this)
+ itemGroup->setParentItem(0);
+ return count;
}
/*!
@@ -1987,14 +2085,23 @@ void QDeclarativeGeoMap::removeMapItemGroup(QDeclarativeGeoMapItemGroup *itemGro
*/
void QDeclarativeGeoMap::removeMapItemView(QDeclarativeGeoMapItemView *itemView)
{
+ if (removeMapItemView_real(itemView))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::removeMapItemView_real(QDeclarativeGeoMapItemView *itemView)
+{
if (!itemView || itemView->m_map != this) // can't remove a view that is already added to another map
- return;
+ return false;
+ // Leaving this as void since the removal is async (potentially transitioned)
+ // && the delegates *could* be empty mapItemGroups.
itemView->removeInstantiatedItems();
itemView->m_map = 0;
// it can be removed from the list at this point, since no operations that require a Map have to be done
// anymore on destruction.
m_mapViews.removeOne(itemView);
+ return removeMapItemGroup_real(itemView); // at this point, delegate instances have been removed.
}
/*!
@@ -2008,13 +2115,21 @@ void QDeclarativeGeoMap::removeMapItemView(QDeclarativeGeoMapItemView *itemView)
*/
void QDeclarativeGeoMap::addMapItemView(QDeclarativeGeoMapItemView *itemView)
{
+ if (addMapItemView_real(itemView))
+ emit mapItemsChanged();
+}
+
+bool QDeclarativeGeoMap::addMapItemView_real(QDeclarativeGeoMapItemView *itemView)
+{
if (!itemView || itemView->m_map) // can't add a view twice
- return;
+ return false;
+ int count = addMapItemGroup_real(itemView); // at this point, delegates aren't yet incubated.
// Not appending it to m_mapViews because it seems unnecessary even if the
// itemView is a child of this (in which case it would be destroyed
m_mapViews.append(itemView);
setupMapView(itemView);
+ return count;
}
/*!
@@ -2067,17 +2182,17 @@ void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF
setMinimumZoomLevel(m_map->minimumZoom(), false);
// Update the center latitudinal threshold
- double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(m_cameraData);
- if (maximumCenterLatitudeAtZoom != m_maximumViewportLatitude) {
+ QGeoCameraData cameraData = m_map->cameraData();
+ const double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(cameraData);
+ const double minimumCenterLatitudeAtZoom = m_map->minimumCenterLatitudeAtZoom(cameraData);
+ if (maximumCenterLatitudeAtZoom != m_maximumViewportLatitude
+ || minimumCenterLatitudeAtZoom != m_minimumViewportLatitude) {
m_maximumViewportLatitude = maximumCenterLatitudeAtZoom;
- QGeoCoordinate coord = m_cameraData.center();
- coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
-
- if (coord != m_cameraData.center()) {
- m_cameraData.setCenter(coord);
- m_map->setCameraData(m_cameraData);
- emit centerChanged(m_cameraData.center());
- }
+ m_minimumViewportLatitude = minimumCenterLatitudeAtZoom;
+ QGeoCoordinate coord = cameraData.center();
+ coord.setLatitude(qBound(m_minimumViewportLatitude, coord.latitude(), m_maximumViewportLatitude));
+ cameraData.setCenter(coord);
+ m_map->setCameraData(cameraData);
}
}
diff --git a/src/location/declarativemaps/qdeclarativegeomap_p.h b/src/location/declarativemaps/qdeclarativegeomap_p.h
index 7f1bf7ab..f59f6f54 100644
--- a/src/location/declarativemaps/qdeclarativegeomap_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomap_p.h
@@ -101,6 +101,7 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMap : public QQuickItem
Q_PROPERTY(bool copyrightsVisible READ copyrightsVisible WRITE setCopyrightsVisible NOTIFY copyrightsVisibleChanged)
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
Q_PROPERTY(bool mapReady READ mapReady NOTIFY mapReadyChanged)
+ Q_PROPERTY(QRectF visibleArea READ visibleArea WRITE setVisibleArea NOTIFY visibleAreaChanged REVISION 12)
Q_INTERFACES(QQmlParserStatus)
public:
@@ -154,6 +155,9 @@ public:
void setColor(const QColor &color);
QColor color() const;
+ QRectF visibleArea() const;
+ void setVisibleArea(const QRectF &visibleArea);
+
bool mapReady() const;
QQmlListProperty<QDeclarativeGeoMapType> supportedMapTypes();
@@ -226,6 +230,7 @@ Q_SIGNALS:
void copyrightsChanged(const QString &copyrightsHtml);
void mapReadyChanged(bool ready);
Q_REVISION(11) void mapObjectsChanged();
+ void visibleAreaChanged();
protected:
void mousePressEvent(QMouseEvent *event) override ;
@@ -249,6 +254,16 @@ protected:
void setError(QGeoServiceProvider::Error error, const QString &errorString);
void initialize();
void setZoomLevel(qreal zoomLevel, bool overzoom);
+ bool addMapChild(QObject *child);
+ bool removeMapChild(QObject *child);
+ bool isGroupNested(QDeclarativeGeoMapItemGroup *group);
+
+ bool addMapItem_real(QDeclarativeGeoMapItemBase *item);
+ bool removeMapItem_real(QDeclarativeGeoMapItemBase *item);
+ bool addMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup);
+ bool removeMapItemGroup_real(QDeclarativeGeoMapItemGroup *itemGroup);
+ bool addMapItemView_real(QDeclarativeGeoMapItemView *itemView);
+ bool removeMapItemView_real(QDeclarativeGeoMapItemView *itemView);
private Q_SLOTS:
void mappingManagerInitialized();
@@ -256,6 +271,7 @@ private Q_SLOTS:
void onSupportedMapTypesChanged();
void onCameraCapabilitiesChanged(const QGeoCameraCapabilities &oldCameraCapabilities);
void onAttachedCopyrightNoticeVisibilityChanged();
+ void onCameraDataChanged(const QGeoCameraData &cameraData);
private:
void setupMapView(QDeclarativeGeoMapItemView *view);
@@ -266,6 +282,7 @@ private:
bool isInteractive();
void attachCopyrightNotice(bool initialVisibility);
void detachCopyrightNotice(bool currentVisibility);
+ QMargins mapMargins() const;
private:
QDeclarativeGeoServiceProvider *m_plugin;
@@ -287,6 +304,7 @@ private:
bool m_pendingFitViewport;
bool m_copyrightsVisible;
double m_maximumViewportLatitude;
+ double m_minimumViewportLatitude = 0.0;
bool m_initialized;
QList<QDeclarativeGeoMapParameter *> m_mapParameters;
QList<QGeoMapObject*> m_pendingMapObjects; // Used only in the initialization phase
@@ -306,6 +324,7 @@ private:
int m_copyNoticesVisible = 0;
qreal m_maxChildZ = 0;
+ QRectF m_visibleArea;
friend class QDeclarativeGeoMapItem;
diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
index faa06fef..7de6afb5 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
@@ -85,10 +85,6 @@ QDeclarativeGeoMapItemBase::QDeclarativeGeoMapItemBase(QQuickItem *parent)
// Changing opacity on a mapItemGroup should affect also the opacity on the children.
// This must be notified to plugins, if they are to render the item.
connect(this, &QQuickItem::opacityChanged, this, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged);
- parentGroup_ = qobject_cast<QDeclarativeGeoMapItemGroup *>(parent);
- if (parentGroup_)
- connect(qobject_cast<QDeclarativeGeoMapItemGroup *>(parent), &QQuickItem::opacityChanged,
- this, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged);
}
QDeclarativeGeoMapItemBase::~QDeclarativeGeoMapItemBase()
@@ -141,6 +137,8 @@ void QDeclarativeGeoMapItemBase::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *m
if (map_ && quickMap_) {
connect(map_, SIGNAL(cameraDataChanged(QGeoCameraData)),
this, SLOT(baseCameraDataChanged(QGeoCameraData)));
+ connect(map_, SIGNAL(visibleAreaChanged()),
+ this, SLOT(visibleAreaChanged()));
connect(quickMap, SIGNAL(heightChanged()), this, SLOT(polishAndUpdate()));
connect(quickMap, SIGNAL(widthChanged()), this, SLOT(polishAndUpdate()));
lastSize_ = QSizeF(quickMap_->width(), quickMap_->height());
@@ -177,6 +175,13 @@ void QDeclarativeGeoMapItemBase::baseCameraDataChanged(const QGeoCameraData &cam
afterViewportChanged(evt);
}
+void QDeclarativeGeoMapItemBase::visibleAreaChanged()
+{
+ QGeoMapViewportChangeEvent evt;
+ evt.mapSize = QSizeF(quickMap_->width(), quickMap_->height());
+ afterViewportChanged(evt);
+}
+
/*!
\internal
*/
@@ -276,49 +281,26 @@ QSGNode *QDeclarativeGeoMapItemBase::updateMapItemPaintNode(QSGNode *oldNode, Up
return 0;
}
+/*!
+ \internal
+
+ The actual combined opacity of the item. Needed by custom renderer to look like
+ the scene-graph one.
+*/
qreal QDeclarativeGeoMapItemBase::mapItemOpacity() const
{
if (parentGroup_)
- return parentGroup_->opacity() * opacity();
+ return parentGroup_->mapItemOpacity() * opacity();
return opacity();
}
-bool QDeclarativeGeoMapItemBase::prepareEnterTransition()
+void QDeclarativeGeoMapItemBase::setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup)
{
- if (m_transitionManager->m_transitionState == QDeclarativeGeoMapItemTransitionManager::EnterTransition
- && m_transitionManager->isRunning())
- return false;
-
- if (m_transitionManager->m_transitionState != QDeclarativeGeoMapItemTransitionManager::EnterTransition) {
- setVisible(true);
- m_transitionManager->m_transitionState = QDeclarativeGeoMapItemTransitionManager::EnterTransition;
- }
- return true;
-}
-
-bool QDeclarativeGeoMapItemBase::prepareExitTransition()
-{
- if (m_transitionManager->m_transitionState == QDeclarativeGeoMapItemTransitionManager::ExitTransition
- && m_transitionManager->isRunning())
- return false;
-
- if (m_transitionManager->m_transitionState != QDeclarativeGeoMapItemTransitionManager::ExitTransition) {
- m_transitionManager->m_transitionState = QDeclarativeGeoMapItemTransitionManager::ExitTransition;
+ parentGroup_ = &parentGroup;
+ if (parentGroup_) {
+ connect(parentGroup_, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged,
+ this, &QDeclarativeGeoMapItemBase::mapItemOpacityChanged);
}
- return true;
-}
-
-void QDeclarativeGeoMapItemBase::finalizeEnterTransition()
-{
- m_transitionManager->m_transitionState = QDeclarativeGeoMapItemTransitionManager::NoTransition;
- emit enterTransitionFinished();
-}
-
-void QDeclarativeGeoMapItemBase::finalizeExitTransition()
-{
- setVisible(false);
- m_transitionManager->m_transitionState = QDeclarativeGeoMapItemTransitionManager::NoTransition;
- emit exitTransitionFinished();
}
bool QDeclarativeGeoMapItemBase::isPolishScheduled() const
@@ -332,43 +314,4 @@ void QDeclarativeGeoMapItemBase::polishAndUpdate()
update();
}
-QDeclarativeGeoMapItemTransitionManager::QDeclarativeGeoMapItemTransitionManager(QDeclarativeGeoMapItemBase *mapItem)
- : QQuickTransitionManager(), m_mapItem(mapItem)
-{
-}
-
-void QDeclarativeGeoMapItemTransitionManager::transitionEnter()
-{
- if (m_transitionState == ExitTransition)
- cancel();
-
- if (!m_mapItem->prepareEnterTransition())
- return;
-
- if (m_view && m_view->m_enter)
- transition(enterActions, m_view->m_enter, m_mapItem);
- else
- finished();
-}
-
-void QDeclarativeGeoMapItemTransitionManager::transitionExit()
-{
- if (!m_mapItem->prepareExitTransition())
- return;
-
- if (m_view && m_view->m_exit)
- transition(exitActions, m_view->m_exit, m_mapItem);
- else
- finished();
-}
-
-void QDeclarativeGeoMapItemTransitionManager::finished()
-{
- if (m_transitionState == EnterTransition)
- m_mapItem->finalizeEnterTransition();
- else if (m_transitionState == ExitTransition)
- m_mapItem->finalizeExitTransition();
-}
-
-
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase_p.h b/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
index 7a284e8a..4eff32db 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
@@ -56,12 +56,11 @@
#include <QtLocation/private/qdeclarativegeomap_p.h>
#include <QtLocation/private/qlocationglobal_p.h>
#include <QtLocation/private/qgeomap_p.h>
-#include <QtQuick/private/qquicktransitionmanager_p_p.h>
+#include <QtLocation/private/qdeclarativegeomapitemtransitionmanager_p.h>
#include <QScopedPointer>
QT_BEGIN_NAMESPACE
-class QDeclarativeGeoMapItemTransitionManager;
-class QDeclarativeGeoMapItemBase;
+
class Q_LOCATION_PRIVATE_EXPORT QGeoMapViewportChangeEvent
{
public:
@@ -80,34 +79,11 @@ public:
bool rollChanged;
};
-class QDeclarativeGeoMapItemTransitionManager : public QQuickTransitionManager
-{
-public:
- enum TransitionState {
- NoTransition, EnterTransition, ExitTransition
- };
-
- QDeclarativeGeoMapItemTransitionManager(QDeclarativeGeoMapItemBase *mapItem);
-
- void transitionEnter();
- void transitionExit();
-
-protected:
- void finished() override;
-
-public:
- QDeclarativeGeoMapItemBase *m_mapItem;
- QDeclarativeGeoMapItemView *m_view = nullptr;
- QList<QQuickStateAction> enterActions;
- QList<QQuickStateAction> exitActions;
- TransitionState m_transitionState = NoTransition;
-};
-
class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMapItemBase : public QQuickItem
{
Q_OBJECT
- Q_PROPERTY(QGeoShape geoShape READ geoShape STORED false )
+ Q_PROPERTY(QGeoShape geoShape READ geoShape WRITE setGeoShape STORED false )
public:
explicit QDeclarativeGeoMapItemBase(QQuickItem *parent = 0);
virtual ~QDeclarativeGeoMapItemBase();
@@ -118,6 +94,7 @@ public:
QDeclarativeGeoMap *quickMap() { return quickMap_; }
QGeoMap *map() { return map_; }
virtual const QGeoShape &geoShape() const = 0;
+ virtual void setGeoShape(const QGeoShape &shape) = 0;
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *);
@@ -125,15 +102,12 @@ public:
virtual QGeoMap::ItemType itemType() const = 0;
qreal mapItemOpacity() const;
- virtual bool prepareEnterTransition();
- virtual bool prepareExitTransition();
- virtual void finalizeEnterTransition();
- virtual void finalizeExitTransition();
+ void setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup);
Q_SIGNALS:
void mapItemOpacityChanged();
- Q_REVISION(11) void enterTransitionFinished();
- Q_REVISION(11) void exitTransitionFinished();
+ Q_REVISION(12) void addTransitionFinished();
+ Q_REVISION(12) void removeTransitionFinished();
protected Q_SLOTS:
virtual void afterChildrenChanged();
@@ -147,6 +121,7 @@ protected:
private Q_SLOTS:
void baseCameraDataChanged(const QGeoCameraData &camera);
+ void visibleAreaChanged();
private:
QPointer<QGeoMap> map_;
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp b/src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp
index b4d214ad..a51dcb31 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitemgroup.cpp
@@ -35,6 +35,8 @@
****************************************************************************/
#include "qdeclarativegeomapitemgroup_p.h"
+#include "qdeclarativegeomapitembase_p.h"
+#include "qdeclarativegeomap_p.h"
QT_BEGIN_NAMESPACE
@@ -135,9 +137,11 @@ QT_BEGIN_NAMESPACE
\image api-mapitemgroup.png
*/
-QDeclarativeGeoMapItemGroup::QDeclarativeGeoMapItemGroup(QQuickItem *parent): QQuickItem(parent), m_quickMap(nullptr)
+QDeclarativeGeoMapItemGroup::QDeclarativeGeoMapItemGroup(QQuickItem *parent)
+: QQuickItem(parent), m_quickMap(nullptr)
{
-
+ connect(this, &QQuickItem::opacityChanged,
+ this, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged);
}
QDeclarativeGeoMapItemGroup::~QDeclarativeGeoMapItemGroup()
@@ -145,9 +149,23 @@ QDeclarativeGeoMapItemGroup::~QDeclarativeGeoMapItemGroup()
}
+void QDeclarativeGeoMapItemGroup::setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup)
+{
+ m_parentGroup = &parentGroup;
+ connect(m_parentGroup, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged,
+ this, &QDeclarativeGeoMapItemGroup::mapItemOpacityChanged);
+}
+
void QDeclarativeGeoMapItemGroup::setQuickMap(QDeclarativeGeoMap *quickMap)
{
+ if (!quickMap && m_quickMap)
+ m_quickMap->disconnect(this);
m_quickMap = quickMap;
+ if (m_quickMap) {
+ onMapSizeChanged();
+ connect(m_quickMap, &QQuickItem::widthChanged, this, &QDeclarativeGeoMapItemGroup::onMapSizeChanged);
+ connect(m_quickMap, &QQuickItem::heightChanged, this, &QDeclarativeGeoMapItemGroup::onMapSizeChanged);
+ }
}
QDeclarativeGeoMap *QDeclarativeGeoMapItemGroup::quickMap() const
@@ -155,4 +173,45 @@ QDeclarativeGeoMap *QDeclarativeGeoMapItemGroup::quickMap() const
return m_quickMap;
}
+qreal QDeclarativeGeoMapItemGroup::mapItemOpacity() const
+{
+ return ((m_parentGroup) ? m_parentGroup->mapItemOpacity() : 1.0) * opacity();
+}
+
+void QDeclarativeGeoMapItemGroup::classBegin()
+{
+ QQuickItem::classBegin();
+}
+
+void QDeclarativeGeoMapItemGroup::componentComplete()
+{
+ QQuickItem::componentComplete();
+
+ // In certain cases the parent won't be set via the constructor, but rather later on
+ // during the instantiation/incubation process.
+ // Therefore calling setParentGroup here, when the parent is known.
+ // The childrenChanged use case to handle dynamically-added items is currently unsupported.
+ const QList<QQuickItem *> &quickKids = childItems();
+ for (QQuickItem *k : quickKids) {
+ QDeclarativeGeoMapItemGroup *childGroup
+ = qobject_cast<QDeclarativeGeoMapItemGroup *>(k);
+ if (childGroup) {
+ childGroup->setParentGroup(*this);
+ continue;
+ }
+ QDeclarativeGeoMapItemBase *childItem
+ = qobject_cast<QDeclarativeGeoMapItemBase *>(k);
+ if (childItem) {
+ childItem->setParentGroup(*this);
+ continue;
+ }
+ }
+}
+
+void QDeclarativeGeoMapItemGroup::onMapSizeChanged()
+{
+ setWidth(m_quickMap->width());
+ setHeight(m_quickMap->height());
+}
+
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h b/src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h
index f91d291c..395e74a1 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitemgroup_p.h
@@ -49,6 +49,7 @@
//
#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativegeomapitemtransitionmanager_p.h>
#include <QtQuick/QQuickItem>
QT_BEGIN_NAMESPACE
@@ -61,10 +62,32 @@ public:
explicit QDeclarativeGeoMapItemGroup(QQuickItem *parent = 0);
virtual ~QDeclarativeGeoMapItemGroup();
+ void setParentGroup(QDeclarativeGeoMapItemGroup &parentGroup);
void setQuickMap(QDeclarativeGeoMap *quickMap);
QDeclarativeGeoMap *quickMap() const;
+
+ qreal mapItemOpacity() const;
+
+Q_SIGNALS:
+ void mapItemOpacityChanged();
+ void addTransitionFinished();
+ void removeTransitionFinished();
+
+protected:
+ // QQmlParserStatus interface
+ void classBegin() override;
+ void componentComplete() override;
+
+protected slots:
+ void onMapSizeChanged();
+
private:
QDeclarativeGeoMap *m_quickMap;
+ QDeclarativeGeoMapItemGroup *m_parentGroup = nullptr;
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager> m_transitionManager;
+
+ friend class QDeclarativeGeoMapItemView;
+ friend class QDeclarativeGeoMapItemTransitionManager;
};
QT_END_NAMESPACE
diff --git a/src/locationlabs/qlocationlabsglobal_p.h b/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager.cpp
index 6dc29296..549ab2cb 100644
--- a/src/locationlabs/qlocationlabsglobal_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager.cpp
@@ -33,37 +33,49 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef QLOCATIONLABSGLOBAL_P_H
-#define QLOCATIONLABSGLOBAL_P_H
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qglobal.h>
+#include "qdeclarativegeomapitemtransitionmanager_p.h"
+#include "qdeclarativegeomapitemview_p.h"
QT_BEGIN_NAMESPACE
-#ifndef QT_STATIC
-# if defined(QT_BUILD_LOCATIONLABS_LIB)
-# define Q_LOCATIONLABS_EXPORT Q_DECL_EXPORT
-# else
-# define Q_LOCATIONLABS_EXPORT Q_DECL_IMPORT
-# endif
-#else
-# define Q_LOCATIONLABS_EXPORT
-#endif
+QDeclarativeGeoMapItemTransitionManager::QDeclarativeGeoMapItemTransitionManager(QObject *mapItem)
+ : QQuickTransitionManager(), m_mapItem(mapItem)
+{
+}
-#define Q_LOCATIONLABS_PRIVATE_EXPORT Q_LOCATIONLABS_EXPORT
+void QDeclarativeGeoMapItemTransitionManager::transitionEnter()
+{
+ if (m_transitionState == ExitTransition)
+ cancel();
-QT_END_NAMESPACE
+ if (!prepareEnterTransition())
+ return;
+
+ if (m_view && m_view->m_enter)
+ transition(enterActions, m_view->m_enter, m_mapItem);
+ else
+ finished();
+}
+
+void QDeclarativeGeoMapItemTransitionManager::transitionExit()
+{
+ if (!prepareExitTransition())
+ return;
-#endif // QLOCATIONLABSGLOBAL_P_H
+ if (m_view && m_view->m_exit)
+ transition(exitActions, m_view->m_exit, m_mapItem);
+ else
+ finished();
+}
+void QDeclarativeGeoMapItemTransitionManager::finished()
+{
+ if (m_transitionState == EnterTransition)
+ finalizeEnterTransition();
+ else if (m_transitionState == ExitTransition)
+ finalizeExitTransition();
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h b/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h
new file mode 100644
index 00000000..0a83fe39
--- /dev/null
+++ b/src/location/declarativemaps/qdeclarativegeomapitemtransitionmanager_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QDECLARATIVEGEOMAPITEMTRANSITIONMANAGER_H
+#define QDECLARATIVEGEOMAPITEMTRANSITIONMANAGER_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 <QtLocation/private/qlocationglobal_p.h>
+#include <QtQuick/QQuickItem>
+#include <QtQuick/private/qquicktransitionmanager_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeGeoMapItemView;
+
+class QDeclarativeGeoMapItemTransitionManager : public QQuickTransitionManager
+{
+public:
+ enum TransitionState {
+ NoTransition, EnterTransition, ExitTransition
+ };
+
+ QDeclarativeGeoMapItemTransitionManager(QObject *mapItem);
+
+ void transitionEnter();
+ void transitionExit();
+
+ bool prepareEnterTransition()
+ {
+ if (m_transitionState == QDeclarativeGeoMapItemTransitionManager::EnterTransition
+ && isRunning())
+ return false;
+
+ if (m_transitionState != QDeclarativeGeoMapItemTransitionManager::EnterTransition) {
+ // setVisible(true);
+ m_transitionState = QDeclarativeGeoMapItemTransitionManager::EnterTransition;
+ }
+ return true;
+ }
+ bool prepareExitTransition()
+ {
+ if (m_transitionState == QDeclarativeGeoMapItemTransitionManager::ExitTransition
+ && isRunning())
+ return false;
+
+ if (m_transitionState != QDeclarativeGeoMapItemTransitionManager::ExitTransition) {
+ m_transitionState = QDeclarativeGeoMapItemTransitionManager::ExitTransition;
+ }
+ return true;
+ }
+ void finalizeEnterTransition()
+ {
+ m_transitionState = QDeclarativeGeoMapItemTransitionManager::NoTransition;
+ // use invokeMethod since this is used on both QDeclarativeGeoMapItemBase and QDeclarativeGeoMapItemGroup
+ QMetaObject::invokeMethod(m_mapItem, QByteArrayLiteral("addTransitionFinished").constData(), Qt::DirectConnection);
+ }
+ void finalizeExitTransition()
+ {
+// setVisible(false);
+ m_transitionState = QDeclarativeGeoMapItemTransitionManager::NoTransition;
+ QMetaObject::invokeMethod(m_mapItem, QByteArrayLiteral("removeTransitionFinished").constData(), Qt::DirectConnection);
+ }
+
+protected:
+ void finished() override;
+
+public:
+ QObject *m_mapItem;
+ QDeclarativeGeoMapItemView *m_view = nullptr;
+ QList<QQuickStateAction> enterActions;
+ QList<QQuickStateAction> exitActions;
+ TransitionState m_transitionState = NoTransition;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
index 21402130..41ab3453 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
@@ -39,7 +39,6 @@
#include "qdeclarativegeomapitemview_p.h"
#include "qdeclarativegeomap_p.h"
#include "qdeclarativegeomapitembase_p.h"
-#include "mapitemviewdelegateincubator_p.h"
#include <QtCore/QAbstractItemModel>
#include <QtQml/QQmlContext>
@@ -75,8 +74,26 @@ QT_BEGIN_NAMESPACE
\snippet declarative/maps.qml MapRoute
*/
+/*!
+ \qmlproperty Transition QtLocation::MapItemView::add
+
+ This property holds the transition that is applied to the map items created by the view
+ when they are instantiated and added to the map.
+
+ \since QtLocation 5.12
+*/
+
+/*!
+ \qmlproperty Transition QtLocation::MapItemView::remove
+
+ This property holds the transition that is applied to the map items created by the view
+ when they are removed.
+
+ \since QtLocation 5.12
+*/
+
QDeclarativeGeoMapItemView::QDeclarativeGeoMapItemView(QQuickItem *parent)
- : QObject(parent), m_componentCompleted(false), m_delegate(0),
+ : QDeclarativeGeoMapItemGroup(parent), m_componentCompleted(false), m_delegate(0),
m_map(0), m_fitViewport(false), m_delegateModel(0)
{
m_exit = new QQuickTransition(this);
@@ -98,6 +115,7 @@ QDeclarativeGeoMapItemView::~QDeclarativeGeoMapItemView()
*/
void QDeclarativeGeoMapItemView::componentComplete()
{
+ QDeclarativeGeoMapItemGroup::componentComplete();
m_componentCompleted = true;
if (!m_itemModel.isNull())
m_delegateModel->setModel(m_itemModel);
@@ -110,14 +128,15 @@ void QDeclarativeGeoMapItemView::componentComplete()
void QDeclarativeGeoMapItemView::classBegin()
{
+ QDeclarativeGeoMapItemGroup::classBegin();
QQmlContext *ctx = qmlContext(this);
m_delegateModel = new QQmlDelegateModel(ctx, this);
m_delegateModel->classBegin();
connect(m_delegateModel, &QQmlInstanceModel::modelUpdated, this, &QDeclarativeGeoMapItemView::modelUpdated);
connect(m_delegateModel, &QQmlInstanceModel::createdItem, this, &QDeclarativeGeoMapItemView::createdItem);
- connect(m_delegateModel, &QQmlInstanceModel::destroyingItem, this, &QDeclarativeGeoMapItemView::destroyingItem);
- connect(m_delegateModel, &QQmlInstanceModel::initItem, this, &QDeclarativeGeoMapItemView::initItem);
+// connect(m_delegateModel, &QQmlInstanceModel::destroyingItem, this, &QDeclarativeGeoMapItemView::destroyingItem);
+// connect(m_delegateModel, &QQmlInstanceModel::initItem, this, &QDeclarativeGeoMapItemView::initItem);
}
void QDeclarativeGeoMapItemView::destroyingItem(QObject */*object*/)
@@ -136,12 +155,22 @@ void QDeclarativeGeoMapItemView::createdItem(int index, QObject */*object*/)
return;
// createdItem is emitted on asynchronous creation. In which case, object has to be invoked again.
// See QQmlDelegateModel::object for further info.
- QDeclarativeGeoMapItemBase *item =
- qobject_cast<QDeclarativeGeoMapItemBase *>(m_delegateModel->object(index, QQmlIncubator::Asynchronous));
+
+ // DelegateModel apparently triggers this method in any case, that is:
+ // 1. Synchronous incubation, delegate instantiated on the first object() call (during the object() call!)
+ // 2. Async incubation, delegate not instantiated on the first object() call
+ // 3. Async incubation, delegate present in the cache, and returned on the first object() call.
+ // createdItem also called during the object() call.
+ if (m_creatingObject) {
+ // Falling into case 1. or 3. Returning early to prevent double referencing the delegate instance.
+ return;
+ }
+
+ QQuickItem *item = qobject_cast<QQuickItem *>(m_delegateModel->object(index, m_incubationMode));
if (item)
- addItemToMap(item, index);
+ addDelegateToMap(item, index, true);
else
- qWarning() << "createdItem for " << index << " produced a null item";
+ qWarning() << "QQmlDelegateModel:: object called in createdItem for " << index << " produced a null item";
}
void QDeclarativeGeoMapItemView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
@@ -161,15 +190,15 @@ void QDeclarativeGeoMapItemView::modelUpdated(const QQmlChangeSet &changeSet, bo
for (auto rit = mapRemoves.rbegin(); rit != mapRemoves.rend(); ++rit) {
const QQmlChangeSet::Change &c = removes.at(rit->second);
for (int idx = c.end() - 1; idx >= c.start(); --idx)
- removeItemFromMap(idx);
+ removeDelegateFromMap(idx);
}
}
+ QBoolBlocker createBlocker(m_creatingObject, true);
for (const QQmlChangeSet::Change &c: changeSet.inserts()) {
for (int idx = c.start(); idx < c.end(); idx++) {
- QDeclarativeGeoMapItemBase *item =
- qobject_cast<QDeclarativeGeoMapItemBase *>(m_delegateModel->object(idx, QQmlIncubator::Asynchronous));
- addItemToMap(item, idx); // if not item, a createdItem signal will be emitted.
+ QObject *delegateInstance = m_delegateModel->object(idx, m_incubationMode);
+ addDelegateToMap(qobject_cast<QQuickItem *>(delegateInstance), idx);
}
}
@@ -272,14 +301,15 @@ void QDeclarativeGeoMapItemView::setMap(QDeclarativeGeoMap *map)
/*!
\internal
*/
-void QDeclarativeGeoMapItemView::removeInstantiatedItems()
+void QDeclarativeGeoMapItemView::removeInstantiatedItems(bool transition)
{
if (!m_map)
return;
+ // FIXME: removeInstantiatedItems should abort, as well as exit transitions terminated QTBUG-69195
// Backward as removeItemFromMap modifies m_instantiatedItems
for (int i = m_instantiatedItems.size() -1; i >= 0 ; i--)
- removeItemFromMap(i);
+ removeDelegateFromMap(i, transition);
}
/*!
@@ -294,71 +324,142 @@ void QDeclarativeGeoMapItemView::instantiateAllItems()
return;
// If here, m_delegateModel may contain data, but QQmlInstanceModel::object for each row hasn't been called yet.
+ QBoolBlocker createBlocker(m_creatingObject, true);
for (int i = 0; i < m_delegateModel->count(); i++) {
- QDeclarativeGeoMapItemBase *item =
- qobject_cast<QDeclarativeGeoMapItemBase *>(m_delegateModel->object(i, QQmlIncubator::Asynchronous));
- addItemToMap(item, i); // if not item, createdItem will be emitted.
+ QObject *delegateInstance = m_delegateModel->object(i, m_incubationMode);
+ addDelegateToMap(qobject_cast<QQuickItem *>(delegateInstance), i);
}
fitViewport();
}
-void QDeclarativeGeoMapItemView::removeItemFromMap(int index)
+void QDeclarativeGeoMapItemView::setIncubateDelegates(bool useIncubators)
+{
+ const QQmlIncubator::IncubationMode incubationMode =
+ (useIncubators) ? QQmlIncubator::Asynchronous : QQmlIncubator::Synchronous;
+ if (m_incubationMode == incubationMode)
+ return;
+ m_incubationMode = incubationMode;
+ emit incubateDelegatesChanged();
+}
+
+bool QDeclarativeGeoMapItemView::incubateDelegates() const
+{
+ return m_incubationMode == QQmlIncubator::Asynchronous;
+}
+
+QList<QQuickItem *> QDeclarativeGeoMapItemView::mapItems()
+{
+ return m_instantiatedItems;
+}
+
+void QDeclarativeGeoMapItemView::removeDelegateFromMap(int index, bool transition)
{
if (index >= 0 && index < m_instantiatedItems.size()) {
- QDeclarativeGeoMapItemBase *item = m_instantiatedItems.takeAt(index);
- if (!item) {
- if (m_incubatingItems.contains(index)) {
- // cancel request
- m_delegateModel->cancel(index);
- m_incubatingItems.remove(index);
- }
+ QQuickItem *item = m_instantiatedItems.takeAt(index);
+ if (!item) { // not yet incubated
+ // Don't cancel incubation explicitly, as DelegateModel apparently takes care of incubating elements when the model
+ // remove those indices.
return;
}
- if (m_exit && m_map) {
- if (!item->m_transitionManager) {
- QScopedPointer<QDeclarativeGeoMapItemTransitionManager>manager(new QDeclarativeGeoMapItemTransitionManager(item));
- item->m_transitionManager.swap(manager);
- item->m_transitionManager->m_view = this;
- }
- connect(item, &QDeclarativeGeoMapItemBase::exitTransitionFinished,
- this, &QDeclarativeGeoMapItemView::exitTransitionFinished);
- item->m_transitionManager->transitionExit();
+ // item can be either a QDeclarativeGeoMapItemBase or a QDeclarativeGeoMapItemGroup (subclass)
+ if (m_exit && m_map && transition) {
+ transitionItemOut(item);
} else {
disconnect(item, 0, this, 0);
- if (m_map)
- m_map->removeMapItem(item);
+ removeDelegateFromMap(item);
+ item->setParentItem(nullptr); // Needed because
+ item->setParent(nullptr); // m_delegateModel->release(item) does not destroy the item most of the times!!
QQmlInstanceModel::ReleaseFlags releaseStatus = m_delegateModel->release(item);
+#ifdef QT_DEBUG
if (releaseStatus == QQmlInstanceModel::Referenced)
- qWarning() << "item "<< index << " still referenced";
+ qWarning() << "item "<< index << "(" << item << ") still referenced";
+#else
+ Q_UNUSED(releaseStatus)
+#endif
}
}
}
+void QDeclarativeGeoMapItemView::removeDelegateFromMap(QQuickItem *o)
+{
+ if (!m_map)
+ return;
+
+ QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(o);
+ if (item) {
+ m_map->removeMapItem(item);
+ return;
+ }
+ QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(o);
+ if (view) {
+ m_map->removeMapItemView(view);
+ return;
+ }
+ QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(o);
+ if (group) {
+ m_map->removeMapItemGroup(group);
+ return;
+ }
+}
+
+void QDeclarativeGeoMapItemView::transitionItemOut(QQuickItem *o)
+{
+ QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(o);
+ if (group) {
+ if (!group->m_transitionManager) {
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager>manager(new QDeclarativeGeoMapItemTransitionManager(group));
+ group->m_transitionManager.swap(manager);
+ group->m_transitionManager->m_view = this;
+ }
+ connect(group, SIGNAL(removeTransitionFinished()),
+ this, SLOT(exitTransitionFinished()));
+
+ group->m_transitionManager->transitionExit();
+ return;
+ }
+ QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(o);
+ if (item) {
+ if (!item->m_transitionManager) {
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager> manager(new QDeclarativeGeoMapItemTransitionManager(item));
+ item->m_transitionManager.swap(manager);
+ item->m_transitionManager->m_view = this;
+ }
+ connect(item, SIGNAL(removeTransitionFinished()),
+ this, SLOT(exitTransitionFinished()) );
+
+ item->m_transitionManager->transitionExit();
+ return;
+ }
+}
+
void QDeclarativeGeoMapItemView::exitTransitionFinished()
{
- QDeclarativeGeoMapItemBase *item = static_cast<QDeclarativeGeoMapItemBase *>(sender());
+ QQuickItem *item = qobject_cast<QQuickItem *>(sender());
+ if (!item)
+ return;
disconnect(item, 0, this, 0);
- if (m_map)
- m_map->removeMapItem(item);
+ removeDelegateFromMap(item);
+ item->setParentItem(nullptr);
+ item->setParent(nullptr);
QQmlInstanceModel::ReleaseFlags releaseStatus = m_delegateModel->release(item);
+#ifdef QT_DEBUG
if (releaseStatus == QQmlInstanceModel::Referenced)
qWarning() << "item "<<item<<" still referenced";
+#else
+ Q_UNUSED(releaseStatus)
+#endif
}
-void QDeclarativeGeoMapItemView::addItemToMap(QDeclarativeGeoMapItemBase *item, int index)
+void QDeclarativeGeoMapItemView::addItemToMap(QDeclarativeGeoMapItemBase *item, int index, bool createdItem)
{
- if (m_map && item && item->quickMap() == m_map) // belonging to another map??
+
+ if (m_map && item->quickMap() == m_map) // test for *item done in the caller
return;
if (m_map) {
- if (!item) {
- m_incubatingItems.insert(index);
- m_instantiatedItems.insert(index, nullptr);
- return;
- }
-
- insertInstantiatedItem(index, item);
+ insertInstantiatedItem(index, item, createdItem);
+ item->setParentItem(this);
m_map->addMapItem(item);
if (m_enter) {
if (!item->m_transitionManager) {
@@ -371,14 +472,77 @@ void QDeclarativeGeoMapItemView::addItemToMap(QDeclarativeGeoMapItemBase *item,
}
}
-void QDeclarativeGeoMapItemView::insertInstantiatedItem(int index, QDeclarativeGeoMapItemBase *o)
+void QDeclarativeGeoMapItemView::insertInstantiatedItem(int index, QQuickItem *o, bool createdItem)
{
- if (m_incubatingItems.contains(index)) {
- m_incubatingItems.remove(index);
+ if (createdItem)
m_instantiatedItems.replace(index, o);
- } else {
+ else
m_instantiatedItems.insert(index, o);
+}
+
+void QDeclarativeGeoMapItemView::addItemViewToMap(QDeclarativeGeoMapItemView *item, int index, bool createdItem)
+{
+ if (m_map && item->quickMap() == m_map) // test for *item done in the caller
+ return;
+
+ if (m_map) {
+ insertInstantiatedItem(index, item, createdItem);
+ item->setParentItem(this);
+ m_map->addMapItemView(item);
+ if (m_enter) {
+ if (!item->m_transitionManager) {
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager> manager(new QDeclarativeGeoMapItemTransitionManager(item));
+ item->m_transitionManager.swap(manager);
+ }
+ item->m_transitionManager->m_view = this;
+ item->m_transitionManager->transitionEnter();
+ }
+ }
+}
+
+void QDeclarativeGeoMapItemView::addItemGroupToMap(QDeclarativeGeoMapItemGroup *item, int index, bool createdItem)
+{
+ if (m_map && item->quickMap() == m_map) // test for *item done in the caller
+ return;
+
+ if (m_map) {
+ insertInstantiatedItem(index, item, createdItem);
+ item->setParentItem(this);
+ m_map->addMapItemGroup(item);
+ if (m_enter) {
+ if (!item->m_transitionManager) {
+ QScopedPointer<QDeclarativeGeoMapItemTransitionManager>manager(new QDeclarativeGeoMapItemTransitionManager(item));
+ item->m_transitionManager.swap(manager);
+ }
+ item->m_transitionManager->m_view = this;
+ item->m_transitionManager->transitionEnter();
+ }
+ }
+}
+
+void QDeclarativeGeoMapItemView::addDelegateToMap(QQuickItem *object, int index, bool createdItem)
+{
+ if (!object) {
+ if (!createdItem)
+ m_instantiatedItems.insert(index, nullptr); // insert placeholder
+ return;
+ }
+ QDeclarativeGeoMapItemBase *item = qobject_cast<QDeclarativeGeoMapItemBase *>(object);
+ if (item) { // else createdItem will be emitted.
+ addItemToMap(item, index, createdItem);
+ return;
+ }
+ QDeclarativeGeoMapItemView *view = qobject_cast<QDeclarativeGeoMapItemView *>(object);
+ if (view) {
+ addItemViewToMap(view, index, createdItem);
+ return;
+ }
+ QDeclarativeGeoMapItemGroup *group = qobject_cast<QDeclarativeGeoMapItemGroup *>(object);
+ if (group) {
+ addItemGroupToMap(group, index, createdItem);
+ return;
}
+ qWarning() << "addDelegateToMap called with a "<< object->metaObject()->className();
}
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
index 1f107fbb..43ca685a 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
@@ -58,6 +58,7 @@
#include <QtQml/qqml.h>
#include <QtQml/private/qqmldelegatemodel_p.h>
#include <QtQuick/private/qquicktransition_p.h>
+#include <QtLocation/private/qdeclarativegeomapitemgroup_p.h>
QT_BEGIN_NAMESPACE
@@ -71,18 +72,19 @@ class QQmlOpenMetaObjectType;
class MapItemViewDelegateIncubator;
class QDeclarativeGeoMapItemViewItemData;
class QDeclarativeGeoMapItemView;
+class QDeclarativeGeoMapItemGroup;
-class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMapItemView : public QObject, public QQmlParserStatus
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMapItemView : public QDeclarativeGeoMapItemGroup
{
Q_OBJECT
- Q_INTERFACES(QQmlParserStatus)
-
Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
Q_PROPERTY(QQmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(bool autoFitViewport READ autoFitViewport WRITE setAutoFitViewport NOTIFY autoFitViewportChanged)
-// Q_PROPERTY(QQuickTransition *enter MEMBER m_enter)
-// Q_PROPERTY(QQuickTransition *exit MEMBER m_exit)
+ Q_PROPERTY(QQuickTransition *add MEMBER m_enter REVISION 12)
+ Q_PROPERTY(QQuickTransition *remove MEMBER m_exit REVISION 12)
+ Q_PROPERTY(QList<QQuickItem *> mapItems READ mapItems REVISION 12)
+ Q_PROPERTY(bool incubateDelegates READ incubateDelegates WRITE setIncubateDelegates NOTIFY incubateDelegatesChanged REVISION 12)
public:
explicit QDeclarativeGeoMapItemView(QQuickItem *parent = 0);
@@ -98,9 +100,14 @@ public:
void setAutoFitViewport(const bool &fit);
void setMap(QDeclarativeGeoMap *);
- void removeInstantiatedItems();
+ void removeInstantiatedItems(bool transition = true);
void instantiateAllItems();
+ void setIncubateDelegates(bool useIncubators);
+ bool incubateDelegates() const;
+
+ QList<QQuickItem *> mapItems();
+
// From QQmlParserStatus
void componentComplete() override;
void classBegin() override;
@@ -109,6 +116,7 @@ Q_SIGNALS:
void modelChanged();
void delegateChanged();
void autoFitViewportChanged();
+ void incubateDelegatesChanged();
private Q_SLOTS:
void destroyingItem(QObject *object);
@@ -119,17 +127,24 @@ private Q_SLOTS:
private:
void fitViewport();
- void removeItemFromMap(int index);
- void addItemToMap(QDeclarativeGeoMapItemBase *item, int index);
- void insertInstantiatedItem(int index, QDeclarativeGeoMapItemBase *o);
+ void removeDelegateFromMap(int index, bool transition = true);
+ void removeDelegateFromMap(QQuickItem *o);
+ void transitionItemOut(QQuickItem *o);
+
+ void insertInstantiatedItem(int index, QQuickItem *o, bool createdItem);
+ void addItemToMap(QDeclarativeGeoMapItemBase *item, int index, bool createdItem);
+ void addItemViewToMap(QDeclarativeGeoMapItemView *item, int index, bool createdItem);
+ void addItemGroupToMap(QDeclarativeGeoMapItemGroup *item, int index, bool createdItem);
+ void addDelegateToMap(QQuickItem *object, int index, bool createdItem = false);
bool m_componentCompleted;
+ QQmlIncubator::IncubationMode m_incubationMode = QQmlIncubator::Asynchronous;
QQmlComponent *m_delegate;
QVariant m_itemModel;
QDeclarativeGeoMap *m_map;
- QList<QDeclarativeGeoMapItemBase *> m_instantiatedItems;
- QSet<int> m_incubatingItems;
+ QList<QQuickItem *> m_instantiatedItems;
bool m_fitViewport;
+ bool m_creatingObject = false;
QQmlDelegateModel *m_delegateModel;
QQuickTransition *m_enter = nullptr;
QQuickTransition *m_exit = nullptr;
diff --git a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp
index 62613126..8c71e7be 100644
--- a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp
@@ -346,6 +346,21 @@ const QGeoShape &QDeclarativeGeoMapQuickItem::geoShape() const
return geoshape_;
}
+void QDeclarativeGeoMapQuickItem::setGeoShape(const QGeoShape &shape)
+{
+ if (shape == geoshape_)
+ return;
+
+ const QGeoRectangle rect = shape.boundingGeoRectangle();
+ geoshape_ = rect;
+ coordinate_ = rect.center();
+
+ // TODO: Handle zoomLevel != 0.0
+ polishAndUpdate();
+ emit coordinateChanged();
+
+}
+
QGeoMap::ItemType QDeclarativeGeoMapQuickItem::itemType() const
{
return QGeoMap::MapQuickItem;
@@ -441,6 +456,10 @@ void QDeclarativeGeoMapQuickItem::updatePolish()
void QDeclarativeGeoMapQuickItem::afterViewportChanged(const QGeoMapViewportChangeEvent &event)
{
Q_UNUSED(event);
+ if (event.mapSize.width() <= 0 || event.mapSize.height() <= 0)
+ return;
+
+ polishAndUpdate();
}
/*!
diff --git a/src/location/declarativemaps/qdeclarativegeomapquickitem_p.h b/src/location/declarativemaps/qdeclarativegeomapquickitem_p.h
index 8e2c2785..a27a0bce 100644
--- a/src/location/declarativemaps/qdeclarativegeomapquickitem_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapquickitem_p.h
@@ -97,6 +97,7 @@ public:
qreal zoomLevel() const;
const QGeoShape &geoShape() const override;
+ void setGeoShape(const QGeoShape &shape) override;
QGeoMap::ItemType itemType() const override;
Q_SIGNALS:
diff --git a/src/location/declarativemaps/qdeclarativegeoroute.cpp b/src/location/declarativemaps/qdeclarativegeoroute.cpp
index 95a26a32..09ed46ab 100644
--- a/src/location/declarativemaps/qdeclarativegeoroute.cpp
+++ b/src/location/declarativemaps/qdeclarativegeoroute.cpp
@@ -79,12 +79,12 @@ QT_BEGIN_NAMESPACE
*/
QDeclarativeGeoRoute::QDeclarativeGeoRoute(QObject *parent)
- : QObject(parent), segmentsDirty_(true)
+ : QObject(parent)
{
}
QDeclarativeGeoRoute::QDeclarativeGeoRoute(const QGeoRoute &route, QObject *parent)
- : QObject(parent), route_(route), segmentsDirty_(true)
+ : QObject(parent), route_(route)
{
}
@@ -95,6 +95,7 @@ void QDeclarativeGeoRoute::initSegments(unsigned int lastIndex) // -1 turns it
if (!segmentsDirty_)
return;
+ const bool isLeg = qobject_cast<QDeclarativeGeoRoute *>(parent());
QGeoRouteSegment segment = route_.firstRouteSegment();
unsigned int idx = 0;
unsigned int initialListSize = static_cast<unsigned int>(segments_.size());
@@ -104,6 +105,10 @@ void QDeclarativeGeoRoute::initSegments(unsigned int lastIndex) // -1 turns it
QQmlEngine::setContextForObject(routeSegment, QQmlEngine::contextForObject(this));
segments_.append(routeSegment);
}
+ if (isLeg && segment.isLegLastSegment()) {
+ segmentsDirty_ = false;
+ return;
+ }
++idx;
segment = segment.nextRouteSegment();
if (idx > lastIndex && segment.isValid()) // Do not clean segmentsDirty_ if there are still segments to initialize
@@ -182,7 +187,7 @@ QJSValue QDeclarativeGeoRoute::path() const
const QGeoCoordinate &c = route_.path().at(i);
QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(c)));
- pathArray->putIndexed(i, cv);
+ pathArray->put(i, cv);
}
return QJSValue(v4, pathArray.asReturnedValue());
@@ -321,4 +326,98 @@ QDeclarativeGeoRouteQuery *QDeclarativeGeoRoute::routeQuery()
return routeQuery_;
}
+/*!
+ \qmlproperty list<Route> QtLocation::Route::legs
+
+ Returns the route legs associated with this route.
+ Route legs are the sub-routes between each two adjacent waypoints.
+ The result may be empty, if this level of detail is not supported by the
+ backend.
+
+ \since QtLocation 5.12
+*/
+QList<QObject *> QDeclarativeGeoRoute::legs()
+{
+ // route_.routeLegs() is expected not to change.
+ // The following if condition is expected to be run only once.
+ if (route_.routeLegs().size() != legs_.size()) {
+ legs_.clear();
+ QList<QGeoRouteLeg> rlegs = route_.routeLegs();
+ for (const QGeoRouteLeg &r: rlegs) {
+ QDeclarativeGeoRouteLeg *dr = new QDeclarativeGeoRouteLeg(r, this);
+ legs_.append(dr);
+ }
+ }
+ return legs_;
+}
+
+/*!
+ \qmlmethod bool QtLocation::Route::equals(Route other)
+
+ This method performs deep comparison.
+
+ \since 5.12
+*/
+bool QDeclarativeGeoRoute::equals(QDeclarativeGeoRoute *other) const
+{
+ return route_ == other->route_;
+}
+
+/*!
+ \qmltype RouteLeg
+ \instantiates QDeclarativeGeoRouteLeg
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-routing
+ \since QtLocation 5.12
+
+ \brief The RouteLeg type represents a leg of a Route, that is the portion
+ of a route between one waypoint and the next.
+
+ \note Since RouteLeg is a subclass of Route, QtLocation::Route::legs will
+ return an empty list if accessed on a route leg.
+*/
+
+/*!
+ \qmlproperty int QtLocation::RouteLeg::legIndex
+
+ Read-only property which holds the index of the leg within the containing Route's list of QtLocation::Route::legs .
+*/
+
+/*!
+ \qmlproperty Route QtLocation::RouteLeg::overallRoute
+
+ Read-only property which holds the Route that contains this leg.
+*/
+
+
+QDeclarativeGeoRouteLeg::QDeclarativeGeoRouteLeg(QObject *parent)
+ : QDeclarativeGeoRoute(parent)
+{
+
+}
+
+QDeclarativeGeoRouteLeg::QDeclarativeGeoRouteLeg(const QGeoRouteLeg &routeLeg, QObject *parent)
+ : QDeclarativeGeoRoute(routeLeg, parent), m_routeLeg(routeLeg)
+{
+
+}
+
+QDeclarativeGeoRouteLeg::~QDeclarativeGeoRouteLeg()
+{
+
+}
+
+int QDeclarativeGeoRouteLeg::legIndex() const
+{
+ return m_routeLeg.legIndex();
+}
+
+QObject *QDeclarativeGeoRouteLeg::overallRoute() const
+{
+ QDeclarativeGeoRoute *containingRoute = qobject_cast<QDeclarativeGeoRoute *>(parent());
+ if (Q_UNLIKELY(!containingRoute))
+ return new QDeclarativeGeoRoute(m_routeLeg.overallRoute(), parent());
+ return containingRoute;
+}
+
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeoroute_p.h b/src/location/declarativemaps/qdeclarativegeoroute_p.h
index c19c2674..98d08e98 100644
--- a/src/location/declarativemaps/qdeclarativegeoroute_p.h
+++ b/src/location/declarativemaps/qdeclarativegeoroute_p.h
@@ -68,6 +68,7 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoRoute : public QObject
Q_PROPERTY(QJSValue path READ path WRITE setPath NOTIFY pathChanged)
Q_PROPERTY(QQmlListProperty<QDeclarativeGeoRouteSegment> segments READ segments CONSTANT)
Q_PROPERTY(QDeclarativeGeoRouteQuery *routeQuery READ routeQuery REVISION 11)
+ Q_PROPERTY(QList<QObject *> legs READ legs CONSTANT REVISION 12)
public:
explicit QDeclarativeGeoRoute(QObject *parent = 0);
@@ -89,6 +90,9 @@ public:
int segmentsCount() const;
const QGeoRoute &route() const;
QDeclarativeGeoRouteQuery *routeQuery();
+ QList<QObject *> legs();
+
+ Q_INVOKABLE bool equals(QDeclarativeGeoRoute *other) const;
Q_SIGNALS:
void pathChanged();
@@ -105,10 +109,30 @@ private:
QGeoRoute route_;
QDeclarativeGeoRouteQuery *routeQuery_ = nullptr;
QList<QDeclarativeGeoRouteSegment *> segments_;
- bool segmentsDirty_;
+ QList<QObject *> legs_;
+ bool segmentsDirty_ = true;
friend class QDeclarativeRouteMapItem;
};
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoRouteLeg : public QDeclarativeGeoRoute
+{
+ Q_OBJECT
+
+ Q_PROPERTY(int legIndex READ legIndex CONSTANT)
+ Q_PROPERTY(QObject * overallRoute READ overallRoute CONSTANT)
+
+public:
+ explicit QDeclarativeGeoRouteLeg(QObject *parent = nullptr);
+ QDeclarativeGeoRouteLeg(const QGeoRouteLeg &routeLeg, QObject *parent = nullptr);
+ ~QDeclarativeGeoRouteLeg() override;
+
+ int legIndex() const;
+ QObject *overallRoute() const;
+
+private:
+ QGeoRouteLeg m_routeLeg;
+};
+
QT_END_NAMESPACE
#endif
diff --git a/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp b/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp
index 775fb114..20ccfdd2 100644
--- a/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp
+++ b/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp
@@ -952,7 +952,7 @@ QJSValue QDeclarativeGeoRouteQuery::excludedAreas() const
const QGeoRectangle &r = request_.excludeAreas().at(i);
QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(r)));
- excludedAreasArray->putIndexed(i, cv);
+ excludedAreasArray->put(i, cv);
}
return QJSValue(v4, excludedAreasArray.asReturnedValue());
diff --git a/src/location/declarativemaps/qdeclarativegeoroutesegment.cpp b/src/location/declarativemaps/qdeclarativegeoroutesegment.cpp
index 5f6fda53..b0e05f32 100644
--- a/src/location/declarativemaps/qdeclarativegeoroutesegment.cpp
+++ b/src/location/declarativemaps/qdeclarativegeoroutesegment.cpp
@@ -153,7 +153,7 @@ QJSValue QDeclarativeGeoRouteSegment::path() const
const QGeoCoordinate &c = segment_.path().at(i);
QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(c)));
- pathArray->putIndexed(i, cv);
+ pathArray->put(i, cv);
}
return QJSValue(v4, pathArray.asReturnedValue());
diff --git a/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp b/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp
index 09309bcd..b594d2dc 100644
--- a/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp
+++ b/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp
@@ -146,6 +146,7 @@ void QDeclarativeGeoServiceProvider::tryAttach()
return;
sharedProvider_ = new QGeoServiceProvider(name_, parameterMap());
+ sharedProvider_->setQmlEngine(qmlEngine(this));
sharedProvider_->setLocale(locales_.at(0));
sharedProvider_->setAllowExperimental(experimental_);
diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp
index e9f91e45..f4cdc6bf 100644
--- a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp
@@ -606,6 +606,19 @@ const QGeoShape &QDeclarativePolygonMapItem::geoShape() const
return geopath_;
}
+void QDeclarativePolygonMapItem::setGeoShape(const QGeoShape &shape)
+{
+ if (shape == geopath_)
+ return;
+
+ geopath_ = shape;
+ regenerateCache();
+ geometry_.setPreserveGeometry(true, geopath_.boundingGeoRectangle().topLeft());
+ borderGeometry_.setPreserveGeometry(true, geopath_.boundingGeoRectangle().topLeft());
+ markSourceDirtyAndUpdate();
+ emit pathChanged();
+}
+
QGeoMap::ItemType QDeclarativePolygonMapItem::itemType() const
{
return QGeoMap::MapPolygon;
diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem_p.h b/src/location/declarativemaps/qdeclarativepolygonmapitem_p.h
index 60e81b08..87d72307 100644
--- a/src/location/declarativemaps/qdeclarativepolygonmapitem_p.h
+++ b/src/location/declarativemaps/qdeclarativepolygonmapitem_p.h
@@ -52,6 +52,7 @@
#include <QtLocation/private/qdeclarativegeomapitembase_p.h>
#include <QtLocation/private/qdeclarativepolylinemapitem_p.h>
#include <QtLocation/private/qgeomapitemgeometry_p.h>
+#include <QtPositioning/qgeopolygon.h>
#include <QSGGeometryNode>
#include <QSGFlatColorMaterial>
@@ -106,6 +107,7 @@ public:
bool contains(const QPointF &point) const override;
const QGeoShape &geoShape() const override;
+ void setGeoShape(const QGeoShape &shape) override;
QGeoMap::ItemType itemType() const override;
Q_SIGNALS:
@@ -124,7 +126,7 @@ private:
void regenerateCache();
void updateCache();
- QGeoPath geopath_;
+ QGeoPolygon geopath_;
QList<QDoubleVector2D> geopathProjected_;
QDeclarativeMapLineProperties border_;
QColor color_;
diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
index e6619800..2fb3098d 100644
--- a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
@@ -398,9 +398,13 @@ QList<QList<QDoubleVector2D> > QGeoMapPolylineGeometry::clipPath(const QGeoMap &
wrappedPath.append(wrappedProjection);
}
+#ifdef QT_LOCATION_DEBUG
+ m_wrappedPath = wrappedPath;
+#endif
+
// 2)
QList<QList<QDoubleVector2D> > clippedPaths;
- const QList<QDoubleVector2D> &visibleRegion = p.visibleGeometryExpanded();
+ const QList<QDoubleVector2D> &visibleRegion = p.projectableGeometry();
if (visibleRegion.size()) {
clippedPaths = clipLine(wrappedPath, visibleRegion);
@@ -428,6 +432,10 @@ QList<QList<QDoubleVector2D> > QGeoMapPolylineGeometry::clipPath(const QGeoMap &
clippedPaths.append(wrappedPath);
}
+#ifdef QT_LOCATION_DEBUG
+ m_clippedPaths = clippedPaths;
+#endif
+
return clippedPaths;
}
@@ -441,14 +449,12 @@ void QGeoMapPolylineGeometry::pathToScreen(const QGeoMap &map,
double minY = qInf();
double maxX = -qInf();
double maxY = -qInf();
-
srcOrigin_ = p.mapProjectionToGeo(p.unwrapMapProjection(leftBoundWrapped));
QDoubleVector2D origin = p.wrappedMapProjectionToItemPosition(leftBoundWrapped);
for (const QList<QDoubleVector2D> &path: clippedPaths) {
QDoubleVector2D lastAddedPoint;
for (int i = 0; i < path.size(); ++i) {
QDoubleVector2D point = p.wrappedMapProjectionToItemPosition(path.at(i));
-
point = point - origin; // (0,0) if point == geoLeftBound_
minX = qMin(point.x(), minX);
@@ -507,6 +513,120 @@ void QGeoMapPolylineGeometry::updateSourcePoints(const QGeoMap &map,
pathToScreen(map, clippedPaths, leftBoundWrapped);
}
+// *** SCREEN CLIPPING *** //
+
+enum ClipPointType {
+ InsidePoint = 0x00,
+ LeftPoint = 0x01,
+ RightPoint = 0x02,
+ BottomPoint = 0x04,
+ TopPoint = 0x08
+};
+
+static inline int clipPointType(qreal x, qreal y, const QRectF &rect)
+{
+ int type = InsidePoint;
+ if (x < rect.left())
+ type |= LeftPoint;
+ else if (x > rect.right())
+ type |= RightPoint;
+ if (y < rect.top())
+ type |= TopPoint;
+ else if (y > rect.bottom())
+ type |= BottomPoint;
+ return type;
+}
+
+static void clipSegmentToRect(qreal x0, qreal y0, qreal x1, qreal y1,
+ const QRectF &clipRect,
+ QVector<qreal> &outPoints,
+ QVector<QPainterPath::ElementType> &outTypes)
+{
+ int type0 = clipPointType(x0, y0, clipRect);
+ int type1 = clipPointType(x1, y1, clipRect);
+ bool accept = false;
+
+ while (true) {
+ if (!(type0 | type1)) {
+ accept = true;
+ break;
+ } else if (type0 & type1) {
+ break;
+ } else {
+ qreal x = 0.0;
+ qreal y = 0.0;
+ int outsideType = type0 ? type0 : type1;
+
+ if (outsideType & BottomPoint) {
+ x = x0 + (x1 - x0) * (clipRect.bottom() - y0) / (y1 - y0);
+ y = clipRect.bottom() - 0.1;
+ } else if (outsideType & TopPoint) {
+ x = x0 + (x1 - x0) * (clipRect.top() - y0) / (y1 - y0);
+ y = clipRect.top() + 0.1;
+ } else if (outsideType & RightPoint) {
+ y = y0 + (y1 - y0) * (clipRect.right() - x0) / (x1 - x0);
+ x = clipRect.right() - 0.1;
+ } else if (outsideType & LeftPoint) {
+ y = y0 + (y1 - y0) * (clipRect.left() - x0) / (x1 - x0);
+ x = clipRect.left() + 0.1;
+ }
+
+ if (outsideType == type0) {
+ x0 = x;
+ y0 = y;
+ type0 = clipPointType(x0, y0, clipRect);
+ } else {
+ x1 = x;
+ y1 = y;
+ type1 = clipPointType(x1, y1, clipRect);
+ }
+ }
+ }
+
+ if (accept) {
+ if (outPoints.size() >= 2) {
+ qreal lastX, lastY;
+ lastY = outPoints.at(outPoints.size() - 1);
+ lastX = outPoints.at(outPoints.size() - 2);
+
+ if (!qFuzzyCompare(lastY, y0) || !qFuzzyCompare(lastX, x0)) {
+ outTypes << QPainterPath::MoveToElement;
+ outPoints << x0 << y0;
+ }
+ } else {
+ outTypes << QPainterPath::MoveToElement;
+ outPoints << x0 << y0;
+ }
+
+ outTypes << QPainterPath::LineToElement;
+ outPoints << x1 << y1;
+ }
+}
+
+static void clipPathToRect(const QVector<qreal> &points,
+ const QVector<QPainterPath::ElementType> &types,
+ const QRectF &clipRect,
+ QVector<qreal> &outPoints,
+ QVector<QPainterPath::ElementType> &outTypes)
+{
+ outPoints.clear();
+ outPoints.reserve(points.size());
+ outTypes.clear();
+ outTypes.reserve(types.size());
+
+ qreal lastX = 0;
+ qreal lastY = 0; // or else used uninitialized
+ for (int i = 0; i < types.size(); ++i) {
+ if (i > 0 && types[i] != QPainterPath::MoveToElement) {
+ qreal x = points[i * 2], y = points[i * 2 + 1];
+ clipSegmentToRect(lastX, lastY, x, y, clipRect, outPoints, outTypes);
+ }
+
+ lastX = points[i * 2];
+ lastY = points[i * 2 + 1];
+ }
+}
+
////////////////////////////////////////////////////////////////////////////
/*!
@@ -526,9 +646,24 @@ void QGeoMapPolylineGeometry::updateScreenPoints(const QGeoMap &map,
return;
}
- // The geometry has already been clipped against the visible region projection in wrapped mercator space.
- QVector<qreal> points = srcPoints_;
- QVector<QPainterPath::ElementType> types = srcPointTypes_;
+ // Create the viewport rect in the same coordinate system
+ // as the actual points
+ QRectF viewport(0, 0, map.viewportWidth(), map.viewportHeight());
+ viewport.adjust(-strokeWidth, -strokeWidth, strokeWidth, strokeWidth);
+ viewport.translate(-1 * origin);
+
+ QVector<qreal> points;
+ QVector<QPainterPath::ElementType> types;
+
+ if (clipToViewport_) {
+ // Although the geometry has already been clipped against the visible region in wrapped mercator space.
+ // This is currently still needed to prevent a number of artifacts deriving from QTriangulatingStroker processing
+ // very large lines (that is, polylines that span many pixels in screen space)
+ clipPathToRect(srcPoints_, srcPointTypes_, viewport, points, types);
+ } else {
+ points = srcPoints_;
+ types = srcPointTypes_;
+ }
QVectorPath vp(points.data(), types.size(), types.data());
QTriangulatingStroker ts;
@@ -998,6 +1133,22 @@ const QGeoShape &QDeclarativePolylineMapItem::geoShape() const
return geopath_;
}
+void QDeclarativePolylineMapItem::setGeoShape(const QGeoShape &shape)
+{
+ if (shape == geopath_)
+ return;
+
+ const QGeoPath geopath(shape); // if shape isn't a path, path will be created as a default-constructed path
+ const bool pathHasChanged = geopath.path() != geopath_.path();
+ geopath_ = geopath;
+
+ regenerateCache();
+ geometry_.setPreserveGeometry(true, geopath_.boundingGeoRectangle().topLeft());
+ markSourceDirtyAndUpdate();
+ if (pathHasChanged)
+ emit pathChanged();
+}
+
QGeoMap::ItemType QDeclarativePolylineMapItem::itemType() const
{
return QGeoMap::MapPolyline;
diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem_p.h b/src/location/declarativemaps/qdeclarativepolylinemapitem_p.h
index 225f21d9..1105bb13 100644
--- a/src/location/declarativemaps/qdeclarativepolylinemapitem_p.h
+++ b/src/location/declarativemaps/qdeclarativepolylinemapitem_p.h
@@ -48,6 +48,7 @@
// We mean it.
//
+#include <QtLocation/private/qlocationglobal_p.h>
#include <QtLocation/private/qdeclarativegeomapitembase_p.h>
#include <QtLocation/private/qgeomapitemgeometry_p.h>
@@ -110,10 +111,15 @@ public:
const QList<QList<QDoubleVector2D> > &clippedPaths,
const QDoubleVector2D &leftBoundWrapped);
-private:
+public:
QVector<qreal> srcPoints_;
QVector<QPainterPath::ElementType> srcPointTypes_;
+#ifdef QT_LOCATION_DEBUG
+ QList<QDoubleVector2D> m_wrappedPath;
+ QList<QList<QDoubleVector2D>> m_clippedPaths;
+#endif
+
friend class QDeclarativeCircleMapItem;
friend class QDeclarativePolygonMapItem;
friend class QDeclarativeRectangleMapItem;
@@ -149,6 +155,7 @@ public:
bool contains(const QPointF &point) const override;
const QGeoShape &geoShape() const override;
+ void setGeoShape(const QGeoShape &shape) override;
QGeoMap::ItemType itemType() const override;
QDeclarativeMapLineProperties *line();
@@ -170,6 +177,9 @@ private:
void regenerateCache();
void updateCache();
+#ifdef QT_LOCATION_DEBUG
+public:
+#endif
QGeoPath geopath_;
QList<QDoubleVector2D> geopathProjected_;
QDeclarativeMapLineProperties line_;
diff --git a/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp b/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp
index e90c0596..ba67ecad 100644
--- a/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp
@@ -352,6 +352,24 @@ const QGeoShape &QDeclarativeRectangleMapItem::geoShape() const
return rectangle_;
}
+void QDeclarativeRectangleMapItem::setGeoShape(const QGeoShape &shape)
+{
+ if (shape == rectangle_)
+ return;
+
+ const QGeoRectangle rectangle = rectangle_.boundingGeoRectangle();
+ const bool tlHasChanged = rectangle.topLeft() != rectangle_.topLeft();
+ const bool brHasChanged = rectangle.bottomRight() != rectangle_.bottomRight();
+ rectangle_ = rectangle;
+
+ updatePath();
+ markSourceDirtyAndUpdate();
+ if (tlHasChanged)
+ emit topLeftChanged(rectangle_.topLeft());
+ if (brHasChanged)
+ emit bottomRightChanged(rectangle_.bottomRight());
+}
+
QGeoMap::ItemType QDeclarativeRectangleMapItem::itemType() const
{
return QGeoMap::MapRectangle;
diff --git a/src/location/declarativemaps/qdeclarativerectanglemapitem_p.h b/src/location/declarativemaps/qdeclarativerectanglemapitem_p.h
index c475bf7f..e2ac2974 100644
--- a/src/location/declarativemaps/qdeclarativerectanglemapitem_p.h
+++ b/src/location/declarativemaps/qdeclarativerectanglemapitem_p.h
@@ -90,6 +90,7 @@ public:
bool contains(const QPointF &point) const override;
const QGeoShape &geoShape() const override;
+ void setGeoShape(const QGeoShape &shape) override;
QGeoMap::ItemType itemType() const override;
Q_SIGNALS:
diff --git a/src/location/declarativemaps/qquickgeomapgesturearea.cpp b/src/location/declarativemaps/qquickgeomapgesturearea.cpp
index 576aeeea..88a766f5 100644
--- a/src/location/declarativemaps/qquickgeomapgesturearea.cpp
+++ b/src/location/declarativemaps/qquickgeomapgesturearea.cpp
@@ -35,7 +35,7 @@
****************************************************************************/
#include "qquickgeomapgesturearea_p.h"
-#include "qquickgeocoordinateanimation_p.h"
+#include <QtPositioningQuick/private/qquickgeocoordinateanimation_p.h>
#include "qdeclarativegeomap_p.h"
#include "error_messages_p.h"
diff --git a/src/location/declarativeplaces/qdeclarativesearchmodelbase.cpp b/src/location/declarativeplaces/qdeclarativesearchmodelbase.cpp
index 92e298d3..b9f782cf 100644
--- a/src/location/declarativeplaces/qdeclarativesearchmodelbase.cpp
+++ b/src/location/declarativeplaces/qdeclarativesearchmodelbase.cpp
@@ -216,6 +216,7 @@ void QDeclarativeSearchModelBase::update()
m_reply->setParent(this);
connect(m_reply, SIGNAL(finished()), this, SLOT(queryFinished()));
+ connect(m_reply, SIGNAL(contentUpdated()), this, SLOT(onContentUpdated()));
}
/*!
@@ -333,6 +334,11 @@ void QDeclarativeSearchModelBase::initializePlugin(QDeclarativeGeoServiceProvide
endResetModel();
}
+void QDeclarativeSearchModelBase::onContentUpdated()
+{
+
+}
+
/*!
\internal
*/
diff --git a/src/location/declarativeplaces/qdeclarativesearchmodelbase_p.h b/src/location/declarativeplaces/qdeclarativesearchmodelbase_p.h
index 2bf1aab5..b85137a6 100644
--- a/src/location/declarativeplaces/qdeclarativesearchmodelbase_p.h
+++ b/src/location/declarativeplaces/qdeclarativesearchmodelbase_p.h
@@ -133,6 +133,7 @@ protected:
protected Q_SLOTS:
virtual void queryFinished() = 0;
+ virtual void onContentUpdated();
private Q_SLOTS:
void pluginNameChanged();
diff --git a/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
index ed99da1c..4cfd26dd 100644
--- a/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
+++ b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
@@ -47,6 +47,7 @@
#include <QtLocation/QPlaceMatchReply>
#include <QtLocation/QPlaceResult>
#include <QtLocation/QPlaceProposedSearchResult>
+#include <QtLocation/private/qplacesearchrequest_p.h>
QT_BEGIN_NAMESPACE
@@ -260,6 +261,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \qmlproperty bool PlaceSearchModel::incremental
+
+ This property controls how paging will affect the PlaceSearchModel.
+ If true, calling \l previousPage or \l nextPage will not reset the model,
+ but new results will instead be appended to the model.
+ Default is false.
+
+ \since QtLocation 5.12
+*/
+
+
+/*!
\qmlmethod void PlaceSearchModel::update()
Updates the model based on the provided query parameters. The model will be populated with a
@@ -733,11 +746,15 @@ void QDeclarativeSearchResultModel::queryFinished()
return;
QPlaceReply *reply = m_reply;
m_reply = 0;
+ reply->deleteLater();
+
+ if (!m_incremental)
+ m_pages.clear();
+
if (reply->error() != QPlaceReply::NoError) {
m_resultsBuffer.clear();
updateLayout();
setStatus(Error, reply->errorString());
- reply->deleteLater();
return;
}
@@ -745,12 +762,18 @@ void QDeclarativeSearchResultModel::queryFinished()
QPlaceSearchReply *searchReply = qobject_cast<QPlaceSearchReply *>(reply);
Q_ASSERT(searchReply);
+ const QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(searchReply->request());
+ if (!rpimpl->related || !m_incremental)
+ m_pages.clear();
m_resultsBuffer = searchReply->results();
+ bool alreadyLoaded = false;
+ if (m_pages.contains(rpimpl->page) && m_resultsBuffer == m_pages.value(rpimpl->page))
+ alreadyLoaded = true;
+ m_pages.insert(rpimpl->page, m_resultsBuffer);
setPreviousPageRequest(searchReply->previousPageRequest());
setNextPageRequest(searchReply->nextPageRequest());
- reply->deleteLater();
-
+ // Performing favorite matching only upon finished()
if (!m_favoritesPlugin) {
updateLayout();
setStatus(Ready);
@@ -772,7 +795,6 @@ void QDeclarativeSearchResultModel::queryFinished()
QPlaceMatchRequest request;
if (m_matchParameters.isEmpty()) {
if (!m_plugin) {
- reply->deleteLater();
setStatus(Error, QStringLiteral("Plugin not assigned"));
return;
}
@@ -785,18 +807,55 @@ void QDeclarativeSearchResultModel::queryFinished()
}
request.setResults(m_resultsBuffer);
+ if (alreadyLoaded)
+ m_resultsBuffer.clear();
m_reply = favoritesManager->matchingPlaces(request);
connect(m_reply, SIGNAL(finished()), this, SLOT(queryFinished()));
+ connect(m_reply, SIGNAL(contentUpdated()), this, SLOT(onContentUpdated()));
}
} else if (reply->type() == QPlaceReply::MatchReply) {
QPlaceMatchReply *matchReply = qobject_cast<QPlaceMatchReply *>(reply);
Q_ASSERT(matchReply);
updateLayout(matchReply->places());
setStatus(Ready);
- reply->deleteLater();
} else {
setStatus(Error, QStringLiteral("Unknown reply type"));
- reply->deleteLater();
+ }
+}
+
+void QDeclarativeSearchResultModel::onContentUpdated()
+{
+ if (!m_reply)
+ return;
+
+ QPlaceReply *reply = m_reply; // not finished, don't delete.
+
+ if (!m_incremental)
+ m_pages.clear();
+
+ if (reply->error() != QPlaceReply::NoError) {
+ m_resultsBuffer.clear();
+ updateLayout();
+ setStatus(Error, reply->errorString());
+ return;
+ }
+
+ if (reply->type() == QPlaceReply::SearchReply) {
+ QPlaceSearchReply *searchReply = qobject_cast<QPlaceSearchReply *>(reply);
+ Q_ASSERT(searchReply);
+
+ const QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(searchReply->request());
+ if (!rpimpl->related || !m_incremental)
+ m_pages.clear();
+ m_resultsBuffer = searchReply->results();
+ if (!(m_pages.contains(rpimpl->page) && m_resultsBuffer == m_pages.value(rpimpl->page))) {
+ m_pages.insert(rpimpl->page, m_resultsBuffer);
+ updateLayout();
+ }
+ } else if (reply->type() == QPlaceReply::MatchReply) {
+ // ToDo: handle incremental match replies
+ } else {
+ setStatus(Error, QStringLiteral("Unknown reply type"));
}
}
@@ -823,14 +882,24 @@ void QDeclarativeSearchResultModel::queryFinished()
*/
void QDeclarativeSearchResultModel::updateLayout(const QList<QPlace> &favoritePlaces)
{
- int oldRowCount = rowCount();
+ const int oldRowCount = rowCount();
+ int start = 0;
- beginResetModel();
- clearData(true);
- m_results = m_resultsBuffer;
- m_resultsBuffer.clear();
+ if (m_incremental) {
+ if (!m_resultsBuffer.size())
+ return;
+
+ beginInsertRows(QModelIndex(), oldRowCount , oldRowCount + m_resultsBuffer.size() - 1);
+ m_results = resultsFromPages();
+ start = oldRowCount;
+ } else {
+ beginResetModel();
+ clearData(true);
+ m_results = m_resultsBuffer;
+ }
- for (int i = 0; i < m_results.count(); ++i) {
+ m_resultsBuffer.clear();
+ for (int i = start; i < m_results.count(); ++i) {
const QPlaceSearchResult &result = m_results.at(i);
if (result.type() == QPlaceSearchResult::PlaceResult) {
@@ -851,7 +920,10 @@ void QDeclarativeSearchResultModel::updateLayout(const QList<QPlace> &favoritePl
m_icons.append(icon);
}
- endResetModel();
+ if (m_incremental)
+ endInsertRows();
+ else
+ endResetModel();
if (m_results.count() != oldRowCount)
emit rowCountChanged();
}
@@ -882,11 +954,39 @@ void QDeclarativeSearchResultModel::placeRemoved(const QString &placeId)
delete m_places.at(row);
m_places.removeAt(row);
m_results.removeAt(row);
+ removePageRow(row);
endRemoveRows();
emit rowCountChanged();
}
+QList<QPlaceSearchResult> QDeclarativeSearchResultModel::resultsFromPages() const
+{
+ QList<QPlaceSearchResult> res;
+ QMapIterator<int, QList<QPlaceSearchResult>> i(m_pages);
+ while (i.hasNext()) {
+ i.next();
+ res.append(i.value());
+ }
+ return res;
+}
+
+void QDeclarativeSearchResultModel::removePageRow(int row)
+{
+ QMapIterator<int, QList<QPlaceSearchResult>> i(m_pages);
+ int scanned = 0;
+ while (i.hasNext()) {
+ i.next();
+ QList<QPlaceSearchResult> page = i.value();
+ scanned += page.size();
+ if (row >= scanned)
+ continue;
+ page.removeAt(row - scanned + page.size());
+ m_pages.insert(i.key(), page);
+ return;
+ }
+}
+
/*!
\internal
*/
diff --git a/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h b/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h
index 77526fd0..40c2e47c 100644
--- a/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h
+++ b/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h
@@ -72,6 +72,8 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeSearchResultModel : public QDeclarat
Q_PROPERTY(QDeclarativeGeoServiceProvider *favoritesPlugin READ favoritesPlugin WRITE setFavoritesPlugin NOTIFY favoritesPluginChanged)
Q_PROPERTY(QVariantMap favoritesMatchParameters READ favoritesMatchParameters WRITE setFavoritesMatchParameters NOTIFY favoritesMatchParametersChanged)
+ Q_PROPERTY(bool incremental MEMBER m_incremental NOTIFY incrementalChanged REVISION 12)
+
Q_ENUMS(SearchResultType RelevanceHint)
public:
@@ -115,12 +117,12 @@ public:
QVariantMap favoritesMatchParameters() const;
void setFavoritesMatchParameters(const QVariantMap &parameters);
- int rowCount(const QModelIndex &parent = QModelIndex()) const;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- virtual void clearData(bool suppressSignal = false);
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ virtual void clearData(bool suppressSignal = false) override;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
Q_INVOKABLE QVariant data(int index, const QString &roleName) const;
- QHash<int, QByteArray> roleNames() const;
+ QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void updateWith(int proposedSearchIndex);
@@ -137,13 +139,15 @@ Q_SIGNALS:
void favoritesPluginChanged();
void favoritesMatchParametersChanged();
void dataChanged();
+ void incrementalChanged();
protected:
- QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request);
- virtual void initializePlugin(QDeclarativeGeoServiceProvider *plugin);
+ QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request) override;
+ virtual void initializePlugin(QDeclarativeGeoServiceProvider *plugin) override;
protected Q_SLOTS:
- virtual void queryFinished();
+ virtual void queryFinished() override;
+ virtual void onContentUpdated() override;
private Q_SLOTS:
void updateLayout(const QList<QPlace> &favoritePlaces = QList<QPlace>());
@@ -162,9 +166,13 @@ private:
};
int getRow(const QString &placeId) const;
+ QList<QPlaceSearchResult> resultsFromPages() const;
+ void removePageRow(int row);
+
QList<QDeclarativeCategory *> m_categories;
QLocation::VisibilityScope m_visibilityScope;
+ QMap<int, QList<QPlaceSearchResult>> m_pages;
QList<QPlaceSearchResult> m_results;
QList<QPlaceSearchResult> m_resultsBuffer;
QList<QDeclarativePlace *> m_places;
@@ -172,6 +180,7 @@ private:
QDeclarativeGeoServiceProvider *m_favoritesPlugin;
QVariantMap m_matchParameters;
+ bool m_incremental = false;
};
QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp b/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
index b7c6e319..3bc45c4f 100644
--- a/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
+++ b/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
@@ -39,6 +39,7 @@
#include "qdeclarativeplaceicon_p.h"
#include "qgeoserviceprovider.h"
#include "error_messages_p.h"
+#include <QtCore/private/qobject_p.h>
#include <QCoreApplication>
#include <QtQml/QQmlInfo>
@@ -121,6 +122,15 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \qmlmethod void QtLocation::CategoryModel::update()
+ \internal
+
+ Updates the model.
+
+ \note The CategoryModel auto updates automatically when needed. Calling this method explicitly is normally not necessary.
+*/
+
+/*!
\internal
\enum QDeclarativeSupportedCategoriesModel::Roles
*/
@@ -143,6 +153,8 @@ QDeclarativeSupportedCategoriesModel::~QDeclarativeSupportedCategoriesModel()
void QDeclarativeSupportedCategoriesModel::componentComplete()
{
m_complete = true;
+ if (m_plugin) // do not try to load or change status when trying to update in componentComplete() if the plugin hasn't been set yet even once.
+ update();
}
/*!
@@ -255,6 +267,7 @@ void QDeclarativeSupportedCategoriesModel::setPlugin(QDeclarativeGeoServiceProvi
//disconnect the manager of the old plugin if we have one
if (m_plugin) {
+ disconnect(m_plugin, nullptr, this, nullptr);
QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
if (serviceProvider) {
QPlaceManager *placeManager = serviceProvider->placeManager();
@@ -273,14 +286,17 @@ void QDeclarativeSupportedCategoriesModel::setPlugin(QDeclarativeGeoServiceProvi
m_plugin = plugin;
- // handle plugin name changes -> update categories
+ // handle plugin attached changes -> update categories
if (m_plugin) {
- connect(m_plugin, SIGNAL(nameChanged(QString)), this, SLOT(connectNotificationSignals()));
- connect(m_plugin, SIGNAL(nameChanged(QString)), this, SLOT(update()));
+ if (m_plugin->isAttached()) {
+ connectNotificationSignals();
+ update();
+ } else {
+ connect(m_plugin, &QDeclarativeGeoServiceProvider::attached, this, &QDeclarativeSupportedCategoriesModel::update);
+ connect(m_plugin, &QDeclarativeGeoServiceProvider::attached, this, &QDeclarativeSupportedCategoriesModel::connectNotificationSignals);
+ }
}
- connectNotificationSignals();
-
if (m_complete)
emit pluginChanged();
}
@@ -499,6 +515,9 @@ void QDeclarativeSupportedCategoriesModel::connectNotificationSignals()
*/
void QDeclarativeSupportedCategoriesModel::update()
{
+ if (!m_complete)
+ return;
+
if (m_response)
return;
diff --git a/src/location/doc/src/plugins/esri.qdoc b/src/location/doc/src/plugins/esri.qdoc
index 2707ca5d..dc28c906 100644
--- a/src/location/doc/src/plugins/esri.qdoc
+++ b/src/location/doc/src/plugins/esri.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -42,18 +42,14 @@ Data is provided by \l {http://www.esri.com/data/find-data}{many different conte
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
+You can use the services provided by Esri's ArcGIS Platform by subscribing to the ArcGIS Developer Program, at no charge. See the "Essentials" plan details here: {https://developers.arcgis.com/pricing/}{ArcGIS Developer Program Pricing}.
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 can request up to one million maps per month.
+ \li 50 credits are included with the Developer subscription. The costs are 40 credits for 1000 geocodes, and 0.5 credits per route generated. Place searches are free.
\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
@@ -70,7 +66,7 @@ gives applications full access to the ArcGIS platform.
\li Description
\row
\li esri.token
- \li Security token for using routing services only. Mapping and geocoding services do not require a token.
+ \li Security token for using routing services only. Mapping, geocoding and place searches services do not require a token.
\endtable
To use the routing services hosted on ArcGIS Online with the Esri plugin, a token is required.
diff --git a/src/location/doc/src/plugins/mapboxgl.qdoc b/src/location/doc/src/plugins/mapboxgl.qdoc
index 51b49f93..b1d721bf 100644
--- a/src/location/doc/src/plugins/mapboxgl.qdoc
+++ b/src/location/doc/src/plugins/mapboxgl.qdoc
@@ -88,6 +88,11 @@ The following table lists optional parameters that can be passed to the Mapbox p
\l{https://www.mapbox.com/tos}{Terms of Services} and must not be used in production. This property has
no effect on styles hosted outside the Mapbox servers.
\row
+ \li mapboxgl.china
+ \li Use Mapbox China API base URLs and styles.
+ Please notice that Mapbox China requires a specific access token. Contact \l
+ {https://www.mapbox.com/contact/sales/} {Mapbox sales} for more information.
+\row
\li mapboxgl.mapping.additional_style_urls
\li Additional, comma separated, Mapbox \l{https://www.mapbox.com/help/define-style-url}
{style URLs} to be added to the available style URLs. Additional styles will be prepended to
diff --git a/src/location/doc/src/qtlocation-qml.qdoc b/src/location/doc/src/qtlocation-qml.qdoc
index 38f43ef1..90f19c5a 100644
--- a/src/location/doc/src/qtlocation-qml.qdoc
+++ b/src/location/doc/src/qtlocation-qml.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -26,83 +26,103 @@
****************************************************************************/
/*!
- \qmlmodule QtLocation 5.11
+ \qmlmodule QtLocation \QtVer
\title Qt Location QML Types
\ingroup qmlmodules
- \brief Provides QML types for mapping and location information
+ \brief Provides QML types for mapping and location information.
-\section1 Overview
+ \section1 Overview
-Provided that a position has been obtained, this module can add a
-\l{QtLocation::Map}{Map} with Places of Interest (POI) and
-\l{QtLocation::Place}{Places}. The user can be made aware of nearby features
-and related information, displayed graphically. Features on the \l Map can be
-places of business, entertainment, and so on. They may include paths, roads,
-or forms of transport, enabling navigation optimization and assistance.
+ Provided that a position has been obtained, the Qt Location module
+ can add a \l{QtLocation::}{Map} with Places of Interest (POI) and
+ \l{QtLocation::Place}{Places}. The user can be made aware of nearby
+ features and related information, displayed on the map. These features
+ can be places of business, entertainment, and so on. They may include
+ paths, roads, or forms of transport, enabling navigation optimization
+ and assistance.
-To perform navigation we need \l {Route}s from start to destination. These routes
-are made up of segments, where each \l {QtLocation::RouteSegment}{RouteSegment}
-can be considered a navigation subtask: drive 100 meters, turn left. The beginning and
-end of each segment is a \e waypoint, that is, one part of our journey.
+ To perform navigation we need \l {Route}s from start to destination.
+ These routes are made up of segments, where each \l {QtLocation::}
+ {RouteSegment} can be considered a navigation subtask; for example,
+ "drive 100 meters", or "turn left". The beginning and end of each
+ segment is a \e waypoint, that is, one part of the journey.
-A typical use case for the API is a user looking for a particular type of
-place, say a restaurant. The user could enter a search string into the map
-application and respond to a list or display of results for restaurants
-"near" the device. The application could then be used to navigate to the
-restaurant using an optimized route that is aware of features in the
-environment that can help or hinder the journey. The navigation then
-proceeds with the user's progress monitored by means of the current
-\l Location. In the context of this API the map application would be aware
-of the location and size of various places and the location of the user.
-Plugins would supply the data required by the application to determine routes
-and navigation instructions. The \l Place types would hold information about the
-destination and surrounding objects including displayable representations.
-The \l Map type would enable this information to be displayed, panned,
-zoomed and so on. The \l Route would be determined by a plugin with each
-\l RouteSegment holding the navigation instructions guided by the updated
-current \l Location.
+ A typical use case for the API is a user looking for a particular type of
+ place, such as a restaurant; the user enters a search string into the map
+ application and is presented with a list of results for restaurants
+ "near" the device. The application can then be used to navigate to the
+ chosen destination using a route that is optimized according to features
+ in the environment that may help or hinder the journey. The navigation then
+ proceeds with the user's progress monitored by means of the current
+ location.
-\l {Plugin}s are a means of specifying which location-based service to use. For
-example, a plugin may allow connection to a provider's service that provides
-geocoding and routing information, which can be consumed by the application.
-There may be various GeoServices plugins for various tasks with some plugins
-providing more than one service. One QML \l Plugin must be created for each
-required GeoService plugin. Plugins are required for maps, routing and geocoding,
-and places, however the default plugin handles all four of these services. A plugin may
-require online access or may support on-board maps and data.
+ In short, the main QML types and their roles are as follows:
-\note Plugins may not provide features such as paging or relevance hints.
+ \list
-The following links provide more detailed information about maps and places:
+ \li The \l [QML] Place instances hold information about the
+ destination and surrounding objects, including displayable
+ representations.
-\table
- \row
- \li \l {Maps and Navigation (QML)}{Maps and Navigation}
- \li Displaying maps and finding routes.
- \row
- \li \l {QML PLaces API} {Places}
- \li Searching for and managing points of interest.
-\endtable
+ \li The \l [QML] Map enables the information contained in
+ \l [QML] {Place} objects to be displayed, panned, zoomed,
+ and so on.
-\section1 Common QML Types
+ \li The \l [QML] Route is be determined by a \e plugin, with each
+ \l [QML] RouteSegment holding the navigation instructions,
+ guided by the continuously updated current \l [QML] Location.
-\annotatedlist qml-QtLocation5-common
+ \endlist
-\section1 Maps QML Types
+ \section2 Plugins
-\annotatedlist qml-QtLocation5-maps
+ \l {Plugin}s supply the data required to calculate routes and navigation
+ instructions, and they are typically tied to a specific location-based
+ service. For example, a plugin may allow connecting to a service that
+ provides geocoding and routing information, which can be consumed by the
+ application.
-\section1 Navigation and Routing QML Types
+ There may be various GeoServices plugins for various tasks, with some
+ plugins providing more than one service. One QML \l Plugin instance must
+ be created for each GeoService plugin. Plugins are required for routing
+ and geocoding, maps, and places, however the default plugin handles all
+ four of these services. A plugin may require online access or it may
+ support on-board maps and data.
-\annotatedlist qml-QtLocation5-routing
+ \note Plugins may not provide features such as paging or relevance hints.
-\section1 Geocoding QML Types
+ \section2 Related Information
-\annotatedlist qml-QtLocation5-geocoding
+ The following links provide more information about maps and places:
-\section1 Places QML Types
+ \table
+ \row
+ \li \l {Maps and Navigation (QML)}{Maps and Navigation}
+ \li Displaying maps and finding routes
+ \row
+ \li \l {QML Places API} {Places}
+ \li Searching for and managing points of interest
+ \endtable
-\annotatedlist qml-QtLocation5-places
+ \section1 Common QML Types
-\section1 Alphabetical Listing of All QML Types
+ \annotatedlist qml-QtLocation5-common
+
+ \section1 Maps QML Types
+
+ \annotatedlist qml-QtLocation5-maps
+
+ \section1 Navigation and Routing QML Types
+
+ \annotatedlist qml-QtLocation5-routing
+
+ \section1 Geocoding QML Types
+
+ \annotatedlist qml-QtLocation5-geocoding
+
+ \section1 Places QML Types
+
+ \annotatedlist qml-QtLocation5-places
+
+ \section1 Alphabetical Listing of All QML Types
*/
diff --git a/src/location/doc/src/qtlocation.qdoc b/src/location/doc/src/qtlocation.qdoc
index 1f27a14a..059d03f2 100644
--- a/src/location/doc/src/qtlocation.qdoc
+++ b/src/location/doc/src/qtlocation.qdoc
@@ -45,12 +45,16 @@
Include the appropriate header in your C++ code. For example,
applications using routes can include:
- \code #include <QGeoRoute> \endcode
+ \code
+ #include <QGeoRoute>
+ \endcode
Add the \e location keyword in the project file to link against the
Qt Location library:
- \code QT += location \endcode
+ \badcode
+ QT += location
+ \endcode
See more in the \l{Qt Location}{Qt Location Overview}.
@@ -83,10 +87,10 @@ The Qt Location API enables you to:
To load the Qt Location module, add the following statement to your .qml files
-\code
- import QtPositioning 5.11
- import QtLocation 5.11
-\endcode
+\qml \QtVer
+import QtPositioning \1
+import QtLocation \1
+\endqml
The QtLocation QML module depends on the QtPositioning QML module.
Therefore every QML application that imports the QtLocation QML module must always
@@ -95,11 +99,15 @@ import the QtPositioning module as well.
For C++ projects include the header appropriate for the current use case,
for example applications using routes may use
-\code #include <QGeoRoute> \endcode
+\code
+#include <QGeoRoute>
+\endcode
The .pro file should have the \e location keyword added
-\code QT += location \endcode
+\code
+QT += location
+\endcode
\section2 Submodules
diff --git a/src/location/labs/qdeclarativenavigator.cpp b/src/location/labs/qdeclarativenavigator.cpp
index 7dba341e..0bf5035f 100644
--- a/src/location/labs/qdeclarativenavigator.cpp
+++ b/src/location/labs/qdeclarativenavigator.cpp
@@ -175,7 +175,7 @@ QT_BEGIN_NAMESPACE
*/
QDeclarativeNavigatorPrivate::QDeclarativeNavigatorPrivate(QParameterizableObject *q_)
- : q(q_)
+ : q(q_), m_params(new QDeclarativeNavigatorParams)
{
}
@@ -203,7 +203,8 @@ void QDeclarativeNavigator::componentComplete()
{
d_ptr->m_completed = true;
// Children have been completed
- d_ptr->m_parameters = quickChildren<QGeoMapParameter>();
+ for (auto param : quickChildren<QGeoMapParameter>())
+ d_ptr->m_params->m_parameters.push_back(param);
if (d_ptr->m_plugin && d_ptr->m_plugin->isAttached())
pluginReady();
}
@@ -215,12 +216,12 @@ QDeclarativeGeoServiceProvider *QDeclarativeNavigator::plugin() const
void QDeclarativeNavigator::setMap(QDeclarativeGeoMap *map)
{
- if (d_ptr->m_map || !map) // set once prop
+ if (d_ptr->m_params->m_map || !map) // set once prop
return;
- d_ptr->m_map = map;
+ d_ptr->m_params->m_map = map;
QDeclarativeNavigatorPrivate *dptr = d_ptr.data();
- connect(map, &QObject::destroyed,
+ connect(map, &QObject::destroyed, this,
[this, dptr]() {
this->mapChanged();
dptr->updateReadyState();
@@ -231,21 +232,21 @@ void QDeclarativeNavigator::setMap(QDeclarativeGeoMap *map)
QDeclarativeGeoMap *QDeclarativeNavigator::map() const
{
- return d_ptr->m_map;
+ return d_ptr->m_params->m_map;
}
void QDeclarativeNavigator::setRoute(QDeclarativeGeoRoute *route)
{
- if (d_ptr->m_route == route) // This isn't set-once
+ if (d_ptr->m_params->m_route == route) // This isn't set-once
return;
- const bool isReady = d_ptr->m_navigationManager && d_ptr->m_navigationManager->ready();
+ const bool isReady = d_ptr->m_navigator && d_ptr->m_navigator->ready();
const bool isActive = active();
if (isReady && isActive)
setActive(false); // Stop current session
- d_ptr->m_route = route;
- d_ptr->m_geoRoute = route ? route->route() : QGeoRoute();
+ d_ptr->m_params->m_route = route;
+ d_ptr->m_params->m_geoRoute = route ? route->route() : QGeoRoute();
if (route) {
connect(route, &QObject::destroyed,
[this]() {
@@ -260,15 +261,15 @@ void QDeclarativeNavigator::setRoute(QDeclarativeGeoRoute *route)
QDeclarativeGeoRoute *QDeclarativeNavigator::route() const
{
- return d_ptr->m_route;
+ return d_ptr->m_params->m_route;
}
void QDeclarativeNavigator::setPositionSource(QDeclarativePositionSource *positionSource)
{
- if (d_ptr->m_positionSource || !positionSource) // set once prop
+ if (d_ptr->m_params->m_positionSource || !positionSource) // set once prop
return;
- d_ptr->m_positionSource = positionSource;
+ d_ptr->m_params->m_positionSource = positionSource;
QDeclarativeNavigatorPrivate *dptr = d_ptr.data();
QObject::connect(positionSource, &QObject::destroyed,
[this, dptr]() {
@@ -282,46 +283,42 @@ void QDeclarativeNavigator::setPositionSource(QDeclarativePositionSource *positi
QDeclarativePositionSource *QDeclarativeNavigator::positionSource() const
{
- return d_ptr->m_positionSource;
+ return d_ptr->m_params->m_positionSource;
}
-QNavigationManager *QDeclarativeNavigator::navigationManager() const
-{
- return d_ptr->m_navigationManager;
-}
bool QDeclarativeNavigator::navigatorReady() const
{
- if (d_ptr->m_navigationManager)
- return d_ptr->m_navigationManager->ready();
+ if (d_ptr->m_navigator)
+ return d_ptr->m_navigator->ready();
return d_ptr->m_ready;
}
bool QDeclarativeNavigator::trackPositionSource() const
{
- return d_ptr->m_trackPositionSource;
+ return d_ptr->m_params->m_trackPositionSource;
}
void QDeclarativeNavigator::setTrackPositionSource(bool trackPositionSource)
{
- if (trackPositionSource == d_ptr->m_trackPositionSource)
+ if (trackPositionSource == d_ptr->m_params->m_trackPositionSource)
return;
- d_ptr->m_trackPositionSource = trackPositionSource;
+ d_ptr->m_params->m_trackPositionSource = trackPositionSource;
emit trackPositionSourceChanged(trackPositionSource);
}
QDeclarativeGeoRoute *QDeclarativeNavigator::currentRoute() const
{
- if (!d_ptr->m_ready || !d_ptr->m_navigationManager->active())
- return d_ptr->m_route.data();
+ if (!d_ptr->m_ready || !d_ptr->m_navigator->active())
+ return d_ptr->m_params->m_route.data();
return d_ptr->m_currentRoute.data();
}
int QDeclarativeNavigator::currentSegment() const
{
- if (!d_ptr->m_ready || !d_ptr->m_navigationManager->active())
+ if (!d_ptr->m_ready || !d_ptr->m_navigator->active())
return 0;
return d_ptr->m_currentSegment;
}
@@ -369,8 +366,8 @@ void QDeclarativeNavigator::start()
return;
}
- if (!d_ptr->m_navigationManager->active())
- d_ptr->m_active = d_ptr->m_navigationManager->start();
+ if (!d_ptr->m_navigator->active())
+ d_ptr->m_active = d_ptr->m_navigator->start();
}
void QDeclarativeNavigator::stop()
@@ -380,8 +377,8 @@ void QDeclarativeNavigator::stop()
return;
}
- if (d_ptr->m_navigationManager->active())
- d_ptr->m_active = d_ptr->m_navigationManager->stop();
+ if (d_ptr->m_navigator->active())
+ d_ptr->m_active = d_ptr->m_navigator->stop();
}
void QDeclarativeNavigator::pluginReady()
@@ -397,23 +394,27 @@ void QDeclarativeNavigator::pluginReady()
bool QDeclarativeNavigator::ensureEngine()
{
- if (d_ptr->m_navigationManager)
+ if (d_ptr->m_navigator)
return true;
if (!d_ptr->m_completed || !d_ptr->m_plugin->isAttached())
return false;
- d_ptr->m_navigationManager = d_ptr->m_plugin->sharedGeoServiceProvider()->navigationManager();
- if (d_ptr->m_navigationManager) {
- d_ptr->m_navigationManager->setNavigator(d_ptr.data());
- d_ptr->m_navigationManager->setParameters(d_ptr->m_parameters);
- connect(d_ptr->m_navigationManager, &QNavigationManager::waypointReached, this, &QDeclarativeNavigator::waypointReached);
- connect(d_ptr->m_navigationManager, &QNavigationManager::destinationReached, this, &QDeclarativeNavigator::destinationReached);
- connect(d_ptr->m_navigationManager, &QNavigationManager::currentRouteChanged, this, &QDeclarativeNavigator::onCurrentRouteChanged);
- connect(d_ptr->m_navigationManager, &QNavigationManager::currentSegmentChanged, this, &QDeclarativeNavigator::onCurrentSegmentChanged);
- connect(d_ptr->m_navigationManager, &QNavigationManager::activeChanged, this, [this](bool active){
+ auto manager = d_ptr->m_plugin->sharedGeoServiceProvider()->navigationManager();
+ if (manager) {
+ d_ptr->m_navigator.reset(manager->createNavigator(d_ptr->m_params));
+ if (!d_ptr->m_navigator)
+ return false;
+ d_ptr->m_navigator->setLocale(manager->locale());
+ d_ptr->m_navigator->setMeasurementSystem(manager->measurementSystem());
+ connect(d_ptr->m_navigator.get(), &QAbstractNavigator::waypointReached, this, &QDeclarativeNavigator::waypointReached);
+ connect(d_ptr->m_navigator.get(), &QAbstractNavigator::destinationReached, this, &QDeclarativeNavigator::destinationReached);
+ connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentRouteChanged, this, &QDeclarativeNavigator::onCurrentRouteChanged);
+ connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentSegmentChanged, this, &QDeclarativeNavigator::onCurrentSegmentChanged);
+ connect(d_ptr->m_navigator.get(), &QAbstractNavigator::activeChanged, this, [this](bool active){
d_ptr->m_active = active;
emit activeChanged(active);
});
+ connect(this, &QDeclarativeNavigator::trackPositionSourceChanged, d_ptr->m_navigator.get(), &QAbstractNavigator::setTrackPosition);
emit navigatorReadyChanged(true);
return true;
}
@@ -422,10 +423,10 @@ bool QDeclarativeNavigator::ensureEngine()
void QDeclarativeNavigator::updateReadyState() {
const bool oldReady = d_ptr->m_ready;
- if (!d_ptr->m_navigationManager)
+ if (!d_ptr->m_navigator)
d_ptr->m_ready = false;
else
- d_ptr->m_ready = d_ptr->m_navigationManager->ready();
+ d_ptr->m_ready = d_ptr->m_navigator->ready();
if (oldReady != d_ptr->m_ready)
emit navigatorReadyChanged(d_ptr->m_ready);
diff --git a/src/location/labs/qdeclarativenavigator_p.h b/src/location/labs/qdeclarativenavigator_p.h
index 3c83ec94..13884c41 100644
--- a/src/location/labs/qdeclarativenavigator_p.h
+++ b/src/location/labs/qdeclarativenavigator_p.h
@@ -107,7 +107,6 @@ public:
void setPositionSource(QDeclarativePositionSource *positionSource);
QDeclarativePositionSource *positionSource() const;
- QNavigationManager *navigationManager() const;
bool navigatorReady() const;
void setTrackPositionSource(bool trackPositionSource);
diff --git a/src/location/labs/qdeclarativenavigator_p_p.h b/src/location/labs/qdeclarativenavigator_p_p.h
index 3710054e..229ead1e 100644
--- a/src/location/labs/qdeclarativenavigator_p_p.h
+++ b/src/location/labs/qdeclarativenavigator_p_p.h
@@ -63,28 +63,34 @@ class QDeclarativePositionSource;
class QGeoMapParameter;
class QDeclarativeGeoRouteSegment;
class QParameterizableObject;
+class QAbstractNavigator;
-class Q_LOCATION_PRIVATE_EXPORT QDeclarativeNavigatorPrivate
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeNavigatorParams
+{
+public:
+ QPointer<QDeclarativeGeoMap> m_map;
+ QPointer<QDeclarativeGeoRoute> m_route;
+ QGeoRoute m_geoRoute;
+ QPointer<QDeclarativePositionSource> m_positionSource;
+ QList<QPointer<QGeoMapParameter>> m_parameters;
+ bool m_trackPositionSource = true;
+};
+
+class QDeclarativeNavigatorPrivate
{
public:
QDeclarativeNavigatorPrivate(QParameterizableObject *q_);
void updateReadyState();
-
QParameterizableObject *q = nullptr;
- QNavigationManager *m_navigationManager = nullptr;
+ QSharedPointer<QDeclarativeNavigatorParams> m_params;
+ QScopedPointer<QAbstractNavigator> m_navigator;
QDeclarativeGeoServiceProvider *m_plugin = nullptr;
- QPointer<QDeclarativeGeoMap> m_map;
- QPointer<QDeclarativeGeoRoute> m_route;
- QGeoRoute m_geoRoute;
- QPointer<QDeclarativePositionSource> m_positionSource;
QPointer<QDeclarativeGeoRoute> m_currentRoute;
- QList<QGeoMapParameter *> m_parameters;
int m_currentSegment = 0;
bool m_active = false;
bool m_completed = false;
bool m_ready = false;
- bool m_trackPositionSource = true;
};
QT_END_NAMESPACE
diff --git a/src/location/maps/maps.pri b/src/location/maps/maps.pri
index b5be4601..68e80442 100644
--- a/src/location/maps/maps.pri
+++ b/src/location/maps/maps.pri
@@ -62,6 +62,8 @@ PRIVATE_HEADERS += \
maps/qgeoprojection_p.h \
maps/qnavigationmanagerengine_p.h \
maps/qnavigationmanager_p.h \
+ maps/qgeocameratiles_p_p.h \
+ maps/qgeotiledmapscene_p_p.h \
maps/qcache3q_p.h
SOURCES += \
@@ -100,3 +102,4 @@ SOURCES += \
maps/qnavigationmanagerengine.cpp \
maps/qnavigationmanager.cpp \
maps/qgeoprojection.cpp
+
diff --git a/src/location/maps/qgeocameratiles.cpp b/src/location/maps/qgeocameratiles.cpp
index 327d54b3..3a2732b2 100644
--- a/src/location/maps/qgeocameratiles.cpp
+++ b/src/location/maps/qgeocameratiles.cpp
@@ -34,6 +34,7 @@
**
****************************************************************************/
#include "qgeocameratiles_p.h"
+#include "qgeocameratiles_p_p.h"
#include "qgeocameradata_p.h"
#include "qgeotilespec_p.h"
#include "qgeomaptype_p.h"
@@ -63,75 +64,6 @@ static QDoubleVector3D toDoubleVector3D(const QVector3D& in)
QT_BEGIN_NAMESPACE
-struct Frustum
-{
- QDoubleVector3D apex;
- QDoubleVector3D topLeftNear;
- QDoubleVector3D topLeftFar;
- QDoubleVector3D topRightNear;
- QDoubleVector3D topRightFar;
- QDoubleVector3D bottomLeftNear;
- QDoubleVector3D bottomLeftFar;
- QDoubleVector3D bottomRightNear;
- QDoubleVector3D bottomRightFar;
-};
-
-typedef QVector<QDoubleVector3D> PolygonVector;
-
-class QGeoCameraTilesPrivate
-{
-public:
- QGeoCameraTilesPrivate();
- ~QGeoCameraTilesPrivate();
-
- QString m_pluginString;
- QGeoMapType m_mapType;
- int m_mapVersion;
- QGeoCameraData m_camera;
- QSize m_screenSize;
- int m_tileSize;
- QSet<QGeoTileSpec> m_tiles;
-
- int m_intZoomLevel;
- int m_sideLength;
-
- bool m_dirtyGeometry;
- bool m_dirtyMetadata;
-
- double m_viewExpansion;
- void updateMetadata();
- void updateGeometry();
-
- Frustum createFrustum(double viewExpansion) const;
-
- struct ClippedFootprint
- {
- ClippedFootprint(const PolygonVector &left_, const PolygonVector &mid_, const PolygonVector &right_)
- : left(left_), mid(mid_), right(right_)
- {}
- PolygonVector left;
- PolygonVector mid;
- PolygonVector right;
- };
-
- PolygonVector frustumFootprint(const Frustum &frustum) const;
-
- QPair<PolygonVector, PolygonVector> splitPolygonAtAxisValue(const PolygonVector &polygon, int axis, double value) const;
- ClippedFootprint clipFootprintToMap(const PolygonVector &footprint) const;
-
- QList<QPair<double, int> > tileIntersections(double p1, int t1, double p2, int t2) const;
- QSet<QGeoTileSpec> tilesFromPolygon(const PolygonVector &polygon) const;
-
- struct TileMap
- {
- TileMap();
-
- void add(int tileX, int tileY);
-
- QMap<int, QPair<int, int> > data;
- };
-};
-
QGeoCameraTiles::QGeoCameraTiles()
: d_ptr(new QGeoCameraTilesPrivate()) {}
@@ -155,6 +87,15 @@ QGeoCameraData QGeoCameraTiles::cameraData() const
return d_ptr->m_camera;
}
+void QGeoCameraTiles::setVisibleArea(const QRectF &visibleArea)
+{
+ if (d_ptr->m_visibleArea == visibleArea)
+ return;
+
+ d_ptr->m_visibleArea = visibleArea;
+ d_ptr->m_dirtyGeometry = true;
+}
+
void QGeoCameraTiles::setScreenSize(const QSize &size)
{
if (d_ptr->m_screenSize == size)
@@ -267,12 +208,22 @@ void QGeoCameraTilesPrivate::updateGeometry()
// Find the frustum from the camera / screen / viewport information
// The larger frustum when stationary is a form of prefetching
Frustum f = createFrustum(m_viewExpansion);
+#ifdef QT_LOCATION_DEBUG
+ m_frustum = f;
+#endif
// Find the polygon where the frustum intersects the plane of the map
PolygonVector footprint = frustumFootprint(f);
+#ifdef QT_LOCATION_DEBUG
+ m_frustumFootprint = footprint;
+#endif
// Clip the polygon to the map, split it up if it cross the dateline
ClippedFootprint polygons = clipFootprintToMap(footprint);
+#ifdef QT_LOCATION_DEBUG
+ m_clippedFootprint = polygons;
+#endif
+
if (!polygons.left.isEmpty()) {
QSet<QGeoTileSpec> tilesLeft = tilesFromPolygon(polygons.left);
@@ -296,6 +247,10 @@ Frustum QGeoCameraTilesPrivate::createFrustum(double viewExpansion) const
if (m_camera.fieldOfView() != 90.0) //aperture(90 / 2) = 1
apertureSize = tan(QLocationUtils::radians(m_camera.fieldOfView()) * 0.5);
QDoubleVector3D center = m_sideLength * QWebMercator::coordToMercator(m_camera.center());
+#ifdef QT_LOCATION_DEBUG
+ m_createFrustum_center = center;
+#endif
+
double f = m_screenSize.height();
@@ -325,7 +280,7 @@ Frustum QGeoCameraTilesPrivate::createFrustum(double viewExpansion) const
side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0));
up = QDoubleVector3D::normal(view, side2);
- double nearPlane = 1 / (4.0 * m_tileSize );
+ double nearPlane = 1.0 / 32.0; // The denominator used to be (4.0 * m_tileSize ), which produces an extremely narrow and tiny near plane.
// farPlane plays a role on how much gets clipped when the map gets tilted. It used to be altitude + 1.0
// The value of 8.0 has been chosen as an acceptable compromise.
// TODO: use m_camera.clipDistance(); when this will be introduced
@@ -357,16 +312,36 @@ Frustum QGeoCameraTilesPrivate::createFrustum(double viewExpansion) const
Frustum frustum;
frustum.apex = eye;
-
- frustum.topLeftFar = cf - (up * hhf) - (right * hwf);
- frustum.topRightFar = cf - (up * hhf) + (right * hwf);
- frustum.bottomLeftFar = cf + (up * hhf) - (right * hwf);
- frustum.bottomRightFar = cf + (up * hhf) + (right * hwf);
-
- frustum.topLeftNear = cn - (up * hhn) - (right * hwn);
- frustum.topRightNear = cn - (up * hhn) + (right * hwn);
- frustum.bottomLeftNear = cn + (up * hhn) - (right * hwn);
- frustum.bottomRightNear = cn + (up * hhn) + (right * hwn);
+#ifdef QT_LOCATION_DEBUG
+ m_createFrustum_eye = eye;
+#endif
+
+ QRectF va = m_visibleArea;
+ if (va.isNull())
+ va = QRectF(0, 0, m_screenSize.width(), m_screenSize.height());
+ QRectF screen = QRectF(QPointF(0,0),m_screenSize);
+ QPointF vaCenter = va.center();
+ QPointF screenCenter = screen.center();
+ QPointF diff = screenCenter - vaCenter;
+ double xdiffpct = diff.x() / m_screenSize.width();
+ double ydiffpct = -(diff.y() / m_screenSize.height());
+
+ double wn = (2 * hwn) * xdiffpct;
+ double hn = (2 * hhn) * ydiffpct;
+ double wf = (2 * hwf) * xdiffpct;
+ double hf = (2 * hhf) * ydiffpct;
+
+ // TODO: fix eye
+
+ frustum.topLeftFar = cf - (up * (hhf + hf)) - (right * (hwf + wf));
+ frustum.topRightFar = cf - (up * (hhf + hf)) + (right * (hwf + wf));
+ frustum.bottomLeftFar = cf + (up * (hhf + hf)) - (right * (hwf + wf));
+ frustum.bottomRightFar = cf + (up * (hhf + hf)) + (right * (hwf + wf));
+
+ frustum.topLeftNear = cn - (up * (hhn + hn)) - (right * (hwn + wn));
+ frustum.topRightNear = cn - (up * (hhn + hn)) + (right * (hwn + wn));
+ frustum.bottomLeftNear = cn + (up * (hhn + hn)) - (right * (hwn + wn));
+ frustum.bottomRightNear = cn + (up * (hhn + hn)) + (right * (hwn + wn));
return frustum;
}
diff --git a/src/location/maps/qgeocameratiles_p.h b/src/location/maps/qgeocameratiles_p.h
index 3ff00688..4b6f3234 100644
--- a/src/location/maps/qgeocameratiles_p.h
+++ b/src/location/maps/qgeocameratiles_p.h
@@ -49,6 +49,7 @@
#include <QtLocation/private/qlocationglobal_p.h>
#include <QtCore/QScopedPointer>
+#include <QRectF>
QT_BEGIN_NAMESPACE
@@ -65,6 +66,7 @@ public:
void setCameraData(const QGeoCameraData &camera);
QGeoCameraData cameraData() const;
+ void setVisibleArea(const QRectF &visibleArea);
void setScreenSize(const QSize &size);
void setTileSize(int tileSize);
int tileSize() const;
@@ -77,6 +79,8 @@ public:
protected:
QScopedPointer<QGeoCameraTilesPrivate> d_ptr;
+
+ friend class QGeoCameraTilesPrivate;
Q_DISABLE_COPY(QGeoCameraTiles)
};
diff --git a/src/location/maps/qgeocameratiles_p_p.h b/src/location/maps/qgeocameratiles_p_p.h
new file mode 100644
index 00000000..846d95f2
--- /dev/null
+++ b/src/location/maps/qgeocameratiles_p_p.h
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QGEOCAMERATILES_P_P_H
+#define QGEOCAMERATILES_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qgeocameratiles_p.h"
+#include <QtPositioning/private/qwebmercator_p.h>
+#include <QtPositioning/private/qdoublevector2d_p.h>
+#include <QtPositioning/private/qdoublevector3d_p.h>
+#include "qgeomaptype_p.h"
+#include "qgeocameradata_p.h"
+#include "qgeotilespec_p.h"
+
+#include <QtCore/qvector.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_NAMESPACE
+
+struct Q_LOCATION_PRIVATE_EXPORT Frustum
+{
+ QDoubleVector3D apex;
+ QDoubleVector3D topLeftNear;
+ QDoubleVector3D topLeftFar;
+ QDoubleVector3D topRightNear;
+ QDoubleVector3D topRightFar;
+ QDoubleVector3D bottomLeftNear;
+ QDoubleVector3D bottomLeftFar;
+ QDoubleVector3D bottomRightNear;
+ QDoubleVector3D bottomRightFar;
+};
+
+typedef QVector<QDoubleVector3D> PolygonVector;
+
+class Q_LOCATION_PRIVATE_EXPORT QGeoCameraTilesPrivate
+{
+public:
+ struct ClippedFootprint
+ {
+ ClippedFootprint()
+ {}
+ ClippedFootprint(const PolygonVector &left_, const PolygonVector &mid_, const PolygonVector &right_)
+ : left(left_), mid(mid_), right(right_)
+ {}
+ PolygonVector left;
+ PolygonVector mid;
+ PolygonVector right;
+ };
+
+ struct TileMap
+ {
+ TileMap();
+
+ void add(int tileX, int tileY);
+
+ QMap<int, QPair<int, int> > data;
+ };
+
+ QGeoCameraTilesPrivate();
+ ~QGeoCameraTilesPrivate();
+
+
+ void updateMetadata();
+ void updateGeometry();
+
+ Frustum createFrustum(double viewExpansion) const;
+ PolygonVector frustumFootprint(const Frustum &frustum) const;
+
+ QPair<PolygonVector, PolygonVector> splitPolygonAtAxisValue(const PolygonVector &polygon, int axis, double value) const;
+ ClippedFootprint clipFootprintToMap(const PolygonVector &footprint) const;
+
+ QList<QPair<double, int> > tileIntersections(double p1, int t1, double p2, int t2) const;
+ QSet<QGeoTileSpec> tilesFromPolygon(const PolygonVector &polygon) const;
+
+ static QGeoCameraTilesPrivate *get(QGeoCameraTiles *o) {
+ return o->d_ptr.data();
+ }
+
+public:
+ QString m_pluginString;
+ QGeoMapType m_mapType;
+ int m_mapVersion;
+ QGeoCameraData m_camera;
+ QSize m_screenSize;
+ QRectF m_visibleArea;
+ int m_tileSize;
+ QSet<QGeoTileSpec> m_tiles;
+
+ int m_intZoomLevel;
+ int m_sideLength;
+ bool m_dirtyGeometry;
+ bool m_dirtyMetadata;
+ double m_viewExpansion;
+
+#ifdef QT_LOCATION_DEBUG
+ // updateGeometry
+ ClippedFootprint m_clippedFootprint;
+ PolygonVector m_frustumFootprint;
+ Frustum m_frustum;
+
+ // createFrustum
+ mutable QDoubleVector3D m_createFrustum_center;
+ mutable QDoubleVector3D m_createFrustum_eye;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOCAMERATILES_P_P_H
diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp
index 5f125169..963ef6bd 100644
--- a/src/location/maps/qgeomap.cpp
+++ b/src/location/maps/qgeomap.cpp
@@ -42,6 +42,7 @@
#include "qgeomapobject_p.h"
#include "qgeomapobject_p_p.h"
#include <QDebug>
+#include <QRectF>
QT_BEGIN_NAMESPACE
@@ -109,7 +110,7 @@ bool QGeoMap::handleEvent(QEvent *event)
return false;
}
-bool QGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate)
+bool QGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate) //FIXME visibleArea
{
Q_D(QGeoMap);
bool res = d->m_geoProjection->setBearing(bearing, coordinate);
@@ -124,7 +125,7 @@ bool QGeoMap::anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QP
{
Q_D(QGeoMap);
QGeoCoordinate newCenter = geoProjection().anchorCoordinateToPoint(coordinate, anchorPoint);
- newCenter.setLatitude(qBound(-d->m_maximumViewportLatitude, newCenter.latitude(), d->m_maximumViewportLatitude));
+ newCenter.setLatitude(qBound(d->m_minimumViewportLatitude, newCenter.latitude(), d->m_maximumViewportLatitude));
QGeoCameraData data = cameraData();
if (data.center() != newCenter) {
data.setCenter(newCenter);
@@ -145,7 +146,7 @@ QGeoShape QGeoMap::visibleRegion() const
return geoProjection().visibleRegion();
}
-QGeoCameraData QGeoMap::cameraData() const
+const QGeoCameraData &QGeoMap::cameraData() const
{
Q_D(const QGeoMap);
return d->m_cameraData;
@@ -180,6 +181,12 @@ double QGeoMap::maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) co
return d->maximumCenterLatitudeAtZoom(cameraData);
}
+double QGeoMap::minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const
+{
+ Q_D(const QGeoMap);
+ return d->minimumCenterLatitudeAtZoom(cameraData);
+}
+
double QGeoMap::mapWidth() const
{
Q_D(const QGeoMap);
@@ -297,6 +304,21 @@ void QGeoMap::removeMapObject(QGeoMapObject * /*obj*/)
{
}
+void QGeoMap::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_D(QGeoMap);
+ const QRectF &va = d->visibleArea();
+ d->setVisibleArea(visibleArea);
+ if (va != d->visibleArea())
+ emit visibleAreaChanged();
+}
+
+QRectF QGeoMap::visibleArea() const
+{
+ Q_D(const QGeoMap);
+ return d->visibleArea();
+}
+
QList<QGeoMapObject *> QGeoMap::mapObjects() const
{
Q_D(const QGeoMap);
@@ -429,4 +451,29 @@ double QGeoMapPrivate::maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraD
return m_maximumViewportLatitude;
}
+double QGeoMapPrivate::minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const
+{
+ m_minimumViewportLatitude = m_geoProjection->minimumCenterLatitudeAtZoom(cameraData);
+ return m_minimumViewportLatitude;
+}
+
+void QGeoMapPrivate::setVisibleArea(const QRectF &/*visibleArea*/)
+{
+
+}
+
+QRectF QGeoMapPrivate::visibleArea() const
+{
+ return QRectF();
+}
+
+QRectF QGeoMapPrivate::clampVisibleArea(const QRectF &visibleArea) const
+{
+ qreal xp = qMin<qreal>(visibleArea.x(), qMax(m_viewportSize.width() - 1, 0));
+ qreal yp = qMin<qreal>(visibleArea.y(), qMax(m_viewportSize.height() - 1, 0));
+ qreal w = qMin<qreal>(visibleArea.width(), qMax<qreal>(m_viewportSize.width() - xp, 0));
+ qreal h = qMin<qreal>(visibleArea.height(), qMax<qreal>(m_viewportSize.height() - yp, 0));
+ return QRectF(xp, yp, w, h);
+}
+
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h
index f6be5cae..874b300f 100644
--- a/src/location/maps/qgeomap_p.h
+++ b/src/location/maps/qgeomap_p.h
@@ -93,7 +93,8 @@ public:
SupportsVisibleRegion = 0x0001,
SupportsSetBearing = 0x0002,
SupportsAnchoringCoordinate = 0x0004,
- SupportsFittingViewportToGeoRectangle = 0x0008
+ SupportsFittingViewportToGeoRectangle = 0x0008,
+ SupportsVisibleArea = 0x0010,
};
Q_DECLARE_FLAGS(Capabilities, Capability)
@@ -107,7 +108,7 @@ public:
int viewportHeight() const;
- QGeoCameraData cameraData() const;
+ const QGeoCameraData &cameraData() const;
QGeoCameraCapabilities cameraCapabilities() const;
virtual Capabilities capabilities() const;
@@ -117,6 +118,7 @@ public:
// returns the minimum zoom at the current viewport size
double minimumZoom() const;
double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const;
+ double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const;
// returns the size of the underlying map, at the current zoom level. Unrelated to width()/height()/size().
double mapWidth() const;
@@ -153,6 +155,9 @@ public:
virtual void setCopyrightVisible(bool visible);
virtual void removeMapObject(QGeoMapObject *obj);
+ void setVisibleArea(const QRectF &visibleArea);
+ QRectF visibleArea() const;
+
protected:
QGeoMap(QGeoMapPrivate &dd, QObject *parent = 0);
void setCameraData(const QGeoCameraData &cameraData);
@@ -167,11 +172,11 @@ Q_SIGNALS:
void copyrightsChanged(const QImage &copyrightsImage);
void copyrightsChanged(const QString &copyrightsHtml);
void copyrightsStyleSheetChanged(const QString &styleSheet);
+ void visibleAreaChanged();
private:
Q_DISABLE_COPY(QGeoMap)
friend class QDeclarativeGeoMap; //updateSceneGraph
- friend class QGeoMapPrivate;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoMap::ItemTypes)
diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h
index 47780c47..331697b2 100644
--- a/src/location/maps/qgeomap_p_p.h
+++ b/src/location/maps/qgeomap_p_p.h
@@ -103,8 +103,18 @@ protected:
virtual void setCopyrightVisible(bool visible);
virtual bool copyrightVisible() const;
virtual double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const;
+ virtual double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const;
+ virtual void setVisibleArea(const QRectF &visibleArea);
+ virtual QRectF visibleArea() const;
+
+ QRectF clampVisibleArea(const QRectF &visibleArea) const;
+
+#ifdef QT_LOCATION_DEBUG
+public:
+#else
protected:
+#endif
QSize m_viewportSize;
QGeoProjection *m_geoProjection;
QPointer<QGeoMappingManagerEngine> m_engine;
@@ -115,6 +125,7 @@ protected:
QGeoCameraCapabilities m_cameraCapabilities;
bool m_copyrightVisible = true;
mutable double m_maximumViewportLatitude = 0;
+ mutable double m_minimumViewportLatitude = 0;
};
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeomapparameter.cpp b/src/location/maps/qgeomapparameter.cpp
index b1d6f060..1b3f0829 100644
--- a/src/location/maps/qgeomapparameter.cpp
+++ b/src/location/maps/qgeomapparameter.cpp
@@ -98,5 +98,11 @@ QVariantMap QGeoMapParameter::toVariantMap() const
return res;
}
+bool QGeoMapParameter::hasProperty(const char *propertyName)
+{
+ return metaObject()->indexOfProperty(propertyName) != -1
+ || dynamicPropertyNames().indexOf(QByteArray(propertyName)) != -1;
+}
+
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeomapparameter_p.h b/src/location/maps/qgeomapparameter_p.h
index 413b420e..c6bbef44 100644
--- a/src/location/maps/qgeomapparameter_p.h
+++ b/src/location/maps/qgeomapparameter_p.h
@@ -74,6 +74,7 @@ public:
void updateProperty(const char *propertyName, QVariant value);
QVariantMap toVariantMap() const;
+ bool hasProperty(const char *propertyName);
Q_SIGNALS:
void propertyUpdated(QGeoMapParameter *param, const char *propertyName);
diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp
index 74736cef..0fdb5f0b 100644
--- a/src/location/maps/qgeoprojection.cpp
+++ b/src/location/maps/qgeoprojection.cpp
@@ -39,6 +39,7 @@
#include <QtPositioning/private/qlocationutils_p.h>
#include <QtPositioning/private/qclipperutils_p.h>
#include <QtPositioning/QGeoPolygon>
+#include <QtPositioning/QGeoRectangle>
#include <QSize>
#include <QtGui/QMatrix4x4>
#include <cmath>
@@ -62,6 +63,30 @@ static QMatrix4x4 toMatrix4x4(const QDoubleMatrix4x4 &m)
m(3,0), m(3,1), m(3,2), m(3,3));
}
+static QPointF centerOffset(const QSizeF &screenSize, const QRectF &visibleArea)
+{
+ QRectF va = visibleArea;
+ if (va.isNull())
+ va = QRectF(0, 0, screenSize.width(), screenSize.height());
+
+ QRectF screen = QRectF(QPointF(0,0),screenSize);
+ QPointF vaCenter = va.center();
+
+ QPointF screenCenter = screen.center();
+ QPointF diff = screenCenter - vaCenter;
+
+ return diff;
+}
+
+static QPointF marginsOffset(const QSizeF &screenSize, const QRectF &visibleArea)
+{
+ QPointF diff = centerOffset(screenSize, visibleArea);
+ qreal xdiffpct = diff.x() / qMax<double>(screenSize.width() - 1, 1);
+ qreal ydiffpct = diff.y() / qMax<double>(screenSize.height() - 1, 1);
+
+ return QPointF(-xdiffpct, -ydiffpct);
+}
+
QT_BEGIN_NAMESPACE
QGeoProjection::QGeoProjection()
@@ -139,7 +164,7 @@ QGeoProjectionWebMercator::QGeoProjectionWebMercator()
m_viewportHeight(1),
m_1_viewportWidth(0),
m_1_viewportHeight(0),
- m_sideLength(256),
+ m_sideLengthPixels(256),
m_aperture(0.0),
m_nearPlane(0.0),
m_farPlane(0.0),
@@ -175,14 +200,36 @@ double QGeoProjectionWebMercator::maximumCenterLatitudeAtZoom(const QGeoCameraDa
// At init time weird things happen
int clampedWindowHeight = (m_viewportHeight > mapEdgeSize) ? mapEdgeSize : m_viewportHeight;
+ QPointF offsetPct = centerOffset(QSizeF(m_viewportWidth, m_viewportHeight), m_visibleArea);
+ double hpct = offsetPct.y() / qMax<double>(m_viewportHeight - 1, 1);
// 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 ;
+ double mercatorTopmost = (clampedWindowHeight * (0.5 - hpct)) / mapEdgeSize ;
QGeoCoordinate topMost = QWebMercator::mercatorToCoord(QDoubleVector2D(0.0, mercatorTopmost));
-
return topMost.latitude();
}
+double QGeoProjectionWebMercator::minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const
+{
+ double mapEdgeSize = std::pow(2.0, cameraData.zoomLevel()) * defaultTileSize;
+
+ // At init time weird things happen
+ int clampedWindowHeight = (m_viewportHeight > mapEdgeSize) ? mapEdgeSize : m_viewportHeight;
+ QPointF offsetPct = centerOffset(QSizeF(m_viewportWidth, m_viewportHeight), m_visibleArea);
+ double hpct = offsetPct.y() / qMax<double>(m_viewportHeight - 1, 1);
+
+ // 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 + hpct)) / mapEdgeSize ;
+ QGeoCoordinate topMost = QWebMercator::mercatorToCoord(QDoubleVector2D(0.0, mercatorTopmost));
+ return -topMost.latitude();
+}
+
+void QGeoProjectionWebMercator::setVisibleArea(const QRectF &visibleArea)
+{
+ m_visibleArea = visibleArea;
+ setupCamera();
+}
+
double QGeoProjectionWebMercator::mapWidth() const
{
return m_mapEdgeSize;
@@ -258,7 +305,8 @@ QDoubleVector2D QGeoProjectionWebMercator::wrappedMapProjectionToItemPosition(co
QDoubleVector2D QGeoProjectionWebMercator::itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const
{
- QDoubleVector2D pos = itemPosition;
+ const QPointF centerOff = centerOffset(QSizeF(m_viewportWidth, m_viewportHeight), m_visibleArea);
+ QDoubleVector2D pos = itemPosition + QDoubleVector2D(centerOff);
pos *= QDoubleVector2D(m_1_viewportWidth, m_1_viewportHeight);
pos *= 2.0;
pos -= QDoubleVector2D(1.0,1.0);
@@ -341,7 +389,7 @@ QMatrix4x4 QGeoProjectionWebMercator::quickItemTransformation(const QGeoCoordina
const QDoubleVector2D anchorMercator = anchorScaled / mapWidth();
const QDoubleVector2D coordAnchored = coordWrapped - anchorMercator;
- const QDoubleVector2D coordAnchoredScaled = coordAnchored * m_sideLength;
+ const QDoubleVector2D coordAnchoredScaled = coordAnchored * m_sideLengthPixels;
QDoubleMatrix4x4 matTranslateScale;
matTranslateScale.translate(coordAnchoredScaled.x(), coordAnchoredScaled.y(), 0.0);
@@ -368,7 +416,7 @@ bool QGeoProjectionWebMercator::isProjectable(const QDoubleVector2D &wrappedProj
if (m_cameraData.tilt() == 0.0)
return true;
- QDoubleVector3D pos = wrappedProjection * m_sideLength;
+ QDoubleVector3D pos = wrappedProjection * m_sideLengthPixels;
// use m_centerNearPlane in order to add an offset to m_eye.
QDoubleVector3D p = m_centerNearPlane - pos;
double dot = QDoubleVector3D::dotProduct(p , m_viewNormalized);
@@ -434,14 +482,52 @@ QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const
QDoubleVector2D pos = itemPosition;
pos *= QDoubleVector2D(m_halfWidth, m_halfHeight);
+ // determine itemPosition on the near plane
QDoubleVector3D p = m_centerNearPlane;
p += m_up * pos.y();
p += m_side * pos.x();
+ // compute the ray using the eye position
QDoubleVector3D ray = m_eye - p;
ray.normalize();
- return (xyPlane.lineIntersection(m_eye, ray, s) / m_sideLength).toVector2D();
+ return (xyPlane.lineIntersection(m_eye, ray, s) / m_sideLengthPixels).toVector2D();
+}
+
+/*
+ Returns a pair of <newCenter, newZoom>
+*/
+QPair<QGeoCoordinate, qreal> QGeoProjectionWebMercator::fitViewportToGeoRectangle(const QGeoRectangle &rectangle,
+ const QMargins &m) const
+{
+ QPair<QGeoCoordinate, qreal> res;
+ res.second = qQNaN();
+ if (m_viewportWidth <= m.left() + m.right() || m_viewportHeight <= m.top() + m.bottom())
+ return res;
+
+ QDoubleVector2D topLeftPoint = geoToMapProjection(rectangle.topLeft());
+ QDoubleVector2D bottomRightPoint = geoToMapProjection(rectangle.bottomRight());
+ if (bottomRightPoint.x() < topLeftPoint.x()) // crossing the dateline
+ bottomRightPoint.setX(bottomRightPoint.x() + 1.0);
+
+ // find center of the bounding box
+ QDoubleVector2D center = (topLeftPoint + bottomRightPoint) * 0.5;
+ center.setX(center.x() > 1.0 ? center.x() - 1.0 : center.x());
+ res.first = mapProjectionToGeo(center);
+
+ // if the shape is empty we just change center position, not zoom
+ double bboxWidth = (bottomRightPoint.x() - topLeftPoint.x()) * mapWidth();
+ double bboxHeight = (bottomRightPoint.y() - topLeftPoint.y()) * mapHeight();
+
+ if (bboxHeight == 0.0 && bboxWidth == 0.0)
+ return res;
+
+ double zoomRatio = qMax(bboxWidth / (m_viewportWidth - m.left() - m.right()),
+ bboxHeight / (m_viewportHeight - m.top() - m.bottom()));
+ zoomRatio = std::log(zoomRatio) / std::log(2.0);
+ res.second = m_cameraData.zoomLevel() - zoomRatio;
+
+ return res;
}
QGeoProjection::ProjectionGroup QGeoProjectionWebMercator::projectionGroup() const
@@ -466,8 +552,8 @@ void QGeoProjectionWebMercator::setupCamera()
m_cameraCenterYMercator = m_centerMercator.y();
int intZoomLevel = static_cast<int>(std::floor(m_cameraData.zoomLevel()));
- m_sideLength = (1 << intZoomLevel) * defaultTileSize;
- m_center = m_centerMercator * m_sideLength;
+ m_sideLengthPixels = (1 << intZoomLevel) * defaultTileSize;
+ m_center = m_centerMercator * m_sideLengthPixels;
//aperture(90 / 2) = 1
m_aperture = tan(QLocationUtils::radians(m_cameraData.fieldOfView()) * 0.5);
@@ -538,7 +624,8 @@ void QGeoProjectionWebMercator::setupCamera()
m_viewMercator = m_eyeMercator - m_centerMercator;
m_upMercator = QDoubleVector3D::normal(m_viewMercator, m_sideMercator);
- m_nearPlaneMercator = 1.0 / m_sideLength;
+ m_nearPlaneMercator = 0.000002; // this value works until ZL 18. Above that, a better progressive formula is needed, or
+ // else, this clips too much.
double aspectRatio = 1.0 * m_viewportWidth / m_viewportHeight;
@@ -563,14 +650,15 @@ void QGeoProjectionWebMercator::setupCamera()
* matScreen = scale(m_viewportWidth, m_viewportHeight, 1.0)
*/
+ QPointF offsetPct = marginsOffset(QSizeF(m_viewportWidth, m_viewportHeight), m_visibleArea);
QDoubleMatrix4x4 matScreenTransformation;
matScreenTransformation.scale(0.5 * m_viewportWidth, 0.5 * m_viewportHeight, 1.0);
- matScreenTransformation(0,3) = 0.5 * m_viewportWidth;
- matScreenTransformation(1,3) = 0.5 * m_viewportHeight;
+ matScreenTransformation(0,3) = (0.5 + offsetPct.x()) * m_viewportWidth;
+ matScreenTransformation(1,3) = (0.5 + offsetPct.y()) * m_viewportHeight;
m_transformation = matScreenTransformation * projectionMatrix * cameraMatrix;
m_quickItemTransformation = m_transformation;
- m_transformation.scale(m_sideLength, m_sideLength, 1.0);
+ m_transformation.scale(m_sideLengthPixels, m_sideLengthPixels, 1.0);
m_centerNearPlane = m_eye - m_viewNormalized;
m_centerNearPlaneMercator = m_eyeMercator - m_viewNormalized * m_nearPlaneMercator;
@@ -597,10 +685,18 @@ void QGeoProjectionWebMercator::updateVisibleRegion()
{
m_visibleRegionDirty = false;
- QDoubleVector2D tl = viewportToWrappedMapProjection(QDoubleVector2D(-1, -1 + m_verticalEstateToSkip ));
- QDoubleVector2D tr = viewportToWrappedMapProjection(QDoubleVector2D( 1, -1 + m_verticalEstateToSkip ));
- QDoubleVector2D bl = viewportToWrappedMapProjection(QDoubleVector2D(-1, 1 ));
- QDoubleVector2D br = viewportToWrappedMapProjection(QDoubleVector2D( 1, 1 ));
+ double viewportHalfWidth = (!m_visibleArea.isEmpty()) ? m_visibleArea.width() / m_viewportWidth : 1.0;
+ double viewportHalfHeight = (!m_visibleArea.isEmpty()) ? m_visibleArea.height() / m_viewportHeight : 1.0;
+
+ double top = qMax<double>(-viewportHalfHeight, -1 + m_verticalEstateToSkip);
+ double bottom = viewportHalfHeight;
+ double left = -viewportHalfWidth;
+ double right = viewportHalfWidth;
+
+ QDoubleVector2D tl = viewportToWrappedMapProjection(QDoubleVector2D(left, top ));
+ QDoubleVector2D tr = viewportToWrappedMapProjection(QDoubleVector2D(right, top ));
+ QDoubleVector2D bl = viewportToWrappedMapProjection(QDoubleVector2D(left, bottom ));
+ QDoubleVector2D br = viewportToWrappedMapProjection(QDoubleVector2D(right, bottom ));
// To make sure that what is returned can be safely converted back to lat/lon without risking overlaps
double mapLeftLongitude = QLocationUtils::mapLeftLongitude(m_cameraData.center().longitude());
diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h
index b0fffa28..2e1af8c5 100644
--- a/src/location/maps/qgeoprojection_p.h
+++ b/src/location/maps/qgeoprojection_p.h
@@ -85,6 +85,7 @@ public:
QGeoProjection();
virtual ~QGeoProjection();
+ virtual void setVisibleArea(const QRectF &visibleArea) = 0;
virtual void setViewportSize(const QSize &size) = 0;
virtual void setCameraData(const QGeoCameraData &cameraData, bool force = true) = 0;
virtual QGeoCameraData cameraData() const = 0;
@@ -92,6 +93,7 @@ public:
// returns the minimum zoom at the current viewport size
virtual double minimumZoom() const = 0;
virtual double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const = 0;
+ virtual double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const = 0;
virtual QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const = 0;
virtual QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const = 0;
@@ -116,7 +118,9 @@ public:
// From QGeoProjection
double minimumZoom() const override;
double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override;
+ double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override;
+ void setVisibleArea(const QRectF &visibleArea) override;
void setViewportSize(const QSize &size) override;
void setCameraData(const QGeoCameraData &cameraData, bool force = true) override;
QGeoCameraData cameraData() const override;
@@ -158,6 +162,9 @@ public:
inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const;
inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition, double &s) const;
+ QPair<QGeoCoordinate, qreal> fitViewportToGeoRectangle(const QGeoRectangle &rectangle,
+ const QMargins &margins) const;
+
private:
void setupCamera();
void updateVisibleRegion();
@@ -188,7 +195,11 @@ public:
QDoubleVector3D m_normal;
};
-private:
+#ifdef QT_LOCATION_DEBUG
+public:
+#else
+protected:
+#endif
QGeoCameraData m_cameraData;
double m_mapEdgeSize;
double m_minimumZoom;
@@ -211,7 +222,7 @@ private:
QDoubleVector3D m_viewNormalized;
QDoubleVector3D m_side;
QDoubleVector3D m_centerNearPlane;
- double m_sideLength; // map edge size at integer zoom level
+ double m_sideLengthPixels; // map edge size at integer zoom level
double m_aperture;
double m_nearPlane;
double m_farPlane;
@@ -234,6 +245,7 @@ private:
QList<QDoubleVector2D> m_visibleRegionExpanded;
QList<QDoubleVector2D> m_projectableRegion;
bool m_visibleRegionDirty;
+ QRectF m_visibleArea;
Q_DISABLE_COPY(QGeoProjectionWebMercator)
};
diff --git a/src/location/maps/qgeoroute.cpp b/src/location/maps/qgeoroute.cpp
index 8d62dceb..799fe7f1 100644
--- a/src/location/maps/qgeoroute.cpp
+++ b/src/location/maps/qgeoroute.cpp
@@ -95,6 +95,11 @@ QExplicitlySharedDataPointer<QGeoRoutePrivate> &QGeoRoute::d()
return d_ptr;
}
+const QExplicitlySharedDataPointer<QGeoRoutePrivate> &QGeoRoute::const_d() const
+{
+ return d_ptr;
+}
+
/*!
Constructs a route object from the contents of \a other.
*/
@@ -294,6 +299,28 @@ QList<QGeoCoordinate> QGeoRoute::path() const
return d_ptr->path();
}
+/*!
+ Sets the route legs for a multi-waypoint route.
+
+ \sa QGeoRouteLeg
+ \since 5.12
+*/
+void QGeoRoute::setRouteLegs(const QList<QGeoRouteLeg> &legs)
+{
+ d_ptr->setRouteLegs(legs);
+}
+
+/*!
+ Returns the legs for the route.
+
+ \sa QGeoRouteLeg
+ \since 5.12
+*/
+QList<QGeoRouteLeg> QGeoRoute::routeLegs() const
+{
+ return d_ptr->routeLegs();
+}
+
/*******************************************************************************
*******************************************************************************/
@@ -341,7 +368,8 @@ bool QGeoRoutePrivate::equals(const QGeoRoutePrivate &other) const
&& (distance() == other.distance())
&& (travelMode() == other.travelMode())
&& (path() == other.path())
- && (metadata() == other.metadata()));
+ && (metadata() == other.metadata())
+ && (routeLegs() == other.routeLegs()));
}
void QGeoRoutePrivate::setId(const QString &id)
@@ -434,6 +462,36 @@ QVariantMap QGeoRoutePrivate::metadata() const
return QVariantMap();
}
+void QGeoRoutePrivate::setRouteLegs(const QList<QGeoRouteLeg> &/*legs*/)
+{
+
+}
+
+QList<QGeoRouteLeg> QGeoRoutePrivate::routeLegs() const
+{
+ return QList<QGeoRouteLeg>();
+}
+
+void QGeoRoutePrivate::setLegIndex(int /*idx*/)
+{
+
+}
+
+int QGeoRoutePrivate::legIndex() const
+{
+ return 0;
+}
+
+void QGeoRoutePrivate::setContainingRoute(const QGeoRoute &/*route*/)
+{
+
+}
+
+QGeoRoute QGeoRoutePrivate::containingRoute() const
+{
+ return QGeoRoute();
+}
+
/*******************************************************************************
*******************************************************************************/
@@ -454,6 +512,7 @@ QGeoRoutePrivateDefault::QGeoRoutePrivateDefault(const QGeoRoutePrivateDefault &
m_distance(other.m_distance),
m_travelMode(other.m_travelMode),
m_path(other.m_path),
+ m_legs(other.m_legs),
m_firstSegment(other.m_firstSegment),
m_numSegments(other.m_numSegments){}
@@ -559,10 +618,124 @@ int QGeoRoutePrivateDefault::segmentsCount() const
QGeoRouteSegment segment = m_firstSegment;
while (segment.isValid()) {
++count;
+ if (segment.isLegLastSegment() && m_containingRoute.data()) // if containing route, this is a leg
+ break;
segment = segment.nextRouteSegment();
}
m_numSegments = count;
return count;
}
+void QGeoRoutePrivateDefault::setRouteLegs(const QList<QGeoRouteLeg> &legs)
+{
+ m_legs = legs;
+}
+
+QList<QGeoRouteLeg> QGeoRoutePrivateDefault::routeLegs() const
+{
+ return m_legs;
+}
+
+void QGeoRoutePrivateDefault::setLegIndex(int idx)
+{
+ if (idx >= 0)
+ m_legIndex = idx;
+}
+
+int QGeoRoutePrivateDefault::legIndex() const
+{
+ return m_legIndex;
+}
+
+void QGeoRoutePrivateDefault::setContainingRoute(const QGeoRoute &route)
+{
+ QScopedPointer<QGeoRoute> containingRoute(new QGeoRoute(route));
+ m_containingRoute.swap(containingRoute);
+}
+
+QGeoRoute QGeoRoutePrivateDefault::containingRoute() const
+{
+ if (m_containingRoute)
+ return *m_containingRoute;
+ return QGeoRoute();
+}
+
+/*!
+ \class QGeoRouteLeg
+ \inmodule QtLocation
+ \ingroup QtLocation-routing
+ \since 5.12
+
+ \brief The QGeoRouteLeg class represents a leg of a route, that is the portion
+ of a route between one waypoint and the next.
+ This is a subclass of QGeoRoute, exposing route leg specific API.
+
+ \note QGeoRoute::routeLegs will return an empty list if called on a route leg.
+
+ \sa QGeoRoute
+*/
+
+/*!
+ Constructs a route leg object.
+*/
+
+QGeoRouteLeg::QGeoRouteLeg() : QGeoRoute()
+{
+
+}
+
+/*!
+ Constructs a route leg object from the contents of \a other.
+*/
+QGeoRouteLeg::QGeoRouteLeg(const QGeoRouteLeg &other) : QGeoRoute(other)
+{
+
+}
+
+/*!
+ Destroys this route object.
+*/
+QGeoRouteLeg::~QGeoRouteLeg()
+{
+
+}
+
+/*!
+ Sets the route leg index to \a idx.
+*/
+void QGeoRouteLeg::setLegIndex(int idx)
+{
+ d()->setLegIndex(idx);
+}
+
+/*!
+ Returns the index of this route leg inside the containing QGeoRoute::routeLegs list.
+ Can be used to find the next legs.
+*/
+int QGeoRouteLeg::legIndex() const
+{
+ return const_d()->legIndex();
+}
+
+/*!
+ Sets the \a route that contains this route leg.
+*/
+void QGeoRouteLeg::setOverallRoute(const QGeoRoute &route)
+{
+ d()->setContainingRoute(route);
+}
+
+/*!
+ Returns the \a route that contains this route leg.
+*/
+QGeoRoute QGeoRouteLeg::overallRoute() const
+{
+ return const_d()->containingRoute();
+}
+
+QGeoRouteLeg::QGeoRouteLeg(const QExplicitlySharedDataPointer<QGeoRoutePrivate> &dd) : QGeoRoute(dd)
+{
+
+}
+
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeoroute.h b/src/location/maps/qgeoroute.h
index ef1f7566..381152e3 100644
--- a/src/location/maps/qgeoroute.h
+++ b/src/location/maps/qgeoroute.h
@@ -50,13 +50,13 @@ class QGeoRectangle;
class QGeoRouteSegment;
class QGeoRoutePrivate;
-
+class QGeoRouteLeg;
class Q_LOCATION_EXPORT QGeoRoute
{
public:
QGeoRoute();
QGeoRoute(const QGeoRoute &other);
- ~QGeoRoute();
+ ~QGeoRoute(); // ### Qt6: make this virtual
QGeoRoute &operator = (const QGeoRoute &other);
@@ -87,9 +87,13 @@ public:
void setPath(const QList<QGeoCoordinate> &path);
QList<QGeoCoordinate> path() const;
+ void setRouteLegs(const QList<QGeoRouteLeg> &legs);
+ QList<QGeoRouteLeg> routeLegs() const;
+
protected:
QGeoRoute(const QExplicitlySharedDataPointer<QGeoRoutePrivate> &dd);
QExplicitlySharedDataPointer<QGeoRoutePrivate> &d();
+ const QExplicitlySharedDataPointer<QGeoRoutePrivate> &const_d() const;
private:
QExplicitlySharedDataPointer<QGeoRoutePrivate> d_ptr;
@@ -97,6 +101,26 @@ private:
friend class QGeoRoutePrivate;
};
+class Q_LOCATION_EXPORT QGeoRouteLeg: public QGeoRoute
+{
+public:
+ QGeoRouteLeg();
+ QGeoRouteLeg(const QGeoRouteLeg &other);
+ ~QGeoRouteLeg();
+
+ void setLegIndex(int idx);
+ int legIndex() const;
+
+ void setOverallRoute(const QGeoRoute &route);
+ QGeoRoute overallRoute() const;
+
+protected:
+ QGeoRouteLeg(const QExplicitlySharedDataPointer<QGeoRoutePrivate> &dd);
+
+ friend class QDeclarativeGeoRoute;
+ friend class QGeoRoutePrivate;
+};
+
QT_END_NAMESPACE
#endif
diff --git a/src/location/maps/qgeoroute_p.h b/src/location/maps/qgeoroute_p.h
index 384802ee..39f96c48 100644
--- a/src/location/maps/qgeoroute_p.h
+++ b/src/location/maps/qgeoroute_p.h
@@ -55,6 +55,7 @@
#include "qgeoroutesegment.h"
#include <QSharedData>
+#include <QScopedPointer>
QT_BEGIN_NAMESPACE
@@ -96,9 +97,18 @@ public:
virtual QVariantMap metadata() const;
+ virtual void setRouteLegs(const QList<QGeoRouteLeg> &legs);
+ virtual QList<QGeoRouteLeg> routeLegs() const;
+
virtual QString engineName() const = 0;
virtual int segmentsCount() const = 0;
+ // QGeoRouteLeg API
+ virtual void setLegIndex(int idx);
+ virtual int legIndex() const;
+ virtual void setContainingRoute(const QGeoRoute &route);
+ virtual QGeoRoute containingRoute() const;
+
static const QGeoRoutePrivate *routePrivateData(const QGeoRoute &route);
protected:
@@ -110,7 +120,7 @@ class Q_LOCATION_PRIVATE_EXPORT QGeoRoutePrivateDefault : public QGeoRoutePriva
public:
QGeoRoutePrivateDefault();
QGeoRoutePrivateDefault(const QGeoRoutePrivateDefault &other);
- ~QGeoRoutePrivateDefault();
+ ~QGeoRoutePrivateDefault() override;
virtual QGeoRoutePrivate *clone() override;
virtual void setId(const QString &id) override;
@@ -140,6 +150,14 @@ public:
virtual QString engineName() const override;
virtual int segmentsCount() const override;
+ virtual void setRouteLegs(const QList<QGeoRouteLeg> &legs) override;
+ virtual QList<QGeoRouteLeg> routeLegs() const override;
+
+ // QGeoRouteLeg API
+ virtual void setLegIndex(int idx) override;
+ virtual int legIndex() const override;
+ virtual void setContainingRoute(const QGeoRoute &route) override;
+ virtual QGeoRoute containingRoute() const override;
QString m_id;
QGeoRouteRequest m_request;
@@ -153,9 +171,11 @@ public:
QGeoRouteRequest::TravelMode m_travelMode;
QList<QGeoCoordinate> m_path;
-
+ QList<QGeoRouteLeg> m_legs;
QGeoRouteSegment m_firstSegment;
mutable int m_numSegments;
+ QScopedPointer<QGeoRoute> m_containingRoute;
+ int m_legIndex = 0;
};
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeorouteparserosrmv5.cpp b/src/location/maps/qgeorouteparserosrmv5.cpp
index 58299d09..39910229 100644
--- a/src/location/maps/qgeorouteparserosrmv5.cpp
+++ b/src/location/maps/qgeorouteparserosrmv5.cpp
@@ -35,8 +35,11 @@
****************************************************************************/
#include "qgeorouteparserosrmv5_p.h"
+#include "qgeoroute.h"
+#include "qgeoroute_p.h"
#include "qgeorouteparser_p_p.h"
#include "qgeoroutesegment.h"
+#include "qgeoroutesegment_p.h"
#include "qgeomaneuver.h"
#include <QtCore/private/qobject_p.h>
@@ -45,6 +48,7 @@
#include <QtCore/QJsonArray>
#include <QtCore/QUrlQuery>
#include <QtPositioning/private/qlocationutils_p.h>
+#include <QtPositioning/qgeopath.h>
QT_BEGIN_NAMESPACE
@@ -912,22 +916,26 @@ QGeoRouteReply::Error QGeoRouteParserOsrmV5Private::parseReply(QList<QGeoRoute>
foreach (const QJsonValue &r, osrmRoutes) {
if (!r.isObject())
continue;
- QJsonObject route = r.toObject();
- if (!route.value(QLatin1String("legs")).isArray())
+ QJsonObject routeObject = r.toObject();
+ if (!routeObject.value(QLatin1String("legs")).isArray())
continue;
- if (!route.value(QLatin1String("duration")).isDouble())
+ if (!routeObject.value(QLatin1String("duration")).isDouble())
continue;
- if (!route.value(QLatin1String("distance")).isDouble())
+ if (!routeObject.value(QLatin1String("distance")).isDouble())
continue;
- double distance = route.value(QLatin1String("distance")).toDouble();
- double travelTime = route.value(QLatin1String("duration")).toDouble();
+ double distance = routeObject.value(QLatin1String("distance")).toDouble();
+ double travelTime = routeObject.value(QLatin1String("duration")).toDouble();
bool error = false;
QList<QGeoRouteSegment> segments;
- QJsonArray legs = route.value(QLatin1String("legs")).toArray();
+ QJsonArray legs = routeObject.value(QLatin1String("legs")).toArray();
+ QList<QGeoRouteLeg> routeLegs;
+ QGeoRoute route;
for (int legIndex = 0; legIndex < legs.size(); ++legIndex) {
const QJsonValue &l = legs.at(legIndex);
+ QGeoRouteLeg routeLeg;
+ QList<QGeoRouteSegment> legSegments;
if (!l.isObject()) { // invalid leg record
error = true;
break;
@@ -937,16 +945,20 @@ QGeoRouteReply::Error QGeoRouteParserOsrmV5Private::parseReply(QList<QGeoRoute>
error = true;
break;
}
+ const double legDistance = leg.value(QLatin1String("distance")).toDouble();
+ const double legTravelTime = leg.value(QLatin1String("duration")).toDouble();
QJsonArray steps = leg.value(QLatin1String("steps")).toArray();
+ QGeoRouteSegment segment;
for (int stepIndex = 0; stepIndex < steps.size(); ++stepIndex) {
const QJsonValue &s = steps.at(stepIndex);
if (!s.isObject()) {
error = true;
break;
}
- QGeoRouteSegment segment = parseStep(s.toObject(), legIndex, stepIndex);
+ segment = parseStep(s.toObject(), legIndex, stepIndex);
if (segment.isValid()) {
- segments.append(segment);
+ // setNextRouteSegment done below for all segments in the route.
+ legSegments.append(segment);
} else {
error = true;
break;
@@ -954,6 +966,23 @@ QGeoRouteReply::Error QGeoRouteParserOsrmV5Private::parseReply(QList<QGeoRoute>
}
if (error)
break;
+
+ QGeoRouteSegmentPrivate *segmentPrivate = QGeoRouteSegmentPrivate::get(segment);
+ segmentPrivate->setLegLastSegment(true);
+ QList<QGeoCoordinate> path;
+ for (const QGeoRouteSegment &s: qAsConst(legSegments))
+ path.append(s.path());
+ routeLeg.setLegIndex(legIndex);
+ routeLeg.setOverallRoute(route); // QGeoRoute::d_ptr is explicitlySharedDataPointer. Modifiers below won't detach it.
+ routeLeg.setDistance(legDistance);
+ routeLeg.setTravelTime(legTravelTime);
+ if (!path.isEmpty()) {
+ routeLeg.setPath(path);
+ routeLeg.setFirstRouteSegment(legSegments.first());
+ }
+ routeLegs << routeLeg;
+
+ segments.append(legSegments);
}
if (!error) {
@@ -964,15 +993,16 @@ QGeoRouteReply::Error QGeoRouteParserOsrmV5Private::parseReply(QList<QGeoRoute>
for (int i = segments.size() - 1; i > 0; --i)
segments[i-1].setNextRouteSegment(segments[i]);
- QGeoRoute r;
- r.setDistance(distance);
- r.setTravelTime(travelTime);
+ route.setDistance(distance);
+ route.setTravelTime(travelTime);
if (!path.isEmpty()) {
- r.setPath(path);
- r.setFirstRouteSegment(segments.first());
+ route.setPath(path);
+ route.setBounds(QGeoPath(path).boundingGeoRectangle());
+ route.setFirstRouteSegment(segments.first());
}
+ route.setRouteLegs(routeLegs);
//r.setTravelMode(QGeoRouteRequest::CarTravel); // The only one supported by OSRM demo service, but other OSRM servers might do cycle or pedestrian too
- routes.append(r);
+ routes.append(route);
}
}
diff --git a/src/location/maps/qgeoroutesegment.cpp b/src/location/maps/qgeoroutesegment.cpp
index 5bfb4f65..aff54fc7 100644
--- a/src/location/maps/qgeoroutesegment.cpp
+++ b/src/location/maps/qgeoroutesegment.cpp
@@ -59,7 +59,7 @@ QGeoRouteSegmentPrivate *QExplicitlySharedDataPointer<QGeoRouteSegmentPrivate>::
A QGeoRouteSegment instance has information about the physical layout
of the route segment, the length of the route and estimated time required
to traverse the route segment and an optional QGeoManeuver associated with
- the end of the route segment.
+ the beginning of the route segment.
QGeoRouteSegment instances can be thought of as edges on a routing
graph, with QGeoManeuver instances as optional labels attached to the
@@ -147,6 +147,21 @@ bool QGeoRouteSegment::isValid() const
}
/*!
+ Returns whether this route segment is the last segment of a route leg.
+
+ \since 5.12
+*/
+bool QGeoRouteSegment::isLegLastSegment() const
+{
+ if (!d_ptr->valid())
+ return false;
+
+ if (!d_ptr->nextRouteSegment())
+ return true;
+ return d_ptr->isLegLastSegment();
+}
+
+/*!
Sets the next route segment in the route to \a routeSegment.
*/
void QGeoRouteSegment::setNextRouteSegment(const QGeoRouteSegment &routeSegment)
@@ -163,8 +178,8 @@ void QGeoRouteSegment::setNextRouteSegment(const QGeoRouteSegment &routeSegment)
*/
QGeoRouteSegment QGeoRouteSegment::nextRouteSegment() const
{
- if (d_ptr->valid() && d_ptr->m_nextSegment)
- return QGeoRouteSegment(d_ptr->m_nextSegment);
+ if (d_ptr->valid() && d_ptr->nextRouteSegment())
+ return QGeoRouteSegment(d_ptr->nextRouteSegment());
return QGeoRouteSegment();
}
@@ -242,7 +257,7 @@ void QGeoRouteSegment::setManeuver(const QGeoManeuver &maneuver)
Returns the maneuver for this route segment.
Will return an invalid QGeoManeuver if no information has been attached
- to the endpoint of this route segment.
+ to the starting point of this route segment.
*/
QGeoManeuver QGeoRouteSegment::maneuver() const
{
@@ -286,6 +301,16 @@ void QGeoRouteSegmentPrivate::setValid(bool valid)
Q_UNUSED(valid)
}
+bool QGeoRouteSegmentPrivate::isLegLastSegment() const
+{
+ return false;
+}
+
+void QGeoRouteSegmentPrivate::setLegLastSegment(bool lastSegment)
+{
+ Q_UNUSED(lastSegment)
+}
+
int QGeoRouteSegmentPrivate::travelTime() const
{
return 0;
@@ -336,6 +361,11 @@ void QGeoRouteSegmentPrivate::setNextRouteSegment(const QExplicitlySharedDataPoi
m_nextSegment = next;
}
+QGeoRouteSegmentPrivate *QGeoRouteSegmentPrivate::get(QGeoRouteSegment &segment)
+{
+ return segment.d_ptr.data();
+}
+
/*******************************************************************************
*******************************************************************************/
@@ -383,6 +413,16 @@ void QGeoRouteSegmentPrivateDefault::setValid(bool valid)
m_valid = valid;
}
+bool QGeoRouteSegmentPrivateDefault::isLegLastSegment() const
+{
+ return m_legLastSegment;
+}
+
+void QGeoRouteSegmentPrivateDefault::setLegLastSegment(bool lastSegment)
+{
+ m_legLastSegment = lastSegment;
+}
+
int QGeoRouteSegmentPrivateDefault::travelTime() const
{
return m_travelTime;
diff --git a/src/location/maps/qgeoroutesegment.h b/src/location/maps/qgeoroutesegment.h
index 3ce01151..1767e33f 100644
--- a/src/location/maps/qgeoroutesegment.h
+++ b/src/location/maps/qgeoroutesegment.h
@@ -61,6 +61,7 @@ public:
bool operator !=(const QGeoRouteSegment &other) const;
bool isValid() const;
+ bool isLegLastSegment() const;
void setNextRouteSegment(const QGeoRouteSegment &routeSegment);
QGeoRouteSegment nextRouteSegment() const;
@@ -83,6 +84,8 @@ protected:
private:
QExplicitlySharedDataPointer<QGeoRouteSegmentPrivate> d_ptr;
+
+ friend class QGeoRouteSegmentPrivate;
};
QT_END_NAMESPACE
diff --git a/src/location/maps/qgeoroutesegment_p.h b/src/location/maps/qgeoroutesegment_p.h
index f0b180da..d72f8b22 100644
--- a/src/location/maps/qgeoroutesegment_p.h
+++ b/src/location/maps/qgeoroutesegment_p.h
@@ -74,6 +74,9 @@ public:
virtual bool valid() const;
virtual void setValid(bool valid);
+ virtual bool isLegLastSegment() const;
+ virtual void setLegLastSegment(bool lastSegment);
+
virtual int travelTime() const;
virtual void setTravelTime(int travelTime);
@@ -90,6 +93,7 @@ public:
virtual void setNextRouteSegment(const QExplicitlySharedDataPointer<QGeoRouteSegmentPrivate> &next);
QExplicitlySharedDataPointer<QGeoRouteSegmentPrivate> m_nextSegment;
+ static QGeoRouteSegmentPrivate *get(QGeoRouteSegment &segment);
protected:
virtual bool equals(const QGeoRouteSegmentPrivate &other) const;
@@ -110,6 +114,9 @@ public:
virtual bool valid() const override;
virtual void setValid(bool valid) override;
+ virtual bool isLegLastSegment() const override;
+ virtual void setLegLastSegment(bool lastSegment) override;
+
virtual int travelTime() const override;
virtual void setTravelTime(int travelTime) override;
@@ -124,6 +131,7 @@ public:
bool m_valid;
+ bool m_legLastSegment = false;
int m_travelTime;
qreal m_distance;
QList<QGeoCoordinate> m_path;
diff --git a/src/location/maps/qgeoserviceprovider.cpp b/src/location/maps/qgeoserviceprovider.cpp
index 2d8151ad..d25c379a 100644
--- a/src/location/maps/qgeoserviceprovider.cpp
+++ b/src/location/maps/qgeoserviceprovider.cpp
@@ -362,7 +362,7 @@ template <> QNavigationManagerEngine *createEngine<QNavigationManagerEngine>(QGe
{
if (!d_ptr->factoryV2)
return nullptr;
- return d_ptr->factoryV2->createNavigationManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->placeError), &(d_ptr->placeErrorString));
+ return d_ptr->factoryV2->createNavigationManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->navigationError), &(d_ptr->navigationErrorString));
}
/* Template for generating the code for each of the geocodingManager(),
@@ -381,11 +381,15 @@ Manager *QGeoServiceProviderPrivate::manager(QGeoServiceProvider::Error *_error,
this->loadPlugin(this->parameterMap);
}
- if (!this->factory || error != QGeoServiceProvider::NoError)
+ if (!this->factory) {
+ error = this->error;
+ errorString = this->errorString;
return 0;
+ }
if (!manager) {
- Engine *engine = createEngine<Engine>(this);
+ Engine *engine = createEngine<Engine>(this); // this sets the specific error variables directly,
+ // from now on the local error, errorString refs should be set.
if (engine) {
engine->setManagerName(
@@ -534,9 +538,13 @@ QPlaceManager *QGeoServiceProvider::placeManager() const
*/
QNavigationManager *QGeoServiceProvider::navigationManager() const
{
- return d_ptr->manager<QNavigationManager, QNavigationManagerEngine>(
+ QNavigationManager * mgr = d_ptr->manager<QNavigationManager, QNavigationManagerEngine>(
&(d_ptr->navigationError), &(d_ptr->navigationErrorString),
&(d_ptr->navigationManager));
+ if (!mgr) {
+ qDebug() << d_ptr->navigationError << d_ptr->navigationErrorString;
+ }
+ return mgr;
}
/*!
@@ -572,6 +580,11 @@ void QGeoServiceProvider::setAllowExperimental(bool allow)
d_ptr->loadMeta();
}
+void QGeoServiceProvider::setQmlEngine(QQmlEngine *engine)
+{
+ d_ptr->qmlEngine = engine;
+}
+
/*!
Sets the parameters used to construct individual manager classes for
this service provider to \a parameters.
@@ -660,7 +673,7 @@ void QGeoServiceProviderPrivate::unload()
delete navigationManager;
navigationManager = nullptr;
- factory = factoryV2 = nullptr;
+ factory = factoryV2 = factoryV3 = nullptr;
error = QGeoServiceProvider::NoError;
errorString = QLatin1String("");
metaData = QJsonObject();
@@ -690,7 +703,7 @@ void QGeoServiceProviderPrivate::filterParameterMap()
void QGeoServiceProviderPrivate::loadMeta()
{
- factory = factoryV2 = nullptr;
+ factory = factoryV2 = factoryV3 = nullptr;
metaData = QJsonObject();
metaData.insert(QStringLiteral("index"), -1);
error = QGeoServiceProvider::NotSupportedError;
@@ -731,7 +744,7 @@ void QGeoServiceProviderPrivate::loadPlugin(const QVariantMap &parameters)
if (int(metaData.value(QStringLiteral("index")).toDouble()) < 0) {
error = QGeoServiceProvider::NotSupportedError;
errorString = QString(QLatin1String("The geoservices provider is not supported."));
- factory = factoryV2 = nullptr;
+ factory = factoryV2 = factoryV3 = nullptr;
return;
}
@@ -742,11 +755,22 @@ void QGeoServiceProviderPrivate::loadPlugin(const QVariantMap &parameters)
// load the actual plugin
QObject *instance = loader()->instance(idx);
- factoryV2 = qobject_cast<QGeoServiceProviderFactoryV2 *>(instance);
- if (!factoryV2)
- factory = qobject_cast<QGeoServiceProviderFactory *>(instance);
- else
- factory = factoryV2;
+ if (!instance) {
+ error = QGeoServiceProvider::LoaderError;
+ errorString = QLatin1String("loader()->instance(idx) failed to return an instance. Set the environment variable QT_DEBUG_PLUGINS to see more details.");
+ return;
+ }
+ factoryV3 = qobject_cast<QGeoServiceProviderFactoryV3 *>(instance);
+ if (!factoryV3) {
+ factoryV2 = qobject_cast<QGeoServiceProviderFactoryV2 *>(instance);
+ if (!factoryV2)
+ factory = qobject_cast<QGeoServiceProviderFactory *>(instance);
+ else
+ factory = factoryV2;
+ } else {
+ factory = factoryV2 = factoryV3;
+ factoryV3->setQmlEngine(qmlEngine);
+ }
}
QHash<QString, QJsonObject> QGeoServiceProviderPrivate::plugins(bool reload)
diff --git a/src/location/maps/qgeoserviceprovider.h b/src/location/maps/qgeoserviceprovider.h
index 640e9843..b2e0be05 100644
--- a/src/location/maps/qgeoserviceprovider.h
+++ b/src/location/maps/qgeoserviceprovider.h
@@ -57,6 +57,7 @@ class QGeoRoutingManagerEngine;
class QPlaceManagerEngine;
class QNavigationManagerEngine;
class QGeoServiceProviderPrivate;
+class QQmlEngine;
class Q_LOCATION_EXPORT QGeoServiceProvider : public QObject
{
@@ -68,7 +69,8 @@ public:
NotSupportedError,
UnknownParameterError,
MissingRequiredParameterError,
- ConnectionError
+ ConnectionError,
+ LoaderError
};
enum RoutingFeature {
@@ -162,6 +164,7 @@ public:
void setParameters(const QVariantMap &parameters);
void setLocale(const QLocale &locale);
void setAllowExperimental(bool allow);
+ void setQmlEngine(QQmlEngine *engine);
private:
QGeoServiceProviderPrivate *d_ptr;
diff --git a/src/location/maps/qgeoserviceprovider_p.h b/src/location/maps/qgeoserviceprovider_p.h
index 11b86bad..c6b03ce5 100644
--- a/src/location/maps/qgeoserviceprovider_p.h
+++ b/src/location/maps/qgeoserviceprovider_p.h
@@ -63,6 +63,8 @@ class QGeoMappingManager;
class QGeoServiceProviderFactory;
class QGeoServiceProviderFactoryV2;
+class QGeoServiceProviderFactoryV3;
+class QQmlEngine;
class QGeoServiceProviderPrivate
{
@@ -84,6 +86,7 @@ public:
QGeoServiceProviderFactory *factory;
QGeoServiceProviderFactoryV2 *factoryV2 = nullptr;
+ QGeoServiceProviderFactoryV3 *factoryV3 = nullptr;
QJsonObject metaData;
QVariantMap parameterMap;
@@ -96,6 +99,7 @@ public:
QGeoMappingManager *mappingManager;
QPlaceManager *placeManager;
QNavigationManager *navigationManager = nullptr;
+ QQmlEngine *qmlEngine = nullptr;
QGeoServiceProvider::Error geocodeError;
QGeoServiceProvider::Error routingError;
diff --git a/src/location/maps/qgeoserviceproviderfactory.cpp b/src/location/maps/qgeoserviceproviderfactory.cpp
index 44ed3535..65a88710 100644
--- a/src/location/maps/qgeoserviceproviderfactory.cpp
+++ b/src/location/maps/qgeoserviceproviderfactory.cpp
@@ -207,4 +207,17 @@ QNavigationManagerEngine *QGeoServiceProviderFactoryV2::createNavigationManagerE
return 0;
}
+/*!
+ Notify the plugin when the qml engine is ready. In this moment the plugins can use it
+ to register Image Providers.
+
+ The default implementation does nothing.
+ \since 5.12
+*/
+void QGeoServiceProviderFactoryV3::setQmlEngine(QQmlEngine *engine)
+{
+ Q_UNUSED(engine)
+}
+
QT_END_NAMESPACE
+
diff --git a/src/location/maps/qgeoserviceproviderfactory.h b/src/location/maps/qgeoserviceproviderfactory.h
index 1eb93a18..8b3b0389 100644
--- a/src/location/maps/qgeoserviceproviderfactory.h
+++ b/src/location/maps/qgeoserviceproviderfactory.h
@@ -44,6 +44,7 @@
#include <QtCore/QString>
QT_BEGIN_NAMESPACE
+class QQmlEngine;
class Q_LOCATION_EXPORT QGeoServiceProviderFactory
{
@@ -82,6 +83,19 @@ public:
Q_DECLARE_INTERFACE(QGeoServiceProviderFactoryV2,
"org.qt-project.qt.geoservice.serviceproviderfactoryV2/5.0")
+class Q_LOCATION_EXPORT QGeoServiceProviderFactoryV3 : public QGeoServiceProviderFactoryV2
+{
+public:
+ virtual ~QGeoServiceProviderFactoryV3() {}
+
+ virtual void setQmlEngine(QQmlEngine * engine);
+};
+
+// Although not actually used for constructing a specialized loader, this is required for
+// casting a QObject * into QGeoServiceProviderFactoryV3 *
+Q_DECLARE_INTERFACE(QGeoServiceProviderFactoryV3,
+ "org.qt-project.qt.geoservice.serviceproviderfactoryV3/5.0")
+
QT_END_NAMESPACE
#endif
diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp
index a1231cf4..74346fdb 100644
--- a/src/location/maps/qgeotiledmap.cpp
+++ b/src/location/maps/qgeotiledmap.cpp
@@ -149,7 +149,8 @@ QGeoMap::Capabilities QGeoTiledMap::capabilities() const
{
return Capabilities(SupportsVisibleRegion
| SupportsSetBearing
- | SupportsAnchoringCoordinate);
+ | SupportsAnchoringCoordinate
+ | SupportsVisibleArea);
}
void QGeoTiledMap::setCopyrightVisible(bool visible)
@@ -353,6 +354,31 @@ void QGeoTiledMapPrivate::updateScene()
emit q->sgNodeChanged();
}
+void QGeoTiledMapPrivate::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_Q(QGeoTiledMap);
+ const QRectF va = clampVisibleArea(visibleArea);
+ if (va == m_visibleArea)
+ return;
+
+ m_visibleArea = va;
+ m_geoProjection->setVisibleArea(va);
+
+ m_visibleTiles->setVisibleArea(va);
+ m_prefetchTiles->setVisibleArea(va);
+ m_mapScene->setVisibleArea(va);
+
+ if (m_copyrightVisible)
+ q->evaluateCopyrights(m_mapScene->visibleTiles());
+ updateScene();
+ q->sgNodeChanged();
+}
+
+QRectF QGeoTiledMapPrivate::visibleArea() const
+{
+ return m_visibleArea;
+}
+
void QGeoTiledMapPrivate::changeActiveMapType(const QGeoMapType mapType)
{
m_visibleTiles->setTileSize(m_cameraCapabilities.tileSize());
diff --git a/src/location/maps/qgeotiledmap_p_p.h b/src/location/maps/qgeotiledmap_p_p.h
index d3791d49..80f658e0 100644
--- a/src/location/maps/qgeotiledmap_p_p.h
+++ b/src/location/maps/qgeotiledmap_p_p.h
@@ -91,12 +91,20 @@ protected:
void updateScene();
+ void setVisibleArea(const QRectF &visibleArea) override;
+ QRectF visibleArea() const override;
+
+#ifdef QT_LOCATION_DEBUG
+public:
+#else
protected:
+#endif
QAbstractGeoTileCache *m_cache;
QGeoCameraTiles *m_visibleTiles;
QGeoCameraTiles *m_prefetchTiles;
QGeoTiledMapScene *m_mapScene;
QGeoTileRequestManager *m_tileRequests;
+ QRectF m_visibleArea;
int m_maxZoomLevel;
int m_minZoomLevel;
QGeoTiledMap::PrefetchStyle m_prefetchStyle;
diff --git a/src/location/maps/qgeotiledmapscene.cpp b/src/location/maps/qgeotiledmapscene.cpp
index ab15e37b..074b67c6 100644
--- a/src/location/maps/qgeotiledmapscene.cpp
+++ b/src/location/maps/qgeotiledmapscene.cpp
@@ -35,15 +35,14 @@
**
****************************************************************************/
#include "qgeotiledmapscene_p.h"
+#include "qgeotiledmapscene_p_p.h"
#include "qgeocameradata_p.h"
#include "qabstractgeotilecache_p.h"
#include "qgeotilespec_p.h"
#include <QtPositioning/private/qdoublevector3d_p.h>
#include <QtPositioning/private/qwebmercator_p.h>
#include <QtCore/private/qobject_p.h>
-#include <QtQuick/QSGImageNode>
#include <QtQuick/QQuickWindow>
-#include <QtQuick/private/qsgdefaultimagenode_p.h>
#include <QtGui/QVector3D>
#include <cmath>
#include <QtPositioning/private/qlocationutils_p.h>
@@ -57,60 +56,6 @@ static QVector3D toVector3D(const QDoubleVector3D& in)
QT_BEGIN_NAMESPACE
-class QGeoTiledMapScenePrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QGeoTiledMapScene)
-public:
- QGeoTiledMapScenePrivate();
- ~QGeoTiledMapScenePrivate();
-
- QSize m_screenSize; // in pixels
- int m_tileSize; // the pixel resolution for each tile
- QGeoCameraData m_cameraData;
- QSet<QGeoTileSpec> m_visibleTiles;
-
- QDoubleVector3D m_cameraUp;
- QDoubleVector3D m_cameraEye;
- QDoubleVector3D m_cameraCenter;
- QMatrix4x4 m_projectionMatrix;
-
- // scales up the tile geometry and the camera altitude, resulting in no visible effect
- // other than to control the accuracy of the render by keeping the values in a sensible range
- double m_scaleFactor;
-
- // rounded down, positive zoom is zooming in, corresponding to reduced altitude
- int m_intZoomLevel;
-
- // mercatorToGrid transform
- // the number of tiles in each direction for the whole map (earth) at the current zoom level.
- // it is 1<<zoomLevel
- int m_sideLength;
- double m_mapEdgeSize;
-
- QHash<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > m_textures;
- QVector<QGeoTileSpec> m_updatedTextures;
-
- // tilesToGrid transform
- int m_minTileX; // the minimum tile index, i.e. 0 to sideLength which is 1<< zoomLevel
- int m_minTileY;
- int m_maxTileX;
- int m_maxTileY;
- int m_tileXWrapsBelow; // the wrap point as a tile index
-
- bool m_linearScaling;
-
- bool m_dropTextures;
-
- void addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture);
-
- void setVisibleTiles(const QSet<QGeoTileSpec> &visibleTiles);
- void removeTiles(const QSet<QGeoTileSpec> &oldTiles);
- bool buildGeometry(const QGeoTileSpec &spec, QSGImageNode *imageNode, bool &overzooming);
- void updateTileBounds(const QSet<QGeoTileSpec> &tiles);
- void setupCamera();
- inline bool isTiltedOrRotated() { return (m_cameraData.tilt() > 0.0) || (m_cameraData.bearing() > 0.0); }
-};
-
QGeoTiledMapScene::QGeoTiledMapScene(QObject *parent)
: QObject(*new QGeoTiledMapScenePrivate(),parent)
{
@@ -153,6 +98,15 @@ void QGeoTiledMapScene::setCameraData(const QGeoCameraData &cameraData)
updateSceneParameters();
}
+void QGeoTiledMapScene::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_D(QGeoTiledMapScene);
+ if (d->m_visibleArea == visibleArea)
+ return;
+ d->m_visibleArea = visibleArea;
+ updateSceneParameters();
+}
+
void QGeoTiledMapScene::setVisibleTiles(const QSet<QGeoTileSpec> &tiles)
{
Q_D(QGeoTiledMapScene);
@@ -191,7 +145,11 @@ void QGeoTiledMapScene::clearTexturedTiles()
QGeoTiledMapScenePrivate::QGeoTiledMapScenePrivate()
: QObjectPrivate(),
m_tileSize(0),
+#ifdef QT_LOCATION_DEBUG
+ m_scaleFactor(1.0),
+#else
m_scaleFactor(10.0),
+#endif
m_intZoomLevel(0),
m_sideLength(0),
m_minTileX(-1),
@@ -465,74 +423,33 @@ void QGeoTiledMapScenePrivate::setupCamera()
float halfHeight = 1 * apertureSize;
halfWidth *= aspectRatio;
- m_projectionMatrix.setToIdentity();
- m_projectionMatrix.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight, nearPlane, farPlane);
-}
-
-class QGeoTiledMapTileContainerNode : public QSGTransformNode
-{
-public:
- void addChild(const QGeoTileSpec &spec, QSGImageNode *node)
- {
- tiles.insert(spec, node);
- appendChildNode(node);
- }
- QHash<QGeoTileSpec, QSGImageNode *> tiles;
-};
-
-class QGeoTiledMapRootNode : public QSGClipNode
-{
-public:
- QGeoTiledMapRootNode()
- : isTextureLinear(false)
- , geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
- , root(new QSGTransformNode())
- , tiles(new QGeoTiledMapTileContainerNode())
- , wrapLeft(new QGeoTiledMapTileContainerNode())
- , wrapRight(new QGeoTiledMapTileContainerNode())
- {
- setIsRectangular(true);
- setGeometry(&geometry);
- root->appendChildNode(tiles);
- root->appendChildNode(wrapLeft);
- root->appendChildNode(wrapRight);
- appendChildNode(root);
- }
-
- ~QGeoTiledMapRootNode()
- {
- qDeleteAll(textures);
- }
-
- void setClipRect(const QRect &rect)
- {
- if (rect != clipRect) {
- QSGGeometry::updateRectGeometry(&geometry, rect);
- QSGClipNode::setClipRect(rect);
- clipRect = rect;
- markDirty(DirtyGeometry);
- }
- }
-
- void updateTiles(QGeoTiledMapTileContainerNode *root,
- QGeoTiledMapScenePrivate *d,
- double camAdjust,
- QQuickWindow *window,
- bool ogl);
+// m_projectionMatrix.setToIdentity();
+// m_projectionMatrix.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight, nearPlane, farPlane);
- bool isTextureLinear;
+ QRectF va = m_visibleArea;
+ if (va.isNull())
+ va = QRectF(0, 0, m_screenSize.width(), m_screenSize.height());
- QSGGeometry geometry;
- QRect clipRect;
+ QRectF screen = QRectF(QPointF(0,0),m_screenSize);
+ QPointF vaCenter = va.center();
- QSGTransformNode *root;
+ QPointF screenCenter = screen.center();
+ QPointF diff = screenCenter - vaCenter;
+ float xdiffpct = diff.x() / m_screenSize.width();
+ float ydiffpct = -(diff.y() / m_screenSize.height());
- QGeoTiledMapTileContainerNode *tiles; // The majority of the tiles
- QGeoTiledMapTileContainerNode *wrapLeft; // When zoomed out, the tiles that wrap around on the left.
- QGeoTiledMapTileContainerNode *wrapRight; // When zoomed out, the tiles that wrap around on the right
-
- QHash<QGeoTileSpec, QSGTexture *> textures;
-};
+ m_projectionMatrix.setToIdentity();
+ float l = -halfWidth + (2 * halfWidth) * xdiffpct;
+ float r = halfWidth + (2 * halfWidth) * xdiffpct;
+ float t = halfHeight + (2 * halfHeight) * ydiffpct;
+ float b = -halfHeight + (2 * halfHeight) * ydiffpct;
+
+ m_projectionMatrix.frustum(l,
+ r,
+ b,
+ t,
+ nearPlane, farPlane);
+}
static bool qgeotiledmapscene_isTileInViewport_Straight(const QRectF &tileRect, const QMatrix4x4 &matrix)
{
@@ -587,6 +504,9 @@ void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
bool straight = !d->isTiltedOrRotated();
bool overzooming;
qreal pixelRatio = window->effectiveDevicePixelRatio();
+#ifdef QT_LOCATION_DEBUG
+ QList<QGeoTileSpec> droppedTiles;
+#endif
for (QHash<QGeoTileSpec, QSGImageNode *>::iterator it = root->tiles.begin();
it != root->tiles.end(); ) {
QSGImageNode *node = it.value();
@@ -596,6 +516,9 @@ void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
QSGNode::DirtyState dirtyBits = 0;
if (!ok) {
+#ifdef QT_LOCATION_DEBUG
+ droppedTiles.append(it.key());
+#endif
it = root->tiles.erase(it);
delete node;
} else {
@@ -622,8 +545,12 @@ void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
for (const QGeoTileSpec &s : toAdd) {
QGeoTileTexture *tileTexture = d->m_textures.value(s).data();
- if (!tileTexture || tileTexture->image.isNull())
+ if (!tileTexture || tileTexture->image.isNull()) {
+#ifdef QT_LOCATION_DEBUG
+ droppedTiles.append(s);
+#endif
continue;
+ }
QSGImageNode *tileNode = window->createImageNode();
// note: setTexture will update coordinates so do it here, before we buildGeometry
tileNode->setTexture(textures.value(s));
@@ -641,9 +568,16 @@ void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
#endif
root->addChild(s, tileNode);
} else {
+#ifdef QT_LOCATION_DEBUG
+ droppedTiles.append(s);
+#endif
delete tileNode;
}
}
+
+#ifdef QT_LOCATION_DEBUG
+ m_droppedTiles[camAdjust] = droppedTiles;
+#endif
}
QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window)
@@ -661,6 +595,11 @@ QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *win
if (!mapRoot)
mapRoot = new QGeoTiledMapRootNode();
+#ifdef QT_LOCATION_DEBUG
+ mapRoot->m_droppedTiles.clear();
+ d->m_mapRoot = mapRoot;
+#endif
+
// Setting clip rect to fullscreen, as now the map can never be smaller than the viewport.
mapRoot->setClipRect(QRect(0, 0, w, h));
@@ -715,6 +654,9 @@ QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *win
}
double sideLength = d->m_scaleFactor * d->m_tileSize * d->m_sideLength;
+#ifdef QT_LOCATION_DEBUG
+ d->m_sideLengthPixel = sideLength;
+#endif
mapRoot->updateTiles(mapRoot->tiles, d, 0, window, isOpenGL);
mapRoot->updateTiles(mapRoot->wrapLeft, d, +sideLength, window, isOpenGL);
mapRoot->updateTiles(mapRoot->wrapRight, d, -sideLength, window, isOpenGL);
diff --git a/src/location/maps/qgeotiledmapscene_p.h b/src/location/maps/qgeotiledmapscene_p.h
index f6a8f714..ac607f41 100644
--- a/src/location/maps/qgeotiledmapscene_p.h
+++ b/src/location/maps/qgeotiledmapscene_p.h
@@ -72,6 +72,7 @@ public:
void setScreenSize(const QSize &size);
void setTileSize(int tileSize);
void setCameraData(const QGeoCameraData &cameraData);
+ void setVisibleArea(const QRectF &visibleArea);
void setVisibleTiles(const QSet<QGeoTileSpec> &tiles);
const QSet<QGeoTileSpec> &visibleTiles() const;
diff --git a/src/location/maps/qgeotiledmapscene_p_p.h b/src/location/maps/qgeotiledmapscene_p_p.h
new file mode 100644
index 00000000..5d98abd5
--- /dev/null
+++ b/src/location/maps/qgeotiledmapscene_p_p.h
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QGEOTILEDMAPSCENE_P_P_H
+#define QGEOTILEDMAPSCENE_P_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qgeotiledmapscene_p.h"
+#include <QtCore/private/qobject_p.h>
+#include <QtPositioning/private/qdoublevector3d_p.h>
+#include <QtQuick/QSGImageNode>
+#include <QtQuick/private/qsgdefaultimagenode_p.h>
+#include <QtQuick/QQuickWindow>
+#include "qgeocameradata_p.h"
+#include "qgeotilespec_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QGeoTiledMapTileContainerNode : public QSGTransformNode
+{
+public:
+ void addChild(const QGeoTileSpec &spec, QSGImageNode *node)
+ {
+ tiles.insert(spec, node);
+ appendChildNode(node);
+ }
+ QHash<QGeoTileSpec, QSGImageNode *> tiles;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QGeoTiledMapRootNode : public QSGClipNode
+{
+public:
+ QGeoTiledMapRootNode()
+ : isTextureLinear(false)
+ , geometry(QSGGeometry::defaultAttributes_Point2D(), 4)
+ , root(new QSGTransformNode())
+ , tiles(new QGeoTiledMapTileContainerNode())
+ , wrapLeft(new QGeoTiledMapTileContainerNode())
+ , wrapRight(new QGeoTiledMapTileContainerNode())
+ {
+ setIsRectangular(true);
+ setGeometry(&geometry);
+ root->appendChildNode(tiles);
+ root->appendChildNode(wrapLeft);
+ root->appendChildNode(wrapRight);
+ appendChildNode(root);
+ }
+
+ ~QGeoTiledMapRootNode()
+ {
+ qDeleteAll(textures);
+ }
+
+ void setClipRect(const QRect &rect)
+ {
+ if (rect != clipRect) {
+ QSGGeometry::updateRectGeometry(&geometry, rect);
+ QSGClipNode::setClipRect(rect);
+ clipRect = rect;
+ markDirty(DirtyGeometry);
+ }
+ }
+
+ void updateTiles(QGeoTiledMapTileContainerNode *root,
+ QGeoTiledMapScenePrivate *d,
+ double camAdjust,
+ QQuickWindow *window,
+ bool ogl);
+
+ bool isTextureLinear;
+
+ QSGGeometry geometry;
+ QRect clipRect;
+
+ QSGTransformNode *root;
+
+ QGeoTiledMapTileContainerNode *tiles; // The majority of the tiles
+ QGeoTiledMapTileContainerNode *wrapLeft; // When zoomed out, the tiles that wrap around on the left.
+ QGeoTiledMapTileContainerNode *wrapRight; // When zoomed out, the tiles that wrap around on the right
+
+ QHash<QGeoTileSpec, QSGTexture *> textures;
+
+#ifdef QT_LOCATION_DEBUG
+ double m_sideLengthPixel;
+ QMap<double, QList<QGeoTileSpec>> m_droppedTiles;
+#endif
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QGeoTiledMapScenePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QGeoTiledMapScene)
+public:
+ QGeoTiledMapScenePrivate();
+ ~QGeoTiledMapScenePrivate();
+
+ void addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture);
+
+ void setVisibleTiles(const QSet<QGeoTileSpec> &visibleTiles);
+ void removeTiles(const QSet<QGeoTileSpec> &oldTiles);
+ bool buildGeometry(const QGeoTileSpec &spec, QSGImageNode *imageNode, bool &overzooming);
+ void updateTileBounds(const QSet<QGeoTileSpec> &tiles);
+ void setupCamera();
+ inline bool isTiltedOrRotated() { return (m_cameraData.tilt() > 0.0) || (m_cameraData.bearing() > 0.0); }
+
+public:
+
+ QSize m_screenSize; // in pixels
+ int m_tileSize; // the pixel resolution for each tile
+ QGeoCameraData m_cameraData;
+ QRectF m_visibleArea;
+ QSet<QGeoTileSpec> m_visibleTiles;
+
+ QDoubleVector3D m_cameraUp;
+ QDoubleVector3D m_cameraEye;
+ QDoubleVector3D m_cameraCenter;
+ QMatrix4x4 m_projectionMatrix;
+
+ // scales up the tile geometry and the camera altitude, resulting in no visible effect
+ // other than to control the accuracy of the render by keeping the values in a sensible range
+ double m_scaleFactor;
+
+ // rounded down, positive zoom is zooming in, corresponding to reduced altitude
+ int m_intZoomLevel;
+
+ // mercatorToGrid transform
+ // the number of tiles in each direction for the whole map (earth) at the current zoom level.
+ // it is 1<<zoomLevel
+ int m_sideLength;
+ double m_mapEdgeSize;
+
+ QHash<QGeoTileSpec, QSharedPointer<QGeoTileTexture> > m_textures;
+ QVector<QGeoTileSpec> m_updatedTextures;
+
+ // tilesToGrid transform
+ int m_minTileX; // the minimum tile index, i.e. 0 to sideLength which is 1<< zoomLevel
+ int m_minTileY;
+ int m_maxTileX;
+ int m_maxTileY;
+ int m_tileXWrapsBelow; // the wrap point as a tile index
+ bool m_linearScaling;
+ bool m_dropTextures;
+
+#ifdef QT_LOCATION_DEBUG
+ double m_sideLengthPixel;
+ QGeoTiledMapRootNode *m_mapRoot = nullptr;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOTILEDMAPSCENE_P_P_H
diff --git a/src/location/maps/qnavigationmanager.cpp b/src/location/maps/qnavigationmanager.cpp
index 5372e3a5..5cae6a04 100644
--- a/src/location/maps/qnavigationmanager.cpp
+++ b/src/location/maps/qnavigationmanager.cpp
@@ -46,8 +46,6 @@ public:
~QNavigationManagerPrivate();
QNavigationManagerEngine *engine = nullptr;
- QDeclarativeNavigatorPrivate *navigator = nullptr;
- QList<QGeoMapParameter *> parameters;
private:
Q_DISABLE_COPY(QNavigationManagerPrivate)
@@ -89,16 +87,6 @@ bool QNavigationManager::isInitialized() const
return d_ptr->engine->isInitialized();
}
-void QNavigationManager::setNavigator(QDeclarativeNavigatorPrivate *navigator)
-{
- d_ptr->navigator = navigator;
-}
-
-QDeclarativeNavigatorPrivate *QNavigationManager::declarativeNavigator() const
-{
- return d_ptr->navigator;
-}
-
void QNavigationManager::setLocale(const QLocale &locale)
{
d_ptr->engine->setLocale(locale);
@@ -109,34 +97,19 @@ QLocale QNavigationManager::locale() const
return d_ptr->engine->locale();
}
-void QNavigationManager::setParameters(const QList<QGeoMapParameter *> &parameters)
-{
- d_ptr->parameters = parameters;
-}
-
-QList<QGeoMapParameter *> QNavigationManager::parameters() const
-{
- return d_ptr->parameters;
-}
-
-bool QNavigationManager::ready() const
-{
- return d_ptr->engine->ready(*d_ptr->navigator, d_ptr->parameters);
-}
-
-bool QNavigationManager::start()
+void QNavigationManager::setMeasurementSystem(QLocale::MeasurementSystem system)
{
- return d_ptr->engine->start(*d_ptr->navigator, d_ptr->parameters);
+ d_ptr->engine->setMeasurementSystem(system);
}
-bool QNavigationManager::stop()
+QLocale::MeasurementSystem QNavigationManager::measurementSystem() const
{
- return d_ptr->engine->stop(*d_ptr->navigator);
+ return d_ptr->engine->measurementSystem();
}
-bool QNavigationManager::active() const
+QAbstractNavigator *QNavigationManager::createNavigator(const QSharedPointer<QDeclarativeNavigatorParams> &navigator)
{
- return d_ptr->engine->active(*d_ptr->navigator);
+ return d_ptr->engine->createNavigator(navigator);
}
QNavigationManager::QNavigationManager(QNavigationManagerEngine *engine, QObject *parent) : QObject(parent),
diff --git a/src/location/maps/qnavigationmanager_p.h b/src/location/maps/qnavigationmanager_p.h
index 1d8c1722..544e15f5 100644
--- a/src/location/maps/qnavigationmanager_p.h
+++ b/src/location/maps/qnavigationmanager_p.h
@@ -51,6 +51,7 @@
#include <QObject>
#include <QSize>
#include <QPair>
+#include <QLocale>
#include <QtLocation/private/qlocationglobal_p.h>
#include <QtLocation/private/qgeomapparameter_p.h>
@@ -58,11 +59,11 @@ QT_BEGIN_NAMESPACE
class QNavigationManagerEngine;
class QNavigationManagerPrivate;
-class QDeclarativeNavigatorPrivate;
+class QDeclarativeNavigatorParams;
class QDeclarativeGeoWaypoint;
class QGeoRoute;
class QGeoRouteSegment;
-
+class QAbstractNavigator;
class Q_LOCATION_PRIVATE_EXPORT QNavigationManager : public QObject
{
Q_OBJECT
@@ -75,32 +76,19 @@ public:
QNavigationManagerEngine *engine();
bool isInitialized() const;
- void setNavigator(QDeclarativeNavigatorPrivate *navigator);
- QDeclarativeNavigatorPrivate *declarativeNavigator() const;
-
void setLocale(const QLocale &locale);
QLocale locale() const;
+ void setMeasurementSystem(QLocale::MeasurementSystem system);
+ QLocale::MeasurementSystem measurementSystem() const;
- void setParameters(const QList<QGeoMapParameter *> &parameters);
- QList<QGeoMapParameter *> parameters() const;
-
- bool ready() const;
- bool start();
- bool stop();
- bool active() const;
+ QAbstractNavigator *createNavigator(const QSharedPointer<QDeclarativeNavigatorParams> &navigator);
Q_SIGNALS:
void initialized();
- // These must be emitted by the engine
- void activeChanged(bool active);
- void waypointReached(const QDeclarativeGeoWaypoint *pos);
- void destinationReached();
- void currentRouteChanged(const QGeoRoute &route);
- void currentSegmentChanged(int segment);
protected:
- QNavigationManager(QNavigationManagerEngine *engine, QObject *parent = 0);
+ QNavigationManager(QNavigationManagerEngine *engine, QObject *parent = nullptr);
private:
QNavigationManagerPrivate *d_ptr;
diff --git a/src/location/maps/qnavigationmanagerengine.cpp b/src/location/maps/qnavigationmanagerengine.cpp
index b9191e74..770e30a6 100644
--- a/src/location/maps/qnavigationmanagerengine.cpp
+++ b/src/location/maps/qnavigationmanagerengine.cpp
@@ -49,9 +49,46 @@ public:
bool initialized = false;
};
+class QAbstractNavigatorPrivate
+{
+public:
+ QLocale locale;
+ QLocale::MeasurementSystem measurementSystem;
+};
+
+QAbstractNavigator::QAbstractNavigator(QObject *parent)
+ : QObject(parent)
+ , d(new QAbstractNavigatorPrivate)
+{
+}
+
+QAbstractNavigator::~QAbstractNavigator()
+{
+}
+
+void QAbstractNavigator::setLocale(const QLocale &locale)
+{
+ d->locale = locale;
+}
+
+QLocale QAbstractNavigator::locale() const
+{
+ return d->locale;
+}
+
+void QAbstractNavigator::setMeasurementSystem(QLocale::MeasurementSystem system)
+{
+ d->measurementSystem = system;
+}
+
+QLocale::MeasurementSystem QAbstractNavigator::measurementSystem() const
+{
+ return d->measurementSystem;
+}
+
QNavigationManagerEngine::QNavigationManagerEngine(const QVariantMap &parameters, QObject *parent)
: QObject(parent)
- , d_ptr(new QNavigationManagerEnginePrivate)
+ , d(new QNavigationManagerEnginePrivate)
{
Q_UNUSED(parameters)
}
@@ -62,64 +99,52 @@ QNavigationManagerEngine::~QNavigationManagerEngine()
void QNavigationManagerEngine::setManagerName(const QString &name)
{
- d_ptr->managerName = name;
+ d->managerName = name;
}
QString QNavigationManagerEngine::managerName() const
{
- return d_ptr->managerName;
+ return d->managerName;
}
void QNavigationManagerEngine::setManagerVersion(int version)
{
- d_ptr->managerVersion = version;
+ d->managerVersion = version;
}
int QNavigationManagerEngine::managerVersion() const
{
- return d_ptr->managerVersion;
+ return d->managerVersion;
}
void QNavigationManagerEngine::setLocale(const QLocale &locale)
{
- d_ptr->locale = locale;
+ d->locale = locale;
}
QLocale QNavigationManagerEngine::locale() const
{
- return d_ptr->locale;
+ return d->locale;
}
void QNavigationManagerEngine::setMeasurementSystem(QLocale::MeasurementSystem system)
{
- d_ptr->measurementSystem = system;
+ d->measurementSystem = system;
}
QLocale::MeasurementSystem QNavigationManagerEngine::measurementSystem() const
{
- return d_ptr->measurementSystem;
+ return d->measurementSystem;
}
bool QNavigationManagerEngine::isInitialized() const
{
- return d_ptr->initialized;
-}
-
-// Subclasses are supposed to emit activeChanged from here.
-bool QNavigationManagerEngine::start(QDeclarativeNavigatorPrivate & /*navigator*/, const QList<QGeoMapParameter*> & /*navigationParams*/)
-{
-
- return false;
-}
-
-bool QNavigationManagerEngine::stop(QDeclarativeNavigatorPrivate & /*navigator*/) // navigator needed to find the right navi session to stop.
-{
- return false;
+ return d->initialized;
}
void QNavigationManagerEngine::engineInitialized()
{
- d_ptr->initialized = true;
+ d->initialized = true;
emit initialized();
}
diff --git a/src/location/maps/qnavigationmanagerengine_p.h b/src/location/maps/qnavigationmanagerengine_p.h
index 803050c5..0852b3ea 100644
--- a/src/location/maps/qnavigationmanagerengine_p.h
+++ b/src/location/maps/qnavigationmanagerengine_p.h
@@ -55,39 +55,68 @@
QT_BEGIN_NAMESPACE
+class QAbstractNavigatorPrivate;
class QGeoMap;
class QGeoMapParameter;
class QMapRouteObject;
+class QGeoRoute;
+class QNavigationManager;
class QNavigationManagerEnginePrivate;
-class QDeclarativeNavigatorPrivate;
+class QDeclarativeNavigatorParams;
+class QDeclarativeGeoWaypoint;
+
+class Q_LOCATION_PRIVATE_EXPORT QAbstractNavigator: public QObject
+{
+ Q_OBJECT
+public:
+ QAbstractNavigator(QObject *parent = nullptr);
+ ~QAbstractNavigator() override;
+ virtual void setLocale(const QLocale &locale);
+ virtual QLocale locale() const;
+ virtual void setMeasurementSystem(QLocale::MeasurementSystem system);
+ virtual QLocale::MeasurementSystem measurementSystem() const;
+ virtual bool active() const = 0;
+ virtual bool ready() const = 0;
+
+public slots:
+ virtual bool start() = 0;
+ virtual bool stop() = 0;
+ virtual void setTrackPosition(bool trackPosition) = 0;
+
+signals:
+ // These must be emitted by the engine
+ void activeChanged(bool active);
+ void waypointReached(const QDeclarativeGeoWaypoint *pos);
+ void destinationReached();
+ void currentRouteChanged(const QGeoRoute &route);
+ void currentSegmentChanged(int segment);
+
+private:
+ QScopedPointer<QAbstractNavigatorPrivate> d;
+};
class Q_LOCATION_PRIVATE_EXPORT QNavigationManagerEngine : public QObject
{
Q_OBJECT
public:
explicit QNavigationManagerEngine(const QVariantMap &parameters, QObject *parent = nullptr);
- virtual ~QNavigationManagerEngine();
+ ~QNavigationManagerEngine() override;
void setManagerName(const QString &name);
QString managerName() const;
void setManagerVersion(int version);
int managerVersion() const;
-
virtual void setLocale(const QLocale &locale);
virtual QLocale locale() const;
virtual void setMeasurementSystem(QLocale::MeasurementSystem system);
virtual QLocale::MeasurementSystem measurementSystem() const;
+
virtual bool isInitialized() const;
- virtual bool ready(const QDeclarativeNavigatorPrivate &navigator, const QList<QGeoMapParameter*> &navigationParams) = 0;
- virtual bool active(const QDeclarativeNavigatorPrivate &navigator) = 0;
+ virtual QAbstractNavigator *createNavigator(const QSharedPointer<QDeclarativeNavigatorParams> &navigator) = 0;
signals:
void initialized();
-public slots:
- virtual bool start(QDeclarativeNavigatorPrivate &navigator, const QList<QGeoMapParameter*> &navigationParams);
- virtual bool stop(QDeclarativeNavigatorPrivate &navigator);
-
protected:
/*!
Marks the engine as initialized. Subclasses of QGeoMappingManagerEngine are to
@@ -96,7 +125,7 @@ protected:
*/
virtual void engineInitialized();
- QScopedPointer<QNavigationManagerEnginePrivate> d_ptr;
+ QScopedPointer<QNavigationManagerEnginePrivate> d;
};
QT_END_NAMESPACE
diff --git a/src/location/places/places.pri b/src/location/places/places.pri
index 1a3796fc..5a766b61 100644
--- a/src/location/places/places.pri
+++ b/src/location/places/places.pri
@@ -24,6 +24,7 @@ PUBLIC_HEADERS += \
places/qplacecontentrequest.h \
places/qplacematchrequest.h \
places/qplacesearchrequest.h \
+ places/qplacesearchrequest_p.h \
#reply classes
places/qplacereply.h \
places/qplacedetailsreply.h \
diff --git a/src/location/places/qplacereply.cpp b/src/location/places/qplacereply.cpp
index 55e67e43..29f1fb84 100644
--- a/src/location/places/qplacereply.cpp
+++ b/src/location/places/qplacereply.cpp
@@ -229,6 +229,19 @@ void QPlaceReply::abort()
*/
/*!
+ \fn void QPlaceReply::contentUpdated()
+
+ This signal is emitted when this reply has updated content available.
+ Depending on the plugin, this signal may never be emitted or emitted
+ multiple times before \l QPlaceReply::finished() is emitted, as some
+ backends are able to return the requested content asynchronously and
+ incrementally.
+
+ \note Do not delete or deleteLater this reply object in the slot
+ connected to this signal. Do it only upon \l QPlaceReply::finished.
+*/
+
+/*!
\fn void QPlaceReply::error(QPlaceReply::Error error, const QString &errorString)
This signal is emitted when an error has been detected in the processing of
diff --git a/src/location/places/qplacereply.h b/src/location/places/qplacereply.h
index 8fd34643..8e84f113 100644
--- a/src/location/places/qplacereply.h
+++ b/src/location/places/qplacereply.h
@@ -86,6 +86,7 @@ public Q_SLOTS:
Q_SIGNALS:
void finished();
+ void contentUpdated();
void aborted();
void error(QPlaceReply::Error error, const QString &errorString = QString());
diff --git a/src/location/places/qplacesearchrequest.cpp b/src/location/places/qplacesearchrequest.cpp
index c2d993e3..49e782c5 100644
--- a/src/location/places/qplacesearchrequest.cpp
+++ b/src/location/places/qplacesearchrequest.cpp
@@ -35,37 +35,17 @@
****************************************************************************/
#include "qplacesearchrequest.h"
+#include "qplacesearchrequest_p.h"
#include "qgeocoordinate.h"
#include "qgeoshape.h"
#include <QtCore/QSharedData>
#include <QtCore/QList>
#include <QtCore/QVariant>
+#include <QDebug>
QT_BEGIN_NAMESPACE
-class QPlaceSearchRequestPrivate : public QSharedData
-{
-public:
- QPlaceSearchRequestPrivate();
- QPlaceSearchRequestPrivate(const QPlaceSearchRequestPrivate &other);
- ~QPlaceSearchRequestPrivate();
-
- QPlaceSearchRequestPrivate &operator=(const QPlaceSearchRequestPrivate &other);
- bool operator==(const QPlaceSearchRequestPrivate &other) const;
-
- void clear();
-
- QString searchTerm;
- QList<QPlaceCategory> categories;
- QGeoShape searchArea;
- QString recommendationId;
- QLocation::VisibilityScope visibilityScope;
- QPlaceSearchRequest::RelevanceHint relevanceHint;
- int limit;
- QVariant searchContext;
-};
-
QPlaceSearchRequestPrivate::QPlaceSearchRequestPrivate()
: QSharedData(),
visibilityScope(QLocation::UnspecifiedVisibility),
@@ -83,7 +63,9 @@ QPlaceSearchRequestPrivate::QPlaceSearchRequestPrivate(const QPlaceSearchRequest
visibilityScope(other.visibilityScope),
relevanceHint(other.relevanceHint),
limit(other.limit),
- searchContext(other.searchContext)
+ searchContext(other.searchContext),
+ related(other.related),
+ page(other.page)
{
}
@@ -102,6 +84,8 @@ QPlaceSearchRequestPrivate &QPlaceSearchRequestPrivate::operator=(const QPlaceSe
relevanceHint = other.relevanceHint;
limit = other.limit;
searchContext = other.searchContext;
+ related = other.related;
+ page = other.page;
}
return *this;
@@ -117,6 +101,8 @@ bool QPlaceSearchRequestPrivate::operator==(const QPlaceSearchRequestPrivate &ot
relevanceHint == other.relevanceHint &&
limit == other.limit &&
searchContext == other.searchContext;
+
+ // deliberately not testing related and page. comparing only the content.
}
void QPlaceSearchRequestPrivate::clear()
@@ -129,6 +115,18 @@ void QPlaceSearchRequestPrivate::clear()
visibilityScope = QLocation::UnspecifiedVisibility;
relevanceHint = QPlaceSearchRequest::UnspecifiedHint;
searchContext.clear();
+ related = false;
+ page = 0;
+}
+
+const QPlaceSearchRequestPrivate *QPlaceSearchRequestPrivate::get(const QPlaceSearchRequest &request)
+{
+ return request.d_ptr.constData();
+}
+
+QPlaceSearchRequestPrivate *QPlaceSearchRequestPrivate::get(QPlaceSearchRequest &request)
+{
+ return request.d_ptr.data();
}
/*!
diff --git a/src/location/places/qplacesearchrequest.h b/src/location/places/qplacesearchrequest.h
index 09654503..d6611017 100644
--- a/src/location/places/qplacesearchrequest.h
+++ b/src/location/places/qplacesearchrequest.h
@@ -98,6 +98,8 @@ private:
QSharedDataPointer<QPlaceSearchRequestPrivate> d_ptr;
inline QPlaceSearchRequestPrivate *d_func();
inline const QPlaceSearchRequestPrivate *d_func() const;
+
+ friend class QPlaceSearchRequestPrivate;
};
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/mapitemviewdelegateincubator_p.h b/src/location/places/qplacesearchrequest_p.h
index 6ee9f6af..fdff89b8 100644
--- a/src/location/declarativemaps/mapitemviewdelegateincubator_p.h
+++ b/src/location/places/qplacesearchrequest_p.h
@@ -1,7 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Copyright (C) 2015 Jolla Ltd, author: Aaron McCarthy <aaron.mccarthy@jollamobile.com>
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
@@ -34,8 +33,9 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-#ifndef MAPITEMVIEWDELEGATEINCUBATOR_H
-#define MAPITEMVIEWDELEGATEINCUBATOR_H
+
+#ifndef QPLACESEARCHREQUEST_P_H
+#define QPLACESEARCHREQUEST_P_H
//
// W A R N I N G
@@ -48,30 +48,43 @@
// We mean it.
//
+#include "qplacesearchrequest.h"
+#include "qgeocoordinate.h"
+#include "qgeoshape.h"
+
+#include <QtCore/QSharedData>
+#include <QtCore/QList>
#include <QtLocation/private/qlocationglobal_p.h>
-#include <QtQml/QQmlIncubator>
+#include <QtCore/QVariant>
QT_BEGIN_NAMESPACE
-class QDeclarativeGeoMapItemView;
-class QDeclarativeGeoMapItemViewItemData;
-
-class Q_LOCATION_PRIVATE_EXPORT MapItemViewDelegateIncubator : public QQmlIncubator
+class Q_LOCATION_PRIVATE_EXPORT QPlaceSearchRequestPrivate : public QSharedData
{
public:
- MapItemViewDelegateIncubator(QDeclarativeGeoMapItemView *view, QDeclarativeGeoMapItemViewItemData *itemData, bool batched = true);
+ QPlaceSearchRequestPrivate();
+ QPlaceSearchRequestPrivate(const QPlaceSearchRequestPrivate &other);
+ ~QPlaceSearchRequestPrivate();
-protected:
- void statusChanged(Status status) override;
+ QPlaceSearchRequestPrivate &operator=(const QPlaceSearchRequestPrivate &other);
+ bool operator==(const QPlaceSearchRequestPrivate &other) const;
-private:
- QDeclarativeGeoMapItemView *m_view;
- QDeclarativeGeoMapItemViewItemData *m_itemData;
- bool m_batched;
+ void clear();
+ static const QPlaceSearchRequestPrivate *get(const QPlaceSearchRequest &request);
+ static QPlaceSearchRequestPrivate *get(QPlaceSearchRequest &request);
- friend class QDeclarativeGeoMapItemView;
+ QString searchTerm;
+ QList<QPlaceCategory> categories;
+ QGeoShape searchArea;
+ QString recommendationId;
+ QLocation::VisibilityScope visibilityScope;
+ QPlaceSearchRequest::RelevanceHint relevanceHint;
+ int limit;
+ QVariant searchContext;
+ bool related = false;
+ int page = 0;
};
QT_END_NAMESPACE
-#endif // MAPITEMVIEWDELEGATEINCUBATOR_H
+#endif // QPLACESEARCHREQUEST_P_H
diff --git a/src/plugins/geoservices/esri/esri.pro b/src/plugins/geoservices/esri/esri.pro
index 3a4da208..fce3947f 100644
--- a/src/plugins/geoservices/esri/esri.pro
+++ b/src/plugins/geoservices/esri/esri.pro
@@ -16,7 +16,10 @@ HEADERS += \
geotiledmap_esri.h \
geotiledmappingmanagerengine_esri.h \
geotiledmapreply_esri.h \
- geotilefetcher_esri.h
+ geotilefetcher_esri.h \
+ placemanagerengine_esri.h \
+ placesearchreply_esri.h \
+ placecategoriesreply_esri.h
SOURCES += \
geocodereply_esri.cpp \
@@ -29,7 +32,10 @@ SOURCES += \
geotiledmap_esri.cpp \
geotiledmappingmanagerengine_esri.cpp \
geotiledmapreply_esri.cpp \
- geotilefetcher_esri.cpp
+ geotilefetcher_esri.cpp \
+ placemanagerengine_esri.cpp \
+ placesearchreply_esri.cpp \
+ placecategoriesreply_esri.cpp
RESOURCES += \
esri.qrc
diff --git a/src/plugins/geoservices/esri/esri_plugin.json b/src/plugins/geoservices/esri/esri_plugin.json
index 3398648e..c1e37614 100644
--- a/src/plugins/geoservices/esri/esri_plugin.json
+++ b/src/plugins/geoservices/esri/esri_plugin.json
@@ -7,7 +7,8 @@
"OnlineMappingFeature",
"OnlineGeocodingFeature",
"ReverseGeocodingFeature",
- "OnlineRoutingFeature"
+ "OnlineRoutingFeature",
+ "OnlinePlacesFeature"
],
"Priority": 1000
}
diff --git a/src/plugins/geoservices/esri/geocodereply_esri.cpp b/src/plugins/geoservices/esri/geocodereply_esri.cpp
index f1dac184..fd1071c9 100644
--- a/src/plugins/geoservices/esri/geocodereply_esri.cpp
+++ b/src/plugins/geoservices/esri/geocodereply_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geocodereply_esri.h b/src/plugins/geoservices/esri/geocodereply_esri.h
index 76b416ce..4f216193 100644
--- a/src/plugins/geoservices/esri/geocodereply_esri.h
+++ b/src/plugins/geoservices/esri/geocodereply_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
index 976c51cf..17ed3cd2 100644
--- a/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
+++ b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h
index ff7bf882..a18f6bdd 100644
--- a/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h
+++ b/src/plugins/geoservices/esri/geocodingmanagerengine_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geomapsource.cpp b/src/plugins/geoservices/esri/geomapsource.cpp
index 7ec63e2f..7a7d264f 100644
--- a/src/plugins/geoservices/esri/geomapsource.cpp
+++ b/src/plugins/geoservices/esri/geomapsource.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geomapsource.h b/src/plugins/geoservices/esri/geomapsource.h
index 86258d2e..24bef6f7 100644
--- a/src/plugins/geoservices/esri/geomapsource.h
+++ b/src/plugins/geoservices/esri/geomapsource.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp b/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
index 30db48f0..17492d94 100644
--- a/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
+++ b/src/plugins/geoservices/esri/georoutejsonparser_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/georoutejsonparser_esri.h b/src/plugins/geoservices/esri/georoutejsonparser_esri.h
index 0511cf4d..d6451d70 100644
--- a/src/plugins/geoservices/esri/georoutejsonparser_esri.h
+++ b/src/plugins/geoservices/esri/georoutejsonparser_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/georoutereply_esri.cpp b/src/plugins/geoservices/esri/georoutereply_esri.cpp
index 811ffd0d..95de6b55 100644
--- a/src/plugins/geoservices/esri/georoutereply_esri.cpp
+++ b/src/plugins/geoservices/esri/georoutereply_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/georoutereply_esri.h b/src/plugins/geoservices/esri/georoutereply_esri.h
index 960c90de..19cb85bd 100644
--- a/src/plugins/geoservices/esri/georoutereply_esri.h
+++ b/src/plugins/geoservices/esri/georoutereply_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
index ae722e59..0e6bc2c7 100644
--- a/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
+++ b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h
index 17aaa3ab..eac32222 100644
--- a/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h
+++ b/src/plugins/geoservices/esri/georoutingmanagerengine_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp
index 0a54e008..197b16cd 100644
--- a/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp
+++ b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
@@ -41,6 +41,7 @@
#include "geotiledmappingmanagerengine_esri.h"
#include "geocodingmanagerengine_esri.h"
#include "georoutingmanagerengine_esri.h"
+#include "placemanagerengine_esri.h"
#include <QtLocation/private/qgeotiledmappingmanagerengine_p.h>
@@ -76,11 +77,7 @@ QGeoRoutingManagerEngine *GeoServiceProviderFactoryEsri::createRoutingManagerEng
QPlaceManagerEngine *GeoServiceProviderFactoryEsri::createPlaceManagerEngine(
const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString) const
{
- Q_UNUSED(parameters)
- Q_UNUSED(error)
- Q_UNUSED(errorString)
-
- return nullptr;
+ return new PlaceManagerEngineEsri(parameters, error, errorString);
}
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h
index abd0d59b..6208348a 100644
--- a/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h
+++ b/src/plugins/geoservices/esri/geoserviceproviderfactory_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geotiledmap_esri.cpp b/src/plugins/geoservices/esri/geotiledmap_esri.cpp
index 8feb9615..020001c4 100644
--- a/src/plugins/geoservices/esri/geotiledmap_esri.cpp
+++ b/src/plugins/geoservices/esri/geotiledmap_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geotiledmap_esri.h b/src/plugins/geoservices/esri/geotiledmap_esri.h
index 7a21af9a..0f62d961 100644
--- a/src/plugins/geoservices/esri/geotiledmap_esri.h
+++ b/src/plugins/geoservices/esri/geotiledmap_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
index 3fa9a177..5d15835d 100644
--- a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
+++ b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
@@ -53,11 +53,6 @@
#include <QJsonDocument>
#include <QJsonObject>
-static void initResources()
-{
- Q_INIT_RESOURCE(esri);
-}
-
QT_BEGIN_NAMESPACE
static const QString kPrefixEsri(QStringLiteral("esri."));
@@ -241,7 +236,6 @@ bool GeoTiledMappingManagerEngineEsri::initializeMapSources(QGeoServiceProvider:
QString *errorString,
const QGeoCameraCapabilities &cameraCaps)
{
- initResources();
QFile mapsFile(":/esri/maps.json");
if (!mapsFile.open(QIODevice::ReadOnly)) {
diff --git a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h
index 63172389..222b1779 100644
--- a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h
+++ b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp b/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp
index f4431bf0..78f6c69a 100644
--- a/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp
+++ b/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geotiledmapreply_esri.h b/src/plugins/geoservices/esri/geotiledmapreply_esri.h
index 572431dd..9e649d4f 100644
--- a/src/plugins/geoservices/esri/geotiledmapreply_esri.h
+++ b/src/plugins/geoservices/esri/geotiledmapreply_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geotilefetcher_esri.cpp b/src/plugins/geoservices/esri/geotilefetcher_esri.cpp
index 8ceba374..00344cf7 100644
--- a/src/plugins/geoservices/esri/geotilefetcher_esri.cpp
+++ b/src/plugins/geoservices/esri/geotilefetcher_esri.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/geotilefetcher_esri.h b/src/plugins/geoservices/esri/geotilefetcher_esri.h
index 5702d1c4..8c109f73 100644
--- a/src/plugins/geoservices/esri/geotilefetcher_esri.h
+++ b/src/plugins/geoservices/esri/geotilefetcher_esri.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2013-2016 Esri <contracts@esri.com>
+** Copyright (C) 2013-2018 Esri <contracts@esri.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtLocation module of the Qt Toolkit.
diff --git a/src/plugins/geoservices/esri/placecategoriesreply_esri.cpp b/src/plugins/geoservices/esri/placecategoriesreply_esri.cpp
new file mode 100644
index 00000000..44c27b19
--- /dev/null
+++ b/src/plugins/geoservices/esri/placecategoriesreply_esri.cpp
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2018 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 "placecategoriesreply_esri.h"
+
+QT_BEGIN_NAMESPACE
+
+PlaceCategoriesReplyEsri::PlaceCategoriesReplyEsri(QObject *parent) :
+ QPlaceReply(parent)
+{
+}
+
+PlaceCategoriesReplyEsri::~PlaceCategoriesReplyEsri()
+{
+}
+
+void PlaceCategoriesReplyEsri::emitFinished()
+{
+ setFinished(true);
+ emit finished();
+}
+
+void PlaceCategoriesReplyEsri::setError(QPlaceReply::Error errorCode, const QString &errorString)
+{
+ QPlaceReply::setError(errorCode, errorString);
+ emit error(errorCode, errorString);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/placecategoriesreply_esri.h b/src/plugins/geoservices/esri/placecategoriesreply_esri.h
new file mode 100644
index 00000000..14efcfea
--- /dev/null
+++ b/src/plugins/geoservices/esri/placecategoriesreply_esri.h
@@ -0,0 +1,61 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2018 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 PLACECATEGORIESREPLYESRI_H
+#define PLACECATEGORIESREPLYESRI_H
+
+#include <QtLocation/QPlaceReply>
+
+QT_BEGIN_NAMESPACE
+
+class PlaceCategoriesReplyEsri : public QPlaceReply
+{
+ Q_OBJECT
+
+public:
+ explicit PlaceCategoriesReplyEsri(QObject *parent = 0);
+ ~PlaceCategoriesReplyEsri();
+
+ void emitFinished();
+ void setError(QPlaceReply::Error errorCode, const QString &errorString);
+};
+
+QT_END_NAMESPACE
+
+#endif // PLACECATEGORIESREPLYESRI_H
diff --git a/src/plugins/geoservices/esri/placemanagerengine_esri.cpp b/src/plugins/geoservices/esri/placemanagerengine_esri.cpp
new file mode 100644
index 00000000..8f973ff3
--- /dev/null
+++ b/src/plugins/geoservices/esri/placemanagerengine_esri.cpp
@@ -0,0 +1,369 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2018 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 "placemanagerengine_esri.h"
+#include "placesearchreply_esri.h"
+#include "placecategoriesreply_esri.h"
+
+#include <QJsonDocument>
+#include <QJsonObject>
+#include <QJsonArray>
+
+#include <QtCore/QUrlQuery>
+
+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-category-filtering.htm
+// https://developers.arcgis.com/rest/geocode/api-reference/geocoding-service-output.htm
+
+static const QString kCategoriesKey(QStringLiteral("categories"));
+static const QString kSingleLineKey(QStringLiteral("singleLine"));
+static const QString kLocationKey(QStringLiteral("location"));
+static const QString kNameKey(QStringLiteral("name"));
+static const QString kOutFieldsKey(QStringLiteral("outFields"));
+static const QString kCandidateFieldsKey(QStringLiteral("candidateFields"));
+static const QString kCountriesKey(QStringLiteral("detailedCountries"));
+static const QString kLocalizedNamesKey(QStringLiteral("localizedNames"));
+static const QString kMaxLocationsKey(QStringLiteral("maxLocations"));
+
+static const QUrl kUrlGeocodeServer("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer?f=pjson");
+static const QUrl kUrlFindAddressCandidates("http://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates");
+
+PlaceManagerEngineEsri::PlaceManagerEngineEsri(const QVariantMap &parameters, QGeoServiceProvider::Error *error,
+ QString *errorString) :
+ QPlaceManagerEngine(parameters),
+ m_networkManager(new QNetworkAccessManager(this))
+{
+ *error = QGeoServiceProvider::NoError;
+ errorString->clear();
+}
+
+PlaceManagerEngineEsri::~PlaceManagerEngineEsri()
+{
+}
+
+QList<QLocale> PlaceManagerEngineEsri::locales() const
+{
+ return m_locales;
+}
+
+void PlaceManagerEngineEsri::setLocales(const QList<QLocale> &locales)
+{
+ m_locales = locales;
+}
+
+/***** Search *****/
+
+QPlaceSearchReply *PlaceManagerEngineEsri::search(const QPlaceSearchRequest &request)
+{
+ bool unsupported = false;
+
+ // Only public visibility supported
+ unsupported |= request.visibilityScope() != QLocation::UnspecifiedVisibility &&
+ request.visibilityScope() != QLocation::PublicVisibility;
+ unsupported |= request.searchTerm().isEmpty() && request.categories().isEmpty();
+
+ if (unsupported)
+ return QPlaceManagerEngine::search(request);
+
+ QUrlQuery queryItems;
+ queryItems.addQueryItem(QStringLiteral("f"), QStringLiteral("json"));
+
+ const QGeoCoordinate center = request.searchArea().center();
+ if (center.isValid())
+ {
+ const QString location = QString("%1,%2").arg(center.longitude()).arg(center.latitude());
+ queryItems.addQueryItem(kLocationKey, location);
+ }
+
+ const QGeoRectangle boundingBox = request.searchArea().boundingGeoRectangle();
+ if (!boundingBox.isEmpty())
+ {
+ const QString searchExtent = QString("%1,%2,%3,%4")
+ .arg(boundingBox.topLeft().longitude())
+ .arg(boundingBox.topLeft().latitude())
+ .arg(boundingBox.bottomRight().longitude())
+ .arg(boundingBox.bottomRight().latitude());
+ queryItems.addQueryItem(QStringLiteral("searchExtent"), searchExtent);
+ }
+
+ if (!request.searchTerm().isEmpty())
+ queryItems.addQueryItem(kSingleLineKey, request.searchTerm());
+
+ QStringList categories;
+ if (!request.categories().isEmpty())
+ {
+ foreach (const QPlaceCategory &placeCategory, request.categories())
+ categories.append(placeCategory.categoryId());
+ queryItems.addQueryItem("category", categories.join(","));
+ }
+
+ if (request.limit() > 0)
+ queryItems.addQueryItem(kMaxLocationsKey, QString::number(request.limit()));
+
+ queryItems.addQueryItem(kOutFieldsKey, QStringLiteral("*"));
+
+ QUrl requestUrl(kUrlFindAddressCandidates);
+ requestUrl.setQuery(queryItems);
+
+ QNetworkRequest networkRequest(requestUrl);
+ networkRequest.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
+ QNetworkReply *networkReply = m_networkManager->get(networkRequest);
+
+ PlaceSearchReplyEsri *reply = new PlaceSearchReplyEsri(request, networkReply, m_candidateFieldsLocale, m_countriesLocale, this);
+ connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), this, SLOT(replyError(QPlaceReply::Error,QString)));
+
+ return reply;
+}
+
+void PlaceManagerEngineEsri::replyFinished()
+{
+ QPlaceReply *reply = qobject_cast<QPlaceReply *>(sender());
+ if (reply)
+ emit finished(reply);
+}
+
+void PlaceManagerEngineEsri::replyError(QPlaceReply::Error errorCode, const QString &errorString)
+{
+ QPlaceReply *reply = qobject_cast<QPlaceReply *>(sender());
+ if (reply)
+ emit error(reply, errorCode, errorString);
+}
+
+/***** Categories *****/
+
+QPlaceReply *PlaceManagerEngineEsri::initializeCategories()
+{
+ initializeGeocodeServer();
+
+ PlaceCategoriesReplyEsri *reply = new PlaceCategoriesReplyEsri(this);
+ connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ connect(reply, SIGNAL(error(QPlaceReply::Error,QString)), this, SLOT(replyError(QPlaceReply::Error,QString)));
+
+ // TODO delayed finished() emission
+ if (!m_categories.isEmpty())
+ reply->emitFinished();
+
+ m_pendingCategoriesReply.append(reply);
+ return reply;
+}
+
+void PlaceManagerEngineEsri::parseCategories(const QJsonArray &jsonArray, const QString &parentCategoryId)
+{
+ foreach (const QJsonValue &jsonValue, jsonArray)
+ {
+ if (!jsonValue.isObject())
+ continue;
+
+ const QJsonObject jsonCategory = jsonValue.toObject();
+ const QString key = jsonCategory.value(kNameKey).toString();
+ const QString localeName = localizedName(jsonCategory);
+
+ if (key.isEmpty())
+ continue;
+
+ QPlaceCategory category;
+ category.setCategoryId(key);
+ category.setName(localeName.isEmpty() ? key : localeName); // localizedNames
+ m_categories.insert(key, category);
+ m_subcategories[parentCategoryId].append(key);
+ m_parentCategory.insert(key, parentCategoryId);
+ emit categoryAdded(category, parentCategoryId);
+
+ if (jsonCategory.contains(kCategoriesKey))
+ {
+ const QJsonArray jsonArray = jsonCategory.value(kCategoriesKey).toArray();
+ parseCategories(jsonArray, key);
+ }
+ }
+}
+
+QString PlaceManagerEngineEsri::parentCategoryId(const QString &categoryId) const
+{
+ return m_parentCategory.value(categoryId);
+}
+
+QStringList PlaceManagerEngineEsri::childCategoryIds(const QString &categoryId) const
+{
+ return m_subcategories.value(categoryId);
+}
+
+QPlaceCategory PlaceManagerEngineEsri::category(const QString &categoryId) const
+{
+ return m_categories.value(categoryId);
+}
+
+QList<QPlaceCategory> PlaceManagerEngineEsri::childCategories(const QString &parentId) const
+{
+ QList<QPlaceCategory> categories;
+ foreach (const QString &id, m_subcategories.value(parentId))
+ categories.append(m_categories.value(id));
+ return categories;
+}
+
+void PlaceManagerEngineEsri::finishCategories()
+{
+ foreach (PlaceCategoriesReplyEsri *reply, m_pendingCategoriesReply)
+ reply->emitFinished();
+ m_pendingCategoriesReply.clear();
+}
+
+void PlaceManagerEngineEsri::errorCaterogies(const QString &error)
+{
+ foreach (PlaceCategoriesReplyEsri *reply, m_pendingCategoriesReply)
+ reply->setError(QPlaceReply::CommunicationError, error);
+}
+
+/***** GeocodeServer *****/
+
+void PlaceManagerEngineEsri::initializeGeocodeServer()
+{
+ // Only fetch categories once
+ if (m_categories.isEmpty() && !m_geocodeServerReply)
+ {
+ m_geocodeServerReply = m_networkManager->get(QNetworkRequest(kUrlGeocodeServer));
+ connect(m_geocodeServerReply, SIGNAL(finished()), this, SLOT(geocodeServerReplyFinished()));
+ connect(m_geocodeServerReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(geocodeServerReplyError()));
+ }
+}
+
+QString PlaceManagerEngineEsri::localizedName(const QJsonObject &jsonObject)
+{
+ const QJsonObject localizedNames = jsonObject.value(kLocalizedNamesKey).toObject();
+
+ foreach (const QLocale &locale, m_locales)
+ {
+ const QString localeStr = locale.name();
+ if (localizedNames.contains(localeStr))
+ {
+ return localizedNames.value(localeStr).toString();
+ }
+
+ const QString shortLocale = localeStr.left(2);
+ if (localizedNames.contains(shortLocale))
+ {
+ return localizedNames.value(shortLocale).toString();
+ }
+ }
+ return QString();
+}
+
+void PlaceManagerEngineEsri::parseCandidateFields(const QJsonArray &jsonArray)
+{
+ foreach (const QJsonValue &jsonValue, jsonArray)
+ {
+ if (!jsonValue.isObject())
+ continue;
+
+ const QJsonObject jsonCandidateField = jsonValue.toObject();
+ if (!jsonCandidateField.contains(kLocalizedNamesKey))
+ continue;
+
+ const QString key = jsonCandidateField.value(kNameKey).toString();
+ m_candidateFieldsLocale.insert(key, localizedName(jsonCandidateField));
+ }
+}
+
+void PlaceManagerEngineEsri::parseCountries(const QJsonArray &jsonArray)
+{
+ foreach (const QJsonValue &jsonValue, jsonArray)
+ {
+ if (!jsonValue.isObject())
+ continue;
+
+ const QJsonObject jsonCountry = jsonValue.toObject();
+ if (!jsonCountry.contains(kLocalizedNamesKey))
+ continue;
+
+ const QString key = jsonCountry.value(kNameKey).toString();
+ m_countriesLocale.insert(key, localizedName(jsonCountry));
+ }
+}
+
+void PlaceManagerEngineEsri::geocodeServerReplyFinished()
+{
+ if (!m_geocodeServerReply)
+ return;
+
+ QJsonDocument document = QJsonDocument::fromJson(m_geocodeServerReply->readAll());
+ if (!document.isObject())
+ {
+ errorCaterogies(m_geocodeServerReply->errorString());
+ return;
+ }
+
+ QJsonObject jsonObject = document.object();
+
+ // parse categories
+ if (jsonObject.contains(kCategoriesKey))
+ {
+ const QJsonArray jsonArray = jsonObject.value(kCategoriesKey).toArray();
+ parseCategories(jsonArray, QString());
+ }
+
+ // parse candidateFields
+ if (jsonObject.contains(kCandidateFieldsKey))
+ {
+ const QJsonArray jsonArray = jsonObject.value(kCandidateFieldsKey).toArray();
+ parseCandidateFields(jsonArray);
+ }
+
+ // parse countries
+ if (jsonObject.contains(kCountriesKey))
+ {
+ const QJsonArray jsonArray = jsonObject.value(kCountriesKey).toArray();
+ parseCountries(jsonArray);
+ }
+
+ finishCategories();
+
+ m_geocodeServerReply->deleteLater();
+}
+
+void PlaceManagerEngineEsri::geocodeServerReplyError()
+{
+ if (m_categories.isEmpty() && !m_geocodeServerReply)
+ return;
+
+ errorCaterogies(m_geocodeServerReply->errorString());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/placemanagerengine_esri.h b/src/plugins/geoservices/esri/placemanagerengine_esri.h
new file mode 100644
index 00000000..2edb2d1a
--- /dev/null
+++ b/src/plugins/geoservices/esri/placemanagerengine_esri.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2018 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 PLACEMANAGERENGINEESRI_H
+#define PLACEMANAGERENGINEESRI_H
+
+#include <QtLocation/QPlaceManagerEngine>
+#include <QtLocation/QGeoServiceProvider>
+
+QT_BEGIN_NAMESPACE
+
+class PlaceCategoriesReplyEsri;
+class QNetworkAccessManager;
+class QNetworkReply;
+
+class PlaceManagerEngineEsri : public QPlaceManagerEngine
+{
+ Q_OBJECT
+
+public:
+ PlaceManagerEngineEsri(const QVariantMap &parameters, QGeoServiceProvider::Error *error, QString *errorString);
+ ~PlaceManagerEngineEsri();
+
+ QPlaceSearchReply *search(const QPlaceSearchRequest &request) override;
+
+ QPlaceReply *initializeCategories() override;
+ QString parentCategoryId(const QString &categoryId) const override;
+ QStringList childCategoryIds(const QString &categoryId) const override;
+ QPlaceCategory category(const QString &categoryId) const override;
+
+ QList<QPlaceCategory> childCategories(const QString &parentId) const override;
+
+ QList<QLocale> locales() const override;
+ void setLocales(const QList<QLocale> &locales) override;
+
+private slots:
+ void geocodeServerReplyFinished();
+ void geocodeServerReplyError();
+ void replyFinished();
+ void replyError(QPlaceReply::Error errorCode, const QString &errorString);
+
+private:
+ QNetworkAccessManager *m_networkManager = Q_NULLPTR;
+
+ // geocode serveur
+ void initializeGeocodeServer();
+
+ QNetworkReply *m_geocodeServerReply = Q_NULLPTR;
+
+ // categories
+ void finishCategories();
+ void errorCaterogies(const QString &error);
+ void parseCategories(const QJsonArray &jsonArray, const QString &parentCategoryId);
+
+ QList<PlaceCategoriesReplyEsri *> m_pendingCategoriesReply;
+ QHash<QString, QPlaceCategory> m_categories;
+ QHash<QString, QStringList> m_subcategories;
+ QHash<QString, QString> m_parentCategory;
+
+ // localized names
+ QString localizedName(const QJsonObject &jsonObject);
+ void parseCandidateFields(const QJsonArray &jsonArray);
+ void parseCountries(const QJsonArray &jsonArray);
+
+ QList<QLocale> m_locales;
+ QHash<QString, QString> m_candidateFieldsLocale;
+ QHash<QString, QString> m_countriesLocale;
+ void localizedName();
+};
+
+QT_END_NAMESPACE
+
+#endif // PLACEMANAGERENGINEESRI_H
diff --git a/src/plugins/geoservices/esri/placesearchreply_esri.cpp b/src/plugins/geoservices/esri/placesearchreply_esri.cpp
new file mode 100644
index 00000000..a5a3585a
--- /dev/null
+++ b/src/plugins/geoservices/esri/placesearchreply_esri.cpp
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2018 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 "placesearchreply_esri.h"
+#include "placemanagerengine_esri.h"
+
+#include <QtCore/QJsonDocument>
+#include <QtCore/QJsonArray>
+#include <QtCore/QJsonObject>
+#include <QtNetwork/QNetworkReply>
+#include <QtPositioning/QGeoCircle>
+#include <QtPositioning/QGeoRectangle>
+#include <QtLocation/QPlaceResult>
+#include <QtLocation/QPlaceSearchRequest>
+#include <QtLocation/private/qplacesearchrequest_p.h>
+
+static const QString kCandidatesKey(QStringLiteral("candidates"));
+static const QString kAttributesKey(QStringLiteral("attributes"));
+static const QString kAddressKey(QStringLiteral("address"));
+static const QString kLongLabelKey(QStringLiteral("LongLabel"));
+static const QString kCityKey(QStringLiteral("City"));
+static const QString kCountryKey(QStringLiteral("Country"));
+static const QString kRegionKey(QStringLiteral("Region"));
+static const QString kPostalKey(QStringLiteral("Postal"));
+static const QString kStAddrKey(QStringLiteral("StAddr"));
+static const QString kStateKey(QStringLiteral("State"));
+static const QString kDistrictKey(QStringLiteral("District"));
+static const QString kLocationKey(QStringLiteral("location"));
+static const QString kXKey(QStringLiteral("x"));
+static const QString kYKey(QStringLiteral("y"));
+static const QString kDistanceKey(QStringLiteral("Distance"));
+static const QString kPhoneKey(QStringLiteral("Phone"));
+static const QString kExtentKey(QStringLiteral("extent"));
+static const QString kXminKey(QStringLiteral("xmin"));
+static const QString kYminKey(QStringLiteral("ymin"));
+static const QString kXmaxKey(QStringLiteral("xmax"));
+static const QString kYmaxKey(QStringLiteral("ymax"));
+
+QT_BEGIN_NAMESPACE
+
+PlaceSearchReplyEsri::PlaceSearchReplyEsri(const QPlaceSearchRequest &request, QNetworkReply *reply,
+ const QHash<QString, QString> &candidateFields,
+ const QHash<QString, QString> &countries, PlaceManagerEngineEsri *parent) :
+ QPlaceSearchReply(parent), m_candidateFields(candidateFields), m_countries(countries)
+{
+ Q_ASSERT(parent);
+ if (!reply) {
+ setError(UnknownError, QStringLiteral("Null reply"));
+ return;
+ }
+ setRequest(request);
+
+ connect(reply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkError(QNetworkReply::NetworkError)));
+ connect(this, &QPlaceReply::aborted, reply, &QNetworkReply::abort);
+ connect(this, &QObject::destroyed, reply, &QObject::deleteLater);
+}
+
+PlaceSearchReplyEsri::~PlaceSearchReplyEsri()
+{
+}
+
+void PlaceSearchReplyEsri::setError(QPlaceReply::Error errorCode, const QString &errorString)
+{
+ QPlaceReply::setError(errorCode, errorString);
+ emit error(errorCode, errorString);
+ setFinished(true);
+ emit finished();
+}
+
+void PlaceSearchReplyEsri::replyFinished()
+{
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+ reply->deleteLater();
+
+ if (reply->error() != QNetworkReply::NoError)
+ return;
+
+ QJsonDocument document = QJsonDocument::fromJson(reply->readAll());
+ if (!document.isObject())
+ {
+ setError(ParseError, tr("Response parse error"));
+ return;
+ }
+
+ QJsonValue suggestions = document.object().value(kCandidatesKey);
+ if (!suggestions.isArray())
+ {
+ setError(ParseError, tr("Response parse error"));
+ return;
+ }
+
+ QJsonArray resultsArray = suggestions.toArray();
+
+ QList<QPlaceSearchResult> results;
+ for (int i = 0; i < resultsArray.count(); ++i)
+ {
+ QJsonObject item = resultsArray.at(i).toObject();
+ QPlaceResult placeResult = parsePlaceResult(item);
+ results.append(placeResult);
+ }
+
+ setResults(results);
+ setFinished(true);
+ emit finished();
+}
+
+void PlaceSearchReplyEsri::networkError(QNetworkReply::NetworkError error)
+{
+ Q_UNUSED(error)
+ QNetworkReply *reply = static_cast<QNetworkReply *>(sender());
+ reply->deleteLater();
+ setError(QPlaceReply::CommunicationError, reply->errorString());
+}
+
+QPlaceResult PlaceSearchReplyEsri::parsePlaceResult(const QJsonObject &item) const
+{
+ QPlace place;
+ QHash<QString, QString> keys;
+
+ // set attributes
+ const QJsonObject attributes = item.value(kAttributesKey).toObject();
+ for (const QString &key: attributes.keys())
+ {
+ const QString value = attributes.value(key).toVariant().toString();
+ if (!value.isEmpty())
+ {
+ QPlaceAttribute attribute;
+ attribute.setLabel(m_candidateFields.value(key, key)); // local name or key
+ attribute.setText(value);
+ place.setExtendedAttribute(key, attribute);
+ keys.insert(key, value);
+ }
+ }
+
+ if (keys.contains(kPhoneKey))
+ {
+ QPlaceContactDetail contactDetail;
+ contactDetail.setLabel(m_candidateFields.value(kPhoneKey, kPhoneKey)); // local name or key
+ contactDetail.setValue(keys.value(kPhoneKey));
+ place.appendContactDetail(QPlaceContactDetail::Phone, contactDetail);
+ }
+
+ // set address
+ QGeoAddress geoAddress;
+ geoAddress.setCity(keys.value(kCityKey));
+ geoAddress.setCountry(m_countries.value(keys.value(kCountryKey))); // mismatch code ISO2 vs ISO3
+ geoAddress.setCounty(keys.value(kRegionKey));
+ geoAddress.setPostalCode(keys.value(kPostalKey));
+ geoAddress.setStreet(keys.value(kStAddrKey));
+ geoAddress.setState(keys.value(kStateKey));
+ geoAddress.setDistrict(keys.value(kDistrictKey));
+
+ // set location
+ const QJsonObject location = item.value(kLocationKey).toObject();
+ const QGeoCoordinate coordinate = QGeoCoordinate(location.value(kYKey).toDouble(),
+ location.value(kXKey).toDouble());
+
+ // set boundingBox
+ const QJsonObject extent = item.value(kExtentKey).toObject();
+ const QGeoCoordinate topLeft(extent.value(kYminKey).toDouble(),
+ extent.value(kXminKey).toDouble());
+ const QGeoCoordinate bottomRight(extent.value(kYmaxKey).toDouble(),
+ extent.value(kXmaxKey).toDouble());
+ const QGeoRectangle boundingBox(topLeft, bottomRight);
+
+ // set geolocation
+ QGeoLocation geoLocation;
+ geoLocation.setCoordinate(coordinate);
+ geoLocation.setAddress(geoAddress);
+ geoLocation.setBoundingBox(boundingBox);
+
+ // set place
+ place.setName(keys.value(kLongLabelKey));
+ place.setLocation(geoLocation);
+ place.setPlaceId(attributes.value(kLongLabelKey).toString());
+
+ // set place result
+ QPlaceResult result;
+ result.setPlace(place);
+ result.setTitle(keys.value(kAddressKey));
+ result.setDistance(keys.value(kDistanceKey).toDouble());
+
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/esri/placesearchreply_esri.h b/src/plugins/geoservices/esri/placesearchreply_esri.h
new file mode 100644
index 00000000..195d650d
--- /dev/null
+++ b/src/plugins/geoservices/esri/placesearchreply_esri.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2013-2018 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 PLACESEARCHREPLYESRI_H
+#define PLACESEARCHREPLYESRI_H
+
+#include <QtLocation/QPlaceSearchReply>
+#include <QNetworkReply>
+
+QT_BEGIN_NAMESPACE
+
+class PlaceManagerEngineEsri;
+class QNetworkReply;
+class QPlaceResult;
+
+class PlaceSearchReplyEsri : public QPlaceSearchReply
+{
+ Q_OBJECT
+
+public:
+ PlaceSearchReplyEsri(const QPlaceSearchRequest &request, QNetworkReply *reply,
+ const QHash<QString, QString> &candidateFields,
+ const QHash<QString, QString> &countries, PlaceManagerEngineEsri *parent);
+ ~PlaceSearchReplyEsri();
+
+ QString requestUrl;
+
+private slots:
+ void setError(QPlaceReply::Error errorCode, const QString &errorString);
+ void replyFinished();
+ void networkError(QNetworkReply::NetworkError error);
+
+private:
+ QPlaceResult parsePlaceResult(const QJsonObject &item) const;
+
+ const QHash<QString, QString> &m_candidateFields;
+ const QHash<QString, QString> &m_countries;
+};
+
+QT_END_NAMESPACE
+
+#endif // PLACESEARCHREPLYESRI_H
diff --git a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp
index af0e263b..dede9dbc 100644
--- a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp
+++ b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp
@@ -70,10 +70,16 @@ public:
#endif
void updateObjectsGeometry();
+
+ void setVisibleArea(const QRectF &visibleArea) override;
+ QRectF visibleArea() const override;
+
protected:
void changeViewportSize(const QSize &size) override;
void changeCameraData(const QGeoCameraData &oldCameraData) override;
void changeActiveMapType(const QGeoMapType mapType) override;
+
+ QRectF m_visibleArea;
};
QGeoMapItemsOverlay::QGeoMapItemsOverlay(QGeoMappingManagerEngineItemsOverlay *engine, QObject *parent)
@@ -131,6 +137,24 @@ void QGeoMapItemsOverlay::removeMapObject(QGeoMapObject *obj)
#endif
}
+void QGeoMapItemsOverlayPrivate::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_Q(QGeoMapItemsOverlay);
+ const QRectF va = clampVisibleArea(visibleArea);
+ if (va == m_visibleArea)
+ return;
+
+ m_visibleArea = va;
+ m_geoProjection->setVisibleArea(va);
+
+ q->sgNodeChanged();
+}
+
+QRectF QGeoMapItemsOverlayPrivate::visibleArea() const
+{
+ return m_visibleArea;
+}
+
QGeoMapItemsOverlayPrivate::QGeoMapItemsOverlayPrivate(QGeoMappingManagerEngineItemsOverlay *engine, QGeoMapItemsOverlay *map)
: QGeoMapPrivate(engine, new QGeoProjectionWebMercator)
{
diff --git a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp
index c5f9d38c..8b0772ad 100644
--- a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp
+++ b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp
@@ -127,6 +127,13 @@ void QGeoRouteReplyMapbox::networkReplyFinished()
QByteArray routeReply = reply->readAll();
QGeoRouteReply::Error error = parser->parseReply(routes, errorString, routeReply);
+ // Setting the request into the result
+ for (QGeoRoute &route : routes) {
+ route.setRequest(request());
+ for (QGeoRoute &leg: route.routeLegs()) {
+ leg.setRequest(request());
+ }
+ }
QVariantMap metadata;
metadata["osrm.reply-json"] = routeReply;
diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp
index dfebc20d..ed36cd5f 100644
--- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp
+++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp
@@ -106,12 +106,12 @@ QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *node, QQuickWindow *w
if (m_useFBO) {
QSGMapboxGLTextureNode *mbglNode = new QSGMapboxGLTextureNode(m_settings, m_viewportSize, window->devicePixelRatio(), q);
QObject::connect(mbglNode->map(), &QMapboxGL::mapChanged, q, &QGeoMapMapboxGL::onMapChanged);
- m_syncState = MapTypeSync | CameraDataSync | ViewportSync;
+ m_syncState = MapTypeSync | CameraDataSync | ViewportSync | VisibleAreaSync;
node = mbglNode;
} else {
QSGMapboxGLRenderNode *mbglNode = new QSGMapboxGLRenderNode(m_settings, m_viewportSize, window->devicePixelRatio(), q);
QObject::connect(mbglNode->map(), &QMapboxGL::mapChanged, q, &QGeoMapMapboxGL::onMapChanged);
- m_syncState = MapTypeSync | CameraDataSync | ViewportSync;
+ m_syncState = MapTypeSync | CameraDataSync | ViewportSync | VisibleAreaSync;
node = mbglNode;
}
}
@@ -125,7 +125,19 @@ QSGNode *QGeoMapMapboxGLPrivate::updateSceneGraph(QSGNode *node, QQuickWindow *w
map->setStyleUrl(m_activeMapType.name());
}
- if (m_syncState & CameraDataSync) {
+ if (m_syncState & VisibleAreaSync) {
+ if (m_visibleArea.isEmpty()) {
+ map->setMargins(QMargins());
+ } else {
+ QMargins margins(m_visibleArea.x(), // left
+ m_visibleArea.y(), // top
+ m_viewportSize.width() - m_visibleArea.width() - m_visibleArea.x(), // right
+ m_viewportSize.height() - m_visibleArea.height() - m_visibleArea.y()); // bottom
+ map->setMargins(margins);
+ }
+ }
+
+ if (m_syncState & CameraDataSync || m_syncState & VisibleAreaSync) {
map->setZoom(zoomLevelFrom256(m_cameraData.zoomLevel() , MBGL_TILE_SIZE));
map->setBearing(m_cameraData.bearing());
map->setPitch(m_cameraData.tilt());
@@ -291,6 +303,25 @@ void QGeoMapMapboxGLPrivate::changeActiveMapType(const QGeoMapType)
emit q->sgNodeChanged();
}
+void QGeoMapMapboxGLPrivate::setVisibleArea(const QRectF &visibleArea)
+{
+ Q_Q(QGeoMapMapboxGL);
+ const QRectF va = clampVisibleArea(visibleArea);
+ if (va == m_visibleArea)
+ return;
+
+ m_visibleArea = va;
+ m_geoProjection->setVisibleArea(va);
+
+ m_syncState = m_syncState | VisibleAreaSync;
+ emit q->sgNodeChanged();
+}
+
+QRectF QGeoMapMapboxGLPrivate::visibleArea() const
+{
+ return m_visibleArea;
+}
+
void QGeoMapMapboxGLPrivate::syncStyleChanges(QMapboxGL *map)
{
for (const auto& change : m_styleChanges) {
@@ -347,7 +378,7 @@ QString QGeoMapMapboxGL::copyrightsStyleSheet() const
return QStringLiteral("* { vertical-align: middle; font-weight: normal }");
}
-void QGeoMapMapboxGL::setMapboxGLSettings(const QMapboxGLSettings& settings)
+void QGeoMapMapboxGL::setMapboxGLSettings(const QMapboxGLSettings& settings, bool useChinaEndpoint)
{
Q_D(QGeoMapMapboxGL);
@@ -355,8 +386,13 @@ void QGeoMapMapboxGL::setMapboxGLSettings(const QMapboxGLSettings& settings)
// If the access token is not set, use the development access token.
// This will only affect mapbox:// styles.
+ // Mapbox China requires a China-specific access token.
if (d->m_settings.accessToken().isEmpty()) {
- d->m_settings.setAccessToken(developmentToken);
+ if (useChinaEndpoint) {
+ qWarning("Mapbox China requires an access token: https://www.mapbox.com/contact/sales");
+ } else {
+ d->m_settings.setAccessToken(developmentToken);
+ }
}
}
@@ -376,7 +412,8 @@ QGeoMap::Capabilities QGeoMapMapboxGL::capabilities() const
{
return Capabilities(SupportsVisibleRegion
| SupportsSetBearing
- | SupportsAnchoringCoordinate);
+ | SupportsAnchoringCoordinate
+ | SupportsVisibleArea );
}
QSGNode *QGeoMapMapboxGL::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window)
diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h
index 0ffaf4ea..5fc2260e 100644
--- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h
+++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h
@@ -54,7 +54,7 @@ public:
virtual ~QGeoMapMapboxGL();
QString copyrightsStyleSheet() const override;
- void setMapboxGLSettings(const QMapboxGLSettings &);
+ void setMapboxGLSettings(const QMapboxGLSettings &, bool useChinaEndpoint);
void setUseFBO(bool);
void setMapItemsBefore(const QString &);
Capabilities capabilities() const override;
diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h
index ffb06208..f07b4c98 100644
--- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h
+++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl_p.h
@@ -43,6 +43,7 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QTimer>
#include <QtCore/QVariant>
+#include <QtCore/QRectF>
#include <QtLocation/private/qgeomap_p_p.h>
#include <QtLocation/private/qgeomapparameter_p.h>
@@ -70,9 +71,10 @@ public:
/* Data members */
enum SyncState : int {
NoSync = 0,
- ViewportSync = 1 << 0,
- CameraDataSync = 1 << 1,
- MapTypeSync = 1 << 2
+ ViewportSync = 1 << 0,
+ CameraDataSync = 1 << 1,
+ MapTypeSync = 1 << 2,
+ VisibleAreaSync = 1 << 3
};
Q_DECLARE_FLAGS(SyncStates, SyncState);
@@ -96,11 +98,16 @@ protected:
void changeCameraData(const QGeoCameraData &oldCameraData) override;
void changeActiveMapType(const QGeoMapType mapType) override;
+ void setVisibleArea(const QRectF &visibleArea) override;
+ QRectF visibleArea() const override;
+
private:
Q_DISABLE_COPY(QGeoMapMapboxGLPrivate);
void syncStyleChanges(QMapboxGL *map);
void threadedRenderingHack(QQuickWindow *window, QMapboxGL *map);
+
+ QRectF m_visibleArea;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoMapMapboxGLPrivate::SyncStates)
diff --git a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp
index cc48afb2..d2463106 100644
--- a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp
+++ b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp
@@ -69,30 +69,45 @@ QGeoMappingManagerEngineMapboxGL::QGeoMappingManagerEngineMapboxGL(const QVarian
int mapId = 0;
const QByteArray pluginName = "mapboxgl";
- mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/streets-v10"),
- tr("Streets"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/basic-v9"),
- tr("Basic"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/bright-v9"),
- tr("Bright"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::TerrainMap, QStringLiteral("mapbox://styles/mapbox/outdoors-v10"),
- tr("Outdoors"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::SatelliteMapDay, QStringLiteral("mapbox://styles/mapbox/satellite-v9"),
- tr("Satellite"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::HybridMap, QStringLiteral("mapbox://styles/mapbox/satellite-streets-v10"),
- tr("Satellite Streets"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::GrayStreetMap, QStringLiteral("mapbox://styles/mapbox/light-v9"),
- tr("Light"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::GrayStreetMap, QStringLiteral("mapbox://styles/mapbox/dark-v9"),
- tr("Dark"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/navigation-preview-day-v2"),
- tr("Navigation Preview Day"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/navigation-preview-night-v2"),
- tr("Navigation Preview Night"), false, true, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::CarNavigationMap, QStringLiteral("mapbox://styles/mapbox/navigation-guidance-day-v2"),
- tr("Navigation Guidance Day"), false, false, ++mapId, pluginName, cameraCaps);
- mapTypes << QGeoMapType(QGeoMapType::CarNavigationMap, QStringLiteral("mapbox://styles/mapbox/navigation-guidance-night-v2"),
- tr("Navigation Guidance Night"), false, true, ++mapId, pluginName, cameraCaps);
+ if (parameters.contains(QStringLiteral("mapboxgl.china"))) {
+ m_useChinaEndpoint = parameters.value(QStringLiteral("mapboxgl.china")).toBool();
+ }
+
+ if (m_useChinaEndpoint) {
+ m_settings.setApiBaseUrl(QStringLiteral("https://api.mapbox.cn"));
+
+ mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/streets-zh-v1"),
+ tr("China Streets"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::GrayStreetMap, QStringLiteral("mapbox://styles/mapbox/light-zh-v1"),
+ tr("China Light"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::GrayStreetMap, QStringLiteral("mapbox://styles/mapbox/dark-zh-v1"),
+ tr("China Dark"), false, false, ++mapId, pluginName, cameraCaps);
+ } else {
+ mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/streets-v10"),
+ tr("Streets"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/basic-v9"),
+ tr("Basic"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/bright-v9"),
+ tr("Bright"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::TerrainMap, QStringLiteral("mapbox://styles/mapbox/outdoors-v10"),
+ tr("Outdoors"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::SatelliteMapDay, QStringLiteral("mapbox://styles/mapbox/satellite-v9"),
+ tr("Satellite"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::HybridMap, QStringLiteral("mapbox://styles/mapbox/satellite-streets-v10"),
+ tr("Satellite Streets"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::GrayStreetMap, QStringLiteral("mapbox://styles/mapbox/light-v9"),
+ tr("Light"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::GrayStreetMap, QStringLiteral("mapbox://styles/mapbox/dark-v9"),
+ tr("Dark"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/navigation-preview-day-v2"),
+ tr("Navigation Preview Day"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/navigation-preview-night-v2"),
+ tr("Navigation Preview Night"), false, true, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::CarNavigationMap, QStringLiteral("mapbox://styles/mapbox/navigation-guidance-day-v2"),
+ tr("Navigation Guidance Day"), false, false, ++mapId, pluginName, cameraCaps);
+ mapTypes << QGeoMapType(QGeoMapType::CarNavigationMap, QStringLiteral("mapbox://styles/mapbox/navigation-guidance-night-v2"),
+ tr("Navigation Guidance Night"), false, true, ++mapId, pluginName, cameraCaps);
+ }
if (parameters.contains(QStringLiteral("mapboxgl.mapping.additional_style_urls"))) {
const QString ids = parameters.value(QStringLiteral("mapboxgl.mapping.additional_style_urls")).toString();
@@ -156,7 +171,7 @@ QGeoMappingManagerEngineMapboxGL::~QGeoMappingManagerEngineMapboxGL()
QGeoMap *QGeoMappingManagerEngineMapboxGL::createMap()
{
QGeoMapMapboxGL* map = new QGeoMapMapboxGL(this, 0);
- map->setMapboxGLSettings(m_settings);
+ map->setMapboxGLSettings(m_settings, m_useChinaEndpoint);
map->setUseFBO(m_useFBO);
map->setMapItemsBefore(m_mapItemsBefore);
diff --git a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.h b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.h
index b3afe77b..9ceb8ccc 100644
--- a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.h
+++ b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.h
@@ -59,6 +59,7 @@ public:
private:
QMapboxGLSettings m_settings;
bool m_useFBO = true;
+ bool m_useChinaEndpoint = false;
QString m_mapItemsBefore;
};
diff --git a/src/plugins/geoservices/mapboxgl/qgeoserviceproviderpluginmapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeoserviceproviderpluginmapboxgl.cpp
index dd25c99e..afa723a5 100644
--- a/src/plugins/geoservices/mapboxgl/qgeoserviceproviderpluginmapboxgl.cpp
+++ b/src/plugins/geoservices/mapboxgl/qgeoserviceproviderpluginmapboxgl.cpp
@@ -40,16 +40,10 @@
#include <QtGui/QOpenGLContext>
-static void initResources()
-{
- Q_INIT_RESOURCE(mapboxgl);
-}
-
QT_BEGIN_NAMESPACE
QGeoServiceProviderFactoryMapboxGL::QGeoServiceProviderFactoryMapboxGL()
{
- initResources();
}
QGeoCodingManagerEngine *QGeoServiceProviderFactoryMapboxGL::createGeocodingManagerEngine(
diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp
index 6c47d3ee..b45fdef1 100644
--- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp
+++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp
@@ -41,6 +41,7 @@
#include <QtCore/QRegularExpression>
#include <QtCore/QStringList>
#include <QtPositioning/QGeoPath>
+#include <QtPositioning/QGeoPolygon>
#include <QtQml/QJSValue>
namespace {
@@ -66,7 +67,7 @@ QString getId(QDeclarativeGeoMapItemBase *mapItem)
// Mapbox GL supports geometry segments that spans above 180 degrees in
// longitude. To keep visual expectations in parity with Qt, we need to adapt
// the coordinates to always use the shortest path when in ambiguity.
-bool geoRectangleCrossesDateLine(const QGeoRectangle &rect) {
+static bool geoRectangleCrossesDateLine(const QGeoRectangle &rect) {
return rect.topLeft().longitude() > rect.bottomRight().longitude();
}
@@ -112,24 +113,35 @@ QMapbox::Feature featureFromMapCircle(QDeclarativeCircleMapItem *mapItem)
return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
}
-QMapbox::Feature featureFromMapPolygon(QDeclarativePolygonMapItem *mapItem)
+static QMapbox::Coordinates qgeocoordinate2mapboxcoordinate(const QList<QGeoCoordinate> &crds, const bool crossesDateline, bool closed = false)
{
- const QGeoPath *path = static_cast<const QGeoPath *>(&mapItem->geoShape());
QMapbox::Coordinates coordinates;
- const bool crossesDateline = geoRectangleCrossesDateLine(path->boundingGeoRectangle());
- for (const QGeoCoordinate &coordinate : path->path()) {
+ for (const QGeoCoordinate &coordinate : crds) {
if (!coordinates.empty() && crossesDateline && qAbs(coordinate.longitude() - coordinates.last().second) > 180.0) {
coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() + (coordinate.longitude() >= 0 ? -360.0 : 360.0) };
} else {
coordinates << QMapbox::Coordinate { coordinate.latitude(), coordinate.longitude() };
}
}
+ if (closed && !coordinates.empty() && coordinates.last() != coordinates.first())
+ coordinates.append(coordinates.first()); // closing the path
+ return coordinates;
+}
- if (!coordinates.empty())
- coordinates.append(coordinates.first()); // closing the path
-
- QMapbox::CoordinatesCollections geometry { { coordinates } };
+QMapbox::Feature featureFromMapPolygon(QDeclarativePolygonMapItem *mapItem)
+{
+ const QGeoPolygon *polygon = static_cast<const QGeoPolygon *>(&mapItem->geoShape());
+ const bool crossesDateline = geoRectangleCrossesDateLine(polygon->boundingGeoRectangle());
+ QMapbox::CoordinatesCollections geometry;
+ QMapbox::CoordinatesCollection poly;
+ QMapbox::Coordinates coordinates = qgeocoordinate2mapboxcoordinate(polygon->path(), crossesDateline, true);
+ poly.push_back(coordinates);
+ for (int i = 0; i < polygon->holesCount(); ++i) {
+ coordinates = qgeocoordinate2mapboxcoordinate(polygon->holePath(i), crossesDateline, true);
+ poly.push_back(coordinates);
+ }
+ geometry.push_back(poly);
return QMapbox::Feature(QMapbox::Feature::PolygonType, geometry, {}, getId(mapItem));
}
@@ -186,8 +198,7 @@ QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::addMapParamete
{
static const QStringList acceptedParameterTypes = QStringList()
<< QStringLiteral("paint") << QStringLiteral("layout") << QStringLiteral("filter")
- << QStringLiteral("layer") << QStringLiteral("source") << QStringLiteral("image")
- << QStringLiteral("margins");
+ << QStringLiteral("layer") << QStringLiteral("source") << QStringLiteral("image");
QList<QSharedPointer<QMapboxGLStyleChange>> changes;
@@ -213,9 +224,6 @@ QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleChange::addMapParamete
case 5: // image
changes << QMapboxGLStyleAddImage::fromMapParameter(param);
break;
- case 6: // margins
- changes << QMapboxGLMapMargins::fromMapParameter(param);
- break;
}
return changes;
@@ -641,38 +649,3 @@ QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddImage::fromMapParameter(QG
return QSharedPointer<QMapboxGLStyleChange>(image);
}
-
-// QMapboxGLMapMargins
-
-void QMapboxGLMapMargins::apply(QMapboxGL *map)
-{
- // FIXME: Qt projection handlers are not yet aware of these margins,
- // thus map items placement, {to,from}Coordinate, mouse area, etc.
- // will require manual fixups.
- map->setMargins(m_margins);
-}
-
-QSharedPointer<QMapboxGLStyleChange> QMapboxGLMapMargins::fromMapParameter(QGeoMapParameter *param)
-{
- Q_ASSERT(param->type() == "margins");
-
- auto mapMargins = new QMapboxGLMapMargins();
-
- QVariant leftMargin = param->property("left");
- if (leftMargin.isValid())
- mapMargins->m_margins.setLeft(leftMargin.toInt());
-
- QVariant topMargin = param->property("top");
- if (topMargin.isValid())
- mapMargins->m_margins.setTop(topMargin.toInt());
-
- QVariant rightMargin = param->property("right");
- if (rightMargin.isValid())
- mapMargins->m_margins.setRight(rightMargin.toInt());
-
- QVariant bottomMargin = param->property("bottom");
- if (bottomMargin.isValid())
- mapMargins->m_margins.setBottom(bottomMargin.toInt());
-
- return QSharedPointer<QMapboxGLStyleChange>(mapMargins);
-}
diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h
index 38aa87f8..fd5b9af4 100644
--- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h
+++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h
@@ -190,17 +190,4 @@ private:
QImage m_sprite;
};
-class QMapboxGLMapMargins : public QMapboxGLStyleChange
-{
-public:
- static QSharedPointer<QMapboxGLStyleChange> fromMapParameter(QGeoMapParameter *);
-
- void apply(QMapboxGL *map) override;
-
-private:
- QMapboxGLMapMargins() = default;
-
- QMargins m_margins;
-};
-
#endif // QQMAPBOXGLSTYLECHANGE_P_H
diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp
index 9808b539..28aa930f 100644
--- a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp
+++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp
@@ -46,6 +46,7 @@
#include <QtLocation/QPlaceIcon>
#include <QtLocation/QPlaceResult>
#include <QtLocation/QPlaceProposedSearchResult>
+#include <QtLocation/private/qplacesearchrequest_p.h>
#include <QtCore/QDebug>
@@ -113,15 +114,24 @@ void QPlaceSearchReplyHere::replyFinished()
results.append(parseSearchResult(item));
}
+ QPlaceSearchRequest r_orig = request();
+ QPlaceSearchRequestPrivate *rpimpl_orig = QPlaceSearchRequestPrivate::get(r_orig);
+
if (resultsObject.contains(QStringLiteral("next"))) {
QPlaceSearchRequest request;
request.setSearchContext(QUrl(resultsObject.value(QStringLiteral("next")).toString()));
+ QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(request);
+ rpimpl->related = true;
+ rpimpl->page = rpimpl_orig->page + 1;
setNextPageRequest(request);
}
if (resultsObject.contains(QStringLiteral("previous"))) {
QPlaceSearchRequest request;
request.setSearchContext(QUrl(resultsObject.value(QStringLiteral("previous")).toString()));
+ QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(request);
+ rpimpl->related = true;
+ rpimpl->page = rpimpl_orig->page - 1;
setPreviousPageRequest(request);
}
diff --git a/src/plugins/geoservices/nokia/qgeoroutexmlparser.cpp b/src/plugins/geoservices/nokia/qgeoroutexmlparser.cpp
index 8e436a97..65e39dee 100644
--- a/src/plugins/geoservices/nokia/qgeoroutexmlparser.cpp
+++ b/src/plugins/geoservices/nokia/qgeoroutexmlparser.cpp
@@ -40,9 +40,12 @@
#include <QStringList>
#include <QString>
#include <QtCore/QThreadPool>
+#include <QDebug>
#include <QtPositioning/QGeoRectangle>
+#include <QtPositioning/QGeoPath>
#include <QtLocation/QGeoRoute>
+#include <QtLocation/private/qgeoroutesegment_p.h>
QT_BEGIN_NAMESPACE
@@ -65,6 +68,10 @@ QGeoRouteXmlParser::~QGeoRouteXmlParser()
void QGeoRouteXmlParser::parse(const QByteArray &data)
{
m_data = data;
+// QFile file("/tmp/here.xml");
+// file.open(QIODevice::WriteOnly);
+// file.write(data);
+// file.close();
QThreadPool::globalInstance()->start(this);
}
@@ -134,8 +141,9 @@ bool QGeoRouteXmlParser::parseRoute(QGeoRoute *route)
{
Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Route");
m_maneuvers.clear();
- m_segments.clear();
-
+// m_segments.clear();
+ m_legs.clear();
+ int legIndex = 0;
m_reader->readNext();
while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Route") &&
!m_reader->hasError()) {
@@ -161,7 +169,7 @@ bool QGeoRouteXmlParser::parseRoute(QGeoRoute *route)
return false;
route->setBounds(bounds);
} else if (m_reader->name() == "Leg") {
- if (!parseLeg())
+ if (!parseLeg(legIndex++))
return false;
} else if (m_reader->name() == "Summary") {
if (!parseSummary(route))
@@ -179,20 +187,32 @@ bool QGeoRouteXmlParser::parseRoute(QGeoRoute *route)
return postProcessRoute(route);
}
-bool QGeoRouteXmlParser::parseLeg()
+bool QGeoRouteXmlParser::parseLeg(int legIndex)
{
- Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Leg");
-
+ Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral("Leg"));
+ QGeoRouteLeg leg;
+ leg.setLegIndex(legIndex);
m_reader->readNext();
- while (!(m_reader->tokenType() == QXmlStreamReader::EndElement && m_reader->name() == "Leg") &&
+ QList<QGeoManeuverContainer> maneuvers;
+ QList<QGeoRouteSegmentContainer> links;
+ while (!(m_reader->tokenType() == QXmlStreamReader::EndElement
+ && m_reader->name() == QStringLiteral("Leg")) &&
!m_reader->hasError()) {
if (m_reader->tokenType() == QXmlStreamReader::StartElement) {
- if (m_reader->name() == "Maneuver") {
- if (!parseManeuver())
- return false;
- } else if (m_reader->name() == "Link") {
- if (!parseLink())
+ if (m_reader->name() == QStringLiteral("Maneuver")) {
+ if (!parseManeuver(maneuvers))
return false;
+ }
+// Currently unused, after requesting shape attribute in maneuvers.
+// Links, however, contain additional info, such as speed limits, and might become needed in the future.
+// else if (m_reader->name() == QStringLiteral("Link")) {
+// if (!parseLink(links))
+// return false;
+// }
+ else if (m_reader->name() == "TravelTime") {
+ leg.setTravelTime(qRound(m_reader->readElementText().toDouble()));
+ } else if (m_reader->name() == "Length") {
+ leg.setDistance(m_reader->readElementText().toDouble());
} else {
m_reader->skipCurrentElement();
}
@@ -200,81 +220,98 @@ bool QGeoRouteXmlParser::parseLeg()
m_reader->readNext();
}
- return !m_reader->hasError();
+ if (m_reader->hasError())
+ return false;
+
+ m_legs << leg;
+// m_segments << links;
+ m_maneuvers << maneuvers;
+ return true;
}
+//static bool fuzzyCompare(const QGeoCoordinate &a, const QGeoCoordinate& b)
+//{
+// return qFuzzyCompare(a.latitude(), b.latitude()) && qFuzzyCompare(a.longitude(), b.longitude());
+//}
+
bool QGeoRouteXmlParser::postProcessRoute(QGeoRoute *route)
{
- QList<QGeoRouteSegment> routeSegments;
+ QList<QList<QGeoRouteSegment>> legSegments;
+ Q_ASSERT(m_maneuvers.size());
+
- int maneuverIndex = 0;
- for (int i = 0; i < m_segments.count(); ++i) {
- // In case there is a maneuver in the middle of the list with no
- // link ID attached, attach it to the next available segment
- while ((maneuverIndex < m_maneuvers.size() - 1) && m_maneuvers.at(maneuverIndex).toId.isEmpty()) {
+ // Step 3: populate the linkMap, linkId -> linkContainer
+ for (int i = 0; i < m_maneuvers.size(); i++) {
+ legSegments << QList<QGeoRouteSegment>();
+ QList<QGeoRouteSegment> &segments = legSegments[i];
+ QList<QGeoManeuverContainer> &maneuvers = m_maneuvers[i];
+ for (int j = 0; j < m_maneuvers.at(i).size(); j++) {
+ QGeoManeuverContainer &maneuver = maneuvers[j];
QGeoRouteSegment segment;
- segment.setManeuver(m_maneuvers.at(maneuverIndex).maneuver);
- QList<QGeoCoordinate> path; // use instruction position as one point segment path
- path.append(m_maneuvers.at(maneuverIndex).maneuver.position());
- segment.setPath(path);
- routeSegments.append(segment);
- ++maneuverIndex;
- }
- QGeoRouteSegment segment = m_segments.at(i).segment;
- if ((maneuverIndex < m_maneuvers.size()) && m_segments.at(i).id == m_maneuvers.at(maneuverIndex).toId) {
- segment.setManeuver(m_maneuvers.at(maneuverIndex).maneuver);
- ++maneuverIndex;
+ QVariantMap extendedAttributes;
+ extendedAttributes["first"] = maneuver.first;
+ extendedAttributes["last"] = maneuver.last;
+ extendedAttributes["legIndex"] = i;
+ extendedAttributes["id"] = maneuver.id;
+ extendedAttributes["toLink"] = maneuver.toLink;
+ extendedAttributes["index"] = j;
+ maneuver.maneuver.setExtendedAttributes(extendedAttributes);
+
+ segment.setDistance(maneuver.maneuver.distanceToNextInstruction());
+ segment.setTravelTime(maneuver.maneuver.timeToNextInstruction());
+ segment.setPath(maneuver.path);
+ segment.setManeuver(maneuver.maneuver);
+ segments << segment;
}
- routeSegments.append(segment);
- }
-
- // For the final maneuver in the list, make sure to attach it to the very
- // last segment on the path, this is why we don't process the last
- // maneuver in the loop above
- while (maneuverIndex < m_maneuvers.size()) {
- QGeoRouteSegment segment;
- segment.setManeuver(m_maneuvers.at(maneuverIndex).maneuver);
- QList<QGeoCoordinate> path; // use instruction position as one point segment path
- path.append(m_maneuvers.at(maneuverIndex).maneuver.position());
- segment.setPath(path);
-
- routeSegments.append(segment);
- ++maneuverIndex;
}
- QList<QGeoRouteSegment> compactedRouteSegments;
- compactedRouteSegments.append(routeSegments.first());
- routeSegments.removeFirst();
-
- while (routeSegments.size() > 0) {
- QGeoRouteSegment segment = routeSegments.first();
- routeSegments.removeFirst();
-
- QGeoRouteSegment lastSegment = compactedRouteSegments.last();
-
- if (lastSegment.maneuver().isValid()) {
- compactedRouteSegments.append(segment);
- } else {
- compactedRouteSegments.removeLast();
- lastSegment.setDistance(lastSegment.distance() + segment.distance());
- lastSegment.setTravelTime(lastSegment.travelTime() + segment.travelTime());
- QList<QGeoCoordinate> path = lastSegment.path();
- path.append(segment.path());
- lastSegment.setPath(path);
- lastSegment.setManeuver(segment.maneuver());
- compactedRouteSegments.append(lastSegment);
+ // Step 7: connect all segments.
+ QGeoRouteSegment segment;
+ QGeoRouteSegment firstSegment;
+ for (auto &segments: legSegments) {
+ for (int j = 0; j < segments.size(); j++) {
+ if (segment.isValid()) {
+ segment.setNextRouteSegment(segments[j]);
+ } else {
+ firstSegment = segments[j];
+ }
+ segment = segments[j];
+ if (j == segments.size() - 1) {
+ QGeoRouteSegmentPrivate *sp = QGeoRouteSegmentPrivate::get(segment);
+ sp->setLegLastSegment(true);
+ }
}
}
- if (compactedRouteSegments.size() > 0) {
- route->setFirstRouteSegment(compactedRouteSegments.at(0));
- for (int i = 0; i < compactedRouteSegments.size() - 1; ++i)
- compactedRouteSegments[i].setNextRouteSegment(compactedRouteSegments.at(i + 1));
+ if (firstSegment.isValid())
+ route->setFirstRouteSegment(firstSegment);
+
+ // Step 8: fill route legs.
+ for (int i = 0; i < m_legs.size(); i++) {
+ m_legs[i].setTravelMode(route->travelMode());
+ m_legs[i].setRequest(route->request());
+ m_legs[i].setOverallRoute(*route);
+ m_legs[i].setLegIndex(i);
+
+ m_legs[i].setFirstRouteSegment(legSegments[i].first());
+
+ // handle path
+ QList<QGeoCoordinate> path;
+ QGeoRouteSegment s = m_legs[i].firstRouteSegment();
+ while (s.isValid()) {
+ path.append(s.path());
+ if (s.isLegLastSegment())
+ break;
+ s = s.nextRouteSegment();
+ }
+ m_legs[i].setPath(path);
+ m_legs[i].setBounds(QGeoPath(path).boundingGeoRectangle());
}
-
+ route->setRouteLegs(m_legs);
+ m_legs.clear();
+// m_segments.clear();
m_maneuvers.clear();
- m_segments.clear();
return true;
}
@@ -394,7 +431,7 @@ bool QGeoRouteXmlParser::parseCoordinates(QGeoCoordinate &coord)
return !m_reader->hasError();
}
-bool QGeoRouteXmlParser::parseManeuver()
+bool QGeoRouteXmlParser::parseManeuver(QList<QGeoManeuverContainer> &maneuvers)
{
Q_ASSERT(m_reader->isStartElement() && m_reader->name() == "Maneuver");
@@ -415,8 +452,14 @@ bool QGeoRouteXmlParser::parseManeuver()
maneuverContainter.maneuver.setPosition(coordinates);
} else if (m_reader->name() == "Instruction") {
maneuverContainter.maneuver.setInstructionText(m_reader->readElementText());
+ } else if (m_reader->name() == "Shape") {
+ QString elementName = m_reader->name().toString();
+ QList<QGeoCoordinate> path;
+ if (!parseGeoPoints(m_reader->readElementText(), &path, elementName))
+ return false;
+ maneuverContainter.path = path;
} else if (m_reader->name() == "ToLink") {
- maneuverContainter.toId = m_reader->readElementText();
+ maneuverContainter.toLink = m_reader->readElementText();
} else if (m_reader->name() == "TravelTime") {
maneuverContainter.maneuver.setTimeToNextInstruction(qRound(m_reader->readElementText().toDouble()));
} else if (m_reader->name() == "Length") {
@@ -457,11 +500,11 @@ bool QGeoRouteXmlParser::parseManeuver()
if (m_reader->hasError())
return false;
- m_maneuvers.append(maneuverContainter);
+ maneuvers.append(maneuverContainter);
return true;
}
-bool QGeoRouteXmlParser::parseLink()
+bool QGeoRouteXmlParser::parseLink(QList<QGeoRouteSegmentContainer> &links)
{
Q_ASSERT(m_reader->isStartElement() && m_reader->name() == QStringLiteral("Link"));
m_reader->readNext();
@@ -498,8 +541,7 @@ bool QGeoRouteXmlParser::parseLink()
if (m_reader->hasError())
return false;
-
- m_segments.append(segmentContainer);
+ links.append(segmentContainer);
return true;
}
diff --git a/src/plugins/geoservices/nokia/qgeoroutexmlparser.h b/src/plugins/geoservices/nokia/qgeoroutexmlparser.h
index e2feb728..7f2cc149 100644
--- a/src/plugins/geoservices/nokia/qgeoroutexmlparser.h
+++ b/src/plugins/geoservices/nokia/qgeoroutexmlparser.h
@@ -45,6 +45,7 @@
#include <QtLocation/QGeoRouteRequest>
#include <QtLocation/QGeoRouteSegment>
#include <QtLocation/QGeoManeuver>
+#include <QtLocation/qgeoroute.h>
QT_BEGIN_NAMESPACE
@@ -58,7 +59,12 @@ class QGeoManeuverContainer
public:
QGeoManeuver maneuver;
QString id;
- QString toId;
+ QString toLink; // Id of the link this maneuver brings into
+ int legIndex = 0;
+ int index = 0;
+ QList<QGeoCoordinate> path;
+ bool first = false;
+ bool last = false;
};
class QGeoRouteSegmentContainer
@@ -67,6 +73,11 @@ public:
QGeoRouteSegment segment;
QString id;
QString maneuverId;
+
+ bool operator ==(const QGeoRouteSegmentContainer &other) const
+ {
+ return ( segment == other.segment && id == other.id && maneuverId == other.maneuverId );
+ }
};
class QGeoDynamicSpeedInfoContainer
@@ -104,9 +115,9 @@ private:
bool parseMode(QGeoRoute *route);
bool parseSummary(QGeoRoute *route);
bool parseGeoPoints(const QString &strPoints, QList<QGeoCoordinate> *geoPoints, const QString &elementName);
- bool parseLeg();
- bool parseManeuver();
- bool parseLink();
+ bool parseLeg(int legIndex);
+ bool parseManeuver(QList<QGeoManeuverContainer> &maneuvers);
+ bool parseLink(QList<QGeoRouteSegmentContainer> &links);
bool postProcessRoute(QGeoRoute *route);
bool parseBoundingBox(QGeoRectangle &bounds);
@@ -117,8 +128,9 @@ private:
QXmlStreamReader *m_reader;
QList<QGeoRoute> m_results;
- QList<QGeoManeuverContainer> m_maneuvers;
- QList<QGeoRouteSegmentContainer> m_segments;
+ QList<QGeoRouteLeg> m_legs;
+ QList<QList<QGeoManeuverContainer>> m_maneuvers;
+ //QList<QList<QGeoRouteSegmentContainer>> m_segments;
};
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp
index 1ae01636..73b998b1 100644
--- a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp
@@ -399,46 +399,36 @@ QString QGeoRoutingManagerEngineNokia::routeRequestString(const QGeoRouteRequest
requestString += trimDouble(area.bottomRight().longitude());
}
-// TODO: work out what was going on here
-// - segment and instruction/maneuever functions are mixed and matched
-// - tried to implement sensible equivalents below
-// QStringList legAttributes;
-// if (request.instructionDetail() & QGeoRouteRequest::BasicSegmentData) {
-// requestString += "&linkattributes=sh,le"; //shape,length
-// legAttributes.append("links");
-// }
-//
-// if (request.instructionDetail() & QGeoRouteRequest::BasicInstructions) {
-// legAttributes.append("maneuvers");
-// requestString += "&maneuverattributes=po,tt,le,di"; //position,traveltime,length,direction
-// if (!(request.instructionDetail() & QGeoRouteRequest::NoSegmentData))
-// requestString += ",li"; //link
-// }
-
QStringList legAttributes;
- if (request.segmentDetail() & QGeoRouteRequest::BasicSegmentData) {
+// if (request.segmentDetail() & QGeoRouteRequest::BasicSegmentData) // QTBUG-70501, this code expects to find links
+ {
requestString += "&linkattributes=sh,le"; //shape,length
legAttributes.append("links");
}
- if (request.maneuverDetail() & QGeoRouteRequest::BasicManeuvers) {
+// if (request.maneuverDetail() & QGeoRouteRequest::BasicManeuvers) // QTBUG-70501, this code expects to find maneuvers
+ {
legAttributes.append("maneuvers");
- requestString += "&maneuverattributes=po,tt,le,di"; //position,traveltime,length,direction
+ //requestString += "&maneuverattributes=po,tt,le,di"; //position,traveltime,length,direction
+ requestString += "&maneuverattributes=all";
if (!(request.segmentDetail() & QGeoRouteRequest::NoSegmentData))
requestString += ",li"; //link
}
+ // Handle QTBUG-70502, when API fixes it
requestString += "&routeattributes=sm,sh,bb,lg"; //summary,shape,boundingBox,legs
if (legAttributes.count() > 0) {
requestString += "&legattributes=";
requestString += legAttributes.join(",");
}
+ // Handle QTBUG-70503, when API fixes it
requestString += "&departure=";
requestString += QDateTime::currentDateTime().toUTC().toString("yyyy-MM-ddThh:mm:ssZ");
requestString += "&instructionformat=text";
+ // ToDo: make this request-able
requestString += "&metricSystem=";
if (QLocale::MetricSystem == measurementSystem())
requestString += "metric";
@@ -447,6 +437,7 @@ QString QGeoRoutingManagerEngineNokia::routeRequestString(const QGeoRouteRequest
const QLocale loc(locale());
+ // ToDo: make this request-able
if (QLocale::C != loc.language() && QLocale::AnyLanguage != loc.language()) {
requestString += "&language=";
requestString += loc.name();
diff --git a/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp b/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp
index f68a0d99..e4ef86d6 100644
--- a/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qgeoserviceproviderplugin_nokia.cpp
@@ -47,11 +47,6 @@
#include <QNetworkProxy>
#include <QCoreApplication>
-static void initResources()
-{
- Q_INIT_RESOURCE(nokia);
-}
-
QT_BEGIN_NAMESPACE
namespace
@@ -117,7 +112,6 @@ namespace
QGeoServiceProviderFactoryNokia::QGeoServiceProviderFactoryNokia()
{
- initResources();
}
QGeoCodingManagerEngine *QGeoServiceProviderFactoryNokia::createGeocodingManagerEngine(
diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp
index ab575463..5094b72e 100644
--- a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp
+++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp
@@ -52,6 +52,7 @@
#include <QtCore/QJsonArray>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
+#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
#include <QtCore/QUrlQuery>
#include <QtNetwork/QNetworkProxy>
@@ -690,13 +691,14 @@ QPlaceIcon QPlaceManagerEngineNokiaV2::icon(const QString &remotePath,
QPlaceIcon icon;
QVariantMap params;
- QRegExp rx("(.*)(/icons/categories/.*)");
+ QRegularExpression rx("(.*)(/icons/categories/.*)");
+ QRegularExpressionMatch match = rx.match(remotePath);
QString iconPrefix;
QString nokiaIcon;
- if (rx.indexIn(remotePath) != -1 && !rx.cap(1).isEmpty() && !rx.cap(2).isEmpty()) {
- iconPrefix = rx.cap(1);
- nokiaIcon = rx.cap(2);
+ if (match.hasMatch() && !match.capturedRef(1).isEmpty() && !match.capturedRef(2).isEmpty()) {
+ iconPrefix = match.captured(1);
+ nokiaIcon = match.captured(2);
if (QFile::exists(m_localDataPath + nokiaIcon))
iconPrefix = QString::fromLatin1("file://") + m_localDataPath;
diff --git a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp
index 732e8d72..af2a03b1 100644
--- a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp
+++ b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp
@@ -75,6 +75,13 @@ void QGeoRouteReplyOsm::networkReplyFinished()
QList<QGeoRoute> routes;
QString errorString;
QGeoRouteReply::Error error = parser->parseReply(routes, errorString, reply->readAll());
+ // Setting the request into the result
+ for (QGeoRoute &route : routes) {
+ route.setRequest(request());
+ for (QGeoRoute &leg: route.routeLegs()) {
+ leg.setRequest(request());
+ }
+ }
if (error == QGeoRouteReply::NoError) {
setRoutes(routes.mid(0, request().numberAlternativeRoutes() + 1));
diff --git a/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp b/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp
index 3c201e41..be66414f 100644
--- a/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp
+++ b/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp
@@ -191,7 +191,7 @@ QPlaceSearchReply *QPlaceManagerEngineOsm::search(const QPlaceSearchRequest &req
this, SLOT(replyError(QPlaceReply::Error,QString)));
if (m_debugQuery)
- reply->requestUrl = requestUrl.toString();
+ reply->requestUrl = requestUrl.url(QUrl::None);
return reply;
}
diff --git a/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp b/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp
index 0228a975..80c50d1b 100644
--- a/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp
+++ b/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp
@@ -48,6 +48,7 @@
#include <QtPositioning/QGeoRectangle>
#include <QtLocation/QPlaceResult>
#include <QtLocation/QPlaceSearchRequest>
+#include <QtLocation/private/qplacesearchrequest_p.h>
QT_BEGIN_NAMESPACE
@@ -135,6 +136,9 @@ void QPlaceSearchReplyOsm::replyFinished()
parameters.insert(QStringLiteral("ExcludePlaceIds"), epi);
r.setSearchContext(parameters);
+ QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(r);
+ rpimpl->related = true;
+ rpimpl->page--;
setPreviousPageRequest(r);
}
@@ -147,6 +151,9 @@ void QPlaceSearchReplyOsm::replyFinished()
parameters.insert(QStringLiteral("ExcludePlaceIds"), epi);
r.setSearchContext(parameters);
+ QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(r);
+ rpimpl->related = true;
+ rpimpl->page++;
setNextPageRequest(r);
}
diff --git a/src/plugins/position/android/src/qgeopositioninfosource_android.cpp b/src/plugins/position/android/src/qgeopositioninfosource_android.cpp
index 7b4706d8..59b8beab 100644
--- a/src/plugins/position/android/src/qgeopositioninfosource_android.cpp
+++ b/src/plugins/position/android/src/qgeopositioninfosource_android.cpp
@@ -223,7 +223,7 @@ void QGeoPositionInfoSourceAndroid::requestTimeout()
const QGeoPositionInfo info = queuedSingleUpdates[i];
//anything newer by 20s is always better
- const int timeDelta = best.timestamp().secsTo(info.timestamp());
+ const qint64 timeDelta = best.timestamp().secsTo(info.timestamp());
if (abs(timeDelta) > 20) {
if (timeDelta > 0)
best = info;
@@ -232,7 +232,7 @@ void QGeoPositionInfoSourceAndroid::requestTimeout()
//compare accuracy
if (info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) &&
- info.hasAttribute(QGeoPositionInfo::HorizontalAccuracy))
+ best.hasAttribute(QGeoPositionInfo::HorizontalAccuracy))
{
best = info.attribute(QGeoPositionInfo::HorizontalAccuracy) <
best.attribute(QGeoPositionInfo::HorizontalAccuracy) ? info : best;
diff --git a/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm
index 94c5b807..6435963b 100644
--- a/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm
+++ b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm
@@ -47,16 +47,16 @@
#define MINIMUM_UPDATE_INTERVAL 1000
@interface PositionLocationDelegate : NSObject <CLLocationManagerDelegate>
+@end
+
+@implementation PositionLocationDelegate
{
QGeoPositionInfoSourceCL *m_positionInfoSource;
}
-@end
-@implementation PositionLocationDelegate
-- (id)initWithInfoSource:(QGeoPositionInfoSourceCL*) positionInfoSource
+- (instancetype)initWithInfoSource:(QGeoPositionInfoSourceCL*) positionInfoSource
{
- self = [super init];
- if (self) {
+ if ((self = [self init])) {
m_positionInfoSource = positionInfoSource;
}
return self;
@@ -140,7 +140,39 @@ void QGeoPositionInfoSourceCL::setUpdateInterval(int msec)
bool QGeoPositionInfoSourceCL::enableLocationManager()
{
if (!m_locationManager) {
- m_locationManager = [[CLLocationManager alloc] init];
+ if ([CLLocationManager locationServicesEnabled]) {
+ // Location Services Are Enabled
+ switch ([CLLocationManager authorizationStatus]) {
+ case kCLAuthorizationStatusNotDetermined:
+ // User has not yet made a choice with regards to this application
+ break;
+ case kCLAuthorizationStatusRestricted:
+ // This application is not authorized to use location services. Due
+ // to active restrictions on location services, the user cannot change
+ // this status, and may not have personally denied authorization
+ return false;
+ case kCLAuthorizationStatusDenied:
+ // User has explicitly denied authorization for this application, or
+ // location services are disabled in Settings
+ return false;
+ case kCLAuthorizationStatusAuthorizedAlways:
+ // This app is authorized to start location services at any time.
+ break;
+#ifndef Q_OS_MACOS
+ case kCLAuthorizationStatusAuthorizedWhenInUse:
+ // This app is authorized to start most location services while running in the foreground.
+ break;
+#endif
+ default:
+ // By default, try to enable it
+ break;
+ }
+ } else {
+ // Location Services Disabled
+ return false;
+ }
+
+ m_locationManager = [[CLLocationManager alloc] init];
#if defined(Q_OS_IOS) || defined(Q_OS_WATCHOS)
if (__builtin_available(watchOS 4.0, *)) {
@@ -162,18 +194,29 @@ bool QGeoPositionInfoSourceCL::enableLocationManager()
m_locationManager.desiredAccuracy = kCLLocationAccuracyBest;
m_locationManager.delegate = [[PositionLocationDelegate alloc] initWithInfoSource:this];
- // These two methods are new in iOS 8. They require NSLocationAlwaysUsageDescription
- // and NSLocationWhenInUseUsageDescription to be set in Info.plist to work (methods are
- // noop if there are no such entries in plist).
+ // -requestAlwaysAuthorization is available on iOS (>= 8.0) and watchOS (>= 2.0).
+ // This method requires both NSLocationAlwaysAndWhenInUseUsageDescription and
+ // NSLocationWhenInUseUsageDescription entries present in Info.plist (otherwise,
+ // while probably a noop, the call generates a warning).
+ // -requestWhenInUseAuthorization only requires NSLocationWhenInUseUsageDescription
+ // entry in Info.plist (available on iOS (>= 8.0), tvOS (>= 9.0) and watchOS (>= 2.0).
+
#ifndef Q_OS_MACOS
+ NSDictionary<NSString *, id> *infoDict = NSBundle.mainBundle.infoDictionary;
+ const bool hasAlwaysUseUsage = !![infoDict objectForKey:@"NSLocationAlwaysAndWhenInUseUsageDescription"];
+ const bool hasWhenInUseUsage = !![infoDict objectForKey:@"NSLocationWhenInUseUsageDescription"];
#ifndef Q_OS_TVOS
- [m_locationManager requestAlwaysAuthorization];
-#endif
- [m_locationManager requestWhenInUseAuthorization];
-#endif
+ if (hasAlwaysUseUsage && hasWhenInUseUsage)
+ [m_locationManager requestAlwaysAuthorization];
+ else
+#endif // !Q_OS_TVOS
+ if (hasWhenInUseUsage)
+ [m_locationManager requestWhenInUseAuthorization];
+#endif // !Q_OS_MACOS
+
}
- return (m_locationManager != 0);
+ return (m_locationManager != nullptr);
}
void QGeoPositionInfoSourceCL::setTimeoutInterval(int msec)
diff --git a/src/plugins/position/geoclue2/geoclue2.pro b/src/plugins/position/geoclue2/geoclue2.pro
new file mode 100644
index 00000000..1bd129d5
--- /dev/null
+++ b/src/plugins/position/geoclue2/geoclue2.pro
@@ -0,0 +1,30 @@
+TARGET = qtposition_geoclue2
+
+QT = core positioning dbus
+
+HEADERS += \
+ qgeopositioninfosource_geoclue2_p.h \
+ qgeopositioninfosourcefactory_geoclue2.h \
+ geocluetypes.h
+
+SOURCES += \
+ qgeopositioninfosource_geoclue2.cpp \
+ qgeopositioninfosourcefactory_geoclue2.cpp \
+ geocluetypes.cpp
+
+QDBUSXML2CPP_INTERFACE_HEADER_FLAGS += \
+ "-N -i geocluetypes.h"
+
+DBUS_INTERFACES += \
+ org.freedesktop.GeoClue2.Manager.xml \
+ org.freedesktop.GeoClue2.Client.xml \
+ org.freedesktop.GeoClue2.Location.xml
+
+INCLUDEPATH += $$QT.location.includes $$OUT_PWD
+
+OTHER_FILES += \
+ plugin.json
+
+PLUGIN_TYPE = position
+PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryGeoclue2
+load(qt_plugin)
diff --git a/src/plugins/position/geoclue2/geocluetypes.cpp b/src/plugins/position/geoclue2/geocluetypes.cpp
new file mode 100644
index 00000000..dec55d3c
--- /dev/null
+++ b/src/plugins/position/geoclue2/geocluetypes.cpp
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** 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$
+**
+****************************************************************************/
+
+#include "geocluetypes.h"
+
+QT_BEGIN_NAMESPACE
+
+QDBusArgument &operator<<(QDBusArgument &arg, const Timestamp &ts)
+{
+ arg.beginStructure();
+ arg << ts.m_seconds;
+ arg << ts.m_microseconds;
+ arg.endStructure();
+ return arg;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &arg, Timestamp &ts)
+{
+ arg.beginStructure();
+ arg >> ts.m_seconds;
+ arg >> ts.m_microseconds;
+ arg.endStructure();
+ return arg;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/position/geoclue2/geocluetypes.h b/src/plugins/position/geoclue2/geocluetypes.h
new file mode 100644
index 00000000..0f3eb522
--- /dev/null
+++ b/src/plugins/position/geoclue2/geocluetypes.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** 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 GEOCLUETYPES_H
+#define GEOCLUETYPES_H
+
+#include <QtDBus/QDBusArgument>
+
+class Timestamp
+{
+public:
+ quint64 m_seconds = 0;
+ quint64 m_microseconds = 0;
+};
+
+Q_DECLARE_METATYPE(Timestamp)
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_TYPEINFO(Timestamp, Q_MOVABLE_TYPE);
+
+QDBusArgument &operator<<(QDBusArgument &arg, const Timestamp &ts);
+const QDBusArgument &operator>>(const QDBusArgument &arg, Timestamp &ts);
+
+QT_END_NAMESPACE
+
+#endif // GEOCLUETYPES_H
diff --git a/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Client.xml b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Client.xml
new file mode 100644
index 00000000..4a9399b7
--- /dev/null
+++ b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Client.xml
@@ -0,0 +1,122 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<!--
+ GeoClue 2.0 Interface Specification
+
+ Copyright 2013 Red Hat, Inc.
+-->
+
+<node>
+
+ <!--
+ org.freedesktop.GeoClue2.Client:
+ @short_description: The Application-specific client API
+
+ This is the interface you use to retrieve location information and receive
+ location update signals from GeoClue service. You get the client object to
+ use this interface on from org.freedesktop.GeoClue2.Manager.GetClient()
+ method.
+ -->
+ <interface name="org.freedesktop.GeoClue2.Client">
+ <!--
+ Location:
+
+ Current location as path to a #org.freedesktop.GeoClue2.Location object.
+ Please note that this property will be set to "/" (D-Bus equivalent of
+ null) initially, until Geoclue finds user's location. You want to delay
+ reading this property until your callback to
+ #org.freedesktop.GeoClue2.Client::LocationUpdated signal is called for
+ the first time after starting the client.
+ -->
+ <property name="Location" type="o" access="read"/>
+
+ <!--
+ DistanceThreshold:
+
+ Contains the current distance threshold in meters. This value is used
+ by the service when it gets new location info. If the distance moved is
+ below the threshold, it won't emit the LocationUpdated signal.
+ The default value is 0. When TimeThreshold is zero, it always emits
+ the signal.
+ -->
+ <property name="DistanceThreshold" type="u" access="readwrite">
+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
+ </property>
+
+ <!--
+ TimeThreshold:
+
+ Contains the current time threshold in seconds. This value is used
+ by the service when it gets new location info. If the time since the
+ last update is below the threshold, it won't emit the LocationUpdated
+ signal. The default value is 0. When TimeThreshold is zero, it always
+ emits the signal.
+ -->
+ <property name="TimeThreshold" type="u" access="readwrite">
+ <annotation name="org.freedesktop.Accounts.DefaultValue" value="0"/>
+ </property>
+
+ <!--
+ DesktopId:
+
+ The desktop file id (the basename of the desktop file). This property
+ must be set by applications for authorization to work.
+ -->
+ <property name="DesktopId" type="s" access="readwrite"/>
+
+ <!--
+ RequestedAccuracyLevel:
+
+ The level of accuracy requested by client, as
+ <link linkend="GClueAccuracyLevel">GClueAccuracyLevel</link>.
+
+ Please keep in mind that the actual accuracy of location information is
+ dependent on available hardware on your machine, external resources
+ and/or how much accuracy user agrees to be confortable with.
+ -->
+ <property name="RequestedAccuracyLevel" type="u" access="readwrite"/>
+
+ <!--
+ Active:
+
+ If client is active, i-e started successfully using
+ org.freedesktop.GeoClue2.Client.Start() and receiving location updates.
+
+ Please keep in mind that geoclue can at any time stop and start the
+ client on user (agent) request. Applications that are interested in
+ in these changes, should watch for changes in this property.
+ -->
+ <property name="Active" type="b" access="read"/>
+
+ <!--
+ Start:
+
+ Start receiving events about the current location. Applications should
+ hook-up to #org.freedesktop.GeoClue2.Client::LocationUpdated signal
+ before calling this method.
+ -->
+ <method name="Start"/>
+
+ <!--
+ Stop:
+
+ Stop receiving events about the current location.
+ -->
+ <method name="Stop"/>
+
+ <!--
+ LocationUpdated:
+ @old: old location as path to a #org.freedesktop.GeoClue2.Location object
+ @new: new location as path to a #org.freedesktop.GeoClue2.Location object
+
+ The signal is emitted every time the location changes.
+ The client should set the DistanceThreshold property to control how
+ often this signal is emitted.
+ -->
+ <signal name="LocationUpdated">
+ <arg name="oldLocation" type="o"/>
+ <arg name="newLocation" type="o"/>
+ </signal>
+ </interface>
+</node>
diff --git a/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Location.xml b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Location.xml
new file mode 100644
index 00000000..ebf2ea6b
--- /dev/null
+++ b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Location.xml
@@ -0,0 +1,96 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<!--
+ GeoClue 2.0 Interface Specification
+
+ Copyright 2013 Red Hat, Inc.
+-->
+
+<node>
+
+ <!--
+ org.freedesktop.GeoClue2.Location:
+ @short_description: The Location interface
+
+ This is the interface you use on location objects.
+ -->
+ <interface name="org.freedesktop.GeoClue2.Location">
+
+ <!--
+ Latitude:
+
+ The latitude of the location, in degrees.
+ -->
+ <property name="Latitude" type="d" access="read"/>
+
+ <!--
+ Longitude:
+
+ The longitude of the location, in degrees.
+ -->
+ <property name="Longitude" type="d" access="read"/>
+
+ <!--
+ Accuracy:
+
+ The accuracy of the location fix, in meters.
+ -->
+ <property name="Accuracy" type="d" access="read"/>
+
+ <!--
+ Altitude:
+
+ The altitude of the location fix, in meters. When unknown, its set to
+ minimum double value, -1.7976931348623157e+308.
+ -->
+ <property name="Altitude" type="d" access="read"/>
+
+ <!--
+ Speed:
+
+ The speed in meters per second. When unknown, it's set to -1.0.
+ -->
+ <property name="Speed" type="d" access="read"/>
+
+ <!--
+ Heading:
+
+ The heading direction in degrees with respect to North direction, in
+ clockwise order. That means North becomes 0 degree, East: 90 degrees,
+ South: 180 degrees, West: 270 degrees and so on. When unknown,
+ it's set to -1.0.
+ -->
+ <property name="Heading" type="d" access="read"/>
+
+ <!--
+ Description:
+
+ A human-readable description of the location, if available.
+
+ WARNING: Applications should not rely on this property since not all
+ sources provide a description. If you really need a description (or
+ more details) about current location, use a reverse-geocoding API, e.g
+ geocode-glib.
+ -->
+ <property name="Description" type="s" access="read"/>
+
+
+ <!--
+ Timestamp:
+
+ The timestamp when the location was determined, in seconds and
+ microseconds since the Epoch. This is the time of measurement if the
+ backend provided that information, otherwise the time when GeoClue
+ received the new location.
+
+ Note that GeoClue can't guarantee that the timestamp will always
+ monotonically increase, as a backend may not respect that.
+ Also note that a timestamp can be very old, e.g. because of a cached
+ location.
+ -->
+ <property name="Timestamp" type="(tt)" access="read">
+ <annotation name="org.qtproject.QtDBus.QtTypeName" value="Timestamp"/>
+ </property>
+ </interface>
+</node>
diff --git a/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Manager.xml b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Manager.xml
new file mode 100644
index 00000000..cf9590f6
--- /dev/null
+++ b/src/plugins/position/geoclue2/org.freedesktop.GeoClue2.Manager.xml
@@ -0,0 +1,60 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+
+<!--
+ GeoClue 2.0 Interface Specification
+
+ Copyright 2013 Red Hat, Inc.
+-->
+
+<node>
+
+ <!--
+ org.freedesktop.GeoClue2.Manager:
+ @short_description: The GeoClue service manager
+
+ This is the interface you use to talk to main GeoClue2 manager object at
+ path "/org/freedesktop/GeoClue2/Manager". The only thing you do with this
+ interface is to call org.freedesktop.GeoClue2.Manager.GetClient() on it
+ to get your application specific client object.
+ -->
+ <interface name="org.freedesktop.GeoClue2.Manager">
+ <!--
+ InUse:
+
+ Whether service is currently is use by any application.
+ -->
+ <property name="InUse" type="b" access="read"/>
+
+ <!--
+ AvailableAccuracyLevel:
+
+ The level of available accuracy, as
+ <link linkend="GClueAccuracyLevel">GClueAccuracyLevel</link>.
+ -->
+ <property name="AvailableAccuracyLevel" type="u" access="read"/>
+
+ <!--
+ GetClient:
+ @client: The path for newly created client object
+
+ Retrieves a client object which can only be used by the calling
+ application only.
+ -->
+ <method name="GetClient">
+ <arg name="client" type="o" direction="out"/>
+ </method>
+
+ <!--
+ AddAgent:
+ @id: The Desktop ID (excluding .desktop) of the agent
+
+ An API for user authorization agents to register themselves. Each agent
+ is responsible for the user it is running as. Application developers
+ can and should simply ignore this API.
+ -->
+ <method name="AddAgent">
+ <arg name="id" type="s" direction="in"/>
+ </method>
+ </interface>
+</node>
diff --git a/src/plugins/position/geoclue2/plugin.json b/src/plugins/position/geoclue2/plugin.json
new file mode 100644
index 00000000..c23d40e0
--- /dev/null
+++ b/src/plugins/position/geoclue2/plugin.json
@@ -0,0 +1,9 @@
+{
+ "Keys": ["geoclue2"],
+ "Provider": "geoclue2",
+ "Position": true,
+ "Satellite": false,
+ "Monitor": false,
+ "Priority": 1000,
+ "Testable": false
+}
diff --git a/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2.cpp b/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2.cpp
new file mode 100644
index 00000000..10484e3b
--- /dev/null
+++ b/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2.cpp
@@ -0,0 +1,443 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qgeopositioninfosource_geoclue2_p.h"
+
+#include <QtCore/QLoggingCategory>
+#include <QtCore/QSaveFile>
+#include <QtCore/QScopedPointer>
+#include <QtCore/QTimer>
+#include <QtDBus/QDBusPendingCallWatcher>
+
+// Auto-generated D-Bus files.
+#include <client_interface.h>
+#include <location_interface.h>
+
+Q_DECLARE_LOGGING_CATEGORY(lcPositioningGeoclue2)
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+
+// NOTE: Copied from the /usr/include/libgeoclue-2.0/gclue-client.h
+enum GClueAccuracyLevel {
+ GCLUE_ACCURACY_LEVEL_NONE = 0,
+ GCLUE_ACCURACY_LEVEL_COUNTRY = 1,
+ GCLUE_ACCURACY_LEVEL_CITY = 4,
+ GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD = 5,
+ GCLUE_ACCURACY_LEVEL_STREET = 6,
+ GCLUE_ACCURACY_LEVEL_EXACT = 8
+};
+
+const char GEOCLUE2_SERVICE_NAME[] = "org.freedesktop.GeoClue2";
+const int MINIMUM_UPDATE_INTERVAL = 1000;
+const int UPDATE_TIMEOUT_COLD_START = 120000;
+
+static QString lastPositionFilePath()
+{
+ return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation)
+ + QStringLiteral("/qtposition-geoclue2");
+}
+
+} // namespace
+
+QGeoPositionInfoSourceGeoclue2::QGeoPositionInfoSourceGeoclue2(QObject *parent)
+ : QGeoPositionInfoSource(parent)
+ , m_requestTimer(new QTimer(this))
+ , m_manager(QLatin1String(GEOCLUE2_SERVICE_NAME),
+ QStringLiteral("/org/freedesktop/GeoClue2/Manager"),
+ QDBusConnection::systemBus(),
+ this)
+{
+ qDBusRegisterMetaType<Timestamp>();
+
+ restoreLastPosition();
+
+ m_requestTimer->setSingleShot(true);
+ connect(m_requestTimer, &QTimer::timeout,
+ this, &QGeoPositionInfoSourceGeoclue2::requestUpdateTimeout);
+}
+
+QGeoPositionInfoSourceGeoclue2::~QGeoPositionInfoSourceGeoclue2()
+{
+ saveLastPosition();
+}
+
+void QGeoPositionInfoSourceGeoclue2::setUpdateInterval(int msec)
+{
+ QGeoPositionInfoSource::setUpdateInterval(msec);
+ configureClient();
+}
+
+QGeoPositionInfo QGeoPositionInfoSourceGeoclue2::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
+{
+ if (fromSatellitePositioningMethodsOnly && !m_lastPositionFromSatellite)
+ return QGeoPositionInfo();
+ return m_lastPosition;
+}
+
+QGeoPositionInfoSourceGeoclue2::PositioningMethods QGeoPositionInfoSourceGeoclue2::supportedPositioningMethods() const
+{
+ bool ok;
+ const auto accuracy = m_manager.property("AvailableAccuracyLevel").toUInt(&ok);
+ if (!ok) {
+ const_cast<QGeoPositionInfoSourceGeoclue2 *>(this)->setError(AccessError);
+ return NoPositioningMethods;
+ }
+
+ switch (accuracy) {
+ case GCLUE_ACCURACY_LEVEL_COUNTRY:
+ case GCLUE_ACCURACY_LEVEL_CITY:
+ case GCLUE_ACCURACY_LEVEL_NEIGHBORHOOD:
+ case GCLUE_ACCURACY_LEVEL_STREET:
+ return NonSatellitePositioningMethods;
+ case GCLUE_ACCURACY_LEVEL_EXACT:
+ return AllPositioningMethods;
+ case GCLUE_ACCURACY_LEVEL_NONE:
+ default:
+ return NoPositioningMethods;
+ }
+}
+
+void QGeoPositionInfoSourceGeoclue2::setPreferredPositioningMethods(PositioningMethods methods)
+{
+ QGeoPositionInfoSource::setPreferredPositioningMethods(methods);
+ configureClient();
+}
+
+int QGeoPositionInfoSourceGeoclue2::minimumUpdateInterval() const
+{
+ return MINIMUM_UPDATE_INTERVAL;
+}
+
+QGeoPositionInfoSource::Error QGeoPositionInfoSourceGeoclue2::error() const
+{
+ return m_error;
+}
+
+void QGeoPositionInfoSourceGeoclue2::startUpdates()
+{
+ if (m_running) {
+ qCWarning(lcPositioningGeoclue2) << "Already running";
+ return;
+ }
+
+ qCDebug(lcPositioningGeoclue2) << "Starting updates";
+ m_running = true;
+
+ startClient();
+
+ if (m_lastPosition.isValid()) {
+ QMetaObject::invokeMethod(this, "positionUpdated", Qt::QueuedConnection,
+ Q_ARG(QGeoPositionInfo, m_lastPosition));
+ }
+}
+
+void QGeoPositionInfoSourceGeoclue2::stopUpdates()
+{
+ if (!m_running) {
+ qCWarning(lcPositioningGeoclue2) << "Already stopped";
+ return;
+ }
+
+ qCDebug(lcPositioningGeoclue2) << "Stopping updates";
+ m_running = false;
+
+ stopClient();
+}
+
+void QGeoPositionInfoSourceGeoclue2::requestUpdate(int timeout)
+{
+ if (timeout < minimumUpdateInterval() && timeout != 0) {
+ emit updateTimeout();
+ return;
+ }
+
+ if (m_requestTimer->isActive()) {
+ qCDebug(lcPositioningGeoclue2) << "Request timer was active, ignoring startUpdates";
+ return;
+ }
+
+ m_requestTimer->start(timeout ? timeout : UPDATE_TIMEOUT_COLD_START);
+ startClient();
+}
+
+void QGeoPositionInfoSourceGeoclue2::setError(QGeoPositionInfoSource::Error error)
+{
+ m_error = error;
+ emit QGeoPositionInfoSource::error(m_error);
+}
+
+void QGeoPositionInfoSourceGeoclue2::restoreLastPosition()
+{
+#if !defined(QT_NO_DATASTREAM)
+ const auto filePath = lastPositionFilePath();
+ QFile file(filePath);
+ if (file.open(QIODevice::ReadOnly)) {
+ QDataStream out(&file);
+ out >> m_lastPosition;
+ }
+#endif
+}
+
+void QGeoPositionInfoSourceGeoclue2::saveLastPosition()
+{
+#if !defined(QT_NO_DATASTREAM) && QT_CONFIG(temporaryfile)
+ if (!m_lastPosition.isValid())
+ return;
+
+ const auto filePath = lastPositionFilePath();
+ QSaveFile file(filePath);
+ if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ QDataStream out(&file);
+ // Only save position and timestamp.
+ out << QGeoPositionInfo(m_lastPosition.coordinate(), m_lastPosition.timestamp());
+ file.commit();
+ }
+#endif
+}
+
+void QGeoPositionInfoSourceGeoclue2::createClient()
+{
+ const QDBusPendingReply<QDBusObjectPath> reply = m_manager.GetClient();
+ const auto watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ [this](QDBusPendingCallWatcher *watcher) {
+ const QScopedPointer<QDBusPendingCallWatcher, QScopedPointerDeleteLater>
+ scopedWatcher(watcher);
+ const QDBusPendingReply<QDBusObjectPath> reply = *scopedWatcher;
+ if (reply.isError()) {
+ const auto error = reply.error();
+ qCWarning(lcPositioningGeoclue2) << "Unable to obtain the client patch:"
+ << error.name() + error.message();
+ setError(AccessError);
+ } else {
+ const QString clientPath = reply.value().path();
+ qCDebug(lcPositioningGeoclue2) << "Client path is:"
+ << clientPath;
+ delete m_client;
+ m_client = new OrgFreedesktopGeoClue2ClientInterface(
+ QLatin1String(GEOCLUE2_SERVICE_NAME),
+ clientPath,
+ QDBusConnection::systemBus(),
+ this);
+ if (!m_client->isValid()) {
+ const auto error = m_client->lastError();
+ qCCritical(lcPositioningGeoclue2) << "Unable to create the client object:"
+ << error.name() << error.message();
+ setError(AccessError);
+ delete m_client;
+ } else {
+ connect(m_client.data(), &OrgFreedesktopGeoClue2ClientInterface::LocationUpdated,
+ this, &QGeoPositionInfoSourceGeoclue2::handleNewLocation);
+
+ if (configureClient())
+ startClient();
+ }
+ }
+ });
+}
+
+void QGeoPositionInfoSourceGeoclue2::startClient()
+{
+ // only start the client if someone asked for it already
+ if (!m_running && !m_requestTimer->isActive())
+ return;
+
+ if (!m_client) {
+ createClient();
+ return;
+ }
+
+ const QDBusPendingReply<> reply = m_client->Start();
+ const auto watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ [this](QDBusPendingCallWatcher *watcher) {
+ const QScopedPointer<QDBusPendingCallWatcher, QScopedPointerDeleteLater>
+ scopedWatcher(watcher);
+ const QDBusPendingReply<> reply = *scopedWatcher;
+ if (reply.isError()) {
+ const auto error = reply.error();
+ qCCritical(lcPositioningGeoclue2) << "Unable to start the client:"
+ << error.name() << error.message();
+ setError(AccessError);
+ delete m_client;
+ } else {
+ qCDebug(lcPositioningGeoclue2) << "Client successfully started";
+
+ const QDBusObjectPath location = m_client->location();
+ const QString path = location.path();
+ if (path.isEmpty() || path == QLatin1String("/"))
+ return;
+
+ handleNewLocation({}, location);
+ }
+ });
+}
+
+void QGeoPositionInfoSourceGeoclue2::stopClient()
+{
+ // Only stop client if updates are no longer wanted.
+ if (m_requestTimer->isActive() || m_running || !m_client)
+ return;
+
+ const QDBusPendingReply<> reply = m_client->Stop();
+ const auto watcher = new QDBusPendingCallWatcher(reply, this);
+ connect(watcher, &QDBusPendingCallWatcher::finished,
+ [this](QDBusPendingCallWatcher *watcher) {
+ const QScopedPointer<QDBusPendingCallWatcher, QScopedPointerDeleteLater>
+ scopedWatcher(watcher);
+ const QDBusPendingReply<> reply = *scopedWatcher;
+ if (reply.isError()) {
+ const auto error = reply.error();
+ qCCritical(lcPositioningGeoclue2) << "Unable to stop the client:"
+ << error.name() << error.message();
+ setError(AccessError);
+ } else {
+ qCDebug(lcPositioningGeoclue2) << "Client successfully stopped";
+ }
+ delete m_client;
+ });
+}
+
+bool QGeoPositionInfoSourceGeoclue2::configureClient()
+{
+ if (!m_client)
+ return false;
+
+ auto desktopId = QString::fromUtf8(qgetenv("QT_GEOCLUE_APP_DESKTOP_ID"));
+ if (desktopId.isEmpty())
+ desktopId = QCoreApplication::applicationName();
+ if (desktopId.isEmpty()) {
+ qCCritical(lcPositioningGeoclue2) << "Unable to configure the client "
+ "due to the application desktop id "
+ "is not set via QT_GEOCLUE_APP_DESKTOP_ID "
+ "envirorment variable or QCoreApplication::applicationName";
+ setError(AccessError);
+ return false;
+ }
+
+ m_client->setDesktopId(desktopId);
+
+ const auto msecs = updateInterval();
+ const uint secs = qMax(uint(msecs), 0u) / 1000u;
+ m_client->setTimeThreshold(secs);
+
+ const auto methods = preferredPositioningMethods();
+ switch (methods) {
+ case SatellitePositioningMethods:
+ m_client->setRequestedAccuracyLevel(GCLUE_ACCURACY_LEVEL_EXACT);
+ break;
+ case NonSatellitePositioningMethods:
+ m_client->setRequestedAccuracyLevel(GCLUE_ACCURACY_LEVEL_STREET);
+ break;
+ case AllPositioningMethods:
+ m_client->setRequestedAccuracyLevel(GCLUE_ACCURACY_LEVEL_EXACT);
+ break;
+ default:
+ m_client->setRequestedAccuracyLevel(GCLUE_ACCURACY_LEVEL_NONE);
+ break;
+ }
+
+ return true;
+}
+
+void QGeoPositionInfoSourceGeoclue2::requestUpdateTimeout()
+{
+ qCDebug(lcPositioningGeoclue2) << "Request update timeout occurred";
+
+ emit updateTimeout();
+
+ stopClient();
+}
+
+void QGeoPositionInfoSourceGeoclue2::handleNewLocation(const QDBusObjectPath &oldLocation,
+ const QDBusObjectPath &newLocation)
+{
+ if (m_requestTimer->isActive())
+ m_requestTimer->stop();
+
+ const auto oldPath = oldLocation.path();
+ const auto newPath = newLocation.path();
+ qCDebug(lcPositioningGeoclue2) << "Old location object path:" << oldPath;
+ qCDebug(lcPositioningGeoclue2) << "New location object path:" << newPath;
+
+ OrgFreedesktopGeoClue2LocationInterface location(
+ QLatin1String(GEOCLUE2_SERVICE_NAME),
+ newPath,
+ QDBusConnection::systemBus(),
+ this);
+ if (!location.isValid()) {
+ const auto error = location.lastError();
+ qCCritical(lcPositioningGeoclue2) << "Unable to create the location object:"
+ << error.name() << error.message();
+ } else {
+ QGeoCoordinate coordinate(location.latitude(),
+ location.longitude());
+ if (const auto altitude = location.altitude() > std::numeric_limits<double>::min())
+ coordinate.setAltitude(altitude);
+
+ const Timestamp ts = location.timestamp();
+ if (ts.m_seconds == 0 && ts.m_microseconds == 0) {
+ const auto dt = QDateTime::currentDateTime();
+ m_lastPosition = QGeoPositionInfo(coordinate, dt);
+ } else {
+ auto dt = QDateTime::fromSecsSinceEpoch(qint64(ts.m_seconds));
+ dt = dt.addMSecs(ts.m_microseconds / 1000);
+ m_lastPosition = QGeoPositionInfo(coordinate, dt);
+ }
+
+ const auto accuracy = location.accuracy();
+ // We assume that an accuracy as 0.0 means that it comes from a sattelite.
+ m_lastPositionFromSatellite = qFuzzyCompare(accuracy, 0.0);
+
+ m_lastPosition.setAttribute(QGeoPositionInfo::HorizontalAccuracy, accuracy);
+ if (const auto speed = location.speed() >= 0.0)
+ m_lastPosition.setAttribute(QGeoPositionInfo::GroundSpeed, speed);
+ if (const auto heading = location.heading() >= 0.0)
+ m_lastPosition.setAttribute(QGeoPositionInfo::Direction, heading);
+
+ emit positionUpdated(m_lastPosition);
+ qCDebug(lcPositioningGeoclue2) << "New position:" << m_lastPosition;
+ }
+
+ stopClient();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2_p.h b/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2_p.h
new file mode 100644
index 00000000..16f5b9a1
--- /dev/null
+++ b/src/plugins/position/geoclue2/qgeopositioninfosource_geoclue2_p.h
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** 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 QGEOPOSITIONINFOSOURCE_GEOCLUE2_P_H
+#define QGEOPOSITIONINFOSOURCE_GEOCLUE2_P_H
+
+#include <QtPositioning/QGeoPositionInfoSource>
+#include <QtCore/QPointer>
+#include <manager_interface.h>
+
+class OrgFreedesktopGeoClue2ClientInterface;
+
+QT_BEGIN_NAMESPACE
+class QDBusObjectPath;
+class QTimer;
+
+class QGeoPositionInfoSourceGeoclue2 : public QGeoPositionInfoSource
+{
+ Q_OBJECT
+
+public:
+ explicit QGeoPositionInfoSourceGeoclue2(QObject *parent = nullptr);
+ ~QGeoPositionInfoSourceGeoclue2();
+
+ // From QGeoPositionInfoSource
+ 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 override;
+
+ void startUpdates() override;
+ void stopUpdates() override;
+ void requestUpdate(int timeout = 5000) override;
+
+private:
+ void setError(QGeoPositionInfoSource::Error error);
+ void restoreLastPosition();
+ void saveLastPosition();
+ void createClient();
+ bool configureClient();
+ void startClient();
+ void stopClient();
+ void requestUpdateTimeout();
+ void handleNewLocation(const QDBusObjectPath &oldLocation,
+ const QDBusObjectPath &newLocation);
+
+ QTimer *m_requestTimer = nullptr;
+ OrgFreedesktopGeoClue2ManagerInterface m_manager;
+ QPointer<OrgFreedesktopGeoClue2ClientInterface> m_client;
+ bool m_running = false;
+ bool m_lastPositionFromSatellite = false;
+ QGeoPositionInfoSource::Error m_error = NoError;
+ QGeoPositionInfo m_lastPosition;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOPOSITIONINFOSOURCE_GEOCLUE2_P_H
diff --git a/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.cpp b/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.cpp
new file mode 100644
index 00000000..a713c31f
--- /dev/null
+++ b/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** 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$
+**
+****************************************************************************/
+
+#include "qgeopositioninfosource_geoclue2_p.h"
+#include "qgeopositioninfosourcefactory_geoclue2.h"
+
+#include <QtCore/QLoggingCategory>
+
+Q_LOGGING_CATEGORY(lcPositioningGeoclue2, "qt.positioning.geoclue2")
+
+QT_BEGIN_NAMESPACE
+
+QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryGeoclue2::positionInfoSource(QObject *parent)
+{
+ return new QGeoPositionInfoSourceGeoclue2(parent);
+}
+
+QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryGeoclue2::satelliteInfoSource(QObject *parent)
+{
+ Q_UNUSED(parent)
+ return nullptr;
+}
+
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryGeoclue2::areaMonitor(QObject *parent)
+{
+ Q_UNUSED(parent)
+ return nullptr;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.h b/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.h
new file mode 100644
index 00000000..bfacd848
--- /dev/null
+++ b/src/plugins/position/geoclue2/qgeopositioninfosourcefactory_geoclue2.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Denis Shienkov <denis.shienkov@gmail.com>
+** Contact: http://www.qt-project.org/legal
+**
+** 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 QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE2_H
+#define QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE2_H
+
+#include <QtCore/QObject>
+#include <QtPositioning/QGeoPositionInfoSourceFactory>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ Qt Positioning plugin for Geoclue. This plugin supports Geoclue version 2.x.
+*/
+class QGeoPositionInfoSourceFactoryGeoclue2 : public QObject, public QGeoPositionInfoSourceFactory
+{
+ Q_OBJECT
+
+ Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0"
+ FILE "plugin.json")
+
+ Q_INTERFACES(QGeoPositionInfoSourceFactory)
+
+public:
+ QGeoPositionInfoSource *positionInfoSource(QObject *parent) override;
+ QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent) override;
+ QGeoAreaMonitorSource *areaMonitor(QObject *parent) override;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOPOSITIONINFOSOURCEFACTORY_GEOCLUE2_H
diff --git a/src/plugins/position/position.pro b/src/plugins/position/position.pro
index b9832ff4..6800d5a3 100644
--- a/src/plugins/position/position.pro
+++ b/src/plugins/position/position.pro
@@ -2,7 +2,8 @@ TEMPLATE = subdirs
QT_FOR_CONFIG += positioning-private
-qtHaveModule(dbus):SUBDIRS += geoclue
+linux:qtHaveModule(dbus):SUBDIRS += geoclue
+linux:qtHaveModule(dbus):SUBDIRS += geoclue2
qtConfig(gypsy):SUBDIRS += gypsy
qtConfig(winrt_geolocation):SUBDIRS += winrt
qtHaveModule(simulator):SUBDIRS += simulator
diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
index 046d862e..139a6b3d 100644
--- a/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
+++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt.cpp
@@ -36,11 +36,12 @@
#include "qgeopositioninfosource_winrt_p.h"
-#include <QCoreApplication>
-#include <QMutex>
-#include <qfunctions_winrt.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qfunctions_winrt.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qmutex.h>
#ifdef Q_OS_WINRT
-#include <private/qeventdispatcher_winrt_p.h>
+#include <QtCore/private/qeventdispatcher_winrt_p.h>
#endif
#include <functional>
@@ -56,10 +57,11 @@ using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::Foundation::Collections;
typedef ITypedEventHandler<Geolocator *, PositionChangedEventArgs *> GeoLocatorPositionHandler;
-typedef ITypedEventHandler<Geolocator *, StatusChangedEventArgs *> GeoLocatorStatusHandler;
typedef IAsyncOperationCompletedHandler<Geoposition*> PositionHandler;
typedef IAsyncOperationCompletedHandler<GeolocationAccessStatus> AccessHandler;
+Q_DECLARE_LOGGING_CATEGORY(lcPositioningWinRT)
+
QT_BEGIN_NAMESPACE
#ifndef Q_OS_WINRT
@@ -70,7 +72,36 @@ HRESULT runOnXamlThread(const std::function<HRESULT ()> &delegate, bool waitForR
return delegate();
}
}
-#endif
+
+static inline HRESULT await(const ComPtr<IAsyncOperation<GeolocationAccessStatus>> &asyncOp,
+ GeolocationAccessStatus *result)
+{
+ ComPtr<IAsyncInfo> asyncInfo;
+ HRESULT hr = asyncOp.As(&asyncInfo);
+ if (FAILED(hr))
+ return hr;
+
+ AsyncStatus status;
+ while (SUCCEEDED(hr = asyncInfo->get_Status(&status)) && status == AsyncStatus::Started)
+ QThread::yieldCurrentThread();
+
+ if (FAILED(hr) || status != AsyncStatus::Completed) {
+ HRESULT ec;
+ hr = asyncInfo->get_ErrorCode(&ec);
+ if (FAILED(hr))
+ return hr;
+ hr = asyncInfo->Close();
+ if (FAILED(hr))
+ return hr;
+ return ec;
+ }
+
+ if (FAILED(hr))
+ return hr;
+
+ return asyncOp->GetResults(result);
+}
+#endif // !Q_OS_WINRT
class QGeoPositionInfoSourceWinRTPrivate {
public:
@@ -83,13 +114,37 @@ public:
EventRegistrationToken positionToken;
QMutex mutex;
bool updatesOngoing;
+ int minimumUpdateInterval;
+
+ PositionStatus nativeStatus() const;
};
+PositionStatus QGeoPositionInfoSourceWinRTPrivate::nativeStatus() const
+{
+#ifdef Q_OS_WINRT
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
+
+ PositionStatus status;
+ HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, &status]() {
+ return locator->get_LocationStatus(&status);
+ });
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Could not query status");
+ return PositionStatus_NotAvailable;
+ }
+ return status;
+#else
+ return PositionStatus_Ready;
+#endif
+}
+
QGeoPositionInfoSourceWinRT::QGeoPositionInfoSourceWinRT(QObject *parent)
: QGeoPositionInfoSource(parent)
, d_ptr(new QGeoPositionInfoSourceWinRTPrivate)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
+ CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
Q_D(QGeoPositionInfoSourceWinRT);
d->positionError = QGeoPositionInfoSource::NoError;
d->updatesOngoing = false;
@@ -97,10 +152,13 @@ QGeoPositionInfoSourceWinRT::QGeoPositionInfoSourceWinRT(QObject *parent)
QGeoPositionInfoSourceWinRT::~QGeoPositionInfoSourceWinRT()
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
+ CoUninitialize();
}
int QGeoPositionInfoSourceWinRT::init()
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(QGeoPositionInfoSourceWinRT);
if (!requestAccess()) {
qWarning ("Location access failed.");
@@ -111,13 +169,11 @@ int QGeoPositionInfoSourceWinRT::init()
&d->locator);
RETURN_HR_IF_FAILED("Could not initialize native location services.");
- hr = d->locator->add_StatusChanged(Callback<GeoLocatorStatusHandler>(this,
- &QGeoPositionInfoSourceWinRT::onStatusChanged).Get(),
- &d->statusToken);
- RETURN_HR_IF_FAILED("Could not add status callback.");
-
- hr = d->locator->put_ReportInterval(1000);
- RETURN_HR_IF_FAILED("Could not initialize report interval.");
+ UINT32 interval;
+ hr = d->locator->get_ReportInterval(&interval);
+ RETURN_HR_IF_FAILED("Could not retrieve report interval.");
+ d->minimumUpdateInterval = static_cast<int>(interval);
+ setUpdateInterval(d->minimumUpdateInterval);
return hr;
});
@@ -137,7 +193,6 @@ int QGeoPositionInfoSourceWinRT::init()
d->positionToken.value = 0;
d->periodicTimer.setSingleShot(true);
- d->periodicTimer.setInterval(minimumUpdateInterval());
connect(&d->periodicTimer, &QTimer::timeout, this, &QGeoPositionInfoSourceWinRT::virtualPositionUpdate);
d->singleUpdateTimer.setSingleShot(true);
@@ -151,6 +206,7 @@ int QGeoPositionInfoSourceWinRT::init()
QGeoPositionInfo QGeoPositionInfoSourceWinRT::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(const QGeoPositionInfoSourceWinRT);
Q_UNUSED(fromSatellitePositioningMethodsOnly)
return d->lastPosition;
@@ -160,13 +216,8 @@ QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceWinRT::supporte
{
Q_D(const QGeoPositionInfoSourceWinRT);
- PositionStatus status;
- HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, &status]() {
- HRESULT hr = d->locator->get_LocationStatus(&status);
- return hr;
- });
- if (FAILED(hr))
- return QGeoPositionInfoSource::NoPositioningMethods;
+ PositionStatus status = d->nativeStatus();
+ qCDebug(lcPositioningWinRT) << __FUNCTION__ << status;
switch (status) {
case PositionStatus::PositionStatus_NoData:
@@ -180,6 +231,7 @@ QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSourceWinRT::supporte
void QGeoPositionInfoSourceWinRT::setPreferredPositioningMethods(QGeoPositionInfoSource::PositioningMethods methods)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__ << methods;
Q_D(QGeoPositionInfoSourceWinRT);
PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
@@ -187,7 +239,7 @@ void QGeoPositionInfoSourceWinRT::setPreferredPositioningMethods(QGeoPositionInf
if (previousPreferredPositioningMethods == preferredPositioningMethods())
return;
- bool needsRestart = d->positionToken.value != 0;
+ const bool needsRestart = d->positionToken.value != 0;
if (needsRestart)
stopHandler();
@@ -207,19 +259,20 @@ void QGeoPositionInfoSourceWinRT::setPreferredPositioningMethods(QGeoPositionInf
void QGeoPositionInfoSourceWinRT::setUpdateInterval(int msec)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__ << msec;
Q_D(QGeoPositionInfoSourceWinRT);
- // Windows Phone 8.1 and Windows 10 do not support 0 interval
-#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
- if (msec == 0)
- msec = minimumUpdateInterval();
-#endif
-
- // If msec is 0 we send updates as data becomes available, otherwise we force msec to be equal
- // to or larger than the minimum update interval.
+ // minimumUpdateInterval is initialized to the lowest possible update interval in init().
+ // Passing 0 will cause an error on Windows 10.
+ // See https://docs.microsoft.com/en-us/uwp/api/windows.devices.geolocation.geolocator.reportinterval
if (msec != 0 && msec < minimumUpdateInterval())
msec = minimumUpdateInterval();
- HRESULT hr = d->locator->put_ReportInterval(msec);
+ const bool needsRestart = d->positionToken.value != 0;
+
+ if (needsRestart)
+ stopHandler();
+
+ HRESULT hr = d->locator->put_ReportInterval(static_cast<UINT32>(msec));
if (FAILED(hr)) {
setError(QGeoPositionInfoSource::UnknownSourceError);
qErrnoWarning(hr, "Failed to set update interval");
@@ -229,17 +282,20 @@ void QGeoPositionInfoSourceWinRT::setUpdateInterval(int msec)
d->periodicTimer.setInterval(qMax(msec, minimumUpdateInterval()));
QGeoPositionInfoSource::setUpdateInterval(msec);
+
+ if (needsRestart)
+ startHandler();
}
int QGeoPositionInfoSourceWinRT::minimumUpdateInterval() const
{
- // We use one second to reduce potential timer events
- // in case the platform itself stops reporting
- return 1000;
+ Q_D(const QGeoPositionInfoSourceWinRT);
+ return d->minimumUpdateInterval;
}
void QGeoPositionInfoSourceWinRT::startUpdates()
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(QGeoPositionInfoSourceWinRT);
if (d->updatesOngoing)
@@ -253,6 +309,7 @@ void QGeoPositionInfoSourceWinRT::startUpdates()
void QGeoPositionInfoSourceWinRT::stopUpdates()
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(QGeoPositionInfoSourceWinRT);
stopHandler();
@@ -262,6 +319,7 @@ void QGeoPositionInfoSourceWinRT::stopUpdates()
bool QGeoPositionInfoSourceWinRT::startHandler()
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(QGeoPositionInfoSourceWinRT);
// Check if already attached
@@ -301,6 +359,7 @@ bool QGeoPositionInfoSourceWinRT::startHandler()
void QGeoPositionInfoSourceWinRT::stopHandler()
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(QGeoPositionInfoSourceWinRT);
if (!d->positionToken.value)
@@ -314,6 +373,7 @@ void QGeoPositionInfoSourceWinRT::stopHandler()
void QGeoPositionInfoSourceWinRT::requestUpdate(int timeout)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(QGeoPositionInfoSourceWinRT);
if (timeout != 0 && timeout < minimumUpdateInterval()) {
@@ -330,6 +390,7 @@ void QGeoPositionInfoSourceWinRT::requestUpdate(int timeout)
void QGeoPositionInfoSourceWinRT::virtualPositionUpdate()
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_D(QGeoPositionInfoSourceWinRT);
QMutexLocker locker(&d->mutex);
@@ -367,6 +428,7 @@ void QGeoPositionInfoSourceWinRT::singleUpdateTimeOut()
void QGeoPositionInfoSourceWinRT::updateSynchronized(QGeoPositionInfo currentInfo)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__ << currentInfo;
Q_D(QGeoPositionInfoSourceWinRT);
QMutexLocker locker(&d->mutex);
@@ -388,11 +450,13 @@ void QGeoPositionInfoSourceWinRT::updateSynchronized(QGeoPositionInfo currentInf
QGeoPositionInfoSource::Error QGeoPositionInfoSourceWinRT::error() const
{
Q_D(const QGeoPositionInfoSourceWinRT);
+ qCDebug(lcPositioningWinRT) << __FUNCTION__ << d->positionError;
return d->positionError;
}
void QGeoPositionInfoSourceWinRT::setError(QGeoPositionInfoSource::Error positionError)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__ << positionError;
Q_D(QGeoPositionInfoSourceWinRT);
if (positionError == d->positionError)
@@ -404,14 +468,9 @@ void QGeoPositionInfoSourceWinRT::setError(QGeoPositionInfoSource::Error positio
bool QGeoPositionInfoSourceWinRT::checkNativeState()
{
Q_D(QGeoPositionInfoSourceWinRT);
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
- PositionStatus status;
- HRESULT hr = d->locator->get_LocationStatus(&status);
- if (FAILED(hr)) {
- setError(QGeoPositionInfoSource::UnknownSourceError);
- qErrnoWarning(hr, "Could not query status");
- return false;
- }
+ PositionStatus status = d->nativeStatus();
bool result = false;
switch (status) {
@@ -432,41 +491,53 @@ bool QGeoPositionInfoSourceWinRT::checkNativeState()
HRESULT QGeoPositionInfoSourceWinRT::onPositionChanged(IGeolocator *locator, IPositionChangedEventArgs *args)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_UNUSED(locator);
HRESULT hr;
- ComPtr<IGeoposition> pos;
- hr = args->get_Position(&pos);
+ ComPtr<IGeoposition> position;
+ hr = args->get_Position(&position);
RETURN_HR_IF_FAILED("Could not access position object.");
QGeoPositionInfo currentInfo;
ComPtr<IGeocoordinate> coord;
- hr = pos->get_Coordinate(&coord);
+ hr = position->get_Coordinate(&coord);
if (FAILED(hr))
qErrnoWarning(hr, "Could not access coordinate");
- DOUBLE lat;
- hr = coord->get_Latitude(&lat);
+ ComPtr<IGeocoordinateWithPoint> pointCoordinate;
+ hr = coord.As(&pointCoordinate);
if (FAILED(hr))
- qErrnoWarning(hr, "Could not access latitude");
+ qErrnoWarning(hr, "Could not cast coordinate.");
- DOUBLE lon;
- hr = coord->get_Longitude(&lon);
+ ComPtr<IGeopoint> point;
+ hr = pointCoordinate->get_Point(&point);
if (FAILED(hr))
- qErrnoWarning(hr, "Could not access longitude");
-
- // Depending on data source altitude can
- // be identified or not
- IReference<double> *alt;
- hr = coord->get_Altitude(&alt);
- if (SUCCEEDED(hr) && alt) {
- double altd;
- hr = alt->get_Value(&altd);
- currentInfo.setCoordinate(QGeoCoordinate(lat, lon, altd));
- } else {
- currentInfo.setCoordinate(QGeoCoordinate(lat, lon));
+ qErrnoWarning(hr, "Could not obtain coordinate's point.");
+
+ BasicGeoposition pos;
+ hr = point->get_Position(&pos);
+ if (FAILED(hr))
+ qErrnoWarning(hr, "Could not obtain point's position.");
+
+ DOUBLE lat = pos.Latitude;
+ DOUBLE lon = pos.Longitude;
+ DOUBLE alt = pos.Altitude;
+
+ bool altitudeAvailable = false;
+ ComPtr<IGeoshape> shape;
+ hr = point.As(&shape);
+ if (SUCCEEDED(hr) && shape) {
+ AltitudeReferenceSystem altitudeSystem;
+ hr = shape->get_AltitudeReferenceSystem(&altitudeSystem);
+ if (SUCCEEDED(hr) && altitudeSystem == AltitudeReferenceSystem_Geoid)
+ altitudeAvailable = true;
}
+ if (altitudeAvailable)
+ currentInfo.setCoordinate(QGeoCoordinate(lat, lon, alt));
+ else
+ currentInfo.setCoordinate(QGeoCoordinate(lat, lon));
DOUBLE accuracy;
hr = coord->get_Accuracy(&accuracy);
@@ -477,7 +548,7 @@ HRESULT QGeoPositionInfoSourceWinRT::onPositionChanged(IGeolocator *locator, IPo
hr = coord->get_AltitudeAccuracy(&altAccuracy);
if (SUCCEEDED(hr) && altAccuracy) {
double value;
- hr = alt->get_Value(&value);
+ hr = altAccuracy->get_Value(&value);
currentInfo.setAttribute(QGeoPositionInfo::VerticalAccuracy, value);
}
@@ -525,16 +596,9 @@ HRESULT QGeoPositionInfoSourceWinRT::onPositionChanged(IGeolocator *locator, IPo
return S_OK;
}
-HRESULT QGeoPositionInfoSourceWinRT::onStatusChanged(IGeolocator*, IStatusChangedEventArgs *args)
-{
- PositionStatus st;
- args->get_Status(&st);
- return S_OK;
-}
-
bool QGeoPositionInfoSourceWinRT::requestAccess() const
{
-#ifdef Q_OS_WINRT
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
static GeolocationAccessStatus accessStatus = GeolocationAccessStatus_Unspecified;
static ComPtr<IGeolocatorStatics> statics;
@@ -557,11 +621,12 @@ bool QGeoPositionInfoSourceWinRT::requestAccess() const
Q_ASSERT_SUCCEEDED(hr);
// We cannot wait inside the XamlThread as that would deadlock
+#ifdef Q_OS_WINRT
QWinRTFunctions::await(op, &accessStatus);
+#else
+ await(op, &accessStatus);
+#endif
return accessStatus == GeolocationAccessStatus_Allowed;
-#else // Q_OS_WINRT
- return true;
-#endif // Q_OS_WINRT
}
QT_END_NAMESPACE
diff --git a/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h b/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h
index 9f3a1c7f..4319ccae 100644
--- a/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h
+++ b/src/plugins/position/winrt/qgeopositioninfosource_winrt_p.h
@@ -51,7 +51,7 @@
#include "qgeopositioninfosource.h"
#include "qgeopositioninfo.h"
-#include <QTimer>
+#include <QtCore/qtimer.h>
#include <EventToken.h>
#include <wrl.h>
@@ -62,7 +62,6 @@ namespace ABI {
namespace Geolocation{
struct IGeolocator;
struct IPositionChangedEventArgs;
- struct IStatusChangedEventArgs;
}
}
}
@@ -76,7 +75,7 @@ class QGeoPositionInfoSourceWinRT : public QGeoPositionInfoSource
{
Q_OBJECT
public:
- QGeoPositionInfoSourceWinRT(QObject *parent = 0);
+ QGeoPositionInfoSourceWinRT(QObject *parent = nullptr);
~QGeoPositionInfoSourceWinRT();
int init();
@@ -92,9 +91,6 @@ public:
HRESULT onPositionChanged(ABI::Windows::Devices::Geolocation::IGeolocator *locator,
ABI::Windows::Devices::Geolocation::IPositionChangedEventArgs *args);
- HRESULT onStatusChanged(ABI::Windows::Devices::Geolocation::IGeolocator*,
- ABI::Windows::Devices::Geolocation::IStatusChangedEventArgs *args);
-
bool requestAccess() const;
Q_SIGNALS:
void nativePositionUpdate(const QGeoPositionInfo);
diff --git a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp
index e58744a0..b1ec6fb3 100644
--- a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp
+++ b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.cpp
@@ -37,24 +37,37 @@
#include "qgeopositioninfosourcefactory_winrt.h"
#include "qgeopositioninfosource_winrt_p.h"
+#include <QtCore/qloggingcategory.h>
+
+Q_LOGGING_CATEGORY(lcPositioningWinRT, "qt.positioning.winrt")
+
+QT_BEGIN_NAMESPACE
+
QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryWinRT::positionInfoSource(QObject *parent)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
QGeoPositionInfoSourceWinRT *src = new QGeoPositionInfoSourceWinRT(parent);
if (src->init() < 0) {
+ qCDebug(lcPositioningWinRT) << __FUNCTION__ << "Source initialization failed.";
delete src;
- src = 0;
+ return nullptr;
}
+ qCDebug(lcPositioningWinRT) << __FUNCTION__ << "Created position info source.";
return src;
}
QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryWinRT::satelliteInfoSource(QObject *parent)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_UNUSED(parent);
- return 0;
+ return nullptr;
}
QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryWinRT::areaMonitor(QObject *parent)
{
+ qCDebug(lcPositioningWinRT) << __FUNCTION__;
Q_UNUSED(parent);
- return 0;
+ return nullptr;
}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h
index 46cd3853..d09ddb64 100644
--- a/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h
+++ b/src/plugins/position/winrt/qgeopositioninfosourcefactory_winrt.h
@@ -37,8 +37,8 @@
#ifndef QGEOPOSITIONINFOSOURCEFACTORY_WINRT_H
#define QGEOPOSITIONINFOSOURCEFACTORY_WINRT_H
-#include <QObject>
-#include <QGeoPositionInfoSourceFactory>
+#include <QtCore/qobject.h>
+#include <QtPositioning/qgeopositioninfosourcefactory.h>
QT_BEGIN_NAMESPACE
diff --git a/src/positioning/doc/src/qtpositioning-qml.qdoc b/src/positioning/doc/src/qtpositioning-qml.qdoc
index 7c9567cb..0c84484b 100644
--- a/src/positioning/doc/src/qtpositioning-qml.qdoc
+++ b/src/positioning/doc/src/qtpositioning-qml.qdoc
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
@@ -26,40 +26,46 @@
****************************************************************************/
/*!
- \qmlmodule QtPositioning 5.11
+ \qmlmodule QtPositioning \QtVer
\title Qt Positioning QML Types
\ingroup qmlmodules
- \brief Provides QML types for position information
+ \brief Provides QML types for position information.
-\section1 Overview
+ \section1 Overview
-The identifying string for this module is \e QtPositioning. To use include the following import
-statement in the QML file.
+ The identifying string for this module is \e QtPositioning. To use the QML
+ from this module, include the following import statement in the QML file:
-\snippet doc_src_qtpositioning.qml import
+ \qml \QtVer
+ import QtPositioning \1
+ \endqml
-\section2 Positioning QML Concepts
+ \section2 Positioning QML Concepts
-Position information can come from a variety of sources including satellites,
-wifi, text files and so on. The position is described by the latitude,
-the longitude, and the altitude in meters. For more information see
-\l {http://en.wikipedia.org/wiki/Geographic_coordinate}{Geographic Coordinate}.
+ Position information can come from a variety of sources including
+ satellites, Wi-Fi, text files and so on. The position is described by the
+ latitude, longitude, and the altitude in meters. For more information, see
+ the Wikipedia page on
+ \l {http://en.wikipedia.org/wiki/Geographic_coordinate}
+ {Geographic Coordinates}.
-The QML position is stored in a \l {coordinate} which contains the
-latitude, longitude and altitude of the device. The \l {QtPositioning::Location}{Location} contains
-this \l {coordinate} and adds an address, it also has a bounding box which
-defines the recommended viewing region when displaying the location.
+ The QML position is stored in a \l {coordinate} which contains the
+ latitude, longitude and altitude of the device. The \l {QtPositioning::}
+ {Location} contains this \l {coordinate} and adds an address, and also has
+ a bounding box which defines the recommended viewing region when displaying
+ the location.
-Now that the device has a position, with regular updates the API can determine
-the speed and heading of the device. It can also define a box or a circle that can
-produce a notification when the device either leaves or enters that region.
+ Now that the device has a position, with regular updates the API can
+ determine the speed and heading of the device. It can also define a
+ box-shaped or circular region that triggers notifications when the device
+ either leaves or enters that region.
-More detailed information retrieving the current position can be found under
-\l {Positioning (QML)}{Location Positioning via QML}
+ More detailed information on retrieving the current position can be found
+ under \l {Positioning (QML)}{Location Positioning via QML}.
-\section1 Basic Types
+ \section1 Basic Types
-\annotatedlist qml-QtPositioning5-basictypes
+ \annotatedlist qml-QtPositioning5-basictypes
-\section1 Alphabetical Listing of All QML Types
+ \section1 Alphabetical Listing of All QML Types
*/
diff --git a/src/positioning/doc/src/qtpositioning.qdoc b/src/positioning/doc/src/qtpositioning.qdoc
index f0094ff0..7c30ef07 100644
--- a/src/positioning/doc/src/qtpositioning.qdoc
+++ b/src/positioning/doc/src/qtpositioning.qdoc
@@ -40,12 +40,15 @@
For C++ projects include the header appropriate for the current use case,
for example applications using routes may use
- \code #include <QGeoCoordinate> \endcode
+ \code
+ #include <QGeoCoordinate>
+ \endcode
The .pro file should have the \e positioning keyword added
- \code QT += positioning \endcode
-
+ \badcode
+ QT += positioning
+ \endcode
See more in the \l{Qt Positioning}{Qt Positioning Overview}.
@@ -87,11 +90,15 @@ To load the Qt Positioning module, add the following statement to your .qml file
For C++ projects include the header appropriate for the current use case,
for example applications using routes may use
-\code #include <QGeoCoordinate> \endcode
+\code
+#include <QGeoCoordinate>
+\endcode
The .pro file should have the \e positioning keyword added
-\code QT += positioning \endcode
+\badcode
+QT += positioning
+\endcode
\section1 Licenses
diff --git a/src/positioning/qgeopath.cpp b/src/positioning/qgeopath.cpp
index d86f6d0c..0c3d0c1c 100644
--- a/src/positioning/qgeopath.cpp
+++ b/src/positioning/qgeopath.cpp
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qgeopath.h"
+#include "qgeopolygon.h"
#include "qgeopath_p.h"
#include "qgeocoordinate.h"
@@ -197,6 +198,18 @@ const QList<QGeoCoordinate> &QGeoPath::path() const
Q_D(const QGeoPath);
return d->path();
}
+
+/*!
+ Clears the path.
+
+ \since 5.12
+*/
+void QGeoPath::clearPath()
+{
+ Q_D(QGeoPath);
+ d->clearPath();
+}
+
/*!
Sets all the elements of the path.
@@ -450,6 +463,12 @@ void QGeoPathPrivate::setPath(const QList<QGeoCoordinate> &path)
computeBoundingBox();
}
+void QGeoPathPrivate::clearPath()
+{
+ m_path.clear();
+ computeBoundingBox();
+}
+
qreal QGeoPathPrivate::width() const
{
return m_width;
@@ -565,11 +584,26 @@ bool QGeoPathPrivate::lineContains(const QGeoCoordinate &coordinate) const
return (m_path[0].distanceTo(coordinate) <= lineRadius);
}
+/*!
+ modified version of polygonContains with holes support.
+*/
bool QGeoPathPrivate::polygonContains(const QGeoCoordinate &coordinate) const
{
if (m_clipperDirty)
const_cast<QGeoPathPrivate *>(this)->updateClipperPath();
+ // iterates the holes List checking whether the point is contained inside the holes
+ for (const QList<QGeoCoordinate> &holePath : qAsConst(m_holesList)) {
+
+ QGeoPolygon holePolygon;
+ holePolygon.setPath(holePath);
+ QGeoPath holeBoundary;
+ holeBoundary.setPath(holePath);
+
+ if (holePolygon.contains(coordinate) && !(holeBoundary.contains(coordinate)))
+ return false;
+ }
+
QDoubleVector2D coord = QWebMercator::coordToMercator(coordinate);
double tlx = QWebMercator::coordToMercator(m_bbox.topLeft()).x();
if (coord.x() < tlx)
@@ -606,6 +640,14 @@ void QGeoPathPrivate::translate(double degreesLatitude, double degreesLongitude)
p.setLatitude(p.latitude() + degreesLatitude);
p.setLongitude(QLocationUtils::wrapLong(p.longitude() + degreesLongitude));
}
+ if (!m_holesList.isEmpty()){
+ for (QList<QGeoCoordinate> &hole: m_holesList){
+ for (QGeoCoordinate &holeVertex: hole){
+ holeVertex.setLatitude(holeVertex.latitude() + degreesLatitude);
+ holeVertex.setLongitude(QLocationUtils::wrapLong(holeVertex.longitude() + degreesLongitude));
+ }
+ }
+ }
m_bbox.translate(degreesLatitude, degreesLongitude);
m_minLati += degreesLatitude;
m_maxLati += degreesLatitude;
@@ -785,4 +827,46 @@ void QGeoPathPrivate::updateClipperPath()
m_clipperPath = QClipperUtils::qListToPath(preservedPath);
}
+
+/*!
+ Sets the \a path for an Hole inside the polygon.The hole has QList<QGeoCoordinate> type
+*/
+void QGeoPathPrivate::addHole(const QList<QGeoCoordinate> &holePath)
+{
+ for (const QGeoCoordinate &holeVertex: holePath)
+ if (!holeVertex.isValid())
+ return;
+
+ m_holesList << holePath;
+}
+
+/*!
+ Returns a QVariant containing a QList<QGeoCoordinate> representing the hole at index
+*/
+const QList<QGeoCoordinate> QGeoPathPrivate::holePath(int index) const
+{
+ return m_holesList.at(index);
+}
+
+
+/*!
+ Removes element at position \a index from the holes QList.
+*/
+void QGeoPathPrivate::removeHole(int index)
+{
+ if (index < 0 || index >= m_holesList.size())
+ return;
+
+ m_holesList.removeAt(index);
+}
+
+/*!
+ Returns the number of holes.
+*/
+int QGeoPathPrivate::holesCount() const
+{
+ return m_holesList.size();
+}
+
QT_END_NAMESPACE
+
diff --git a/src/positioning/qgeopath.h b/src/positioning/qgeopath.h
index 178ac3bf..e4af2add 100644
--- a/src/positioning/qgeopath.h
+++ b/src/positioning/qgeopath.h
@@ -72,6 +72,7 @@ public:
void setPath(const QList<QGeoCoordinate> &path);
const QList<QGeoCoordinate> &path() const;
+ void clearPath();
void setVariantPath(const QVariantList &path);
QVariantList variantPath() const;
diff --git a/src/positioning/qgeopath_p.h b/src/positioning/qgeopath_p.h
index ecba2dcc..d39f0ab2 100644
--- a/src/positioning/qgeopath_p.h
+++ b/src/positioning/qgeopath_p.h
@@ -85,6 +85,8 @@ public:
const QList<QGeoCoordinate> &path() const;
void setPath(const QList<QGeoCoordinate> &path);
+ void clearPath();
+
qreal width() const;
void setWidth(const qreal &width);
double length(int indexFrom, int indexTo) const;
@@ -99,8 +101,14 @@ public:
void computeBoundingBox();
void updateBoundingBox();
void updateClipperPath();
+ void addHole(const QList<QGeoCoordinate> &holePath);
+ const QList<QGeoCoordinate> holePath(int index) const;
+ void removeHole(int index);
+ int holesCount() const;
+
QList<QGeoCoordinate> m_path;
+ QList<QList<QGeoCoordinate>> m_holesList;
QVector<double> m_deltaXs; // longitude deltas from m_path[0]
double m_minX; // minimum value inside deltaXs
double m_maxX; // maximum value inside deltaXs
diff --git a/src/positioning/qgeopolygon.cpp b/src/positioning/qgeopolygon.cpp
index 1dafd1e0..66659d4b 100644
--- a/src/positioning/qgeopolygon.cpp
+++ b/src/positioning/qgeopolygon.cpp
@@ -178,7 +178,7 @@ bool QGeoPolygon::operator!=(const QGeoPolygon &other) const
}
/*!
- Sets the \a polygon from a list of coordinates.
+ Sets the \a polygon's boundary from a list of coordinates.
*/
void QGeoPolygon::setPath(const QList<QGeoCoordinate> &path)
{
@@ -187,7 +187,7 @@ void QGeoPolygon::setPath(const QList<QGeoCoordinate> &path)
}
/*!
- Returns all the elements.
+ Returns all the elements of the polygon's boundary.
*/
const QList<QGeoCoordinate> &QGeoPolygon::path() const
{
@@ -196,6 +196,36 @@ const QList<QGeoCoordinate> &QGeoPolygon::path() const
}
/*!
+ Sets all the elements of the polygon's perimeter.
+
+ \since QtPositioning 5.12
+*/
+void QGeoPolygon::setPerimeter(const QVariantList &path)
+{
+ Q_D(QGeoPolygon);
+ QList<QGeoCoordinate> p;
+ for (const auto &c: path) {
+ if (c.canConvert<QGeoCoordinate>())
+ p << c.value<QGeoCoordinate>();
+ }
+ d->setPath(p);
+}
+
+/*!
+ Returns all the elements of the polygon's perimeter.
+
+ \since QtPositioning 5.12
+*/
+QVariantList QGeoPolygon::perimeter() const
+{
+ Q_D(const QGeoPolygon);
+ QVariantList p;
+ for (const auto &c: d->path())
+ p << QVariant::fromValue(c);
+ return p;
+}
+
+/*!
Translates this geo polygon by \a degreesLatitude northwards and \a degreesLongitude eastwards.
Negative values of \a degreesLatitude and \a degreesLongitude correspond to
@@ -324,4 +354,82 @@ QString QGeoPolygon::toString() const
return QStringLiteral("QGeoPolygon([ %1 ])").arg(pathString);
}
+/*!
+ Sets the \a path for a hole inside the polygon. The hole is a QVariant containing a QList<QGeoCoordinate>.
+
+ \since 5.12
+*/
+void QGeoPolygon::addHole(const QVariant &holePath)
+{
+ Q_D(QGeoPolygon);
+ QList<QGeoCoordinate> qgcHolePath;
+ if (holePath.canConvert<QVariantList>()) {
+ const QVariantList qvlHolePath = holePath.toList();
+ for (const QVariant &vertex : qvlHolePath) {
+ if (vertex.canConvert<QGeoCoordinate>())
+ qgcHolePath << vertex.value<QGeoCoordinate>();
+ }
+ }
+ //ToDo: add QGeoShape support
+ return d->addHole(qgcHolePath);
+}
+
+/*!
+ Overloaded method. Sets the \a path for a hole inside the polygon. The hole is a QList<QGeoCoordinate>.
+
+ \since 5.12
+*/
+void QGeoPolygon::addHole(const QList<QGeoCoordinate> &holePath)
+{
+ Q_D(QGeoPolygon);
+ return d->addHole(holePath);
+}
+
+/*!
+ Returns a QVariant containing a QVariant containing a QList<QGeoCoordinate> which represents the hole at index.
+
+ \since 5.12
+*/
+const QVariantList QGeoPolygon::hole(int index) const
+{
+ Q_D(const QGeoPolygon);
+ QVariantList holeCoordinates;
+ for (const QGeoCoordinate &coords: d->holePath(index))
+ holeCoordinates << QVariant::fromValue(coords);
+ return holeCoordinates;
+}
+
+/*!
+ Returns a QList<QGeoCoordinate> which represents the hole at \a index.
+
+ \since 5.12
+*/
+const QList<QGeoCoordinate> QGeoPolygon::holePath(int index) const
+{
+ Q_D(const QGeoPolygon);
+ return d->holePath(index);
+}
+
+/*!
+ Removes element at position \a index from the holes QList.
+
+ \since 5.12
+*/
+void QGeoPolygon::removeHole(int index)
+{
+ Q_D(QGeoPolygon);
+ return d->removeHole(index);
+}
+
+/*!
+ Returns the number of holes.
+
+ \since 5.12
+*/
+int QGeoPolygon::holesCount() const
+{
+ Q_D(const QGeoPolygon);
+ return d->holesCount();
+}
+
QT_END_NAMESPACE
diff --git a/src/positioning/qgeopolygon.h b/src/positioning/qgeopolygon.h
index 90886da7..ccc4b98b 100644
--- a/src/positioning/qgeopolygon.h
+++ b/src/positioning/qgeopolygon.h
@@ -41,6 +41,7 @@
#define QGEOPOLYGON_H
#include <QtPositioning/QGeoShape>
+#include <QtCore/QVariantList>
QT_BEGIN_NAMESPACE
@@ -51,6 +52,7 @@ typedef QGeoPathPrivate QGeoPolygonPrivate;
class Q_POSITIONING_EXPORT QGeoPolygon : public QGeoShape
{
Q_GADGET
+ Q_PROPERTY(QVariantList perimeter READ perimeter WRITE setPerimeter REVISION 12)
public:
QGeoPolygon();
@@ -68,9 +70,15 @@ public:
using QGeoShape::operator!=;
bool operator!=(const QGeoPolygon &other) const;
- void setPath(const QList<QGeoCoordinate> &path);
+ void setPath(const QList<QGeoCoordinate> &path); // ### Qt6: rename into setPerimeter
const QList<QGeoCoordinate> &path() const;
+ Q_INVOKABLE void addHole(const QVariant &holePath);
+ void addHole(const QList<QGeoCoordinate> &holePath);
+ Q_INVOKABLE const QVariantList hole(int index) const;
+ const QList<QGeoCoordinate> holePath(int index) const;
+ Q_INVOKABLE void removeHole(int index);
+ Q_INVOKABLE int holesCount() const;
Q_INVOKABLE void translate(double degreesLatitude, double degreesLongitude);
Q_INVOKABLE QGeoPolygon translated(double degreesLatitude, double degreesLongitude) const;
Q_INVOKABLE double length(int indexFrom = 0, int indexTo = -1) const;
@@ -85,6 +93,10 @@ public:
Q_INVOKABLE QString toString() const;
+protected:
+ void setPerimeter(const QVariantList &path);
+ QVariantList perimeter() const;
+
private:
inline QGeoPolygonPrivate *d_func();
inline const QGeoPolygonPrivate *d_func() const;
diff --git a/src/positioning/qgeopositioninfosource.cpp b/src/positioning/qgeopositioninfosource.cpp
index 02aa1aa3..cafb4f8a 100644
--- a/src/positioning/qgeopositioninfosource.cpp
+++ b/src/positioning/qgeopositioninfosource.cpp
@@ -476,4 +476,12 @@ QStringList QGeoPositionInfoSource::availableSources()
\value UnknownSourceError An unidentified error occurred.
*/
+/*!
+ \fn void QGeoPositionInfoSource::supportedPositioningMethodsChanged()
+
+ This signal is emitted after the supportedPositioningMethods change.
+
+ \since Qt 5.12
+*/
+
QT_END_NAMESPACE
diff --git a/src/positioning/qgeopositioninfosource.h b/src/positioning/qgeopositioninfosource.h
index 24784462..7fe02270 100644
--- a/src/positioning/qgeopositioninfosource.h
+++ b/src/positioning/qgeopositioninfosource.h
@@ -101,6 +101,7 @@ Q_SIGNALS:
void positionUpdated(const QGeoPositionInfo &update);
void updateTimeout();
void error(QGeoPositionInfoSource::Error);
+ void supportedPositioningMethodsChanged();
private:
Q_DISABLE_COPY(QGeoPositionInfoSource)
diff --git a/src/positioningquick/qdeclarativepositionsource.cpp b/src/positioningquick/qdeclarativepositionsource.cpp
index ec462f23..c9fd2c8e 100644
--- a/src/positioningquick/qdeclarativepositionsource.cpp
+++ b/src/positioningquick/qdeclarativepositionsource.cpp
@@ -177,11 +177,10 @@ void QDeclarativePositionSource::setName(const QString &newName)
PositioningMethods previousPositioningMethods = supportedPositioningMethods();
PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
- delete m_positionSource;
if (newName.isEmpty())
- m_positionSource = QGeoPositionInfoSource::createDefaultSource(this);
+ setSource(QGeoPositionInfoSource::createDefaultSource(this));
else
- m_positionSource = QGeoPositionInfoSource::createSource(newName, this);
+ setSource(QGeoPositionInfoSource::createSource(newName, this));
if (m_positionSource) {
connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
@@ -280,8 +279,7 @@ void QDeclarativePositionSource::setNmeaSource(const QUrl &nmeaSource)
// because QNmeaPositionInfoSource can be bound only to a one file.
delete m_nmeaSocket;
m_nmeaSocket = 0;
- delete m_positionSource;
- m_positionSource = 0;
+ setSource(nullptr);
setPosition(QGeoPositionInfo());
// Create the NMEA source based on the given data. QML has automatically set QUrl
// type to point to correct path. If the file is not found, check if the file actually
@@ -296,7 +294,7 @@ void QDeclarativePositionSource::setNmeaSource(const QUrl &nmeaSource)
#ifdef QDECLARATIVE_POSITION_DEBUG
qDebug() << "QDeclarativePositionSource NMEA File was found: " << localFileName;
#endif
- m_positionSource = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::SimulationMode);
+ setSource(new QNmeaPositionInfoSource(QNmeaPositionInfoSource::SimulationMode));
(qobject_cast<QNmeaPositionInfoSource *>(m_positionSource))->setUserEquivalentRangeError(2.5); // it is internally multiplied by 2 in qlocationutils_readGga
(qobject_cast<QNmeaPositionInfoSource *>(m_positionSource))->setDevice(m_nmeaFile);
connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
@@ -345,9 +343,9 @@ void QDeclarativePositionSource::socketConnected()
// because QNmeaPositionInfoSource can be bound only to a one file.
delete m_nmeaFile;
m_nmeaFile = 0;
- delete m_positionSource;
+ setSource(nullptr);
- m_positionSource = new QNmeaPositionInfoSource(QNmeaPositionInfoSource::RealTimeMode);
+ setSource(new QNmeaPositionInfoSource(QNmeaPositionInfoSource::RealTimeMode));
(qobject_cast<QNmeaPositionInfoSource *>(m_positionSource))->setDevice(m_nmeaSocket);
connect(m_positionSource, &QNmeaPositionInfoSource::positionUpdated,
@@ -419,6 +417,20 @@ void QDeclarativePositionSource::setPosition(const QGeoPositionInfo &pi)
emit positionChanged();
}
+void QDeclarativePositionSource::setSource(QGeoPositionInfoSource *source)
+{
+ if (m_positionSource)
+ delete m_positionSource;
+
+ if (!source) {
+ m_positionSource = nullptr;
+ } else {
+ m_positionSource = source;
+ connect(m_positionSource, &QGeoPositionInfoSource::supportedPositioningMethodsChanged,
+ this, &QDeclarativePositionSource::supportedPositioningMethodsChanged);
+ }
+}
+
/*!
\internal
*/
@@ -712,7 +724,7 @@ void QDeclarativePositionSource::componentComplete()
PositioningMethods previousPositioningMethods = supportedPositioningMethods();
PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
- m_positionSource = QGeoPositionInfoSource::createDefaultSource(this);
+ setSource(QGeoPositionInfoSource::createDefaultSource(this));
if (m_positionSource) {
connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
this, SLOT(positionUpdateReceived(QGeoPositionInfo)));
diff --git a/src/positioningquick/qdeclarativepositionsource_p.h b/src/positioningquick/qdeclarativepositionsource_p.h
index bb9b618a..39bcd899 100644
--- a/src/positioningquick/qdeclarativepositionsource_p.h
+++ b/src/positioningquick/qdeclarativepositionsource_p.h
@@ -153,6 +153,7 @@ private Q_SLOTS:
private:
void setPosition(const QGeoPositionInfo &pi);
+ void setSource(QGeoPositionInfoSource *source);
QGeoPositionInfoSource *m_positionSource;
QDeclarativePosition m_position;
diff --git a/src/imports/positioning/qquickgeocoordinateanimation.cpp b/src/positioningquick/qquickgeocoordinateanimation.cpp
index b00f187d..b00f187d 100644
--- a/src/imports/positioning/qquickgeocoordinateanimation.cpp
+++ b/src/positioningquick/qquickgeocoordinateanimation.cpp
diff --git a/src/imports/positioning/qquickgeocoordinateanimation_p.h b/src/positioningquick/qquickgeocoordinateanimation_p.h
index 95f8dc07..c616d780 100644
--- a/src/imports/positioning/qquickgeocoordinateanimation_p.h
+++ b/src/positioningquick/qquickgeocoordinateanimation_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <QtPositioningQuick/private/qpositioningquickglobal_p.h>
#include <QtQuick/private/qquickanimation_p.h>
#include <QtPositioning/qgeocoordinate.h>
@@ -58,7 +59,7 @@ QT_BEGIN_NAMESPACE
class QQuickGeoCoordinateAnimationPrivate;
-class QQuickGeoCoordinateAnimation : public QQuickPropertyAnimation
+class Q_POSITIONINGQUICK_PRIVATE_EXPORT QQuickGeoCoordinateAnimation : public QQuickPropertyAnimation
{
Q_OBJECT
Q_DECLARE_PRIVATE(QQuickGeoCoordinateAnimation)
@@ -90,7 +91,7 @@ Q_SIGNALS:
void directionChanged();
};
-QVariant q_coordinateInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress);
+QVariant Q_POSITIONINGQUICK_PRIVATE_EXPORT q_coordinateInterpolator(const QGeoCoordinate &from, const QGeoCoordinate &to, qreal progress);
QT_END_NAMESPACE
diff --git a/src/imports/positioning/qquickgeocoordinateanimation_p_p.h b/src/positioningquick/qquickgeocoordinateanimation_p_p.h
index 946a38cb..946a38cb 100644
--- a/src/imports/positioning/qquickgeocoordinateanimation_p_p.h
+++ b/src/positioningquick/qquickgeocoordinateanimation_p_p.h