| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2015 The Qt Company Ltd. | 
| 4 | ** Contact: http://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the QtLocation module of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:LGPL3$ | 
| 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 http://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at http://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU Lesser General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation and appearing in the file LICENSE.LGPLv3 included in the | 
| 21 | ** packaging of this file. Please review the following information to | 
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | 
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl.html. | 
| 24 | ** | 
| 25 | ** GNU General Public License Usage | 
| 26 | ** Alternatively, this file may be used under the terms of the GNU | 
| 27 | ** General Public License version 2.0 or later as published by the Free | 
| 28 | ** Software Foundation and appearing in the file LICENSE.GPL included in | 
| 29 | ** the packaging of this file. Please review the following information to | 
| 30 | ** ensure the GNU General Public License version 2.0 requirements will be | 
| 31 | ** met: http://www.gnu.org/licenses/gpl-2.0.html. | 
| 32 | ** | 
| 33 | ** $QT_END_LICENSE$ | 
| 34 | ** | 
| 35 | ****************************************************************************/ | 
| 36 |  | 
| 37 | #include "qdeclarativegeoroutemodel_p.h" | 
| 38 | #include "qdeclarativegeoroute_p.h" | 
| 39 | #include "error_messages_p.h" | 
| 40 | #include "locationvaluetypehelper_p.h" | 
| 41 |  | 
| 42 | #include <QtCore/QCoreApplication> | 
| 43 | #include <QtQml/QQmlEngine> | 
| 44 | #include <QtQml/qqmlinfo.h> | 
| 45 | #include <QtQml/private/qqmlengine_p.h> | 
| 46 | #include <QtQml/private/qv4scopedvalue_p.h> | 
| 47 | #include <QtQml/private/qv4arrayobject_p.h> | 
| 48 | #include <QtLocation/QGeoRoutingManager> | 
| 49 | #include <QtPositioning/QGeoRectangle> | 
| 50 | #include "qdeclarativegeomapparameter_p.h" | 
| 51 |  | 
| 52 | QT_BEGIN_NAMESPACE | 
| 53 |  | 
| 54 | static bool compareFloats(qreal a, qreal b) | 
| 55 | { | 
| 56 |     return (qIsNaN(d: a) && qIsNaN(d: b)) | 
| 57 |            || a == b; | 
| 58 | } | 
| 59 |  | 
| 60 | static bool compareParameterList(const QList<QDeclarativeGeoMapParameter *> &a, const QList<QDeclarativeGeoMapParameter *> &b) | 
| 61 | { | 
| 62 |     if (a.size() != b.size()) | 
| 63 |         return false; | 
| 64 |     if (a != b) { | 
| 65 |         for (int i = 0; i < a.size(); ++i) { | 
| 66 |             if (! (*a.at(i) == *b.at(i))) | 
| 67 |                 return false; | 
| 68 |         } | 
| 69 |     } | 
| 70 |     return true; | 
| 71 | } | 
| 72 |  | 
| 73 | static int findWaypoint(const QList<QDeclarativeGeoWaypoint *> &waypoints, const QDeclarativeGeoWaypoint *w) | 
| 74 | { | 
| 75 |     for (int i = waypoints.size() - 1; i >= 0; --i) { | 
| 76 |         if (waypoints.at(i) == w || *waypoints.at(i) == *w) | 
| 77 |             return i; | 
| 78 |     } | 
| 79 |     return -1; | 
| 80 | } | 
| 81 |  | 
| 82 | static int findWaypoint(const QList<QDeclarativeGeoWaypoint *> &waypoints, const QGeoCoordinate &c) | 
| 83 | { | 
| 84 |     for (int i = waypoints.size() - 1; i >= 0; --i) { | 
| 85 |         if (waypoints.at(i)->coordinate() == c) | 
| 86 |             return i; | 
| 87 |     } | 
| 88 |     return -1; | 
| 89 | } | 
| 90 |  | 
| 91 | static QList<QGeoCoordinate> waypointCoordinates(const QList<QDeclarativeGeoWaypoint *> &waypoints) | 
| 92 | { | 
| 93 |     QList<QGeoCoordinate> res; | 
| 94 |     for (const QDeclarativeGeoWaypoint *w: waypoints) | 
| 95 |         res << w->coordinate(); | 
| 96 |     return res; | 
| 97 | } | 
| 98 |  | 
| 99 | static QList<QVariantMap> waypointMetadata(const QList<QDeclarativeGeoWaypoint *> &waypoints) | 
| 100 | { | 
| 101 |     QList<QVariantMap> res; | 
| 102 |     for (QDeclarativeGeoWaypoint *w: waypoints) | 
| 103 |         res << w->metadata(); | 
| 104 |     return res; | 
| 105 | } | 
| 106 |  | 
| 107 | /*! | 
| 108 |     \qmltype RouteModel | 
| 109 |     \instantiates QDeclarativeGeoRouteModel | 
| 110 |     \inqmlmodule QtLocation | 
| 111 |     \ingroup qml-QtLocation5-routing | 
| 112 |     \since QtLocation 5.5 | 
| 113 |  | 
| 114 |     \brief The RouteModel type provides access to routes. | 
| 115 |  | 
| 116 |     The RouteModel type is used as part of a model/view grouping to retrieve | 
| 117 |     geographic routes from a backend provider. Routes include data about driving | 
| 118 |     directions between two points, walking directions with multiple waypoints, | 
| 119 |     and various other similar concepts. It functions much like other Model | 
| 120 |     types in QML (see for example \l {Models and Views in Qt Quick#Models}{ListModel} | 
| 121 |     and \l {QtQuick.XmlListModel::XmlListModel}{XmlListModel}), and interacts with | 
| 122 |     views such as \l MapItemView, and \l{ListView}. | 
| 123 |  | 
| 124 |     Like \l Map and \l GeocodeModel, all the data for a RouteModel to work comes | 
| 125 |     from a services plugin. This is contained in the \l{plugin} property, and | 
| 126 |     this must be set before the RouteModel can do any useful work. | 
| 127 |  | 
| 128 |     Once the plugin is set, create a \l RouteQuery with the appropriate | 
| 129 |     waypoints and other settings, and set the RouteModel's \l{query} | 
| 130 |     property. If \l autoUpdate is enabled, the update will being automatically. | 
| 131 |     Otherwise, the \l{update} method may be used. By default, autoUpdate is | 
| 132 |     disabled. | 
| 133 |  | 
| 134 |     The data stored and returned in the RouteModel consists of \l Route objects, | 
| 135 |     as a list with the role name "routeData". See the documentation for \l Route | 
| 136 |     for further details on its structure and contents. | 
| 137 |  | 
| 138 |     \section2 Example Usage | 
| 139 |  | 
| 140 |     The following snippet is two-part, showing firstly the declaration of | 
| 141 |     objects, and secondly a short piece of procedural code using it. We set | 
| 142 |     the routeModel's \l{autoUpdate} property to false, and call \l{update} once | 
| 143 |     the query is set up, to avoid useless extra requests halfway through the | 
| 144 |     set up of the query. | 
| 145 |  | 
| 146 |     \code | 
| 147 |     Plugin { | 
| 148 |         id: aPlugin | 
| 149 |         name: "osm" | 
| 150 |     } | 
| 151 |  | 
| 152 |     RouteQuery { | 
| 153 |         id: aQuery | 
| 154 |     } | 
| 155 |  | 
| 156 |     RouteModel { | 
| 157 |         id: routeModel | 
| 158 |         plugin: aPlugin | 
| 159 |         query: aQuery | 
| 160 |         autoUpdate: false | 
| 161 |     } | 
| 162 |     \endcode | 
| 163 |  | 
| 164 |     \code | 
| 165 |     { | 
| 166 |         aQuery.addWaypoint(...) | 
| 167 |         aQuery.addWaypoint(...) | 
| 168 |         aQuery.travelModes = ... | 
| 169 |         routeModel.update() | 
| 170 |     } | 
| 171 |     \endcode | 
| 172 |  | 
| 173 | */ | 
| 174 |  | 
| 175 | QDeclarativeGeoRouteModel::QDeclarativeGeoRouteModel(QObject *parent) | 
| 176 |     : QAbstractListModel(parent), | 
| 177 |       complete_(false), | 
| 178 |       plugin_(0), | 
| 179 |       routeQuery_(0), | 
| 180 |       autoUpdate_(false), | 
| 181 |       status_(QDeclarativeGeoRouteModel::Null), | 
| 182 |       error_(QDeclarativeGeoRouteModel::NoError) | 
| 183 | { | 
| 184 | } | 
| 185 |  | 
| 186 | QDeclarativeGeoRouteModel::~QDeclarativeGeoRouteModel() | 
| 187 | { | 
| 188 |     if (!routes_.empty()) { | 
| 189 |         qDeleteAll(c: routes_); | 
| 190 |         routes_.clear(); | 
| 191 |     } | 
| 192 | } | 
| 193 |  | 
| 194 | /*! | 
| 195 |     \qmlproperty int QtLocation::RouteModel::count | 
| 196 |  | 
| 197 |     This property holds how many routes the model currently has. | 
| 198 |     Amongst other uses, you can use this value when accessing routes | 
| 199 |     via the QtLocation::RouteModel::get -method. | 
| 200 | */ | 
| 201 |  | 
| 202 | int QDeclarativeGeoRouteModel::count() const | 
| 203 | { | 
| 204 |     return routes_.count(); | 
| 205 | } | 
| 206 |  | 
| 207 | /*! | 
| 208 |     \qmlmethod void QtLocation::RouteModel::reset() | 
| 209 |  | 
| 210 |     Resets the model. All route data is cleared, any outstanding requests | 
| 211 |     are aborted and possible errors are cleared. Model status will be set | 
| 212 |     to RouteModel.Null | 
| 213 | */ | 
| 214 |  | 
| 215 | void QDeclarativeGeoRouteModel::reset() | 
| 216 | { | 
| 217 |     if (!routes_.isEmpty()) { | 
| 218 |         beginResetModel(); | 
| 219 |         qDeleteAll(c: routes_); | 
| 220 |         routes_.clear(); | 
| 221 |         emit countChanged(); | 
| 222 |         emit routesChanged(); | 
| 223 |         endResetModel(); | 
| 224 |     } | 
| 225 |  | 
| 226 |     emit abortRequested(); | 
| 227 |     setError(error: NoError, errorString: QString()); | 
| 228 |     setStatus(QDeclarativeGeoRouteModel::Null); | 
| 229 | } | 
| 230 |  | 
| 231 | /*! | 
| 232 |     \qmlmethod void QtLocation::RouteModel::cancel() | 
| 233 |  | 
| 234 |     Cancels any outstanding requests and clears errors.  Model status will be set to either | 
| 235 |     RouteModel.Null or RouteModel.Ready. | 
| 236 | */ | 
| 237 | void QDeclarativeGeoRouteModel::cancel() | 
| 238 | { | 
| 239 |     emit abortRequested(); | 
| 240 |     setError(error: NoError, errorString: QString()); | 
| 241 |     setStatus(routes_.isEmpty() ? Null : Ready); | 
| 242 | } | 
| 243 |  | 
| 244 | /*! | 
| 245 |     \qmlmethod Route QtLocation::RouteModel::get(int index) | 
| 246 |  | 
| 247 |     Returns the Route at the specified \a index. Use the \l count | 
| 248 |     property to check the amount of routes available. The routes | 
| 249 |     are indexed from zero, so the accessible range is 0...(count - 1). | 
| 250 |  | 
| 251 |     If you access out of bounds, a zero (null object) is returned and | 
| 252 |     a warning is issued. | 
| 253 | */ | 
| 254 |  | 
| 255 | QDeclarativeGeoRoute *QDeclarativeGeoRouteModel::get(int index) | 
| 256 | { | 
| 257 |     if (index < 0 || index >= routes_.count()) { | 
| 258 |         qmlWarning(me: this) << QStringLiteral("Index '%1' out of range" ).arg(a: index); | 
| 259 |         return 0; | 
| 260 |     } | 
| 261 |     return routes_.at(i: index); | 
| 262 | } | 
| 263 |  | 
| 264 | /*! | 
| 265 |     \internal | 
| 266 | */ | 
| 267 | void QDeclarativeGeoRouteModel::componentComplete() | 
| 268 | { | 
| 269 |     complete_ = true; | 
| 270 |     if (autoUpdate_) { | 
| 271 |         update(); | 
| 272 |     } | 
| 273 | } | 
| 274 |  | 
| 275 | /*! | 
| 276 |     \internal | 
| 277 | */ | 
| 278 | int QDeclarativeGeoRouteModel::rowCount(const QModelIndex &parent) const | 
| 279 | { | 
| 280 |     Q_UNUSED(parent); | 
| 281 |     return routes_.count(); | 
| 282 | } | 
| 283 |  | 
| 284 | /*! | 
| 285 |     \internal | 
| 286 | */ | 
| 287 | QVariant QDeclarativeGeoRouteModel::data(const QModelIndex &index, int role) const | 
| 288 | { | 
| 289 |     if (!index.isValid()) { | 
| 290 |         qmlWarning(me: this) << QStringLiteral("Error in indexing route model's data (invalid index)." ); | 
| 291 |         return QVariant(); | 
| 292 |     } | 
| 293 |  | 
| 294 |     if (index.row() >= routes_.count()) { | 
| 295 |         qmlWarning(me: this) << QStringLiteral("Fatal error in indexing route model's data (index overflow)." ); | 
| 296 |         return QVariant(); | 
| 297 |     } | 
| 298 |  | 
| 299 |     if (role == RouteRole) { | 
| 300 |         QObject *route = routes_.at(i: index.row()); | 
| 301 |         return QVariant::fromValue(value: route); | 
| 302 |     } | 
| 303 |     return QVariant(); | 
| 304 | } | 
| 305 |  | 
| 306 | QHash<int, QByteArray> QDeclarativeGeoRouteModel::roleNames() const | 
| 307 | { | 
| 308 |     QHash<int, QByteArray> roleNames = QAbstractListModel::roleNames(); | 
| 309 |     roleNames.insert(akey: RouteRole, avalue: "routeData" ); | 
| 310 |     return roleNames; | 
| 311 | } | 
| 312 |  | 
| 313 | /*! | 
| 314 |     \internal | 
| 315 | */ | 
| 316 | void QDeclarativeGeoRouteModel::setPlugin(QDeclarativeGeoServiceProvider *plugin) | 
| 317 | { | 
| 318 |     if (plugin_ == plugin) | 
| 319 |         return; | 
| 320 |  | 
| 321 |     reset(); // reset the model | 
| 322 |  | 
| 323 |     if (plugin_) | 
| 324 |         disconnect(sender: plugin_, SIGNAL(localesChanged()), receiver: this, SIGNAL(measurementSystemChanged())); | 
| 325 |     if (plugin) | 
| 326 |         connect(sender: plugin, SIGNAL(localesChanged()), receiver: this, SIGNAL(measurementSystemChanged())); | 
| 327 |  | 
| 328 |     plugin_ = plugin; | 
| 329 |  | 
| 330 |     if (complete_) | 
| 331 |         emit pluginChanged(); | 
| 332 |  | 
| 333 |     if (!plugin) | 
| 334 |         return; | 
| 335 |  | 
| 336 |     if (plugin_->isAttached()) { | 
| 337 |         pluginReady(); | 
| 338 |     } else { | 
| 339 |         connect(sender: plugin_, SIGNAL(attached()), | 
| 340 |                 receiver: this, SLOT(pluginReady())); | 
| 341 |     } | 
| 342 | } | 
| 343 |  | 
| 344 | /*! | 
| 345 |     \internal | 
| 346 | */ | 
| 347 | void QDeclarativeGeoRouteModel::pluginReady() | 
| 348 | { | 
| 349 |     QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); | 
| 350 |     QGeoRoutingManager *routingManager = serviceProvider->routingManager(); | 
| 351 |  | 
| 352 |     if (serviceProvider->routingError() != QGeoServiceProvider::NoError) { | 
| 353 |         QDeclarativeGeoRouteModel::RouteError newError = UnknownError; | 
| 354 |         switch (serviceProvider->routingError()) { | 
| 355 |         case QGeoServiceProvider::NotSupportedError: | 
| 356 |             newError = EngineNotSetError; break; | 
| 357 |         case QGeoServiceProvider::UnknownParameterError: | 
| 358 |             newError = UnknownParameterError; break; | 
| 359 |         case QGeoServiceProvider::MissingRequiredParameterError: | 
| 360 |             newError = MissingRequiredParameterError; break; | 
| 361 |         case QGeoServiceProvider::ConnectionError: | 
| 362 |             newError = CommunicationError; break; | 
| 363 |         default: | 
| 364 |             break; | 
| 365 |         } | 
| 366 |  | 
| 367 |         setError(error: newError, errorString: serviceProvider->routingErrorString()); | 
| 368 |         return; | 
| 369 |     } | 
| 370 |  | 
| 371 |     if (!routingManager) { | 
| 372 |         setError(error: EngineNotSetError, errorString: tr(s: "Plugin does not support routing." )); | 
| 373 |         return; | 
| 374 |     } | 
| 375 |  | 
| 376 |     connect(sender: routingManager, SIGNAL(finished(QGeoRouteReply*)), | 
| 377 |             receiver: this, SLOT(routingFinished(QGeoRouteReply*))); | 
| 378 |     connect(sender: routingManager, SIGNAL(error(QGeoRouteReply*,QGeoRouteReply::Error,QString)), | 
| 379 |             receiver: this, SLOT(routingError(QGeoRouteReply*,QGeoRouteReply::Error,QString))); | 
| 380 | } | 
| 381 |  | 
| 382 | /*! | 
| 383 |     \internal | 
| 384 | */ | 
| 385 | void QDeclarativeGeoRouteModel::queryDetailsChanged() | 
| 386 | { | 
| 387 |     if (autoUpdate_ && complete_) | 
| 388 |         update(); | 
| 389 | } | 
| 390 |  | 
| 391 | /*! | 
| 392 |     \qmlproperty Plugin QtLocation::RouteModel::plugin | 
| 393 |  | 
| 394 |     This property holds the plugin that providers the actual | 
| 395 |     routing service. Note that all plugins do not necessarily | 
| 396 |     provide routing (could for example provide only geocoding or maps). | 
| 397 |  | 
| 398 |     A valid plugin must be set before the RouteModel can perform any useful | 
| 399 |     operations. | 
| 400 |  | 
| 401 |     \sa Plugin | 
| 402 | */ | 
| 403 |  | 
| 404 | QDeclarativeGeoServiceProvider *QDeclarativeGeoRouteModel::plugin() const | 
| 405 | { | 
| 406 |     return plugin_; | 
| 407 | } | 
| 408 |  | 
| 409 | /*! | 
| 410 |     \internal | 
| 411 | */ | 
| 412 | void QDeclarativeGeoRouteModel::setQuery(QDeclarativeGeoRouteQuery *query) | 
| 413 | { | 
| 414 |     if (!query || query == routeQuery_) | 
| 415 |         return; | 
| 416 |     if (routeQuery_) | 
| 417 |         routeQuery_->disconnect(receiver: this); | 
| 418 |     routeQuery_ = query; | 
| 419 |     connect(sender: query, SIGNAL(queryDetailsChanged()), receiver: this, SLOT(queryDetailsChanged())); | 
| 420 |     if (complete_) { | 
| 421 |         emit queryChanged(); | 
| 422 |         if (autoUpdate_) | 
| 423 |             update(); | 
| 424 |     } | 
| 425 | } | 
| 426 |  | 
| 427 | /*! | 
| 428 |     \qmlproperty RouteQuery QtLocation::RouteModel::query | 
| 429 |  | 
| 430 |     This property holds the data of the route request. | 
| 431 |     The primary data are the waypoint coordinates and possible further | 
| 432 |     preferences (means of traveling, things to avoid on route etc). | 
| 433 | */ | 
| 434 |  | 
| 435 | QDeclarativeGeoRouteQuery *QDeclarativeGeoRouteModel::query() const | 
| 436 | { | 
| 437 |     return routeQuery_; | 
| 438 | } | 
| 439 |  | 
| 440 | /*! | 
| 441 |     \internal | 
| 442 | */ | 
| 443 | void QDeclarativeGeoRouteModel::setAutoUpdate(bool autoUpdate) | 
| 444 | { | 
| 445 |     if (autoUpdate_ == autoUpdate) | 
| 446 |         return; | 
| 447 |     autoUpdate_ = autoUpdate; | 
| 448 |     if (complete_) | 
| 449 |         emit autoUpdateChanged(); | 
| 450 | } | 
| 451 |  | 
| 452 | /*! | 
| 453 |     \qmlproperty bool QtLocation::RouteModel::autoUpdate | 
| 454 |  | 
| 455 |     This property controls whether the Model automatically updates in response | 
| 456 |     to changes in its attached RouteQuery. The default value of this property | 
| 457 |     is false. | 
| 458 |  | 
| 459 |     If setting this value to 'true', note that any change at all in | 
| 460 |     the RouteQuery object set in the \l{query} property will trigger a new | 
| 461 |     request to be sent. If you are adjusting many properties of the RouteQuery | 
| 462 |     with autoUpdate enabled, this can generate large numbers of useless (and | 
| 463 |     later discarded) requests. | 
| 464 | */ | 
| 465 |  | 
| 466 | bool QDeclarativeGeoRouteModel::autoUpdate() const | 
| 467 | { | 
| 468 |     return autoUpdate_; | 
| 469 | } | 
| 470 |  | 
| 471 | /*! | 
| 472 |     \qmlproperty Locale::MeasurementSystem QtLocation::RouteModel::measurementSystem | 
| 473 |  | 
| 474 |     This property holds the measurement system which will be used when calculating the route. This | 
| 475 |     property is changed when the \l {QtLocation::Plugin::locales}{Plugin::locales} property of | 
| 476 |     \l {QtLocation::RouteModel::plugin}{plugin} changes. | 
| 477 |  | 
| 478 |     If setting this property it must be set after the \l {QtLocation::RouteModel::plugin}{plugin} | 
| 479 |     property is set. | 
| 480 | */ | 
| 481 | void QDeclarativeGeoRouteModel::setMeasurementSystem(QLocale::MeasurementSystem ms) | 
| 482 | { | 
| 483 |     if (!plugin_) | 
| 484 |         return; | 
| 485 |  | 
| 486 |     QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); | 
| 487 |     if (!serviceProvider) | 
| 488 |         return; | 
| 489 |  | 
| 490 |     QGeoRoutingManager *routingManager = serviceProvider->routingManager(); | 
| 491 |     if (!routingManager) | 
| 492 |         return; | 
| 493 |  | 
| 494 |     if (routingManager->measurementSystem() == ms) | 
| 495 |         return; | 
| 496 |  | 
| 497 |     routingManager->setMeasurementSystem(ms); | 
| 498 |     emit measurementSystemChanged(); | 
| 499 | } | 
| 500 |  | 
| 501 | QLocale::MeasurementSystem QDeclarativeGeoRouteModel::measurementSystem() const | 
| 502 | { | 
| 503 |     if (!plugin_) | 
| 504 |         return QLocale().measurementSystem(); | 
| 505 |  | 
| 506 |     QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); | 
| 507 |     if (!serviceProvider) { | 
| 508 |         if (plugin_->locales().isEmpty()) | 
| 509 |             return QLocale().measurementSystem(); | 
| 510 |  | 
| 511 |         return QLocale(plugin_->locales().first()).measurementSystem(); | 
| 512 |     } | 
| 513 |  | 
| 514 |     QGeoRoutingManager *routingManager = serviceProvider->routingManager(); | 
| 515 |     if (!routingManager) { | 
| 516 |         if (plugin_->locales().isEmpty()) | 
| 517 |             return QLocale().measurementSystem(); | 
| 518 |  | 
| 519 |         return QLocale(plugin_->locales().first()).measurementSystem(); | 
| 520 |     } | 
| 521 |  | 
| 522 |     return routingManager->measurementSystem(); | 
| 523 | } | 
| 524 |  | 
| 525 | /*! | 
| 526 |     \internal | 
| 527 | */ | 
| 528 | void QDeclarativeGeoRouteModel::setStatus(QDeclarativeGeoRouteModel::Status status) | 
| 529 | { | 
| 530 |     if (status_ == status) | 
| 531 |         return; | 
| 532 |  | 
| 533 |     status_ = status; | 
| 534 |  | 
| 535 |     if (complete_) | 
| 536 |         emit statusChanged(); | 
| 537 | } | 
| 538 |  | 
| 539 | /*! | 
| 540 |     \qmlproperty enumeration QtLocation::RouteModel::status | 
| 541 |  | 
| 542 |     This read-only property holds the current status of the model. | 
| 543 |  | 
| 544 |     \list | 
| 545 |     \li RouteModel.Null - No route requests have been issued or \l reset has been called. | 
| 546 |     \li RouteModel.Ready - Route request(s) have finished successfully. | 
| 547 |     \li RouteModel.Loading - Route request has been issued but not yet finished | 
| 548 |     \li RouteModel.Error - Routing error has occurred, details are in \l error and \l errorString | 
| 549 |     \endlist | 
| 550 | */ | 
| 551 |  | 
| 552 | QDeclarativeGeoRouteModel::Status QDeclarativeGeoRouteModel::status() const | 
| 553 | { | 
| 554 |     return status_; | 
| 555 | } | 
| 556 |  | 
| 557 | /*! | 
| 558 |     \qmlproperty string QtLocation::RouteModel::errorString | 
| 559 |  | 
| 560 |     This read-only property holds the textual presentation of the latest routing error. | 
| 561 |     If no error has occurred or the model has been reset, an empty string is returned. | 
| 562 |  | 
| 563 |     An empty string may also be returned if an error occurred which has no associated | 
| 564 |     textual representation. | 
| 565 | */ | 
| 566 |  | 
| 567 | QString QDeclarativeGeoRouteModel::errorString() const | 
| 568 | { | 
| 569 |     return errorString_; | 
| 570 | } | 
| 571 |  | 
| 572 | /*! | 
| 573 |     \qmlproperty enumeration QtLocation::RouteModel::error | 
| 574 |  | 
| 575 |     This read-only property holds the latest error value of the routing request. | 
| 576 |  | 
| 577 |     \list | 
| 578 |     \li RouteModel.NoError - No error has occurred. | 
| 579 |     \li RouteModel.CommunicationError - An error occurred while communicating with the service provider. | 
| 580 |     \li RouteModel.EngineNotSetError - The model's plugin property was not set or there is no routing manager associated with the plugin. | 
| 581 |     \li RouteModel.MissingRequiredParameterError - A required parameter was not specified. | 
| 582 |     \li RouteModel.ParseError - The response from the service provider was in an unrecognizable format. | 
| 583 |     \li RouteModel.UnknownError - An error occurred which does not fit into any of the other categories. | 
| 584 |     \li RouteModel.UnknownParameterError - The plugin did not recognize one of the parameters it was given. | 
| 585 |     \li RouteModel.UnsupportedOptionError - The requested operation is not supported by the routing provider. | 
| 586 |                                             This may happen when the loaded engine does not support a particular | 
| 587 |                                             type of routing request. | 
| 588 |     \endlist | 
| 589 | */ | 
| 590 |  | 
| 591 | QDeclarativeGeoRouteModel::RouteError QDeclarativeGeoRouteModel::error() const | 
| 592 | { | 
| 593 |     return error_; | 
| 594 | } | 
| 595 |  | 
| 596 | void QDeclarativeGeoRouteModel::setError(RouteError error, const QString& errorString) | 
| 597 | { | 
| 598 |     if (error_ == error && errorString_ == errorString) | 
| 599 |         return; | 
| 600 |     error_ = error; | 
| 601 |     errorString_ = errorString; | 
| 602 |     emit errorChanged(); | 
| 603 | } | 
| 604 |  | 
| 605 | /*! | 
| 606 |     \qmlmethod void QtLocation::RouteModel::update() | 
| 607 |  | 
| 608 |     Instructs the RouteModel to update its data. This is most useful | 
| 609 |     when \l autoUpdate is disabled, to force a refresh when the query | 
| 610 |     has been changed. | 
| 611 | */ | 
| 612 | void QDeclarativeGeoRouteModel::update() | 
| 613 | { | 
| 614 |     if (!complete_) | 
| 615 |         return; | 
| 616 |  | 
| 617 |     if (!plugin_) { | 
| 618 |         setError(error: EngineNotSetError, errorString: tr(s: "Cannot route, plugin not set." )); | 
| 619 |         return; | 
| 620 |     } | 
| 621 |  | 
| 622 |     QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider(); | 
| 623 |     if (!serviceProvider) | 
| 624 |         return; | 
| 625 |  | 
| 626 |     QGeoRoutingManager *routingManager = serviceProvider->routingManager(); | 
| 627 |     if (!routingManager) { | 
| 628 |         setError(error: EngineNotSetError, errorString: tr(s: "Cannot route, route manager not set." )); | 
| 629 |         return; | 
| 630 |     } | 
| 631 |     if (!routeQuery_) { | 
| 632 |         setError(error: ParseError, errorString: tr(s: "Cannot route, valid query not set." )); | 
| 633 |         return; | 
| 634 |     } | 
| 635 |     emit abortRequested(); // Clear previous requests | 
| 636 |     QGeoRouteRequest request = routeQuery_->routeRequest(); | 
| 637 |     if (request.waypoints().count() < 2) { | 
| 638 |         setError(error: ParseError,errorString: tr(s: "Not enough waypoints for routing." )); | 
| 639 |         return; | 
| 640 |     } | 
| 641 |  | 
| 642 |     setError(error: NoError, errorString: QString()); | 
| 643 |  | 
| 644 |     QGeoRouteReply *reply = routingManager->calculateRoute(request); | 
| 645 |     setStatus(QDeclarativeGeoRouteModel::Loading); | 
| 646 |     if (!reply->isFinished()) { | 
| 647 |         connect(sender: this, signal: &QDeclarativeGeoRouteModel::abortRequested, receiver: reply, slot: &QGeoRouteReply::abort); | 
| 648 |     } else { | 
| 649 |         if (reply->error() == QGeoRouteReply::NoError) { | 
| 650 |             routingFinished(reply); | 
| 651 |         } else { | 
| 652 |             routingError(reply, error: reply->error(), errorString: reply->errorString()); | 
| 653 |         } | 
| 654 |     } | 
| 655 | } | 
| 656 |  | 
| 657 | /*! | 
| 658 |     \internal | 
| 659 | */ | 
| 660 | void QDeclarativeGeoRouteModel::routingFinished(QGeoRouteReply *reply) | 
| 661 | { | 
| 662 |     if (!reply) | 
| 663 |         return; | 
| 664 |     reply->deleteLater(); | 
| 665 |     if (reply->error() != QGeoRouteReply::NoError) | 
| 666 |         return; | 
| 667 |  | 
| 668 |     beginResetModel(); | 
| 669 |     int oldCount = routes_.count(); | 
| 670 |     qDeleteAll(c: routes_); | 
| 671 |     // Convert routes to declarative | 
| 672 |     routes_.clear(); | 
| 673 |     for (int i = 0; i < reply->routes().size(); ++i) { | 
| 674 |         QDeclarativeGeoRoute *route = new QDeclarativeGeoRoute(reply->routes().at(i), this); | 
| 675 |         QQmlEngine::setContextForObject(route, QQmlEngine::contextForObject(this)); | 
| 676 |         routes_.append(t: route); | 
| 677 |     } | 
| 678 |     endResetModel(); | 
| 679 |  | 
| 680 |     setError(error: NoError, errorString: QString()); | 
| 681 |     setStatus(QDeclarativeGeoRouteModel::Ready); | 
| 682 |  | 
| 683 |     if (oldCount != 0 || routes_.count() != 0) | 
| 684 |         emit routesChanged(); | 
| 685 |     if (oldCount != routes_.count()) | 
| 686 |         emit countChanged(); | 
| 687 | } | 
| 688 |  | 
| 689 | /*! | 
| 690 |     \internal | 
| 691 | */ | 
| 692 | void QDeclarativeGeoRouteModel::routingError(QGeoRouteReply *reply, | 
| 693 |                                                QGeoRouteReply::Error error, | 
| 694 |                                                const QString &errorString) | 
| 695 | { | 
| 696 |     if (!reply) | 
| 697 |         return; | 
| 698 |     reply->deleteLater(); | 
| 699 |     setError(error: static_cast<QDeclarativeGeoRouteModel::RouteError>(error), errorString); | 
| 700 |     setStatus(QDeclarativeGeoRouteModel::Error); | 
| 701 | } | 
| 702 |  | 
| 703 |  | 
| 704 | /*! | 
| 705 |     \qmltype RouteQuery | 
| 706 |     \instantiates QDeclarativeGeoRouteQuery | 
| 707 |     \inqmlmodule QtLocation | 
| 708 |     \ingroup qml-QtLocation5-routing | 
| 709 |     \since QtLocation 5.5 | 
| 710 |  | 
| 711 |     \brief The RouteQuery type is used to provide query parameters to a | 
| 712 |            RouteModel. | 
| 713 |  | 
| 714 |     A RouteQuery is used to pack all the parameters necessary to make a request | 
| 715 |     to a routing service, which can then populate the contents of a RouteModel. | 
| 716 |  | 
| 717 |     These parameters describe key details of the route, such as \l waypoints to | 
| 718 |     pass through, \l excludedAreas to avoid, the \l travelModes in use, as well | 
| 719 |     as detailed preferences on how to optimize the route and what features | 
| 720 |     to prefer or avoid along the path (such as toll roads, highways, etc). | 
| 721 |  | 
| 722 |     RouteQuery objects are used exclusively to fill out the value of a | 
| 723 |     RouteModel's \l{RouteModel::query}{query} property, which can then begin | 
| 724 |     the retrieval process to populate the model. | 
| 725 |  | 
| 726 |     Some plugins might allow or require specific parameters to operate. | 
| 727 |     In order to specify these plugin-specific parameters, MapParameter elements | 
| 728 |     can be nested inside a RouteQuery. | 
| 729 |  | 
| 730 |     \section2 Example Usage | 
| 731 |  | 
| 732 |     The following snipped shows an incomplete example of creating a RouteQuery | 
| 733 |     object and setting it as the value of a RouteModel's \l{RouteModel::query}{query} | 
| 734 |     property. | 
| 735 |  | 
| 736 |     \code | 
| 737 |     RouteQuery { | 
| 738 |         id: aQuery | 
| 739 |     } | 
| 740 |  | 
| 741 |     RouteModel { | 
| 742 |         query: aQuery | 
| 743 |         autoUpdate: false | 
| 744 |     } | 
| 745 |     \endcode | 
| 746 |  | 
| 747 |     For a more complete example, see the documentation for the \l{RouteModel} | 
| 748 |     type, and the Mapviewer example. | 
| 749 |  | 
| 750 |     \sa RouteModel | 
| 751 |  | 
| 752 | */ | 
| 753 |  | 
| 754 | QDeclarativeGeoRouteQuery::QDeclarativeGeoRouteQuery(QObject *parent) | 
| 755 | :   QObject(parent), complete_(false), m_excludedAreaCoordinateChanged(false) | 
| 756 | { | 
| 757 | } | 
| 758 |  | 
| 759 | QDeclarativeGeoRouteQuery::QDeclarativeGeoRouteQuery(const QGeoRouteRequest &request, QObject *parent) | 
| 760 | :   QObject(parent), request_(request), complete_(false), m_excludedAreaCoordinateChanged(false) | 
| 761 | { | 
| 762 |     // Extra params assumed to be already set in the request. | 
| 763 |     // Init waypoints | 
| 764 |     const QList<QGeoCoordinate> wpts = request_.waypoints(); | 
| 765 |     const QList<QVariantMap> meta = request_.waypointsMetadata(); | 
| 766 |     for (int i = 0; i < wpts.size(); ++i) { | 
| 767 |         QDeclarativeGeoWaypoint *w = new QDeclarativeGeoWaypoint(this); | 
| 768 |         w->setCoordinate(wpts.at(i)); | 
| 769 |         w->setMetadata(meta.at(i)); | 
| 770 |         m_waypoints << w; | 
| 771 |     } | 
| 772 | } | 
| 773 |  | 
| 774 | QDeclarativeGeoRouteQuery::~QDeclarativeGeoRouteQuery() | 
| 775 | { | 
| 776 | } | 
| 777 |  | 
| 778 | /*! | 
| 779 |     \internal | 
| 780 | */ | 
| 781 | void QDeclarativeGeoRouteQuery::componentComplete() | 
| 782 | { | 
| 783 |     complete_ = true; | 
| 784 | } | 
| 785 |  | 
| 786 | /*! | 
| 787 |     \qmlproperty QList<FeatureType> RouteQuery::featureTypes | 
| 788 |  | 
| 789 |     List of features that will be considered when planning the | 
| 790 |     route. Features with a weight of NeutralFeatureWeight will not be returned. | 
| 791 |  | 
| 792 |     \list | 
| 793 |     \li RouteQuery.NoFeature - No features will be taken into account when planning the route | 
| 794 |     \li RouteQuery.TollFeature - Consider tollways when planning the route | 
| 795 |     \li RouteQuery.HighwayFeature - Consider highways when planning the route | 
| 796 |     \li RouteQuery.PublicTransitFeature - Consider public transit when planning the route | 
| 797 |     \li RouteQuery.FerryFeature - Consider ferries when planning the route | 
| 798 |     \li RouteQuery.TunnelFeature - Consider tunnels when planning the route | 
| 799 |     \li RouteQuery.DirtRoadFeature - Consider dirt roads when planning the route | 
| 800 |     \li RouteQuery.ParksFeature - Consider parks when planning the route | 
| 801 |     \li RouteQuery.MotorPoolLaneFeature - Consider motor pool lanes when planning the route | 
| 802 |     \li RouteQuery.TrafficFeature - Consider traffic when planning the route | 
| 803 |     \endlist | 
| 804 |  | 
| 805 |     \sa setFeatureWeight, featureWeight | 
| 806 | */ | 
| 807 |  | 
| 808 | QList<int> QDeclarativeGeoRouteQuery::featureTypes() | 
| 809 | { | 
| 810 |     QList<int> list; | 
| 811 |  | 
| 812 |     for (int i = 0; i < request_.featureTypes().count(); ++i) { | 
| 813 |         list.append(t: static_cast<int>(request_.featureTypes().at(i))); | 
| 814 |     } | 
| 815 |     return list; | 
| 816 | } | 
| 817 |  | 
| 818 | /*! | 
| 819 |     \qmlproperty int RouteQuery::numberAlternativeRoutes | 
| 820 |  | 
| 821 |     The number of alternative routes requested when requesting routes. | 
| 822 |     The default value is 0. | 
| 823 | */ | 
| 824 |  | 
| 825 |  | 
| 826 | int QDeclarativeGeoRouteQuery::numberAlternativeRoutes() const | 
| 827 | { | 
| 828 |     return request_.numberAlternativeRoutes(); | 
| 829 | } | 
| 830 |  | 
| 831 | void QDeclarativeGeoRouteQuery::setNumberAlternativeRoutes(int numberAlternativeRoutes) | 
| 832 | { | 
| 833 |     if (numberAlternativeRoutes == request_.numberAlternativeRoutes()) | 
| 834 |         return; | 
| 835 |  | 
| 836 |     request_.setNumberAlternativeRoutes(numberAlternativeRoutes); | 
| 837 |  | 
| 838 |     if (complete_) { | 
| 839 |         emit numberAlternativeRoutesChanged(); | 
| 840 |         emit queryDetailsChanged(); | 
| 841 |     } | 
| 842 | } | 
| 843 |  | 
| 844 | /*! | 
| 845 |     \qmlproperty list<coordinate> RouteQuery::waypoints | 
| 846 |  | 
| 847 |  | 
| 848 |     The coordinates of the waypoints for the desired route. | 
| 849 |     The waypoints should be given in order from origin to destination. | 
| 850 |     Two or more coordinates are needed. | 
| 851 |  | 
| 852 |     Waypoints can be set as part of the RouteQuery type declaration or | 
| 853 |     dynamically with the functions provided. | 
| 854 |  | 
| 855 |     When setting this property to a list of waypoints, each waypoint | 
| 856 |     can be either a \l coordinate or a \l Waypoint, interchangeably. | 
| 857 |     If a \l coordinate is passed, it will be internally converted to a | 
| 858 |     \l Waypoint. | 
| 859 |  | 
| 860 |     This property, however, always contains a list of coordinates. | 
| 861 |  | 
| 862 |     \sa waypointObjects, addWaypoint, removeWaypoint, clearWaypoints | 
| 863 | */ | 
| 864 |  | 
| 865 | QVariantList QDeclarativeGeoRouteQuery::waypoints() | 
| 866 | { | 
| 867 |     QVariantList res; | 
| 868 |  | 
| 869 |     for (const auto &w : m_waypoints) | 
| 870 |         res << QVariant::fromValue(value: w->coordinate()); | 
| 871 |  | 
| 872 |     return res; | 
| 873 | } | 
| 874 |  | 
| 875 | /*! | 
| 876 |     \qmlmethod list<Waypoint> QtLocation::RouteQuery::waypointObjects() | 
| 877 |  | 
| 878 |     This method can be used to retrieve the list of Waypoint objects | 
| 879 |     relative to RouteQuery::waypoints. | 
| 880 |  | 
| 881 |     \sa waypointObjects, addWaypoint, removeWaypoint, clearWaypoints | 
| 882 | */ | 
| 883 | QVariantList QDeclarativeGeoRouteQuery::waypointObjects() | 
| 884 | { | 
| 885 |     QVariantList res; | 
| 886 |  | 
| 887 |     for (const auto &w : m_waypoints) | 
| 888 |         res << QVariant::fromValue(value: w); | 
| 889 |  | 
| 890 |     return res; | 
| 891 | } | 
| 892 |  | 
| 893 | void QDeclarativeGeoRouteQuery::setWaypoints(const QVariantList &value) | 
| 894 | { | 
| 895 |     QList<QDeclarativeGeoWaypoint *> waypointList; | 
| 896 |     bool allWaypoints = true; | 
| 897 |  | 
| 898 |     for (const auto &w: value) { | 
| 899 |         // First, test if this is already a QDeclarativeGeoWaypoint | 
| 900 |         // From QVariant to QObject * | 
| 901 |         QDeclarativeGeoWaypoint *waypoint = nullptr; | 
| 902 |         QObject *obj = qvariant_cast<QObject *>(v: w); | 
| 903 |         waypoint = qobject_cast<QDeclarativeGeoWaypoint *>(object: obj); | 
| 904 |  | 
| 905 |         if (waypoint) { | 
| 906 |             waypointList << waypoint; | 
| 907 |             continue; | 
| 908 |         } | 
| 909 |  | 
| 910 |         // if here, w is not a Waypoint, so either a QGeoCoordinate or a variant map, so a waypoint has to be instantiated. | 
| 911 |         allWaypoints = false; | 
| 912 |  | 
| 913 |         QGeoCoordinate c = parseCoordinate(value: w); | 
| 914 |         if (!c.isValid()) { | 
| 915 |             qmlWarning(me: this) << QStringLiteral("Invalid waypoint" ); | 
| 916 |             flushWaypoints(waypoints&: waypointList); | 
| 917 |             return; | 
| 918 |         } | 
| 919 |  | 
| 920 |         waypoint = new QDeclarativeGeoWaypoint(this); | 
| 921 |         waypoint->setCoordinate(c); | 
| 922 |         waypointList << waypoint; | 
| 923 |  | 
| 924 |     } | 
| 925 |  | 
| 926 |     if (allWaypoints && m_waypoints == waypointList) | 
| 927 |         return; | 
| 928 |  | 
| 929 |     flushWaypoints(waypoints&: m_waypoints); | 
| 930 |     m_waypoints = waypointList; | 
| 931 |     for (const QDeclarativeGeoWaypoint *w: qAsConst(t&: m_waypoints)) | 
| 932 |         connect(sender: w, signal: &QDeclarativeGeoWaypoint::waypointDetailsChanged, receiver: this, slot: &QDeclarativeGeoRouteQuery::waypointChanged); | 
| 933 |  | 
| 934 |     waypointChanged(); | 
| 935 | } | 
| 936 |  | 
| 937 | /*! | 
| 938 |     \qmlproperty list<georectangle> RouteQuery::excludedAreas | 
| 939 |  | 
| 940 |     Areas that the route must not cross. | 
| 941 |  | 
| 942 |     Excluded areas can be set as part of the \l RouteQuery type declaration or | 
| 943 |     dynamically with the functions provided. | 
| 944 |  | 
| 945 |     \sa addExcludedArea, removeExcludedArea, clearExcludedAreas | 
| 946 | */ | 
| 947 | QJSValue QDeclarativeGeoRouteQuery::excludedAreas() const | 
| 948 | { | 
| 949 |     QQmlContext *context = QQmlEngine::contextForObject(parent()); | 
| 950 |     QQmlEngine *engine = context->engine(); | 
| 951 |     QV4::ExecutionEngine *v4 = QQmlEnginePrivate::getV4Engine(e: engine); | 
| 952 |  | 
| 953 |     QV4::Scope scope(v4); | 
| 954 |     QV4::Scoped<QV4::ArrayObject> excludedAreasArray(scope, v4->newArrayObject(count: request_.excludeAreas().length())); | 
| 955 |     for (int i = 0; i < request_.excludeAreas().length(); ++i) { | 
| 956 |         const QGeoRectangle &r = request_.excludeAreas().at(i); | 
| 957 |  | 
| 958 |         QV4::ScopedValue cv(scope, v4->fromVariant(QVariant::fromValue(value: r))); | 
| 959 |         excludedAreasArray->put(idx: i, v: cv); | 
| 960 |     } | 
| 961 |  | 
| 962 |     return QJSValue(v4, excludedAreasArray.asReturnedValue()); | 
| 963 | } | 
| 964 |  | 
| 965 | void QDeclarativeGeoRouteQuery::setExcludedAreas(const QJSValue &value) | 
| 966 | { | 
| 967 |     if (!value.isArray()) | 
| 968 |         return; | 
| 969 |  | 
| 970 |     QList<QGeoRectangle> excludedAreasList; | 
| 971 |     quint32 length = value.property(QStringLiteral("length" )).toUInt(); | 
| 972 |     for (quint32 i = 0; i < length; ++i) { | 
| 973 |         bool ok; | 
| 974 |         QGeoRectangle r = parseRectangle(value: value.property(arrayIndex: i), ok: &ok); | 
| 975 |  | 
| 976 |         if (!ok || !r.isValid()) { | 
| 977 |             qmlWarning(me: this) << QStringLiteral("Unsupported area type" ); | 
| 978 |             return; | 
| 979 |         } | 
| 980 |  | 
| 981 |         excludedAreasList.append(t: r); | 
| 982 |     } | 
| 983 |  | 
| 984 |     if (request_.excludeAreas() == excludedAreasList) | 
| 985 |         return; | 
| 986 |  | 
| 987 |     request_.setExcludeAreas(excludedAreasList); | 
| 988 |  | 
| 989 |     if (complete_) { | 
| 990 |         emit excludedAreasChanged(); | 
| 991 |         emit queryDetailsChanged(); | 
| 992 |     } | 
| 993 | } | 
| 994 |  | 
| 995 | /*! | 
| 996 |     \qmlmethod void QtLocation::RouteQuery::addExcludedArea(georectangle area) | 
| 997 |  | 
| 998 |     Adds the specified georectangle \a area to the excluded areas | 
| 999 |     (areas that the route must not cross). | 
| 1000 |     The same area can only be added once. | 
| 1001 |  | 
| 1002 |     \sa removeExcludedArea, clearExcludedAreas | 
| 1003 | */ | 
| 1004 |  | 
| 1005 |  | 
| 1006 | void QDeclarativeGeoRouteQuery::addExcludedArea(const QGeoRectangle &area) | 
| 1007 | { | 
| 1008 |     if (!area.isValid()) | 
| 1009 |         return; | 
| 1010 |  | 
| 1011 |     QList<QGeoRectangle> excludedAreas = request_.excludeAreas(); | 
| 1012 |  | 
| 1013 |     if (excludedAreas.contains(t: area)) | 
| 1014 |         return; | 
| 1015 |  | 
| 1016 |     excludedAreas.append(t: area); | 
| 1017 |  | 
| 1018 |     request_.setExcludeAreas(excludedAreas); | 
| 1019 |  | 
| 1020 |     if (complete_) { | 
| 1021 |         emit excludedAreasChanged(); | 
| 1022 |         emit queryDetailsChanged(); | 
| 1023 |     } | 
| 1024 | } | 
| 1025 |  | 
| 1026 | /*! | 
| 1027 |     \qmlmethod void QtLocation::RouteQuery::removeExcludedArea(georectangle area) | 
| 1028 |  | 
| 1029 |     Removes the given \a area from excluded areas (areas that the route must not cross). | 
| 1030 |  | 
| 1031 |     \sa addExcludedArea, clearExcludedAreas | 
| 1032 | */ | 
| 1033 |  | 
| 1034 | void QDeclarativeGeoRouteQuery::removeExcludedArea(const QGeoRectangle &area) | 
| 1035 | { | 
| 1036 |     if (!area.isValid()) | 
| 1037 |         return; | 
| 1038 |  | 
| 1039 |     QList<QGeoRectangle> excludedAreas = request_.excludeAreas(); | 
| 1040 |  | 
| 1041 |     int index = excludedAreas.lastIndexOf(t: area); | 
| 1042 |     if (index == -1) { | 
| 1043 |         qmlWarning(me: this) << QStringLiteral("Cannot remove nonexistent area." ); | 
| 1044 |         return; | 
| 1045 |     } | 
| 1046 |     excludedAreas.removeAt(i: index); | 
| 1047 |     request_.setExcludeAreas(excludedAreas); | 
| 1048 |  | 
| 1049 |     if (complete_) { | 
| 1050 |         emit excludedAreasChanged(); | 
| 1051 |         emit queryDetailsChanged(); | 
| 1052 |     } | 
| 1053 | } | 
| 1054 |  | 
| 1055 | /*! | 
| 1056 |     \qmlmethod void QtLocation::RouteQuery::clearExcludedAreas() | 
| 1057 |  | 
| 1058 |     Clears all excluded areas (areas that the route must not cross). | 
| 1059 |  | 
| 1060 |     \sa addExcludedArea, removeExcludedArea | 
| 1061 | */ | 
| 1062 |  | 
| 1063 | void QDeclarativeGeoRouteQuery::clearExcludedAreas() | 
| 1064 | { | 
| 1065 |     if (request_.excludeAreas().isEmpty()) | 
| 1066 |         return; | 
| 1067 |  | 
| 1068 |     request_.setExcludeAreas(QList<QGeoRectangle>()); | 
| 1069 |  | 
| 1070 |     if (complete_) { | 
| 1071 |         emit excludedAreasChanged(); | 
| 1072 |         emit queryDetailsChanged(); | 
| 1073 |     } | 
| 1074 | } | 
| 1075 |  | 
| 1076 | /*! | 
| 1077 |     \qmlmethod void QtLocation::RouteQuery::addWaypoint(coordinate) | 
| 1078 |  | 
| 1079 |     Appends a coordinate to the list of waypoints. Same coordinate | 
| 1080 |     can be set multiple times. | 
| 1081 |     The \a coordinate argument can be a \l coordinate or a \l Waypoint. | 
| 1082 |     If a \l coordinate is used, it will be internally converted to a | 
| 1083 |     \l Waypoint. | 
| 1084 |  | 
| 1085 |     \sa removeWaypoint, clearWaypoints | 
| 1086 | */ | 
| 1087 | void QDeclarativeGeoRouteQuery::addWaypoint(const QVariant &waypoint) | 
| 1088 | { | 
| 1089 |     QDeclarativeGeoWaypoint *w = nullptr; | 
| 1090 |     QObject *obj = qvariant_cast<QObject *>(v: waypoint); | 
| 1091 |     w = qobject_cast<QDeclarativeGeoWaypoint *>(object: obj); | 
| 1092 |  | 
| 1093 |     if (w) { | 
| 1094 |         if (! w->isValid()) { | 
| 1095 |             qmlWarning(me: this) << QStringLiteral("Invalid waypoint" ); | 
| 1096 |             return; | 
| 1097 |         } | 
| 1098 |  | 
| 1099 |         m_waypoints << w; | 
| 1100 |         connect(sender: w, signal: &QDeclarativeGeoWaypoint::waypointDetailsChanged, receiver: this, slot: &QDeclarativeGeoRouteQuery::waypointChanged); | 
| 1101 |         waypointChanged(); | 
| 1102 |         return; | 
| 1103 |     } | 
| 1104 |  | 
| 1105 |     // if here, waypoint is not a Waypoint, so either a QGeoCoordinate or a variant map, so a waypoint has to be instantiated. | 
| 1106 |  | 
| 1107 |     QGeoCoordinate c = parseCoordinate(value: waypoint); | 
| 1108 |     if (!c.isValid()) { | 
| 1109 |         qmlWarning(me: this) << QStringLiteral("Invalid coordinate as waypoint" ); | 
| 1110 |         return; | 
| 1111 |     } | 
| 1112 |  | 
| 1113 |     w = new QDeclarativeGeoWaypoint(this); | 
| 1114 |     w->setCoordinate(c); | 
| 1115 |     m_waypoints << w; | 
| 1116 |     connect(sender: w, signal: &QDeclarativeGeoWaypoint::waypointDetailsChanged, receiver: this, slot: &QDeclarativeGeoRouteQuery::waypointChanged); | 
| 1117 |     waypointChanged(); | 
| 1118 | } | 
| 1119 |  | 
| 1120 | /*! | 
| 1121 |     \qmlmethod void QtLocation::RouteQuery::removeWaypoint(coordinate) | 
| 1122 |  | 
| 1123 |     Removes the given \a coordinate from the list of waypoints. If the | 
| 1124 |     same coordinate appears multiple times, the most recently added | 
| 1125 |     coordinate instance is removed. | 
| 1126 |  | 
| 1127 |     \sa addWaypoint, clearWaypoints | 
| 1128 | */ | 
| 1129 | void QDeclarativeGeoRouteQuery::removeWaypoint(const QVariant &waypoint) | 
| 1130 | { | 
| 1131 |     QDeclarativeGeoWaypoint *w = nullptr; | 
| 1132 |     QObject *obj = qvariant_cast<QObject *>(v: waypoint); | 
| 1133 |     w = qobject_cast<QDeclarativeGeoWaypoint *>(object: obj); | 
| 1134 |  | 
| 1135 |     if (w) { | 
| 1136 |         if (!w->isValid()) { | 
| 1137 |             qmlWarning(me: this) << QStringLiteral("Invalid waypoint" ); | 
| 1138 |             return; | 
| 1139 |         } | 
| 1140 |  | 
| 1141 |         int idx = findWaypoint(waypoints: m_waypoints, w); | 
| 1142 |         if (idx >= 0) { | 
| 1143 |             QDeclarativeGeoWaypoint *toRemove = m_waypoints.takeAt(i: idx); | 
| 1144 |             toRemove->disconnect(receiver: this); | 
| 1145 |             if (toRemove->parent() == this) | 
| 1146 |                 delete toRemove; | 
| 1147 |  | 
| 1148 |             waypointChanged(); | 
| 1149 |         } else { | 
| 1150 |             qmlWarning(me: this) << QStringLiteral("Cannot remove nonexistent waypoint." ); | 
| 1151 |         } | 
| 1152 |         return; | 
| 1153 |     } | 
| 1154 |  | 
| 1155 |     QGeoCoordinate c = parseCoordinate(value: waypoint); | 
| 1156 |     if (!c.isValid()) { | 
| 1157 |         qmlWarning(me: this) << QStringLiteral("Invalid coordinate as waypoint" ); | 
| 1158 |         return; | 
| 1159 |     } | 
| 1160 |  | 
| 1161 |     int idx = findWaypoint(waypoints: m_waypoints, c); | 
| 1162 |     if (idx >= 0) { | 
| 1163 |         QDeclarativeGeoWaypoint *toRemove = m_waypoints.takeAt(i: idx); | 
| 1164 |         toRemove->disconnect(receiver: this); | 
| 1165 |         if (toRemove->parent() == this) | 
| 1166 |             delete toRemove; | 
| 1167 |  | 
| 1168 |         waypointChanged(); | 
| 1169 |     } else { | 
| 1170 |         qmlWarning(me: this) << QStringLiteral("Cannot remove nonexistent waypoint." ); | 
| 1171 |     } | 
| 1172 | } | 
| 1173 |  | 
| 1174 | /*! | 
| 1175 |     \qmlmethod void QtLocation::RouteQuery::clearWaypoints() | 
| 1176 |  | 
| 1177 |     Clears all waypoints. | 
| 1178 |  | 
| 1179 |     \sa removeWaypoint, addWaypoint | 
| 1180 | */ | 
| 1181 | void QDeclarativeGeoRouteQuery::clearWaypoints() | 
| 1182 | { | 
| 1183 |     if (m_waypoints.isEmpty()) | 
| 1184 |         return; | 
| 1185 |  | 
| 1186 |     flushWaypoints(waypoints&: m_waypoints); | 
| 1187 |     waypointChanged(); | 
| 1188 | } | 
| 1189 |  | 
| 1190 | void QDeclarativeGeoRouteQuery::flushWaypoints(QList<QDeclarativeGeoWaypoint *> &waypoints) | 
| 1191 | { | 
| 1192 |     for (const QDeclarativeGeoWaypoint *w : qAsConst(t&: waypoints)) { | 
| 1193 |         w->disconnect(receiver: this); | 
| 1194 |         if (w->parent() == this) // w has been created internally as a result of adding a QGeoCoordinate | 
| 1195 |             delete w; | 
| 1196 |     } | 
| 1197 |     waypoints.clear(); | 
| 1198 | } | 
| 1199 |  | 
| 1200 | /*! | 
| 1201 |     \qmlmethod void QtLocation::RouteQuery::setFeatureWeight(FeatureType feature, FeatureWeight weight) | 
| 1202 |  | 
| 1203 |     Defines the \a weight  to associate with a \a feature during the planning | 
| 1204 |     of a route. | 
| 1205 |  | 
| 1206 |     Following lists the possible feature weights: | 
| 1207 |  | 
| 1208 |     \value RouteQuery.NeutralFeatureWeight | 
| 1209 |     The presence or absence of the feature does not affect the planning of the | 
| 1210 |     route | 
| 1211 |  | 
| 1212 |     \value RouteQuery.PreferFeatureWeight | 
| 1213 |     Routes which contain the feature are preferred over those that do not | 
| 1214 |  | 
| 1215 |     \value RouteQuery.RequireFeatureWeight | 
| 1216 |     Only routes which contain the feature are considered, otherwise no | 
| 1217 |     route will be returned | 
| 1218 |  | 
| 1219 |     \value RouteQuery.AvoidFeatureWeight | 
| 1220 |     Routes which do not contain the feature are preferred over those that | 
| 1221 |     do | 
| 1222 |  | 
| 1223 |     \value RouteQuery.DisallowFeatureWeight | 
| 1224 |     Only routes which do not contain the feature are considered, otherwise | 
| 1225 |     no route will be returned | 
| 1226 |  | 
| 1227 |     \sa featureTypes, resetFeatureWeights, featureWeight | 
| 1228 |  | 
| 1229 | */ | 
| 1230 |  | 
| 1231 | void QDeclarativeGeoRouteQuery::setFeatureWeight(FeatureType featureType, FeatureWeight featureWeight) | 
| 1232 | { | 
| 1233 |     if (featureType == NoFeature && !request_.featureTypes().isEmpty()) { | 
| 1234 |         resetFeatureWeights(); | 
| 1235 |         return; | 
| 1236 |     } | 
| 1237 |  | 
| 1238 |     // Check if the weight changes, as we need to signal it | 
| 1239 |     FeatureWeight originalWeight = static_cast<FeatureWeight>(request_.featureWeight(featureType: static_cast<QGeoRouteRequest::FeatureType>(featureType))); | 
| 1240 |     if (featureWeight == originalWeight) | 
| 1241 |         return; | 
| 1242 |  | 
| 1243 |     request_.setFeatureWeight(featureType: static_cast<QGeoRouteRequest::FeatureType>(featureType), | 
| 1244 |                               featureWeight: static_cast<QGeoRouteRequest::FeatureWeight>(featureWeight)); | 
| 1245 |     if (complete_ && ((originalWeight == NeutralFeatureWeight) || (featureWeight == NeutralFeatureWeight))) { | 
| 1246 |         // featureTypes should now give a different list, because the original and new weight | 
| 1247 |         // were not same, and other one was neutral weight | 
| 1248 |         emit featureTypesChanged(); | 
| 1249 |         emit queryDetailsChanged(); | 
| 1250 |     } | 
| 1251 | } | 
| 1252 |  | 
| 1253 | /*! | 
| 1254 |     \qmlmethod void QtLocation::RouteQuery::resetFeatureWeights() | 
| 1255 |  | 
| 1256 |     Resets all feature weights to their default state (NeutralFeatureWeight). | 
| 1257 |  | 
| 1258 |     \sa featureTypes, setFeatureWeight, featureWeight | 
| 1259 | */ | 
| 1260 | void QDeclarativeGeoRouteQuery::resetFeatureWeights() | 
| 1261 | { | 
| 1262 |     // reset all feature types. | 
| 1263 |     QList<QGeoRouteRequest::FeatureType> featureTypes = request_.featureTypes(); | 
| 1264 |     for (int i = 0; i < featureTypes.count(); ++i) { | 
| 1265 |         request_.setFeatureWeight(featureType: featureTypes.at(i), featureWeight: QGeoRouteRequest::NeutralFeatureWeight); | 
| 1266 |     } | 
| 1267 |     if (complete_) { | 
| 1268 |         emit featureTypesChanged(); | 
| 1269 |         emit queryDetailsChanged(); | 
| 1270 |     } | 
| 1271 | } | 
| 1272 |  | 
| 1273 | /*! | 
| 1274 |     \qmlmethod FeatureWeight QtLocation::RouteQuery::featureWeight(FeatureType featureType) | 
| 1275 |  | 
| 1276 |     Gets the weight for the \a featureType. | 
| 1277 |  | 
| 1278 |     \sa featureTypes, setFeatureWeight, resetFeatureWeights | 
| 1279 | */ | 
| 1280 |  | 
| 1281 | int QDeclarativeGeoRouteQuery::featureWeight(FeatureType featureType) | 
| 1282 | { | 
| 1283 |     return request_.featureWeight(featureType: static_cast<QGeoRouteRequest::FeatureType>(featureType)); | 
| 1284 | } | 
| 1285 |  | 
| 1286 | /*! | 
| 1287 |     \internal | 
| 1288 | */ | 
| 1289 | void QDeclarativeGeoRouteQuery::setTravelModes(QDeclarativeGeoRouteQuery::TravelModes travelModes) | 
| 1290 | { | 
| 1291 |     QGeoRouteRequest::TravelModes reqTravelModes; | 
| 1292 |  | 
| 1293 |     if (travelModes & QDeclarativeGeoRouteQuery::CarTravel) | 
| 1294 |         reqTravelModes |= QGeoRouteRequest::CarTravel; | 
| 1295 |     if (travelModes & QDeclarativeGeoRouteQuery::PedestrianTravel) | 
| 1296 |         reqTravelModes |= QGeoRouteRequest::PedestrianTravel; | 
| 1297 |     if (travelModes & QDeclarativeGeoRouteQuery::BicycleTravel) | 
| 1298 |         reqTravelModes |= QGeoRouteRequest::BicycleTravel; | 
| 1299 |     if (travelModes & QDeclarativeGeoRouteQuery::PublicTransitTravel) | 
| 1300 |         reqTravelModes |= QGeoRouteRequest::PublicTransitTravel; | 
| 1301 |     if (travelModes & QDeclarativeGeoRouteQuery::TruckTravel) | 
| 1302 |         reqTravelModes |= QGeoRouteRequest::TruckTravel; | 
| 1303 |  | 
| 1304 |     if (reqTravelModes == request_.travelModes()) | 
| 1305 |         return; | 
| 1306 |  | 
| 1307 |     request_.setTravelModes(reqTravelModes); | 
| 1308 |  | 
| 1309 |     if (complete_) { | 
| 1310 |         emit travelModesChanged(); | 
| 1311 |         emit queryDetailsChanged(); | 
| 1312 |     } | 
| 1313 | } | 
| 1314 |  | 
| 1315 |  | 
| 1316 | /*! | 
| 1317 |     \qmlproperty enumeration RouteQuery::segmentDetail | 
| 1318 |  | 
| 1319 |     The level of detail which will be used in the representation of routing segments. | 
| 1320 |  | 
| 1321 |     \value RouteQuery.NoSegmentData | 
| 1322 |     No segment data should be included with the route | 
| 1323 |  | 
| 1324 |     \value RouteQuery.BasicSegmentData | 
| 1325 |     Basic segment data will be included with the route | 
| 1326 |  | 
| 1327 |     The default value is \c {RouteQuery.BasicSegmentData}. | 
| 1328 | */ | 
| 1329 |  | 
| 1330 | void QDeclarativeGeoRouteQuery::setSegmentDetail(SegmentDetail segmentDetail) | 
| 1331 | { | 
| 1332 |     if (static_cast<QGeoRouteRequest::SegmentDetail>(segmentDetail) == request_.segmentDetail()) | 
| 1333 |         return; | 
| 1334 |     request_.setSegmentDetail(static_cast<QGeoRouteRequest::SegmentDetail>(segmentDetail)); | 
| 1335 |     if (complete_) { | 
| 1336 |         emit segmentDetailChanged(); | 
| 1337 |         emit queryDetailsChanged(); | 
| 1338 |     } | 
| 1339 | } | 
| 1340 |  | 
| 1341 | QDeclarativeGeoRouteQuery::SegmentDetail QDeclarativeGeoRouteQuery::segmentDetail() const | 
| 1342 | { | 
| 1343 |     return static_cast<QDeclarativeGeoRouteQuery::SegmentDetail>(request_.segmentDetail()); | 
| 1344 | } | 
| 1345 |  | 
| 1346 | /*! | 
| 1347 |     \qmlproperty enumeration RouteQuery::maneuverDetail | 
| 1348 |  | 
| 1349 |     The level of detail which will be used in the representation of routing maneuvers. | 
| 1350 |  | 
| 1351 |     \value RouteQuery.NoManeuvers | 
| 1352 |     No maneuvers should be included with the route | 
| 1353 |  | 
| 1354 |     \value RouteQuery.BasicManeuvers | 
| 1355 |     Basic maneuvers will be included with the route | 
| 1356 |  | 
| 1357 |     The default value is \c {RouteQuery.BasicManeuvers}. | 
| 1358 | */ | 
| 1359 |  | 
| 1360 | void QDeclarativeGeoRouteQuery::setManeuverDetail(ManeuverDetail maneuverDetail) | 
| 1361 | { | 
| 1362 |     if (static_cast<QGeoRouteRequest::ManeuverDetail>(maneuverDetail) == request_.maneuverDetail()) | 
| 1363 |         return; | 
| 1364 |     request_.setManeuverDetail(static_cast<QGeoRouteRequest::ManeuverDetail>(maneuverDetail)); | 
| 1365 |     if (complete_) { | 
| 1366 |         emit maneuverDetailChanged(); | 
| 1367 |         emit queryDetailsChanged(); | 
| 1368 |     } | 
| 1369 | } | 
| 1370 |  | 
| 1371 | QDeclarativeGeoRouteQuery::ManeuverDetail QDeclarativeGeoRouteQuery::maneuverDetail() const | 
| 1372 | { | 
| 1373 |     return static_cast<QDeclarativeGeoRouteQuery::ManeuverDetail>(request_.maneuverDetail()); | 
| 1374 | } | 
| 1375 |  | 
| 1376 | /*! | 
| 1377 |     \qmlproperty enumeration RouteQuery::travelModes | 
| 1378 |  | 
| 1379 |     The travel modes which should be considered during the planning of the route. | 
| 1380 |     Values can be combined with OR ('|') -operator. | 
| 1381 |  | 
| 1382 |     \value RouteQuery.CarTravel | 
| 1383 |     The route will be optimized for someone who is driving a car | 
| 1384 |  | 
| 1385 |     \value RouteQuery.PedestrianTravel | 
| 1386 |     The route will be optimized for someone who is walking | 
| 1387 |  | 
| 1388 |     \value RouteQuery.BicycleTravel | 
| 1389 |     The route will be optimized for someone who is riding a bicycle | 
| 1390 |  | 
| 1391 |     \value RouteQuery.PublicTransit | 
| 1392 |     Travel The route will be optimized for someone who is making use of public transit | 
| 1393 |  | 
| 1394 |     \value RouteQuery.TruckTravel | 
| 1395 |     The route will be optimized for someone who is driving a truck | 
| 1396 |  | 
| 1397 |     The default value is \c {RouteQuery.CarTravel}. | 
| 1398 | */ | 
| 1399 |  | 
| 1400 | QDeclarativeGeoRouteQuery::TravelModes QDeclarativeGeoRouteQuery::travelModes() const | 
| 1401 | { | 
| 1402 |     QGeoRouteRequest::TravelModes reqTravelModes = request_.travelModes(); | 
| 1403 |     QDeclarativeGeoRouteQuery::TravelModes travelModes; | 
| 1404 |  | 
| 1405 |     if (reqTravelModes & QGeoRouteRequest::CarTravel) | 
| 1406 |         travelModes |= QDeclarativeGeoRouteQuery::CarTravel; | 
| 1407 |     if (reqTravelModes & QGeoRouteRequest::PedestrianTravel) | 
| 1408 |         travelModes |= QDeclarativeGeoRouteQuery::PedestrianTravel; | 
| 1409 |     if (reqTravelModes & QGeoRouteRequest::BicycleTravel) | 
| 1410 |         travelModes |= QDeclarativeGeoRouteQuery::BicycleTravel; | 
| 1411 |     if (reqTravelModes & QGeoRouteRequest::PublicTransitTravel) | 
| 1412 |         travelModes |= QDeclarativeGeoRouteQuery::PublicTransitTravel; | 
| 1413 |     if (reqTravelModes & QGeoRouteRequest::TruckTravel) | 
| 1414 |         travelModes |= QDeclarativeGeoRouteQuery::TruckTravel; | 
| 1415 |  | 
| 1416 |     return travelModes; | 
| 1417 | } | 
| 1418 |  | 
| 1419 | /*! | 
| 1420 |     \qmlproperty enumeration RouteQuery::routeOptimizations | 
| 1421 |  | 
| 1422 |     The route optimizations which should be considered during the planning of the route. | 
| 1423 |     Values can be combined with OR ('|') -operator. | 
| 1424 |  | 
| 1425 |  | 
| 1426 |     \value RouteQuery.ShortestRoute | 
| 1427 |     Minimize the length of the journey | 
| 1428 |  | 
| 1429 |     \value RouteQuery.FastestRoute | 
| 1430 |     Minimize the traveling time for the journey | 
| 1431 |  | 
| 1432 |     \value RouteQuery.MostEconomicRoute | 
| 1433 |     Minimize the cost of the journey | 
| 1434 |  | 
| 1435 |     \value RouteQuery.MostScenicRoute | 
| 1436 |     Maximize the scenic potential of the journey | 
| 1437 |  | 
| 1438 |     The default value is \c {RouteQuery.FastestRoute}. | 
| 1439 | */ | 
| 1440 |  | 
| 1441 | QDeclarativeGeoRouteQuery::RouteOptimizations QDeclarativeGeoRouteQuery::routeOptimizations() const | 
| 1442 | { | 
| 1443 |     QGeoRouteRequest::RouteOptimizations reqOptimizations = request_.routeOptimization(); | 
| 1444 |     QDeclarativeGeoRouteQuery::RouteOptimizations optimization; | 
| 1445 |  | 
| 1446 |     if (reqOptimizations & QGeoRouteRequest::ShortestRoute) | 
| 1447 |         optimization |= QDeclarativeGeoRouteQuery::ShortestRoute; | 
| 1448 |     if (reqOptimizations & QGeoRouteRequest::FastestRoute) | 
| 1449 |         optimization |= QDeclarativeGeoRouteQuery::FastestRoute; | 
| 1450 |     if (reqOptimizations & QGeoRouteRequest::MostEconomicRoute) | 
| 1451 |         optimization |= QDeclarativeGeoRouteQuery::MostEconomicRoute; | 
| 1452 |     if (reqOptimizations & QGeoRouteRequest::MostScenicRoute) | 
| 1453 |         optimization |= QDeclarativeGeoRouteQuery::MostScenicRoute; | 
| 1454 |  | 
| 1455 |     return optimization; | 
| 1456 | } | 
| 1457 |  | 
| 1458 | /*! | 
| 1459 |     \qmlproperty date RouteQuery::departureTime | 
| 1460 |  | 
| 1461 |     The departure time to be used when querying for the route. | 
| 1462 |     The default value is an invalid date, meaning no departure time will be used in the query. | 
| 1463 |  | 
| 1464 |     \since 5.13 | 
| 1465 | */ | 
| 1466 | void QDeclarativeGeoRouteQuery::setDepartureTime(const QDateTime &departureTime) | 
| 1467 | { | 
| 1468 |     if (departureTime == request_.departureTime()) | 
| 1469 |         return; | 
| 1470 |  | 
| 1471 |     request_.setDepartureTime(departureTime); | 
| 1472 |     if (complete_) { | 
| 1473 |         emit departureTimeChanged(); | 
| 1474 |         emit queryDetailsChanged(); | 
| 1475 |     } | 
| 1476 | } | 
| 1477 |  | 
| 1478 | QDateTime QDeclarativeGeoRouteQuery::departureTime() const | 
| 1479 | { | 
| 1480 |     return request_.departureTime(); | 
| 1481 | } | 
| 1482 |  | 
| 1483 | void QDeclarativeGeoRouteQuery::setRouteOptimizations(QDeclarativeGeoRouteQuery::RouteOptimizations optimization) | 
| 1484 | { | 
| 1485 |     QGeoRouteRequest::RouteOptimizations reqOptimizations; | 
| 1486 |  | 
| 1487 |     if (optimization & QDeclarativeGeoRouteQuery::ShortestRoute) | 
| 1488 |         reqOptimizations |= QGeoRouteRequest::ShortestRoute; | 
| 1489 |     if (optimization & QDeclarativeGeoRouteQuery::FastestRoute) | 
| 1490 |         reqOptimizations |= QGeoRouteRequest::FastestRoute; | 
| 1491 |     if (optimization & QDeclarativeGeoRouteQuery::MostEconomicRoute) | 
| 1492 |         reqOptimizations |= QGeoRouteRequest::MostEconomicRoute; | 
| 1493 |     if (optimization & QDeclarativeGeoRouteQuery::MostScenicRoute) | 
| 1494 |         reqOptimizations |= QGeoRouteRequest::MostScenicRoute; | 
| 1495 |  | 
| 1496 |     if (reqOptimizations == request_.routeOptimization()) | 
| 1497 |         return; | 
| 1498 |  | 
| 1499 |     request_.setRouteOptimization(reqOptimizations); | 
| 1500 |  | 
| 1501 |     if (complete_) { | 
| 1502 |         emit routeOptimizationsChanged(); | 
| 1503 |         emit queryDetailsChanged(); | 
| 1504 |     } | 
| 1505 | } | 
| 1506 |  | 
| 1507 | /*! | 
| 1508 |     \internal | 
| 1509 | */ | 
| 1510 | QGeoRouteRequest QDeclarativeGeoRouteQuery::routeRequest() | 
| 1511 | { | 
| 1512 |     if (m_extraParametersChanged) { | 
| 1513 |         m_extraParametersChanged = false; | 
| 1514 |         // Update extra params into request | 
| 1515 |         const QList<QDeclarativeGeoMapParameter *> params = quickChildren<QDeclarativeGeoMapParameter>(); | 
| 1516 |         QVariantMap ; | 
| 1517 |         for (const QDeclarativeGeoMapParameter *p: params) | 
| 1518 |             extraParameters[p->type()] = p->toVariantMap(); | 
| 1519 |         request_.setExtraParameters(extraParameters); | 
| 1520 |     } | 
| 1521 |     if (m_waypointsChanged) { | 
| 1522 |         m_waypointsChanged = false; | 
| 1523 |         // Update waypoints and metadata into request | 
| 1524 |         request_.setWaypoints(waypointCoordinates(waypoints: m_waypoints)); | 
| 1525 |         request_.setWaypointsMetadata(waypointMetadata(waypoints: m_waypoints)); | 
| 1526 |     } | 
| 1527 |     return request_; | 
| 1528 | } | 
| 1529 |  | 
| 1530 |  | 
| 1531 | /*! | 
| 1532 |     \qmlproperty VariantMap RouteQuery::extraParameters | 
| 1533 |     \readonly | 
| 1534 |  | 
| 1535 |     The route query extra parameters. This property is read only. If the query is | 
| 1536 |     defined by the user, these can be set by using MapParameters. | 
| 1537 |     If the route query comes from the engine via signals, the query is intended to be read-only. | 
| 1538 |  | 
| 1539 |     \since 5.11 | 
| 1540 | */ | 
| 1541 | QVariantMap QDeclarativeGeoRouteQuery::() | 
| 1542 | { | 
| 1543 |     return routeRequest().extraParameters(); | 
| 1544 | } | 
| 1545 |  | 
| 1546 | void QDeclarativeGeoRouteQuery::excludedAreaCoordinateChanged() | 
| 1547 | { | 
| 1548 |     if (!m_excludedAreaCoordinateChanged) { | 
| 1549 |         m_excludedAreaCoordinateChanged = true; | 
| 1550 |         QMetaObject::invokeMethod(obj: this, member: "doCoordinateChanged" , type: Qt::QueuedConnection); | 
| 1551 |     } | 
| 1552 | } | 
| 1553 |  | 
| 1554 | void QDeclarativeGeoRouteQuery::() | 
| 1555 | { | 
| 1556 |     m_extraParametersChanged = true; | 
| 1557 |     if (complete_) { | 
| 1558 |         emit extraParametersChanged(); | 
| 1559 |         emit queryDetailsChanged(); | 
| 1560 |     } | 
| 1561 | } | 
| 1562 |  | 
| 1563 | void QDeclarativeGeoRouteQuery::waypointChanged() | 
| 1564 | { | 
| 1565 |     m_waypointsChanged = true; | 
| 1566 |     if (complete_) { | 
| 1567 |         emit waypointsChanged(); | 
| 1568 |         emit queryDetailsChanged(); | 
| 1569 |     } | 
| 1570 | } | 
| 1571 |  | 
| 1572 | void QDeclarativeGeoRouteQuery::append(QQmlListProperty<QObject> *p, QObject *v) | 
| 1573 | { | 
| 1574 |     QDeclarativeGeoRouteQuery *query = static_cast<QDeclarativeGeoRouteQuery*>(p->object); | 
| 1575 |     query->m_children.append(t: v); | 
| 1576 |  | 
| 1577 |     QDeclarativeGeoMapParameter *param = qobject_cast<QDeclarativeGeoMapParameter *>(object: v); | 
| 1578 |     if (param) { | 
| 1579 |         query->m_extraParametersChanged = true; | 
| 1580 |         query->connect(sender: param, signal: &QGeoMapParameter::propertyUpdated, | 
| 1581 |                        receiver: query, slot: &QDeclarativeGeoRouteQuery::extraParameterChanged); | 
| 1582 |         if (query->complete_) { | 
| 1583 |             emit query->extraParametersChanged(); | 
| 1584 |             emit query->queryDetailsChanged(); | 
| 1585 |         } | 
| 1586 |     } | 
| 1587 | } | 
| 1588 |  | 
| 1589 | int QDeclarativeGeoRouteQuery::count(QQmlListProperty<QObject> *p) | 
| 1590 | { | 
| 1591 |     return static_cast<QDeclarativeGeoRouteQuery*>(p->object)->m_children.count(); | 
| 1592 | } | 
| 1593 |  | 
| 1594 | QObject *QDeclarativeGeoRouteQuery::at(QQmlListProperty<QObject> *p, int idx) | 
| 1595 | { | 
| 1596 |     return static_cast<QDeclarativeGeoRouteQuery*>(p->object)->m_children.at(i: idx); | 
| 1597 | } | 
| 1598 |  | 
| 1599 | void QDeclarativeGeoRouteQuery::clear(QQmlListProperty<QObject> *p) | 
| 1600 | { | 
| 1601 |     QDeclarativeGeoRouteQuery *query = static_cast<QDeclarativeGeoRouteQuery*>(p->object); | 
| 1602 |     for (auto kid : qAsConst(t&: query->m_children)) { | 
| 1603 |         auto val = qobject_cast<QDeclarativeGeoMapParameter *>(object: kid); | 
| 1604 |         if (val) { | 
| 1605 |             val->disconnect(sender: val, signal: nullptr, receiver: query, member: nullptr); | 
| 1606 |             query->m_extraParametersChanged = true; | 
| 1607 |         } | 
| 1608 |     } | 
| 1609 |     query->m_children.clear(); | 
| 1610 |     if (query->m_extraParametersChanged && query->complete_) { | 
| 1611 |         emit query->extraParametersChanged(); | 
| 1612 |         emit query->queryDetailsChanged(); | 
| 1613 |     } | 
| 1614 | } | 
| 1615 |  | 
| 1616 | QQmlListProperty<QObject> QDeclarativeGeoRouteQuery::declarativeChildren() | 
| 1617 | { | 
| 1618 |     return QQmlListProperty<QObject>(this, nullptr, | 
| 1619 |                                            &QDeclarativeGeoRouteQuery::append, | 
| 1620 |                                            &QDeclarativeGeoRouteQuery::count, | 
| 1621 |                                            &QDeclarativeGeoRouteQuery::at, | 
| 1622 |                                            &QDeclarativeGeoRouteQuery::clear); | 
| 1623 | } | 
| 1624 |  | 
| 1625 | void QDeclarativeGeoRouteQuery::doCoordinateChanged() | 
| 1626 | { | 
| 1627 |     m_excludedAreaCoordinateChanged = false; | 
| 1628 |     if (complete_) | 
| 1629 |         emit queryDetailsChanged(); | 
| 1630 | } | 
| 1631 |  | 
| 1632 | /*! | 
| 1633 |     \qmltype Waypoint | 
| 1634 |     \instantiates QDeclarativeGeoWaypoint | 
| 1635 |     \inqmlmodule QtLocation | 
| 1636 |     \ingroup qml-QtLocation5-routing | 
| 1637 |     \since QtLocation 5.11 | 
| 1638 |  | 
| 1639 |     \brief The Waypoint type provides a mean to specify a waypoint in a \l RouteQuery | 
| 1640 |     in a more detailed way than by using a simple \l coordinate. | 
| 1641 |  | 
| 1642 |     A Waypoint is a type that allows to specify properties of a waypoint in a \l RouteQuery, | 
| 1643 |     such as the waypoint coordinate, or the angle of approach to the waypoint. | 
| 1644 |  | 
| 1645 |     Additional information that are backend-specific can be specified by nesting \l MapParameter | 
| 1646 |     elements. | 
| 1647 |  | 
| 1648 |     Changing properties of the waypoint or of its nested MapParameteters will cause the containing | 
| 1649 |     \l RouteQuery to emit the queryDetailsChanged signal. | 
| 1650 |  | 
| 1651 |     \section2 Example Usage | 
| 1652 |  | 
| 1653 |     \code | 
| 1654 |     Plugin { | 
| 1655 |         id: aPlugin | 
| 1656 |         name: "osm" | 
| 1657 |     } | 
| 1658 |  | 
| 1659 |     Waypoint { | 
| 1660 |         id: waypointStart | 
| 1661 |         coordinate: ... | 
| 1662 |         bearing: ... | 
| 1663 |     } | 
| 1664 |     Waypoint { | 
| 1665 |         id: waypointFinish | 
| 1666 |         coordinate: ... | 
| 1667 |         bearing: ... | 
| 1668 |     } | 
| 1669 |  | 
| 1670 |     RouteQuery { | 
| 1671 |         id: aQuery | 
| 1672 |         Component.onCompleted: { | 
| 1673 |             travelModes = RouteQuery.CarTravel | 
| 1674 |             addWaypoint(waypointStart) | 
| 1675 |             var aWaypoint = Qt.createQmlObject ('import QtLocation 5.11; Waypoint { ... }', ...) | 
| 1676 |             addWaypoint(aWaypoint) | 
| 1677 |             addWaypoint(waypointFinish) | 
| 1678 |         } | 
| 1679 |     } | 
| 1680 |  | 
| 1681 |     RouteModel { | 
| 1682 |         id: routeModel | 
| 1683 |         plugin: aPlugin | 
| 1684 |         query: aQuery | 
| 1685 |         autoUpdate: true | 
| 1686 |     } | 
| 1687 |     \endcode | 
| 1688 |  | 
| 1689 |     \sa RouteQuery | 
| 1690 | */ | 
| 1691 |  | 
| 1692 |  | 
| 1693 | /* | 
| 1694 |  * | 
| 1695 |     At the time of adding this class (2017.11), 3 routing services are natively supported in Qt: Esri, Here and OSRM. | 
| 1696 |     Waypoint documentation for each of these: | 
| 1697 |     Esri: http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#//02r300000036000000 ,  called "stop" | 
| 1698 |     HERE: https://developer.here.com/documentation/routing/topics/resource-param-type-waypoint.html | 
| 1699 |     OSRM: https://github.com/Project-OSRM/osrm-backend/blob/master/docs/http.md , under Request Options | 
| 1700 |  * | 
| 1701 |  */ | 
| 1702 |  | 
| 1703 |  | 
| 1704 | static QGeoCoordinate convertWaypointToCoordinate(const QDeclarativeGeoWaypoint *value) | 
| 1705 | { | 
| 1706 |     return value->coordinate(); | 
| 1707 | } | 
| 1708 |  | 
| 1709 | struct WaypointVariantConversions | 
| 1710 | { | 
| 1711 |     WaypointVariantConversions() | 
| 1712 |     { | 
| 1713 |         QMetaType::registerConverter<QDeclarativeGeoWaypoint *, QGeoCoordinate>(function: convertWaypointToCoordinate); | 
| 1714 |     } | 
| 1715 | }; | 
| 1716 |  | 
| 1717 | Q_GLOBAL_STATIC(WaypointVariantConversions, initWaypointConversions) | 
| 1718 |  | 
| 1719 |  | 
| 1720 | QDeclarativeGeoWaypoint::QDeclarativeGeoWaypoint(QObject *parent) : QGeoCoordinateObject(parent) | 
| 1721 | { | 
| 1722 |     initWaypointConversions(); | 
| 1723 |     connect(sender: this, signal: &QGeoCoordinateObject::coordinateChanged, | 
| 1724 |             receiver: this, slot: &QDeclarativeGeoWaypoint::waypointDetailsChanged); | 
| 1725 | } | 
| 1726 |  | 
| 1727 | QDeclarativeGeoWaypoint::~QDeclarativeGeoWaypoint() | 
| 1728 | { | 
| 1729 |  | 
| 1730 | } | 
| 1731 |  | 
| 1732 | bool QDeclarativeGeoWaypoint::operator==(const QDeclarativeGeoWaypoint &other) const | 
| 1733 | { | 
| 1734 |     const QList<QDeclarativeGeoMapParameter *> params = quickChildren<QDeclarativeGeoMapParameter>(); | 
| 1735 |     const QList<QDeclarativeGeoMapParameter *> otherParams = other.quickChildren<QDeclarativeGeoMapParameter>(); | 
| 1736 |  | 
| 1737 |     return coordinate() == other.coordinate() && | 
| 1738 |            compareFloats(a: m_bearing, b: other.bearing()) && | 
| 1739 |            compareParameterList(a: params, b: otherParams); | 
| 1740 | } | 
| 1741 |  | 
| 1742 | /*! | 
| 1743 |     \qmlproperty coordinate Waypoint::coordinate | 
| 1744 |  | 
| 1745 |     The waypoint's coordinate. The default value is undefined. | 
| 1746 | */ | 
| 1747 |  | 
| 1748 |  | 
| 1749 | /*! | 
| 1750 |     \qmlproperty real Waypoint::latitude | 
| 1751 |  | 
| 1752 |     The latitude of the waypoint's coordinate. The default value is NaN. | 
| 1753 |     Changing this property will affect the \l Waypoint::coordinate property as well. | 
| 1754 | */ | 
| 1755 | qreal QDeclarativeGeoWaypoint::latitude() const | 
| 1756 | { | 
| 1757 |     return m_coordinate.latitude(); | 
| 1758 | } | 
| 1759 |  | 
| 1760 | void QDeclarativeGeoWaypoint::setLatitude(qreal latitude) | 
| 1761 | { | 
| 1762 |     if (compareFloats(a: latitude, b: m_coordinate.latitude())) | 
| 1763 |         return; | 
| 1764 |  | 
| 1765 |     m_coordinate.setLatitude(latitude); | 
| 1766 |     if (m_complete) { | 
| 1767 |         emit coordinateChanged(); | 
| 1768 |         emit waypointDetailsChanged(); | 
| 1769 |     } | 
| 1770 | } | 
| 1771 |  | 
| 1772 | /*! | 
| 1773 |     \qmlproperty real Waypoint::longitude | 
| 1774 |  | 
| 1775 |     The longitude of the waypoint's coordinate. The default value is NaN. | 
| 1776 |     Changing this property will affect the \l Waypoint::coordinate property as well. | 
| 1777 | */ | 
| 1778 | qreal QDeclarativeGeoWaypoint::longitude() const | 
| 1779 | { | 
| 1780 |     return m_coordinate.longitude(); | 
| 1781 | } | 
| 1782 |  | 
| 1783 | void QDeclarativeGeoWaypoint::setLongitude(qreal longitude) | 
| 1784 | { | 
| 1785 |     if (compareFloats(a: longitude, b: m_coordinate.longitude())) | 
| 1786 |         return; | 
| 1787 |  | 
| 1788 |     m_coordinate.setLongitude(longitude); | 
| 1789 |     if (m_complete) { | 
| 1790 |         emit coordinateChanged(); | 
| 1791 |         emit waypointDetailsChanged(); | 
| 1792 |     } | 
| 1793 | } | 
| 1794 |  | 
| 1795 | /*! | 
| 1796 |     \qmlproperty real Waypoint::altitude | 
| 1797 |  | 
| 1798 |     The altitude of the waypoint's coordinate. The default value is NaN. | 
| 1799 |     Changing this property will affect the \l Waypoint::coordinate property as well. | 
| 1800 | */ | 
| 1801 | qreal QDeclarativeGeoWaypoint::altitude() const | 
| 1802 | { | 
| 1803 |     return m_coordinate.altitude(); | 
| 1804 | } | 
| 1805 |  | 
| 1806 | void QDeclarativeGeoWaypoint::setAltitude(qreal altitude) | 
| 1807 | { | 
| 1808 |     if (compareFloats(a: altitude, b: m_coordinate.altitude())) | 
| 1809 |         return; | 
| 1810 |  | 
| 1811 |     m_coordinate.setAltitude(altitude); | 
| 1812 |     if (m_complete) { | 
| 1813 |         emit coordinateChanged(); | 
| 1814 |         emit waypointDetailsChanged(); | 
| 1815 |     } | 
| 1816 | } | 
| 1817 |  | 
| 1818 | bool QDeclarativeGeoWaypoint::isValid() const | 
| 1819 | { | 
| 1820 |     return m_coordinate.isValid(); | 
| 1821 | } | 
| 1822 |  | 
| 1823 | /*! | 
| 1824 |     \qmlproperty real Waypoint::bearing | 
| 1825 |  | 
| 1826 |     The bearing specifying the angle of approach of the waypoint, that is the bearing with which the waypoint is to be approached. | 
| 1827 |     This information may be used by the provider to filter the road segment the waypoint will be placed on, and, | 
| 1828 |     depending on the provider and the \l {QGeoRouteRequest::TravelMode} {travel mode} used, to restrict the maneuvers | 
| 1829 |     allowed at the waypoint, potentially making the provider calculating and returning a different route. | 
| 1830 |  | 
| 1831 |     If set to NaN, this value will not be considered. | 
| 1832 |  | 
| 1833 |     The default value is NaN. | 
| 1834 | */ | 
| 1835 | qreal QDeclarativeGeoWaypoint::bearing() const | 
| 1836 | { | 
| 1837 |     return m_bearing; | 
| 1838 | } | 
| 1839 |  | 
| 1840 | void QDeclarativeGeoWaypoint::setBearing(qreal bearing) | 
| 1841 | { | 
| 1842 |     if (compareFloats(a: bearing, b: m_bearing)) | 
| 1843 |         return; | 
| 1844 |  | 
| 1845 |     m_bearing = bearing; | 
| 1846 |  | 
| 1847 |     // Bearing is actually packed into QGeoRouteRequest::waypointMetadata() together with the extra parameters | 
| 1848 |     m_metadataChanged = true; | 
| 1849 |     if (m_complete) { | 
| 1850 |         emit bearingChanged(); | 
| 1851 |         emit waypointDetailsChanged(); | 
| 1852 |     } | 
| 1853 | } | 
| 1854 |  | 
| 1855 | /*! | 
| 1856 |     \qmlproperty VariantMap Waypoint::metadata | 
| 1857 |     \readonly | 
| 1858 |  | 
| 1859 |     The waypoint metadata. This property is read only. If the waypoint is | 
| 1860 |     defined by the user, these can be set by using MapParameters. | 
| 1861 |     If the waypoint comes from the engine via signals, or as part of a read-only route query, | 
| 1862 |     the waypoint is intended to be read-only. | 
| 1863 | */ | 
| 1864 | QVariantMap QDeclarativeGeoWaypoint::metadata() | 
| 1865 | { | 
| 1866 |     if (m_metadataChanged) { | 
| 1867 |         m_metadataChanged = false; | 
| 1868 |         m_metadata.clear(); | 
| 1869 |         // Update metadata | 
| 1870 |         const QList<QDeclarativeGeoMapParameter *> params = quickChildren<QDeclarativeGeoMapParameter>(); | 
| 1871 |         QVariantMap ; | 
| 1872 |         for (const QDeclarativeGeoMapParameter *p: params) | 
| 1873 |             extraParameters[p->type()] = p->toVariantMap(); | 
| 1874 |         m_metadata[QStringLiteral("extra" )] = extraParameters; | 
| 1875 |         m_metadata[QStringLiteral("bearing" )] = m_bearing; | 
| 1876 |     } | 
| 1877 |     return m_metadata; | 
| 1878 | } | 
| 1879 |  | 
| 1880 | // Used only by QDeclarativeGeoRouteRequest | 
| 1881 | void QDeclarativeGeoWaypoint::setMetadata(const QVariantMap &meta) | 
| 1882 | { | 
| 1883 |     m_metadata = meta; | 
| 1884 |     if (m_metadata.contains(QStringLiteral("bearing" )) && m_metadata.value(QStringLiteral("bearing" )).canConvert<double>()) | 
| 1885 |         m_bearing = m_metadata.value(QStringLiteral("bearing" )).toDouble(); | 
| 1886 |     m_metadataChanged = false; | 
| 1887 | } | 
| 1888 |  | 
| 1889 | void QDeclarativeGeoWaypoint::() | 
| 1890 | { | 
| 1891 |     m_metadataChanged = true; | 
| 1892 |     if (m_complete) { | 
| 1893 |         emit extraParametersChanged(); | 
| 1894 |         emit waypointDetailsChanged(); | 
| 1895 |     } | 
| 1896 | } | 
| 1897 |  | 
| 1898 | void QDeclarativeGeoWaypoint::append(QQmlListProperty<QObject> *p, QObject *v) | 
| 1899 | { | 
| 1900 |     QDeclarativeGeoWaypoint *waypoint = static_cast<QDeclarativeGeoWaypoint*>(p->object); | 
| 1901 |     waypoint->m_children.append(t: v); | 
| 1902 |  | 
| 1903 |     QDeclarativeGeoMapParameter *param = qobject_cast<QDeclarativeGeoMapParameter *>(object: v); | 
| 1904 |     if (param) { | 
| 1905 |         waypoint->connect(sender: param, signal: &QGeoMapParameter::propertyUpdated, | 
| 1906 |                        receiver: waypoint, slot: &QDeclarativeGeoWaypoint::extraParameterChanged); | 
| 1907 |         waypoint->extraParameterChanged(); | 
| 1908 |     } | 
| 1909 | } | 
| 1910 |  | 
| 1911 | int QDeclarativeGeoWaypoint::count(QQmlListProperty<QObject> *p) | 
| 1912 | { | 
| 1913 |     return static_cast<QDeclarativeGeoWaypoint*>(p->object)->m_children.count(); | 
| 1914 | } | 
| 1915 |  | 
| 1916 | QObject *QDeclarativeGeoWaypoint::at(QQmlListProperty<QObject> *p, int idx) | 
| 1917 | { | 
| 1918 |     return static_cast<QDeclarativeGeoWaypoint*>(p->object)->m_children.at(i: idx); | 
| 1919 | } | 
| 1920 |  | 
| 1921 | void QDeclarativeGeoWaypoint::clear(QQmlListProperty<QObject> *p) | 
| 1922 | { | 
| 1923 |     QDeclarativeGeoWaypoint *waypoint = static_cast<QDeclarativeGeoWaypoint*>(p->object); | 
| 1924 |     for (auto kid : qAsConst(t&: waypoint->m_children)) { | 
| 1925 |         auto val = qobject_cast<QDeclarativeGeoMapParameter *>(object: kid); | 
| 1926 |         if (val) { | 
| 1927 |             val->disconnect(receiver: waypoint); | 
| 1928 |             waypoint->m_metadataChanged = true; | 
| 1929 |         } | 
| 1930 |     } | 
| 1931 |     waypoint->m_children.clear(); | 
| 1932 |     if (waypoint->m_metadataChanged && waypoint->m_complete) { | 
| 1933 |         emit waypoint->extraParametersChanged(); | 
| 1934 |         emit waypoint->waypointDetailsChanged(); | 
| 1935 |     } | 
| 1936 | } | 
| 1937 |  | 
| 1938 | QQmlListProperty<QObject> QDeclarativeGeoWaypoint::declarativeChildren() | 
| 1939 | { | 
| 1940 |     return QQmlListProperty<QObject>(this, nullptr, | 
| 1941 |                                      &QDeclarativeGeoWaypoint::append, | 
| 1942 |                                      &QDeclarativeGeoWaypoint::count, | 
| 1943 |                                      &QDeclarativeGeoWaypoint::at, | 
| 1944 |                                      &QDeclarativeGeoWaypoint::clear); | 
| 1945 | } | 
| 1946 |  | 
| 1947 | QT_END_NAMESPACE | 
| 1948 |  |