// Copyright (C) 2015 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qgeoroute.h" #include "qgeoroute_p.h" #include "qgeorectangle.h" #include "qgeoroutesegment.h" #include #include QT_BEGIN_NAMESPACE QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QGeoRoutePrivate) /*! \class QGeoRoute \inmodule QtLocation \ingroup QtLocation-routing \since 5.6 \brief The QGeoRoute class represents a route between two points. A QGeoRoute object contains high level information about a route, such as the length the route, the estimated travel time for the route, and enough information to render a basic image of the route on a map. The QGeoRoute object also contains a list of QGeoRouteSegment objecs which describe subsections of the route in greater detail. Routing information is normally requested using QGeoRoutingManager::calculateRoute(), which returns a QGeoRouteReply instance. If the operation is completed successfully the routing information can be accessed with QGeoRouteReply::routes() \sa QGeoRoutingManager */ /*! \qmlvaluetype route \inqmlmodule QtLocation \ingroup qml-QtLocation5-routing \since QtLocation 5.5 \brief The route type represents one geographical route. A route type contains high level information about a route, such as the length the route, the estimated travel time for the route, and enough information to render a basic image of the route on a map. The QGeoRoute object also contains a list of \l routeSegment objects which describe subsections of the route in greater detail. The primary means of acquiring route objects is \l RouteModel. \section1 Example This example shows how to display a route's maneuvers in a ListView: \snippet declarative/routing.qml QtQuick import \snippet declarative/maps.qml QtLocation import \codeline \snippet declarative/routing.qml Route Maneuver List1 \snippet declarative/routing.qml Route Maneuver List2 \snippet declarative/routing.qml Route Maneuver List3 */ /*! Constructs a route object. */ QGeoRoute::QGeoRoute() : d_ptr(new QGeoRoutePrivate()) {} /*! Returns the private implementation. */ QExplicitlySharedDataPointer &QGeoRoute::d() { return d_ptr; } const QExplicitlySharedDataPointer &QGeoRoute::const_d() const { return d_ptr; } /*! Constructs a route object from the contents of \a other. */ QGeoRoute::QGeoRoute(const QGeoRoute &other) noexcept = default; /*! Destroys this route object. */ QGeoRoute::~QGeoRoute() = default; /*! Assigns the contents of \a other to this route and returns a reference to this route. */ QGeoRoute &QGeoRoute::operator=(const QGeoRoute & other) noexcept { if (this == &other) return *this; d_ptr = other.d_ptr; return *this; } /*! \fn bool QGeoRoute::operator==(const QGeoRoute &lhs, const QGeoRoute &rhs) noexcept Returns whether the routes \a lhs and \a rhs are equal. */ /*! \fn bool QGeoRoute::operator!=(const QGeoRoute &lhs, const QGeoRoute &rhs) noexcept Returns whether the routes \a lhs and \a rhs are not equal. */ bool QGeoRoute::isEqual(const QGeoRoute &other) const noexcept { return ( (d_ptr.constData() == other.d_ptr.constData()) || (*d_ptr) == (*other.d_ptr)); } /*! \property QGeoRoute::routeId \brief the identifier of this route Service providers which support the updating of routes commonly assign identifiers to routes. If this route came from such a service provider, then changing the identifier will probably cause route updates to stop working. */ void QGeoRoute::setRouteId(const QString &id) { d_ptr->setId(id); } QString QGeoRoute::routeId() const { return d_ptr->id(); } /*! \internal \property QGeoRoute::request \brief the route request which describes the criteria used in the calculation of this route */ void QGeoRoute::setRequest(const QGeoRouteRequest &request) { d_ptr->setRequest(request); } QGeoRouteRequest QGeoRoute::request() const { return d_ptr->request(); } /*! \qmlproperty georectangle QtLocation::route::bounds Read-only property which holds a bounding box which encompasses the entire route. */ /*! \property QGeoRoute::bounds \brief the bounding box which encompasses the entire route */ void QGeoRoute::setBounds(const QGeoRectangle &bounds) { d_ptr->setBounds(bounds); } QGeoRectangle QGeoRoute::bounds() const { return d_ptr->bounds(); } /*! Sets the first route segment in the route to \a routeSegment. */ void QGeoRoute::setFirstRouteSegment(const QGeoRouteSegment &routeSegment) { d_ptr->setFirstSegment(routeSegment); } /*! Returns the first route segment in the route. Will return an invalid route segment if there are no route segments associated with the route. The remaining route segments can be accessed sequentially with QGeoRouteSegment::nextRouteSegment. */ QGeoRouteSegment QGeoRoute::firstRouteSegment() const { return d_ptr->firstSegment(); } /*! \qmlmethod int QtLocation::route::segmentsCount() Returns the number of segments in the route \sa routeSegment \since 5.11 */ /*! \property QGeoRoute::segmentsCount \brief the number of segments in the route */ qsizetype QGeoRoute::segmentsCount() const { return d_ptr->segmentsCount(); } /*! \qmlproperty list QtLocation::route::segments Read-only property which holds the list of \l routeSegment objects of this route. To access individual segments you can use standard list accessors: 'segments.length' indicates the number of objects and 'segments[index starting from zero]' gives the actual objects. \sa routeSegment */ /*! \property QGeoRoute::segments \brief the list of QGeoRouteSegment objects of this route */ QList QGeoRoute::segments() const { return d_ptr->segments(); } /*! \qmlproperty int QtLocation::route::travelTime Read-only property which holds the estimated amount of time it will take to traverse this route, in seconds. */ /*! \property QGeoRoute::travelTime \brief the estimated amount of time it will take to traverse this route, in seconds */ void QGeoRoute::setTravelTime(int secs) { d_ptr->setTravelTime(secs); } int QGeoRoute::travelTime() const { return d_ptr->travelTime(); } /*! \qmlproperty real QtLocation::route::distance Read-only property which holds distance covered by this route, in meters. */ /*! \property QGeoRoute::distance \brief the distance covered by this route, in meters */ void QGeoRoute::setDistance(qreal distance) { d_ptr->setDistance(distance); } qreal QGeoRoute::distance() const { return d_ptr->distance(); } /*! Sets the travel mode for this route to \a mode. This should be one of the travel modes returned by request().travelModes(). */ void QGeoRoute::setTravelMode(QGeoRouteRequest::TravelMode mode) { d_ptr->setTravelMode(mode); } /*! Returns the travel mode for the this route. This should be one of the travel modes returned by request().travelModes(). */ QGeoRouteRequest::TravelMode QGeoRoute::travelMode() const { return d_ptr->travelMode(); } /*! \qmlproperty list QtLocation::route::path Read-only property which holds the geographical coordinates of this route. Coordinates are listed in the order in which they would be traversed by someone traveling along this segment of the route. To access individual segments you can use standard list accessors: 'path.length' indicates the number of objects and 'path[index starting from zero]' gives the actual object. \sa QtPositioning::coordinate */ /*! \property QGeoRoute::path \brief the geometric shape of the route The coordinates should be listed in the order in which they would be traversed by someone traveling along this segment of the route. */ void QGeoRoute::setPath(const QList &path) { d_ptr->setPath(path); } QList QGeoRoute::path() const { return d_ptr->path(); } /*! \qmlproperty list QtLocation::route::legs Returns the route legs associated with this route. Route legs are the sub-routes between each two adjacent waypoints. The result may be empty, if this level of detail is not supported by the backend. \since QtLocation 5.12 */ /*! \property QGeoRoute::routeLegs \brief the route \a legs for a multi-waypoint route \since 5.12 */ void QGeoRoute::setRouteLegs(const QList &legs) { d_ptr->setRouteLegs(legs); } QList QGeoRoute::routeLegs() const { return d_ptr->routeLegs(); } /*! \qmlproperty Object route::extendedAttributes This property holds the extended attributes of the route and is a map. These attributes are plugin specific, and can be empty. Consult the \l {Qt Location#Plugin References and Parameters}{plugin documentation} for what attributes are supported and how they should be used. Note, due to limitations of the QQmlPropertyMap, it is not possible to declaratively specify the attributes in QML, assignment of attributes keys and values can only be accomplished by JavaScript. \since QtLocation 5.13 */ /*! \property QGeoRoute::extendedAttributes \brief the extended attributes associated with this route \since 5.13 */ void QGeoRoute::setExtendedAttributes(const QVariantMap &extendedAttributes) { d_ptr->setExtendedAttributes(extendedAttributes); } QVariantMap QGeoRoute::extendedAttributes() const { return d_ptr->extendedAttributes(); } /*! \qmlproperty int QtLocation::route::legIndex Read-only property which holds the index of the leg within the containing route's list of QtLocation::route::legs. The index is -1 if this route is not a leg within an overall route. \sa overallRoute */ /*! \property QGeoRoute::legIndex \brief the leg index of this route The index of the leg inside the containing QGeoRoute::routeLegs list can be used to find the next legs. */ void QGeoRoute::setLegIndex(int idx) { d()->setLegIndex(idx); } int QGeoRoute::legIndex() const { return const_d()->legIndex(); } /*! \qmlproperty Route QtLocation::route::overallRoute Read-only property which holds the route that contains this leg. */ /*! \property QGeoRoute::overallRoute \brief the route that contains this route leg This this route is not a leg within an overall route, then this property holds an empty route. */ void QGeoRoute::setOverallRoute(const QGeoRoute &route) { d()->setContainingRoute(route); } QGeoRoute QGeoRoute::overallRoute() const { return const_d()->containingRoute(); } /******************************************************************************* *******************************************************************************/ bool QGeoRoutePrivate::operator ==(const QGeoRoutePrivate &other) const { return equals(other); } bool QGeoRoutePrivate::equals(const QGeoRoutePrivate &other) const { // here both routes are of type QGeoRoutePrivate QGeoRouteSegment s1 = firstSegment(); QGeoRouteSegment s2 = other.firstSegment(); while (true) { if (s1.isValid() != s2.isValid()) return false; if (!s1.isValid()) break; if (s1 != s2) return false; s1 = s1.nextRouteSegment(); 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() && routeLegs() == other.routeLegs() && extendedAttributes() == other.extendedAttributes(); } void QGeoRoutePrivate::setId(const QString &id) { m_id = id; } QString QGeoRoutePrivate::id() const { return m_id; } void QGeoRoutePrivate::setRequest(const QGeoRouteRequest &request) { m_request = request; } QGeoRouteRequest QGeoRoutePrivate::request() const { return m_request; } void QGeoRoutePrivate::setBounds(const QGeoRectangle &bounds) { m_bounds = bounds; } QGeoRectangle QGeoRoutePrivate::bounds() const { return m_bounds; } void QGeoRoutePrivate::setTravelTime(int travelTime) { m_travelTime = travelTime; } int QGeoRoutePrivate::travelTime() const { return m_travelTime; } void QGeoRoutePrivate::setDistance(qreal distance) { m_distance = distance; } qreal QGeoRoutePrivate::distance() const { return m_distance; } void QGeoRoutePrivate::setTravelMode(QGeoRouteRequest::TravelMode mode) { m_travelMode = mode; } QGeoRouteRequest::TravelMode QGeoRoutePrivate::travelMode() const { return m_travelMode; } void QGeoRoutePrivate::setPath(const QList &path) { m_path = path; } QList QGeoRoutePrivate::path() const { return m_path; } void QGeoRoutePrivate::setFirstSegment(const QGeoRouteSegment &firstSegment) { m_firstSegment = firstSegment; m_numSegments = -1; } QGeoRouteSegment QGeoRoutePrivate::firstSegment() const { return m_firstSegment; } int QGeoRoutePrivate::segmentsCount() const { if (m_numSegments >= 0) return m_numSegments; int count = 0; forEachSegment([&count](const QGeoRouteSegment &){ ++count; }); m_numSegments = count; return count; } QList QGeoRoutePrivate::segments() const { QList segments; forEachSegment([&segments](const QGeoRouteSegment &segment){ segments.append(segment); }); return segments; } void QGeoRoutePrivate::setRouteLegs(const QList &legs) { m_legs = legs; } QList QGeoRoutePrivate::routeLegs() const { return m_legs; } void QGeoRoutePrivate::setExtendedAttributes(const QVariantMap &extendedAttributes) { m_extendedAttributes = extendedAttributes; } QVariantMap QGeoRoutePrivate::extendedAttributes() const { return m_extendedAttributes; } void QGeoRoutePrivate::setLegIndex(int idx) { if (idx >= 0) m_legIndex = idx; } int QGeoRoutePrivate::legIndex() const { return m_legIndex; } void QGeoRoutePrivate::setContainingRoute(const QGeoRoute &route) { m_containingRoute.reset(new QGeoRoute(route)); } QGeoRoute QGeoRoutePrivate::containingRoute() const { if (m_containingRoute) return *m_containingRoute; return QGeoRoute(); } QT_END_NAMESPACE #include "moc_qgeoroute.cpp"