1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtLocation module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 or (at your option) any later version
20 ** approved by the KDE Free Qt Foundation. The licenses are as published by
21 ** the Free Software Foundation and appearing in the file LICENSE.GPL3
22 ** included in the packaging of this file. Please review the following
23 ** information to ensure the GNU General Public License requirements will
24 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
25 **
26 ** $QT_END_LICENSE$
27 **
28 ****************************************************************************/
29 
30 #include "qdeclarativenavigator_p.h"
31 #include "qdeclarativenavigator_p_p.h"
32 #include <QtLocation/private/qdeclarativegeomap_p.h>
33 #include <QtLocation/private/qdeclarativegeoserviceprovider_p.h>
34 #include <QtLocation/private/qnavigationmanager_p.h>
35 #include <QtLocation/private/qnavigationmanagerengine_p.h>
36 #include <QtLocation/private/qgeomapparameter_p.h>
37 #include <QtLocation/private/qdeclarativegeoroute_p.h>
38 #include <QtLocation/private/qdeclarativegeoroutemodel_p.h>
39 #include <QtLocation/private/qdeclarativegeoroutesegment_p.h>
40 #include <QtLocation/qgeoserviceprovider.h>
41 #include <QtPositioningQuick/private/qdeclarativepositionsource_p.h>
42 #include <QtQml/qqmlinfo.h>
43 
44 QT_BEGIN_NAMESPACE
45 
46 /*!
47     \qmlmodule Qt.labs.location 1.0
48     \title Qt Labs Location QML Types
49     \ingroup qmlmodules
50     \brief Provides experimental QtLocation QML types, such as \l Navigator and
51     various map objects types (not to be confused with map items).
52 
53     To use this module, import the module with the following line:
54 
55     \qml
56     import Qt.labs.location 1.0
57     \endqml
58 
59     \note These types are experimental and subject to source-incompatible changes from one
60     Qt minor release to the next, until they are ready to be moved to the stable QtLocation QML
61     module.
62 */
63 
64 /*!
65     \qmltype Navigator
66     \instantiates QDeclarativeNavigator
67     \inqmlmodule Qt.labs.location
68     \ingroup qml-QtLocation5-maps
69 
70     \brief The Navigator type offers functionalities to perform turn-by-turn navigation.
71 
72     The Navigator purpose is to use a plugin's turn-by-turn navigation implementation in a QML
73     application in a seamless manner.
74     This object may take control of the map position, orientation, tilting and zoom, as well as changing
75     the map style, elements on the map such as direction information.
76     In certain cases, it may also restrict user interaction with the Map and with the items on it.
77 */
78 
79 /*!
80     \qmlproperty Plugin Qt.labs.location::Navigator::plugin
81 
82     This property holds the plugin which provides the navigation functionality.
83 
84     This is a write-once property. Once the Navigator has a plugin associated with
85     it, any attempted modifications of the plugin property will be ignored.
86 
87     \sa Plugin
88 */
89 
90 /*!
91     \qmlproperty Map Qt.labs.location::Navigator::map
92 
93     This property holds the Map that the navigator is in charge of controlling.
94 
95     This is a write-once property. Once the Navigator has a Map associated with
96     it, any attempted modifications of the map property will be ignored.
97 
98     \sa Map
99 */
100 
101 /*!
102     \qmlproperty Route Qt.labs.location::Navigator::route
103 
104     This property holds the Route that the navigator is using
105     to perform the navigation.
106 
107     \note Setting this property while a navigation session is ongoing will
108     stop the navigation.
109 
110     \sa Route
111 */
112 
113 /*!
114     \qmlproperty PositionSource Qt.labs.location::Navigator::positionSource
115 
116     This property holds the PositionSource that the navigator will receive position
117     updates from to perform the navigation.
118 
119     This is a write-once property. Once the Navigator has a PositionSource associated with
120     it, any attempted modifications of the positionSource property will be ignored.
121 
122     \sa PositionSource
123 */
124 
125 /*!
126     \qmlproperty bool Qt.labs.location::Navigator::active
127 
128     This property tells whether the Navigator is navigating or not.
129     Set this property to \c true to start the navigation.
130     Set it to \c false to stop an active navigation session.
131 */
132 
133 /*!
134     \qmlproperty bool Qt.labs.location::Navigator::navigatorReady
135 
136     This read-only property tells whether the navigator is ready
137     to start the navigation or not.
138     A Navigator becomes ready once the plugin is attached and a navigation engine has been
139     instantiated, and the other required properties are set to valid values.
140 */
141 
142 /*!
143     \qmlproperty bool Qt.labs.location::Navigator::trackPositionSource
144 
145     This property tells whether the Navigator should control the Map camera to
146     keep track of position source updates. This property is enabled (\c true) by
147     default, and setting it to \c false is useful in cases where e.g. the user
148     starts gesturing over the map area.
149 
150     Navigator plugins can also control this property directly e.g. user map
151     interaction could trigger the property change. Honoring the user-specified
152     value of this property is plugin dependent.
153 */
154 
155 /*!
156     \qmlproperty bool Qt.labs.location::Navigator::automaticReroutingEnabled
157 
158     This property tells whether the Navigator should automatically recalculate
159     the route when the position from \l positionSource ends too far from the route.
160     The operation performed in such case is equivalent to calling \l recalculateRoutes.
161     The default value is \c true.
162 
163     \note Whether this property has any effect is plugin-dependent.
164     Also, whether or not it has an effect while the navigator is active is plugin-dependent.
165 */
166 
167 /*!
168     \qmlproperty bool Qt.labs.location::Navigator::isOnRoute
169 
170     While the Navigator is in active tracking mode, this property tells
171     whether the position from \l positionSource is on the route or not.
172 */
173 
174 /*!
175     \qmlmethod void Qt.labs.location::Navigator::recalculateRoutes()
176 
177     Calling this method forces the backend to trigger a routes recalculation.
178 
179     \sa automaticReroutingEnabled
180 */
181 
182 /*!
183     \qmlproperty enumeration Qt.labs.location::Navigator::error
184     \readonly
185 
186     This read-only property holds the latest error value of the geocoding request.
187 
188     \value Navigator.NoError
189            No error has occurred.
190     \value Navigator.NotSupportedError
191            Navigation is not supported by the service provider.
192     \value Navigator.ConnectionError
193            An error occurred while communicating with the service provider.
194     \value Navigator.LoaderError
195            The geoservice provider library could not be loaded. Setting
196            QT_DEBUG_PLUGINS environment variable may help diagnosing the
197            problem.
198     \value Navigator.UnknownParameterError
199            An unknown parameter was specified.
200     \value Navigator.MissingRequiredParameterError
201            Required parameter was not specified.
202     \value Navigator.UnknownError
203            Unknown error occurred.
204 */
205 
QDeclarativeNavigatorPrivate(QParameterizableObject * q_)206 QDeclarativeNavigatorPrivate::QDeclarativeNavigatorPrivate(QParameterizableObject *q_)
207     : q(q_), m_params(new QDeclarativeNavigatorParams), m_basicDirections(static_cast<QDeclarativeNavigator *>(q_))
208 {
209 }
210 
QDeclarativeNavigator(QObject * parent)211 QDeclarativeNavigator::QDeclarativeNavigator(QObject *parent)
212     : QParameterizableObject(parent), d_ptr(new QDeclarativeNavigatorPrivate(this))
213 {
214 }
215 
~QDeclarativeNavigator()216 QDeclarativeNavigator::~QDeclarativeNavigator()
217 {
218 }
219 
classBegin()220 void QDeclarativeNavigator::classBegin()
221 {
222 }
223 
componentComplete()224 void QDeclarativeNavigator::componentComplete()
225 {
226     d_ptr->m_completed = true;
227     // Children have been completed
228     for (auto param : quickChildren<QGeoMapParameter>())
229         d_ptr->m_params->m_parameters.push_back(param);
230     if (d_ptr->m_plugin && d_ptr->m_plugin->isAttached())
231         pluginReady();
232 }
233 
plugin() const234 QDeclarativeGeoServiceProvider *QDeclarativeNavigator::plugin() const
235 {
236     return d_ptr->m_plugin;
237 }
238 
setMap(QDeclarativeGeoMap * map)239 void QDeclarativeNavigator::setMap(QDeclarativeGeoMap *map)
240 {
241     if (d_ptr->m_params->m_map || !map) // set once prop
242         return;
243 
244     d_ptr->m_params->m_map = map;
245     connect(map, &QObject::destroyed, this,
246             [this]() {
247                 this->mapChanged();
248                 this->updateReadyState();
249             });
250     emit mapChanged();
251     updateReadyState();
252 }
253 
map() const254 QDeclarativeGeoMap *QDeclarativeNavigator::map() const
255 {
256     return d_ptr->m_params->m_map;
257 }
258 
setRoute(QDeclarativeGeoRoute * route)259 void QDeclarativeNavigator::setRoute(QDeclarativeGeoRoute *route)
260 {
261     if (d_ptr->m_params->m_route == route) // This isn't set-once
262         return;
263 
264     const bool isReady = d_ptr->m_navigator && d_ptr->m_navigator->ready();
265     const bool isActive = active();
266     if (isReady && isActive)
267         setActive(false); // Stop current session
268 
269     d_ptr->m_params->m_route = route;
270     d_ptr->m_params->m_geoRoute = route ? route->route() : QGeoRoute();
271     if (route) {
272         connect(route, &QObject::destroyed,
273                 [this]() {
274                     // Do not stop navigation if route disappears. d_ptr->m_geoRoute will still be valid.
275                     // Engines can stop navigation if desired.
276                     this->routeChanged();
277                 });
278     }
279     emit routeChanged();
280     updateReadyState();
281 }
282 
route() const283 QDeclarativeGeoRoute *QDeclarativeNavigator::route() const
284 {
285     return d_ptr->m_params->m_route;
286 }
287 
setPositionSource(QDeclarativePositionSource * positionSource)288 void QDeclarativeNavigator::setPositionSource(QDeclarativePositionSource *positionSource)
289 {
290     if (d_ptr->m_params->m_positionSource || !positionSource) // set once prop
291         return;
292 
293     d_ptr->m_params->m_positionSource = positionSource;
294     QObject::connect(positionSource, &QObject::destroyed,
295             [this]() {
296                 this->positionSourceChanged();
297                 this->updateReadyState();
298             }
299     );
300     emit positionSourceChanged();
301     updateReadyState();
302 }
303 
positionSource() const304 QDeclarativePositionSource *QDeclarativeNavigator::positionSource() const
305 {
306     return d_ptr->m_params->m_positionSource;
307 }
308 
309 // navigator automatically adjusts route when user leaves it
automaticReroutingEnabled() const310 bool QDeclarativeNavigator::automaticReroutingEnabled() const
311 {
312     if (d_ptr->m_navigator)
313         return d_ptr->m_navigator->automaticReroutingEnabled();
314     return d_ptr->m_params->m_autoRerouting;
315 }
316 
317 // Whether or not it has an effect while the navigator is active should be plugin-dependent
setAutomaticReroutingEnabled(bool autoRerouting)318 void QDeclarativeNavigator::setAutomaticReroutingEnabled(bool autoRerouting)
319 {
320     const bool autoReroutingOld = automaticReroutingEnabled();
321     d_ptr->m_params->m_autoRerouting = autoRerouting;
322     // Done this way, and not via signal like setTrackPositionSource because
323     // plugins might not support automatic rerouting.
324     if (d_ptr->m_navigator)
325         d_ptr->m_navigator->setAutomaticReroutingEnabled(autoRerouting);
326     if (autoRerouting != autoReroutingOld)
327         emit automaticReroutingEnabledChanged();
328 }
329 
330 
navigatorReady() const331 bool QDeclarativeNavigator::navigatorReady() const
332 {
333     if (d_ptr->m_navigator)
334         return d_ptr->m_navigator->ready();
335     return d_ptr->m_ready;
336 }
337 
trackPositionSource() const338 bool QDeclarativeNavigator::trackPositionSource() const
339 {
340     return d_ptr->m_params->m_trackPositionSource;
341 }
342 
343 // Navigator is in active tracking mode and the route is being followed.
344 // This may turn \c false if the user leaves the route.
isOnRoute() const345 bool QDeclarativeNavigator::isOnRoute() const
346 {
347     if (d_ptr->m_navigator)
348         return d_ptr->m_navigator->isOnRoute();
349     return false;
350 }
351 
setTrackPositionSource(bool trackPositionSource)352 void QDeclarativeNavigator::setTrackPositionSource(bool trackPositionSource)
353 {
354     if (trackPositionSource == d_ptr->m_params->m_trackPositionSource)
355         return;
356 
357     d_ptr->m_params->m_trackPositionSource = trackPositionSource;
358 
359     emit trackPositionSourceChanged(trackPositionSource);
360 }
361 
directions() const362 QDeclarativeNavigationBasicDirections *QDeclarativeNavigator::directions() const
363 {
364     return &d_ptr->m_basicDirections;
365 }
366 
error() const367 QDeclarativeNavigator::NavigationError QDeclarativeNavigator::error() const
368 {
369     return d_ptr->m_error;
370 }
371 
errorString() const372 QString QDeclarativeNavigator::errorString() const
373 {
374     return d_ptr->m_errorString;
375 }
376 
recalculateRoutes()377 void QDeclarativeNavigator::recalculateRoutes()
378 {
379     if (d_ptr->m_navigator)
380         d_ptr->m_navigator->recalculateRoutes();
381 }
382 
383 /*  !NOT DOCUMENTED YET!
384     \qmlproperty QAbstractNavigator *Qt.labs.location::Navigator::engineHandle
385 
386     This property returns a handle to the navigation object created by the engine.
387     This object can carry engine-specific properties, signals and methods, to expose
388     engine-specific features and data.
389 
390     \warning Using this property leads to writing code that's likely to work
391              with only a single plugin.
392 */
abstractNavigator() const393 QAbstractNavigator *QDeclarativeNavigator::abstractNavigator() const
394 {
395     return d_ptr->m_navigator.data();
396 
397 }
398 
active() const399 bool QDeclarativeNavigator::active() const
400 {
401     return d_ptr->m_active;
402 }
403 
setPlugin(QDeclarativeGeoServiceProvider * plugin)404 void QDeclarativeNavigator::setPlugin(QDeclarativeGeoServiceProvider *plugin)
405 {
406     if (d_ptr->m_plugin)
407         return; // set once property.
408 
409     d_ptr->m_plugin = plugin;
410     emit pluginChanged();
411 
412     if (d_ptr->m_plugin->isAttached()) {
413         pluginReady();
414     } else {
415         connect(d_ptr->m_plugin, &QDeclarativeGeoServiceProvider::attached,
416                 this, &QDeclarativeNavigator::pluginReady);
417     }
418 }
419 
setActive(bool active)420 void QDeclarativeNavigator::setActive(bool active)
421 {
422     if (d_ptr->m_active == active)
423         return;
424 
425     d_ptr->m_active = active;
426     if (!d_ptr->m_plugin)
427         return;
428 
429     if (active)
430         start();
431     else
432         stop();
433 }
434 
start()435 void QDeclarativeNavigator::start()
436 {
437     if (!d_ptr->m_ready) {
438         qmlWarning(this) << QStringLiteral("Navigation manager not ready.");
439         return;
440     }
441 
442     if (!d_ptr->m_navigator->active())
443         d_ptr->m_active = d_ptr->m_navigator->start();
444 }
445 
stop()446 void QDeclarativeNavigator::stop()
447 {
448     if (!ensureEngine()) { // If somebody re-set route to null or something, this may become !d_ptr->m_ready
449         qmlWarning(this) << QStringLiteral("Navigation manager not ready.");
450         return;
451     }
452 
453     if (d_ptr->m_navigator->active())
454         d_ptr->m_active = d_ptr->m_navigator->stop();
455 
456     // Cached data are cleared in response to signals emitted by m_navigator upon stop().
457     // For example, m_navigator emits currentRouteChanged with an empty route,
458     // and QDeclarativeNavigationBasicDirections reacts by clearing the declarative route.
459 }
460 
pluginReady()461 void QDeclarativeNavigator::pluginReady()
462 {
463     if (!d_ptr->m_completed)
464         return;
465 
466     ensureEngine();
467     updateReadyState();
468     if (d_ptr->m_active)
469         start();
470 }
471 
ensureEngine()472 bool QDeclarativeNavigator::ensureEngine()
473 {
474     if (d_ptr->m_navigator)
475         return true;
476     if (!d_ptr->m_completed || !d_ptr->m_plugin->isAttached())
477         return false;
478 
479     QGeoServiceProvider *serviceProvider = d_ptr->m_plugin->sharedGeoServiceProvider();
480     // if m_plugin->isAttached(), serviceProvider cannot be null
481     QNavigationManager *manager = serviceProvider->navigationManager();
482 
483     if (serviceProvider->navigationError() != QGeoServiceProvider::NoError) {
484         QDeclarativeNavigator::NavigationError newError = UnknownError;
485         switch (serviceProvider->navigationError()) {
486         case QGeoServiceProvider::NotSupportedError:
487             newError = NotSupportedError; break;
488         case QGeoServiceProvider::UnknownParameterError:
489             newError = UnknownParameterError; break;
490         case QGeoServiceProvider::MissingRequiredParameterError:
491             newError = MissingRequiredParameterError; break;
492         case QGeoServiceProvider::ConnectionError:
493             newError = ConnectionError; break;
494         case QGeoServiceProvider::LoaderError:
495             newError = LoaderError; break;
496         default:
497             break;
498         }
499 
500         setError(newError, serviceProvider->navigationErrorString());
501         return false;
502     }
503 
504     if (!manager) {
505         setError(NotSupportedError, tr("Plugin does not support navigation."));
506         return false;
507     }
508 
509     d_ptr->m_navigator.reset(manager->createNavigator(d_ptr->m_params));
510     if (!d_ptr->m_navigator) {
511         setError(UnknownError, tr("Failed to create a navigator object."));
512         return false;
513     }
514 
515     d_ptr->m_navigator->setLocale(manager->locale());
516     d_ptr->m_navigator->setMeasurementSystem(manager->measurementSystem());
517 
518     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::activeChanged, this, [this](bool active){
519         d_ptr->m_active = active;
520         emit activeChanged(active);
521     });
522     connect(this, &QDeclarativeNavigator::trackPositionSourceChanged, d_ptr->m_navigator.get(), &QAbstractNavigator::setTrackPosition);
523 
524     // read-only progress info updates
525     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::waypointReached,
526             &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::waypointReached);
527     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::destinationReached,
528             &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::destinationReached);
529     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentRouteChanged,
530             &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::onCurrentRouteChanged);
531     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentRouteLegChanged,
532             &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::onCurrentRouteLegChanged);
533     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::currentSegmentChanged,
534             &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::currentSegmentChanged);
535     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::nextManeuverIconChanged,
536             &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::nextManeuverIconChanged);
537     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::progressInformationChanged,
538             &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::progressInformationChanged);
539     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::isOnRouteChanged,
540             this, &QDeclarativeNavigator::isOnRouteChanged);
541     connect(d_ptr->m_navigator.get(), &QAbstractNavigator::alternativeRoutesChanged,
542             &d_ptr->m_basicDirections, &QDeclarativeNavigationBasicDirections::onAlternativeRoutesChanged);
543 
544     emit navigatorReadyChanged(true);
545     return true;
546 }
547 
updateReadyState()548 void QDeclarativeNavigator::updateReadyState() {
549     const bool oldReady = d_ptr->m_ready;
550     if (!d_ptr->m_navigator)
551         d_ptr->m_ready = false;
552     else
553         d_ptr->m_ready = d_ptr->m_navigator->ready();
554 
555     if (oldReady != d_ptr->m_ready)
556         emit navigatorReadyChanged(d_ptr->m_ready);
557 }
558 
setError(QDeclarativeNavigator::NavigationError error,const QString & errorString)559 void QDeclarativeNavigator::setError(QDeclarativeNavigator::NavigationError error, const QString &errorString)
560 {
561     d_ptr->m_error = error;
562     d_ptr->m_errorString = errorString;
563     emit errorChanged();
564 }
565 
QDeclarativeNavigationBasicDirections(QDeclarativeNavigator * parent)566 QDeclarativeNavigationBasicDirections::QDeclarativeNavigationBasicDirections(QDeclarativeNavigator *parent)
567 :   QObject(parent), m_navigator(parent), m_routes(QByteArrayLiteral("routeData"), this)
568 {
569     if (m_navigator)
570         m_navigatorPrivate = m_navigator->d_ptr.data();
571 }
572 
573 /*!
574     \qmlpropertygroup Qt.labs.location::Navigator::directions
575     \readonly
576     \qmlproperty Variant Qt.labs.location::Navigator::directions.nextManeuverIcon
577     \qmlproperty real Qt.labs.location::Navigator::directions.distanceToNextManeuver
578     \qmlproperty real Qt.labs.location::Navigator::directions.remainingTravelDistance
579     \qmlproperty real Qt.labs.location::Navigator::directions.remainingTravelDistanceToNextWaypoint
580     \qmlproperty real Qt.labs.location::Navigator::directions.traveledDistance
581     \qmlproperty int Qt.labs.location::Navigator::directions.timeToNextManeuver
582     \qmlproperty int Qt.labs.location::Navigator::directions.remainingTravelTime
583     \qmlproperty int Qt.labs.location::Navigator::directions.remainingTravelTimeToNextWaypoint
584     \qmlproperty int Qt.labs.location::Navigator::directions.traveledTime
585     \qmlproperty Route Qt.labs.location::Navigator::directions.currentRoute
586     \qmlproperty RouteLeg Qt.labs.location::Navigator::directions.currentRouteLeg
587     \qmlproperty int Qt.labs.location::Navigator::directions.currentSegment
588     \qmlproperty model Qt.labs.location::Navigator::directions.alternativeRoutes
589 
590     These read-only properties are part of the \e directions property group.
591     This property group holds the navigation progress information that can be
592     used to access the route data and to extract directions.
593 
594     \note Some backends might not provide a full set of navigation progress
595           information.
596 
597     \list
598         \li The \c nextManeuverIcon property holds the next turn icon.
599         \li The \c distanceToNextManeuver property holds the distance to the
600             next maneuver, in meters.
601         \li The \c remainingTravelDistance property holds the remaining travel
602             distance, in meters.
603         \li The \c remainingTravelDistanceToNextWaypoint property holds the
604             remaining travel distance to the next waypoint, in meters.
605         \li The \c traveledDistance property holds the traveled distance, in
606             meters.
607         \li The \c timeToNextManeuver property holds the time to the next
608             maneuver, in milliseconds.
609         \li The \c remainingTravelTime property holds the remaining travel
610             time, in milliseconds.
611         \li The \c remainingTravelTimeToNextWaypoint property holds the
612             remaining travel time to the next waypoint, in milliseconds.
613         \li The \c traveledTime property holds the traveled time, in
614             milliseconds.
615         \li The \c currentRoute property holds the current route the navigator
616             is following. This can be the same as \l route, or can be
617             different, if the navigator cannot follow the user-specified route.
618             For example, if the position coming from \l positionSource is
619             considerably off route, the navigation engine may recalculate and
620             start to follow a new route.
621         \li The \c currentRouteLeg property holds the current route leg the
622             navigator is following. This is always a part of \c currentRoute,
623             so the \l {RouteLeg::}{overallRoute} property of \c currentRouteLeg
624             holds the same route as \c currentRoute.
625         \li The \c currentSegment property holds the index of the current
626             RouteSegment in the \c currentRoute.
627         \li The \c alternativeRoutes property holds the list of alternative routes provided by
628             the engine. If no alternative routes are present, the model will be empty.
629     \endlist
630 
631     \sa directions.waypointReached(), directions.destinationReached(), Route, RouteLeg, RouteSegment, Waypoint
632 */
633 
634 /*!
635     \qmlsignal Qt.labs.location::Navigator::directions.waypointReached(Waypoint waypoint)
636 
637     This signal is emitted when a \a waypoint has been reached.
638 
639     \sa directions, directions.destinationReached()
640 */
641 
642 /*!
643     \qmlsignal Qt.labs.location::Navigator::directions.destinationReached()
644 
645     This signal is emitted when the last waypoint of the route, the
646     destination, has been reached.
647 
648     \sa directions, directions.waypointReached()
649 */
nextManeuverIcon() const650 QVariant QDeclarativeNavigationBasicDirections::nextManeuverIcon() const
651 {
652     if (m_navigatorPrivate->m_navigator)
653         return m_navigatorPrivate->m_navigator->nextManeuverIcon();
654     return QVariant();
655 }
656 
distanceToNextManeuver() const657 qreal QDeclarativeNavigationBasicDirections::distanceToNextManeuver() const
658 {
659     if (m_navigatorPrivate->m_navigator)
660         return m_navigatorPrivate->m_navigator->distanceToNextManeuver();
661     return qQNaN();
662 }
663 
remainingTravelDistance() const664 qreal QDeclarativeNavigationBasicDirections::remainingTravelDistance() const
665 {
666     if (m_navigatorPrivate->m_navigator)
667         return m_navigatorPrivate->m_navigator->remainingTravelDistance();
668     return qQNaN();
669 }
670 
remainingTravelDistanceToNextWaypoint() const671 qreal QDeclarativeNavigationBasicDirections::remainingTravelDistanceToNextWaypoint() const
672 {
673     if (m_navigatorPrivate->m_navigator)
674         return m_navigatorPrivate->m_navigator->remainingTravelDistanceToNextWaypoint();
675     return qQNaN();
676 }
677 
traveledDistance() const678 qreal QDeclarativeNavigationBasicDirections::traveledDistance() const
679 {
680     if (m_navigatorPrivate->m_navigator)
681         return m_navigatorPrivate->m_navigator->traveledDistance();
682     return 0;
683 }
684 
timeToNextManeuver() const685 int QDeclarativeNavigationBasicDirections::timeToNextManeuver() const
686 {
687     if (m_navigatorPrivate->m_navigator)
688         return m_navigatorPrivate->m_navigator->timeToNextManeuver();
689     return -1;
690 }
691 
remainingTravelTime() const692 int QDeclarativeNavigationBasicDirections::remainingTravelTime() const
693 {
694     if (m_navigatorPrivate->m_navigator)
695         return m_navigatorPrivate->m_navigator->remainingTravelTime();
696     return -1;
697 }
698 
remainingTravelTimeToNextWaypoint() const699 int QDeclarativeNavigationBasicDirections::remainingTravelTimeToNextWaypoint() const
700 {
701     if (m_navigatorPrivate->m_navigator)
702         return m_navigatorPrivate->m_navigator->remainingTravelTimeToNextWaypoint();
703     return -1;
704 }
705 
traveledTime() const706 int QDeclarativeNavigationBasicDirections::traveledTime() const
707 {
708     if (m_navigatorPrivate->m_navigator)
709         return m_navigatorPrivate->m_navigator->traveledTime();
710     return 0;
711 }
712 
currentRoute() const713 QDeclarativeGeoRoute *QDeclarativeNavigationBasicDirections::currentRoute() const
714 {
715     if (!m_navigatorPrivate->m_ready
716             || !m_navigatorPrivate->m_navigator
717             || !m_navigatorPrivate->m_navigator->active())
718         return m_navigatorPrivate->m_params->m_route.data(); // the user-specified route, if any
719     return m_currentRoute;
720 }
721 
currentRouteLeg() const722 QDeclarativeGeoRouteLeg *QDeclarativeNavigationBasicDirections::currentRouteLeg() const
723 {
724     if (!m_navigatorPrivate->m_ready
725             || !m_navigatorPrivate->m_navigator
726             || !m_navigatorPrivate->m_navigator->active())
727         return nullptr;
728     return m_currentRouteLeg;
729 }
730 
currentSegment() const731 int QDeclarativeNavigationBasicDirections::currentSegment() const
732 {
733     if (!m_navigatorPrivate->m_ready
734             || !m_navigatorPrivate->m_navigator
735             || !m_navigatorPrivate->m_navigator->active())
736         return 0;
737     return m_navigatorPrivate->m_navigator->currentSegment();
738 }
739 
alternativeRoutes()740 QAbstractItemModel *QDeclarativeNavigationBasicDirections::alternativeRoutes()
741 {
742     return &m_routes;
743 }
744 
onCurrentRouteChanged()745 void QDeclarativeNavigationBasicDirections::onCurrentRouteChanged()
746 {
747     if (m_currentRoute)
748         m_currentRoute->deleteLater();
749     m_currentRoute = new QDeclarativeGeoRoute(m_navigatorPrivate->m_navigator->currentRoute(), this);
750     emit currentRouteChanged();
751 }
752 
onCurrentRouteLegChanged()753 void QDeclarativeNavigationBasicDirections::onCurrentRouteLegChanged()
754 {
755     if (m_currentRouteLeg)
756         m_currentRouteLeg->deleteLater();
757     m_currentRouteLeg = new QDeclarativeGeoRouteLeg(m_navigatorPrivate->m_navigator->currentRouteLeg(), this);
758     emit currentRouteLegChanged();
759 }
760 
onAlternativeRoutesChanged()761 void QDeclarativeNavigationBasicDirections::onAlternativeRoutesChanged()
762 {
763     const QList<QGeoRoute> &routes = m_navigatorPrivate->m_navigator->alternativeRoutes();
764     QList<QDeclarativeGeoRoute *> declarativeRoutes;
765     for (int i = 0; i < routes.size(); ++i) {
766         QDeclarativeGeoRoute *route = new QDeclarativeGeoRoute(routes.at(i), &m_routes);
767         QQmlEngine::setContextForObject(route, QQmlEngine::contextForObject(this));
768         declarativeRoutes.append(route);
769     }
770     m_routes.updateData(declarativeRoutes);
771 }
772 
773 QT_END_NAMESPACE
774 
775