diff options
Diffstat (limited to 'src/location/labs')
31 files changed, 2056 insertions, 230 deletions
diff --git a/src/location/labs/qdeclarativenavigator.cpp b/src/location/labs/qdeclarativenavigator.cpp index 5b98f27f..eccfd082 100644 --- a/src/location/labs/qdeclarativenavigator.cpp +++ b/src/location/labs/qdeclarativenavigator.cpp @@ -37,6 +37,7 @@ #include <QtLocation/private/qdeclarativegeoroute_p.h> #include <QtLocation/private/qdeclarativegeoroutemodel_p.h> #include <QtLocation/private/qdeclarativegeoroutesegment_p.h> +#include <QtLocation/qgeoserviceprovider.h> #include <QtPositioningQuick/private/qdeclarativepositionsource_p.h> #include <QtQml/qqmlinfo.h> @@ -157,53 +158,27 @@ QT_BEGIN_NAMESPACE */ /*! - \qmlproperty Route Qt.labs.location::Navigator::currentRoute + \qmlproperty enumeration Qt.labs.location::Navigator::error - This read-only property holds the current route the navigator following. - This can be the same as \l route, or can be different, if the navigator - cannot follow the user-specified route. - For example if the position coming from \l positionSource is considerably - off route, the navigation engine might recalculate and start following a - new route. + This read-only property holds the latest error value of the geocoding request. - \sa Route -*/ - -/*! - \qmlproperty int Qt.labs.location::Navigator::currentSegment - - This read-only property holds the index of the current RouteSegment in the \l currentRoute. - - \sa RouteSegment -*/ - -/*! - \qmlsignal Qt.labs.location::Navigator::waypointReached(Waypoint waypoint) - - This signal is emitted when the waypoint \e waypoint has been reached. - - \sa Waypoint -*/ - -/*! - \qmlsignal Qt.labs.location::Navigator::destinationReached() + \list + \li Navigator.NoError - No error has occurred. + \li GeocodeModel.NotSupportedError - Navigation is not supported by the service provider. + \li GeocodeModel.ConnectionError - An error occurred while communicating with the service provider. + \li GeocodeModel.LoaderError - The geoservice provider library could not be loaded. Setting QT_DEBUG_PLUGINS environment variable may help diagnosing the reason. + \li GeocodeModel.UnknownParameterError - An unknown parameter was specified + \li GeocodeModel.MissingRequiredParameterError - required parameter was not specified. + \li GeocodeModel.UnknownError - An error occurred which does not fit into any of the other categories. - This signal is emitted when the last waypoint of the route, the destination, - has been reached. + \endlist */ QDeclarativeNavigatorPrivate::QDeclarativeNavigatorPrivate(QParameterizableObject *q_) - : q(q_), m_params(new QDeclarativeNavigatorParams) -{ -} - -void QDeclarativeNavigatorPrivate::updateReadyState() + : q(q_), m_params(new QDeclarativeNavigatorParams), m_basicDirections(static_cast<QDeclarativeNavigator *>(q_)) { - qobject_cast<QDeclarativeNavigator *>(q)->updateReadyState(); } - - QDeclarativeNavigator::QDeclarativeNavigator(QObject *parent) : QParameterizableObject(parent), d_ptr(new QDeclarativeNavigatorPrivate(this)) { @@ -238,11 +213,10 @@ void QDeclarativeNavigator::setMap(QDeclarativeGeoMap *map) return; d_ptr->m_params->m_map = map; - QDeclarativeNavigatorPrivate *dptr = d_ptr.data(); connect(map, &QObject::destroyed, this, - [this, dptr]() { + [this]() { this->mapChanged(); - dptr->updateReadyState(); + this->updateReadyState(); }); emit mapChanged(); updateReadyState(); @@ -288,11 +262,10 @@ void QDeclarativeNavigator::setPositionSource(QDeclarativePositionSource *positi return; d_ptr->m_params->m_positionSource = positionSource; - QDeclarativeNavigatorPrivate *dptr = d_ptr.data(); QObject::connect(positionSource, &QObject::destroyed, - [this, dptr]() { + [this]() { this->positionSourceChanged(); - dptr->updateReadyState(); + this->updateReadyState(); } ); emit positionSourceChanged(); @@ -327,18 +300,34 @@ void QDeclarativeNavigator::setTrackPositionSource(bool trackPositionSource) emit trackPositionSourceChanged(trackPositionSource); } -QDeclarativeGeoRoute *QDeclarativeNavigator::currentRoute() const +QDeclarativeNavigationBasicDirections *QDeclarativeNavigator::directions() const { - if (!d_ptr->m_ready || !d_ptr->m_navigator->active()) - return d_ptr->m_params->m_route.data(); - return d_ptr->m_currentRoute.data(); + return &d_ptr->m_basicDirections; } -int QDeclarativeNavigator::currentSegment() const +QDeclarativeNavigator::NavigationError QDeclarativeNavigator::error() const { - if (!d_ptr->m_ready || !d_ptr->m_navigator->active()) - return 0; - return d_ptr->m_currentSegment; + return d_ptr->m_error; +} + +QString QDeclarativeNavigator::errorString() const +{ + return d_ptr->m_errorString; +} + +/* !NOT DOCUMENTED YET! + \qmlproperty QAbstractNavigator *Qt.labs.location::Navigator::engineHandle + + This property returns a handle to the navigation object created by the engine. + This object can carry engine-specific properties, signals and methods, to expose + engine-specific features and data. + + \note Using this property leads to writing code that won't work with different plugins. +*/ +QAbstractNavigator *QDeclarativeNavigator::abstractNavigator() const +{ + return d_ptr->m_navigator.data(); + } bool QDeclarativeNavigator::active() const @@ -397,6 +386,10 @@ void QDeclarativeNavigator::stop() if (d_ptr->m_navigator->active()) d_ptr->m_active = d_ptr->m_navigator->stop(); + + // Cached data are cleared in response to signals emitted by m_navigator upon stop(). + // For example, m_navigator emits currentRouteChanged with an empty route, + // and QDeclarativeNavigationBasicDirections reacts by clearing the declarative route. } void QDeclarativeNavigator::pluginReady() @@ -417,26 +410,69 @@ bool QDeclarativeNavigator::ensureEngine() if (!d_ptr->m_completed || !d_ptr->m_plugin->isAttached()) return false; - auto manager = d_ptr->m_plugin->sharedGeoServiceProvider()->navigationManager(); - if (manager) { - d_ptr->m_navigator.reset(manager->createNavigator(d_ptr->m_params)); - if (!d_ptr->m_navigator) - return false; - d_ptr->m_navigator->setLocale(manager->locale()); - d_ptr->m_navigator->setMeasurementSystem(manager->measurementSystem()); - connect(d_ptr->m_navigator.get(), &QAbstractNavigator::waypointReached, this, &QDeclarativeNavigator::waypointReached); - connect(d_ptr->m_navigator.get(), &QAbstractNavigator::destinationReached, this, &QDeclarativeNavigator::destinationReached); - connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentRouteChanged, this, &QDeclarativeNavigator::onCurrentRouteChanged); - connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentSegmentChanged, this, &QDeclarativeNavigator::onCurrentSegmentChanged); - connect(d_ptr->m_navigator.get(), &QAbstractNavigator::activeChanged, this, [this](bool active){ - d_ptr->m_active = active; - emit activeChanged(active); - }); - connect(this, &QDeclarativeNavigator::trackPositionSourceChanged, d_ptr->m_navigator.get(), &QAbstractNavigator::setTrackPosition); - emit navigatorReadyChanged(true); - return true; + QGeoServiceProvider *serviceProvider = d_ptr->m_plugin->sharedGeoServiceProvider(); + // if m_plugin->isAttached(), serviceProvider cannot be null + QNavigationManager *manager = serviceProvider->navigationManager(); + + if (serviceProvider->navigationError() != QGeoServiceProvider::NoError) { + QDeclarativeNavigator::NavigationError newError = UnknownError; + switch (serviceProvider->navigationError()) { + case QGeoServiceProvider::NotSupportedError: + newError = NotSupportedError; break; + case QGeoServiceProvider::UnknownParameterError: + newError = UnknownParameterError; break; + case QGeoServiceProvider::MissingRequiredParameterError: + newError = MissingRequiredParameterError; break; + case QGeoServiceProvider::ConnectionError: + newError = ConnectionError; break; + case QGeoServiceProvider::LoaderError: + newError = LoaderError; break; + default: + break; + } + + setError(newError, serviceProvider->navigationErrorString()); + return false; } - return false; + + if (!manager) { + setError(NotSupportedError, tr("Plugin does not support navigation.")); + return false; + } + + d_ptr->m_navigator.reset(manager->createNavigator(d_ptr->m_params)); + if (!d_ptr->m_navigator) { + setError(UnknownError, tr("Failed to create a navigator object.")); + return false; + } + + d_ptr->m_navigator->setLocale(manager->locale()); + d_ptr->m_navigator->setMeasurementSystem(manager->measurementSystem()); + + connect(d_ptr->m_navigator.get(), &QAbstractNavigator::activeChanged, this, [this](bool active){ + d_ptr->m_active = active; + emit activeChanged(active); + }); + connect(this, &QDeclarativeNavigator::trackPositionSourceChanged, d_ptr->m_navigator.get(), &QAbstractNavigator::setTrackPosition); + + // read-only progress info updates + connect(d_ptr->m_navigator.get(), &QAbstractNavigator::waypointReached, + &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::waypointReached); + connect(d_ptr->m_navigator.get(), &QAbstractNavigator::destinationReached, + &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::destinationReached); + connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentRouteChanged, + &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::onCurrentRouteChanged); + connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentRouteLegChanged, + &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::onCurrentRouteLegChanged); + connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentSegmentChanged, + &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::currentSegmentChanged); + connect(d_ptr->m_navigator.get(), &QAbstractNavigator::nextManeuverIconChanged, + &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::nextManeuverIconChanged); + connect(d_ptr->m_navigator.get(), &QAbstractNavigator::progressInformationChanged, + &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::progressInformationChanged); + + emit navigatorReadyChanged(true); + return true; } void QDeclarativeNavigator::updateReadyState() { @@ -450,18 +486,175 @@ void QDeclarativeNavigator::updateReadyState() { emit navigatorReadyChanged(d_ptr->m_ready); } -void QDeclarativeNavigator::onCurrentRouteChanged(const QGeoRoute &route) +void QDeclarativeNavigator::setError(QDeclarativeNavigator::NavigationError error, const QString &errorString) { - if (d_ptr->m_currentRoute) - d_ptr->m_currentRoute->deleteLater(); - d_ptr->m_currentRoute = new QDeclarativeGeoRoute(route, this); + d_ptr->m_error = error; + d_ptr->m_errorString = errorString; + emit errorChanged(); +} + +QDeclarativeNavigationBasicDirections::QDeclarativeNavigationBasicDirections(QDeclarativeNavigator *parent) +: QObject(parent), m_navigator(parent) +{ + if (m_navigator) + m_navigatorPrivate = m_navigator->d_ptr.data(); +} + +/*! + \qmlpropertygroup Qt.labs.location::Navigator::directions + \qmlproperty Variant Qt.labs.location::Navigator::directions.nextManeuverIcon + \qmlproperty real Qt.labs.location::Navigator::directions.distanceToNextManeuver + \qmlproperty real Qt.labs.location::Navigator::directions.remainingTravelDistance + \qmlproperty real Qt.labs.location::Navigator::directions.remainingTravelDistanceToNextWaypoint + \qmlproperty real Qt.labs.location::Navigator::directions.traveledDistance + \qmlproperty int Qt.labs.location::Navigator::directions.timeToNextManeuver + \qmlproperty int Qt.labs.location::Navigator::directions.remainingTravelTime + \qmlproperty int Qt.labs.location::Navigator::directions.remainingTravelTimeToNextWaypoint + \qmlproperty int Qt.labs.location::Navigator::directions.traveledTime + \qmlproperty Route Qt.labs.location::Navigator::directions.currentRoute + \qmlproperty RouteLeg Qt.labs.location::Navigator::directions.currentRouteLeg + \qmlproperty int Qt.labs.location::Navigator::directions.currentSegment + + \qmlsignal Qt.labs.location::Navigator::directions.waypointReached(Waypoint waypoint) + \qmlsignal Qt.labs.location::Navigator::directions.destinationReached() + + These read-only properties are part of the directions property group. + The directions property group holds the navigation progress information + that can be used to access the route data and to extract directions. + + \note specific backends might not provide (some of) these information. + + \list + \li The \l nextManeuverIcon property holds the next turn icon. + \li The \l distanceToNextManeuver property holds the distance to the next maneuver, in meters. + \li The \l remainingTravelDistance property holds the remaining travel distance, in meters. + \li The \l remainingTravelDistanceToNextWaypoint property holds the remaining travel distance to the next waypoint, in meters. + \li The \l traveledDistance property holds the traveled distance, in meters. + \li The \l timeToNextManeuver property holds the time to the next maneuver, in milliseconds. + \li The \l remainingTravelTime property holds the remaining travel time, in milliseconds. + \li The \l remainingTravelTimeToNextWaypoint property holds the remaining travel time to the next waypoint, in milliseconds. + \li The \l traveledTime property holds the traveled time, in milliseconds. + \li The \l currentRoute property olds the current route the navigator is following. This can be the same as \l route, or can be different, if the navigator + cannot follow the user-specified route. For example if the position coming from \l positionSource is considerably + off route, the navigation engine might recalculate and start following a + new route. + \li The \l currentRouteSegment property holds the current route leg the navigator is following. + This is always a part of \l currentRoute, and so the property \l RouteLeg::overallRoute + of currentRouteLeg will hold the same route as \l currentRoute. + \li The \l currentSegment property holds the index of the current RouteSegment in the \l currentRoute. + \li The \l waypointReached signal is emitted when the waypoint \e waypoint has been reached. + \li The \l destinationReached signal is emitted when the last waypoint of the route, the destination, + has been reached. + \endlist + + \sa Route, RouteLeg, RouteSegment, Waypoint +*/ + +QVariant QDeclarativeNavigationBasicDirections::nextManeuverIcon() const +{ + if (m_navigatorPrivate->m_navigator) + return m_navigatorPrivate->m_navigator->nextManeuverIcon(); + return QVariant(); +} + +qreal QDeclarativeNavigationBasicDirections::distanceToNextManeuver() const +{ + if (m_navigatorPrivate->m_navigator) + return m_navigatorPrivate->m_navigator->distanceToNextManeuver(); + return qQNaN(); +} + +qreal QDeclarativeNavigationBasicDirections::remainingTravelDistance() const +{ + if (m_navigatorPrivate->m_navigator) + return m_navigatorPrivate->m_navigator->remainingTravelDistance(); + return qQNaN(); +} + +qreal QDeclarativeNavigationBasicDirections::remainingTravelDistanceToNextWaypoint() const +{ + if (m_navigatorPrivate->m_navigator) + return m_navigatorPrivate->m_navigator->remainingTravelDistanceToNextWaypoint(); + return qQNaN(); +} + +qreal QDeclarativeNavigationBasicDirections::traveledDistance() const +{ + if (m_navigatorPrivate->m_navigator) + return m_navigatorPrivate->m_navigator->traveledDistance(); + return 0; +} + +int QDeclarativeNavigationBasicDirections::timeToNextManeuver() const +{ + if (m_navigatorPrivate->m_navigator) + return m_navigatorPrivate->m_navigator->timeToNextManeuver(); + return -1; +} + +int QDeclarativeNavigationBasicDirections::remainingTravelTime() const +{ + if (m_navigatorPrivate->m_navigator) + return m_navigatorPrivate->m_navigator->remainingTravelTime(); + return -1; +} + +int QDeclarativeNavigationBasicDirections::remainingTravelTimeToNextWaypoint() const +{ + if (m_navigatorPrivate->m_navigator) + return m_navigatorPrivate->m_navigator->remainingTravelTimeToNextWaypoint(); + return -1; +} + +int QDeclarativeNavigationBasicDirections::traveledTime() const +{ + if (m_navigatorPrivate->m_navigator) + return m_navigatorPrivate->m_navigator->traveledTime(); + return 0; +} + +QDeclarativeGeoRoute *QDeclarativeNavigationBasicDirections::currentRoute() const +{ + if (!m_navigatorPrivate->m_ready + || !m_navigatorPrivate->m_navigator + || !m_navigatorPrivate->m_navigator->active()) + return m_navigatorPrivate->m_params->m_route.data(); // the user-specified route, if any + return m_currentRoute; +} + +QDeclarativeGeoRouteLeg *QDeclarativeNavigationBasicDirections::currentRouteLeg() const +{ + if (!m_navigatorPrivate->m_ready + || !m_navigatorPrivate->m_navigator + || !m_navigatorPrivate->m_navigator->active()) + return nullptr; + return m_currentRouteLeg; +} + +int QDeclarativeNavigationBasicDirections::currentSegment() const +{ + if (!m_navigatorPrivate->m_ready + || !m_navigatorPrivate->m_navigator + || !m_navigatorPrivate->m_navigator->active()) + return 0; + return m_navigatorPrivate->m_navigator->currentSegment(); +} + +void QDeclarativeNavigationBasicDirections::onCurrentRouteChanged() +{ + if (m_currentRoute) + m_currentRoute->deleteLater(); + m_currentRoute = new QDeclarativeGeoRoute(m_navigatorPrivate->m_navigator->currentRoute(), this); emit currentRouteChanged(); } -void QDeclarativeNavigator::onCurrentSegmentChanged(int segment) +void QDeclarativeNavigationBasicDirections::onCurrentRouteLegChanged() { - d_ptr->m_currentSegment = segment; - emit currentSegmentChanged(); + if (m_currentRouteLeg) + m_currentRouteLeg->deleteLater(); + m_currentRouteLeg = new QDeclarativeGeoRouteLeg(m_navigatorPrivate->m_navigator->currentRouteLeg(), this); + emit currentRouteLegChanged(); } QT_END_NAMESPACE + diff --git a/src/location/labs/qdeclarativenavigator_p.h b/src/location/labs/qdeclarativenavigator_p.h index 13884c41..e12d6ba4 100644 --- a/src/location/labs/qdeclarativenavigator_p.h +++ b/src/location/labs/qdeclarativenavigator_p.h @@ -52,6 +52,7 @@ #include <QtQml/qqml.h> #include <QSharedPointer> #include <QtLocation/private/qparameterizableobject_p.h> +#include <QtLocation/qgeoserviceprovider.h> QT_BEGIN_NAMESPACE @@ -59,12 +60,16 @@ class QDeclarativeGeoServiceProvider; class QDeclarativeGeoMap; class QNavigationManager; class QDeclarativeGeoRoute; +class QDeclarativeGeoRouteLeg; class QDeclarativePositionSource; class QDeclarativeGeoWaypoint; class QGeoRoute; +class QGeoRouteLeg; class QGeoRouteSegment; class QDeclarativeNavigatorPrivate; class QDeclarativeGeoRouteSegment; +class QDeclarativeNavigationBasicDirections; +class QAbstractNavigator; class Q_LOCATION_PRIVATE_EXPORT QDeclarativeNavigator : public QParameterizableObject, public QQmlParserStatus { @@ -76,11 +81,28 @@ 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(QDeclarativeGeoRoute *currentRoute READ currentRoute NOTIFY currentRouteChanged) - Q_PROPERTY(int currentSegment READ currentSegment NOTIFY currentSegmentChanged) + Q_PROPERTY(QDeclarativeNavigationBasicDirections *directions READ directions CONSTANT) + Q_PROPERTY(NavigationError error READ error NOTIFY errorChanged) + Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) + Q_PROPERTY(QAbstractNavigator *engineHandle READ abstractNavigator CONSTANT) + Q_INTERFACES(QQmlParserStatus) public: + enum NavigationError { + //QGeoServiceProvider related errors start here + NoError = QGeoServiceProvider::NoError, + NotSupportedError = QGeoServiceProvider::NotSupportedError, //TODO Qt6 consider merge with NotSupportedError + ConnectionError = QGeoServiceProvider::ConnectionError, //TODO Qt6 merge with Map's ConnectionError + LoaderError = QGeoServiceProvider::LoaderError, + UnknownParameterError = QGeoServiceProvider::UnknownParameterError, //TODO Qt6 consider rename UnsupportedOperationError + MissingRequiredParameterError = QGeoServiceProvider::MissingRequiredParameterError, + //we leave gap for future QGeoCodeReply errors + + // Navigation-specific error should start at 100 + UnknownError = 100 + }; + explicit QDeclarativeNavigator(QObject *parent = nullptr); ~QDeclarativeNavigator(); @@ -112,36 +134,34 @@ public: void setTrackPositionSource(bool trackPositionSource); bool trackPositionSource() const; - QDeclarativeGeoRoute *currentRoute() const; - int currentSegment() const; + QDeclarativeNavigationBasicDirections *directions() const; + QAbstractNavigator *abstractNavigator() const; + + NavigationError error() const; + QString errorString() const; signals: void navigatorReadyChanged(bool ready); void trackPositionSourceChanged(bool trackPositionSource); void activeChanged(bool active); - void waypointReached(const QDeclarativeGeoWaypoint *pos); - void destinationReached(); void pluginChanged(); void mapChanged(); void routeChanged(); void positionSourceChanged(); - void currentRouteChanged(); - void currentSegmentChanged(); + void errorChanged(); -private: +protected: void pluginReady(); bool ensureEngine(); void updateReadyState(); - -private slots: - void onCurrentRouteChanged(const QGeoRoute &route); - void onCurrentSegmentChanged(int segment); + void setError(NavigationError error, const QString &errorString); private: QScopedPointer<QDeclarativeNavigatorPrivate> d_ptr; friend class QDeclarativeNavigatorPrivate; + friend class QDeclarativeNavigationBasicDirections; }; QT_END_NAMESPACE diff --git a/src/location/labs/qdeclarativenavigator_p_p.h b/src/location/labs/qdeclarativenavigator_p_p.h index 229ead1e..77fe2ff2 100644 --- a/src/location/labs/qdeclarativenavigator_p_p.h +++ b/src/location/labs/qdeclarativenavigator_p_p.h @@ -52,6 +52,7 @@ #include <QtLocation/private/qlocationglobal_p.h> #include <QtCore/qpointer.h> #include <QtLocation/qgeoroute.h> +#include <QtLocation/private/qdeclarativenavigator_p.h> QT_BEGIN_NAMESPACE @@ -59,12 +60,69 @@ class QDeclarativeGeoServiceProvider; class QDeclarativeGeoMap; class QNavigationManager; class QDeclarativeGeoRoute; +class QDeclarativeGeoRouteLeg; class QDeclarativePositionSource; class QGeoMapParameter; class QDeclarativeGeoRouteSegment; class QParameterizableObject; class QAbstractNavigator; +class Q_LOCATION_PRIVATE_EXPORT QDeclarativeNavigationBasicDirections : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QVariant nextManeuverIcon READ nextManeuverIcon NOTIFY nextManeuverIconChanged) + Q_PROPERTY(qreal distanceToNextManeuver READ distanceToNextManeuver NOTIFY progressInformationChanged) + Q_PROPERTY(qreal remainingTravelDistance READ remainingTravelDistance NOTIFY progressInformationChanged) + Q_PROPERTY(qreal remainingTravelDistanceToNextWaypoint READ remainingTravelDistanceToNextWaypoint NOTIFY progressInformationChanged) + Q_PROPERTY(qreal traveledDistance READ traveledDistance NOTIFY progressInformationChanged) + Q_PROPERTY(int timeToNextManeuver READ timeToNextManeuver NOTIFY progressInformationChanged) + Q_PROPERTY(int remainingTravelTime READ remainingTravelTime NOTIFY progressInformationChanged) + Q_PROPERTY(int remainingTravelTimeToNextWaypoint READ remainingTravelTimeToNextWaypoint NOTIFY progressInformationChanged) + Q_PROPERTY(int traveledTime READ traveledTime NOTIFY progressInformationChanged) + Q_PROPERTY(QDeclarativeGeoRoute *currentRoute READ currentRoute NOTIFY currentRouteChanged) + Q_PROPERTY(QDeclarativeGeoRouteLeg *currentRouteLeg READ currentRouteLeg NOTIFY currentRouteChanged) + Q_PROPERTY(int currentSegment READ currentSegment NOTIFY currentSegmentChanged) + +public: + explicit QDeclarativeNavigationBasicDirections(QDeclarativeNavigator *parent); + + QVariant nextManeuverIcon() const; + qreal distanceToNextManeuver() const; + qreal remainingTravelDistance() const; + qreal remainingTravelDistanceToNextWaypoint() const; + qreal traveledDistance() const; + int timeToNextManeuver() const; + int remainingTravelTime() const; + int remainingTravelTimeToNextWaypoint() const; + int traveledTime() const; + + QDeclarativeGeoRoute *currentRoute() const; + QDeclarativeGeoRouteLeg *currentRouteLeg() const; + int currentSegment() const; + +Q_SIGNALS: + void progressInformationChanged(); + void nextManeuverIconChanged(); + void currentRouteChanged(); + void currentRouteLegChanged(); + void currentSegmentChanged(); + void waypointReached(const QDeclarativeGeoWaypoint *pos); + void destinationReached(); + +protected slots: + void onCurrentRouteChanged(); + void onCurrentRouteLegChanged(); + +protected: + QDeclarativeNavigator *m_navigator; + QDeclarativeNavigatorPrivate *m_navigatorPrivate; + QPointer<QDeclarativeGeoRoute> m_currentRoute; + QPointer<QDeclarativeGeoRouteLeg> m_currentRouteLeg; + + friend class QDeclarativeNavigator; +}; + class Q_LOCATION_PRIVATE_EXPORT QDeclarativeNavigatorParams { public: @@ -81,16 +139,17 @@ class QDeclarativeNavigatorPrivate public: QDeclarativeNavigatorPrivate(QParameterizableObject *q_); - void updateReadyState(); QParameterizableObject *q = nullptr; QSharedPointer<QDeclarativeNavigatorParams> m_params; QScopedPointer<QAbstractNavigator> m_navigator; QDeclarativeGeoServiceProvider *m_plugin = nullptr; - QPointer<QDeclarativeGeoRoute> m_currentRoute; - int m_currentSegment = 0; + QDeclarativeNavigationBasicDirections m_basicDirections; + bool m_active = false; bool m_completed = false; bool m_ready = false; + QDeclarativeNavigator::NavigationError m_error = QDeclarativeNavigator::NoError; + QString m_errorString; }; QT_END_NAMESPACE diff --git a/src/location/labs/qgeojson.cpp b/src/location/labs/qgeojson.cpp new file mode 100644 index 00000000..f7f37661 --- /dev/null +++ b/src/location/labs/qgeojson.cpp @@ -0,0 +1,1242 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2018 Julian Sherollari <jdotsh@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore 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 "qgeojson_p.h" +#include <qjsonobject.h> +#include <qjsonvalue.h> +#include <qjsonarray.h> +#include <qgeocoordinate.h> +#include <qgeocircle.h> +#include <qgeopath.h> +#include <qgeopolygon.h> +#include <qtextstream.h> + +QT_BEGIN_NAMESPACE + +/*! \class QGeoJson + \inmodule QtLocation + \since 5.13 + + QGeoJson class can be used to convert between a GeoJSON document (see the + \l {https://en.wikipedia.org/wiki/GeoJSON} {Wikipedia page}, \l + {https://tools.ietf.org/html/rfc7946} {RFC}) and a \l + {http://doc.qt.io/qt-5/qvariant.html#QVariantList-typedef} {QVariantList} + of \l QVariantMap elements ready to be used as Model in a \l MapItemView. + WARNING! This private class is part of Qt labs, thus not stable API, it is + part of the experimental components of QtLocation. Until it is promoted to + public API, it may be subject to source and binary-breaking changes. + + \section2 Importing GeoJSON + + The method \l importGeoJson accepts a \l + {http://doc.qt.io/qt-5/qjsondocument.html} {QJsonDocument} from which it + extracts a single \l {https://tools.ietf.org/html/rfc7159} {JSON} object, + since the GeoJSON RFC expects that a valid GeoJSON Document has in its root + a single JSON object. This method doesn't perform any validation on the + input. The importer returns a QVariantList containing a single QVariantMap. + This map has always at least 2 (key, value) pairs. The first one has \c + type as key, and the corresponding value is a string identifying the + GeoJSON type. This value can be one of the GeoJSON object types: \c Point, + \c MultiPoint, \c LineString, \c MultiLineString, \c Polygon, \c + MultiPolygon, \c GeometryCollection, \c FeatureCollection. The second pair + has \c data as key, and the corresponding value can be either a QGeoShape + or a list, depending on the GeoJSON type. The next section provides details + about this node. The \c Feature type is converted into the type of the + geometry contained within, with an additional (key, value) pair, where the + key is \c properties and the value is a \l QVariantMap. Thus, a feature Map + is distinguishable from the corresponding geometry, by looking for a \c + properties member. + + \section3 Structure of the data node + + For the single type geometry objects (\c Point, \c LineString, and \c + Polygon), the value corresponding to the \c data key is a QGeoShape: + + \list + \li When the type is \c Point, the data is a QGeoCircle with the point + coordinates stored in the center property. + + For example, the following GeoJSON document contains a \c Point + geometry: + + \code + { + "type" : "Point", + "data" : [60.0, 11.0] + } + \endcode + + it is converted to a QVariantMap with the following structure: + + \code + { + type : Point + data : QGeoCircle({60.000, 11.000}, -1) + } + \endcode + + \li When the type is \c LineString the data ia a QGeoPath. + + For example, the following GeoJSON document contains a \c LineString + geometry: + + \code + { + "type" : "LineString", + "coordinates" : [[13.5, 43],[10.73, 59.92]] + } + \endcode + + it is converted to a QVariantMap with the following structure: + + \code + { + type : LineString, + data : QGeoPath([{43.000, 13.500}, {59.920, 10.730}]) + } + \endcode + + \li When the type is \c Polygon, the data is a QGeoPolygon (holes are + supported). + + For example, the following GeoJSON document contains a \c Polygon + geometry: + + \code + { + "type" : "Polygon", + "coordinates" : [ + [[17.13, 51.11], + [30.54, 50.42], + [26.70, 58.36], + [17.13, 51.11]] + ], + "bbox" : [60, 60, -60, -60] + + } + \endcode + + it is converted to a QVariantMap with the following structure: + + \code + { + type : Polygon + data : QGeoPolygon([{51.110, 17.130}, {50.420,30.540}, {58.360, 26.700}, {51.110, 17.130}]) + } + \endcode + + \endlist + + For the homogeneously typed multipart geometry objects (\c MultiPoint, \c + MultiLineString, \c MultiPolygon) the value corresponding to the \c data + key is a QVariantList. Each element of the list is a QVariantMap of one of + the above listed types. The elements in this list will be all of the same + GeoJSON type: + + \list + \li When the type is \c MultiPoint, the data is a List of Points. + + For example, the following GeoJSON document contains a \c MultiPoint + geometry: + + \code + { + "type" : "MultiPoint", + "coordinates" : [ + [11,60], + [5.5,60.3], + [5.7,58.90] + ] + } + \endcode + + it is converted to a QVariantMap with the following structure: + + \code + { + type : MultiPoint + data : [ + { + type : Point + data : QGeoCircle({60.000, 11.000}, -1) + }, + { + type : Point + data : QGeoCircle({60.300, 5.500}, -1) + }, + { + type : Point + data : QGeoCircle({58.900, 5.700}, -1) + } + ] + } + \endcode + + \li When the type is \c MultiLineString, the data is a List of LineStrings. + + For example, the following GeoJSON document contains a \c MultiLineString + geometry: + + \code + { + "type" : "MultiLineString", + "coordinates" : [ + [[13.5, 43], [10.73, 59.92]], + [[9.15, 45], [-3.15, 58.90]] + ] + } + \endcode + + it is converted to a QVariantMap with the following structure: + + \code + { + type : MultiLineString + data : [ + { + type : LineString + data : QGeoPath([{45.000, 9.150}, {58.900, -3.150}]) + }, + { + type : LineString + data : QGeoPath([{43.000, 13.500}, {59.920, 10.730}]) + } + ] + } + \endcode + + \li When the type is \c MultiPolygon, the data is a List of Polygons. + + For example, the following GeoJSON document contains a \c MultiPolygon + geometry: + + \code + { + "type" : "MultiPoint", + "coordinates" : [ + [11,60], + [5.5,60.3], + [5.7,58.90] + ] + } + \endcode + + it is converted to a QVariantMap with the following structure: + + \code + { + type : MultiPoint + data : [ + { + type : Point + data : QGeoCircle({60.000, 11.000}, -1) + }, + { + type : Point + data : QGeoCircle({60.300, 5.500}, -1) + }, + { + type : Point + data : QGeoCircle({58.900, 5.700}, -1) + } + ] + } + \endcode + + \endlist + + The \c GeometryCollection is a heterogeneous composition of other geometry + types. In the resulting QVariantMap, the value of the \c data member is a + QVariantList populated by QVariantMaps of various geometries, including the + GeometryCollection itself. + + For example, the following \c GeometryCollection: + + \code + { + "type" : "GeometryCollection", + "geometries" : [ + { + "type" : "MultiPoint", + "coordinates" : [ + [11,60], [5.5,60.3], [5.7,58.90] + ] + }, + { + "type" : "MultiLineString", + "coordinates" : [ + [[13.5, 43], [10.73, 59.92]], + [[9.15, 45], [-3.15, 58.90]] + ] + }, + { + "type" : "MultiPolygon", + "coordinates" : [ + [ + [[17.13, 51.11], + [30.54, 50.42], + [26.74, 58.36], + [17.13, 51.11]] + ], + [ + [[19.84, 41.33], + [30.45, 49.26], + [17.07, 50.10], + [19.84, 41.33]] + ] + ] + } + ] + } + \endcode + + it is converted to a QVariantMap with the following structure: + + \code + { + type : GeometryCollection + data : [ + { + type : MultiPolygon + data : [ + { + type : Polygon + data : QGeoPolygon([{41.330, 19.840}, {49.260, 30.450}, {50.100, 17.070}, {41.330, 19.840}]) + } + { + type : Polygon + data : QGeoPolygon([{51.110, 17.130}, {50.420, 30.540}, {58.360, 26.740}, {51.110, 17.130}]) + } + ] + } + { + type : MultiLineString + data : [ + { + type : LineString + data : QGeoPath([{45.000, 9.150}, {58.900, -3.150}]) + } + { + type : LineString + data : QGeoPath([{43.000, 13.500}, {59.920, 10.730}]) + } + ] + } + { + type : MultiPoint + data : [ + { + type : Point + data : QGeoCircle({58.900, 5.700}, -1) + }, + { + type : Point + data : QGeoCircle({60.300, 5.500}, -1) + }, + { + type : Point + data : QGeoCircle({60.000, 11.000}, -1) + } + ] + } + ] + } + \endcode + + The \c Feature object, which consists of one of the previous geometries + together with related attributes, is structured like one of the 7 above + mentioned geometry types, plus a \c properties member. The value of this + member is a QVariantMap. The only way to distinguish a Feature from the + included geometry is to check if a \c properties node is present in the + QVariantMap. + + For example, the following \c Feature: + + \code + { + "type" : "Feature", + "id" : "Poly", + "properties" : { + "text" : "This is a Feature with a Polygon" + }, + "geometry" : { + "type" : "Polygon", + "coordinates" : [ + [[17.13, 51.11], + [30.54, 50.42], + [26.70, 58.36], + [17.13, 51.11]], + [[23.46, 54.36], + [20.52, 51.91], + [28.25, 51.50], + [26.80, 54.36], + [23.46, 54.36]] + ] + } + } + \endcode + + it is converted to a QVariantMap with the following structure: + + \code + { + type : Polygon + data : QGeoPolygon([{51.110, 17.130}, {50.420,30.540}, {58.360, 26.700}, {51.110, 17.130}]) + properties : {text : This is a Feature with a Polygon} + } + \endcode + + The \c FeatureCollection is a composition of Feature objects. The value of + the \c data member in a FeatureCollection is a QVariantList populated by + Feature type QVariantMaps. + + For example, the following \c FeatureCollection: + + \code + { + "type" : "FeatureCollection", + "features" : [ + { + "type" : "Feature", + "id" : "Poly", + "properties" : { + "text" : "This is a Feature with a Polygon" + }, + "geometry" : { + "type" : "Polygon", + "coordinates" : [ + [[17.13, 51.11], + [30.54, 50.42], + [26.70, 58.36], + [17.13, 51.11]], + [[23.46, 54.36], + [20.52, 51.91], + [28.25, 51.50], + [26.80, 54.36], + [23.46, 54.36]] + ] + } + }, + { + "type" : "Feature", + "id" : "MultiLine", + "properties" : { + "text" : "This is a Feature with a MultiLineString" + }, + "geometry" : { + "type" : "MultiLineString", + "coordinates" : [ + [[13.5, 43], [10.73, 59.92]], + [[9.15, 45], [-3.15, 58.90]] + ] + } + } + ] + } + \endcode + + it is converted to a QVariantMap with the following structure: + + \code + { + type : FeatureCollection + data : [ + { + type : MultiLineString + data : [ + { + type : LineString + data : QGeoPath([{45.000, 9.150}, {58.900, -3.150}]) + } + { + type : LineString + data : QGeoPath([{43.000, 13.500}, {59.920, 10.730}]) + } + ] + properties : {text : This is a Feature with a MultiLineString} + }, + { + type : Polygon + data : QGeoPolygon({51.110, 17.130}, {50.420, 30.540}, {58.360, 26.700}, {51.110, 17.130}) + properties : {text : This is a Feature with a Polygon} + } + ] + } + \endcode + + \section2 Exporting GeoJSON + + The exporter accepts the QVariantList returned by \l {The importer}, and + returns a JSON document. The exporter is complementary to the importer + because it executes the inverse action. + + \section2 The toString function + + The \l toString outputs, for debugging purposes, the content of a + QVariantList structured like \l importGeoJson does, to a QString using a + prettyfied format. +*/ + +static QGeoCoordinate importPosition(const QVariant &position) +{ + QGeoCoordinate returnedCoordinates; + const QVariantList positionList = position.value<QVariantList>(); + for (int i = 0; i < positionList.size(); ++i) { // Iterating Point coordinates arrays + switch (i) { + case 0: + returnedCoordinates.setLongitude(positionList.at(i).toDouble()); + break; + case 1: + returnedCoordinates.setLatitude(positionList.at(i).toDouble()); + break; + case 2: + returnedCoordinates.setAltitude(positionList.at(i).toDouble()); + break; + default: + break; + } + } + return returnedCoordinates; +} + +static QList<QGeoCoordinate> importArrayOfPositions(const QVariant &arrayOfPositions) +{ + QList <QGeoCoordinate> returnedCoordinates; + const QVariantList positionsList = arrayOfPositions.value<QVariantList>(); + QGeoCoordinate singlePosition; + for (int i = 0; i < positionsList.size(); ++i) { // Iterating the LineString coordinates nested arrays + singlePosition = importPosition((positionsList.at(i))); + returnedCoordinates.append(singlePosition); // Populating the QList of coordinates + } + return returnedCoordinates; +} + +static QList<QList<QGeoCoordinate>> importArrayOfArrayOfPositions(const QVariant &arrayOfArrayofPositions) +{ + QList<QList<QGeoCoordinate>> returnedCoordinates; + const QVariantList positionsList = arrayOfArrayofPositions.value<QVariantList>(); + QList<QGeoCoordinate> arrayOfPositions; + for (int i = 0; i < positionsList.size(); ++i) { // Iterating the Polygon coordinates nested arrays + arrayOfPositions = importArrayOfPositions((positionsList.at(i))); + returnedCoordinates << arrayOfPositions; + } + return returnedCoordinates; +} + +static QGeoCircle importPoint(const QVariantMap &inputMap) +{ + QGeoCircle returnedObject; + QGeoCoordinate center; + QVariant valueCoords = inputMap.value(QStringLiteral("coordinates")); + center = importPosition(valueCoords); + returnedObject.setCenter(center); + return returnedObject; +} + +static QGeoPath importLineString(const QVariantMap &inputMap) +{ + QGeoPath returnedObject; + QList <QGeoCoordinate> coordinatesList; + const QVariant valueCoordinates = inputMap.value(QStringLiteral("coordinates")); + coordinatesList = importArrayOfPositions(valueCoordinates); + returnedObject.setPath(coordinatesList); + return returnedObject; +} + +static QGeoPolygon importPolygon(const QVariantMap &inputMap) +{ + QGeoPolygon returnedObject; + const QVariant valueCoordinates = inputMap.value(QStringLiteral("coordinates")); + QList<QList<QGeoCoordinate>> perimeters = importArrayOfArrayOfPositions(valueCoordinates); + for (int i = 0; i < perimeters.size(); ++i) { // Import an array of QList<QGeocoordinates> + if (i == 0) + returnedObject.setPath(perimeters.at(i)); // External perimeter + else + returnedObject.addHole(perimeters.at(i)); // Inner perimeters + } + return returnedObject; +} + +static QVariantList importMultiPoint(const QVariantMap &inputMap) +{ + QVariantList returnedObject; + const QVariantList coordinatesList = inputMap.value(QStringLiteral("coordinates")).value<QVariantList>(); + QVariantMap singlePointMap; + QGeoCircle parsedPoint; + for (int i = 0; i < coordinatesList.size(); ++i) { // Iterating MultiPoint coordinates nasted arrays + parsedPoint.setCenter(importPosition(coordinatesList.at(i))); + singlePointMap.insert(QStringLiteral("type"), QStringLiteral("Point")); + singlePointMap.insert(QStringLiteral("data"), QVariant::fromValue(parsedPoint)); + returnedObject.append(QVariant::fromValue(singlePointMap)); + } + return returnedObject; +} + +static QVariantList importMultiLineString(const QVariantMap &inputMap) +{ + QVariantList returnedObject; + QGeoPath parsedLineString; + const QVariant listCoords = inputMap.value(QStringLiteral("coordinates")); + const QVariantList list = listCoords.value<QVariantList>(); + QVariantMap singleLinestringMap; + for (int i = 0; i < list.size(); ++i) { // Iterating the MultiLineString coordinates nasted arrays using importArrayOfPositions + singleLinestringMap.clear(); + const QList <QGeoCoordinate> coordinatesList = importArrayOfPositions(list.at(i)); + singleLinestringMap.insert(QStringLiteral("type"), QStringLiteral("LineString")); + parsedLineString.setPath(coordinatesList); + singleLinestringMap.insert(QStringLiteral("data"), QVariant::fromValue(parsedLineString)); + returnedObject.append(QVariant::fromValue(singleLinestringMap)); + } + return returnedObject; +} + +static QVariantList importMultiPolygon(const QVariantMap &inputMap) +{ + QVariantList returnedObject; + QGeoPolygon singlePoly; + QVariantMap singlePolygonMap; + const QVariant valueCoordinates = inputMap.value(QStringLiteral("coordinates")); + const QVariantList list = valueCoordinates.value<QVariantList>(); + for (int i = 0; i < list.size(); ++i) { // Iterating the MultiPolygon coordinates nasted arrays + singlePolygonMap.clear(); + const QList<QList<QGeoCoordinate>> coordinatesList = importArrayOfArrayOfPositions(list.at(i)); + + for (int j = 0; j < coordinatesList.size(); ++j) { + if (j == 0) + singlePoly.setPath(coordinatesList.at(j)); + else + singlePoly.addHole(coordinatesList.at(j)); + } + singlePolygonMap.insert(QStringLiteral("type"), QStringLiteral("Polygon")); + singlePolygonMap.insert(QStringLiteral("data"), QVariant::fromValue(singlePoly)); + returnedObject.append(QVariant::fromValue(singlePolygonMap)); + } + return returnedObject; +} + +static QVariantMap importGeometry(const QVariantMap &inputMap); // Function prototype for a tail recursion + +static QVariantList importGeometryCollection(const QVariantMap &inputMap) +{ + QVariantList returnedObject; + const QVariant listGeometries = inputMap.value(QStringLiteral("geometries")); + const QVariantList list = listGeometries.value<QVariantList>(); // QVariantList of heterogeneous composition of the other geometry types + for (int i = 0; i < list.size(); ++i) { + QVariantMap geometryMap = list.at(i).value<QVariantMap>(); + QVariantMap geoMap = importGeometry(geometryMap); + returnedObject.append(geoMap); + } + return returnedObject; +} + +static QVariantMap importGeometry(const QVariantMap &inputMap) +{ + QVariantMap returnedObject; + QString geometryTypes[] = { + QStringLiteral("Point"), + QStringLiteral("MultiPoint"), + QStringLiteral("LineString"), + QStringLiteral("MultiLineString"), + QStringLiteral("Polygon"), + QStringLiteral("MultiPolygon"), + QStringLiteral("GeometryCollection") + }; + enum geoTypeSwitch { + Point, + MultiPoint, + LineString, + MultiLineString, + Polygon, + MultiPolygon, + GeometryCollection + }; + for (int i = 0; i<7; ++i) { + if (inputMap.value(QStringLiteral("type")).value<QString>() == geometryTypes[i]) { + switch (i) { + case Point: { + returnedObject.insert(QStringLiteral("type"), QStringLiteral("Point")); + returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importPoint(inputMap))); + break; + } + case MultiPoint: { + returnedObject.insert(QStringLiteral("type"), QStringLiteral("MultiPoint")); + returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importMultiPoint(inputMap))); + break; + } + case LineString: { + returnedObject.insert(QStringLiteral("type"), QStringLiteral("LineString")); + returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importLineString(inputMap))); + break; + } + case MultiLineString: { + returnedObject.insert(QStringLiteral("type"), QStringLiteral("MultiLineString")); + returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importMultiLineString(inputMap))); + break; + } + case Polygon: { + returnedObject.insert(QStringLiteral("type"), QStringLiteral("Polygon")); + returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importPolygon(inputMap))); + break; + } + case MultiPolygon: { + returnedObject.insert(QStringLiteral("type"), QStringLiteral("MultiPolygon")); + returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importMultiPolygon(inputMap))); + break; + } + case GeometryCollection: { + returnedObject.insert(QStringLiteral("type"), QStringLiteral("GeometryCollection")); + returnedObject.insert(QStringLiteral("data"), QVariant::fromValue(importGeometryCollection(inputMap))); + break; + } + default: + break; + } + } + } + return returnedObject; +} + +static QVariantList importFeatureCollection(const QVariantMap &inputMap) +{ + QVariantList returnedObject; + const QVariantList featuresList = inputMap.value(QStringLiteral("features")).value<QVariantList>(); + for (int i = 0; i < featuresList.size(); ++i) { + QVariantMap inputFeatureMap = featuresList.at(i).value<QVariantMap>(); + QVariantMap singleFeatureMap = importGeometry(inputFeatureMap.value(QStringLiteral("geometry")).value<QVariantMap>()); + const QVariantMap importedProperties = inputFeatureMap.value(QStringLiteral("properties")).value<QVariantMap>(); + singleFeatureMap.insert(QStringLiteral("properties"), importedProperties); + if (inputFeatureMap.contains(QStringLiteral("id"))) { + QVariant importedId = inputFeatureMap.value(QStringLiteral("id")).value<QVariant>(); + singleFeatureMap.insert(QStringLiteral("id"), importedId); + } + returnedObject.append(singleFeatureMap); + } + return returnedObject; +} + +static QJsonValue exportPosition(const QGeoCoordinate &obtainedCoordinates) +{ + QJsonValue geoLat = obtainedCoordinates.latitude(); + QJsonValue geoLong = obtainedCoordinates.longitude(); + QJsonArray array = {geoLong, geoLat}; + QJsonValue geoAlt; + if (!qIsNaN(obtainedCoordinates.altitude())) { + geoAlt = obtainedCoordinates.altitude(); + array.append(geoAlt); + } + QJsonValue geoArray = array; + return geoArray; +} + +static QJsonValue exportArrayOfPositions(const QList<QGeoCoordinate> &obtainedCoordinatesList) +{ + QJsonValue lineCoordinates; + QJsonValue multiPosition; + QJsonArray arrayPosition; + for (int i = 0; i < obtainedCoordinatesList.size(); ++i) { + multiPosition = exportPosition(obtainedCoordinatesList.at(i)); + arrayPosition.append(multiPosition); + } + lineCoordinates = arrayPosition; + return lineCoordinates; +} + +static QJsonValue exportArrayOfArrayOfPositions(const QList<QList<QGeoCoordinate>> &obtainedCoordinates) +{ + QJsonValue lineCoordinates; + QJsonValue polyCoordinates; + QJsonArray arrayPath; + for (int i = 0; i < obtainedCoordinates.size(); ++i) { + lineCoordinates = exportArrayOfPositions(obtainedCoordinates.at(i)); + arrayPath.append(lineCoordinates); + } + polyCoordinates = arrayPath; + return polyCoordinates; +} + +static QJsonObject exportPoint(const QVariantMap &pointMap) +{ + QJsonObject parsedPoint; + QGeoCircle circle = pointMap.value(QStringLiteral("data")).value<QGeoCircle>(); + parsedPoint.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("Point"))); + parsedPoint.insert(QStringLiteral("coordinates"), exportPosition(circle.center())); + return parsedPoint; +} + +static QJsonObject exportLineString(const QVariantMap &lineStringMap) +{ + QJsonObject parsedLineString; + QList <QGeoCoordinate> linestringPath = lineStringMap.value(QStringLiteral("data")).value<QGeoPath>().path(); + parsedLineString.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("LineString"))); + parsedLineString.insert(QStringLiteral("coordinates"), exportArrayOfPositions(linestringPath)); + return parsedLineString; +} + +static QJsonObject exportPolygon(const QVariantMap &polygonMap) +{ + QVariant polygonVariant = polygonMap.value(QStringLiteral("data")); + QJsonObject parsedPolygon; + QJsonValue polyCoordinates; + QList<QList<QGeoCoordinate>> obtainedCoordinatesPoly; + QGeoPolygon parsedPoly = polygonVariant.value<QGeoPolygon>(); + obtainedCoordinatesPoly << parsedPoly.path(); + if (parsedPoly.holesCount()!=0) + for (int i = 0; i < parsedPoly.holesCount(); ++i) { + obtainedCoordinatesPoly << parsedPoly.holePath(i); + } + polyCoordinates = exportArrayOfArrayOfPositions(obtainedCoordinatesPoly); + parsedPolygon.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("Polygon"))); + parsedPolygon.insert(QStringLiteral("coordinates"), polyCoordinates); + return parsedPolygon; +} + +static QJsonObject exportMultiPoint(const QVariantMap &multiPointMap) +{ + QJsonObject parsedMultiPoint; + QList <QGeoCoordinate> obtainedCoordinatesMP; + QVariantList multiCircleVariantList = multiPointMap.value(QStringLiteral("data")).value<QVariantList>(); + for (const QVariant &exCircleVariantMap: multiCircleVariantList) { + obtainedCoordinatesMP << exCircleVariantMap.value<QVariantMap>().value(QStringLiteral("data")).value<QGeoCircle>().center(); + } + QJsonValue multiPosition = exportArrayOfPositions(obtainedCoordinatesMP); + parsedMultiPoint.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("MultiPoint"))); + parsedMultiPoint.insert(QStringLiteral("coordinates"), multiPosition); + return parsedMultiPoint; +} + +static QJsonObject exportMultiLineString(const QVariantMap &multiLineStringMap) +{ + QJsonObject parsedMultiLineString; + QList<QList<QGeoCoordinate>> extractedCoordinatesValue; + QVariant multiPathVariant = multiLineStringMap.value(QStringLiteral("data")); + QVariantList multiPathList = multiPathVariant.value<QVariantList>(); + for (int i = 0; i < multiPathList.size(); ++i) { + extractedCoordinatesValue << multiPathList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPath>().path(); + } + QJsonValue exportedCoordinatesValue = exportArrayOfArrayOfPositions(extractedCoordinatesValue); + parsedMultiLineString.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("MultiLineString"))); + parsedMultiLineString.insert(QStringLiteral("coordinates"), exportedCoordinatesValue); + return parsedMultiLineString; +} + +static QJsonObject exportMultiPolygon(const QVariantMap &multiPolygonMap) +{ + QJsonObject parsedMultiPolygon; + QJsonValue polyCoordinates; + QJsonArray parsedArrayPolygon; + QList<QList<QGeoCoordinate>> extractedCoordinatesValue; + QVariant multiPolygonVariant = multiPolygonMap.value(QStringLiteral("data")); + QVariantList multiPolygonList = multiPolygonVariant.value<QVariantList>(); + int polyHoles = 0; + int currentHole; + for (int i = 0; i < multiPolygonList.size(); ++i) { // Start parsing Polygon list + extractedCoordinatesValue << multiPolygonList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPolygon>().path(); // Extract external polygon path + polyHoles = multiPolygonList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPolygon>().holesCount(); + if (polyHoles) // Check if the polygon has holes + for (currentHole = 0 ; currentHole < polyHoles; currentHole++) + extractedCoordinatesValue << multiPolygonList.at(i).value<QVariantMap>().value(QStringLiteral("data")).value<QGeoPolygon>().holePath(currentHole); + polyCoordinates = exportArrayOfArrayOfPositions(extractedCoordinatesValue); // Generates QJsonDocument compatible value + parsedArrayPolygon.append(polyCoordinates); // Adds one level of nesting in coordinates + extractedCoordinatesValue.clear(); // Clears the temporary polygon linear ring storage + } + QJsonValue exportedCoordinatesNodeValue = parsedArrayPolygon; + parsedMultiPolygon.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("MultiPolygon"))); + parsedMultiPolygon.insert(QStringLiteral("coordinates"), exportedCoordinatesNodeValue); + return parsedMultiPolygon; +} + +static QJsonObject exportGeometry(const QVariantMap &geometryMap); // Function prototype + +static QJsonObject exportGeometryCollection(const QVariantMap &geometryCollection) +{ + QJsonObject parsed; + QJsonObject parsedGeometry; + QJsonValue valueGeometries; + QJsonArray parsedGeometries; + QVariantList geometriesList = geometryCollection.value(QStringLiteral("data")).value<QVariantList>(); + for (int i = 0; i < geometriesList.size(); ++i) { + parsedGeometry = exportGeometry(geometriesList.at(i).value<QVariantMap>()); + valueGeometries = parsedGeometry; + parsedGeometries.append(valueGeometries); + } + QJsonValue exportedGeometriesValue = parsedGeometries; + parsed.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("GeometryCollection"))); + parsed.insert(QStringLiteral("geometries"), exportedGeometriesValue); + return parsed; +} + +static QJsonObject exportGeometry(const QVariantMap &geometryMap) +{ + QJsonObject exportedGeometry; + if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("Point")) + exportedGeometry = exportPoint(geometryMap); + if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("MultiPoint")) + exportedGeometry = exportMultiPoint(geometryMap); + if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("LineString")) + exportedGeometry = exportLineString(geometryMap); + if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("MultiLineString")) + exportedGeometry = exportMultiLineString(geometryMap); + if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("Polygon")) + exportedGeometry = exportPolygon(geometryMap); + if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("MultiPolygon")) + exportedGeometry = exportMultiPolygon(geometryMap); + if (geometryMap.value(QStringLiteral("type")) == QStringLiteral("GeometryCollection")) + exportedGeometry = exportGeometryCollection(geometryMap); + return exportedGeometry; +} + +static QJsonObject exportFeature(const QVariantMap &featureMap) +{ + QJsonObject exportedFeature; + QJsonValue geometryNodeValue = QJsonValue(exportGeometry(featureMap)); + QJsonValue propertiesNodeValue = featureMap.value(QStringLiteral("properties")).value<QVariant>().toJsonValue(); + QJsonValue idNodeValue = featureMap.value(QStringLiteral("id")).value<QVariant>().toJsonValue(); + exportedFeature.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("Feature"))); + exportedFeature.insert(QStringLiteral("geometry"), geometryNodeValue); + exportedFeature.insert(QStringLiteral("properties"), propertiesNodeValue); + exportedFeature.insert(QStringLiteral("id"), idNodeValue); + return exportedFeature; +} + +static QJsonObject exportFeatureCollection(const QVariantMap &featureCollection) +{ + QJsonObject exportedFeatureCollection; + QJsonArray featureArray; + QVariantList featureList = featureCollection.value(QStringLiteral("data")).value<QVariantList>(); + for (int i = 0; i < featureList.size(); ++i) { + featureArray.append(QJsonValue(exportFeature(featureList.at(i).value<QVariantMap>()))); + } + exportedFeatureCollection.insert(QStringLiteral("type"), QJsonValue(QStringLiteral("FeatureCollection"))); + exportedFeatureCollection.insert(QStringLiteral("features"), QJsonValue(featureArray) ); + return exportedFeatureCollection; +} + +/*! +This method imports the \a geoJson document, expected to contain valid GeoJSON +data, into a QVariantList structured like described in the section \l +{Importing GeoJSON}. + +\note This method performs no validation on the input. + +\sa exportGeoJson +*/ +QVariantList QGeoJson::importGeoJson(const QJsonDocument &geoJson) +{ + QVariantList returnedList; + QJsonObject object = geoJson.object(); // Read json object from imported doc + QVariantMap rootGeoJsonObject = object.toVariantMap(); // Extraced map using Qt's API + QString geoType[] = { + QStringLiteral("Point"), + QStringLiteral("MultiPoint"), + QStringLiteral("LineString"), + QStringLiteral("MultiLineString"), + QStringLiteral("Polygon"), + QStringLiteral("MultiPolygon"), + QStringLiteral("GeometryCollection"), + QStringLiteral("Feature"), + QStringLiteral("FeatureCollection") + }; + enum geoTypeSwitch { + Point, + MultiPoint, + LineString, + MultiLineString, + Polygon, + MultiPolygon, + GeometryCollection, + Feature, + FeatureCollection + }; + QVariantMap parsedGeoJsonMap; + + // Checking whether the JSON object has a "type" member + const QVariant keyVariant = rootGeoJsonObject.value(QStringLiteral("type")); + if (keyVariant == QVariant::Invalid) { + // Type check failed + } + QString valueType = keyVariant.value<QString>(); + + // Checking whether the "type" member has a GeoJSON admitted value + for (int i = 0; i < 9; ++i) { + if (valueType == geoType[i]) { + switch (i) { + case Point: { + QGeoCircle circle = importPoint(rootGeoJsonObject); + QVariant dataNodeValue = QVariant::fromValue(circle); + parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("Point")); + parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); + break; + } + case MultiPoint: { + QVariantList multiCircle = importMultiPoint(rootGeoJsonObject); + QVariant dataNodeValue = QVariant::fromValue(multiCircle); + QList <QGeoCircle> testlist; + parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("MultiPoint")); + parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); + break; + } + case LineString: { + QGeoPath lineString = importLineString(rootGeoJsonObject); + QVariant dataNodeValue = QVariant::fromValue(lineString); + parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("LineString")); + parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); + break; + } + case MultiLineString: { + QVariantList multiLineString = importMultiLineString(rootGeoJsonObject); + QVariant dataNodeValue = QVariant::fromValue(multiLineString); + parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("MultiLineString")); + parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); + break; + } + case Polygon: { + QGeoPolygon poly = importPolygon(rootGeoJsonObject); + QVariant dataNodeValue = QVariant::fromValue(poly); + parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("Polygon")); + parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); + break; + } + case MultiPolygon: { + QVariantList multiPoly = importMultiPolygon(rootGeoJsonObject); + QVariant dataNodeValue = QVariant::fromValue(multiPoly); + parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("MultiPolygon")); + parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); + break; + } + // List of GeoJson geometry objects + case GeometryCollection: { + QVariantList multiGeo = importGeometryCollection(rootGeoJsonObject); + QVariant dataNodeValue = QVariant::fromValue(multiGeo); + parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("GeometryCollection")); + parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); + break; + } + // Single GeoJson geometry object with properties + case Feature: { + parsedGeoJsonMap = importGeometry(rootGeoJsonObject.value(QStringLiteral("geometry")).value<QVariantMap>()); + QVariantMap importedProperties = rootGeoJsonObject.value(QStringLiteral("properties")).value<QVariantMap>(); + parsedGeoJsonMap.insert(QStringLiteral("properties"), importedProperties); + if (rootGeoJsonObject.contains(QStringLiteral("id"))){ + QVariant importedId = rootGeoJsonObject.value(QStringLiteral("id")).value<QVariant>(); + parsedGeoJsonMap.insert(QStringLiteral("id"), importedId); + } + break; + } + // Heterogeneous list of GeoJSON geometries with properties + case FeatureCollection: { + QVariantList featCollection = importFeatureCollection(rootGeoJsonObject); + QVariant dataNodeValue = QVariant::fromValue(featCollection); + parsedGeoJsonMap.insert(QStringLiteral("type"), QStringLiteral("FeatureCollection")); + parsedGeoJsonMap.insert(QStringLiteral("data"), dataNodeValue); + break; + } + default: + break; + } + QVariant bboxNodeValue = rootGeoJsonObject.value(QStringLiteral("bbox")); + if (bboxNodeValue != QVariant::Invalid) { + parsedGeoJsonMap.insert(QStringLiteral("bbox"), bboxNodeValue); + } + returnedList.append(parsedGeoJsonMap); + } else if (i >= 9) { + // Error + break; + } + } + return returnedList; +} + +/*! +This method exports the QVariantList \a geoData, expected to be structured like +described in the section \l {Importing GeoJSON}, to a QJsonDocument containing +the data converted to GeoJSON. + +\note This method performs no validation on the input. + +\sa importGeoJson +*/ +QJsonDocument QGeoJson::exportGeoJson(const QVariantList &geoData) +{ + QVariantMap exportMap = geoData.at(0).value<QVariantMap>(); // Extracting the QVMap + QJsonObject newObject; + QJsonDocument newDocument; + if (exportMap.contains(QStringLiteral("properties"))) { + newObject = exportFeature(exportMap); + } else { + if (exportMap.value(QStringLiteral("type")) == QStringLiteral("Point")) // Check the value corresponding to the key "Point" + newObject = exportPoint(exportMap); + if (exportMap.value(QStringLiteral("type")) == QStringLiteral("MultiPoint")) + newObject = exportMultiPoint(exportMap); + if (exportMap.value(QStringLiteral("type")) == QStringLiteral("LineString")) + newObject = exportLineString(exportMap); + if (exportMap.value(QStringLiteral("type")) == QStringLiteral("MultiLineString")) + newObject = exportMultiLineString(exportMap); + if (exportMap.value(QStringLiteral("type")) == QStringLiteral("Polygon")) + newObject = exportPolygon(exportMap); + if (exportMap.value(QStringLiteral("type")) == QStringLiteral("MultiPolygon")) + newObject = exportMultiPolygon(exportMap); + if (exportMap.value(QStringLiteral("type")) == QStringLiteral("GeometryCollection")) + newObject = exportGeometryCollection(exportMap); + if (exportMap.value(QStringLiteral("type")) == QStringLiteral("FeatureCollection")) + newObject = exportFeatureCollection(exportMap); + } + if (exportMap.contains((QStringLiteral("bbox")))) { + QJsonArray bboxArray; + QVariantList bboxList = exportMap.value(QStringLiteral("bbox")).value<QVariantList>(); + for (int i = 0; i < bboxList.size(); ++i) { + bboxArray.append(QJsonValue(bboxList.at(i).value<double>())); + } + newObject.insert(QStringLiteral("bbox"), QJsonValue(bboxArray)); + } + newDocument.setObject(newObject); + return newDocument; +} + +// Functions for toString +QTextStream &operator << (QTextStream &stream, const QGeoCoordinate &crd) +{ + stream << "{ " << QString::number(crd.latitude(), 'f', 3) << ", " + << QString::number(crd.longitude(), 'f', 3) << ", " + << QString::number(crd.altitude(), 'f', 3) << " }"; + return stream; +} + +QTextStream &operator << (QTextStream &stream, const QGeoShape &shape) +{ + switch (shape.type()) { + case QGeoShape::CircleType: { + QGeoCircle circle(shape); + stream << "QGeoCircle(" <<circle.center() << ", "<< QString::number(circle.radius()) << ")"; + break; + } + case QGeoShape::PathType: { + QGeoPath path(shape); + stream << "QGeoPath("; + for (auto c: path.path()) + stream << c << ", "; + stream << ")"; + break; + } + case QGeoShape::PolygonType: { + QGeoPolygon poly(shape); + stream << "QGeoPolygon("; + for (auto c: poly.path()) + stream << c << ", "; + stream << ")"; + break; + } + default: + stream << "QGeoShape(Unknown)"; + break; + } + return stream; +} + +static const QString sTab = QStringLiteral(" "); + +QString printQvariant(const QVariant v, int tabs = 0) { + QString sTabs; + QString res; + QTextStream stream(&res); + for (int i = 0; i< tabs; i++) { + sTabs += sTab; + } + if (v.type() == QVariant::List) { + stream << sTabs << "[\n"; + const QVariantList &l = v.toList(); + for (int i = 0; i < l.size(); ++i) + stream << printQvariant(l.at(i), tabs + 1); + stream << sTabs << "]\n"; + } else if (v.type() == QVariant::Map) { + stream << sTabs << "{\n"; + const QVariantList &l = v.toList(); + const QVariantMap &map = v.toMap(); + + // Either one or the other are valid + if (!map.keys().isEmpty()) { + // Handle type first, to easy reading + if (map.contains(QStringLiteral("type"))) { + stream << sTabs << sTab << QStringLiteral("type") << " : " + << printQvariant(map[QStringLiteral("type")], tabs + 1).remove(QRegExp(QStringLiteral("^[ ]*")));; + } + for (QVariantMap::const_iterator iter = map.begin(); iter != map.end(); ++iter) { + if (iter.key() == QStringLiteral("type")) + continue; + stream << sTabs << sTab << iter.key() << " : " << printQvariant(iter.value(), tabs + 1).remove(QRegExp(QStringLiteral("^[ ]*")));; + } + } + for (int i = 0; i < l.size(); ++i) + stream << printQvariant(l.at(i), tabs + 1); + stream << sTabs << "}\n"; + } else { + stream << sTabs; + QGeoShape workigGeometry; + if ( v.canConvert<QGeoShape>()) { + workigGeometry = v.value<QGeoShape>(); + if (workigGeometry.type() == QGeoShape::CircleType) { + QGeoCircle circle = v.value<QGeoCircle>(); + stream << circle<< "\n"; + } else if (workigGeometry.type() == QGeoShape::PathType) { + QGeoPath path = v.value<QGeoPath>(); + stream << path<< "\n"; + } else if (workigGeometry.type() == QGeoShape::PolygonType) { + QGeoPolygon polygon = v.value<QGeoPolygon>(); + stream << polygon<< "\n"; + } + } else { + if (v.isNull()) + stream << "null\n"; + else + stream << v.toString() << "\n"; + } + } + return res; +} + +/*! +This method accepts the QVariantLists structured like described in section \l +{Importing GeoJSON}, and returns a string containing the same data in a +readable form. +*/ +QString QGeoJson::toString(const QVariantList &geoData) { + return printQvariant(geoData.first(), 0); +} + +QT_END_NAMESPACE diff --git a/src/location/labs/qgeojson_p.h b/src/location/labs/qgeojson_p.h new file mode 100644 index 00000000..064dfcf6 --- /dev/null +++ b/src/location/labs/qgeojson_p.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Copyright (C) 2018 Julian Sherollari <jdotsh@gmail.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore 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 QGEOJSON_H +#define QGEOJSON_H + +#include <QtCore/qvariant.h> +#include <QtCore/qjsondocument.h> +#include <QtLocation/private/qlocationglobal_p.h> + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + + +QT_BEGIN_NAMESPACE + +class Q_LOCATION_PRIVATE_EXPORT QGeoJson +{ +public: + + // This method imports a GeoJSON file to a QVariantList + static QVariantList importGeoJson(const QJsonDocument &doc); + + // This method exports a GeoJSON file from a QVariantList + static QJsonDocument exportGeoJson(const QVariantList &list); + + // This method exports the content of the imported QVariantList in a + // readable format + static QString toString(const QVariantList + &importedGeoJson); + +}; + +QT_END_NAMESPACE + +#endif // QGEOJSON_H diff --git a/src/location/labs/qgeotiledmaplabs.cpp b/src/location/labs/qgeotiledmaplabs.cpp index 22d582c0..7d8d7108 100644 --- a/src/location/labs/qgeotiledmaplabs.cpp +++ b/src/location/labs/qgeotiledmaplabs.cpp @@ -44,6 +44,8 @@ #include <QtLocation/private/qmapiconobjectqsg_p_p.h> #include <QtLocation/private/qdeclarativepolylinemapitem_p.h> #include <QtLocation/private/qgeomapobjectqsgsupport_p.h> +#include <QtPositioning/private/qlocationutils_p.h> +#include <math.h> QT_BEGIN_NAMESPACE @@ -57,6 +59,7 @@ public: QGeoMapObjectPrivate *createMapObjectImplementation(QGeoMapObject *obj) override; virtual QList<QGeoMapObject *> mapObjects() const override; void removeMapObject(QGeoMapObject *obj); + QList<QObject *>mapObjectsAt(const QGeoCoordinate &coordinate) const; void updateMapObjects(QSGNode *root, QQuickWindow *window); void updateObjectsGeometry(); @@ -95,6 +98,34 @@ void QGeoTiledMapLabsPrivate::removeMapObject(QGeoMapObject *obj) m_qsgSupport.removeMapObject(obj); } +QList<QObject *> QGeoTiledMapLabsPrivate::mapObjectsAt(const QGeoCoordinate &coordinate) const +{ + // ToDo: use a space partitioning strategy + QList<QObject *> res; + for (const auto o: mapObjects()) { + // explicitly handle lines + bool contains = false; + if (o->type() == QGeoMapObject::PolylineType ) { + QMapPolylineObject *mpo = static_cast<QMapPolylineObject *>(o); + qreal mpp = QLocationUtils::metersPerPixel(m_cameraData.zoomLevel(), coordinate); + QGeoPath path = o->geoShape(); + path.setWidth(mpp * mpo->border()->width()); + contains = path.contains(coordinate); + } else if (o->type() == QGeoMapObject::RouteType) { + qreal mpp = QLocationUtils::metersPerPixel(m_cameraData.zoomLevel(), coordinate); + QGeoPath path = o->geoShape(); + path.setWidth(mpp * 4); // MapRouteObjectQSG has a hardcoded 4 pixels width; + contains = path.contains(coordinate); + } else { + contains = o->geoShape().contains(coordinate); + } + + if (contains) + res.append(o); + } + return res; +} + void QGeoTiledMapLabsPrivate::updateMapObjects(QSGNode *root, QQuickWindow *window) { m_qsgSupport.updateMapObjects(root, window); @@ -161,6 +192,12 @@ void QGeoTiledMapLabs::removeMapObject(QGeoMapObject *obj) d->removeMapObject(obj); } +QList<QObject *> QGeoTiledMapLabs::mapObjectsAt(const QGeoCoordinate &coordinate) const +{ + Q_D(const QGeoTiledMapLabs); + return d->mapObjectsAt(coordinate); +} + QGeoTiledMapLabs::QGeoTiledMapLabs(QGeoTiledMapLabsPrivate &dd, QGeoTiledMappingManagerEngine *engine, QObject *parent) : QGeoTiledMap(dd, engine, parent) { diff --git a/src/location/labs/qgeotiledmaplabs_p.h b/src/location/labs/qgeotiledmaplabs_p.h index 4f179028..d10ec633 100644 --- a/src/location/labs/qgeotiledmaplabs_p.h +++ b/src/location/labs/qgeotiledmaplabs_p.h @@ -72,6 +72,7 @@ public: bool createMapObjectImplementation(QGeoMapObject *obj) override; void removeMapObject(QGeoMapObject *obj) override; + QList<QObject *> mapObjectsAt(const QGeoCoordinate &coordinate) const override; protected: QSGNode *updateSceneGraph(QSGNode *node, QQuickWindow *window) override; diff --git a/src/location/labs/qmapcircleobject.cpp b/src/location/labs/qmapcircleobject.cpp index d7f1d58f..5f0db29d 100644 --- a/src/location/labs/qmapcircleobject.cpp +++ b/src/location/labs/qmapcircleobject.cpp @@ -37,6 +37,7 @@ #include "qmapcircleobject_p.h" #include "qmapcircleobject_p_p.h" #include <QExplicitlySharedDataPointer> +#include <QtPositioning/qgeocircle.h> QT_BEGIN_NAMESPACE @@ -68,7 +69,30 @@ QGeoMapObject::Type QMapCircleObjectPrivate::type() const return QGeoMapObject::CircleType; } +QGeoShape QMapCircleObjectPrivate::geoShape() const +{ + return QGeoCircle(center(), radius()); +} + +void QMapCircleObjectPrivate::setGeoShape(const QGeoShape &shape) +{ + if (shape == geoShape()) + return; + const QGeoCircle circle(shape); // if shape isn't a circle, circle will be created as a default-constructed circle + const bool centerHasChanged = circle.center() != center(); + const bool radiusHasChanged = circle.radius() != radius(); + + if (centerHasChanged) + setCenter(circle.center()); // to handle overrides + if (radiusHasChanged) + setRadius(circle.radius()); // to handle overrides + + if (centerHasChanged) + emit static_cast<QMapCircleObject *>(q)->centerChanged(); + if (radiusHasChanged) + emit static_cast<QMapCircleObject *>(q)->radiusChanged(); +} // // QMapCircleObjectPrivate default implementation @@ -162,8 +186,6 @@ QGeoMapObjectPrivate *QMapCircleObjectPrivateDefault::clone() return new QMapCircleObjectPrivateDefault(static_cast<QMapCircleObjectPrivate &>(*this)); } - - QMapCircleObject::QMapCircleObject(QObject *parent) : QGeoMapObject(QExplicitlySharedDataPointer<QGeoMapObjectPrivate>(new QMapCircleObjectPrivateDefault(this)), parent) diff --git a/src/location/labs/qmapcircleobject_p_p.h b/src/location/labs/qmapcircleobject_p_p.h index b3353b62..4bf212c7 100644 --- a/src/location/labs/qmapcircleobject_p_p.h +++ b/src/location/labs/qmapcircleobject_p_p.h @@ -76,6 +76,8 @@ public: // QGeoMapObjectPrivate interface bool equals(const QGeoMapObjectPrivate &other) const override; + virtual QGeoShape geoShape() const override; + virtual void setGeoShape(const QGeoShape &shape) override; }; diff --git a/src/location/labs/qmapiconobject.cpp b/src/location/labs/qmapiconobject.cpp index be82ebbf..a0cd4d46 100644 --- a/src/location/labs/qmapiconobject.cpp +++ b/src/location/labs/qmapiconobject.cpp @@ -37,6 +37,7 @@ #include "qmapiconobject_p.h" #include "qmapiconobject_p_p.h" #include <QExplicitlySharedDataPointer> +#include <QtPositioning/QGeoCircle> QT_BEGIN_NAMESPACE @@ -91,7 +92,9 @@ QMapIconObjectPrivateDefault::QMapIconObjectPrivateDefault(const QMapIconObjectP { m_coordinate = other.coordinate(); m_content = other.content(); - m_size = other.size(); + m_iconSize = other.iconSize(); + qreal radius = QGeoCircle(other.geoShape()).radius(); + m_radius = (qIsFinite(radius)) ? radius : 100.0; } QMapIconObjectPrivateDefault::~QMapIconObjectPrivateDefault() @@ -104,9 +107,9 @@ QGeoCoordinate QMapIconObjectPrivateDefault::coordinate() const return m_coordinate; } -void QMapIconObjectPrivateDefault::setCoordinate(const QGeoCoordinate ¢er) +void QMapIconObjectPrivateDefault::setCoordinate(const QGeoCoordinate &coordinate) { - m_coordinate = center; + m_coordinate = coordinate; } QVariant QMapIconObjectPrivateDefault::content() const @@ -119,14 +122,14 @@ void QMapIconObjectPrivateDefault::setContent(const QVariant &content) m_content = content; } -QSizeF QMapIconObjectPrivateDefault::size() const +QSizeF QMapIconObjectPrivateDefault::iconSize() const { - return m_size; + return m_iconSize; } -void QMapIconObjectPrivateDefault::setSize(const QSizeF &size) +void QMapIconObjectPrivateDefault::setIconSize(const QSizeF &size) { - m_size = size; + m_iconSize = size; } QGeoMapObjectPrivate *QMapIconObjectPrivateDefault::clone() @@ -134,6 +137,30 @@ QGeoMapObjectPrivate *QMapIconObjectPrivateDefault::clone() return new QMapIconObjectPrivateDefault(static_cast<QMapIconObjectPrivate &>(*this)); } +QGeoShape QMapIconObjectPrivateDefault::geoShape() const +{ + return QGeoCircle(coordinate(), m_radius); // fixing the radius to 100 meters, as a meaningful size for + // fitting the viewport to this icon without losing context completely +} + +void QMapIconObjectPrivateDefault::setGeoShape(const QGeoShape &shape) +{ + QGeoCoordinate crd; + const QGeoCircle circle(shape); // if shape isn't a circle, circle will be created as a default-constructed circle + if (circle.isValid()) { + crd = circle.center(); + m_radius = circle.radius(); + } else { + crd = shape.boundingGeoRectangle().center(); + } + + if (crd == coordinate()) + return; + + setCoordinate(crd); + emit static_cast<QMapIconObject *>(q)->coordinateChanged(crd); +} + /* @@ -206,25 +233,25 @@ void QMapIconObject::setCoordinate(const QGeoCoordinate ¢er) } /*! - \qmlproperty Variant Qt.labs.location::MapIconObject::size + \qmlproperty Variant Qt.labs.location::MapIconObject::iconSize The size of the icon as it will be shown on the map. */ -QSizeF QMapIconObject::size() const +QSizeF QMapIconObject::iconSize() const { const QMapIconObjectPrivate *d = static_cast<const QMapIconObjectPrivate *>(d_ptr.data()); - return d->size(); + return d->iconSize(); } -void QMapIconObject::setSize(const QSizeF &size) +void QMapIconObject::setIconSize(const QSizeF &size) { QMapIconObjectPrivate *d = static_cast<QMapIconObjectPrivate*>(d_ptr.data()); - if (d->size() == size) + if (d->iconSize() == size) return; - d->setSize(size); - emit sizeChanged(); + d->setIconSize(size); + emit iconSizeChanged(); } void QMapIconObject::setMap(QGeoMap *map) diff --git a/src/location/labs/qmapiconobject_p.h b/src/location/labs/qmapiconobject_p.h index 16b00d04..6ba2f83e 100644 --- a/src/location/labs/qmapiconobject_p.h +++ b/src/location/labs/qmapiconobject_p.h @@ -61,7 +61,7 @@ class Q_LOCATION_PRIVATE_EXPORT QMapIconObject : public QGeoMapObject Q_OBJECT Q_PROPERTY(QGeoCoordinate coordinate READ coordinate WRITE setCoordinate NOTIFY coordinateChanged) Q_PROPERTY(QVariant content READ content WRITE setContent NOTIFY contentChanged) - Q_PROPERTY(QSizeF size READ size WRITE setSize NOTIFY sizeChanged) + Q_PROPERTY(QSizeF iconSize READ iconSize WRITE setIconSize NOTIFY iconSizeChanged) public: QMapIconObject(QObject *parent = nullptr); @@ -69,18 +69,18 @@ public: QVariant content() const; QGeoCoordinate coordinate() const; - QSizeF size() const; + QSizeF iconSize() const; void setContent(QVariant content); void setCoordinate(const QGeoCoordinate &coordinate); - void setSize(const QSizeF &size); + void setIconSize(const QSizeF &size); void setMap(QGeoMap *map) override; signals: void contentChanged(QVariant content); void coordinateChanged(QGeoCoordinate coordinate); - void sizeChanged(); + void iconSizeChanged(); }; QT_END_NAMESPACE diff --git a/src/location/labs/qmapiconobject_p_p.h b/src/location/labs/qmapiconobject_p_p.h index 08a1a893..01ed5b4a 100644 --- a/src/location/labs/qmapiconobject_p_p.h +++ b/src/location/labs/qmapiconobject_p_p.h @@ -66,8 +66,8 @@ public: virtual void setCoordinate(const QGeoCoordinate &coordinate) = 0; virtual QVariant content() const = 0; virtual void setContent(const QVariant &content) = 0; - virtual QSizeF size() const = 0; - virtual void setSize(const QSizeF &size) = 0; + virtual QSizeF iconSize() const = 0; + virtual void setIconSize(const QSizeF &size) = 0; // QGeoMapObjectPrivate interface bool equals(const QGeoMapObjectPrivate &other) const override; @@ -85,16 +85,19 @@ public: void setCoordinate(const QGeoCoordinate &coordinate) override; QVariant content() const override; void setContent(const QVariant &content) override; - virtual QSizeF size() const override; - virtual void setSize(const QSizeF &size) override; + virtual QSizeF iconSize() const override; + virtual void setIconSize(const QSizeF &size) override; - // QMapIconObjectPrivate interface + // QGeoMapObjectPrivate interface QGeoMapObjectPrivate *clone() override; + QGeoShape geoShape() const override; + void setGeoShape(const QGeoShape &shape) override; public: QVariant m_content; QGeoCoordinate m_coordinate; - QSizeF m_size; + QSizeF m_iconSize; + qreal m_radius = 100.0; // can be set only via setGeoShape, will be used only by private: QMapIconObjectPrivateDefault(const QMapIconObjectPrivateDefault &other) = delete; diff --git a/src/location/labs/qmapobjectview.cpp b/src/location/labs/qmapobjectview.cpp index fc583415..90234ea6 100644 --- a/src/location/labs/qmapobjectview.cpp +++ b/src/location/labs/qmapobjectview.cpp @@ -89,7 +89,8 @@ QGeoMapObject::Type QMapObjectViewPrivate::type() const */ -QMapObjectViewPrivateDefault::QMapObjectViewPrivateDefault(const QMapObjectViewPrivate &other) : QMapObjectViewPrivate(other.q) +QMapObjectViewPrivateDefault::QMapObjectViewPrivateDefault(const QMapObjectViewPrivate &other) +: QMapObjectViewPrivate(other.q), m_model(other.model()), m_delegate(other.delegate()) { } @@ -98,6 +99,26 @@ QMapObjectViewPrivateDefault::~QMapObjectViewPrivateDefault() } +QVariant QMapObjectViewPrivateDefault::model() const +{ + return m_model; +} + +void QMapObjectViewPrivateDefault::setModel(const QVariant &model) +{ + m_model = model; +} + +QQmlComponent *QMapObjectViewPrivateDefault::delegate() const +{ + return m_delegate; +} + +void QMapObjectViewPrivateDefault::setDelegate(QQmlComponent *delegate) +{ + m_delegate = delegate; +} + QMapObjectViewPrivateDefault::QMapObjectViewPrivateDefault(QGeoMapObject *q) : QMapObjectViewPrivate(q) { @@ -108,6 +129,36 @@ QGeoMapObjectPrivate *QMapObjectViewPrivateDefault::clone() return new QMapObjectViewPrivateDefault(*this); } +bool QMapObjectViewPrivateDefault::equals(const QGeoMapObjectPrivate &other) const +{ + if (other.type() != type()) + return false; + + const QMapObjectViewPrivate &o = static_cast<const QMapObjectViewPrivate &>(other); + return (QGeoMapObjectPrivate::equals(o) + && model() == o.model() + && delegate() == o.delegate()); +} + +QGeoShape QMapObjectViewPrivateDefault::geoShape() const +{ + const QMapObjectView *qq = static_cast<const QMapObjectView *>(q); + QGeoRectangle rect; + const QList<QGeoMapObject *> kids = qq->geoMapObjectChildren(); + for (const auto &kid: kids) { + if (!rect.isValid()) + rect = kid->geoShape().boundingGeoRectangle(); + else + rect = rect.united(kid->geoShape().boundingGeoRectangle()); + } + return rect; +} + +void QMapObjectViewPrivateDefault::setGeoShape(const QGeoShape &/*shape*/) +{ + // MOV doesn't support setting the geoshape. +} + /* QMapObjectView @@ -160,10 +211,11 @@ void QMapObjectView::classBegin() void QMapObjectView::componentComplete() { QGeoMapObject::componentComplete(); - if (m_delegate) - m_delegateModel->setDelegate(m_delegate); - if (m_model.isValid()) - m_delegateModel->setModel(m_model); + QMapObjectViewPrivate *d = static_cast<QMapObjectViewPrivate *>(d_ptr.data()); + if (d->delegate()) + m_delegateModel->setDelegate(d->delegate()); + if (d->model().isValid()) + m_delegateModel->setModel(d->model()); m_delegateModel->componentComplete(); } @@ -175,7 +227,8 @@ void QMapObjectView::componentComplete() */ QVariant QMapObjectView::model() const { - return m_model; + const QMapObjectViewPrivate *d = static_cast<const QMapObjectViewPrivate *>(d_ptr.data()); + return d->model(); } /*! @@ -187,14 +240,16 @@ QVariant QMapObjectView::model() const */ QQmlComponent *QMapObjectView::delegate() const { - return m_delegate; + const QMapObjectViewPrivate *d = static_cast<const QMapObjectViewPrivate *>(d_ptr.data()); + return d->delegate(); } void QMapObjectView::setModel(QVariant model) { - if (m_model == model) + QMapObjectViewPrivate *d = static_cast<QMapObjectViewPrivate *>(d_ptr.data()); + if (d->model() == model) return; - m_model = model; + d->setModel(model); if (d_ptr->m_componentCompleted) m_delegateModel->setModel(model); @@ -204,9 +259,10 @@ void QMapObjectView::setModel(QVariant model) void QMapObjectView::setDelegate(QQmlComponent *delegate) { - if (m_delegate == delegate) + QMapObjectViewPrivate *d = static_cast<QMapObjectViewPrivate *>(d_ptr.data()); + if (d->delegate() == delegate) return; - m_delegate = delegate; + d->setDelegate(delegate); if (d_ptr->m_componentCompleted) m_delegateModel->setDelegate(delegate); diff --git a/src/location/labs/qmapobjectview_p.h b/src/location/labs/qmapobjectview_p.h index 76affced..be5801d3 100644 --- a/src/location/labs/qmapobjectview_p.h +++ b/src/location/labs/qmapobjectview_p.h @@ -103,8 +103,6 @@ protected: void flushDelegateModel(); void flushUserAddedMapObjects(); - QVariant m_model; - QQmlComponent *m_delegate = nullptr; QQmlDelegateModel *m_delegateModel = nullptr; QVector<QPointer<QGeoMapObject>> m_instantiatedMapObjects; QVector<QPointer<QGeoMapObject>> m_pendingMapObjects; // for items instantiated before the map is set diff --git a/src/location/labs/qmapobjectview_p_p.h b/src/location/labs/qmapobjectview_p_p.h index 7550e209..55f45f67 100644 --- a/src/location/labs/qmapobjectview_p_p.h +++ b/src/location/labs/qmapobjectview_p_p.h @@ -65,6 +65,11 @@ public: QMapObjectViewPrivate(QGeoMapObject *q); ~QMapObjectViewPrivate() override; + virtual QVariant model() const = 0; + virtual void setModel(const QVariant &model) = 0; + virtual QQmlComponent *delegate() const = 0; + virtual void setDelegate(QQmlComponent *delegate) = 0; + virtual QGeoMapObject::Type type() const override final; }; @@ -75,10 +80,20 @@ public: QMapObjectViewPrivateDefault(const QMapObjectViewPrivate &other); ~QMapObjectViewPrivateDefault() override; + virtual QVariant model() const override; + virtual void setModel(const QVariant &model) override; + virtual QQmlComponent *delegate() const override; + virtual void setDelegate(QQmlComponent *delegate) override; // QGeoMapObjectPrivate interface public: QGeoMapObjectPrivate *clone() override; + bool equals(const QGeoMapObjectPrivate &other) const override; + virtual QGeoShape geoShape() const override; + virtual void setGeoShape(const QGeoShape &shape) override; + + QVariant m_model; + QQmlComponent *m_delegate = nullptr; }; QT_END_NAMESPACE diff --git a/src/location/labs/qmappolygonobject.cpp b/src/location/labs/qmappolygonobject.cpp index 1d495899..6ccba748 100644 --- a/src/location/labs/qmappolygonobject.cpp +++ b/src/location/labs/qmappolygonobject.cpp @@ -70,7 +70,10 @@ QMapPolygonObjectPrivateDefault::QMapPolygonObjectPrivateDefault(QGeoMapObject * QMapPolygonObjectPrivateDefault::QMapPolygonObjectPrivateDefault(const QMapPolygonObjectPrivate &other) : QMapPolygonObjectPrivate(other.q) { - m_path = other.path(); + m_path.setPath(other.path()); // to stay on the safe side + QGeoPolygon poly(other.geoShape()); // to handle holes + for (int i = 0; i < poly.holesCount(); i++) + m_path.addHole(poly.holePath(i)); m_borderColor = other.borderColor(); m_fillColor = other.fillColor(); m_borderWidth = other.borderWidth(); @@ -88,12 +91,12 @@ QGeoMapObject::Type QMapPolygonObjectPrivate::type() const QList<QGeoCoordinate> QMapPolygonObjectPrivateDefault::path() const { - return m_path; + return m_path.path(); } void QMapPolygonObjectPrivateDefault::setPath(const QList<QGeoCoordinate> &path) { - m_path = path; + m_path.setPath(path); } QColor QMapPolygonObjectPrivateDefault::fillColor() const @@ -131,6 +134,23 @@ QGeoMapObjectPrivate *QMapPolygonObjectPrivateDefault::clone() return new QMapPolygonObjectPrivateDefault(static_cast<QMapPolygonObjectPrivate &>(*this)); } +QGeoShape QMapPolygonObjectPrivateDefault::geoShape() const +{ + return m_path; +} + +void QMapPolygonObjectPrivateDefault::setGeoShape(const QGeoShape &shape) +{ + if (shape == m_path) + return; + + const QGeoPolygon poly(shape); + setPath(poly.path()); // to handle overrides + for (int i = 0; i < poly.holesCount(); i++) + m_path.addHole(poly.holePath(i)); + emit static_cast<QMapPolygonObject *>(q)->pathChanged(); +} + bool QMapPolygonObjectPrivate::equals(const QGeoMapObjectPrivate &other) const { if (other.type() != type()) // This check might be unnecessary, depending on how equals gets used @@ -138,12 +158,27 @@ bool QMapPolygonObjectPrivate::equals(const QGeoMapObjectPrivate &other) const const QMapPolygonObjectPrivate &o = static_cast<const QMapPolygonObjectPrivate &>(other); return (QGeoMapObjectPrivate::equals(o) - && path() == o.path() + && geoShape() == o.geoShape() && borderColor() == o.borderColor() && fillColor() == o.fillColor() && borderWidth() == o.borderWidth()); } +QGeoShape QMapPolygonObjectPrivate::geoShape() const +{ + return QGeoPolygon(path()); +} + +void QMapPolygonObjectPrivate::setGeoShape(const QGeoShape &shape) +{ + if (shape == geoShape()) + return; + + const QGeoPolygon poly(shape); + setPath(poly.path()); // to handle overrides + emit static_cast<QMapPolygonObject *>(q)->pathChanged(); +} + diff --git a/src/location/labs/qmappolygonobject_p_p.h b/src/location/labs/qmappolygonobject_p_p.h index d7e95d49..767765df 100644 --- a/src/location/labs/qmappolygonobject_p_p.h +++ b/src/location/labs/qmappolygonobject_p_p.h @@ -52,6 +52,7 @@ #include <QtLocation/private/qgeomapobject_p_p.h> #include <QGeoCoordinate> #include <QColor> +#include <QGeoPolygon> QT_BEGIN_NAMESPACE @@ -74,6 +75,8 @@ public: // QGeoMapObjectPrivate interface bool equals(const QGeoMapObjectPrivate &other) const override; + virtual QGeoShape geoShape() const override; + virtual void setGeoShape(const QGeoShape &shape) override; }; class Q_LOCATION_PRIVATE_EXPORT QMapPolygonObjectPrivateDefault : public QMapPolygonObjectPrivate @@ -95,9 +98,11 @@ public: // QGeoMapObjectPrivate interface QGeoMapObjectPrivate *clone() override; + virtual QGeoShape geoShape() const override; + virtual void setGeoShape(const QGeoShape &shape) override; public: - QList<QGeoCoordinate> m_path; + QGeoPolygon m_path; // small overhead compared to plain QList<QGeoCoordinate> QColor m_borderColor; QColor m_fillColor = Qt::transparent; qreal m_borderWidth = 0; diff --git a/src/location/labs/qmappolylineobject.cpp b/src/location/labs/qmappolylineobject.cpp index 1c351962..c6d3cdaf 100644 --- a/src/location/labs/qmappolylineobject.cpp +++ b/src/location/labs/qmappolylineobject.cpp @@ -37,6 +37,7 @@ #include "qmappolylineobject_p.h" #include "qmappolylineobject_p_p.h" #include <QtLocation/private/locationvaluetypehelper_p.h> +#include <QtPositioning/QGeoPath> QT_BEGIN_NAMESPACE @@ -127,6 +128,23 @@ bool QMapPolylineObjectPrivate::equals(const QGeoMapObjectPrivate &other) const && width() == o.width()); } +QGeoShape QMapPolylineObjectPrivate::geoShape() const +{ + return QGeoPath(path()); +} + +void QMapPolylineObjectPrivate::setGeoShape(const QGeoShape &shape) +{ + const QGeoPath p(shape); + if (p == path()) + return; + + setPath(p.path()); // to handle overrides + emit static_cast<QMapPolylineObject *>(q)->pathChanged(); +} + + + QGeoMapObjectPrivate *QMapPolylineObjectPrivateDefault::clone() { return new QMapPolylineObjectPrivateDefault(static_cast<QMapPolylineObjectPrivate &>(*this)); diff --git a/src/location/labs/qmappolylineobject_p_p.h b/src/location/labs/qmappolylineobject_p_p.h index 1d5919d2..a0eb3711 100644 --- a/src/location/labs/qmappolylineobject_p_p.h +++ b/src/location/labs/qmappolylineobject_p_p.h @@ -72,6 +72,8 @@ public: // QGeoMapObjectPrivate interface bool equals(const QGeoMapObjectPrivate &other) const override; + virtual QGeoShape geoShape() const override; + virtual void setGeoShape(const QGeoShape &shape) override; }; class Q_LOCATION_PRIVATE_EXPORT QMapPolylineObjectPrivateDefault : public QMapPolylineObjectPrivate diff --git a/src/location/labs/qmaprouteobject.cpp b/src/location/labs/qmaprouteobject.cpp index c3365d30..fd29954b 100644 --- a/src/location/labs/qmaprouteobject.cpp +++ b/src/location/labs/qmaprouteobject.cpp @@ -100,7 +100,7 @@ QGeoRoute QMapRouteObjectPrivate::route() const void QMapRouteObjectPrivate::setRoute(const QDeclarativeGeoRoute *route) { - Q_UNUSED(route) + Q_UNUSED(route); } bool QMapRouteObjectPrivate::equals(const QGeoMapObjectPrivate &other) const @@ -118,6 +118,16 @@ QGeoMapObjectPrivate *QMapRouteObjectPrivate::clone() return new QMapRouteObjectPrivate(*this); } +QGeoShape QMapRouteObjectPrivate::geoShape() const +{ + return route().bounds(); +} + +void QMapRouteObjectPrivate::setGeoShape(const QGeoShape &/*shape*/) +{ + // Not supported for MapRouteObject +} + /* @@ -172,7 +182,7 @@ void QMapRouteObject::setMap(QGeoMap *map) if (!map) { // Map was set, now it has ben re-set to NULL, but not inside d_ptr. // so m_map inside d_ptr can still be used to remove itself, inside the destructor. - d_ptr = new QMapRouteObjectPrivate(*d); + d_ptr = new QMapRouteObjectPrivate(*d); // This is not losing data: check MapRouteObjectPrivate::declarativeGeoRoute() // Old pimpl deleted implicitly by QExplicitlySharedDataPointer } } diff --git a/src/location/labs/qmaprouteobject_p_p.h b/src/location/labs/qmaprouteobject_p_p.h index e01b1cc6..f12f9b33 100644 --- a/src/location/labs/qmaprouteobject_p_p.h +++ b/src/location/labs/qmaprouteobject_p_p.h @@ -72,6 +72,8 @@ public: // QGeoMapObjectPrivate interface bool equals(const QGeoMapObjectPrivate &other) const override; QGeoMapObjectPrivate *clone() override; + virtual QGeoShape geoShape() const override; + virtual void setGeoShape(const QGeoShape &shape) override; }; QT_END_NAMESPACE diff --git a/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp b/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp index e0e3a6d7..1a1b102b 100644 --- a/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp +++ b/src/location/labs/qsg/qgeomapobjectqsgsupport.cpp @@ -126,7 +126,11 @@ QGeoMapObjectPrivate *QGeoMapObjectQSGSupport::createMapObjectImplementationPriv QList<QGeoMapObject *> QGeoMapObjectQSGSupport::mapObjects() const { - return QList<QGeoMapObject *>(); + QList<QGeoMapObject *> res; + for (int i = 0; i < m_mapObjects.size(); ++i) { + res.append(m_mapObjects.at(i).object.data()); + } + return res; } void QGeoMapObjectQSGSupport::removeMapObject(QGeoMapObject *obj) diff --git a/src/location/labs/qsg/qmapcircleobjectqsg.cpp b/src/location/labs/qsg/qmapcircleobjectqsg.cpp index 775016b9..32f3030b 100644 --- a/src/location/labs/qsg/qmapcircleobjectqsg.cpp +++ b/src/location/labs/qsg/qmapcircleobjectqsg.cpp @@ -50,12 +50,10 @@ QMapCircleObjectPrivateQSG::QMapCircleObjectPrivateQSG(const QMapCircleObjectPri : QMapCircleObjectPrivateDefault(other) { // Data already cloned by the *Default copy constructor, but necessary - // update operations triggered by setters overrides - setCenter(center()); - setRadius(radius()); - setColor(color()); - setBorderColor(borderColor()); - setBorderWidth(borderWidth()); + // update operations triggered only by setters overrides + updateGeometry(); + if (m_map) + emit m_map->sgNodeChanged(); } QMapCircleObjectPrivateQSG::~QMapCircleObjectPrivateQSG() @@ -77,7 +75,7 @@ void QMapCircleObjectPrivateQSG::updateCirclePath() void QMapCircleObjectPrivateQSG::updateGeometry() { if (!m_map || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator - || !qIsFinite(m_radius) || !m_center.isValid()) + || !qIsFinite(radius()) || !center().isValid()) return; const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection()); @@ -153,7 +151,7 @@ QSGNode *QMapCircleObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, QSGNode *root, QQuickWindow * /*window*/) { -// Q_UNUSED(visibleNode) // coz of -Werror=unused-but-set-parameter +// Q_UNUSED(visibleNode); // coz of -Werror=unused-but-set-parameter MapPolygonNode *node = static_cast<MapPolygonNode *>(oldNode); bool created = false; @@ -182,7 +180,7 @@ QSGNode *QMapCircleObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, void QMapCircleObjectPrivateQSG::setCenter(const QGeoCoordinate ¢er) { - m_center = center; + QMapCircleObjectPrivateDefault::setCenter(center); updateGeometry(); if (m_map) emit m_map->sgNodeChanged(); @@ -190,7 +188,7 @@ void QMapCircleObjectPrivateQSG::setCenter(const QGeoCoordinate ¢er) void QMapCircleObjectPrivateQSG::setRadius(qreal radius) { - m_radius = radius; + QMapCircleObjectPrivateDefault::setRadius(radius); updateGeometry(); if (m_map) emit m_map->sgNodeChanged(); @@ -198,7 +196,7 @@ void QMapCircleObjectPrivateQSG::setRadius(qreal radius) void QMapCircleObjectPrivateQSG::setColor(const QColor &color) { - m_fillColor = color; + QMapCircleObjectPrivateDefault::setColor(color); updateGeometry(); if (m_map) emit m_map->sgNodeChanged(); @@ -206,7 +204,7 @@ void QMapCircleObjectPrivateQSG::setColor(const QColor &color) void QMapCircleObjectPrivateQSG::setBorderColor(const QColor &color) { - m_borderColor = color; + QMapCircleObjectPrivateDefault::setBorderColor(color); updateGeometry(); if (m_map) emit m_map->sgNodeChanged(); @@ -214,7 +212,7 @@ void QMapCircleObjectPrivateQSG::setBorderColor(const QColor &color) void QMapCircleObjectPrivateQSG::setBorderWidth(qreal width) { - m_borderWidth = width; + QMapCircleObjectPrivateDefault::setBorderWidth(width); updateGeometry(); if (m_map) emit m_map->sgNodeChanged(); diff --git a/src/location/labs/qsg/qmapiconobjectqsg.cpp b/src/location/labs/qsg/qmapiconobjectqsg.cpp index 47c39695..d9a80c91 100644 --- a/src/location/labs/qsg/qmapiconobjectqsg.cpp +++ b/src/location/labs/qsg/qmapiconobjectqsg.cpp @@ -67,8 +67,10 @@ QMapIconObjectPrivateQSG::QMapIconObjectPrivateQSG(QGeoMapObject *q) QMapIconObjectPrivateQSG::QMapIconObjectPrivateQSG(const QMapIconObjectPrivate &other) : QMapIconObjectPrivateDefault(other) { + // Data already cloned by the *Default copy constructor, but necessary + // update operations triggered only by setters overrides setContent(content()); - setCoordinate(coordinate()); +// setCoordinate(coordinate()); } QMapIconObjectPrivateQSG::~QMapIconObjectPrivateQSG() @@ -99,7 +101,7 @@ QSGNode *QMapIconObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, QSGNode *root, QQuickWindow *window) { - Q_UNUSED(visibleNode) + Q_UNUSED(visibleNode); bool created = false; RootNode *node = static_cast<RootNode *>(oldNode); if (!node) { @@ -116,7 +118,7 @@ QSGNode *QMapIconObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, m_imageNode->setTexture(window->createTextureFromImage(m_image)); QRect rect = m_image.rect(); m_imageNode->setSourceRect(rect); - m_imageNode->setRect(QRectF(QPointF(0,0), m_size)); + m_imageNode->setRect(QRectF(QPointF(0,0), iconSize())); } if (m_geometryDirty) { @@ -211,9 +213,9 @@ void QMapIconObjectPrivateQSG::setContent(const QVariant &content) emit m_map->sgNodeChanged(); } -void QMapIconObjectPrivateQSG::setSize(const QSizeF &size) +void QMapIconObjectPrivateQSG::setIconSize(const QSizeF &size) { - QMapIconObjectPrivateDefault::setSize(size); + QMapIconObjectPrivateDefault::setIconSize(size); updateGeometry(); } diff --git a/src/location/labs/qsg/qmapiconobjectqsg_p_p.h b/src/location/labs/qsg/qmapiconobjectqsg_p_p.h index c57828af..abc2fe9b 100644 --- a/src/location/labs/qsg/qmapiconobjectqsg_p_p.h +++ b/src/location/labs/qsg/qmapiconobjectqsg_p_p.h @@ -77,7 +77,7 @@ public: // QGeoMapIconPrivate interface void setCoordinate(const QGeoCoordinate &coordinate) override; void setContent(const QVariant &content) override; - void setSize(const QSizeF &size) override; + void setIconSize(const QSizeF &size) override; // QGeoMapObjectPrivate QGeoMapObjectPrivate *clone() override; diff --git a/src/location/labs/qsg/qmappolygonobjectqsg.cpp b/src/location/labs/qsg/qmappolygonobjectqsg.cpp index 99a84ec5..9963cac9 100644 --- a/src/location/labs/qsg/qmappolygonobjectqsg.cpp +++ b/src/location/labs/qsg/qmappolygonobjectqsg.cpp @@ -37,22 +37,24 @@ #include "qmappolygonobjectqsg_p_p.h" #include <QtQuick/qsgnode.h> #include <QtQuick/qsgsimplerectnode.h> +#include <QtPositioning/private/qgeopolygon_p.h> QT_BEGIN_NAMESPACE QMapPolygonObjectPrivateQSG::QMapPolygonObjectPrivateQSG(QGeoMapObject *q) - : QMapPolygonObjectPrivate(q) + : QMapPolygonObjectPrivateDefault(q) { } QMapPolygonObjectPrivateQSG::QMapPolygonObjectPrivateQSG(const QMapPolygonObjectPrivate &other) - : QMapPolygonObjectPrivate(other.q) + : QMapPolygonObjectPrivateDefault(other) { - setPath(other.path()); - setFillColor(other.fillColor()); - setBorderColor(other.borderColor()); - setBorderWidth(other.borderWidth()); + // Data already cloned by the *Default copy constructor, but necessary + // update operations triggered only by setters overrides + updateGeometry(); + if (m_map) + emit m_map->sgNodeChanged(); } QMapPolygonObjectPrivateQSG::~QMapPolygonObjectPrivateQSG() @@ -69,8 +71,8 @@ QList<QDoubleVector2D> QMapPolygonObjectPrivateQSG::projectPath() const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection()); - geopathProjected_.reserve(m_geoPath.path().size()); - for (const QGeoCoordinate &c : m_geoPath.path()) + geopathProjected_.reserve(m_path.path().size()); + for (const QGeoCoordinate &c : m_path.path()) geopathProjected_ << p.geoToMapProjection(c); return geopathProjected_; } @@ -80,7 +82,7 @@ QSGNode *QMapPolygonObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, QSGNode *root, QQuickWindow * /*window*/) { - Q_UNUSED(visibleNode) + Q_UNUSED(visibleNode); MapPolygonNode *node = static_cast<MapPolygonNode *>(oldNode); bool created = false; @@ -107,29 +109,9 @@ QSGNode *QMapPolygonObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, return node; } -QList<QGeoCoordinate> QMapPolygonObjectPrivateQSG::path() const -{ - return m_geoPath.path(); -} - -QColor QMapPolygonObjectPrivateQSG::fillColor() const -{ - return m_fillColor; -} - -QColor QMapPolygonObjectPrivateQSG::borderColor() const -{ - return m_borderColor; -} - -qreal QMapPolygonObjectPrivateQSG::borderWidth() const -{ - return m_borderWidth; -} - void QMapPolygonObjectPrivateQSG::setPath(const QList<QGeoCoordinate> &path) { - m_geoPath.setPath(path); + QMapPolygonObjectPrivateDefault::setPath(path); updateGeometry(); if (m_map) @@ -138,7 +120,7 @@ void QMapPolygonObjectPrivateQSG::setPath(const QList<QGeoCoordinate> &path) void QMapPolygonObjectPrivateQSG::setFillColor(const QColor &color) { - m_fillColor = color; + QMapPolygonObjectPrivateDefault::setFillColor(color); updateGeometry(); if (m_map) @@ -147,7 +129,7 @@ void QMapPolygonObjectPrivateQSG::setFillColor(const QColor &color) void QMapPolygonObjectPrivateQSG::setBorderColor(const QColor &color) { - m_borderColor = color; + QMapPolygonObjectPrivateDefault::setBorderColor(color); updateGeometry(); if (m_map) @@ -156,7 +138,7 @@ void QMapPolygonObjectPrivateQSG::setBorderColor(const QColor &color) void QMapPolygonObjectPrivateQSG::setBorderWidth(qreal width) { - m_borderWidth = width; + QMapPolygonObjectPrivateDefault::setBorderWidth(width); updateGeometry(); if (m_map) @@ -168,9 +150,21 @@ QGeoMapObjectPrivate *QMapPolygonObjectPrivateQSG::clone() return new QMapPolygonObjectPrivateQSG(static_cast<QMapPolygonObjectPrivate &>(*this)); } +void QMapPolygonObjectPrivateQSG::setGeoShape(const QGeoShape &shape) +{ + if (shape == m_path) + return; + + m_path = QGeoPathEager(shape); + updateGeometry(); + if (m_map) + emit m_map->sgNodeChanged(); + emit static_cast<QMapPolygonObject *>(q)->pathChanged(); +} + void QMapPolygonObjectPrivateQSG::updateGeometry() { - if (!m_map || m_geoPath.path().length() == 0 + if (!m_map || m_path.path().length() == 0 || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; @@ -180,7 +174,7 @@ void QMapPolygonObjectPrivateQSG::updateGeometry() const QList<QDoubleVector2D> &geopathProjected = projectPath(); m_geometry.markSourceDirty(); - m_geometry.setPreserveGeometry(true, m_geoPath.boundingGeoRectangle().topLeft()); + m_geometry.setPreserveGeometry(true, m_path.boundingGeoRectangle().topLeft()); m_geometry.updateSourcePoints(*m_map, geopathProjected); m_geometry.updateScreenPoints(*m_map); @@ -193,7 +187,7 @@ void QMapPolygonObjectPrivateQSG::updateGeometry() closedPath << closedPath.first(); m_borderGeometry.markSourceDirty(); - m_borderGeometry.setPreserveGeometry(true, m_geoPath.boundingGeoRectangle().topLeft()); + m_borderGeometry.setPreserveGeometry(true, m_path.boundingGeoRectangle().topLeft()); const QGeoCoordinate &geometryOrigin = m_geometry.origin(); diff --git a/src/location/labs/qsg/qmappolygonobjectqsg_p_p.h b/src/location/labs/qsg/qmappolygonobjectqsg_p_p.h index b288528a..0f42a92e 100644 --- a/src/location/labs/qsg/qmappolygonobjectqsg_p_p.h +++ b/src/location/labs/qsg/qmappolygonobjectqsg_p_p.h @@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE -class Q_LOCATION_PRIVATE_EXPORT QMapPolygonObjectPrivateQSG : public QMapPolygonObjectPrivate, public QQSGMapObject +class Q_LOCATION_PRIVATE_EXPORT QMapPolygonObjectPrivateQSG : public QMapPolygonObjectPrivateDefault, public QQSGMapObject { public: QMapPolygonObjectPrivateQSG(QGeoMapObject *q); @@ -73,12 +73,7 @@ public: QSGNode *root, QQuickWindow *window) override; - // QGeoMapPolylinePrivate interface - QList<QGeoCoordinate> path() const override; - QColor fillColor() const override; - QColor borderColor() const override; - qreal borderWidth() const override; - + // QGeoMapPolygonPrivate interface void setPath(const QList<QGeoCoordinate> &path) override; void setFillColor(const QColor &color) override; void setBorderColor(const QColor &color) override; @@ -86,15 +81,12 @@ public: // QGeoMapObjectPrivate QGeoMapObjectPrivate *clone() override; + virtual void setGeoShape(const QGeoShape &shape) override; // Data Members QGeoMapPolygonGeometry m_geometry; QGeoMapPolylineGeometry m_borderGeometry; - QGeoPath m_geoPath; - QColor m_fillColor; - QColor m_borderColor; - qreal m_borderWidth = 0; bool m_updatingGeometry = false; }; diff --git a/src/location/labs/qsg/qmappolylineobjectqsg.cpp b/src/location/labs/qsg/qmappolylineobjectqsg.cpp index 5b184326..2bf5b287 100644 --- a/src/location/labs/qsg/qmappolylineobjectqsg.cpp +++ b/src/location/labs/qsg/qmappolylineobjectqsg.cpp @@ -45,18 +45,20 @@ QT_BEGIN_NAMESPACE */ QMapPolylineObjectPrivateQSG::QMapPolylineObjectPrivateQSG(QGeoMapObject *q) - : QMapPolylineObjectPrivate(q) + : QMapPolylineObjectPrivateDefault(q) { } QMapPolylineObjectPrivateQSG::QMapPolylineObjectPrivateQSG(const QMapPolylineObjectPrivate &other) - : QMapPolylineObjectPrivate(other.q) + : QMapPolylineObjectPrivateDefault(other) { - // do the appropriate internal update and trigger map repaint - setPath(other.path()); - setColor(other.color()); - setWidth(other.width()); + m_geoPath.setPath(m_path); + // rest of the data already cloned by the *Default copy constructor, but necessary + // update operations triggered only by setters overrides + updateGeometry(); + if (m_map) + emit m_map->sgNodeChanged(); } QMapPolylineObjectPrivateQSG::~QMapPolylineObjectPrivateQSG() @@ -102,7 +104,7 @@ QSGNode *QMapPolylineObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, QSGNode *root, QQuickWindow * /*window*/) { - Q_UNUSED(visibleNode) + Q_UNUSED(visibleNode); MapPolylineNode *node = static_cast<MapPolylineNode *>(oldNode); bool created = false; @@ -127,24 +129,23 @@ QSGNode *QMapPolylineObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode, return node; } -QList<QGeoCoordinate> QMapPolylineObjectPrivateQSG::path() const { return m_geoPath.path(); } - -QColor QMapPolylineObjectPrivateQSG::color() const { return m_color; } - -qreal QMapPolylineObjectPrivateQSG::width() const { return m_width; } +QList<QGeoCoordinate> QMapPolylineObjectPrivateQSG::path() const +{ + return m_geoPath.path(); +} void QMapPolylineObjectPrivateQSG::setPath(const QList<QGeoCoordinate> &path) { + m_path = path; m_geoPath.setPath(path); updateGeometry(); - if (m_map) emit m_map->sgNodeChanged(); } void QMapPolylineObjectPrivateQSG::setColor(const QColor &color) { - m_color = color; + QMapPolylineObjectPrivateDefault::setColor(color); updateGeometry(); if (m_map) @@ -153,7 +154,7 @@ void QMapPolylineObjectPrivateQSG::setColor(const QColor &color) void QMapPolylineObjectPrivateQSG::setWidth(qreal width) { - m_width = width; + QMapPolylineObjectPrivateDefault::setWidth(width); updateGeometry(); if (m_map) @@ -165,4 +166,9 @@ QGeoMapObjectPrivate *QMapPolylineObjectPrivateQSG::clone() return new QMapPolylineObjectPrivateQSG(static_cast<QMapPolylineObjectPrivate &>(*this)); } +QGeoShape QMapPolylineObjectPrivateQSG::geoShape() const +{ + return m_geoPath; +} + QT_END_NAMESPACE diff --git a/src/location/labs/qsg/qmappolylineobjectqsg_p_p.h b/src/location/labs/qsg/qmappolylineobjectqsg_p_p.h index 792413e5..e8eb5839 100644 --- a/src/location/labs/qsg/qmappolylineobjectqsg_p_p.h +++ b/src/location/labs/qsg/qmappolylineobjectqsg_p_p.h @@ -54,10 +54,11 @@ #include <QtLocation/private/qmappolylineobject_p.h> #include <QtLocation/private/qqsgmapobject_p.h> #include <QtCore/qscopedvaluerollback.h> +#include <QtPositioning/private/qgeopath_p.h> QT_BEGIN_NAMESPACE -class Q_LOCATION_PRIVATE_EXPORT QMapPolylineObjectPrivateQSG : public QMapPolylineObjectPrivate, public QQSGMapObject +class Q_LOCATION_PRIVATE_EXPORT QMapPolylineObjectPrivateQSG : public QMapPolylineObjectPrivateDefault, public QQSGMapObject { public: QMapPolylineObjectPrivateQSG(QGeoMapObject *q); @@ -75,22 +76,17 @@ public: // QGeoMapPolylinePrivate interface QList<QGeoCoordinate> path() const override; - QColor color() const override; - qreal width() const override; - void setPath(const QList<QGeoCoordinate> &path) override; void setColor(const QColor &color) override; void setWidth(qreal width) override; // QGeoMapObjectPrivate QGeoMapObjectPrivate *clone() override; + virtual QGeoShape geoShape() const override; // Data Members + QGeoPathEager m_geoPath; QGeoMapPolylineGeometry m_geometry; - QGeoPath m_geoPath; - - QColor m_color; - qreal m_width = 0; bool m_updatingGeometry = false; }; diff --git a/src/location/labs/qsg/qmaprouteobjectqsg.cpp b/src/location/labs/qsg/qmaprouteobjectqsg.cpp index eaea64f3..8f347f88 100644 --- a/src/location/labs/qsg/qmaprouteobjectqsg.cpp +++ b/src/location/labs/qsg/qmaprouteobjectqsg.cpp @@ -100,4 +100,9 @@ void QMapRouteObjectPrivateQSG::setVisible(bool visible) m_polyline->setVisible(visible); } +QGeoShape QMapRouteObjectPrivateQSG::geoShape() const +{ + return m_polyline->geoShape(); +} + QT_END_NAMESPACE diff --git a/src/location/labs/qsg/qmaprouteobjectqsg_p_p.h b/src/location/labs/qsg/qmaprouteobjectqsg_p_p.h index 0c946259..2ade5d53 100644 --- a/src/location/labs/qsg/qmaprouteobjectqsg_p_p.h +++ b/src/location/labs/qsg/qmaprouteobjectqsg_p_p.h @@ -80,6 +80,7 @@ public: QGeoMapObjectPrivate *clone() override; void setMap(QGeoMap *map) override; void setVisible(bool visible) override; + virtual QGeoShape geoShape() const override; // Data Members QScopedPointer<QMapPolylineObjectPrivateQSG> m_polyline; |