diff options
author | Alexandru Croitor <alexandru.croitor@qt.io> | 2019-07-25 11:01:35 +0200 |
---|---|---|
committer | Alexandru Croitor <alexandru.croitor@qt.io> | 2019-07-25 11:02:09 +0200 |
commit | cd84a8cac6a43cfeede4d098ed72c9bd3ce4f111 (patch) | |
tree | 05e10e315cc208aa83e6d34a262717e245330d5e /src | |
parent | 57d50ee43efd8e3c3e1c04f1aad3e0043e79096a (diff) | |
parent | f8694e1f3430b7851fc90e26c6d778a86219379a (diff) | |
download | qtlocation-cd84a8cac6a43cfeede4d098ed72c9bd3ce4f111.tar.gz |
Merge remote-tracking branch 'origin/dev' into wip/qt6
Change-Id: Ifb3e30bbad659239e28f4aa79e769e7b429fb9e4
Diffstat (limited to 'src')
20 files changed, 411 insertions, 70 deletions
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/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/declarativeplaces/qdeclarativesearchresultmodel.cpp b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp index 4cfd26dd..c620b9f7 100644 --- a/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp +++ b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp @@ -973,16 +973,15 @@ QList<QPlaceSearchResult> QDeclarativeSearchResultModel::resultsFromPages() cons void QDeclarativeSearchResultModel::removePageRow(int row) { - QMapIterator<int, QList<QPlaceSearchResult>> i(m_pages); + QMutableMapIterator<int, QList<QPlaceSearchResult>> i(m_pages); int scanned = 0; while (i.hasNext()) { i.next(); - QList<QPlaceSearchResult> page = i.value(); + 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/qtlocation.qdocconf b/src/location/doc/qtlocation.qdocconf index 0c43bfa7..0ffbe4d6 100644 --- a/src/location/doc/qtlocation.qdocconf +++ b/src/location/doc/qtlocation.qdocconf @@ -1,4 +1,5 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) +include($QT_INSTALL_DOCS/config/exampleurl-qtlocation.qdocconf) project = QtLocation description = Qt Location Reference Documentation diff --git a/src/location/labs/qdeclarativenavigator.cpp b/src/location/labs/qdeclarativenavigator.cpp index 89b5abef..ae273774 100644 --- a/src/location/labs/qdeclarativenavigator.cpp +++ b/src/location/labs/qdeclarativenavigator.cpp @@ -352,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 @@ -510,6 +516,8 @@ bool QDeclarativeNavigator::ensureEngine() &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; @@ -534,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(); @@ -704,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) @@ -720,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 3c168c70..24ff798f 100644 --- a/src/location/labs/qdeclarativenavigator_p.h +++ b/src/location/labs/qdeclarativenavigator_p.h @@ -149,6 +149,8 @@ public: NavigationError error() const; QString errorString() const; + Q_INVOKABLE void recalculateRoutes(); + signals: void navigatorReadyChanged(bool ready); void trackPositionSourceChanged(bool trackPositionSource); diff --git a/src/location/labs/qdeclarativenavigator_p_p.h b/src/location/labs/qdeclarativenavigator_p_p.h index 04b8b1ef..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; }; 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 9089316f..8d2c9a99 100644 --- a/src/location/maps/qnavigationmanagerengine_p.h +++ b/src/location/maps/qnavigationmanagerengine_p.h @@ -98,10 +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; @@ -120,6 +122,7 @@ signals: void nextManeuverIconChanged(); void progressInformationChanged(); void isOnRouteChanged(); + void alternativeRoutesChanged(); private: QScopedPointer<QAbstractNavigatorPrivate> d; diff --git a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp index 58092ea3..043f7682 100644 --- a/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp +++ b/src/plugins/position/serialnmea/qgeopositioninfosourcefactory_serialnmea.cpp @@ -49,18 +49,22 @@ Q_LOGGING_CATEGORY(lcSerial, "qt.positioning.serialnmea") class NmeaSource : public QNmeaPositionInfoSource { public: - NmeaSource(QObject *parent); + NmeaSource(QObject *parent, const QVariantMap ¶meters); bool isValid() const { return !m_port.isNull(); } private: QScopedPointer<QSerialPort> m_port; }; -NmeaSource::NmeaSource(QObject *parent) +NmeaSource::NmeaSource(QObject *parent, const QVariantMap ¶meters) : QNmeaPositionInfoSource(RealTimeMode, parent), m_port(new QSerialPort) { - 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"); if (requestedPort.isEmpty()) { const QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts(); qCDebug(lcSerial) << "Found" << ports.count() << "serial ports"; @@ -110,18 +114,35 @@ NmeaSource::NmeaSource(QObject *parent) 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) { + return satelliteInfoSourceWithParameters(parent, QVariantMap()); +} + +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactorySerialNmea::areaMonitor(QObject *parent) +{ + return areaMonitorWithParameters(parent, QVariantMap()); +} + +QGeoPositionInfoSource *QGeoPositionInfoSourceFactorySerialNmea::positionInfoSourceWithParameters(QObject *parent, const QVariantMap ¶meters) +{ + QScopedPointer<NmeaSource> src(new NmeaSource(parent, parameters)); + return src->isValid() ? src.take() : nullptr; +} + +QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactorySerialNmea::satelliteInfoSourceWithParameters(QObject *parent, const QVariantMap ¶meters) +{ Q_UNUSED(parent); + Q_UNUSED(parameters) return nullptr; } -QGeoAreaMonitorSource *QGeoPositionInfoSourceFactorySerialNmea::areaMonitor(QObject *parent) +QGeoAreaMonitorSource *QGeoPositionInfoSourceFactorySerialNmea::areaMonitorWithParameters(QObject *parent, const QVariantMap ¶meters) { 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 ¶meters); + QGeoSatelliteInfoSource *satelliteInfoSourceWithParameters(QObject *parent, const QVariantMap ¶meters); + QGeoAreaMonitorSource *areaMonitorWithParameters(QObject *parent, const QVariantMap ¶meters); }; #endif diff --git a/src/positioning/doc/qtpositioning.qdocconf b/src/positioning/doc/qtpositioning.qdocconf index 3f6438ef..41a06c49 100644 --- a/src/positioning/doc/qtpositioning.qdocconf +++ b/src/positioning/doc/qtpositioning.qdocconf @@ -1,4 +1,5 @@ include($QT_INSTALL_DOCS/global/qt-module-defaults.qdocconf) +include($QT_INSTALL_DOCS/config/exampleurl-qtlocation.qdocconf) project = QtPositioning description = Qt Positioning Reference Documentation diff --git a/src/positioning/qgeopositioninfosource.cpp b/src/positioning/qgeopositioninfosource.cpp index 29a0d019..69fcdef0 100644 --- a/src/positioning/qgeopositioninfosource.cpp +++ b/src/positioning/qgeopositioninfosource.cpp @@ -108,6 +108,11 @@ QGeoPositionInfoSourcePrivate *QGeoPositionInfoSourcePrivate::get(const QGeoPosi return source.d; } +QGeoPositionInfoSourcePrivate::~QGeoPositionInfoSourcePrivate() +{ + +} + void QGeoPositionInfoSourcePrivate::loadMeta() { metaData = plugins().value(providerName); @@ -128,6 +133,16 @@ void QGeoPositionInfoSourcePrivate::loadPlugin() 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) { static QHash<QString, QJsonObject> plugins; @@ -216,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. @@ -382,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 23b3ac46..eaf5e106 100644 --- a/src/positioning/qgeopositioninfosource.h +++ b/src/positioning/qgeopositioninfosource.h @@ -87,6 +87,9 @@ 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 ¶meters, QObject *parent); static QGeoPositionInfoSource *createSource(const QString &sourceName, QObject *parent); @@ -106,6 +109,9 @@ Q_SIGNALS: void error(QGeoPositionInfoSource::Error); void supportedPositioningMethodsChanged(); +protected: + QGeoPositionInfoSource(QGeoPositionInfoSourcePrivate &dd, QObject *parent); + private: Q_DISABLE_COPY(QGeoPositionInfoSource) QGeoPositionInfoSourcePrivate *d; diff --git a/src/positioning/qgeopositioninfosource_p.h b/src/positioning/qgeopositioninfosource_p.h index f5f85ec9..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,10 +61,11 @@ 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; @@ -74,6 +76,8 @@ public: 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/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 c6daaae5..dff0006c 100644 --- a/src/positioningquick/qdeclarativepositionsource_p.h +++ b/src/positioningquick/qdeclarativepositionsource_p.h @@ -56,7 +56,8 @@ #include <QtCore/QObject> #include <QtNetwork/QAbstractSocket> #include <QtQml/QQmlParserStatus> -#include <QtPositioning/QGeoPositionInfoSource> +#include <QtPositioning/qgeopositioninfosource.h> +#include <QtPositioningQuick/private/qdeclarativepluginparameter_p.h> QT_BEGIN_NAMESPACE @@ -76,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: @@ -121,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(); @@ -149,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; @@ -161,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 |