diff options
Diffstat (limited to 'src')
55 files changed, 1117 insertions, 163 deletions
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 9ecbe3642fb4a53b558598239b59bf1d0224c25 +Subproject c53896caefc96a8c18ab746026330ddc4fc0338 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 dedb590e..37cfc303 100644 --- a/src/location/declarativemaps/qdeclarativegeomap.cpp +++ b/src/location/declarativemaps/qdeclarativegeomap.cpp @@ -190,7 +190,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 +222,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 +766,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); } } @@ -1454,6 +1473,57 @@ 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. + + \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. + + \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 +1966,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}. 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 a17bf672..d8c19528 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 33a984d6..fc2debc3 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/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 013a8c33..218d806b 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 */ @@ -566,6 +577,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/geoservices.pro b/src/plugins/geoservices/geoservices.pro index 459897a8..07c34798 100644 --- a/src/plugins/geoservices/geoservices.pro +++ b/src/plugins/geoservices/geoservices.pro @@ -7,7 +7,7 @@ qtConfig(concurrent) { } qtConfig(opengl):qtConfig(c++14):!win32|mingw:!qnx { - !exists(../../3rdparty/mapbox-gl-native/CMakeLists.txt) { + !exists(../../3rdparty/mapbox-gl-native/mapbox-gl-native.pro) { warning("Submodule mapbox-gl-native does not exist. Run 'git submodule update --init' on qtlocation.") } else { SUBDIRS += mapboxgl ../../3rdparty/mapbox-gl-native 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 3b9026ce..c82b98f3 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp +++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp @@ -425,7 +425,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..9fa8f695 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp +++ b/src/plugins/geoservices/mapboxgl/qgeomappingmanagerenginemapboxgl.cpp @@ -70,25 +70,25 @@ 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); + tr("Dark"), false, false, ++mapId, pluginName, cameraCaps); mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/traffic-day-v1"), - tr("Streets Traffic Day"), false, false, ++mapId, pluginName); + tr("Streets Traffic Day"), false, false, ++mapId, pluginName, cameraCaps); mapTypes << QGeoMapType(QGeoMapType::TransitMap, QStringLiteral("mapbox://styles/mapbox/traffic-night-v1"), - tr("Streets Traffic Night"), false, true, ++mapId, pluginName); + tr("Streets Traffic 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 +99,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/mapboxgl/qmapboxglstylechange.cpp b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp index c6972b07..f79f0a38 100644 --- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp +++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp @@ -54,7 +54,7 @@ QString formatPropertyName(QString *name) bool isImmutableProperty(const QString &name) { - return name == QStringLiteral("type") || name == QStringLiteral("layer") || name == QStringLiteral("class"); + return name == QStringLiteral("type") || name == QStringLiteral("layer"); } QString getId(QDeclarativeGeoMapItemBase *mapItem) @@ -288,7 +288,7 @@ QMapboxGLStyleSetPaintProperty::QMapboxGLStyleSetPaintProperty(const QString& la void QMapboxGLStyleSetPaintProperty::apply(QMapboxGL *map) { - map->setPaintProperty(m_layer, m_property, m_value, m_class); + map->setPaintProperty(m_layer, m_property, m_value); } QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::fromMapParameter(QGeoMapParameter *param) @@ -313,7 +313,6 @@ QList<QSharedPointer<QMapboxGLStyleChange>> QMapboxGLStyleSetPaintProperty::from paint->m_layer = param->property("layer").toString(); paint->m_property = formatPropertyName(&name); - paint->m_class = param->property("class").toString(); changes << QSharedPointer<QMapboxGLStyleChange>(paint); } @@ -399,15 +398,30 @@ QSharedPointer<QMapboxGLStyleChange> QMapboxGLStyleAddLayer::fromMapParameter(QG Q_ASSERT(param->type() == "layer"); auto layer = new QMapboxGLStyleAddLayer(); - layer->m_params[QStringLiteral("id")] = param->property("name"); - layer->m_params[QStringLiteral("source")] = param->property("source"); - layer->m_params[QStringLiteral("type")] = param->property("layerType"); - if (param->property("sourceLayer").isValid()) { - layer->m_params[QStringLiteral("source-layer")] = param->property("sourceLayer"); - } + static const QStringList layerProperties = QStringList() + << QStringLiteral("name") << QStringLiteral("layerType") << QStringLiteral("before"); - layer->m_before = param->property("before").toString(); + // Offset objectName and type properties. + for (int i = 2; i < param->metaObject()->propertyCount(); ++i) { + QString name = param->metaObject()->property(i).name(); + QVariant value = param->property(name.toLatin1()); + + switch (layerProperties.indexOf(name)) { + case -1: + layer->m_params[formatPropertyName(&name)] = value; + break; + case 0: // name + layer->m_params[QStringLiteral("id")] = value; + break; + case 1: // layerType + layer->m_params[QStringLiteral("type")] = value; + break; + case 2: // before + layer->m_before = value.toString(); + break; + } + } return QSharedPointer<QMapboxGLStyleChange>(layer); } diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h index 9164591a..aa81d89f 100644 --- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h +++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange_p.h @@ -102,7 +102,6 @@ private: QString m_layer; QString m_property; QVariant m_value; - QString m_class; }; class QMapboxGLStyleAddLayer : public QMapboxGLStyleChange 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..f36a6694 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::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 da7b61d2..3f0062c0 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, @@ -351,16 +351,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 563ac161..95e5d44b 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..e79e64d5 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::get32(); } 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::get32(); } while (idToSatSource()->contains(key)); idToSatSource()->insert(key, src); diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro index 32f3c05c..974a8d48 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 += \ @@ -59,6 +60,7 @@ PRIVATE_HEADERS += \ qlocationdata_simulator_p.h \ qdoublematrix4x4_p.h \ qgeopath_p.h \ + qgeopolygon_p.h \ qclipperutils_p.h SOURCES += \ @@ -82,6 +84,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; |