diff options
75 files changed, 1951 insertions, 261 deletions
diff --git a/.qmake.conf b/.qmake.conf index 33ba37ba..4afd972d 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,4 +1,4 @@ load(qt_build_config) CONFIG += warning_clean -MODULE_VERSION = 5.9.3 +MODULE_VERSION = 5.10.0 diff --git a/dist/changes-5.10.0 b/dist/changes-5.10.0 new file mode 100644 index 00000000..1703cf6f --- /dev/null +++ b/dist/changes-5.10.0 @@ -0,0 +1,62 @@ +Qt 5.10 introduces many new features and improvements as well as bugfixes +over the 5.9.x series. For more details, refer to the online documentation +included in this distribution. The documentation is also available online: + +http://doc.qt.io/qt-5/index.html + +The Qt version 5.10 series is binary compatible with the 5.9.x series. +Applications compiled for 5.9 will continue to run with 5.10. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + +https://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Qt 5.10.0 Changes * +**************************************************************************** + + - This release contains only minor code improvements. + +QtLocation +---------- + + - Map: + * [QTBUG-55782] Added methods to add or remove MapItemViews at runtime. + * Visible region now returns a QGeoPolygon. + + - MapGestureArea: + * Added rotation and tilt scroll wheel actions. + + - MapPolyline: + * Added setPath overload taking a QGeoPath. + + - MapboxGL: + * Updated Mapbox GL Native to v1.1.0. + * [QTBUG-62002] Updated map styles. + * [QTBUG-61442] Fix MapParameter dynamic usage. + + - QDeclarativeGeoMap: + * Added setBearing overload to rotate the map around a given + QGeoCoordinate. + * Added alignCoordinateToPoint method to QDeclarativeGeoMap. + + - QDeclarativeGeoMapType: + * [QTBUG-58931] Added CameraCapabilities and metadata properties to + QDeclarativeGeoMapType. + + - QGeoRouteRequest/RouteQuery: + * Add TrafficFeature to the query features. + +QtPositioning +------------- + + - QGeoPath: + * Add ::size() to QGeoPath to retrieve the number of coordinates in the + path. + + - QGeoPolygon: + * Added QGeoPolygon shape. diff --git a/examples/positioning/weatherinfo/appmodel.cpp b/examples/positioning/weatherinfo/appmodel.cpp index dd285f33..d07a5980 100644 --- a/examples/positioning/weatherinfo/appmodel.cpp +++ b/examples/positioning/weatherinfo/appmodel.cpp @@ -57,7 +57,6 @@ #include <qnetworkconfigmanager.h> #include <qnetworksession.h> -#include <QSignalMapper> #include <QJsonDocument> #include <QJsonObject> #include <QJsonArray> @@ -155,8 +154,6 @@ public: WeatherData now; QList<WeatherData*> forecast; QQmlListProperty<WeatherData> *fcProp; - QSignalMapper *geoReplyMapper; - QSignalMapper *weatherReplyMapper, *forecastReplyMapper; bool ready; bool useGps; QElapsedTimer throttle; @@ -220,16 +217,6 @@ AppModel::AppModel(QObject *parent) : forecastAt, forecastClear); - d->geoReplyMapper = new QSignalMapper(this); - d->weatherReplyMapper = new QSignalMapper(this); - d->forecastReplyMapper = new QSignalMapper(this); - - connect(d->geoReplyMapper, SIGNAL(mapped(QObject*)), - this, SLOT(handleGeoNetworkData(QObject*))); - connect(d->weatherReplyMapper, SIGNAL(mapped(QObject*)), - this, SLOT(handleWeatherNetworkData(QObject*))); - connect(d->forecastReplyMapper, SIGNAL(mapped(QObject*)), - this, SLOT(handleForecastNetworkData(QObject*))); connect(&d->delayedCityRequestTimer, SIGNAL(timeout()), this, SLOT(queryCity())); connect(&d->requestNewWeatherTimer, SIGNAL(timeout()), @@ -322,9 +309,8 @@ void AppModel::queryCity() QNetworkReply *rep = d->nam->get(QNetworkRequest(url)); // connect up the signal right away - d->geoReplyMapper->setMapping(rep, rep); - connect(rep, SIGNAL(finished()), - d->geoReplyMapper, SLOT(map())); + connect(rep, &QNetworkReply::finished, + this, [this, rep]() { handleGeoNetworkData(rep); }); } void AppModel::positionError(QGeoPositionInfoSource::Error e) @@ -354,9 +340,8 @@ void AppModel::hadError(bool tryAgain) d->delayedCityRequestTimer.start(); } -void AppModel::handleGeoNetworkData(QObject *replyObj) +void AppModel::handleGeoNetworkData(QNetworkReply *networkReply) { - QNetworkReply *networkReply = qobject_cast<QNetworkReply*>(replyObj); if (!networkReply) { hadError(false); // should retry? return; @@ -403,9 +388,8 @@ void AppModel::refreshWeather() QNetworkReply *rep = d->nam->get(QNetworkRequest(url)); // connect up the signal right away - d->weatherReplyMapper->setMapping(rep, rep); - connect(rep, SIGNAL(finished()), - d->weatherReplyMapper, SLOT(map())); + connect(rep, &QNetworkReply::finished, + this, [this, rep]() { handleWeatherNetworkData(rep); }); } static QString niceTemperatureString(double t) @@ -413,10 +397,9 @@ static QString niceTemperatureString(double t) return QString::number(qRound(t-ZERO_KELVIN)) + QChar(0xB0); } -void AppModel::handleWeatherNetworkData(QObject *replyObj) +void AppModel::handleWeatherNetworkData(QNetworkReply *networkReply) { qCDebug(requestsLog) << "got weather network data"; - QNetworkReply *networkReply = qobject_cast<QNetworkReply*>(replyObj); if (!networkReply) return; @@ -462,14 +445,13 @@ void AppModel::handleWeatherNetworkData(QObject *replyObj) QNetworkReply *rep = d->nam->get(QNetworkRequest(url)); // connect up the signal right away - d->forecastReplyMapper->setMapping(rep, rep); - connect(rep, SIGNAL(finished()), d->forecastReplyMapper, SLOT(map())); + connect(rep, &QNetworkReply::finished, + this, [this, rep]() { handleForecastNetworkData(rep); }); } -void AppModel::handleForecastNetworkData(QObject *replyObj) +void AppModel::handleForecastNetworkData(QNetworkReply *networkReply) { qCDebug(requestsLog) << "got forecast"; - QNetworkReply *networkReply = qobject_cast<QNetworkReply*>(replyObj); if (!networkReply) return; diff --git a/examples/positioning/weatherinfo/appmodel.h b/examples/positioning/weatherinfo/appmodel.h index 645202d6..a4d4e87a 100644 --- a/examples/positioning/weatherinfo/appmodel.h +++ b/examples/positioning/weatherinfo/appmodel.h @@ -159,10 +159,9 @@ private slots: void networkSessionOpened(); void positionUpdated(QGeoPositionInfo gpsPos); void positionError(QGeoPositionInfoSource::Error e); - // these would have QNetworkReply* params but for the signalmapper - void handleGeoNetworkData(QObject *networkReply); - void handleWeatherNetworkData(QObject *networkReply); - void handleForecastNetworkData(QObject *networkReply); + void handleGeoNetworkData(QNetworkReply *networkReply); + void handleWeatherNetworkData(QNetworkReply *networkReply); + void handleForecastNetworkData(QNetworkReply *networkReply); //! [3] signals: diff --git a/src/3rdparty/clip2tri/clip2tri.cpp b/src/3rdparty/clip2tri/clip2tri.cpp index e715d1c7..db4911c1 100644 --- a/src/3rdparty/clip2tri/clip2tri.cpp +++ b/src/3rdparty/clip2tri/clip2tri.cpp @@ -173,6 +173,11 @@ Paths clip2tri::execute(const clip2tri::Operation op, const PolyFillType subjFil return solution; } +int clip2tri::pointInPolygon(const IntPoint &pt, const Path &path) +{ + return PointInPolygon(pt, path); +} + Path clip2tri::upscaleClipperPoints(const vector<Point> &inputPolygon) { Path outputPolygon; diff --git a/src/3rdparty/clip2tri/clip2tri.h b/src/3rdparty/clip2tri/clip2tri.h index 61c8a0f5..3848d009 100644 --- a/src/3rdparty/clip2tri/clip2tri.h +++ b/src/3rdparty/clip2tri/clip2tri.h @@ -91,6 +91,8 @@ public: const PolyFillType subjFillType = pftNonZero, const PolyFillType clipFillType = pftNonZero); + static int pointInPolygon(const IntPoint &pt, const Path &path); + Clipper clipper; bool openSubject; }; diff --git a/src/3rdparty/mapbox-gl-native b/src/3rdparty/mapbox-gl-native -Subproject a2120304a881507ed60c3199925946c1df06b44 +Subproject 572822c8ca15be190b43afbf7f91d132e988bf2 diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp index 0a20e5ad..9c89d3b8 100644 --- a/src/imports/location/location.cpp +++ b/src/imports/location/location.cpp @@ -100,7 +100,7 @@ public: int minor = 0; // Register the 5.0 types - // 5.0 is siltent and not advertised + // 5.0 is silent and not advertised qmlRegisterType<QDeclarativeGeoServiceProvider >(uri, major, minor, "Plugin"); qmlRegisterType<QDeclarativeGeoServiceProviderParameter >(uri, major, minor, "PluginParameter"); @@ -175,6 +175,11 @@ public: qmlRegisterType<QDeclarativeGeoMapCopyrightNotice>(uri, major, minor, "MapCopyrightNotice"); qmlRegisterType<QDeclarativeGeoMapItemGroup>(uri, major, minor, "MapItemGroup"); + // Register the 5.10 types + minor = 10; + qmlRegisterUncreatableType<QDeclarativeGeoCameraCapabilities>(uri, major, minor, "CameraCapabilities" + , QStringLiteral("CameraCapabilities is not intended instantiable by developer.")); + //registrations below are version independent qRegisterMetaType<QPlaceCategory>(); qRegisterMetaType<QPlace>(); diff --git a/src/imports/positioning/locationsingleton.cpp b/src/imports/positioning/locationsingleton.cpp index 19b05761..e9b58834 100644 --- a/src/imports/positioning/locationsingleton.cpp +++ b/src/imports/positioning/locationsingleton.cpp @@ -234,6 +234,37 @@ QGeoPath LocationSingleton::path(const QJSValue &value, qreal width) const } /*! + \qmlmethod geopolygon QtPositioning::polygon() const + + Constructs an empty geopolygon. + + \sa {geopolygon} + \since 5.10 +*/ +QGeoPath LocationSingleton::polygon() const +{ + return QGeoPolygon(); +} + +/*! + \qmlmethod geopolygon QtPositioning::polygon(list<coordinate> coordinates) const + + Constructs a geopolygon from coordinates. + + \sa {geopolygon} + \since 5.10 +*/ +QGeoPath LocationSingleton::polygon(const QVariantList &coordinates) const +{ + QList<QGeoCoordinate> internalCoordinates; + for (int i = 0; i < coordinates.size(); i++) { + if (coordinates.at(i).canConvert<QGeoCoordinate>()) + internalCoordinates << coordinates.at(i).value<QGeoCoordinate>(); + } + return QGeoPolygon(internalCoordinates); +} + +/*! \qmlmethod geocircle QtPositioning::shapeToCircle(geoshape shape) const Converts \a shape to a geocircle. @@ -272,3 +303,15 @@ QGeoPath LocationSingleton::shapeToPath(const QGeoShape &shape) const return QGeoPath(shape); } +/*! + \qmlmethod geopath QtPositioning::shapeToPolygon(geoshape shape) const + + Converts \a shape to a geopolygon. + + \sa {geopolygon} + \since 5.10 +*/ +QGeoPolygon LocationSingleton::shapeToPolygon(const QGeoShape &shape) const +{ + return QGeoPolygon(shape); +} diff --git a/src/imports/positioning/locationsingleton.h b/src/imports/positioning/locationsingleton.h index 4faf2738..6a560fa8 100644 --- a/src/imports/positioning/locationsingleton.h +++ b/src/imports/positioning/locationsingleton.h @@ -47,6 +47,7 @@ #include <QtPositioning/QGeoRectangle> #include <QtPositioning/QGeoCircle> #include <QtPositioning/QGeoPath> +#include <QtPositioning/QGeoPolygon> #include <QtQml/QJSValue> #include <QVariant> @@ -76,9 +77,13 @@ public: Q_INVOKABLE QGeoPath path() const; Q_INVOKABLE QGeoPath path(const QJSValue &value, qreal width = 0.0) const; + Q_INVOKABLE QGeoPath polygon() const; + Q_INVOKABLE QGeoPath polygon(const QVariantList &value) const; + Q_INVOKABLE QGeoCircle shapeToCircle(const QGeoShape &shape) const; Q_INVOKABLE QGeoRectangle shapeToRectangle(const QGeoShape &shape) const; Q_INVOKABLE QGeoPath shapeToPath(const QGeoShape &shape) const; + Q_INVOKABLE QGeoPolygon shapeToPolygon(const QGeoShape &shape) const; }; #endif // LOCATIONSINGLETON_H diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp index 2ed482e3..34885f54 100644 --- a/src/location/declarativemaps/qdeclarativegeomap.cpp +++ b/src/location/declarativemaps/qdeclarativegeomap.cpp @@ -46,6 +46,7 @@ #include <QtPositioning/QGeoCircle> #include <QtPositioning/QGeoRectangle> #include <QtPositioning/QGeoPath> +#include <QtPositioning/QGeoPolygon> #include <QtQuick/QQuickWindow> #include <QtQuick/QSGRectangleNode> #include <QtQuick/private/qquickwindow_p.h> @@ -190,7 +191,11 @@ QDeclarativeGeoMap::QDeclarativeGeoMap(QQuickItem *parent) m_activeMapType = new QDeclarativeGeoMapType(QGeoMapType(QGeoMapType::NoMap, tr("No Map"), - tr("No Map"), false, false, 0, QByteArrayLiteral("")), this); + tr("No Map"), + false, false, + 0, + QByteArrayLiteral(""), + QGeoCameraCapabilities()), this); m_cameraData.setCenter(QGeoCoordinate(51.5073,-0.1277)); //London city center m_cameraData.setZoomLevel(8.0); @@ -218,8 +223,18 @@ QDeclarativeGeoMap::~QDeclarativeGeoMap() m_map->clearMapItems(); } - if (!m_mapViews.isEmpty()) - qDeleteAll(m_mapViews); + // This forces the destruction of the associated items now, not when QObject destructor is called, at which point + // QDeclarativeGeoMap is long gone + if (!m_mapViews.isEmpty()) { + for (QDeclarativeGeoMapItemView *v : qAsConst(m_mapViews)) { + if (!v) + continue; + if (v->parent() == this) + delete v; + else + v->removeInstantiatedItems(); + } + } // remove any map items associations for (int i = 0; i < m_mapItems.count(); ++i) { if (m_mapItems.at(i)) @@ -752,7 +767,12 @@ void QDeclarativeGeoMap::mappingManagerInitialized() } else { m_activeMapType = new QDeclarativeGeoMapType(QGeoMapType(QGeoMapType::NoMap, tr("No Map"), - tr("No Map"), false, false, 0, QByteArrayLiteral("")), this); + tr("No Map"), + false, + false, + 0, + QByteArrayLiteral(""), + QGeoCameraCapabilities()), this); } } @@ -1322,22 +1342,22 @@ QGeoShape QDeclarativeGeoMap::visibleRegion() const return m_visibleRegion; const QList<QDoubleVector2D> &visibleRegion = m_map->geoProjection().visibleRegion(); - QGeoPath path; + QGeoPolygon poly; for (int i = 0; i < visibleRegion.size(); ++i) { const QDoubleVector2D &c = visibleRegion.at(i); // If a segment spans more than half of the map longitudinally, split in 2. if (i && qAbs(visibleRegion.at(i-1).x() - c.x()) >= 0.5) { // This assumes a segment is never >= 1.0 (whole map span) QDoubleVector2D extraPoint = (visibleRegion.at(i-1) + c) * 0.5; - path.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(extraPoint)); + poly.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(extraPoint)); } - path.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(c)); + poly.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(c)); } if (visibleRegion.size() >= 2 && qAbs(visibleRegion.last().x() - visibleRegion.first().x()) >= 0.5) { QDoubleVector2D extraPoint = (visibleRegion.last() + visibleRegion.first()) * 0.5; - path.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(extraPoint)); + poly.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(extraPoint)); } - return path.boundingGeoRectangle(); + return poly; } /*! @@ -1454,6 +1474,61 @@ QQmlListProperty<QDeclarativeGeoMapType> QDeclarativeGeoMap::supportedMapTypes() } /*! + \qmlmethod void QtLocation::Map::setBearing(real bearing, coordinate coordinate) + + Sets the bearing for the map to \a bearing, rotating it around \a coordinate. + If the Plugin used for the Map supports bearing, the valid range for \a bearing is between 0 and 360. + If the Plugin used for the Map does not support bearing, or if the map is tilted and \a coordinate happens + to be behind the camera, or if the map is not ready (see \l mapReady), calling this method will have no effect. + + The release of this API with Qt 5.10 is a Technology Preview. + + \since 5.10 +*/ +void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate) +{ + if (!m_map) + return; + + const QDoubleVector2D coordWrapped = m_map->geoProjection().geoToWrappedMapProjection(coordinate); + if (!m_map->geoProjection().isProjectable(coordWrapped)) + return; + + const QPointF rotationPoint = m_map->geoProjection().wrappedMapProjectionToItemPosition(coordWrapped).toPointF(); + + // First set bearing + setBearing(bearing); + // then reanchor + setCenter(m_map->geoProjection().anchorCoordinateToPoint(coordinate, rotationPoint)); +} + +/*! + \qmlmethod void QtLocation::Map::alignCoordinateToPoint(coordinate coordinate, QPointF point) + + Aligns \a coordinate to \a point. + This method effectively extends the functionality offered by the \l center qml property, allowing + to align a coordinate to point of the Map element other than its center. + This is useful in those applications where the center of the scene (e.g., a cursor) is not to be + placed exactly in the center of the map. + + If the map is tilted, and \a coordinate happens to be behind the camera, or if the map is not ready + (see \l mapReady), calling this method will have no effect. + + The release of this API with Qt 5.10 is a Technology Preview. + + \sa center + + \since 5.10 +*/ +void QDeclarativeGeoMap::alignCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &point) +{ + if (!m_map) + return; + + setCenter(m_map->geoProjection().anchorCoordinateToPoint(coordinate, point)); +} + +/*! \qmlmethod coordinate QtLocation::Map::toCoordinate(QPointF position, bool clipToViewPort) Returns the coordinate which corresponds to the \a position relative to the map item. @@ -1896,6 +1971,47 @@ void QDeclarativeGeoMap::removeMapItemGroup(QDeclarativeGeoMapItemGroup *itemGro } /*! + \qmlmethod void QtLocation::Map::removeMapItemView(MapItemView itemView) + + Removes \a itemView and the items instantiated by it from the Map. + + \sa MapItemView, addMapItemView + + \since 5.10 +*/ +void QDeclarativeGeoMap::removeMapItemView(QDeclarativeGeoMapItemView *itemView) +{ + if (!itemView || itemView->map_ != this) // can't remove a view that is already added to another map + return; + + itemView->removeInstantiatedItems(); + itemView->map_ = 0; + // it can be removed from the list at this point, since no operations that require a Map have to be done + // anymore on destruction. + m_mapViews.removeOne(itemView); +} + +/*! + \qmlmethod void QtLocation::Map::addMapItemView(MapItemView itemView) + + Adds \a itemView to the Map. + + \sa MapItemView, removeMapItemView + + \since 5.10 +*/ +void QDeclarativeGeoMap::addMapItemView(QDeclarativeGeoMapItemView *itemView) +{ + if (!itemView || itemView->map_) // can't add a view twice + return; + + // Not appending it to m_mapViews because it seems unnecessary even if the + // itemView is a child of this (in which case it would be destroyed + m_mapViews.append(itemView); + setupMapView(itemView); +} + +/*! \qmlproperty MapType QtLocation::Map::activeMapType \brief Access to the currently active \l{MapType}{map type}. @@ -2155,7 +2271,7 @@ bool QDeclarativeGeoMap::sendTouchEvent(QTouchEvent *event) auto touchPointGrabberItem = [touchDevice, windowPriv](const QTouchEvent::TouchPoint &point) -> QQuickItem* { if (QQuickEventPoint *eventPointer = windowPriv->pointerEventInstance(touchDevice)->pointById(point.id())) - return eventPointer->grabber(); + return eventPointer->grabberItem(); return nullptr; }; diff --git a/src/location/declarativemaps/qdeclarativegeomap_p.h b/src/location/declarativemaps/qdeclarativegeomap_p.h index e8ff3265..5c568d8f 100644 --- a/src/location/declarativemaps/qdeclarativegeomap_p.h +++ b/src/location/declarativemaps/qdeclarativegeomap_p.h @@ -155,12 +155,18 @@ public: QQmlListProperty<QDeclarativeGeoMapType> supportedMapTypes(); + Q_INVOKABLE void setBearing(qreal bearing, const QGeoCoordinate &coordinate); + Q_INVOKABLE void alignCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &point); + Q_INVOKABLE void removeMapItem(QDeclarativeGeoMapItemBase *item); Q_INVOKABLE void addMapItem(QDeclarativeGeoMapItemBase *item); Q_INVOKABLE void addMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup); Q_INVOKABLE void removeMapItemGroup(QDeclarativeGeoMapItemGroup *itemGroup); + Q_INVOKABLE void removeMapItemView(QDeclarativeGeoMapItemView *itemView); + Q_INVOKABLE void addMapItemView(QDeclarativeGeoMapItemView *itemView); + Q_INVOKABLE void clearMapItems(); QList<QObject *> mapItems(); diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp index 8207caa5..24ed6700 100644 --- a/src/location/declarativemaps/qdeclarativegeomapitemview.cpp +++ b/src/location/declarativemaps/qdeclarativegeomapitemview.cpp @@ -431,6 +431,9 @@ void QDeclarativeGeoMapItemView::instantiateAllItems() fitViewport(); } +/* + * used internally +*/ void QDeclarativeGeoMapItemView::removeItemData(QDeclarativeGeoMapItemViewItemData *itemData) { if (!itemData) diff --git a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h index 8c83e37d..8f1a081f 100644 --- a/src/location/declarativemaps/qdeclarativegeomapitemview_p.h +++ b/src/location/declarativemaps/qdeclarativegeomapitemview_p.h @@ -141,6 +141,7 @@ private: int m_readyIncubators; bool m_repopulating; + friend class QDeclarativeGeoMap; friend class QDeclarativeGeoMapItemViewItemData; friend class MapItemViewDelegateIncubator; }; diff --git a/src/location/declarativemaps/qdeclarativegeomaptype.cpp b/src/location/declarativemaps/qdeclarativegeomaptype.cpp index 86444aa4..7e40d414 100644 --- a/src/location/declarativemaps/qdeclarativegeomaptype.cpp +++ b/src/location/declarativemaps/qdeclarativegeomaptype.cpp @@ -57,7 +57,8 @@ QT_BEGIN_NAMESPACE QDeclarativeGeoMapType::QDeclarativeGeoMapType(const QGeoMapType mapType, QObject *parent) : QObject(parent), - mapType_(mapType) {} + mapType_(mapType), + cameraCapabilities_(new QDeclarativeGeoCameraCapabilities(mapType.cameraCapabilities(), this)) {} QDeclarativeGeoMapType::~QDeclarativeGeoMapType() {} @@ -131,4 +132,116 @@ bool QDeclarativeGeoMapType::night() const return mapType_.night(); } +/*! + \qmlproperty CameraCapabilities MapType::cameraCapabilities + \since Qt Location 5.10 + + This property holds the camera capabilities for this map type. +*/ +QDeclarativeGeoCameraCapabilities *QDeclarativeGeoMapType::cameraCapabilities() const +{ + return cameraCapabilities_; +} + +/*! + \qmlproperty VariantMap MapType::metadata + \since Qt Location 5.10 + + This property holds optional, extra metadata related to a specific map type. + The content of this property is entirely plugin-specific. +*/ +QVariantMap QDeclarativeGeoMapType::metadata() const +{ + return mapType_.metadata(); +} + +/* + * QDeclarativeGeoCameraCapabilities implementation + */ + +/*! + \qmltype CameraCapabilities + \instantiates QDeclarativeGeoCameraCapabilities + \inherits QObject + \inqmlmodule QtLocation + \ingroup qml-QtLocation5-maps + \since Qt Location 5.10 + + \brief The CameraCapabilities type holds information about the camera capabilities for a specific map type. + + This includes the map minimum and maximum zoom level, minimum and maximum tilt angle and + minimum and maximum field of view. +*/ + +QDeclarativeGeoCameraCapabilities::QDeclarativeGeoCameraCapabilities(const QGeoCameraCapabilities &cameraCaps, QObject *parent) + : QObject(parent), cameraCaps_(cameraCaps) +{ + +} + +QDeclarativeGeoCameraCapabilities::~QDeclarativeGeoCameraCapabilities() +{ + +} + +/*! + \qmlproperty qreal CameraCapabilities::minimumZoomLevel + + This read-only property holds the minimum available zoom level with this map type. +*/ +qreal QDeclarativeGeoCameraCapabilities::minimumZoomLevel() const +{ + return cameraCaps_.minimumZoomLevelAt256(); +} + +/*! + \qmlproperty qreal CameraCapabilities::maximumZoomLevel + + This read-only property holds the maximum available zoom level with this map type. +*/ +qreal QDeclarativeGeoCameraCapabilities::maximumZoomLevel() const +{ + return cameraCaps_.maximumZoomLevelAt256(); +} + +/*! + \qmlproperty qreal CameraCapabilities::minimumTilt + + This read-only property holds the minimum available tilt with this map type. +*/ +qreal QDeclarativeGeoCameraCapabilities::minimumTilt() const +{ + return cameraCaps_.minimumTilt(); +} + +/*! + \qmlproperty qreal CameraCapabilities::maximumTilt + + This read-only property holds the maximum available tilt with this map type. +*/ +qreal QDeclarativeGeoCameraCapabilities::maximumTilt() const +{ + return cameraCaps_.maximumTilt(); +} + +/*! + \qmlproperty qreal CameraCapabilities::minimumFieldOfView + + This read-only property holds the minimum available field of view with this map type. +*/ +qreal QDeclarativeGeoCameraCapabilities::minimumFieldOfView() const +{ + return cameraCaps_.minimumFieldOfView(); +} + +/*! + \qmlproperty qreal CameraCapabilities::maximumFieldOfView + + This read-only property holds the maximum available field of view with this map type. +*/ +qreal QDeclarativeGeoCameraCapabilities::maximumFieldOfView() const +{ + return cameraCaps_.maximumFieldOfView(); +} + QT_END_NAMESPACE diff --git a/src/location/declarativemaps/qdeclarativegeomaptype_p.h b/src/location/declarativemaps/qdeclarativegeomaptype_p.h index 7b449aa0..5d99083d 100644 --- a/src/location/declarativemaps/qdeclarativegeomaptype_p.h +++ b/src/location/declarativemaps/qdeclarativegeomaptype_p.h @@ -56,6 +56,31 @@ QT_BEGIN_NAMESPACE +class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoCameraCapabilities: public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal minimumZoomLevel READ minimumZoomLevel CONSTANT) + Q_PROPERTY(qreal maximumZoomLevel READ maximumZoomLevel CONSTANT) + Q_PROPERTY(qreal minimumTilt READ minimumTilt CONSTANT) + Q_PROPERTY(qreal maximumTilt READ maximumTilt CONSTANT) + Q_PROPERTY(qreal minimumFieldOfView READ minimumFieldOfView CONSTANT) + Q_PROPERTY(qreal maximumFieldOfView READ maximumFieldOfView CONSTANT) + +public: + QDeclarativeGeoCameraCapabilities(const QGeoCameraCapabilities &cameraCaps, QObject *parent = 0); + ~QDeclarativeGeoCameraCapabilities(); + + qreal minimumZoomLevel() const; + qreal maximumZoomLevel() const; + qreal minimumTilt() const; + qreal maximumTilt() const; + qreal minimumFieldOfView() const; + qreal maximumFieldOfView() const; + +private: + QGeoCameraCapabilities cameraCaps_; +}; + class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMapType : public QObject { Q_OBJECT @@ -66,6 +91,8 @@ class Q_LOCATION_PRIVATE_EXPORT QDeclarativeGeoMapType : public QObject Q_PROPERTY(QString description READ description CONSTANT) Q_PROPERTY(bool mobile READ mobile CONSTANT) Q_PROPERTY(bool night READ night CONSTANT REVISION 1) + Q_PROPERTY(QDeclarativeGeoCameraCapabilities *cameraCapabilities READ cameraCapabilities CONSTANT) + Q_PROPERTY(QVariantMap metadata READ metadata CONSTANT) public: enum MapStyle { @@ -91,11 +118,14 @@ public: QString description() const; bool mobile() const; bool night() const; + QDeclarativeGeoCameraCapabilities *cameraCapabilities() const; + QVariantMap metadata() const; const QGeoMapType mapType() { return mapType_; } private: QGeoMapType mapType_; + QDeclarativeGeoCameraCapabilities *cameraCapabilities_; }; QT_END_NAMESPACE diff --git a/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp b/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp index 94bd63c8..0383c0c4 100644 --- a/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp +++ b/src/location/declarativemaps/qdeclarativegeoroutemodel.cpp @@ -722,6 +722,7 @@ void QDeclarativeGeoRouteQuery::componentComplete() \li RouteQuery.DirtRoadFeature - Consider dirt roads when planning the route \li RouteQuery.ParksFeature - Consider parks when planning the route \li RouteQuery.MotorPoolLaneFeature - Consider motor pool lanes when planning the route + \li RouteQuery.TrafficFeature - Consider traffic when planning the route \endlist \sa setFeatureWeight, featureWeight diff --git a/src/location/declarativemaps/qdeclarativegeoroutemodel_p.h b/src/location/declarativemaps/qdeclarativegeoroutemodel_p.h index 3dfd2ce6..18486ac8 100644 --- a/src/location/declarativemaps/qdeclarativegeoroutemodel_p.h +++ b/src/location/declarativemaps/qdeclarativegeoroutemodel_p.h @@ -238,7 +238,8 @@ public: TunnelFeature = QGeoRouteRequest::TunnelFeature, DirtRoadFeature = QGeoRouteRequest::DirtRoadFeature, ParksFeature = QGeoRouteRequest::ParksFeature, - MotorPoolLaneFeature = QGeoRouteRequest::MotorPoolLaneFeature + MotorPoolLaneFeature = QGeoRouteRequest::MotorPoolLaneFeature, + TrafficFeature = QGeoRouteRequest::TrafficFeature }; Q_DECLARE_FLAGS(FeatureTypes, FeatureType) diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp index 2c6d3ba4..a97271aa 100644 --- a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp +++ b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp @@ -494,6 +494,27 @@ void QDeclarativePolylineMapItem::setPath(const QJSValue &value) } /*! + \qmlmethod int MapPolyline::setPath(geopath path) + + Sets the \l path using a \l QGeoPath type. + + \since 5.10 + + \sa path +*/ +void QDeclarativePolylineMapItem::setPath(const QGeoPath &path) +{ + if (geopath_.path() == path.path()) + return; + + geopath_ = path; + regenerateCache(); + geometry_.setPreserveGeometry(true, geopath_.boundingGeoRectangle().topLeft()); + markSourceDirtyAndUpdate(); + emit pathChanged(); +} + +/*! \internal */ void QDeclarativePolylineMapItem::setPathFromGeoList(const QList<QGeoCoordinate> &path) diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem_p.h b/src/location/declarativemaps/qdeclarativepolylinemapitem_p.h index ec57c980..6b3c42e9 100644 --- a/src/location/declarativemaps/qdeclarativepolylinemapitem_p.h +++ b/src/location/declarativemaps/qdeclarativepolylinemapitem_p.h @@ -141,6 +141,7 @@ public: QJSValue path() const; virtual void setPath(const QJSValue &value); + Q_INVOKABLE void setPath(const QGeoPath &path); bool contains(const QPointF &point) const Q_DECL_OVERRIDE; const QGeoShape &geoShape() const Q_DECL_OVERRIDE; diff --git a/src/location/declarativemaps/qquickgeomapgesturearea.cpp b/src/location/declarativemaps/qquickgeomapgesturearea.cpp index 4f949ad0..d62ae8cf 100644 --- a/src/location/declarativemaps/qquickgeomapgesturearea.cpp +++ b/src/location/declarativemaps/qquickgeomapgesturearea.cpp @@ -84,18 +84,6 @@ static qreal distanceBetweenTouchPoints(const QPointF &p1, const QPointF &p2) return QLineF(p1, p2).length(); } -// Returns the new map center after anchoring coordinate to anchorPoint on the screen -// Approach: find the displacement in (wrapped) mercator space, and apply that to the center -static QGeoCoordinate anchorCoordinateToPoint(QGeoMap &map, const QGeoCoordinate &coordinate, const QPointF &anchorPoint) -{ - QDoubleVector2D centerProj = map.geoProjection().geoToWrappedMapProjection(map.cameraData().center()); - QDoubleVector2D coordProj = map.geoProjection().geoToWrappedMapProjection(coordinate); - - QDoubleVector2D anchorProj = map.geoProjection().itemPositionToWrappedMapProjection(QDoubleVector2D(anchorPoint)); - // Y-clamping done in mercatorToCoord - return map.geoProjection().wrappedMapProjectionToGeo(centerProj + coordProj - anchorProj); -} - static qreal angleFromPoints(const QPointF &p1, const QPointF &p2) { return QLineF(p1, p2).angle(); @@ -255,6 +243,8 @@ QT_BEGIN_NAMESPACE MapGestureArea objects are used as part of a Map, to provide for panning, flicking and pinch-to-zoom gesture used on touch displays, as well as two finger rotation and two finger parallel vertical sliding to tilt the map. + On platforms supporting \l QWheelEvent, using the scroll wheel alone, or in combination with + key modifiers Shift or Control will also zoom, rotate or tilt the map, respectively. A MapGestureArea is automatically created with a new Map and available with the \l{Map::gesture}{gesture} property. This is the only way @@ -951,15 +941,26 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) const QGeoCoordinate &wheelGeoPos = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(event->posF()), false); const QPointF &preZoomPoint = event->posF(); - const double zoomLevelDelta = event->angleDelta().y() * qreal(0.001); - // Gesture area should always honor maxZL, but Map might not. - m_declarativeMap->setZoomLevel(qMin<qreal>(m_declarativeMap->zoomLevel() + zoomLevelDelta, maximumZoomLevel()), - false); - const QPointF &postZoomPoint = m_map->geoProjection().coordinateToItemPosition(wheelGeoPos, false).toPointF(); - - if (preZoomPoint != postZoomPoint) // need to re-anchor the wheel geoPos to the event position - m_declarativeMap->setCenter(anchorCoordinateToPoint(*m_map, wheelGeoPos, preZoomPoint)); - + // Not using AltModifier as, for some reason, it causes angleDelta to be 0 + if (event->modifiers() & Qt::ShiftModifier && rotationEnabled()) { + // First set bearing + const double bearingDelta = event->angleDelta().y() * qreal(0.05); + m_declarativeMap->setBearing(m_declarativeMap->bearing() + bearingDelta); + // then reanchor + m_declarativeMap->setCenter(m_map->geoProjection().anchorCoordinateToPoint(wheelGeoPos, preZoomPoint)); + } else if (event->modifiers() & Qt::ControlModifier && tiltEnabled()) { + const double tiltDelta = event->angleDelta().y() * qreal(0.05); + m_declarativeMap->setTilt(m_declarativeMap->tilt() + tiltDelta); + } else if (pinchEnabled()) { + const double zoomLevelDelta = event->angleDelta().y() * qreal(0.001); + // Gesture area should always honor maxZL, but Map might not. + m_declarativeMap->setZoomLevel(qMin<qreal>(m_declarativeMap->zoomLevel() + zoomLevelDelta, maximumZoomLevel()), + false); + const QPointF &postZoomPoint = m_map->geoProjection().coordinateToItemPosition(wheelGeoPos, false).toPointF(); + + if (preZoomPoint != postZoomPoint) // need to re-anchor the wheel geoPos to the event position + m_declarativeMap->setCenter(m_map->geoProjection().anchorCoordinateToPoint(wheelGeoPos, preZoomPoint)); + } event->accept(); } #endif @@ -1705,7 +1706,7 @@ bool QQuickGeoMapGestureArea::canStartPan() */ void QQuickGeoMapGestureArea::updatePan() { - QGeoCoordinate animationStartCoordinate = anchorCoordinateToPoint(*m_map, m_startCoord, m_touchPointsCentroid); + QGeoCoordinate animationStartCoordinate = m_map->geoProjection().anchorCoordinateToPoint(m_startCoord, m_touchPointsCentroid); m_declarativeMap->setCenter(animationStartCoordinate); } diff --git a/src/location/doc/qtlocation.qdocconf b/src/location/doc/qtlocation.qdocconf index 695860a0..464e8e76 100644 --- a/src/location/doc/qtlocation.qdocconf +++ b/src/location/doc/qtlocation.qdocconf @@ -16,7 +16,7 @@ qhp.QtLocation.indexRoot = qhp.QtLocation.filterAttributes = qtlocation $QT_VERSION qtrefdoc qhp.QtLocation.customFilters.Qt.name = QtLocation $QT_VERSION -qhp.QtLocation.customFilters.Qt.filterAttributes = qtLocation $QT_VERSION +qhp.QtLocation.customFilters.Qt.filterAttributes = qtlocation $QT_VERSION qhp.QtLocation.subprojects = classes qml examples qhp.QtLocation.subprojects.classes.title = C++ Classes qhp.QtLocation.subprojects.classes.indexTitle = Qt Location C++ Classes @@ -43,6 +43,8 @@ sourcedirs += .. \ examplesinstallpath = location +manifestmeta.highlighted.names = "QtLocation/Map Viewer (QML)" + exampledirs += ../../../examples/location \ snippets/ diff --git a/src/location/doc/src/plugins/mapboxgl.qdoc b/src/location/doc/src/plugins/mapboxgl.qdoc index 6593a9e3..8ad6a9c2 100644 --- a/src/location/doc/src/plugins/mapboxgl.qdoc +++ b/src/location/doc/src/plugins/mapboxgl.qdoc @@ -109,6 +109,12 @@ The following table lists optional parameters that can be passed to the Mapbox p but the offline database must be populated using the \l {https://github.com/mapbox/mapbox-gl-native/blob/master/bin/offline.cpp} {offline tool}. The offline database will work alongside with the ambient cache in the same file. Make sure to comply with Mapbox Terms of Service before creating an offline database. + + \b {Note:} The map tile cache file name must be "mapboxgl.db". When using the offline tool, the default + output is "offline.db". For using the generated output from the offline tool, you must move that to the + proper directory, and rename it as "mapboxgl.db". The offline tool also provides the "--output" + parameter for specifying the name of the generated output. + \row \li mapboxgl.mapping.cache.memory \li Whether or not the cache should be in-memory only. Valid values are \b true and \b false. The default diff --git a/src/location/maps/qgeomappingmanagerengine.cpp b/src/location/maps/qgeomappingmanagerengine.cpp index ffc0f065..187b30eb 100644 --- a/src/location/maps/qgeomappingmanagerengine.cpp +++ b/src/location/maps/qgeomappingmanagerengine.cpp @@ -154,7 +154,13 @@ QGeoCameraCapabilities QGeoMappingManagerEngine::cameraCapabilities(int mapId) c { Q_UNUSED(mapId) Q_D(const QGeoMappingManagerEngine); - return d->capabilities_; + + if (mapId == 0) + return d->capabilities_; + int idx = mapId - 1; + if (idx >= supportedMapTypes().size()) + return d->capabilities_; + return supportedMapTypes().at(idx).cameraCapabilities(); } void QGeoMappingManagerEngine::setCameraCapabilities(const QGeoCameraCapabilities &capabilities) diff --git a/src/location/maps/qgeomappingmanagerengine_p.h b/src/location/maps/qgeomappingmanagerengine_p.h index 0f347d73..dd4aa681 100644 --- a/src/location/maps/qgeomappingmanagerengine_p.h +++ b/src/location/maps/qgeomappingmanagerengine_p.h @@ -90,7 +90,7 @@ public: QList<QGeoMapType> supportedMapTypes() const; // the class is private, so this can be virtual here for now. - virtual QGeoCameraCapabilities cameraCapabilities(int mapId = 0) const; + QGeoCameraCapabilities cameraCapabilities(int mapId = 0) const; void setLocale(const QLocale &locale); QLocale locale() const; diff --git a/src/location/maps/qgeomaptype.cpp b/src/location/maps/qgeomaptype.cpp index 34781451..c4635998 100644 --- a/src/location/maps/qgeomaptype.cpp +++ b/src/location/maps/qgeomaptype.cpp @@ -46,8 +46,11 @@ QGeoMapType::QGeoMapType(const QGeoMapType &other) : d_ptr(other.d_ptr) {} QGeoMapType::QGeoMapType(QGeoMapType::MapStyle style, const QString &name, - const QString &description, bool mobile, bool night, int mapId, QByteArray pluginName) -: d_ptr(new QGeoMapTypePrivate(style, name, description, mobile, night, mapId, pluginName)) + const QString &description, bool mobile, bool night, int mapId, + const QByteArray &pluginName, + const QGeoCameraCapabilities &cameraCapabilities, + const QVariantMap &metadata) +: d_ptr(new QGeoMapTypePrivate(style, name, description, mobile, night, mapId, pluginName, cameraCapabilities, metadata)) { } @@ -107,6 +110,16 @@ QByteArray QGeoMapType::pluginName() const return d_ptr->pluginName_; } +QGeoCameraCapabilities QGeoMapType::cameraCapabilities() const +{ + return d_ptr->cameraCapabilities_; +} + +QVariantMap QGeoMapType::metadata() const +{ + return d_ptr->metadata_; +} + QGeoMapTypePrivate::QGeoMapTypePrivate() : style_(QGeoMapType::NoMap), mobile_(false), night_(false), mapId_(0) { @@ -114,15 +127,18 @@ QGeoMapTypePrivate::QGeoMapTypePrivate() QGeoMapTypePrivate::QGeoMapTypePrivate(const QGeoMapTypePrivate &other) : QSharedData(other), style_(other.style_), name_(other.name_), description_(other.description_), - mobile_(other.mobile_), night_(other.night_), mapId_(other.mapId_), pluginName_(other.pluginName_) + mobile_(other.mobile_), night_(other.night_), mapId_(other.mapId_), pluginName_(other.pluginName_), + cameraCapabilities_(other.cameraCapabilities_), metadata_(other.metadata_) { } QGeoMapTypePrivate::QGeoMapTypePrivate(QGeoMapType::MapStyle style, const QString &name, const QString &description, bool mobile, bool night, - int mapId, QByteArray pluginName) + int mapId, const QByteArray &pluginName, + const QGeoCameraCapabilities &cameraCapabilities, + const QVariantMap &metadata) : style_(style), name_(name), description_(description), mobile_(mobile), night_(night), - mapId_(mapId), pluginName_(pluginName) + mapId_(mapId), pluginName_(pluginName), cameraCapabilities_(cameraCapabilities), metadata_(metadata) { } @@ -134,7 +150,8 @@ bool QGeoMapTypePrivate::operator==(const QGeoMapTypePrivate &other) const { return pluginName_ == other.pluginName_ && style_ == other.style_ && name_ == other.name_ && description_ == other.description_ && mobile_ == other.mobile_ && night_ == other.night_ && - mapId_ == other.mapId_; + mapId_ == other.mapId_ && cameraCapabilities_ == other.cameraCapabilities_ && + metadata_ == other.metadata_; } QT_END_NAMESPACE diff --git a/src/location/maps/qgeomaptype_p.h b/src/location/maps/qgeomaptype_p.h index 4b5cb0d0..3ce0e95a 100644 --- a/src/location/maps/qgeomaptype_p.h +++ b/src/location/maps/qgeomaptype_p.h @@ -51,6 +51,8 @@ #include <QtCore/QString> #include <QtCore/QSharedDataPointer> #include <QtLocation/private/qlocationglobal_p.h> +#include <QtLocation/private/qgeocameracapabilities_p.h> +#include <QVariantMap> QT_BEGIN_NAMESPACE @@ -59,7 +61,7 @@ class QGeoMapTypePrivate; class Q_LOCATION_PRIVATE_EXPORT QGeoMapType { public: - enum MapStyle { + enum MapStyle { // ### Qt6: change this to be a QFlags instead, or remove. NoMap = 0, StreetMap, SatelliteMapDay, @@ -77,7 +79,9 @@ public: QGeoMapType(); QGeoMapType(const QGeoMapType &other); QGeoMapType(MapStyle style, const QString &name, const QString &description, bool mobile, - bool night, int mapId, QByteArray pluginName); + bool night, int mapId, const QByteArray &pluginName, + const QGeoCameraCapabilities &cameraCapabilities, + const QVariantMap &metadata = QVariantMap()); ~QGeoMapType(); QGeoMapType &operator = (const QGeoMapType &other); @@ -92,6 +96,8 @@ public: bool night() const; int mapId() const; QByteArray pluginName() const; + QGeoCameraCapabilities cameraCapabilities() const; + QVariantMap metadata() const; private: QSharedDataPointer<QGeoMapTypePrivate> d_ptr; diff --git a/src/location/maps/qgeomaptype_p_p.h b/src/location/maps/qgeomaptype_p_p.h index 039c0962..e66991ab 100644 --- a/src/location/maps/qgeomaptype_p_p.h +++ b/src/location/maps/qgeomaptype_p_p.h @@ -50,9 +50,10 @@ #include <QMetaType> #include <QString> +#include <QVariantMap> #include <QByteArray> #include <QSharedData> - +#include "qgeocameracapabilities_p.h" #include "qgeomaptype_p.h" QT_BEGIN_NAMESPACE @@ -62,7 +63,9 @@ class QGeoMapTypePrivate : public QSharedData public: QGeoMapTypePrivate(); QGeoMapTypePrivate(QGeoMapType::MapStyle style, const QString &name, const QString &description, bool mobile, - bool night, int mapId, QByteArray pluginName); + bool night, int mapId, const QByteArray &pluginName, + const QGeoCameraCapabilities &cameraCapabilities, + const QVariantMap &metadata); QGeoMapTypePrivate(const QGeoMapTypePrivate &other); ~QGeoMapTypePrivate(); @@ -77,6 +80,8 @@ public: bool night_; int mapId_; QByteArray pluginName_; + QGeoCameraCapabilities cameraCapabilities_; + QVariantMap metadata_; }; QT_END_NAMESPACE diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp index fcf9a350..1df174fb 100644 --- a/src/location/maps/qgeoprojection.cpp +++ b/src/location/maps/qgeoprojection.cpp @@ -73,6 +73,17 @@ QGeoProjection::~QGeoProjection() } +QGeoCoordinate QGeoProjection::anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const +{ + // Approach: find the displacement in (wrapped) mercator space, and apply that to the center + QDoubleVector2D centerProj = geoToWrappedMapProjection(cameraData().center()); + QDoubleVector2D coordProj = geoToWrappedMapProjection(coordinate); + + QDoubleVector2D anchorProj = itemPositionToWrappedMapProjection(QDoubleVector2D(anchorPoint)); + // Y-clamping done in mercatorToCoord + return wrappedMapProjectionToGeo(centerProj + coordProj - anchorProj); +} + /* * QGeoProjectionWebMercator implementation */ @@ -576,6 +587,11 @@ void QGeoProjectionWebMercator::updateVisibleRegion() } } +QGeoCameraData QGeoProjectionWebMercator::cameraData() const +{ + return m_cameraData; +} + /* * * Line implementation diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h index 76e11af0..ca81df3a 100644 --- a/src/location/maps/qgeoprojection_p.h +++ b/src/location/maps/qgeoprojection_p.h @@ -92,6 +92,12 @@ public: virtual QDoubleVector2D geoToWrappedMapProjection(const QGeoCoordinate &coordinate) const = 0; virtual QGeoCoordinate wrappedMapProjectionToGeo(const QDoubleVector2D &wrappedProjection) const = 0; virtual QMatrix4x4 quickItemTransformation(const QGeoCoordinate &coordinate, const QPointF &anchorPoint, qreal zoomLevel) const = 0; + + // Returns the new map center after anchoring coordinate to anchorPoint on the screen + QGeoCoordinate anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const; + +private: + virtual QGeoCameraData cameraData() const = 0; }; class Q_LOCATION_PRIVATE_EXPORT QGeoProjectionWebMercator : public QGeoProjection @@ -133,6 +139,7 @@ public: private: void setupCamera(); void updateVisibleRegion(); + QGeoCameraData cameraData() const Q_DECL_OVERRIDE; public: struct Line2D diff --git a/src/location/maps/qgeorouterequest.cpp b/src/location/maps/qgeorouterequest.cpp index 753d2ee9..a1b32d85 100644 --- a/src/location/maps/qgeorouterequest.cpp +++ b/src/location/maps/qgeorouterequest.cpp @@ -134,6 +134,8 @@ QT_BEGIN_NAMESPACE Consider parks when planning the route. \value MotorPoolLaneFeature Consider motor pool lanes when planning the route. + \value TrafficFeature + Consider the current traffic situation when planning the route. Since QtLocation 5.10 */ /*! diff --git a/src/location/maps/qgeorouterequest.h b/src/location/maps/qgeorouterequest.h index 6fcc7ad3..cf89d13d 100644 --- a/src/location/maps/qgeorouterequest.h +++ b/src/location/maps/qgeorouterequest.h @@ -70,7 +70,8 @@ public: TunnelFeature = 0x00000010, DirtRoadFeature = 0x00000020, ParksFeature = 0x00000040, - MotorPoolLaneFeature = 0x00000080 + MotorPoolLaneFeature = 0x00000080, + TrafficFeature = 0x00000100 }; Q_DECLARE_FLAGS(FeatureTypes, FeatureType) diff --git a/src/location/maps/qgeotilefetcher.cpp b/src/location/maps/qgeotilefetcher.cpp index 70ebbcd1..bab75034 100644 --- a/src/location/maps/qgeotilefetcher.cpp +++ b/src/location/maps/qgeotilefetcher.cpp @@ -126,7 +126,7 @@ void QGeoTileFetcher::requestNextTile() const QGeoCameraCapabilities & cameraCaps = d->engine_->cameraCapabilities(ts.mapId()); // the ZL in QGeoTileSpec is relative to the native tile size of the provider. // It gets denormalized in QGeoTiledMap. - if (ts.zoom() < cameraCaps.minimumZoomLevel() || ts.zoom() > cameraCaps.maximumZoomLevel()) + if (ts.zoom() < cameraCaps.minimumZoomLevel() || ts.zoom() > cameraCaps.maximumZoomLevel() || !fetchingEnabled()) return; QGeoTiledMapReply *reply = getTileImage(ts); @@ -189,6 +189,11 @@ bool QGeoTileFetcher::initialized() const return true; } +bool QGeoTileFetcher::fetchingEnabled() const +{ + return true; +} + void QGeoTileFetcher::handleReply(QGeoTiledMapReply *reply, const QGeoTileSpec &spec) { Q_D(QGeoTileFetcher); diff --git a/src/location/maps/qgeotilefetcher_p.h b/src/location/maps/qgeotilefetcher_p.h index d052a8a8..88880424 100644 --- a/src/location/maps/qgeotilefetcher_p.h +++ b/src/location/maps/qgeotilefetcher_p.h @@ -89,6 +89,7 @@ protected: void timerEvent(QTimerEvent *event); QAbstractGeoTileCache::CacheAreas cacheHint() const; virtual bool initialized() const; + virtual bool fetchingEnabled() const; private: diff --git a/src/plugins/geoservices/esri/geomapsource.cpp b/src/plugins/geoservices/esri/geomapsource.cpp index 19f284e6..7ec63e2f 100644 --- a/src/plugins/geoservices/esri/geomapsource.cpp +++ b/src/plugins/geoservices/esri/geomapsource.cpp @@ -67,8 +67,8 @@ static const MapStyleData mapStyles[] = GeoMapSource::GeoMapSource(QGeoMapType::MapStyle style, const QString &name, const QString &description, bool mobile, bool night, int mapId, - const QString &url, const QString ©right) : - QGeoMapType(style, name, description, mobile, night, mapId, "esri"), + const QString &url, const QString ©right, const QGeoCameraCapabilities &cameraCapabilities) : + QGeoMapType(style, name, description, mobile, night, mapId, "esri", cameraCapabilities), m_url(url), m_copyright(copyright) { } diff --git a/src/plugins/geoservices/esri/geomapsource.h b/src/plugins/geoservices/esri/geomapsource.h index 8660e999..86258d2e 100644 --- a/src/plugins/geoservices/esri/geomapsource.h +++ b/src/plugins/geoservices/esri/geomapsource.h @@ -41,6 +41,7 @@ #define GEOMAPSOURCE_H #include <QtLocation/private/qgeomaptype_p.h> +#include <QtLocation/private/qgeocameracapabilities_p.h> QT_BEGIN_NAMESPACE @@ -49,7 +50,7 @@ class GeoMapSource : public QGeoMapType public: GeoMapSource(QGeoMapType::MapStyle style, const QString &name, const QString &description, bool mobile, bool night, int mapId, - const QString &url, const QString ©right); + const QString &url, const QString ©right, const QGeoCameraCapabilities &cameraCapabilities); inline const QString &url() const; inline const QString ©right() const; diff --git a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp index 23783d7e..ac8f8450 100644 --- a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp +++ b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.cpp @@ -106,7 +106,7 @@ GeoTiledMappingManagerEngineEsri::GeoTiledMappingManagerEngineEsri(const QVarian setTileSize(QSize(256, 256)); - if (!initializeMapSources(error, errorString)) + if (!initializeMapSources(error, errorString, cameraCaps)) return; QList<QGeoMapType> mapTypes; @@ -119,7 +119,8 @@ GeoTiledMappingManagerEngineEsri::GeoTiledMappingManagerEngineEsri(const QVarian mapSource->mobile(), mapSource->night(), mapSource->mapId(), - "esri"); + "esri", + cameraCaps); } setSupportedMapTypes(mapTypes); @@ -237,7 +238,8 @@ QGeoMap *GeoTiledMappingManagerEngineEsri::createMap() // template = 'http://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{{z}}/{{y}}/{{x}}.png' bool GeoTiledMappingManagerEngineEsri::initializeMapSources(QGeoServiceProvider::Error *error, - QString *errorString) + QString *errorString, + const QGeoCameraCapabilities &cameraCaps) { initResources(); QFile mapsFile(":/esri/maps.json"); @@ -271,9 +273,7 @@ bool GeoTiledMappingManagerEngineEsri::initializeMapSources(QGeoServiceProvider: foreach (QVariant mapSourceElement, mapSources) { QVariantMap mapSource = mapSourceElement.toMap(); - int mapId = mapSource[kPropMapId].toInt(); - if (mapId <= 0) - mapId = m_mapSources.count() + 1; + int mapId = m_mapSources.count() + 1; m_mapSources << new GeoMapSource( GeoMapSource::mapStyle(mapSource[kPropStyle].toString()), @@ -283,7 +283,8 @@ bool GeoTiledMappingManagerEngineEsri::initializeMapSources(QGeoServiceProvider: mapSource[kPropMapId].toBool(), mapId, GeoMapSource::toFormat(mapSource[kPropUrl].toString()), - mapSource[kPropCopyright].toString() + mapSource[kPropCopyright].toString(), + cameraCaps ); } diff --git a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h index a13ba05c..ea0c3c8b 100644 --- a/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h +++ b/src/plugins/geoservices/esri/geotiledmappingmanagerengine_esri.h @@ -63,7 +63,7 @@ public: GeoMapSource *mapSource(int mapId) const; private: - bool initializeMapSources(QGeoServiceProvider::Error *error, QString *errorString); + bool initializeMapSources(QGeoServiceProvider::Error *error, QString *errorString, const QGeoCameraCapabilities &cameraCaps); QList<GeoMapSource *> m_mapSources; }; diff --git a/src/plugins/geoservices/itemsoverlay/qgeomappingmanagerengineitemsoverlay.cpp b/src/plugins/geoservices/itemsoverlay/qgeomappingmanagerengineitemsoverlay.cpp index 955fbcae..c19815e8 100644 --- a/src/plugins/geoservices/itemsoverlay/qgeomappingmanagerengineitemsoverlay.cpp +++ b/src/plugins/geoservices/itemsoverlay/qgeomappingmanagerengineitemsoverlay.cpp @@ -62,7 +62,7 @@ QGeoMappingManagerEngineItemsOverlay::QGeoMappingManagerEngineItemsOverlay(const setCameraCapabilities(cameraCaps); QList<QGeoMapType> mapTypes; - mapTypes << QGeoMapType(QGeoMapType::NoMap, tr("Empty Map"), tr("Empty Map"), false, false, 1, "itemsoverlay"); + mapTypes << QGeoMapType(QGeoMapType::NoMap, tr("Empty Map"), tr("Empty Map"), false, false, 1, "itemsoverlay", cameraCaps); setSupportedMapTypes(mapTypes); engineInitialized(); diff --git a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp index f5776852..78ccab8c 100644 --- a/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp +++ b/src/plugins/geoservices/mapbox/qgeoroutingmanagerenginemapbox.cpp @@ -77,14 +77,21 @@ QGeoRouteReply* QGeoRoutingManagerEngineMapbox::calculateRoute(const QGeoRouteRe QString url("https://api.mapbox.com/directions/v5/mapbox/"); QGeoRouteRequest::TravelModes travelModes = request.travelModes(); - if (travelModes.testFlag(QGeoRouteRequest::PedestrianTravel)) + if (travelModes.testFlag(QGeoRouteRequest::PedestrianTravel)) { url += "walking/"; - else - if (travelModes.testFlag(QGeoRouteRequest::BicycleTravel)) + } else if (travelModes.testFlag(QGeoRouteRequest::BicycleTravel)) { url += "cycling/"; - else - if (travelModes.testFlag(QGeoRouteRequest::CarTravel)) - url += "driving/"; + } else if (travelModes.testFlag(QGeoRouteRequest::CarTravel)) { + const QList<QGeoRouteRequest::FeatureType> &featureTypes = request.featureTypes(); + int trafficFeatureIdx = featureTypes.indexOf(QGeoRouteRequest::TrafficFeature); + QGeoRouteRequest::FeatureWeight trafficWeight = request.featureWeight(QGeoRouteRequest::TrafficFeature); + if (trafficFeatureIdx >= 0 && + (trafficWeight == QGeoRouteRequest::AvoidFeatureWeight || trafficWeight == QGeoRouteRequest::DisallowFeatureWeight)) { + url += "driving-traffic/"; + } else { + url += "driving/"; + } + } foreach (const QGeoCoordinate &c, request.waypoints()) { url += QString("%1,%2;").arg(c.longitude()).arg(c.latitude()); diff --git a/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp index 03a574c3..632b2286 100644 --- a/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp +++ b/src/plugins/geoservices/mapbox/qgeotiledmappingmanagerenginemapbox.cpp @@ -66,41 +66,41 @@ QGeoTiledMappingManagerEngineMapbox::QGeoTiledMappingManagerEngineMapbox(const Q // as index 0 to retain compatibility with the current API, that expects the passed map_id to be on by default. if (parameters.contains(QStringLiteral("mapbox.mapping.map_id"))) { const QString name = parameters.value(QStringLiteral("mapbox.mapping.map_id")).toString(); - mapTypes << QGeoMapType(QGeoMapType::CustomMap, name, name, false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, name, name, false, false, mapTypes.size() + 1, pluginName, cameraCaps); } else if (parameters.contains(QStringLiteral("mapbox.map_id"))) { //deprecated const QString name = parameters.value(QStringLiteral("mapbox.map_id")).toString(); - mapTypes << QGeoMapType(QGeoMapType::CustomMap, name, name, false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, name, name, false, false, mapTypes.size() + 1, pluginName, cameraCaps); } // As of 2016.06.15, valid mapbox map_ids are documented at https://www.mapbox.com/api-documentation/#maps //: Noun describing map type 'Street map' - mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.streets"), tr("Street"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.streets"), tr("Street"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map using light colors (weak contrast) - mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.light"), tr("Light"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.light"), tr("Light"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map using dark colors - mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.dark"), tr("Dark"), false, true, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.dark"), tr("Dark"), false, true, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map created by satellite - mapTypes << QGeoMapType(QGeoMapType::SatelliteMapDay, QStringLiteral("mapbox.satellite"), tr("Satellite"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::SatelliteMapDay, QStringLiteral("mapbox.satellite"), tr("Satellite"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a street map created by satellite - mapTypes << QGeoMapType(QGeoMapType::HybridMap, QStringLiteral("mapbox.streets-satellite"), tr("Streets Satellite"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::HybridMap, QStringLiteral("mapbox.streets-satellite"), tr("Streets Satellite"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map using wheat paste colors - mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.wheatpaste"), tr("Wheatpaste"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.wheatpaste"), tr("Wheatpaste"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a basic street map - mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.streets-basic"), tr("Streets Basic"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox.streets-basic"), tr("Streets Basic"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map using cartoon-style fonts - mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.comic"), tr("Comic"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.comic"), tr("Comic"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map for outdoor activities - mapTypes << QGeoMapType(QGeoMapType::PedestrianMap, QStringLiteral("mapbox.outdoors"), tr("Outdoors"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::PedestrianMap, QStringLiteral("mapbox.outdoors"), tr("Outdoors"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map for sports - mapTypes << QGeoMapType(QGeoMapType::CycleMap, QStringLiteral("mapbox.run-bike-hike"), tr("Run Bike Hike"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CycleMap, QStringLiteral("mapbox.run-bike-hike"), tr("Run Bike Hike"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map drawn by pencil - mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.pencil"), tr("Pencil"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.pencil"), tr("Pencil"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a treasure map with pirate boat watermark - mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.pirates"), tr("Pirates"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.pirates"), tr("Pirates"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map using emerald colors - mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.emerald"), tr("Emerald"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.emerald"), tr("Emerald"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); //: Noun describing type of a map with high contrast - mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.high-contrast"), tr("High Contrast"), false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, QStringLiteral("mapbox.high-contrast"), tr("High Contrast"), false, false, mapTypes.size() + 1, pluginName, cameraCaps); // New way to specify multiple customized map_ids via additional_map_ids if (parameters.contains(QStringLiteral("mapbox.mapping.additional_map_ids"))) { @@ -109,7 +109,7 @@ QGeoTiledMappingManagerEngineMapbox::QGeoTiledMappingManagerEngineMapbox(const Q for (const QString &name: idList) { if (!name.isEmpty()) - mapTypes << QGeoMapType(QGeoMapType::CustomMap, name, name, false, false, mapTypes.size() + 1, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, name, name, false, false, mapTypes.size() + 1, pluginName, cameraCaps); } } diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp index e27e2622..dd5c9a86 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp +++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp @@ -450,7 +450,7 @@ void QGeoMapMapboxGL::copyrightsChanged(const QString ©rightsHtml) if (d->m_developmentMode) { copyrightsHtmlFinal.prepend("<a href='https://www.mapbox.com/pricing'>" - + tr("Development access token, do not use in production!") + "</a> - "); + + tr("Development access token, do not use in production.") + "</a> - "); } if (d->m_activeMapType.name().startsWith("mapbox://")) { diff --git a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp index 211c0bba..cc48afb2 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp +++ b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp @@ -70,25 +70,29 @@ QGeoMappingManagerEngineMapboxGL::QGeoMappingManagerEngineMapboxGL(const QVarian const QByteArray pluginName = "mapboxgl"; mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/streets-v10"), - tr("Streets"), false, false, ++mapId, pluginName); + tr("Streets"), false, false, ++mapId, pluginName, cameraCaps); mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/basic-v9"), - tr("Basic"), false, false, ++mapId, pluginName); + tr("Basic"), false, false, ++mapId, pluginName, cameraCaps); mapTypes << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("mapbox://styles/mapbox/bright-v9"), - tr("Bright"), false, false, ++mapId, pluginName); + tr("Bright"), false, false, ++mapId, pluginName, cameraCaps); mapTypes << QGeoMapType(QGeoMapType::TerrainMap, QStringLiteral("mapbox://styles/mapbox/outdoors-v10"), - tr("Outdoors"), false, false, ++mapId, pluginName); + tr("Outdoors"), false, false, ++mapId, pluginName, cameraCaps); mapTypes << QGeoMapType(QGeoMapType::SatelliteMapDay, QStringLiteral("mapbox://styles/mapbox/satellite-v9"), - tr("Satellite"), false, false, ++mapId, pluginName); + tr("Satellite"), false, false, ++mapId, pluginName, cameraCaps); mapTypes << QGeoMapType(QGeoMapType::HybridMap, QStringLiteral("mapbox://styles/mapbox/satellite-streets-v10"), - tr("Satellite Streets"), false, false, ++mapId, pluginName); + tr("Satellite Streets"), false, false, ++mapId, pluginName, cameraCaps); mapTypes << QGeoMapType(QGeoMapType::GrayStreetMap, QStringLiteral("mapbox://styles/mapbox/light-v9"), - tr("Light"), false, false, ++mapId, pluginName); + tr("Light"), false, false, ++mapId, pluginName, cameraCaps); mapTypes << QGeoMapType(QGeoMapType::GrayStreetMap, QStringLiteral("mapbox://styles/mapbox/dark-v9"), - tr("Dark"), false, false, ++mapId, pluginName); - mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/traffic-day-v1"), - tr("Streets Traffic Day"), false, false, ++mapId, pluginName); - mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/traffic-night-v1"), - tr("Streets Traffic Night"), false, true, ++mapId, pluginName); + tr("Dark"), false, false, ++mapId, pluginName, cameraCaps); + mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/navigation-preview-day-v2"), + tr("Navigation Preview Day"), false, false, ++mapId, pluginName, cameraCaps); + mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/navigation-preview-night-v2"), + tr("Navigation Preview Night"), false, true, ++mapId, pluginName, cameraCaps); + mapTypes << QGeoMapType(QGeoMapType::CarNavigationMap, QStringLiteral("mapbox://styles/mapbox/navigation-guidance-day-v2"), + tr("Navigation Guidance Day"), false, false, ++mapId, pluginName, cameraCaps); + mapTypes << QGeoMapType(QGeoMapType::CarNavigationMap, QStringLiteral("mapbox://styles/mapbox/navigation-guidance-night-v2"), + tr("Navigation Guidance Night"), false, true, ++mapId, pluginName, cameraCaps); if (parameters.contains(QStringLiteral("mapboxgl.mapping.additional_style_urls"))) { const QString ids = parameters.value(QStringLiteral("mapboxgl.mapping.additional_style_urls")).toString(); @@ -99,7 +103,7 @@ QGeoMappingManagerEngineMapboxGL::QGeoMappingManagerEngineMapboxGL(const QVarian continue; mapTypes.prepend(QGeoMapType(QGeoMapType::CustomMap, *it, - tr("User provided style"), false, false, ++mapId, pluginName)); + tr("User provided style"), false, false, ++mapId, pluginName, cameraCaps)); } } diff --git a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp index a33d1ba8..d7e4cf8d 100644 --- a/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeoroutingmanagerengine_nokia.cpp @@ -360,6 +360,7 @@ QString QGeoRoutingManagerEngineNokia::modesRequestString(const QGeoRouteRequest case QGeoRouteRequest::PublicTransitFeature: case QGeoRouteRequest::ParksFeature: case QGeoRouteRequest::MotorPoolLaneFeature: + case QGeoRouteRequest::TrafficFeature: case QGeoRouteRequest::NoFeature: break; } diff --git a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp index 146071f7..e315c44e 100644 --- a/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp +++ b/src/plugins/geoservices/nokia/qgeotiledmappingmanagerengine_nokia.cpp @@ -90,29 +90,30 @@ QGeoTiledMappingManagerEngineNokia::QGeoTiledMappingManagerEngineNokia( setTileSize(QSize(256, 256)); + int mapId = 0; const QByteArray pluginName = "here"; QList<QGeoMapType> types; - types << QGeoMapType(QGeoMapType::StreetMap, tr("Street Map"), tr("Normal map view in daylight mode"), false, false, 1, pluginName); - types << QGeoMapType(QGeoMapType::SatelliteMapDay, tr("Satellite Map"), tr("Satellite map view in daylight mode"), false, false, 2, pluginName); - types << QGeoMapType(QGeoMapType::TerrainMap, tr("Terrain Map"), tr("Terrain map view in daylight mode"), false, false, 3, pluginName); - types << QGeoMapType(QGeoMapType::HybridMap, tr("Hybrid Map"), tr("Satellite map view with streets in daylight mode"), false, false, 4, pluginName); - types << QGeoMapType(QGeoMapType::TransitMap, tr("Transit Map"), tr("Color-reduced map view with public transport scheme in daylight mode"), false, false, 5, pluginName); - types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Gray Street Map"), tr("Color-reduced map view in daylight mode"), false, false, 6, pluginName); - types << QGeoMapType(QGeoMapType::StreetMap, tr("Mobile Street Map"), tr("Mobile normal map view in daylight mode"), true, false, 7, pluginName); - types << QGeoMapType(QGeoMapType::TerrainMap, tr("Mobile Terrain Map"), tr("Mobile terrain map view in daylight mode"), true, false, 8, pluginName); - types << QGeoMapType(QGeoMapType::HybridMap, tr("Mobile Hybrid Map"), tr("Mobile satellite map view with streets in daylight mode"), true, false, 9, pluginName); - types << QGeoMapType(QGeoMapType::TransitMap, tr("Mobile Transit Map"), tr("Mobile color-reduced map view with public transport scheme in daylight mode"), true, false, 10, pluginName); - types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Mobile Gray Street Map"), tr("Mobile color-reduced map view in daylight mode"), true, false, 11, pluginName); - types << QGeoMapType(QGeoMapType::StreetMap, tr("Custom Street Map"), tr("Normal map view in daylight mode"), false, false, 12, pluginName); - types << QGeoMapType(QGeoMapType::StreetMap, tr("Night Street Map"), tr("Normal map view in night mode"), false, true, 13, pluginName); - types << QGeoMapType(QGeoMapType::StreetMap, tr("Mobile Night Street Map"), tr("Mobile normal map view in night mode"), true, true, 14, pluginName); - types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Gray Night Street Map"), tr("Color-reduced map view in night mode (especially used for background maps)"), false, true, 15, pluginName); - types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Mobile Gray Night Street Map"), tr("Mobile color-reduced map view in night mode (especially used for background maps)"), true, true, 16, pluginName); - types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Pedestrian Street Map"), tr("Pedestrian map view in daylight mode"), false, false, 17, pluginName); - types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Mobile Pedestrian Street Map"), tr("Mobile pedestrian map view in daylight mode for mobile usage"), true, false, 18, pluginName); - types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Pedestrian Night Street Map"), tr("Pedestrian map view in night mode"), false, true, 19, pluginName); - types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Mobile Pedestrian Night Street Map"), tr("Mobile pedestrian map view in night mode for mobile usage"), true, true, 20, pluginName); - types << QGeoMapType(QGeoMapType::CarNavigationMap, tr("Car Navigation Map"), tr("Normal map view in daylight mode for car navigation"), false, false, 21, pluginName); + types << QGeoMapType(QGeoMapType::StreetMap, tr("Street Map"), tr("Normal map view in daylight mode"), false, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::SatelliteMapDay, tr("Satellite Map"), tr("Satellite map view in daylight mode"), false, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::TerrainMap, tr("Terrain Map"), tr("Terrain map view in daylight mode"), false, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::HybridMap, tr("Hybrid Map"), tr("Satellite map view with streets in daylight mode"), false, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::TransitMap, tr("Transit Map"), tr("Color-reduced map view with public transport scheme in daylight mode"), false, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Gray Street Map"), tr("Color-reduced map view in daylight mode"), false, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::StreetMap, tr("Mobile Street Map"), tr("Mobile normal map view in daylight mode"), true, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::TerrainMap, tr("Mobile Terrain Map"), tr("Mobile terrain map view in daylight mode"), true, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::HybridMap, tr("Mobile Hybrid Map"), tr("Mobile satellite map view with streets in daylight mode"), true, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::TransitMap, tr("Mobile Transit Map"), tr("Mobile color-reduced map view with public transport scheme in daylight mode"), true, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Mobile Gray Street Map"), tr("Mobile color-reduced map view in daylight mode"), true, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::StreetMap, tr("Custom Street Map"), tr("Normal map view in daylight mode"), false, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::StreetMap, tr("Night Street Map"), tr("Normal map view in night mode"), false, true, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::StreetMap, tr("Mobile Night Street Map"), tr("Mobile normal map view in night mode"), true, true, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Gray Night Street Map"), tr("Color-reduced map view in night mode (especially used for background maps)"), false, true, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::GrayStreetMap, tr("Mobile Gray Night Street Map"), tr("Mobile color-reduced map view in night mode (especially used for background maps)"), true, true, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Pedestrian Street Map"), tr("Pedestrian map view in daylight mode"), false, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Mobile Pedestrian Street Map"), tr("Mobile pedestrian map view in daylight mode for mobile usage"), true, false, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Pedestrian Night Street Map"), tr("Pedestrian map view in night mode"), false, true, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::PedestrianMap, tr("Mobile Pedestrian Night Street Map"), tr("Mobile pedestrian map view in night mode for mobile usage"), true, true, ++mapId, pluginName, capabilities); + types << QGeoMapType(QGeoMapType::CarNavigationMap, tr("Car Navigation Map"), tr("Normal map view in daylight mode for car navigation"), false, false, ++mapId, pluginName, capabilities); setSupportedMapTypes(types); QGeoTileFetcherNokia *fetcher = new QGeoTileFetcherNokia(parameters, networkManager, this, tileSize(), ppi); diff --git a/src/plugins/geoservices/nokia/qgeouriprovider.cpp b/src/plugins/geoservices/nokia/qgeouriprovider.cpp index 80b47f31..b471f7c1 100644 --- a/src/plugins/geoservices/nokia/qgeouriprovider.cpp +++ b/src/plugins/geoservices/nokia/qgeouriprovider.cpp @@ -37,6 +37,7 @@ #include <QMap> #include <QVariant> +#include <QRandomGenerator> #include <QSet> #include <QString> @@ -60,7 +61,7 @@ QGeoUriProvider::QGeoUriProvider( QString QGeoUriProvider::getCurrentHost() const { if (m_maxSubdomains) { - QString result(m_firstSubdomain.toLatin1() + qrand() % m_maxSubdomains); + QString result(m_firstSubdomain.toLatin1() + QRandomGenerator::global()->bounded(m_maxSubdomains)); result += '.' + m_currentHost; return result; } diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp index 45e7efbe..9174ad62 100644 --- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp +++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.cpp @@ -164,25 +164,25 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian /* QGeoTileProviderOsms setup */ const QByteArray pluginName = "osm"; m_providers.push_back( new QGeoTileProviderOsm( nm, - QGeoMapType(QGeoMapType::StreetMap, tr("Street Map"), tr("Street map view in daylight mode"), false, false, 1, pluginName), + QGeoMapType(QGeoMapType::StreetMap, tr("Street Map"), tr("Street map view in daylight mode"), false, false, 1, pluginName, cameraCaps), providers_street, cameraCaps )); m_providers.push_back( new QGeoTileProviderOsm( nm, - QGeoMapType(QGeoMapType::SatelliteMapDay, tr("Satellite Map"), tr("Satellite map view in daylight mode"), false, false, 2, pluginName), + QGeoMapType(QGeoMapType::SatelliteMapDay, tr("Satellite Map"), tr("Satellite map view in daylight mode"), false, false, 2, pluginName, cameraCaps), providers_satellite, cameraCaps )); m_providers.push_back( new QGeoTileProviderOsm( nm, - QGeoMapType(QGeoMapType::CycleMap, tr("Cycle Map"), tr("Cycle map view in daylight mode"), false, false, 3, pluginName), + QGeoMapType(QGeoMapType::CycleMap, tr("Cycle Map"), tr("Cycle map view in daylight mode"), false, false, 3, pluginName, cameraCaps), providers_cycle, cameraCaps )); m_providers.push_back( new QGeoTileProviderOsm( nm, - QGeoMapType(QGeoMapType::TransitMap, tr("Transit Map"), tr("Public transit map view in daylight mode"), false, false, 4, pluginName), + QGeoMapType(QGeoMapType::TransitMap, tr("Transit Map"), tr("Public transit map view in daylight mode"), false, false, 4, pluginName, cameraCaps), providers_transit, cameraCaps )); m_providers.push_back( new QGeoTileProviderOsm( nm, - QGeoMapType(QGeoMapType::TransitMap, tr("Night Transit Map"), tr("Public transit map view in night mode"), false, true, 5, pluginName), + QGeoMapType(QGeoMapType::TransitMap, tr("Night Transit Map"), tr("Public transit map view in night mode"), false, true, 5, pluginName, cameraCaps), providers_nighttransit, cameraCaps )); m_providers.push_back( new QGeoTileProviderOsm( nm, - QGeoMapType(QGeoMapType::TerrainMap, tr("Terrain Map"), tr("Terrain map view"), false, false, 6, pluginName), + QGeoMapType(QGeoMapType::TerrainMap, tr("Terrain Map"), tr("Terrain map view"), false, false, 6, pluginName, cameraCaps), providers_terrain, cameraCaps )); m_providers.push_back( new QGeoTileProviderOsm( nm, - QGeoMapType(QGeoMapType::PedestrianMap, tr("Hiking Map"), tr("Hiking map view"), false, false, 7, pluginName), + QGeoMapType(QGeoMapType::PedestrianMap, tr("Hiking Map"), tr("Hiking map view"), false, false, 7, pluginName, cameraCaps), providers_hiking, cameraCaps )); if (parameters.contains(QStringLiteral("osm.mapping.custom.host")) @@ -206,7 +206,7 @@ QGeoTiledMappingManagerEngineOsm::QGeoTiledMappingManagerEngineOsm(const QVarian m_providers.push_back( new QGeoTileProviderOsm( nm, - QGeoMapType(QGeoMapType::CustomMap, tr("Custom URL Map"), tr("Custom url map view set via urlprefix parameter"), false, false, 8, pluginName), + QGeoMapType(QGeoMapType::CustomMap, tr("Custom URL Map"), tr("Custom url map view set via urlprefix parameter"), false, false, 8, pluginName, cameraCaps), { new TileProvider(tmsServer + QStringLiteral("%z/%x/%y.png"), QStringLiteral("png"), mapCopyright, @@ -352,16 +352,6 @@ QString QGeoTiledMappingManagerEngineOsm::customCopyright() const return m_customCopyright; } -QGeoCameraCapabilities QGeoTiledMappingManagerEngineOsm::cameraCapabilities(int mapId) const -{ - if (mapId == 0) - return QGeoMappingManagerEngine::cameraCapabilities(mapId); - int idx = mapId - 1; - if (idx >= m_providers.size()) - return QGeoMappingManagerEngine::cameraCapabilities(mapId); - return m_providers[idx]->cameraCapabilities(); -} - void QGeoTiledMappingManagerEngineOsm::onProviderResolutionFinished(const QGeoTileProviderOsm *provider) { if (!provider->isResolved()) diff --git a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h index c5f16c2b..12290c8f 100644 --- a/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h +++ b/src/plugins/geoservices/osm/qgeotiledmappingmanagerengineosm.h @@ -62,7 +62,6 @@ public: QGeoMap *createMap() override; const QVector<QGeoTileProviderOsm *> &providers(); QString customCopyright() const; - QGeoCameraCapabilities cameraCapabilities(int mapId) const override; protected Q_SLOTS: void onProviderResolutionFinished(const QGeoTileProviderOsm *provider); diff --git a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp index a0cbd843..f7ab8c99 100644 --- a/src/plugins/geoservices/osm/qgeotileproviderosm.cpp +++ b/src/plugins/geoservices/osm/qgeotileproviderosm.cpp @@ -236,7 +236,8 @@ void QGeoTileProviderOsm::updateCameraCapabilities() m_cameraCapabilities.setMinimumZoomLevel(minimumZoomLevel()); m_cameraCapabilities.setMaximumZoomLevel(maximumZoomLevel()); - // Pushing the change + m_mapType = QGeoMapType(m_mapType.style(), m_mapType.name(), m_mapType.description(), m_mapType.mobile(), + m_mapType.night(), m_mapType.mapId(), m_mapType.pluginName(), m_cameraCapabilities); } void QGeoTileProviderOsm::addProvider(TileProvider *provider) diff --git a/src/plugins/position/android/src/jnipositioning.cpp b/src/plugins/position/android/src/jnipositioning.cpp index 9bd49e90..9bef8d36 100644 --- a/src/plugins/position/android/src/jnipositioning.cpp +++ b/src/plugins/position/android/src/jnipositioning.cpp @@ -40,6 +40,7 @@ #include <QDateTime> #include <QDebug> #include <QMap> +#include <QRandomGenerator> #include <QtGlobal> #include <QtCore/private/qjnihelpers_p.h> #include <android/log.h> @@ -100,7 +101,6 @@ namespace AndroidPositioning { { static bool firstInit = true; if (firstInit) { - qsrand( QDateTime::currentMSecsSinceEpoch() / 1000 ); firstInit = false; } @@ -109,7 +109,7 @@ namespace AndroidPositioning { QGeoPositionInfoSourceAndroid *src = qobject_cast<QGeoPositionInfoSourceAndroid *>(obj); Q_ASSERT(src); do { - key = qrand(); + key = QRandomGenerator::global()->generate(); } while (idToPosSource()->contains(key)); idToPosSource()->insert(key, src); @@ -117,7 +117,7 @@ namespace AndroidPositioning { QGeoSatelliteInfoSourceAndroid *src = qobject_cast<QGeoSatelliteInfoSourceAndroid *>(obj); Q_ASSERT(src); do { - key = qrand(); + key = QRandomGenerator::global()->generate(); } while (idToSatSource()->contains(key)); idToSatSource()->insert(key, src); diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro index 32f3c05c..d02237be 100644 --- a/src/positioning/positioning.pro +++ b/src/positioning/positioning.pro @@ -38,6 +38,7 @@ PUBLIC_HEADERS += \ qnmeapositioninfosource.h \ qgeopositioninfosourcefactory.h \ qpositioningglobal.h \ + qgeopolygon.h \ qgeopath.h \ PRIVATE_HEADERS += \ @@ -82,6 +83,7 @@ SOURCES += \ qdoublevector2d.cpp \ qdoublevector3d.cpp \ qgeopath.cpp \ + qgeopolygon.cpp \ qlocationdata_simulator.cpp \ qwebmercator.cpp \ qdoublematrix4x4.cpp \ diff --git a/src/positioning/qgeopath.cpp b/src/positioning/qgeopath.cpp index ad3536af..5e7a4077 100644 --- a/src/positioning/qgeopath.cpp +++ b/src/positioning/qgeopath.cpp @@ -109,7 +109,7 @@ Q_GLOBAL_STATIC(PathVariantConversions, initPathConversions) Constructs a new, empty geo path. */ QGeoPath::QGeoPath() -: QGeoShape(new QGeoPathPrivate) +: QGeoShape(new QGeoPathPrivate(QGeoShape::PathType)) { initPathConversions(); } @@ -119,7 +119,7 @@ QGeoPath::QGeoPath() (\a path and \a width). */ QGeoPath::QGeoPath(const QList<QGeoCoordinate> &path, const qreal &width) -: QGeoShape(new QGeoPathPrivate(path, width)) +: QGeoShape(new QGeoPathPrivate(QGeoShape::PathType, path, width)) { initPathConversions(); } @@ -141,7 +141,7 @@ QGeoPath::QGeoPath(const QGeoShape &other) { initPathConversions(); if (type() != QGeoShape::PathType) - d_ptr = new QGeoPathPrivate; + d_ptr = new QGeoPathPrivate(QGeoShape::PathType); } /*! @@ -247,6 +247,17 @@ double QGeoPath::length(int indexFrom, int indexTo) const } /*! + Returns the number of elements in the path. + + \since 5.10 +*/ +int QGeoPath::size() const +{ + Q_D(const QGeoPath); + return d->size(); +} + +/*! Appends \a coordinate to the path. */ void QGeoPath::addCoordinate(const QGeoCoordinate &coordinate) @@ -330,22 +341,22 @@ QString QGeoPath::toString() const * QGeoPathPrivate *******************************************************************************/ -QGeoPathPrivate::QGeoPathPrivate() -: QGeoShapePrivate(QGeoShape::PathType), m_width(0) +QGeoPathPrivate::QGeoPathPrivate(QGeoShape::ShapeType type) +: QGeoShapePrivate(type), m_width(0), m_clipperDirty(true) { } -QGeoPathPrivate::QGeoPathPrivate(const QList<QGeoCoordinate> &path, const qreal width) -: QGeoShapePrivate(QGeoShape::PathType), m_width(0) +QGeoPathPrivate::QGeoPathPrivate(QGeoShape::ShapeType type, const QList<QGeoCoordinate> &path, const qreal width) +: QGeoShapePrivate(type), m_width(0), m_clipperDirty(true) { setPath(path); setWidth(width); } QGeoPathPrivate::QGeoPathPrivate(const QGeoPathPrivate &other) -: QGeoShapePrivate(QGeoShape::PathType), m_path(other.m_path), +: QGeoShapePrivate(other.type), 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) + m_maxLati(other.m_maxLati), m_bbox(other.m_bbox), m_width(other.m_width), m_clipperDirty(true) { } @@ -364,17 +375,25 @@ bool QGeoPathPrivate::operator==(const QGeoShapePrivate &other) const 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; + + if (type == QGeoShape::PathType) + return m_width == otherPath.m_width && m_path == otherPath.m_path; + else + return m_path == otherPath.m_path; } bool QGeoPathPrivate::isValid() const { - return !isEmpty(); + if (type == QGeoShape::PathType) + return !isEmpty(); + else + return m_path.size() > 2; + } bool QGeoPathPrivate::isEmpty() const { - return m_path.isEmpty(); + return m_path.isEmpty(); // this should perhaps return geometric emptiness, less than 2 points for line, or empty polygon for polygons } const QList<QGeoCoordinate> &QGeoPathPrivate::path() const @@ -405,6 +424,7 @@ void QGeoPathPrivate::setWidth(const qreal &width) double QGeoPathPrivate::length(int indexFrom, int indexTo) const { + bool wrap = indexTo == -1; if (indexTo < 0 || indexTo >= path().size()) indexTo = path().size() - 1; double len = 0.0; @@ -412,14 +432,29 @@ double QGeoPathPrivate::length(int indexFrom, int indexTo) const // 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]); + if (wrap) + len += m_path.last().distanceTo(m_path.first()); return len; } +int QGeoPathPrivate::size() const +{ + return m_path.size(); +} + /*! Returns true if coordinate is present in m_path. */ bool QGeoPathPrivate::contains(const QGeoCoordinate &coordinate) const { + if (type == QGeoShape::PathType) + return lineContains(coordinate); + else + return polygonContains(coordinate); +} + +bool QGeoPathPrivate::lineContains(const QGeoCoordinate &coordinate) const +{ // Unoptimized approach: // - consider each segment of the path // - project it into mercator space (rhumb lines are straight in mercator space) @@ -487,6 +522,20 @@ bool QGeoPathPrivate::contains(const QGeoCoordinate &coordinate) const return (m_path[0].distanceTo(coordinate) <= lineRadius); } +bool QGeoPathPrivate::polygonContains(const QGeoCoordinate &coordinate) const +{ + if (m_clipperDirty) + const_cast<QGeoPathPrivate *>(this)->updateClipperPath(); + + QDoubleVector2D coord = QWebMercator::coordToMercator(coordinate); + double tlx = QWebMercator::coordToMercator(m_bbox.topLeft()).x(); + if (coord.x() < tlx) + coord.setX(coord.x() + 1.0); + + IntPoint intCoord = QClipperUtils::toIntPoint(coord); + return c2t::clip2tri::pointInPolygon(intCoord, m_clipperPath) != 0; +} + QGeoCoordinate QGeoPathPrivate::center() const { return boundingGeoRectangle().center(); @@ -575,6 +624,7 @@ void QGeoPathPrivate::removeCoordinate(int index) void QGeoPathPrivate::computeBoundingBox() { + m_clipperDirty = true; if (m_path.isEmpty()) { m_deltaXs.clear(); m_minX = qInf(); @@ -625,6 +675,7 @@ void QGeoPathPrivate::computeBoundingBox() void QGeoPathPrivate::updateBoundingBox() { + m_clipperDirty = true; if (m_path.isEmpty()) { m_deltaXs.clear(); m_minX = qInf(); @@ -677,4 +728,18 @@ void QGeoPathPrivate::updateBoundingBox() QGeoCoordinate(m_minLati, currentMaxLongi)); } +void QGeoPathPrivate::updateClipperPath() +{ + m_clipperDirty = false; + double tlx = QWebMercator::coordToMercator(m_bbox.topLeft()).x(); + QList<QDoubleVector2D> preservedPath; + for (const QGeoCoordinate &c : m_path) { + QDoubleVector2D crd = QWebMercator::coordToMercator(c); + if (crd.x() < tlx) + crd.setX(crd.x() + 1.0); + preservedPath << crd; + } + m_clipperPath = QClipperUtils::qListToPath(preservedPath); +} + QT_END_NAMESPACE diff --git a/src/positioning/qgeopath.h b/src/positioning/qgeopath.h index 09a53a49..ad41c23c 100644 --- a/src/positioning/qgeopath.h +++ b/src/positioning/qgeopath.h @@ -78,6 +78,7 @@ public: 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 int size() 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); diff --git a/src/positioning/qgeopath_p.h b/src/positioning/qgeopath_p.h index 2256796d..3eceff24 100644 --- a/src/positioning/qgeopath_p.h +++ b/src/positioning/qgeopath_p.h @@ -54,6 +54,7 @@ #include "qgeoshape_p.h" #include "qgeocoordinate.h" #include "qlocationutils_p.h" +#include <QtPositioning/private/qclipperutils_p.h> #include <QtCore/QVector> @@ -62,14 +63,16 @@ QT_BEGIN_NAMESPACE class QGeoPathPrivate : public QGeoShapePrivate { public: - QGeoPathPrivate(); - QGeoPathPrivate(const QList<QGeoCoordinate> &path, const qreal width = 0.0); + QGeoPathPrivate(QGeoShape::ShapeType type); + QGeoPathPrivate(QGeoShape::ShapeType type, 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; + bool lineContains(const QGeoCoordinate &coordinate) const; + bool polygonContains(const QGeoCoordinate &coordinate) const; QGeoCoordinate center() const Q_DECL_OVERRIDE; QGeoRectangle boundingGeoRectangle() const Q_DECL_OVERRIDE; @@ -85,6 +88,7 @@ public: qreal width() const; void setWidth(const qreal &width); double length(int indexFrom, int indexTo) const; + int size() const; void addCoordinate(const QGeoCoordinate &coordinate); void insertCoordinate(int index, const QGeoCoordinate &coordinate); void replaceCoordinate(int index, const QGeoCoordinate &coordinate); @@ -94,7 +98,7 @@ public: void removeCoordinate(int index); void computeBoundingBox(); void updateBoundingBox(); - + void updateClipperPath(); QList<QGeoCoordinate> m_path; QVector<double> m_deltaXs; // longitude deltas from m_path[0] @@ -104,6 +108,8 @@ public: double m_maxLati; // minimum latitude. paths do not wrap around through the poles QGeoRectangle m_bbox; qreal m_width; + bool m_clipperDirty; + QtClipperLib::Path m_clipperPath; }; QT_END_NAMESPACE diff --git a/src/positioning/qgeopolygon.cpp b/src/positioning/qgeopolygon.cpp new file mode 100644 index 00000000..d817ea07 --- /dev/null +++ b/src/positioning/qgeopolygon.cpp @@ -0,0 +1,326 @@ +/**************************************************************************** +** +** 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 "qgeopolygon.h" +#include "qgeopath_p.h" + +#include "qgeocoordinate.h" +#include "qnumeric.h" +#include "qlocationutils_p.h" +#include "qwebmercator_p.h" + +#include "qdoublevector2d_p.h" +#include "qdoublevector3d_p.h" +#include "qwebmercator_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \class QGeoPolygon + \inmodule QtPositioning + \ingroup QtPositioning-positioning + \since 5.10 + + \brief The QGeoPolygon class defines a geographic polygon. + + The polygon is defined by an ordered list of QGeoCoordinates representing its perimeter. + + Each two adjacent elements in this list 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 date line in the longitudinal direction, + but never crosses the poles. + + This is relevant for the calculation of the bounding box returned by + \l QGeoShape::boundingGeoRectangle() 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 QGeoPolygon::path + \brief This property holds the list of coordinates for the geo polygon. + + The polygon is both invalid and empty if it contains no coordinate. + + A default constructed QGeoPolygon is therefore invalid. +*/ + +inline QGeoPolygonPrivate *QGeoPolygon::d_func() +{ + return static_cast<QGeoPolygonPrivate *>(d_ptr.data()); +} + +inline const QGeoPolygonPrivate *QGeoPolygon::d_func() const +{ + return static_cast<const QGeoPolygonPrivate *>(d_ptr.constData()); +} + +struct PolygonVariantConversions +{ + PolygonVariantConversions() + { + QMetaType::registerConverter<QGeoShape, QGeoPolygon>(); + QMetaType::registerConverter<QGeoPolygon, QGeoShape>(); + } +}; + +Q_GLOBAL_STATIC(PolygonVariantConversions, initPathConversions) + +/*! + Constructs a new, empty geo path. +*/ +QGeoPolygon::QGeoPolygon() +: QGeoShape(new QGeoPolygonPrivate(QGeoShape::PolygonType)) +{ + initPathConversions(); +} + +/*! + Constructs a new geo path from a list of coordinates + (\a path and \a width). +*/ +QGeoPolygon::QGeoPolygon(const QList<QGeoCoordinate> &path) +: QGeoShape(new QGeoPolygonPrivate(QGeoShape::PolygonType, path)) +{ + initPathConversions(); +} + +/*! + Constructs a new geo path from the contents of \a other. +*/ +QGeoPolygon::QGeoPolygon(const QGeoPolygon &other) +: QGeoShape(other) +{ + initPathConversions(); +} + +/*! + Constructs a new geo path from the contents of \a other. +*/ +QGeoPolygon::QGeoPolygon(const QGeoShape &other) +: QGeoShape(other) +{ + initPathConversions(); + if (type() != QGeoShape::PolygonType) + d_ptr = new QGeoPolygonPrivate(QGeoShape::PolygonType); +} + +/*! + Destroys this path. +*/ +QGeoPolygon::~QGeoPolygon() {} + +/*! + Assigns \a other to this geo path and returns a reference to this geo path. +*/ +QGeoPolygon &QGeoPolygon::operator=(const QGeoPolygon &other) +{ + QGeoShape::operator=(other); + return *this; +} + +/*! + Returns whether this geo path is equal to \a other. +*/ +bool QGeoPolygon::operator==(const QGeoPolygon &other) const +{ + Q_D(const QGeoPolygon); + return *d == *other.d_func(); +} + +/*! + Returns whether this geo path is not equal to \a other. +*/ +bool QGeoPolygon::operator!=(const QGeoPolygon &other) const +{ + Q_D(const QGeoPolygon); + return !(*d == *other.d_func()); +} + +void QGeoPolygon::setPath(const QList<QGeoCoordinate> &path) +{ + Q_D(QGeoPolygon); + return d->setPath(path); +} + +/*! + Returns all the elements. Equivalent to QGeoShape::center(). + The center coordinate, in case of a QGeoPolygon, is the center of its bounding box. +*/ +const QList<QGeoCoordinate> &QGeoPolygon::path() const +{ + Q_D(const QGeoPolygon); + return d->path(); +} + +/*! + 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 QGeoPolygon::translate(double degreesLatitude, double degreesLongitude) +{ + Q_D(QGeoPolygon); + d->translate(degreesLatitude, degreesLongitude); +} + +/*! + Returns a copy of this geo polygon 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() +*/ +QGeoPolygon QGeoPolygon::translated(double degreesLatitude, double degreesLongitude) const +{ + QGeoPolygon result(*this); + result.translate(degreesLatitude, degreesLongitude); + return result; +} + +/*! + Returns the length of the polygon's perimeter, 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 QGeoPolygon::length(int indexFrom, int indexTo) const +{ + Q_D(const QGeoPolygon); + return d->length(indexFrom, indexTo); +} + +/*! + Returns the number of elements in the polygon. + + \since 5.10 +*/ +int QGeoPolygon::size() const +{ + Q_D(const QGeoPolygon); + return d->size(); +} + +/*! + Appends \a coordinate to the polygon. +*/ +void QGeoPolygon::addCoordinate(const QGeoCoordinate &coordinate) +{ + Q_D(QGeoPolygon); + d->addCoordinate(coordinate); +} + +/*! + Inserts \a coordinate at the specified \a index. +*/ +void QGeoPolygon::insertCoordinate(int index, const QGeoCoordinate &coordinate) +{ + Q_D(QGeoPolygon); + d->insertCoordinate(index, coordinate); +} + +/*! + Replaces the path element at the specified \a index with \a coordinate. +*/ +void QGeoPolygon::replaceCoordinate(int index, const QGeoCoordinate &coordinate) +{ + Q_D(QGeoPolygon); + d->replaceCoordinate(index, coordinate); +} + +/*! + Returns the coordinate at \a index . +*/ +QGeoCoordinate QGeoPolygon::coordinateAt(int index) const +{ + Q_D(const QGeoPolygon); + return d->coordinateAt(index); +} + +/*! + Returns true if the polygon's perimeter contains \a coordinate as one of the elements. +*/ +bool QGeoPolygon::containsCoordinate(const QGeoCoordinate &coordinate) const +{ + Q_D(const QGeoPolygon); + return d->containsCoordinate(coordinate); +} + +/*! + Removes the last occurrence of \a coordinate from the polygon. +*/ +void QGeoPolygon::removeCoordinate(const QGeoCoordinate &coordinate) +{ + Q_D(QGeoPolygon); + d->removeCoordinate(coordinate); +} + +/*! + Removes element at position \a index from the polygon. +*/ +void QGeoPolygon::removeCoordinate(int index) +{ + Q_D(QGeoPolygon); + d->removeCoordinate(index); +} + +/*! + Returns the geo path properties as a string. +*/ +QString QGeoPolygon::toString() const +{ + if (type() != QGeoShape::PolygonType) { + qWarning("Not a polygon"); + return QStringLiteral("QGeoPolygon(not a polygon)"); + } + + QString pathString; + for (const auto &p : path()) + pathString += p.toString() + QLatin1Char(','); + + return QStringLiteral("QGeoPolygon([ %1 ])").arg(pathString); +} + +QT_END_NAMESPACE diff --git a/src/positioning/qgeopolygon.h b/src/positioning/qgeopolygon.h new file mode 100644 index 00000000..90886da7 --- /dev/null +++ b/src/positioning/qgeopolygon.h @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** 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 QGEOPOLYGON_H +#define QGEOPOLYGON_H + +#include <QtPositioning/QGeoShape> + +QT_BEGIN_NAMESPACE + +class QGeoCoordinate; +class QGeoPathPrivate; +typedef QGeoPathPrivate QGeoPolygonPrivate; + +class Q_POSITIONING_EXPORT QGeoPolygon : public QGeoShape +{ + Q_GADGET + +public: + QGeoPolygon(); + QGeoPolygon(const QList<QGeoCoordinate> &path); + QGeoPolygon(const QGeoPolygon &other); + QGeoPolygon(const QGeoShape &other); + + ~QGeoPolygon(); + + QGeoPolygon &operator=(const QGeoPolygon &other); + + using QGeoShape::operator==; + bool operator==(const QGeoPolygon &other) const; + + using QGeoShape::operator!=; + bool operator!=(const QGeoPolygon &other) const; + + void setPath(const QList<QGeoCoordinate> &path); + const QList<QGeoCoordinate> &path() const; + + Q_INVOKABLE void translate(double degreesLatitude, double degreesLongitude); + Q_INVOKABLE QGeoPolygon translated(double degreesLatitude, double degreesLongitude) const; + Q_INVOKABLE double length(int indexFrom = 0, int indexTo = -1) const; + Q_INVOKABLE int size() 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 QGeoPolygonPrivate *d_func(); + inline const QGeoPolygonPrivate *d_func() const; +}; + +Q_DECLARE_TYPEINFO(QGeoPolygon, Q_MOVABLE_TYPE); + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QGeoPolygon) + +#endif // QGEOPOLYGON_H diff --git a/src/positioning/qgeoshape.cpp b/src/positioning/qgeoshape.cpp index ad7b0c58..7acbc9fa 100644 --- a/src/positioning/qgeoshape.cpp +++ b/src/positioning/qgeoshape.cpp @@ -42,6 +42,7 @@ #include "qgeorectangle.h" #include "qgeocircle.h" #include "qgeopath.h" +#include "qgeopolygon.h" #ifndef QT_NO_DEBUG_STREAM @@ -345,6 +346,9 @@ QDebug operator<<(QDebug dbg, const QGeoShape &shape) case QGeoShape::PathType: dbg << "Path"; break; + case QGeoShape::PolygonType: + dbg << "Polygon"; + break; case QGeoShape::CircleType: dbg << "Circle"; } @@ -379,6 +383,13 @@ QDataStream &operator<<(QDataStream &stream, const QGeoShape &shape) stream << c; break; } + case QGeoShape::PolygonType: { + QGeoPolygon p = shape; + stream << p.path().size(); + for (const auto &c: p.path()) + stream << c; + break; + } } return stream; @@ -419,6 +430,18 @@ QDataStream &operator>>(QDataStream &stream, QGeoShape &shape) shape = QGeoPath(l); break; } + case QGeoShape::PolygonType: { + QList<QGeoCoordinate> l; + QGeoCoordinate c; + int sz; + stream >> sz; + for (int i = 0; i < sz; i++) { + stream >> c; + l.append(c); + } + shape = QGeoPolygon(l); + break; + } } return stream; diff --git a/src/positioning/qgeoshape.h b/src/positioning/qgeoshape.h index defd0eec..c0bc658b 100644 --- a/src/positioning/qgeoshape.h +++ b/src/positioning/qgeoshape.h @@ -66,7 +66,8 @@ public: UnknownType, RectangleType, CircleType, - PathType + PathType, + PolygonType }; ShapeType type() const; diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro index 5594b8b0..1229874a 100644 --- a/tests/auto/auto.pro +++ b/tests/auto/auto.pro @@ -62,9 +62,6 @@ qtHaveModule(location) { declarative_geoshape !mac: SUBDIRS += declarative_ui - - # QTBUG-60268 - boot2qt: SUBDIRS -= declarative_ui } } @@ -78,6 +75,7 @@ SUBDIRS += \ qgeorectangle \ qgeocircle \ qgeopath \ + qgeopolygon \ qgeocoordinate \ qgeolocation \ qgeopositioninfo \ diff --git a/tests/auto/declarative_ui/tst_map.qml b/tests/auto/declarative_ui/tst_map.qml index 8821f55e..f05b2c72 100644 --- a/tests/auto/declarative_ui/tst_map.qml +++ b/tests/auto/declarative_ui/tst_map.qml @@ -29,7 +29,7 @@ import QtQuick 2.0 import QtTest 1.0 import QtPositioning 5.5 -import QtLocation 5.9 +import QtLocation 5.10 import QtLocation.Test 5.6 Item { @@ -298,6 +298,8 @@ Item { //initial plugin values compare(map.minimumZoomLevel, 0) compare(map.maximumZoomLevel, 20) + compare(map.activeMapType.cameraCapabilities.minimumZoomLevel, 0) + compare(map.activeMapType.cameraCapabilities.maximumZoomLevel, 20) //Higher min level than curr zoom, should change curr zoom map.minimumZoomLevel = 5 @@ -321,6 +323,8 @@ Item { map.zoomLevel = 18 map.maximumZoomLevel = 16 compare(map.zoomLevel, 16) + compare(map.activeMapType.cameraCapabilities.minimumZoomLevel, 0) + compare(map.activeMapType.cameraCapabilities.maximumZoomLevel, 20) //reseting default map.minimumZoomLevel = 0 @@ -336,6 +340,8 @@ Item { //initial plugin values compare(map.minimumTilt, 0) compare(map.maximumTilt, 60) + compare(map.activeMapType.cameraCapabilities.minimumTilt, 0) + compare(map.activeMapType.cameraCapabilities.maximumTilt, 60) //Higher min level than curr tilt, should change curr tilt map.minimumTilt = 5 @@ -343,6 +349,9 @@ Item { compare(map.tilt, 5) compare(map.minimumTilt, 5) compare(map.maximumTilt, 18) + // Capabilities remain the same + compare(map.activeMapType.cameraCapabilities.minimumTilt, 0) + compare(map.activeMapType.cameraCapabilities.maximumTilt, 60) //Trying to set higher than max, max should be set. map.maximumTilt = 61 @@ -376,6 +385,8 @@ Item { //initial plugin values compare(map.minimumFieldOfView, 45) compare(map.maximumFieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.minimumFieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.maximumFieldOfView, 45) map.minimumFieldOfView = 5 map.maximumFieldOfView = 18 @@ -388,6 +399,8 @@ Item { // camera caps are [1-179], user previously asked for [5-18] compare(map.minimumFieldOfView, 5) compare(map.maximumFieldOfView, 18) + compare(map.activeMapType.cameraCapabilities.minimumFieldOfView, 1) + compare(map.activeMapType.cameraCapabilities.maximumFieldOfView, 179) map.fieldOfView = 4 compare(map.fieldOfView, 5) @@ -426,6 +439,8 @@ Item { compare(map.minimumFieldOfView, 45) compare(map.maximumFieldOfView, 45) compare(map.fieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.minimumFieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.maximumFieldOfView, 45) } function test_zoom() @@ -561,6 +576,59 @@ Item { compare(mapTiltBearing.tilt, 25.0) } + function test_map_setbearing() + { + var zeroCoord = QtPositioning.coordinate(0,0) + mapTiltBearing.bearing = 0.0 + mapTiltBearing.tilt = 0.0 + mapTiltBearing.zoomLevel = 3 + mapTiltBearing.center = zeroCoord + compare(mapTiltBearing.bearing, 0.0) + compare(mapTiltBearing.tilt, 0.0) + compare(mapTiltBearing.zoomLevel, 3) + compare(mapTiltBearing.center, zeroCoord) + + var fulcrum = QtPositioning.coordinate(20,-20) + var fulcrumPos = mapTiltBearing.fromCoordinate(fulcrum) + var bearing = 90.0 + mapTiltBearing.setBearing(bearing, fulcrum) + var fulcrumPosAfter = mapTiltBearing.fromCoordinate(fulcrum) + compare(mapTiltBearing.bearing, bearing) + compare(fulcrumPos, fulcrumPosAfter) + + // resetting + mapTiltBearing.center = coordinate1 + mapTiltBearing.zoomLevel = 4 + mapTiltBearing.bearing = 45.0 + mapTiltBearing.tilt = 25.0 + } + + function test_map_align_coordinate_to_point() + { + var zeroCoord = QtPositioning.coordinate(0,0) + mapTiltBearing.bearing = 0.0 + mapTiltBearing.tilt = 0.0 + mapTiltBearing.zoomLevel = 3 + mapTiltBearing.center = zeroCoord + compare(mapTiltBearing.bearing, 0.0) + compare(mapTiltBearing.tilt, 0.0) + compare(mapTiltBearing.zoomLevel, 3) + compare(mapTiltBearing.center, zeroCoord) + + var coord = QtPositioning.coordinate(20,-20) + var point = Qt.point(400, 400) + mapTiltBearing.alignCoordinateToPoint(coord, point) + var coordAfter = mapTiltBearing.toCoordinate(point) + compare(coord.latitude, coordAfter.latitude) + compare(coord.longitude, coordAfter.longitude) + + // resetting + mapTiltBearing.center = coordinate1 + mapTiltBearing.zoomLevel = 4 + mapTiltBearing.bearing = 45.0 + mapTiltBearing.tilt = 25.0 + } + function test_coordinate_conversion() { wait(1000) diff --git a/tests/auto/declarative_ui/tst_map_flick.qml b/tests/auto/declarative_ui/tst_map_flick.qml index c153411f..ba10d12e 100644 --- a/tests/auto/declarative_ui/tst_map_flick.qml +++ b/tests/auto/declarative_ui/tst_map_flick.qml @@ -170,7 +170,7 @@ Item { map.center.longitude = 11 mousePress(page, 0, 50) for (var i = 0; i < 50; i += 5) { - wait(20) + wait(25) mouseMove(page, 0, (50 + i), 0, Qt.LeftButton); } mouseRelease(page, 0, 100) @@ -207,7 +207,7 @@ Item { map.center.longitude = 11 mousePress(page, 10, 95) for (var i = 45; i > 0; i -= 5) { - wait(20) + wait(25) mouseMove(page, 10, (50 + i), 0, Qt.LeftButton); } mouseRelease(page, 10, 50) @@ -242,7 +242,7 @@ Item { mousePress(page, pos, pos) for (var i = pos; i < 50; i += 5) { pos = i - wait(20) + wait(25) mouseMove(page, pos, pos, 0, Qt.LeftButton); } mouseRelease(page, pos, pos) @@ -263,7 +263,7 @@ Item { map.center.longitude = 50 mousePress(page, 0, 0) for (var i = 0; i < 50; i += 5) { - wait(20) + wait(25) mouseMove(page, i, i, 0, Qt.LeftButton); } mouseRelease(page, 50, 50) @@ -290,7 +290,7 @@ Item { map.center.longitude = 50 mousePress(page, 0, 0) for (var i = 0; i < 50; i += 5) { - wait(20) + wait(25) mouseMove(page, i, i, 0, Qt.LeftButton); } mouseRelease(page, 50, 50) @@ -324,7 +324,7 @@ Item { map.center.longitude = 50 mousePress(page, 0, 0) for (var i = 0; i < 50; i += 5) { - wait(20) + wait(25) mouseMove(page, i, i, 0, Qt.LeftButton); } mouseRelease(page, 50, 50) diff --git a/tests/auto/declarative_ui/tst_map_item_details.qml b/tests/auto/declarative_ui/tst_map_item_details.qml index 80225c16..e7695288 100644 --- a/tests/auto/declarative_ui/tst_map_item_details.qml +++ b/tests/auto/declarative_ui/tst_map_item_details.qml @@ -157,6 +157,17 @@ Item { } MapPolyline { + id: polylineForSetpath + line.width: 3 + path: [ + { latitude: 20, longitude: 175 }, + { latitude: 20, longitude: -175 }, + { latitude: 10, longitude: -175 }, + { latitude: 10, longitude: 175 } + ] + } + + MapPolyline { id: extMapPolylineDateline line.width : 3 path: [ @@ -395,6 +406,33 @@ Item { verify(extMapPolyline.path.length == 0) } + function test_polyline_setpath() + { + compare (polylineForSetpath.line.width, 3.0) + verify(polylineForSetpath.path.length == 4) + compare(polylineForSetpath.path[0], QtPositioning.coordinate(20, 175)) + compare(polylineForSetpath.path[3], QtPositioning.coordinate(10, 175)) + + + var originalPath = QtPositioning.shapeToPath(polylineForSetpath.geoShape) + + var geoPath = QtPositioning.path([ { latitude: 20, longitude: -15 }, + { latitude: 20, longitude: -5 }, + { latitude: 10, longitude: -5 }, + { latitude: 10, longitude: -15 }, + { latitude: 10, longitude: -105 } ], 50) + + polylineForSetpath.setPath(geoPath) + verify(polylineForSetpath.path.length == 5) + compare(polylineForSetpath.path[0], QtPositioning.coordinate(20, -15)) + compare(polylineForSetpath.path[3], QtPositioning.coordinate(10, -15)) + + polylineForSetpath.setPath(originalPath) + verify(polylineForSetpath.path.length == 4) + compare(polylineForSetpath.path[0], QtPositioning.coordinate(20, 175)) + compare(polylineForSetpath.path[3], QtPositioning.coordinate(10, 175)) + } + /* (0,0) ---------------------------------------------------- (600,0) diff --git a/tests/auto/declarative_ui/tst_map_item_fit_viewport.qml b/tests/auto/declarative_ui/tst_map_item_fit_viewport.qml index adf9c347..8d1ee42b 100644 --- a/tests/auto/declarative_ui/tst_map_item_fit_viewport.qml +++ b/tests/auto/declarative_ui/tst_map_item_fit_viewport.qml @@ -572,13 +572,13 @@ Item { } function calculate_fit_circle_bounds() { - var circleDiagonal = Math.sqrt(2 * fitCircle.radius * fitCircle.radius) + var circleDiagonal = Math.sqrt(2) * fitCircle.radius fitCircleTopLeft = fitCircle.center.atDistanceAndAzimuth(circleDiagonal,-45) fitCircleBottomRight = fitCircle.center.atDistanceAndAzimuth(circleDiagonal,135) } function calculate_bounds(){ - var circleDiagonal = Math.sqrt(2 * preMapCircle.radius * preMapCircle.radius) + var circleDiagonal = Math.sqrt(2) * preMapCircle.radius var itemTopLeft = preMapCircle.center.atDistanceAndAzimuth(circleDiagonal,-45) var itemBottomRight = preMapCircle.center.atDistanceAndAzimuth(circleDiagonal,135) diff --git a/tests/auto/declarative_ui/tst_map_itemview.qml b/tests/auto/declarative_ui/tst_map_itemview.qml index bbd70c8e..ff24e7af 100644 --- a/tests/auto/declarative_ui/tst_map_itemview.qml +++ b/tests/auto/declarative_ui/tst_map_itemview.qml @@ -46,6 +46,35 @@ Item { && mapForTestingListModel.mapReady && mapForTestingRouteModel.mapReady + MapItemView { + id: routeItemViewExtra + model: routeModel + delegate: Component { + MapRoute { + route: routeData + } + } + } + + MapItemView { + id: listModelItemViewExtra + model: ListModel { + id: testingListModelExtra + ListElement { lat: 11; lon: 31 } + ListElement { lat: 12; lon: 32 } + ListElement { lat: 13; lon: 33 } + } + delegate: Component { + MapCircle { + radius: 1500000 + center { + latitude: lat + longitude: lon + } + } + } + } + Map { id: map objectName: 'staticallyDeclaredMap' @@ -432,6 +461,42 @@ Item { testingListModel.clear() compare(mapForTestingListModel.mapItems.length, 0) + + // Repopulating the model with initial data + testingListModel.append({ "lat": 11, "lon": 31 }) + testingListModel.append({ "lat": 12, "lon": 32 }) + testingListModel.append({ "lat": 13, "lon": 33 }) + } + + function test_add_extra_listmodel() { + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + mapForTestingListModel.addMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 6) + mapForTestingListModel.removeMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + mapForTestingListModel.addMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 6) + mapForTestingListModel.removeMapItemView(listModelItemView) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + mapForTestingListModel.removeMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 0) + mapForTestingListModel.addMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + testingListModelExtra.clear() + tryCompare(mapForTestingListModel, "mapItemsLength", 0) + mapForTestingListModel.removeMapItemView(listModelItemViewExtra) + + mapForTestingListModel.addMapItemView(listModelItemView) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) + + testingListModelExtra.append({ "lat": 11, "lon": 31 }) + testingListModelExtra.append({ "lat": 12, "lon": 32 }) + testingListModelExtra.append({ "lat": 13, "lon": 33 }) + + mapForTestingListModel.addMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 6) + mapForTestingListModel.removeMapItemView(listModelItemViewExtra) + tryCompare(mapForTestingListModel, "mapItemsLength", 3) } function test_routemodel() { @@ -451,6 +516,18 @@ Item { routeQuery.numberAlternativeRoutes = 3 routeModel.update(); tryCompare(mapForTestingRouteModel, "mapItemsLength", 3) + + // Test adding the extra mapitemview fed from the same route model + mapForTestingRouteModel.addMapItemView(routeItemViewExtra) + tryCompare(mapForTestingRouteModel, "mapItemsLength", 6) + routeQuery.numberAlternativeRoutes = 4 + routeModel.update(); + tryCompare(mapForTestingRouteModel, "mapItemsLength", 8) + routeQuery.numberAlternativeRoutes = 3 + routeModel.update(); + mapForTestingRouteModel.removeMapItemView(routeItemViewExtra) + tryCompare(mapForTestingRouteModel, "mapItemsLength", 3) + mapForTestingRouteModel.addMapItem(externalCircle2) compare(mapForTestingRouteModel.mapItems.length, 4) compare(mapForTestingRouteModel.mapItems[3], externalCircle2) diff --git a/tests/auto/declarative_ui/tst_map_maptype.qml b/tests/auto/declarative_ui/tst_map_maptype.qml index 1de30439..f4564ea6 100644 --- a/tests/auto/declarative_ui/tst_map_maptype.qml +++ b/tests/auto/declarative_ui/tst_map_maptype.qml @@ -28,7 +28,7 @@ import QtQuick 2.0 import QtTest 1.0 -import QtLocation 5.6 +import QtLocation 5.10 Item{ id: page @@ -122,6 +122,13 @@ Item{ compare(map.minimumFieldOfView, 45) compare(map.maximumFieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.minimumZoomLevel, 0) + compare(map.activeMapType.cameraCapabilities.maximumZoomLevel, 20) + compare(map.activeMapType.cameraCapabilities.minimumTilt, 0) + compare(map.activeMapType.cameraCapabilities.maximumTilt, 60) + compare(map.activeMapType.cameraCapabilities.minimumFieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.maximumFieldOfView, 45) + tryCompare(minimumZoomLevelChangedSpy, "count", 0) tryCompare(maximumZoomLevelChangedSpy, "count", 0) tryCompare(minimumTiltChangedSpy, "count", 0) @@ -139,6 +146,13 @@ Item{ compare(map.minimumFieldOfView, 45) compare(map.maximumFieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.minimumZoomLevel, 0) + compare(map.activeMapType.cameraCapabilities.maximumZoomLevel, 20) + compare(map.activeMapType.cameraCapabilities.minimumTilt, 0) + compare(map.activeMapType.cameraCapabilities.maximumTilt, 60) + compare(map.activeMapType.cameraCapabilities.minimumFieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.maximumFieldOfView, 45) + tryCompare(minimumZoomLevelChangedSpy, "count", 0) tryCompare(maximumZoomLevelChangedSpy, "count", 0) tryCompare(minimumTiltChangedSpy, "count", 0) @@ -156,6 +170,13 @@ Item{ compare(map.minimumFieldOfView, 1) compare(map.maximumFieldOfView, 179) + compare(map.activeMapType.cameraCapabilities.minimumZoomLevel, 0) + compare(map.activeMapType.cameraCapabilities.maximumZoomLevel, 19) + compare(map.activeMapType.cameraCapabilities.minimumTilt, 0) + compare(map.activeMapType.cameraCapabilities.maximumTilt, 80) + compare(map.activeMapType.cameraCapabilities.minimumFieldOfView, 1) + compare(map.activeMapType.cameraCapabilities.maximumFieldOfView, 179) + tryCompare(minimumZoomLevelChangedSpy, "count", 0) tryCompare(maximumZoomLevelChangedSpy, "count", 1) tryCompare(minimumTiltChangedSpy, "count", 0) @@ -173,13 +194,29 @@ Item{ compare(map.minimumFieldOfView, 45) compare(map.maximumFieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.minimumZoomLevel, 0) + compare(map.activeMapType.cameraCapabilities.maximumZoomLevel, 20) + compare(map.activeMapType.cameraCapabilities.minimumTilt, 0) + compare(map.activeMapType.cameraCapabilities.maximumTilt, 60) + compare(map.activeMapType.cameraCapabilities.minimumFieldOfView, 45) + compare(map.activeMapType.cameraCapabilities.maximumFieldOfView, 45) + tryCompare(minimumZoomLevelChangedSpy, "count", 0) tryCompare(maximumZoomLevelChangedSpy, "count", 2) tryCompare(minimumTiltChangedSpy, "count", 0) tryCompare(maximumTiltChangedSpy, "count", 2) tryCompare(minimumFieldOfViewChangedSpy, "count", 2) tryCompare(maximumFieldOfViewChangedSpy, "count", 2) + } + function test_maptype_metadata() + { + map.activeMapType = map.supportedMapTypes[0] + compare(Object.keys(map.activeMapType.metadata).length, 0) + + map.activeMapType = map.supportedMapTypes[3] + compare(Object.keys(map.activeMapType.metadata).length, 1) + compare(map.activeMapType.metadata['foo'], 42) } } } diff --git a/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h index 2fcf654d..297be0d5 100644 --- a/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h +++ b/tests/auto/geotestplugin/qgeotiledmappingmanagerengine_test.h @@ -64,14 +64,27 @@ public: const QByteArray pluginName = "qmlgeo.test.plugin"; QList<QGeoMapType> mapTypes; - mapTypes << QGeoMapType(QGeoMapType::StreetMap, tr("StreetMap"), tr("StreetMap"), false, false, 1, pluginName); - mapTypes << QGeoMapType(QGeoMapType::SatelliteMapDay, tr("SatelliteMapDay"), tr("SatelliteMapDay"), false, false, 2, pluginName); - mapTypes << QGeoMapType(QGeoMapType::CycleMap, tr("CycleMap"), tr("CycleMap"), false, false, 3, pluginName); - mapTypes << QGeoMapType(QGeoMapType::CustomMap, tr("AlternateCameraCapabilities"), tr("AlternateCameraCapabilities"), false, false, 4, pluginName); + + mapTypes << QGeoMapType(QGeoMapType::StreetMap, tr("StreetMap"), tr("StreetMap"), false, false, 1, pluginName, capabilities); + mapTypes << QGeoMapType(QGeoMapType::SatelliteMapDay, tr("SatelliteMapDay"), tr("SatelliteMapDay"), false, false, 2, pluginName, capabilities); + mapTypes << QGeoMapType(QGeoMapType::CycleMap, tr("CycleMap"), tr("CycleMap"), false, false, 3, pluginName, capabilities); + + QGeoCameraCapabilities capabilities4; + capabilities4.setMinimumZoomLevel(0.0); + capabilities4.setMaximumZoomLevel(19.0); + capabilities4.setSupportsBearing(true); + capabilities4.setSupportsTilting(true); + capabilities4.setMinimumTilt(0); + capabilities4.setMaximumTilt(80); + capabilities4.setMinimumFieldOfView(1); + capabilities4.setMaximumFieldOfView(179); + QVariantMap meta; + meta["foo"] = 42; + mapTypes << QGeoMapType(QGeoMapType::CustomMap, tr("AlternateCameraCapabilities"), tr("AlternateCameraCapabilities"), false, false, 4, pluginName, capabilities4, meta); if (parameters.contains(QStringLiteral("extraMapTypeName"))) { QString extraMapTypeName = parameters.value(QStringLiteral("extraMapTypeName")).toString(); - mapTypes << QGeoMapType(QGeoMapType::CustomMap, extraMapTypeName, extraMapTypeName, false, false, 5, pluginName); + mapTypes << QGeoMapType(QGeoMapType::CustomMap, extraMapTypeName, extraMapTypeName, false, false, 5, pluginName, capabilities); } setSupportedMapTypes(mapTypes); @@ -97,28 +110,6 @@ public: { return new QGeoTiledMapTest(this); } - - QGeoCameraCapabilities cameraCapabilities(int mapId) const Q_DECL_OVERRIDE - { - switch (mapId) { - case 4: - { - QGeoCameraCapabilities capabilities; - capabilities.setMinimumZoomLevel(0.0); - capabilities.setMaximumZoomLevel(19.0); - capabilities.setSupportsBearing(true); - capabilities.setSupportsTilting(true); - capabilities.setMinimumTilt(0); - capabilities.setMaximumTilt(80); - capabilities.setMinimumFieldOfView(1); - capabilities.setMaximumFieldOfView(179); - return capabilities; - } - default: - return QGeoMappingManagerEngine::cameraCapabilities(mapId); - } - } - }; #endif diff --git a/tests/auto/maptype/tst_maptype.cpp b/tests/auto/maptype/tst_maptype.cpp index 43d3175c..f571158e 100644 --- a/tests/auto/maptype/tst_maptype.cpp +++ b/tests/auto/maptype/tst_maptype.cpp @@ -28,6 +28,7 @@ #include <QtCore/QString> #include <QtTest/QtTest> +#include <QVariantMap> #include <QtLocation/private/qgeomaptype_p.h> @@ -52,9 +53,18 @@ tst_MapType::tst_MapType() {} void tst_MapType::constructorTest() { + QGeoCameraCapabilities capabilities; + capabilities.setMinimumZoomLevel(0.0); + capabilities.setMaximumZoomLevel(20.0); + capabilities.setSupportsBearing(true); + capabilities.setSupportsTilting(true); + capabilities.setMinimumTilt(0); + capabilities.setMaximumTilt(60); + capabilities.setMinimumFieldOfView(20); + capabilities.setMaximumFieldOfView(90); const QByteArray pluginName = "tst_MapType"; QGeoMapType *testObjPtr = new QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street map"), - QStringLiteral("map description"), true, true, 1, pluginName); + QStringLiteral("map description"), true, true, 1, pluginName, capabilities); QVERIFY(testObjPtr); QCOMPARE(testObjPtr->style(), QGeoMapType::StreetMap); QCOMPARE(testObjPtr->name(), QStringLiteral("street map")); @@ -63,6 +73,8 @@ void tst_MapType::constructorTest() QVERIFY(testObjPtr->night()); QCOMPARE(testObjPtr->mapId(), 1); QCOMPARE(testObjPtr->pluginName(), pluginName); + QCOMPARE(testObjPtr->cameraCapabilities(), capabilities); + QCOMPARE(testObjPtr->metadata(), QVariantMap()); delete testObjPtr; testObjPtr = new QGeoMapType(); @@ -73,6 +85,7 @@ void tst_MapType::constructorTest() QVERIFY2(!testObjPtr->night(), "Wrong default value"); QCOMPARE(testObjPtr->mapId(), 0); QCOMPARE(testObjPtr->pluginName(), QByteArrayLiteral("")); + QCOMPARE(testObjPtr->cameraCapabilities(), QGeoCameraCapabilities()); delete testObjPtr; } @@ -83,57 +96,82 @@ void tst_MapType::comparison_data() QTest::addColumn<bool>("expected"); const QByteArray pluginName = "tst_MapType"; + QGeoCameraCapabilities capabilities; + capabilities.setMinimumZoomLevel(0.0); + capabilities.setMaximumZoomLevel(20.0); + capabilities.setSupportsBearing(true); + capabilities.setSupportsTilting(true); + capabilities.setMinimumTilt(0); + capabilities.setMaximumTilt(60); + capabilities.setMinimumFieldOfView(20); + capabilities.setMaximumFieldOfView(90); + QGeoCameraCapabilities capabilities2 = capabilities; + capabilities2.setMaximumFieldOfView(80); QTest::newRow("null") << QGeoMapType() << QGeoMapType() << true; QTest::newRow("equal") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << true; QTest::newRow("style") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << QGeoMapType(QGeoMapType::TerrainMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << false; QTest::newRow("name") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("different name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << false; QTest::newRow("description") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("different desc"), false, false, 42, pluginName) + QStringLiteral("different desc"), false, false, 42, pluginName, capabilities) << false; QTest::newRow("mobile") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), true, false, 42, pluginName) + QStringLiteral("street desc"), true, false, 42, pluginName, capabilities) << false; QTest::newRow("night") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, true, 42, pluginName) + QStringLiteral("street desc"), false, true, 42, pluginName, capabilities) << false; QTest::newRow("id") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 99, pluginName) + QStringLiteral("street desc"), false, false, 99, pluginName, capabilities) << false; QTest::newRow("plugin_name") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, pluginName) + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), - QStringLiteral("street desc"), false, false, 42, QByteArrayLiteral("abc")) + QStringLiteral("street desc"), false, false, 42, QByteArrayLiteral("abc"), capabilities) + << false; + + QTest::newRow("camera_capabilities") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) + << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities2) + << false; + + QVariantMap metadata; + metadata["foo"] = 42; + QTest::newRow("metadata") << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities) + << QGeoMapType(QGeoMapType::StreetMap, QStringLiteral("street name"), + QStringLiteral("street desc"), false, false, 42, pluginName, capabilities, metadata) << false; } diff --git a/tests/auto/nokia_services/routing/tst_routing.cpp b/tests/auto/nokia_services/routing/tst_routing.cpp index c214556f..833c95af 100644 --- a/tests/auto/nokia_services/routing/tst_routing.cpp +++ b/tests/auto/nokia_services/routing/tst_routing.cpp @@ -234,7 +234,8 @@ void tst_nokia_routing::calculateRoute() m_routingManager->calculateRoute(m_dummyRequest); m_replyUnowned->complete(); m_replyUnowned = 0; - QTRY_VERIFY_WITH_TIMEOUT(m_calculationDone, 100); + // Timeout of 200ms is required for slow targets (e.g. Qemu) + QTRY_VERIFY_WITH_TIMEOUT(m_calculationDone, 200); } void tst_nokia_routing::onReply(QGeoRouteReply* reply) diff --git a/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp b/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp index 75c1eecb..4cd83446 100644 --- a/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp +++ b/tests/auto/qgeoareamonitor/tst_qgeoareamonitor.cpp @@ -720,14 +720,14 @@ private slots: QGeoAreaMonitorInfo info; QTest::newRow("uninitialized") << info << 45 << QString("QGeoAreaMonitorInfo(\"\", QGeoShape(Unknown), " - "persistent: false, expiry: QDateTime( Qt::TimeSpec(LocalTime))) 45"); + "persistent: false, expiry: QDateTime(Invalid)) 45"); info.setArea(QGeoRectangle()); info.setPersistent(true); info.setName("RectangleAreaMonitor"); QTest::newRow("Rectangle Test") << info << 45 << QString("QGeoAreaMonitorInfo(\"RectangleAreaMonitor\", QGeoShape(Rectangle), " - "persistent: true, expiry: QDateTime( Qt::TimeSpec(LocalTime))) 45"); + "persistent: true, expiry: QDateTime(Invalid)) 45"); info = QGeoAreaMonitorInfo(); info.setArea(QGeoCircle()); @@ -738,7 +738,7 @@ private slots: info.setNotificationParameters(map); QTest::newRow("Circle Test") << info << 45 << QString("QGeoAreaMonitorInfo(\"CircleAreaMonitor\", QGeoShape(Circle), " - "persistent: false, expiry: QDateTime( Qt::TimeSpec(LocalTime))) 45"); + "persistent: false, expiry: QDateTime(Invalid)) 45"); // we ignore any further QDateTime related changes to avoid depending on QDateTime related // failures in case its QDebug string changes diff --git a/tests/auto/qgeocameratiles/tst_qgeocameratiles.cpp b/tests/auto/qgeocameratiles/tst_qgeocameratiles.cpp index 0c664ba6..49c4657e 100644 --- a/tests/auto/qgeocameratiles/tst_qgeocameratiles.cpp +++ b/tests/auto/qgeocameratiles/tst_qgeocameratiles.cpp @@ -150,7 +150,7 @@ void tst_QGeoCameraTiles::tilesPlugin() ct.setTileSize(16); ct.setCameraData(camera); ct.setScreenSize(QSize(32, 32)); - ct.setMapType(QGeoMapType(QGeoMapType::StreetMap, "street map", "street map", false, false, 1, QByteArrayLiteral(""))); + ct.setMapType(QGeoMapType(QGeoMapType::StreetMap, "street map", "street map", false, false, 1, QByteArrayLiteral(""), QGeoCameraCapabilities())); QSet<QGeoTileSpec> tiles1 = ct.createTiles(); @@ -202,7 +202,7 @@ void tst_QGeoCameraTiles::tilesMapType() QSet<QGeoTileSpec> tiles1 = ct.createTiles(); - QGeoMapType mapType1 = QGeoMapType(QGeoMapType::StreetMap, "street map", "street map", false, false, 1, QByteArrayLiteral("")); + QGeoMapType mapType1 = QGeoMapType(QGeoMapType::StreetMap, "street map", "street map", false, false, 1, QByteArrayLiteral(""), QGeoCameraCapabilities()); ct.setMapType(mapType1); QSet<QGeoTileSpec> tiles2 = ct.createTiles(); @@ -220,7 +220,7 @@ void tst_QGeoCameraTiles::tilesMapType() QCOMPARE(tiles2, tiles2_check); - QGeoMapType mapType2 = QGeoMapType(QGeoMapType::StreetMap, "satellite map", "satellite map", false, false, 2, QByteArrayLiteral("")); + QGeoMapType mapType2 = QGeoMapType(QGeoMapType::StreetMap, "satellite map", "satellite map", false, false, 2, QByteArrayLiteral(""), QGeoCameraCapabilities()); ct.setMapType(mapType2); QSet<QGeoTileSpec> tiles3 = ct.createTiles(); diff --git a/tests/auto/qgeopath/tst_qgeopath.cpp b/tests/auto/qgeopath/tst_qgeopath.cpp index 9244394a..86ff137d 100644 --- a/tests/auto/qgeopath/tst_qgeopath.cpp +++ b/tests/auto/qgeopath/tst_qgeopath.cpp @@ -47,6 +47,7 @@ private slots: void path(); void width(); + void size(); void translate_data(); void translate(); @@ -188,6 +189,32 @@ void tst_QGeoPath::width() QCOMPARE(p.width(), qreal(10.0)); } +void tst_QGeoPath::size() +{ + QList<QGeoCoordinate> coords; + + QGeoPath p1(coords, 3); + QCOMPARE(p1.size(), coords.size()); + + coords.append(QGeoCoordinate(1,1)); + QGeoPath p2(coords, 3); + QCOMPARE(p2.size(), coords.size()); + + coords.append(QGeoCoordinate(2,2)); + QGeoPath p3(coords, 3); + QCOMPARE(p3.size(), coords.size()); + + coords.append(QGeoCoordinate(3,0)); + QGeoPath p4(coords, 3); + QCOMPARE(p4.size(), coords.size()); + + p4.removeCoordinate(2); + QCOMPARE(p4.size(), coords.size() - 1); + + p4.removeCoordinate(coords.first()); + QCOMPARE(p4.size(), coords.size() - 2); +} + void tst_QGeoPath::translate_data() { QTest::addColumn<QGeoCoordinate>("c1"); diff --git a/tests/auto/qgeopolygon/qgeopolygon.pro b/tests/auto/qgeopolygon/qgeopolygon.pro new file mode 100644 index 00000000..f6314ca4 --- /dev/null +++ b/tests/auto/qgeopolygon/qgeopolygon.pro @@ -0,0 +1,8 @@ +TEMPLATE = app +CONFIG += testcase +TARGET = tst_qgeopolygon + +SOURCES += \ + tst_qgeopolygon.cpp + +QT += positioning testlib diff --git a/tests/auto/qgeopolygon/tst_qgeopolygon.cpp b/tests/auto/qgeopolygon/tst_qgeopolygon.cpp new file mode 100644 index 00000000..12e39f0f --- /dev/null +++ b/tests/auto/qgeopolygon/tst_qgeopolygon.cpp @@ -0,0 +1,402 @@ +/**************************************************************************** +** +** 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/QGeoPolygon> + +QT_USE_NAMESPACE + +class tst_QGeoPolygon : public QObject +{ + Q_OBJECT + +private slots: + void defaultConstructor(); + void listConstructor(); + void assignment(); + + void comparison(); + void type(); + + void path(); + void size(); + + 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_QGeoPolygon::defaultConstructor() +{ + QGeoPolygon p; + QVERIFY(!p.path().size()); + QVERIFY(!p.size()); + QVERIFY(!p.isValid()); + QVERIFY(p.isEmpty()); +} + +void tst_QGeoPolygon::listConstructor() +{ + QList<QGeoCoordinate> coords; + coords.append(QGeoCoordinate(1,1)); + coords.append(QGeoCoordinate(2,2)); + QGeoPolygon p2(coords); + QCOMPARE(p2.path().size(), 2); + QCOMPARE(p2.size(), 2); + QVERIFY(!p2.isValid()); // a polygon can't have only 2 coords + QVERIFY(!p2.isEmpty()); + + coords.append(QGeoCoordinate(3,0)); + + QGeoPolygon p(coords); + QCOMPARE(p.path().size(), 3); + QCOMPARE(p.size(), 3); + QVERIFY(p.isValid()); + QVERIFY(!p.isEmpty()); + + + for (const QGeoCoordinate &c : coords) { + QCOMPARE(p.path().contains(c), true); + QCOMPARE(p.containsCoordinate(c), true); + } +} + +void tst_QGeoPolygon::assignment() +{ + QGeoPolygon p1; + QList<QGeoCoordinate> coords; + coords.append(QGeoCoordinate(1,1)); + coords.append(QGeoCoordinate(2,2)); + coords.append(QGeoCoordinate(3,0)); + QGeoPolygon p2(coords); + + QVERIFY(p1 != p2); + + p1 = p2; + QCOMPARE(p1.path(), coords); + 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 polygon + QGeoPolygon p3 = area; + QCOMPARE(p3.path(), coords); + QVERIFY(p3 == p1); + + // Check that the copy is not modified when modifying the original. + p1.addCoordinate(QGeoCoordinate(4,0)); + QVERIFY(p3 != p1); +} + +void tst_QGeoPolygon::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)); + QGeoPolygon c1(coords); + QGeoPolygon c2(coords); + QGeoPolygon c3(coords2); + + QVERIFY(c1 == c2); + QVERIFY(!(c1 != c2)); + + QVERIFY(!(c1 == c3)); + QVERIFY(c1 != c3); + + 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_QGeoPolygon::type() +{ + QGeoPolygon c; + QCOMPARE(c.type(), QGeoShape::PolygonType); +} + +void tst_QGeoPolygon::path() +{ + QList<QGeoCoordinate> coords; + coords.append(QGeoCoordinate(1,1)); + coords.append(QGeoCoordinate(2,2)); + coords.append(QGeoCoordinate(3,0)); + + QGeoPolygon p; + p.setPath(coords); + QCOMPARE(p.path().size(), 3); + QCOMPARE(p.size(), 3); + + for (const QGeoCoordinate &c : coords) { + QCOMPARE(p.path().contains(c), true); + QCOMPARE(p.containsCoordinate(c), true); + } +} + +void tst_QGeoPolygon::size() +{ + QList<QGeoCoordinate> coords; + + QGeoPolygon p1(coords); + QCOMPARE(p1.size(), coords.size()); + + coords.append(QGeoCoordinate(1,1)); + QGeoPolygon p2(coords); + QCOMPARE(p2.size(), coords.size()); + + coords.append(QGeoCoordinate(2,2)); + QGeoPolygon p3(coords); + QCOMPARE(p3.size(), coords.size()); + + coords.append(QGeoCoordinate(3,0)); + QGeoPolygon p4(coords); + QCOMPARE(p4.size(), coords.size()); + + p4.removeCoordinate(2); + QCOMPARE(p4.size(), coords.size() - 1); + + p4.removeCoordinate(coords.first()); + QCOMPARE(p4.size(), coords.size() - 2); +} + +void tst_QGeoPolygon::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_QGeoPolygon::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); + QGeoPolygon 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_QGeoPolygon::valid_data() +{ + QTest::addColumn<QGeoCoordinate>("c1"); + QTest::addColumn<QGeoCoordinate>("c2"); + QTest::addColumn<QGeoCoordinate>("c3"); + QTest::addColumn<bool>("valid"); + + QTest::newRow("empty coords") << QGeoCoordinate() << QGeoCoordinate() << QGeoCoordinate() << false; + QTest::newRow("invalid coord") << QGeoCoordinate(50, 50) << QGeoCoordinate(60, 60) << QGeoCoordinate(700, 700) << false; + QTest::newRow("good") << QGeoCoordinate(10, 10) << QGeoCoordinate(11, 11) << QGeoCoordinate(10, 12) << true; +} + +void tst_QGeoPolygon::valid() +{ + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(QGeoCoordinate, c3); + QFETCH(bool, valid); + + QList<QGeoCoordinate> coords; + coords.append(c1); + coords.append(c2); + coords.append(c3); + QGeoPolygon p(coords); + + QCOMPARE(p.isValid(), valid); + + QGeoShape area = p; + QCOMPARE(area.isValid(), valid); +} + +void tst_QGeoPolygon::contains_data() +{ + QTest::addColumn<QGeoCoordinate>("c1"); + QTest::addColumn<QGeoCoordinate>("c2"); + QTest::addColumn<QGeoCoordinate>("c3"); + 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] << QGeoCoordinate(2, 2) << true; + QTest::newRow("Not so far away") << c[0] << c[1] << c[2] << QGeoCoordinate(0.8, 0.8) << false; + QTest::newRow("Not so far away and large line") << c[0] << c[1] << c[2] << QGeoCoordinate(0.8, 0.8) << false; + QTest::newRow("Inside") << c[0] << c[1] << c[2] << QGeoCoordinate(2.0, 1.0) << true; +} + +void tst_QGeoPolygon::contains() +{ + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(QGeoCoordinate, c3); + QFETCH(QGeoCoordinate, probe); + QFETCH(bool, result); + + QList<QGeoCoordinate> coords; + coords.append(c1); + coords.append(c2); + coords.append(c3); + QGeoPolygon p(coords); + + QCOMPARE(p.contains(probe), result); + + QGeoShape area = p; + QCOMPARE(area.contains(probe), result); +} + +void tst_QGeoPolygon::boundingGeoRectangle_data() +{ + QTest::addColumn<QGeoCoordinate>("c1"); + QTest::addColumn<QGeoCoordinate>("c2"); + QTest::addColumn<QGeoCoordinate>("c3"); + 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] << QGeoCoordinate(2, 2) << true; + QTest::newRow("Not so far away") << c[0] << c[1] << c[2] << QGeoCoordinate(0, 0) << false; + QTest::newRow("Inside the bounds") << c[0] << c[1] << c[2] << QGeoCoordinate(1, 0) << true; + QTest::newRow("Inside the bounds") << c[0] << c[1] << c[2] << QGeoCoordinate(1.1, 0.1) << true; +} + +void tst_QGeoPolygon::boundingGeoRectangle() +{ + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(QGeoCoordinate, c3); + QFETCH(QGeoCoordinate, probe); + QFETCH(bool, result); + + QList<QGeoCoordinate> coords; + coords.append(c1); + coords.append(c2); + coords.append(c3); + QGeoPolygon p(coords); + + QGeoRectangle box = p.boundingGeoRectangle(); + QCOMPARE(box.contains(probe), result); +} + +void tst_QGeoPolygon::extendShape() +{ + QFETCH(QGeoCoordinate, c1); + QFETCH(QGeoCoordinate, c2); + QFETCH(QGeoCoordinate, c3); + QFETCH(QGeoCoordinate, probe); + QFETCH(bool, before); + QFETCH(bool, after); + + QList<QGeoCoordinate> coords; + coords.append(c1); + coords.append(c2); + coords.append(c3); + QGeoPolygon p(coords); + + + QCOMPARE(p.contains(probe), before); + p.extendShape(probe); + QCOMPARE(p.contains(probe), after); +} + +void tst_QGeoPolygon::extendShape_data() +{ + QTest::addColumn<QGeoCoordinate>("c1"); + QTest::addColumn<QGeoCoordinate>("c2"); + QTest::addColumn<QGeoCoordinate>("c3"); + 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] << QGeoCoordinate(2, 2) << true << true; + QTest::newRow("Not so far away") << c[0] << c[1] << c[2] << QGeoCoordinate(0, 0) << false << true; + QTest::newRow("Contained point") << c[0] << c[1] << c[2] << QGeoCoordinate(2.0, 1.0) << true << true; +} + +QTEST_MAIN(tst_QGeoPolygon) +#include "tst_qgeopolygon.moc" diff --git a/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp b/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp index ae0083ba..14b40eb6 100644 --- a/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp +++ b/tests/auto/qgeotiledmap/tst_qgeotiledmap.cpp @@ -113,6 +113,7 @@ void tst_QGeoTiledMap::initTestCase() m_map.reset(static_cast<QGeoTiledMapTest*>(mappingManager->createMap(this))); QVERIFY(m_map); m_map->setViewportSize(QSize(256, 256)); + m_map->setActiveMapType(m_map->m_engine->supportedMapTypes().first()); m_fetcher = static_cast<QGeoTileFetcherTest*>(m_map->m_engine->tileFetcher()); m_tilesCounter.reset(new FetchTileCounter()); connect(m_fetcher, SIGNAL(tileFetched(const QGeoTileSpec&)), m_tilesCounter.data(), SLOT(tileFetched(const QGeoTileSpec&))); @@ -133,6 +134,8 @@ void tst_QGeoTiledMap::fetchTiles() //prev_visible camera.setZoomLevel(zoomLevel-1); + // Delay needed on slow targets (e.g. Qemu) + QTest::qWait(10); m_map->clearData(); m_tilesCounter->m_tiles.clear(); m_map->setCameraData(camera); @@ -141,6 +144,8 @@ void tst_QGeoTiledMap::fetchTiles() //visible + prefetch camera.setZoomLevel(zoomLevel); + // Delay needed on slow targets (e.g. Qemu) + QTest::qWait(10); m_map->clearData(); m_tilesCounter->m_tiles.clear(); m_map->setCameraData(camera); @@ -154,6 +159,8 @@ void tst_QGeoTiledMap::fetchTiles() //next visible camera.setZoomLevel(zoomLevel + 1); + // Delay needed on slow targets (e.g. Qemu) + QTest::qWait(10); m_map->clearData(); m_tilesCounter->m_tiles.clear(); m_map->setCameraData(camera); diff --git a/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel.cpp b/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel.cpp index e0004596..939225a7 100644 --- a/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel.cpp +++ b/tests/plugins/declarativetestplugin/qdeclarativelocationtestmodel.cpp @@ -41,8 +41,6 @@ QDeclarativeLocationTestModel::QDeclarativeLocationTestModel(QObject *parent): crazyLevel_(0), crazyMode_(false) { - // seed crazy random generator - qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid()); timer_.setSingleShot(true); connect(&timer_, SIGNAL(timeout()), this, SLOT(timerFired())); } @@ -63,7 +61,7 @@ void QDeclarativeLocationTestModel::timerFired() repopulate(); if (crazyMode_) { //qDebug() << "raw randomw value: " << qrand(); - int delay = (qAbs(qrand()) % crazyLevel_); // writing software is exact science + int delay = (QRandomGenerator::global()->bounded(uint(INT_MAX) + 1) % crazyLevel_); // writing software is exact science delay = qMax(1000, delay); // 3 ms at minimum qDebug() << "starting timer with : " << delay; timer_.start(delay); @@ -164,7 +162,7 @@ void QDeclarativeLocationTestModel::repopulate() } int datacount = datacount_; if (crazyMode_) - datacount = (qAbs(qrand()) % datacount_); + datacount = QRandomGenerator::global()->bounded(datacount_); for (int i = 0; i < datacount; ++i) { DataObject* dataobject = new DataObject; @@ -206,7 +204,7 @@ void QDeclarativeLocationTestModel::scheduleRepopulation() if (crazyMode_) { // start generating arbitrary amount of data at arbitrary intervals - int delay = (qAbs(qrand()) % crazyLevel_); // writing software is exact science + int delay = QRandomGenerator::global()->bounded(crazyLevel_); // writing software is exact science delay = qMax(3, delay); // 3 ms at minimum qDebug() << "starting timer with : " << delay; timer_.start(delay); |