diff options
99 files changed, 2912 insertions, 917 deletions
diff --git a/.qmake.conf b/.qmake.conf index aefa1e70..b1c22d3b 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,3 +1,3 @@ load(qt_build_config) -MODULE_VERSION = 5.8.0 +MODULE_VERSION = 5.9.0 diff --git a/examples/location/mapviewer/main.cpp b/examples/location/mapviewer/main.cpp index 1b526435..a58dcd44 100644 --- a/examples/location/mapviewer/main.cpp +++ b/examples/location/mapviewer/main.cpp @@ -89,6 +89,24 @@ int main(int argc, char *argv[]) QVariantMap parameters; QStringList args(QCoreApplication::arguments()); + // Fetch tokens from the environment, if present + const QByteArray mapboxMapID = qgetenv("MAPBOX_MAP_ID"); + const QByteArray mapboxAccessToken = qgetenv("MAPBOX_ACCESS_TOKEN"); + const QByteArray hereAppID = qgetenv("HERE_APP_ID"); + const QByteArray hereToken = qgetenv("HERE_TOKEN"); + const QByteArray esriToken = qgetenv("ESRI_TOKEN"); + + if (!mapboxMapID.isEmpty()) + parameters["mapbox.map_id"] = QString::fromLocal8Bit(mapboxMapID); + if (!mapboxAccessToken.isEmpty()) + parameters["mapbox.access_token"] = QString::fromLocal8Bit(mapboxAccessToken); + if (!hereAppID.isEmpty()) + parameters["here.app_id"] = QString::fromLocal8Bit(hereAppID); + if (!hereToken.isEmpty()) + parameters["here.token"] = QString::fromLocal8Bit(hereToken); + if (!esriToken.isEmpty()) + parameters["esri.token"] = QString::fromLocal8Bit(esriToken); + if (parseArgs(args, parameters)) return 0; if (!args.contains(QStringLiteral("osm.useragent"))) diff --git a/examples/location/places/main.cpp b/examples/location/places/main.cpp index 8c3b64ed..a30fb857 100644 --- a/examples/location/places/main.cpp +++ b/examples/location/places/main.cpp @@ -90,6 +90,24 @@ int main(int argc, char *argv[]) QVariantMap parameters; QStringList args(QCoreApplication::arguments()); + // Fetch tokens from the environment, if present + const QByteArray mapboxMapID = qgetenv("MAPBOX_MAP_ID"); + const QByteArray mapboxAccessToken = qgetenv("MAPBOX_ACCESS_TOKEN"); + const QByteArray hereAppID = qgetenv("HERE_APP_ID"); + const QByteArray hereToken = qgetenv("HERE_TOKEN"); + const QByteArray esriToken = qgetenv("ESRI_TOKEN"); + + if (!mapboxMapID.isEmpty()) + parameters["mapbox.map_id"] = QString::fromLocal8Bit(mapboxMapID); + if (!mapboxAccessToken.isEmpty()) + parameters["mapbox.access_token"] = QString::fromLocal8Bit(mapboxAccessToken); + if (!hereAppID.isEmpty()) + parameters["here.app_id"] = QString::fromLocal8Bit(hereAppID); + if (!hereToken.isEmpty()) + parameters["here.token"] = QString::fromLocal8Bit(hereToken); + if (!esriToken.isEmpty()) + parameters["esri.token"] = QString::fromLocal8Bit(esriToken); + if (parseArgs(args, parameters)) return 0; diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp index 6405313b..f9b3545f 100644 --- a/src/imports/location/location.cpp +++ b/src/imports/location/location.cpp @@ -49,6 +49,7 @@ #include "qdeclarativeroutemapitem_p.h" #include "qdeclarativepolylinemapitem_p.h" #include "qdeclarativepolygonmapitem_p.h" +#include "qdeclarativegeomapparameter_p.h" //Place includes #include "qdeclarativecategory_p.h" @@ -166,6 +167,11 @@ public: minor = 7; qmlRegisterType<QDeclarativeGeoManeuver>(uri, major, minor, "RouteManeuver"); + // Register the 5.9 types + minor = 9; + qmlRegisterType<QDeclarativeGeoMapParameter>(uri, major, minor, "MapParameter"); + + //registrations below are version independent qRegisterMetaType<QPlaceCategory>(); qRegisterMetaType<QPlace>(); diff --git a/src/imports/location/location.pro b/src/imports/location/location.pro index 57172ad8..e733a768 100644 --- a/src/imports/location/location.pro +++ b/src/imports/location/location.pro @@ -30,7 +30,8 @@ HEADERS += \ qquickgeomapgesturearea_p.h\ ../positioning/qquickgeocoordinateanimation_p.h \ mapitemviewdelegateincubator.h \ - qdeclarativegeomapitemview_p_p.h + qdeclarativegeomapitemview_p_p.h \ + qdeclarativegeomapparameter_p.h SOURCES += \ location.cpp \ @@ -56,7 +57,8 @@ SOURCES += \ locationvaluetypehelper.cpp \ qquickgeomapgesturearea.cpp \ ../positioning/qquickgeocoordinateanimation.cpp \ - mapitemviewdelegateincubator.cpp + mapitemviewdelegateincubator.cpp \ + qdeclarativegeomapparameter.cpp include(declarativeplaces/declarativeplaces.pri) diff --git a/src/imports/location/qdeclarativecirclemapitem.cpp b/src/imports/location/qdeclarativecirclemapitem.cpp index 6890703b..c440664c 100644 --- a/src/imports/location/qdeclarativecirclemapitem.cpp +++ b/src/imports/location/qdeclarativecirclemapitem.cpp @@ -46,6 +46,7 @@ #include <QPainter> #include "qdoublevector2d_p.h" +#include "qlocationutils_p.h" /* poly2tri triangulator includes */ #include "../../3rdparty/poly2tri/common/shapes.h" @@ -294,12 +295,8 @@ static void calculatePeripheralPoints(QList<QGeoCoordinate> &path, qreal resultLonRad = lonRad + std::atan2(std::sin(azimuthRad) * cosLatRad_x_sinRatio, cosRatio - sinLatRad * std::sin(resultLatRad)); qreal lat2 = qgeocoordinate_radToDeg(resultLatRad); - qreal lon2 = qgeocoordinate_radToDeg(resultLonRad); - if (lon2 < -180.0) { - lon2 += 360.0; - } else if (lon2 > 180.0) { - lon2 -= 360.0; - } + qreal lon2 = QLocationUtils::wrapLong(qgeocoordinate_radToDeg(resultLonRad)); + path << QGeoCoordinate(lat2, lon2, center.altitude()); // Consider only points in the left half of the circle for the left bound. if (azimuthRad > M_PI) { diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp index 0450bf56..d432e776 100644 --- a/src/imports/location/qdeclarativegeomap.cpp +++ b/src/imports/location/qdeclarativegeomap.cpp @@ -42,6 +42,7 @@ #include "qgeomappingmanager_p.h" #include "qgeocameracapabilities_p.h" #include "qgeomap_p.h" +#include "qdeclarativegeomapparameter_p.h" #include <QtPositioning/QGeoCircle> #include <QtPositioning/QGeoRectangle> #include <QtQuick/QQuickWindow> @@ -158,7 +159,6 @@ static const qreal EARTH_MEAN_RADIUS = 6371007.2; QDeclarativeGeoMap::QDeclarativeGeoMap(QQuickItem *parent) : QQuickItem(parent), m_plugin(0), - m_serviceProvider(0), m_mappingManager(0), m_activeMapType(0), m_gestureArea(new QQuickGeoMapGestureArea(this)), @@ -331,11 +331,11 @@ void QDeclarativeGeoMap::initialize() */ void QDeclarativeGeoMap::pluginReady() { - m_serviceProvider = m_plugin->sharedGeoServiceProvider(); - m_mappingManager = m_serviceProvider->mappingManager(); + QGeoServiceProvider *provider = m_plugin->sharedGeoServiceProvider(); + m_mappingManager = provider->mappingManager(); - if (m_serviceProvider->error() != QGeoServiceProvider::NoError) { - setError(m_serviceProvider->error(), m_serviceProvider->errorString()); + if (provider->error() != QGeoServiceProvider::NoError) { + setError(provider->error(), provider->errorString()); return; } @@ -360,6 +360,7 @@ void QDeclarativeGeoMap::pluginReady() void QDeclarativeGeoMap::componentComplete() { m_componentCompleted = true; + populateParameters(); populateMap(); QQuickItem::componentComplete(); } @@ -455,6 +456,19 @@ void QDeclarativeGeoMap::populateMap() } } +void QDeclarativeGeoMap::populateParameters() +{ + QObjectList kids = children(); + QList<QQuickItem *> quickKids = childItems(); + for (int i = 0; i < quickKids.count(); ++i) + kids.append(quickKids.at(i)); + for (int i = 0; i < kids.size(); ++i) { + QDeclarativeGeoMapParameter *mapParameter = qobject_cast<QDeclarativeGeoMapParameter *>(kids.at(i)); + if (mapParameter) + addMapParameter(mapParameter); + } +} + /*! \internal */ @@ -590,6 +604,11 @@ void QDeclarativeGeoMap::mappingManagerInitialized() if (item) item.data()->setMap(this, m_map); } + + // All map parameters that were added before the plugin was ready + // need to be added to m_map + for (QDeclarativeGeoMapParameter *p : m_mapParameters) + m_map->addParameter(p); } /*! @@ -803,7 +822,7 @@ void QDeclarativeGeoMap::setVisibleRegion(const QGeoShape &shape) return; } - if (!width() || !height()) { + if (!m_map || !width() || !height()) { m_pendingFitViewport = true; return; } @@ -1210,6 +1229,95 @@ void QDeclarativeGeoMap::addMapItem(QDeclarativeGeoMapItemBase *item) } /*! + \qmlmethod void QtLocation::Map::addMapParameter(MapParameter parameter) + + Adds a MapParameter object to the map. The effect of this call is dependent + on the combination of the content of the MapParameter and the type of + underlying QGeoMap. If a MapParameter that is not supported by the underlying + QGeoMap gets added, the call has no effect. + + The release of this API with Qt 5.9 is a Technology Preview. + + \sa MapParameter, removeMapParameter, mapParameters, clearMapParameters + + \since 5.9 +*/ +void QDeclarativeGeoMap::addMapParameter(QDeclarativeGeoMapParameter *parameter) +{ + if (!parameter->isComponentComplete()) { + connect(parameter, &QDeclarativeGeoMapParameter::completed, this, &QDeclarativeGeoMap::addMapParameter); + return; + } + + disconnect(parameter); + if (m_mapParameters.contains(parameter)) + return; + parameter->setParent(this); + m_mapParameters.insert(parameter); // parameter now owned by QDeclarativeGeoMap + if (m_map) + m_map->addParameter(parameter); +} + +/*! + \qmlmethod void QtLocation::Map::removeMapParameter(MapParameter parameter) + + Removes the given MapParameter object from the map. + + The release of this API with Qt 5.9 is a Technology Preview. + + \sa MapParameter, addMapParameter, mapParameters, clearMapParameters + + \since 5.9 +*/ +void QDeclarativeGeoMap::removeMapParameter(QDeclarativeGeoMapParameter *parameter) +{ + if (!m_mapParameters.contains(parameter)) + return; + if (m_map) + m_map->removeParameter(parameter); + m_mapParameters.remove(parameter); +} + +/*! + \qmlmethod void QtLocation::Map::clearMapParameters() + + Removes all map parameters from the map. + + The release of this API with Qt 5.9 is a Technology Preview. + + \sa MapParameter, mapParameters, addMapParameter, removeMapParameter, clearMapParameters + + \since 5.9 +*/ +void QDeclarativeGeoMap::clearMapParameters() +{ + if (m_map) + m_map->clearParameters(); + m_mapParameters.clear(); +} + +/*! + \qmlproperty list<MapParameters> QtLocation::Map::mapParameters + + Returns the list of all map parameters in no particular order. + These items include map parameters that were declared statically as part of + the type declaration, as well as dynamical map parameters (\l addMapParameter). + + The release of this API with Qt 5.9 is a Technology Preview. + + \sa MapParameter, addMapParameter, removeMapParameter, clearMapParameters + + \since 5.9 +*/ +QList<QObject *> QDeclarativeGeoMap::mapParameters() +{ + QList<QObject *> ret; + for (QDeclarativeGeoMapParameter *p : m_mapParameters) + ret << p; + return ret; +} + +/*! \qmlproperty list<MapItem> QtLocation::Map::mapItems Returns the list of all map items in no particular order. @@ -1312,11 +1420,26 @@ void QDeclarativeGeoMap::geometryChanged(const QRectF &newGeometry, const QRectF m_map->setViewportSize(newGeometry.size().toSize()); - if (!m_initialized) + if (!m_initialized) { initialize(); - else + } else { setMinimumZoomLevel(m_map->minimumZoomAtViewportSize(newGeometry.width(), newGeometry.height())); + // Update the center latitudinal threshold + double maximumCenterLatitudeAtZoom = m_map->maximumCenterLatitudeAtZoom(m_cameraData.zoomLevel()); + if (maximumCenterLatitudeAtZoom != m_maximumViewportLatitude) { + m_maximumViewportLatitude = maximumCenterLatitudeAtZoom; + QGeoCoordinate coord = m_cameraData.center(); + coord.setLatitude(qBound(-m_maximumViewportLatitude, coord.latitude(), m_maximumViewportLatitude)); + + if (coord != m_cameraData.center()) { + m_cameraData.setCenter(coord); + m_map->setCameraData(m_cameraData); + emit centerChanged(m_cameraData.center()); + } + } + } + /*! The fitViewportTo*() functions depend on a valid map geometry. If they were called prior to the first resize they cause diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h index 262314ed..e0940f97 100644 --- a/src/imports/location/qdeclarativegeomap_p.h +++ b/src/imports/location/qdeclarativegeomap_p.h @@ -54,6 +54,7 @@ #include "qgeocameradata_p.h" #include <QtQuick/QQuickItem> #include <QtCore/QPointer> +#include <QtCore/QSet> #include <QtGui/QColor> #include <QtPositioning/qgeoshape.h> @@ -62,6 +63,7 @@ QT_BEGIN_NAMESPACE class QDeclarativeGeoServiceProvider; class QDeclarativeGeoMapType; class QDeclarativeGeoMapCopyrightNotice; +class QDeclarativeGeoMapParameter; class QDeclarativeGeoMap : public QQuickItem { @@ -76,6 +78,7 @@ class QDeclarativeGeoMap : public QQuickItem Q_PROPERTY(QQmlListProperty<QDeclarativeGeoMapType> supportedMapTypes READ supportedMapTypes NOTIFY supportedMapTypesChanged) Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter NOTIFY centerChanged) Q_PROPERTY(QList<QObject *> mapItems READ mapItems NOTIFY mapItemsChanged) + Q_PROPERTY(QList<QObject *> mapParameters READ mapParameters) Q_PROPERTY(QGeoServiceProvider::Error error READ error NOTIFY errorChanged) Q_PROPERTY(QString errorString READ errorString NOTIFY errorChanged) Q_PROPERTY(QGeoShape visibleRegion READ visibleRegion WRITE setVisibleRegion) @@ -119,9 +122,15 @@ public: Q_INVOKABLE void removeMapItem(QDeclarativeGeoMapItemBase *item); Q_INVOKABLE void addMapItem(QDeclarativeGeoMapItemBase *item); + Q_INVOKABLE void clearMapItems(); QList<QObject *> mapItems(); + Q_INVOKABLE void addMapParameter(QDeclarativeGeoMapParameter *parameter); + Q_INVOKABLE void removeMapParameter(QDeclarativeGeoMapParameter *parameter); + Q_INVOKABLE void clearMapParameters(); + QList<QObject *> mapParameters(); + Q_INVOKABLE QGeoCoordinate toCoordinate(const QPointF &position, bool clipToViewPort = true) const; Q_INVOKABLE QPointF fromCoordinate(const QGeoCoordinate &coordinate, bool clipToViewPort = true) const; @@ -177,13 +186,13 @@ private Q_SLOTS: private: void setupMapView(QDeclarativeGeoMapItemView *view); void populateMap(); + void populateParameters(); void fitViewportToMapItemsRefine(bool refine); void fitViewportToGeoShape(); bool isInteractive(); private: QDeclarativeGeoServiceProvider *m_plugin; - QGeoServiceProvider *m_serviceProvider; QGeoMappingManager *m_mappingManager; QDeclarativeGeoMapType *m_activeMapType; QList<QDeclarativeGeoMapType *> m_supportedMapTypes; @@ -203,6 +212,7 @@ private: double m_maximumViewportLatitude; bool m_initialized; bool m_validRegion; + QSet<QDeclarativeGeoMapParameter *> m_mapParameters; friend class QDeclarativeGeoMapItem; friend class QDeclarativeGeoMapItemView; diff --git a/src/imports/location/qdeclarativegeomapitemview_p_p.h b/src/imports/location/qdeclarativegeomapitemview_p_p.h index 5a4e3b25..3ad3ceb4 100644 --- a/src/imports/location/qdeclarativegeomapitemview_p_p.h +++ b/src/imports/location/qdeclarativegeomapitemview_p_p.h @@ -60,7 +60,9 @@ class MapItemViewDelegateIncubator; class QDeclarativeGeoMapItemView; class QDeclarativeGeoMapItemBase; -struct QDeclarativeGeoMapItemViewItemData { +class QDeclarativeGeoMapItemViewItemData +{ +public: QDeclarativeGeoMapItemViewItemData() : incubator(0), item(0), context(0), modelData(0), modelDataMeta(0) { diff --git a/src/imports/location/qdeclarativegeomapparameter.cpp b/src/imports/location/qdeclarativegeomapparameter.cpp new file mode 100644 index 00000000..88d609f4 --- /dev/null +++ b/src/imports/location/qdeclarativegeomapparameter.cpp @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeomapparameter_p.h" + +#include <QByteArray> +#include <QMetaObject> +#include <QMetaProperty> +#include <QSignalMapper> + +QT_BEGIN_NAMESPACE + +/*! + \qmltype MapParameter + \instantiates QDeclarativeGeoMapParameter + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.9 + + \brief The MapParameter type represents a parameter for a Map element. + This type provides a mean to specify plugin-dependent optional parameters + for a map. + + MapParameters by default contain only the \l type property, and + are highly plugin-dependent. + For this reason, additional properties have to be defined inside a + MapParameter at declaration time, using the QML syntax "property var foo". + + What properties have to be put inside a particular MapParameter type for + a particular plugin can be found in the documentation of the plugin. + Note that MapProperties are \b optional. + By not specifying any of them, the Map will have the default behavior. + + The release of this API with Qt 5.9 is a Technology Preview. +*/ + +/*! + \qmlproperty georectangle QtLocation::MapParameter::type + + Set-once property which holds a string defining the type of the MapParameter +*/ + +QDeclarativeGeoMapParameter::QDeclarativeGeoMapParameter(QObject *parent) +: QGeoMapParameter(parent), m_initialPropertyCount(metaObject()->propertyCount()), m_complete(false) +{ + +} + +QDeclarativeGeoMapParameter::~QDeclarativeGeoMapParameter() +{ +} + +bool QDeclarativeGeoMapParameter::isComponentComplete() const +{ + return m_complete; +} + +int QDeclarativeGeoMapParameter::initialPropertyCount() const +{ + return m_initialPropertyCount; +} + +void QDeclarativeGeoMapParameter::classBegin() +{ +} + +void QDeclarativeGeoMapParameter::componentComplete() +{ + for (int i = m_initialPropertyCount; i < metaObject()->propertyCount(); ++i) { + QMetaProperty property = metaObject()->property(i); + + if (!property.hasNotifySignal()) { + return; + } + + QSignalMapper *mapper = new QSignalMapper(this); + mapper->setMapping(this, i); + + const QByteArray signalName = '2' + property.notifySignal().methodSignature(); // TODO: explain why '2' + QObject::connect(this, signalName, mapper, SLOT(map())); + QObject::connect(mapper, SIGNAL(mapped(int)), this, SLOT(onPropertyUpdated(int))); + } + m_complete = true; + emit completed(this); +} + +void QDeclarativeGeoMapParameter::onPropertyUpdated(int index) +{ + emit propertyUpdated(this, metaObject()->property(index).name()); +} + +QT_END_NAMESPACE diff --git a/src/imports/location/qdeclarativegeomapparameter_p.h b/src/imports/location/qdeclarativegeomapparameter_p.h new file mode 100644 index 00000000..31ea5b04 --- /dev/null +++ b/src/imports/location/qdeclarativegeomapparameter_p.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDECLARATIVEGEOMAPPARAMETER_P_H +#define QDECLARATIVEGEOMAPPARAMETER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtLocation/private/qgeomapparameter_p.h> +#include <QQmlParserStatus> +#include <qqml.h> + +QT_BEGIN_NAMESPACE + +class QDeclarativeGeoMapParameter : public QGeoMapParameter, public QQmlParserStatus +{ + Q_OBJECT + Q_INTERFACES(QQmlParserStatus) + +public: + explicit QDeclarativeGeoMapParameter(QObject *parent = 0); + virtual ~QDeclarativeGeoMapParameter(); + + bool isComponentComplete() const; + +Q_SIGNALS: + void completed(QDeclarativeGeoMapParameter *); + +protected: + int initialPropertyCount() const; + // QQmlParserStatus implementation + void classBegin() override; + void componentComplete() override; + +private slots: + void onPropertyUpdated(int index); + +private: + int m_initialPropertyCount; + bool m_complete; +}; + +QT_END_NAMESPACE + +QML_DECLARE_TYPE(QDeclarativeGeoMapParameter) + +#endif // QDECLARATIVEGEOMAPPARAMETER_P_H diff --git a/src/imports/location/qdeclarativegeoroutemodel.cpp b/src/imports/location/qdeclarativegeoroutemodel.cpp index 0c64c23a..af01d25d 100644 --- a/src/imports/location/qdeclarativegeoroutemodel.cpp +++ b/src/imports/location/qdeclarativegeoroutemodel.cpp @@ -120,7 +120,6 @@ QDeclarativeGeoRouteModel::QDeclarativeGeoRouteModel(QObject *parent) complete_(false), plugin_(0), routeQuery_(0), - reply_(0), autoUpdate_(false), status_(QDeclarativeGeoRouteModel::Null), error_(QDeclarativeGeoRouteModel::NoError) @@ -133,7 +132,6 @@ QDeclarativeGeoRouteModel::~QDeclarativeGeoRouteModel() qDeleteAll(routes_); routes_.clear(); } - delete reply_; } /*! @@ -168,7 +166,7 @@ void QDeclarativeGeoRouteModel::reset() endResetModel(); } - abortRequest(); + emit abortRequested(); setError(NoError, QString()); setStatus(QDeclarativeGeoRouteModel::Null); } @@ -181,25 +179,12 @@ void QDeclarativeGeoRouteModel::reset() */ void QDeclarativeGeoRouteModel::cancel() { - abortRequest(); + emit abortRequested(); setError(NoError, QString()); setStatus(routes_.isEmpty() ? Null : Ready); } /*! - \internal -*/ -void QDeclarativeGeoRouteModel::abortRequest() -{ - if (reply_) { - reply_->abort(); - reply_->deleteLater(); - reply_ = 0; - } -} - - -/*! \qmlmethod void QtLocation::RouteModel::get(int) Returns the Route at given index. Use \l count property to check the @@ -589,7 +574,7 @@ void QDeclarativeGeoRouteModel::update() setError(ParseError,"Cannot route, valid query not set."); return; } - abortRequest(); // Clear previus requests + emit abortRequested(); // Clear previous requests QGeoRouteRequest request = routeQuery_->routeRequest(); if (request.waypoints().count() < 2) { setError(ParseError,tr("Not enough waypoints for routing.")); @@ -598,13 +583,15 @@ void QDeclarativeGeoRouteModel::update() setError(NoError, QString()); - reply_ = routingManager->calculateRoute(request); + QGeoRouteReply *reply = routingManager->calculateRoute(request); setStatus(QDeclarativeGeoRouteModel::Loading); - if (reply_->isFinished()) { - if (reply_->error() == QGeoRouteReply::NoError) { - routingFinished(reply_); + if (!reply->isFinished()) { + connect(this, &QDeclarativeGeoRouteModel::abortRequested, reply, &QGeoRouteReply::abort); + } else { + if (reply->error() == QGeoRouteReply::NoError) { + routingFinished(reply); } else { - routingError(reply_, reply_->error(), reply_->errorString()); + routingError(reply, reply->error(), reply->errorString()); } } } @@ -614,7 +601,10 @@ void QDeclarativeGeoRouteModel::update() */ void QDeclarativeGeoRouteModel::routingFinished(QGeoRouteReply *reply) { - if (reply != reply_ || reply->error() != QGeoRouteReply::NoError) + if (!reply) + return; + reply->deleteLater(); + if (reply->error() != QGeoRouteReply::NoError) return; beginResetModel(); @@ -632,9 +622,6 @@ void QDeclarativeGeoRouteModel::routingFinished(QGeoRouteReply *reply) setError(NoError, QString()); setStatus(QDeclarativeGeoRouteModel::Ready); - reply->deleteLater(); - reply_ = 0; - if (oldCount != 0 || routes_.count() != 0) emit routesChanged(); if (oldCount != routes_.count()) @@ -648,12 +635,11 @@ void QDeclarativeGeoRouteModel::routingError(QGeoRouteReply *reply, QGeoRouteReply::Error error, const QString &errorString) { - if (reply != reply_) + if (!reply) return; + reply->deleteLater(); setError(static_cast<QDeclarativeGeoRouteModel::RouteError>(error), errorString); setStatus(QDeclarativeGeoRouteModel::Error); - reply->deleteLater(); - reply_ = 0; } diff --git a/src/imports/location/qdeclarativegeoroutemodel_p.h b/src/imports/location/qdeclarativegeoroutemodel_p.h index 66769ea7..30fc1ecc 100644 --- a/src/imports/location/qdeclarativegeoroutemodel_p.h +++ b/src/imports/location/qdeclarativegeoroutemodel_p.h @@ -155,6 +155,7 @@ Q_SIGNALS: void errorChanged(); //emitted also for errorString notification void routesChanged(); void measurementSystemChanged(); + void abortRequested(); public Q_SLOTS: void update(); @@ -170,13 +171,11 @@ private Q_SLOTS: private: void setStatus(Status status); void setError(RouteError error, const QString &errorString); - void abortRequest(); bool complete_; QDeclarativeGeoServiceProvider *plugin_; QDeclarativeGeoRouteQuery *routeQuery_; - QGeoRouteReply *reply_; QList<QDeclarativeGeoRoute *> routes_; bool autoUpdate_; diff --git a/src/imports/location/qdeclarativepolygonmapitem.cpp b/src/imports/location/qdeclarativepolygonmapitem.cpp index 32dbb206..41196770 100644 --- a/src/imports/location/qdeclarativepolygonmapitem.cpp +++ b/src/imports/location/qdeclarativepolygonmapitem.cpp @@ -150,8 +150,6 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, if (!sourceDirty_) return; - double minX = -1.0; - // build the actual path QDoubleVector2D origin; QDoubleVector2D lastPoint; @@ -182,13 +180,10 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, if (i == 0) { origin = point; - minX = point.x(); srcOrigin_ = coord; srcPath_.moveTo(point.toPointF() - origin.toPointF()); lastPoint = point; } else { - if (point.x() <= minX) - minX = point.x(); const QDoubleVector2D diff = (point - lastPoint); if (diff.x() * diff.x() + diff.y() * diff.y() >= 3.0) { srcPath_.lineTo(point.toPointF() - origin.toPointF()); @@ -203,7 +198,6 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, srcPath_ = srcPath_.simplified(); sourceBounds_ = srcPath_.boundingRect(); - geoLeftBound_ = map.itemPositionToCoordinate(QDoubleVector2D(minX, 0), false); } /*! diff --git a/src/imports/location/qquickgeomapgesturearea.cpp b/src/imports/location/qquickgeomapgesturearea.cpp index 0baaf98e..3d881ae2 100644 --- a/src/imports/location/qquickgeomapgesturearea.cpp +++ b/src/imports/location/qquickgeomapgesturearea.cpp @@ -1017,6 +1017,7 @@ void QQuickGeoMapGestureArea::updatePinch() // Add to starting zoom level. Sign of (dist-pinchstartdist) takes care of zoom in / out m_pinch.m_zoom.m_start; } + m_pinch.m_event.setCenter(mapFromScene(m_sceneCenter)); m_pinch.m_event.setAngle(m_twoTouchAngle); diff --git a/src/imports/positioning/locationsingleton.cpp b/src/imports/positioning/locationsingleton.cpp index f12486b0..a48c1a96 100644 --- a/src/imports/positioning/locationsingleton.cpp +++ b/src/imports/positioning/locationsingleton.cpp @@ -179,6 +179,19 @@ QGeoCircle LocationSingleton::circle(const QGeoCoordinate ¢er, qreal radius) } /*! + \qmlmethod geopath QtPositioning::path() const + + Constructs an empty geopath. + + \sa {geopath} + \since 5.9 +*/ +QGeoPath LocationSingleton::path() const +{ + return QGeoPath(); +} + +/*! \qmlmethod geocircle QtPositioning::shapeToCircle(geoshape shape) const Converts \a shape to a geocircle. @@ -204,3 +217,16 @@ QGeoRectangle LocationSingleton::shapeToRectangle(const QGeoShape &shape) const return QGeoRectangle(shape); } +/*! + \qmlmethod geopath QtPositioning::shapeToPath(geoshape shape) const + + Converts \a shape to a geopath. + + \sa {geopath} + \since 5.9 +*/ +QGeoPath LocationSingleton::shapeToPath(const QGeoShape &shape) const +{ + return QGeoPath(shape); +} + diff --git a/src/imports/positioning/locationsingleton.h b/src/imports/positioning/locationsingleton.h index cc4ea5ce..9a5320e0 100644 --- a/src/imports/positioning/locationsingleton.h +++ b/src/imports/positioning/locationsingleton.h @@ -46,6 +46,7 @@ #include <QtPositioning/QGeoShape> #include <QtPositioning/QGeoRectangle> #include <QtPositioning/QGeoCircle> +#include <QtPositioning/QGeoPath> #include <QVariant> class LocationSingleton : public QObject @@ -71,8 +72,11 @@ public: Q_INVOKABLE QGeoCircle circle() const; Q_INVOKABLE QGeoCircle circle(const QGeoCoordinate ¢er, qreal radius = -1.0) const; + Q_INVOKABLE QGeoPath path() const; + Q_INVOKABLE QGeoCircle shapeToCircle(const QGeoShape &shape) const; Q_INVOKABLE QGeoRectangle shapeToRectangle(const QGeoShape &shape) const; + Q_INVOKABLE QGeoPath shapeToPath(const QGeoShape &shape) const; }; #endif // LOCATIONSINGLETON_H diff --git a/src/imports/positioning/positioning.cpp b/src/imports/positioning/positioning.cpp index 4c54c211..b7914e5d 100644 --- a/src/imports/positioning/positioning.cpp +++ b/src/imports/positioning/positioning.cpp @@ -55,6 +55,7 @@ #include <QtPositioning/QGeoRectangle> #include <QtPositioning/QGeoCircle> +#include <QtPositioning/QGeoPath> #include <QtPositioning/QGeoLocation> #include <QtCore/QDebug> @@ -527,6 +528,8 @@ public: QMetaType::registerEqualsComparator<QGeoRectangle>(); qRegisterMetaType<QGeoCircle>(); QMetaType::registerEqualsComparator<QGeoCircle>(); + qRegisterMetaType<QGeoPath>(); + QMetaType::registerEqualsComparator<QGeoPath>(); qRegisterMetaType<QGeoLocation>(); qRegisterMetaType<QGeoShape>(); QMetaType::registerEqualsComparator<QGeoShape>(); diff --git a/src/location/maps/maps.pri b/src/location/maps/maps.pri index 1ea54208..3f76f737 100644 --- a/src/location/maps/maps.pri +++ b/src/location/maps/maps.pri @@ -18,6 +18,7 @@ PUBLIC_HEADERS += \ maps/qgeoserviceprovider.h PRIVATE_HEADERS += \ + maps/qgeomapparameter_p.h \ maps/qgeocameracapabilities_p.h \ maps/qgeocameradata_p.h \ maps/qgeocameratiles_p.h \ @@ -91,4 +92,5 @@ SOURCES += \ maps/qgeotiledmapscene.cpp \ maps/qgeorouteparser.cpp \ maps/qgeorouteparserosrmv5.cpp \ - maps/qgeorouteparserosrmv4.cpp + maps/qgeorouteparserosrmv4.cpp \ + maps/qgeomapparameter.cpp diff --git a/src/location/maps/qgeocodereply.cpp b/src/location/maps/qgeocodereply.cpp index 47018217..d5112a69 100644 --- a/src/location/maps/qgeocodereply.cpp +++ b/src/location/maps/qgeocodereply.cpp @@ -233,6 +233,7 @@ void QGeoCodeReply::abort() { if (!isFinished()) setFinished(true); + emit aborted(); } /*! diff --git a/src/location/maps/qgeocodereply.h b/src/location/maps/qgeocodereply.h index 048493b4..c92bc606 100644 --- a/src/location/maps/qgeocodereply.h +++ b/src/location/maps/qgeocodereply.h @@ -80,6 +80,7 @@ public: Q_SIGNALS: void finished(); + void aborted(); void error(QGeoCodeReply::Error error, const QString &errorString = QString()); protected: diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index 0e0a2007..ac6d661b 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -130,6 +130,32 @@ void QGeoMap::clearData() } +void QGeoMap::addParameter(QGeoMapParameter *param) +{ + Q_D(QGeoMap); + if (param && !d->m_mapParameters.contains(param)) { + d->m_mapParameters.insert(param); + d->addParameter(param); + } +} + +void QGeoMap::removeParameter(QGeoMapParameter *param) +{ + Q_D(QGeoMap); + if (param && d->m_mapParameters.contains(param)) { + d->removeParameter(param); + d->m_mapParameters.remove(param); + } +} + +void QGeoMap::clearParameters() +{ + Q_D(QGeoMap); + for (QGeoMapParameter *p : d->m_mapParameters) + d->removeParameter(p); + d->m_mapParameters.clear(); +} + QGeoMapPrivate::QGeoMapPrivate(QGeoMappingManagerEngine *engine) : QObjectPrivate(), m_engine(engine), @@ -141,4 +167,14 @@ QGeoMapPrivate::~QGeoMapPrivate() { } +void QGeoMapPrivate::addParameter(QGeoMapParameter *param) +{ + Q_UNUSED(param) +} + +void QGeoMapPrivate::removeParameter(QGeoMapParameter *param) +{ + Q_UNUSED(param) +} + QT_END_NAMESPACE diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h index ea4806c0..7a12820f 100644 --- a/src/location/maps/qgeomap_p.h +++ b/src/location/maps/qgeomap_p.h @@ -61,6 +61,7 @@ class QGeoCameraCapabilities; class QGeoCoordinate; class QSGNode; class QQuickWindow; +class QGeoMapParameter; class Q_LOCATION_EXPORT QGeoMap : public QObject { @@ -94,6 +95,10 @@ public: virtual void prefetchData(); virtual void clearData(); + void addParameter(QGeoMapParameter *param); + void removeParameter(QGeoMapParameter *param); + void clearParameters(); + protected: QGeoMap(QGeoMapPrivate &dd, QObject *parent = 0); void setCameraData(const QGeoCameraData &cameraData); @@ -108,7 +113,6 @@ Q_SIGNALS: private: Q_DISABLE_COPY(QGeoMap) - friend class QGeoMapController; //setCameraData friend class QDeclarativeGeoMap; //updateSceneGraph }; diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h index b95c1dc7..91938903 100644 --- a/src/location/maps/qgeomap_p_p.h +++ b/src/location/maps/qgeomap_p_p.h @@ -52,6 +52,7 @@ #include <QtLocation/private/qgeomaptype_p.h> #include <QtCore/private/qobject_p.h> #include <QtCore/QSize> +#include <QtCore/QSet> QT_BEGIN_NAMESPACE @@ -59,6 +60,7 @@ QT_BEGIN_NAMESPACE class QGeoMappingManagerEngine; class QGeoMap; class QGeoMapController; +class QGeoMapParameter; class Q_LOCATION_PRIVATE_EXPORT QGeoMapPrivate : public QObjectPrivate { @@ -69,6 +71,9 @@ public: protected: /* Hooks into the actual map implementations */ + virtual void addParameter(QGeoMapParameter *param); + virtual void removeParameter(QGeoMapParameter *param); + virtual void changeViewportSize(const QSize &size) = 0; // called by QGeoMap::setSize() virtual void changeCameraData(const QGeoCameraData &oldCameraData) = 0; // called by QGeoMap::setCameraData() virtual void changeActiveMapType(const QGeoMapType mapType) = 0; // called by QGeoMap::setActiveMapType() @@ -76,9 +81,9 @@ protected: protected: QSize m_viewportSize; QPointer<QGeoMappingManagerEngine> m_engine; - QGeoMapController *m_controller; QGeoCameraData m_cameraData; QGeoMapType m_activeMapType; + QSet<QGeoMapParameter *> m_mapParameters; }; QT_END_NAMESPACE diff --git a/src/location/maps/qgeomapparameter.cpp b/src/location/maps/qgeomapparameter.cpp new file mode 100644 index 00000000..b8f9561f --- /dev/null +++ b/src/location/maps/qgeomapparameter.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qgeomapparameter_p.h" +#include <QtCore/QVariant> + +QT_BEGIN_NAMESPACE + +QGeoMapParameter::QGeoMapParameter(QObject *parent) : QObject(parent) +{ + +} + +QGeoMapParameter::~QGeoMapParameter() +{ +} + +QString QGeoMapParameter::type() const +{ + return m_type; +} + +void QGeoMapParameter::setType(const QString &type) +{ + if (m_type.isEmpty()) + m_type = type; +} + +// DO NOT USE to set "type" +void QGeoMapParameter::updateProperty(const char *propertyName, QVariant value) +{ + setProperty(propertyName, value); + // This should technically be emitted only for dynamically added properties. + // Since this object has only type defined as Q_PROPERTY() which is a set-once + // no check is really needed here. + emit propertyUpdated(this, propertyName); +} + +QT_END_NAMESPACE + diff --git a/src/location/maps/qgeomapparameter_p.h b/src/location/maps/qgeomapparameter_p.h new file mode 100644 index 00000000..c3bef4d8 --- /dev/null +++ b/src/location/maps/qgeomapparameter_p.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QGEOMAPPARAMETER_P_H +#define QGEOMAPPARAMETER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QObject> +#include <QString> +#include <QtLocation/qlocationglobal.h> + +QT_BEGIN_NAMESPACE + +class Q_LOCATION_EXPORT QGeoMapParameter : public QObject +{ + Q_OBJECT + + Q_PROPERTY(QString type READ type WRITE setType) +public: + explicit QGeoMapParameter(QObject *parent = 0); + virtual ~QGeoMapParameter(); + + QString type() const; + void setType(const QString &type); + + void updateProperty(const char *propertyName, QVariant value); + +Q_SIGNALS: + void propertyUpdated(QGeoMapParameter *param, const char *propertyName); + +protected: + QString m_type; + + Q_DISABLE_COPY(QGeoMapParameter) + friend class QGeoMap; +}; + +QT_END_NAMESPACE + +#endif // QGEOMAPPARAMETER_P_H diff --git a/src/location/maps/qgeoroutereply.cpp b/src/location/maps/qgeoroutereply.cpp index ab869d3c..b1c98349 100644 --- a/src/location/maps/qgeoroutereply.cpp +++ b/src/location/maps/qgeoroutereply.cpp @@ -218,8 +218,7 @@ void QGeoRouteReply::addRoutes(const QList<QGeoRoute> &routes) */ void QGeoRouteReply::abort() { - if (!isFinished()) - setFinished(true); + emit aborted(); } /*! diff --git a/src/location/maps/qgeoroutereply.h b/src/location/maps/qgeoroutereply.h index 318d85f8..c1d6e8d1 100644 --- a/src/location/maps/qgeoroutereply.h +++ b/src/location/maps/qgeoroutereply.h @@ -74,6 +74,7 @@ public: Q_SIGNALS: void finished(); + void aborted(); void error(QGeoRouteReply::Error error, const QString &errorString = QString()); protected: diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp index 04f9ad21..a3cad550 100644 --- a/src/location/maps/qgeotiledmap.cpp +++ b/src/location/maps/qgeotiledmap.cpp @@ -60,6 +60,17 @@ QGeoTiledMap::QGeoTiledMap(QGeoTiledMappingManagerEngine *engine, QObject *paren this,&QGeoTiledMap::handleTileVersionChanged); } +QGeoTiledMap::QGeoTiledMap(QGeoTiledMapPrivate &dd, QGeoTiledMappingManagerEngine *engine, QObject *parent) + : QGeoMap(dd, parent) +{ + Q_D(QGeoTiledMap); + + d->m_tileRequests = new QGeoTileRequestManager(this, engine); + + QObject::connect(engine,&QGeoTiledMappingManagerEngine::tileVersionChanged, + this,&QGeoTiledMap::handleTileVersionChanged); +} + QGeoTiledMap::~QGeoTiledMap() { Q_D(QGeoTiledMap); diff --git a/src/location/maps/qgeotiledmap_p.h b/src/location/maps/qgeotiledmap_p.h index d00a1ed9..b148b59c 100644 --- a/src/location/maps/qgeotiledmap_p.h +++ b/src/location/maps/qgeotiledmap_p.h @@ -49,10 +49,10 @@ #include <QObject> #include <QString> - -#include "qgeomap_p.h" -#include "qgeocameradata_p.h" -#include "qgeomaptype_p.h" +#include <QtLocation/private/qlocationglobal_p.h> +#include <QtLocation/private/qgeomap_p.h> +#include <QtLocation/private/qgeocameradata_p.h> +#include <QtLocation/private/qgeomaptype_p.h> #include <QtPositioning/private/qdoublevector2d_p.h> @@ -70,7 +70,7 @@ class QSGNode; class QPointF; -class Q_LOCATION_EXPORT QGeoTiledMap : public QGeoMap +class Q_LOCATION_PRIVATE_EXPORT QGeoTiledMap : public QGeoMap { Q_OBJECT Q_DECLARE_PRIVATE(QGeoTiledMap) @@ -103,6 +103,8 @@ protected: QSGNode *updateSceneGraph(QSGNode *, QQuickWindow *window) Q_DECL_OVERRIDE; virtual void evaluateCopyrights(const QSet<QGeoTileSpec> &visibleTiles); + QGeoTiledMap(QGeoTiledMapPrivate &dd, QGeoTiledMappingManagerEngine *engine, QObject *parent); + private Q_SLOTS: void handleTileVersionChanged(); diff --git a/src/location/maps/qgeotiledmap_p_p.h b/src/location/maps/qgeotiledmap_p_p.h index 01646d66..72873d77 100644 --- a/src/location/maps/qgeotiledmap_p_p.h +++ b/src/location/maps/qgeotiledmap_p_p.h @@ -47,9 +47,10 @@ // We mean it. // -#include "qgeomap_p_p.h" -#include "qgeocameradata_p.h" -#include "qgeomaptype_p.h" +#include <QtLocation/private/qlocationglobal_p.h> +#include <QtLocation/private/qgeomap_p_p.h> +#include <QtLocation/private/qgeocameradata_p.h> +#include <QtLocation/private/qgeomaptype_p.h> #include <QtPositioning/private/qdoublevector3d_p.h> #include <QtPositioning/private/qdoublevector2d_p.h> #include <QtCore/QPointer> @@ -66,7 +67,7 @@ class QGeoTileSpec; class QSGNode; class QQuickWindow; -class QGeoTiledMapPrivate : public QGeoMapPrivate +class Q_LOCATION_PRIVATE_EXPORT QGeoTiledMapPrivate : public QGeoMapPrivate { Q_DECLARE_PUBLIC(QGeoTiledMap) public: @@ -89,10 +90,9 @@ protected: void changeTileVersion(int version); void clearScene(); -private: void updateScene(); -private: +protected: QAbstractGeoTileCache *m_cache; QGeoCameraTiles *m_visibleTiles; QGeoCameraTiles *m_prefetchTiles; @@ -101,7 +101,6 @@ private: int m_maxZoomLevel; int m_minZoomLevel; QGeoTiledMap::PrefetchStyle m_prefetchStyle; - bool m_geomoteryUpdated; Q_DISABLE_COPY(QGeoTiledMapPrivate) }; diff --git a/src/location/maps/qgeotiledmapreply.cpp b/src/location/maps/qgeotiledmapreply.cpp index f2dfd9eb..34ca041f 100644 --- a/src/location/maps/qgeotiledmapreply.cpp +++ b/src/location/maps/qgeotiledmapreply.cpp @@ -242,6 +242,7 @@ void QGeoTiledMapReply::abort() { if (!isFinished()) setFinished(true); + emit aborted(); } /* diff --git a/src/location/maps/qgeotiledmapreply_p.h b/src/location/maps/qgeotiledmapreply_p.h index 91852cc3..fc991bb7 100644 --- a/src/location/maps/qgeotiledmapreply_p.h +++ b/src/location/maps/qgeotiledmapreply_p.h @@ -88,6 +88,7 @@ public: Q_SIGNALS: void finished(); + void aborted(); void error(QGeoTiledMapReply::Error error, const QString &errorString = QString()); protected: diff --git a/src/location/places/qplacereply.cpp b/src/location/places/qplacereply.cpp index 0590871d..582987b4 100644 --- a/src/location/places/qplacereply.cpp +++ b/src/location/places/qplacereply.cpp @@ -199,6 +199,7 @@ QPlaceReply::Error QPlaceReply::error() const */ void QPlaceReply::abort() { + emit aborted(); } /*! diff --git a/src/location/places/qplacereply.h b/src/location/places/qplacereply.h index 374c68b3..3eb3d6cc 100644 --- a/src/location/places/qplacereply.h +++ b/src/location/places/qplacereply.h @@ -86,6 +86,7 @@ public Q_SLOTS: Q_SIGNALS: void finished(); + void aborted(); void error(QPlaceReply::Error error, const QString &errorString = QString()); protected: diff --git a/src/plugins/geoservices/esri/geocodereply_esri.cpp b/src/plugins/geoservices/esri/geocodereply_esri.cpp index a7ad9368..f1dac184 100644 --- a/src/plugins/geoservices/esri/geocodereply_esri.cpp +++ b/src/plugins/geoservices/esri/geocodereply_esri.cpp @@ -51,11 +51,17 @@ QT_BEGIN_NAMESPACE GeoCodeReplyEsri::GeoCodeReplyEsri(QNetworkReply *reply, OperationType operationType, QObject *parent) : - QGeoCodeReply(parent), m_reply(reply), m_operationType(operationType) + QGeoCodeReply(parent), m_operationType(operationType) { - connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } + connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + connect(this, &QGeoCodeReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); setLimit(1); setOffset(0); @@ -63,49 +69,25 @@ GeoCodeReplyEsri::GeoCodeReplyEsri(QNetworkReply *reply, OperationType operation GeoCodeReplyEsri::~GeoCodeReplyEsri() { - if (m_reply) - m_reply->deleteLater(); -} - -void GeoCodeReplyEsri::abort() -{ - if (!m_reply) - return; - - m_reply->abort(); - QGeoCodeReply::abort(); - - m_reply->deleteLater(); - m_reply = Q_NULLPTR; } void GeoCodeReplyEsri::networkReplyError(QNetworkReply::NetworkError error) { Q_UNUSED(error) - - if (!m_reply) - return; - - setError(QGeoCodeReply::CommunicationError, m_reply->errorString()); - - m_reply->deleteLater(); - m_reply = Q_NULLPTR; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + setError(QGeoCodeReply::CommunicationError, reply->errorString()); } void GeoCodeReplyEsri::networkReplyFinished() { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) - { - setError(QGeoCodeReply::CommunicationError, m_reply->errorString()); - m_reply->deleteLater(); - m_reply = Q_NULLPTR; + if (reply->error() != QNetworkReply::NoError) return; - } - QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); if (document.isObject()) { QJsonObject object = document.object(); @@ -148,9 +130,6 @@ void GeoCodeReplyEsri::networkReplyFinished() } else { setError(QGeoCodeReply::CommunicationError, QStringLiteral("Unknown document")); } - - m_reply->deleteLater(); - m_reply = Q_NULLPTR; } QGeoLocation GeoCodeReplyEsri::parseAddress(const QJsonObject& object) diff --git a/src/plugins/geoservices/esri/geocodereply_esri.h b/src/plugins/geoservices/esri/geocodereply_esri.h index 4434b7dc..a857599b 100644 --- a/src/plugins/geoservices/esri/geocodereply_esri.h +++ b/src/plugins/geoservices/esri/geocodereply_esri.h @@ -58,9 +58,7 @@ public: public: GeoCodeReplyEsri(QNetworkReply *reply, OperationType operationType, QObject *parent = Q_NULLPTR); - virtual ~GeoCodeReplyEsri(); - - void abort() Q_DECL_OVERRIDE; + ~GeoCodeReplyEsri(); inline OperationType operationType() const; @@ -72,7 +70,6 @@ private Q_SLOTS: QGeoLocation parseCandidate(const QJsonObject &candidate); private: - QNetworkReply *m_reply; OperationType m_operationType; }; diff --git a/src/plugins/geoservices/esri/georoutereply_esri.cpp b/src/plugins/geoservices/esri/georoutereply_esri.cpp index 4a7d5c67..811ffd0d 100644 --- a/src/plugins/geoservices/esri/georoutereply_esri.cpp +++ b/src/plugins/geoservices/esri/georoutereply_esri.cpp @@ -48,43 +48,32 @@ QT_BEGIN_NAMESPACE GeoRouteReplyEsri::GeoRouteReplyEsri(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent) : - QGeoRouteReply(request, parent), m_reply(reply) + QGeoRouteReply(request, parent) { - connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } + connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + connect(this, &QGeoRouteReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } GeoRouteReplyEsri::~GeoRouteReplyEsri() { - if (m_reply) - m_reply->deleteLater(); -} - -void GeoRouteReplyEsri::abort() -{ - if (!m_reply) - return; - - m_reply->abort(); - m_reply->deleteLater(); - m_reply = Q_NULLPTR; } void GeoRouteReplyEsri::networkReplyFinished() { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) - { - setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); - m_reply->deleteLater(); - m_reply = Q_NULLPTR; + if (reply->error() != QNetworkReply::NoError) return; - } - QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); GeoRouteJsonParserEsri parser(document); if (parser.isValid()) @@ -94,21 +83,14 @@ void GeoRouteReplyEsri::networkReplyFinished() } else { setError(QGeoRouteReply::ParseError, parser.errorString()); } - - m_reply->deleteLater(); - m_reply = Q_NULLPTR; } void GeoRouteReplyEsri::networkReplyError(QNetworkReply::NetworkError error) { Q_UNUSED(error) - - if (!m_reply) - return; - - setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); - m_reply->deleteLater(); - m_reply = Q_NULLPTR; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + setError(QGeoRouteReply::CommunicationError, reply->errorString()); } QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/georoutereply_esri.h b/src/plugins/geoservices/esri/georoutereply_esri.h index 6e97ee9f..049dc3ba 100644 --- a/src/plugins/geoservices/esri/georoutereply_esri.h +++ b/src/plugins/geoservices/esri/georoutereply_esri.h @@ -51,16 +51,11 @@ class GeoRouteReplyEsri : public QGeoRouteReply public: GeoRouteReplyEsri(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent = Q_NULLPTR); - virtual ~GeoRouteReplyEsri(); - - void abort() Q_DECL_OVERRIDE; + ~GeoRouteReplyEsri(); private Q_SLOTS: void networkReplyFinished(); void networkReplyError(QNetworkReply::NetworkError error); - -private: - QNetworkReply *m_reply; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp b/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp index e0816c15..f4431bf0 100644 --- a/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp +++ b/src/plugins/geoservices/esri/geotiledmapreply_esri.cpp @@ -49,50 +49,32 @@ static const unsigned char gifSignature[] = {0x47, 0x49, 0x46, 0x38, 0x00}; GeoTiledMapReplyEsri::GeoTiledMapReplyEsri(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent) : - QGeoTiledMapReply(spec, parent), m_reply(reply) + QGeoTiledMapReply(spec, parent) { - connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } + connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); - connect(m_reply, SIGNAL(destroyed()), this, SLOT(replyDestroyed())); + connect(this, &QGeoTiledMapReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } GeoTiledMapReplyEsri::~GeoTiledMapReplyEsri() { - if (m_reply) { - m_reply->deleteLater(); - m_reply = Q_NULLPTR; - } -} - -void GeoTiledMapReplyEsri::abort() -{ - if (!m_reply) - return; - - m_reply->abort(); - QGeoTiledMapReply::abort(); -} - -void GeoTiledMapReplyEsri::replyDestroyed() -{ - m_reply = Q_NULLPTR; } void GeoTiledMapReplyEsri::networkReplyFinished() { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) - { - setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); - m_reply->deleteLater(); - m_reply = Q_NULLPTR; + if (reply->error() != QNetworkReply::NoError) return; - } - QByteArray const& imageData = m_reply->readAll(); + QByteArray const& imageData = reply->readAll(); bool validFormat = true; if (imageData.startsWith(reinterpret_cast<const char*>(pngSignature))) @@ -108,22 +90,16 @@ void GeoTiledMapReplyEsri::networkReplyFinished() setMapImageData(imageData); setFinished(true); - - m_reply->deleteLater(); - m_reply = Q_NULLPTR; } void GeoTiledMapReplyEsri::networkReplyError(QNetworkReply::NetworkError error) { - if (!m_reply) - return; - - if (error != QNetworkReply::OperationCanceledError) - setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); - - setFinished(true); - m_reply->deleteLater(); - m_reply = Q_NULLPTR; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + if (error == QNetworkReply::OperationCanceledError) + setFinished(true); + else + setError(QGeoTiledMapReply::CommunicationError, reply->errorString()); } QT_END_NAMESPACE diff --git a/src/plugins/geoservices/esri/geotiledmapreply_esri.h b/src/plugins/geoservices/esri/geotiledmapreply_esri.h index 32a35698..b459e943 100644 --- a/src/plugins/geoservices/esri/geotiledmapreply_esri.h +++ b/src/plugins/geoservices/esri/geotiledmapreply_esri.h @@ -52,17 +52,11 @@ class GeoTiledMapReplyEsri : public QGeoTiledMapReply public: GeoTiledMapReplyEsri(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent = Q_NULLPTR); - virtual ~GeoTiledMapReplyEsri(); - - void abort() Q_DECL_OVERRIDE; + ~GeoTiledMapReplyEsri(); private Q_SLOTS: - void replyDestroyed(); void networkReplyFinished(); void networkReplyError(QNetworkReply::NetworkError error); - -private: - QNetworkReply *m_reply; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/mapbox/qgeomapreplymapbox.cpp b/src/plugins/geoservices/mapbox/qgeomapreplymapbox.cpp index 5fe9caa8..4b60231d 100644 --- a/src/plugins/geoservices/mapbox/qgeomapreplymapbox.cpp +++ b/src/plugins/geoservices/mapbox/qgeomapreplymapbox.cpp @@ -39,59 +39,42 @@ #include <QtLocation/private/qgeotilespec_p.h> QGeoMapReplyMapbox::QGeoMapReplyMapbox(QNetworkReply *reply, const QGeoTileSpec &spec, const QString &format, QObject *parent) -: QGeoTiledMapReply(spec, parent), m_reply(reply), m_format (format) +: QGeoTiledMapReply(spec, parent), m_format (format) { - connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } + connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + connect(this, &QGeoTiledMapReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } QGeoMapReplyMapbox::~QGeoMapReplyMapbox() { - if (m_reply) { - m_reply->deleteLater(); - m_reply = 0; - } -} - -void QGeoMapReplyMapbox::abort() -{ - if (!m_reply) - return; - - m_reply->abort(); -} - -QNetworkReply *QGeoMapReplyMapbox::networkReply() const -{ - return m_reply; } void QGeoMapReplyMapbox::networkReplyFinished() { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) + if (reply->error() != QNetworkReply::NoError) return; - setMapImageData(m_reply->readAll()); + setMapImageData(reply->readAll()); setMapImageFormat(m_format); setFinished(true); - - m_reply->deleteLater(); - m_reply = 0; } void QGeoMapReplyMapbox::networkReplyError(QNetworkReply::NetworkError error) { - if (!m_reply) - return; - - if (error != QNetworkReply::OperationCanceledError) - setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); - - setFinished(true); - m_reply->deleteLater(); - m_reply = 0; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + if (error == QNetworkReply::OperationCanceledError) + setFinished(true); + else + setError(QGeoTiledMapReply::CommunicationError, reply->errorString()); } diff --git a/src/plugins/geoservices/mapbox/qgeomapreplymapbox.h b/src/plugins/geoservices/mapbox/qgeomapreplymapbox.h index 67ad61ad..c4a1dd82 100644 --- a/src/plugins/geoservices/mapbox/qgeomapreplymapbox.h +++ b/src/plugins/geoservices/mapbox/qgeomapreplymapbox.h @@ -51,16 +51,11 @@ public: explicit QGeoMapReplyMapbox(QNetworkReply *reply, const QGeoTileSpec &spec, const QString &format, QObject *parent = 0); ~QGeoMapReplyMapbox(); - void abort(); - - QNetworkReply *networkReply() const; - private Q_SLOTS: void networkReplyFinished(); void networkReplyError(QNetworkReply::NetworkError error); private: - QPointer<QNetworkReply> m_reply; QString m_format; }; diff --git a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp index 4c98412b..8fc3386a 100644 --- a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp +++ b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.cpp @@ -84,28 +84,21 @@ static QList<QGeoCoordinate> parseGeometry(const QJsonValue &geometry) QGeoRouteReplyMapbox::QGeoRouteReplyMapbox(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent) -: QGeoRouteReply(request, parent), m_reply(reply) +: QGeoRouteReply(request, parent) { - connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } + connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + connect(this, &QGeoRouteReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } QGeoRouteReplyMapbox::~QGeoRouteReplyMapbox() { - if (m_reply) - m_reply->deleteLater(); -} - -void QGeoRouteReplyMapbox::abort() -{ - if (!m_reply) - return; - - m_reply->abort(); - - m_reply->deleteLater(); - m_reply = 0; } static QGeoRoute constructRoute(const QJsonObject &obj) @@ -177,25 +170,19 @@ static QGeoRoute constructRoute(const QJsonObject &obj) void QGeoRouteReplyMapbox::networkReplyFinished() { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) { - setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); - m_reply->deleteLater(); - m_reply = 0; + if (reply->error() != QNetworkReply::NoError) return; - } - QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); if (document.isObject()) { QJsonObject object = document.object(); QString status = object.value(QStringLiteral("code")).toString(); if (status != QStringLiteral("Ok")) { setError(QGeoRouteReply::UnknownError, object.value(QStringLiteral("message")).toString()); - m_reply->deleteLater(); - m_reply = 0; return; } @@ -210,22 +197,14 @@ void QGeoRouteReplyMapbox::networkReplyFinished() } else { setError(QGeoRouteReply::ParseError, QStringLiteral("Couldn't parse json.")); } - - m_reply->deleteLater(); - m_reply = 0; } void QGeoRouteReplyMapbox::networkReplyError(QNetworkReply::NetworkError error) { Q_UNUSED(error) - - if (!m_reply) - return; - - setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); - - m_reply->deleteLater(); - m_reply = 0; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + setError(QGeoRouteReply::CommunicationError, reply->errorString()); } QT_END_NAMESPACE diff --git a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.h b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.h index 9df45ac4..f19faee7 100644 --- a/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.h +++ b/src/plugins/geoservices/mapbox/qgeoroutereplymapbox.h @@ -55,14 +55,9 @@ public: QGeoRouteReplyMapbox(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent = 0); ~QGeoRouteReplyMapbox(); - void abort() Q_DECL_OVERRIDE; - private Q_SLOTS: void networkReplyFinished(); void networkReplyError(QNetworkReply::NetworkError error); - -private: - QNetworkReply *m_reply; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp index d6ef8f0a..f5776852 100644 --- a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp +++ b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp @@ -89,10 +89,19 @@ QGeoRouteReply* QGeoRoutingManagerEngineMapbox::calculateRoute(const QGeoRouteRe foreach (const QGeoCoordinate &c, request.waypoints()) { url += QString("%1,%2;").arg(c.longitude()).arg(c.latitude()); } - if (url.right(1) == ";") url.chop(1); - url += QString("?steps=true&overview=full&geometries=geojson&access_token=%1").arg(m_accessToken); - - networkRequest.setUrl(QUrl(url)); + if (url.right(1) == ";") + url.chop(1); + + QUrlQuery query; + query.addQueryItem(QStringLiteral("steps"), QStringLiteral("true")); + query.addQueryItem(QStringLiteral("alternatives"), QStringLiteral("true")); + query.addQueryItem(QStringLiteral("overview"), QStringLiteral("full")); + query.addQueryItem(QStringLiteral("geometries"), QStringLiteral("geojson")); + query.addQueryItem(QStringLiteral("access_token"), m_accessToken); + + QUrl u(url); + u.setQuery(query); + networkRequest.setUrl(u); QNetworkReply *reply = m_networkManager->get(networkRequest); QGeoRouteReplyMapbox *routeReply = new QGeoRouteReplyMapbox(reply, request, this); diff --git a/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp index 9a5cbf48..f67fa5bb 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp +++ b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.cpp @@ -48,30 +48,26 @@ QT_BEGIN_NAMESPACE QPlaceContentReplyImpl::QPlaceContentReplyImpl(const QPlaceContentRequest &request, QNetworkReply *reply, QPlaceManagerEngineNokiaV2 *engine) - : QPlaceContentReply(engine), m_reply(reply), m_engine(engine) + : QPlaceContentReply(engine), m_engine(engine) { Q_ASSERT(engine); - setRequest(request); - - if (!m_reply) + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); return; + } + setRequest(request); - m_reply->setParent(this); - connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError))); + connect(this, &QPlaceReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } QPlaceContentReplyImpl::~QPlaceContentReplyImpl() { } -void QPlaceContentReplyImpl::abort() -{ - if (m_reply) - m_reply->abort(); -} - void QPlaceContentReplyImpl::setError(QPlaceReply::Error error_, const QString &errorString) { QPlaceContentReply::setError(error_, errorString); @@ -82,31 +78,32 @@ void QPlaceContentReplyImpl::setError(QPlaceReply::Error error_, const QString & void QPlaceContentReplyImpl::replyFinished() { - if (m_reply->isOpen()) { - QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); - if (!document.isObject()) { - setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); - return; - } - - QJsonObject object = document.object(); - - QPlaceContent::Collection collection; - int totalCount; - QPlaceContentRequest previous; - QPlaceContentRequest next; - - parseCollection(request().contentType(), object, &collection, &totalCount, - &previous, &next, m_engine); - - setTotalCount(totalCount); - setContent(collection); - setPreviousPageRequest(previous); - setNextPageRequest(next); + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) + return; + + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); + if (!document.isObject()) { + setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); + return; } - m_reply->deleteLater(); - m_reply = 0; + QJsonObject object = document.object(); + + QPlaceContent::Collection collection; + int totalCount; + QPlaceContentRequest previous; + QPlaceContentRequest next; + + parseCollection(request().contentType(), object, &collection, &totalCount, + &previous, &next, m_engine); + + setTotalCount(totalCount); + setContent(collection); + setPreviousPageRequest(previous); + setNextPageRequest(next); setFinished(true); emit finished(); @@ -114,13 +111,12 @@ void QPlaceContentReplyImpl::replyFinished() void QPlaceContentReplyImpl::replyError(QNetworkReply::NetworkError error) { - switch (error) { - case QNetworkReply::OperationCanceledError: - setError(CancelError, "Request canceled."); - break; - default: - setError(CommunicationError, "Network error."); - } + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + if (error == QNetworkReply::OperationCanceledError) + setError(QPlaceReply::CancelError, QStringLiteral("Request cancelled")); + else + setError(QPlaceReply::CommunicationError, reply->errorString()); } QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.h b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.h index c7ef7ee4..596b9a4c 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.h +++ b/src/plugins/geoservices/nokia/placesv2/qplacecontentreplyimpl.h @@ -54,15 +54,12 @@ public: QPlaceManagerEngineNokiaV2 *engine); ~QPlaceContentReplyImpl(); - void abort(); - private slots: void setError(QPlaceReply::Error error_, const QString &errorString); void replyFinished(); void replyError(QNetworkReply::NetworkError error); private: - QNetworkReply *m_reply; QPlaceManagerEngineNokiaV2 *m_engine; }; diff --git a/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp index e85b9cc7..1e7f2d2f 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp +++ b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.cpp @@ -88,27 +88,23 @@ static bool countryTableContains(const QString &countryCode) QPlaceDetailsReplyImpl::QPlaceDetailsReplyImpl(QNetworkReply *reply, QPlaceManagerEngineNokiaV2 *parent) - : QPlaceDetailsReply(parent), m_reply(reply), m_engine(parent) +: QPlaceDetailsReply(parent), m_engine(parent) { - Q_ASSERT(parent); - - if (!m_reply) + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); return; - - m_reply->setParent(this); - connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); + } + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(replyError(QNetworkReply::NetworkError))); + connect(this, &QPlaceReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } QPlaceDetailsReplyImpl::~QPlaceDetailsReplyImpl() { } -void QPlaceDetailsReplyImpl::abort() -{ - if (m_reply) - m_reply->abort(); -} - void QPlaceDetailsReplyImpl::setError(QPlaceReply::Error error_, const QString &errorString) { QPlaceReply::setError(error_, errorString); @@ -119,23 +115,13 @@ void QPlaceDetailsReplyImpl::setError(QPlaceReply::Error error_, const QString & void QPlaceDetailsReplyImpl::replyFinished() { - if (m_reply->error() != QNetworkReply::NoError) { - switch (m_reply->error()) { - case QNetworkReply::OperationCanceledError: - setError(CancelError, "Request canceled."); - break; - case QNetworkReply::ContentNotFoundError: - setError(PlaceDoesNotExistError, - QString::fromLatin1("The id, %1, does not reference an existing place") - .arg(m_placeId)); - break; - default: - setError(CommunicationError, "Network error."); - } + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) return; - } - QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); if (!document.isObject()) { setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); return; @@ -337,11 +323,23 @@ void QPlaceDetailsReplyImpl::replyFinished() place.setDetailsFetched(true); setPlace(place); - m_reply->deleteLater(); - m_reply = 0; - setFinished(true); emit finished(); } +void QPlaceDetailsReplyImpl::replyError(QNetworkReply::NetworkError error) +{ + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + if (error == QNetworkReply::OperationCanceledError) { + setError(QPlaceReply::CancelError, QStringLiteral("Request cancelled")); + } else if (error == QNetworkReply::ContentNotFoundError) { + setError(QPlaceReply::PlaceDoesNotExistError, + QString::fromLatin1("The id, %1, does not reference an existing place") + .arg(m_placeId)); + } else { + setError(QPlaceReply::CommunicationError, reply->errorString()); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.h b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.h index 2524d04a..dc537c80 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.h +++ b/src/plugins/geoservices/nokia/placesv2/qplacedetailsreplyimpl.h @@ -53,15 +53,14 @@ public: QPlaceDetailsReplyImpl(QNetworkReply *reply, QPlaceManagerEngineNokiaV2 *parent); ~QPlaceDetailsReplyImpl(); - void abort(); void setPlaceId(const QString &placeId) { m_placeId = placeId; } private slots: void setError(QPlaceReply::Error error_, const QString &errorString); void replyFinished(); + void replyError(QNetworkReply::NetworkError error); private: - QNetworkReply *m_reply; QPlaceManagerEngineNokiaV2 *m_engine; QString m_placeId; }; diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp index 3a56c927..9808b539 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp +++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.cpp @@ -54,29 +54,25 @@ QT_BEGIN_NAMESPACE QPlaceSearchReplyHere::QPlaceSearchReplyHere(const QPlaceSearchRequest &request, QNetworkReply *reply, QPlaceManagerEngineNokiaV2 *parent) - : QPlaceSearchReply(parent), m_reply(reply), m_engine(parent) + : QPlaceSearchReply(parent), m_engine(parent) { - Q_ASSERT(parent); - - setRequest(request); - - if (!m_reply) + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); return; + } + setRequest(request); - m_reply->setParent(this); - connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(replyError(QNetworkReply::NetworkError))); + connect(this, &QPlaceReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } QPlaceSearchReplyHere::~QPlaceSearchReplyHere() { } -void QPlaceSearchReplyHere::abort() -{ - if (m_reply) - m_reply->abort(); -} - void QPlaceSearchReplyHere::setError(QPlaceReply::Error error_, const QString &errorString) { QPlaceReply::setError(error_, errorString); @@ -87,23 +83,13 @@ void QPlaceSearchReplyHere::setError(QPlaceReply::Error error_, const QString &e void QPlaceSearchReplyHere::replyFinished() { - if (m_reply->error() != QNetworkReply::NoError) { - switch (m_reply->error()) { - case QNetworkReply::OperationCanceledError: - setError(CancelError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, CANCEL_ERROR)); - break; - case QNetworkReply::ContentNotFoundError: - setError(PlaceDoesNotExistError, - QString::fromLatin1("The id, %1, does not reference an existing place") - .arg(request().recommendationId())); - break; - default: - setError(CommunicationError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, NETWORK_ERROR)); - } + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) return; - } - QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); if (!document.isObject()) { setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); return; @@ -141,9 +127,6 @@ void QPlaceSearchReplyHere::replyFinished() setResults(results); - m_reply->deleteLater(); - m_reply = 0; - setFinished(true); emit finished(); } @@ -227,4 +210,19 @@ QPlaceProposedSearchResult QPlaceSearchReplyHere::parseSearchResult(const QJsonO return result; } +void QPlaceSearchReplyHere::replyError(QNetworkReply::NetworkError error) +{ + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + if (error == QNetworkReply::OperationCanceledError) { + setError(QPlaceReply::CancelError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, CANCEL_ERROR)); + } else if (error == QNetworkReply::ContentNotFoundError) { + setError(QPlaceReply::PlaceDoesNotExistError, + QString::fromLatin1("The id, %1, does not reference an existing place") + .arg(request().recommendationId())); + } else { + setError(QPlaceReply::CommunicationError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, NETWORK_ERROR)); + } +} + QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.h b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.h index a712ab84..b3d97a3d 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.h +++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchreplyhere.h @@ -56,17 +56,15 @@ public: QPlaceManagerEngineNokiaV2 *parent); ~QPlaceSearchReplyHere(); - void abort(); - private slots: void setError(QPlaceReply::Error error_, const QString &errorString); void replyFinished(); + void replyError(QNetworkReply::NetworkError error); private: QPlaceResult parsePlaceResult(const QJsonObject &item) const; QPlaceProposedSearchResult parseSearchResult(const QJsonObject &item) const; - QNetworkReply *m_reply; QPlaceManagerEngineNokiaV2 *m_engine; }; diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.cpp b/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.cpp index 6ed8b5a2..9882545d 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.cpp +++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.cpp @@ -46,25 +46,23 @@ QT_BEGIN_NAMESPACE QPlaceSearchSuggestionReplyImpl::QPlaceSearchSuggestionReplyImpl(QNetworkReply *reply, QObject *parent) -: QPlaceSearchSuggestionReply(parent), m_reply(reply) +: QPlaceSearchSuggestionReply(parent) { - if (!m_reply) + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); return; - - m_reply->setParent(this); - connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); + } + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), + this, SLOT(replyError(QNetworkReply::NetworkError))); + connect(this, &QPlaceReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } QPlaceSearchSuggestionReplyImpl::~QPlaceSearchSuggestionReplyImpl() { } -void QPlaceSearchSuggestionReplyImpl::abort() -{ - if (m_reply) - m_reply->abort(); -} - void QPlaceSearchSuggestionReplyImpl::setError(QPlaceReply::Error error_, const QString &errorString) { @@ -76,18 +74,13 @@ void QPlaceSearchSuggestionReplyImpl::setError(QPlaceReply::Error error_, void QPlaceSearchSuggestionReplyImpl::replyFinished() { - if (m_reply->error() != QNetworkReply::NoError) { - switch (m_reply->error()) { - case QNetworkReply::OperationCanceledError: - setError(CancelError, "Request canceled."); - break; - default: - setError(CommunicationError, "Network error."); - } + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + + if (reply->error() != QNetworkReply::NoError) return; - } - QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); if (!document.isObject()) { setError(ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, PARSE_ERROR)); emit error(error(), errorString()); @@ -107,11 +100,18 @@ void QPlaceSearchSuggestionReplyImpl::replyFinished() setSuggestions(s); - m_reply->deleteLater(); - m_reply = 0; - setFinished(true); emit finished(); } +void QPlaceSearchSuggestionReplyImpl::replyError(QNetworkReply::NetworkError error) +{ + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + if (error == QNetworkReply::OperationCanceledError) + setError(QPlaceReply::CancelError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, CANCEL_ERROR)); + else + setError(QPlaceReply::CommunicationError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, NETWORK_ERROR)); +} + QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.h b/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.h index dbcba3ab..97ae3e1e 100644 --- a/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.h +++ b/src/plugins/geoservices/nokia/placesv2/qplacesearchsuggestionreplyimpl.h @@ -50,14 +50,10 @@ public: explicit QPlaceSearchSuggestionReplyImpl(QNetworkReply *reply, QObject *parent = 0); ~QPlaceSearchSuggestionReplyImpl(); - void abort(); - private slots: void setError(QPlaceReply::Error error_, const QString &errorString); void replyFinished(); - -private: - QNetworkReply *m_reply; + void replyError(QNetworkReply::NetworkError error); }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp b/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp index e99b9815..0fb6eb2a 100644 --- a/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeocodereply_nokia.cpp @@ -53,13 +53,21 @@ QT_BEGIN_NAMESPACE QGeoCodeReplyNokia::QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offset, const QGeoShape &viewport, bool manualBoundsRequired, QObject *parent) -: QGeoCodeReply(parent), m_reply(reply), m_parsing(false), m_manualBoundsRequired(manualBoundsRequired) +: QGeoCodeReply(parent), m_parsing(false), m_manualBoundsRequired(manualBoundsRequired) { + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } qRegisterMetaType<QList<QGeoLocation> >(); - connect(m_reply, SIGNAL(finished()), this, SLOT(networkFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + connect(reply, SIGNAL(finished()), this, SLOT(networkFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkError(QNetworkReply::NetworkError))); + connect(this, &QGeoCodeReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QGeoCodeReply::aborted, [this](){ m_parsing = false; }); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); + setLimit(limit); setOffset(offset); @@ -68,29 +76,14 @@ QGeoCodeReplyNokia::QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offs QGeoCodeReplyNokia::~QGeoCodeReplyNokia() { - abort(); -} - -void QGeoCodeReplyNokia::abort() -{ - if (!m_reply) { - m_parsing = false; - return; - } - - m_reply->abort(); - - m_reply->deleteLater(); - m_reply = 0; - m_parsing = false; } void QGeoCodeReplyNokia::networkFinished() { - if (!m_reply) - return; + QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) + if (reply->error() != QNetworkReply::NoError) return; QGeoCodeJsonParser *parser = new QGeoCodeJsonParser; // QRunnable, autoDelete = true. @@ -101,23 +94,16 @@ void QGeoCodeReplyNokia::networkFinished() connect(parser, SIGNAL(error(QString)), this, SLOT(parseError(QString))); m_parsing = true; - parser->parse(m_reply->readAll()); - - m_reply->deleteLater(); - m_reply = 0; + parser->parse(reply->readAll()); } void QGeoCodeReplyNokia::networkError(QNetworkReply::NetworkError error) { Q_UNUSED(error) - if (!m_reply) - return; - - setError(QGeoCodeReply::CommunicationError, m_reply->errorString()); - - m_reply->deleteLater(); - m_reply = 0; + QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + setError(QGeoCodeReply::CommunicationError, reply->errorString()); } void QGeoCodeReplyNokia::appendResults(const QList<QGeoLocation> &locations) @@ -136,7 +122,6 @@ void QGeoCodeReplyNokia::parseError(const QString &errorString) setError(QGeoCodeReply::ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, RESPONSE_NOT_RECOGNIZABLE)); - abort(); } QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeocodereply_nokia.h b/src/plugins/geoservices/nokia/qgeocodereply_nokia.h index 0d0c47d1..90443ebc 100644 --- a/src/plugins/geoservices/nokia/qgeocodereply_nokia.h +++ b/src/plugins/geoservices/nokia/qgeocodereply_nokia.h @@ -49,8 +49,6 @@ public: QGeoCodeReplyNokia(QNetworkReply *reply, int limit, int offset, const QGeoShape &viewport, bool manualBoundsRequired, QObject *parent = 0); ~QGeoCodeReplyNokia(); - void abort(); - private Q_SLOTS: void networkFinished(); void networkError(QNetworkReply::NetworkError error); @@ -58,7 +56,6 @@ private Q_SLOTS: void parseError(const QString &errorString); private: - QNetworkReply *m_reply; bool m_parsing; bool m_manualBoundsRequired; }; diff --git a/src/plugins/geoservices/nokia/qgeomapreply_nokia.cpp b/src/plugins/geoservices/nokia/qgeomapreply_nokia.cpp index c95f8de3..6e1a1e85 100644 --- a/src/plugins/geoservices/nokia/qgeomapreply_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeomapreply_nokia.cpp @@ -42,63 +42,50 @@ QT_BEGIN_NAMESPACE QGeoMapReplyNokia::QGeoMapReplyNokia(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent) - : QGeoTiledMapReply(spec, parent), - m_reply(reply) + : QGeoTiledMapReply(spec, parent) { - connect(m_reply, + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } + connect(reply, SIGNAL(finished()), this, SLOT(networkFinished())); - connect(m_reply, + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkError(QNetworkReply::NetworkError))); + connect(this, &QGeoTiledMapReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } QGeoMapReplyNokia::~QGeoMapReplyNokia() { } -QNetworkReply *QGeoMapReplyNokia::networkReply() const -{ - return m_reply; -} - -void QGeoMapReplyNokia::abort() -{ - if (!m_reply) - return; - - m_reply->abort(); -} - void QGeoMapReplyNokia::networkFinished() { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) + if (reply->error() != QNetworkReply::NoError) return; - setMapImageData(m_reply->readAll()); + setMapImageData(reply->readAll()); setMapImageFormat("png"); setFinished(true); - - m_reply->deleteLater(); - m_reply = 0; } void QGeoMapReplyNokia::networkError(QNetworkReply::NetworkError error) { - if (!m_reply) - return; - - if (error != QNetworkReply::OperationCanceledError) - setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); - setFinished(true); - m_reply->deleteLater(); - m_reply = 0; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + if (error == QNetworkReply::OperationCanceledError) + setFinished(true); + else + setError(QGeoTiledMapReply::CommunicationError, reply->errorString()); } QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeomapreply_nokia.h b/src/plugins/geoservices/nokia/qgeomapreply_nokia.h index 55759914..d835757c 100644 --- a/src/plugins/geoservices/nokia/qgeomapreply_nokia.h +++ b/src/plugins/geoservices/nokia/qgeomapreply_nokia.h @@ -52,16 +52,9 @@ public: QGeoMapReplyNokia(QNetworkReply *reply, const QGeoTileSpec &spec, QObject *parent = 0); ~QGeoMapReplyNokia(); - void abort(); - - QNetworkReply *networkReply() const; - private Q_SLOTS: void networkFinished(); void networkError(QNetworkReply::NetworkError error); - -private: - QPointer<QNetworkReply> m_reply; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeoroutereply_nokia.cpp b/src/plugins/geoservices/nokia/qgeoroutereply_nokia.cpp index 45ea071f..b5fdfee1 100644 --- a/src/plugins/geoservices/nokia/qgeoroutereply_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeoroutereply_nokia.cpp @@ -49,43 +49,41 @@ QT_BEGIN_NAMESPACE QGeoRouteReplyNokia::QGeoRouteReplyNokia(const QGeoRouteRequest &request, const QList<QNetworkReply *> &replies, QObject *parent) -: QGeoRouteReply(request, parent), m_replies(replies), m_parsers(0) +: QGeoRouteReply(request, parent), m_parsers(0) { qRegisterMetaType<QList<QGeoRoute> >(); - foreach (QNetworkReply *reply, m_replies) { + bool failure = false; + foreach (QNetworkReply *reply, replies) { + if (!reply) { + failure = true; + continue; + } connect(reply, SIGNAL(finished()), this, SLOT(networkFinished())); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkError(QNetworkReply::NetworkError))); + connect(this, &QGeoRouteReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } + if (failure) + setError(UnknownError, QStringLiteral("Null reply")); + else + connect(this, &QGeoRouteReply::aborted, [this](){ m_parsers = 0; }); } QGeoRouteReplyNokia::~QGeoRouteReplyNokia() { - abort(); -} - -void QGeoRouteReplyNokia::abort() -{ - if (m_replies.isEmpty() && !m_parsers) - return; - - foreach (QNetworkReply *reply, m_replies) { - reply->abort(); - reply->deleteLater(); - } - m_replies.clear(); - m_parsers = 0; } void QGeoRouteReplyNokia::networkFinished() { QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); - if (!reply) - return; + reply->deleteLater(); - if (reply->error() != QNetworkReply::NoError) + if (reply->error() != QNetworkReply::NoError + && reply->error() != QNetworkReply::UnknownContentError) { return; + } QGeoRouteXmlParser *parser = new QGeoRouteXmlParser(request()); connect(parser, SIGNAL(results(QList<QGeoRoute>)), @@ -94,32 +92,17 @@ void QGeoRouteReplyNokia::networkFinished() ++m_parsers; parser->parse(reply->readAll()); - - m_replies.removeOne(reply); - reply->deleteLater(); } void QGeoRouteReplyNokia::networkError(QNetworkReply::NetworkError error) { - QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); - if (!reply) + if (error == QNetworkReply::UnknownContentError) return; - - if (error == QNetworkReply::UnknownContentError) { - QGeoRouteXmlParser *parser = new QGeoRouteXmlParser(request()); - connect(parser, SIGNAL(results(QList<QGeoRoute>)), - this, SLOT(appendResults(QList<QGeoRoute>))); - connect(parser, SIGNAL(error(QString)), this, SLOT(parserError(QString))); - - ++m_parsers; - parser->parse(reply->readAll()); - - m_replies.removeOne(reply); - reply->deleteLater(); - } else { - setError(QGeoRouteReply::CommunicationError, reply->errorString()); - abort(); - } + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + setError(QGeoRouteReply::CommunicationError, reply->errorString()); + if (error != QNetworkReply::OperationCanceledError) // Any error not caused by abort() + emit aborted(); // aborts all unfinished replies and sets m_parsers to 0 } void QGeoRouteReplyNokia::appendResults(const QList<QGeoRoute> &routes) @@ -130,19 +113,16 @@ void QGeoRouteReplyNokia::appendResults(const QList<QGeoRoute> &routes) --m_parsers; addRoutes(routes); - if (!m_parsers && m_replies.isEmpty()) + if (!m_parsers) setFinished(true); } void QGeoRouteReplyNokia::parserError(const QString &errorString) { Q_UNUSED(errorString) - - --m_parsers; - + emit aborted(); setError(QGeoRouteReply::ParseError, QCoreApplication::translate(NOKIA_PLUGIN_CONTEXT_NAME, RESPONSE_NOT_RECOGNIZABLE)); - abort(); } QT_END_NAMESPACE diff --git a/src/plugins/geoservices/nokia/qgeoroutereply_nokia.h b/src/plugins/geoservices/nokia/qgeoroutereply_nokia.h index 9d32bdb3..d38262a5 100644 --- a/src/plugins/geoservices/nokia/qgeoroutereply_nokia.h +++ b/src/plugins/geoservices/nokia/qgeoroutereply_nokia.h @@ -51,8 +51,6 @@ public: QGeoRouteReplyNokia(const QGeoRouteRequest &request, const QList<QNetworkReply*> &replies, QObject *parent = 0); ~QGeoRouteReplyNokia(); - void abort(); - private Q_SLOTS: void networkFinished(); void networkError(QNetworkReply::NetworkError error); @@ -60,7 +58,6 @@ private Q_SLOTS: void parserError(const QString &errorString); private: - QList<QNetworkReply *> m_replies; int m_parsers; }; diff --git a/src/plugins/geoservices/osm/qgeocodereplyosm.cpp b/src/plugins/geoservices/osm/qgeocodereplyosm.cpp index 15b1724e..a30601d0 100644 --- a/src/plugins/geoservices/osm/qgeocodereplyosm.cpp +++ b/src/plugins/geoservices/osm/qgeocodereplyosm.cpp @@ -50,31 +50,23 @@ QT_BEGIN_NAMESPACE QGeoCodeReplyOsm::QGeoCodeReplyOsm(QNetworkReply *reply, QObject *parent) -: QGeoCodeReply(parent), m_reply(reply) +: QGeoCodeReply(parent) { - connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } + connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); - + connect(this, &QGeoCodeReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); setLimit(1); setOffset(0); } QGeoCodeReplyOsm::~QGeoCodeReplyOsm() { - if (m_reply) - m_reply->deleteLater(); -} - -void QGeoCodeReplyOsm::abort() -{ - if (!m_reply) - return; - - m_reply->abort(); - - m_reply->deleteLater(); - m_reply = 0; } static QGeoAddress parseAddressObject(const QJsonObject &object) @@ -108,14 +100,14 @@ static QGeoAddress parseAddressObject(const QJsonObject &object) void QGeoCodeReplyOsm::networkReplyFinished() { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) + if (reply->error() != QNetworkReply::NoError) return; QList<QGeoLocation> locations; - QJsonDocument document = QJsonDocument::fromJson(m_reply->readAll()); + QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); if (document.isObject()) { QJsonObject object = document.object(); @@ -169,22 +161,14 @@ void QGeoCodeReplyOsm::networkReplyFinished() setLocations(locations); setFinished(true); - - m_reply->deleteLater(); - m_reply = 0; } void QGeoCodeReplyOsm::networkReplyError(QNetworkReply::NetworkError error) { Q_UNUSED(error) - - if (!m_reply) - return; - - setError(QGeoCodeReply::CommunicationError, m_reply->errorString()); - - m_reply->deleteLater(); - m_reply = 0; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + setError(QGeoCodeReply::CommunicationError, reply->errorString()); } QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeocodereplyosm.h b/src/plugins/geoservices/osm/qgeocodereplyosm.h index 2772910e..0847f58c 100644 --- a/src/plugins/geoservices/osm/qgeocodereplyosm.h +++ b/src/plugins/geoservices/osm/qgeocodereplyosm.h @@ -53,14 +53,9 @@ public: explicit QGeoCodeReplyOsm(QNetworkReply *reply, QObject *parent = 0); ~QGeoCodeReplyOsm(); - void abort(); - private Q_SLOTS: void networkReplyFinished(); void networkReplyError(QNetworkReply::NetworkError error); - -private: - QNetworkReply *m_reply; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeomapreplyosm.cpp b/src/plugins/geoservices/osm/qgeomapreplyosm.cpp index 052ed351..a06f91f3 100644 --- a/src/plugins/geoservices/osm/qgeomapreplyosm.cpp +++ b/src/plugins/geoservices/osm/qgeomapreplyosm.cpp @@ -45,64 +45,45 @@ QGeoMapReplyOsm::QGeoMapReplyOsm(QNetworkReply *reply, const QGeoTileSpec &spec, const QString &imageFormat, QObject *parent) -: QGeoTiledMapReply(spec, parent), m_reply(reply) +: QGeoTiledMapReply(spec, parent) { - connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } + connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + connect(this, &QGeoTiledMapReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); setMapImageFormat(imageFormat); } QGeoMapReplyOsm::~QGeoMapReplyOsm() { - if (m_reply) { - m_reply->deleteLater(); - m_reply = 0; - } -} - -void QGeoMapReplyOsm::abort() -{ - if (!m_reply) - return; - - m_reply->abort(); -} - -QNetworkReply *QGeoMapReplyOsm::networkReply() const -{ - return m_reply; } void QGeoMapReplyOsm::networkReplyFinished() { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) { - m_reply->deleteLater(); - m_reply = 0; + if (reply->error() != QNetworkReply::NoError) // Already handled in networkReplyError return; - } - QByteArray a = m_reply->readAll(); + QByteArray a = reply->readAll(); setMapImageData(a); setFinished(true); - - m_reply->deleteLater(); - m_reply = 0; } void QGeoMapReplyOsm::networkReplyError(QNetworkReply::NetworkError error) { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + if (error == QNetworkReply::OperationCanceledError) + setFinished(true); + else + setError(QGeoTiledMapReply::CommunicationError, reply->errorString()); - if (error != QNetworkReply::OperationCanceledError) - setError(QGeoTiledMapReply::CommunicationError, m_reply->errorString()); - - setFinished(true); - m_reply->deleteLater(); - m_reply = 0; } diff --git a/src/plugins/geoservices/osm/qgeomapreplyosm.h b/src/plugins/geoservices/osm/qgeomapreplyosm.h index 804a0a24..ef0cbb15 100644 --- a/src/plugins/geoservices/osm/qgeomapreplyosm.h +++ b/src/plugins/geoservices/osm/qgeomapreplyosm.h @@ -40,12 +40,8 @@ #ifndef QGEOMAPREPLYOSM_H #define QGEOMAPREPLYOSM_H -#include "qgeotilefetcherosm.h" -#include "qgeotileproviderosm.h" - #include <QtNetwork/QNetworkReply> #include <QtLocation/private/qgeotiledmapreply_p.h> -#include <QtCore/qpointer.h> QT_BEGIN_NAMESPACE @@ -57,16 +53,9 @@ public: QGeoMapReplyOsm(QNetworkReply *reply, const QGeoTileSpec &spec, const QString &imageFormat, QObject *parent = 0); ~QGeoMapReplyOsm(); - void abort(); - - QNetworkReply *networkReply() const; - private Q_SLOTS: void networkReplyFinished(); void networkReplyError(QNetworkReply::NetworkError error); - -private: - QPointer<QNetworkReply> m_reply; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp index c640e595..6924fda7 100644 --- a/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp +++ b/src/plugins/geoservices/osm/qgeoroutereplyosm.cpp @@ -44,48 +44,37 @@ QT_BEGIN_NAMESPACE QGeoRouteReplyOsm::QGeoRouteReplyOsm(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent) -: QGeoRouteReply(request, parent), m_reply(reply) +: QGeoRouteReply(request, parent) { - connect(m_reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); - connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); + return; + } + connect(reply, SIGNAL(finished()), this, SLOT(networkReplyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkReplyError(QNetworkReply::NetworkError))); + connect(this, &QGeoRouteReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } QGeoRouteReplyOsm::~QGeoRouteReplyOsm() { - if (m_reply) - m_reply->deleteLater(); -} - -void QGeoRouteReplyOsm::abort() -{ - if (!m_reply) - return; - - m_reply->abort(); - - m_reply->deleteLater(); - m_reply = 0; } void QGeoRouteReplyOsm::networkReplyFinished() { - if (!m_reply) - return; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (m_reply->error() != QNetworkReply::NoError) { - setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); - m_reply->deleteLater(); - m_reply = 0; + if (reply->error() != QNetworkReply::NoError) return; - } QGeoRoutingManagerEngineOsm *engine = qobject_cast<QGeoRoutingManagerEngineOsm *>(parent()); const QGeoRouteParser *parser = engine->routeParser(); QList<QGeoRoute> routes; QString errorString; - QGeoRouteReply::Error error = parser->parseReply(routes, errorString, m_reply->readAll()); + QGeoRouteReply::Error error = parser->parseReply(routes, errorString, reply->readAll()); if (error == QGeoRouteReply::NoError) { setRoutes(routes.mid(0,1)); // TODO QTBUG-56426 @@ -94,22 +83,14 @@ void QGeoRouteReplyOsm::networkReplyFinished() } else { setError(error, errorString); } - - m_reply->deleteLater(); - m_reply = 0; } void QGeoRouteReplyOsm::networkReplyError(QNetworkReply::NetworkError error) { Q_UNUSED(error) - - if (!m_reply) - return; - - setError(QGeoRouteReply::CommunicationError, m_reply->errorString()); - - m_reply->deleteLater(); - m_reply = 0; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + setError(QGeoRouteReply::CommunicationError, reply->errorString()); } QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qgeoroutereplyosm.h b/src/plugins/geoservices/osm/qgeoroutereplyosm.h index 8733c154..feaae59c 100644 --- a/src/plugins/geoservices/osm/qgeoroutereplyosm.h +++ b/src/plugins/geoservices/osm/qgeoroutereplyosm.h @@ -54,14 +54,9 @@ public: QGeoRouteReplyOsm(QNetworkReply *reply, const QGeoRouteRequest &request, QObject *parent = 0); ~QGeoRouteReplyOsm(); - void abort() Q_DECL_OVERRIDE; - private Q_SLOTS: void networkReplyFinished(); void networkReplyError(QNetworkReply::NetworkError error); - -private: - QNetworkReply *m_reply; }; QT_END_NAMESPACE diff --git a/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp b/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp index 719769f0..dcf02b13 100644 --- a/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp +++ b/src/plugins/geoservices/osm/qplacemanagerengineosm.cpp @@ -260,9 +260,6 @@ void QPlaceManagerEngineOsm::setLocales(const QList<QLocale> &locales) void QPlaceManagerEngineOsm::categoryReplyFinished() { QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender()); - if (!reply) - return; - reply->deleteLater(); QXmlStreamReader parser(reply); diff --git a/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp b/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp index 3cb0ab60..35b05d4d 100644 --- a/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp +++ b/src/plugins/geoservices/osm/qplacesearchreplyosm.cpp @@ -53,32 +53,28 @@ QT_BEGIN_NAMESPACE QPlaceSearchReplyOsm::QPlaceSearchReplyOsm(const QPlaceSearchRequest &request, QNetworkReply *reply, QPlaceManagerEngineOsm *parent) -: QPlaceSearchReply(parent), m_reply(reply) +: QPlaceSearchReply(parent) { Q_ASSERT(parent); - - setRequest(request); - - if (!m_reply) + if (!reply) { + setError(UnknownError, QStringLiteral("Null reply")); return; + } + setRequest(request); - m_reply->setParent(this); - connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(networkError(QNetworkReply::NetworkError))); + connect(this, &QPlaceReply::aborted, reply, &QNetworkReply::abort); + connect(this, &QObject::destroyed, reply, &QObject::deleteLater); } QPlaceSearchReplyOsm::~QPlaceSearchReplyOsm() { } -void QPlaceSearchReplyOsm::abort() -{ - if (m_reply) - m_reply->abort(); -} - void QPlaceSearchReplyOsm::setError(QPlaceReply::Error errorCode, const QString &errorString) { - QPlaceReply::setError(errorCode, errorString); + setError(errorCode, errorString); emit error(errorCode, errorString); setFinished(true); emit finished(); @@ -99,14 +95,11 @@ static QGeoRectangle parseBoundingBox(const QJsonArray &coordinates) void QPlaceSearchReplyOsm::replyFinished() { - QNetworkReply *reply = m_reply; - m_reply->deleteLater(); - m_reply = 0; + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); - if (reply->error() != QNetworkReply::NoError) { - setError(CommunicationError, tr("Communication error")); + if (reply->error() != QNetworkReply::NoError) return; - } QJsonDocument document = QJsonDocument::fromJson(reply->readAll()); if (!document.isArray()) { @@ -163,6 +156,14 @@ void QPlaceSearchReplyOsm::replyFinished() emit finished(); } +void QPlaceSearchReplyOsm::networkError(QNetworkReply::NetworkError error) +{ + Q_UNUSED(error) + QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); + reply->deleteLater(); + setError(QPlaceReply::CommunicationError, reply->errorString()); +} + QPlaceResult QPlaceSearchReplyOsm::parsePlaceResult(const QJsonObject &item) const { QPlace place; diff --git a/src/plugins/geoservices/osm/qplacesearchreplyosm.h b/src/plugins/geoservices/osm/qplacesearchreplyosm.h index e495d4fa..223e5f0c 100644 --- a/src/plugins/geoservices/osm/qplacesearchreplyosm.h +++ b/src/plugins/geoservices/osm/qplacesearchreplyosm.h @@ -41,6 +41,7 @@ #define QPLACESEARCHREPLYOSM_H #include <QtLocation/QPlaceSearchReply> +#include <QNetworkReply> QT_BEGIN_NAMESPACE @@ -57,16 +58,13 @@ public: QPlaceManagerEngineOsm *parent); ~QPlaceSearchReplyOsm(); - void abort(); - private slots: void setError(QPlaceReply::Error errorCode, const QString &errorString); void replyFinished(); + void networkError(QNetworkReply::NetworkError error); private: QPlaceResult parsePlaceResult(const QJsonObject &item) const; - - QNetworkReply *m_reply; }; QT_END_NAMESPACE diff --git a/src/plugins/position/corelocation/corelocation.pro b/src/plugins/position/corelocation/corelocation.pro index dbb5b6b3..947a1d0c 100644 --- a/src/plugins/position/corelocation/corelocation.pro +++ b/src/plugins/position/corelocation/corelocation.pro @@ -13,9 +13,7 @@ HEADERS += \ OTHER_FILES += \ plugin.json -osx: LIBS += -framework Foundation -else: ios|tvos: LIBS += -framework CoreFoundation -LIBS += -framework CoreLocation +LIBS += -framework Foundation -framework CoreLocation PLUGIN_TYPE = position PLUGIN_CLASS_NAME = QGeoPositionInfoSourceFactoryCL diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro index 3cc059c0..a311e5e1 100644 --- a/src/positioning/positioning.pro +++ b/src/positioning/positioning.pro @@ -32,7 +32,8 @@ PUBLIC_HEADERS += \ qgeosatelliteinfosource.h \ qnmeapositioninfosource.h \ qgeopositioninfosourcefactory.h \ - qpositioningglobal.h + qpositioningglobal.h \ + qgeopath.h \ PRIVATE_HEADERS += \ qgeoaddress_p.h \ @@ -50,7 +51,8 @@ PRIVATE_HEADERS += \ qdoublevector3d_p.h \ qgeoprojection_p.h \ qpositioningglobal_p.h \ - qlocationdata_simulator_p.h + qlocationdata_simulator_p.h \ + qgeopath_p.h SOURCES += \ qgeoaddress.cpp \ @@ -73,7 +75,8 @@ SOURCES += \ qdoublevector2d.cpp \ qdoublevector3d.cpp \ qgeoprojection.cpp \ - qlocationdata_simulator.cpp + qlocationdata_simulator.cpp \ + qgeopath.cpp HEADERS += $$PUBLIC_HEADERS $$PRIVATE_HEADERS diff --git a/src/positioning/qgeocircle.cpp b/src/positioning/qgeocircle.cpp index 3f2707a4..17263a42 100644 --- a/src/positioning/qgeocircle.cpp +++ b/src/positioning/qgeocircle.cpp @@ -42,9 +42,11 @@ #include "qgeocoordinate.h" #include "qnumeric.h" +#include "qlocationutils_p.h" #include "qdoublevector2d_p.h" #include "qdoublevector3d_p.h" +#include <cmath> QT_BEGIN_NAMESPACE /*! @@ -191,12 +193,12 @@ bool QGeoCircle::operator!=(const QGeoCircle &other) const bool QGeoCirclePrivate::isValid() const { - return m_center.isValid() && !qIsNaN(radius) && radius >= -1e-7; + return m_center.isValid() && !qIsNaN(m_radius) && m_radius >= -1e-7; } bool QGeoCirclePrivate::isEmpty() const { - return !isValid() || radius <= 1e-7; + return !isValid() || m_radius <= 1e-7; } /*! @@ -206,7 +208,7 @@ void QGeoCircle::setCenter(const QGeoCoordinate ¢er) { Q_D(QGeoCircle); - d->m_center = center; + d->setCenter(center); } /*! @@ -226,7 +228,7 @@ void QGeoCircle::setRadius(qreal radius) { Q_D(QGeoCircle); - d->radius = radius; + d->setRadius(radius); } /*! @@ -236,7 +238,7 @@ qreal QGeoCircle::radius() const { Q_D(const QGeoCircle); - return d->radius; + return d->m_radius; } bool QGeoCirclePrivate::contains(const QGeoCoordinate &coordinate) const @@ -246,7 +248,7 @@ bool QGeoCirclePrivate::contains(const QGeoCoordinate &coordinate) const // see QTBUG-41447 for details qreal distance = m_center.distanceTo(coordinate); - if (qFuzzyCompare(distance, radius) || distance <= radius) + if (qFuzzyCompare(distance, m_radius) || distance <= m_radius) return true; return false; @@ -257,6 +259,103 @@ QGeoCoordinate QGeoCirclePrivate::center() const return m_center; } +QGeoRectangle QGeoCirclePrivate::boundingGeoRectangle() const +{ + return m_bbox; +} + +void QGeoCirclePrivate::updateBoundingBox() +{ + if (isEmpty()) { + if (m_center.isValid()) { + m_bbox.setTopLeft(m_center); + m_bbox.setBottomRight(m_center); + } + return; + } + + bool crossNorth = crossNorthPole(); + bool crossSouth = crossSouthPole(); + + if (crossNorth && crossSouth) { + // Circle crossing both poles fills the whole map + m_bbox = QGeoRectangle(QGeoCoordinate(90.0, -180.0), QGeoCoordinate(-90.0, 180.0)); + } else if (crossNorth) { + // Circle crossing one pole fills the map in the longitudinal direction + m_bbox = QGeoRectangle(QGeoCoordinate(90.0, -180.0), QGeoCoordinate(m_center.atDistanceAndAzimuth(m_radius, 180.0).latitude(), 180.0)); + } else if (crossSouth) { + m_bbox = QGeoRectangle(QGeoCoordinate(m_center.atDistanceAndAzimuth(m_radius, 0.0).latitude(), -180.0), QGeoCoordinate(-90, 180.0)); + } else { + // Regular circle not crossing anything + + // Calculate geo bounding box of the circle + // + // A circle tangential point with a meridian, together with pole and + // the circle center create a spherical triangle. + // Finding the tangential point with the spherical law of sines: + // + // * lon_delta_in_rad : delta between the circle center and a tangential + // point (absolute value). + // * r_in_rad : angular radius of the circle + // * lat_in_rad : latitude of the circle center + // * alpha_in_rad : angle between meridian and radius of the circle. + // At the tangential point, sin(alpha_in_rad) == 1. + // * lat_delta_in_rad - absolute delta of latitudes between the circle center and + // any of the two points where the great circle going through the circle + // center and the pole crosses the circle. In other words, the points + // on the circle with azimuth 0 or 180. + // + // Using: + // sin(lon_delta_in_rad)/sin(r_in_rad) = sin(alpha_in_rad)/sin(pi/2 - lat_in_rad) + + double r_in_rad = m_radius / QLocationUtils::earthMeanRadius(); // angular r + double lat_delta_in_deg = QLocationUtils::degrees(r_in_rad); + double lon_delta_in_deg = QLocationUtils::degrees(std::asin( + std::sin(r_in_rad) / + std::cos(QLocationUtils::radians(m_center.latitude())) + )); + + QGeoCoordinate topLeft; + topLeft.setLatitude(m_center.latitude() + lat_delta_in_deg); + topLeft.setLongitude(m_center.longitude() - lon_delta_in_deg); + QGeoCoordinate bottomRight; + bottomRight.setLatitude(m_center.latitude() - lat_delta_in_deg); + bottomRight.setLongitude(m_center.longitude() + lon_delta_in_deg); + + m_bbox = QGeoRectangle(topLeft, bottomRight); + } +} + +void QGeoCirclePrivate::setCenter(const QGeoCoordinate &c) +{ + m_center = c; + updateBoundingBox(); +} + +void QGeoCirclePrivate::setRadius(const qreal r) +{ + m_radius = r; + updateBoundingBox(); +} + +bool QGeoCirclePrivate::crossNorthPole() const +{ + const QGeoCoordinate northPole(90.0, m_center.longitude()); + qreal distanceToPole = m_center.distanceTo(northPole); + if (distanceToPole < m_radius) + return true; + return false; +} + +bool QGeoCirclePrivate::crossSouthPole() const +{ + const QGeoCoordinate southPole(-90.0, m_center.longitude()); + qreal distanceToPole = m_center.distanceTo(southPole); + if (distanceToPole < m_radius) + return true; + return false; +} + /*! Extends the circle to include \a coordinate */ @@ -265,7 +364,7 @@ void QGeoCirclePrivate::extendShape(const QGeoCoordinate &coordinate) if (!isValid() || !coordinate.isValid() || contains(coordinate)) return; - radius = m_center.distanceTo(coordinate); + setRadius(m_center.distanceTo(coordinate)); } /*! @@ -285,12 +384,9 @@ void QGeoCircle::translate(double degreesLatitude, double degreesLongitude) lat += degreesLatitude; lon += degreesLongitude; + lon = QLocationUtils::wrapLong(lon); - if (lon < -180.0) - lon += 360.0; - if (lon > 180.0) - lon -= 360.0; - + // TODO: remove this and simply clip latitude. if (lat > 90.0) { lat = 180.0 - lat; if (lon < 0.0) @@ -307,7 +403,7 @@ void QGeoCircle::translate(double degreesLatitude, double degreesLongitude) lon -= 180; } - d->m_center = QGeoCoordinate(lat, lon); + d->setCenter(QGeoCoordinate(lat, lon)); } /*! @@ -349,18 +445,19 @@ QString QGeoCircle::toString() const *******************************************************************************/ QGeoCirclePrivate::QGeoCirclePrivate() -: QGeoShapePrivate(QGeoShape::CircleType), radius(-1.0) +: QGeoShapePrivate(QGeoShape::CircleType), m_radius(-1.0) { } QGeoCirclePrivate::QGeoCirclePrivate(const QGeoCoordinate ¢er, qreal radius) -: QGeoShapePrivate(QGeoShape::CircleType), m_center(center), radius(radius) +: QGeoShapePrivate(QGeoShape::CircleType), m_center(center), m_radius(radius) { + updateBoundingBox(); } QGeoCirclePrivate::QGeoCirclePrivate(const QGeoCirclePrivate &other) : QGeoShapePrivate(QGeoShape::CircleType), m_center(other.m_center), - radius(other.radius) + m_radius(other.m_radius), m_bbox(other.m_bbox) { } @@ -378,8 +475,7 @@ bool QGeoCirclePrivate::operator==(const QGeoShapePrivate &other) const const QGeoCirclePrivate &otherCircle = static_cast<const QGeoCirclePrivate &>(other); - return radius == otherCircle.radius && m_center == otherCircle.m_center; + return m_radius == otherCircle.m_radius && m_center == otherCircle.m_center; } QT_END_NAMESPACE - diff --git a/src/positioning/qgeocircle.h b/src/positioning/qgeocircle.h index b4b6c45e..e8632fe9 100644 --- a/src/positioning/qgeocircle.h +++ b/src/positioning/qgeocircle.h @@ -75,8 +75,8 @@ public: void setRadius(qreal radius); qreal radius() const; - void translate(double degreesLatitude, double degreesLongitude); - QGeoCircle translated(double degreesLatitude, double degreesLongitude) const; + Q_INVOKABLE void translate(double degreesLatitude, double degreesLongitude); + Q_INVOKABLE QGeoCircle translated(double degreesLatitude, double degreesLongitude) const; Q_INVOKABLE QString toString() const; diff --git a/src/positioning/qgeocircle_p.h b/src/positioning/qgeocircle_p.h index 311aba8b..07d79db4 100644 --- a/src/positioning/qgeocircle_p.h +++ b/src/positioning/qgeocircle_p.h @@ -70,6 +70,14 @@ public: QGeoCoordinate center() const Q_DECL_OVERRIDE; + QGeoRectangle boundingGeoRectangle() const Q_DECL_OVERRIDE; + + bool crossNorthPole() const; + bool crossSouthPole() const; + void updateBoundingBox(); + void setCenter(const QGeoCoordinate &c); + void setRadius(const qreal r); + void extendShape(const QGeoCoordinate &coordinate) Q_DECL_OVERRIDE; QGeoShapePrivate *clone() const Q_DECL_OVERRIDE; @@ -77,7 +85,8 @@ public: bool operator==(const QGeoShapePrivate &other) const Q_DECL_OVERRIDE; QGeoCoordinate m_center; - qreal radius; + qreal m_radius; + QGeoRectangle m_bbox; }; QT_END_NAMESPACE diff --git a/src/positioning/qgeocoordinate.cpp b/src/positioning/qgeocoordinate.cpp index 0386e859..8d39a62e 100644 --- a/src/positioning/qgeocoordinate.cpp +++ b/src/positioning/qgeocoordinate.cpp @@ -517,14 +517,8 @@ QGeoCoordinate QGeoCoordinate::atDistanceAndAzimuth(qreal distance, qreal azimut double resultLon, resultLat; QGeoCoordinatePrivate::atDistanceAndAzimuth(*this, distance, azimuth, &resultLon, &resultLat); - - if (resultLon > 180.0) - resultLon -= 360.0; - else if (resultLon < -180.0) - resultLon += 360.0; - double resultAlt = d->alt + distanceUp; - return QGeoCoordinate(resultLat, resultLon, resultAlt); + return QGeoCoordinate(resultLat, QLocationUtils::wrapLong(resultLon), resultAlt); } /*! diff --git a/src/positioning/qgeopath.cpp b/src/positioning/qgeopath.cpp new file mode 100644 index 00000000..523a79fb --- /dev/null +++ b/src/positioning/qgeopath.cpp @@ -0,0 +1,679 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeopath.h" +#include "qgeopath_p.h" + +#include "qgeocoordinate.h" +#include "qnumeric.h" +#include "qlocationutils_p.h" +#include "qgeoprojection_p.h" + +#include "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" +QT_BEGIN_NAMESPACE + +/*! + \class QGeoPath + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.9 + + \brief The QGeoPath class defines a geographic path. + + The path is defined by an ordered list of QGeoCoordinates. + + Each two adjacent elements in the path are intended to be connected + together by the shortest line segment of constant bearing passing + through both elements. + This type of connection can cross the dateline in the longitudinal direction, + but never crosses the poles. + + This is relevant for the calculation of the bounding box returned by + \l QGeoShape::geoBoundingBox() for this shape, which will have the latitude of + the top left corner set to the maximum latitude in the path point set. + Similarly, the latitude of the bottom right corner will be the minimum latitude + in the path point set. + + This class is a \l Q_GADGET. + It can be \l{Cpp_value_integration_positioning}{directly used from C++ and QML}. +*/ + +/*! + \property QGeoPath::path + \brief This property holds the list of coordinates for the geo path. + + The path is both invalid and empty if it contains no coordinate. + + A default constructed QGeoPath is therefore invalid. +*/ + +inline QGeoPathPrivate *QGeoPath::d_func() +{ + return static_cast<QGeoPathPrivate *>(d_ptr.data()); +} + +inline const QGeoPathPrivate *QGeoPath::d_func() const +{ + return static_cast<const QGeoPathPrivate *>(d_ptr.constData()); +} + +struct PathVariantConversions +{ + PathVariantConversions() + { + QMetaType::registerConverter<QGeoShape, QGeoPath>(); + QMetaType::registerConverter<QGeoPath, QGeoShape>(); + } +}; + +Q_GLOBAL_STATIC(PathVariantConversions, initPathConversions) + +/*! + Constructs a new, empty geo path. +*/ +QGeoPath::QGeoPath() +: QGeoShape(new QGeoPathPrivate) +{ + initPathConversions(); +} + +/*! + Constructs a new geo path from a list of coordinates. +*/ +QGeoPath::QGeoPath(const QList<QGeoCoordinate> &path, const qreal &width) +: QGeoShape(new QGeoPathPrivate(path, width)) +{ + initPathConversions(); +} + +/*! + Constructs a new geo path from the contents of \a other. +*/ +QGeoPath::QGeoPath(const QGeoPath &other) +: QGeoShape(other) +{ + initPathConversions(); +} + +/*! + Constructs a new geo path from the contents of \a other. +*/ +QGeoPath::QGeoPath(const QGeoShape &other) +: QGeoShape(other) +{ + initPathConversions(); + if (type() != QGeoShape::PathType) + d_ptr = new QGeoPathPrivate; +} + +/*! + Destroys this path. +*/ +QGeoPath::~QGeoPath() {} + +/*! + Assigns \a other to this geo path and returns a reference to this geo path. +*/ +QGeoPath &QGeoPath::operator=(const QGeoPath &other) +{ + QGeoShape::operator=(other); + return *this; +} + +/*! + Returns whether this geo path is equal to \a other. +*/ +bool QGeoPath::operator==(const QGeoPath &other) const +{ + Q_D(const QGeoPath); + return *d == *other.d_func(); +} + +/*! + Returns whether this geo path is not equal to \a other. +*/ +bool QGeoPath::operator!=(const QGeoPath &other) const +{ + Q_D(const QGeoPath); + return !(*d == *other.d_func()); +} + +void QGeoPath::setPath(const QList<QGeoCoordinate> &path) +{ + Q_D(QGeoPath); + return d->setPath(path); +} + +/*! + Returns all the elements. Equivalent to QGeoShape::center(). + The center coordinate, in case of a QGeoPath, is the center of its bounding box. +*/ +const QList<QGeoCoordinate> &QGeoPath::path() const +{ + Q_D(const QGeoPath); + return d->path(); +} + +void QGeoPath::setWidth(const qreal &width) +{ + Q_D(QGeoPath); + d->setWidth(width); +} + +/*! + Returns the width of the path, in meters. This information is used in the \l contains method + The default value is 0. +*/ +qreal QGeoPath::width() const +{ + Q_D(const QGeoPath); + return d->width(); +} + +/*! + Translates this geo path by \a degreesLatitude northwards and \a degreesLongitude eastwards. + + Negative values of \a degreesLatitude and \a degreesLongitude correspond to + southward and westward translation respectively. +*/ +void QGeoPath::translate(double degreesLatitude, double degreesLongitude) +{ + Q_D(QGeoPath); + d->translate(degreesLatitude, degreesLongitude); +} + +/*! + Returns a copy of this geo path translated by \a degreesLatitude northwards and + \a degreesLongitude eastwards. + + Negative values of \a degreesLatitude and \a degreesLongitude correspond to + southward and westward translation respectively. + + \sa translate() +*/ +QGeoPath QGeoPath::translated(double degreesLatitude, double degreesLongitude) const +{ + QGeoPath result(*this); + result.translate(degreesLatitude, degreesLongitude); + return result; +} + +/*! + Returns the length of the path, in meters, from the element \a indexFrom to the element \a indexTo. + The length is intended to be the sum of the shortest distances for each pair of adjacent points. +*/ +double QGeoPath::length(int indexFrom, int indexTo) const +{ + Q_D(const QGeoPath); + return d->length(indexFrom, indexTo); +} + +/*! + Appends \a coordinate to the path. +*/ +void QGeoPath::addCoordinate(const QGeoCoordinate &coordinate) +{ + Q_D(QGeoPath); + d->addCoordinate(coordinate); +} + +/*! + Inserts \a coordinate at the specified \a index. +*/ +void QGeoPath::insertCoordinate(int index, const QGeoCoordinate &coordinate) +{ + Q_D(QGeoPath); + d->insertCoordinate(index, coordinate); +} + +/*! + Replaces the path element at the specified \a index with \a coordinate. +*/ +void QGeoPath::replaceCoordinate(int index, const QGeoCoordinate &coordinate) +{ + Q_D(QGeoPath); + d->replaceCoordinate(index, coordinate); +} + +/*! + Returns the coordinate at \a index . +*/ +QGeoCoordinate QGeoPath::coordinateAt(int index) const +{ + Q_D(const QGeoPath); + return d->coordinateAt(index); +} + +/*! + Returns true if the path contains \a coordinate as one of the elements. +*/ +bool QGeoPath::containsCoordinate(const QGeoCoordinate &coordinate) const +{ + Q_D(const QGeoPath); + return d->containsCoordinate(coordinate); +} + +/*! + Removes the last occurrence of \a coordinate from the path. +*/ +void QGeoPath::removeCoordinate(const QGeoCoordinate &coordinate) +{ + Q_D(QGeoPath); + d->removeCoordinate(coordinate); +} + +/*! + Removes element at position \a index from the path. +*/ +void QGeoPath::removeCoordinate(int index) +{ + Q_D(QGeoPath); + d->removeCoordinate(index); +} + +/*! + Returns the geo path properties as a string. +*/ +QString QGeoPath::toString() const +{ + if (type() != QGeoShape::PathType) { + qWarning("Not a path"); + return QStringLiteral("QGeoPath(not a path)"); + } + + QString pathString; + for (const auto &p : path()) + pathString += p.toString() + QLatin1Char(','); + + return QStringLiteral("QGeoPath([ %1 ])").arg(pathString); +} + +/******************************************************************************* + * QGeoPathPrivate +*******************************************************************************/ + +QGeoPathPrivate::QGeoPathPrivate() +: QGeoShapePrivate(QGeoShape::PathType), m_width(0) +{ +} + +QGeoPathPrivate::QGeoPathPrivate(const QList<QGeoCoordinate> &path, const qreal width) +: QGeoShapePrivate(QGeoShape::PathType), m_width(0) +{ + setPath(path); + setWidth(width); +} + +QGeoPathPrivate::QGeoPathPrivate(const QGeoPathPrivate &other) +: QGeoShapePrivate(QGeoShape::PathType), m_path(other.m_path), + m_deltaXs(other.m_deltaXs), m_minX(other.m_minX), m_maxX(other.m_maxX), m_minLati(other.m_minLati), + m_maxLati(other.m_maxLati), m_bbox(other.m_bbox), m_width(other.m_width) +{ +} + +QGeoPathPrivate::~QGeoPathPrivate() {} + +QGeoShapePrivate *QGeoPathPrivate::clone() const +{ + return new QGeoPathPrivate(*this); +} + +bool QGeoPathPrivate::operator==(const QGeoShapePrivate &other) const +{ + if (!QGeoShapePrivate::operator==(other)) + return false; + + const QGeoPathPrivate &otherPath = static_cast<const QGeoPathPrivate &>(other); + if (m_path.size() != otherPath.m_path.size()) + return false; + return m_width == otherPath.m_width && m_path == otherPath.m_path; +} + +bool QGeoPathPrivate::isValid() const +{ + return !isEmpty(); +} + +bool QGeoPathPrivate::isEmpty() const +{ + return m_path.isEmpty(); +} + +const QList<QGeoCoordinate> &QGeoPathPrivate::path() const +{ + return m_path; +} + +void QGeoPathPrivate::setPath(const QList<QGeoCoordinate> &path) +{ + for (const QGeoCoordinate &c: path) + if (!c.isValid()) + return; + m_path = path; + computeBoundingBox(); +} + +qreal QGeoPathPrivate::width() const +{ + return m_width; +} + +void QGeoPathPrivate::setWidth(const qreal &width) +{ + if (qIsNaN(width) || width < 0.0) + return; + m_width = width; +} + +double QGeoPathPrivate::length(int indexFrom, int indexTo) const +{ + if (indexTo < 0 || indexTo >= path().size()) + indexTo = path().size() - 1; + double len = 0.0; + // TODO: consider calculating the length of the actual rhumb line segments + // instead of the shortest path from A to B. + for (int i = indexFrom; i < indexTo; i++) + len += m_path[i].distanceTo(m_path[i+1]); + return len; +} + +/*! + Returns true if coordinate is present in m_path. +*/ +bool QGeoPathPrivate::contains(const QGeoCoordinate &coordinate) const +{ + // Unoptimized approach: + // - consider each segment of the path + // - project it into mercator space (rhumb lines are straight in mercator space) + // - find closest point to coordinate + // - unproject the closest point + // - calculate coordinate to closest point distance with distanceTo() + // - if not within lineRadius, advance + // + // To keep wrapping into the equation: + // If the mercator x value of a coordinate of the line, or the coordinate parameter, is less + // than mercator(m_bbox).x, add that to the conversion. + + double lineRadius = qMax(width() * 0.5, 0.2); // minimum radius: 20cm + + if (!m_path.size()) + return false; + else if (m_path.size() == 1) + return (m_path[0].distanceTo(coordinate) <= lineRadius); + + double leftBoundMercator = QGeoProjection::coordToMercator(m_bbox.topLeft()).x(); + + QDoubleVector2D p = QGeoProjection::coordToMercator(coordinate); + if (p.x() < leftBoundMercator) + p.setX(p.x() + leftBoundMercator); // unwrap X + + QDoubleVector2D a; + QDoubleVector2D b; + if (m_path.size()) { + a = QGeoProjection::coordToMercator(m_path[0]); + if (a.x() < leftBoundMercator) + a.setX(a.x() + leftBoundMercator); // unwrap X + } + for (int i = 1; i < m_path.size(); i++) { + b = QGeoProjection::coordToMercator(m_path[i]); + if (b.x() < leftBoundMercator) + b.setX(b.x() + leftBoundMercator); // unwrap X + if (b == a) + continue; + + double u = ((p.x() - a.x()) * (b.x() - a.x()) + (p.y() - a.y()) * (b.y() - a.y()) ) / (b - a).lengthSquared(); + QDoubleVector2D intersection(a.x() + u * (b.x() - a.x()) , a.y() + u * (b.y() - a.y()) ); + + QDoubleVector2D candidate = ( (p-a).length() < (p-b).length() ) ? a : b; + + if (u < (b - a).length() + && (p-intersection).length() < (p-candidate).length() ) // And it falls in the segment + candidate = intersection; + + + if (candidate.x() > 1.0) + candidate.setX(candidate.x() - leftBoundMercator); // wrap X + + QGeoCoordinate closest = QGeoProjection::mercatorToCoord(candidate); + + double distanceMeters = coordinate.distanceTo(closest); + if (distanceMeters <= lineRadius) + return true; + + // swap + a = b; + } + + // Last check if the coordinate is on the left of leftBoundMercator, but close enough to + // m_path[0] + return (m_path[0].distanceTo(coordinate) <= lineRadius); +} + +QGeoCoordinate QGeoPathPrivate::center() const +{ + return boundingGeoRectangle().center(); +} + +QGeoRectangle QGeoPathPrivate::boundingGeoRectangle() const +{ + return m_bbox; +} + +void QGeoPathPrivate::extendShape(const QGeoCoordinate &coordinate) +{ + if (!coordinate.isValid() || contains(coordinate)) + return; + addCoordinate(coordinate); +} + +void QGeoPathPrivate::translate(double degreesLatitude, double degreesLongitude) +{ + if (degreesLatitude > 0.0) + degreesLatitude = qMin(degreesLatitude, 90.0 - m_maxLati); + else + degreesLatitude = qMax(degreesLatitude, -90.0 - m_minLati); + for (QGeoCoordinate &p: m_path) { + p.setLatitude(p.latitude() + degreesLatitude); + p.setLongitude(QLocationUtils::wrapLong(p.longitude() + degreesLongitude)); + } + m_bbox.translate(degreesLatitude, degreesLongitude); + m_minLati += degreesLatitude; + m_maxLati += degreesLatitude; +} + +void QGeoPathPrivate::addCoordinate(const QGeoCoordinate &coordinate) +{ + if (!coordinate.isValid()) + return; + m_path.append(coordinate); + updateBoundingBox(); +} + +void QGeoPathPrivate::insertCoordinate(int index, const QGeoCoordinate &coordinate) +{ + if (index < 0 || index > m_path.size() || !coordinate.isValid()) + return; + + m_path.insert(index, coordinate); + computeBoundingBox(); +} + +void QGeoPathPrivate::replaceCoordinate(int index, const QGeoCoordinate &coordinate) +{ + if (index < 0 || index >= m_path.size() || !coordinate.isValid()) + return; + + m_path[index] = coordinate; + computeBoundingBox(); +} + +QGeoCoordinate QGeoPathPrivate::coordinateAt(int index) const +{ + if (index < 0 || index >= m_path.size()) + return QGeoCoordinate(); + + return m_path.at(index); +} + +bool QGeoPathPrivate::containsCoordinate(const QGeoCoordinate &coordinate) const +{ + return m_path.indexOf(coordinate) > -1; +} + +void QGeoPathPrivate::removeCoordinate(const QGeoCoordinate &coordinate) +{ + int index = m_path.lastIndexOf(coordinate); + removeCoordinate(index); +} + +void QGeoPathPrivate::removeCoordinate(int index) +{ + if (index < 0 || index >= m_path.size()) + return; + + m_path.removeAt(index); + computeBoundingBox(); +} + +void QGeoPathPrivate::computeBoundingBox() +{ + if (m_path.isEmpty()) { + m_deltaXs.clear(); + m_minX = qInf(); + m_maxX = -qInf(); + m_minLati = qInf(); + m_maxLati = -qInf(); + m_bbox = QGeoRectangle(); + return; + } + + m_minLati = m_maxLati = m_path.at(0).latitude(); + int minId = 0; + int maxId = 0; + m_deltaXs.resize(m_path.size()); + m_deltaXs[0] = m_minX = m_maxX = 0.0; + + for (int i = 1; i < m_path.size(); i++) { + const QGeoCoordinate &geoFrom = m_path.at(i-1); + const QGeoCoordinate &geoTo = m_path.at(i); + double longiFrom = geoFrom.longitude(); + double longiTo = geoTo.longitude(); + double deltaLongi = longiTo - longiFrom; + if (qAbs(deltaLongi) > 180.0) { + if (longiTo > 0.0) + longiTo -= 360.0; + else + longiTo += 360.0; + deltaLongi = longiTo - longiFrom; + } + m_deltaXs[i] = m_deltaXs[i-1] + deltaLongi; + if (m_deltaXs[i] < m_minX) { + m_minX = m_deltaXs[i]; + minId = i; + } + if (m_deltaXs[i] > m_maxX) { + m_maxX = m_deltaXs[i]; + maxId = i; + } + if (geoTo.latitude() > m_maxLati) + m_maxLati = geoTo.latitude(); + if (geoTo.latitude() < m_minLati) + m_minLati = geoTo.latitude(); + } + + m_bbox = QGeoRectangle(QGeoCoordinate(m_maxLati, m_path.at(minId).longitude()), + QGeoCoordinate(m_minLati, m_path.at(maxId).longitude())); +} + +void QGeoPathPrivate::updateBoundingBox() +{ + if (m_path.isEmpty()) { + m_deltaXs.clear(); + m_minX = qInf(); + m_maxX = -qInf(); + m_minLati = qInf(); + m_maxLati = -qInf(); + m_bbox = QGeoRectangle(); + return; + } else if (m_path.size() == 1) { // was 0 now is 1 + m_deltaXs.resize(1); + m_deltaXs[0] = m_minX = m_maxX = 0.0; + m_minLati = m_maxLati = m_path.at(0).latitude(); + m_bbox = QGeoRectangle(QGeoCoordinate(m_maxLati, m_path.at(0).longitude()), + QGeoCoordinate(m_minLati, m_path.at(0).longitude())); + return; + } else if ( m_path.size() != m_deltaXs.size() + 1 ) { // this case should not happen + computeBoundingBox(); // something went wrong + return; + } + + const QGeoCoordinate &geoFrom = m_path.at(m_path.size()-2); + const QGeoCoordinate &geoTo = m_path.last(); + double longiFrom = geoFrom.longitude(); + double longiTo = geoTo.longitude(); + double deltaLongi = longiTo - longiFrom; + if (qAbs(deltaLongi) > 180.0) { + if (longiTo > 0.0) + longiTo -= 360.0; + else + longiTo += 360.0; + deltaLongi = longiTo - longiFrom; + } + + m_deltaXs.push_back(m_deltaXs.last() + deltaLongi); + double currentMinLongi = m_bbox.topLeft().longitude(); + double currentMaxLongi = m_bbox.bottomRight().longitude(); + if (m_deltaXs.last() < m_minX) { + m_minX = m_deltaXs.last(); + currentMinLongi = geoTo.longitude(); + } + if (m_deltaXs.last() > m_maxX) { + m_maxX = m_deltaXs.last(); + currentMaxLongi = geoTo.longitude(); + } + if (geoTo.latitude() > m_maxLati) + m_maxLati = geoTo.latitude(); + if (geoTo.latitude() < m_minLati) + m_minLati = geoTo.latitude(); + m_bbox = QGeoRectangle(QGeoCoordinate(m_maxLati, currentMinLongi), + QGeoCoordinate(m_minLati, currentMaxLongi)); +} + +QT_END_NAMESPACE diff --git a/src/positioning/qgeopath.h b/src/positioning/qgeopath.h new file mode 100644 index 00000000..09a53a49 --- /dev/null +++ b/src/positioning/qgeopath.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPATH_H +#define QGEOPATH_H + +#include <QtPositioning/QGeoShape> + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; +class QGeoPathPrivate; + +class Q_POSITIONING_EXPORT QGeoPath : public QGeoShape +{ + Q_GADGET + Q_PROPERTY(QList<QGeoCoordinate> path READ path WRITE setPath) + Q_PROPERTY(qreal width READ width WRITE setWidth) + +public: + QGeoPath(); + QGeoPath(const QList<QGeoCoordinate> &path, const qreal &width = 0.0); + QGeoPath(const QGeoPath &other); + QGeoPath(const QGeoShape &other); + + ~QGeoPath(); + + QGeoPath &operator=(const QGeoPath &other); + + using QGeoShape::operator==; + bool operator==(const QGeoPath &other) const; + + using QGeoShape::operator!=; + bool operator!=(const QGeoPath &other) const; + + void setPath(const QList<QGeoCoordinate> &path); + const QList<QGeoCoordinate> &path() const; + + void setWidth(const qreal &width); + qreal width() const; + + Q_INVOKABLE void translate(double degreesLatitude, double degreesLongitude); + Q_INVOKABLE QGeoPath translated(double degreesLatitude, double degreesLongitude) const; + Q_INVOKABLE double length(int indexFrom = 0, int indexTo = -1) const; + Q_INVOKABLE void addCoordinate(const QGeoCoordinate &coordinate); + Q_INVOKABLE void insertCoordinate(int index, const QGeoCoordinate &coordinate); + Q_INVOKABLE void replaceCoordinate(int index, const QGeoCoordinate &coordinate); + Q_INVOKABLE QGeoCoordinate coordinateAt(int index) const; + Q_INVOKABLE bool containsCoordinate(const QGeoCoordinate &coordinate) const; + Q_INVOKABLE void removeCoordinate(const QGeoCoordinate &coordinate); + Q_INVOKABLE void removeCoordinate(int index); + + Q_INVOKABLE QString toString() const; + +private: + inline QGeoPathPrivate *d_func(); + inline const QGeoPathPrivate *d_func() const; +}; + +Q_DECLARE_TYPEINFO(QGeoPath, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoPath) + +#endif // QGEOPATH_H diff --git a/src/positioning/qgeopath_p.h b/src/positioning/qgeopath_p.h new file mode 100644 index 00000000..2256796d --- /dev/null +++ b/src/positioning/qgeopath_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtPositioning module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOPATH_P_H +#define QGEOPATH_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qgeoshape_p.h" +#include "qgeocoordinate.h" +#include "qlocationutils_p.h" + +#include <QtCore/QVector> + +QT_BEGIN_NAMESPACE + +class QGeoPathPrivate : public QGeoShapePrivate +{ +public: + QGeoPathPrivate(); + QGeoPathPrivate(const QList<QGeoCoordinate> &path, const qreal width = 0.0); + QGeoPathPrivate(const QGeoPathPrivate &other); + ~QGeoPathPrivate(); + + bool isValid() const Q_DECL_OVERRIDE; + bool isEmpty() const Q_DECL_OVERRIDE; + bool contains(const QGeoCoordinate &coordinate) const Q_DECL_OVERRIDE; + + QGeoCoordinate center() const Q_DECL_OVERRIDE; + QGeoRectangle boundingGeoRectangle() const Q_DECL_OVERRIDE; + void extendShape(const QGeoCoordinate &coordinate) Q_DECL_OVERRIDE; + void translate(double degreesLatitude, double degreesLongitude); + + QGeoShapePrivate *clone() const Q_DECL_OVERRIDE; + + bool operator==(const QGeoShapePrivate &other) const Q_DECL_OVERRIDE; + + const QList<QGeoCoordinate> &path() const; + void setPath(const QList<QGeoCoordinate> &path); + qreal width() const; + void setWidth(const qreal &width); + double length(int indexFrom, int indexTo) const; + void addCoordinate(const QGeoCoordinate &coordinate); + void insertCoordinate(int index, const QGeoCoordinate &coordinate); + void replaceCoordinate(int index, const QGeoCoordinate &coordinate); + QGeoCoordinate coordinateAt(int index) const; + bool containsCoordinate(const QGeoCoordinate &coordinate) const; + void removeCoordinate(const QGeoCoordinate &coordinate); + void removeCoordinate(int index); + void computeBoundingBox(); + void updateBoundingBox(); + + + QList<QGeoCoordinate> m_path; + QVector<double> m_deltaXs; // longitude deltas from m_path[0] + double m_minX; // minimum value inside deltaXs + double m_maxX; // maximum value inside deltaXs + double m_minLati; // minimum latitude. paths do not wrap around through the poles + double m_maxLati; // minimum latitude. paths do not wrap around through the poles + QGeoRectangle m_bbox; + qreal m_width; +}; + +QT_END_NAMESPACE + +#endif // QGEOPATH_P_H diff --git a/src/positioning/qgeorectangle.cpp b/src/positioning/qgeorectangle.cpp index bbcafd6b..e74beee3 100644 --- a/src/positioning/qgeorectangle.cpp +++ b/src/positioning/qgeorectangle.cpp @@ -40,8 +40,11 @@ #include "qgeorectangle.h" #include "qgeorectangle_p.h" +#include "qgeoprojection_p.h" +#include "qdoublevector2d_p.h" #include "qgeocoordinate.h" #include "qnumeric.h" +#include "qlocationutils_p.h" #include <QList> QT_BEGIN_NAMESPACE @@ -440,16 +443,8 @@ void QGeoRectangle::setCenter(const QGeoCoordinate ¢er) double tlLon = center.longitude() - width / 2.0; double brLat = center.latitude() - height / 2.0; double brLon = center.longitude() + width / 2.0; - - if (tlLon < -180.0) - tlLon += 360.0; - if (tlLon > 180.0) - tlLon -= 360.0; - - if (brLon < -180.0) - brLon += 360.0; - if (brLon > 180.0) - brLon -= 360.0; + tlLon = QLocationUtils::wrapLong(tlLon); + brLon = QLocationUtils::wrapLong(brLon); if (tlLat > 90.0) { brLat = 2 * center.latitude() - 90.0; @@ -515,18 +510,10 @@ void QGeoRectangle::setWidth(double degreesWidth) QGeoCoordinate c = center(); double tlLon = c.longitude() - degreesWidth / 2.0; - - if (tlLon < -180.0) - tlLon += 360.0; - if (tlLon > 180.0) - tlLon -= 360.0; + tlLon = QLocationUtils::wrapLong(tlLon); double brLon = c.longitude() + degreesWidth / 2.0; - - if (brLon < -180.0) - brLon += 360.0; - if (brLon > 180.0) - brLon -= 360.0; + brLon = QLocationUtils::wrapLong(brLon); d->topLeft = QGeoCoordinate(tlLat, tlLon); d->bottomRight = QGeoCoordinate(brLat, brLon); @@ -614,10 +601,7 @@ double QGeoRectangle::height() const Q_D(const QGeoRectangle); - double result = d->topLeft.latitude() - d->bottomRight.latitude(); - if (result < 0.0) - result = qQNaN(); - return result; + return d->topLeft.latitude() - d->bottomRight.latitude(); } bool QGeoRectanglePrivate::contains(const QGeoCoordinate &coordinate) const @@ -666,14 +650,15 @@ QGeoCoordinate QGeoRectanglePrivate::center() const if (topLeft.longitude() > bottomRight.longitude()) cLon = cLon - 180.0; - if (cLon < -180.0) - cLon += 360.0; - if (cLon > 180.0) - cLon -= 360.0; - + cLon = QLocationUtils::wrapLong(cLon); return QGeoCoordinate(cLat, cLon); } +QGeoRectangle QGeoRectanglePrivate::boundingGeoRectangle() const +{ + return QGeoRectangle(topLeft, bottomRight); +} + /*! Returns whether the geo rectangle \a rectangle is contained within this geo rectangle. @@ -763,37 +748,18 @@ void QGeoRectangle::translate(double degreesLatitude, double degreesLongitude) double brLat = d->bottomRight.latitude(); double brLon = d->bottomRight.longitude(); - if ((tlLat != 90.0) || (brLat != -90.0)) { - tlLat += degreesLatitude; - brLat += degreesLatitude; - } + if (degreesLatitude >= 0.0) + degreesLatitude = qMin(degreesLatitude, 90.0 - tlLat); + else + degreesLatitude = qMax(degreesLatitude, -90.0 - brLat); if ( (tlLon != -180.0) || (brLon != 180.0) ) { - tlLon += degreesLongitude; - brLon += degreesLongitude; + tlLon = QLocationUtils::wrapLong(tlLon + degreesLongitude); + brLon = QLocationUtils::wrapLong(brLon + degreesLongitude); } - if (tlLon < -180.0) - tlLon += 360.0; - if (tlLon > 180.0) - tlLon -= 360.0; - - if (brLon < -180.0) - brLon += 360.0; - if (brLon > 180.0) - brLon -= 360.0; - - if (tlLat > 90.0) - tlLat = 90.0; - - if (tlLat < -90.0) - tlLat = -90.0; - - if (brLat > 90.0) - brLat = 90.0; - - if (brLat < -90.0) - brLat = -90.0; + tlLat += degreesLatitude; + brLat += degreesLatitude; d->topLeft = QGeoCoordinate(tlLat, tlLon); d->bottomRight = QGeoCoordinate(brLat, brLon); diff --git a/src/positioning/qgeorectangle.h b/src/positioning/qgeorectangle.h index 7e921730..9e9acf91 100644 --- a/src/positioning/qgeorectangle.h +++ b/src/positioning/qgeorectangle.h @@ -42,89 +42,7 @@ #include <QtPositioning/QGeoShape> -QT_BEGIN_NAMESPACE - -class QGeoCoordinate; -class QGeoRectanglePrivate; - -class Q_POSITIONING_EXPORT QGeoRectangle : public QGeoShape -{ - Q_GADGET - Q_PROPERTY(QGeoCoordinate bottomLeft READ bottomLeft WRITE setBottomLeft) - Q_PROPERTY(QGeoCoordinate bottomRight READ bottomRight WRITE setBottomRight) - Q_PROPERTY(QGeoCoordinate topLeft READ topLeft WRITE setTopLeft) - Q_PROPERTY(QGeoCoordinate topRight READ topRight WRITE setTopRight) - Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter) - Q_PROPERTY(double height READ height WRITE setHeight) - Q_PROPERTY(double width READ width WRITE setWidth) - -public: - QGeoRectangle(); - QGeoRectangle(const QGeoCoordinate ¢er, double degreesWidth, double degreesHeight); - QGeoRectangle(const QGeoCoordinate &topLeft, const QGeoCoordinate &bottomRight); - QGeoRectangle(const QList<QGeoCoordinate> &coordinates); - QGeoRectangle(const QGeoRectangle &other); - QGeoRectangle(const QGeoShape &other); - - ~QGeoRectangle(); - - QGeoRectangle &operator=(const QGeoRectangle &other); - - using QGeoShape::operator==; - bool operator==(const QGeoRectangle &other) const; - - using QGeoShape::operator!=; - bool operator!=(const QGeoRectangle &other) const; - - void setTopLeft(const QGeoCoordinate &topLeft); - QGeoCoordinate topLeft() const; - - void setTopRight(const QGeoCoordinate &topRight); - QGeoCoordinate topRight() const; - - void setBottomLeft(const QGeoCoordinate &bottomLeft); - QGeoCoordinate bottomLeft() const; - - void setBottomRight(const QGeoCoordinate &bottomRight); - QGeoCoordinate bottomRight() const; - - void setCenter(const QGeoCoordinate ¢er); - QGeoCoordinate center() const; - - void setWidth(double degreesWidth); - double width() const; - - void setHeight(double degreesHeight); - double height() const; - - using QGeoShape::contains; - bool contains(const QGeoRectangle &rectangle) const; - bool intersects(const QGeoRectangle &rectangle) const; - - void translate(double degreesLatitude, double degreesLongitude); - QGeoRectangle translated(double degreesLatitude, double degreesLongitude) const; - - QGeoRectangle united(const QGeoRectangle &rectangle) const; - QGeoRectangle operator|(const QGeoRectangle &rectangle) const; - QGeoRectangle &operator|=(const QGeoRectangle &rectangle); - - Q_INVOKABLE QString toString() const; - -private: - inline QGeoRectanglePrivate *d_func(); - inline const QGeoRectanglePrivate *d_func() const; -}; - -Q_DECLARE_TYPEINFO(QGeoRectangle, Q_MOVABLE_TYPE); - -inline QGeoRectangle QGeoRectangle::operator|(const QGeoRectangle &rectangle) const -{ - return united(rectangle); -} - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(QGeoRectangle) +// QGeoRectangle declaration now in qgeoshape.h. +// This file remains for compatibility. #endif - diff --git a/src/positioning/qgeorectangle_p.h b/src/positioning/qgeorectangle_p.h index 188e5548..ee1b1732 100644 --- a/src/positioning/qgeorectangle_p.h +++ b/src/positioning/qgeorectangle_p.h @@ -70,6 +70,8 @@ public: QGeoCoordinate center() const Q_DECL_OVERRIDE; + QGeoRectangle boundingGeoRectangle() const Q_DECL_OVERRIDE; + void extendShape(const QGeoCoordinate &coordinate) Q_DECL_OVERRIDE; QGeoShapePrivate *clone() const Q_DECL_OVERRIDE; diff --git a/src/positioning/qgeoshape.cpp b/src/positioning/qgeoshape.cpp index bac37605..c1f7bd9d 100644 --- a/src/positioning/qgeoshape.cpp +++ b/src/positioning/qgeoshape.cpp @@ -41,6 +41,8 @@ #include "qgeoshape_p.h" #include "qgeorectangle.h" #include "qgeocircle.h" +#include "qgeopath.h" + #ifndef QT_NO_DEBUG_STREAM #include <QtCore/QDebug> @@ -227,6 +229,22 @@ bool QGeoShape::contains(const QGeoCoordinate &coordinate) const } /*! + Returns a \a QGeoRectangle representing the geographical bounding rectangle of the + geo shape, that defines the latitudinal/longitudinal bounds of the geo shape. + + \since 5.9 +*/ +QGeoRectangle QGeoShape::boundingGeoRectangle() const +{ + Q_D(const QGeoShape); + + if (d) + return d->boundingGeoRectangle(); + else + return QGeoRectangle(); +} + +/*! Returns the coordinate located at the geometric center of the geo shape. \since 5.5 @@ -313,6 +331,9 @@ QDebug operator<<(QDebug dbg, const QGeoShape &shape) case QGeoShape::RectangleType: dbg << "Rectangle"; break; + case QGeoShape::PathType: + dbg << "Path"; + break; case QGeoShape::CircleType: dbg << "Circle"; } @@ -340,6 +361,13 @@ QDataStream &operator<<(QDataStream &stream, const QGeoShape &shape) stream << c.center() << c.radius(); break; } + case QGeoShape::PathType: { + QGeoPath p = shape; + stream << p.path().size(); + for (const auto &c: p.path()) + stream << c; + break; + } } return stream; @@ -368,6 +396,18 @@ QDataStream &operator>>(QDataStream &stream, QGeoShape &shape) shape = QGeoCircle(c, r); break; } + case QGeoShape::PathType: { + QList<QGeoCoordinate> l; + QGeoCoordinate c; + int sz; + stream >> sz; + for (int i = 0; i < sz; i++) { + stream >> c; + l.append(c); + } + shape = QGeoPath(l); + break; + } } return stream; diff --git a/src/positioning/qgeoshape.h b/src/positioning/qgeoshape.h index f8a30358..40123f88 100644 --- a/src/positioning/qgeoshape.h +++ b/src/positioning/qgeoshape.h @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE class QDebug; class QGeoShapePrivate; +class QGeoRectangle; class Q_POSITIONING_EXPORT QGeoShape { @@ -64,7 +65,8 @@ public: enum ShapeType { UnknownType, RectangleType, - CircleType + CircleType, + PathType }; ShapeType type() const; @@ -72,10 +74,10 @@ public: bool isValid() const; bool isEmpty() const; Q_INVOKABLE bool contains(const QGeoCoordinate &coordinate) const; + Q_INVOKABLE QGeoRectangle boundingGeoRectangle() const; + Q_INVOKABLE QGeoCoordinate center() const; - QGeoCoordinate center() const; - - void extendShape(const QGeoCoordinate &coordinate); + Q_INVOKABLE void extendShape(const QGeoCoordinate &coordinate); bool operator==(const QGeoShape &other) const; bool operator!=(const QGeoShape &other) const; @@ -104,9 +106,89 @@ Q_POSITIONING_EXPORT QDataStream &operator<<(QDataStream &stream, const QGeoShap Q_POSITIONING_EXPORT QDataStream &operator>>(QDataStream &stream, QGeoShape &shape); #endif + + +// QGeoRectangle is declared here because of QGeoShape::boundingGeoRectangle +class QGeoRectanglePrivate; + +class Q_POSITIONING_EXPORT QGeoRectangle : public QGeoShape +{ + Q_GADGET + Q_PROPERTY(QGeoCoordinate bottomLeft READ bottomLeft WRITE setBottomLeft) + Q_PROPERTY(QGeoCoordinate bottomRight READ bottomRight WRITE setBottomRight) + Q_PROPERTY(QGeoCoordinate topLeft READ topLeft WRITE setTopLeft) + Q_PROPERTY(QGeoCoordinate topRight READ topRight WRITE setTopRight) + Q_PROPERTY(QGeoCoordinate center READ center WRITE setCenter) + Q_PROPERTY(double height READ height WRITE setHeight) + Q_PROPERTY(double width READ width WRITE setWidth) + +public: + QGeoRectangle(); + QGeoRectangle(const QGeoCoordinate ¢er, double degreesWidth, double degreesHeight); + QGeoRectangle(const QGeoCoordinate &topLeft, const QGeoCoordinate &bottomRight); + QGeoRectangle(const QList<QGeoCoordinate> &coordinates); + QGeoRectangle(const QGeoRectangle &other); + QGeoRectangle(const QGeoShape &other); + + ~QGeoRectangle(); + + QGeoRectangle &operator=(const QGeoRectangle &other); + + using QGeoShape::operator==; + bool operator==(const QGeoRectangle &other) const; + + using QGeoShape::operator!=; + bool operator!=(const QGeoRectangle &other) const; + + void setTopLeft(const QGeoCoordinate &topLeft); + QGeoCoordinate topLeft() const; + + void setTopRight(const QGeoCoordinate &topRight); + QGeoCoordinate topRight() const; + + void setBottomLeft(const QGeoCoordinate &bottomLeft); + QGeoCoordinate bottomLeft() const; + + void setBottomRight(const QGeoCoordinate &bottomRight); + QGeoCoordinate bottomRight() const; + + void setCenter(const QGeoCoordinate ¢er); + QGeoCoordinate center() const; + + void setWidth(double degreesWidth); + double width() const; + + void setHeight(double degreesHeight); + double height() const; + + using QGeoShape::contains; + bool contains(const QGeoRectangle &rectangle) const; + Q_INVOKABLE bool intersects(const QGeoRectangle &rectangle) const; + + Q_INVOKABLE void translate(double degreesLatitude, double degreesLongitude); + Q_INVOKABLE QGeoRectangle translated(double degreesLatitude, double degreesLongitude) const; + + Q_INVOKABLE QGeoRectangle united(const QGeoRectangle &rectangle) const; + QGeoRectangle operator|(const QGeoRectangle &rectangle) const; + QGeoRectangle &operator|=(const QGeoRectangle &rectangle); + + Q_INVOKABLE QString toString() const; + +private: + inline QGeoRectanglePrivate *d_func(); + inline const QGeoRectanglePrivate *d_func() const; +}; + +Q_DECLARE_TYPEINFO(QGeoRectangle, Q_MOVABLE_TYPE); + +inline QGeoRectangle QGeoRectangle::operator|(const QGeoRectangle &rectangle) const +{ + return united(rectangle); +} + QT_END_NAMESPACE Q_DECLARE_METATYPE(QGeoShape) +Q_DECLARE_METATYPE(QGeoRectangle) #endif - diff --git a/src/positioning/qgeoshape_p.h b/src/positioning/qgeoshape_p.h index 275886ff..251e872c 100644 --- a/src/positioning/qgeoshape_p.h +++ b/src/positioning/qgeoshape_p.h @@ -69,6 +69,8 @@ public: virtual QGeoCoordinate center() const = 0; + virtual QGeoRectangle boundingGeoRectangle() const = 0; + virtual void extendShape(const QGeoCoordinate &coordinate) = 0; virtual QGeoShapePrivate *clone() const = 0; @@ -89,4 +91,3 @@ Q_INLINE_TEMPLATE QGeoShapePrivate *QSharedDataPointer<QGeoShapePrivate>::clone( QT_END_NAMESPACE #endif - diff --git a/src/positioning/qlocationutils_p.h b/src/positioning/qlocationutils_p.h index 00c4d3e3..32addb63 100644 --- a/src/positioning/qlocationutils_p.h +++ b/src/positioning/qlocationutils_p.h @@ -53,6 +53,14 @@ #include <QtCore/QtGlobal> #include <math.h> +#ifndef M_1_180 +#define M_1_180 0.0055555555555555555555555555555555555555556 +#endif + +#ifndef M_1_PI +#define M_1_PI 0.31830988618379067154 +#endif + QT_BEGIN_NAMESPACE class QTime; class QByteArray; @@ -176,6 +184,47 @@ public: return CardinalNNW; } + // For values exceeding +- 720.0 + inline static double wrapLongExt(double lng) { + double remainder = fmod(lng + 180.0, 360.0); + return fmod(remainder + 360.0, 360.0) - 180.0; + } + + // Mirrors the azimuth against the X axis. Azimuth assumed to be in [0,360[ + inline static double mirrorAzimuthX(double azimuth) { + if (azimuth <= 90.0) + return 180.0 - azimuth; + else + return 180.0 + (360.0 - azimuth); + } + + // Mirrors the azimuth against the Y axis. Azimuth assumed to be in [0,360[ + inline static double mirrorAzimuthY(double azimuth) { + if (azimuth == 0.0) + return 0.0; + return 360.0 - azimuth; + } + + inline static double radians(double degrees) + { + return degrees * M_PI * M_1_180; + } + + inline static double degrees(double radians) + { + return radians * 180.0 * M_1_PI; + } + + inline static double earthMeanRadius() + { + return 6371007.2; + } + + inline static double mercatorMaxLatitude() + { + return 85.05113; + } + /* Creates a QGeoPositionInfo from a GGA, GLL, RMC, VTG or ZDA sentence. diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index e3236deb..ba7dc523 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -74,6 +74,7 @@ SUBDIRS += \ qgeoshape \ qgeorectangle \ qgeocircle \ + qgeopath \ qgeocoordinate \ qgeolocation \ qgeopositioninfo \ diff --git a/tests/auto/declarative_ui/tst_map.qml b/tests/auto/declarative_ui/tst_map.qml index 5f02962d..a81885fb 100644 --- a/tests/auto/declarative_ui/tst_map.qml +++ b/tests/auto/declarative_ui/tst_map.qml @@ -28,8 +28,8 @@ import QtQuick 2.0 import QtTest 1.0 -import QtLocation 5.6 import QtPositioning 5.5 +import QtLocation 5.9 Item { width:100 @@ -82,7 +82,11 @@ Item { Map {id: coordinateMap; plugin: herePlugin; center: coordinate3; width: 1000; height: 1000; zoomLevel: 15 } - + MapParameter { + id: testParameter + type: "cameraCenter_test" + property var center: QtPositioning.coordinate(-33.0, -47.0) + } TestCase { @@ -128,6 +132,51 @@ Item { compare(map.center.latitude, 12) } + function test_map_parameters() + { + // coordinate is set at map element declaration + var center = map.toCoordinate(Qt.point((map.width - 1) / 2.0, (map.height - 1) / 2.0)) + fuzzyCompare(center.latitude, 10, 0.1) + fuzzyCompare(center.longitude, 11, 0.1) + + compare(map.mapParameters.length, 0) + + map.addMapParameter(testParameter) + + compare(map.mapParameters.length, 1) + + center = map.toCoordinate(Qt.point((map.width - 1) / 2.0, (map.height - 1) / 2.0)) + fuzzyCompare(center.latitude, -33, 0.1) + fuzzyCompare(center.longitude, -47, 0.1) + + map.addMapParameter(testParameter) + compare(map.mapParameters.length, 1) + + map.removeMapParameter(testParameter) + compare(map.mapParameters.length, 0) + + center = map.toCoordinate(Qt.point((map.width - 1) / 2.0, (map.height - 1) / 2.0)) + fuzzyCompare(center.latitude, -33, 0.1) + fuzzyCompare(center.longitude, -47, 0.1) + + testParameter.center = map.center + map.addMapParameter(testParameter) + compare(map.mapParameters.length, 1) + + var center = map.toCoordinate(Qt.point((map.width - 1) / 2.0, (map.height - 1) / 2.0)) + fuzzyCompare(center.latitude, 10, 0.1) + fuzzyCompare(center.longitude, 11, 0.1) + + testParameter.center = QtPositioning.coordinate(-33.0, -47.0) + + center = map.toCoordinate(Qt.point((map.width - 1) / 2.0, (map.height - 1) / 2.0)) + fuzzyCompare(center.latitude, -33, 0.1) + fuzzyCompare(center.longitude, -47, 0.1) + + map.removeMapParameter(testParameter) + compare(map.mapParameters.length, 0) + } + function test_map_clamp() { //valid diff --git a/tests/auto/geotestplugin/geotestplugin.pro b/tests/auto/geotestplugin/geotestplugin.pro index fb3f1b39..f4fe25b3 100644 --- a/tests/auto/geotestplugin/geotestplugin.pro +++ b/tests/auto/geotestplugin/geotestplugin.pro @@ -14,7 +14,8 @@ HEADERS += qgeocodingmanagerengine_test.h \ qgeotiledmap_test.h \ qgeotilefetcher_test.h -SOURCES += qgeoserviceproviderplugin_test.cpp +SOURCES += qgeoserviceproviderplugin_test.cpp \ + qgeotiledmap_test.cpp OTHER_FILES += \ geotestplugin.json \ diff --git a/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h b/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h index 1d9f0792..ecbb60d1 100644 --- a/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h +++ b/tests/auto/geotestplugin/qgeocodingmanagerengine_test.h @@ -57,11 +57,6 @@ public: void callSetOffset ( int offset ) {setOffset(offset);} void callSetLocations ( const QList<QGeoLocation> & locations ) {setLocations(locations);} void callSetViewport ( const QGeoShape &viewport ) {setViewport(viewport);} - void abort() { - emit aborted(); - } -Q_SIGNALS: - void aborted(); }; class QGeoCodingManagerEngineTest: public QGeoCodingManagerEngine diff --git a/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h index 8ae58042..0a1e7ce6 100644 --- a/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h +++ b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h @@ -52,12 +52,6 @@ public: void callSetError ( Error error, const QString & errorString ) {setError(error, errorString);} void callSetFinished ( bool finished ) {setFinished(finished);} void callSetRoutes(const QList<QGeoRoute> &routes) {setRoutes(routes);} - - void abort() { - emit aborted(); - } -Q_SIGNALS: - void aborted(); }; class QGeoRoutingManagerEngineTest: public QGeoRoutingManagerEngine diff --git a/tests/auto/geotestplugin/qgeotiledmap_test.cpp b/tests/auto/geotestplugin/qgeotiledmap_test.cpp new file mode 100644 index 00000000..ef2af7db --- /dev/null +++ b/tests/auto/geotestplugin/qgeotiledmap_test.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeotiledmap_test.h" +#include <QtLocation/private/qgeotiledmap_p_p.h> +#include <QtLocation/private/qgeomapparameter_p.h> + +QT_USE_NAMESPACE + +class QGeoTiledMapTestPrivate: public QGeoTiledMapPrivate +{ + Q_DECLARE_PUBLIC(QGeoTiledMapTest) +public: + QGeoTiledMapTestPrivate(QGeoTiledMappingManagerEngine *engine) + : QGeoTiledMapPrivate(engine) + { + + } + + ~QGeoTiledMapTestPrivate() + { + + } + + void addParameter(QGeoMapParameter *param) override + { + Q_Q(QGeoTiledMapTest); + if (param->type() == QStringLiteral("cameraCenter_test")) { + // We assume that cameraCenter_test parameters have a QGeoCoordinate property named "center" + // Handle the parameter + QGeoCameraData cameraData = m_cameraData; + QGeoCoordinate newCenter = param->property("center").value<QGeoCoordinate>(); + cameraData.setCenter(newCenter); + q->setCameraData(cameraData); + // Connect for further changes handling + q->connect(param, SIGNAL(propertyUpdated(QGeoMapParameter *, const char *)), + q, SLOT(onCameraCenter_testChanged(QGeoMapParameter*, const char*))); + + } + } + void removeParameter(QGeoMapParameter *param) override + { + Q_Q(QGeoTiledMapTest); + param->disconnect(q); + } +}; + +QGeoTiledMapTest::QGeoTiledMapTest(QGeoTiledMappingManagerEngine *engine, QObject *parent) +: QGeoTiledMap(*new QGeoTiledMapTestPrivate(engine), engine, parent), m_engine(engine) +{ +} + +void QGeoTiledMapTest::onCameraCenter_testChanged(QGeoMapParameter *param, const char *propertyName) +{ + Q_D(QGeoTiledMapTest); + if (strcmp(propertyName, "center") == 0) { + QGeoCameraData cameraData = d->m_cameraData; + // Not testing for propertyName as this param has only one allowed property + QGeoCoordinate newCenter = param->property(propertyName).value<QGeoCoordinate>(); + cameraData.setCenter(newCenter); + setCameraData(cameraData); + } +} diff --git a/tests/auto/geotestplugin/qgeotiledmap_test.h b/tests/auto/geotestplugin/qgeotiledmap_test.h index 27ff7164..19c7620e 100644 --- a/tests/auto/geotestplugin/qgeotiledmap_test.h +++ b/tests/auto/geotestplugin/qgeotiledmap_test.h @@ -33,17 +33,25 @@ #include <QtLocation/private/qgeotiledmap_p.h> QT_USE_NAMESPACE + class QGeoTiledMappingManagerEngineTest; +class QGeoTiledMapTestPrivate; + class QGeoTiledMapTest: public QGeoTiledMap { Q_OBJECT + Q_DECLARE_PRIVATE(QGeoTiledMapTest) public: - QGeoTiledMapTest(QGeoTiledMappingManagerEngine *engine, QObject *parent = 0): - QGeoTiledMap(engine, parent), - m_engine(engine){} + QGeoTiledMapTest(QGeoTiledMappingManagerEngine *engine, QObject *parent = 0); + +protected slots: + void onCameraCenter_testChanged(QGeoMapParameter *param, const char *propertyName); + public: using QGeoTiledMap::setCameraData; QGeoTiledMappingManagerEngine *m_engine; }; #endif + + diff --git a/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h index 2765c268..015a203a 100644 --- a/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h +++ b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h @@ -57,6 +57,9 @@ public: capabilities.setMinimumZoomLevel(0.0); capabilities.setMaximumZoomLevel(20.0); capabilities.setSupportsBearing(true); + capabilities.setSupportsTilting(true); + capabilities.setMinimumTilt(0); + capabilities.setMaximumTilt(60); setTileSize(QSize(256, 256)); QList<QGeoMapType> mapTypes; diff --git a/tests/auto/qgeocameracapabilities/tst_qgeocameracapabilities.cpp b/tests/auto/qgeocameracapabilities/tst_qgeocameracapabilities.cpp index 54755421..09d7293b 100644 --- a/tests/auto/qgeocameracapabilities/tst_qgeocameracapabilities.cpp +++ b/tests/auto/qgeocameracapabilities/tst_qgeocameracapabilities.cpp @@ -29,8 +29,8 @@ #include <QtCore/QString> #include <QtTest/QtTest> -#include "qgeocameracapabilities_p.h" -#include "qgeotiledmap_p.h" +#include <QtLocation/private/qgeocameracapabilities_p.h> +#include <QtLocation/private/qgeotiledmap_p.h> QT_USE_NAMESPACE diff --git a/tests/auto/qgeocircle/tst_qgeocircle.cpp b/tests/auto/qgeocircle/tst_qgeocircle.cpp index 01fbed6b..fb2f248b 100644 --- a/tests/auto/qgeocircle/tst_qgeocircle.cpp +++ b/tests/auto/qgeocircle/tst_qgeocircle.cpp @@ -60,6 +60,9 @@ private slots: void contains_data(); void contains(); + void boundingGeoRectangle_data(); + void boundingGeoRectangle(); + void extendShape(); void extendShape_data(); @@ -243,7 +246,7 @@ void tst_QGeoCircle::valid() QCOMPARE(c.isValid(), valid); QGeoShape area = c; - QCOMPARE(c.isValid(), valid); + QCOMPARE(area.isValid(), valid); } void tst_QGeoCircle::empty_data() @@ -281,7 +284,7 @@ void tst_QGeoCircle::contains_data() QTest::addColumn<QGeoCoordinate>("probe"); QTest::addColumn<bool>("result"); - QTest::newRow("own centre") << QGeoCoordinate(1,1) << qreal(100.0) << + QTest::newRow("own center") << QGeoCoordinate(1,1) << qreal(100.0) << QGeoCoordinate(1,1) << true; QTest::newRow("over the hills") << QGeoCoordinate(1,1) << qreal(100.0) << QGeoCoordinate(30, 40) << false; @@ -291,6 +294,7 @@ void tst_QGeoCircle::contains_data() QGeoCoordinate(1.00077538, 0.99955527) << true; QTest::newRow("at 1.01*radius") << QGeoCoordinate(1,1) << qreal(100.0) << QGeoCoordinate(1.00071413, 0.99943423) << false; + // TODO: add tests for edge circle cases: cross 1 pole, cross both poles } void tst_QGeoCircle::contains() @@ -307,6 +311,38 @@ void tst_QGeoCircle::contains() QCOMPARE(area.contains(probe), result); } +void tst_QGeoCircle::boundingGeoRectangle_data() +{ + QTest::addColumn<QGeoCoordinate>("center"); + QTest::addColumn<qreal>("radius"); + QTest::addColumn<QGeoCoordinate>("probe"); + QTest::addColumn<bool>("result"); + + QTest::newRow("own center") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(1,1) << true; + QTest::newRow("over the hills") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(30, 40) << false; + QTest::newRow("at 0.5*radius") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(1.00015374,1.00015274) << true; + QTest::newRow("at 0.99*radius") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(1.00077538, 0.99955527) << true; + QTest::newRow("Outside the box") << QGeoCoordinate(1,1) << qreal(100.0) << + QGeoCoordinate(1.00071413, 0.99903423) << false; + // TODO: add tests for edge circle cases: cross 1 pole, cross both poles +} + +void tst_QGeoCircle::boundingGeoRectangle() +{ + QFETCH(QGeoCoordinate, center); + QFETCH(qreal, radius); + QFETCH(QGeoCoordinate, probe); + QFETCH(bool, result); + + QGeoCircle c(center, radius); + QGeoRectangle box = c.boundingGeoRectangle(); + QCOMPARE(box.contains(probe), result); +} + void tst_QGeoCircle::extendShape() { QFETCH(QGeoCircle, circle); diff --git a/tests/auto/qgeopath/qgeopath.pro b/tests/auto/qgeopath/qgeopath.pro new file mode 100644 index 00000000..eec05974 --- /dev/null +++ b/tests/auto/qgeopath/qgeopath.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeopath + +SOURCES += \ + tst_qgeopath.cpp + +QT += positioning testlib diff --git a/tests/auto/qgeopath/tst_qgeopath.cpp b/tests/auto/qgeopath/tst_qgeopath.cpp new file mode 100644 index 00000000..8c4ac767 --- /dev/null +++ b/tests/auto/qgeopath/tst_qgeopath.cpp @@ -0,0 +1,385 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtTest/QtTest> +#include <QtPositioning/QGeoCoordinate> +#include <QtPositioning/QGeoRectangle> +#include <QtPositioning/QGeoPath> + +QT_USE_NAMESPACE + +class tst_QGeoPath : public QObject +{ + Q_OBJECT + +private slots: + void defaultConstructor(); + void listConstructor(); + void assignment(); + + void comparison(); + void type(); + + void path(); + void width(); + + void translate_data(); + void translate(); + + void valid_data(); + void valid(); + + void contains_data(); + void contains(); + + void boundingGeoRectangle_data(); + void boundingGeoRectangle(); + + void extendShape(); + void extendShape_data(); +}; + +void tst_QGeoPath::defaultConstructor() +{ + QGeoPath p; + QVERIFY(!p.path().size()); + QCOMPARE(p.width(), qreal(0.0)); +} + +void tst_QGeoPath::listConstructor() +{ + QList<QGeoCoordinate> coords; + coords.append(QGeoCoordinate(1,1)); + coords.append(QGeoCoordinate(2,2)); + coords.append(QGeoCoordinate(3,0)); + + QGeoPath p(coords, 1.0); + QCOMPARE(p.width(), qreal(1.0)); + QCOMPARE(p.path().size(), 3); + + for (const QGeoCoordinate &c : coords) { + QCOMPARE(p.path().contains(c), true); + } +} + +void tst_QGeoPath::assignment() +{ + QGeoPath p1; + QList<QGeoCoordinate> coords; + coords.append(QGeoCoordinate(1,1)); + coords.append(QGeoCoordinate(2,2)); + coords.append(QGeoCoordinate(3,0)); + QGeoPath p2(coords, 1.0); + + QVERIFY(p1 != p2); + + p1 = p2; + QCOMPARE(p1.path(), coords); + QCOMPARE(p1.width(), 1.0); + QCOMPARE(p1, p2); + + // Assign c1 to an area + QGeoShape area = p1; + QCOMPARE(area.type(), p1.type()); + QVERIFY(area == p1); + + // Assign the area back to a bounding circle + QGeoPath p3 = area; + QCOMPARE(p3.path(), coords); + QCOMPARE(p3.width(), 1.0); + + // Check that the copy is not modified when modifying the original. + p1.setWidth(2.0); + QVERIFY(p3.width() != p1.width()); + QVERIFY(p3 != p1); +} + +void tst_QGeoPath::comparison() +{ + QList<QGeoCoordinate> coords; + coords.append(QGeoCoordinate(1,1)); + coords.append(QGeoCoordinate(2,2)); + coords.append(QGeoCoordinate(3,0)); + QList<QGeoCoordinate> coords2; + coords2.append(QGeoCoordinate(3,1)); + coords2.append(QGeoCoordinate(4,2)); + coords2.append(QGeoCoordinate(3,0)); + QGeoPath c1(coords, qreal(50.0)); + QGeoPath c2(coords, qreal(50.0)); + QGeoPath c3(coords, qreal(35.0)); + QGeoPath c4(coords2, qreal(50.0)); + + QVERIFY(c1 == c2); + QVERIFY(!(c1 != c2)); + + QVERIFY(!(c1 == c3)); + QVERIFY(c1 != c3); + + QVERIFY(!(c1 == c4)); + QVERIFY(c1 != c4); + + QVERIFY(!(c2 == c3)); + QVERIFY(c2 != c3); + + QGeoRectangle b1(QGeoCoordinate(20,20),QGeoCoordinate(10,30)); + QVERIFY(!(c1 == b1)); + QVERIFY(c1 != b1); + + QGeoShape *c2Ptr = &c2; + QVERIFY(c1 == *c2Ptr); + QVERIFY(!(c1 != *c2Ptr)); + + QGeoShape *c3Ptr = &c3; + QVERIFY(!(c1 == *c3Ptr)); + QVERIFY(c1 != *c3Ptr); +} + +void tst_QGeoPath::type() +{ + QGeoPath c; + QCOMPARE(c.type(), QGeoShape::PathType); +} + +void tst_QGeoPath::path() +{ + QList<QGeoCoordinate> coords; + coords.append(QGeoCoordinate(1,1)); + coords.append(QGeoCoordinate(2,2)); + coords.append(QGeoCoordinate(3,0)); + + QGeoPath p; + p.setPath(coords); + QCOMPARE(p.path().size(), 3); + + for (const QGeoCoordinate &c : coords) { + QCOMPARE(p.path().contains(c), true); + } +} + +void tst_QGeoPath::width() +{ + QGeoPath p; + p.setWidth(10.0); + QCOMPARE(p.width(), qreal(10.0)); +} + +void tst_QGeoPath::translate_data() +{ + QTest::addColumn<QGeoCoordinate>("c1"); + QTest::addColumn<QGeoCoordinate>("c2"); + QTest::addColumn<QGeoCoordinate>("c3"); + QTest::addColumn<double>("lat"); + QTest::addColumn<double>("lon"); + + QTest::newRow("Simple") << QGeoCoordinate(1,1) << QGeoCoordinate(2,2) << + QGeoCoordinate(3,0) << 5.0 << 4.0; + QTest::newRow("Backward") << QGeoCoordinate(1,1) << QGeoCoordinate(2,2) << + QGeoCoordinate(3,0) << -5.0 << -4.0; +} + +void tst_QGeoPath::translate() +{ + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(QGeoCoordinate, c3); + QFETCH(double, lat); + QFETCH(double, lon); + + QList<QGeoCoordinate> coords; + coords.append(c1); + coords.append(c2); + coords.append(c3); + QGeoPath p(coords); + + p.translate(lat, lon); + + for (int i = 0; i < p.path().size(); i++) { + QCOMPARE(coords[i].latitude(), p.path()[i].latitude() - lat ); + QCOMPARE(coords[i].longitude(), p.path()[i].longitude() - lon ); + } +} + +void tst_QGeoPath::valid_data() +{ + QTest::addColumn<QGeoCoordinate>("c1"); + QTest::addColumn<QGeoCoordinate>("c2"); + QTest::addColumn<QGeoCoordinate>("c3"); + QTest::addColumn<qreal>("width"); + QTest::addColumn<bool>("valid"); + + QTest::newRow("empty coords") << QGeoCoordinate() << QGeoCoordinate() << QGeoCoordinate() << qreal(5.0) << false; + QTest::newRow("invalid coord") << QGeoCoordinate(50, 50) << QGeoCoordinate(60, 60) << QGeoCoordinate(700, 700) << qreal(5.0) << false; + QTest::newRow("bad width") << QGeoCoordinate(10, 10) << QGeoCoordinate(11, 11) << QGeoCoordinate(10, 12) << qreal(-5.0) << true; + QTest::newRow("NaN width") << QGeoCoordinate(10, 10) << QGeoCoordinate(11, 11) << QGeoCoordinate(10, 12) << qreal(qQNaN()) << true; + QTest::newRow("zero width") << QGeoCoordinate(10, 10) << QGeoCoordinate(11, 11) << QGeoCoordinate(10, 12) << qreal(0) << true; + QTest::newRow("good") << QGeoCoordinate(10, 10) << QGeoCoordinate(11, 11) << QGeoCoordinate(10, 12) << qreal(5) << true; +} + +void tst_QGeoPath::valid() +{ + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(QGeoCoordinate, c3); + QFETCH(qreal, width); + QFETCH(bool, valid); + + QList<QGeoCoordinate> coords; + coords.append(c1); + coords.append(c2); + coords.append(c3); + QGeoPath p(coords, width); + + QCOMPARE(p.isValid(), valid); + + QGeoShape area = p; + QCOMPARE(area.isValid(), valid); +} + +void tst_QGeoPath::contains_data() +{ + QTest::addColumn<QGeoCoordinate>("c1"); + QTest::addColumn<QGeoCoordinate>("c2"); + QTest::addColumn<QGeoCoordinate>("c3"); + QTest::addColumn<qreal>("width"); + QTest::addColumn<QGeoCoordinate>("probe"); + QTest::addColumn<bool>("result"); + + QList<QGeoCoordinate> c; + c.append(QGeoCoordinate(1,1)); + c.append(QGeoCoordinate(2,2)); + c.append(QGeoCoordinate(3,0)); + + QTest::newRow("One of the points") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(2, 2) << true; + QTest::newRow("Not so far away") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(0, 0) << false; + QTest::newRow("Not so far away and large line") << c[0] << c[1] << c[2] << 100000.0 << QGeoCoordinate(0, 0) << true; +} + +void tst_QGeoPath::contains() +{ + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(QGeoCoordinate, c3); + QFETCH(qreal, width); + QFETCH(QGeoCoordinate, probe); + QFETCH(bool, result); + + QList<QGeoCoordinate> coords; + coords.append(c1); + coords.append(c2); + coords.append(c3); + QGeoPath p(coords, width); + + QCOMPARE(p.contains(probe), result); + + QGeoShape area = p; + QCOMPARE(area.contains(probe), result); +} + +void tst_QGeoPath::boundingGeoRectangle_data() +{ + QTest::addColumn<QGeoCoordinate>("c1"); + QTest::addColumn<QGeoCoordinate>("c2"); + QTest::addColumn<QGeoCoordinate>("c3"); + QTest::addColumn<qreal>("width"); + QTest::addColumn<QGeoCoordinate>("probe"); + QTest::addColumn<bool>("result"); + + QList<QGeoCoordinate> c; + c.append(QGeoCoordinate(1,1)); + c.append(QGeoCoordinate(2,2)); + c.append(QGeoCoordinate(3,0)); + + QTest::newRow("One of the points") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(2, 2) << true; + QTest::newRow("Not so far away") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(0, 0) << false; + QTest::newRow("Inside the bounds") << c[0] << c[1] << c[2] << 100.0 << QGeoCoordinate(1, 0) << true; + QTest::newRow("Inside the bounds") << c[0] << c[1] << c[2] << 100.0 << QGeoCoordinate(1.1, 0.1) << true; +} + +void tst_QGeoPath::boundingGeoRectangle() +{ + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(QGeoCoordinate, c3); + QFETCH(qreal, width); + QFETCH(QGeoCoordinate, probe); + QFETCH(bool, result); + + QList<QGeoCoordinate> coords; + coords.append(c1); + coords.append(c2); + coords.append(c3); + QGeoPath p(coords, width); + + QGeoRectangle box = p.boundingGeoRectangle(); + QCOMPARE(box.contains(probe), result); +} + +void tst_QGeoPath::extendShape() +{ + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(QGeoCoordinate, c3); + QFETCH(qreal, width); + QFETCH(QGeoCoordinate, probe); + QFETCH(bool, before); + QFETCH(bool, after); + + QList<QGeoCoordinate> coords; + coords.append(c1); + coords.append(c2); + coords.append(c3); + QGeoPath p(coords, width); + + + QCOMPARE(p.contains(probe), before); + p.extendShape(probe); + QCOMPARE(p.contains(probe), after); +} + +void tst_QGeoPath::extendShape_data() +{ + QTest::addColumn<QGeoCoordinate>("c1"); + QTest::addColumn<QGeoCoordinate>("c2"); + QTest::addColumn<QGeoCoordinate>("c3"); + QTest::addColumn<qreal>("width"); + QTest::addColumn<QGeoCoordinate>("probe"); + QTest::addColumn<bool>("before"); + QTest::addColumn<bool>("after"); + + QList<QGeoCoordinate> c; + c.append(QGeoCoordinate(1,1)); + c.append(QGeoCoordinate(2,2)); + c.append(QGeoCoordinate(3,0)); + + QTest::newRow("One of the points") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(2, 2) << true << true; + QTest::newRow("Not so far away") << c[0] << c[1] << c[2] << 0.0 << QGeoCoordinate(0, 0) << false << true; + QTest::newRow("Not so far away and large line") << c[0] << c[1] << c[2] << 100000.0 << QGeoCoordinate(0, 0) << true << true; +} + +QTEST_MAIN(tst_QGeoPath) +#include "tst_qgeopath.moc" diff --git a/tests/auto/qgeorectangle/tst_qgeorectangle.cpp b/tests/auto/qgeorectangle/tst_qgeorectangle.cpp index 71a3765a..06b65e86 100644 --- a/tests/auto/qgeorectangle/tst_qgeorectangle.cpp +++ b/tests/auto/qgeorectangle/tst_qgeorectangle.cpp @@ -71,6 +71,9 @@ private slots: void center(); void center_data(); + void boundingGeoRectangle(); + void boundingGeoRectangle_data(); + void containsCoord(); void containsCoord_data(); @@ -957,6 +960,28 @@ void tst_QGeoRectangle::center_data() QGeoCoordinate(-90.0, -170.0)); } +void tst_QGeoRectangle::boundingGeoRectangle_data() +{ + QTest::addColumn<QGeoRectangle>("rectangle"); + + QGeoRectangle b1(QGeoCoordinate(70, 30), QGeoCoordinate(30, 70)); + QGeoRectangle b2(QGeoCoordinate(70, 150), QGeoCoordinate(30, -170)); + QGeoRectangle b3(QGeoCoordinate(90, 30), QGeoCoordinate(50, 70)); + QGeoRectangle b4(QGeoCoordinate(-50, 30), QGeoCoordinate(-90, 70)); + + QTest::newRow("Box 1") << b1; + QTest::newRow("Box 2") << b2; + QTest::newRow("Box 3") << b3; + QTest::newRow("Box 4") << b4; +} + +void tst_QGeoRectangle::boundingGeoRectangle() +{ + QFETCH(QGeoRectangle, rectangle); + + QGeoRectangle box = rectangle.boundingGeoRectangle(); + QCOMPARE(box, rectangle); +} void tst_QGeoRectangle::containsCoord() { @@ -1769,14 +1794,14 @@ void tst_QGeoRectangle::translate_data() << 20.0 << 20.0 << QGeoRectangle(QGeoCoordinate(90.0, -10.0), - QGeoCoordinate(40.0, 50.0)); + QGeoCoordinate(30.0, 50.0)); QTest::newRow("non wrapping -> south clip") << QGeoRectangle(QGeoCoordinate(-20.0, -30.0), QGeoCoordinate(-80.0, 30.0)) << -20.0 << 20.0 - << QGeoRectangle(QGeoCoordinate(-40.0, -10.0), + << QGeoRectangle(QGeoCoordinate(-30.0, -10.0), QGeoCoordinate(-90.0, 50.0)); QTest::newRow("wrapping -> non wrapping") @@ -1801,14 +1826,14 @@ void tst_QGeoRectangle::translate_data() << 20.0 << 20.0 << QGeoRectangle(QGeoCoordinate(90.0, 150.0), - QGeoCoordinate(40.0, -150.0)); + QGeoCoordinate(30.0, -150.0)); QTest::newRow("wrapping -> south clip") << QGeoRectangle(QGeoCoordinate(-20.0, 130.0), QGeoCoordinate(-80.0, -170.0)) << -20.0 << 20.0 - << QGeoRectangle(QGeoCoordinate(-40.0, 150.0), + << QGeoRectangle(QGeoCoordinate(-30.0, 150.0), QGeoCoordinate(-90.0, -150.0)); } diff --git a/tests/auto/qgeoroutereply/tst_qgeoroutereply.cpp b/tests/auto/qgeoroutereply/tst_qgeoroutereply.cpp index 447181f2..de406b40 100644 --- a/tests/auto/qgeoroutereply/tst_qgeoroutereply.cpp +++ b/tests/auto/qgeoroutereply/tst_qgeoroutereply.cpp @@ -197,7 +197,7 @@ void tst_QGeoRouteReply::abort() reply->abort(); QCOMPARE(signalerror->count(), 0); - QCOMPARE(signalfinished->count(), 1); + QCOMPARE(signalfinished->count(), 0); } void tst_QGeoRouteReply::error() |