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 "qdeclarativegeocodemodel_p.h"
38#include "error_messages_p.h"
39
40#include <QtCore/QCoreApplication>
41#include <QtQml/QQmlInfo>
42#include <QtPositioning/QGeoCircle>
43#include <QtLocation/QGeoServiceProvider>
44#include <QtLocation/QGeoCodingManager>
45#include <QtLocation/private/qgeocodereply_p.h>
46#include <QtPositioning/QGeoPolygon>
47
48QT_BEGIN_NAMESPACE
49
50/*!
51 \qmltype GeocodeModel
52 \instantiates QDeclarativeGeocodeModel
53 \inqmlmodule QtLocation
54 \ingroup qml-QtLocation5-geocoding
55 \since QtLocation 5.5
56
57 \brief The GeocodeModel type provides support for searching operations
58 related to geographic information.
59
60 The GeocodeModel type is used as part of a model/view grouping to
61 match addresses or search strings with geographic locations. How the
62 geographic locations generated are used or displayed is decided by any
63 Views attached to the GeocodeModel (for example a \l MapItemView or \l{ListView}).
64
65 Like \l Map and \l RouteModel, all the data for a GeocodeModel to work
66 comes from a services plugin. This is contained in the \l{plugin} property,
67 and this must be set before the GeocodeModel can do any useful work.
68
69 Once the plugin is set, the \l{query} property can be used to specify the
70 address or search string to match. If \l{autoUpdate} is enabled, the Model
71 will update its output automatically. Otherwise, the \l{update} method may
72 be used. By default, autoUpdate is disabled.
73
74 The data stored and returned in the GeocodeModel consists of \l [QML] {Location}
75 objects, as a list with the role name "locationData". See the documentation
76 for \l [QML] {Location} for further details on its structure and contents.
77
78 \section2 Example Usage
79
80 The following snippet is two-part, showing firstly the declaration of
81 objects, and secondly a short piece of procedural code using it. We set
82 the geocodeModel's \l{autoUpdate} property to false, and call \l{update} once
83 the query is set up. In this case, as we use a string value in \l{query},
84 only one update would occur, even with autoUpdate enabled. However, if we
85 provided an \l{Address} object we may inadvertently trigger multiple
86 requests whilst setting its properties.
87
88 \code
89 Plugin {
90 id: aPlugin
91 }
92
93 GeocodeModel {
94 id: geocodeModel
95 plugin: aPlugin
96 autoUpdate: false
97 }
98 \endcode
99
100 \code
101 {
102 geocodeModel.query = "53 Brandl St, Eight Mile Plains, Australia"
103 geocodeModel.update()
104 }
105 \endcode
106*/
107
108/*!
109 \qmlsignal QtLocation::GeocodeModel::locationsChanged()
110
111 This signal is emitted when locations in the model have changed.
112
113 \sa count
114*/
115
116
117QDeclarativeGeocodeModel::QDeclarativeGeocodeModel(QObject *parent)
118: QAbstractListModel(parent), autoUpdate_(false), complete_(false), reply_(0), plugin_(0),
119 status_(QDeclarativeGeocodeModel::Null), error_(QDeclarativeGeocodeModel::NoError),
120 address_(0), limit_(-1), offset_(0)
121{
122}
123
124QDeclarativeGeocodeModel::~QDeclarativeGeocodeModel()
125{
126 qDeleteAll(c: declarativeLocations_);
127 declarativeLocations_.clear();
128 delete reply_;
129}
130
131/*!
132 \internal
133 From QQmlParserStatus
134*/
135void QDeclarativeGeocodeModel::componentComplete()
136{
137 complete_ = true;
138 if (autoUpdate_)
139 update();
140}
141
142/*!
143 \qmlmethod void QtLocation::GeocodeModel::update()
144
145 Instructs the GeocodeModel to update its data. This is most useful
146 when \l autoUpdate is disabled, to force a refresh when the query
147 has been changed.
148*/
149void QDeclarativeGeocodeModel::update()
150{
151 if (!complete_)
152 return;
153
154 if (!plugin_) {
155 setError(error: EngineNotSetError, errorString: tr(s: "Cannot geocode, plugin not set."));
156 return;
157 }
158
159 QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider();
160 if (!serviceProvider)
161 return;
162
163 QGeoCodingManager *geocodingManager = serviceProvider->geocodingManager();
164 if (!geocodingManager) {
165 setError(error: EngineNotSetError, errorString: tr(s: "Cannot geocode, geocode manager not set."));
166 return;
167 }
168 if (!coordinate_.isValid() && (!address_ || address_->address().isEmpty()) &&
169 (searchString_.isEmpty())) {
170 setError(error: ParseError, errorString: tr(s: "Cannot geocode, valid query not set."));
171 return;
172 }
173 abortRequest(); // abort possible previous requests
174 setError(error: NoError, errorString: QString());
175
176 if (coordinate_.isValid()) {
177 setStatus(QDeclarativeGeocodeModel::Loading);
178 reply_ = geocodingManager->reverseGeocode(coordinate: coordinate_, bounds: boundingArea_);
179 if (reply_->isFinished()) {
180 if (reply_->error() == QGeoCodeReply::NoError) {
181 geocodeFinished(reply: reply_);
182 } else {
183 geocodeError(reply: reply_, error: reply_->error(), errorString: reply_->errorString());
184 }
185 }
186 } else if (address_) {
187 setStatus(QDeclarativeGeocodeModel::Loading);
188 reply_ = geocodingManager->geocode(address: address_->address(), bounds: boundingArea_);
189 if (reply_->isFinished()) {
190 if (reply_->error() == QGeoCodeReply::NoError) {
191 geocodeFinished(reply: reply_);
192 } else {
193 geocodeError(reply: reply_, error: reply_->error(), errorString: reply_->errorString());
194 }
195 }
196 } else if (!searchString_.isEmpty()) {
197 setStatus(QDeclarativeGeocodeModel::Loading);
198 reply_ = geocodingManager->geocode(searchString: searchString_, limit: limit_, offset: offset_, bounds: boundingArea_);
199 if (reply_->isFinished()) {
200 if (reply_->error() == QGeoCodeReply::NoError) {
201 geocodeFinished(reply: reply_);
202 } else {
203 geocodeError(reply: reply_, error: reply_->error(), errorString: reply_->errorString());
204 }
205 }
206 }
207}
208
209/*!
210 \internal
211*/
212void QDeclarativeGeocodeModel::abortRequest()
213{
214 if (reply_) {
215 reply_->abort();
216 reply_->deleteLater();
217 reply_ = 0;
218 }
219}
220
221/*!
222 \internal
223*/
224void QDeclarativeGeocodeModel::queryContentChanged()
225{
226 if (autoUpdate_)
227 update();
228}
229
230/*!
231 \internal
232 From QAbstractListModel
233*/
234int QDeclarativeGeocodeModel::rowCount(const QModelIndex &parent) const
235{
236 Q_UNUSED(parent);
237 return declarativeLocations_.count();
238}
239
240/*!
241 \internal
242*/
243QVariant QDeclarativeGeocodeModel::data(const QModelIndex &index, int role) const
244{
245 if (!index.isValid())
246 return QVariant();
247 if (index.row() >= declarativeLocations_.count())
248 return QVariant();
249 if (role == QDeclarativeGeocodeModel::LocationRole) {
250 QObject *locationObject = declarativeLocations_.at(i: index.row());
251 Q_ASSERT(locationObject);
252 return QVariant::fromValue(value: locationObject);
253 }
254 return QVariant();
255}
256
257QHash<int, QByteArray> QDeclarativeGeocodeModel::roleNames() const
258{
259 QHash<int, QByteArray> roleNames = QAbstractItemModel::roleNames();
260 roleNames.insert(akey: LocationRole, avalue: "locationData");
261 return roleNames;
262}
263
264/*!
265 \internal
266*/
267void QDeclarativeGeocodeModel::setPlugin(QDeclarativeGeoServiceProvider *plugin)
268{
269 if (plugin_ == plugin)
270 return;
271
272 reset(); // reset the model
273 plugin_ = plugin;
274 if (complete_)
275 emit pluginChanged();
276
277 if (!plugin)
278 return;
279
280 if (plugin_->isAttached()) {
281 pluginReady();
282 } else {
283 connect(sender: plugin_, SIGNAL(attached()),
284 receiver: this, SLOT(pluginReady()));
285 }
286}
287
288/*!
289 \internal
290*/
291void QDeclarativeGeocodeModel::pluginReady()
292{
293 QGeoServiceProvider *serviceProvider = plugin_->sharedGeoServiceProvider();
294 QGeoCodingManager *geocodingManager = serviceProvider->geocodingManager();
295
296 if (serviceProvider->geocodingError() != QGeoServiceProvider::NoError) {
297 QDeclarativeGeocodeModel::GeocodeError newError = UnknownError;
298 switch (serviceProvider->geocodingError()) {
299 case QGeoServiceProvider::NotSupportedError:
300 newError = EngineNotSetError; break;
301 case QGeoServiceProvider::UnknownParameterError:
302 newError = UnknownParameterError; break;
303 case QGeoServiceProvider::MissingRequiredParameterError:
304 newError = MissingRequiredParameterError; break;
305 case QGeoServiceProvider::ConnectionError:
306 newError = CommunicationError; break;
307 default:
308 break;
309 }
310
311 setError(error: newError, errorString: serviceProvider->geocodingErrorString());
312 return;
313 }
314
315 if (!geocodingManager) {
316 setError(error: EngineNotSetError,errorString: tr(s: "Plugin does not support (reverse) geocoding."));
317 return;
318 }
319
320 connect(sender: geocodingManager, SIGNAL(finished(QGeoCodeReply*)),
321 receiver: this, SLOT(geocodeFinished(QGeoCodeReply*)));
322 connect(sender: geocodingManager, SIGNAL(error(QGeoCodeReply*,QGeoCodeReply::Error,QString)),
323 receiver: this, SLOT(geocodeError(QGeoCodeReply*,QGeoCodeReply::Error,QString)));
324
325 if (complete_ && autoUpdate_)
326 update();
327}
328
329/*!
330 \qmlproperty Plugin QtLocation::GeocodeModel::plugin
331
332 This property holds the plugin that provides the actual geocoding service.
333 Note that all plugins do not necessarily provide geocoding (could for example provide
334 only routing or maps).
335
336 \sa Plugin
337*/
338
339QDeclarativeGeoServiceProvider *QDeclarativeGeocodeModel::plugin() const
340{
341 return plugin_;
342}
343
344void QDeclarativeGeocodeModel::setBounds(const QVariant &boundingArea)
345{
346 QGeoShape s;
347
348 if (boundingArea.userType() == qMetaTypeId<QGeoRectangle>())
349 s = boundingArea.value<QGeoRectangle>();
350 else if (boundingArea.userType() == qMetaTypeId<QGeoCircle>())
351 s = boundingArea.value<QGeoCircle>();
352 else if (boundingArea.userType() == qMetaTypeId<QGeoShape>())
353 s = boundingArea.value<QGeoShape>();
354
355
356 if (boundingArea_ == s)
357 return;
358
359 boundingArea_ = s;
360 emit boundsChanged();
361}
362
363/*!
364 \qmlproperty geoshape QtLocation::GeocodeModel::bounds
365
366 This property holds the bounding area used to limit the results to those
367 within the area. This is particularly useful if query is only partially filled out,
368 as the service will attempt to (reverse) geocode all matches for the specified data.
369
370 Accepted types are \l {georectangle} and
371 \l {geocircle}.
372*/
373QVariant QDeclarativeGeocodeModel::bounds() const
374{
375 if (boundingArea_.type() == QGeoShape::RectangleType)
376 return QVariant::fromValue(value: QGeoRectangle(boundingArea_));
377 else if (boundingArea_.type() == QGeoShape::CircleType)
378 return QVariant::fromValue(value: QGeoCircle(boundingArea_));
379 else if (boundingArea_.type() == QGeoShape::PolygonType)
380 return QVariant::fromValue(value: QGeoPolygon(boundingArea_));
381 else
382 return QVariant::fromValue(value: boundingArea_);
383}
384
385void QDeclarativeGeocodeModel::geocodeFinished(QGeoCodeReply *reply)
386{
387 if (reply != reply_ || reply->error() != QGeoCodeReply::NoError)
388 return;
389
390 reply->deleteLater();
391 reply_ = 0;
392 int oldCount = declarativeLocations_.count();
393 // const QVariantMap &extraData = QGeoCodeReplyPrivate::get(*reply)->extraData();
394 setLocations(reply->locations());
395 setError(error: NoError, errorString: QString());
396 setStatus(QDeclarativeGeocodeModel::Ready);
397 emit locationsChanged();
398 if (oldCount != declarativeLocations_.count())
399 emit countChanged();
400}
401
402/*!
403 \internal
404*/
405void QDeclarativeGeocodeModel::geocodeError(QGeoCodeReply *reply,
406 QGeoCodeReply::Error error,
407 const QString &errorString)
408{
409 if (reply != reply_)
410 return;
411
412 reply->deleteLater();
413 reply_ = 0;
414 int oldCount = declarativeLocations_.count();
415 if (oldCount > 0) {
416 // Reset the model
417 setLocations(reply->locations());
418 emit locationsChanged();
419 emit countChanged();
420 }
421 setError(error: static_cast<QDeclarativeGeocodeModel::GeocodeError>(error), errorString);
422 setStatus(QDeclarativeGeocodeModel::Error);
423}
424
425/*!
426 \qmlproperty enumeration QtLocation::GeocodeModel::status
427
428 This read-only property holds the current status of the model.
429
430 \list
431 \li GeocodeModel.Null - No geocode requests have been issued or \l reset has been called.
432 \li GeocodeModel.Ready - Geocode request(s) have finished successfully.
433 \li GeocodeModel.Loading - Geocode request has been issued but not yet finished
434 \li GeocodeModel.Error - Geocoding error has occurred, details are in \l error and \l errorString
435 \endlist
436*/
437
438QDeclarativeGeocodeModel::Status QDeclarativeGeocodeModel::status() const
439{
440 return status_;
441}
442
443void QDeclarativeGeocodeModel::setStatus(QDeclarativeGeocodeModel::Status status)
444{
445 if (status_ == status)
446 return;
447 status_ = status;
448 emit statusChanged();
449}
450
451/*!
452 \qmlproperty enumeration QtLocation::GeocodeModel::error
453
454 This read-only property holds the latest error value of the geocoding request.
455
456 \list
457 \li GeocodeModel.NoError - No error has occurred.
458 \li GeocodeModel.CombinationError - An error occurred while results where being combined from multiple sources.
459 \li GeocodeModel.CommunicationError - An error occurred while communicating with the service provider.
460 \li GeocodeModel.EngineNotSetError - The model's plugin property was not set or there is no geocoding manager associated with the plugin.
461 \li GeocodeModel.MissingRequiredParameterError - A required parameter was not specified.
462 \li GeocodeModel.ParseError - The response from the service provider was in an unrecognizable format.
463 \li GeocodeModel.UnknownError - An error occurred which does not fit into any of the other categories.
464 \li GeocodeModel.UnknownParameterError - The plugin did not recognize one of the parameters it was given.
465 \li GeocodeModel.UnsupportedOptionError - The requested operation is not supported by the geocoding provider.
466 This may happen when the loaded engine does not support a particular geocoding request
467 such as reverse geocoding.
468 \endlist
469*/
470
471QDeclarativeGeocodeModel::GeocodeError QDeclarativeGeocodeModel::error() const
472{
473 return error_;
474}
475
476void QDeclarativeGeocodeModel::setError(GeocodeError error, const QString &errorString)
477{
478 if (error_ == error && errorString_ == errorString)
479 return;
480 error_ = error;
481 errorString_ = errorString;
482 emit errorChanged();
483}
484
485/*!
486 \qmlproperty string QtLocation::GeocodeModel::errorString
487
488 This read-only property holds the textual presentation of the latest geocoding error.
489 If no error has occurred or the model has been reset, an empty string is returned.
490
491 An empty string may also be returned if an error occurred which has no associated
492 textual representation.
493*/
494
495QString QDeclarativeGeocodeModel::errorString() const
496{
497 return errorString_;
498}
499
500/*!
501 \internal
502*/
503void QDeclarativeGeocodeModel::setLocations(const QList<QGeoLocation> &locations)
504{
505 beginResetModel();
506 qDeleteAll(c: declarativeLocations_);
507 declarativeLocations_.clear();
508 for (int i = 0; i < locations.count(); ++i) {
509 QDeclarativeGeoLocation *location = new QDeclarativeGeoLocation(locations.at(i), this);
510 declarativeLocations_.append(t: location);
511 }
512 endResetModel();
513}
514
515/*!
516 \qmlproperty int QtLocation::GeocodeModel::count
517
518 This property holds how many locations the model currently has.
519 Amongst other uses, you can use this value when accessing locations
520 via the GeocodeModel::get -method.
521*/
522
523int QDeclarativeGeocodeModel::count() const
524{
525 return declarativeLocations_.count();
526}
527
528/*!
529 \qmlmethod Location QtLocation::GeocodeModel::get(int index)
530
531 Returns the \l [QML] {Location} at given \a index. Use \l count property to check the
532 amount of locations available. The locations are indexed from zero, so the accessible range
533 is 0...(count - 1).
534
535 If you access out of bounds, a zero (null object) is returned and a warning is issued.
536*/
537
538QDeclarativeGeoLocation *QDeclarativeGeocodeModel::get(int index)
539{
540 if (index < 0 || index >= declarativeLocations_.count()) {
541 qmlWarning(me: this) << QStringLiteral("Index '%1' out of range").arg(a: index);
542 return 0;
543 }
544 return declarativeLocations_.at(i: index);
545}
546
547/*!
548 \qmlproperty int QtLocation::GeocodeModel::limit
549
550 This property holds the maximum number of results. The limit and \l offset values are only
551 applicable with free string geocoding (that is they are not considered when using addresses
552 or coordinates in the search query).
553
554 If limit is -1 the entire result set will be returned, otherwise at most limit results will be
555 returned. The limit and \l offset results can be used together to implement paging.
556*/
557
558int QDeclarativeGeocodeModel::limit() const
559{
560 return limit_;
561}
562
563void QDeclarativeGeocodeModel::setLimit(int limit)
564{
565 if (limit == limit_)
566 return;
567 limit_ = limit;
568 if (autoUpdate_) {
569 update();
570 }
571 emit limitChanged();
572}
573
574/*!
575 \qmlproperty int QtLocation::GeocodeModel::offset
576
577 This property tells not to return the first 'offset' number of the results. The \l limit and
578 offset values are only applicable with free string geocoding (that is they are not considered
579 when using addresses or coordinates in the search query).
580
581 The \l limit and offset results can be used together to implement paging.
582*/
583
584int QDeclarativeGeocodeModel::offset() const
585{
586 return offset_;
587}
588
589void QDeclarativeGeocodeModel::setOffset(int offset)
590{
591 if (offset == offset_)
592 return;
593 offset_ = offset;
594 if (autoUpdate_) {
595 update();
596 }
597 emit offsetChanged();
598}
599
600/*!
601 \qmlmethod void QtLocation::GeocodeModel::reset()
602
603 Resets the model. All location data is cleared, any outstanding requests
604 are aborted and possible errors are cleared. Model status will be set
605 to GeocodeModel.Null
606*/
607
608void QDeclarativeGeocodeModel::reset()
609{
610 beginResetModel();
611 if (!declarativeLocations_.isEmpty()) {
612 setLocations(QList<QGeoLocation>());
613 emit countChanged();
614 }
615 endResetModel();
616
617 abortRequest();
618 setError(error: NoError, errorString: QString());
619 setStatus(QDeclarativeGeocodeModel::Null);
620}
621
622/*!
623 \qmlmethod void QtLocation::GeocodeModel::cancel()
624
625 Cancels any outstanding requests and clears errors. Model status will be set to either
626 GeocodeModel.Null or GeocodeModel.Ready.
627*/
628void QDeclarativeGeocodeModel::cancel()
629{
630 abortRequest();
631 setError(error: NoError, errorString: QString());
632 setStatus(declarativeLocations_.isEmpty() ? Null : Ready);
633}
634
635/*!
636 \qmlproperty QVariant QtLocation::GeocodeModel::query
637
638 This property holds the data of the geocoding request.
639 The property accepts three types of queries which determine both the data and
640 the type of action to be performed:
641
642 \list
643 \li Address - Geocoding (address to coordinate)
644 \li \l {coordinate} - Reverse geocoding (coordinate to address)
645 \li string - Geocoding (address to coordinate)
646 \endlist
647*/
648
649QVariant QDeclarativeGeocodeModel::query() const
650{
651 return queryVariant_;
652}
653
654void QDeclarativeGeocodeModel::setQuery(const QVariant &query)
655{
656 if (query == queryVariant_)
657 return;
658
659 if (query.userType() == qMetaTypeId<QGeoCoordinate>()) {
660 if (address_) {
661 address_->disconnect(receiver: this);
662 address_ = 0;
663 }
664 searchString_.clear();
665
666 coordinate_ = query.value<QGeoCoordinate>();
667 } else if (query.type() == QVariant::String) {
668 searchString_ = query.toString();
669 if (address_) {
670 address_->disconnect(receiver: this);
671 address_ = 0;
672 }
673 coordinate_ = QGeoCoordinate();
674 } else if (QObject *object = query.value<QObject *>()) {
675 if (QDeclarativeGeoAddress *address = qobject_cast<QDeclarativeGeoAddress *>(object)) {
676 if (address_)
677 address_->disconnect(receiver: this);
678 coordinate_ = QGeoCoordinate();
679 searchString_.clear();
680
681 address_ = address;
682 connect(sender: address_, SIGNAL(countryChanged()), receiver: this, SLOT(queryContentChanged()));
683 connect(sender: address_, SIGNAL(countryCodeChanged()), receiver: this, SLOT(queryContentChanged()));
684 connect(sender: address_, SIGNAL(stateChanged()), receiver: this, SLOT(queryContentChanged()));
685 connect(sender: address_, SIGNAL(countyChanged()), receiver: this, SLOT(queryContentChanged()));
686 connect(sender: address_, SIGNAL(cityChanged()), receiver: this, SLOT(queryContentChanged()));
687 connect(sender: address_, SIGNAL(districtChanged()), receiver: this, SLOT(queryContentChanged()));
688 connect(sender: address_, SIGNAL(streetChanged()), receiver: this, SLOT(queryContentChanged()));
689 connect(sender: address_, SIGNAL(postalCodeChanged()), receiver: this, SLOT(queryContentChanged()));
690 } else {
691 qmlWarning(me: this) << QStringLiteral("Unsupported query type for geocode model ")
692 << QStringLiteral("(coordinate, string and Address supported).");
693 return;
694 }
695 } else {
696 qmlWarning(me: this) << QStringLiteral("Unsupported query type for geocode model ")
697 << QStringLiteral("(coordinate, string and Address supported).");
698 return;
699 }
700
701 queryVariant_ = query;
702 emit queryChanged();
703 if (autoUpdate_)
704 update();
705}
706
707/*!
708 \qmlproperty bool QtLocation::GeocodeModel::autoUpdate
709
710 This property controls whether the Model automatically updates in response
711 to changes in its attached query. The default value of this property
712 is false.
713
714 If setting this value to 'true' and using an Address or
715 \l {coordinate} as the query, note that any change at all in the
716 object's properties will trigger a new request to be sent. If you are adjusting many
717 properties of the object whilst autoUpdate is enabled, this can generate large numbers of
718 useless (and later discarded) requests.
719*/
720
721bool QDeclarativeGeocodeModel::autoUpdate() const
722{
723 return autoUpdate_;
724}
725
726void QDeclarativeGeocodeModel::setAutoUpdate(bool update)
727{
728 if (autoUpdate_ == update)
729 return;
730 autoUpdate_ = update;
731 emit autoUpdateChanged();
732}
733
734QT_END_NAMESPACE
735

source code of qtlocation/src/location/declarativemaps/qdeclarativegeocodemodel.cpp