summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf6
-rw-r--r--examples/location/location.pro5
-rw-r--r--examples/location/mapviewer/mapviewer.pro2
m---------src/3rdparty/mapbox-gl-native0
-rw-r--r--src/imports/location/location.cpp8
-rw-r--r--src/imports/location/location.pro2
-rw-r--r--src/imports/positioning/positioning.cpp7
-rw-r--r--src/location/declarativemaps/locationvaluetypehelper.cpp2
-rw-r--r--src/location/declarativemaps/qdeclarativecirclemapitem.cpp11
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap.cpp28
-rw-r--r--src/location/declarativemaps/qdeclarativegeomap_p.h3
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitembase.cpp19
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitembase_p.h5
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemview.cpp1
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapitemview_p.h2
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapparameter.cpp25
-rw-r--r--src/location/declarativemaps/qdeclarativegeomapquickitem.cpp11
-rw-r--r--src/location/declarativemaps/qdeclarativegeoroute.cpp2
-rw-r--r--src/location/declarativemaps/qdeclarativegeoroutemodel.cpp2
-rw-r--r--src/location/declarativemaps/qdeclarativegeoroutesegment.cpp2
-rw-r--r--src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp122
-rw-r--r--src/location/declarativemaps/qdeclarativegeoserviceprovider_p.h54
-rw-r--r--src/location/declarativemaps/qdeclarativepolygonmapitem.cpp11
-rw-r--r--src/location/declarativemaps/qdeclarativepolylinemapitem.cpp11
-rw-r--r--src/location/declarativemaps/qdeclarativerectanglemapitem.cpp11
-rw-r--r--src/location/declarativemaps/qquickgeomapgesturearea.cpp4
-rw-r--r--src/location/declarativeplaces/qdeclarativeplace.cpp2
-rw-r--r--src/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp25
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp14
-rw-r--r--src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp22
-rw-r--r--src/location/doc/snippets/places/requesthandler.h4
-rw-r--r--src/location/labs/qdeclarativenavigator.cpp59
-rw-r--r--src/location/labs/qdeclarativenavigator_p.h13
-rw-r--r--src/location/labs/qdeclarativenavigator_p_p.h50
-rw-r--r--src/location/labs/qmapobjectview.cpp2
-rw-r--r--src/location/maps/qgeotiledmapscene.cpp8
-rw-r--r--src/location/maps/qgeotilefetcher.cpp5
-rw-r--r--src/location/maps/qnavigationmanagerengine.cpp5
-rw-r--r--src/location/maps/qnavigationmanagerengine_p.h7
-rw-r--r--src/location/places/qplace.cpp5
-rw-r--r--src/plugins/geoservices/mapboxgl/qsgmapboxglnode.cpp4
-rw-r--r--src/plugins/position/corelocation/qgeopositioninfosource_cl.mm4
-rw-r--r--src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp2
-rw-r--r--src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp26
-rw-r--r--src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp194
-rw-r--r--src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h8
-rw-r--r--src/plugins/position/serialnmea/qiopipe.cpp202
-rw-r--r--src/plugins/position/serialnmea/qiopipe_p.h112
-rw-r--r--src/plugins/position/serialnmea/qnmeasatelliteinfosource.cpp558
-rw-r--r--src/plugins/position/serialnmea/qnmeasatelliteinfosource_p.h96
-rw-r--r--src/plugins/position/serialnmea/serialnmea.pro6
-rw-r--r--src/positioning/doc/src/plugins/serialnmea.qdoc78
-rw-r--r--src/positioning/doc/src/qtpositioning-plugins.qdoc40
-rw-r--r--src/positioning/positioning.pro5
-rw-r--r--src/positioning/qgeopositioninfosource.cpp149
-rw-r--r--src/positioning/qgeopositioninfosource.h11
-rw-r--r--src/positioning/qgeopositioninfosource_p.h11
-rw-r--r--src/positioning/qgeopositioninfosourcefactory.cpp4
-rw-r--r--src/positioning/qgeopositioninfosourcefactory.h15
-rw-r--r--src/positioning/qgeosatelliteinfo.cpp61
-rw-r--r--src/positioning/qgeosatelliteinfo.h2
-rw-r--r--src/positioning/qgeosatelliteinfo_p.h67
-rw-r--r--src/positioning/qgeosatelliteinfosource.cpp108
-rw-r--r--src/positioning/qgeosatelliteinfosource.h6
-rw-r--r--src/positioning/qgeosatelliteinfosource_p.h70
-rw-r--r--src/positioning/qlocationutils.cpp102
-rw-r--r--src/positioning/qlocationutils_p.h27
-rw-r--r--src/positioningquick/qdeclarativepluginparameter.cpp135
-rw-r--r--src/positioningquick/qdeclarativepluginparameter_p.h94
-rw-r--r--src/positioningquick/qdeclarativeposition_p.h4
-rw-r--r--src/positioningquick/qdeclarativepositionsource.cpp229
-rw-r--r--src/positioningquick/qdeclarativepositionsource_p.h27
-rw-r--r--tests/auto/auto.pro1
-rw-r--r--tests/auto/declarative_core/tst_plugin.qml2
-rw-r--r--tests/auto/declarative_core/tst_positionsource.qml133
-rw-r--r--tests/auto/declarative_ui/BLACKLIST20
-rw-r--r--tests/auto/geotestplugin/geotestplugin.json3
-rw-r--r--tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h4
-rw-r--r--tests/auto/geotestplugin/qplacemanagerengine_test.h27
-rw-r--r--tests/auto/nokia_services/places_semiauto/tst_places.cpp4
-rw-r--r--tests/auto/positionplugin/plugin.cpp74
-rw-r--r--tests/auto/positionplugin/plugin.json2
-rw-r--r--tests/auto/positionplugin/positionplugin.pro4
-rw-r--r--tests/auto/positionpluginV1/plugin.cpp212
-rw-r--r--tests/auto/positionpluginV1/plugin.json9
-rw-r--r--tests/auto/positionpluginV1/positionpluginV1.pro12
-rw-r--r--tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp7
-rw-r--r--tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp4
-rw-r--r--tests/auto/utils/qlocationtestutils.cpp3
89 files changed, 3096 insertions, 459 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 3ca13dd6..f06fddf5 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -1,7 +1,9 @@
load(qt_build_config)
-
CONFIG += warning_clean
-MODULE_VERSION = 5.13.1
+
+DEFINES += QT_NO_JAVA_STYLE_ITERATORS QT_NO_LINKED_LIST
+
+MODULE_VERSION = 5.14.0
# Adds a way to debug location. The define is needed for multiple subprojects as they
# include the essential headers.
diff --git a/examples/location/location.pro b/examples/location/location.pro
index 6506813f..69fa6516 100644
--- a/examples/location/location.pro
+++ b/examples/location/location.pro
@@ -7,6 +7,7 @@ qtHaveModule(quick) {
mapviewer \
minimal_map \
itemview_transitions \
- planespotter \
- geojson_viewer
+ planespotter
+
+ qtHaveModule(widgets): SUBDIRS += geojson_viewer
}
diff --git a/examples/location/mapviewer/mapviewer.pro b/examples/location/mapviewer/mapviewer.pro
index 8e3daf81..a5cbbecb 100644
--- a/examples/location/mapviewer/mapviewer.pro
+++ b/examples/location/mapviewer/mapviewer.pro
@@ -6,7 +6,7 @@ SOURCES += main.cpp
# Workaround for QTBUG-38735
QT_FOR_CONFIG += location-private
-qtConfig(geoservices_mapboxgl): QT += sql opengl
+qtConfig(geoservices_mapboxgl): QT += sql
qtConfig(geoservices_osm): QT += concurrent
RESOURCES += \
diff --git a/src/3rdparty/mapbox-gl-native b/src/3rdparty/mapbox-gl-native
-Subproject 4b85252fbe811a786c6ee9eabedb7639b031dc5
+Subproject 5233c75b3f6c73623c5473b2d6573f31f3ddb4b
diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp
index 45087751..40dffd5d 100644
--- a/src/imports/location/location.cpp
+++ b/src/imports/location/location.cpp
@@ -35,6 +35,7 @@
****************************************************************************/
#include <QtLocation/private/qdeclarativegeoserviceprovider_p.h>
+#include <QtPositioningQuick/private/qdeclarativepluginparameter_p.h>
#include <QtLocation/private/qdeclarativegeomap_p.h>
#include <QtLocation/private/qdeclarativegeoroute_p.h>
@@ -97,7 +98,7 @@ public:
// 5.0 is silent and not advertised
qmlRegisterType<QDeclarativeGeoServiceProvider >(uri, major, minor, "Plugin");
- qmlRegisterType<QDeclarativeGeoServiceProviderParameter >(uri, major, minor, "PluginParameter");
+ qmlRegisterType<QDeclarativePluginParameter >(uri, major, minor, "PluginParameter");
qmlRegisterUncreatableType<QDeclarativeGeoServiceProviderRequirements>(uri, major, minor, "PluginRequirements",
QStringLiteral("PluginRequirements is not intended instantiable by developer."));
qmlRegisterType<QDeclarativeGeoMap >(uri, major, minor, "Map");
@@ -200,6 +201,11 @@ public:
qmlRegisterType<QDeclarativeGeoRoute, 13>(uri, major, minor, "Route");
qmlRegisterType<QDeclarativeGeoRouteQuery, 13>(uri, major, minor, "RouteQuery");
+ minor = 14;
+ qmlRegisterType<QDeclarativeGeoMap, 14>(uri, major, minor, "Map");
+ qmlRegisterUncreatableType<QDeclarativeGeoMapItemBase, 14>(uri, major, minor, "GeoMapItemBase",
+ QStringLiteral("GeoMapItemBase is not intended instantiable by developer."));
+
// Register the latest Qt version as QML type version
qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR);
diff --git a/src/imports/location/location.pro b/src/imports/location/location.pro
index dec1149b..40605806 100644
--- a/src/imports/location/location.pro
+++ b/src/imports/location/location.pro
@@ -1,4 +1,4 @@
-QT += quick-private network positioning-private location-private qml-private core-private gui-private
+QT += quick-private network positioning-private positioningquick-private location-private qml-private core-private gui-private
SOURCES += \
location.cpp
diff --git a/src/imports/positioning/positioning.cpp b/src/imports/positioning/positioning.cpp
index 4349f63b..38b9378a 100644
--- a/src/imports/positioning/positioning.cpp
+++ b/src/imports/positioning/positioning.cpp
@@ -41,9 +41,9 @@
#include <QtPositioningQuick/private/qdeclarativegeoaddress_p.h>
#include <QtPositioningQuick/private/qdeclarativegeolocation_p.h>
#include <QtPositioning/private/qwebmercator_p.h>
-
-#include <QtPositioningQuick/private/qdeclarativepositionsource_p.h>
#include <QtPositioningQuick/private/qdeclarativeposition_p.h>
+#include <QtPositioningQuick/private/qdeclarativepositionsource_p.h>
+#include <QtPositioningQuick/private/qdeclarativepluginparameter_p.h>
#include <QtPositioningQuick/private/qquickgeocoordinateanimation_p.h>
#include "locationsingleton.h"
@@ -616,6 +616,9 @@ public:
minor = 13;
qmlRegisterType<QDeclarativeGeoLocation, 13>(uri, major, minor, "Location");
+ minor = 14;
+ qmlRegisterType<QDeclarativePluginParameter >(uri, major, minor, "PluginParameter");
+
// Register the latest Qt version as QML type version
qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR);
} else {
diff --git a/src/location/declarativemaps/locationvaluetypehelper.cpp b/src/location/declarativemaps/locationvaluetypehelper.cpp
index 8c96c8e7..3e2f3658 100644
--- a/src/location/declarativemaps/locationvaluetypehelper.cpp
+++ b/src/location/declarativemaps/locationvaluetypehelper.cpp
@@ -38,6 +38,8 @@
#include <QVariantMap>
#include <QtQml/QQmlInfo>
#include <private/qqmlengine_p.h>
+#include <private/qv4scopedvalue_p.h>
+#include <private/qv4arrayobject_p.h>
QGeoCoordinate parseCoordinate(const QJSValue &value, bool *ok)
diff --git a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp
index b3496816..846fccbf 100644
--- a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp
@@ -128,6 +128,17 @@ QT_BEGIN_NAMESPACE
\image api-mapcircle.png
*/
+/*!
+ \qmlproperty bool QtLocation::MapCircle::autoFadeIn
+
+ This property holds whether the item automatically fades in when zooming into the map
+ starting from very low zoom levels. By default this is \c true.
+ Setting this property to \c false causes the map item to always have the opacity specified
+ with the \l QtQuick::Item::opacity property, which is 1.0 by default.
+
+ \since 5.14
+*/
+
static const int CircleSamples = 128;
struct Vertex
diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp
index 5997bd3e..4704dc3e 100644
--- a/src/location/declarativemaps/qdeclarativegeomap.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomap.cpp
@@ -450,7 +450,7 @@ QQuickGeoMapGestureArea *QDeclarativeGeoMap::gesture()
*/
void QDeclarativeGeoMap::populateMap()
{
- QSet<QObject *> kids = children().toSet();
+ QSet<QObject *> kids(children().cbegin(), children().cend());
const QList<QQuickItem *> quickKids = childItems();
for (QQuickItem *ite: quickKids)
kids.insert(ite);
@@ -892,8 +892,10 @@ void QDeclarativeGeoMap::setZoomLevel(qreal zoomLevel, bool overzoom)
} else {
const bool zlHasChanged = zoomLevel != m_cameraData.zoomLevel();
m_cameraData.setZoomLevel(zoomLevel);
- if (zlHasChanged)
+ if (zlHasChanged) {
emit zoomLevelChanged(zoomLevel);
+ emit visibleRegionChanged();
+ }
}
}
@@ -976,8 +978,10 @@ void QDeclarativeGeoMap::setBearing(qreal bearing)
} else {
const bool bearingHasChanged = bearing != m_cameraData.bearing();
m_cameraData.setBearing(bearing);
- if (bearingHasChanged)
+ if (bearingHasChanged) {
emit bearingChanged(bearing);
+ emit visibleRegionChanged();
+ }
}
}
@@ -1041,8 +1045,10 @@ void QDeclarativeGeoMap::setTilt(qreal tilt)
} else {
const bool tiltHasChanged = tilt != m_cameraData.tilt();
m_cameraData.setTilt(tilt);
- if (tiltHasChanged)
+ if (tiltHasChanged) {
emit tiltChanged(tilt);
+ emit visibleRegionChanged();
+ }
}
}
@@ -1099,8 +1105,10 @@ void QDeclarativeGeoMap::setFieldOfView(qreal fieldOfView)
} else {
const bool fovChanged = fieldOfView != m_cameraData.fieldOfView();
m_cameraData.setFieldOfView(fieldOfView);
- if (fovChanged)
+ if (fovChanged) {
emit fieldOfViewChanged(fieldOfView);
+ emit visibleRegionChanged();
+ }
}
}
@@ -1266,8 +1274,10 @@ void QDeclarativeGeoMap::setCenter(const QGeoCoordinate &center)
} else {
const bool centerHasChanged = center != m_cameraData.center();
m_cameraData.setCenter(center);
- if (centerHasChanged)
+ if (centerHasChanged) {
emit centerChanged(center);
+ emit visibleRegionChanged();
+ }
}
}
@@ -1309,15 +1319,18 @@ void QDeclarativeGeoMap::setVisibleRegion(const QGeoShape &shape)
// shape invalidated -> nothing to fit anymore
m_visibleRegion = QGeoRectangle();
m_pendingFitViewport = false;
+ emit visibleRegionChanged();
return;
}
if (!m_map || !width() || !height()) {
m_pendingFitViewport = true;
+ emit visibleRegionChanged();
return;
}
fitViewportToGeoShape(m_visibleRegion);
+ emit visibleRegionChanged();
}
QGeoShape QDeclarativeGeoMap::visibleRegion() const
@@ -1755,6 +1768,9 @@ void QDeclarativeGeoMap::onCameraDataChanged(const QGeoCameraData &cameraData)
emit tiltChanged(m_cameraData.tilt());
if (fovHasChanged)
emit fieldOfViewChanged(m_cameraData.fieldOfView());
+ if (centerHasChanged || zoomHasChanged || bearingHasChanged
+ || tiltHasChanged || fovHasChanged)
+ emit visibleRegionChanged();
}
/*!
diff --git a/src/location/declarativemaps/qdeclarativegeomap_p.h b/src/location/declarativemaps/qdeclarativegeomap_p.h
index 55751365..c97c3622 100644
--- a/src/location/declarativemaps/qdeclarativegeomap_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomap_p.h
@@ -97,7 +97,7 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMap : public QQuickItem
Q_PROPERTY(QList<QObject *> mapParameters READ mapParameters)
Q_PROPERTY(QGeoServiceProvider::Error error READ error NOTIFY errorChanged)
Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged)
- Q_PROPERTY(QGeoShape visibleRegion READ visibleRegion WRITE setVisibleRegion)
+ Q_PROPERTY(QGeoShape visibleRegion READ visibleRegion WRITE setVisibleRegion NOTIFY visibleRegionChanged)
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)
@@ -233,6 +233,7 @@ Q_SIGNALS:
void mapReadyChanged(bool ready);
Q_REVISION(11) void mapObjectsChanged();
void visibleAreaChanged();
+ Q_REVISION(14) void visibleRegionChanged();
protected:
void mousePressEvent(QMouseEvent *event) override ;
diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
index 162dcac4..9a2ae50b 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp
@@ -208,14 +208,31 @@ void QDeclarativeGeoMapItemBase::setPositionOnMap(const QGeoCoordinate &coordina
setPosition(topLeft);
}
+bool QDeclarativeGeoMapItemBase::autoFadeIn() const
+{
+ return m_autoFadeIn;
+}
+
static const double opacityRampMin = 1.5;
static const double opacityRampMax = 2.5;
+
+void QDeclarativeGeoMapItemBase::setAutoFadeIn(bool fadeIn)
+{
+ if (fadeIn == m_autoFadeIn)
+ return;
+ m_autoFadeIn = fadeIn;
+ if (quickMap_ && quickMap_->zoomLevel() < opacityRampMax)
+ polishAndUpdate();
+}
+
/*!
\internal
*/
float QDeclarativeGeoMapItemBase::zoomLevelOpacity() const
{
- if (quickMap_->zoomLevel() > opacityRampMax)
+ if (!m_autoFadeIn) // Consider skipping the opacity node instead.
+ return 1.0;
+ else if (quickMap_->zoomLevel() > opacityRampMax)
return 1.0;
else if (quickMap_->zoomLevel() > opacityRampMin)
return quickMap_->zoomLevel() - opacityRampMin;
diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase_p.h b/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
index 23fd1da6..38a118e5 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitembase_p.h
@@ -84,6 +84,7 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMapItemBase : public QQuickItem
Q_OBJECT
Q_PROPERTY(QGeoShape geoShape READ geoShape WRITE setGeoShape STORED false )
+ Q_PROPERTY(bool autoFadeIn READ autoFadeIn WRITE setAutoFadeIn REVISION 14)
public:
explicit QDeclarativeGeoMapItemBase(QQuickItem *parent = 0);
virtual ~QDeclarativeGeoMapItemBase();
@@ -96,6 +97,9 @@ public:
virtual const QGeoShape &geoShape() const = 0;
virtual void setGeoShape(const QGeoShape &shape) = 0;
+ bool autoFadeIn() const;
+ void setAutoFadeIn(bool fadeIn);
+
QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
virtual QSGNode *updateMapItemPaintNode(QSGNode *, UpdatePaintNodeData *);
@@ -135,6 +139,7 @@ private:
QDeclarativeGeoMapItemGroup *parentGroup_;
QScopedPointer<QDeclarativeGeoMapItemTransitionManager> m_transitionManager;
+ bool m_autoFadeIn = true;
friend class QDeclarativeGeoMap;
friend class QDeclarativeGeoMapItemView;
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
index f7a251a2..43e24620 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp
@@ -42,7 +42,6 @@
#include <QtCore/QAbstractItemModel>
#include <QtQml/QQmlContext>
-#include <QtQml/private/qqmldelegatemodel_p.h>
#include <QtQml/private/qqmlopenmetaobject_p.h>
#include <QtQuick/private/qquickanimation_p.h>
#include <QtQml/QQmlListProperty>
diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
index abac5bd5..8b2ab034 100644
--- a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
+++ b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h
@@ -56,7 +56,7 @@
#include <QtQml/QQmlParserStatus>
#include <QtQml/QQmlIncubator>
#include <QtQml/qqml.h>
-#include <QtQml/private/qqmldelegatemodel_p.h>
+#include <private/qqmldelegatemodel_p.h>
#include <QtQuick/private/qquicktransition_p.h>
#include <QtLocation/private/qdeclarativegeomapitemgroup_p.h>
diff --git a/src/location/declarativemaps/qdeclarativegeomapparameter.cpp b/src/location/declarativemaps/qdeclarativegeomapparameter.cpp
index c1361d5d..2408e1c7 100644
--- a/src/location/declarativemaps/qdeclarativegeomapparameter.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapparameter.cpp
@@ -39,10 +39,28 @@
#include <QByteArray>
#include <QMetaObject>
#include <QMetaProperty>
-#include <QSignalMapper>
+#include <QObject>
QT_BEGIN_NAMESPACE
+namespace {
+class SignalMapper : public QObject
+{
+ Q_OBJECT
+
+ int i;
+public:
+ explicit SignalMapper(int i, QObject *parent = nullptr)
+ : QObject(parent), i(i) {}
+
+public Q_SLOTS:
+ void map() { emit mapped(i); }
+
+Q_SIGNALS:
+ void mapped(int);
+};
+} // unnamed namespace
+
/*!
\qmltype MapParameter
\inqmlmodule QtLocation
@@ -114,8 +132,7 @@ void QDeclarativeGeoMapParameter::componentComplete()
return;
}
- QSignalMapper *mapper = new QSignalMapper(this);
- mapper->setMapping(this, i);
+ SignalMapper *mapper = new SignalMapper(i, this);
const QByteArray signalName = '2' + property.notifySignal().methodSignature(); // TODO: explain why '2'
QObject::connect(this, signalName, mapper, SLOT(map()));
@@ -131,3 +148,5 @@ void QDeclarativeGeoMapParameter::onPropertyUpdated(int index)
}
QT_END_NAMESPACE
+
+#include "qdeclarativegeomapparameter.moc"
diff --git a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp
index f7409788..ccca309b 100644
--- a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp
+++ b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp
@@ -115,6 +115,17 @@ QT_BEGIN_NAMESPACE
\image api-mapquickitem.png
*/
+/*!
+ \qmlproperty bool QtLocation::MapQuickItem::autoFadeIn
+
+ This property holds whether the item automatically fades in when zooming into the map
+ starting from very low zoom levels. By default this is \c true.
+ Setting this property to \c false causes the map item to always have the opacity specified
+ with the \l QtQuick::Item::opacity property, which is 1.0 by default.
+
+ \since 5.14
+*/
+
QMapQuickItemMatrix4x4::QMapQuickItemMatrix4x4(QObject *parent) : QQuickTransform(parent) { }
void QMapQuickItemMatrix4x4::setMatrix(const QMatrix4x4 &matrix)
diff --git a/src/location/declarativemaps/qdeclarativegeoroute.cpp b/src/location/declarativemaps/qdeclarativegeoroute.cpp
index 8f5ec5fe..c536b65b 100644
--- a/src/location/declarativemaps/qdeclarativegeoroute.cpp
+++ b/src/location/declarativemaps/qdeclarativegeoroute.cpp
@@ -43,6 +43,8 @@
#include <QtQml/QQmlEngine>
#include <QtQml/qqmlinfo.h>
#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/private/qv4scopedvalue_p.h>
+#include <QtQml/private/qv4arrayobject_p.h>
#include <QtPositioning/QGeoRectangle>
QT_BEGIN_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp b/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp
index 695f6972..f74557c0 100644
--- a/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp
+++ b/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp
@@ -43,6 +43,8 @@
#include <QtQml/QQmlEngine>
#include <QtQml/qqmlinfo.h>
#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/private/qv4scopedvalue_p.h>
+#include <QtQml/private/qv4arrayobject_p.h>
#include <QtLocation/QGeoRoutingManager>
#include <QtPositioning/QGeoRectangle>
#include "qdeclarativegeomapparameter_p.h"
diff --git a/src/location/declarativemaps/qdeclarativegeoroutesegment.cpp b/src/location/declarativemaps/qdeclarativegeoroutesegment.cpp
index b0e05f32..6751a47b 100644
--- a/src/location/declarativemaps/qdeclarativegeoroutesegment.cpp
+++ b/src/location/declarativemaps/qdeclarativegeoroutesegment.cpp
@@ -38,6 +38,8 @@
#include <QtQml/QQmlEngine>
#include <QtQml/private/qqmlengine_p.h>
+#include <QtQml/private/qv4scopedvalue_p.h>
+#include <QtQml/private/qv4arrayobject_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp b/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp
index b594d2dc..7810dc74 100644
--- a/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp
+++ b/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp
@@ -124,7 +124,7 @@ void QDeclarativeGeoServiceProvider::setName(const QString &name)
\internal
*/
bool QDeclarativeGeoServiceProvider::parametersReady() {
- for (const QDeclarativeGeoServiceProviderParameter *p: qAsConst(parameters_)) {
+ for (const QDeclarativePluginParameter *p: qAsConst(parameters_)) {
if (!p->isInitialized())
return false;
}
@@ -179,9 +179,9 @@ void QDeclarativeGeoServiceProvider::componentComplete()
{
complete_ = true;
- for (QDeclarativeGeoServiceProviderParameter *p: qAsConst(parameters_)) {
+ for (QDeclarativePluginParameter *p: qAsConst(parameters_)) {
if (!p->isInitialized()) {
- connect(p, &QDeclarativeGeoServiceProviderParameter::initialized,
+ connect(p, &QDeclarativePluginParameter::initialized,
this, &QDeclarativeGeoServiceProvider::tryAttach);
}
}
@@ -192,7 +192,8 @@ void QDeclarativeGeoServiceProvider::componentComplete()
|| required_->mappingRequirements() != NoMappingFeatures
|| required_->routingRequirements() != NoRoutingFeatures
|| required_->geocodingRequirements() != NoGeocodingFeatures
- || required_->placesRequirements() != NoPlacesFeatures) {
+ || required_->placesRequirements() != NoPlacesFeatures
+ || required_->navigationRequirements() != NoNavigationFeatures) {
QStringList providers = QGeoServiceProvider::availableServiceProviders();
@@ -602,9 +603,9 @@ void QDeclarativeGeoServiceProvider::setLocales(const QStringList &locales)
This property holds the list of plugin parameters.
*/
-QQmlListProperty<QDeclarativeGeoServiceProviderParameter> QDeclarativeGeoServiceProvider::parameters()
+QQmlListProperty<QDeclarativePluginParameter> QDeclarativeGeoServiceProvider::parameters()
{
- return QQmlListProperty<QDeclarativeGeoServiceProviderParameter>(this,
+ return QQmlListProperty<QDeclarativePluginParameter>(this,
0,
parameter_append,
parameter_count,
@@ -615,7 +616,7 @@ QQmlListProperty<QDeclarativeGeoServiceProviderParameter> QDeclarativeGeoService
/*!
\internal
*/
-void QDeclarativeGeoServiceProvider::parameter_append(QQmlListProperty<QDeclarativeGeoServiceProviderParameter> *prop, QDeclarativeGeoServiceProviderParameter *parameter)
+void QDeclarativeGeoServiceProvider::parameter_append(QQmlListProperty<QDeclarativePluginParameter> *prop, QDeclarativePluginParameter *parameter)
{
QDeclarativeGeoServiceProvider *p = static_cast<QDeclarativeGeoServiceProvider *>(prop->object);
p->parameters_.append(parameter);
@@ -626,7 +627,7 @@ void QDeclarativeGeoServiceProvider::parameter_append(QQmlListProperty<QDeclarat
/*!
\internal
*/
-int QDeclarativeGeoServiceProvider::parameter_count(QQmlListProperty<QDeclarativeGeoServiceProviderParameter> *prop)
+int QDeclarativeGeoServiceProvider::parameter_count(QQmlListProperty<QDeclarativePluginParameter> *prop)
{
return static_cast<QDeclarativeGeoServiceProvider *>(prop->object)->parameters_.count();
}
@@ -634,7 +635,7 @@ int QDeclarativeGeoServiceProvider::parameter_count(QQmlListProperty<QDeclarativ
/*!
\internal
*/
-QDeclarativeGeoServiceProviderParameter *QDeclarativeGeoServiceProvider::parameter_at(QQmlListProperty<QDeclarativeGeoServiceProviderParameter> *prop, int index)
+QDeclarativePluginParameter *QDeclarativeGeoServiceProvider::parameter_at(QQmlListProperty<QDeclarativePluginParameter> *prop, int index)
{
return static_cast<QDeclarativeGeoServiceProvider *>(prop->object)->parameters_[index];
}
@@ -642,7 +643,7 @@ QDeclarativeGeoServiceProviderParameter *QDeclarativeGeoServiceProvider::paramet
/*!
\internal
*/
-void QDeclarativeGeoServiceProvider::parameter_clear(QQmlListProperty<QDeclarativeGeoServiceProviderParameter> *prop)
+void QDeclarativeGeoServiceProvider::parameter_clear(QQmlListProperty<QDeclarativePluginParameter> *prop)
{
QDeclarativeGeoServiceProvider *p = static_cast<QDeclarativeGeoServiceProvider *>(prop->object);
p->parameters_.clear();
@@ -658,7 +659,7 @@ QVariantMap QDeclarativeGeoServiceProvider::parameterMap() const
QVariantMap map;
for (int i = 0; i < parameters_.size(); ++i) {
- QDeclarativeGeoServiceProviderParameter *parameter = parameters_.at(i);
+ QDeclarativePluginParameter *parameter = parameters_.at(i);
map.insert(parameter->name(), parameter->value());
}
@@ -673,7 +674,8 @@ QDeclarativeGeoServiceProviderRequirements::QDeclarativeGeoServiceProviderRequir
mapping_(QDeclarativeGeoServiceProvider::NoMappingFeatures),
routing_(QDeclarativeGeoServiceProvider::NoRoutingFeatures),
geocoding_(QDeclarativeGeoServiceProvider::NoGeocodingFeatures),
- places_(QDeclarativeGeoServiceProvider::NoPlacesFeatures)
+ places_(QDeclarativeGeoServiceProvider::NoPlacesFeatures),
+ navigation_(QDeclarativeGeoServiceProvider::NoNavigationFeatures)
{
}
@@ -769,6 +771,27 @@ void QDeclarativeGeoServiceProviderRequirements::setPlacesRequirements(const QDe
/*!
\internal
*/
+QDeclarativeGeoServiceProvider::NavigationFeatures QDeclarativeGeoServiceProviderRequirements::navigationRequirements() const
+{
+ return navigation_;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeGeoServiceProviderRequirements::setNavigationRequirements(const QDeclarativeGeoServiceProvider::NavigationFeatures &features)
+{
+ if (navigation_ == features)
+ return;
+
+ navigation_ = features;
+ emit navigationRequirementsChanged(navigation_);
+ emit requirementsChanged();
+}
+
+/*!
+ \internal
+*/
bool QDeclarativeGeoServiceProviderRequirements::matches(const QGeoServiceProvider *provider) const
{
QGeoServiceProvider::MappingFeatures mapping =
@@ -817,13 +840,25 @@ bool QDeclarativeGeoServiceProviderRequirements::matches(const QGeoServiceProvid
return false;
}
+ QGeoServiceProvider::NavigationFeatures navigation =
+ static_cast<QGeoServiceProvider::NavigationFeatures>(int(navigation_));
+
+ if (navigation == QGeoServiceProvider::AnyNavigationFeatures) {
+ if (provider->navigationFeatures() == QGeoServiceProvider::NoNavigationFeatures)
+ return false;
+ } else {
+ if ((provider->navigationFeatures() & navigation) != navigation)
+ return false;
+ }
+
return true;
}
bool QDeclarativeGeoServiceProviderRequirements::operator == (const QDeclarativeGeoServiceProviderRequirements &rhs) const
{
return (mapping_ == rhs.mapping_ && routing_ == rhs.routing_
- && geocoding_ == rhs.geocoding_ && places_ == rhs.places_);
+ && geocoding_ == rhs.geocoding_ && places_ == rhs.places_
+ && navigation_ == rhs.navigation_);
}
/*******************************************************************************
@@ -831,21 +866,25 @@ bool QDeclarativeGeoServiceProviderRequirements::operator == (const QDeclarative
/*!
\qmltype PluginParameter
- \instantiates QDeclarativeGeoServiceProviderParameter
+ \instantiates QDeclarativePluginParameter
\inqmlmodule QtLocation
\ingroup qml-QtLocation5-common
\since QtLocation 5.5
- \brief The PluginParameter type describes a parameter to a \l Plugin.
+ \brief The PluginParameter type describes a parameter for a plugin, either
+ geo service \l Plugin, or \l{Qt Positioning plugins}{position Plugin}.
The PluginParameter object is used to provide a parameter of some kind
- to a Plugin. Typically these parameters contain details like an application
- token for access to a service, or a proxy server to use for network access.
+ to a plugin. Typically these parameters contain details like an application
+ token for access to a service, or a proxy server to use for network access,
+ or the serial port to which a serial GPS receiver is connected.
- To set such a parameter, declare a PluginParameter inside a \l Plugin
- object, and give it \l{name} and \l{value} properties. A list of valid
+ To set such a parameter, declare a PluginParameter inside an element that accepts
+ plugin parameters as configuration objects, such as a \l Plugin object, or a
+ \l PositionSource object, and give it \l{name} and \l{value} properties. A list of valid
parameter names for each plugin is available from the
- \l {Qt Location#Plugin References and Parameters}{plugin reference pages}.
+ \l {Qt Location#Plugin References and Parameters}{plugin reference pages} for geoservice plugins,
+ and \l {Qt Positioning plugins#Default plugins} for position plugins.
\section2 Example Usage
@@ -861,33 +900,12 @@ bool QDeclarativeGeoServiceProviderRequirements::operator == (const QDeclarative
\endcode
*/
-QDeclarativeGeoServiceProviderParameter::QDeclarativeGeoServiceProviderParameter(QObject *parent)
- : QObject(parent) {}
-
-QDeclarativeGeoServiceProviderParameter::~QDeclarativeGeoServiceProviderParameter() {}
-
/*!
\qmlproperty string PluginParameter::name
This property holds the name of the plugin parameter as a single formatted string.
This property is a write-once property.
*/
-void QDeclarativeGeoServiceProviderParameter::setName(const QString &name)
-{
- if (!name_.isEmpty() || name.isEmpty())
- return;
-
- name_ = name;
-
- emit nameChanged(name_);
- if (value_.isValid())
- emit initialized();
-}
-
-QString QDeclarativeGeoServiceProviderParameter::name() const
-{
- return name_;
-}
/*!
\qmlproperty QVariant PluginParameter::value
@@ -895,29 +913,9 @@ QString QDeclarativeGeoServiceProviderParameter::name() const
This property holds the value of the plugin parameter which support different types of values (variant).
This property is a write-once property.
*/
-void QDeclarativeGeoServiceProviderParameter::setValue(const QVariant &value)
-{
- if (value_.isValid() || !value.isValid() || value.isNull())
- return;
-
- value_ = value;
-
- emit valueChanged(value_);
- if (!name_.isEmpty())
- emit initialized();
-}
-
-QVariant QDeclarativeGeoServiceProviderParameter::value() const
-{
- return value_;
-}
-
-bool QDeclarativeGeoServiceProviderParameter::isInitialized() const
-{
- return !name_.isEmpty() && value_.isValid();
-}
/*******************************************************************************
+ * Implementation now in positioningquick
*******************************************************************************/
QT_END_NAMESPACE
diff --git a/src/location/declarativemaps/qdeclarativegeoserviceprovider_p.h b/src/location/declarativemaps/qdeclarativegeoserviceprovider_p.h
index f6a663f3..165f7ba4 100644
--- a/src/location/declarativemaps/qdeclarativegeoserviceprovider_p.h
+++ b/src/location/declarativemaps/qdeclarativegeoserviceprovider_p.h
@@ -58,38 +58,10 @@
#include <QtQml/QQmlParserStatus>
#include <QtQml/QQmlListProperty>
#include <QtLocation/QGeoServiceProvider>
+#include <QtPositioningQuick/private/qdeclarativepluginparameter_p.h>
QT_BEGIN_NAMESPACE
-class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoServiceProviderParameter : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
- Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
-
-public:
- explicit QDeclarativeGeoServiceProviderParameter(QObject *parent = 0);
- ~QDeclarativeGeoServiceProviderParameter();
-
- void setName(const QString &name);
- QString name() const;
-
- void setValue(const QVariant &value);
- QVariant value() const;
-
- bool isInitialized() const;
-
-Q_SIGNALS:
- void nameChanged(const QString &name);
- void valueChanged(const QVariant &value);
- void initialized();
-
-private:
- QString name_;
- QVariant value_;
-};
-
class QDeclarativeGeoServiceProviderRequirements;
class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoServiceProvider : public QObject, public QQmlParserStatus
@@ -102,7 +74,7 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoServiceProvider : public QObject,
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
Q_PROPERTY(QStringList availableServiceProviders READ availableServiceProviders CONSTANT)
- Q_PROPERTY(QQmlListProperty<QDeclarativeGeoServiceProviderParameter> parameters READ parameters)
+ Q_PROPERTY(QQmlListProperty<QDeclarativePluginParameter> parameters READ parameters)
Q_PROPERTY(QDeclarativeGeoServiceProviderRequirements *required READ requirements WRITE setRequirements)
Q_PROPERTY(QStringList locales READ locales WRITE setLocales NOTIFY localesChanged)
Q_PROPERTY(QStringList preferred READ preferred WRITE setPreferred NOTIFY preferredChanged)
@@ -189,7 +161,7 @@ public:
void setName(const QString &name);
QString name() const;
- QQmlListProperty<QDeclarativeGeoServiceProviderParameter> parameters();
+ QQmlListProperty<QDeclarativePluginParameter> parameters();
QVariantMap parameterMap() const;
QStringList availableServiceProviders();
@@ -226,14 +198,14 @@ Q_SIGNALS:
private:
bool parametersReady();
void tryAttach();
- static void parameter_append(QQmlListProperty<QDeclarativeGeoServiceProviderParameter> *prop, QDeclarativeGeoServiceProviderParameter *mapObject);
- static int parameter_count(QQmlListProperty<QDeclarativeGeoServiceProviderParameter> *prop);
- static QDeclarativeGeoServiceProviderParameter *parameter_at(QQmlListProperty<QDeclarativeGeoServiceProviderParameter> *prop, int index);
- static void parameter_clear(QQmlListProperty<QDeclarativeGeoServiceProviderParameter> *prop);
+ static void parameter_append(QQmlListProperty<QDeclarativePluginParameter> *prop, QDeclarativePluginParameter *mapObject);
+ static int parameter_count(QQmlListProperty<QDeclarativePluginParameter> *prop);
+ static QDeclarativePluginParameter *parameter_at(QQmlListProperty<QDeclarativePluginParameter> *prop, int index);
+ static void parameter_clear(QQmlListProperty<QDeclarativePluginParameter> *prop);
QGeoServiceProvider *sharedProvider_;
QString name_;
- QList<QDeclarativeGeoServiceProviderParameter *> parameters_;
+ QList<QDeclarativePluginParameter *> parameters_;
QDeclarativeGeoServiceProviderRequirements *required_;
bool complete_;
bool experimental_;
@@ -257,6 +229,9 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoServiceProviderRequirements : pub
Q_PROPERTY(QDeclarativeGeoServiceProvider::PlacesFeatures places
READ placesRequirements WRITE setPlacesRequirements
NOTIFY placesRequirementsChanged)
+ Q_PROPERTY(QDeclarativeGeoServiceProvider::NavigationFeatures navigation
+ READ navigationRequirements WRITE setNavigationRequirements
+ NOTIFY navigationRequirementsChanged)
public:
explicit QDeclarativeGeoServiceProviderRequirements(QObject *parent = 0);
@@ -274,6 +249,9 @@ public:
QDeclarativeGeoServiceProvider::PlacesFeatures placesRequirements() const;
void setPlacesRequirements(const QDeclarativeGeoServiceProvider::PlacesFeatures &features);
+ QDeclarativeGeoServiceProvider::NavigationFeatures navigationRequirements() const;
+ void setNavigationRequirements(const QDeclarativeGeoServiceProvider::NavigationFeatures &features);
+
Q_INVOKABLE bool matches(const QGeoServiceProvider *provider) const;
bool operator == (const QDeclarativeGeoServiceProviderRequirements &rhs) const;
@@ -283,6 +261,7 @@ Q_SIGNALS:
void routingRequirementsChanged(const QDeclarativeGeoServiceProvider::RoutingFeatures &features);
void geocodingRequirementsChanged(const QDeclarativeGeoServiceProvider::GeocodingFeatures &features);
void placesRequirementsChanged(const QDeclarativeGeoServiceProvider::PlacesFeatures &features);
+ void navigationRequirementsChanged(const QDeclarativeGeoServiceProvider::NavigationFeatures &features);
void requirementsChanged();
@@ -291,12 +270,11 @@ private:
QDeclarativeGeoServiceProvider::RoutingFeatures routing_;
QDeclarativeGeoServiceProvider::GeocodingFeatures geocoding_;
QDeclarativeGeoServiceProvider::PlacesFeatures places_;
-
+ QDeclarativeGeoServiceProvider::NavigationFeatures navigation_;
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QDeclarativeGeoServiceProviderParameter)
QML_DECLARE_TYPE(QDeclarativeGeoServiceProviderRequirements)
QML_DECLARE_TYPE(QDeclarativeGeoServiceProvider)
diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp
index fcfa14a5..7a3873a4 100644
--- a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp
@@ -135,6 +135,17 @@ QT_BEGIN_NAMESPACE
\image api-mappolygon.png
*/
+/*!
+ \qmlproperty bool QtLocation::MapPolygon::autoFadeIn
+
+ This property holds whether the item automatically fades in when zooming into the map
+ starting from very low zoom levels. By default this is \c true.
+ Setting this property to \c false causes the map item to always have the opacity specified
+ with the \l QtQuick::Item::opacity property, which is 1.0 by default.
+
+ \since 5.14
+*/
+
QGeoMapPolygonGeometry::QGeoMapPolygonGeometry()
: assumeSimple_(false)
{
diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
index 63146fbc..5ca612db 100644
--- a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
@@ -297,6 +297,17 @@ static QList<QList<QDoubleVector2D> > clipLine(
\image api-mappolyline.png
*/
+/*!
+ \qmlproperty bool QtLocation::MapPolyline::autoFadeIn
+
+ This property holds whether the item automatically fades in when zooming into the map
+ starting from very low zoom levels. By default this is \c true.
+ Setting this property to \c false causes the map item to always have the opacity specified
+ with the \l QtQuick::Item::opacity property, which is 1.0 by default.
+
+ \since 5.14
+*/
+
QDeclarativeMapLineProperties::QDeclarativeMapLineProperties(QObject *parent) :
QObject(parent),
width_(1.0),
diff --git a/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp b/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp
index 74f95734..fd4109a7 100644
--- a/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp
@@ -114,6 +114,17 @@ QT_BEGIN_NAMESPACE
\image api-maprectangle.png
*/
+/*!
+ \qmlproperty bool QtLocation::MapRectangle::autoFadeIn
+
+ This property holds whether the item automatically fades in when zooming into the map
+ starting from very low zoom levels. By default this is \c true.
+ Setting this property to \c false causes the map item to always have the opacity specified
+ with the \l QtQuick::Item::opacity property, which is 1.0 by default.
+
+ \since 5.14
+*/
+
QDeclarativeRectangleMapItem::QDeclarativeRectangleMapItem(QQuickItem *parent)
: QDeclarativeGeoMapItemBase(parent), border_(this), color_(Qt::transparent), dirtyMaterial_(true),
updatingGeometry_(false)
diff --git a/src/location/declarativemaps/qquickgeomapgesturearea.cpp b/src/location/declarativemaps/qquickgeomapgesturearea.cpp
index 13315917..a33db67a 100644
--- a/src/location/declarativemaps/qquickgeomapgesturearea.cpp
+++ b/src/location/declarativemaps/qquickgeomapgesturearea.cpp
@@ -999,8 +999,8 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event)
return;
}
- const QGeoCoordinate &wheelGeoPos = m_declarativeMap->toCoordinate(event->posF(), false);
- const QPointF &preZoomPoint = event->posF();
+ const QGeoCoordinate &wheelGeoPos = m_declarativeMap->toCoordinate(event->position(), false);
+ const QPointF &preZoomPoint = event->position();
// Not using AltModifier as, for some reason, it causes angleDelta to be 0
if (event->modifiers() & Qt::ShiftModifier && rotationEnabled()) {
diff --git a/src/location/declarativeplaces/qdeclarativeplace.cpp b/src/location/declarativeplaces/qdeclarativeplace.cpp
index 89027d0e..74a8f0c0 100644
--- a/src/location/declarativeplaces/qdeclarativeplace.cpp
+++ b/src/location/declarativeplaces/qdeclarativeplace.cpp
@@ -1085,7 +1085,7 @@ void QDeclarativePlace::pullExtendedAttributes()
QStringList attributeTypes = m_src.extendedAttributeTypes();
foreach (const QString &attributeType, attributeTypes) {
m_extendedAttributes->insert(attributeType,
- qVariantFromValue(new QDeclarativePlaceAttribute(m_src.extendedAttribute(attributeType))));
+ QVariant::fromValue(new QDeclarativePlaceAttribute(m_src.extendedAttribute(attributeType))));
}
emit extendedAttributesChanged();
diff --git a/src/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp b/src/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp
index 1920583b..3d64d299 100644
--- a/src/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp
+++ b/src/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp
@@ -149,10 +149,7 @@ void QDeclarativePlaceContentModel::initializeCollection(int totalCount, const Q
int initialCount = m_contentCount;
clearData();
- QMapIterator<int, QPlaceContent> i(collection);
- while (i.hasNext()) {
- i.next();
-
+ for (auto i = collection.cbegin(), end = collection.cend(); i != end; ++i) {
const QPlaceContent &content = i.value();
if (content.type() != m_type)
continue;
@@ -317,11 +314,9 @@ void QDeclarativePlaceContentModel::fetchFinished()
QPlaceContent::Collection contents = reply->content();
//find out which indexes are new and which ones have changed.
- QMapIterator<int, QPlaceContent> it(contents);
QList<int> changedIndexes;
QList<int> newIndexes;
- while (it.hasNext()) {
- it.next();
+ for (auto it = contents.cbegin(), end = contents.cend(); it != end; ++it) {
if (!m_content.contains(it.key()))
newIndexes.append(it.key());
else if (it.value() != m_content.value(it.key()))
@@ -330,14 +325,14 @@ void QDeclarativePlaceContentModel::fetchFinished()
//insert new indexes in blocks where within each
//block, the indexes are consecutive.
- QListIterator<int> newIndexesIter(newIndexes);
int startIndex = -1;
- while (newIndexesIter.hasNext()) {
- int currentIndex = newIndexesIter.next();
+ for (auto it = newIndexes.cbegin(), end = newIndexes.cend(); it != end; ++it) {
+ int currentIndex = *it;
if (startIndex == -1)
startIndex = currentIndex;
- if (!newIndexesIter.hasNext() || (newIndexesIter.hasNext() && (newIndexesIter.peekNext() > (currentIndex + 1)))) {
+ auto next = std::next(it);
+ if (next == end || *next > (currentIndex + 1)) {
beginInsertRows(QModelIndex(),startIndex,currentIndex);
for (int i = startIndex; i <= currentIndex; ++i) {
const QPlaceContent &content = contents.value(i);
@@ -360,13 +355,13 @@ void QDeclarativePlaceContentModel::fetchFinished()
//modify changed indexes in blocks where within each
//block, the indexes are consecutive.
startIndex = -1;
- QListIterator<int> changedIndexesIter(changedIndexes);
- while (changedIndexesIter.hasNext()) {
- int currentIndex = changedIndexesIter.next();
+ for (auto it = changedIndexes.cbegin(), end = changedIndexes.cend(); it != end; ++it) {
+ int currentIndex = *it;
if (startIndex == -1)
startIndex = currentIndex;
- if (!changedIndexesIter.hasNext() || (changedIndexesIter.hasNext() && changedIndexesIter.peekNext() > (currentIndex + 1))) {
+ auto next = std::next(it);
+ if (next == end || *next > (currentIndex + 1)) {
for (int i = startIndex; i <= currentIndex; ++i) {
const QPlaceContent &content = contents.value(i);
m_content.insert(i, content);
diff --git a/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
index 4cfd26dd..9129731b 100644
--- a/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
+++ b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
@@ -963,26 +963,20 @@ void QDeclarativeSearchResultModel::placeRemoved(const QString &placeId)
QList<QPlaceSearchResult> QDeclarativeSearchResultModel::resultsFromPages() const
{
QList<QPlaceSearchResult> res;
- QMapIterator<int, QList<QPlaceSearchResult>> i(m_pages);
- while (i.hasNext()) {
- i.next();
- res.append(i.value());
- }
+ for (const auto &e : m_pages)
+ res.append(e);
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();
+ for (auto i = m_pages.begin(), end = m_pages.end(); i != end; ++i) {
+ 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;
}
}
diff --git a/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp b/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
index 38bfb249..08179c93 100644
--- a/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
+++ b/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
@@ -631,24 +631,24 @@ QStringList QDeclarativeSupportedCategoriesModel::populateCategories(QPlaceManag
Q_ASSERT(manager);
QStringList childIds;
- PlaceCategoryNode *node;
- QMap<QString, QPlaceCategory> sortedCategories;
- foreach ( const QPlaceCategory &category, manager->childCategories(parent.categoryId()))
- sortedCategories.insert(category.name(), category);
+ const auto byName = [](const QPlaceCategory &lhs, const QPlaceCategory &rhs) {
+ return lhs.name() < rhs.name();
+ };
- QMapIterator<QString, QPlaceCategory> iter(sortedCategories);
- while (iter.hasNext()) {
- iter.next();
- node = new PlaceCategoryNode;
+ auto categories = manager->childCategories(parent.categoryId());
+ std::sort(categories.begin(), categories.end(), byName);
+
+ for (const auto &category : qAsConst(categories)) {
+ auto node = new PlaceCategoryNode;
node->parentId = parent.categoryId();
- node->declCategory = QSharedPointer<QDeclarativeCategory>(new QDeclarativeCategory(iter.value(), m_plugin ,this));
+ node->declCategory = QSharedPointer<QDeclarativeCategory>(new QDeclarativeCategory(category, m_plugin ,this));
if (m_hierarchical)
- node->childIds = populateCategories(manager, iter.value());
+ node->childIds = populateCategories(manager, category);
m_categoriesTree.insert(node->declCategory->categoryId(), node);
- childIds.append(iter.value().categoryId());
+ childIds.append(category.categoryId());
if (!m_hierarchical) {
childIds.append(populateCategories(manager,node->declCategory->category()));
diff --git a/src/location/doc/snippets/places/requesthandler.h b/src/location/doc/snippets/places/requesthandler.h
index e5ee0d00..9aa5fe76 100644
--- a/src/location/doc/snippets/places/requesthandler.h
+++ b/src/location/doc/snippets/places/requesthandler.h
@@ -358,8 +358,8 @@ public slots:
//! [Image handler]
void handleImagesReply() {
if (contentReply->error() == QPlaceReply::NoError) {
- QMapIterator<int, QPlaceContent> iter(contentReply->content());
- while (iter.hasNext()) {
+ const auto content = contentReply->content();
+ for (auto iter = content.cbegin(), end = content.cend(); iter != end; ++iter) {
qDebug() << "Index: " << iter.key();
QPlaceImage image = iter.value();
qDebug() << image.url();
diff --git a/src/location/labs/qdeclarativenavigator.cpp b/src/location/labs/qdeclarativenavigator.cpp
index 3fc9fb88..ae273774 100644
--- a/src/location/labs/qdeclarativenavigator.cpp
+++ b/src/location/labs/qdeclarativenavigator.cpp
@@ -284,6 +284,27 @@ QDeclarativePositionSource *QDeclarativeNavigator::positionSource() const
return d_ptr->m_params->m_positionSource;
}
+// navigator automatically adjusts route when user leaves it
+bool QDeclarativeNavigator::automaticReroutingEnabled() const
+{
+ if (d_ptr->m_navigator)
+ return d_ptr->m_navigator->automaticReroutingEnabled();
+ return d_ptr->m_params->m_autoRerouting;
+}
+
+// Whether or not it has an effect while the navigator is active should be plugin-dependent
+void QDeclarativeNavigator::setAutomaticReroutingEnabled(bool autoRerouting)
+{
+ const bool autoReroutingOld = automaticReroutingEnabled();
+ d_ptr->m_params->m_autoRerouting = autoRerouting;
+ // Done this way, and not via signal like setTrackPositionSource because
+ // plugins might not support automatic rerouting.
+ if (d_ptr->m_navigator)
+ d_ptr->m_navigator->setAutomaticReroutingEnabled(autoRerouting);
+ if (autoRerouting != autoReroutingOld)
+ emit automaticReroutingEnabledChanged();
+}
+
bool QDeclarativeNavigator::navigatorReady() const
{
@@ -297,6 +318,15 @@ bool QDeclarativeNavigator::trackPositionSource() const
return d_ptr->m_params->m_trackPositionSource;
}
+// Navigator is in active tracking mode and the route is being followed.
+// This may turn \c false if the user leaves the route.
+bool QDeclarativeNavigator::isOnRoute() const
+{
+ if (d_ptr->m_navigator)
+ return d_ptr->m_navigator->isOnRoute();
+ return false;
+}
+
void QDeclarativeNavigator::setTrackPositionSource(bool trackPositionSource)
{
if (trackPositionSource == d_ptr->m_params->m_trackPositionSource)
@@ -322,6 +352,12 @@ QString QDeclarativeNavigator::errorString() const
return d_ptr->m_errorString;
}
+void QDeclarativeNavigator::recalculateRoutes()
+{
+ if (d_ptr->m_navigator)
+ d_ptr->m_navigator->recalculateRoutes();
+}
+
/* !NOT DOCUMENTED YET!
\qmlproperty QAbstractNavigator *Qt.labs.location::Navigator::engineHandle
@@ -478,6 +514,10 @@ bool QDeclarativeNavigator::ensureEngine()
&d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::nextManeuverIconChanged);
connect(d_ptr->m_navigator.get(), &QAbstractNavigator::progressInformationChanged,
&d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::progressInformationChanged);
+ connect(d_ptr->m_navigator.get(), &QAbstractNavigator::isOnRouteChanged,
+ this, &QDeclarativeNavigator::isOnRouteChanged);
+ connect(d_ptr->m_navigator.get(), &QAbstractNavigator::alternativeRoutesChanged,
+ &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::onAlternativeRoutesChanged);
emit navigatorReadyChanged(true);
return true;
@@ -502,7 +542,7 @@ void QDeclarativeNavigator::setError(QDeclarativeNavigator::NavigationError erro
}
QDeclarativeNavigationBasicDirections::QDeclarativeNavigationBasicDirections(QDeclarativeNavigator *parent)
-: QObject(parent), m_navigator(parent)
+: QObject(parent), m_navigator(parent), m_routes(QByteArrayLiteral("routeData"), this)
{
if (m_navigator)
m_navigatorPrivate = m_navigator->d_ptr.data();
@@ -672,6 +712,11 @@ int QDeclarativeNavigationBasicDirections::currentSegment() const
return m_navigatorPrivate->m_navigator->currentSegment();
}
+QAbstractItemModel *QDeclarativeNavigationBasicDirections::alternativeRoutes()
+{
+ return &m_routes;
+}
+
void QDeclarativeNavigationBasicDirections::onCurrentRouteChanged()
{
if (m_currentRoute)
@@ -688,5 +733,17 @@ void QDeclarativeNavigationBasicDirections::onCurrentRouteLegChanged()
emit currentRouteLegChanged();
}
+void QDeclarativeNavigationBasicDirections::onAlternativeRoutesChanged()
+{
+ const QList<QGeoRoute> &routes = m_navigatorPrivate->m_navigator->alternativeRoutes();
+ QList<QDeclarativeGeoRoute *> declarativeRoutes;
+ for (int i = 0; i < routes.size(); ++i) {
+ QDeclarativeGeoRoute *route = new QDeclarativeGeoRoute(routes.at(i), &m_routes);
+ QQmlEngine::setContextForObject(route, QQmlEngine::contextForObject(this));
+ declarativeRoutes.append(route);
+ }
+ m_routes.updateData(declarativeRoutes);
+}
+
QT_END_NAMESPACE
diff --git a/src/location/labs/qdeclarativenavigator_p.h b/src/location/labs/qdeclarativenavigator_p.h
index e12d6ba4..24ff798f 100644
--- a/src/location/labs/qdeclarativenavigator_p.h
+++ b/src/location/labs/qdeclarativenavigator_p.h
@@ -81,6 +81,8 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeNavigator : public QParameterizableO
Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
Q_PROPERTY(bool navigatorReady READ navigatorReady NOTIFY navigatorReadyChanged)
Q_PROPERTY(bool trackPositionSource READ trackPositionSource WRITE setTrackPositionSource NOTIFY trackPositionSourceChanged)
+ Q_PROPERTY(bool automaticReroutingEnabled READ automaticReroutingEnabled WRITE setAutomaticReroutingEnabled NOTIFY automaticReroutingEnabledChanged)
+ Q_PROPERTY(bool isOnRoute READ isOnRoute NOTIFY isOnRouteChanged)
Q_PROPERTY(QDeclarativeNavigationBasicDirections *directions READ directions CONSTANT)
Q_PROPERTY(NavigationError error READ error NOTIFY errorChanged)
Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged)
@@ -129,17 +131,26 @@ public:
void setPositionSource(QDeclarativePositionSource *positionSource);
QDeclarativePositionSource *positionSource() const;
+ // To enable/disable automatic route recalculation in the engines
+ bool automaticReroutingEnabled() const;
+ void setAutomaticReroutingEnabled(bool autoRerouting);
+
bool navigatorReady() const;
void setTrackPositionSource(bool trackPositionSource);
bool trackPositionSource() const;
+ // To discover/notify when the tracked position goes off the active navigation route
+ bool isOnRoute() const;
+
QDeclarativeNavigationBasicDirections *directions() const;
QAbstractNavigator *abstractNavigator() const;
NavigationError error() const;
QString errorString() const;
+ Q_INVOKABLE void recalculateRoutes();
+
signals:
void navigatorReadyChanged(bool ready);
void trackPositionSourceChanged(bool trackPositionSource);
@@ -150,6 +161,8 @@ signals:
void routeChanged();
void positionSourceChanged();
void errorChanged();
+ void automaticReroutingEnabledChanged();
+ void isOnRouteChanged();
protected:
void pluginReady();
diff --git a/src/location/labs/qdeclarativenavigator_p_p.h b/src/location/labs/qdeclarativenavigator_p_p.h
index 77fe2ff2..5bf1bd12 100644
--- a/src/location/labs/qdeclarativenavigator_p_p.h
+++ b/src/location/labs/qdeclarativenavigator_p_p.h
@@ -53,6 +53,9 @@
#include <QtCore/qpointer.h>
#include <QtLocation/qgeoroute.h>
#include <QtLocation/private/qdeclarativenavigator_p.h>
+#include <QAbstractListModel>
+#include <QtLocation/private/qdeclarativegeoroute_p.h>
+#include <QtLocation/private/qdeclarativegeoroutemodel_p.h>
QT_BEGIN_NAMESPACE
@@ -67,6 +70,48 @@ class QDeclarativeGeoRouteSegment;
class QParameterizableObject;
class QAbstractNavigator;
+template<typename T, int Role>
+class ReadOnlyListModel : public QAbstractListModel
+{
+public:
+ explicit ReadOnlyListModel(const QByteArray &dataRoleName, QObject *parent = nullptr)
+ : QAbstractListModel(parent)
+ {
+ m_roleNames.insert(Role, dataRoleName);
+ }
+
+ int rowCount(const QModelIndex &) const override
+ {
+ return m_data.size();
+ }
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ const int row = index.row();
+ if (!index.isValid() || row < 0 || row >= m_data.size() || role != Role)
+ return QVariant();
+
+ return QVariant::fromValue(m_data.at(row));
+ }
+
+ QHash<int, QByteArray> roleNames() const override
+ {
+ return m_roleNames;
+ }
+
+ void updateData(const QList<T*> &data)
+ {
+ beginResetModel();
+ qDeleteAll(m_data);
+ m_data = data;
+ endResetModel();
+ }
+
+protected:
+ QHash<int, QByteArray> m_roleNames;
+ QList<T*> m_data;
+};
+
class Q_LOCATION_PRIVATE_EXPORT QDeclarativeNavigationBasicDirections : public QObject
{
Q_OBJECT
@@ -83,6 +128,7 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeNavigationBasicDirections : public Q
Q_PROPERTY(QDeclarativeGeoRoute *currentRoute READ currentRoute NOTIFY currentRouteChanged)
Q_PROPERTY(QDeclarativeGeoRouteLeg *currentRouteLeg READ currentRouteLeg NOTIFY currentRouteChanged)
Q_PROPERTY(int currentSegment READ currentSegment NOTIFY currentSegmentChanged)
+ Q_PROPERTY(QAbstractItemModel *alternativeRoutes READ alternativeRoutes CONSTANT)
public:
explicit QDeclarativeNavigationBasicDirections(QDeclarativeNavigator *parent);
@@ -100,6 +146,7 @@ public:
QDeclarativeGeoRoute *currentRoute() const;
QDeclarativeGeoRouteLeg *currentRouteLeg() const;
int currentSegment() const;
+ QAbstractItemModel *alternativeRoutes();
Q_SIGNALS:
void progressInformationChanged();
@@ -113,12 +160,14 @@ Q_SIGNALS:
protected slots:
void onCurrentRouteChanged();
void onCurrentRouteLegChanged();
+ void onAlternativeRoutesChanged();
protected:
QDeclarativeNavigator *m_navigator;
QDeclarativeNavigatorPrivate *m_navigatorPrivate;
QPointer<QDeclarativeGeoRoute> m_currentRoute;
QPointer<QDeclarativeGeoRouteLeg> m_currentRouteLeg;
+ ReadOnlyListModel<QDeclarativeGeoRoute, QDeclarativeGeoRouteModel::RouteRole> m_routes;
friend class QDeclarativeNavigator;
};
@@ -132,6 +181,7 @@ public:
QPointer<QDeclarativePositionSource> m_positionSource;
QList<QPointer<QGeoMapParameter>> m_parameters;
bool m_trackPositionSource = true;
+ bool m_autoRerouting = true;
};
class QDeclarativeNavigatorPrivate
diff --git a/src/location/labs/qmapobjectview.cpp b/src/location/labs/qmapobjectview.cpp
index 90234ea6..8cbf8ded 100644
--- a/src/location/labs/qmapobjectview.cpp
+++ b/src/location/labs/qmapobjectview.cpp
@@ -36,7 +36,7 @@
#include "qmapobjectview_p.h"
#include "qmapobjectview_p_p.h"
-#include <QtQml/private/qqmldelegatemodel_p.h>
+#include <private/qqmldelegatemodel_p.h>
#include <QtLocation/private/qgeomap_p.h>
QT_BEGIN_NAMESPACE
diff --git a/src/location/maps/qgeotiledmapscene.cpp b/src/location/maps/qgeotiledmapscene.cpp
index a5f94c8d..a8bee156 100644
--- a/src/location/maps/qgeotiledmapscene.cpp
+++ b/src/location/maps/qgeotiledmapscene.cpp
@@ -495,7 +495,9 @@ void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
cameraMatrix.lookAt(toVector3D(eye), toVector3D(center), toVector3D(d->m_cameraUp));
root->setMatrix(d->m_projectionMatrix * cameraMatrix);
- const QSet<QGeoTileSpec> tilesInSG = QSet<QGeoTileSpec>::fromList(root->tiles.keys());
+ QSet<QGeoTileSpec> tilesInSG;
+ for (auto it = root->tiles.cbegin(), end = root->tiles.cend(); it != end; ++it)
+ tilesInSG.insert(it.key());
const QSet<QGeoTileSpec> toRemove = tilesInSG - d->m_visibleTiles;
const QSet<QGeoTileSpec> toAdd = d->m_visibleTiles - tilesInSG;
@@ -640,7 +642,9 @@ QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *win
d->m_updatedTextures.clear();
}
- const QSet<QGeoTileSpec> textures = QSet<QGeoTileSpec>::fromList(mapRoot->textures.keys());
+ QSet<QGeoTileSpec> textures;
+ for (auto it = mapRoot->textures.cbegin(), end = mapRoot->textures.cend(); it != end; ++it)
+ textures.insert(it.key());
const QSet<QGeoTileSpec> toRemove = textures - d->m_visibleTiles;
const QSet<QGeoTileSpec> toAdd = d->m_visibleTiles - textures;
diff --git a/src/location/maps/qgeotilefetcher.cpp b/src/location/maps/qgeotilefetcher.cpp
index b3f7021b..cfca57ac 100644
--- a/src/location/maps/qgeotilefetcher.cpp
+++ b/src/location/maps/qgeotilefetcher.cpp
@@ -43,6 +43,9 @@
#include "qgeotilespec_p.h"
#include "qgeotiledmap_p.h"
+#include <algorithm>
+#include <iterator>
+
QT_BEGIN_NAMESPACE
QGeoTileFetcher::QGeoTileFetcher(QGeoMappingManagerEngine *parent)
@@ -75,7 +78,7 @@ void QGeoTileFetcher::updateTileRequests(const QSet<QGeoTileSpec> &tilesAdded,
cancelTileRequests(tilesRemoved);
- d->queue_ += tilesAdded.toList();
+ std::copy(tilesAdded.cbegin(), tilesAdded.cend(), std::back_inserter(d->queue_));
if (d->enabled_ && initialized() && !d->queue_.isEmpty() && !d->timer_.isActive())
d->timer_.start(0, this);
diff --git a/src/location/maps/qnavigationmanagerengine.cpp b/src/location/maps/qnavigationmanagerengine.cpp
index 8837e5c6..aa5a980b 100644
--- a/src/location/maps/qnavigationmanagerengine.cpp
+++ b/src/location/maps/qnavigationmanagerengine.cpp
@@ -141,6 +141,11 @@ QGeoRouteLeg QAbstractNavigator::currentRouteLeg() const
return QGeoRouteLeg();
}
+QList<QGeoRoute> QAbstractNavigator::alternativeRoutes() const
+{
+ return QList<QGeoRoute>();
+}
+
int QAbstractNavigator::currentSegment() const
{
return 0;
diff --git a/src/location/maps/qnavigationmanagerengine_p.h b/src/location/maps/qnavigationmanagerengine_p.h
index 331df64f..8d2c9a99 100644
--- a/src/location/maps/qnavigationmanagerengine_p.h
+++ b/src/location/maps/qnavigationmanagerengine_p.h
@@ -98,7 +98,12 @@ public:
virtual int traveledTime() const;
virtual QGeoRoute currentRoute() const;
virtual QGeoRouteLeg currentRouteLeg() const;
+ virtual QList<QGeoRoute> alternativeRoutes() const = 0;
virtual int currentSegment() const;
+ virtual void setAutomaticReroutingEnabled(bool autoRerouting) = 0;
+ virtual bool automaticReroutingEnabled() const = 0; // configured via navigation params at construction time
+ virtual bool isOnRoute() = 0;
+ virtual void recalculateRoutes() = 0;
public slots:
virtual bool start() = 0;
@@ -116,6 +121,8 @@ signals:
void nextManeuverIconChanged();
void progressInformationChanged();
+ void isOnRouteChanged();
+ void alternativeRoutesChanged();
private:
QScopedPointer<QAbstractNavigatorPrivate> d;
diff --git a/src/location/places/qplace.cpp b/src/location/places/qplace.cpp
index ab115b5b..4e3e36d3 100644
--- a/src/location/places/qplace.cpp
+++ b/src/location/places/qplace.cpp
@@ -297,11 +297,8 @@ void QPlace::setContent(QPlaceContent::Type type, const QPlaceContent::Collectio
*/
void QPlace::insertContent(QPlaceContent::Type type, const QPlaceContent::Collection &content)
{
- QMapIterator<int, QPlaceContent> iter(content);
- while (iter.hasNext()) {
- iter.next();
+ for (auto iter = content.cbegin(), end = content.cend(); iter != end; ++iter)
d_ptr->m_contentCollections[type].insert(iter.key(), iter.value());
- }
}
/*!
diff --git a/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.cpp b/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.cpp
index ed594b56..2370e2cc 100644
--- a/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.cpp
+++ b/src/plugins/geoservices/mapboxgl/qsgmapboxglnode.cpp
@@ -38,6 +38,10 @@
#include "qsgmapboxglnode.h"
#include "qgeomapmapboxgl.h"
+#if QT_HAS_INCLUDE(<QtQuick/private/qsgplaintexture_p.h>)
+#include <QtQuick/private/qsgplaintexture_p.h>
+#endif
+
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLFunctions>
diff --git a/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm
index dc3903de..fae16715 100644
--- a/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm
+++ b/src/plugins/position/corelocation/qgeopositioninfosource_cl.mm
@@ -68,10 +68,8 @@
Q_UNUSED(oldLocation);
// Convert location timestamp to QDateTime
- QDateTime timeStamp;
NSTimeInterval locationTimeStamp = [newLocation.timestamp timeIntervalSince1970];
- timeStamp.setTime_t((uint) locationTimeStamp);
- timeStamp.setTime(timeStamp.time().addMSecs((uint)(locationTimeStamp * 1000) % 1000));
+ const QDateTime timeStamp = QDateTime::fromMSecsSinceEpoch(qRound64(locationTimeStamp * 1000), Qt::UTC);
// Construct position info from location data
QGeoPositionInfo location(QGeoCoordinate(newLocation.coordinate.latitude,
diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp
index a82cfb63..95ca42be 100644
--- a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp
+++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp
@@ -142,7 +142,7 @@ void QGeoPositionInfoSourceGeoclueMaster::updatePosition(PositionFields fields,
if (fields & Altitude)
coordinate.setAltitude(altitude);
- m_lastPosition = QGeoPositionInfo(coordinate, QDateTime::fromTime_t(timestamp));
+ m_lastPosition = QGeoPositionInfo(coordinate, QDateTime::fromSecsSinceEpoch(timestamp));
m_lastPositionFromSatellite = accuracy.level() == Accuracy::Detailed;
diff --git a/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp b/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp
index e39a6212..bbc70f0a 100644
--- a/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp
+++ b/src/plugins/position/positionpoll/qgeoareamonitor_polling.cpp
@@ -47,6 +47,8 @@
#include <QtCore/qdebug.h>
#include <QtCore/qmutex.h>
+#include <mutex>
+
#define UPDATE_INTERVAL_5S 5000
typedef QHash<QString, QGeoAreaMonitorInfo> MonitorTable;
@@ -74,7 +76,7 @@ class QGeoAreaMonitorPollingPrivate : public QObject
{
Q_OBJECT
public:
- QGeoAreaMonitorPollingPrivate() : source(0), mutex(QMutex::Recursive)
+ QGeoAreaMonitorPollingPrivate()
{
nextExpiryTimer = new QTimer(this);
nextExpiryTimer->setSingleShot(true);
@@ -84,7 +86,7 @@ public:
void startMonitoring(const QGeoAreaMonitorInfo &monitor)
{
- QMutexLocker locker(&mutex);
+ const std::lock_guard<QRecursiveMutex> locker(mutex);
activeMonitorAreas.insert(monitor.identifier(), monitor);
singleShotTrigger.remove(monitor.identifier());
@@ -95,7 +97,7 @@ public:
void requestUpdate(const QGeoAreaMonitorInfo &monitor, int signalId)
{
- QMutexLocker locker(&mutex);
+ const std::lock_guard<QRecursiveMutex> locker(mutex);
activeMonitorAreas.insert(monitor.identifier(), monitor);
singleShotTrigger.insert(monitor.identifier(), signalId);
@@ -106,7 +108,7 @@ public:
QGeoAreaMonitorInfo stopMonitoring(const QGeoAreaMonitorInfo &monitor)
{
- QMutexLocker locker(&mutex);
+ const std::lock_guard<QRecursiveMutex> locker(mutex);
QGeoAreaMonitorInfo mon = activeMonitorAreas.take(monitor.identifier());
@@ -118,7 +120,7 @@ public:
void registerClient(QGeoAreaMonitorPolling *client)
{
- QMutexLocker locker(&mutex);
+ const std::lock_guard<QRecursiveMutex> locker(mutex);
connect(this, SIGNAL(timeout(QGeoAreaMonitorInfo)),
client, SLOT(timeout(QGeoAreaMonitorInfo)));
@@ -134,7 +136,7 @@ public:
void deregisterClient(QGeoAreaMonitorPolling *client)
{
- QMutexLocker locker(&mutex);
+ const std::lock_guard<QRecursiveMutex> locker(mutex);
registeredClients.removeAll(client);
if (registeredClients.isEmpty())
@@ -143,7 +145,7 @@ public:
void setPositionSource(QGeoPositionInfoSource *newSource)
{
- QMutexLocker locker(&mutex);
+ const std::lock_guard<QRecursiveMutex> locker(mutex);
if (newSource == source)
return;
@@ -169,20 +171,20 @@ public:
QGeoPositionInfoSource* positionSource() const
{
- QMutexLocker locker(&mutex);
+ const std::lock_guard<QRecursiveMutex> locker(mutex);
return source;
}
MonitorTable activeMonitors() const
{
- QMutexLocker locker(&mutex);
+ const std::lock_guard<QRecursiveMutex> locker(mutex);
return activeMonitorAreas;
}
void checkStartStop()
{
- QMutexLocker locker(&mutex);
+ const std::lock_guard<QRecursiveMutex> locker(mutex);
bool signalsConnected = false;
foreach (const QGeoAreaMonitorPolling *client, registeredClients) {
@@ -307,9 +309,9 @@ private:
MonitorTable activeMonitorAreas;
- QGeoPositionInfoSource* source;
+ QGeoPositionInfoSource* source = nullptr;
QList<QGeoAreaMonitorPolling*> registeredClients;
- mutable QMutex mutex;
+ mutable QRecursiveMutex mutex;
};
Q_GLOBAL_STATIC(QGeoAreaMonitorPollingPrivate, pollingPrivate)
diff --git a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp
index 58092ea3..d56f1d46 100644
--- a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp
+++ b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp
@@ -43,30 +43,101 @@
#include <QtSerialPort/qserialportinfo.h>
#include <QtCore/qloggingcategory.h>
#include <QSet>
+#include "qiopipe_p.h"
+#include <QSharedPointer>
+#include "qnmeasatelliteinfosource_p.h"
Q_LOGGING_CATEGORY(lcSerial, "qt.positioning.serialnmea")
+class IODeviceContainer
+{
+public:
+ IODeviceContainer() {}
+ IODeviceContainer(IODeviceContainer const&) = delete;
+ void operator=(IODeviceContainer const&) = delete;
+
+ QSharedPointer<QIOPipe> serial(const QString &portName)
+ {
+ if (m_serialPorts.contains(portName)) {
+ m_serialPorts[portName].refs++;
+ QIOPipe *endPipe = new QIOPipe(m_serialPorts[portName].proxy);
+ m_serialPorts[portName].proxy->addChildPipe(endPipe);
+ return QSharedPointer<QIOPipe>(endPipe);
+ }
+ IODevice device;
+ QSerialPort *port = new QSerialPort(portName);
+ port->setBaudRate(4800);
+ qCDebug(lcSerial) << "Opening serial port" << portName;
+ if (!port->open(QIODevice::ReadOnly)) {
+ qWarning("serialnmea: Failed to open %s", qPrintable(portName));
+ delete port;
+ return {};
+ }
+ qCDebug(lcSerial) << "Opened successfully";
+ device.device = port;
+ device.refs = 1;
+ device.proxy = new QIOPipe(port, QIOPipe::ProxyPipe);
+ m_serialPorts[portName] = device;
+ QIOPipe *endPipe = new QIOPipe(device.proxy);
+ device.proxy->addChildPipe(endPipe);
+ return QSharedPointer<QIOPipe>(endPipe);
+ }
+
+ void releaseSerial(const QString &portName, QSharedPointer<QIOPipe> &pipe) {
+ if (!m_serialPorts.contains(portName))
+ return;
+
+ pipe.clear(); // make sure to release the pipe returned by getSerial, or else, if there are still refs, data will be leaked through it
+ IODevice &device = m_serialPorts[portName];
+ if (device.refs > 1) {
+ device.refs--;
+ return;
+ }
+
+ IODevice taken = m_serialPorts.take(portName);
+ taken.device->deleteLater();
+ }
+
+private:
+
+ struct IODevice {
+ QIODevice *device = nullptr;
+ QIOPipe *proxy = nullptr; // adding client pipes as children of proxy allows to dynamically add clients to one device.
+ unsigned int refs = 1;
+ };
+
+ QMap<QString, IODevice> m_serialPorts;
+};
+
+Q_GLOBAL_STATIC(IODeviceContainer, deviceContainer)
+
+
class NmeaSource : public QNmeaPositionInfoSource
{
public:
- NmeaSource(QObject *parent);
+ explicit NmeaSource(QObject *parent, const QVariantMap &parameters);
+ ~NmeaSource() override;
bool isValid() const { return !m_port.isNull(); }
private:
- QScopedPointer<QSerialPort> m_port;
+ QSharedPointer<QIOPipe> m_port;
+ QString m_portName;
};
-NmeaSource::NmeaSource(QObject *parent)
- : QNmeaPositionInfoSource(RealTimeMode, parent),
- m_port(new QSerialPort)
+NmeaSource::NmeaSource(QObject *parent, const QVariantMap &parameters)
+ : QNmeaPositionInfoSource(RealTimeMode, parent)
{
- QByteArray requestedPort = qgetenv("QT_NMEA_SERIAL_PORT");
+ QByteArray requestedPort;
+ if (parameters.contains(QStringLiteral("serialnmea.serial_port")))
+ requestedPort = parameters.value(QStringLiteral("serialnmea.serial_port")).toString().toLatin1();
+ else
+ requestedPort = qgetenv("QT_NMEA_SERIAL_PORT");
+ QString portName;
if (requestedPort.isEmpty()) {
const QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
qCDebug(lcSerial) << "Found" << ports.count() << "serial ports";
if (ports.isEmpty()) {
qWarning("serialnmea: No serial ports found");
- m_port.reset();
return;
}
@@ -74,8 +145,7 @@ NmeaSource::NmeaSource(QObject *parent)
QSet<int> supportedDevices;
supportedDevices << 0x67b; // GlobalSat (BU-353S4 and probably others)
supportedDevices << 0xe8d; // Qstarz MTK II
- QString portName;
- foreach (const QSerialPortInfo& port, ports) {
+ for (const QSerialPortInfo& port : ports) {
if (port.hasVendorIdentifier() && supportedDevices.contains(port.vendorIdentifier())) {
portName = port.portName();
break;
@@ -84,44 +154,116 @@ NmeaSource::NmeaSource(QObject *parent)
if (portName.isEmpty()) {
qWarning("serialnmea: No known GPS device found. Specify the COM port via QT_NMEA_SERIAL_PORT.");
- m_port.reset();
return;
}
-
- m_port->setPortName(portName);
+ m_portName = portName;
} else {
- m_port->setPortName(QString::fromUtf8(requestedPort));
+ m_portName = QString::fromUtf8(requestedPort);
}
- m_port->setBaudRate(4800);
-
- qCDebug(lcSerial) << "Opening serial port" << m_port->portName();
-
- if (!m_port->open(QIODevice::ReadOnly)) {
- qWarning("serialnmea: Failed to open %s", qPrintable(m_port->portName()));
- m_port.reset();
+ m_port = deviceContainer->serial(m_portName);
+ if (!m_port)
return;
- }
setDevice(m_port.data());
+}
- qCDebug(lcSerial) << "Opened successfully";
+NmeaSource::~NmeaSource()
+{
+ deviceContainer->releaseSerial(m_portName, m_port);
}
+
+
+class NmeaSatelliteSource : public QNmeaSatelliteInfoSource
+{
+public:
+ NmeaSatelliteSource(QObject *parent, const QVariantMap &parameters)
+ : QNmeaSatelliteInfoSource(parent)
+ {
+ QByteArray requestedPort;
+ if (parameters.contains(QStringLiteral("serialnmea.serial_port")))
+ requestedPort = parameters.value(QStringLiteral("serialnmea.serial_port")).toString().toLatin1();
+ else
+ requestedPort = qgetenv("QT_NMEA_SERIAL_PORT");
+ QString portName;
+ if (requestedPort.isEmpty()) {
+ const QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
+ qCDebug(lcSerial) << "Found" << ports.count() << "serial ports";
+ if (ports.isEmpty()) {
+ qWarning("serialnmea: No serial ports found");
+ return;
+ }
+
+ // Try to find a well-known device.
+ QSet<int> supportedDevices;
+ supportedDevices << 0x67b; // GlobalSat (BU-353S4 and probably others)
+ supportedDevices << 0xe8d; // Qstarz MTK II
+ foreach (const QSerialPortInfo& port, ports) {
+ if (port.hasVendorIdentifier() && supportedDevices.contains(port.vendorIdentifier())) {
+ portName = port.portName();
+ break;
+ }
+ }
+
+ if (portName.isEmpty()) {
+ qWarning("serialnmea: No known GPS device found. Specify the COM port via QT_NMEA_SERIAL_PORT.");
+ return;
+ }
+ m_portName = portName;
+ } else {
+ m_portName = QString::fromUtf8(requestedPort);
+ }
+
+ m_port = deviceContainer->serial(m_portName);
+ if (!m_port)
+ return;
+
+ setDevice(m_port.data());
+ }
+
+ ~NmeaSatelliteSource()
+ {
+ deviceContainer->releaseSerial(m_portName, m_port);
+ }
+
+ bool isValid() const { return !m_port.isNull(); }
+
+private:
+ QSharedPointer<QIOPipe> m_port;
+ QString m_portName;
+};
+
QGeoPositionInfoSource *QGeoPositionInfoSourceFactorySerialNmea::positionInfoSource(QObject *parent)
{
- QScopedPointer<NmeaSource> src(new NmeaSource(parent));
- return src->isValid() ? src.take() : nullptr;
+ return positionInfoSourceWithParameters(parent, QVariantMap());
}
QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactorySerialNmea::satelliteInfoSource(QObject *parent)
{
- Q_UNUSED(parent);
- return nullptr;
+ return satelliteInfoSourceWithParameters(parent, QVariantMap());
}
QGeoAreaMonitorSource *QGeoPositionInfoSourceFactorySerialNmea::areaMonitor(QObject *parent)
{
+ return areaMonitorWithParameters(parent, QVariantMap());
+}
+
+QGeoPositionInfoSource *QGeoPositionInfoSourceFactorySerialNmea::positionInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters)
+{
+ QScopedPointer<NmeaSource> src(new NmeaSource(parent, parameters));
+ return src->isValid() ? src.take() : nullptr;
+}
+
+QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactorySerialNmea::satelliteInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters)
+{
+ QScopedPointer<NmeaSatelliteSource> src(new NmeaSatelliteSource(parent, parameters));
+ return src->isValid() ? src.take() : nullptr;
+}
+
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactorySerialNmea::areaMonitorWithParameters(QObject *parent, const QVariantMap &parameters)
+{
Q_UNUSED(parent);
+ Q_UNUSED(parameters)
return nullptr;
}
diff --git a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h
index e372d56f..c8ca0e7e 100644
--- a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h
+++ b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.h
@@ -43,17 +43,21 @@
#include <QObject>
#include <qgeopositioninfosourcefactory.h>
-class QGeoPositionInfoSourceFactorySerialNmea : public QObject, public QGeoPositionInfoSourceFactory
+class QGeoPositionInfoSourceFactorySerialNmea : public QObject, public QGeoPositionInfoSourceFactoryV2
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0"
FILE "plugin.json")
- Q_INTERFACES(QGeoPositionInfoSourceFactory)
+ Q_INTERFACES(QGeoPositionInfoSourceFactoryV2)
public:
QGeoPositionInfoSource *positionInfoSource(QObject *parent);
QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
QGeoAreaMonitorSource *areaMonitor(QObject *parent);
+
+ QGeoPositionInfoSource *positionInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters);
+ QGeoSatelliteInfoSource *satelliteInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters);
+ QGeoAreaMonitorSource *areaMonitorWithParameters(QObject *parent, const QVariantMap &parameters);
};
#endif
diff --git a/src/plugins/position/serialnmea/qiopipe.cpp b/src/plugins/position/serialnmea/qiopipe.cpp
new file mode 100644
index 00000000..ce908d4d
--- /dev/null
+++ b/src/plugins/position/serialnmea/qiopipe.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** 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 "qiopipe_p.h"
+#include <QtCore/qmetaobject.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ proxying means do *not* emit readyRead, and instead pump data
+ into child pipes directly in a zero-copy fashion.
+*/
+QIOPipePrivate::QIOPipePrivate(QIODevice *iodevice, bool proxying)
+ : m_proxying(proxying), source(iodevice)
+{
+ const QIOPipe *parentPipe = qobject_cast<QIOPipe *>(iodevice);
+ if (parentPipe && parentPipe->d_func()->m_proxying) // with proxying parent,
+ return; // don't do anything
+
+ // read available data, does not emit.
+ readAvailableData();
+ // connect readyRead to onReadyRead
+ QObjectPrivate::connect(source, &QIODevice::readyRead, this, &QIOPipePrivate::_q_onReadyRead);
+}
+
+QIOPipePrivate::~QIOPipePrivate()
+{
+}
+
+bool QIOPipePrivate::readAvailableData() {
+ if (!source)
+ return false;
+ QByteArray ba = source->readAll();
+ if (!ba.size())
+ return false;
+
+ pumpData(ba);
+ return true;
+}
+
+void QIOPipePrivate::pumpData(const QByteArray &ba)
+{
+ if (m_proxying) {
+ QVector<int> toRemove;
+ for (int i = 0; i < childPipes.size(); ++i) {
+ const QPointer<QIOPipe> &cp = childPipes.at(i);
+ if (!cp) {
+ toRemove.append(i);
+ continue;
+ }
+ QIOPipePrivate *cpp = cp->d_func();
+ cpp->pushData(ba);
+ }
+ for (int i = toRemove.size() - 1; i >= 0; --i) {
+ childPipes.remove(i);
+ }
+ } else {
+ for (int i = 0; i < readBuffers.size(); i++)
+ readBuffers[i].append(ba);
+ }
+}
+
+void QIOPipePrivate::pushData(const QByteArray &ba)
+{
+ Q_Q(QIOPipe);
+ if (!ba.size())
+ return;
+
+ pumpData(ba);
+ if (!m_proxying)
+ emit q->readyRead();
+}
+
+void QIOPipePrivate::_q_onReadyRead()
+{
+ Q_Q(QIOPipe);
+ if (readAvailableData() && !m_proxying)
+ emit q->readyRead();
+}
+
+void QIOPipePrivate::addChildPipe(QIOPipe *childPipe)
+{
+ if (childPipes.contains(childPipe))
+ return;
+ childPipes.append(childPipe);
+}
+
+void QIOPipePrivate::removeChildPipe(QIOPipe *childPipe)
+{
+ childPipes.removeOne(childPipe);
+}
+
+QIOPipe::QIOPipe(QIODevice *parent, Mode mode)
+ : QIODevice(*new QIOPipePrivate(parent, mode == ProxyPipe), parent)
+{
+ if (!parent->isOpen() && !parent->open(QIODevice::ReadOnly)) {
+ qWarning() << "QIOPipe: Failed to open " << parent;
+ return;
+ }
+ open(ReadOnly);
+}
+
+QIOPipe::~QIOPipe()
+{
+
+}
+
+bool QIOPipe::open(QIODevice::OpenMode mode)
+{
+ if (isOpen())
+ return true;
+
+ static const OpenMode supportedOpenMode = ReadOnly; // Currently limit it to read only
+ if (!(mode & supportedOpenMode)) {
+ qFatal("Unsupported open mode");
+ return false;
+ }
+
+ return QIODevice::open(mode);
+}
+
+bool QIOPipe::isSequential() const
+{
+ return true;
+}
+
+void QIOPipe::setReadChannelCount(int count)
+{
+ Q_D(QIOPipe);
+ d->setReadChannelCount(qMax(count, 1));
+}
+
+void QIOPipe::addChildPipe(QIOPipe *childPipe)
+{
+ Q_D(QIOPipe);
+ d->addChildPipe(childPipe);
+}
+
+/*!
+ \reimp
+
+ \omit
+ This function does not really read anything, as we use QIODevicePrivate's
+ buffer. The buffer will be read inside of QIODevice before this
+ method will be called.
+ See QIODevicePrivate::read, buffer.read(data, maxSize).
+ \endomit
+*/
+qint64 QIOPipe::readData(char *data, qint64 maxlen)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxlen);
+
+ // return 0 indicating there may be more data in the future
+ // Returning -1 means no more data in the future (end of stream).
+ return qint64(0);
+}
+
+qint64 QIOPipe::writeData(const char * /*data*/, qint64 /*len*/)
+{
+ qFatal("QIOPipe is a read-only device");
+ return qint64(0);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/position/serialnmea/qiopipe_p.h b/src/plugins/position/serialnmea/qiopipe_p.h
new file mode 100644
index 00000000..25758fcb
--- /dev/null
+++ b/src/plugins/position/serialnmea/qiopipe_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** 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 QIOPIPE_P_H
+#define QIOPIPE_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/qiodevice.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/private/qiodevice_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QIOPipePrivate;
+
+class QIOPipe : public QIODevice
+{
+ Q_OBJECT
+
+public:
+ enum Mode {
+ EndPipe = 0x0000,
+ ProxyPipe = 0x0001
+ };
+
+ explicit QIOPipe(QIODevice *parent, Mode mode = EndPipe);
+ ~QIOPipe() override;
+
+ bool open(OpenMode openMode) override;
+ bool isSequential() const override;
+ void setReadChannelCount(int count);
+ void addChildPipe(QIOPipe *childPipe);
+
+protected:
+ qint64 readData(char *data, qint64 maxlen) override;
+ qint64 writeData(const char *data, qint64 len) override;
+
+private:
+ Q_DECLARE_PRIVATE(QIOPipe)
+ Q_DISABLE_COPY(QIOPipe)
+};
+
+class QIOPipePrivate : public QIODevicePrivate
+{
+ Q_DECLARE_PUBLIC(QIOPipe)
+
+public:
+ explicit QIOPipePrivate(QIODevice *iodevice, bool proxying);
+ ~QIOPipePrivate() override;
+
+ bool readAvailableData();
+ void pumpData(const QByteArray &ba);
+ void pushData(const QByteArray &ba);
+ void _q_onReadyRead();
+ void addChildPipe(QIOPipe *childPipe);
+ void removeChildPipe(QIOPipe *childPipe);
+
+ bool m_proxying = false;
+ QPointer<QIODevice> source;
+ QVector<QPointer<QIOPipe>> childPipes;
+};
+
+#endif // QIOPIPE_P_H
+
+QT_END_NAMESPACE
diff --git a/src/plugins/position/serialnmea/qnmeasatelliteinfosource.cpp b/src/plugins/position/serialnmea/qnmeasatelliteinfosource.cpp
new file mode 100644
index 00000000..d31106fc
--- /dev/null
+++ b/src/plugins/position/serialnmea/qnmeasatelliteinfosource.cpp
@@ -0,0 +1,558 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnmeasatelliteinfosource_p.h"
+#include <QtPositioning/private/qgeosatelliteinfo_p.h>
+#include <QtPositioning/private/qgeosatelliteinfosource_p.h>
+#include <QtPositioning/private/qlocationutils_p.h>
+
+#include <QIODevice>
+#include <QBasicTimer>
+#include <QTimerEvent>
+#include <QTimer>
+#include <array>
+#include <QDebug>
+#include <QtCore/QtNumeric>
+
+
+//QT_BEGIN_NAMESPACE
+
+#define USE_NMEA_PIMPL 1
+
+#if USE_NMEA_PIMPL
+class QGeoSatelliteInfoPrivateNmea : public QGeoSatelliteInfoPrivate
+{
+public:
+ QGeoSatelliteInfoPrivateNmea(const QGeoSatelliteInfoPrivate &other);
+ QGeoSatelliteInfoPrivateNmea(const QGeoSatelliteInfoPrivateNmea &other);
+ virtual ~QGeoSatelliteInfoPrivateNmea();
+ virtual QGeoSatelliteInfoPrivate *clone() const;
+
+ QList<QByteArray> nmeaSentences;
+};
+
+QGeoSatelliteInfoPrivateNmea::QGeoSatelliteInfoPrivateNmea(const QGeoSatelliteInfoPrivate &other)
+: QGeoSatelliteInfoPrivate(other)
+{
+}
+
+QGeoSatelliteInfoPrivateNmea::QGeoSatelliteInfoPrivateNmea(const QGeoSatelliteInfoPrivateNmea &other)
+: QGeoSatelliteInfoPrivate(other)
+{
+ nmeaSentences = other.nmeaSentences;
+}
+
+QGeoSatelliteInfoPrivateNmea::~QGeoSatelliteInfoPrivateNmea() {}
+
+QGeoSatelliteInfoPrivate *QGeoSatelliteInfoPrivateNmea::clone() const
+{
+ return new QGeoSatelliteInfoPrivateNmea(*this);
+}
+#else
+typedef QGeoSatelliteInfoPrivate QGeoSatelliteInfoPrivateNmea;
+#endif
+
+class QNmeaSatelliteInfoSourcePrivate : public QObject, public QGeoSatelliteInfoSourcePrivate
+{
+ Q_OBJECT
+public:
+ QNmeaSatelliteInfoSourcePrivate(QNmeaSatelliteInfoSource *parent);
+ ~QNmeaSatelliteInfoSourcePrivate();
+
+ void startUpdates();
+ void stopUpdates();
+ void requestUpdate(int msec);
+ void notifyNewUpdate();
+
+public slots:
+ void readyRead();
+ void emitPendingUpdate();
+ void sourceDataClosed();
+ void updateRequestTimeout();
+
+
+public:
+ QGeoSatelliteInfoSource *m_source = nullptr;
+ QGeoSatelliteInfoSource::Error m_satelliteError = QGeoSatelliteInfoSource::NoError;
+ QPointer<QIODevice> m_device;
+ struct Update {
+ QList<QGeoSatelliteInfo> m_satellitesInView;
+ QList<QGeoSatelliteInfo> m_satellitesInUse;
+ QList<int> m_inUse; // temp buffer for GSA received before GSV
+ bool m_validInView = false;
+ bool m_validInUse = false;
+ bool m_fresh = false;
+ bool m_updatingGsv = false;
+#if USE_NMEA_PIMPL
+ QByteArray gsa;
+ QList<QByteArray> gsv;
+#endif
+ void setSatellitesInView(const QList<QGeoSatelliteInfo> &inView)
+ {
+ m_updatingGsv = false;
+ m_satellitesInView = inView;
+ m_validInView = m_fresh = true;
+ if (m_inUse.size()) {
+ m_satellitesInUse.clear();
+ m_validInUse = false;
+ bool corrupt = false;
+ for (const auto i: m_inUse) {
+ bool found = false;
+ for (const auto &s: m_satellitesInView) {
+ if (s.satelliteIdentifier() == i) {
+ m_satellitesInUse.append(s);
+ found = true;
+ }
+ }
+ if (!found) { // received a GSA before a GSV, but it was incorrect or something. Unrelated to this GSV at least.
+ m_satellitesInUse.clear();
+ corrupt = true;
+ break;
+ }
+ }
+ m_validInUse = !corrupt;
+ m_inUse.clear();
+ }
+ }
+
+// void setSatellitesInUse(const QList<QGeoSatelliteInfo> &inUse)
+// {
+// m_satellitesInUse = inUse;
+// m_validInUse = true;
+// m_inUse.clear();
+// }
+
+ bool setSatellitesInUse(const QList<int> &inUse)
+ {
+ m_satellitesInUse.clear();
+ m_validInUse = false;
+ m_inUse = inUse;
+ if (m_updatingGsv) {
+ m_satellitesInUse.clear();
+ m_validInView = false;
+ return false;
+ }
+ for (const auto i: inUse) {
+ bool found = false;
+ for (const auto &s: m_satellitesInView) {
+ if (s.satelliteIdentifier() == i) {
+ m_satellitesInUse.append(s);
+ found = true;
+ }
+ }
+ if (!found) { // if satellites in use aren't in view, the related GSV is still to be received.
+ m_inUse = inUse; // So clear outdated data, buffer the info, and set it later.
+ m_satellitesInUse.clear();
+ m_satellitesInView.clear();
+ m_validInView = false;
+ return false;
+ }
+ }
+ m_validInUse = m_fresh = true;
+ return true;
+ }
+
+ void consume()
+ {
+ m_fresh = false;
+ }
+
+ bool isFresh()
+ {
+ return m_fresh;
+ }
+
+ QSet<int> inUse() const
+ {
+ QSet<int> res;
+ for (const auto &s: m_satellitesInUse)
+ res.insert(s.satelliteIdentifier());
+ return res;
+ }
+
+ void clear()
+ {
+ m_satellitesInView.clear();
+ m_satellitesInUse.clear();
+ m_validInView = m_validInUse = false;
+ }
+
+ bool isValid()
+ {
+ return m_validInView || m_validInUse; // GSV without GSA is valid. GSA with outdated but still matching GSV also valid.
+ }
+ } m_pendingUpdate, m_lastUpdate;
+ bool m_fresh = false;
+ bool m_invokedStart = false;
+ bool m_noUpdateLastInterval = false;
+ bool m_updateTimeoutSent = false;
+ bool m_connectedReadyRead = false;
+ int m_pushDelay = 20;
+ QBasicTimer *m_updateTimer = nullptr; // the timer used in startUpdates()
+ QTimer *m_requestTimer = nullptr; // the timer used in requestUpdate()
+
+protected:
+ void readAvailableData();
+ bool openSourceDevice();
+ bool initialize();
+ void prepareSourceDevice();
+ bool emitUpdated(Update &update);
+ void timerEvent(QTimerEvent *event) override;
+};
+
+QNmeaSatelliteInfoSourcePrivate::QNmeaSatelliteInfoSourcePrivate(QNmeaSatelliteInfoSource *parent)
+: m_source(parent)
+{
+}
+
+void QNmeaSatelliteInfoSourcePrivate::notifyNewUpdate()
+{
+ if (m_pendingUpdate.isValid() && m_pendingUpdate.isFresh()) {
+ if (m_requestTimer && m_requestTimer->isActive()) { // User called requestUpdate()
+ m_requestTimer->stop();
+ emitUpdated(m_pendingUpdate);
+ } else if (m_invokedStart) { // user called startUpdates()
+ if (m_updateTimer && m_updateTimer->isActive()) { // update interval > 0
+ // for periodic updates, only want the most recent update
+ if (m_noUpdateLastInterval) {
+ // if the update was invalid when timerEvent was last called, a valid update
+ // should be sent ASAP
+ emitPendingUpdate(); // m_noUpdateLastInterval handled in there.
+ }
+ } else { // update interval <= 0, send anything new ASAP
+ m_noUpdateLastInterval = !emitUpdated(m_pendingUpdate);
+ }
+ }
+ }
+}
+
+QNmeaSatelliteInfoSourcePrivate::~QNmeaSatelliteInfoSourcePrivate()
+{
+ delete m_updateTimer;
+}
+
+void QNmeaSatelliteInfoSourcePrivate::startUpdates()
+{
+ if (m_invokedStart)
+ return;
+
+ m_invokedStart = true;
+ m_pendingUpdate.clear();
+ m_noUpdateLastInterval = false;
+
+ bool initialized = initialize();
+ if (!initialized)
+ return;
+
+ // Do not support simulation just yet
+// if (m_updateMode == QNmeaPositionInfoSource::RealTimeMode)
+ {
+ // skip over any buffered data - we only want the newest data.
+ // Don't do this in requestUpdate. In that case bufferedData is good to have/use.
+ if (m_device->bytesAvailable()) {
+ if (m_device->isSequential())
+ m_device->readAll();
+ else
+ m_device->seek(m_device->bytesAvailable());
+ }
+ }
+
+ if (m_updateTimer)
+ m_updateTimer->stop();
+
+ if (m_source->updateInterval() > 0) {
+ if (!m_updateTimer)
+ m_updateTimer = new QBasicTimer;
+ m_updateTimer->start(m_source->updateInterval(), this);
+ }
+
+ if (initialized)
+ prepareSourceDevice();
+}
+
+void QNmeaSatelliteInfoSourcePrivate::stopUpdates()
+{
+ m_invokedStart = false;
+ if (m_updateTimer)
+ m_updateTimer->stop();
+ m_pendingUpdate.clear();
+ m_noUpdateLastInterval = false;
+}
+
+void QNmeaSatelliteInfoSourcePrivate::requestUpdate(int msec)
+{
+ if (m_requestTimer && m_requestTimer->isActive())
+ return;
+
+ if (msec <= 0 || msec < m_source->minimumUpdateInterval()) {
+ emit m_source->requestTimeout();
+ return;
+ }
+
+ if (!m_requestTimer) {
+ m_requestTimer = new QTimer(this);
+ connect(m_requestTimer, SIGNAL(timeout()), SLOT(updateRequestTimeout()));
+ }
+
+ bool initialized = initialize();
+ if (!initialized) {
+ emit m_source->requestTimeout();
+ return;
+ }
+
+ m_requestTimer->start(msec);
+ prepareSourceDevice();
+}
+
+void QNmeaSatelliteInfoSourcePrivate::readyRead()
+{
+ readAvailableData();
+}
+
+void QNmeaSatelliteInfoSourcePrivate::emitPendingUpdate()
+{
+ if (m_pendingUpdate.isValid() && m_pendingUpdate.isFresh()) {
+ m_updateTimeoutSent = false;
+ m_noUpdateLastInterval = false;
+ if (!emitUpdated(m_pendingUpdate))
+ m_noUpdateLastInterval = true;
+// m_pendingUpdate.clear(); // Do not clear, it will be incrementally updated
+ } else { // invalid or not fresh update
+ if (m_noUpdateLastInterval && !m_updateTimeoutSent) {
+ m_updateTimeoutSent = true;
+ emit m_source->requestTimeout();
+ }
+ m_noUpdateLastInterval = true;
+ }
+}
+
+void QNmeaSatelliteInfoSourcePrivate::sourceDataClosed()
+{
+ if (m_device && m_device->bytesAvailable())
+ readAvailableData();
+}
+
+void QNmeaSatelliteInfoSourcePrivate::updateRequestTimeout()
+{
+ m_requestTimer->stop();
+ emit m_source->requestTimeout();
+}
+
+void QNmeaSatelliteInfoSourcePrivate::readAvailableData()
+{
+ while (m_device->canReadLine()) {
+ char buf[1024];
+ qint64 size = m_device->readLine(buf, sizeof(buf));
+ QList<int> satInUse;
+ const bool satInUseParsed = QLocationUtils::getSatInUseFromNmea(buf, size, satInUse);
+ if (satInUseParsed) {
+ m_pendingUpdate.setSatellitesInUse(satInUse);
+#if USE_NMEA_PIMPL
+ m_pendingUpdate.gsa = QByteArray(buf, size);
+ if (m_pendingUpdate.m_satellitesInUse.size()) {
+ for (auto &s: m_pendingUpdate.m_satellitesInUse)
+ static_cast<QGeoSatelliteInfoPrivateNmea *>(QGeoSatelliteInfoPrivate::get(s))->nmeaSentences.append(m_pendingUpdate.gsa);
+ for (auto &s: m_pendingUpdate.m_satellitesInView)
+ static_cast<QGeoSatelliteInfoPrivateNmea *>(QGeoSatelliteInfoPrivate::get(s))->nmeaSentences.append(m_pendingUpdate.gsa);
+ }
+#endif
+ } else {
+ const QLocationUtils::GSVParseStatus parserStatus = QLocationUtils::getSatInfoFromNmea(buf, size, m_pendingUpdate.m_satellitesInView);
+ if (parserStatus == QLocationUtils::GSVPartiallyParsed) {
+ m_pendingUpdate.m_updatingGsv = true;
+#if USE_NMEA_PIMPL
+ m_pendingUpdate.gsv.append(QByteArray(buf, size));
+#endif
+ } else if (parserStatus == QLocationUtils::GSVFullyParsed) {
+#if USE_NMEA_PIMPL
+ m_pendingUpdate.gsv.append(QByteArray(buf, size));
+ for (int i = 0; i < m_pendingUpdate.m_satellitesInView.size(); i++) {
+ const QGeoSatelliteInfo &s = m_pendingUpdate.m_satellitesInView.at(i);
+ QGeoSatelliteInfoPrivateNmea *pimpl = new QGeoSatelliteInfoPrivateNmea(*QGeoSatelliteInfoPrivate::get(s));
+ pimpl->nmeaSentences.append(m_pendingUpdate.gsa);
+ pimpl->nmeaSentences.append(m_pendingUpdate.gsv);
+ m_pendingUpdate.m_satellitesInView.replace(i, QGeoSatelliteInfo(*pimpl));
+ }
+ m_pendingUpdate.gsv.clear();
+#endif
+ m_pendingUpdate.setSatellitesInView(m_pendingUpdate.m_satellitesInView);
+ }
+ }
+ }
+ notifyNewUpdate();
+}
+
+bool QNmeaSatelliteInfoSourcePrivate::openSourceDevice()
+{
+ if (!m_device) {
+ qWarning("QNmeaSatelliteInfoSource: no QIODevice data source, call setDevice() first");
+ return false;
+ }
+
+ if (!m_device->isOpen() && !m_device->open(QIODevice::ReadOnly)) {
+ qWarning("QNmeaSatelliteInfoSource: cannot open QIODevice data source");
+ return false;
+ }
+
+ connect(m_device, SIGNAL(aboutToClose()), SLOT(sourceDataClosed()));
+ connect(m_device, SIGNAL(readChannelFinished()), SLOT(sourceDataClosed()));
+ connect(m_device, SIGNAL(destroyed()), SLOT(sourceDataClosed()));
+
+ return true;
+}
+
+bool QNmeaSatelliteInfoSourcePrivate::initialize()
+{
+ if (!openSourceDevice())
+ return false;
+
+ return true;
+}
+
+void QNmeaSatelliteInfoSourcePrivate::prepareSourceDevice()
+{
+ if (!m_connectedReadyRead) {
+ connect(m_device, SIGNAL(readyRead()), SLOT(readyRead()));
+ m_connectedReadyRead = true;
+ }
+}
+
+bool QNmeaSatelliteInfoSourcePrivate::emitUpdated(QNmeaSatelliteInfoSourcePrivate::Update &update)
+{
+ bool emitted = false;
+ if (!update.isFresh())
+ return emitted;
+
+ update.consume();
+ const bool inUseUpdated = update.m_satellitesInUse != m_lastUpdate.m_satellitesInUse;
+ const bool inViewUpdated = update.m_satellitesInView != m_lastUpdate.m_satellitesInView;
+
+
+ m_lastUpdate = update;
+ if (update.m_validInUse && inUseUpdated) {
+ emit m_source->satellitesInUseUpdated(update.m_satellitesInUse);
+ emitted = true;
+ }
+ if (update.m_validInView && inViewUpdated) {
+ emit m_source->satellitesInViewUpdated(update.m_satellitesInView);
+ emitted = true;
+ }
+ return emitted;
+}
+
+void QNmeaSatelliteInfoSourcePrivate::timerEvent(QTimerEvent * /*event*/)
+{
+ emitPendingUpdate();
+}
+
+
+// currently supports only realtime
+QNmeaSatelliteInfoSource::QNmeaSatelliteInfoSource(QObject *parent)
+: QGeoSatelliteInfoSource(*new QNmeaSatelliteInfoSourcePrivate(this), parent)
+{
+ d = static_cast<QNmeaSatelliteInfoSourcePrivate *>(QGeoSatelliteInfoSourcePrivate::get(*this));
+}
+
+QNmeaSatelliteInfoSource::~QNmeaSatelliteInfoSource()
+{
+ // d deleted in superclass destructor
+}
+
+void QNmeaSatelliteInfoSource::setDevice(QIODevice *device)
+{
+ if (device != d->m_device) {
+ if (!d->m_device)
+ d->m_device = device;
+ else
+ qWarning("QNmeaPositionInfoSource: source device has already been set");
+ }
+}
+
+QIODevice *QNmeaSatelliteInfoSource::device() const
+{
+ return d->m_device;
+}
+
+void QNmeaSatelliteInfoSource::setUpdateInterval(int msec)
+{
+ int interval = msec;
+ if (interval != 0)
+ interval = qMax(msec, minimumUpdateInterval());
+ QGeoSatelliteInfoSource::setUpdateInterval(interval);
+ if (d->m_invokedStart) {
+ d->stopUpdates();
+ d->startUpdates();
+ }
+}
+
+int QNmeaSatelliteInfoSource::minimumUpdateInterval() const
+{
+ return 2; // Some chips are capable of over 100 updates per seconds.
+}
+
+QGeoSatelliteInfoSource::Error QNmeaSatelliteInfoSource::error() const
+{
+ return d->m_satelliteError;
+}
+
+void QNmeaSatelliteInfoSource::startUpdates()
+{
+ d->startUpdates();
+}
+
+void QNmeaSatelliteInfoSource::stopUpdates()
+{
+ d->stopUpdates();
+}
+
+void QNmeaSatelliteInfoSource::requestUpdate(int msec)
+{
+ d->requestUpdate(msec == 0 ? 60000 * 5 : msec); // 5min default timeout
+}
+
+void QNmeaSatelliteInfoSource::setError(QGeoSatelliteInfoSource::Error satelliteError)
+{
+ d->m_satelliteError = satelliteError;
+ emit QGeoSatelliteInfoSource::error(satelliteError);
+}
+
+
+//QT_END_NAMESPACE
+
+#include "qnmeasatelliteinfosource.moc"
diff --git a/src/plugins/position/serialnmea/qnmeasatelliteinfosource_p.h b/src/plugins/position/serialnmea/qnmeasatelliteinfosource_p.h
new file mode 100644
index 00000000..2f7469c6
--- /dev/null
+++ b/src/plugins/position/serialnmea/qnmeasatelliteinfosource_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNMESATELLITEINFOSOURCE_P_H
+#define QNMESATELLITEINFOSOURCE_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 <QtPositioning/private/qpositioningglobal_p.h>
+#include <QtPositioning/qgeosatelliteinfosource.h>
+#include <QtPositioning/qgeosatelliteinfo.h>
+
+#include <QObject>
+#include <QQueue>
+#include <QPointer>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qtimer.h>
+
+//QT_BEGIN_NAMESPACE
+
+class QNmeaSatelliteInfoSourcePrivate;
+class /*Q_POSITIONING_PRIVATE_EXPORT*/ QNmeaSatelliteInfoSource : public QGeoSatelliteInfoSource
+{
+ Q_OBJECT
+public:
+ explicit QNmeaSatelliteInfoSource( QObject *parent = nullptr);
+ ~QNmeaSatelliteInfoSource() override;
+
+ void setDevice(QIODevice *source);
+ QIODevice *device() const;
+
+ void setUpdateInterval(int msec) override;
+ int minimumUpdateInterval() const override;
+ Error error() const override;
+
+public Q_SLOTS:
+ void startUpdates() override;
+ void stopUpdates() override;
+ void requestUpdate(int timeout = 0) override;
+
+protected:
+ QNmeaSatelliteInfoSourcePrivate *d;
+ void setError(QGeoSatelliteInfoSource::Error satelliteError);
+
+ friend class QNmeaSatelliteInfoSourcePrivate;
+ Q_DISABLE_COPY(QNmeaSatelliteInfoSource)
+};
+
+//QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/position/serialnmea/serialnmea.pro b/src/plugins/position/serialnmea/serialnmea.pro
index bdeb3f13..4e0088bb 100644
--- a/src/plugins/position/serialnmea/serialnmea.pro
+++ b/src/plugins/position/serialnmea/serialnmea.pro
@@ -1,12 +1,12 @@
TARGET = qtposition_serialnmea
-QT = core positioning serialport
+QT = core-private positioning-private serialport
HEADERS += \
- qgeopositioninfosourcefactory_serialnmea.h
+ qgeopositioninfosourcefactory_serialnmea.h qnmeasatelliteinfosource_p.h qiopipe_p.h
SOURCES += \
- qgeopositioninfosourcefactory_serialnmea.cpp
+ qgeopositioninfosourcefactory_serialnmea.cpp qnmeasatelliteinfosource.cpp qiopipe.cpp
OTHER_FILES += \
plugin.json
diff --git a/src/positioning/doc/src/plugins/serialnmea.qdoc b/src/positioning/doc/src/plugins/serialnmea.qdoc
new file mode 100644
index 00000000..3e9861b5
--- /dev/null
+++ b/src/positioning/doc/src/plugins/serialnmea.qdoc
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** 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 Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+\page position-plugin-serialnmea.html
+\title Qt Positioning Serial NMEA plugin
+\ingroup QtPositioning-plugins
+
+\brief Reads the NMEA stream from a serial connection to provide position updates.
+
+\section1 Overview
+
+Included with Qt Location is a position plugin which parses NMEA sentences streamed
+over a serial port into position updates.
+
+This plugin can be loaded by using the provider name \b serialnmea.
+
+
+\section1 Parameters
+
+The following table lists parameters that \e can be passed to the serialnmea plugin.
+
+\table
+\header
+ \li Parameter
+ \li Description
+\row
+ \li serialnmea.serial_port
+ \li The serial port where the NMEA stream is coming.
+\endtable
+
+\section1 Parameter Usage Example
+
+The following examples show how to create a \b serialnmea PositionSource
+listening on a specific serial port
+
+\section2 QML
+
+\code
+PositionSource {
+ name: "serialnmea"
+ PluginParameter { name: "serialnmea.serial_port"; value: "tnt1" }
+}
+\endcode
+
+\section2 C++
+
+\code
+QVariantMap params;
+params["serialnmea.serial_port"] = "tnt1";
+QGeoPositionInfoSource *positionSource = QGeoPositionInfoSource::createSource("serialnmea", params, this);
+\endcode
+
+*/
diff --git a/src/positioning/doc/src/qtpositioning-plugins.qdoc b/src/positioning/doc/src/qtpositioning-plugins.qdoc
index 37d25fc5..77fdf3aa 100644
--- a/src/positioning/doc/src/qtpositioning-plugins.qdoc
+++ b/src/positioning/doc/src/qtpositioning-plugins.qdoc
@@ -27,11 +27,43 @@
/*!
\page qtpositioning-plugins.html
-\title Qt Positioning service plugins
-\brief Implementing Qt Positioning plugins
+\title Qt Positioning plugins
+\brief Default Plugins and Implementing Qt Positioning plugins
+
+Qt Positioning provides the majority of its functionality through plugins.
+This document outlines how to develop a new position plugin.
+
+\section1 Default plugins
+Some plugins already ship with Qt. These are:
+
+\table
+ \row
+ \li \b android
+ \li Wraps Android positioning subsystem. Available only on Android.
+ \row
+ \li \b corelocation
+ \li Wraps iOS and macOS positioning subsystems. Available only on Apple platforms supporting corelocation.
+ \row
+ \li \b geoclue
+ \li Interfaces with \l{https://www.freedesktop.org/wiki/Software/GeoClue/}{GeoClue} v0.12. Requires GeoClue 0.12 to be present to function.
+ \row
+ \li \b geoclue2
+ \li Interfaces with \l{https://www.freedesktop.org/wiki/Software/GeoClue/}{GeoClue} v2. Requires GeoClue v2 to be present to function.
+ \row
+ \li \b gypsy
+ \li Interfaces with \l{https://gypsy.freedesktop.org/wiki/}{Gypsy} daemon. Requires Gypsy to be present to function.
+ \row
+ \li \b winrt
+ \li Wraps WinRT positioning subsystem. Available only on WinRT and Windows10.
+ \row
+ \li \b serialnmea
+ \li A \l {Qt Positioning Serial NMEA plugin}{Serial NMEA} backend that parses NMEA streams from a GPS receiver over a
+ serial link to provide position updates.
+ \row
+ \li \b positionpoll
+ \li A backend providing only area monitoring functionalities via polling on position updates.
+\endtable
-Qt Positioning provides the majority of its functionality through plugins. This
-document outlines how to develop a new position plugin.
\section1 Plugin Description
diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro
index 35e8e9e1..1eff0ab2 100644
--- a/src/positioning/positioning.pro
+++ b/src/positioning/positioning.pro
@@ -7,7 +7,7 @@ INCLUDEPATH += ../3rdparty/clipper
INCLUDEPATH += ../3rdparty/clip2tri
QMAKE_DOCS = $$PWD/doc/qtpositioning.qdocconf
-OTHER_FILES += configure.json doc/src/*.qdoc # show .qdoc files in Qt Creator
+OTHER_FILES += configure.json doc/src/*.qdoc doc/src/plugins/*.qdoc # show .qdoc files in Qt Creator
ANDROID_BUNDLED_JAR_DEPENDENCIES = \
jar/QtPositioning.jar:org.qtproject.qt5.android.positioning.QtPositioning
@@ -59,6 +59,8 @@ PRIVATE_HEADERS += \
qgeopolygon_p.h \
qgeocoordinateobject_p.h \
qgeopositioninfo_p.h \
+ qgeosatelliteinfo_p.h \
+ qgeosatelliteinfosource_p.h \
qclipperutils_p.h
SOURCES += \
@@ -89,7 +91,6 @@ SOURCES += \
HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS
-
load(qt_module)
LIBS_PRIVATE += -L$$MODULE_BASE_OUTDIR/lib -lclip2tri$$qtPlatformTargetSuffix()
diff --git a/src/positioning/qgeopositioninfosource.cpp b/src/positioning/qgeopositioninfosource.cpp
index 2e126175..69fcdef0 100644
--- a/src/positioning/qgeopositioninfosource.cpp
+++ b/src/positioning/qgeopositioninfosource.cpp
@@ -103,6 +103,16 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
\value AllPositioningMethods Satellite-based positioning methods as soon as available. Otherwise non-satellite based methods.
*/
+QGeoPositionInfoSourcePrivate *QGeoPositionInfoSourcePrivate::get(const QGeoPositionInfoSource &source)
+{
+ return source.d;
+}
+
+QGeoPositionInfoSourcePrivate::~QGeoPositionInfoSourcePrivate()
+{
+
+}
+
void QGeoPositionInfoSourcePrivate::loadMeta()
{
metaData = plugins().value(providerName);
@@ -113,7 +123,24 @@ void QGeoPositionInfoSourcePrivate::loadPlugin()
int idx = int(metaData.value(QStringLiteral("index")).toDouble());
if (idx < 0)
return;
- factory = qobject_cast<QGeoPositionInfoSourceFactory *>(loader()->instance(idx));
+ QObject *instance = loader()->instance(idx);
+ if (!instance)
+ return;
+ factoryV2 = qobject_cast<QGeoPositionInfoSourceFactoryV2 *>(instance);
+ if (!factoryV2)
+ factory = qobject_cast<QGeoPositionInfoSourceFactory *>(instance);
+ else
+ factory = factoryV2;
+}
+
+bool QGeoPositionInfoSourcePrivate::setBackendProperty(const QString &/*name*/, QVariant /*value*/)
+{
+ return false;
+}
+
+QVariant QGeoPositionInfoSourcePrivate::backendProperty(const QString &/*name*/) const
+{
+ return QVariant();
}
QHash<QString, QJsonObject> QGeoPositionInfoSourcePrivate::plugins(bool reload)
@@ -204,6 +231,36 @@ QString QGeoPositionInfoSource::sourceName() const
}
/*!
+ Sets the backend-specific property named \a name to \a value.
+ Returns \c true on success, \c false otherwise.
+ Backend-specific properties can be used to configure the positioning subsystem behavior
+ at runtime.
+ Supported backend-specific properties are listed and described in
+ \l {Qt Positioning plugins#Default plugins}.
+
+ \sa backendProperty
+ \since Qt 5.14
+*/
+bool QGeoPositionInfoSource::setBackendProperty(const QString &name, QVariant value)
+{
+ return d->setBackendProperty(name, value);
+}
+
+/*!
+ Returns the value of the backend-specific property named \a name, if present.
+ Otherwise, the returned value will be invalid.
+ Supported backend-specific properties are listed and described in
+ \l {Qt Positioning plugins#Default plugins}.
+
+ \sa setBackendProperty
+ \since Qt 5.14
+*/
+QVariant QGeoPositionInfoSource::backendProperty(const QString &name) const
+{
+ return d->backendProperty(name);
+}
+
+/*!
\property QGeoPositionInfoSource::updateInterval
\brief This property holds the requested interval in milliseconds between each update.
@@ -271,6 +328,22 @@ QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSource::preferredPosi
return d->methods;
}
+static QGeoPositionInfoSource* createSource_real(const QJsonObject &meta, const QVariantMap &parameters, QObject *parent)
+{
+ QGeoPositionInfoSourcePrivate d;
+ d.metaData = meta;
+ d.loadPlugin();
+ QGeoPositionInfoSource *s = nullptr;
+ if (!parameters.isEmpty() && d.factoryV2)
+ s = d.factoryV2->positionInfoSourceWithParameters(parent, parameters);
+ else if (d.factory)
+ s = d.factory->positionInfoSource(parent);
+ if (s)
+ QGeoPositionInfoSourcePrivate::get(*s)->metaData = d.metaData;
+
+ return s;
+}
+
/*!
Creates and returns a position source with the given \a parent that
reads from the system's default sources of location data, or the plugin
@@ -281,27 +354,32 @@ QGeoPositionInfoSource::PositioningMethods QGeoPositionInfoSource::preferredPosi
*/
QGeoPositionInfoSource *QGeoPositionInfoSource::createDefaultSource(QObject *parent)
{
+ return createDefaultSource(QVariantMap(), parent);
+}
+
+/*!
+ Creates and returns a position source with the given \a parent that
+ reads from the system's default sources of location data, or the plugin
+ with the highest available priority.
+
+ Returns nullptr if the system has no default position source, no valid plugins
+ could be found or the user does not have the permission to access the current position.
+
+ This method passes \a parameters to the factory to configure the source.
+
+ \since Qt 5.14
+*/
+QGeoPositionInfoSource *QGeoPositionInfoSource::createDefaultSource(const QVariantMap &parameters, QObject *parent)
+{
QList<QJsonObject> plugins = QGeoPositionInfoSourcePrivate::pluginsSorted();
foreach (const QJsonObject &obj, plugins) {
if (obj.value(QStringLiteral("Position")).isBool()
&& obj.value(QStringLiteral("Position")).toBool())
- {
- QGeoPositionInfoSourcePrivate d;
- d.metaData = obj;
- d.loadPlugin();
- QGeoPositionInfoSource *s = 0;
- if (d.factory)
- s = d.factory->positionInfoSource(parent);
- if (s) {
- s->d->metaData = d.metaData;
- return s;
- }
- }
+ return createSource_real(obj, parameters, parent);
}
- return 0;
+ return nullptr;
}
-
/*!
Creates and returns a position source with the given \a parent,
by loading the plugin named \a sourceName.
@@ -310,25 +388,27 @@ QGeoPositionInfoSource *QGeoPositionInfoSource::createDefaultSource(QObject *par
*/
QGeoPositionInfoSource *QGeoPositionInfoSource::createSource(const QString &sourceName, QObject *parent)
{
+ return createSource(sourceName, QVariantMap(), parent);
+}
+
+/*!
+ Creates and returns a position source with the given \a parent,
+ by loading the plugin named \a sourceName.
+
+ Returns nullptr if the plugin cannot be found.
+
+ This method passes \a parameters to the factory to configure the source.
+
+ \since Qt 5.14
+*/
+QGeoPositionInfoSource *QGeoPositionInfoSource::createSource(const QString &sourceName, const QVariantMap &parameters, QObject *parent)
+{
QHash<QString, QJsonObject> plugins = QGeoPositionInfoSourcePrivate::plugins();
if (plugins.contains(sourceName))
- {
- QGeoPositionInfoSourcePrivate d;
- d.metaData = plugins.value(sourceName);
- d.loadPlugin();
- QGeoPositionInfoSource *src = 0;
- if (d.factory)
- src = d.factory->positionInfoSource(parent);
- if (src)
- {
- src->d->metaData = d.metaData;
- return src;
- }
- }
- return 0;
+ return createSource_real(plugins.value(sourceName), parameters, parent);
+ return nullptr;
}
-
/*!
Returns a list of available source plugins. This includes any default backend
plugin for the current platform.
@@ -347,6 +427,15 @@ QStringList QGeoPositionInfoSource::availableSources()
return plugins;
}
+QGeoPositionInfoSource::QGeoPositionInfoSource(QGeoPositionInfoSourcePrivate &dd, QObject *parent)
+: QObject(parent),
+ d(&dd)
+{
+ qRegisterMetaType<QGeoPositionInfo>();
+ d->interval = 0;
+ d->methods = NoPositioningMethods;
+}
+
/*!
\fn QGeoPositionInfo QGeoPositionInfoSource::lastKnownPosition(bool fromSatellitePositioningMethodsOnly = false) const = 0;
diff --git a/src/positioning/qgeopositioninfosource.h b/src/positioning/qgeopositioninfosource.h
index 7fe02270..eaf5e106 100644
--- a/src/positioning/qgeopositioninfosource.h
+++ b/src/positioning/qgeopositioninfosource.h
@@ -36,6 +36,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
#ifndef QGEOPOSITIONINFOSOURCE_H
#define QGEOPOSITIONINFOSOURCE_H
@@ -86,8 +87,13 @@ public:
QString sourceName() const;
+ bool setBackendProperty(const QString &name, QVariant value);
+ QVariant backendProperty(const QString &name) const;
+
static QGeoPositionInfoSource *createDefaultSource(QObject *parent);
+ static QGeoPositionInfoSource *createDefaultSource(const QVariantMap &parameters, QObject *parent);
static QGeoPositionInfoSource *createSource(const QString &sourceName, QObject *parent);
+ static QGeoPositionInfoSource *createSource(const QString &sourceName, const QVariantMap &parameters, QObject *parent);
static QStringList availableSources();
virtual Error error() const = 0;
@@ -103,9 +109,14 @@ Q_SIGNALS:
void error(QGeoPositionInfoSource::Error);
void supportedPositioningMethodsChanged();
+protected:
+ QGeoPositionInfoSource(QGeoPositionInfoSourcePrivate &dd, QObject *parent);
+
private:
Q_DISABLE_COPY(QGeoPositionInfoSource)
QGeoPositionInfoSourcePrivate *d;
+
+ friend class QGeoPositionInfoSourcePrivate;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoPositionInfoSource::PositioningMethods)
diff --git a/src/positioning/qgeopositioninfosource_p.h b/src/positioning/qgeopositioninfosource_p.h
index 32fd23e6..ccd92a4e 100644
--- a/src/positioning/qgeopositioninfosource_p.h
+++ b/src/positioning/qgeopositioninfosource_p.h
@@ -51,6 +51,7 @@
// We mean it.
//
+#include <QtPositioning/private/qpositioningglobal_p.h>
#include "qgeopositioninfosource.h"
#include "qgeopositioninfosourcefactory.h"
#include <QJsonObject>
@@ -60,17 +61,23 @@
QT_BEGIN_NAMESPACE
-class QGeoPositionInfoSourcePrivate
+class Q_POSITIONING_PRIVATE_EXPORT QGeoPositionInfoSourcePrivate
{
public:
+ static QGeoPositionInfoSourcePrivate *get(const QGeoPositionInfoSource &source);
+ virtual ~QGeoPositionInfoSourcePrivate();
+
int interval;
QGeoPositionInfoSource::PositioningMethods methods;
QJsonObject metaData;
- QGeoPositionInfoSourceFactory *factory;
+ QGeoPositionInfoSourceFactory *factory = nullptr;
+ QGeoPositionInfoSourceFactoryV2 *factoryV2 = nullptr;
QString providerName;
void loadMeta();
void loadPlugin();
+ virtual bool setBackendProperty(const QString &name, QVariant value);
+ virtual QVariant backendProperty(const QString &name) const;
static QHash<QString, QJsonObject> plugins(bool reload = false);
static void loadPluginMetadata(QHash<QString, QJsonObject> &list);
diff --git a/src/positioning/qgeopositioninfosourcefactory.cpp b/src/positioning/qgeopositioninfosourcefactory.cpp
index 6c6e9c73..76803566 100644
--- a/src/positioning/qgeopositioninfosourcefactory.cpp
+++ b/src/positioning/qgeopositioninfosourcefactory.cpp
@@ -84,4 +84,8 @@ QT_BEGIN_NAMESPACE
QGeoPositionInfoSourceFactory::~QGeoPositionInfoSourceFactory()
{}
+QGeoPositionInfoSourceFactoryV2::~QGeoPositionInfoSourceFactoryV2()
+{}
+
QT_END_NAMESPACE
+
diff --git a/src/positioning/qgeopositioninfosourcefactory.h b/src/positioning/qgeopositioninfosourcefactory.h
index b30aaf7e..e55a1eb3 100644
--- a/src/positioning/qgeopositioninfosourcefactory.h
+++ b/src/positioning/qgeopositioninfosourcefactory.h
@@ -61,6 +61,21 @@ public:
Q_DECLARE_INTERFACE(QGeoPositionInfoSourceFactory,
"org.qt-project.qt.position.sourcefactory/5.0")
+class Q_POSITIONING_EXPORT QGeoPositionInfoSourceFactoryV2 : public QGeoPositionInfoSourceFactory
+{
+public:
+ virtual ~QGeoPositionInfoSourceFactoryV2();
+
+ virtual QGeoPositionInfoSource *positionInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters) = 0;
+ virtual QGeoSatelliteInfoSource *satelliteInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters) = 0;
+ virtual QGeoAreaMonitorSource *areaMonitorWithParameters(QObject *parent, const QVariantMap &parameters) = 0;
+};
+
+// Although not actually used for constructing a specialized loader, this is required for
+// casting a QObject * into QGeoPositionInfoSourceFactoryV2 *
+Q_DECLARE_INTERFACE(QGeoPositionInfoSourceFactoryV2,
+ "org.qt-project.qt.position.sourcefactoryV2/5.0")
+
QT_END_NAMESPACE
#endif // QGEOPOSITIONINFOSOURCEFACTORY_H
diff --git a/src/positioning/qgeosatelliteinfo.cpp b/src/positioning/qgeosatelliteinfo.cpp
index e62bd164..91ebfa85 100644
--- a/src/positioning/qgeosatelliteinfo.cpp
+++ b/src/positioning/qgeosatelliteinfo.cpp
@@ -37,6 +37,7 @@
**
****************************************************************************/
#include "qgeosatelliteinfo.h"
+#include "qgeosatelliteinfo_p.h"
#include <QHash>
#include <QDebug>
@@ -44,16 +45,6 @@
QT_BEGIN_NAMESPACE
-class QGeoSatelliteInfoPrivate
-{
-public:
- int signal;
- int satId;
- QGeoSatelliteInfo::SatelliteSystem system;
- QHash<int, qreal> doubleAttribs;
-};
-
-
/*!
\class QGeoSatelliteInfo
\inmodule QtPositioning
@@ -103,6 +94,10 @@ QGeoSatelliteInfo::QGeoSatelliteInfo(const QGeoSatelliteInfo &other)
operator=(other);
}
+QGeoSatelliteInfo::QGeoSatelliteInfo(QGeoSatelliteInfoPrivate &dd) : d(&dd)
+{
+}
+
/*!
Destroys a satellite information object.
*/
@@ -119,10 +114,9 @@ QGeoSatelliteInfo &QGeoSatelliteInfo::operator=(const QGeoSatelliteInfo & other)
if (this == &other)
return *this;
- d->signal = other.d->signal;
- d->satId = other.d->satId;
- d->system = other.d->system;
- d->doubleAttribs = other.d->doubleAttribs;
+ delete d;
+ d = other.d->clone();
+
return *this;
}
@@ -132,10 +126,7 @@ QGeoSatelliteInfo &QGeoSatelliteInfo::operator=(const QGeoSatelliteInfo & other)
*/
bool QGeoSatelliteInfo::operator==(const QGeoSatelliteInfo &other) const
{
- return d->signal == other.d->signal
- && d->satId == other.d->satId
- && d->system == other.d->system
- && d->doubleAttribs == other.d->doubleAttribs;
+ return *d == *other.d;
}
/*!
@@ -309,6 +300,40 @@ QDataStream &operator>>(QDataStream &stream, QGeoSatelliteInfo &info)
info.d->system = (QGeoSatelliteInfo::SatelliteSystem)system;
return stream;
}
+
+QGeoSatelliteInfoPrivate::QGeoSatelliteInfoPrivate()
+{
+
+}
+
+QGeoSatelliteInfoPrivate::QGeoSatelliteInfoPrivate(const QGeoSatelliteInfoPrivate &other)
+{
+ signal = other.signal;
+ satId = other.satId;
+ system = other.system;
+ doubleAttribs = other.doubleAttribs;
+}
+
+QGeoSatelliteInfoPrivate::~QGeoSatelliteInfoPrivate() {}
+
+QGeoSatelliteInfoPrivate *QGeoSatelliteInfoPrivate::clone() const
+{
+ return new QGeoSatelliteInfoPrivate(*this);
+}
+
+bool QGeoSatelliteInfoPrivate::operator==(const QGeoSatelliteInfoPrivate &other) const
+{
+ return signal == other.signal
+ && satId == other.satId
+ && system == other.system
+ && doubleAttribs == other.doubleAttribs;
+}
+
+QGeoSatelliteInfoPrivate *QGeoSatelliteInfoPrivate::get(const QGeoSatelliteInfo &info)
+{
+ return info.d;
+}
+
#endif
QT_END_NAMESPACE
diff --git a/src/positioning/qgeosatelliteinfo.h b/src/positioning/qgeosatelliteinfo.h
index e68d8d9f..28766257 100644
--- a/src/positioning/qgeosatelliteinfo.h
+++ b/src/positioning/qgeosatelliteinfo.h
@@ -63,6 +63,7 @@ public:
QGeoSatelliteInfo();
QGeoSatelliteInfo(const QGeoSatelliteInfo &other);
+ QGeoSatelliteInfo(QGeoSatelliteInfoPrivate &dd);
~QGeoSatelliteInfo();
QGeoSatelliteInfo &operator=(const QGeoSatelliteInfo &other);
@@ -96,6 +97,7 @@ private:
friend Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &stream, QGeoSatelliteInfo &info);
#endif
QGeoSatelliteInfoPrivate *d;
+ friend class QGeoSatelliteInfoPrivate;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/positioning/qgeosatelliteinfo_p.h b/src/positioning/qgeosatelliteinfo_p.h
new file mode 100644
index 00000000..6320bf2e
--- /dev/null
+++ b/src/positioning/qgeosatelliteinfo_p.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOSATELLITEINFO_P_H
+#define QGEOSATELLITEINFO_P_H
+
+#include <QtPositioning/private/qpositioningglobal_p.h>
+#include <QtPositioning/qgeosatelliteinfo.h>
+#include <QHash>
+
+QT_BEGIN_NAMESPACE
+
+class Q_POSITIONING_PRIVATE_EXPORT QGeoSatelliteInfoPrivate
+{
+public:
+ QGeoSatelliteInfoPrivate();
+ QGeoSatelliteInfoPrivate(const QGeoSatelliteInfoPrivate &other);
+ virtual ~QGeoSatelliteInfoPrivate();
+ virtual QGeoSatelliteInfoPrivate *clone() const;
+ virtual bool operator==(const QGeoSatelliteInfoPrivate &other) const;
+ static QGeoSatelliteInfoPrivate *get(const QGeoSatelliteInfo &info);
+
+ int signal;
+ int satId;
+ QGeoSatelliteInfo::SatelliteSystem system;
+ QHash<int, qreal> doubleAttribs;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOSATELLITEINFO_P_H
diff --git a/src/positioning/qgeosatelliteinfosource.cpp b/src/positioning/qgeosatelliteinfosource.cpp
index c55c36d3..6796b921 100644
--- a/src/positioning/qgeosatelliteinfosource.cpp
+++ b/src/positioning/qgeosatelliteinfosource.cpp
@@ -37,6 +37,7 @@
**
****************************************************************************/
#include <qgeosatelliteinfosource.h>
+#include <qgeosatelliteinfosource_p.h>
#include "qgeopositioninfosourcefactory.h"
#include "qgeopositioninfosource_p.h"
#include <QPluginLoader>
@@ -84,16 +85,20 @@ QT_BEGIN_NAMESPACE
update intervals, as returned by minimumUpdateInterval().
*/
-class QGeoSatelliteInfoSourcePrivate
-{
-public:
- int interval;
- QString providerName;
-};
-
/*!
Creates a satellite source with the specified \a parent.
*/
+
+QGeoSatelliteInfoSourcePrivate::~QGeoSatelliteInfoSourcePrivate()
+{
+
+}
+
+QGeoSatelliteInfoSourcePrivate *QGeoSatelliteInfoSourcePrivate::get(QGeoSatelliteInfoSource &source)
+{
+ return source.d;
+}
+
QGeoSatelliteInfoSource::QGeoSatelliteInfoSource(QObject *parent)
: QObject(parent),
d(new QGeoSatelliteInfoSourcePrivate)
@@ -101,6 +106,13 @@ QGeoSatelliteInfoSource::QGeoSatelliteInfoSource(QObject *parent)
d->interval = 0;
}
+QGeoSatelliteInfoSource::QGeoSatelliteInfoSource(QGeoSatelliteInfoSourcePrivate &dd, QObject *parent)
+: QObject(parent),
+ d(&dd)
+{
+
+}
+
/*!
Destroys the satellite source.
*/
@@ -153,7 +165,21 @@ int QGeoSatelliteInfoSource::updateInterval() const
return d->interval;
}
-
+static QGeoSatelliteInfoSource* createSource_real(const QJsonObject &meta, const QVariantMap &parameters, QObject *parent)
+{
+ QGeoPositionInfoSourcePrivate d;
+ d.metaData = meta;
+ d.loadPlugin();
+ QGeoSatelliteInfoSource *s = nullptr;
+ if (!parameters.isEmpty() && d.factoryV2)
+ s = d.factoryV2->satelliteInfoSourceWithParameters(parent, parameters);
+ else if (d.factory)
+ s = d.factory->satelliteInfoSource(parent);
+ if (s)
+ QGeoSatelliteInfoSourcePrivate::get(*s)->providerName = d.metaData.value(QStringLiteral("Provider")).toString();
+
+ return s;
+}
/*!
Creates and returns a source with the specified \a parent that reads
@@ -165,6 +191,34 @@ int QGeoSatelliteInfoSource::updateInterval() const
*/
QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(QObject *parent)
{
+ return createDefaultSource(QVariantMap(), parent);
+}
+
+/*!
+ Creates and returns a source with the given \a parent,
+ by loading the plugin named \a sourceName.
+
+ Returns 0 if the plugin cannot be found.
+*/
+QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createSource(const QString &sourceName, QObject *parent)
+{
+ return createSource(sourceName, QVariantMap(), parent);
+}
+
+/*!
+ Creates and returns a satellite source with the given \a parent that
+ reads from the system's default sources of satellite data, or the plugin
+ with the highest available priority.
+
+ Returns nullptr if the system has no default satellite source, no valid plugins
+ could be found or the user does not have the permission to access the satellite information.
+
+ This method passes \a parameters to the factory to configure the source.
+
+ \since Qt 5.14
+*/
+QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(const QVariantMap &parameters, QObject *parent)
+{
QList<QJsonObject> plugins = QGeoPositionInfoSourcePrivate::pluginsSorted();
foreach (const QJsonObject &obj, plugins) {
if (obj.value(QStringLiteral("Satellite")).isBool()
@@ -176,43 +230,29 @@ QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createDefaultSource(QObject *p
if (inTest)
continue;
}
- QGeoPositionInfoSourcePrivate d;
- d.metaData = obj;
- d.loadPlugin();
- QGeoSatelliteInfoSource *s = 0;
- if (d.factory)
- s = d.factory->satelliteInfoSource(parent);
- if (s)
- s->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString();
- return s;
+ return createSource_real(obj, parameters, parent);
}
}
- return 0;
+ return nullptr;
}
/*!
- Creates and returns a source with the given \a parent,
+ Creates and returns a satellite source with the given \a parent,
by loading the plugin named \a sourceName.
- Returns 0 if the plugin cannot be found.
+ Returns nullptr if the plugin cannot be found.
+
+ This method passes \a parameters to the factory to configure the source.
+
+ \since Qt 5.14
*/
-QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createSource(const QString &sourceName, QObject *parent)
+QGeoSatelliteInfoSource *QGeoSatelliteInfoSource::createSource(const QString &sourceName, const QVariantMap &parameters, QObject *parent)
{
QHash<QString, QJsonObject> plugins = QGeoPositionInfoSourcePrivate::plugins();
- if (plugins.contains(sourceName)) {
- QGeoPositionInfoSourcePrivate d;
- d.metaData = plugins.value(sourceName);
- d.loadPlugin();
- QGeoSatelliteInfoSource *src = 0;
- if (d.factory)
- src = d.factory->satelliteInfoSource(parent);
- if (src)
- src->d->providerName = d.metaData.value(QStringLiteral("Provider")).toString();
- return src;
- }
-
- return 0;
+ if (plugins.contains(sourceName))
+ return createSource_real(plugins.value(sourceName), parameters, parent);
+ return nullptr;
}
/*!
diff --git a/src/positioning/qgeosatelliteinfosource.h b/src/positioning/qgeosatelliteinfosource.h
index 391eefcf..4f073864 100644
--- a/src/positioning/qgeosatelliteinfosource.h
+++ b/src/positioning/qgeosatelliteinfosource.h
@@ -67,6 +67,8 @@ public:
static QGeoSatelliteInfoSource *createDefaultSource(QObject *parent);
static QGeoSatelliteInfoSource *createSource(const QString &sourceName, QObject *parent);
+ static QGeoSatelliteInfoSource *createDefaultSource(const QVariantMap &parameters, QObject *parent);
+ static QGeoSatelliteInfoSource *createSource(const QString &sourceName, const QVariantMap &parameters, QObject *parent);
static QStringList availableSources();
QString sourceName() const;
@@ -88,9 +90,13 @@ Q_SIGNALS:
void requestTimeout();
void error(QGeoSatelliteInfoSource::Error);
+protected:
+ QGeoSatelliteInfoSource(QGeoSatelliteInfoSourcePrivate &dd, QObject *parent);
+
private:
Q_DISABLE_COPY(QGeoSatelliteInfoSource)
QGeoSatelliteInfoSourcePrivate *d;
+ friend class QGeoSatelliteInfoSourcePrivate;
};
QT_END_NAMESPACE
diff --git a/src/positioning/qgeosatelliteinfosource_p.h b/src/positioning/qgeosatelliteinfosource_p.h
new file mode 100644
index 00000000..58001b21
--- /dev/null
+++ b/src/positioning/qgeosatelliteinfosource_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtPositioning module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOSATELLITEINFOSOURCE_P_H
+#define QGEOSATELLITEINFOSOURCE_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 <QtPositioning/private/qpositioningglobal_p.h>
+#include <QString>
+
+QT_BEGIN_NAMESPACE
+class QGeoSatelliteInfoSource;
+class Q_POSITIONING_PRIVATE_EXPORT QGeoSatelliteInfoSourcePrivate
+{
+public:
+ virtual ~QGeoSatelliteInfoSourcePrivate();
+ static QGeoSatelliteInfoSourcePrivate *get(QGeoSatelliteInfoSource &source);
+ int interval;
+ QString providerName;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOSATELLITEINFOSOURCE_P_H
diff --git a/src/positioning/qlocationutils.cpp b/src/positioning/qlocationutils.cpp
index f5062eb6..fec8ccba 100644
--- a/src/positioning/qlocationutils.cpp
+++ b/src/positioning/qlocationutils.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qlocationutils_p.h"
#include "qgeopositioninfo.h"
+#include "qgeosatelliteinfo.h"
#include <QTime>
#include <QList>
@@ -124,6 +125,25 @@ static void qlocationutils_readGsa(const char *data, int size, QGeoPositionInfo
}
}
+static void qlocationutils_readGsa(const char *data,
+ int size,
+ QList<int> &pnrsInUse)
+{
+ QList<QByteArray> parts = QByteArray::fromRawData(data, size).split(',');
+ pnrsInUse.clear();
+ if (parts.count() <= 2)
+ return;
+ bool ok;
+ for (int i = 3; i <= qMin(14, parts.size()); ++i) {
+ const QByteArray &pnrString = parts.at(i);
+ if (pnrString.isEmpty())
+ continue;
+ int pnr = pnrString.toInt(&ok);
+ if (ok)
+ pnrsInUse.append(pnr);
+ }
+}
+
static void qlocationutils_readGll(const char *data, int size, QGeoPositionInfo *info, bool *hasFix)
{
QByteArray sentence(data, size);
@@ -269,6 +289,9 @@ QLocationUtils::NmeaSentence QLocationUtils::getNmeaSentenceType(const char *dat
if (data[3] == 'G' && data[4] == 'S' && data[5] == 'A')
return NmeaSentenceGSA;
+ if (data[3] == 'G' && data[4] == 'S' && data[5] == 'V')
+ return NmeaSentenceGSV;
+
if (data[3] == 'G' && data[4] == 'L' && data[5] == 'L')
return NmeaSentenceGLL;
@@ -329,6 +352,85 @@ bool QLocationUtils::getPosInfoFromNmea(const char *data, int size, QGeoPosition
}
}
+QLocationUtils::GSVParseStatus QLocationUtils::getSatInfoFromNmea(const char *data, int size, QList<QGeoSatelliteInfo> &infos)
+{
+ if (!data || !size)
+ return GSVNotParsed;
+
+ NmeaSentence nmeaType = getNmeaSentenceType(data, size);
+ if (nmeaType != NmeaSentenceGSV)
+ return GSVNotParsed;
+
+ QList<QByteArray> parts = QByteArray::fromRawData(data, size).split(',');
+
+ if (parts.count() <= 3) {
+ infos.clear();
+ return GSVFullyParsed; // Malformed sentence.
+ }
+ bool ok;
+ const int totalSentences = parts.at(1).toInt(&ok);
+ if (!ok) {
+ infos.clear();
+ return GSVFullyParsed; // Malformed sentence.
+ }
+
+ const int sentence = parts.at(2).toInt(&ok);
+ if (!ok) {
+ infos.clear();
+ return GSVFullyParsed; // Malformed sentence.
+ }
+
+ const int totalSats = parts.at(3).toInt(&ok);
+ if (!ok) {
+ infos.clear();
+ return GSVFullyParsed; // Malformed sentence.
+ }
+
+ if (sentence == 1)
+ infos.clear();
+
+ const int numSatInSentence = qMin(sentence * 4, totalSats) - (sentence - 1) * 4;
+
+ int field = 4;
+ for (int i = 0; i < numSatInSentence; ++i) {
+ QGeoSatelliteInfo info;
+ const int prn = parts.at(field++).toInt(&ok);
+ info.setSatelliteIdentifier((ok) ? prn : 0);
+ const int elevation = parts.at(field++).toInt(&ok);
+ info.setAttribute(QGeoSatelliteInfo::Elevation, (ok) ? elevation : 0);
+ const int azimuth = parts.at(field++).toInt(&ok);
+ info.setAttribute(QGeoSatelliteInfo::Azimuth, (ok) ? azimuth : 0);
+ const int snr = parts.at(field++).toInt(&ok);
+ info.setSignalStrength((ok) ? snr : -1);
+ infos.append(info);
+ }
+
+ if (sentence == totalSentences)
+ return GSVFullyParsed;
+ return GSVPartiallyParsed;
+}
+
+bool QLocationUtils::getSatInUseFromNmea(const char *data, int size, QList<int> &pnrsInUse)
+{
+ pnrsInUse.clear();
+ if (!data || !size)
+ return false;
+
+ NmeaSentence nmeaType = getNmeaSentenceType(data, size);
+ if (nmeaType != NmeaSentenceGSA)
+ return false;
+
+ // Adjust size so that * and following characters are not parsed by the following functions.
+ for (int i = 0; i < size; ++i) {
+ if (data[i] == '*') {
+ size = i;
+ break;
+ }
+ }
+ qlocationutils_readGsa(data, size, pnrsInUse);
+ return true;
+}
+
bool QLocationUtils::hasValidNmeaChecksum(const char *data, int size)
{
int asteriskIndex = -1;
diff --git a/src/positioning/qlocationutils_p.h b/src/positioning/qlocationutils_p.h
index e3881f6f..e2d739e7 100644
--- a/src/positioning/qlocationutils_p.h
+++ b/src/positioning/qlocationutils_p.h
@@ -65,6 +65,7 @@ class QTime;
class QByteArray;
class QGeoPositionInfo;
+class QGeoSatelliteInfo;
class Q_POSITIONING_PRIVATE_EXPORT QLocationUtils
{
public:
@@ -94,7 +95,8 @@ public:
NmeaSentenceGLL, // Lat/Lon data
NmeaSentenceRMC, // Recommended minimum data for gps
NmeaSentenceVTG, // Vector track an Speed over the Ground
- NmeaSentenceZDA // Date and Time
+ NmeaSentenceZDA, // Date and Time
+ NmeaSentenceGSV // Per-Satellite Info
};
inline static bool isValidLat(double lat) {
@@ -282,6 +284,29 @@ public:
bool *hasFix = nullptr);
/*
+ Retruns a list of QGeoSatelliteInfo in the view.
+
+ Note: this function has to be called repeatedly until it returns true.
+ Reason being that GSV sentences can be split into multiple samples, so getting the full data
+ requires parsing multiple sentences.
+ */
+ enum GSVParseStatus {
+ GSVNotParsed,
+ GSVPartiallyParsed,
+ GSVFullyParsed
+ };
+ static GSVParseStatus getSatInfoFromNmea(const char *data,
+ int size,
+ QList<QGeoSatelliteInfo> &infos);
+
+ /*
+ Parses GSA for satellites in use.
+ */
+ static bool getSatInUseFromNmea(const char *data,
+ int size,
+ QList<int> &pnrsInUse);
+
+ /*
Returns true if the given NMEA sentence has a valid checksum.
*/
static bool hasValidNmeaChecksum(const char *data, int size);
diff --git a/src/positioningquick/qdeclarativepluginparameter.cpp b/src/positioningquick/qdeclarativepluginparameter.cpp
new file mode 100644
index 00000000..678e8a6a
--- /dev/null
+++ b/src/positioningquick/qdeclarativepluginparameter.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativepluginparameter_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype PluginParameter
+ \instantiates QDeclarativePluginParameter
+ \inqmlmodule QtPositioning
+ \ingroup qml-QtPositioning5-common
+ \since QtPositioning 5.14
+
+ \brief The PluginParameter type describes a parameter for a plugin, either
+ geoservice \l Plugin, or position plugin.
+
+ The PluginParameter object is used to provide a parameter of some kind
+ to a plugin. Typically these parameters contain details like an application
+ token for access to a service, or a proxy server to use for network access,
+ or the serial port to which a serial GPS receiver is connected.
+
+ To set such a parameter, declare a PluginParameter inside an element that accepts
+ plugin parameters as configuration objects, such as a \l Plugin object, or a
+ \l PositionSource object, and give it \l{name} and \l{value} properties. A list of valid
+ parameter names for each plugin is available from the
+ \l {Qt Location#Plugin References and Parameters}{plugin reference pages} for geoservice plugins,
+ and \l {Qt Positioning plugins#Default plugins} for position plugins.
+
+ \section2 Example Usage
+
+ The following example shows an instantiation of the \l {Qt Location HERE Plugin}{HERE} plugin
+ with a mapping API \e app_id and \e token pair specific to the application.
+
+ \code
+ Plugin {
+ name: "here"
+ PluginParameter { name: "here.app_id"; value: "EXAMPLE_API_ID" }
+ PluginParameter { name: "here.token"; value: "EXAMPLE_TOKEN_123" }
+ }
+ \endcode
+*/
+
+/*!
+ \qmlproperty string PluginParameter::name
+
+ This property holds the name of the plugin parameter as a single formatted string.
+ This property is a write-once property.
+*/
+
+/*!
+ \qmlproperty QVariant PluginParameter::value
+
+ This property holds the value of the plugin parameter which support different types of values (variant).
+ This property is a write-once property.
+*/
+
+QDeclarativePluginParameter::QDeclarativePluginParameter(QObject *parent)
+ : QObject(parent) {}
+
+QDeclarativePluginParameter::~QDeclarativePluginParameter() {}
+
+void QDeclarativePluginParameter::setName(const QString &name)
+{
+ if (!name_.isEmpty() || name.isEmpty())
+ return;
+
+ name_ = name;
+
+ emit nameChanged(name_);
+ if (value_.isValid())
+ emit initialized();
+}
+
+QString QDeclarativePluginParameter::name() const
+{
+ return name_;
+}
+
+void QDeclarativePluginParameter::setValue(const QVariant &value)
+{
+ if (value_.isValid() || !value.isValid() || value.isNull())
+ return;
+
+ value_ = value;
+
+ emit valueChanged(value_);
+ if (!name_.isEmpty())
+ emit initialized();
+}
+
+QVariant QDeclarativePluginParameter::value() const
+{
+ return value_;
+}
+
+bool QDeclarativePluginParameter::isInitialized() const
+{
+ return !name_.isEmpty() && value_.isValid();
+}
+
+QT_END_NAMESPACE
diff --git a/src/positioningquick/qdeclarativepluginparameter_p.h b/src/positioningquick/qdeclarativepluginparameter_p.h
new file mode 100644
index 00000000..f5035aae
--- /dev/null
+++ b/src/positioningquick/qdeclarativepluginparameter_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 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 QDECLARATIVEPLUGINPARAMETER_P_H
+#define QDECLARATIVEPLUGINPARAMETER_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 <QtPositioningQuick/private/qpositioningquickglobal_p.h>
+#include <QtQml/qqml.h>
+#include <QtCore/QMap>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtCore/QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class Q_POSITIONINGQUICK_PRIVATE_EXPORT QDeclarativePluginParameter : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ explicit QDeclarativePluginParameter(QObject *parent = 0);
+ ~QDeclarativePluginParameter();
+
+ void setName(const QString &name);
+ QString name() const;
+
+ void setValue(const QVariant &value);
+ QVariant value() const;
+
+ bool isInitialized() const;
+
+Q_SIGNALS:
+ void nameChanged(const QString &name);
+ void valueChanged(const QVariant &value);
+ void initialized();
+
+private:
+ QString name_;
+ QVariant value_;
+};
+
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativePluginParameter)
+
+#endif // QDECLARATIVEPLUGINPARAMETER_P_H
diff --git a/src/positioningquick/qdeclarativeposition_p.h b/src/positioningquick/qdeclarativeposition_p.h
index 141c37b7..c2a8d987 100644
--- a/src/positioningquick/qdeclarativeposition_p.h
+++ b/src/positioningquick/qdeclarativeposition_p.h
@@ -53,11 +53,11 @@
// We mean it.
//
+#include <QtPositioningQuick/private/qpositioningquickglobal_p.h>
+#include <QtPositioning/QGeoPositionInfo>
#include <QtCore/QObject>
#include <QtCore/QDateTime>
#include <QtQml/qqml.h>
-#include <QtPositioningQuick/private/qpositioningquickglobal_p.h>
-#include <QtPositioning/QGeoPositionInfo>
QT_BEGIN_NAMESPACE
diff --git a/src/positioningquick/qdeclarativepositionsource.cpp b/src/positioningquick/qdeclarativepositionsource.cpp
index c9fd2c8e..cfbcc9da 100644
--- a/src/positioningquick/qdeclarativepositionsource.cpp
+++ b/src/positioningquick/qdeclarativepositionsource.cpp
@@ -43,7 +43,8 @@
#include <QtCore/QCoreApplication>
#include <QtQml/qqmlinfo.h>
#include <QtQml/qqml.h>
-#include <qnmeapositioninfosource.h>
+#include <QtPositioning/qnmeapositioninfosource.h>
+#include <qdeclarativepluginparameter_p.h>
#include <QFile>
#include <QtNetwork/QTcpSocket>
#include <QTimer>
@@ -109,7 +110,7 @@ QT_BEGIN_NAMESPACE
a PositionSource in your application to retrieve local data for users
from a REST web service.
- \sa {QtPositioning::Position}, {QGeoPositionInfoSource}
+ \sa {QtPositioning::Position}, {QGeoPositionInfoSource}, {PluginParameter}
*/
@@ -164,7 +165,7 @@ QString QDeclarativePositionSource::name() const
if (m_positionSource)
return m_positionSource->sourceName();
else
- return QString();
+ return m_providerName;
}
void QDeclarativePositionSource::setName(const QString &newName)
@@ -172,15 +173,41 @@ void QDeclarativePositionSource::setName(const QString &newName)
if (m_positionSource && m_positionSource->sourceName() == newName)
return;
+ if (m_providerName == newName && m_providerName.isEmpty())
+ return; // previously attached to a default source, now requesting the same.
+
const QString previousName = name();
+ m_providerName = newName;
+
+ if (!m_componentComplete || !m_parametersInitialized) {
+ if (previousName != name())
+ emit nameChanged();
+ return;
+ }
+
+ tryAttach(newName, false);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePositionSource::tryAttach(const QString &newName, bool useFallback)
+{
+ const QString previousName = name();
+ const bool sourceExisted = m_positionSource;
+ m_providerName = newName;
+
int previousUpdateInterval = updateInterval();
PositioningMethods previousPositioningMethods = supportedPositioningMethods();
PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
- if (newName.isEmpty())
- setSource(QGeoPositionInfoSource::createDefaultSource(this));
- else
- setSource(QGeoPositionInfoSource::createSource(newName, this));
+ if (newName.isEmpty()) {
+ setSource(QGeoPositionInfoSource::createDefaultSource(parameterMap(), this));
+ } else {
+ setSource(QGeoPositionInfoSource::createSource(newName, parameterMap(), this));
+ if (!m_positionSource && useFallback)
+ setSource(QGeoPositionInfoSource::createDefaultSource(parameterMap(), this));
+ }
if (m_positionSource) {
connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
@@ -194,7 +221,12 @@ void QDeclarativePositionSource::setName(const QString &newName)
m_positionSource->setPreferredPositioningMethods(
static_cast<QGeoPositionInfoSource::PositioningMethods>(int(m_preferredPositioningMethods)));
- setPosition(m_positionSource->lastKnownPosition());
+ const QGeoPositionInfo &lastKnown = m_positionSource->lastKnownPosition();
+ if (lastKnown.isValid())
+ setPosition(lastKnown);
+ } else if (m_active) {
+ m_active = false;
+ emit activeChanged();
}
if (previousUpdateInterval != updateInterval())
@@ -208,9 +240,13 @@ void QDeclarativePositionSource::setName(const QString &newName)
emit validityChanged();
- if (m_active) {
- m_active = false;
- emit activeChanged();
+ if (m_active) { // implies m_positionSource
+ if (!sourceExisted) {
+ QTimer::singleShot(0, this, SLOT(start())); // delay ensures all properties have been set
+ } else {
+ m_active = false;
+ emit activeChanged();
+ }
}
if (previousName != name())
@@ -232,9 +268,6 @@ bool QDeclarativePositionSource::isValid() const
return (m_positionSource != 0);
}
-/*!
- \internal
-*/
void QDeclarativePositionSource::setNmeaSource(const QUrl &nmeaSource)
{
if (nmeaSource.scheme() == QLatin1String("socket")) {
@@ -411,6 +444,24 @@ void QDeclarativePositionSource::updateTimeoutReceived()
emit updateTimeout();
}
+/*!
+ \internal
+*/
+void QDeclarativePositionSource::onParameterInitialized()
+{
+ m_parametersInitialized = true;
+ for (QDeclarativePluginParameter *p: qAsConst(m_parameters)) {
+ if (!p->isInitialized()) {
+ m_parametersInitialized = false;
+ break;
+ }
+ }
+
+ // If here, componentComplete has been called.
+ if (m_parametersInitialized)
+ tryAttach(m_providerName);
+}
+
void QDeclarativePositionSource::setPosition(const QGeoPositionInfo &pi)
{
m_position.setPosition(pi);
@@ -431,6 +482,30 @@ void QDeclarativePositionSource::setSource(QGeoPositionInfoSource *source)
}
}
+bool QDeclarativePositionSource::parametersReady()
+{
+ for (const QDeclarativePluginParameter *p: qAsConst(m_parameters)) {
+ if (!p->isInitialized())
+ return false;
+ }
+ return true;
+}
+
+/*!
+ \internal
+*/
+QVariantMap QDeclarativePositionSource::parameterMap() const
+{
+ QVariantMap map;
+
+ for (int i = 0; i < m_parameters.size(); ++i) {
+ QDeclarativePluginParameter *parameter = m_parameters.at(i);
+ map.insert(parameter->name(), parameter->value());
+ }
+
+ return map;
+}
+
/*!
\internal
*/
@@ -717,47 +792,111 @@ QGeoPositionInfoSource *QDeclarativePositionSource::positionSource() const
return m_positionSource;
}
-void QDeclarativePositionSource::componentComplete()
+/*!
+ \qmlproperty list<PluginParameter> PositionSource::parameters
+ \default
+
+ This property holds the list of plugin parameters.
+
+ \since QtPositioning 5.14
+*/
+QQmlListProperty<QDeclarativePluginParameter> QDeclarativePositionSource::parameters()
{
- if (!m_positionSource) {
- int previousUpdateInterval = updateInterval();
- PositioningMethods previousPositioningMethods = supportedPositioningMethods();
- PositioningMethods previousPreferredPositioningMethods = preferredPositioningMethods();
+ return QQmlListProperty<QDeclarativePluginParameter>(this,
+ 0,
+ parameter_append,
+ parameter_count,
+ parameter_at,
+ parameter_clear);
+}
- setSource(QGeoPositionInfoSource::createDefaultSource(this));
- if (m_positionSource) {
- connect(m_positionSource, SIGNAL(positionUpdated(QGeoPositionInfo)),
- this, SLOT(positionUpdateReceived(QGeoPositionInfo)));
- connect(m_positionSource, SIGNAL(error(QGeoPositionInfoSource::Error)),
- this, SLOT(sourceErrorReceived(QGeoPositionInfoSource::Error)));
- connect(m_positionSource, SIGNAL(updateTimeout()),
- this, SLOT(updateTimeoutReceived()));
+/*!
+ \internal
+*/
+void QDeclarativePositionSource::parameter_append(QQmlListProperty<QDeclarativePluginParameter> *prop, QDeclarativePluginParameter *parameter)
+{
+ QDeclarativePositionSource *p = static_cast<QDeclarativePositionSource *>(prop->object);
+ p->m_parameters.append(parameter);
+}
- m_positionSource->setUpdateInterval(m_updateInterval);
- m_positionSource->setPreferredPositioningMethods(
- static_cast<QGeoPositionInfoSource::PositioningMethods>(int(m_preferredPositioningMethods)));
+/*!
+ \internal
+*/
+int QDeclarativePositionSource::parameter_count(QQmlListProperty<QDeclarativePluginParameter> *prop)
+{
+ return static_cast<QDeclarativePositionSource *>(prop->object)->m_parameters.count();
+}
- setPosition(m_positionSource->lastKnownPosition());
+/*!
+ \internal
+*/
+QDeclarativePluginParameter *QDeclarativePositionSource::parameter_at(QQmlListProperty<QDeclarativePluginParameter> *prop, int index)
+{
+ return static_cast<QDeclarativePositionSource *>(prop->object)->m_parameters[index];
+}
- if (m_active)
- QTimer::singleShot(0, this, SLOT(start())); // delay ensures all properties have been set
- } else if (m_active) {
- m_active = false;
- emit activeChanged();
+/*!
+ \internal
+*/
+void QDeclarativePositionSource::parameter_clear(QQmlListProperty<QDeclarativePluginParameter> *prop)
+{
+ QDeclarativePositionSource *p = static_cast<QDeclarativePositionSource *>(prop->object);
+ p->m_parameters.clear();
+}
+
+
+void QDeclarativePositionSource::componentComplete()
+{
+ m_componentComplete = true;
+ m_parametersInitialized = true;
+ for (QDeclarativePluginParameter *p: qAsConst(m_parameters)) {
+ if (!p->isInitialized()) {
+ m_parametersInitialized = false;
+ connect(p, &QDeclarativePluginParameter::initialized,
+ this, &QDeclarativePositionSource::onParameterInitialized);
}
+ }
- if (previousUpdateInterval != updateInterval())
- emit updateIntervalChanged();
+ if (m_parametersInitialized)
+ tryAttach(m_providerName);
+}
- if (previousPreferredPositioningMethods != preferredPositioningMethods())
- emit preferredPositioningMethodsChanged();
+/*!
+ \qmlmethod bool QtLocation::PositionSource::setBackendProperty(string name, Variant value)
- if (previousPositioningMethods != supportedPositioningMethods())
- emit supportedPositioningMethodsChanged();
+ Sets the backend-specific property named \a name to \a value.
+ Returns true on success, false otherwise, including if called on an uninitialized PositionSource.
+ Supported backend-specific properties are listed and described in
+ \l {Qt Positioning plugins#Default plugins}.
- emit validityChanged();
- emit nameChanged();
- }
+ \since Qt Positioning 5.14
+
+ \sa backendProperty, QGeoPositionInfoSource::setBackendProperty
+*/
+bool QDeclarativePositionSource::setBackendProperty(const QString &name, QVariant value)
+{
+ if (m_positionSource)
+ return m_positionSource->setBackendProperty(name, value);
+ return false;
+}
+
+/*!
+ \qmlmethod Variant QtLocation::PositionSource::backendProperty(string name)
+
+ Returns the value of the backend-specific property named \a name, if present.
+ Otherwise, including if called on an uninitialized PositionSource, the return value will be invalid.
+ Supported backend-specific properties are listed and described in
+ \l {Qt Positioning plugins#Default plugins}.
+
+ \since Qt Positioning 5.14
+
+ \sa backendProperty, QGeoPositionInfoSource::setBackendProperty
+*/
+QVariant QDeclarativePositionSource::backendProperty(const QString &name) const
+{
+ if (m_positionSource)
+ return m_positionSource->backendProperty(name);
+ return QVariant();
}
/*!
diff --git a/src/positioningquick/qdeclarativepositionsource_p.h b/src/positioningquick/qdeclarativepositionsource_p.h
index 39bcd899..dff0006c 100644
--- a/src/positioningquick/qdeclarativepositionsource_p.h
+++ b/src/positioningquick/qdeclarativepositionsource_p.h
@@ -51,13 +51,13 @@
// We mean it.
//
-#include "qdeclarativeposition_p.h"
-
+#include <QtPositioningQuick/private/qpositioningquickglobal_p.h>
+#include <QtPositioningQuick/private/qdeclarativeposition_p.h>
#include <QtCore/QObject>
#include <QtNetwork/QAbstractSocket>
#include <QtQml/QQmlParserStatus>
-#include <QtPositioningQuick/private/qpositioningquickglobal_p.h>
-#include <QtPositioning/QGeoPositionInfoSource>
+#include <QtPositioning/qgeopositioninfosource.h>
+#include <QtPositioningQuick/private/qdeclarativepluginparameter_p.h>
QT_BEGIN_NAMESPACE
@@ -77,8 +77,10 @@ class Q_POSITIONINGQUICK_PRIVATE_EXPORT QDeclarativePositionSource : public QObj
Q_PROPERTY(PositioningMethods preferredPositioningMethods READ preferredPositioningMethods WRITE setPreferredPositioningMethods NOTIFY preferredPositioningMethodsChanged)
Q_PROPERTY(SourceError sourceError READ sourceError NOTIFY sourceErrorChanged)
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QQmlListProperty<QDeclarativePluginParameter> parameters READ parameters REVISION 14)
Q_ENUMS(PositioningMethod)
+ Q_CLASSINFO("DefaultProperty", "parameters")
Q_INTERFACES(QQmlParserStatus)
public:
@@ -122,11 +124,16 @@ public:
PositioningMethods preferredPositioningMethods() const;
SourceError sourceError() const;
QGeoPositionInfoSource *positionSource() const;
+ QQmlListProperty<QDeclarativePluginParameter> parameters();
+ QVariantMap parameterMap() const;
// Virtuals from QQmlParserStatus
void classBegin() { }
void componentComplete();
+ Q_INVOKABLE bool setBackendProperty(const QString &name, QVariant value);
+ Q_INVOKABLE QVariant backendProperty(const QString &name) const;
+
public Q_SLOTS:
void update(); // TODO Qt 6 change to void update(int)
void start();
@@ -150,10 +157,18 @@ private Q_SLOTS:
void socketConnected();
void socketError(QAbstractSocket::SocketError error);
void updateTimeoutReceived();
+ void onParameterInitialized();
private:
void setPosition(const QGeoPositionInfo &pi);
void setSource(QGeoPositionInfoSource *source);
+ bool parametersReady();
+ void tryAttach(const QString &name, bool useFallback = true);
+
+ static void parameter_append(QQmlListProperty<QDeclarativePluginParameter> *prop, QDeclarativePluginParameter *mapObject);
+ static int parameter_count(QQmlListProperty<QDeclarativePluginParameter> *prop);
+ static QDeclarativePluginParameter *parameter_at(QQmlListProperty<QDeclarativePluginParameter> *prop, int index);
+ static void parameter_clear(QQmlListProperty<QDeclarativePluginParameter> *prop);
QGeoPositionInfoSource *m_positionSource;
QDeclarativePosition m_position;
@@ -162,10 +177,14 @@ private:
QTcpSocket *m_nmeaSocket;
QString m_nmeaFileName;
QUrl m_nmeaSource;
+ QString m_providerName;
bool m_active;
bool m_singleUpdate;
int m_updateInterval;
SourceError m_sourceError;
+ QList<QDeclarativePluginParameter *> m_parameters;
+ bool m_componentComplete = false;
+ bool m_parametersInitialized = false;
};
QT_END_NAMESPACE
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 745e264b..05559d12 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -86,6 +86,7 @@ SUBDIRS += \
!android: SUBDIRS += \
positionplugin \
+ positionpluginV1 \
positionplugintest \
qgeoareamonitor \
qgeopositioninfosource \
diff --git a/tests/auto/declarative_core/tst_plugin.qml b/tests/auto/declarative_core/tst_plugin.qml
index 7b880f1d..23c1ff9f 100644
--- a/tests/auto/declarative_core/tst_plugin.qml
+++ b/tests/auto/declarative_core/tst_plugin.qml
@@ -54,6 +54,7 @@ Item {
mapping: Plugin.OfflineMappingFeature;
geocoding: Plugin.OfflineGeocodingFeature;
places: Plugin.AnyPlacesFeatures;
+ navigation: Plugin.AnyNavigationFeatures;
}
}
@@ -120,6 +121,7 @@ Item {
verify(requiredPlugin.supportsMapping(requiredPlugin.required.mapping))
verify(requiredPlugin.supportsGeocoding(requiredPlugin.required.geocoding))
verify(requiredPlugin.supportsPlaces(requiredPlugin.required.places))
+ verify(requiredPlugin.supportsNavigation(requiredPlugin.required.navigation))
}
function test_placesFeatures() {
diff --git a/tests/auto/declarative_core/tst_positionsource.qml b/tests/auto/declarative_core/tst_positionsource.qml
index a663f3ab..7b787a0c 100644
--- a/tests/auto/declarative_core/tst_positionsource.qml
+++ b/tests/auto/declarative_core/tst_positionsource.qml
@@ -28,7 +28,7 @@
import QtQuick 2.0
import QtTest 1.0
-import QtPositioning 5.2
+import QtPositioning 5.14
TestCase {
id: testCase
@@ -106,6 +106,26 @@ TestCase {
SignalSpy { id: directionValidSpy; target: testingSource.position; signalName: "directionValidChanged" }
SignalSpy { id: directionSpy; target: testingSource.position; signalName: "directionChanged" }
+ PositionSource {
+ id: testingSourceWParams
+ name: "test.source"
+ updateInterval: 1000
+ PluginParameter {
+ id: altitudeParameter
+ name: "test.source.altitude"
+ value: 42.42
+ }
+ }
+
+ SignalSpy { id: updateSpyWParams; target: testingSourceWParams; signalName: "positionChanged" }
+ SignalSpy { id: directionValidSpyWParams; target: testingSourceWParams.position; signalName: "directionValidChanged" }
+ SignalSpy { id: directionSpyWParams; target: testingSourceWParams.position; signalName: "directionChanged" }
+
+ PositionSource { id: testingSourceV1; name: "test.source.v1"; updateInterval: 1000 }
+ SignalSpy { id: updateSpyV1; target: testingSourceV1; signalName: "positionChanged" }
+ SignalSpy { id: directionValidSpyV1; target: testingSourceV1.position; signalName: "directionValidChanged" }
+ SignalSpy { id: directionSpyV1; target: testingSourceV1.position; signalName: "directionChanged" }
+
function test_updateInterval() {
testingSource.updateInterval = 1000;
compare(testingSource.updateInterval, 1000);
@@ -125,40 +145,83 @@ TestCase {
}
function test_updates() {
- updateSpy.clear();
-
- compare(directionValidSpy.count, 0)
- compare(directionSpy.count, 0)
-
- testingSource.active = true;
-
- tryCompare(updateSpy, "count", 1, 1500);
- compare(testingSource.position.coordinate.longitude, 0.1);
- compare(testingSource.position.coordinate.latitude, 0.1);
- compare(directionValidSpy.count, 1)
- compare(directionSpy.count, 1)
- fuzzyCompare(testingSource.position.direction, 45, 0.1)
- verify(!testingSource.position.speedValid)
- verify(isNaN(testingSource.position.speed))
-
- tryCompare(updateSpy, "count", 2, 1500);
- compare(testingSource.position.coordinate.longitude, 0.2);
- compare(testingSource.position.coordinate.latitude, 0.2);
- compare(directionValidSpy.count, 1)
- compare(directionSpy.count, 2)
- fuzzyCompare(testingSource.position.direction, 45, 0.1)
- verify(testingSource.position.speedValid)
- verify(testingSource.position.speed > 10000)
-
- testingSource.active = false;
+ updateSpyV1.clear();
+
+ compare(directionValidSpyV1.count, 0)
+ compare(directionSpyV1.count, 0)
+
+ testingSourceV1.active = true;
+
+ tryCompare(updateSpyV1, "count", 1, 1500);
+ compare(testingSourceV1.position.coordinate.longitude, 0.1);
+ compare(testingSourceV1.position.coordinate.latitude, 0.1);
+ compare(directionValidSpyV1.count, 1)
+ compare(directionSpyV1.count, 1)
+ fuzzyCompare(testingSourceV1.position.direction, 45, 0.1)
+ verify(!testingSourceV1.position.speedValid)
+ verify(isNaN(testingSourceV1.position.speed))
+
+ tryCompare(updateSpyV1, "count", 2, 1500);
+ compare(testingSourceV1.position.coordinate.longitude, 0.2);
+ compare(testingSourceV1.position.coordinate.latitude, 0.2);
+ compare(directionValidSpyV1.count, 1)
+ compare(directionSpyV1.count, 2)
+ fuzzyCompare(testingSourceV1.position.direction, 45, 0.1)
+ verify(testingSourceV1.position.speedValid)
+ verify(testingSourceV1.position.speed > 10000)
+
+ testingSourceV1.active = false;
+ wait(2500);
+ compare(updateSpyV1.count, 2);
+ compare(testingSourceV1.position.coordinate.longitude, 0.2);
+ compare(testingSourceV1.position.coordinate.latitude, 0.2);
+ compare(directionValidSpyV1.count, 1)
+ compare(directionSpyV1.count, 2)
+ fuzzyCompare(testingSourceV1.position.direction, 45, 0.1)
+ verify(testingSourceV1.position.speedValid)
+ verify(testingSourceV1.position.speed > 10000)
+ }
+
+ function test_updates_w_params() {
+ updateSpyWParams.clear();
+
+ compare(directionValidSpyWParams.count, 0)
+ compare(directionSpyWParams.count, 0)
+ compare(testingSourceWParams.backendProperty("altitude"), altitudeParameter.value)
+ testingSourceWParams.active = true;
+
+ tryCompare(updateSpyWParams, "count", 1, 1500);
+ compare(testingSourceWParams.position.coordinate.longitude, 0.1);
+ compare(testingSourceWParams.position.coordinate.latitude, 0.1);
+ compare(testingSourceWParams.position.coordinate.altitude, altitudeParameter.value);
+ compare(directionValidSpyWParams.count, 1)
+ compare(directionSpyWParams.count, 1)
+ fuzzyCompare(testingSourceWParams.position.direction, 45, 0.1)
+ verify(!testingSourceWParams.position.speedValid)
+ verify(isNaN(testingSourceWParams.position.speed))
+ testingSourceWParams.setBackendProperty("altitude", 24.24)
+
+ tryCompare(updateSpyWParams, "count", 2, 1500);
+ compare(testingSourceWParams.position.coordinate.longitude, 0.2);
+ compare(testingSourceWParams.position.coordinate.latitude, 0.2);
+ compare(testingSourceWParams.position.coordinate.altitude, 24.24);
+ compare(directionValidSpyWParams.count, 1)
+ compare(directionSpyWParams.count, 2)
+ fuzzyCompare(testingSourceWParams.position.direction, 45, 0.1)
+ verify(testingSourceWParams.position.speedValid)
+ verify(testingSourceWParams.position.speed > 10000)
+ compare(testingSourceWParams.backendProperty("altitude"), 24.24)
+
+ testingSourceWParams.active = false;
wait(2500);
- compare(updateSpy.count, 2);
- compare(testingSource.position.coordinate.longitude, 0.2);
- compare(testingSource.position.coordinate.latitude, 0.2);
- compare(directionValidSpy.count, 1)
- compare(directionSpy.count, 2)
- fuzzyCompare(testingSource.position.direction, 45, 0.1)
- verify(testingSource.position.speedValid)
- verify(testingSource.position.speed > 10000)
+ compare(updateSpyWParams.count, 2);
+ compare(testingSourceWParams.position.coordinate.longitude, 0.2);
+ compare(testingSourceWParams.position.coordinate.latitude, 0.2);
+ compare(testingSourceWParams.position.coordinate.altitude, 24.24);
+ compare(directionValidSpyWParams.count, 1)
+ compare(directionSpyWParams.count, 2)
+ fuzzyCompare(testingSourceWParams.position.direction, 45, 0.1)
+ verify(testingSourceWParams.position.speedValid)
+ verify(testingSourceWParams.position.speed > 10000)
}
}
diff --git a/tests/auto/declarative_ui/BLACKLIST b/tests/auto/declarative_ui/BLACKLIST
deleted file mode 100644
index 4abe024c..00000000
--- a/tests/auto/declarative_ui/BLACKLIST
+++ /dev/null
@@ -1,20 +0,0 @@
-[MapFlick::test_disable_onFlickStarted_with_disabled]
-windows
-
-[MapFlick::test_flick_down]
-windows
-
-[MapFlick::test_flick_up]
-windows
-
-[MapFlick::test_flick_down_with_filtering]
-windows
-
-[MapFlick::test_disable_onFlickStarted_with_nogesture]
-windows
-
-[MapFlick::test_flick_diagonal]
-windows
-
-[MapFlick::test_flick_up_with_filtering]
-windows
diff --git a/tests/auto/geotestplugin/geotestplugin.json b/tests/auto/geotestplugin/geotestplugin.json
index 52721715..f6218b67 100644
--- a/tests/auto/geotestplugin/geotestplugin.json
+++ b/tests/auto/geotestplugin/geotestplugin.json
@@ -14,6 +14,7 @@
"OfflinePlacesFeature",
"SavePlaceFeature",
"SaveCategoryFeature",
- "SearchSuggestionsFeature"
+ "SearchSuggestionsFeature",
+ "OfflineNavigationFeature"
]
}
diff --git a/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h
index c606fdb0..ac195d69 100644
--- a/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h
+++ b/tests/auto/geotestplugin/qgeoserviceproviderplugin_test.h
@@ -34,10 +34,10 @@
QT_USE_NAMESPACE
-class QGeoServiceProviderFactoryTest: public QObject, public QGeoServiceProviderFactory
+class QGeoServiceProviderFactoryTest: public QObject, public QGeoServiceProviderFactoryV2
{
Q_OBJECT
- Q_INTERFACES(QGeoServiceProviderFactory)
+ Q_INTERFACES(QGeoServiceProviderFactoryV2)
Q_PLUGIN_METADATA(IID "org.qt-project.qt.geoservice.serviceproviderfactory/5.0"
FILE "geotestplugin.json")
diff --git a/tests/auto/geotestplugin/qplacemanagerengine_test.h b/tests/auto/geotestplugin/qplacemanagerengine_test.h
index 7245ccf1..0c707b65 100644
--- a/tests/auto/geotestplugin/qplacemanagerengine_test.h
+++ b/tests/auto/geotestplugin/qplacemanagerengine_test.h
@@ -474,9 +474,12 @@ public:
results.append(r);
}
} else if (!query.categories().isEmpty()) {
- QSet<QPlaceCategory> categories = query.categories().toSet();
- foreach (const QPlace &place, m_places) {
- if (place.categories().toSet().intersect(categories).isEmpty())
+ const auto &categoryList = query.categories();
+ const QSet<QPlaceCategory> categories(categoryList.cbegin(), categoryList.cend());
+ for (const QPlace &place : qAsConst(m_places)) {
+ const auto &placeCategoryList = place.categories();
+ const QSet<QPlaceCategory> placeCategories(placeCategoryList.cbegin(), placeCategoryList.cend());
+ if (!placeCategories.intersects(categories))
continue;
QPlaceResult r;
@@ -571,11 +574,8 @@ public:
m_categories.insert(category.categoryId(), category);
QStringList children = m_childCategories.value(parentId);
- QMutableHashIterator<QString, QStringList> i(m_childCategories);
- while (i.hasNext()) {
- i.next();
- i.value().removeAll(category.categoryId());
- }
+ for (QStringList &c : m_childCategories)
+ c.removeAll(category.categoryId());
if (!children.contains(category.categoryId())) {
children.append(category.categoryId());
@@ -611,11 +611,8 @@ public:
} else {
m_categories.remove(categoryId);
- QMutableHashIterator<QString, QStringList> i(m_childCategories);
- while (i.hasNext()) {
- i.next();
- i.value().removeAll(categoryId);
- }
+ for (auto &c : m_childCategories)
+ c.removeAll(categoryId);
}
QMetaObject::invokeMethod(reply, "emitFinished", Qt::QueuedConnection);
@@ -634,9 +631,7 @@ public:
QString parentCategoryId(const QString &categoryId) const override
{
- QHashIterator<QString, QStringList> i(m_childCategories);
- while (i.hasNext()) {
- i.next();
+ for (auto i = m_childCategories.cbegin(), end = m_childCategories.cend(); i != end; ++i) {
if (i.value().contains(categoryId))
return i.key();
}
diff --git a/tests/auto/nokia_services/places_semiauto/tst_places.cpp b/tests/auto/nokia_services/places_semiauto/tst_places.cpp
index 2f68ab44..c198c616 100644
--- a/tests/auto/nokia_services/places_semiauto/tst_places.cpp
+++ b/tests/auto/nokia_services/places_semiauto/tst_places.cpp
@@ -610,9 +610,7 @@ void tst_QPlaceManagerNokia::content()
QVERIFY(results.count() > 0);
- QMapIterator<int, QPlaceContent> iter(results);
- while (iter.hasNext()) {
- iter.next();
+ for (auto iter = results.cbegin(), end = results.cend(); iter != end; ++iter) {
switch (type) {
case (QPlaceContent::ImageType): {
QPlaceImage image = iter.value();
diff --git a/tests/auto/positionplugin/plugin.cpp b/tests/auto/positionplugin/plugin.cpp
index a15a89a5..9d5c7dd5 100644
--- a/tests/auto/positionplugin/plugin.cpp
+++ b/tests/auto/positionplugin/plugin.cpp
@@ -27,6 +27,7 @@
****************************************************************************/
#include <QtPositioning/qgeopositioninfosource.h>
+#include <QtPositioning/private/qgeopositioninfosource_p.h>
#include <QtPositioning/qgeopositioninfosourcefactory.h>
#include <QObject>
#include <QtPlugin>
@@ -39,7 +40,7 @@ class DummySource : public QGeoPositionInfoSource
Q_OBJECT
public:
- DummySource(QObject *parent=0);
+ DummySource(const QVariantMap &parameters, QObject *parent=0);
~DummySource();
void startUpdates();
@@ -65,13 +66,42 @@ private slots:
void doTimeout();
};
-DummySource::DummySource(QObject *parent) :
- QGeoPositionInfoSource(parent),
+class DummySourcePrivate : public QGeoPositionInfoSourcePrivate
+{
+public:
+ bool setBackendProperty(const QString &name, QVariant value) override
+ {
+ if (name == QStringLiteral("altitude")) {
+ m_altitude = value.toReal();
+ return true;
+ }
+ return false;
+ }
+ QVariant backendProperty(const QString &name) const override
+ {
+ if (name == QStringLiteral("altitude"))
+ return m_altitude;
+ return QVariant();
+ }
+
+ qreal m_altitude = 0.0;
+};
+
+DummySource::DummySource(const QVariantMap &parameters, QObject *parent) :
+ QGeoPositionInfoSource(*new DummySourcePrivate, parent),
timer(new QTimer(this)),
timeoutTimer(new QTimer(this)),
singleTimer(new QTimer(this)),
lastPosition(QGeoCoordinate(0,0), QDateTime::currentDateTime())
{
+ DummySourcePrivate *dd = static_cast<DummySourcePrivate *>(QGeoPositionInfoSourcePrivate::get(*this));
+ if (parameters.contains(QStringLiteral("test.source.altitude"))) {
+ const qreal alti = parameters.value(QStringLiteral("test.source.altitude")).toReal();
+ dd->m_altitude = alti;
+ QGeoCoordinate crd = lastPosition.coordinate();
+ crd.setAltitude(alti);
+ lastPosition.setCoordinate(crd);
+ }
timer->setInterval(1000);
connect(timer, SIGNAL(timeout()),
this, SLOT(updatePosition()));
@@ -151,13 +181,15 @@ DummySource::~DummySource()
void DummySource::updatePosition()
{
+ DummySourcePrivate *dd = static_cast<DummySourcePrivate *>(QGeoPositionInfoSourcePrivate::get(*this));
timeoutTimer->stop();
singleTimer->stop();
const QDateTime now = QDateTime::currentDateTime();
QGeoCoordinate coord(lastPosition.coordinate().latitude() + 0.1,
- lastPosition.coordinate().longitude() + 0.1);
+ lastPosition.coordinate().longitude() + 0.1,
+ dd->m_altitude);
QGeoPositionInfo info(coord, now);
info.setAttribute(QGeoPositionInfo::Direction, lastPosition.coordinate().azimuthTo(coord));
@@ -179,35 +211,55 @@ void DummySource::doTimeout()
}
-class QGeoPositionInfoSourceFactoryTest : public QObject, public QGeoPositionInfoSourceFactory
+class QGeoPositionInfoSourceFactoryTest : public QObject, public QGeoPositionInfoSourceFactoryV2
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0"
FILE "plugin.json")
- Q_INTERFACES(QGeoPositionInfoSourceFactory)
+ Q_INTERFACES(QGeoPositionInfoSourceFactoryV2)
public:
QGeoPositionInfoSource *positionInfoSource(QObject *parent);
QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
QGeoAreaMonitorSource *areaMonitor(QObject *parent);
+
+ QGeoPositionInfoSource *positionInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters);
+ QGeoSatelliteInfoSource *satelliteInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters);
+ QGeoAreaMonitorSource *areaMonitorWithParameters(QObject *parent, const QVariantMap &parameters);
};
QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryTest::positionInfoSource(QObject *parent)
{
- return new DummySource(parent);
+ return new DummySource(QVariantMap(), parent);
}
QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryTest::satelliteInfoSource(QObject *parent)
{
- Q_UNUSED(parent);
- // not implemented
- return 0;
+ return satelliteInfoSourceWithParameters(parent, QVariantMap());
}
QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryTest::areaMonitor(QObject* parent)
{
+ return areaMonitorWithParameters(parent, QVariantMap());
+}
+
+QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryTest::positionInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters)
+{
+ return new DummySource(parameters, parent);
+}
+
+QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryTest::satelliteInfoSourceWithParameters(QObject *parent, const QVariantMap &parameters)
+{
+ Q_UNUSED(parent);
+ Q_UNUSED(parameters)
+ return nullptr;
+}
+
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryTest::areaMonitorWithParameters(QObject *parent, const QVariantMap &parameters)
+{
Q_UNUSED(parent);
- return 0;
+ Q_UNUSED(parameters)
+ return nullptr;
}
#include "plugin.moc"
diff --git a/tests/auto/positionplugin/plugin.json b/tests/auto/positionplugin/plugin.json
index 68acaded..a38d2a5a 100644
--- a/tests/auto/positionplugin/plugin.json
+++ b/tests/auto/positionplugin/plugin.json
@@ -4,6 +4,6 @@
"Position": true,
"Satellite": false,
"Monitor": false,
- "Priority": 0,
+ "Priority": 1,
"Testable": true
}
diff --git a/tests/auto/positionplugin/positionplugin.pro b/tests/auto/positionplugin/positionplugin.pro
index dd04e7fb..84d08ac0 100644
--- a/tests/auto/positionplugin/positionplugin.pro
+++ b/tests/auto/positionplugin/positionplugin.pro
@@ -1,8 +1,8 @@
TARGET = qtposition_testplugin
-QT += positioning
+QT += positioning-private
PLUGIN_TYPE = position
-PLUGIN_CLASS_NAME = TestPositionPlugin
+PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryTest
PLUGIN_EXTENDS = -
load(qt_plugin)
diff --git a/tests/auto/positionpluginV1/plugin.cpp b/tests/auto/positionpluginV1/plugin.cpp
new file mode 100644
index 00000000..bf8b8234
--- /dev/null
+++ b/tests/auto/positionpluginV1/plugin.cpp
@@ -0,0 +1,212 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtPositioning/qgeopositioninfosource.h>
+#include <QtPositioning/qgeopositioninfosourcefactory.h>
+#include <QObject>
+#include <QtPlugin>
+#include <QTimer>
+
+QT_USE_NAMESPACE
+
+class DummySource : public QGeoPositionInfoSource
+{
+ Q_OBJECT
+
+public:
+ DummySource(QObject *parent = nullptr);
+ ~DummySource();
+
+ void startUpdates();
+ void stopUpdates();
+ void requestUpdate(int timeout=5000);
+
+ QGeoPositionInfo lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const;
+ PositioningMethods supportedPositioningMethods() const;
+
+ void setUpdateInterval(int msec);
+ int minimumUpdateInterval() const;
+ Error error() const;
+
+private:
+ QTimer *timer;
+ QTimer *timeoutTimer;
+ QTimer *singleTimer;
+ QGeoPositionInfo lastPosition;
+ QDateTime lastUpdateTime;
+
+private slots:
+ void updatePosition();
+ void doTimeout();
+};
+
+DummySource::DummySource(QObject *parent) :
+ QGeoPositionInfoSource(parent),
+ timer(new QTimer(this)),
+ timeoutTimer(new QTimer(this)),
+ singleTimer(new QTimer(this)),
+ lastPosition(QGeoCoordinate(0,0), QDateTime::currentDateTime())
+{
+ timer->setInterval(1000);
+ connect(timer, SIGNAL(timeout()),
+ this, SLOT(updatePosition()));
+ connect(singleTimer, SIGNAL(timeout()),
+ this, SLOT(updatePosition()));
+ connect(timeoutTimer, SIGNAL(timeout()),
+ this, SLOT(doTimeout()));
+}
+
+QGeoPositionInfoSource::Error DummySource::error() const
+{
+ return QGeoPositionInfoSource::NoError;
+}
+
+
+void DummySource::setUpdateInterval(int msec)
+{
+ if (msec == 0) {
+ timer->setInterval(1000);
+ } else if (msec < 1000) {
+ msec = 1000;
+ timer->setInterval(msec);
+ } else {
+ timer->setInterval(msec);
+ }
+
+ QGeoPositionInfoSource::setUpdateInterval(msec);
+}
+
+int DummySource::minimumUpdateInterval() const
+{
+ return 1000;
+}
+
+QGeoPositionInfo DummySource::lastKnownPosition(bool fromSatellitePositioningMethodsOnly) const
+{
+ Q_UNUSED(fromSatellitePositioningMethodsOnly);
+ return lastPosition;
+}
+
+QGeoPositionInfoSource::PositioningMethods DummySource::supportedPositioningMethods() const
+{
+ return QGeoPositionInfoSource::AllPositioningMethods;
+}
+
+void DummySource::startUpdates()
+{
+ timer->start();
+}
+
+void DummySource::stopUpdates()
+{
+ timer->stop();
+}
+
+void DummySource::requestUpdate(int timeout)
+{
+ if (timeout == 0)
+ timeout = 5000;
+ if (timeout < 0)
+ timeout = 0;
+
+ timeoutTimer->setInterval(timeout);
+ timeoutTimer->start();
+
+ if (timer->isActive()) {
+ timer->stop();
+ timer->start();
+ }
+
+ singleTimer->setInterval(1000);
+ singleTimer->start();
+}
+
+DummySource::~DummySource()
+{}
+
+void DummySource::updatePosition()
+{
+ timeoutTimer->stop();
+ singleTimer->stop();
+
+ const QDateTime now = QDateTime::currentDateTime();
+
+ QGeoCoordinate coord(lastPosition.coordinate().latitude() + 0.1,
+ lastPosition.coordinate().longitude() + 0.1);
+
+ QGeoPositionInfo info(coord, now);
+ info.setAttribute(QGeoPositionInfo::Direction, lastPosition.coordinate().azimuthTo(coord));
+ if (lastUpdateTime.isValid()) {
+ double speed = lastPosition.coordinate().distanceTo(coord) / lastUpdateTime.msecsTo(now);
+ info.setAttribute(QGeoPositionInfo::GroundSpeed, 1000 * speed);
+ }
+
+ lastUpdateTime = now;
+ lastPosition = info;
+ emit positionUpdated(info);
+}
+
+void DummySource::doTimeout()
+{
+ timeoutTimer->stop();
+ singleTimer->stop();
+ emit updateTimeout();
+}
+
+
+class QGeoPositionInfoSourceFactoryTestV1 : 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);
+ QGeoSatelliteInfoSource *satelliteInfoSource(QObject *parent);
+ QGeoAreaMonitorSource *areaMonitor(QObject *parent);
+};
+
+QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryTestV1::positionInfoSource(QObject *parent)
+{
+ return new DummySource(parent);
+}
+
+QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryTestV1::satelliteInfoSource(QObject *parent)
+{
+ Q_UNUSED(parent);
+ return nullptr;
+}
+
+QGeoAreaMonitorSource *QGeoPositionInfoSourceFactoryTestV1::areaMonitor(QObject* parent)
+{
+ Q_UNUSED(parent);
+ return nullptr;
+}
+
+#include "plugin.moc"
diff --git a/tests/auto/positionpluginV1/plugin.json b/tests/auto/positionpluginV1/plugin.json
new file mode 100644
index 00000000..9acf27e7
--- /dev/null
+++ b/tests/auto/positionpluginV1/plugin.json
@@ -0,0 +1,9 @@
+{
+ "Keys": ["test.source.v1"],
+ "Provider": "test.source.v1",
+ "Position": true,
+ "Satellite": false,
+ "Monitor": false,
+ "Priority": 0,
+ "Testable": true
+}
diff --git a/tests/auto/positionpluginV1/positionpluginV1.pro b/tests/auto/positionpluginV1/positionpluginV1.pro
new file mode 100644
index 00000000..925a7e29
--- /dev/null
+++ b/tests/auto/positionpluginV1/positionpluginV1.pro
@@ -0,0 +1,12 @@
+TARGET = qtposition_testpluginv1
+QT += positioning
+
+PLUGIN_TYPE = position
+PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryTestV1
+PLUGIN_EXTENDS = -
+load(qt_plugin)
+
+SOURCES += plugin.cpp
+
+OTHER_FILES += \
+ plugin.json
diff --git a/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp b/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp
index 5da6b4d4..c7189278 100644
--- a/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp
+++ b/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp
@@ -145,7 +145,7 @@ void tst_QGeoTiledMap::fetchTiles()
m_tilesCounter->m_tiles.clear();
m_map->setCameraData(camera);
waitForFetch(visibleCount);
- QSet<QGeoTileSpec> visible = m_tilesCounter->m_tiles;
+ const QSet<QGeoTileSpec> visible = m_tilesCounter->m_tiles;
m_map->clearData();
m_tilesCounter->m_tiles.clear();
m_map->prefetchData();
@@ -164,9 +164,8 @@ void tst_QGeoTiledMap::fetchTiles()
QVERIFY2(visibleCount == visible.size(), "visible count incorrect");
QVERIFY2(prefetchCount == prefetched.size(), "prefetch count incorrect");
- QSetIterator<QGeoTileSpec> i(visible);
- while (i.hasNext())
- QVERIFY2(prefetched.contains(i.next()),"visible tile missing from prefetched tiles");
+ for (const QGeoTileSpec &tile : visible)
+ QVERIFY2(prefetched.contains(tile),"visible tile missing from prefetched tiles");
//for zoomLevels wihtout fractions more tiles are fetched for current zoomlevel due to ViewExpansion
if (qCeil(zoomLevel) != zoomLevel && style == QGeoTiledMap::PrefetchNeighbourLayer && nearestNeighbourLayer < zoomLevel)
diff --git a/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp
index 37fe7abc..51f996fb 100644
--- a/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp
+++ b/tests/auto/qnmeapositioninfosource/tst_qnmeapositioninfosource.cpp
@@ -32,6 +32,8 @@
#include "tst_qnmeapositioninfosource.h"
+#include <QtCore/QDateTime>
+#include <QtCore/QElapsedTimer>
#include <QtCore/QtNumeric>
#ifdef Q_OS_WIN
@@ -264,7 +266,7 @@ void tst_QNmeaPositionInfoSource::startUpdates_withTimeout()
proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addMSecs(2200)).toLatin1());
proxy->feedBytes(QLocationTestUtils::createRmcSentence(dt.addSecs(9)).toLatin1());
- QTime t;
+ QElapsedTimer t;
t.start();
for (int j = 1; j < 4; ++j) {
diff --git a/tests/auto/utils/qlocationtestutils.cpp b/tests/auto/utils/qlocationtestutils.cpp
index d6e77855..df595daa 100644
--- a/tests/auto/utils/qlocationtestutils.cpp
+++ b/tests/auto/utils/qlocationtestutils.cpp
@@ -46,8 +46,7 @@ QString QLocationTestUtils::addNmeaChecksumAndBreaks(const QString &sentence)
int result = 0;
for (int i=1; i<sentence.length()-1; i++)
result ^= sentence[i].toLatin1();
- QString sum;
- sum.sprintf("%02x", result);
+ const QString sum = QString::asprintf("%02x", result);
return sentence + sum + "\r\n";
}