From 2dc1acb63777c983cfc4cbdbd2176a8dab112209 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 25 Jul 2017 13:29:22 +0300 Subject: Send raw QEvents to map Change-Id: I09622d5e47812782727f7ebeb64e23f15e315315 Reviewed-by: Paolo Angelelli --- .../declarativemaps/qquickgeomapgesturearea.cpp | 31 ++++++++++++++++++++++ src/location/maps/qgeomap.cpp | 15 +++++++++++ src/location/maps/qgeomap_p.h | 2 ++ 3 files changed, 48 insertions(+) diff --git a/src/location/declarativemaps/qquickgeomapgesturearea.cpp b/src/location/declarativemaps/qquickgeomapgesturearea.cpp index fc2debc3..99b65766 100644 --- a/src/location/declarativemaps/qquickgeomapgesturearea.cpp +++ b/src/location/declarativemaps/qquickgeomapgesturearea.cpp @@ -509,6 +509,7 @@ void QQuickGeoMapGestureArea::setMap(QGeoMap *map) m_flick.m_animation->setProperty(QStringLiteral("center")); m_flick.m_animation->setEasing(QEasingCurve(QEasingCurve::OutQuad)); connect(m_flick.m_animation, &QQuickAbstractAnimation::stopped, this, &QQuickGeoMapGestureArea::handleFlickAnimationStopped); + m_map->setAcceptedGestures(panEnabled(), flickEnabled(), pinchEnabled(), rotationEnabled(), tiltEnabled()); } /*! @@ -583,6 +584,9 @@ void QQuickGeoMapGestureArea::setAcceptedGestures(AcceptedGestures acceptedGestu setTiltEnabled(acceptedGestures & TiltGesture); } + if (m_map) + m_map->setAcceptedGestures(panEnabled(), flickEnabled(), pinchEnabled(), rotationEnabled(), tiltEnabled()); + emit acceptedGesturesChanged(); } @@ -648,6 +652,8 @@ void QQuickGeoMapGestureArea::setEnabled(bool enabled) setRotationEnabled(false); setTiltEnabled(false); } + if (m_map) + m_map->setAcceptedGestures(panEnabled(), flickEnabled(), pinchEnabled(), rotationEnabled(), tiltEnabled()); emit enabledChanged(); } @@ -857,6 +863,11 @@ QTouchEvent::TouchPoint* createTouchPointFromMouseEvent(QMouseEvent *event, Qt:: */ void QQuickGeoMapGestureArea::handleMousePressEvent(QMouseEvent *event) { + if (m_map && m_map->handleEvent(event)) { + event->accept(); + return; + } + m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointPressed)); if (m_touchPoints.isEmpty()) update(); event->accept(); @@ -867,6 +878,11 @@ void QQuickGeoMapGestureArea::handleMousePressEvent(QMouseEvent *event) */ void QQuickGeoMapGestureArea::handleMouseMoveEvent(QMouseEvent *event) { + if (m_map && m_map->handleEvent(event)) { + event->accept(); + return; + } + m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointMoved)); if (m_touchPoints.isEmpty()) update(); event->accept(); @@ -877,6 +893,11 @@ void QQuickGeoMapGestureArea::handleMouseMoveEvent(QMouseEvent *event) */ void QQuickGeoMapGestureArea::handleMouseReleaseEvent(QMouseEvent *event) { + if (m_map && m_map->handleEvent(event)) { + event->accept(); + return; + } + if (!m_mousePoint.isNull()) { //this looks super ugly , however is required in case we do not get synthesized MouseReleaseEvent //and we reset the point already in handleTouchUngrabEvent @@ -917,6 +938,11 @@ void QQuickGeoMapGestureArea::handleTouchUngrabEvent() */ void QQuickGeoMapGestureArea::handleTouchEvent(QTouchEvent *event) { + if (m_map && m_map->handleEvent(event)) { + event->accept(); + return; + } + m_touchPoints.clear(); m_mousePoint.reset(); @@ -938,6 +964,11 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) if (!m_map) return; + if (m_map->handleEvent(event)) { + event->accept(); + return; + } + const QGeoCoordinate &wheelGeoPos = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(event->posF()), false); const QPointF &preZoomPoint = event->posF(); diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index 0c6ce0a7..f9a72d14 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -98,6 +98,12 @@ void QGeoMap::setCameraCapabilities(const QGeoCameraCapabilities &cameraCapabili d->setCameraCapabilities(cameraCapabilities); } +bool QGeoMap::handleEvent(QEvent *event) +{ + Q_UNUSED(event) + return false; +} + QGeoCameraData QGeoMap::cameraData() const { Q_D(const QGeoMap); @@ -230,6 +236,15 @@ QString QGeoMap::copyrightsStyleSheet() const return QStringLiteral("#copyright-root { background: rgba(255, 255, 255, 128) }"); } +void QGeoMap::setAcceptedGestures(bool pan, bool flick, bool pinch, bool rotate, bool tilt) +{ + Q_UNUSED(pan) + Q_UNUSED(flick) + Q_UNUSED(pinch) + Q_UNUSED(rotate) + Q_UNUSED(tilt) +} + QGeoMapPrivate::QGeoMapPrivate(QGeoMappingManagerEngine *engine, QGeoProjection *geoProjection) : QObjectPrivate(), m_geoProjection(geoProjection), diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h index bb7ade55..40d520fe 100644 --- a/src/location/maps/qgeomap_p.h +++ b/src/location/maps/qgeomap_p.h @@ -123,6 +123,8 @@ public: void clearMapItems(); virtual QString copyrightsStyleSheet() const; + virtual void setAcceptedGestures(bool pan, bool flick, bool pinch, bool rotate, bool tilt); + virtual bool handleEvent(QEvent *event); protected: QGeoMap(QGeoMapPrivate &dd, QObject *parent = 0); -- cgit v1.2.3 From 8ac6377e62af803b567449cdf30c669b92114cc4 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Tue, 25 Jul 2017 17:11:32 +0200 Subject: Make QGeoRoute extensible This change makes it possible to subclass QGeoRoute, QGeoRouteSegment or QGeoRouteManeuver, with custom private implementations. It also attempts to minimize the cost that creating a QDeclarativeGeoRoute currently has, by deferring the initialization of QDeclarativeGeoRoute::segments_ to the first access, and also populating the list only to the requested point. Change-Id: I4c87391bcc380ddca6523c748ebb97d2a44ed9d2 Reviewed-by: BogDan Vatra --- .../declarativemaps/qdeclarativegeoroute.cpp | 53 +++- .../declarativemaps/qdeclarativegeoroute_p.h | 5 +- src/location/maps/qgeomaneuver.cpp | 280 ++++++++++++++++--- src/location/maps/qgeomaneuver.h | 4 +- src/location/maps/qgeomaneuver_p.h | 84 +++++- src/location/maps/qgeoroute.cpp | 301 ++++++++++++++++++--- src/location/maps/qgeoroute.h | 4 +- src/location/maps/qgeoroute_p.h | 89 +++++- src/location/maps/qgeoroutesegment.cpp | 212 ++++++++++++--- src/location/maps/qgeoroutesegment.h | 3 +- src/location/maps/qgeoroutesegment_p.h | 66 ++++- tests/auto/declarative_core/tst_routing.qml | 96 ++++--- .../geotestplugin/qgeoroutingmanagerengine_test.h | 29 +- 13 files changed, 1018 insertions(+), 208 deletions(-) diff --git a/src/location/declarativemaps/qdeclarativegeoroute.cpp b/src/location/declarativemaps/qdeclarativegeoroute.cpp index 039b1297..5540263c 100644 --- a/src/location/declarativemaps/qdeclarativegeoroute.cpp +++ b/src/location/declarativemaps/qdeclarativegeoroute.cpp @@ -37,6 +37,7 @@ #include "qdeclarativegeoroute_p.h" #include "locationvaluetypehelper_p.h" #include +#include #include #include @@ -77,29 +78,37 @@ QT_BEGIN_NAMESPACE */ QDeclarativeGeoRoute::QDeclarativeGeoRoute(QObject *parent) - : QObject(parent) + : QObject(parent), segmentsDirty_(true) { - this->init(); } QDeclarativeGeoRoute::QDeclarativeGeoRoute(const QGeoRoute &route, QObject *parent) - : QObject(parent), - route_(route) + : QObject(parent), route_(route), segmentsDirty_(true) { - this->init(); } QDeclarativeGeoRoute::~QDeclarativeGeoRoute() {} -void QDeclarativeGeoRoute::init() +void QDeclarativeGeoRoute::initSegments(unsigned int lastIndex) // -1 turns it into unsigned int max { + if (!segmentsDirty_) + return; + QGeoRouteSegment segment = route_.firstRouteSegment(); + unsigned int idx = 0; + unsigned int initialListSize = static_cast(segments_.size()); while (segment.isValid()) { - QDeclarativeGeoRouteSegment *routeSegment = new QDeclarativeGeoRouteSegment(segment, this); - QQmlEngine::setContextForObject(routeSegment, QQmlEngine::contextForObject(this)); - segments_.append(routeSegment); + if (idx >= initialListSize) { + QDeclarativeGeoRouteSegment *routeSegment = new QDeclarativeGeoRouteSegment(segment, this); + QQmlEngine::setContextForObject(routeSegment, QQmlEngine::contextForObject(this)); + segments_.append(routeSegment); + } + ++idx; segment = segment.nextRouteSegment(); + if (idx > lastIndex && segment.isValid()) // Do not clean segmentsDirty_ if there are still segments to initialize + return; } + segmentsDirty_ = false; } /*! @@ -229,7 +238,9 @@ QQmlListProperty QDeclarativeGeoRoute::segments() void QDeclarativeGeoRoute::segments_append(QQmlListProperty *prop, QDeclarativeGeoRouteSegment *segment) { - static_cast(prop->object)->appendSegment(segment); + QDeclarativeGeoRoute *declRoute = static_cast(prop->object); + declRoute->initSegments(); + declRoute->appendSegment(segment); } /*! @@ -237,7 +248,8 @@ void QDeclarativeGeoRoute::segments_append(QQmlListProperty *prop) { - return static_cast(prop->object)->segments_.count(); + QDeclarativeGeoRoute *declRoute = static_cast(prop->object); + return declRoute->segmentsCount(); } /*! @@ -245,7 +257,9 @@ int QDeclarativeGeoRoute::segments_count(QQmlListProperty *prop, int index) { - return static_cast(prop->object)->segments_.at(index); + QDeclarativeGeoRoute *declRoute = static_cast(prop->object); + declRoute->initSegments(index); // init only what's needed. + return declRoute->segments_.at(index); } /*! @@ -272,4 +286,19 @@ void QDeclarativeGeoRoute::clearSegments() segments_.clear(); } +/*! + \qmlmethod int QtLocation::Route::segmentsCount() + + Returns the number of segments in the route + + \sa RouteSegment + + \since 5.11 +*/ + +int QDeclarativeGeoRoute::segmentsCount() const +{ + return qMax(route_.d_ptr->segmentsCount(), segments_.count()); +} + QT_END_NAMESPACE diff --git a/src/location/declarativemaps/qdeclarativegeoroute_p.h b/src/location/declarativemaps/qdeclarativegeoroute_p.h index e4501770..738d2089 100644 --- a/src/location/declarativemaps/qdeclarativegeoroute_p.h +++ b/src/location/declarativemaps/qdeclarativegeoroute_p.h @@ -84,6 +84,8 @@ public: void appendSegment(QDeclarativeGeoRouteSegment *segment); void clearSegments(); + int segmentsCount() const; + Q_SIGNALS: void pathChanged(); @@ -93,11 +95,12 @@ private: static QDeclarativeGeoRouteSegment *segments_at(QQmlListProperty *prop, int index); static void segments_clear(QQmlListProperty *prop); - void init(); + void initSegments(unsigned int lastIndex = -1); QList routePath(); QGeoRoute route_; QList segments_; + bool segmentsDirty_; friend class QDeclarativeRouteMapItem; }; diff --git a/src/location/maps/qgeomaneuver.cpp b/src/location/maps/qgeomaneuver.cpp index f38cb293..78efb971 100644 --- a/src/location/maps/qgeomaneuver.cpp +++ b/src/location/maps/qgeomaneuver.cpp @@ -115,7 +115,7 @@ The instruction indicates that the direction of travel should bear to the left. setWaypoint() is called. */ QGeoManeuver::QGeoManeuver() - : d_ptr(new QGeoManeuverPrivate()) {} + : d_ptr(new QGeoManeuverPrivateDefault()) {} /*! Constructs a maneuver object from the contents of \a other. @@ -165,7 +165,7 @@ bool QGeoManeuver::operator!= (const QGeoManeuver &other) const */ bool QGeoManeuver::isValid() const { - return d_ptr->valid; + return d_ptr->valid(); } /*! @@ -174,8 +174,8 @@ bool QGeoManeuver::isValid() const */ void QGeoManeuver::setPosition(const QGeoCoordinate &position) { - d_ptr->valid = true; - d_ptr->position = position; + d_ptr->setValid(true); + d_ptr->setPosition(position); } /*! @@ -183,7 +183,7 @@ void QGeoManeuver::setPosition(const QGeoCoordinate &position) */ QGeoCoordinate QGeoManeuver::position() const { - return d_ptr->position; + return d_ptr->position(); } /*! @@ -191,8 +191,8 @@ QGeoCoordinate QGeoManeuver::position() const */ void QGeoManeuver::setInstructionText(const QString &instructionText) { - d_ptr->valid = true; - d_ptr->text = instructionText; + d_ptr->setValid(true); + d_ptr->setText(instructionText); } /*! @@ -200,7 +200,7 @@ void QGeoManeuver::setInstructionText(const QString &instructionText) */ QString QGeoManeuver::instructionText() const { - return d_ptr->text; + return d_ptr->text(); } /*! @@ -209,8 +209,8 @@ QString QGeoManeuver::instructionText() const */ void QGeoManeuver::setDirection(QGeoManeuver::InstructionDirection direction) { - d_ptr->valid = true; - d_ptr->direction = direction; + d_ptr->setValid(true); + d_ptr->setDirection(direction); } /*! @@ -218,7 +218,7 @@ void QGeoManeuver::setDirection(QGeoManeuver::InstructionDirection direction) */ QGeoManeuver::InstructionDirection QGeoManeuver::direction() const { - return d_ptr->direction; + return d_ptr->direction(); } /*! @@ -228,8 +228,8 @@ QGeoManeuver::InstructionDirection QGeoManeuver::direction() const */ void QGeoManeuver::setTimeToNextInstruction(int secs) { - d_ptr->valid = true; - d_ptr->timeToNextInstruction = secs; + d_ptr->setValid(true); + d_ptr->setTimeToNextInstruction(secs); } /*! @@ -239,7 +239,7 @@ void QGeoManeuver::setTimeToNextInstruction(int secs) */ int QGeoManeuver::timeToNextInstruction() const { - return d_ptr->timeToNextInstruction; + return d_ptr->timeToNextInstruction(); } /*! @@ -249,8 +249,8 @@ int QGeoManeuver::timeToNextInstruction() const */ void QGeoManeuver::setDistanceToNextInstruction(qreal distance) { - d_ptr->valid = true; - d_ptr->distanceToNextInstruction = distance; + d_ptr->setValid(true); + d_ptr->setDistanceToNextInstruction(distance); } /*! @@ -260,7 +260,7 @@ void QGeoManeuver::setDistanceToNextInstruction(qreal distance) */ qreal QGeoManeuver::distanceToNextInstruction() const { - return d_ptr->distanceToNextInstruction; + return d_ptr->distanceToNextInstruction(); } /*! @@ -268,8 +268,8 @@ qreal QGeoManeuver::distanceToNextInstruction() const */ void QGeoManeuver::setWaypoint(const QGeoCoordinate &coordinate) { - d_ptr->valid = true; - d_ptr->waypoint = coordinate; + d_ptr->setValid(true); + d_ptr->setWaypoint(coordinate); } /*! @@ -280,39 +280,231 @@ void QGeoManeuver::setWaypoint(const QGeoCoordinate &coordinate) */ QGeoCoordinate QGeoManeuver::waypoint() const { - return d_ptr->waypoint; + return d_ptr->waypoint(); } +QGeoManeuver::QGeoManeuver(const QSharedDataPointer &dd) + : d_ptr(dd) {} + + /******************************************************************************* *******************************************************************************/ QGeoManeuverPrivate::QGeoManeuverPrivate() - : valid(false), - direction(QGeoManeuver::NoDirection), - timeToNextInstruction(0), - distanceToNextInstruction(0.0) {} +{ + +} QGeoManeuverPrivate::QGeoManeuverPrivate(const QGeoManeuverPrivate &other) - : QSharedData(other), - valid(other.valid), - position(other.position), - text(other.text), - direction(other.direction), - timeToNextInstruction(other.timeToNextInstruction), - distanceToNextInstruction(other.distanceToNextInstruction), - waypoint(other.waypoint) {} - -QGeoManeuverPrivate::~QGeoManeuverPrivate() {} - -bool QGeoManeuverPrivate::operator ==(const QGeoManeuverPrivate &other) const -{ - return ((valid == other.valid) - && (position == other.position) - && (text == other.text) - && (direction == other.direction) - && (timeToNextInstruction == other.timeToNextInstruction) - && (distanceToNextInstruction == other.distanceToNextInstruction) - && (waypoint == other.waypoint)); + : QSharedData(other) +{ + +} + +QGeoManeuverPrivate::~QGeoManeuverPrivate() +{ + +} + +bool QGeoManeuverPrivate::operator==(const QGeoManeuverPrivate &other) const +{ + return ((valid() == other.valid()) + && (position() == other.position()) + && (text() == other.text()) + && (direction() == other.direction()) + && (timeToNextInstruction() == other.timeToNextInstruction()) + && (distanceToNextInstruction() == other.distanceToNextInstruction()) + && (waypoint() == other.waypoint())); +} + +bool QGeoManeuverPrivate::valid() const +{ + return false; +} + +void QGeoManeuverPrivate::setValid(bool valid) +{ + Q_UNUSED(valid) +} + +QString QGeoManeuverPrivate::id() const +{ + return QString(); +} + +void QGeoManeuverPrivate::setId(const QString id) +{ + Q_UNUSED(id) +} + +QGeoCoordinate QGeoManeuverPrivate::position() const +{ + return QGeoCoordinate(); +} + +void QGeoManeuverPrivate::setPosition(const QGeoCoordinate &position) +{ + Q_UNUSED(position) +} + +QString QGeoManeuverPrivate::text() const +{ + return QString(); +} + +void QGeoManeuverPrivate::setText(const QString &text) +{ + Q_UNUSED(text) +} + +QGeoManeuver::InstructionDirection QGeoManeuverPrivate::direction() const +{ + return QGeoManeuver::NoDirection; +} + +void QGeoManeuverPrivate::setDirection(QGeoManeuver::InstructionDirection direction) +{ + Q_UNUSED(direction) +} + +int QGeoManeuverPrivate::timeToNextInstruction() const +{ + return 0; +} + +void QGeoManeuverPrivate::setTimeToNextInstruction(int timeToNextInstruction) +{ + Q_UNUSED(timeToNextInstruction) +} + +qreal QGeoManeuverPrivate::distanceToNextInstruction() const +{ + return 0; +} + +void QGeoManeuverPrivate::setDistanceToNextInstruction(qreal distanceToNextInstruction) +{ + Q_UNUSED(distanceToNextInstruction) +} + +QGeoCoordinate QGeoManeuverPrivate::waypoint() const +{ + return QGeoCoordinate(); +} + +void QGeoManeuverPrivate::setWaypoint(const QGeoCoordinate &waypoint) +{ + Q_UNUSED(waypoint) +} + + + +/******************************************************************************* +*******************************************************************************/ + +QGeoManeuverPrivateDefault::QGeoManeuverPrivateDefault() + : m_valid(false), + m_direction(QGeoManeuver::NoDirection), + m_timeToNextInstruction(0), + m_distanceToNextInstruction(0.0) {} + +QGeoManeuverPrivateDefault::QGeoManeuverPrivateDefault(const QGeoManeuverPrivateDefault &other) + : QGeoManeuverPrivate(other), + m_valid(other.m_valid), + m_position(other.m_position), + m_text(other.m_text), + m_direction(other.m_direction), + m_timeToNextInstruction(other.m_timeToNextInstruction), + m_distanceToNextInstruction(other.m_distanceToNextInstruction), + m_waypoint(other.m_waypoint) {} + +QGeoManeuverPrivateDefault::~QGeoManeuverPrivateDefault() {} + + + +bool QGeoManeuverPrivateDefault::operator ==(const QGeoManeuverPrivateDefault &other) const +{ + return QGeoManeuverPrivateDefault::operator ==(other); +} + +bool QGeoManeuverPrivateDefault::valid() const +{ + return m_valid; +} + +void QGeoManeuverPrivateDefault::setValid(bool valid) +{ + m_valid = valid; +} + +QString QGeoManeuverPrivateDefault::id() const +{ + return m_id; +} + +void QGeoManeuverPrivateDefault::setId(const QString id) +{ + m_id = id; +} + +QGeoCoordinate QGeoManeuverPrivateDefault::position() const +{ + return m_position; +} + +void QGeoManeuverPrivateDefault::setPosition(const QGeoCoordinate &position) +{ + m_position = position; +} + +QString QGeoManeuverPrivateDefault::text() const +{ + return m_text; +} + +void QGeoManeuverPrivateDefault::setText(const QString &text) +{ + m_text = text; +} + +QGeoManeuver::InstructionDirection QGeoManeuverPrivateDefault::direction() const +{ + return m_direction; +} + +void QGeoManeuverPrivateDefault::setDirection(QGeoManeuver::InstructionDirection direction) +{ + m_direction = direction; +} + +int QGeoManeuverPrivateDefault::timeToNextInstruction() const +{ + return m_timeToNextInstruction; +} + +void QGeoManeuverPrivateDefault::setTimeToNextInstruction(int timeToNextInstruction) +{ + m_timeToNextInstruction = timeToNextInstruction; +} + +qreal QGeoManeuverPrivateDefault::distanceToNextInstruction() const +{ + return m_distanceToNextInstruction; +} + +void QGeoManeuverPrivateDefault::setDistanceToNextInstruction(qreal distanceToNextInstruction) +{ + m_distanceToNextInstruction = distanceToNextInstruction; +} + +QGeoCoordinate QGeoManeuverPrivateDefault::waypoint() const +{ + return m_waypoint; +} + +void QGeoManeuverPrivateDefault::setWaypoint(const QGeoCoordinate &waypoint) +{ + m_waypoint = waypoint; } QT_END_NAMESPACE diff --git a/src/location/maps/qgeomaneuver.h b/src/location/maps/qgeomaneuver.h index 9710f8fc..1e4bff24 100644 --- a/src/location/maps/qgeomaneuver.h +++ b/src/location/maps/qgeomaneuver.h @@ -95,7 +95,9 @@ public: void setWaypoint(const QGeoCoordinate &coordinate); QGeoCoordinate waypoint() const; -private: +protected: + QGeoManeuver(const QSharedDataPointer &dd); + QSharedDataPointer d_ptr; }; diff --git a/src/location/maps/qgeomaneuver_p.h b/src/location/maps/qgeomaneuver_p.h index c048f132..484354ba 100644 --- a/src/location/maps/qgeomaneuver_p.h +++ b/src/location/maps/qgeomaneuver_p.h @@ -48,31 +48,91 @@ // We mean it. // -#include "qgeomaneuver.h" -#include "qgeocoordinate.h" +#include +#include +#include #include #include QT_BEGIN_NAMESPACE -class QGeoManeuverPrivate : public QSharedData +class Q_LOCATION_PRIVATE_EXPORT QGeoManeuverPrivate : public QSharedData { public: QGeoManeuverPrivate(); QGeoManeuverPrivate(const QGeoManeuverPrivate &other); - ~QGeoManeuverPrivate(); + virtual ~QGeoManeuverPrivate(); bool operator== (const QGeoManeuverPrivate &other) const; - bool valid; - QString id; - QGeoCoordinate position; - QString text; - QGeoManeuver::InstructionDirection direction; - int timeToNextInstruction; - qreal distanceToNextInstruction; - QGeoCoordinate waypoint; + virtual bool valid() const; + virtual void setValid(bool valid); + + virtual QString id() const; + virtual void setId(const QString id); + + virtual QGeoCoordinate position() const; + virtual void setPosition(const QGeoCoordinate &position); + + virtual QString text() const; + virtual void setText(const QString &text); + + virtual QGeoManeuver::InstructionDirection direction() const; + virtual void setDirection(QGeoManeuver::InstructionDirection direction); + + virtual int timeToNextInstruction() const; + virtual void setTimeToNextInstruction(int timeToNextInstruction); + + virtual qreal distanceToNextInstruction() const; + virtual void setDistanceToNextInstruction(qreal distanceToNextInstruction); + + virtual QGeoCoordinate waypoint() const; + virtual void setWaypoint(const QGeoCoordinate &waypoint); + +}; + +class Q_LOCATION_PRIVATE_EXPORT QGeoManeuverPrivateDefault : public QGeoManeuverPrivate +{ +public: + QGeoManeuverPrivateDefault(); + QGeoManeuverPrivateDefault(const QGeoManeuverPrivateDefault &other); + ~QGeoManeuverPrivateDefault(); + + bool operator== (const QGeoManeuverPrivateDefault &other) const; + + virtual bool valid() const override; + virtual void setValid(bool valid) override; + + virtual QString id() const override; + virtual void setId(const QString id) override; + + virtual QGeoCoordinate position() const override; + virtual void setPosition(const QGeoCoordinate &position) override; + + virtual QString text() const override; + virtual void setText(const QString &text) override; + + virtual QGeoManeuver::InstructionDirection direction() const override; + virtual void setDirection(QGeoManeuver::InstructionDirection direction) override; + + virtual int timeToNextInstruction() const override; + virtual void setTimeToNextInstruction(int timeToNextInstruction) override; + + virtual qreal distanceToNextInstruction() const override; + virtual void setDistanceToNextInstruction(qreal distanceToNextInstruction) override; + + virtual QGeoCoordinate waypoint() const override; + virtual void setWaypoint(const QGeoCoordinate &waypoint) override; + + bool m_valid; + QString m_id; + QGeoCoordinate m_position; + QString m_text; + QGeoManeuver::InstructionDirection m_direction; + int m_timeToNextInstruction; + qreal m_distanceToNextInstruction; + QGeoCoordinate m_waypoint; }; QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroute.cpp b/src/location/maps/qgeoroute.cpp index facf1949..95603218 100644 --- a/src/location/maps/qgeoroute.cpp +++ b/src/location/maps/qgeoroute.cpp @@ -71,7 +71,14 @@ QT_BEGIN_NAMESPACE Constructs a route object. */ QGeoRoute::QGeoRoute() - : d_ptr(new QGeoRoutePrivate()) {} + : d_ptr(new QGeoRoutePrivateDefault()) {} + +/*! + Constructs a route object using dd as private implementation. +*/ +QGeoRoute::QGeoRoute(const QExplicitlySharedDataPointer &dd): d_ptr(dd) +{ +} /*! Constructs a route object from the contents of \a other. @@ -104,7 +111,8 @@ QGeoRoute &QGeoRoute::operator= (const QGeoRoute & other) */ bool QGeoRoute::operator ==(const QGeoRoute &other) const { - return (*d_ptr.constData() == *other.d_ptr.constData()); + return ( (d_ptr.constData() == other.d_ptr.constData()) + || (*d_ptr) == (*other.d_ptr)); } /*! @@ -112,7 +120,7 @@ bool QGeoRoute::operator ==(const QGeoRoute &other) const */ bool QGeoRoute::operator !=(const QGeoRoute &other) const { - return !(*d_ptr.constData() == *other.d_ptr.constData()); + return !(operator==(other)); } /*! @@ -124,7 +132,7 @@ bool QGeoRoute::operator !=(const QGeoRoute &other) const */ void QGeoRoute::setRouteId(const QString &id) { - d_ptr->id = id; + d_ptr->setId(id); } /*! @@ -136,7 +144,7 @@ void QGeoRoute::setRouteId(const QString &id) */ QString QGeoRoute::routeId() const { - return d_ptr->id; + return d_ptr->id(); } /*! @@ -145,7 +153,7 @@ QString QGeoRoute::routeId() const */ void QGeoRoute::setRequest(const QGeoRouteRequest &request) { - d_ptr->request = request; + d_ptr->setRequest(request); } /*! @@ -154,7 +162,7 @@ void QGeoRoute::setRequest(const QGeoRouteRequest &request) */ QGeoRouteRequest QGeoRoute::request() const { - return d_ptr->request; + return d_ptr->request(); } /*! @@ -162,7 +170,7 @@ QGeoRouteRequest QGeoRoute::request() const */ void QGeoRoute::setBounds(const QGeoRectangle &bounds) { - d_ptr->bounds = bounds; + d_ptr->setBounds(bounds); } /*! @@ -170,7 +178,7 @@ void QGeoRoute::setBounds(const QGeoRectangle &bounds) */ QGeoRectangle QGeoRoute::bounds() const { - return d_ptr->bounds; + return d_ptr->bounds(); } /*! @@ -178,7 +186,7 @@ QGeoRectangle QGeoRoute::bounds() const */ void QGeoRoute::setFirstRouteSegment(const QGeoRouteSegment &routeSegment) { - d_ptr->firstSegment = routeSegment; + d_ptr->setFirstSegment(routeSegment); } /*! @@ -192,7 +200,7 @@ void QGeoRoute::setFirstRouteSegment(const QGeoRouteSegment &routeSegment) */ QGeoRouteSegment QGeoRoute::firstRouteSegment() const { - return d_ptr->firstSegment; + return d_ptr->firstSegment(); } /*! @@ -201,7 +209,7 @@ QGeoRouteSegment QGeoRoute::firstRouteSegment() const */ void QGeoRoute::setTravelTime(int secs) { - d_ptr->travelTime = secs; + d_ptr->setTravelTime(secs); } /*! @@ -210,7 +218,7 @@ void QGeoRoute::setTravelTime(int secs) */ int QGeoRoute::travelTime() const { - return d_ptr->travelTime; + return d_ptr->travelTime(); } /*! @@ -218,7 +226,7 @@ int QGeoRoute::travelTime() const */ void QGeoRoute::setDistance(qreal distance) { - d_ptr->distance = distance; + d_ptr->setDistance(distance); } /*! @@ -226,7 +234,7 @@ void QGeoRoute::setDistance(qreal distance) */ qreal QGeoRoute::distance() const { - return d_ptr->distance; + return d_ptr->distance(); } /*! @@ -236,7 +244,7 @@ qreal QGeoRoute::distance() const */ void QGeoRoute::setTravelMode(QGeoRouteRequest::TravelMode mode) { - d_ptr->travelMode = mode; + d_ptr->setTravelMode(mode); } /*! @@ -246,7 +254,7 @@ void QGeoRoute::setTravelMode(QGeoRouteRequest::TravelMode mode) */ QGeoRouteRequest::TravelMode QGeoRoute::travelMode() const { - return d_ptr->travelMode; + return d_ptr->travelMode(); } /*! @@ -257,7 +265,7 @@ QGeoRouteRequest::TravelMode QGeoRoute::travelMode() const */ void QGeoRoute::setPath(const QList &path) { - d_ptr->path = path; + d_ptr->setPath(path); } /*! @@ -268,34 +276,37 @@ void QGeoRoute::setPath(const QList &path) */ QList QGeoRoute::path() const { - return d_ptr->path; + return d_ptr->path(); } /******************************************************************************* *******************************************************************************/ QGeoRoutePrivate::QGeoRoutePrivate() - : travelTime(0), - distance(0.0), - travelMode(QGeoRouteRequest::CarTravel) {} - -QGeoRoutePrivate::QGeoRoutePrivate(const QGeoRoutePrivate &other) - : QSharedData(other), - id(other.id), - request(other.request), - bounds(other.bounds), - travelTime(other.travelTime), - distance(other.distance), - travelMode(other.travelMode), - path(other.path), - firstSegment(other.firstSegment) {} +{ + +} + +QGeoRoutePrivate::QGeoRoutePrivate(const QGeoRoutePrivate &other) : QSharedData(other) +{ + +} QGeoRoutePrivate::~QGeoRoutePrivate() {} bool QGeoRoutePrivate::operator ==(const QGeoRoutePrivate &other) const { - QGeoRouteSegment s1 = firstSegment; - QGeoRouteSegment s2 = other.firstSegment; + return equals(other); +} + +bool QGeoRoutePrivate::equals(const QGeoRoutePrivate &other) const +{ + if (!other.engineName().isEmpty()) // only way to know if other comes from an engine without dynamic_cast + return false; + + // here both routes are of type QGeoRoutePrivateDefault + QGeoRouteSegment s1 = firstSegment(); + QGeoRouteSegment s2 = other.firstSegment(); while (true) { if (s1.isValid() != s2.isValid()) @@ -308,13 +319,219 @@ bool QGeoRoutePrivate::operator ==(const QGeoRoutePrivate &other) const s2 = s2.nextRouteSegment(); } - return ((id == other.id) - && (request == other.request) - && (bounds == other.bounds) - && (travelTime == other.travelTime) - && (distance == other.distance) - && (travelMode == other.travelMode) - && (path == other.path)); + return ((id() == other.id()) + && (request() == other.request()) + && (bounds() == other.bounds()) + && (travelTime() == other.travelTime()) + && (distance() == other.distance()) + && (travelMode() == other.travelMode()) + && (path() == other.path())); +} + +void QGeoRoutePrivate::setId(const QString &id) +{ + Q_UNUSED(id) +} + +QString QGeoRoutePrivate::id() const +{ + return QString(); +} + +void QGeoRoutePrivate::setRequest(const QGeoRouteRequest &request) +{ + Q_UNUSED(request) +} + +QGeoRouteRequest QGeoRoutePrivate::request() const +{ + return QGeoRouteRequest(); +} + +void QGeoRoutePrivate::setBounds(const QGeoRectangle &bounds) +{ + Q_UNUSED(bounds) +} + +QGeoRectangle QGeoRoutePrivate::bounds() const +{ + return QGeoRectangle(); +} + +void QGeoRoutePrivate::setTravelTime(int travelTime) +{ + Q_UNUSED(travelTime) +} + +int QGeoRoutePrivate::travelTime() const +{ + return 0; +} + +void QGeoRoutePrivate::setDistance(qreal distance) +{ + Q_UNUSED(distance) +} + +qreal QGeoRoutePrivate::distance() const +{ + return 0; +} + +void QGeoRoutePrivate::setTravelMode(QGeoRouteRequest::TravelMode mode) +{ + Q_UNUSED(mode) +} + +QGeoRouteRequest::TravelMode QGeoRoutePrivate::travelMode() const +{ + return QGeoRouteRequest::CarTravel; +} + +void QGeoRoutePrivate::setPath(const QList &path) +{ + Q_UNUSED(path) +} + +QList QGeoRoutePrivate::path() const +{ + return QList(); +} + +void QGeoRoutePrivate::setFirstSegment(const QGeoRouteSegment &firstSegment) +{ + Q_UNUSED(firstSegment) +} + +QGeoRouteSegment QGeoRoutePrivate::firstSegment() const +{ + return QGeoRouteSegment(); +} + +/******************************************************************************* +*******************************************************************************/ + + +QGeoRoutePrivateDefault::QGeoRoutePrivateDefault() + : m_travelTime(0), + m_distance(0.0), + m_travelMode(QGeoRouteRequest::CarTravel), + m_numSegments(-1) {} + +QGeoRoutePrivateDefault::QGeoRoutePrivateDefault(const QGeoRoutePrivateDefault &other) + : QGeoRoutePrivate(other), + m_id(other.m_id), + m_request(other.m_request), + m_bounds(other.m_bounds), + m_routeSegments(other.m_routeSegments), + m_travelTime(other.m_travelTime), + m_distance(other.m_distance), + m_travelMode(other.m_travelMode), + m_path(other.m_path), + m_firstSegment(other.m_firstSegment), + m_numSegments(other.m_numSegments){} + + +QGeoRoutePrivateDefault::~QGeoRoutePrivateDefault() {} + +void QGeoRoutePrivateDefault::setId(const QString &id) +{ + m_id = id; +} + +QString QGeoRoutePrivateDefault::id() const +{ + return m_id; +} + +void QGeoRoutePrivateDefault::setRequest(const QGeoRouteRequest &request) +{ + m_request = request; +} + +QGeoRouteRequest QGeoRoutePrivateDefault::request() const +{ + return m_request; +} + +void QGeoRoutePrivateDefault::setBounds(const QGeoRectangle &bounds) +{ + m_bounds = bounds; +} + +QGeoRectangle QGeoRoutePrivateDefault::bounds() const +{ + return m_bounds; +} + +void QGeoRoutePrivateDefault::setTravelTime(int travelTime) +{ + m_travelTime = travelTime; +} + +int QGeoRoutePrivateDefault::travelTime() const +{ + return m_travelTime; +} + +void QGeoRoutePrivateDefault::setDistance(qreal distance) +{ + m_distance = distance; +} + +qreal QGeoRoutePrivateDefault::distance() const +{ + return m_distance; +} + +void QGeoRoutePrivateDefault::setTravelMode(QGeoRouteRequest::TravelMode mode) +{ + m_travelMode = mode; +} + +QGeoRouteRequest::TravelMode QGeoRoutePrivateDefault::travelMode() const +{ + return m_travelMode; +} + +void QGeoRoutePrivateDefault::setPath(const QList &path) +{ + m_path = path; +} + +QList QGeoRoutePrivateDefault::path() const +{ + return m_path; +} + +void QGeoRoutePrivateDefault::setFirstSegment(const QGeoRouteSegment &firstSegment) +{ + m_firstSegment = firstSegment; +} + +QGeoRouteSegment QGeoRoutePrivateDefault::firstSegment() const +{ + return m_firstSegment; +} + +QString QGeoRoutePrivateDefault::engineName() const +{ + return QString(); +} + +int QGeoRoutePrivateDefault::segmentsCount() const +{ + if (m_numSegments >= 0) + return m_numSegments; + + int count = 0; + QGeoRouteSegment segment = m_firstSegment; + while (segment.isValid()) { + ++count; + segment = segment.nextRouteSegment(); + } + m_numSegments = count; + return count; } QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroute.h b/src/location/maps/qgeoroute.h index 68e73c09..7dee719f 100644 --- a/src/location/maps/qgeoroute.h +++ b/src/location/maps/qgeoroute.h @@ -87,8 +87,10 @@ public: void setPath(const QList &path); QList path() const; -private: +protected: + QGeoRoute(const QExplicitlySharedDataPointer &dd); QExplicitlySharedDataPointer d_ptr; + friend class QDeclarativeGeoRoute; }; QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroute_p.h b/src/location/maps/qgeoroute_p.h index 66ef3c68..1a8f9b0c 100644 --- a/src/location/maps/qgeoroute_p.h +++ b/src/location/maps/qgeoroute_p.h @@ -48,6 +48,7 @@ // We mean it. // +#include #include "qgeoroute.h" #include "qgeorouterequest.h" #include "qgeorectangle.h" @@ -59,29 +60,95 @@ QT_BEGIN_NAMESPACE class QGeoCoordinate; -class QGeoRoutePrivate : public QSharedData +class Q_LOCATION_PRIVATE_EXPORT QGeoRoutePrivate : public QSharedData { public: QGeoRoutePrivate(); QGeoRoutePrivate(const QGeoRoutePrivate &other); - ~QGeoRoutePrivate(); + virtual ~QGeoRoutePrivate(); bool operator == (const QGeoRoutePrivate &other) const; - QString id; - QGeoRouteRequest request; + virtual void setId(const QString &id); + virtual QString id() const; - QGeoRectangle bounds; -// QList routeSegments; + virtual void setRequest(const QGeoRouteRequest &request); + virtual QGeoRouteRequest request() const; - int travelTime; - qreal distance; + virtual void setBounds(const QGeoRectangle &bounds); + virtual QGeoRectangle bounds() const; - QGeoRouteRequest::TravelMode travelMode; + virtual void setTravelTime(int travelTime); + virtual int travelTime() const; - QList path; + virtual void setDistance(qreal distance); + virtual qreal distance() const; - QGeoRouteSegment firstSegment; + virtual void setTravelMode(QGeoRouteRequest::TravelMode mode); + virtual QGeoRouteRequest::TravelMode travelMode() const; + + virtual void setPath(const QList &path); + virtual QList path() const; + + virtual void setFirstSegment(const QGeoRouteSegment &firstSegment); + virtual QGeoRouteSegment firstSegment() const; + + virtual bool equals(const QGeoRoutePrivate &other) const; + + virtual QString engineName() const = 0; + virtual int segmentsCount() const = 0; +}; + +class Q_LOCATION_PRIVATE_EXPORT QGeoRoutePrivateDefault : public QGeoRoutePrivate +{ +public: + QGeoRoutePrivateDefault(); + QGeoRoutePrivateDefault(const QGeoRoutePrivateDefault &other); + ~QGeoRoutePrivateDefault(); + + virtual void setId(const QString &id) override; + virtual QString id() const override; + + virtual void setRequest(const QGeoRouteRequest &request) override; + virtual QGeoRouteRequest request() const override; + + virtual void setBounds(const QGeoRectangle &bounds) override; + virtual QGeoRectangle bounds() const override; + + virtual void setTravelTime(int travelTime) override; + virtual int travelTime() const override; + + virtual void setDistance(qreal distance) override; + virtual qreal distance() const override; + + virtual void setTravelMode(QGeoRouteRequest::TravelMode mode) override; + virtual QGeoRouteRequest::TravelMode travelMode() const override; + + virtual void setPath(const QList &path) override; + virtual QList path() const override; + + virtual void setFirstSegment(const QGeoRouteSegment &firstSegment) override; + virtual QGeoRouteSegment firstSegment() const override; + + virtual QString engineName() const override; + virtual int segmentsCount() const override; + + + QString m_id; + QGeoRouteRequest m_request; + + QGeoRectangle m_bounds; + mutable QList m_routeSegments; + + int m_travelTime; + qreal m_distance; + + QGeoRouteRequest::TravelMode m_travelMode; + + QList m_path; + + QGeoRouteSegment m_firstSegment; + mutable int m_numSegments; }; QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroutesegment.cpp b/src/location/maps/qgeoroutesegment.cpp index 45c2cc69..d9de9870 100644 --- a/src/location/maps/qgeoroutesegment.cpp +++ b/src/location/maps/qgeoroutesegment.cpp @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE setTravelTime(), setDistance(), setPath() or setManeuver() is called. */ QGeoRouteSegment::QGeoRouteSegment() - : d_ptr(new QGeoRouteSegmentPrivate()) {} + : d_ptr(new QGeoRouteSegmentPrivateDefault()) {} /*! Constructs a route segment object from the contents of \a other. @@ -78,8 +78,8 @@ QGeoRouteSegment::QGeoRouteSegment(const QGeoRouteSegment &other) /*! \internal */ -QGeoRouteSegment::QGeoRouteSegment(QExplicitlySharedDataPointer &d_ptr) - : d_ptr(d_ptr) {} +QGeoRouteSegment::QGeoRouteSegment(const QExplicitlySharedDataPointer &dd) + : d_ptr(dd) {} /*! Destroys this route segment object. @@ -129,7 +129,7 @@ bool QGeoRouteSegment::operator !=(const QGeoRouteSegment &other) const */ bool QGeoRouteSegment::isValid() const { - return d_ptr->valid; + return d_ptr->valid(); } /*! @@ -137,8 +137,8 @@ bool QGeoRouteSegment::isValid() const */ void QGeoRouteSegment::setNextRouteSegment(const QGeoRouteSegment &routeSegment) { - d_ptr->valid = true; - d_ptr->nextSegment = routeSegment.d_ptr; + d_ptr->setValid(true); + d_ptr->setNextRouteSegment(routeSegment.d_ptr); } /*! @@ -149,12 +149,10 @@ void QGeoRouteSegment::setNextRouteSegment(const QGeoRouteSegment &routeSegment) */ QGeoRouteSegment QGeoRouteSegment::nextRouteSegment() const { - if (d_ptr->valid && d_ptr->nextSegment) - return QGeoRouteSegment(d_ptr->nextSegment); + if (d_ptr->valid() && d_ptr->m_nextSegment) + return QGeoRouteSegment(d_ptr->m_nextSegment); - QGeoRouteSegment segment; - segment.d_ptr->valid = false; - return segment; + return QGeoRouteSegment(); } /*! @@ -163,8 +161,8 @@ QGeoRouteSegment QGeoRouteSegment::nextRouteSegment() const */ void QGeoRouteSegment::setTravelTime(int secs) { - d_ptr->valid = true; - d_ptr->travelTime = secs; + d_ptr->setValid(true); + d_ptr->setTravelTime(secs); } /*! @@ -173,7 +171,7 @@ void QGeoRouteSegment::setTravelTime(int secs) */ int QGeoRouteSegment::travelTime() const { - return d_ptr->travelTime; + return d_ptr->travelTime(); } /*! @@ -181,8 +179,8 @@ int QGeoRouteSegment::travelTime() const */ void QGeoRouteSegment::setDistance(qreal distance) { - d_ptr->valid = true; - d_ptr->distance = distance; + d_ptr->setValid(true); + d_ptr->setDistance(distance); } /*! @@ -190,7 +188,7 @@ void QGeoRouteSegment::setDistance(qreal distance) */ qreal QGeoRouteSegment::distance() const { - return d_ptr->distance; + return d_ptr->distance(); } /*! @@ -201,8 +199,8 @@ qreal QGeoRouteSegment::distance() const */ void QGeoRouteSegment::setPath(const QList &path) { - d_ptr->valid = true; - d_ptr->path = path; + d_ptr->setValid(true); + d_ptr->setPath(path); } /*! @@ -214,7 +212,7 @@ void QGeoRouteSegment::setPath(const QList &path) QList QGeoRouteSegment::path() const { - return d_ptr->path; + return d_ptr->path(); } /*! @@ -222,8 +220,8 @@ QList QGeoRouteSegment::path() const */ void QGeoRouteSegment::setManeuver(const QGeoManeuver &maneuver) { - d_ptr->valid = true; - d_ptr->maneuver = maneuver; + d_ptr->setValid(true); + d_ptr->setManeuver(maneuver); } /*! @@ -234,42 +232,174 @@ void QGeoRouteSegment::setManeuver(const QGeoManeuver &maneuver) */ QGeoManeuver QGeoRouteSegment::maneuver() const { - return d_ptr->maneuver; + return d_ptr->maneuver(); } /******************************************************************************* *******************************************************************************/ -QGeoRouteSegmentPrivate::QGeoRouteSegmentPrivate() - : valid(false), - travelTime(0), - distance(0.0) {} +QGeoRouteSegmentPrivate::QGeoRouteSegmentPrivate() {} QGeoRouteSegmentPrivate::QGeoRouteSegmentPrivate(const QGeoRouteSegmentPrivate &other) - : QSharedData(other), - valid(other.valid), - travelTime(other.travelTime), - distance(other.distance), - path(other.path), - maneuver(other.maneuver), - nextSegment(other.nextSegment) {} + : QSharedData(other), m_nextSegment(other.m_nextSegment) {} QGeoRouteSegmentPrivate::~QGeoRouteSegmentPrivate() { - nextSegment.reset(); + m_nextSegment.reset(); } bool QGeoRouteSegmentPrivate::operator ==(const QGeoRouteSegmentPrivate &other) const { - return ((valid == other.valid) - && (travelTime == other.travelTime) - && (distance == other.distance) - && (path == other.path) - && (maneuver == other.maneuver)); + return ((valid() == other.valid()) + && (travelTime() == other.travelTime()) + && (distance() == other.distance()) + && (path() == other.path()) + && (maneuver() == other.maneuver())); +} + +bool QGeoRouteSegmentPrivate::valid() const +{ + return false; +} + +void QGeoRouteSegmentPrivate::setValid(bool valid) +{ + Q_UNUSED(valid) +} + +int QGeoRouteSegmentPrivate::travelTime() const +{ + return 0; +} + +void QGeoRouteSegmentPrivate::setTravelTime(int travelTime) +{ + Q_UNUSED(travelTime) +} + +qreal QGeoRouteSegmentPrivate::distance() const +{ + return 0; +} + +void QGeoRouteSegmentPrivate::setDistance(qreal distance) +{ + Q_UNUSED(distance) +} + +QList QGeoRouteSegmentPrivate::path() const +{ + return QList(); +} + +void QGeoRouteSegmentPrivate::setPath(const QList &path) +{ + Q_UNUSED(path) +} + +QGeoManeuver QGeoRouteSegmentPrivate::maneuver() const +{ + return QGeoManeuver(); +} + +void QGeoRouteSegmentPrivate::setManeuver(const QGeoManeuver &maneuver) +{ + Q_UNUSED(maneuver) +} + +QExplicitlySharedDataPointer QGeoRouteSegmentPrivate::nextRouteSegment() const +{ + return m_nextSegment; +} + +void QGeoRouteSegmentPrivate::setNextRouteSegment(const QExplicitlySharedDataPointer &next) +{ + m_nextSegment = next; } /******************************************************************************* *******************************************************************************/ -QT_END_NAMESPACE +QGeoRouteSegmentPrivateDefault::QGeoRouteSegmentPrivateDefault() + : m_valid(false), + m_travelTime(0), + m_distance(0.0) +{ +} + +QGeoRouteSegmentPrivateDefault::QGeoRouteSegmentPrivateDefault(const QGeoRouteSegmentPrivateDefault &other) + : QGeoRouteSegmentPrivate(other), + m_valid(other.m_valid), + m_travelTime(other.m_travelTime), + m_distance(other.m_distance), + m_path(other.m_path), + m_maneuver(other.m_maneuver) +{ + +} + +QGeoRouteSegmentPrivateDefault::~QGeoRouteSegmentPrivateDefault() +{ + +} + +bool QGeoRouteSegmentPrivateDefault::operator ==(const QGeoRouteSegmentPrivateDefault &other) const +{ + return QGeoRouteSegmentPrivateDefault::operator ==(other); +} + +bool QGeoRouteSegmentPrivateDefault::valid() const +{ + return m_valid; +} + +void QGeoRouteSegmentPrivateDefault::setValid(bool valid) +{ + m_valid = valid; +} + +int QGeoRouteSegmentPrivateDefault::travelTime() const +{ + return m_travelTime; +} + +void QGeoRouteSegmentPrivateDefault::setTravelTime(int travelTime) +{ + m_travelTime = travelTime; +} + +qreal QGeoRouteSegmentPrivateDefault::distance() const +{ + return m_distance; +} + +void QGeoRouteSegmentPrivateDefault::setDistance(qreal distance) +{ + m_distance = distance; +} + +QList QGeoRouteSegmentPrivateDefault::path() const +{ + return m_path; +} + +void QGeoRouteSegmentPrivateDefault::setPath(const QList &path) +{ + m_path = path; +} + +QGeoManeuver QGeoRouteSegmentPrivateDefault::maneuver() const +{ + return m_maneuver; +} + +void QGeoRouteSegmentPrivateDefault::setManeuver(const QGeoManeuver &maneuver) +{ + m_maneuver = maneuver; +} + +/******************************************************************************* +*******************************************************************************/ + +QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroutesegment.h b/src/location/maps/qgeoroutesegment.h index bddc172c..a90399be 100644 --- a/src/location/maps/qgeoroutesegment.h +++ b/src/location/maps/qgeoroutesegment.h @@ -78,9 +78,8 @@ public: QGeoManeuver maneuver() const; protected: - QGeoRouteSegment(QExplicitlySharedDataPointer &d_ptr); + QGeoRouteSegment(const QExplicitlySharedDataPointer &dd); -private: QExplicitlySharedDataPointer d_ptr; }; diff --git a/src/location/maps/qgeoroutesegment_p.h b/src/location/maps/qgeoroutesegment_p.h index 1751266a..8f452896 100644 --- a/src/location/maps/qgeoroutesegment_p.h +++ b/src/location/maps/qgeoroutesegment_p.h @@ -48,7 +48,10 @@ // We mean it. // -#include "qgeomaneuver.h" +#include +#include +#include + #include #include @@ -58,23 +61,68 @@ QT_BEGIN_NAMESPACE class QGeoCoordinate; -class QGeoRouteSegmentPrivate : public QSharedData +class Q_LOCATION_PRIVATE_EXPORT QGeoRouteSegmentPrivate : public QSharedData { public: QGeoRouteSegmentPrivate(); QGeoRouteSegmentPrivate(const QGeoRouteSegmentPrivate &other); - ~QGeoRouteSegmentPrivate(); + virtual ~QGeoRouteSegmentPrivate(); bool operator ==(const QGeoRouteSegmentPrivate &other) const; - bool valid; + virtual bool valid() const; + virtual void setValid(bool valid); + + virtual int travelTime() const; + virtual void setTravelTime(int travelTime); + + virtual qreal distance() const; + virtual void setDistance(qreal distance); + + virtual QList path() const; + virtual void setPath(const QList &path); + + virtual QGeoManeuver maneuver() const; + virtual void setManeuver(const QGeoManeuver &maneuver); + + virtual QExplicitlySharedDataPointer nextRouteSegment() const; + virtual void setNextRouteSegment(const QExplicitlySharedDataPointer &next); + + QExplicitlySharedDataPointer m_nextSegment; +}; + + + +class Q_LOCATION_PRIVATE_EXPORT QGeoRouteSegmentPrivateDefault : public QGeoRouteSegmentPrivate +{ +public: + QGeoRouteSegmentPrivateDefault(); + QGeoRouteSegmentPrivateDefault(const QGeoRouteSegmentPrivateDefault &other); + ~QGeoRouteSegmentPrivateDefault(); + + bool operator ==(const QGeoRouteSegmentPrivateDefault &other) const; + + virtual bool valid() const override; + virtual void setValid(bool valid) override; + + virtual int travelTime() const override; + virtual void setTravelTime(int travelTime) override; + + virtual qreal distance() const override; + virtual void setDistance(qreal distance) override; + + virtual QList path() const override; + virtual void setPath(const QList &path) override; + + virtual QGeoManeuver maneuver() const override; + virtual void setManeuver(const QGeoManeuver &maneuver) override; - int travelTime; - qreal distance; - QList path; - QGeoManeuver maneuver; - QExplicitlySharedDataPointer nextSegment; + bool m_valid; + int m_travelTime; + qreal m_distance; + QList m_path; + QGeoManeuver m_maneuver; }; QT_END_NAMESPACE diff --git a/tests/auto/declarative_core/tst_routing.qml b/tests/auto/declarative_core/tst_routing.qml index fdbfe7b6..c090a5ea 100644 --- a/tests/auto/declarative_core/tst_routing.qml +++ b/tests/auto/declarative_core/tst_routing.qml @@ -502,6 +502,14 @@ Item { ] } + Plugin { + id: testPlugin_slacker_alt + name: "qmlgeo.test.plugin" + allowExperimental: true + PluginParameter { name: "gc_finishRequestImmediately"; value: false} + PluginParameter { name: "gc_alternateGeoRoute"; value: true} + } + Plugin { id: bacicRoutingPlugin_slacker; name: "qmlgeo.test.plugin" @@ -529,24 +537,27 @@ Item { property variant f2coordinate3: QtPositioning.coordinate(63, 64) RouteQuery {id: routeQuery} + property var routeQueryDefaultWaypoints: [ + { latitude: 60, longitude: 60 }, + { latitude: 61, longitude: 62 }, + { latitude: 63, longitude: 64 }, + { latitude: 65, longitude: 66 }, + { latitude: 67, longitude: 68 } + ] + property var routeQuery2DefaultWaypoints: [ + f2coordinate1, + f2coordinate2, + f2coordinate3 + ] RouteQuery { id: filledRouteQuery numberAlternativeRoutes: 0 - waypoints: [ - { latitude: 60, longitude: 60 }, - { latitude: 61, longitude: 62 }, - { latitude: 63, longitude: 64 }, - { latitude: 65, longitude: 66 }, - { latitude: 67, longitude: 68 } - ] + waypoints: routeQueryDefaultWaypoints } RouteQuery { id: filledRouteQuery2 - waypoints: [ - f2coordinate1, - f2coordinate2, - f2coordinate3 - ] + numberAlternativeRoutes: 0 + waypoints: routeQuery2DefaultWaypoints } RouteModel { id: routeModelAutomatic; @@ -554,8 +565,15 @@ Item { query: filledRouteQuery; autoUpdate: true } + RouteModel { + id: routeModelAutomaticAltImpl; + plugin: testPlugin_slacker_alt; + query: filledRouteQuery; + autoUpdate: true + } SignalSpy {id: automaticRoutesSpy; target: routeModelAutomatic; signalName: "routesChanged" } + SignalSpy {id: automaticRoutesSpyAlt; target: routeModelAutomaticAltImpl; signalName: "routesChanged" } RouteModel {id: routeModel; plugin: testPlugin_immediate; query: routeQuery } SignalSpy {id: testRoutesSpy; target: routeModel; signalName: "routesChanged"} @@ -740,26 +758,34 @@ Item { compare(testCountSlackSpy.count, 1) compare(routeModelSlack.count, 1) + test_basic_routing_automatic(routeModelAutomatic, automaticRoutesSpy, "routeModelAutomatic") + test_basic_routing_automatic(routeModelAutomaticAltImpl, automaticRoutesSpyAlt, "routeModelAutomaticAltImpl") + } + + function test_basic_routing_automatic(model, spy, label) { + if (label === undefined) + return + console.log("testing",label) // Autoupdate - automaticRoutesSpy.clear(); + spy.clear(); filledRouteQuery.numberAlternativeRoutes = 1 // 'altroutes - 70' is the echoed errorcode - tryCompare (automaticRoutesSpy, "count", 1) // 5 sec - compare(routeModelAutomatic.count, 1) // There should be a route already - compare (routeModelAutomatic.get(0).path.length, 5) - compare (routeModelAutomatic.get(0).path[0].latitude, filledRouteQuery.waypoints[0].latitude) + tryCompare (spy, "count", 1) // 5 sec + compare(model.count, 1) // There should be a route already + compare (model.get(0).path.length, 5) + compare (model.get(0).path[0].latitude, filledRouteQuery.waypoints[0].latitude) // Remove a waypoint and check that autoupdate works filledRouteQuery.removeWaypoint(fcoordinate2) - tryCompare (automaticRoutesSpy, "count", 2) - compare (routeModelAutomatic.get(0).path.length, 4) - compare (routeModelAutomatic.get(0).path[0].latitude, fcoordinate1.latitude) + tryCompare (spy, "count", 2) + compare (model.get(0).path.length, 4) + compare (model.get(0).path[0].latitude, fcoordinate1.latitude) // Add a waypoint and check that autoupdate works filledRouteQuery.addWaypoint(fcoordinate2); - tryCompare (automaticRoutesSpy, "count", 3) - compare(routeModelAutomatic.count, 1); - compare(routeModelAutomatic.get(0).path.length, 5); - compare(routeModelAutomatic.get(0).path[0].latitude, filledRouteQuery.waypoints[0].latitude); + tryCompare (spy, "count", 3) + compare(model.count, 1); + compare(model.get(0).path.length, 5); + compare(model.get(0).path[0].latitude, filledRouteQuery.waypoints[0].latitude); // Change contents of a coordinate and check that autoupdate works filledRouteQuery.waypoints = [ @@ -769,14 +795,14 @@ Item { { latitude: 65, longitude: 66 }, { latitude: 67, longitude: 68 } ]; - tryCompare (automaticRoutesSpy, "count", 4) - compare(routeModelAutomatic.get(0).path[0].latitude, fcoordinate1.latitude + 1) // new value should be echoed + tryCompare (spy, "count", 4) + compare(model.get(0).path[0].latitude, fcoordinate1.latitude + 1) // new value should be echoed // Change query - routeModelAutomatic.query = filledRouteQuery2 + model.query = filledRouteQuery2 filledRouteQuery2.numberAlternativeRoutes = 3 - tryCompare (automaticRoutesSpy, "count", 5) - compare (routeModelAutomatic.get(0).path.length, 3) + tryCompare (spy, "count", 5) + compare (model.get(0).path.length, 3) // Verify that the old query is disconnected internally ie. does not trigger update filledRouteQuery.waypoints = [ @@ -787,10 +813,18 @@ Item { { latitude: 67, longitude: 68 } ]; wait(800) // wait to hope no further updates comes through - compare (automaticRoutesSpy.count, 5) - compare(routeModelAutomatic.get(0).path.length, 3); + compare (spy.count, 5) + compare(model.get(0).path.length, 3); + + // ReSetting + filledRouteQuery.numberAlternativeRoutes = 0 + filledRouteQuery2.numberAlternativeRoutes = 0 + filledRouteQuery.waypoints = routeQueryDefaultWaypoints + filledRouteQuery2.waypoints = routeQuery2DefaultWaypoints } + + function test_route_query_handles_destroyed_qml_objects() { var coordinate = QtPositioning.coordinate(11, 52); routeQuery.addWaypoint(coordinate); diff --git a/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h index 0a1e7ce6..c77cb0a5 100644 --- a/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h +++ b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -42,6 +43,24 @@ QT_USE_NAMESPACE +class QGeoRoutePrivateDefaultAlt : public QGeoRoutePrivateDefault +{ +public: + QGeoRoutePrivateDefaultAlt() {} + QGeoRoutePrivateDefaultAlt(const QGeoRoutePrivateDefaultAlt &other) + : QGeoRoutePrivateDefault(other) {} + ~QGeoRoutePrivateDefaultAlt() {} +}; + +class QGeoRouteAlt : public QGeoRoute +{ +public: + QGeoRouteAlt() + : QGeoRoute(QExplicitlySharedDataPointer(new QGeoRoutePrivateDefaultAlt())) + { + } +}; + class RouteReplyTest :public QGeoRouteReply { Q_OBJECT @@ -62,6 +81,7 @@ class QGeoRoutingManagerEngineTest: public QGeoRoutingManagerEngine int timerId_; QGeoRouteReply::Error errorCode_; QString errorString_; + bool alternateGeoRouteImplementation_; public: QGeoRoutingManagerEngineTest(const QVariantMap ¶meters, @@ -70,7 +90,8 @@ public: routeReply_(0), finishRequestImmediately_(true), timerId_(0), - errorCode_(QGeoRouteReply::NoError) + errorCode_(QGeoRouteReply::NoError), + alternateGeoRouteImplementation_(false) { Q_UNUSED(error) Q_UNUSED(errorString) @@ -79,6 +100,10 @@ public: finishRequestImmediately_ = qvariant_cast(parameters.value("gc_finishRequestImmediately")); } + if (parameters.contains("gc_alternateGeoRoute")) { + alternateGeoRouteImplementation_ = qvariant_cast(parameters.value("gc_alternateGeoRoute")); + } + setLocale(QLocale (QLocale::German, QLocale::Germany)); setSupportedFeatureTypes ( QGeoRouteRequest::NoFeature | QGeoRouteRequest::TollFeature | @@ -136,6 +161,8 @@ public: QList routes; for (int i = 0; i < request.numberAlternativeRoutes(); ++i) { QGeoRoute route; + if (alternateGeoRouteImplementation_) + route = QGeoRouteAlt(); route.setPath(request.waypoints()); routes.append(route); } -- cgit v1.2.3 From c61f38b10bf6b4521ec8f847b8d4d5ec47477074 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Thu, 24 Aug 2017 15:20:02 +0300 Subject: Introduce QParameterizableObject QParameterizableObject is a base class for QObjects-derived objects (but not QQuickItem-derived ones!) that need to have MapParameter(s) attached. Change-Id: Ib92b0676d8c8e02d08d9b76b05ecd4adc2d84e7b Reviewed-by: Paolo Angelelli Reviewed-by: BogDan Vatra --- src/location/declarativemaps/declarativemaps.pri | 6 +- .../declarativemaps/qparameterizableobject.cpp | 84 ++++++++++++++++++++++ .../declarativemaps/qparameterizableobject_p.h | 80 +++++++++++++++++++++ 3 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 src/location/declarativemaps/qparameterizableobject.cpp create mode 100644 src/location/declarativemaps/qparameterizableobject_p.h diff --git a/src/location/declarativemaps/declarativemaps.pri b/src/location/declarativemaps/declarativemaps.pri index 34c9f588..e607ea2b 100644 --- a/src/location/declarativemaps/declarativemaps.pri +++ b/src/location/declarativemaps/declarativemaps.pri @@ -27,6 +27,7 @@ PRIVATE_HEADERS += \ declarativemaps/locationvaluetypehelper_p.h \ declarativemaps/qquickgeomapgesturearea_p.h \ declarativemaps/qdeclarativegeomapitemgroup_p.h \ + declarativemaps/qparameterizableobject_p.h \ declarativemaps/mapitemviewdelegateincubator_p.h \ ../imports/positioning/qquickgeocoordinateanimation_p.h @@ -53,9 +54,10 @@ SOURCES += \ declarativemaps/error_messages.cpp \ declarativemaps/locationvaluetypehelper.cpp \ declarativemaps/qquickgeomapgesturearea.cpp \ + declarativemaps/qparameterizableobject.cpp \ declarativemaps/qdeclarativegeomapitemgroup.cpp \ - ../imports/positioning/qquickgeocoordinateanimation.cpp \ - declarativemaps/mapitemviewdelegateincubator.cpp + declarativemaps/mapitemviewdelegateincubator.cpp \ + ../imports/positioning/qquickgeocoordinateanimation.cpp load(qt_build_paths) LIBS_PRIVATE += -L$$MODULE_BASE_OUTDIR/lib -lpoly2tri$$qtPlatformTargetSuffix() -lclip2tri$$qtPlatformTargetSuffix() diff --git a/src/location/declarativemaps/qparameterizableobject.cpp b/src/location/declarativemaps/qparameterizableobject.cpp new file mode 100644 index 00000000..a95f290e --- /dev/null +++ b/src/location/declarativemaps/qparameterizableobject.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qparameterizableobject_p.h" +#include "qdeclarativegeomapparameter_p.h" +#include + +QT_BEGIN_NAMESPACE + +QParameterizableObject::QParameterizableObject(QObject *parent) + : QObject(parent) +{} + +QQmlListProperty QParameterizableObject::declarativeParameters() +{ + return QQmlListProperty(this, nullptr, + &QParameterizableObject::append, + &QParameterizableObject::count, + &QParameterizableObject::at, + &QParameterizableObject::clear); +} + +QList QParameterizableObject::parameters() const +{ + QList params; + for (auto param : qAsConst(m_parameters)) + params << param; + return params; +} + +void QParameterizableObject::append(QQmlListProperty *p, QDeclarativeGeoMapParameter *v) +{ + static_cast(p->object)->m_parameters.append(v); +} + +int QParameterizableObject::count(QQmlListProperty *p) +{ + return static_cast(p->object)->m_parameters.count(); +} + +QDeclarativeGeoMapParameter *QParameterizableObject::at(QQmlListProperty *p, int idx) +{ + return static_cast(p->object)->m_parameters.at(idx); +} + +void QParameterizableObject::clear(QQmlListProperty *p) +{ + static_cast(p->object)->m_parameters.clear(); +} + +QT_END_NAMESPACE diff --git a/src/location/declarativemaps/qparameterizableobject_p.h b/src/location/declarativemaps/qparameterizableobject_p.h new file mode 100644 index 00000000..c6118c93 --- /dev/null +++ b/src/location/declarativemaps/qparameterizableobject_p.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPARAMETERIZABLEOBJECT_H +#define QPARAMETERIZABLEOBJECT_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +class QDeclarativeGeoMapParameter; +class QGeoMapParameter; +class Q_LOCATION_PRIVATE_EXPORT QParameterizableObject : public QObject +{ + Q_OBJECT + Q_PROPERTY(QQmlListProperty parameters READ declarativeParameters DESIGNABLE false) + Q_CLASSINFO("DefaultProperty", "parameters") + +public: + explicit QParameterizableObject(QObject *parent = nullptr); + QList parameters() const; + +protected: + static void append(QQmlListProperty *p, QDeclarativeGeoMapParameter *v); + static int count(QQmlListProperty *p); + static QDeclarativeGeoMapParameter *at(QQmlListProperty *p, int idx); + static void clear(QQmlListProperty *p); + + QQmlListProperty declarativeParameters(); + QList m_parameters; +}; +QT_END_NAMESPACE + +#endif // QPARAMETERIZABLEOBJECT_H -- cgit v1.2.3 From 5edef5e181e0f3cf2e04182d06b3c781717e6f87 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Tue, 5 Sep 2017 18:37:09 +0200 Subject: Fix enabling polymorphic pimpl in QGeoRoute/Segment/Maneuver Change 8ac6377e62af803b567449cdf30c669b92114cc4 allowed to subclass private implementations of these 3 classes. However, the pimpl was kept in a QExplicitlySharedDataPointer for the first two, and QSharedDataPointer for the last class. Failing to specialize the clone method of the pointer would result in incorrect detach behavior, which would however only be visible with the third class (the first two never call detach() internally, and the line QEXPECT_FAIL("", "QGeoRoute equality operators broken", Continue); in the tests make it clear. This change also adds the equals virtual method also to QGeoRouteSegment and QGeoManeuver private implementations. Change-Id: If51dafebb19e4cb2d1bcf40c2b6f136f804198e0 Reviewed-by: Alex Blasche --- src/location/maps/qgeomaneuver.cpp | 20 ++++++--- src/location/maps/qgeomaneuver_p.h | 6 ++- src/location/maps/qgeoroute.cpp | 11 +++++ src/location/maps/qgeoroute_p.h | 7 +++- src/location/maps/qgeoroutesegment.cpp | 16 ++++++++ src/location/maps/qgeoroutesegment_p.h | 5 +++ tests/auto/declarative_core/tst_routing.qml | 3 ++ .../geotestplugin/qgeoroutingmanagerengine_test.h | 5 +++ tests/auto/qgeomaneuver/qgeomaneuver.pro | 2 +- tests/auto/qgeomaneuver/tst_qgeomaneuver.cpp | 48 +++++++++++++++++++++- tests/auto/qgeomaneuver/tst_qgeomaneuver.h | 1 + tests/auto/qgeoroute/qgeoroute.pro | 2 +- tests/auto/qgeoroute/tst_qgeoroute.cpp | 18 +++++++- 13 files changed, 130 insertions(+), 14 deletions(-) diff --git a/src/location/maps/qgeomaneuver.cpp b/src/location/maps/qgeomaneuver.cpp index 78efb971..9d6a4bf0 100644 --- a/src/location/maps/qgeomaneuver.cpp +++ b/src/location/maps/qgeomaneuver.cpp @@ -41,6 +41,12 @@ QT_BEGIN_NAMESPACE +template<> +QGeoManeuverPrivate *QSharedDataPointer::clone() +{ + return d->clone(); +} + /*! \class QGeoManeuver \inmodule QtLocation @@ -146,7 +152,8 @@ QGeoManeuver &QGeoManeuver::operator= (const QGeoManeuver & other) */ bool QGeoManeuver::operator== (const QGeoManeuver &other) const { - return (*(d_ptr.constData()) == *(other.d_ptr.constData())); + return ( (d_ptr.constData() == other.d_ptr.constData()) + || (*(d_ptr.constData()) == *(other.d_ptr.constData())) ); } /*! @@ -307,6 +314,11 @@ QGeoManeuverPrivate::~QGeoManeuverPrivate() } bool QGeoManeuverPrivate::operator==(const QGeoManeuverPrivate &other) const +{ + return equals(other); +} + +bool QGeoManeuverPrivate::equals(const QGeoManeuverPrivate &other) const { return ((valid() == other.valid()) && (position() == other.position()) @@ -420,11 +432,9 @@ QGeoManeuverPrivateDefault::QGeoManeuverPrivateDefault(const QGeoManeuverPrivate QGeoManeuverPrivateDefault::~QGeoManeuverPrivateDefault() {} - - -bool QGeoManeuverPrivateDefault::operator ==(const QGeoManeuverPrivateDefault &other) const +QGeoManeuverPrivate *QGeoManeuverPrivateDefault::clone() { - return QGeoManeuverPrivateDefault::operator ==(other); + return new QGeoManeuverPrivateDefault(*this); } bool QGeoManeuverPrivateDefault::valid() const diff --git a/src/location/maps/qgeomaneuver_p.h b/src/location/maps/qgeomaneuver_p.h index 484354ba..e17bf880 100644 --- a/src/location/maps/qgeomaneuver_p.h +++ b/src/location/maps/qgeomaneuver_p.h @@ -63,6 +63,7 @@ public: QGeoManeuverPrivate(); QGeoManeuverPrivate(const QGeoManeuverPrivate &other); virtual ~QGeoManeuverPrivate(); + virtual QGeoManeuverPrivate *clone() = 0; bool operator== (const QGeoManeuverPrivate &other) const; @@ -90,6 +91,8 @@ public: virtual QGeoCoordinate waypoint() const; virtual void setWaypoint(const QGeoCoordinate &waypoint); +protected: + virtual bool equals(const QGeoManeuverPrivate &other) const; }; class Q_LOCATION_PRIVATE_EXPORT QGeoManeuverPrivateDefault : public QGeoManeuverPrivate @@ -98,8 +101,7 @@ public: QGeoManeuverPrivateDefault(); QGeoManeuverPrivateDefault(const QGeoManeuverPrivateDefault &other); ~QGeoManeuverPrivateDefault(); - - bool operator== (const QGeoManeuverPrivateDefault &other) const; + virtual QGeoManeuverPrivate *clone() override; virtual bool valid() const override; virtual void setValid(bool valid) override; diff --git a/src/location/maps/qgeoroute.cpp b/src/location/maps/qgeoroute.cpp index 95603218..2e7b259a 100644 --- a/src/location/maps/qgeoroute.cpp +++ b/src/location/maps/qgeoroute.cpp @@ -44,6 +44,12 @@ QT_BEGIN_NAMESPACE +template<> +QGeoRoutePrivate *QExplicitlySharedDataPointer::clone() +{ + return d->clone(); +} + /*! \class QGeoRoute \inmodule QtLocation @@ -434,6 +440,11 @@ QGeoRoutePrivateDefault::QGeoRoutePrivateDefault(const QGeoRoutePrivateDefault & QGeoRoutePrivateDefault::~QGeoRoutePrivateDefault() {} +QGeoRoutePrivate *QGeoRoutePrivateDefault::clone() +{ + return new QGeoRoutePrivateDefault(*this); +} + void QGeoRoutePrivateDefault::setId(const QString &id) { m_id = id; diff --git a/src/location/maps/qgeoroute_p.h b/src/location/maps/qgeoroute_p.h index 1a8f9b0c..26eb613c 100644 --- a/src/location/maps/qgeoroute_p.h +++ b/src/location/maps/qgeoroute_p.h @@ -66,6 +66,7 @@ public: QGeoRoutePrivate(); QGeoRoutePrivate(const QGeoRoutePrivate &other); virtual ~QGeoRoutePrivate(); + virtual QGeoRoutePrivate *clone() = 0; bool operator == (const QGeoRoutePrivate &other) const; @@ -93,10 +94,11 @@ public: virtual void setFirstSegment(const QGeoRouteSegment &firstSegment); virtual QGeoRouteSegment firstSegment() const; - virtual bool equals(const QGeoRoutePrivate &other) const; - virtual QString engineName() const = 0; virtual int segmentsCount() const = 0; + +protected: + virtual bool equals(const QGeoRoutePrivate &other) const; }; class Q_LOCATION_PRIVATE_EXPORT QGeoRoutePrivateDefault : public QGeoRoutePrivate @@ -105,6 +107,7 @@ public: QGeoRoutePrivateDefault(); QGeoRoutePrivateDefault(const QGeoRoutePrivateDefault &other); ~QGeoRoutePrivateDefault(); + virtual QGeoRoutePrivate *clone() override; virtual void setId(const QString &id) override; virtual QString id() const override; diff --git a/src/location/maps/qgeoroutesegment.cpp b/src/location/maps/qgeoroutesegment.cpp index d9de9870..8dbe18fc 100644 --- a/src/location/maps/qgeoroutesegment.cpp +++ b/src/location/maps/qgeoroutesegment.cpp @@ -42,6 +42,12 @@ QT_BEGIN_NAMESPACE +template<> +QGeoRouteSegmentPrivate *QExplicitlySharedDataPointer::clone() +{ + return d->clone(); +} + /*! \class QGeoRouteSegment \inmodule QtLocation @@ -249,6 +255,11 @@ QGeoRouteSegmentPrivate::~QGeoRouteSegmentPrivate() } bool QGeoRouteSegmentPrivate::operator ==(const QGeoRouteSegmentPrivate &other) const +{ + return equals(other); +} + +bool QGeoRouteSegmentPrivate::equals(const QGeoRouteSegmentPrivate &other) const { return ((valid() == other.valid()) && (travelTime() == other.travelTime()) @@ -344,6 +355,11 @@ QGeoRouteSegmentPrivateDefault::~QGeoRouteSegmentPrivateDefault() } +QGeoRouteSegmentPrivate *QGeoRouteSegmentPrivateDefault::clone() +{ + return new QGeoRouteSegmentPrivateDefault(*this); +} + bool QGeoRouteSegmentPrivateDefault::operator ==(const QGeoRouteSegmentPrivateDefault &other) const { return QGeoRouteSegmentPrivateDefault::operator ==(other); diff --git a/src/location/maps/qgeoroutesegment_p.h b/src/location/maps/qgeoroutesegment_p.h index 8f452896..f0b180da 100644 --- a/src/location/maps/qgeoroutesegment_p.h +++ b/src/location/maps/qgeoroutesegment_p.h @@ -67,6 +67,7 @@ public: QGeoRouteSegmentPrivate(); QGeoRouteSegmentPrivate(const QGeoRouteSegmentPrivate &other); virtual ~QGeoRouteSegmentPrivate(); + virtual QGeoRouteSegmentPrivate *clone() = 0; bool operator ==(const QGeoRouteSegmentPrivate &other) const; @@ -89,6 +90,9 @@ public: virtual void setNextRouteSegment(const QExplicitlySharedDataPointer &next); QExplicitlySharedDataPointer m_nextSegment; + +protected: + virtual bool equals(const QGeoRouteSegmentPrivate &other) const; }; @@ -99,6 +103,7 @@ public: QGeoRouteSegmentPrivateDefault(); QGeoRouteSegmentPrivateDefault(const QGeoRouteSegmentPrivateDefault &other); ~QGeoRouteSegmentPrivateDefault(); + virtual QGeoRouteSegmentPrivate *clone() override; bool operator ==(const QGeoRouteSegmentPrivateDefault &other) const; diff --git a/tests/auto/declarative_core/tst_routing.qml b/tests/auto/declarative_core/tst_routing.qml index c090a5ea..b81426a3 100644 --- a/tests/auto/declarative_core/tst_routing.qml +++ b/tests/auto/declarative_core/tst_routing.qml @@ -774,6 +774,9 @@ Item { compare (model.get(0).path.length, 5) compare (model.get(0).path[0].latitude, filledRouteQuery.waypoints[0].latitude) + if (label === "routeModelAutomaticAltImpl") // Test that it is an altImpl + compare(model.get(0).travelTime, 123456) + // Remove a waypoint and check that autoupdate works filledRouteQuery.removeWaypoint(fcoordinate2) tryCompare (spy, "count", 2) diff --git a/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h index c77cb0a5..b7f6030e 100644 --- a/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h +++ b/tests/auto/geotestplugin/qgeoroutingmanagerengine_test.h @@ -50,6 +50,11 @@ public: QGeoRoutePrivateDefaultAlt(const QGeoRoutePrivateDefaultAlt &other) : QGeoRoutePrivateDefault(other) {} ~QGeoRoutePrivateDefaultAlt() {} + + int travelTime() const override + { + return 123456; // To identify this is actually a QGeoRoutePrivateDefaultAlt + } }; class QGeoRouteAlt : public QGeoRoute diff --git a/tests/auto/qgeomaneuver/qgeomaneuver.pro b/tests/auto/qgeomaneuver/qgeomaneuver.pro index 670d0cd6..fac57c96 100644 --- a/tests/auto/qgeomaneuver/qgeomaneuver.pro +++ b/tests/auto/qgeomaneuver/qgeomaneuver.pro @@ -8,4 +8,4 @@ HEADERS += ../utils/qlocationtestutils_p.h \ SOURCES += tst_qgeomaneuver.cpp \ ../utils/qlocationtestutils.cpp -QT += location testlib +QT += location-private testlib diff --git a/tests/auto/qgeomaneuver/tst_qgeomaneuver.cpp b/tests/auto/qgeomaneuver/tst_qgeomaneuver.cpp index 25d5bf75..c35b57f6 100644 --- a/tests/auto/qgeomaneuver/tst_qgeomaneuver.cpp +++ b/tests/auto/qgeomaneuver/tst_qgeomaneuver.cpp @@ -27,7 +27,30 @@ ****************************************************************************/ #include "tst_qgeomaneuver.h" +#include +class QGeoManeuverPrivateDefaultAlt : public QGeoManeuverPrivateDefault +{ +public: + QGeoManeuverPrivateDefaultAlt() {} + QGeoManeuverPrivateDefaultAlt(const QGeoManeuverPrivateDefaultAlt &other) + : QGeoManeuverPrivateDefault(other) {} + ~QGeoManeuverPrivateDefaultAlt() {} + + QString text() const override + { + return QStringLiteral("QGeoManeuverPrivateDefaultAlt"); // To identify this is actually a QGeoManeuverPrivateDefaultAlt + } +}; + +class QGeoManeuverAlt : public QGeoManeuver +{ +public: + QGeoManeuverAlt() + : QGeoManeuver(QSharedDataPointer(new QGeoManeuverPrivateDefaultAlt())) + { + } +}; tst_QGeoManeuver::tst_QGeoManeuver() { @@ -241,9 +264,7 @@ void tst_QGeoManeuver::operators(){ qgeomaneuvercopy->setTimeToNextInstruction(70); qgeomaneuvercopy->setDistanceToNextInstruction(56065.45); -// Not passing QVERIFY(!(qgeomaneuver->operator ==(*qgeomaneuvercopy))); -// Not passing QVERIFY(qgeomaneuver->operator !=(*qgeomaneuvercopy)); *qgeomaneuvercopy = qgeomaneuvercopy->operator =(*qgeomaneuver); @@ -253,5 +274,28 @@ void tst_QGeoManeuver::operators(){ delete qgeomaneuvercopy; } +void tst_QGeoManeuver::alternateImplementation() +{ + QGeoManeuver qgeomaneuvercopy = *qgeomaneuver; + + QVERIFY(qgeomaneuvercopy == (*qgeomaneuver)); + + qgeomaneuvercopy.setDirection(QGeoManeuver::DirectionForward); + qgeomaneuvercopy.setInstructionText("Turn left in 80m"); + qgeomaneuvercopy.setTimeToNextInstruction(70); + qgeomaneuvercopy.setDistanceToNextInstruction(56065.45); + + QVERIFY(qgeomaneuvercopy != (*qgeomaneuver)); + + QGeoManeuverAlt mAlt; + QGeoManeuver m = mAlt; + + QCOMPARE(m.instructionText(), "QGeoManeuverPrivateDefaultAlt"); + m = qgeomaneuvercopy; + QCOMPARE(m.instructionText(), "Turn left in 80m"); + m = mAlt; + QCOMPARE(m.instructionText(), "QGeoManeuverPrivateDefaultAlt"); +} + QTEST_APPLESS_MAIN(tst_QGeoManeuver); diff --git a/tests/auto/qgeomaneuver/tst_qgeomaneuver.h b/tests/auto/qgeomaneuver/tst_qgeomaneuver.h index aad28c8c..279ed23c 100644 --- a/tests/auto/qgeomaneuver/tst_qgeomaneuver.h +++ b/tests/auto/qgeomaneuver/tst_qgeomaneuver.h @@ -69,6 +69,7 @@ private Q_SLOTS: void waypoint_data(); void isValid(); void operators(); + void alternateImplementation(); //End Unit Test for QGeoRouteManeuver private: diff --git a/tests/auto/qgeoroute/qgeoroute.pro b/tests/auto/qgeoroute/qgeoroute.pro index 87ace5ca..e62adcfa 100644 --- a/tests/auto/qgeoroute/qgeoroute.pro +++ b/tests/auto/qgeoroute/qgeoroute.pro @@ -6,4 +6,4 @@ TARGET=tst_qgeoroute HEADERS += tst_qgeoroute.h SOURCES += tst_qgeoroute.cpp -QT += location testlib +QT += location-private testlib diff --git a/tests/auto/qgeoroute/tst_qgeoroute.cpp b/tests/auto/qgeoroute/tst_qgeoroute.cpp index 6cef9862..709597f8 100644 --- a/tests/auto/qgeoroute/tst_qgeoroute.cpp +++ b/tests/auto/qgeoroute/tst_qgeoroute.cpp @@ -27,6 +27,7 @@ ****************************************************************************/ #include "tst_qgeoroute.h" +#include "../geotestplugin/qgeoroutingmanagerengine_test.h" tst_QGeoRoute::tst_QGeoRoute() @@ -71,6 +72,13 @@ void tst_QGeoRoute::copy_constructor() { QGeoRoute *qgeoroutecopy = new QGeoRoute(*qgeoroute); QCOMPARE(*qgeoroute, *qgeoroutecopy); + + // CoW + qreal distance = qgeoroute->distance(); + qgeoroutecopy->setDistance(distance + 10.0); + + QVERIFY(*qgeoroute == *qgeoroutecopy); // QGeoRoute uses a QExplicitlySharedDataPointer. no implicit detach() + delete qgeoroutecopy; } @@ -263,7 +271,7 @@ void tst_QGeoRoute::operators() QVERIFY(qgeoroute->operator ==(*qgeoroutecopy)); QVERIFY(!qgeoroute->operator !=(*qgeoroutecopy)); - qgeoroute->setDistance(543.324); + qgeoroute->setDistance(543.324); // QExplicitlySharedDataPointer does not detach implicitly. qgeoroute->setRouteId("RouteId 111"); qgeoroute->setTravelMode(QGeoRouteRequest::PedestrianTravel); qgeoroute->setTravelTime(10); @@ -282,6 +290,14 @@ void tst_QGeoRoute::operators() QVERIFY(qgeoroute->operator ==(*qgeoroutecopy)); QVERIFY(!qgeoroute->operator !=(*qgeoroutecopy)); + + QGeoRouteAlt rAlt; + QGeoRoute r; + QCOMPARE(rAlt.travelTime(), 123456); + QCOMPARE(r.travelTime(), 0); + r = rAlt; + QCOMPARE(r.travelTime(), 123456); + delete qgeoroutecopy; } -- cgit v1.2.3 From 20c21955c2ccfd2bf5ec285b8b488f3bf89c269b Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Fri, 12 Jan 2018 13:16:50 +0100 Subject: Fix property name in tst_place.qml Change-Id: I8d0209d3bed93a60692210f985ce65d58ce5d6ca Reviewed-by: Alex Blasche --- tests/auto/declarative_core/tst_place.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/declarative_core/tst_place.qml b/tests/auto/declarative_core/tst_place.qml index 459b8f33..bb789b42 100644 --- a/tests/auto/declarative_core/tst_place.qml +++ b/tests/auto/declarative_core/tst_place.qml @@ -134,7 +134,7 @@ TestCase { function compare_place(place1, place2) { // check simple properties var simpleProperties = ["name", "placeId", "primaryPhone", "primaryFax", "primaryEmail", - "primaryUrl", "visibility"]; + "primaryWebsite", "visibility"]; for (x in simpleProperties) { if (place1[simpleProperties[x]] !== place2[simpleProperties[x]]) return false; -- cgit v1.2.3 From 723b69ecd818e42cf3f0b63e69872edc847be549 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Fri, 12 Jan 2018 18:12:27 +0100 Subject: Move QML/Cpp list conversions into locationvaluetypehelper Change-Id: Iee7f48f7d24b40a2824775654030397617c40640 Reviewed-by: Alex Blasche --- .../declarativemaps/locationvaluetypehelper.cpp | 41 ++++++++++++++++++++++ .../declarativemaps/locationvaluetypehelper_p.h | 3 +- .../declarativemaps/qdeclarativepolygonmapitem.cpp | 29 ++------------- .../qdeclarativepolylinemapitem.cpp | 31 ++-------------- 4 files changed, 47 insertions(+), 57 deletions(-) diff --git a/src/location/declarativemaps/locationvaluetypehelper.cpp b/src/location/declarativemaps/locationvaluetypehelper.cpp index 5f75e225..cda37b5f 100644 --- a/src/location/declarativemaps/locationvaluetypehelper.cpp +++ b/src/location/declarativemaps/locationvaluetypehelper.cpp @@ -36,6 +36,8 @@ #include "locationvaluetypehelper_p.h" #include +#include +#include QGeoCoordinate parseCoordinate(const QJSValue &value, bool *ok) @@ -145,3 +147,42 @@ QGeoCircle parseCircle(const QJSValue &value, bool *ok) return c; } + +QJSValue fromList(const QObject *object, const QList &list) +{ + QQmlContext *context = QQmlEngine::contextForObject(object); + QQmlEngine *engine = context->engine(); + QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); + + QV4::Scope scope(v4); + QV4::Scoped pathArray(scope, v4->newArrayObject(list.length())); + int i = 0; + for (const auto &val : list) { + QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(val))); + pathArray->putIndexed(i++, cv); + } + + return QJSValue(v4, pathArray.asReturnedValue()); +} + +QList toList(const QObject *object, const QJSValue &value) +{ + if (!value.isArray()) + return {}; + + QList pathList; + quint32 length = value.property(QStringLiteral("length")).toUInt(); + for (quint32 i = 0; i < length; ++i) { + bool ok; + QGeoCoordinate c = parseCoordinate(value.property(i), &ok); + + if (!ok || !c.isValid()) { + qmlWarning(object) << "Unsupported path type"; + return {}; + } + + pathList.append(c); + } + + return pathList; +} diff --git a/src/location/declarativemaps/locationvaluetypehelper_p.h b/src/location/declarativemaps/locationvaluetypehelper_p.h index 09f3ab06..7b005fe6 100644 --- a/src/location/declarativemaps/locationvaluetypehelper_p.h +++ b/src/location/declarativemaps/locationvaluetypehelper_p.h @@ -58,5 +58,6 @@ QGeoCoordinate parseCoordinate(const QJSValue &value, bool *ok = nullptr); QGeoCoordinate parseCoordinate(const QVariant &value, bool *ok = nullptr); QGeoRectangle parseRectangle(const QJSValue &value, bool *ok); QGeoCircle parseCircle(const QJSValue &value, bool *ok); - +QJSValue fromList(const QObject *object, const QList &list); +QList toList(const QObject *object, const QJSValue &value); #endif diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp index 7460a376..8c7afc17 100644 --- a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp +++ b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp @@ -380,20 +380,7 @@ void QDeclarativePolygonMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap *m */ QJSValue QDeclarativePolygonMapItem::path() const { - QQmlContext *context = QQmlEngine::contextForObject(this); - QQmlEngine *engine = context->engine(); - QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); - - QV4::Scope scope(v4); - QV4::Scoped pathArray(scope, v4->newArrayObject(geopath_.path().length())); - for (int i = 0; i < geopath_.path().length(); ++i) { - const QGeoCoordinate &c = geopath_.coordinateAt(i); - - QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(c))); - pathArray->putIndexed(i, cv); - } - - return QJSValue(v4, pathArray.asReturnedValue()); + return fromList(this, geopath_.path()); } void QDeclarativePolygonMapItem::setPath(const QJSValue &value) @@ -401,19 +388,7 @@ void QDeclarativePolygonMapItem::setPath(const QJSValue &value) if (!value.isArray()) return; - QList pathList; - quint32 length = value.property(QStringLiteral("length")).toUInt(); - for (quint32 i = 0; i < length; ++i) { - bool ok; - QGeoCoordinate c = parseCoordinate(value.property(i), &ok); - - if (!ok || !c.isValid()) { - qmlWarning(this) << "Unsupported path type"; - return; - } - - pathList.append(c); - } + QList pathList = toList(this, value); // Equivalent to QDeclarativePolylineMapItem::setPathFromGeoList if (geopath_.path() == pathList) diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp index a97271aa..7c1b922f 100644 --- a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp +++ b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp @@ -455,20 +455,7 @@ void QDeclarativePolylineMapItem::setMap(QDeclarativeGeoMap *quickMap, QGeoMap * QJSValue QDeclarativePolylineMapItem::path() const { - QQmlContext *context = QQmlEngine::contextForObject(this); - QQmlEngine *engine = context->engine(); - QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(engine); - - QV4::Scope scope(v4); - QV4::Scoped pathArray(scope, v4->newArrayObject(geopath_.path().length())); - for (int i = 0; i < geopath_.path().length(); ++i) { - const QGeoCoordinate &c = geopath_.coordinateAt(i); - - QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(c))); - pathArray->putIndexed(i, cv); - } - - return QJSValue(v4, pathArray.asReturnedValue()); + return fromList(this, geopath_.path()); } void QDeclarativePolylineMapItem::setPath(const QJSValue &value) @@ -476,21 +463,7 @@ void QDeclarativePolylineMapItem::setPath(const QJSValue &value) if (!value.isArray()) return; - QList pathList; - quint32 length = value.property(QStringLiteral("length")).toUInt(); - for (quint32 i = 0; i < length; ++i) { - bool ok; - QGeoCoordinate c = parseCoordinate(value.property(i), &ok); - - if (!ok || !c.isValid()) { - qmlWarning(this) << "Unsupported path type"; - return; - } - - pathList.append(c); - } - - setPathFromGeoList(pathList); + setPathFromGeoList(toList(this, value)); } /*! -- cgit v1.2.3 From 2ad79b69958f38d4ad6b0965d9563c5ab794ecfa Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Tue, 23 Jan 2018 13:23:39 +0100 Subject: Add static QGeoMapPrivate *QGeoMapPrivate::get The intended use is inside map object implementations, where the objects have only a pointer to QGeoMap, but may need to access the SDK specific data. Change-Id: If37fc7d77a8670e03e78053ee747f2b64c2b9deb Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/location/maps/qgeomap.cpp | 5 +++++ src/location/maps/qgeomap_p_p.h | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index f9a72d14..fd03de01 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -277,6 +277,11 @@ const QGeoCameraCapabilities &QGeoMapPrivate::cameraCapabilities() const return m_cameraCapabilities; } +const QGeoMapPrivate *QGeoMapPrivate::get(const QGeoMap &map) +{ + return map.d_func(); +} + void QGeoMapPrivate::addParameter(QGeoMapParameter *param) { Q_UNUSED(param) diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h index ec498484..ef57ceb2 100644 --- a/src/location/maps/qgeomap_p_p.h +++ b/src/location/maps/qgeomap_p_p.h @@ -77,6 +77,9 @@ public: const QGeoProjection *geoProjection() const; void setCameraCapabilities(const QGeoCameraCapabilities &cameraCapabilities); const QGeoCameraCapabilities &cameraCapabilities() const; + + static const QGeoMapPrivate *get(const QGeoMap &map); + protected: /* Hooks into the actual map implementations */ virtual void addParameter(QGeoMapParameter *param); -- cgit v1.2.3 From eb8a6480201e6594ef07affda616892ea1824c24 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Fri, 12 Jan 2018 18:21:20 +0100 Subject: Extend QParameterizableObject to accept any QObject as quick child In this way, not only map parameters can be nested, but also QGeoMapObjects themselves, allowing to avoid one long standing limitation present in map items, where nested items have never been supported. Change-Id: I90ec7a6aeb1d91a38182258b422b8c60bcc9616e Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../declarativemaps/qparameterizableobject.cpp | 42 ++++++++++++---------- .../declarativemaps/qparameterizableobject_p.h | 33 +++++++++++------ 2 files changed, 46 insertions(+), 29 deletions(-) diff --git a/src/location/declarativemaps/qparameterizableobject.cpp b/src/location/declarativemaps/qparameterizableobject.cpp index a95f290e..0e138b86 100644 --- a/src/location/declarativemaps/qparameterizableobject.cpp +++ b/src/location/declarativemaps/qparameterizableobject.cpp @@ -44,41 +44,45 @@ QParameterizableObject::QParameterizableObject(QObject *parent) : QObject(parent) {} -QQmlListProperty QParameterizableObject::declarativeParameters() +void QParameterizableObject::appendChild(QObject *v) { - return QQmlListProperty(this, nullptr, - &QParameterizableObject::append, - &QParameterizableObject::count, - &QParameterizableObject::at, - &QParameterizableObject::clear); + m_children.append(v); } -QList QParameterizableObject::parameters() const +void QParameterizableObject::clearChildren() { - QList params; - for (auto param : qAsConst(m_parameters)) - params << param; - return params; + m_children.clear(); } -void QParameterizableObject::append(QQmlListProperty *p, QDeclarativeGeoMapParameter *v) +QQmlListProperty QParameterizableObject::declarativeChildren() { - static_cast(p->object)->m_parameters.append(v); + return QQmlListProperty(this, nullptr, + &QParameterizableObject::append, + &QParameterizableObject::count, + &QParameterizableObject::at, + &QParameterizableObject::clear); } -int QParameterizableObject::count(QQmlListProperty *p) +void QParameterizableObject::append(QQmlListProperty *p, QObject *v) { - return static_cast(p->object)->m_parameters.count(); + QParameterizableObject *object = static_cast(p->object); + object->appendChild(v); } -QDeclarativeGeoMapParameter *QParameterizableObject::at(QQmlListProperty *p, int idx) +int QParameterizableObject::count(QQmlListProperty *p) { - return static_cast(p->object)->m_parameters.at(idx); + return static_cast(p->object)->m_children.count(); } -void QParameterizableObject::clear(QQmlListProperty *p) +QObject *QParameterizableObject::at(QQmlListProperty *p, int idx) { - static_cast(p->object)->m_parameters.clear(); + return static_cast(p->object)->m_children.at(idx); +} + +void QParameterizableObject::clear(QQmlListProperty *p) +{ + QParameterizableObject *object = static_cast(p->object); + object->clearChildren(); } QT_END_NAMESPACE diff --git a/src/location/declarativemaps/qparameterizableobject_p.h b/src/location/declarativemaps/qparameterizableobject_p.h index c6118c93..e450c6ec 100644 --- a/src/location/declarativemaps/qparameterizableobject_p.h +++ b/src/location/declarativemaps/qparameterizableobject_p.h @@ -54,26 +54,39 @@ #include QT_BEGIN_NAMESPACE -class QDeclarativeGeoMapParameter; class QGeoMapParameter; class Q_LOCATION_PRIVATE_EXPORT QParameterizableObject : public QObject { Q_OBJECT - Q_PROPERTY(QQmlListProperty parameters READ declarativeParameters DESIGNABLE false) - Q_CLASSINFO("DefaultProperty", "parameters") + Q_PROPERTY(QQmlListProperty quickChildren READ declarativeChildren DESIGNABLE false) + Q_CLASSINFO("DefaultProperty", "quickChildren") public: explicit QParameterizableObject(QObject *parent = nullptr); - QList parameters() const; + + template + QList quickChildren() const + { + QList res; + for (auto kid : qAsConst(m_children)) { + auto val = qobject_cast(kid); + if (val) + res.push_back(val); + } + return res; + } protected: - static void append(QQmlListProperty *p, QDeclarativeGeoMapParameter *v); - static int count(QQmlListProperty *p); - static QDeclarativeGeoMapParameter *at(QQmlListProperty *p, int idx); - static void clear(QQmlListProperty *p); + virtual void appendChild(QObject *v); + virtual void clearChildren(); + + static void append(QQmlListProperty *p, QObject *v); + static int count(QQmlListProperty *p); + static QObject *at(QQmlListProperty *p, int idx); + static void clear(QQmlListProperty *p); - QQmlListProperty declarativeParameters(); - QList m_parameters; + QQmlListProperty declarativeChildren(); + QList m_children; }; QT_END_NAMESPACE -- cgit v1.2.3 From 05f635b24a9a290beae8eac2ade5ab77ade45b38 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Fri, 12 Jan 2018 18:22:49 +0100 Subject: Allow to extract pimpl from QGeoRoute Needed to properly implement Navigators, which only get QGeoRoutes, and may find easier to directly access the private implementation rather than going through the routeId. Change-Id: I6c23d7b5336d1fb99fad3cf588cbf78437e0563f Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/location/maps/qgeoroute.cpp | 5 +++++ src/location/maps/qgeoroute.h | 1 + src/location/maps/qgeoroute_p.h | 2 ++ 3 files changed, 8 insertions(+) diff --git a/src/location/maps/qgeoroute.cpp b/src/location/maps/qgeoroute.cpp index 2e7b259a..d2f6fb51 100644 --- a/src/location/maps/qgeoroute.cpp +++ b/src/location/maps/qgeoroute.cpp @@ -414,6 +414,11 @@ QGeoRouteSegment QGeoRoutePrivate::firstSegment() const return QGeoRouteSegment(); } +const QGeoRoutePrivate *QGeoRoutePrivate::routePrivateData(const QGeoRoute &route) +{ + return route.d_ptr.data(); +} + /******************************************************************************* *******************************************************************************/ diff --git a/src/location/maps/qgeoroute.h b/src/location/maps/qgeoroute.h index 7dee719f..de319b4c 100644 --- a/src/location/maps/qgeoroute.h +++ b/src/location/maps/qgeoroute.h @@ -91,6 +91,7 @@ protected: QGeoRoute(const QExplicitlySharedDataPointer &dd); QExplicitlySharedDataPointer d_ptr; friend class QDeclarativeGeoRoute; + friend class QGeoRoutePrivate; }; QT_END_NAMESPACE diff --git a/src/location/maps/qgeoroute_p.h b/src/location/maps/qgeoroute_p.h index 26eb613c..d56b2d44 100644 --- a/src/location/maps/qgeoroute_p.h +++ b/src/location/maps/qgeoroute_p.h @@ -97,6 +97,8 @@ public: virtual QString engineName() const = 0; virtual int segmentsCount() const = 0; + static const QGeoRoutePrivate *routePrivateData(const QGeoRoute &route); + protected: virtual bool equals(const QGeoRoutePrivate &other) const; }; -- cgit v1.2.3 From 5a6b1a0cff406a37faca940ae3b0e774c6d1c4d6 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Fri, 12 Jan 2018 17:16:39 +0100 Subject: Add QNavigationManager/QNavigationManagerEngine This patch introduces the abovementioned classes to be subclassed in plugins. These are currently private, and intended to be only used in QML through appropriate wrappers. Change-Id: I4a063031a983e4bd070f503e1458b62e44c6e340 Reviewed-by: Eskil Abrahamsen Blomfeldt --- .../qdeclarativegeoserviceprovider.cpp | 49 +++++++- .../qdeclarativegeoserviceprovider_p.h | 11 ++ src/location/maps/maps.pri | 4 + src/location/maps/qgeoserviceprovider.cpp | 43 ++++++- src/location/maps/qgeoserviceprovider.h | 15 +++ src/location/maps/qgeoserviceprovider_p.h | 3 + src/location/maps/qgeoserviceproviderfactory.cpp | 22 ++++ src/location/maps/qgeoserviceproviderfactory.h | 3 + src/location/maps/qnavigationmanager.cpp | 115 +++++++++++++++++++ src/location/maps/qnavigationmanager_p.h | 93 +++++++++++++++ src/location/maps/qnavigationmanagerengine.cpp | 126 +++++++++++++++++++++ src/location/maps/qnavigationmanagerengine_p.h | 104 +++++++++++++++++ 12 files changed, 581 insertions(+), 7 deletions(-) create mode 100644 src/location/maps/qnavigationmanager.cpp create mode 100644 src/location/maps/qnavigationmanager_p.h create mode 100644 src/location/maps/qnavigationmanagerengine.cpp create mode 100644 src/location/maps/qnavigationmanagerengine_p.h diff --git a/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp b/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp index 9e4fee8a..39d0394b 100644 --- a/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp +++ b/src/location/declarativemaps/qdeclarativegeoserviceprovider.cpp @@ -57,8 +57,8 @@ QT_BEGIN_NAMESPACE Plugins recognized by the system have a \l name property, a simple string normally indicating the name of the service that the Plugin retrieves data from. They also have a variety of features, which can be test for using the - \l {supportsRouting()}, \l {supportsGeocoding()}, \l {supportsMapping()} and - \l {supportsPlaces()} methods. + \l {supportsRouting()}, \l {supportsGeocoding()}, \l {supportsMapping()}, + \l {supportsPlaces()} and \l {supportsNavigation()} methods. When a Plugin object is created, it is "detached" and not associated with any actual service plugin. Once it has received information via setting @@ -226,8 +226,8 @@ void QDeclarativeGeoServiceProvider::componentComplete() \qmlmethod bool Plugin::supportsGeocoding(GeocodingFeatures features) This method returns a boolean indicating whether the specified set of \a features are supported - by the geo service provider plugin. True is returned if all specified \a features are - supported; otherwise false is returned. + by the geo service provider plugin. \c True is returned if all specified \a features are + supported; otherwise \c false is returned. The \a features parameter can be any flag combination of: \table @@ -401,17 +401,54 @@ bool QDeclarativeGeoServiceProvider::supportsRouting(const RoutingFeatures &feat \li Matches a geo service provider that provides any places features. \endtable */ -bool QDeclarativeGeoServiceProvider::supportsPlaces(const PlacesFeatures &features) const +bool QDeclarativeGeoServiceProvider::supportsPlaces(const PlacesFeatures &feature) const { QGeoServiceProvider *sp = sharedGeoServiceProvider(); QGeoServiceProvider::PlacesFeatures f = - static_cast(int(features)); + static_cast(int(feature)); if (f == QGeoServiceProvider::AnyPlacesFeatures) return (sp && (sp->placesFeatures() != QGeoServiceProvider::NoPlacesFeatures)); else return (sp && (sp->placesFeatures() & f) == f); } +/*! + \qmlmethod bool Plugin::supportsNavigation(NavigationFeatures features) + + This method returns a boolean indicating whether the specified set of \a features are supported + by the geo service provider plugin. True is returned if all specified \a features are + supported; otherwise false is returned. + + The \a features parameter can be any flag combination of: + \table + \header + \li Feature + \li Description + \row + \li Plugin.NoNavigationFeatures + \li No navigation features are supported. + \row + \li Plugin.OnlineNavigationFeature + \li Online navigation is supported. + \row + \li Plugin.OfflineNavigationFeature + \li Offline navigation is supported. + \row + \li Plugin.AnyNavigationFeatures + \li Matches a geo service provider that provides any navigation features. + \endtable +*/ +bool QDeclarativeGeoServiceProvider::supportsNavigation(const QDeclarativeGeoServiceProvider::NavigationFeature &feature) const +{ + QGeoServiceProvider *sp = sharedGeoServiceProvider(); + QGeoServiceProvider::NavigationFeatures f = + static_cast(int(feature)); + if (f == QGeoServiceProvider::AnyNavigationFeatures) + return (sp && (sp->navigationFeatures() != QGeoServiceProvider::NoNavigationFeatures)); + else + return (sp && (sp->navigationFeatures() & f) == f); +} + /*! \qmlproperty enumeration Plugin::required diff --git a/src/location/declarativemaps/qdeclarativegeoserviceprovider_p.h b/src/location/declarativemaps/qdeclarativegeoserviceprovider_p.h index c1ad4987..2add07dd 100644 --- a/src/location/declarativemaps/qdeclarativegeoserviceprovider_p.h +++ b/src/location/declarativemaps/qdeclarativegeoserviceprovider_p.h @@ -160,6 +160,13 @@ public: AnyPlacesFeatures = QGeoServiceProvider::AnyPlacesFeatures }; + enum NavigationFeature { + NoNavigationFeatures = QGeoServiceProvider::NoNavigationFeatures, + OnlineNavigationFeature = QGeoServiceProvider::OnlineNavigationFeature, + OfflineNavigationFeature = QGeoServiceProvider::OfflineNavigationFeature, + AnyNavigationFeatures = QGeoServiceProvider::AnyNavigationFeatures + }; + Q_DECLARE_FLAGS(RoutingFeatures, RoutingFeature) Q_FLAGS(RoutingFeatures) @@ -172,6 +179,9 @@ public: Q_DECLARE_FLAGS(PlacesFeatures, PlacesFeature) Q_FLAGS(PlacesFeatures) + Q_DECLARE_FLAGS(NavigationFeatures, NavigationFeature) + Q_FLAGS(NavigationFeatures) + // From QQmlParserStatus virtual void classBegin() {} virtual void componentComplete(); @@ -196,6 +206,7 @@ public: Q_INVOKABLE bool supportsGeocoding(const GeocodingFeatures &feature = AnyGeocodingFeatures) const; Q_INVOKABLE bool supportsMapping(const MappingFeatures &feature = AnyMappingFeatures) const; Q_INVOKABLE bool supportsPlaces(const PlacesFeatures &feature = AnyPlacesFeatures) const; + Q_INVOKABLE bool supportsNavigation(const NavigationFeature &feature = AnyNavigationFeatures) const; QStringList locales() const; void setLocales(const QStringList &locales); diff --git a/src/location/maps/maps.pri b/src/location/maps/maps.pri index aaad5897..b5be4601 100644 --- a/src/location/maps/maps.pri +++ b/src/location/maps/maps.pri @@ -60,6 +60,8 @@ PRIVATE_HEADERS += \ maps/qgeorouteparserosrmv5_p.h \ maps/qgeorouteparserosrmv4_p.h \ maps/qgeoprojection_p.h \ + maps/qnavigationmanagerengine_p.h \ + maps/qnavigationmanager_p.h \ maps/qcache3q_p.h SOURCES += \ @@ -95,4 +97,6 @@ SOURCES += \ maps/qgeorouteparserosrmv5.cpp \ maps/qgeorouteparserosrmv4.cpp \ maps/qgeomapparameter.cpp \ + maps/qnavigationmanagerengine.cpp \ + maps/qnavigationmanager.cpp \ maps/qgeoprojection.cpp diff --git a/src/location/maps/qgeoserviceprovider.cpp b/src/location/maps/qgeoserviceprovider.cpp index 7e7b3c90..4c4b5a02 100644 --- a/src/location/maps/qgeoserviceprovider.cpp +++ b/src/location/maps/qgeoserviceprovider.cpp @@ -42,11 +42,13 @@ #include "qgeomappingmanager_p.h" #include "qgeoroutingmanager.h" #include "qplacemanager.h" +#include "qnavigationmanager_p.h" #include "qgeocodingmanagerengine.h" #include "qgeomappingmanagerengine_p.h" #include "qgeoroutingmanagerengine.h" #include "qplacemanagerengine.h" #include "qplacemanagerengine_p.h" +#include "qnavigationmanagerengine_p.h" #include #include @@ -201,6 +203,18 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, features. */ +/*! + \enum QGeoServiceProvider::NavigationFeature + + Describes the navigation features supported by the geo service provider. + + \value NoNavigationFeatures No navigation features are supported. + \value OnlineNavigationFeature Online navigation is supported. + \value OfflineNavigationFeature Offline navigation is supported. + \value AnyNavigationFeatures Matches a geo service provider that provides any navigation + features. +*/ + /*! Returns a list of names of the available service providers, for use with the QGeoServiceProvider constructors. @@ -310,6 +324,16 @@ QGeoServiceProvider::PlacesFeatures QGeoServiceProvider::placesFeatures() const return d_ptr->features("PlacesFeatures"); } +/*! + Returns the navigation features supported by the geo service provider. + + \since QtLocation 5.11 +*/ +QGeoServiceProvider::NavigationFeatures QGeoServiceProvider::navigationFeatures() const +{ + return d_ptr->features("NavigationFeatures"); +} + /* Sadly, these are necessary to figure out which of the factory->createX * methods we need to call. Ideally it would be nice to find a way to embed * these into the manager() template. */ @@ -334,6 +358,10 @@ template <> QPlaceManagerEngine *createEngine(QGeoServicePr { return d_ptr->factory->createPlaceManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->placeError), &(d_ptr->placeErrorString)); } +template <> QNavigationManagerEngine *createEngine(QGeoServiceProviderPrivate *d_ptr) +{ + return d_ptr->factory->createNavigationManagerEngine(d_ptr->cleanedParameterMap, &(d_ptr->placeError), &(d_ptr->placeErrorString)); +} /* Template for generating the code for each of the geocodingManager(), * mappingManager() etc methods */ @@ -493,7 +521,20 @@ QPlaceManager *QGeoServiceProvider::placeManager() const { return d_ptr->manager( &(d_ptr->placeError), &(d_ptr->placeErrorString), - &(d_ptr->placeManager)); + &(d_ptr->placeManager)); +} + +/*! + Returns a new QNavigationManager made available by the service provider. + + After this function has been called, error() and errorString() will + report any errors which occurred during the construction of the QNavigationManagerEngine. +*/ +QNavigationManager *QGeoServiceProvider::navigationManager() const +{ + return d_ptr->manager( + &(d_ptr->navigationError), &(d_ptr->navigationErrorString), + &(d_ptr->navigationManager)); } /*! diff --git a/src/location/maps/qgeoserviceprovider.h b/src/location/maps/qgeoserviceprovider.h index ea8c2b61..640e9843 100644 --- a/src/location/maps/qgeoserviceprovider.h +++ b/src/location/maps/qgeoserviceprovider.h @@ -50,10 +50,12 @@ class QGeoCodingManager; class QGeoMappingManager; class QGeoRoutingManager; class QPlaceManager; +class QNavigationManager; class QGeoCodingManagerEngine; class QGeoMappingManagerEngine; class QGeoRoutingManagerEngine; class QPlaceManagerEngine; +class QNavigationManagerEngine; class QGeoServiceProviderPrivate; class Q_LOCATION_EXPORT QGeoServiceProvider : public QObject @@ -113,6 +115,13 @@ public: AnyPlacesFeatures = ~(0) }; + enum NavigationFeature { + NoNavigationFeatures = 0, + OnlineNavigationFeature = (1<<0), + OfflineNavigationFeature = (1<<1), + AnyNavigationFeatures = ~(0) + }; + Q_DECLARE_FLAGS(RoutingFeatures, RoutingFeature) Q_FLAGS(RoutingFeatures) @@ -125,6 +134,9 @@ public: Q_DECLARE_FLAGS(PlacesFeatures, PlacesFeature) Q_FLAGS(PlacesFeatures) + Q_DECLARE_FLAGS(NavigationFeatures, NavigationFeature) + Q_FLAGS(NavigationFeatures) + static QStringList availableServiceProviders(); QGeoServiceProvider(const QString &providerName, const QVariantMap ¶meters = QVariantMap(), @@ -136,11 +148,13 @@ public: GeocodingFeatures geocodingFeatures() const; MappingFeatures mappingFeatures() const; PlacesFeatures placesFeatures() const; + NavigationFeatures navigationFeatures() const; QGeoCodingManager *geocodingManager() const; QGeoMappingManager *mappingManager() const; QGeoRoutingManager *routingManager() const; QPlaceManager *placeManager() const; + QNavigationManager *navigationManager() const; Error error() const; QString errorString() const; @@ -157,6 +171,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoServiceProvider::RoutingFeatures) Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoServiceProvider::GeocodingFeatures) Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoServiceProvider::MappingFeatures) Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoServiceProvider::PlacesFeatures) +Q_DECLARE_OPERATORS_FOR_FLAGS(QGeoServiceProvider::NavigationFeatures) QT_END_NAMESPACE diff --git a/src/location/maps/qgeoserviceprovider_p.h b/src/location/maps/qgeoserviceprovider_p.h index 6bfb9b26..6703bf67 100644 --- a/src/location/maps/qgeoserviceprovider_p.h +++ b/src/location/maps/qgeoserviceprovider_p.h @@ -93,16 +93,19 @@ public: QGeoRoutingManager *routingManager; QGeoMappingManager *mappingManager; QPlaceManager *placeManager; + QNavigationManager *navigationManager; QGeoServiceProvider::Error geocodeError; QGeoServiceProvider::Error routingError; QGeoServiceProvider::Error mappingError; QGeoServiceProvider::Error placeError; + QGeoServiceProvider::Error navigationError; QString geocodeErrorString; QString routingErrorString; QString mappingErrorString; QString placeErrorString; + QString navigationErrorString; QGeoServiceProvider::Error error; QString errorString; diff --git a/src/location/maps/qgeoserviceproviderfactory.cpp b/src/location/maps/qgeoserviceproviderfactory.cpp index 7efc8a9f..c8192a32 100644 --- a/src/location/maps/qgeoserviceproviderfactory.cpp +++ b/src/location/maps/qgeoserviceproviderfactory.cpp @@ -160,4 +160,26 @@ QPlaceManagerEngine *QGeoServiceProviderFactory::createPlaceManagerEngine(const return 0; } +/*! + Returns a new QNavigationManagerEngine instance, initialized with \a + parameters, which implements navigation functionality. + + If \a error is not nullptr, it should be set to QGeoServiceProvider::NoError on + success or an appropriate QGeoServiceProvider::Error on failure. + + If \a errorString is not nullptr, it should be set to a string describing any + error which occurred. + + The default implementation returns nullptr, which causes a + QGeoServiceProvider::NotSupportedError in QGeoServiceProvider. +*/ +QNavigationManagerEngine *QGeoServiceProviderFactory::createNavigationManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const +{ + Q_UNUSED(parameters) + Q_UNUSED(error) + Q_UNUSED(errorString) + + return 0; +} + QT_END_NAMESPACE diff --git a/src/location/maps/qgeoserviceproviderfactory.h b/src/location/maps/qgeoserviceproviderfactory.h index cc60cf7c..e1164189 100644 --- a/src/location/maps/qgeoserviceproviderfactory.h +++ b/src/location/maps/qgeoserviceproviderfactory.h @@ -62,6 +62,9 @@ public: virtual QPlaceManagerEngine *createPlaceManagerEngine(const QVariantMap ¶meters, QGeoServiceProvider::Error *error, QString *errorString) const; + virtual QNavigationManagerEngine *createNavigationManagerEngine(const QVariantMap ¶meters, + QGeoServiceProvider::Error *error, + QString *errorString) const; }; Q_DECLARE_INTERFACE(QGeoServiceProviderFactory, diff --git a/src/location/maps/qnavigationmanager.cpp b/src/location/maps/qnavigationmanager.cpp new file mode 100644 index 00000000..1e83b2c9 --- /dev/null +++ b/src/location/maps/qnavigationmanager.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qnavigationmanager_p.h" +#include "qnavigationmanagerengine_p.h" + +QT_BEGIN_NAMESPACE + +class QNavigationManagerPrivate +{ +public: + QNavigationManagerPrivate(); + ~QNavigationManagerPrivate(); + + QNavigationManagerEngine *engine = nullptr; + +private: + Q_DISABLE_COPY(QNavigationManagerPrivate) +}; + +QNavigationManagerPrivate::QNavigationManagerPrivate() +{ + +} + +QNavigationManagerPrivate::~QNavigationManagerPrivate() +{ + delete engine; + engine = nullptr; +} + +QNavigationManager::~QNavigationManager() +{ + delete d_ptr; +} + +QString QNavigationManager::managerName() const +{ + return d_ptr->engine->managerName(); +} + +int QNavigationManager::managerVersion() const +{ + return d_ptr->engine->managerVersion(); +} + +QNavigationManagerEngine *QNavigationManager::engine() +{ + return d_ptr->engine; +} + +bool QNavigationManager::isInitialized() const +{ + return d_ptr->engine->isInitialized(); +} + +void QNavigationManager::setLocale(const QLocale &locale) +{ + d_ptr->engine->setLocale(locale); +} + +QLocale QNavigationManager::locale() const +{ + return d_ptr->engine->locale(); +} + +QNavigationManager::QNavigationManager(QNavigationManagerEngine *engine, QObject *parent) : QObject(parent), + d_ptr(new QNavigationManagerPrivate) +{ + d_ptr->engine = engine; + if (!d_ptr->engine) { + qFatal("The navigation manager engine that was set for this mapping manager was NULL."); + } + + connect(d_ptr->engine, + SIGNAL(initialized()), + this, + SIGNAL(initialized()), + Qt::QueuedConnection); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qnavigationmanager_p.h b/src/location/maps/qnavigationmanager_p.h new file mode 100644 index 00000000..e461bcf1 --- /dev/null +++ b/src/location/maps/qnavigationmanager_p.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNAVIGATIONMANAGER_P_H +#define QNAVIGATIONMANAGER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QNavigationManagerEngine; +class QNavigationManagerPrivate; +class Q_LOCATION_PRIVATE_EXPORT QNavigationManager : public QObject +{ + Q_OBJECT + +public: + ~QNavigationManager(); + + QString managerName() const; + int managerVersion() const; + + QNavigationManagerEngine *engine(); + + bool isInitialized() const; + void setLocale(const QLocale &locale); + QLocale locale() const; + +Q_SIGNALS: + void initialized(); + +protected: + QNavigationManager(QNavigationManagerEngine *engine, QObject *parent = 0); + +private: + QNavigationManagerPrivate *d_ptr; + Q_DISABLE_COPY(QNavigationManager) + + friend class QGeoServiceProvider; + friend class QGeoServiceProviderPrivate; +}; + + +QT_END_NAMESPACE + +#endif // QNAVIGATIONMANAGER_P_H diff --git a/src/location/maps/qnavigationmanagerengine.cpp b/src/location/maps/qnavigationmanagerengine.cpp new file mode 100644 index 00000000..265237ee --- /dev/null +++ b/src/location/maps/qnavigationmanagerengine.cpp @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeoroute.h" +#include "qnavigationmanagerengine_p.h" + +QT_BEGIN_NAMESPACE + +class QNavigationManagerEnginePrivate +{ +public: + QString managerName; + int managerVersion; + QLocale locale; + QLocale::MeasurementSystem measurementSystem; + bool initialized = false; +}; + +QNavigationManagerEngine::QNavigationManagerEngine(const QVariantMap ¶meters, QObject *parent) + : QObject(parent) + , d_ptr(new QNavigationManagerEnginePrivate) +{ + Q_UNUSED(parameters) +} + +QNavigationManagerEngine::~QNavigationManagerEngine() +{ +} + +void QNavigationManagerEngine::setManagerName(const QString &name) +{ + d_ptr->managerName = name; +} + +QString QNavigationManagerEngine::managerName() const +{ + return d_ptr->managerName; +} + +void QNavigationManagerEngine::setManagerVersion(int version) +{ + d_ptr->managerVersion = version; +} + +int QNavigationManagerEngine::managerVersion() const +{ + return d_ptr->managerVersion; +} + +void QNavigationManagerEngine::setLocale(const QLocale &locale) +{ + d_ptr->locale = locale; +} + +QLocale QNavigationManagerEngine::locale() const +{ + return d_ptr->locale; +} + +void QNavigationManagerEngine::setMeasurementSystem(QLocale::MeasurementSystem system) +{ + d_ptr->measurementSystem = system; +} + +QLocale::MeasurementSystem QNavigationManagerEngine::measurementSystem() const +{ + return d_ptr->measurementSystem; +} + +bool QNavigationManagerEngine::isInitialized() const +{ + return d_ptr->initialized; +} + +bool QNavigationManagerEngine::start(const QList &navigationParams, const QMapRouteObject &route) +{ + Q_UNUSED(navigationParams); + Q_UNUSED(route); + return false; +} + +bool QNavigationManagerEngine::stop() +{ + return false; +} + +void QNavigationManagerEngine::engineInitialized() +{ + d_ptr->initialized = true; + emit initialized(); +} + +QT_END_NAMESPACE diff --git a/src/location/maps/qnavigationmanagerengine_p.h b/src/location/maps/qnavigationmanagerengine_p.h new file mode 100644 index 00000000..5b8bd185 --- /dev/null +++ b/src/location/maps/qnavigationmanagerengine_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QNAVIGATIONMANAGERENGINE_H +#define QNAVIGATIONMANAGERENGINE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMap; +class QGeoMapParameter; +class QMapRouteObject; +class QNavigationManagerEnginePrivate; + +class Q_LOCATION_PRIVATE_EXPORT QNavigationManagerEngine : public QObject +{ + Q_OBJECT +public: + explicit QNavigationManagerEngine(const QVariantMap ¶meters, QObject *parent = Q_NULLPTR); + virtual ~QNavigationManagerEngine(); + + void setManagerName(const QString &name); + QString managerName() const; + void setManagerVersion(int version); + int managerVersion() const; + + virtual void setLocale(const QLocale &locale); + virtual QLocale locale() const; + virtual void setMeasurementSystem(QLocale::MeasurementSystem system); + virtual QLocale::MeasurementSystem measurementSystem() const; + bool isInitialized() const; + +signals: + void activeChanged(bool active); + void waypointReached(const QGeoCoordinate &pos); + void destinationReached(); + void initialized(); + +public slots: + virtual bool start(const QList &navigationParams, const QMapRouteObject &route); + virtual bool stop(); + +protected: + /*! + Marks the engine as initialized. Subclasses of QGeoMappingManagerEngine are to + call this method after performing implementation-specific initialization within + the constructor. + */ + void engineInitialized(); + + QScopedPointer d_ptr; +}; + +QT_END_NAMESPACE + +#endif // QNAVIGATIONMANAGERENGINE_H -- cgit v1.2.3 From 0aa7ae19eafebd0b146f9d97e04bd171c213dd76 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Mon, 15 Jan 2018 17:56:49 +0100 Subject: Add QDeclarativeGeoRoute::route getter To allow private classes to access the embedded QGeoRoute without the need to be friend. Change-Id: I7184e1a9fd038af3b82d71671667cd5b2e3449a7 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/location/declarativemaps/qdeclarativegeoroute.cpp | 5 +++++ src/location/declarativemaps/qdeclarativegeoroute_p.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/location/declarativemaps/qdeclarativegeoroute.cpp b/src/location/declarativemaps/qdeclarativegeoroute.cpp index 5540263c..aab59dc2 100644 --- a/src/location/declarativemaps/qdeclarativegeoroute.cpp +++ b/src/location/declarativemaps/qdeclarativegeoroute.cpp @@ -301,4 +301,9 @@ int QDeclarativeGeoRoute::segmentsCount() const return qMax(route_.d_ptr->segmentsCount(), segments_.count()); } +const QGeoRoute &QDeclarativeGeoRoute::route() const +{ + return route_; +} + QT_END_NAMESPACE diff --git a/src/location/declarativemaps/qdeclarativegeoroute_p.h b/src/location/declarativemaps/qdeclarativegeoroute_p.h index 738d2089..2be3d3f1 100644 --- a/src/location/declarativemaps/qdeclarativegeoroute_p.h +++ b/src/location/declarativemaps/qdeclarativegeoroute_p.h @@ -85,6 +85,7 @@ public: void clearSegments(); int segmentsCount() const; + const QGeoRoute &route() const; Q_SIGNALS: void pathChanged(); -- cgit v1.2.3 From 466bf13d25a507bcaeae661b8d52aa1c6604d64f Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Mon, 22 Jan 2018 14:45:55 +0100 Subject: Export locationvaluehelper functions So they can be used also in the locationlabs module Change-Id: I57e1fba503af1250134f1fdbd922de81c72ffcd9 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/location/declarativemaps/locationvaluetypehelper_p.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/location/declarativemaps/locationvaluetypehelper_p.h b/src/location/declarativemaps/locationvaluetypehelper_p.h index 7b005fe6..79b4b6f8 100644 --- a/src/location/declarativemaps/locationvaluetypehelper_p.h +++ b/src/location/declarativemaps/locationvaluetypehelper_p.h @@ -48,16 +48,17 @@ // We mean it. // +#include #include #include #include #include #include -QGeoCoordinate parseCoordinate(const QJSValue &value, bool *ok = nullptr); -QGeoCoordinate parseCoordinate(const QVariant &value, bool *ok = nullptr); -QGeoRectangle parseRectangle(const QJSValue &value, bool *ok); -QGeoCircle parseCircle(const QJSValue &value, bool *ok); -QJSValue fromList(const QObject *object, const QList &list); -QList toList(const QObject *object, const QJSValue &value); +QGeoCoordinate Q_LOCATION_PRIVATE_EXPORT parseCoordinate(const QJSValue &value, bool *ok = nullptr); +QGeoCoordinate Q_LOCATION_PRIVATE_EXPORT parseCoordinate(const QVariant &value, bool *ok = nullptr); +QGeoRectangle Q_LOCATION_PRIVATE_EXPORT parseRectangle(const QJSValue &value, bool *ok); +QGeoCircle Q_LOCATION_PRIVATE_EXPORT parseCircle(const QJSValue &value, bool *ok); +QJSValue Q_LOCATION_PRIVATE_EXPORT fromList(const QObject *object, const QList &list); +QList Q_LOCATION_PRIVATE_EXPORT toList(const QObject *object, const QJSValue &value); #endif -- cgit v1.2.3 From 3aca8077a21d4219b62a03bdc790a2019eb072cc Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Tue, 16 Jan 2018 12:34:06 +0100 Subject: Add sync.profile and configure.json to .pro files So that they show up in creator and can be inspected/modified easily. Change-Id: Ice26038fd9542496ea98221d6a8b0b05620507dd Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Oswald Buddenhagen --- qtlocation.pro | 2 ++ src/location/location.pro | 2 +- src/positioning/positioning.pro | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/qtlocation.pro b/qtlocation.pro index 53069981..3d942a6f 100644 --- a/qtlocation.pro +++ b/qtlocation.pro @@ -3,3 +3,5 @@ qtCompileTest(gypsy) qtCompileTest(winrt) load(qt_parts) + +DISTFILES += sync.profile configure.json diff --git a/src/location/location.pro b/src/location/location.pro index f91a20d0..199c5bd2 100644 --- a/src/location/location.pro +++ b/src/location/location.pro @@ -22,7 +22,7 @@ MODULE_PLUGIN_TYPES = \ geoservices QMAKE_DOCS = $$PWD/doc/qtlocation.qdocconf -OTHER_FILES += doc/src/*.qdoc # show .qdoc files in Qt Creator +OTHER_FILES += configure.json doc/src/*.qdoc # show .qdoc files in Qt Creator PUBLIC_HEADERS += \ qlocation.h \ diff --git a/src/positioning/positioning.pro b/src/positioning/positioning.pro index 666e9b1a..17f47240 100644 --- a/src/positioning/positioning.pro +++ b/src/positioning/positioning.pro @@ -7,7 +7,7 @@ INCLUDEPATH += ../3rdparty/clipper INCLUDEPATH += ../3rdparty/clip2tri QMAKE_DOCS = $$PWD/doc/qtpositioning.qdocconf -OTHER_FILES += doc/src/*.qdoc # show .qdoc files in Qt Creator +OTHER_FILES += configure.json doc/src/*.qdoc # show .qdoc files in Qt Creator ANDROID_BUNDLED_JAR_DEPENDENCIES = \ jar/QtPositioning.jar:org.qtproject.qt5.android.positioning.QtPositioning -- cgit v1.2.3 From d8a7da2c00d9b292e56f28cf2df4f191e6edce2c Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Fri, 12 Jan 2018 18:23:28 +0100 Subject: Introduce QGeoMapObject QGeoMapObject is a new class of map item, not deriving anymore from QQuickItem, and designed to be more lightweight, and, most importantly, to be easily backable by SDK-specific implementations, so to act as an as thin as possible wrapper around those. QGeoMapObject is intended to be the base class for this type of items. This patch provides no mean to dynamically add/remove GeoMapObjects. The intended way to do it is by using a MapObjectView, coming initially with the Qt.labs.location extra plugin. Change-Id: I8d6a45a4a32059c7ec4d904f75352e176bffda1e Reviewed-by: Alex Blasche --- src/location/declarativemaps/declarativemaps.pri | 5 +- .../declarativemaps/qdeclarativegeomap.cpp | 96 +++++++- .../declarativemaps/qdeclarativegeomap_p.h | 9 + src/location/declarativemaps/qgeomapobject.cpp | 262 +++++++++++++++++++++ src/location/declarativemaps/qgeomapobject_p.h | 131 +++++++++++ src/location/declarativemaps/qgeomapobject_p_p.h | 92 ++++++++ src/location/maps/qgeomap.cpp | 30 +++ src/location/maps/qgeomap_p.h | 6 + src/location/maps/qgeomap_p_p.h | 3 + 9 files changed, 626 insertions(+), 8 deletions(-) create mode 100644 src/location/declarativemaps/qgeomapobject.cpp create mode 100644 src/location/declarativemaps/qgeomapobject_p.h create mode 100644 src/location/declarativemaps/qgeomapobject_p_p.h diff --git a/src/location/declarativemaps/declarativemaps.pri b/src/location/declarativemaps/declarativemaps.pri index e607ea2b..335dc55a 100644 --- a/src/location/declarativemaps/declarativemaps.pri +++ b/src/location/declarativemaps/declarativemaps.pri @@ -29,6 +29,8 @@ PRIVATE_HEADERS += \ declarativemaps/qdeclarativegeomapitemgroup_p.h \ declarativemaps/qparameterizableobject_p.h \ declarativemaps/mapitemviewdelegateincubator_p.h \ + declarativemaps/qgeomapobject_p.h \ + declarativemaps/qgeomapobject_p_p.h \ ../imports/positioning/qquickgeocoordinateanimation_p.h SOURCES += \ @@ -57,9 +59,8 @@ SOURCES += \ declarativemaps/qparameterizableobject.cpp \ declarativemaps/qdeclarativegeomapitemgroup.cpp \ declarativemaps/mapitemviewdelegateincubator.cpp \ + declarativemaps/qgeomapobject.cpp \ ../imports/positioning/qquickgeocoordinateanimation.cpp load(qt_build_paths) LIBS_PRIVATE += -L$$MODULE_BASE_OUTDIR/lib -lpoly2tri$$qtPlatformTargetSuffix() -lclip2tri$$qtPlatformTargetSuffix() - - diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp index 34885f54..42ed633d 100644 --- a/src/location/declarativemaps/qdeclarativegeomap.cpp +++ b/src/location/declarativemaps/qdeclarativegeomap.cpp @@ -43,6 +43,7 @@ #include "qgeocameracapabilities_p.h" #include "qgeomap_p.h" #include "qdeclarativegeomapparameter_p.h" +#include "qgeomapobject_p.h" #include #include #include @@ -102,15 +103,17 @@ QT_BEGIN_NAMESPACE \section2 Map Objects Map related objects can be declared within the body of a Map object in Qt Quick and will - automatically appear on the Map. To add objects programmatically, first be - sure they are created with the Map as their parent (for example in an argument to - Component::createObject), and then call the \l addMapItem method on the Map. + automatically appear on the Map. To add an object programmatically, first be + sure it is created with the Map as its parent (for example in an argument to + Component::createObject). + Then call the \l addMapItem method on the Map, if the type of this object is one of + \l MapCircle, \l MapRectangle, \l MapPolyline, \l MapPolygon, \l MapRoute or \l MapQuickItem. A corresponding \l removeMapItem method also exists to do the opposite and - remove an object from the Map. + remove any of the above types of map objects from the Map. Moving Map objects around, resizing them or changing their shape normally does not involve any special interaction with Map itself -- changing these - details about a map object will automatically update the display. + properties in a map object will automatically update the display. \section2 Interaction @@ -257,7 +260,7 @@ QDeclarativeGeoMap::~QDeclarativeGeoMap() delete m_copyrights.data(); m_copyrights.clear(); - delete m_map; + delete m_map; // map objects get reset here } /*! @@ -422,6 +425,9 @@ void QDeclarativeGeoMap::initialize() m_map->setCameraData(m_cameraData); + for (auto obj : qAsConst(m_pendingMapObjects)) + obj->setMap(m_map); + m_initialized = true; if (centerHasChanged) @@ -578,6 +584,10 @@ void QDeclarativeGeoMap::populateMap() addMapItemGroup(itemGroup); continue; } + + QGeoMapObject *mapObject = qobject_cast(k); + if (mapObject) + addMapObject(mapObject); } } @@ -1647,6 +1657,11 @@ QGeoServiceProvider::Error QDeclarativeGeoMap::error() const return m_error; } +QGeoMap *QDeclarativeGeoMap::map() const +{ + return m_map; +} + /*! \internal */ @@ -1845,6 +1860,75 @@ QList QDeclarativeGeoMap::mapParameters() return ret; } +/* + \internal +*/ +void QDeclarativeGeoMap::addMapObject(QGeoMapObject *object) +{ + if (!object || object->map()) + return; + + if (!m_initialized) { + m_pendingMapObjects.append(object); + return; + } + + int curObjects = m_map->mapObjects().size(); + // object adds itself to the map + object->setMap(m_map); + + if (curObjects != m_map->mapObjects().size()) + emit mapObjectsChanged(); +} + +/* + \internal +*/ +void QDeclarativeGeoMap::removeMapObject(QGeoMapObject *object) +{ + if (!object || object->map() != m_map) // if !initialized this is fine, since both object and m_map are supposed to be NULL + return; + + if (!m_initialized) { + m_pendingMapObjects.removeOne(object); + return; + } + + int curObjects = m_map->mapObjects().size(); + // object adds itself to the map + object->setMap(nullptr); + + if (curObjects != m_map->mapObjects().size()) + emit mapObjectsChanged(); +} + +/* + \internal +*/ +void QDeclarativeGeoMap::clearMapObjects() +{ + if (!m_initialized) { + m_pendingMapObjects.clear(); + } else { + const QList objs = m_map->mapObjects(); + for (QGeoMapObject *o: objs) + o->setMap(nullptr); + if (objs.size()) + emit mapObjectsChanged(); + } +} + +/* + \internal +*/ +QList QDeclarativeGeoMap::mapObjects() +{ + if (!m_initialized) + return m_pendingMapObjects; + else + return m_map->mapObjects(); +} + /*! \qmlproperty list QtLocation::Map::mapItems diff --git a/src/location/declarativemaps/qdeclarativegeomap_p.h b/src/location/declarativemaps/qdeclarativegeomap_p.h index 5c568d8f..27ee9822 100644 --- a/src/location/declarativemaps/qdeclarativegeomap_p.h +++ b/src/location/declarativemaps/qdeclarativegeomap_p.h @@ -175,6 +175,12 @@ public: Q_INVOKABLE void clearMapParameters(); QList mapParameters(); + void addMapObject(QGeoMapObject *object); + void removeMapObject(QGeoMapObject *object); + void clearMapObjects(); + QList mapObjects(); + + Q_INVOKABLE QGeoCoordinate toCoordinate(const QPointF &position, bool clipToViewPort = true) const; Q_INVOKABLE QPointF fromCoordinate(const QGeoCoordinate &coordinate, bool clipToViewPort = true) const; @@ -188,6 +194,7 @@ public: QString errorString() const; QGeoServiceProvider::Error error() const; + QGeoMap* map() const; Q_SIGNALS: void pluginChanged(QDeclarativeGeoServiceProvider *plugin); @@ -212,6 +219,7 @@ Q_SIGNALS: void copyrightsChanged(const QImage ©rightsImage); void copyrightsChanged(const QString ©rightsHtml); void mapReadyChanged(bool ready); + void mapObjectsChanged(); protected: void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE ; @@ -273,6 +281,7 @@ private: double m_maximumViewportLatitude; bool m_initialized; QList m_mapParameters; + QList m_pendingMapObjects; // Used only in the initialization phase QGeoCameraCapabilities m_cameraCapabilities; qreal m_userMinimumZoomLevel; qreal m_userMaximumZoomLevel; diff --git a/src/location/declarativemaps/qgeomapobject.cpp b/src/location/declarativemaps/qgeomapobject.cpp new file mode 100644 index 00000000..7ccbbf16 --- /dev/null +++ b/src/location/declarativemaps/qgeomapobject.cpp @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdeclarativegeomap_p.h" +#include "qgeomapobject_p.h" +#include "qgeomapobject_p_p.h" + +QT_BEGIN_NAMESPACE + +/*! + \internal + + \qmltype GeoMapObject + \instantiates QGeoMapObject + \inqmlmodule Qt.labs.location + \ingroup qml-QtLocation5-maps + + \brief The GeoObject type is a base class for geographical objects that can be added to a map. + + The difference between a GeoMapObject and a MapItem is twofold. First, GeoMapObject are always backed + by a plugin-specific implementation and do not come with a default implementation. If a plugin does + not support a specific GeoMapObject type, adding such a GeoMapObject will have no effect. + Second, GeoMapObject are not QQuickItems, thus being a much more lightweight way to add content to + a map. + + GeoMapObject support is plugin-dependent, and is documented per plugin. +*/ + +template<> +QGeoMapObjectPrivate *QExplicitlySharedDataPointer::clone() +{ + return d->clone(); +} + +QGeoMapObject::~QGeoMapObject() +{ + +} + +/*! + Returns whether this geographical object and \a other are equal. +*/ +bool QGeoMapObject::operator ==(const QGeoMapObject &other) const +{ + return ( (d_ptr.constData() == other.d_ptr.constData()) + || (*d_ptr) == (*other.d_ptr)); +} + +/*! + Returns whether this geographical object and \a other are not equal. +*/ +bool QGeoMapObject::operator !=(const QGeoMapObject &other) const +{ + return !(operator==(other)); +} + +/*! + \internal + Returns which features are supported by the geographical object +*/ +QGeoMapObject::Features QGeoMapObject::features() const +{ + return d_ptr->features(); +} + +QGeoMapObjectPrivate *QGeoMapObject::implementation() const +{ + return d_ptr.data(); +} + +bool QGeoMapObject::setImplementation(QGeoMapObjectPrivate *pimpl) +{ + if (d_ptr->type() != pimpl->type()) + return false; + d_ptr = QExplicitlySharedDataPointer(pimpl); + return true; +} + +bool QGeoMapObject::implemented() const +{ + return !d_ptr->engineName().isEmpty(); +} + +bool QGeoMapObject::visible() const +{ + return d_ptr->visible(); +} + +void QGeoMapObject::setVisible(bool visible) +{ + if (visible == d_ptr->visible()) + return; + + d_ptr->setVisible(visible); + + if (d_ptr->m_componentCompleted) + setChildrenVisibility(); + emit visibleChanged(); +} + +QGeoMapObject::Type QGeoMapObject::type() const +{ + return d_ptr->type(); +} + +QList QGeoMapObject::geoMapObjectChildren() const +{ + return quickChildren(); +} + +QGeoMapObject::QGeoMapObject(const QExplicitlySharedDataPointer &dd, QObject *parent) + : QParameterizableObject(parent), d_ptr(dd) +{ +} + +void QGeoMapObject::setChildrenVisibility() +{ + const bool v = visible(); + const QList kids = geoMapObjectChildren(); + for (auto kid : qAsConst(kids)) + kid->setVisible(v); +} + +void QGeoMapObject::classBegin() +{ + +} + +void QGeoMapObject::completeComponent() +{ + d_ptr->m_componentCompleted = true; + setChildrenVisibility(); +} + +void QGeoMapObject::componentComplete() +{ + completeComponent(); + emit completed(); +} + +void QGeoMapObject::setMap(QGeoMap *map) +{ + if (d_ptr->m_map == map) + return; + + d_ptr->m_map = map; + if (map) { + QGeoMapObjectPrivate *pimpl = d_ptr.data(); + if (!map->createMapObjectImplementation(this)) + qWarning() << "Unsupported type " << type(); + else + delete pimpl; // delete old implementation + } + + const QList kids = geoMapObjectChildren(); + for (auto kid : kids) + kid->setMap(map); +} + +QGeoMap *QGeoMapObject::map() const +{ + return d_ptr->m_map; +} + + +// +// QGeoMapObjectPrivate +// + +QGeoMapObjectPrivate::QGeoMapObjectPrivate() +{ +} + +QGeoMapObjectPrivate::QGeoMapObjectPrivate(QGeoMapObject *q) : q(q) +{ +} + +QGeoMapObjectPrivate::QGeoMapObjectPrivate(const QGeoMapObjectPrivate &other) + :QSharedData(other) + ,q(other.q) + ,m_componentCompleted(other.m_componentCompleted) + ,m_visible(other.m_visible) +{ + +} + +QGeoMapObjectPrivate::~QGeoMapObjectPrivate() +{ +} + +bool QGeoMapObjectPrivate::operator ==(const QGeoMapObjectPrivate &other) const +{ + return (type() == other.type() && engineName() == other.engineName() + && equals(other)); +} + +QByteArray QGeoMapObjectPrivate::engineName() const +{ + return QByteArray(); +} + +QGeoMapObject::Type QGeoMapObjectPrivate::type() const +{ + return QGeoMapObject::InvalidType; +} + +QGeoMapObject::Features QGeoMapObjectPrivate::features() const +{ + return QGeoMapObject::NoFeature; +} + +bool QGeoMapObjectPrivate::equals(const QGeoMapObjectPrivate &other) const +{ + return (visible() == other.visible() && type() == other.type() + && engineName() == other.engineName() && features() == other.features() + && m_map == other.m_map); +} + +bool QGeoMapObjectPrivate::visible() const +{ + return m_visible; +} + +void QGeoMapObjectPrivate::setVisible(bool visible) +{ + m_visible = visible; +} + +QT_END_NAMESPACE diff --git a/src/location/declarativemaps/qgeomapobject_p.h b/src/location/declarativemaps/qgeomapobject_p.h new file mode 100644 index 00000000..9f479dd7 --- /dev/null +++ b/src/location/declarativemaps/qgeomapobject_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPOBJECTBASE_H +#define QGEOMAPOBJECTBASE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include + +QT_BEGIN_NAMESPACE + +class QGeoMapObjectPrivate; +class QGeoMap; + +class Q_LOCATION_PRIVATE_EXPORT QGeoMapObject : public QParameterizableObject, public QQmlParserStatus +{ + Q_OBJECT + + Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged) + Q_PROPERTY(Type type READ type CONSTANT) + +public: + enum Feature { + NoFeature = 0x0, + Clickable = 0x01, + Draggable = 0x02, + AllFeatures = 0xFFFFFFFF + }; + + enum Type { + InvalidType = 0, + LayerType = 1, + RouteType = 2, + RectangleType = 3, + CircleType = 4, + PolylineType = 5, + PolygonType = 6, + IconType = 7, + UserType = 0x0100 + }; + + Q_ENUM(Type) + Q_DECLARE_FLAGS(Features, Feature) + + virtual ~QGeoMapObject(); + + bool operator == (const QGeoMapObject &other) const; + bool operator != (const QGeoMapObject &other) const; + + Features features() const; + QGeoMapObjectPrivate *implementation() const; + bool setImplementation(QGeoMapObjectPrivate *pimpl); + bool implemented() const; + + bool visible() const; + void setVisible(bool visible); + + Type type() const; + + virtual QList geoMapObjectChildren() const; + virtual void setMap(QGeoMap *map); + QGeoMap *map() const; + +Q_SIGNALS: + void visibleChanged(); + void selected(); + void completed(); + +protected: + QGeoMapObject(const QExplicitlySharedDataPointer &dd, QObject *parent = nullptr); + QExplicitlySharedDataPointer d_ptr; + + void setChildrenVisibility(); + + // QQmlParserStatus interface + void classBegin() override; + void componentComplete() override; + void completeComponent(); + + friend class QGeoMap; + friend class QDeclarativeGeoMap; + friend class QGeoMapLayer; + friend class QDeclarativeNavigator; +}; +QT_END_NAMESPACE + +#endif // QGEOMAPOBJECTBASE_H diff --git a/src/location/declarativemaps/qgeomapobject_p_p.h b/src/location/declarativemaps/qgeomapobject_p_p.h new file mode 100644 index 00000000..365298b3 --- /dev/null +++ b/src/location/declarativemaps/qgeomapobject_p_p.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOMAPOBJECTBASE_P_H +#define QGEOMAPOBJECTBASE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include +#include +#include +#include + +#include +#include "qgeomapobject_p.h" + +QT_BEGIN_NAMESPACE + +class QGeoMapObject; +class Q_LOCATION_PRIVATE_EXPORT QGeoMapObjectPrivate : public QSharedData +{ +public: + virtual ~QGeoMapObjectPrivate(); + + bool operator == (const QGeoMapObjectPrivate &other) const; + + virtual QByteArray engineName() const; + virtual QGeoMapObject::Features features() const; + virtual bool equals(const QGeoMapObjectPrivate &other) const; + virtual QGeoMapObject::Type type() const; + virtual bool visible() const; + virtual void setVisible(bool visible); + virtual QGeoMapObjectPrivate *clone() = 0; // to allow proper detaching + + QGeoMapObject *q = nullptr; + QPointer m_map; + bool m_componentCompleted = false; + bool m_visible = false; + +protected: + QGeoMapObjectPrivate(QGeoMapObject *q); + QGeoMapObjectPrivate(const QGeoMapObjectPrivate &other); + +private: + QGeoMapObjectPrivate(); +}; + +QT_END_NAMESPACE + +#endif // QGEOMAPOBJECTBASE_P_H diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index fd03de01..529ebf82 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -39,6 +39,7 @@ #include "qgeocameracapabilities_p.h" #include "qgeomappingmanagerengine_p.h" #include "qdeclarativegeomapitembase_p.h" +#include "qgeomapobject_p.h" #include QT_BEGIN_NAMESPACE @@ -50,7 +51,10 @@ QGeoMap::QGeoMap(QGeoMapPrivate &dd, QObject *parent) QGeoMap::~QGeoMap() { + Q_D(QGeoMap); clearParameters(); + for (QGeoMapObject *p : d->mapObjects()) + p->setMap(nullptr); // forces replacing pimpls with the default ones. } void QGeoMap::setViewportSize(const QSize& size) @@ -231,6 +235,21 @@ void QGeoMap::clearMapItems() d->m_mapItems.clear(); } +/*! + Fills obj with a backend-specific pimpl. +*/ +bool QGeoMap::createMapObjectImplementation(QGeoMapObject *obj) +{ + Q_D(QGeoMap); + return d->createMapObjectImplementation(obj); +} + +QList QGeoMap::mapObjects() const +{ + Q_D(const QGeoMap); + return d->mapObjects(); +} + QString QGeoMap::copyrightsStyleSheet() const { return QStringLiteral("#copyright-root { background: rgba(255, 255, 255, 128) }"); @@ -307,4 +326,15 @@ void QGeoMapPrivate::removeMapItem(QDeclarativeGeoMapItemBase *item) Q_UNUSED(item) } +bool QGeoMapPrivate::createMapObjectImplementation(QGeoMapObject *obj) +{ + Q_UNUSED(obj) + return false; +} + +QList QGeoMapPrivate::mapObjects() const +{ + return QList(); +} + QT_END_NAMESPACE diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h index 40d520fe..7c7825f2 100644 --- a/src/location/maps/qgeomap_p.h +++ b/src/location/maps/qgeomap_p.h @@ -54,6 +54,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -65,6 +66,7 @@ class QSGNode; class QQuickWindow; class QGeoMapParameter; class QDeclarativeGeoMapItemBase; +class QGeoMapObject; class Q_LOCATION_PRIVATE_EXPORT QGeoMap : public QObject { @@ -122,6 +124,10 @@ public: void removeMapItem(QDeclarativeGeoMapItemBase *item); void clearMapItems(); + bool createMapObjectImplementation(QGeoMapObject *obj); + QList mapObjects() const; + + virtual QString copyrightsStyleSheet() const; virtual void setAcceptedGestures(bool pan, bool flick, bool pinch, bool rotate, bool tilt); virtual bool handleEvent(QEvent *event); diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h index ef57ceb2..80fc70d2 100644 --- a/src/location/maps/qgeomap_p_p.h +++ b/src/location/maps/qgeomap_p_p.h @@ -89,6 +89,9 @@ protected: virtual void addMapItem(QDeclarativeGeoMapItemBase *item); virtual void removeMapItem(QDeclarativeGeoMapItemBase *item); + virtual bool createMapObjectImplementation(QGeoMapObject *obj); + virtual QList mapObjects() const; + virtual void changeViewportSize(const QSize &size) = 0; // called by QGeoMap::setSize() virtual void changeCameraData(const QGeoCameraData &oldCameraData) = 0; // called by QGeoMap::setCameraData() virtual void changeActiveMapType(const QGeoMapType mapType) = 0; // called by QGeoMap::setActiveMapType() -- cgit v1.2.3 From a6ff21e1e5ae264b7de264b47e08d334739fa4c6 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Tue, 29 Aug 2017 16:48:51 +0200 Subject: Make QPlace extensible This change makes it possible to subclass QPlace with custom private implementations. Change-Id: I363c0e8b7db41d9a8400ce6dbddf5405c619eeef Reviewed-by: Alex Blasche --- .../declarativeplaces/qdeclarativeplace.cpp | 4 +- .../declarativeplaces/qdeclarativeplace_p.h | 2 +- src/location/places/qplace.cpp | 427 +++++++++++++-------- src/location/places/qplace.h | 5 + src/location/places/qplace_p.h | 124 ++++-- src/location/places/qplacecontent.h | 3 +- .../nokia/placesv2/jsonparserhelpers.cpp | 1 + .../nokia/qplacemanagerengine_nokiav2.cpp | 1 + .../auto/declarative_core/tst_placesearchmodel.qml | 18 + tests/auto/geotestplugin/place_data.json | 3 +- .../auto/geotestplugin/qplacemanagerengine_test.h | 39 ++ 11 files changed, 429 insertions(+), 198 deletions(-) diff --git a/src/location/declarativeplaces/qdeclarativeplace.cpp b/src/location/declarativeplaces/qdeclarativeplace.cpp index 0e1a19aa..5c09f71b 100644 --- a/src/location/declarativeplaces/qdeclarativeplace.cpp +++ b/src/location/declarativeplaces/qdeclarativeplace.cpp @@ -385,7 +385,7 @@ void QDeclarativePlace::setPlace(const QPlace &src) m_src.content(QPlaceContent::EditorialType)); } - synchronizeExtendedAttributes(); + pullExtendedAttributes(); synchronizeContacts(); } @@ -1076,7 +1076,7 @@ void QDeclarativePlace::initializeFavorite(QDeclarativeGeoServiceProvider *plugi /*! \internal */ -void QDeclarativePlace::synchronizeExtendedAttributes() +void QDeclarativePlace::pullExtendedAttributes() { QStringList keys = m_extendedAttributes->keys(); foreach (const QString &key, keys) diff --git a/src/location/declarativeplaces/qdeclarativeplace_p.h b/src/location/declarativeplaces/qdeclarativeplace_p.h index 5a1470fe..67d2c8df 100644 --- a/src/location/declarativeplaces/qdeclarativeplace_p.h +++ b/src/location/declarativeplaces/qdeclarativeplace_p.h @@ -216,7 +216,7 @@ private Q_SLOTS: void cleanupDeletedCategories(); private: void synchronizeCategories(); - void synchronizeExtendedAttributes(); + void pullExtendedAttributes(); void synchronizeContacts(); void primarySignalsEmission(const QString &type = QString()); QString primaryValue(const QString &contactType) const; diff --git a/src/location/places/qplace.cpp b/src/location/places/qplace.cpp index 82f9f641..33623f54 100644 --- a/src/location/places/qplace.cpp +++ b/src/location/places/qplace.cpp @@ -45,6 +45,12 @@ QT_BEGIN_NAMESPACE +template<> +QPlacePrivate *QSharedDataPointer::clone() +{ + return d->clone(); +} + /*! \class QPlace \inmodule QtLocation @@ -116,10 +122,25 @@ QT_BEGIN_NAMESPACE Constructs an empty place object. */ QPlace::QPlace() - : d_ptr(new QPlacePrivate()) + : d_ptr(new QPlacePrivateDefault()) +{ +} + +/*! + Constructs an place object using dd as private implementation. +*/ +QPlace::QPlace(const QSharedDataPointer &dd): d_ptr(dd) { } +/*! + Returns the d-pointer. +*/ +QSharedDataPointer &QPlace::d() +{ + return d_ptr; +} + /*! Constructs a copy of \a other. */ @@ -164,8 +185,8 @@ inline const QPlacePrivate *QPlace::d_func() const */ bool QPlace::operator== (const QPlace &other) const { - Q_D(const QPlace); - return *d == *other.d_func(); + return ( (d_ptr.constData() == other.d_ptr.constData()) + || (*d_ptr) == (*other.d_ptr)); } /*! @@ -174,8 +195,7 @@ bool QPlace::operator== (const QPlace &other) const */ bool QPlace::operator!= (const QPlace &other) const { - Q_D(const QPlace); - return !(*d == *other.d_func()); + return !(operator==(other)); } /*! @@ -183,8 +203,7 @@ bool QPlace::operator!= (const QPlace &other) const */ QList QPlace::categories() const { - Q_D(const QPlace); - return d->categories; + return d_ptr->categories(); } /*! @@ -192,9 +211,8 @@ QList QPlace::categories() const */ void QPlace::setCategory(const QPlaceCategory &category) { - Q_D(QPlace); - d->categories.clear(); - d->categories.append(category); + d_ptr->setCategories(QList()); + d_ptr->setCategories(QList() << category); } /*! @@ -202,8 +220,7 @@ void QPlace::setCategory(const QPlaceCategory &category) */ void QPlace::setCategories(const QList &categories) { - Q_D(QPlace); - d->categories = categories; + d_ptr->setCategories(categories); } /*! @@ -211,8 +228,7 @@ void QPlace::setCategories(const QList &categories) */ QGeoLocation QPlace::location() const { - Q_D(const QPlace); - return d->location; + return d_ptr->location(); } /*! @@ -220,8 +236,7 @@ QGeoLocation QPlace::location() const */ void QPlace::setLocation(const QGeoLocation &location) { - Q_D(QPlace); - d->location = location; + d_ptr->setLocation(location); } /*! @@ -229,8 +244,7 @@ void QPlace::setLocation(const QGeoLocation &location) */ QPlaceRatings QPlace::ratings() const { - Q_D(const QPlace); - return d->ratings; + return d_ptr->ratings(); } /*! @@ -238,8 +252,7 @@ QPlaceRatings QPlace::ratings() const */ void QPlace::setRatings(const QPlaceRatings &rating) { - Q_D(QPlace); - d->ratings = rating; + d_ptr->setRatings(rating); } /*! @@ -247,8 +260,7 @@ void QPlace::setRatings(const QPlaceRatings &rating) */ QPlaceSupplier QPlace::supplier() const { - Q_D(const QPlace); - return d->supplier; + return d_ptr->supplier(); } /*! @@ -256,8 +268,7 @@ QPlaceSupplier QPlace::supplier() const */ void QPlace::setSupplier(const QPlaceSupplier &supplier) { - Q_D(QPlace); - d->supplier = supplier; + d_ptr->setSupplier(supplier); } /*! @@ -269,8 +280,7 @@ void QPlace::setSupplier(const QPlaceSupplier &supplier) */ QPlaceContent::Collection QPlace::content(QPlaceContent::Type type) const { - Q_D(const QPlace); - return d->contentCollections.value(type); + return d_ptr->m_contentCollections.value(type); } /*! @@ -278,8 +288,7 @@ QPlaceContent::Collection QPlace::content(QPlaceContent::Type type) const */ void QPlace::setContent(QPlaceContent::Type type, const QPlaceContent::Collection &content) { - Q_D(QPlace); - d->contentCollections.insert(type, content); + d_ptr->m_contentCollections.insert(type, content); } /*! @@ -288,11 +297,10 @@ void QPlace::setContent(QPlaceContent::Type type, const QPlaceContent::Collectio */ void QPlace::insertContent(QPlaceContent::Type type, const QPlaceContent::Collection &content) { - Q_D(QPlace); QMapIterator iter(content); while (iter.hasNext()) { iter.next(); - d->contentCollections[type].insert(iter.key(), iter.value()); + d_ptr->m_contentCollections[type].insert(iter.key(), iter.value()); } } @@ -306,8 +314,7 @@ void QPlace::insertContent(QPlaceContent::Type type, const QPlaceContent::Collec */ int QPlace::totalContentCount(QPlaceContent::Type type) const { - Q_D(const QPlace); - return d->contentCounts.value(type, 0); + return d_ptr->m_contentCounts.value(type, 0); } /*! @@ -315,8 +322,7 @@ int QPlace::totalContentCount(QPlaceContent::Type type) const */ void QPlace::setTotalContentCount(QPlaceContent::Type type, int totalCount) { - Q_D(QPlace); - d->contentCounts.insert(type, totalCount); + d_ptr->m_contentCounts.insert(type, totalCount); } /*! @@ -324,8 +330,7 @@ void QPlace::setTotalContentCount(QPlaceContent::Type type, int totalCount) */ QString QPlace::name() const { - Q_D(const QPlace); - return d->name; + return d_ptr->name(); } /*! @@ -333,8 +338,7 @@ QString QPlace::name() const */ void QPlace::setName(const QString &name) { - Q_D(QPlace); - d->name = name; + d_ptr->setName(name); } /*! @@ -344,8 +348,7 @@ void QPlace::setName(const QString &name) */ QString QPlace::placeId() const { - Q_D(const QPlace); - return d->placeId; + return d_ptr->placeId(); } /*! @@ -353,8 +356,7 @@ QString QPlace::placeId() const */ void QPlace::setPlaceId(const QString &identifier) { - Q_D(QPlace); - d->placeId = identifier; + d_ptr->setPlaceId(identifier); } /*! @@ -363,8 +365,7 @@ void QPlace::setPlaceId(const QString &identifier) */ QString QPlace::attribution() const { - Q_D(const QPlace); - return d->attribution; + return d_ptr->attribution(); } /*! @@ -372,8 +373,7 @@ QString QPlace::attribution() const */ void QPlace::setAttribution(const QString &attribution) { - Q_D(QPlace); - d->attribution = attribution; + d_ptr->setAttribution(attribution); } /*! @@ -381,8 +381,7 @@ void QPlace::setAttribution(const QString &attribution) */ QPlaceIcon QPlace::icon() const { - Q_D(const QPlace); - return d->icon; + return d_ptr->icon(); } /*! @@ -390,8 +389,7 @@ QPlaceIcon QPlace::icon() const */ void QPlace::setIcon(const QPlaceIcon &icon) { - Q_D(QPlace); - d->icon = icon; + d_ptr->setIcon(icon); } /*! @@ -400,8 +398,7 @@ void QPlace::setIcon(const QPlaceIcon &icon) */ QString QPlace::primaryPhone() const { - Q_D(const QPlace); - QList phoneNumbers = d->contacts.value(QPlaceContactDetail::Phone); + QList phoneNumbers = d_ptr->contacts().value(QPlaceContactDetail::Phone); if (!phoneNumbers.isEmpty()) return phoneNumbers.at(0).value(); else @@ -414,8 +411,7 @@ QString QPlace::primaryPhone() const */ QString QPlace::primaryFax() const { - Q_D(const QPlace); - QList faxNumbers = d->contacts.value(QPlaceContactDetail::Fax); + QList faxNumbers = d_ptr->contacts().value(QPlaceContactDetail::Fax); if (!faxNumbers.isEmpty()) return faxNumbers.at(0).value(); else @@ -429,8 +425,7 @@ QString QPlace::primaryFax() const */ QString QPlace::primaryEmail() const { - Q_D(const QPlace); - QList emailAddresses = d->contacts.value(QPlaceContactDetail::Email); + QList emailAddresses = d_ptr->contacts().value(QPlaceContactDetail::Email); if (!emailAddresses.isEmpty()) return emailAddresses.at(0).value(); else @@ -444,8 +439,7 @@ QString QPlace::primaryEmail() const */ QUrl QPlace::primaryWebsite() const { - Q_D(const QPlace); - QList websites = d->contacts.value(QPlaceContactDetail::Website); + QList websites = d_ptr->contacts().value(QPlaceContactDetail::Website); if (!websites.isEmpty()) return QUrl(websites.at(0).value()); else @@ -458,8 +452,7 @@ QUrl QPlace::primaryWebsite() const */ bool QPlace::detailsFetched() const { - Q_D(const QPlace); - return d->detailsFetched; + return d_ptr->detailsFetched(); } /*! @@ -467,8 +460,7 @@ bool QPlace::detailsFetched() const */ void QPlace::setDetailsFetched(bool fetched) { - Q_D(QPlace); - d->detailsFetched = fetched; + d_ptr->setDetailsFetched(fetched); } /*! @@ -476,8 +468,7 @@ void QPlace::setDetailsFetched(bool fetched) */ QStringList QPlace::extendedAttributeTypes() const { - Q_D(const QPlace); - return d->extendedAttributes.keys(); + return d_ptr->extendedAttributes().keys(); } /*! @@ -487,8 +478,7 @@ QStringList QPlace::extendedAttributeTypes() const */ QPlaceAttribute QPlace::extendedAttribute(const QString &attributeType) const { - Q_D(const QPlace); - return d->extendedAttributes.value(attributeType); + return d_ptr->extendedAttribute(attributeType); } /*! @@ -501,11 +491,10 @@ QPlaceAttribute QPlace::extendedAttribute(const QString &attributeType) const void QPlace::setExtendedAttribute(const QString &attributeType, const QPlaceAttribute &attribute) { - Q_D(QPlace); if (attribute == QPlaceAttribute()) - d->extendedAttributes.remove(attributeType); + d_ptr->extendedAttributes().remove(attributeType); else - d->extendedAttributes.insert(attributeType, attribute); + d_ptr->extendedAttributes().insert(attributeType, attribute); } /*! @@ -515,8 +504,7 @@ void QPlace::setExtendedAttribute(const QString &attributeType, */ void QPlace::removeExtendedAttribute(const QString &attributeType) { - Q_D(QPlace); - d->extendedAttributes.remove(attributeType); + setExtendedAttribute(attributeType, QPlaceAttribute()); } /*! @@ -526,8 +514,7 @@ void QPlace::removeExtendedAttribute(const QString &attributeType) */ QStringList QPlace::contactTypes() const { - Q_D(const QPlace); - return d->contacts.keys(); + return d_ptr->contacts().keys(); } /*! @@ -537,8 +524,7 @@ QStringList QPlace::contactTypes() const */ QList QPlace::contactDetails(const QString &contactType) const { - Q_D(const QPlace); - return d->contacts.value(contactType); + return d_ptr->contacts().value(contactType); } /*! @@ -551,11 +537,10 @@ QList QPlace::contactDetails(const QString &contactType) co */ void QPlace::setContactDetails(const QString &contactType, QList details) { - Q_D(QPlace); if (details.isEmpty()) - d->contacts.remove(contactType); + d_ptr->contacts().remove(contactType); else - d->contacts.insert(contactType, details); + d_ptr->contacts().insert(contactType, details); } /*! @@ -565,10 +550,9 @@ void QPlace::setContactDetails(const QString &contactType, QList details = d->contacts.value(contactType); + QList details = d_ptr->contacts().value(contactType); details.append(detail); - d->contacts.insert(contactType, details); + d_ptr->contacts().insert(contactType, details); } /*! @@ -578,8 +562,7 @@ void QPlace::appendContactDetail(const QString &contactType, const QPlaceContact */ void QPlace::removeContactDetails(const QString &contactType) { - Q_D(QPlace); - d->contacts.remove(contactType); + d_ptr->contacts().remove(contactType); } /*! @@ -587,8 +570,7 @@ void QPlace::removeContactDetails(const QString &contactType) */ void QPlace::setVisibility(QLocation::Visibility visibility) { - Q_D(QPlace); - d->visibility = visibility; + d_ptr->setVisibility(visibility); } /*! @@ -600,8 +582,7 @@ void QPlace::setVisibility(QLocation::Visibility visibility) */ QLocation::Visibility QPlace::visibility() const { - Q_D(const QPlace); - return d->visibility; + return d_ptr->visibility(); } /*! @@ -609,113 +590,225 @@ QLocation::Visibility QPlace::visibility() const */ bool QPlace::isEmpty() const { - Q_D(const QPlace); - return d->isEmpty(); + return d_ptr->isEmpty(); } /******************************************************************************* *******************************************************************************/ QPlacePrivate::QPlacePrivate() -: QSharedData(), visibility(QLocation::UnspecifiedVisibility), detailsFetched(false) +: QSharedData() { } QPlacePrivate::QPlacePrivate(const QPlacePrivate &other) : QSharedData(other), - categories(other.categories), - location(other.location), - ratings(other.ratings), - supplier(other.supplier), - name(other.name), - placeId(other.placeId), - attribution(other.attribution), - contentCollections(other.contentCollections), - contentCounts(other.contentCounts), - extendedAttributes(other.extendedAttributes), - contacts(other.contacts), - visibility(other.visibility), - icon(other.icon), - detailsFetched(other.detailsFetched) + m_contentCollections(other.m_contentCollections), + m_contentCounts(other.m_contentCounts) { } QPlacePrivate::~QPlacePrivate() {} -QPlacePrivate &QPlacePrivate::operator= (const QPlacePrivate & other) +bool QPlacePrivate::operator== (const QPlacePrivate &other) const { - if (this == &other) - return *this; + return (categories() == other.categories() + && location() == other.location() + && ratings() == other.ratings() + && supplier() == other.supplier() + && m_contentCollections == other.m_contentCollections + && m_contentCounts == other.m_contentCounts + && name() == other.name() + && placeId() == other.placeId() + && attribution() == other.attribution() + && contacts() == other.contacts() + && extendedAttributes() == other.extendedAttributes() + && visibility() == other.visibility() + && icon() == other.icon() + ); +} - categories = other.categories; - location = other.location; - ratings = other.ratings; - supplier = other.supplier; - name = other.name; - placeId = other.placeId; - attribution = other.attribution; - contentCollections = other.contentCollections; - contentCounts = other.contentCounts; - contacts = other.contacts; - extendedAttributes = other.extendedAttributes; - visibility = other.visibility; - detailsFetched = other.detailsFetched; - icon = other.icon; - return *this; +bool QPlacePrivate::isEmpty() const +{ + return (categories().isEmpty() + && location().isEmpty() + && ratings().isEmpty() + && supplier().isEmpty() + && m_contentCollections.isEmpty() + && m_contentCounts.isEmpty() + && name().isEmpty() + && placeId().isEmpty() + && attribution().isEmpty() + && contacts().isEmpty() + && extendedAttributes().isEmpty() + && QLocation::UnspecifiedVisibility == visibility() + && icon().isEmpty() + ); } -bool QPlacePrivate::operator== (const QPlacePrivate &other) const +QPlaceAttribute QPlacePrivate::extendedAttribute(const QString &attributeType) const { -#ifdef QPLACE_DEBUG - qDebug() << "categories: " << (categories == other.categories); - qDebug() << "location:" << (location == other.location); - qDebug() << "ratings" << (ratings == other.ratings); - qDebug() << "supplier" << (supplier == other.supplier); - qDebug() << "contentCollections " << (contentCollections == other.contentCollections); - qDebug() << "contentCounts " << (contentCounts == other.contentCounts); - qDebug() << "name " << (name == other.name); - qDebug() << "placeId" << (placeId == other.placeId); - qDebug() << "attribution" << (attribution == other.attribution); - qDebug() << "contacts" << (contacts == other.contacts); - qDebug() << "extendedAttributes" << (extendedAttributes == other.extendedAttributes); - qDebug() << "visibility" << (visibility == other.visibility); - qDebug() << "icon" << (icon == other.icon); -#endif + return extendedAttributes().value(attributeType); +} - return (categories == other.categories - && location == other.location - && ratings == other.ratings - && supplier == other.supplier - && contentCollections == other.contentCollections - && contentCounts == other.contentCounts - && name == other.name - && placeId == other.placeId - && attribution == other.attribution - && contacts == other.contacts - && extendedAttributes == other.extendedAttributes - && visibility == other.visibility - && icon == other.icon - ); + + +// +// Default implementation +// + +QPlacePrivateDefault::QPlacePrivateDefault() + : QPlacePrivate(), m_visibility(QLocation::UnspecifiedVisibility), m_detailsFetched(false) +{ } +QPlacePrivateDefault::QPlacePrivateDefault(const QPlacePrivateDefault &other) + : QPlacePrivate(other), + m_categories(other.m_categories), + m_location(other.m_location), + m_ratings(other.m_ratings), + m_supplier(other.m_supplier), + m_name(other.m_name), + m_placeId(other.m_placeId), + m_attribution(other.m_attribution), + m_extendedAttributes(other.m_extendedAttributes), + m_contacts(other.m_contacts), + m_visibility(other.m_visibility), + m_icon(other.m_icon), + m_detailsFetched(other.m_detailsFetched) +{ +} -bool QPlacePrivate::isEmpty() const +QPlacePrivateDefault::~QPlacePrivateDefault() { - return (categories.isEmpty() - && location.isEmpty() - && ratings.isEmpty() - && supplier.isEmpty() - && contentCollections.isEmpty() - && contentCounts.isEmpty() - && name.isEmpty() - && placeId.isEmpty() - && attribution.isEmpty() - && contacts.isEmpty() - && extendedAttributes.isEmpty() - && QLocation::UnspecifiedVisibility == visibility - && icon.isEmpty() - ); } +QPlacePrivate *QPlacePrivateDefault::clone() +{ + return new QPlacePrivateDefault(*this); +} + +QList QPlacePrivateDefault::categories() const +{ + return m_categories; +} + +void QPlacePrivateDefault::setCategories(const QList &categories) +{ + m_categories = categories; +} + +QGeoLocation QPlacePrivateDefault::location() const +{ + return m_location; +} + +void QPlacePrivateDefault::setLocation(const QGeoLocation &location) +{ + m_location = location; +} + +QPlaceRatings QPlacePrivateDefault::ratings() const +{ + return m_ratings; +} + +void QPlacePrivateDefault::setRatings(const QPlaceRatings &ratings) +{ + m_ratings = ratings; +} + +QPlaceSupplier QPlacePrivateDefault::supplier() const +{ + return m_supplier; +} + +void QPlacePrivateDefault::setSupplier(const QPlaceSupplier &supplier) +{ + m_supplier = supplier; +} + +QString QPlacePrivateDefault::name() const +{ + return m_name; +} + +void QPlacePrivateDefault::setName(const QString &name) +{ + m_name = name; +} + +QString QPlacePrivateDefault::placeId() const +{ + return m_placeId; +} + +void QPlacePrivateDefault::setPlaceId(const QString &placeIdentifier) +{ + m_placeId = placeIdentifier; +} + +QString QPlacePrivateDefault::attribution() const +{ + return m_attribution; +} + +void QPlacePrivateDefault::setAttribution(const QString &attribution) +{ + m_attribution = attribution; +} + +QLocation::Visibility QPlacePrivateDefault::visibility() const +{ + return m_visibility; +} + +void QPlacePrivateDefault::setVisibility(QLocation::Visibility visibility) +{ + m_visibility = visibility; +} + +QPlaceIcon QPlacePrivateDefault::icon() const +{ + return m_icon; +} + +void QPlacePrivateDefault::setIcon(const QPlaceIcon &icon) +{ + m_icon = icon; +} + +bool QPlacePrivateDefault::detailsFetched() const +{ + return m_detailsFetched; +} + +void QPlacePrivateDefault::setDetailsFetched(bool fetched) +{ + m_detailsFetched = fetched; +} + +QMap QPlacePrivateDefault::extendedAttributes() const +{ + return m_extendedAttributes; +} + +QMap &QPlacePrivateDefault::extendedAttributes() +{ + return m_extendedAttributes; +} + +QMap > QPlacePrivateDefault::contacts() const +{ + return m_contacts; +} + +QMap > &QPlacePrivateDefault::contacts() +{ + return m_contacts; +} + + + QT_END_NAMESPACE diff --git a/src/location/places/qplace.h b/src/location/places/qplace.h index a36ce08b..5eac1c89 100644 --- a/src/location/places/qplace.h +++ b/src/location/places/qplace.h @@ -119,11 +119,16 @@ public: bool isEmpty() const; +protected: + QPlace(const QSharedDataPointer &dd); + QSharedDataPointer &d(); + private: QSharedDataPointer d_ptr; inline QPlacePrivate *d_func(); inline const QPlacePrivate *d_func() const; + friend class QDeclarativePlace; }; Q_DECLARE_TYPEINFO(QPlace, Q_MOVABLE_TYPE); diff --git a/src/location/places/qplace_p.h b/src/location/places/qplace_p.h index cb1b13c0..5b6f167e 100644 --- a/src/location/places/qplace_p.h +++ b/src/location/places/qplace_p.h @@ -51,45 +51,117 @@ #include #include -#include "qplace.h" -#include "qgeoaddress.h" -#include "qgeorectangle.h" -#include "qgeocoordinate.h" -#include "qplacesupplier.h" +#include +#include +#include +#include +#include +#include #include QT_BEGIN_NAMESPACE -class QPlacePrivate : public QSharedData +class Q_LOCATION_PRIVATE_EXPORT QPlacePrivate : public QSharedData { public: QPlacePrivate(); QPlacePrivate(const QPlacePrivate &other); - ~QPlacePrivate(); - - QPlacePrivate &operator= (const QPlacePrivate &other); + virtual ~QPlacePrivate(); + virtual QPlacePrivate *clone() = 0; bool operator==(const QPlacePrivate &other) const; - bool isEmpty() const; - - QList categories; - QGeoLocation location; - QPlaceRatings ratings; - QPlaceSupplier supplier; - QString name; - QString placeId; - QString attribution; - - QMap contentCollections; - QMap contentCounts; + virtual bool isEmpty() const; + virtual QList categories() const = 0; + virtual void setCategories(const QList &categories) = 0; + virtual QGeoLocation location() const = 0; + virtual void setLocation(const QGeoLocation &location) = 0; + virtual QPlaceRatings ratings() const = 0; + virtual void setRatings(const QPlaceRatings &ratings) = 0; + virtual QPlaceSupplier supplier() const = 0; + virtual void setSupplier(const QPlaceSupplier &supplier) = 0; + virtual QString name() const = 0; + virtual void setName(const QString &name) = 0; + virtual QString placeId() const = 0; + virtual void setPlaceId(const QString &placeIdentifier) = 0; + virtual QString attribution() const = 0; + virtual void setAttribution(const QString &attribution) = 0; + virtual QLocation::Visibility visibility() const = 0; + virtual void setVisibility(QLocation::Visibility visibility) = 0; + virtual QPlaceIcon icon() const = 0; + virtual void setIcon(const QPlaceIcon &icon) = 0; + virtual bool detailsFetched() const = 0; + virtual void setDetailsFetched(bool fetched) = 0; + + virtual QMap extendedAttributes() const = 0; + virtual QMap &extendedAttributes() = 0; + virtual QMap > contacts() const = 0; + virtual QMap > &contacts() = 0; + virtual QPlaceAttribute extendedAttribute(const QString &attributeType) const; + + + // The place content, that has to be manually retrieved from the place manager and manually added to the place. + // Currently, place content types can be: + // ImageType, + // ReviewType, + // EditorialType, + // CustomType = 0x0100 + QMap m_contentCollections; + QMap m_contentCounts; +}; - QMap extendedAttributes; - QMap > contacts; - QLocation::Visibility visibility; - QPlaceIcon icon; - bool detailsFetched; +class Q_LOCATION_PRIVATE_EXPORT QPlacePrivateDefault : public QPlacePrivate +{ +public: + QPlacePrivateDefault(); + QPlacePrivateDefault(const QPlacePrivateDefault &other); + virtual ~QPlacePrivateDefault(); + virtual QPlacePrivate *clone() override; + + virtual QList categories() const override; + virtual void setCategories(const QList &categories) override; + virtual QGeoLocation location() const override; + virtual void setLocation(const QGeoLocation &location) override; + virtual QPlaceRatings ratings() const override; + virtual void setRatings(const QPlaceRatings &ratings) override; + virtual QPlaceSupplier supplier() const override; + virtual void setSupplier(const QPlaceSupplier &supplier) override; + virtual QString name() const override; + virtual void setName(const QString &name) override; + virtual QString placeId() const override; + virtual void setPlaceId(const QString &placeIdentifier) override; + virtual QString attribution() const override; + virtual void setAttribution(const QString &attribution) override; + virtual QLocation::Visibility visibility() const override; + virtual void setVisibility(QLocation::Visibility visibility) override; + virtual QPlaceIcon icon() const override; + virtual void setIcon(const QPlaceIcon &icon) override; + virtual bool detailsFetched() const override; + virtual void setDetailsFetched(bool fetched) override; + + virtual QMap extendedAttributes() const override; + virtual QMap &extendedAttributes() override; + virtual QMap > contacts() const override; + virtual QMap > &contacts() override; + + + // data members + + QList m_categories; + QGeoLocation m_location; + QPlaceRatings m_ratings; + QPlaceSupplier m_supplier; + QString m_name; + QString m_placeId; + QString m_attribution; + + QMap m_extendedAttributes; + QMap > m_contacts; + + QLocation::Visibility m_visibility; + QPlaceIcon m_icon; + bool m_detailsFetched; }; QT_END_NAMESPACE diff --git a/src/location/places/qplacecontent.h b/src/location/places/qplacecontent.h index 87a293da..d8e4d4e3 100644 --- a/src/location/places/qplacecontent.h +++ b/src/location/places/qplacecontent.h @@ -64,7 +64,8 @@ public: NoType = 0, ImageType, ReviewType, - EditorialType + EditorialType, + CustomType = 0x0100 }; QPlaceContent(); diff --git a/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp index f877e9d7..b09331b3 100644 --- a/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp +++ b/src/plugins/geoservices/nokia/placesv2/jsonparserhelpers.cpp @@ -233,6 +233,7 @@ void parseCollection(QPlaceContent::Type type, const QJsonObject &object, collection->insert(offset + i, parseEditorial(itemObject, engine)); break; case QPlaceContent::NoType: + default: break; } } diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp index 67b7e70f..ab575463 100644 --- a/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp +++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokiav2.cpp @@ -313,6 +313,7 @@ QPlaceContentReply *QPlaceManagerEngineNokiaV2::getPlaceContent(const QPlaceCont networkReply = sendRequest(requestUrl); break; case QPlaceContent::NoType: + default: ; } } diff --git a/tests/auto/declarative_core/tst_placesearchmodel.qml b/tests/auto/declarative_core/tst_placesearchmodel.qml index 2d3c599c..4c7897b5 100644 --- a/tests/auto/declarative_core/tst_placesearchmodel.qml +++ b/tests/auto/declarative_core/tst_placesearchmodel.qml @@ -128,6 +128,16 @@ TestCase { "4dcc74ce-fdeb-443e-827c-367438017cf1" ] }, + { + tag: "searchTerm, multiple results", + property: "searchTerm", + value: "sea", + reset: "", + alternate: true, + places: [ + "8f72057a-54b2-4e95-a7bb-97b4d2b5721e" + ] + }, { tag: "categories, single result", property: "categories", @@ -192,6 +202,14 @@ TestCase { verify(data.places.indexOf(place.placeId) >= 0); } + // Test for alternate implementation + if (data.alternate !== undefined && data.alternate === true) { + for (var ii = 0; ii < testModel.count; ++ii) { + var p = testModel.data(ii, "place"); + compare(p.extendedAttributes["x_provider"].text, "QPlacePrivateDefaultAlt") + } + } + testModel.reset(); compare(statusChangedSpy.count, 3); diff --git a/tests/auto/geotestplugin/place_data.json b/tests/auto/geotestplugin/place_data.json index 20062816..3aafcbec 100644 --- a/tests/auto/geotestplugin/place_data.json +++ b/tests/auto/geotestplugin/place_data.json @@ -130,7 +130,8 @@ "location": { "latitude": 0.1002, "longitude": 0.1002 - } + }, + "alternateImplementation": true }, { "name": "Country Gardens", diff --git a/tests/auto/geotestplugin/qplacemanagerengine_test.h b/tests/auto/geotestplugin/qplacemanagerengine_test.h index f8af1edc..30e5422e 100644 --- a/tests/auto/geotestplugin/qplacemanagerengine_test.h +++ b/tests/auto/geotestplugin/qplacemanagerengine_test.h @@ -51,6 +51,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -64,6 +65,37 @@ QT_END_NAMESPACE QT_USE_NAMESPACE +class QPlacePrivateDefaultAlt : public QPlacePrivateDefault +{ +public: + QPlacePrivateDefaultAlt() {} + QPlacePrivateDefaultAlt(const QPlacePrivateDefaultAlt &other) + : QPlacePrivateDefault(other) + { + } + ~QPlacePrivateDefaultAlt() {} + + QPlaceAttribute extendedAttribute(const QString &attributeType) const override + { + if (attributeType == QStringLiteral("x_provider")) { + QPlaceAttribute a; + a.setLabel(QStringLiteral("x_provider")); + a.setText(QStringLiteral("QPlacePrivateDefaultAlt")); + return a; + } else { + return QPlacePrivateDefault::extendedAttribute(attributeType); + } + } +}; + +class QPlaceAlt : public QPlace +{ +public: + QPlaceAlt() : QPlace(QSharedDataPointer(new QPlacePrivateDefaultAlt())) + { + } +}; + class PlaceReply : public QPlaceReply { Q_OBJECT @@ -233,6 +265,13 @@ public: QJsonObject p = places.at(i).toObject(); QPlace place; + if (p.value(QStringLiteral("alternateImplementation")).toBool(false)) { + place = QPlaceAlt(); + QPlaceAttribute att; + att.setLabel(QStringLiteral("x_provider")); + att.setText(QStringLiteral("42")); // Doesn't matter, wont be used. + place.setExtendedAttribute(QStringLiteral("x_provider"), att); + } place.setName(p.value(QStringLiteral("name")).toString()); place.setPlaceId(p.value(QStringLiteral("id")).toString()); -- cgit v1.2.3 From 69a42c4a5c37a5a74c4b285c64328bc88ed8e059 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Thu, 21 Sep 2017 18:14:26 +0200 Subject: Allow plugins to use alternative map projections QtLocation mapping has always been geared around the WebMercator projection. Some mapping SDKs support additional projections, such as General Perspective (often called globe view or globe rendering). The goal of this patch is to allow a plugin to provide such a view, disabling WebMercator specific features, and redirecting API calls to plugin-specific implementations. In particular, this patch disables the rendering of Map Items (QDeclarativeGeoMapItemBase and sons) for projections different from WebMercator, with the exception of MapQuickItems. MapQuickItems, in turn, lose the ability to draw "on the map", when the projection is different from WebMercator. However, they can still be used to add geolocated popups, buttons and other UI elements. fitViewportToMapItems is also disabled, for both it can't be computed and there wouldn't be any item to fit (with the exception of mapquickitems) Change-Id: I9fa2fdd01a35a078fc4663efc9d269c4ecaa3f41 Reviewed-by: Alex Blasche --- .../declarativemaps/qdeclarativecirclemapitem.cpp | 48 +++-- .../declarativemaps/qdeclarativegeomap.cpp | 224 +++++++++++++-------- .../declarativemaps/qdeclarativegeomapitembase.cpp | 16 +- .../qdeclarativegeomapquickitem.cpp | 50 +++-- .../declarativemaps/qdeclarativepolygonmapitem.cpp | 30 +-- .../qdeclarativepolylinemapitem.cpp | 28 +-- .../qdeclarativerectanglemapitem.cpp | 16 +- .../declarativemaps/qquickgeomapgesturearea.cpp | 23 +-- src/location/maps/qgeomap.cpp | 59 +++++- src/location/maps/qgeomap_p.h | 18 ++ src/location/maps/qgeomap_p_p.h | 3 + src/location/maps/qgeoprojection.cpp | 95 ++++++++- src/location/maps/qgeoprojection_p.h | 118 ++++++----- src/location/maps/qgeotiledmap.cpp | 7 + src/location/maps/qgeotiledmap_p.h | 1 + .../geoservices/mapboxgl/qgeomapmapboxgl.cpp | 7 + src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h | 1 + .../geoservices/mapboxgl/qmapboxglstylechange.cpp | 6 +- 18 files changed, 515 insertions(+), 235 deletions(-) diff --git a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp index 91328dc7..a1e34a30 100644 --- a/src/location/declarativemaps/qdeclarativecirclemapitem.cpp +++ b/src/location/declarativemaps/qdeclarativecirclemapitem.cpp @@ -144,6 +144,7 @@ QGeoMapCircleGeometry::QGeoMapCircleGeometry() */ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QList &circlePath, const QGeoMap &map) { + const QGeoProjectionWebMercator &p = static_cast(map.geoProjection()); // Not checking for !screenDirty anymore, as everything is now recalculated. clear(); if (map.viewportWidth() == 0 || map.viewportHeight() == 0 || circlePath.size() < 3) // a circle requires at least 3 points; @@ -160,23 +161,23 @@ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QList fill; fill << tl << tr << br << bl; QList hole; for (const QDoubleVector2D &c: circlePath) - hole << map.geoProjection().wrapMapProjection(c); + hole << p.wrapMapProjection(c); c2t::clip2tri clipper; clipper.addSubjectPath(QClipperUtils::qListToPath(fill), true); @@ -184,9 +185,9 @@ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QList > clippedPaths; - const QList &visibleRegion = map.geoProjection().visibleRegion(); + const QList &visibleRegion = p.visibleGeometry(); if (visibleRegion.size()) { clipper.clearClipper(); for (const Path &p: difference) @@ -210,19 +211,19 @@ void QGeoMapCircleGeometry::updateScreenPointsInvert(const QList &path: clippedPaths) { QDoubleVector2D lastAddedPoint; for (int i = 0; i < path.size(); ++i) { - QDoubleVector2D point = map.geoProjection().wrappedMapProjectionToItemPosition(path.at(i)); + QDoubleVector2D point = p.wrappedMapProjectionToItemPosition(path.at(i)); //point = point - origin; // Do this using ppi.translate() if (i == 0) { @@ -483,9 +484,11 @@ QSGNode *QDeclarativeCircleMapItem::updateMapItemPaintNode(QSGNode *oldNode, Upd */ void QDeclarativeCircleMapItem::updatePolish() { - if (!map() || !circle_.isValid()) + if (!map() || !circle_.isValid() + || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); QScopedValueRollback rollback(updatingGeometry_); updatingGeometry_ = true; @@ -533,7 +536,7 @@ void QDeclarativeCircleMapItem::updatePolish() QDoubleVector2D borderLeftBoundWrapped; QList > clippedPaths = borderGeometry_.clipPath(*map(), closedPath, borderLeftBoundWrapped); if (clippedPaths.size()) { - borderLeftBoundWrapped = map()->geoProjection().geoToWrappedMapProjection(geometryOrigin); + borderLeftBoundWrapped = p.geoToWrappedMapProjection(geometryOrigin); borderGeometry_.pathToScreen(*map(), clippedPaths, borderLeftBoundWrapped); borderGeometry_.updateScreenPoints(*map(), border_.width()); geoms << &borderGeometry_; @@ -565,13 +568,15 @@ void QDeclarativeCircleMapItem::afterViewportChanged(const QGeoMapViewportChange */ void QDeclarativeCircleMapItem::updateCirclePath() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); QList path; calculatePeripheralPoints(path, circle_.center(), circle_.radius(), CircleSamples, leftBound_); circlePath_.clear(); for (const QGeoCoordinate &c : path) - circlePath_ << map()->geoProjection().geoToMapProjection(c); + circlePath_ << p.geoToMapProjection(c); } /*! @@ -644,6 +649,7 @@ void QDeclarativeCircleMapItem::updateCirclePathForRendering(QList(map()->geoProjection()); const qreal poleLat = 90; const qreal distanceToNorthPole = center.distanceTo(QGeoCoordinate(poleLat, 0)); const qreal distanceToSouthPole = center.distanceTo(QGeoCoordinate(-poleLat, 0)); @@ -651,11 +657,11 @@ void QDeclarativeCircleMapItem::updateCirclePathForRendering(QList wrapPathIndex; - QDoubleVector2D prev = map()->geoProjection().wrapMapProjection(path.at(0)); + QDoubleVector2D prev = p.wrapMapProjection(path.at(0)); for (int i = 1; i <= path.count(); ++i) { int index = i % path.count(); - QDoubleVector2D point = map()->geoProjection().wrapMapProjection(path.at(index)); + QDoubleVector2D point = p.wrapMapProjection(path.at(index)); double diff = qAbs(point.x() - prev.x()); if (diff > 0.5) { continue; @@ -665,7 +671,7 @@ void QDeclarativeCircleMapItem::updateCirclePathForRendering(QListgeoProjection().wrapMapProjection(path.at(index)); + QDoubleVector2D point = p.wrapMapProjection(path.at(index)); if ( (qAbs(point.x() - prev.x())) >= 0.5 ) { wrapPathIndex << index; if (wrapPathIndex.size() == 2 || !(crossNorthPole && crossSouthPole)) diff --git a/src/location/declarativemaps/qdeclarativegeomap.cpp b/src/location/declarativemaps/qdeclarativegeomap.cpp index 42ed633d..c5d01ebd 100644 --- a/src/location/declarativemaps/qdeclarativegeomap.cpp +++ b/src/location/declarativemaps/qdeclarativegeomap.cpp @@ -61,6 +61,15 @@ QT_BEGIN_NAMESPACE +static qreal sanitizeBearing(qreal bearing) +{ + bearing = std::fmod(bearing, qreal(360.0)); + if (bearing < 0.0) + bearing += 360.0; + + return bearing; +} + /*! \qmltype Map \instantiates QDeclarativeGeoMap @@ -389,7 +398,7 @@ void QDeclarativeGeoMap::initialize() QGeoCoordinate center = m_cameraData.center(); - if (qIsNaN(m_userMinimumZoomLevel)) + if (!qIsFinite(m_userMinimumZoomLevel)) setMinimumZoomLevel(m_map->minimumZoom(), false); else setMinimumZoomLevel(qMax(m_map->minimumZoom(), m_userMinimumZoomLevel), false); @@ -681,7 +690,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.maximumZoomLevelAt256() < m_gestureArea->maximumZoomLevel()) { setMaximumZoomLevel(m_cameraCapabilities.maximumZoomLevelAt256(), false); } else if (m_cameraCapabilities.maximumZoomLevelAt256() > m_gestureArea->maximumZoomLevel()) { - if (qIsNaN(m_userMaximumZoomLevel)) { + if (!qIsFinite(m_userMaximumZoomLevel)) { // If the user didn't set anything setMaximumZoomLevel(m_cameraCapabilities.maximumZoomLevelAt256(), false); } else { // Try to set what the user requested @@ -694,7 +703,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.minimumZoomLevelAt256() > m_gestureArea->minimumZoomLevel()) { setMinimumZoomLevel(m_cameraCapabilities.minimumZoomLevelAt256(), false); } else if (m_cameraCapabilities.minimumZoomLevelAt256() < m_gestureArea->minimumZoomLevel()) { - if (qIsNaN(m_userMinimumZoomLevel)) { + if (!qIsFinite(m_userMinimumZoomLevel)) { // If the user didn't set anything, trying to set the new caps. setMinimumZoomLevel(m_cameraCapabilities.minimumZoomLevelAt256(), false); } else { // Try to set what the user requested @@ -710,7 +719,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.maximumTilt() < m_maximumTilt) { setMaximumTilt(m_cameraCapabilities.maximumTilt(), false); } else if (m_cameraCapabilities.maximumTilt() > m_maximumTilt) { - if (qIsNaN(m_userMaximumTilt)) + if (!qIsFinite(m_userMaximumTilt)) setMaximumTilt(m_cameraCapabilities.maximumTilt(), false); else // Try to set what the user requested setMaximumTilt(qMin(m_cameraCapabilities.maximumTilt(), m_userMaximumTilt), false); @@ -719,7 +728,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.minimumTilt() > m_minimumTilt) { setMinimumTilt(m_cameraCapabilities.minimumTilt(), false); } else if (m_cameraCapabilities.minimumTilt() < m_minimumTilt) { - if (qIsNaN(m_userMinimumTilt)) + if (!qIsFinite(m_userMinimumTilt)) setMinimumTilt(m_cameraCapabilities.minimumTilt(), false); else // Try to set what the user requested setMinimumTilt(qMax(m_cameraCapabilities.minimumTilt(), m_userMinimumTilt), false); @@ -729,7 +738,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.maximumFieldOfView() < m_maximumFieldOfView) { setMaximumFieldOfView(m_cameraCapabilities.maximumFieldOfView(), false); } else if (m_cameraCapabilities.maximumFieldOfView() > m_maximumFieldOfView) { - if (qIsNaN(m_userMaximumFieldOfView)) + if (!qIsFinite(m_userMaximumFieldOfView)) setMaximumFieldOfView(m_cameraCapabilities.maximumFieldOfView(), false); else // Try to set what the user requested setMaximumFieldOfView(qMin(m_cameraCapabilities.maximumFieldOfView(), m_userMaximumFieldOfView), false); @@ -738,7 +747,7 @@ void QDeclarativeGeoMap::onCameraCapabilitiesChanged(const QGeoCameraCapabilitie if (m_cameraCapabilities.minimumFieldOfView() > m_minimumFieldOfView) { setMinimumFieldOfView(m_cameraCapabilities.minimumFieldOfView(), false); } else if (m_cameraCapabilities.minimumFieldOfView() < m_minimumFieldOfView) { - if (qIsNaN(m_userMinimumFieldOfView)) + if (!qIsFinite(m_userMinimumFieldOfView)) setMinimumFieldOfView(m_cameraCapabilities.minimumFieldOfView(), false); else // Try to set what the user requested setMinimumFieldOfView(qMax(m_cameraCapabilities.minimumFieldOfView(), m_userMinimumFieldOfView), false); @@ -1042,12 +1051,8 @@ qreal QDeclarativeGeoMap::zoomLevel() const */ void QDeclarativeGeoMap::setBearing(qreal bearing) { - bearing = std::fmod(bearing, qreal(360.0)); - if (bearing < 0.0) - bearing += 360.0; - if (m_map && !m_cameraCapabilities.supportsBearing()) - bearing = 0.0; - if (m_cameraData.bearing() == bearing || bearing < 0.0) + bearing = sanitizeBearing(bearing); + if (m_cameraData.bearing() == bearing) return; m_cameraData.setBearing(bearing); @@ -1056,6 +1061,45 @@ void QDeclarativeGeoMap::setBearing(qreal bearing) emit bearingChanged(bearing); } +/*! + \qmlmethod void QtLocation::Map::setBearing(real bearing, coordinate coordinate) + + Sets the bearing for the map to \a bearing, rotating it around \a coordinate. + If the Plugin used for the Map supports bearing, the valid range for \a bearing is between 0 and 360. + If the Plugin used for the Map does not support bearing, or if the map is tilted and \a coordinate happens + to be behind the camera, or if the map is not ready (see \l mapReady), calling this method will have no effect. + + The release of this API with Qt 5.10 is a Technology Preview. + + \since 5.10 +*/ +void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate) +{ + if (!m_map) + return; + + const QGeoCoordinate currentCenter = center(); + const qreal currentBearing = QDeclarativeGeoMap::bearing(); + bearing = sanitizeBearing(bearing); + + if (!coordinate.isValid() + || !qIsFinite(bearing) + || (coordinate == currentCenter && bearing == currentBearing)) + return; + + if (m_map->capabilities() & QGeoMap::SupportsSetBearing) { + if (!m_map->setBearing(bearing, coordinate)) + return; + + m_cameraData = m_map->cameraData(); + + if (m_cameraData.center() != currentCenter) + emit centerChanged(m_cameraData.center()); + if (m_cameraData.bearing() != currentBearing) + emit bearingChanged(bearing); + } +} + qreal QDeclarativeGeoMap::bearing() const { return m_cameraData.bearing(); @@ -1351,23 +1395,23 @@ QGeoShape QDeclarativeGeoMap::visibleRegion() const if (!m_map || !width() || !height()) return m_visibleRegion; - const QList &visibleRegion = m_map->geoProjection().visibleRegion(); - QGeoPolygon poly; - for (int i = 0; i < visibleRegion.size(); ++i) { - const QDoubleVector2D &c = visibleRegion.at(i); - // If a segment spans more than half of the map longitudinally, split in 2. - if (i && qAbs(visibleRegion.at(i-1).x() - c.x()) >= 0.5) { // This assumes a segment is never >= 1.0 (whole map span) - QDoubleVector2D extraPoint = (visibleRegion.at(i-1) + c) * 0.5; - poly.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(extraPoint)); - } - poly.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(c)); - } - if (visibleRegion.size() >= 2 && qAbs(visibleRegion.last().x() - visibleRegion.first().x()) >= 0.5) { - QDoubleVector2D extraPoint = (visibleRegion.last() + visibleRegion.first()) * 0.5; - poly.addCoordinate(m_map->geoProjection().wrappedMapProjectionToGeo(extraPoint)); + if (m_map->capabilities() & QGeoMap::SupportsVisibleRegion) { + return m_map->visibleRegion(); + } else { + // ToDo: handle projections not supporting visible region in a better way. + // This approach will fail when horizon is in the view or the map is greatly zoomed out. + QList visiblePoly; + visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(0,0), false); + visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_map->viewportWidth() - 1, + 0), false); + visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_map->viewportWidth() - 1, + m_map->viewportHeight() - 1), false); + visiblePoly << m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(0, + m_map->viewportHeight() - 1), false); + QGeoPath path; + path.setPath(visiblePoly); + return path.boundingGeoRectangle(); } - - return poly; } /*! @@ -1439,35 +1483,53 @@ bool QDeclarativeGeoMap::mapReady() const // TODO: offer the possibility to specify the margins. void QDeclarativeGeoMap::fitViewportToGeoShape() { - const int margins = 10; - if (!m_map || !m_visibleRegion.isValid() || width() <= margins || height() <= margins) - return; - - QDoubleVector2D topLeftPoint = m_map->geoProjection().geoToMapProjection(m_visibleRegion.topLeft()); - QDoubleVector2D bottomRightPoint = m_map->geoProjection().geoToMapProjection(m_visibleRegion.bottomRight()); - if (bottomRightPoint.x() < topLeftPoint.x()) // crossing the dateline - bottomRightPoint.setX(bottomRightPoint.x() + 1.0); - - // find center of the bounding box - QDoubleVector2D center = (topLeftPoint + bottomRightPoint) * 0.5; - center.setX(center.x() > 1.0 ? center.x() - 1.0 : center.x()); - QGeoCoordinate centerCoordinate = m_map->geoProjection().mapProjectionToGeo(center); - - // position camera to the center of bounding box - setProperty("center", QVariant::fromValue(centerCoordinate)); // not using setCenter(centerCoordinate) to honor a possible animation set on the center property - - // if the shape is empty we just change center position, not zoom - double bboxWidth = (bottomRightPoint.x() - topLeftPoint.x()) * m_map->mapWidth(); - double bboxHeight = (bottomRightPoint.y() - topLeftPoint.y()) * m_map->mapHeight(); - - if (bboxHeight == 0.0 && bboxWidth == 0.0) - return; - - double zoomRatio = qMax(bboxWidth / (width() - margins), - bboxHeight / (height() - margins)); - zoomRatio = std::log(zoomRatio) / std::log(2.0); - double newZoom = qMax(minimumZoomLevel(), zoomLevel() - zoomRatio); - setProperty("zoomLevel", QVariant::fromValue(newZoom)); // not using setZoomLevel(newZoom) to honor a possible animation set on the zoomLevel property + if (m_map->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { + // This case remains handled here, and not inside QGeoMap*::fitViewportToGeoRectangle, + // in order to honor animations on center and zoomLevel + const QGeoProjectionWebMercator &p = static_cast(m_map->geoProjection()); + const int margins = 10; + if (!m_map || !m_visibleRegion.isValid() || width() <= margins || height() <= margins) + return; + + QDoubleVector2D topLeftPoint = p.geoToMapProjection(m_visibleRegion.topLeft()); + QDoubleVector2D bottomRightPoint = p.geoToMapProjection(m_visibleRegion.bottomRight()); + if (bottomRightPoint.x() < topLeftPoint.x()) // crossing the dateline + bottomRightPoint.setX(bottomRightPoint.x() + 1.0); + + // find center of the bounding box + QDoubleVector2D center = (topLeftPoint + bottomRightPoint) * 0.5; + center.setX(center.x() > 1.0 ? center.x() - 1.0 : center.x()); + QGeoCoordinate centerCoordinate = p.mapProjectionToGeo(center); + + // position camera to the center of bounding box + setProperty("center", QVariant::fromValue(centerCoordinate)); // not using setCenter(centerCoordinate) to honor a possible animation set on the center property + + // if the shape is empty we just change center position, not zoom + double bboxWidth = (bottomRightPoint.x() - topLeftPoint.x()) * m_map->mapWidth(); + double bboxHeight = (bottomRightPoint.y() - topLeftPoint.y()) * m_map->mapHeight(); + + if (bboxHeight == 0.0 && bboxWidth == 0.0) + return; + + double zoomRatio = qMax(bboxWidth / (width() - margins), + bboxHeight / (height() - margins)); + zoomRatio = std::log(zoomRatio) / std::log(2.0); + double newZoom = qMax(minimumZoomLevel(), zoomLevel() - zoomRatio); + setProperty("zoomLevel", QVariant::fromValue(newZoom)); // not using setZoomLevel(newZoom) to honor a possible animation set on the zoomLevel property + } else if (m_map->capabilities() & QGeoMap::SupportsFittingViewportToGeoRectangle) { + // Animations cannot be honored in this case, as m_map act as a black box + const QGeoCoordinate currentCenter = center(); + const qreal currentZoom = zoomLevel(); + + if (!m_map->fitViewportToGeoRectangle(m_visibleRegion)) + return; + + m_cameraData = m_map->cameraData(); + if (m_cameraData.center() != currentCenter) + emit centerChanged(m_cameraData.center()); + if (m_cameraData.zoomLevel() != currentZoom) + emit zoomLevelChanged(m_cameraData.zoomLevel()); + } } @@ -1483,35 +1545,6 @@ QQmlListProperty QDeclarativeGeoMap::supportedMapTypes() return QQmlListProperty(this, m_supportedMapTypes); } -/*! - \qmlmethod void QtLocation::Map::setBearing(real bearing, coordinate coordinate) - - Sets the bearing for the map to \a bearing, rotating it around \a coordinate. - If the Plugin used for the Map supports bearing, the valid range for \a bearing is between 0 and 360. - If the Plugin used for the Map does not support bearing, or if the map is tilted and \a coordinate happens - to be behind the camera, or if the map is not ready (see \l mapReady), calling this method will have no effect. - - The release of this API with Qt 5.10 is a Technology Preview. - - \since 5.10 -*/ -void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate) -{ - if (!m_map) - return; - - const QDoubleVector2D coordWrapped = m_map->geoProjection().geoToWrappedMapProjection(coordinate); - if (!m_map->geoProjection().isProjectable(coordWrapped)) - return; - - const QPointF rotationPoint = m_map->geoProjection().wrappedMapProjectionToItemPosition(coordWrapped).toPointF(); - - // First set bearing - setBearing(bearing); - // then reanchor - setCenter(m_map->geoProjection().anchorCoordinateToPoint(coordinate, rotationPoint)); -} - /*! \qmlmethod void QtLocation::Map::alignCoordinateToPoint(coordinate coordinate, QPointF point) @@ -1532,10 +1565,23 @@ void QDeclarativeGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordin */ void QDeclarativeGeoMap::alignCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &point) { - if (!m_map) + if (!m_map || !(m_map->capabilities() & QGeoMap::SupportsAnchoringCoordinate)) + return; + + const QGeoCoordinate currentCenter = center(); + + if (!coordinate.isValid() + || !qIsFinite(point.x()) + || !qIsFinite(point.y())) return; - setCenter(m_map->geoProjection().anchorCoordinateToPoint(coordinate, point)); + if (!m_map->anchorCoordinateToPoint(coordinate, point)) + return; + + m_cameraData = m_map->cameraData(); + + if (m_cameraData.center() != currentCenter) + emit centerChanged(m_cameraData.center()); } /*! diff --git a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp index 729825fd..fed0a74b 100644 --- a/src/location/declarativemaps/qdeclarativegeomapitembase.cpp +++ b/src/location/declarativemaps/qdeclarativegeomapitembase.cpp @@ -185,11 +185,19 @@ void QDeclarativeGeoMapItemBase::setPositionOnMap(const QGeoCoordinate &coordina if (!map_ || !quickMap_) return; - QDoubleVector2D wrappedProjection = map_->geoProjection().geoToWrappedMapProjection(coordinate); - if (!map_->geoProjection().isProjectable(wrappedProjection)) - return; + QDoubleVector2D pos; + if (map()->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); + QDoubleVector2D wrappedProjection = p.geoToWrappedMapProjection(coordinate); + if (!p.isProjectable(wrappedProjection)) + return; + pos = p.wrappedMapProjectionToItemPosition(wrappedProjection); + } else { + pos = map()->geoProjection().coordinateToItemPosition(coordinate, false); + if (qIsNaN(pos.x())) + return; + } - QDoubleVector2D pos = map_->geoProjection().wrappedMapProjectionToItemPosition(wrappedProjection); QPointF topLeft = pos.toPointF() - offset; setPosition(topLeft); diff --git a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp index 7c0764aa..43efc940 100644 --- a/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp +++ b/src/location/declarativemaps/qdeclarativegeomapquickitem.cpp @@ -210,9 +210,12 @@ void QDeclarativeGeoMapQuickItem::geometryChanged(const QRectF &newGeometry, con QGeoCoordinate newCoordinate; // with zoomLevel set the anchorPoint has to be factored into the transformation to properly transform around it. - if (zoomLevel_ != 0.0) { + if (zoomLevel_ != 0.0 + && map()->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); + // When dragStartCoordinate_ can't be projected to screen, dragging must be disabled. - if (!map()->geoProjection().isProjectable(map()->geoProjection().geoToWrappedMapProjection(dragStartCoordinate_))) + if (!p.isProjectable(p.geoToWrappedMapProjection(dragStartCoordinate_))) return; QDoubleVector2D pos = map()->geoProjection().coordinateToItemPosition(dragStartCoordinate_, false); @@ -392,27 +395,42 @@ void QDeclarativeGeoMapQuickItem::updatePolish() setWidth(sourceItem_.data()->width()); setHeight(sourceItem_.data()->height()); - if (zoomLevel_ != 0.0) { // zoom level initialized to 0.0. If it's different, it has been set explicitly. + if (zoomLevel_ != 0.0 // zoom level initialized to 0.0. If it's different, it has been set explicitly. + && map()->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { // Currently unsupported on any other projection + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); + if (!matrix_) { matrix_ = new QMapQuickItemMatrix4x4(this); matrix_->appendToItem(opacityContainer_); } - matrix_->setMatrix(map()->geoProjection().quickItemTransformation(coordinate(), anchorPoint_, zoomLevel_)); + matrix_->setMatrix(p.quickItemTransformation(coordinate(), anchorPoint_, zoomLevel_)); setPosition(QPointF(0,0)); } else { - // if the coordinate is behind the camera, we use the transformation to get the item out of the way - if (map()->cameraData().tilt() > 0.0 - && !map()->geoProjection().isProjectable(map()->geoProjection().geoToWrappedMapProjection(coordinate()))) { - if (!matrix_) { - matrix_ = new QMapQuickItemMatrix4x4(this); - matrix_->appendToItem(opacityContainer_); + if (map()->geoProjection().projectionType() == QGeoProjection::ProjectionWebMercator) { + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); + if (map()->cameraData().tilt() > 0.0 + && !p.isProjectable(p.geoToWrappedMapProjection(coordinate()))) { + // if the coordinate is behind the camera, we use the transformation to get the item out of the way + if (!matrix_) { + matrix_ = new QMapQuickItemMatrix4x4(this); + matrix_->appendToItem(opacityContainer_); + } + matrix_->setMatrix(p.quickItemTransformation(coordinate(), anchorPoint_, map()->cameraData().zoomLevel())); + setPosition(QPointF(0,0)); + } else { // All good, rendering screen-aligned + if (matrix_) + matrix_->setMatrix(QMatrix4x4()); + setPositionOnMap(coordinate(), anchorPoint_); + } + } else { // On other projections we can only currently test if coordinateToItemPosition returns a valid position + if (map()->cameraData().tilt() > 0.0 + && qIsNaN(map()->geoProjection().coordinateToItemPosition(coordinate(), false).x())) { + opacityContainer_->setVisible(false); + } else { + if (matrix_) + matrix_->setMatrix(QMatrix4x4()); + setPositionOnMap(coordinate(), anchorPoint_); } - matrix_->setMatrix(map()->geoProjection().quickItemTransformation(coordinate(), anchorPoint_, map()->cameraData().zoomLevel())); - setPosition(QPointF(0,0)); - } else { - if (matrix_) - matrix_->setMatrix(QMatrix4x4()); - setPositionOnMap(coordinate(), anchorPoint_); } } } diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp index 8c7afc17..aa3a3bd9 100644 --- a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp +++ b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp @@ -147,14 +147,14 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, { if (!sourceDirty_) return; - + const QGeoProjectionWebMercator &p = static_cast(map.geoProjection()); srcPath_ = QPainterPath(); // build the actual path // The approach is the same as described in QGeoMapPolylineGeometry::updateSourcePoints srcOrigin_ = geoLeftBound_; double unwrapBelowX = 0; - QDoubleVector2D leftBoundWrapped = map.geoProjection().wrapMapProjection(map.geoProjection().geoToMapProjection(geoLeftBound_)); + QDoubleVector2D leftBoundWrapped = p.wrapMapProjection(p.geoToMapProjection(geoLeftBound_)); if (preserveGeometry_) unwrapBelowX = leftBoundWrapped.x(); @@ -164,7 +164,7 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, // 1) for (int i = 0; i < path.size(); ++i) { const QDoubleVector2D &coord = path.at(i); - QDoubleVector2D wrappedProjection = map.geoProjection().wrapMapProjection(coord); + QDoubleVector2D wrappedProjection = p.wrapMapProjection(coord); // We can get NaN if the map isn't set up correctly, or the projection // is faulty -- probably best thing to do is abort @@ -187,7 +187,7 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, // 2) QList > clippedPaths; - const QList &visibleRegion = map.geoProjection().projectableRegion(); + const QList &visibleRegion = p.projectableGeometry(); if (visibleRegion.size()) { c2t::clip2tri clipper; clipper.addSubjectPath(QClipperUtils::qListToPath(wrappedPath), true); @@ -210,17 +210,17 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map, // in turn will make the geometry wrap around. lb.setX(qMax(wrappedLeftBound.x(), lb.x())); leftBoundWrapped = lb; - srcOrigin_ = map.geoProjection().mapProjectionToGeo(map.geoProjection().unwrapMapProjection(lb)); + srcOrigin_ = p.mapProjectionToGeo(p.unwrapMapProjection(lb)); } else { clippedPaths.append(wrappedPath); } // 3) - QDoubleVector2D origin = map.geoProjection().wrappedMapProjectionToItemPosition(leftBoundWrapped); + QDoubleVector2D origin = p.wrappedMapProjectionToItemPosition(leftBoundWrapped); for (const QList &path: clippedPaths) { QDoubleVector2D lastAddedPoint; for (int i = 0; i < path.size(); ++i) { - QDoubleVector2D point = map.geoProjection().wrappedMapProjectionToItemPosition(path.at(i)); + QDoubleVector2D point = p.wrappedMapProjectionToItemPosition(path.at(i)); point = point - origin; // (0,0) if point == geoLeftBound_ if (i == 0) { @@ -500,9 +500,11 @@ QSGNode *QDeclarativePolygonMapItem::updateMapItemPaintNode(QSGNode *oldNode, Up */ void QDeclarativePolygonMapItem::updatePolish() { - if (!map() || geopath_.path().length() == 0) + if (!map() || geopath_.path().length() == 0 + || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); QScopedValueRollback rollback(updatingGeometry_); updatingGeometry_ = true; @@ -527,7 +529,7 @@ void QDeclarativePolygonMapItem::updatePolish() QDoubleVector2D borderLeftBoundWrapped; QList > clippedPaths = borderGeometry_.clipPath(*map(), closedPath, borderLeftBoundWrapped); if (clippedPaths.size()) { - borderLeftBoundWrapped = map()->geoProjection().geoToWrappedMapProjection(geometryOrigin); + borderLeftBoundWrapped = p.geoToWrappedMapProjection(geometryOrigin); borderGeometry_.pathToScreen(*map(), clippedPaths, borderLeftBoundWrapped); borderGeometry_.updateScreenPoints(*map(), border_.width()); @@ -571,12 +573,13 @@ void QDeclarativePolygonMapItem::afterViewportChanged(const QGeoMapViewportChang */ void QDeclarativePolygonMapItem::regenerateCache() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); geopathProjected_.clear(); geopathProjected_.reserve(geopath_.path().size()); for (const QGeoCoordinate &c : geopath_.path()) - geopathProjected_ << map()->geoProjection().geoToMapProjection(c); + geopathProjected_ << p.geoToMapProjection(c); } /*! @@ -584,9 +587,10 @@ void QDeclarativePolygonMapItem::regenerateCache() */ void QDeclarativePolygonMapItem::updateCache() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; - geopathProjected_ << map()->geoProjection().geoToMapProjection(geopath_.path().last()); + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); + geopathProjected_ << p.geoToMapProjection(geopath_.path().last()); } /*! diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp index 7c1b922f..90ed95e4 100644 --- a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp +++ b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp @@ -189,11 +189,11 @@ QList > QGeoMapPolylineGeometry::clipPath(const QGeoMap & * 2.1) recalculate the origin and geoLeftBound to prevent these parameters from ending in unprojectable areas * 2.2) ensure the left bound does not wrap around due to QGeoCoordinate <-> clipper conversions */ - + const QGeoProjectionWebMercator &p = static_cast(map.geoProjection()); srcOrigin_ = geoLeftBound_; double unwrapBelowX = 0; - leftBoundWrapped = map.geoProjection().wrapMapProjection(map.geoProjection().geoToMapProjection(geoLeftBound_)); + leftBoundWrapped = p.wrapMapProjection(p.geoToMapProjection(geoLeftBound_)); if (preserveGeometry_) unwrapBelowX = leftBoundWrapped.x(); @@ -203,7 +203,7 @@ QList > QGeoMapPolylineGeometry::clipPath(const QGeoMap & // 1) for (int i = 0; i < path.size(); ++i) { const QDoubleVector2D &coord = path.at(i); - QDoubleVector2D wrappedProjection = map.geoProjection().wrapMapProjection(coord); + QDoubleVector2D wrappedProjection = p.wrapMapProjection(coord); // We can get NaN if the map isn't set up correctly, or the projection // is faulty -- probably best thing to do is abort @@ -226,7 +226,7 @@ QList > QGeoMapPolylineGeometry::clipPath(const QGeoMap & // 2) QList > clippedPaths; - const QList &visibleRegion = map.geoProjection().projectableRegion(); + const QList &visibleRegion = p.projectableGeometry(); if (visibleRegion.size()) { c2t::clip2tri clipper; clipper.addSubjectPath(QClipperUtils::qListToPath(wrappedPath), false); @@ -265,18 +265,19 @@ void QGeoMapPolylineGeometry::pathToScreen(const QGeoMap &map, const QList > &clippedPaths, const QDoubleVector2D &leftBoundWrapped) { + const QGeoProjectionWebMercator &p = static_cast(map.geoProjection()); // 3) project the resulting geometry to screen position and calculate screen bounds double minX = qInf(); double minY = qInf(); double maxX = -qInf(); double maxY = -qInf(); - srcOrigin_ = map.geoProjection().mapProjectionToGeo(map.geoProjection().unwrapMapProjection(leftBoundWrapped)); - QDoubleVector2D origin = map.geoProjection().wrappedMapProjectionToItemPosition(leftBoundWrapped); + srcOrigin_ = p.mapProjectionToGeo(p.unwrapMapProjection(leftBoundWrapped)); + QDoubleVector2D origin = p.wrappedMapProjectionToItemPosition(leftBoundWrapped); for (const QList &path: clippedPaths) { QDoubleVector2D lastAddedPoint; for (int i = 0; i < path.size(); ++i) { - QDoubleVector2D point = map.geoProjection().wrappedMapProjectionToItemPosition(path.at(i)); + QDoubleVector2D point = p.wrappedMapProjectionToItemPosition(path.at(i)); point = point - origin; // (0,0) if point == geoLeftBound_ @@ -722,12 +723,13 @@ void QDeclarativePolylineMapItem::afterViewportChanged(const QGeoMapViewportChan */ void QDeclarativePolylineMapItem::regenerateCache() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); geopathProjected_.clear(); geopathProjected_.reserve(geopath_.path().size()); for (const QGeoCoordinate &c : geopath_.path()) - geopathProjected_ << map()->geoProjection().geoToMapProjection(c); + geopathProjected_ << p.geoToMapProjection(c); } /*! @@ -735,9 +737,10 @@ void QDeclarativePolylineMapItem::regenerateCache() */ void QDeclarativePolylineMapItem::updateCache() { - if (!map()) + if (!map() || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; - geopathProjected_ << map()->geoProjection().geoToMapProjection(geopath_.path().last()); + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); + geopathProjected_ << p.geoToMapProjection(geopath_.path().last()); } /*! @@ -745,7 +748,8 @@ void QDeclarativePolylineMapItem::updateCache() */ void QDeclarativePolylineMapItem::updatePolish() { - if (!map() || geopath_.path().length() == 0) + if (!map() || geopath_.path().length() == 0 + || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; QScopedValueRollback rollback(updatingGeometry_); diff --git a/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp b/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp index 79750416..0206ac96 100644 --- a/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp +++ b/src/location/declarativemaps/qdeclarativerectanglemapitem.cpp @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -272,9 +273,12 @@ QSGNode *QDeclarativeRectangleMapItem::updateMapItemPaintNode(QSGNode *oldNode, */ void QDeclarativeRectangleMapItem::updatePolish() { - if (!map() || !topLeft().isValid() || !bottomRight().isValid()) + if (!map() || !topLeft().isValid() || !bottomRight().isValid() + || map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator) return; + const QGeoProjectionWebMercator &p = static_cast(map()->geoProjection()); + QScopedValueRollback rollback(updatingGeometry_); updatingGeometry_ = true; @@ -299,7 +303,7 @@ void QDeclarativeRectangleMapItem::updatePolish() QDoubleVector2D borderLeftBoundWrapped; QList > clippedPaths = borderGeometry_.clipPath(*map(), closedPath, borderLeftBoundWrapped); if (clippedPaths.size()) { - borderLeftBoundWrapped = map()->geoProjection().geoToWrappedMapProjection(geometryOrigin); + borderLeftBoundWrapped = p.geoToWrappedMapProjection(geometryOrigin); borderGeometry_.pathToScreen(*map(), clippedPaths, borderLeftBoundWrapped); borderGeometry_.updateScreenPoints(*map(), border_.width()); @@ -355,11 +359,11 @@ void QDeclarativeRectangleMapItem::updatePath() if (!map()) return; pathMercator_.clear(); - pathMercator_ << map()->geoProjection().geoToMapProjection(rectangle_.topLeft()); - pathMercator_ << map()->geoProjection().geoToMapProjection( + pathMercator_ << QWebMercator::coordToMercator(rectangle_.topLeft()); + pathMercator_ << QWebMercator::coordToMercator( QGeoCoordinate(rectangle_.topLeft().latitude(), rectangle_.bottomRight().longitude())); - pathMercator_ << map()->geoProjection().geoToMapProjection(rectangle_.bottomRight()); - pathMercator_ << map()->geoProjection().geoToMapProjection( + pathMercator_ << QWebMercator::coordToMercator(rectangle_.bottomRight()); + pathMercator_ << QWebMercator::coordToMercator( QGeoCoordinate(rectangle_.bottomRight().latitude(), rectangle_.topLeft().longitude())); } diff --git a/src/location/declarativemaps/qquickgeomapgesturearea.cpp b/src/location/declarativemaps/qquickgeomapgesturearea.cpp index 2f095ee0..1703bcfa 100644 --- a/src/location/declarativemaps/qquickgeomapgesturearea.cpp +++ b/src/location/declarativemaps/qquickgeomapgesturearea.cpp @@ -969,7 +969,7 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) return; } - const QGeoCoordinate &wheelGeoPos = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(event->posF()), false); + const QGeoCoordinate &wheelGeoPos = m_declarativeMap->toCoordinate(event->posF(), false); const QPointF &preZoomPoint = event->posF(); // Not using AltModifier as, for some reason, it causes angleDelta to be 0 @@ -977,9 +977,7 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) emit rotationStarted(&m_pinch.m_event); // 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)); + m_declarativeMap->setBearing(m_declarativeMap->bearing() + bearingDelta, wheelGeoPos); emit rotationUpdated(&m_pinch.m_event); emit rotationFinished(&m_pinch.m_event); } else if (event->modifiers() & Qt::ControlModifier && tiltEnabled()) { @@ -993,10 +991,10 @@ void QQuickGeoMapGestureArea::handleWheelEvent(QWheelEvent *event) // Gesture area should always honor maxZL, but Map might not. m_declarativeMap->setZoomLevel(qMin(m_declarativeMap->zoomLevel() + zoomLevelDelta, maximumZoomLevel()), false); - const QPointF &postZoomPoint = m_map->geoProjection().coordinateToItemPosition(wheelGeoPos, false).toPointF(); + const QPointF &postZoomPoint = m_declarativeMap->fromCoordinate(wheelGeoPos, false); if (preZoomPoint != postZoomPoint) // need to re-anchor the wheel geoPos to the event position - m_declarativeMap->setCenter(m_map->geoProjection().anchorCoordinateToPoint(wheelGeoPos, preZoomPoint)); + m_declarativeMap->alignCoordinateToPoint(wheelGeoPos, preZoomPoint); } event->accept(); } @@ -1134,7 +1132,7 @@ void QQuickGeoMapGestureArea::touchPointStateMachine() if (m_allPoints.count() == 0) { setTouchPointState(touchPoints0); } else if (m_allPoints.count() == 2) { - m_touchCenterCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_touchPointsCentroid), false); + m_touchCenterCoord = m_declarativeMap->toCoordinate(m_touchPointsCentroid, false); startTwoTouchPoints(); setTouchPointState(touchPoints2); } @@ -1143,7 +1141,7 @@ void QQuickGeoMapGestureArea::touchPointStateMachine() if (m_allPoints.count() == 0) { setTouchPointState(touchPoints0); } else if (m_allPoints.count() == 1) { - m_touchCenterCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_touchPointsCentroid), false); + m_touchCenterCoord = m_declarativeMap->toCoordinate(m_touchPointsCentroid, false); startOneTouchPoint(); setTouchPointState(touchPoints1); } @@ -1171,7 +1169,7 @@ void QQuickGeoMapGestureArea::startOneTouchPoint() m_sceneStartPoint1 = mapFromScene(m_allPoints.at(0).scenePos()); m_lastPos = m_sceneStartPoint1; m_lastPosTime.start(); - QGeoCoordinate startCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_sceneStartPoint1), false); + QGeoCoordinate startCoord = m_declarativeMap->toCoordinate(m_sceneStartPoint1, false); // ensures a smooth transition for panning m_startCoord.setLongitude(m_startCoord.longitude() + startCoord.longitude() - m_touchCenterCoord.longitude()); @@ -1198,7 +1196,7 @@ void QQuickGeoMapGestureArea::startTwoTouchPoints() QPointF startPos = (m_sceneStartPoint1 + m_sceneStartPoint2) * 0.5; m_lastPos = startPos; m_lastPosTime.start(); - QGeoCoordinate startCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(startPos), false); + QGeoCoordinate startCoord = m_declarativeMap->toCoordinate(startPos, false); m_startCoord.setLongitude(m_startCoord.longitude() + startCoord.longitude() - m_touchCenterCoord.longitude()); m_startCoord.setLatitude(m_startCoord.latitude() + startCoord.latitude() - @@ -1668,7 +1666,7 @@ void QQuickGeoMapGestureArea::panStateMachine() case flickInactive: if (!isTiltActive() && canStartPan()) { // Update startCoord_ to ensure smooth start for panning when going over startDragDistance - QGeoCoordinate newStartCoord = m_map->geoProjection().itemPositionToCoordinate(QDoubleVector2D(m_touchPointsCentroid), false); + QGeoCoordinate newStartCoord = m_declarativeMap->toCoordinate(m_touchPointsCentroid, false); m_startCoord.setLongitude(newStartCoord.longitude()); m_startCoord.setLatitude(newStartCoord.latitude()); m_declarativeMap->setKeepMouseGrab(true); @@ -1743,8 +1741,7 @@ bool QQuickGeoMapGestureArea::canStartPan() */ void QQuickGeoMapGestureArea::updatePan() { - QGeoCoordinate animationStartCoordinate = m_map->geoProjection().anchorCoordinateToPoint(m_startCoord, m_touchPointsCentroid); - m_declarativeMap->setCenter(animationStartCoordinate); + m_declarativeMap->alignCoordinateToPoint(m_startCoord, m_touchPointsCentroid); } /*! diff --git a/src/location/maps/qgeomap.cpp b/src/location/maps/qgeomap.cpp index 529ebf82..4ac36fed 100644 --- a/src/location/maps/qgeomap.cpp +++ b/src/location/maps/qgeomap.cpp @@ -91,7 +91,7 @@ void QGeoMap::setCameraData(const QGeoCameraData &cameraData) if (cameraData == d->m_cameraData) return; d->m_cameraData = cameraData; - d->m_geoProjection->setCameraData(cameraData); + d->m_geoProjection->setCameraData(cameraData, false); d->changeCameraData(cameraData); emit cameraDataChanged(d->m_cameraData); } @@ -108,6 +108,40 @@ bool QGeoMap::handleEvent(QEvent *event) return false; } +bool QGeoMap::setBearing(qreal bearing, const QGeoCoordinate &coordinate) +{ + Q_D(QGeoMap); + bool res = d->m_geoProjection->setBearing(bearing, coordinate); + if (!res) + return false; + + setCameraData(geoProjection().cameraData()); + return true; +} + +bool QGeoMap::anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) +{ + QGeoCoordinate newCenter = geoProjection().anchorCoordinateToPoint(coordinate, anchorPoint); + QGeoCameraData data = cameraData(); + if (data.center() != newCenter) { + data.setCenter(newCenter); + setCameraData(data); + return true; + } + return false; +} + +bool QGeoMap::fitViewportToGeoRectangle(const QGeoRectangle &rectangle) +{ + Q_UNUSED(rectangle) + return false; +} + +QGeoShape QGeoMap::visibleRegion() const +{ + return geoProjection().visibleRegion(); +} + QGeoCameraData QGeoMap::cameraData() const { Q_D(const QGeoMap); @@ -146,13 +180,13 @@ double QGeoMap::maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) co double QGeoMap::mapWidth() const { Q_D(const QGeoMap); - return d->m_geoProjection->mapWidth(); + return d->mapWidth(); } double QGeoMap::mapHeight() const { Q_D(const QGeoMap); - return d->m_geoProjection->mapHeight(); + return d->mapHeight(); } const QGeoProjection &QGeoMap::geoProjection() const @@ -167,6 +201,11 @@ QGeoCameraCapabilities QGeoMap::cameraCapabilities() const return d->m_cameraCapabilities; } +QGeoMap::Capabilities QGeoMap::capabilities() const +{ + return Capabilities(QGeoMap::SupportsNothing); +} + void QGeoMap::prefetchData() { @@ -337,4 +376,18 @@ QList QGeoMapPrivate::mapObjects() const return QList(); } +double QGeoMapPrivate::mapWidth() const +{ + if (m_geoProjection->projectionType() == QGeoProjection::ProjectionWebMercator) + return static_cast(m_geoProjection)->mapWidth(); + return 0; // override this for maps supporting other projections +} + +double QGeoMapPrivate::mapHeight() const +{ + if (m_geoProjection->projectionType() == QGeoProjection::ProjectionWebMercator) + return static_cast(m_geoProjection)->mapHeight(); + return 0; // override this for maps supporting other projections +} + QT_END_NAMESPACE diff --git a/src/location/maps/qgeomap_p.h b/src/location/maps/qgeomap_p.h index 7c7825f2..b2382099 100644 --- a/src/location/maps/qgeomap_p.h +++ b/src/location/maps/qgeomap_p.h @@ -73,6 +73,8 @@ class Q_LOCATION_PRIVATE_EXPORT QGeoMap : public QObject Q_OBJECT Q_DECLARE_PRIVATE(QGeoMap) + Q_ENUMS(Capability) + Q_FLAGS(Capabilities) public: enum ItemType { NoItem = 0x0000, @@ -86,6 +88,16 @@ public: Q_DECLARE_FLAGS(ItemTypes, ItemType) + enum Capability { + SupportsNothing = 0x0000, + SupportsVisibleRegion = 0x0001, + SupportsSetBearing = 0x0002, + SupportsAnchoringCoordinate = 0x0004, + SupportsFittingViewportToGeoRectangle = 0x0008 + }; + + Q_DECLARE_FLAGS(Capabilities, Capability) + virtual ~QGeoMap(); // Sets the display size @@ -97,6 +109,7 @@ public: QGeoCameraData cameraData() const; QGeoCameraCapabilities cameraCapabilities() const; + virtual Capabilities capabilities() const; void setActiveMapType(const QGeoMapType mapType); const QGeoMapType activeMapType() const; @@ -132,6 +145,11 @@ public: virtual void setAcceptedGestures(bool pan, bool flick, bool pinch, bool rotate, bool tilt); virtual bool handleEvent(QEvent *event); + virtual bool setBearing(qreal bearing, const QGeoCoordinate &coordinate); + virtual QGeoShape visibleRegion() const; + virtual bool anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint); + virtual bool fitViewportToGeoRectangle(const QGeoRectangle &rectangle); + protected: QGeoMap(QGeoMapPrivate &dd, QObject *parent = 0); void setCameraData(const QGeoCameraData &cameraData); diff --git a/src/location/maps/qgeomap_p_p.h b/src/location/maps/qgeomap_p_p.h index 80fc70d2..d6ab40b6 100644 --- a/src/location/maps/qgeomap_p_p.h +++ b/src/location/maps/qgeomap_p_p.h @@ -96,6 +96,9 @@ protected: virtual void changeCameraData(const QGeoCameraData &oldCameraData) = 0; // called by QGeoMap::setCameraData() virtual void changeActiveMapType(const QGeoMapType mapType) = 0; // called by QGeoMap::setActiveMapType() + virtual double mapWidth() const; + virtual double mapHeight() const; + protected: QSize m_viewportSize; QGeoProjection *m_geoProjection; diff --git a/src/location/maps/qgeoprojection.cpp b/src/location/maps/qgeoprojection.cpp index 1df174fb..1ab9970b 100644 --- a/src/location/maps/qgeoprojection.cpp +++ b/src/location/maps/qgeoprojection.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -74,6 +75,30 @@ QGeoProjection::~QGeoProjection() } QGeoCoordinate QGeoProjection::anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const +{ + Q_UNUSED(coordinate) + Q_UNUSED(anchorPoint) + return QGeoCoordinate(); +} + +QGeoShape QGeoProjection::visibleRegion() const +{ + return QGeoShape(); +} + +bool QGeoProjection::setBearing(qreal bearing, const QGeoCoordinate &coordinate) +{ + Q_UNUSED(bearing) + Q_UNUSED(coordinate) + return false; +} + + +/* + * QGeoProjectionWebMercator implementation +*/ + +QGeoCoordinate QGeoProjectionWebMercator::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()); @@ -84,9 +109,25 @@ QGeoCoordinate QGeoProjection::anchorCoordinateToPoint(const QGeoCoordinate &coo return wrappedMapProjectionToGeo(centerProj + coordProj - anchorProj); } -/* - * QGeoProjectionWebMercator implementation -*/ +bool QGeoProjectionWebMercator::setBearing(qreal bearing, const QGeoCoordinate &coordinate) +{ + const QDoubleVector2D coordWrapped = geoToWrappedMapProjection(coordinate); + if (!isProjectable(coordWrapped)) + return false; + const QPointF rotationPoint = wrappedMapProjectionToItemPosition(coordWrapped).toPointF(); + + QGeoCameraData camera = cameraData(); + // first set bearing + camera.setBearing(bearing); + setCameraData(camera); + camera = cameraData(); + + // then reanchor + const QGeoCoordinate center = anchorCoordinateToPoint(coordinate, rotationPoint); + camera.setCenter(center); + setCameraData(camera); + return true; +} QGeoProjectionWebMercator::QGeoProjectionWebMercator() : QGeoProjection(), @@ -154,6 +195,9 @@ double QGeoProjectionWebMercator::mapHeight() const void QGeoProjectionWebMercator::setViewportSize(const QSize &size) { + if (int(m_viewportWidth) == size.width() && int(m_viewportHeight) == size.height()) + return; + m_viewportWidth = size.width(); m_viewportHeight = size.height(); m_1_viewportWidth = 1.0 / m_viewportWidth; @@ -162,8 +206,11 @@ void QGeoProjectionWebMercator::setViewportSize(const QSize &size) setupCamera(); } -void QGeoProjectionWebMercator::setCameraData(const QGeoCameraData &cameraData) +void QGeoProjectionWebMercator::setCameraData(const QGeoCameraData &cameraData, bool force) { + if (m_cameraData == cameraData && !force) + return; + m_cameraData = cameraData; m_mapEdgeSize = std::pow(2.0, cameraData.zoomLevel()) * defaultTileSize; setupCamera(); @@ -331,20 +378,41 @@ bool QGeoProjectionWebMercator::isProjectable(const QDoubleVector2D &wrappedProj return true; } -QList QGeoProjectionWebMercator::visibleRegion() const +QList QGeoProjectionWebMercator::visibleGeometry() const { if (m_visibleRegionDirty) const_cast(this)->updateVisibleRegion(); return m_visibleRegion; } -QList QGeoProjectionWebMercator::projectableRegion() const +QList QGeoProjectionWebMercator::projectableGeometry() const { if (m_visibleRegionDirty) const_cast(this)->updateVisibleRegion(); return m_projectableRegion; } +QGeoShape QGeoProjectionWebMercator::visibleRegion() const +{ + const QList &visibleRegion = visibleGeometry(); + QGeoPolygon poly; + for (int i = 0; i < visibleRegion.size(); ++i) { + const QDoubleVector2D &c = visibleRegion.at(i); + // If a segment spans more than half of the map longitudinally, split in 2. + if (i && qAbs(visibleRegion.at(i-1).x() - c.x()) >= 0.5) { // This assumes a segment is never >= 1.0 (whole map span) + QDoubleVector2D extraPoint = (visibleRegion.at(i-1) + c) * 0.5; + poly.addCoordinate(wrappedMapProjectionToGeo(extraPoint)); + } + poly.addCoordinate(wrappedMapProjectionToGeo(c)); + } + if (visibleRegion.size() >= 2 && qAbs(visibleRegion.last().x() - visibleRegion.first().x()) >= 0.5) { + QDoubleVector2D extraPoint = (visibleRegion.last() + visibleRegion.first()) * 0.5; + poly.addCoordinate(wrappedMapProjectionToGeo(extraPoint)); + } + + return poly; +} + QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const { double s; @@ -369,6 +437,21 @@ QDoubleVector2D QGeoProjectionWebMercator::viewportToWrappedMapProjection(const return (xyPlane.lineIntersection(m_eye, ray, s) / m_sideLength).toVector2D(); } +QGeoProjection::ProjectionGroup QGeoProjectionWebMercator::projectionGroup() const +{ + return QGeoProjection::ProjectionCylindrical; +} + +QGeoProjection::Datum QGeoProjectionWebMercator::datum() const +{ + return QGeoProjection::DatumWGS84; +} + +QGeoProjection::ProjectionType QGeoProjectionWebMercator::projectionType() const +{ + return QGeoProjection::ProjectionWebMercator; +} + void QGeoProjectionWebMercator::setupCamera() { m_centerMercator = geoToMapProjection(m_cameraData.center()); diff --git a/src/location/maps/qgeoprojection_p.h b/src/location/maps/qgeoprojection_p.h index ca81df3a..dc05d4d1 100644 --- a/src/location/maps/qgeoprojection_p.h +++ b/src/location/maps/qgeoprojection_p.h @@ -51,53 +51,60 @@ #include #include #include +#include QT_BEGIN_NAMESPACE class Q_LOCATION_PRIVATE_EXPORT QGeoProjection { public: + enum ProjectionGroup { + ProjectionOther, + ProjectionCylindrical, + ProjectionPseudocylindrical, + ProjectionAzimuthal, + ProjectionPseudoazimuthal, + ProjectionConic, + ProjectionPseudoconic + //Polyhedral + //Retroazimuthal + }; + + enum Datum { + DatumUnknown, + DatumWGS84, + DatumSphere + }; + + enum ProjectionType { + ProjectionUnknown, + ProjectionGeneralPerspective, + ProjectionWebMercator + }; + QGeoProjection(); virtual ~QGeoProjection(); virtual void setViewportSize(const QSize &size) = 0; - virtual void setCameraData(const QGeoCameraData &cameraData) = 0; + virtual void setCameraData(const QGeoCameraData &cameraData, bool force = true) = 0; + virtual QGeoCameraData cameraData() const = 0; // returns the minimum zoom at the current viewport size virtual double minimumZoom() const = 0; virtual double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const = 0; - // returns the size of the underlying map, at the current zoom level. - virtual double mapWidth() const = 0; - virtual double mapHeight() const = 0; - - virtual bool isProjectable(const QDoubleVector2D &wrappedProjection) const = 0; - virtual QList visibleRegion() const = 0; - virtual QList projectableRegion() const = 0; - - // Conversion methods for QGeoCoordinate <-> screen. - // This currently assumes that the "MapProjection" space is [0, 1][0, 1] for every type of possibly supported map projection - virtual QDoubleVector2D geoToMapProjection(const QGeoCoordinate &coordinate) const = 0; - virtual QGeoCoordinate mapProjectionToGeo(const QDoubleVector2D &projection) const = 0; - - virtual QDoubleVector2D wrapMapProjection(const QDoubleVector2D &projection) const = 0; - virtual QDoubleVector2D unwrapMapProjection(const QDoubleVector2D &wrappedProjection) const = 0; - - virtual QDoubleVector2D wrappedMapProjectionToItemPosition(const QDoubleVector2D &wrappedProjection) const = 0; - virtual QDoubleVector2D itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const = 0; - - // Convenience methods to avoid the chain itemPositionToWrappedProjection(wrapProjection(geoToProjection())) virtual QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const = 0; virtual QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const = 0; - 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; + + virtual ProjectionGroup projectionGroup() const = 0; + virtual Datum datum() const = 0; + virtual ProjectionType projectionType() const = 0; // Returns the new map center after anchoring coordinate to anchorPoint on the screen - QGeoCoordinate anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const; + virtual QGeoCoordinate anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const; -private: - virtual QGeoCameraData cameraData() const = 0; + virtual QGeoShape visibleRegion() const; + virtual bool setBearing(qreal bearing, const QGeoCoordinate &coordinate); }; class Q_LOCATION_PRIVATE_EXPORT QGeoProjectionWebMercator : public QGeoProjection @@ -106,40 +113,53 @@ public: QGeoProjectionWebMercator(); ~QGeoProjectionWebMercator(); - double minimumZoom() const Q_DECL_OVERRIDE; - double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const Q_DECL_OVERRIDE; + // From QGeoProjection + double minimumZoom() const override; + double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override; + + void setViewportSize(const QSize &size) override; + void setCameraData(const QGeoCameraData &cameraData, bool force = true) override; + QGeoCameraData cameraData() const override; - // The size of the underlying map, at the current zoom level. - double mapWidth() const Q_DECL_OVERRIDE; - double mapHeight() const Q_DECL_OVERRIDE; + QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const override; + QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const override; - void setViewportSize(const QSize &size) Q_DECL_OVERRIDE; - void setCameraData(const QGeoCameraData &cameraData) Q_DECL_OVERRIDE; + QGeoProjection::ProjectionGroup projectionGroup() const override; + QGeoProjection::Datum datum() const override; + QGeoProjection::ProjectionType projectionType() const override; - QDoubleVector2D geoToMapProjection(const QGeoCoordinate &coordinate) const Q_DECL_OVERRIDE; - QGeoCoordinate mapProjectionToGeo(const QDoubleVector2D &projection) const Q_DECL_OVERRIDE; + QGeoCoordinate anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const override; + bool setBearing(qreal bearing, const QGeoCoordinate &coordinate) override; - QDoubleVector2D wrapMapProjection(const QDoubleVector2D &projection) const Q_DECL_OVERRIDE; - QDoubleVector2D unwrapMapProjection(const QDoubleVector2D &wrappedProjection) const Q_DECL_OVERRIDE; + QGeoShape visibleRegion() const override; - QDoubleVector2D wrappedMapProjectionToItemPosition(const QDoubleVector2D &wrappedProjection) const Q_DECL_OVERRIDE; - QDoubleVector2D itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const Q_DECL_OVERRIDE; + // Specific to QGeoProjectionWebMercator + double mapWidth() const; // The size of the underlying map, at the current zoom level. + double mapHeight() const; - QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const Q_DECL_OVERRIDE; - QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const Q_DECL_OVERRIDE; - QDoubleVector2D geoToWrappedMapProjection(const QGeoCoordinate &coordinate) const Q_DECL_OVERRIDE; - QGeoCoordinate wrappedMapProjectionToGeo(const QDoubleVector2D &wrappedProjection) const Q_DECL_OVERRIDE; - QMatrix4x4 quickItemTransformation(const QGeoCoordinate &coordinate, const QPointF &anchorPoint, qreal zoomLevel) const Q_DECL_OVERRIDE; + QDoubleVector2D geoToMapProjection(const QGeoCoordinate &coordinate) const; + QGeoCoordinate mapProjectionToGeo(const QDoubleVector2D &projection) const; + + QDoubleVector2D wrapMapProjection(const QDoubleVector2D &projection) const; + QDoubleVector2D unwrapMapProjection(const QDoubleVector2D &wrappedProjection) const; + + QDoubleVector2D wrappedMapProjectionToItemPosition(const QDoubleVector2D &wrappedProjection) const; + QDoubleVector2D itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const; + + QDoubleVector2D geoToWrappedMapProjection(const QGeoCoordinate &coordinate) const; + QGeoCoordinate wrappedMapProjectionToGeo(const QDoubleVector2D &wrappedProjection) const; + QMatrix4x4 quickItemTransformation(const QGeoCoordinate &coordinate, const QPointF &anchorPoint, qreal zoomLevel) const; + + bool isProjectable(const QDoubleVector2D &wrappedProjection) const; + QList visibleGeometry() const; + QList projectableGeometry() const; - bool isProjectable(const QDoubleVector2D &wrappedProjection) const Q_DECL_OVERRIDE; - QList visibleRegion() const Q_DECL_OVERRIDE; - QList projectableRegion() const Q_DECL_OVERRIDE; inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const; inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition, double &s) const; + private: void setupCamera(); void updateVisibleRegion(); - QGeoCameraData cameraData() const Q_DECL_OVERRIDE; public: struct Line2D diff --git a/src/location/maps/qgeotiledmap.cpp b/src/location/maps/qgeotiledmap.cpp index 0eeb189d..81eb3b14 100644 --- a/src/location/maps/qgeotiledmap.cpp +++ b/src/location/maps/qgeotiledmap.cpp @@ -143,6 +143,13 @@ void QGeoTiledMap::clearData() d->m_mapScene->clearTexturedTiles(); } +QGeoMap::Capabilities QGeoTiledMap::capabilities() const +{ + return Capabilities(SupportsVisibleRegion + | SupportsSetBearing + | SupportsAnchoringCoordinate); +} + void QGeoTiledMap::clearScene(int mapId) { Q_D(QGeoTiledMap); diff --git a/src/location/maps/qgeotiledmap_p.h b/src/location/maps/qgeotiledmap_p.h index b709cb57..6152d60d 100644 --- a/src/location/maps/qgeotiledmap_p.h +++ b/src/location/maps/qgeotiledmap_p.h @@ -86,6 +86,7 @@ public: void prefetchData() Q_DECL_OVERRIDE; void clearData() Q_DECL_OVERRIDE; + Capabilities capabilities() const override; public Q_SLOTS: virtual void clearScene(int mapId); diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp index dd5c9a86..c04aa5e3 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp +++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.cpp @@ -372,6 +372,13 @@ void QGeoMapMapboxGL::setMapItemsBefore(const QString &before) d->m_mapItemsBefore = before; } +QGeoMap::Capabilities QGeoMapMapboxGL::capabilities() const +{ + return Capabilities(SupportsVisibleRegion + | SupportsSetBearing + | SupportsAnchoringCoordinate); +} + QSGNode *QGeoMapMapboxGL::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window) { Q_D(QGeoMapMapboxGL); diff --git a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h index 73cfd75a..df76fcab 100644 --- a/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h +++ b/src/plugins/geoservices/mapboxgl/qgeomapmapboxgl.h @@ -57,6 +57,7 @@ public: void setMapboxGLSettings(const QMapboxGLSettings &); void setUseFBO(bool); void setMapItemsBefore(const QString &); + Capabilities capabilities() const override; private Q_SLOTS: // QMapboxGL diff --git a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp index f39bfae3..4835c201 100644 --- a/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp +++ b/src/plugins/geoservices/mapboxgl/qmapboxglstylechange.cpp @@ -89,18 +89,18 @@ QMapbox::Feature featureFromMapRectangle(QDeclarativeRectangleMapItem *mapItem) QMapbox::Feature featureFromMapCircle(QDeclarativeCircleMapItem *mapItem) { static const int circleSamples = 128; - + const QGeoProjectionWebMercator &p = static_cast(mapItem->map()->geoProjection()); QList path; QGeoCoordinate leftBound; QDeclarativeCircleMapItem::calculatePeripheralPoints(path, mapItem->center(), mapItem->radius(), circleSamples, leftBound); QList pathProjected; for (const QGeoCoordinate &c : qAsConst(path)) - pathProjected << mapItem->map()->geoProjection().geoToMapProjection(c); + pathProjected << p.geoToMapProjection(c); if (QDeclarativeCircleMapItem::crossEarthPole(mapItem->center(), mapItem->radius())) mapItem->preserveCircleGeometry(pathProjected, mapItem->center(), mapItem->radius()); path.clear(); for (const QDoubleVector2D &c : qAsConst(pathProjected)) - path << mapItem->map()->geoProjection().mapProjectionToGeo(c); + path << p.mapProjectionToGeo(c); QMapbox::Coordinates coordinates; -- cgit v1.2.3 From 1cac68cce12f3333a1920bdf2abca71470fbab4c Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Mon, 15 Jan 2018 16:15:47 +0100 Subject: Introduce Qt.location.labs Introducing the new labs qml plugin, Qt.labs.location, and associated qt module. The intended use is to introduce and validate new QML API before they can be moved into QtLocation. Change-Id: If70d1dcedaf708be96e918dc5e25578df93db370 Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Alex Blasche --- src/imports/imports.pro | 2 +- src/imports/location/location.cpp | 1 + src/imports/locationlabs/locationlabs.cpp | 89 ++++++++++++++++++++++ src/imports/locationlabs/locationlabs.pro | 15 ++++ src/imports/locationlabs/plugin.json | 2 + src/imports/locationlabs/qmldir | 4 + src/location/configure.json | 8 ++ src/location/declarativemaps/qgeomapobject_p.h | 2 +- src/locationlabs/locationlabs.pro | 11 +++ .../itemsoverlay/qgeomapitemsoverlay.cpp | 2 +- src/src.pro | 11 ++- sync.profile | 1 + 12 files changed, 144 insertions(+), 4 deletions(-) create mode 100644 src/imports/locationlabs/locationlabs.cpp create mode 100644 src/imports/locationlabs/locationlabs.pro create mode 100644 src/imports/locationlabs/plugin.json create mode 100644 src/imports/locationlabs/qmldir create mode 100644 src/locationlabs/locationlabs.pro diff --git a/src/imports/imports.pro b/src/imports/imports.pro index 460fe156..2fd8dbd0 100644 --- a/src/imports/imports.pro +++ b/src/imports/imports.pro @@ -2,4 +2,4 @@ TEMPLATE = subdirs qtHaveModule(positioning): SUBDIRS += positioning qtHaveModule(location): SUBDIRS += location - +qtHaveModule(locationlabs): SUBDIRS += locationlabs diff --git a/src/imports/location/location.cpp b/src/imports/location/location.cpp index dbcb3662..d489d655 100644 --- a/src/imports/location/location.cpp +++ b/src/imports/location/location.cpp @@ -53,6 +53,7 @@ #include #include #include +#include //Place includes #include diff --git a/src/imports/locationlabs/locationlabs.cpp b/src/imports/locationlabs/locationlabs.cpp new file mode 100644 index 00000000..a7719139 --- /dev/null +++ b/src/imports/locationlabs/locationlabs.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//#include +//#include +//#include +//#include + +#include +#include +#include + +static void initResources() +{ +#ifdef QT_STATIC + Q_INIT_RESOURCE(qmake_QtLocationLabs); +#endif +} + +QT_BEGIN_NAMESPACE + + +class QtLocationLabsDeclarativeModule: public QQmlExtensionPlugin +{ + Q_OBJECT + + Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid + FILE "plugin.json") + +public: + QtLocationLabsDeclarativeModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } + virtual void registerTypes(const char *uri) + { + if (QLatin1String(uri) == QLatin1String("Qt.labs.location")) { + + // @uri QtLocationLabs +// int major = 5; +// int minor = 11; + + // Register the 5.11 types +// qmlRegisterType(uri, major, minor, "Navigator"); +// qmlRegisterType(uri, major, minor, "MapIconObject"); +// qmlRegisterType(uri, major, minor, "MapObjectView"); +// qmlRegisterType(uri, major, minor, "MapRouteObject"); + + // Register the latest Qt version as QML type version + qmlRegisterModule(uri, QT_VERSION_MAJOR, QT_VERSION_MINOR); + } else { + qDebug() << "Unsupported URI given to load location QML plugin: " << QLatin1String(uri); + } + } +}; + +#include "locationlabs.moc" + +QT_END_NAMESPACE diff --git a/src/imports/locationlabs/locationlabs.pro b/src/imports/locationlabs/locationlabs.pro new file mode 100644 index 00000000..65941355 --- /dev/null +++ b/src/imports/locationlabs/locationlabs.pro @@ -0,0 +1,15 @@ +QT += quick-private network positioning-private location-private locationlabs-private qml-private core-private gui-private + +TARGET = locationlabsplugin +TARGETPATH = Qt/labs/location +IMPORT_VERSION = 5.11 + +SOURCES += \ + locationlabs.cpp + +#CONFIG += no_cxx_module +load(qml_plugin) + +OTHER_FILES += \ + plugin.json \ + qmldir diff --git a/src/imports/locationlabs/plugin.json b/src/imports/locationlabs/plugin.json new file mode 100644 index 00000000..2c63c085 --- /dev/null +++ b/src/imports/locationlabs/plugin.json @@ -0,0 +1,2 @@ +{ +} diff --git a/src/imports/locationlabs/qmldir b/src/imports/locationlabs/qmldir new file mode 100644 index 00000000..ddaf6ebc --- /dev/null +++ b/src/imports/locationlabs/qmldir @@ -0,0 +1,4 @@ +module Qt.labs.location +plugin locationlabsplugin +classname QtLocationLabsDeclarativeModule +typeinfo plugins.qmltypes diff --git a/src/location/configure.json b/src/location/configure.json index bfa3d6f2..8f74a4be 100644 --- a/src/location/configure.json +++ b/src/location/configure.json @@ -5,6 +5,13 @@ ], "features": { + "labs_plugin": { + "label": "Qt.labs.location experimental QML plugin", + "purpose": "Provides experimental QtLocation QML types", + "section": "Location", + "autoDetect": false, + "output": [ "privateFeature" ] + }, "geoservices_osm": { "label": "OpenStreetMap", "purpose": "Provides access to OpenStreetMap geoservices", @@ -53,6 +60,7 @@ { "section": "Qt Location", "entries": [ + "labs_plugin", { "section": "Geoservice plugins", "entries": [ diff --git a/src/location/declarativemaps/qgeomapobject_p.h b/src/location/declarativemaps/qgeomapobject_p.h index 9f479dd7..91e5667f 100644 --- a/src/location/declarativemaps/qgeomapobject_p.h +++ b/src/location/declarativemaps/qgeomapobject_p.h @@ -73,7 +73,7 @@ public: enum Type { InvalidType = 0, - LayerType = 1, + ViewType = 1, RouteType = 2, RectangleType = 3, CircleType = 4, diff --git a/src/locationlabs/locationlabs.pro b/src/locationlabs/locationlabs.pro new file mode 100644 index 00000000..add700ca --- /dev/null +++ b/src/locationlabs/locationlabs.pro @@ -0,0 +1,11 @@ +TARGET = QtLocationLabs + +QT += core-private gui-private quick-private location-private positioning-private positioningquick-private + +CONFIG += simd optimize_full + +SOURCES += $$files(*.cpp) +HEADERS += $$files(*.h) + +load(qt_module) + diff --git a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp index fecae107..8d5edc6d 100644 --- a/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp +++ b/src/plugins/geoservices/itemsoverlay/qgeomapitemsoverlay.cpp @@ -43,7 +43,7 @@ QT_BEGIN_NAMESPACE class QGeoMapItemsOverlayPrivate : public QGeoMapPrivate { - Q_DECLARE_PUBLIC(QGeoMap) + Q_DECLARE_PUBLIC(QGeoMapItemsOverlay) public: QGeoMapItemsOverlayPrivate(QGeoMappingManagerEngineItemsOverlay *engine); diff --git a/src/src.pro b/src/src.pro index 74c5ac4c..9cef3da0 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,5 +1,9 @@ TEMPLATE = subdirs +QT_FOR_CONFIG += location-private +include($$OUT_PWD/location/qtlocation-config.pri) +include($$OUT_PWD/positioning/qtpositioning-config.pri) + clip2tri.subdir = 3rdparty/clip2tri poly2tri.subdir = 3rdparty/poly2tri clipper.subdir = 3rdparty/clipper @@ -17,10 +21,15 @@ qtHaveModule(quick) { plugins.depends += location + exists(locationlabs):qtConfig(labs_plugin) { + SUBDIRS += locationlabs + locationlabs.depends += location + } + SUBDIRS += imports imports.depends += positioningquick positioning location + exists(locationlabs):qtConfig(labs_plugin): imports.depends += locationlabs } - plugins.depends += positioning SUBDIRS += plugins diff --git a/sync.profile b/sync.profile index dcdc7296..57d89c2b 100644 --- a/sync.profile +++ b/sync.profile @@ -2,6 +2,7 @@ "QtLocation" => "$basedir/src/location", "QtPositioning" => "$basedir/src/positioning", "QtPositioningQuick" => "$basedir/src/positioningquick", + "QtLocationLabs" => "$basedir/src/locationlabs", ); %moduleheaders = ( # restrict the module headers to those found in relative path ); -- cgit v1.2.3 From 8cadb29f0d649293d3697649807179ab504f37f1 Mon Sep 17 00:00:00 2001 From: Paolo Angelelli Date: Thu, 25 Jan 2018 16:28:43 +0100 Subject: Revert changing access rights to d_ptr in QGeoRoute/Segment As some compilers may put these information in the signature, changing this may break the ABI. Change-Id: I80cce605c735680e6969e84feac57f58b4aa5af4 Reviewed-by: Alex Blasche --- src/location/maps/qgeoroute.cpp | 8 ++++++++ src/location/maps/qgeoroute.h | 3 +++ src/location/maps/qgeoroutesegment.cpp | 8 ++++++++ src/location/maps/qgeoroutesegment.h | 2 ++ 4 files changed, 21 insertions(+) diff --git a/src/location/maps/qgeoroute.cpp b/src/location/maps/qgeoroute.cpp index d2f6fb51..237d9b68 100644 --- a/src/location/maps/qgeoroute.cpp +++ b/src/location/maps/qgeoroute.cpp @@ -86,6 +86,14 @@ QGeoRoute::QGeoRoute(const QExplicitlySharedDataPointer &dd): { } +/*! + Returns the private implementation. +*/ +QExplicitlySharedDataPointer &QGeoRoute::d() +{ + return d_ptr; +} + /*! Constructs a route object from the contents of \a other. */ diff --git a/src/location/maps/qgeoroute.h b/src/location/maps/qgeoroute.h index de319b4c..ef1f7566 100644 --- a/src/location/maps/qgeoroute.h +++ b/src/location/maps/qgeoroute.h @@ -89,6 +89,9 @@ public: protected: QGeoRoute(const QExplicitlySharedDataPointer &dd); + QExplicitlySharedDataPointer &d(); + +private: QExplicitlySharedDataPointer d_ptr; friend class QDeclarativeGeoRoute; friend class QGeoRoutePrivate; diff --git a/src/location/maps/qgeoroutesegment.cpp b/src/location/maps/qgeoroutesegment.cpp index 8dbe18fc..1f72bf73 100644 --- a/src/location/maps/qgeoroutesegment.cpp +++ b/src/location/maps/qgeoroutesegment.cpp @@ -87,6 +87,14 @@ QGeoRouteSegment::QGeoRouteSegment(const QGeoRouteSegment &other) QGeoRouteSegment::QGeoRouteSegment(const QExplicitlySharedDataPointer &dd) : d_ptr(dd) {} +/*! + Returns the private implementation. +*/ +QExplicitlySharedDataPointer &QGeoRouteSegment::d() +{ + return d_ptr; +} + /*! Destroys this route segment object. */ diff --git a/src/location/maps/qgeoroutesegment.h b/src/location/maps/qgeoroutesegment.h index a90399be..3ce01151 100644 --- a/src/location/maps/qgeoroutesegment.h +++ b/src/location/maps/qgeoroutesegment.h @@ -79,7 +79,9 @@ public: protected: QGeoRouteSegment(const QExplicitlySharedDataPointer &dd); + QExplicitlySharedDataPointer &d(); +private: QExplicitlySharedDataPointer d_ptr; }; -- cgit v1.2.3