Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qdeclarativegeoroutemodel.cpp
Go to the documentation of this file.
1// Copyright (C) 2022 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7
8#include <QtCore/QCoreApplication>
9#include <QtQml/QQmlEngine>
10#include <QtQml/qqmlinfo.h>
11#include <QtLocation/QGeoRoutingManager>
12#include <QtPositioning/QGeoRectangle>
13
15
16/*!
17 \qmltype RouteModel
18 \nativetype QDeclarativeGeoRouteModel
19 \inqmlmodule QtLocation
20 \ingroup qml-QtLocation5-routing
21 \since QtLocation 5.5
22
23 \brief The RouteModel type provides access to routes.
24
25 The RouteModel type is used as part of a model/view grouping to retrieve
26 geographic routes from a backend provider. Routes include data about driving
27 directions between two points, walking directions with multiple waypoints,
28 and various other similar concepts. It functions much like other Model
29 types in QML (see for example \l {Models and Views in Qt Quick#Models}{ListModel}),
30 and interacts with views such as \l MapItemView, and \l{ListView}.
31
32 Like \l Map and \l GeocodeModel, all the data for a RouteModel to work comes
33 from a services plugin. This is contained in the \l{plugin} property, and
34 this must be set before the RouteModel can do any useful work.
35
36 Once the plugin is set, create a \l RouteQuery with the appropriate
37 waypoints and other settings, and set the RouteModel's \l{query}
38 property. If \l autoUpdate is enabled, the update will being automatically.
39 Otherwise, the \l{update} method may be used. By default, autoUpdate is
40 disabled.
41
42 The data stored and returned in the RouteModel consists of \l route objects,
43 as a list with the role name "routeData". See the documentation for \l route
44 for further details on its structure and contents.
45
46 \section2 Example Usage
47
48 The following snippet is two-part, showing firstly the declaration of
49 objects, and secondly a short piece of procedural code using it. We set
50 the routeModel's \l{autoUpdate} property to false, and call \l{update} once
51 the query is set up, to avoid useless extra requests halfway through the
52 set up of the query.
53
54 \code
55 Plugin {
56 id: aPlugin
57 name: "osm"
58 }
59
60 RouteQuery {
61 id: aQuery
62 }
63
64 RouteModel {
65 id: routeModel
66 plugin: aPlugin
67 query: aQuery
68 autoUpdate: false
69 }
70 \endcode
71
72 \code
73 {
74 aQuery.addWaypoint(...)
75 aQuery.addWaypoint(...)
76 aQuery.travelModes = ...
77 routeModel.update()
78 }
79 \endcode
80
81*/
82
83QDeclarativeGeoRouteModel::QDeclarativeGeoRouteModel(QObject *parent)
84 : QAbstractListModel(parent)
85{
86}
87
88/*!
89 \qmlproperty int QtLocation::RouteModel::count
90
91 This property holds how many routes the model currently has.
92 Amongst other uses, you can use this value when accessing routes
93 via the QtLocation::RouteModel::get -method.
94*/
95
96int QDeclarativeGeoRouteModel::count() const
97{
98 return routes_.count();
99}
100
101/*!
102 \qmlmethod void QtLocation::RouteModel::reset()
103
104 Resets the model. All route data is cleared, any outstanding requests
105 are aborted and possible errors are cleared. Model status will be set
106 to RouteModel.Null
107*/
108
109void QDeclarativeGeoRouteModel::reset()
110{
111 if (!routes_.isEmpty()) {
112 beginResetModel();
113 routes_.clear();
114 emit countChanged();
115 emit routesChanged();
116 endResetModel();
117 }
118
119 emit abortRequested();
120 setError(NoError, QString());
121 setStatus(QDeclarativeGeoRouteModel::Null);
122}
123
124/*!
125 \qmlmethod void QtLocation::RouteModel::cancel()
126
127 Cancels any outstanding requests and clears errors. Model status will be set to either
128 RouteModel.Null or RouteModel.Ready.
129*/
130void QDeclarativeGeoRouteModel::cancel()
131{
132 emit abortRequested();
133 setError(NoError, QString());
134 setStatus(routes_.isEmpty() ? Null : Ready);
135}
136
137/*!
138 \qmlmethod route QtLocation::RouteModel::get(int index)
139
140 Returns the route at the specified \a index. Use the \l count
141 property to check the amount of routes available. The routes
142 are indexed from zero, so the accessible range is 0...(count - 1).
143
144 If you access out of bounds, an empty route is returned and
145 a warning is issued.
146*/
147
148QGeoRoute QDeclarativeGeoRouteModel::get(int index)
149{
150 if (index < 0 || index >= routes_.count()) {
151 qmlWarning(this) << QStringLiteral("Index '%1' out of range").arg(index);
152 return QGeoRoute();
153 }
154 return routes_.at(index);
155}
156
157/*!
158 \internal
159*/
160void QDeclarativeGeoRouteModel::componentComplete()
161{
162 complete_ = true;
163 if (autoUpdate_) {
164 update();
165 }
166}
167
168/*!
169 \internal
170*/
171int QDeclarativeGeoRouteModel::rowCount(const QModelIndex &parent) const
172{
173 Q_UNUSED(parent);
174 return routes_.count();
175}
176
177/*!
178 \internal
179*/
180QVariant QDeclarativeGeoRouteModel::data(const QModelIndex &index, int role) const
181{
182 if (!index.isValid()) {
183 qmlWarning(this) << QStringLiteral("Error in indexing route model's data (invalid index).");
184 return QVariant();
185 }
186
187 if (index.row() >= routes_.count()) {
188 qmlWarning(this) << QStringLiteral("Fatal error in indexing route model's data (index overflow).");
189 return QVariant();
190 }
191
192 if (role == RouteRole)
193 return QVariant::fromValue(routes_.at(index.row()));
194 return QVariant();
195}
196
197QHash<int, QByteArray> QDeclarativeGeoRouteModel::roleNames() const
198{
199 QHash<int, QByteArray> roleNames = QAbstractListModel::roleNames();
200 roleNames.insert(RouteRole, "routeData");
201 return roleNames;
202}
203
204/*!
205 \internal
206*/
207void QDeclarativeGeoRouteModel::setPlugin(QDeclarativeGeoServiceProvider *plugin)
208{
209 if (plugin_ == plugin)
210 return;
211
212 reset(); // reset the model
213
214 if (plugin_) {
215 disconnect(plugin_, &QDeclarativeGeoServiceProvider::localesChanged,
216 this, &QDeclarativeGeoRouteModel::measurementSystemChanged);
217 }
218 if (plugin) {
219 connect(plugin, &QDeclarativeGeoServiceProvider::localesChanged,
220 this, &QDeclarativeGeoRouteModel::measurementSystemChanged);
221 }
222
223 plugin_ = plugin;
224
225 if (complete_)
226 emit pluginChanged();
227
228 if (!plugin)
229 return;
230
231 if (plugin_->isAttached()) {
232 pluginReady();
233 } else {
234 connect(plugin_, &QDeclarativeGeoServiceProvider::attached,
235 this, &QDeclarativeGeoRouteModel::pluginReady);
236 }
237}
238
239/*!
240 \internal
241*/
242void QDeclarativeGeoRouteModel::pluginReady()
243{
244 QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider();
245 QGeoRoutingManager *routingManager = serviceProvider->routingManager();
246
247 if (serviceProvider->routingError() != QGeoServiceProvider::NoError) {
248 QDeclarativeGeoRouteModel::RouteError newError = UnknownError;
249 switch (serviceProvider->routingError()) {
250 case QGeoServiceProvider::NotSupportedError:
251 newError = EngineNotSetError; break;
252 case QGeoServiceProvider::UnknownParameterError:
253 newError = UnknownParameterError; break;
254 case QGeoServiceProvider::MissingRequiredParameterError:
255 newError = MissingRequiredParameterError; break;
256 case QGeoServiceProvider::ConnectionError:
257 newError = CommunicationError; break;
258 default:
259 break;
260 }
261
262 setError(newError, serviceProvider->routingErrorString());
263 return;
264 }
265
266 if (!routingManager) {
267 setError(EngineNotSetError, tr("Plugin does not support routing."));
268 return;
269 }
270
271 connect(routingManager, &QGeoRoutingManager::finished,
272 this, &QDeclarativeGeoRouteModel::routingFinished);
273 connect(routingManager, &QGeoRoutingManager::errorOccurred,
274 this, &QDeclarativeGeoRouteModel::routingError);
275}
276
277/*!
278 \internal
279*/
280void QDeclarativeGeoRouteModel::queryDetailsChanged()
281{
282 if (autoUpdate_ && complete_)
283 update();
284}
285
286/*!
287 \qmlproperty Plugin QtLocation::RouteModel::plugin
288
289 This property holds the plugin that providers the actual
290 routing service. Note that all plugins do not necessarily
291 provide routing (could for example provide only geocoding or maps).
292
293 A valid plugin must be set before the RouteModel can perform any useful
294 operations.
295
296 \sa Plugin
297*/
298
299QDeclarativeGeoServiceProvider *QDeclarativeGeoRouteModel::plugin() const
300{
301 return plugin_;
302}
303
304/*!
305 \internal
306*/
307void QDeclarativeGeoRouteModel::setQuery(QDeclarativeGeoRouteQuery *query)
308{
309 if (!query || query == routeQuery_)
310 return;
311 if (routeQuery_)
312 routeQuery_->disconnect(this);
313 routeQuery_ = query;
314 connect(query, &QDeclarativeGeoRouteQuery::queryDetailsChanged,
315 this, &QDeclarativeGeoRouteModel::queryDetailsChanged);
316 if (complete_) {
317 emit queryChanged();
318 if (autoUpdate_)
319 update();
320 }
321}
322
323/*!
324 \qmlproperty RouteQuery QtLocation::RouteModel::query
325
326 This property holds the data of the route request.
327 The primary data are the waypoint coordinates and possible further
328 preferences (means of traveling, things to avoid on route etc).
329*/
330
331QDeclarativeGeoRouteQuery *QDeclarativeGeoRouteModel::query() const
332{
333 return routeQuery_;
334}
335
336/*!
337 \internal
338*/
339void QDeclarativeGeoRouteModel::setAutoUpdate(bool autoUpdate)
340{
341 if (autoUpdate_ == autoUpdate)
342 return;
343 autoUpdate_ = autoUpdate;
344 if (complete_)
345 emit autoUpdateChanged();
346}
347
348/*!
349 \qmlproperty bool QtLocation::RouteModel::autoUpdate
350
351 This property controls whether the Model automatically updates in response
352 to changes in its attached RouteQuery. The default value of this property
353 is false.
354
355 If setting this value to 'true', note that any change at all in
356 the RouteQuery object set in the \l{query} property will trigger a new
357 request to be sent. If you are adjusting many properties of the RouteQuery
358 with autoUpdate enabled, this can generate large numbers of useless (and
359 later discarded) requests.
360*/
361
362bool QDeclarativeGeoRouteModel::autoUpdate() const
363{
364 return autoUpdate_;
365}
366
367/*!
368 \qmlproperty Locale::MeasurementSystem QtLocation::RouteModel::measurementSystem
369
370 This property holds the measurement system which will be used when calculating the route. This
371 property is changed when the \l {QtLocation::Plugin::locales}{Plugin::locales} property of
372 \l {QtLocation::RouteModel::plugin}{plugin} changes.
373
374 If setting this property it must be set after the \l {QtLocation::RouteModel::plugin}{plugin}
375 property is set.
376*/
377void QDeclarativeGeoRouteModel::setMeasurementSystem(QLocale::MeasurementSystem ms)
378{
379 if (!plugin_)
380 return;
381
382 QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider();
383 if (!serviceProvider)
384 return;
385
386 QGeoRoutingManager *routingManager = serviceProvider->routingManager();
387 if (!routingManager)
388 return;
389
390 if (routingManager->measurementSystem() == ms)
391 return;
392
393 routingManager->setMeasurementSystem(ms);
394 emit measurementSystemChanged();
395}
396
397QLocale::MeasurementSystem QDeclarativeGeoRouteModel::measurementSystem() const
398{
399 if (!plugin_)
400 return QLocale().measurementSystem();
401
402 QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider();
403 if (!serviceProvider) {
404 if (plugin_->locales().isEmpty())
405 return QLocale().measurementSystem();
406
407 return QLocale(plugin_->locales().first()).measurementSystem();
408 }
409
410 QGeoRoutingManager *routingManager = serviceProvider->routingManager();
411 if (!routingManager) {
412 if (plugin_->locales().isEmpty())
413 return QLocale().measurementSystem();
414
415 return QLocale(plugin_->locales().first()).measurementSystem();
416 }
417
418 return routingManager->measurementSystem();
419}
420
421/*!
422 \internal
423*/
424void QDeclarativeGeoRouteModel::setStatus(QDeclarativeGeoRouteModel::Status status)
425{
426 if (status_ == status)
427 return;
428
429 status_ = status;
430
431 if (complete_)
432 emit statusChanged();
433}
434
435/*!
436 \qmlproperty enumeration QtLocation::RouteModel::status
437
438 This read-only property holds the current status of the model.
439
440 \list
441 \li RouteModel.Null - No route requests have been issued or \l reset has been called.
442 \li RouteModel.Ready - Route request(s) have finished successfully.
443 \li RouteModel.Loading - Route request has been issued but not yet finished
444 \li RouteModel.Error - Routing error has occurred, details are in \l error and \l errorString
445 \endlist
446*/
447
448QDeclarativeGeoRouteModel::Status QDeclarativeGeoRouteModel::status() const
449{
450 return status_;
451}
452
453/*!
454 \qmlproperty string QtLocation::RouteModel::errorString
455
456 This read-only property holds the textual presentation of the latest routing error.
457 If no error has occurred or the model has been reset, an empty string is returned.
458
459 An empty string may also be returned if an error occurred which has no associated
460 textual representation.
461*/
462
463QString QDeclarativeGeoRouteModel::errorString() const
464{
465 return errorString_;
466}
467
468/*!
469 \qmlproperty enumeration QtLocation::RouteModel::error
470
471 This read-only property holds the latest error value of the routing request.
472
473 \list
474 \li RouteModel.NoError - No error has occurred.
475 \li RouteModel.CommunicationError - An error occurred while communicating with the service provider.
476 \li RouteModel.EngineNotSetError - The model's plugin property was not set or there is no routing manager associated with the plugin.
477 \li RouteModel.MissingRequiredParameterError - A required parameter was not specified.
478 \li RouteModel.ParseError - The response from the service provider was in an unrecognizable format.
479 \li RouteModel.UnknownError - An error occurred which does not fit into any of the other categories.
480 \li RouteModel.UnknownParameterError - The plugin did not recognize one of the parameters it was given.
481 \li RouteModel.UnsupportedOptionError - The requested operation is not supported by the routing provider.
482 This may happen when the loaded engine does not support a particular
483 type of routing request.
484 \endlist
485*/
486
487QDeclarativeGeoRouteModel::RouteError QDeclarativeGeoRouteModel::error() const
488{
489 return error_;
490}
491
492void QDeclarativeGeoRouteModel::setError(RouteError error, const QString& errorString)
493{
494 if (error_ == error && errorString_ == errorString)
495 return;
496 error_ = error;
497 errorString_ = errorString;
498 emit errorChanged();
499}
500
501/*!
502 \qmlmethod void QtLocation::RouteModel::update()
503
504 Instructs the RouteModel to update its data. This is most useful
505 when \l autoUpdate is disabled, to force a refresh when the query
506 has been changed.
507*/
508void QDeclarativeGeoRouteModel::update()
509{
510 if (!complete_)
511 return;
512
513 if (!plugin_) {
514 setError(EngineNotSetError, tr("Cannot route, plugin not set."));
515 return;
516 }
517
518 QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider();
519 if (!serviceProvider)
520 return;
521
522 QGeoRoutingManager *routingManager = serviceProvider->routingManager();
523 if (!routingManager) {
524 setError(EngineNotSetError, tr("Cannot route, route manager not set."));
525 return;
526 }
527 if (!routeQuery_) {
528 setError(ParseError, tr("Cannot route, valid query not set."));
529 return;
530 }
531 emit abortRequested(); // Clear previous requests
532 QGeoRouteRequest request = routeQuery_->routeRequest();
533 if (request.waypoints().count() < 2) {
534 setError(ParseError,tr("Not enough waypoints for routing."));
535 return;
536 }
537
538 setError(NoError, QString());
539
540 QGeoRouteReply *reply = routingManager->calculateRoute(request);
541 setStatus(QDeclarativeGeoRouteModel::Loading);
542 if (!reply->isFinished()) {
543 connect(this, &QDeclarativeGeoRouteModel::abortRequested, reply, &QGeoRouteReply::abort);
544 } else {
545 if (reply->error() == QGeoRouteReply::NoError) {
546 routingFinished(reply);
547 } else {
548 routingError(reply, reply->error(), reply->errorString());
549 }
550 }
551}
552
553/*!
554 \internal
555*/
556void QDeclarativeGeoRouteModel::routingFinished(QGeoRouteReply *reply)
557{
558 if (!reply)
559 return;
560 reply->deleteLater();
561 if (reply->error() != QGeoRouteReply::NoError)
562 return;
563
564 beginResetModel();
565 const int oldCount = routes_.count();
566 routes_ = reply->routes();
567 endResetModel();
568
569 setError(NoError, QString());
570 setStatus(QDeclarativeGeoRouteModel::Ready);
571
572 if (oldCount != 0 || routes_.count() != 0)
573 emit routesChanged();
574 if (oldCount != routes_.count())
575 emit countChanged();
576}
577
578/*!
579 \internal
580*/
581void QDeclarativeGeoRouteModel::routingError(QGeoRouteReply *reply,
582 QGeoRouteReply::Error error,
583 const QString &errorString)
584{
585 if (!reply)
586 return;
587 reply->deleteLater();
588 setError(static_cast<QDeclarativeGeoRouteModel::RouteError>(error), errorString);
589 setStatus(QDeclarativeGeoRouteModel::Error);
590}
591
592
593/*!
594 \qmltype RouteQuery
595 \nativetype QDeclarativeGeoRouteQuery
596 \inqmlmodule QtLocation
597 \ingroup qml-QtLocation5-routing
598 \since QtLocation 5.5
599
600 \brief The RouteQuery type is used to provide query parameters to a
601 RouteModel.
602
603 A RouteQuery is used to pack all the parameters necessary to make a request
604 to a routing service, which can then populate the contents of a RouteModel.
605
606 These parameters describe key details of the route, such as \l waypoints to
607 pass through, \l excludedAreas to avoid, the \l travelModes in use, as well
608 as detailed preferences on how to optimize the route and what features
609 to prefer or avoid along the path (such as toll roads, highways, etc).
610
611 RouteQuery objects are used exclusively to fill out the value of a
612 RouteModel's \l{RouteModel::query}{query} property, which can then begin
613 the retrieval process to populate the model.
614
615 Some plugins might allow or require specific parameters to operate.
616 In order to specify these plugin-specific parameters, MapParameter elements
617 can be nested inside a RouteQuery.
618
619 \section2 Example Usage
620
621 The following snipped shows an incomplete example of creating a RouteQuery
622 object and setting it as the value of a RouteModel's \l{RouteModel::query}{query}
623 property.
624
625 \code
626 RouteQuery {
627 id: aQuery
628 }
629
630 RouteModel {
631 query: aQuery
632 autoUpdate: false
633 }
634 \endcode
635
636 For a more complete example, see the documentation for the \l{RouteModel}
637 type, and the Mapviewer example.
638
639 \sa RouteModel
640
641*/
642
643QDeclarativeGeoRouteQuery::QDeclarativeGeoRouteQuery(QObject *parent)
644 : QObject(parent)
645{
646}
647
648QDeclarativeGeoRouteQuery::QDeclarativeGeoRouteQuery(const QGeoRouteRequest &request, QObject *parent)
649 : QObject(parent), request_(request)
650{
651 // Extra params assumed to be already set in the request.
652 // Init waypoints
653 m_waypoints = request_.waypoints();
654}
655
656QDeclarativeGeoRouteQuery::~QDeclarativeGeoRouteQuery()
657{
658}
659
660/*!
661 \internal
662*/
663void QDeclarativeGeoRouteQuery::componentComplete()
664{
665 complete_ = true;
666}
667
668/*!
669 \qmlproperty QList<FeatureType> RouteQuery::featureTypes
670
671 List of features that will be considered when planning the
672 route. Features with a weight of NeutralFeatureWeight will not be returned.
673
674 \list
675 \li RouteQuery.NoFeature - No features will be taken into account when planning the route
676 \li RouteQuery.TollFeature - Consider tollways when planning the route
677 \li RouteQuery.HighwayFeature - Consider highways when planning the route
678 \li RouteQuery.PublicTransitFeature - Consider public transit when planning the route
679 \li RouteQuery.FerryFeature - Consider ferries when planning the route
680 \li RouteQuery.TunnelFeature - Consider tunnels when planning the route
681 \li RouteQuery.DirtRoadFeature - Consider dirt roads when planning the route
682 \li RouteQuery.ParksFeature - Consider parks when planning the route
683 \li RouteQuery.MotorPoolLaneFeature - Consider motor pool lanes when planning the route
684 \li RouteQuery.TrafficFeature - Consider traffic when planning the route
685 \endlist
686
687 \sa setFeatureWeight, featureWeight
688*/
689
690QList<int> QDeclarativeGeoRouteQuery::featureTypes() const
691{
692 QList<int> list;
693
694 const auto featureTypes = request_.featureTypes();
695 for (const auto &featureType : featureTypes)
696 list.append(static_cast<int>(featureType));
697 return list;
698}
699
700/*!
701 \qmlproperty int RouteQuery::numberAlternativeRoutes
702
703 The number of alternative routes requested when requesting routes.
704 The default value is 0.
705*/
706
707
708int QDeclarativeGeoRouteQuery::numberAlternativeRoutes() const
709{
710 return request_.numberAlternativeRoutes();
711}
712
713void QDeclarativeGeoRouteQuery::setNumberAlternativeRoutes(int numberAlternativeRoutes)
714{
715 if (numberAlternativeRoutes == request_.numberAlternativeRoutes())
716 return;
717
718 request_.setNumberAlternativeRoutes(numberAlternativeRoutes);
719
720 if (complete_) {
721 emit numberAlternativeRoutesChanged();
722 emit queryDetailsChanged();
723 }
724}
725
726/*!
727 \qmlproperty list<coordinate> RouteQuery::waypoints
728
729 The coordinates of the waypoints for the desired route.
730 The waypoints should be given in order from origin to destination.
731 Two or more coordinates are needed.
732
733 Waypoints can be set as part of the RouteQuery type declaration or
734 dynamically with the functions provided.
735
736 \sa addWaypoint, removeWaypoint, clearWaypoints
737*/
738
739QList<QGeoCoordinate> QDeclarativeGeoRouteQuery::waypoints() const
740{
741 return m_waypoints;
742}
743
744void QDeclarativeGeoRouteQuery::setWaypoints(const QList<QGeoCoordinate> &value)
745{
746 if (m_waypoints == value)
747 return;
748
749 m_waypoints = value;
750 waypointChanged();
751}
752
753/*!
754 \qmlproperty list<geoRectangle> RouteQuery::excludedAreas
755
756 Areas that the route must not cross.
757
758 Excluded areas can be set as part of the \l RouteQuery type declaration or
759 dynamically with the functions provided.
760
761 \sa addExcludedArea, removeExcludedArea, clearExcludedAreas
762*/
763QList<QGeoRectangle> QDeclarativeGeoRouteQuery::excludedAreas() const
764{
765 return request_.excludeAreas();
766}
767
768void QDeclarativeGeoRouteQuery::setExcludedAreas(const QList<QGeoRectangle> &value)
769{
770 if (request_.excludeAreas() == value)
771 return;
772
773 request_.setExcludeAreas(value);
774
775 if (complete_) {
776 emit excludedAreasChanged();
777 emit queryDetailsChanged();
778 }
779}
780
781/*!
782 \qmlmethod void QtLocation::RouteQuery::addExcludedArea(geoRectangle area)
783
784 Adds the specified geoRectangle \a area to the excluded areas
785 (areas that the route must not cross).
786 The same area can only be added once.
787
788 \sa removeExcludedArea, clearExcludedAreas
789*/
790
791
792void QDeclarativeGeoRouteQuery::addExcludedArea(const QGeoRectangle &area)
793{
794 if (!area.isValid())
795 return;
796
797 QList<QGeoRectangle> excludedAreas = request_.excludeAreas();
798
799 if (excludedAreas.contains(area))
800 return;
801
802 excludedAreas.append(area);
803
804 request_.setExcludeAreas(excludedAreas);
805
806 if (complete_) {
807 emit excludedAreasChanged();
808 emit queryDetailsChanged();
809 }
810}
811
812/*!
813 \qmlmethod void QtLocation::RouteQuery::removeExcludedArea(geoRectangle area)
814
815 Removes the given \a area from excluded areas (areas that the route must not cross).
816
817 \sa addExcludedArea, clearExcludedAreas
818*/
819
820void QDeclarativeGeoRouteQuery::removeExcludedArea(const QGeoRectangle &area)
821{
822 if (!area.isValid())
823 return;
824
825 QList<QGeoRectangle> excludedAreas = request_.excludeAreas();
826
827 int index = excludedAreas.lastIndexOf(area);
828 if (index == -1) {
829 qmlWarning(this) << QStringLiteral("Cannot remove nonexistent area.");
830 return;
831 }
832 excludedAreas.removeAt(index);
833 request_.setExcludeAreas(excludedAreas);
834
835 if (complete_) {
836 emit excludedAreasChanged();
837 emit queryDetailsChanged();
838 }
839}
840
841/*!
842 \qmlmethod void QtLocation::RouteQuery::clearExcludedAreas()
843
844 Clears all excluded areas (areas that the route must not cross).
845
846 \sa addExcludedArea, removeExcludedArea
847*/
848
849void QDeclarativeGeoRouteQuery::clearExcludedAreas()
850{
851 if (request_.excludeAreas().isEmpty())
852 return;
853
854 request_.setExcludeAreas(QList<QGeoRectangle>());
855
856 if (complete_) {
857 emit excludedAreasChanged();
858 emit queryDetailsChanged();
859 }
860}
861
862/*!
863 \qmlmethod void QtLocation::RouteQuery::addWaypoint(coordinate)
864
865 Appends the given \a coordinate to the list of waypoints. The same
866 coordinate can be set multiple times.
867
868 \sa removeWaypoint, clearWaypoints
869*/
870void QDeclarativeGeoRouteQuery::addWaypoint(const QGeoCoordinate &waypoint)
871{
872 if (!waypoint.isValid()) {
873 qmlWarning(this) << QStringLiteral("Invalid coordinate as waypoint");
874 return;
875 }
876
877 m_waypoints << waypoint;
878 waypointChanged();
879}
880
881/*!
882 \qmlmethod void QtLocation::RouteQuery::removeWaypoint(coordinate)
883
884 Removes the given \a coordinate from the list of waypoints. If the
885 same coordinate appears multiple times, the most recently added
886 coordinate instance is removed.
887
888 \sa addWaypoint, clearWaypoints
889*/
890void QDeclarativeGeoRouteQuery::removeWaypoint(const QGeoCoordinate &waypoint)
891{
892 if (!waypoint.isValid()) {
893 qmlWarning(this) << QStringLiteral("Invalid coordinate as waypoint");
894 return;
895 }
896
897 if (qsizetype idx = m_waypoints.lastIndexOf(waypoint); idx >= 0) {
898 m_waypoints.remove(idx);
899 waypointChanged();
900 } else {
901 qmlWarning(this) << QStringLiteral("Cannot remove nonexistent waypoint.");
902 }
903}
904
905/*!
906 \qmlmethod void QtLocation::RouteQuery::clearWaypoints()
907
908 Clears all waypoints.
909
910 \sa removeWaypoint, addWaypoint
911*/
912void QDeclarativeGeoRouteQuery::clearWaypoints()
913{
914 if (m_waypoints.isEmpty())
915 return;
916
917 m_waypoints.clear();
918 waypointChanged();
919}
920
921/*!
922 \qmlmethod void QtLocation::RouteQuery::setFeatureWeight(FeatureType feature, FeatureWeight weight)
923
924 Defines the \a weight to associate with a \a feature during the planning
925 of a route.
926
927 Following lists the possible feature weights:
928
929 \value RouteQuery.NeutralFeatureWeight
930 The presence or absence of the feature does not affect the planning of the
931 route
932
933 \value RouteQuery.PreferFeatureWeight
934 Routes which contain the feature are preferred over those that do not
935
936 \value RouteQuery.RequireFeatureWeight
937 Only routes which contain the feature are considered, otherwise no
938 route will be returned
939
940 \value RouteQuery.AvoidFeatureWeight
941 Routes which do not contain the feature are preferred over those that
942 do
943
944 \value RouteQuery.DisallowFeatureWeight
945 Only routes which do not contain the feature are considered, otherwise
946 no route will be returned
947
948 \sa featureTypes, resetFeatureWeights, featureWeight
949
950*/
951
952void QDeclarativeGeoRouteQuery::setFeatureWeight(FeatureType featureType, FeatureWeight featureWeight)
953{
954 if (featureType == NoFeature && !request_.featureTypes().isEmpty()) {
955 resetFeatureWeights();
956 return;
957 }
958
959 // Check if the weight changes, as we need to signal it
960 FeatureWeight originalWeight = static_cast<FeatureWeight>(request_.featureWeight(static_cast<QGeoRouteRequest::FeatureType>(featureType)));
961 if (featureWeight == originalWeight)
962 return;
963
964 request_.setFeatureWeight(static_cast<QGeoRouteRequest::FeatureType>(featureType),
965 static_cast<QGeoRouteRequest::FeatureWeight>(featureWeight));
966 if (complete_ && ((originalWeight == NeutralFeatureWeight) || (featureWeight == NeutralFeatureWeight))) {
967 // featureTypes should now give a different list, because the original and new weight
968 // were not same, and other one was neutral weight
969 emit featureTypesChanged();
970 emit queryDetailsChanged();
971 }
972}
973
974/*!
975 \qmlmethod void QtLocation::RouteQuery::resetFeatureWeights()
976
977 Resets all feature weights to their default state (NeutralFeatureWeight).
978
979 \sa featureTypes, setFeatureWeight, featureWeight
980*/
981void QDeclarativeGeoRouteQuery::resetFeatureWeights()
982{
983 // reset all feature types.
984 const auto featureTypes = request_.featureTypes();
985 for (const auto &featureType : featureTypes)
986 request_.setFeatureWeight(featureType, QGeoRouteRequest::NeutralFeatureWeight);
987 if (complete_) {
988 emit featureTypesChanged();
989 emit queryDetailsChanged();
990 }
991}
992
993/*!
994 \qmlmethod FeatureWeight QtLocation::RouteQuery::featureWeight(FeatureType featureType)
995
996 Gets the weight for the \a featureType.
997
998 \sa featureTypes, setFeatureWeight, resetFeatureWeights
999*/
1000
1001int QDeclarativeGeoRouteQuery::featureWeight(FeatureType featureType)
1002{
1003 return request_.featureWeight(static_cast<QGeoRouteRequest::FeatureType>(featureType));
1004}
1005
1006/*!
1007 \internal
1008*/
1009void QDeclarativeGeoRouteQuery::setTravelModes(QDeclarativeGeoRouteQuery::TravelModes travelModes)
1010{
1011 QGeoRouteRequest::TravelModes reqTravelModes;
1012
1013 if (travelModes & QDeclarativeGeoRouteQuery::CarTravel)
1014 reqTravelModes |= QGeoRouteRequest::CarTravel;
1015 if (travelModes & QDeclarativeGeoRouteQuery::PedestrianTravel)
1016 reqTravelModes |= QGeoRouteRequest::PedestrianTravel;
1017 if (travelModes & QDeclarativeGeoRouteQuery::BicycleTravel)
1018 reqTravelModes |= QGeoRouteRequest::BicycleTravel;
1019 if (travelModes & QDeclarativeGeoRouteQuery::PublicTransitTravel)
1020 reqTravelModes |= QGeoRouteRequest::PublicTransitTravel;
1021 if (travelModes & QDeclarativeGeoRouteQuery::TruckTravel)
1022 reqTravelModes |= QGeoRouteRequest::TruckTravel;
1023
1024 if (reqTravelModes == request_.travelModes())
1025 return;
1026
1027 request_.setTravelModes(reqTravelModes);
1028
1029 if (complete_) {
1030 emit travelModesChanged();
1031 emit queryDetailsChanged();
1032 }
1033}
1034
1035
1036/*!
1037 \qmlproperty enumeration RouteQuery::segmentDetail
1038
1039 The level of detail which will be used in the representation of routing segments.
1040
1041 \value RouteQuery.NoSegmentData
1042 No segment data should be included with the route
1043
1044 \value RouteQuery.BasicSegmentData
1045 Basic segment data will be included with the route
1046
1047 The default value is \c {RouteQuery.BasicSegmentData}.
1048*/
1049
1050void QDeclarativeGeoRouteQuery::setSegmentDetail(SegmentDetail segmentDetail)
1051{
1052 if (static_cast<QGeoRouteRequest::SegmentDetail>(segmentDetail) == request_.segmentDetail())
1053 return;
1054 request_.setSegmentDetail(static_cast<QGeoRouteRequest::SegmentDetail>(segmentDetail));
1055 if (complete_) {
1056 emit segmentDetailChanged();
1057 emit queryDetailsChanged();
1058 }
1059}
1060
1061QDeclarativeGeoRouteQuery::SegmentDetail QDeclarativeGeoRouteQuery::segmentDetail() const
1062{
1063 return static_cast<QDeclarativeGeoRouteQuery::SegmentDetail>(request_.segmentDetail());
1064}
1065
1066/*!
1067 \qmlproperty enumeration RouteQuery::maneuverDetail
1068
1069 The level of detail which will be used in the representation of routing maneuvers.
1070
1071 \value RouteQuery.NoManeuvers
1072 No maneuvers should be included with the route
1073
1074 \value RouteQuery.BasicManeuvers
1075 Basic maneuvers will be included with the route
1076
1077 The default value is \c {RouteQuery.BasicManeuvers}.
1078*/
1079
1080void QDeclarativeGeoRouteQuery::setManeuverDetail(ManeuverDetail maneuverDetail)
1081{
1082 if (static_cast<QGeoRouteRequest::ManeuverDetail>(maneuverDetail) == request_.maneuverDetail())
1083 return;
1084 request_.setManeuverDetail(static_cast<QGeoRouteRequest::ManeuverDetail>(maneuverDetail));
1085 if (complete_) {
1086 emit maneuverDetailChanged();
1087 emit queryDetailsChanged();
1088 }
1089}
1090
1091QDeclarativeGeoRouteQuery::ManeuverDetail QDeclarativeGeoRouteQuery::maneuverDetail() const
1092{
1093 return static_cast<QDeclarativeGeoRouteQuery::ManeuverDetail>(request_.maneuverDetail());
1094}
1095
1096/*!
1097 \qmlproperty enumeration RouteQuery::travelModes
1098
1099 The travel modes which should be considered during the planning of the route.
1100 Values can be combined with OR ('|') -operator.
1101
1102 \value RouteQuery.CarTravel
1103 The route will be optimized for someone who is driving a car
1104
1105 \value RouteQuery.PedestrianTravel
1106 The route will be optimized for someone who is walking
1107
1108 \value RouteQuery.BicycleTravel
1109 The route will be optimized for someone who is riding a bicycle
1110
1111 \value RouteQuery.PublicTransit
1112 Travel The route will be optimized for someone who is making use of public transit
1113
1114 \value RouteQuery.TruckTravel
1115 The route will be optimized for someone who is driving a truck
1116
1117 The default value is \c {RouteQuery.CarTravel}.
1118*/
1119
1120QDeclarativeGeoRouteQuery::TravelModes QDeclarativeGeoRouteQuery::travelModes() const
1121{
1122 QGeoRouteRequest::TravelModes reqTravelModes = request_.travelModes();
1123 QDeclarativeGeoRouteQuery::TravelModes travelModes;
1124
1125 if (reqTravelModes & QGeoRouteRequest::CarTravel)
1126 travelModes |= QDeclarativeGeoRouteQuery::CarTravel;
1127 if (reqTravelModes & QGeoRouteRequest::PedestrianTravel)
1128 travelModes |= QDeclarativeGeoRouteQuery::PedestrianTravel;
1129 if (reqTravelModes & QGeoRouteRequest::BicycleTravel)
1130 travelModes |= QDeclarativeGeoRouteQuery::BicycleTravel;
1131 if (reqTravelModes & QGeoRouteRequest::PublicTransitTravel)
1132 travelModes |= QDeclarativeGeoRouteQuery::PublicTransitTravel;
1133 if (reqTravelModes & QGeoRouteRequest::TruckTravel)
1134 travelModes |= QDeclarativeGeoRouteQuery::TruckTravel;
1135
1136 return travelModes;
1137}
1138
1139/*!
1140 \qmlproperty enumeration RouteQuery::routeOptimizations
1141
1142 The route optimizations which should be considered during the planning of the route.
1143 Values can be combined with OR ('|') -operator.
1144
1145
1146 \value RouteQuery.ShortestRoute
1147 Minimize the length of the journey
1148
1149 \value RouteQuery.FastestRoute
1150 Minimize the traveling time for the journey
1151
1152 \value RouteQuery.MostEconomicRoute
1153 Minimize the cost of the journey
1154
1155 \value RouteQuery.MostScenicRoute
1156 Maximize the scenic potential of the journey
1157
1158 The default value is \c {RouteQuery.FastestRoute}.
1159*/
1160
1161QDeclarativeGeoRouteQuery::RouteOptimizations QDeclarativeGeoRouteQuery::routeOptimizations() const
1162{
1163 QGeoRouteRequest::RouteOptimizations reqOptimizations = request_.routeOptimization();
1164 QDeclarativeGeoRouteQuery::RouteOptimizations optimization;
1165
1166 if (reqOptimizations & QGeoRouteRequest::ShortestRoute)
1167 optimization |= QDeclarativeGeoRouteQuery::ShortestRoute;
1168 if (reqOptimizations & QGeoRouteRequest::FastestRoute)
1169 optimization |= QDeclarativeGeoRouteQuery::FastestRoute;
1170 if (reqOptimizations & QGeoRouteRequest::MostEconomicRoute)
1171 optimization |= QDeclarativeGeoRouteQuery::MostEconomicRoute;
1172 if (reqOptimizations & QGeoRouteRequest::MostScenicRoute)
1173 optimization |= QDeclarativeGeoRouteQuery::MostScenicRoute;
1174
1175 return optimization;
1176}
1177
1178/*!
1179 \qmlproperty date RouteQuery::departureTime
1180
1181 The departure time to be used when querying for the route.
1182 The default value is an invalid date, meaning no departure time will be used in the query.
1183
1184 \since 5.13
1185*/
1186void QDeclarativeGeoRouteQuery::setDepartureTime(const QDateTime &departureTime)
1187{
1188 if (departureTime == request_.departureTime())
1189 return;
1190
1191 request_.setDepartureTime(departureTime);
1192 if (complete_) {
1193 emit departureTimeChanged();
1194 emit queryDetailsChanged();
1195 }
1196}
1197
1198QDateTime QDeclarativeGeoRouteQuery::departureTime() const
1199{
1200 return request_.departureTime();
1201}
1202
1203void QDeclarativeGeoRouteQuery::setRouteOptimizations(QDeclarativeGeoRouteQuery::RouteOptimizations optimization)
1204{
1205 QGeoRouteRequest::RouteOptimizations reqOptimizations;
1206
1207 if (optimization & QDeclarativeGeoRouteQuery::ShortestRoute)
1208 reqOptimizations |= QGeoRouteRequest::ShortestRoute;
1209 if (optimization & QDeclarativeGeoRouteQuery::FastestRoute)
1210 reqOptimizations |= QGeoRouteRequest::FastestRoute;
1211 if (optimization & QDeclarativeGeoRouteQuery::MostEconomicRoute)
1212 reqOptimizations |= QGeoRouteRequest::MostEconomicRoute;
1213 if (optimization & QDeclarativeGeoRouteQuery::MostScenicRoute)
1214 reqOptimizations |= QGeoRouteRequest::MostScenicRoute;
1215
1216 if (reqOptimizations == request_.routeOptimization())
1217 return;
1218
1219 request_.setRouteOptimization(reqOptimizations);
1220
1221 if (complete_) {
1222 emit routeOptimizationsChanged();
1223 emit queryDetailsChanged();
1224 }
1225}
1226
1227/*!
1228 \internal
1229*/
1230QGeoRouteRequest QDeclarativeGeoRouteQuery::routeRequest() const
1231{
1232 if (m_waypointsChanged) {
1233 m_waypointsChanged = false;
1234 // Update waypoints and metadata into request
1235 request_.setWaypoints(m_waypoints);
1236 }
1237 return request_;
1238}
1239
1240void QDeclarativeGeoRouteQuery::excludedAreaCoordinateChanged()
1241{
1242 if (!m_excludedAreaCoordinateChanged) {
1243 m_excludedAreaCoordinateChanged = true;
1244 QMetaObject::invokeMethod(this, "doCoordinateChanged", Qt::QueuedConnection);
1245 }
1246}
1247
1248void QDeclarativeGeoRouteQuery::waypointChanged()
1249{
1250 m_waypointsChanged = true;
1251 if (complete_) {
1252 emit waypointsChanged();
1253 emit queryDetailsChanged();
1254 }
1255}
1256
1257void QDeclarativeGeoRouteQuery::doCoordinateChanged()
1258{
1259 m_excludedAreaCoordinateChanged = false;
1260 if (complete_)
1261 emit queryDetailsChanged();
1262}
1263
1264QT_END_NAMESPACE
Combined button and popup list for selecting options.