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 
48 QT_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 
QDeclarativeGeocodeModel(QObject * parent)117 QDeclarativeGeocodeModel::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 
~QDeclarativeGeocodeModel()124 QDeclarativeGeocodeModel::~QDeclarativeGeocodeModel()
125 {
126     qDeleteAll(declarativeLocations_);
127     declarativeLocations_.clear();
128     delete reply_;
129 }
130 
131 /*!
132     \internal
133     From QQmlParserStatus
134 */
componentComplete()135 void 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 */
update()149 void QDeclarativeGeocodeModel::update()
150 {
151     if (!complete_)
152         return;
153 
154     if (!plugin_) {
155         setError(EngineNotSetError, tr("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(EngineNotSetError, tr("Cannot geocode, geocode manager not set."));
166         return;
167     }
168     if (!coordinate_.isValid() && (!address_ || address_->address().isEmpty()) &&
169         (searchString_.isEmpty())) {
170         setError(ParseError, tr("Cannot geocode, valid query not set."));
171         return;
172     }
173     abortRequest(); // abort possible previous requests
174     setError(NoError, QString());
175 
176     if (coordinate_.isValid()) {
177         setStatus(QDeclarativeGeocodeModel::Loading);
178         reply_ = geocodingManager->reverseGeocode(coordinate_, boundingArea_);
179         if (reply_->isFinished()) {
180             if (reply_->error() == QGeoCodeReply::NoError) {
181                 geocodeFinished(reply_);
182             } else {
183                 geocodeError(reply_, reply_->error(), reply_->errorString());
184             }
185         }
186     } else if (address_) {
187         setStatus(QDeclarativeGeocodeModel::Loading);
188         reply_ = geocodingManager->geocode(address_->address(), boundingArea_);
189         if (reply_->isFinished()) {
190             if (reply_->error() == QGeoCodeReply::NoError) {
191                 geocodeFinished(reply_);
192             } else {
193                 geocodeError(reply_, reply_->error(), reply_->errorString());
194             }
195         }
196     } else if (!searchString_.isEmpty()) {
197         setStatus(QDeclarativeGeocodeModel::Loading);
198         reply_ = geocodingManager->geocode(searchString_, limit_, offset_, boundingArea_);
199         if (reply_->isFinished()) {
200             if (reply_->error() == QGeoCodeReply::NoError) {
201                 geocodeFinished(reply_);
202             } else {
203                 geocodeError(reply_, reply_->error(), reply_->errorString());
204             }
205         }
206     }
207 }
208 
209 /*!
210     \internal
211 */
abortRequest()212 void QDeclarativeGeocodeModel::abortRequest()
213 {
214     if (reply_) {
215         reply_->abort();
216         reply_->deleteLater();
217         reply_ = 0;
218     }
219 }
220 
221 /*!
222     \internal
223 */
queryContentChanged()224 void QDeclarativeGeocodeModel::queryContentChanged()
225 {
226     if (autoUpdate_)
227         update();
228 }
229 
230 /*!
231     \internal
232     From QAbstractListModel
233 */
rowCount(const QModelIndex & parent) const234 int QDeclarativeGeocodeModel::rowCount(const QModelIndex &parent) const
235 {
236     Q_UNUSED(parent);
237     return declarativeLocations_.count();
238 }
239 
240 /*!
241     \internal
242 */
data(const QModelIndex & index,int role) const243 QVariant 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(index.row());
251         Q_ASSERT(locationObject);
252         return QVariant::fromValue(locationObject);
253     }
254     return QVariant();
255 }
256 
roleNames() const257 QHash<int, QByteArray> QDeclarativeGeocodeModel::roleNames() const
258 {
259     QHash<int, QByteArray> roleNames = QAbstractItemModel::roleNames();
260     roleNames.insert(LocationRole, "locationData");
261     return roleNames;
262 }
263 
264 /*!
265     \internal
266 */
setPlugin(QDeclarativeGeoServiceProvider * plugin)267 void 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(plugin_, SIGNAL(attached()),
284                 this, SLOT(pluginReady()));
285     }
286 }
287 
288 /*!
289     \internal
290 */
pluginReady()291 void 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(newError, serviceProvider->geocodingErrorString());
312         return;
313     }
314 
315     if (!geocodingManager) {
316         setError(EngineNotSetError,tr("Plugin does not support (reverse) geocoding."));
317         return;
318     }
319 
320     connect(geocodingManager, SIGNAL(finished(QGeoCodeReply*)),
321             this, SLOT(geocodeFinished(QGeoCodeReply*)));
322     connect(geocodingManager, SIGNAL(error(QGeoCodeReply*,QGeoCodeReply::Error,QString)),
323             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 
plugin() const339 QDeclarativeGeoServiceProvider *QDeclarativeGeocodeModel::plugin() const
340 {
341     return plugin_;
342 }
343 
setBounds(const QVariant & boundingArea)344 void 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 */
bounds() const373 QVariant QDeclarativeGeocodeModel::bounds() const
374 {
375     if (boundingArea_.type() == QGeoShape::RectangleType)
376         return QVariant::fromValue(QGeoRectangle(boundingArea_));
377     else if (boundingArea_.type() == QGeoShape::CircleType)
378         return QVariant::fromValue(QGeoCircle(boundingArea_));
379     else if (boundingArea_.type() == QGeoShape::PolygonType)
380         return QVariant::fromValue(QGeoPolygon(boundingArea_));
381     else
382         return QVariant::fromValue(boundingArea_);
383 }
384 
geocodeFinished(QGeoCodeReply * reply)385 void 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(NoError, QString());
396     setStatus(QDeclarativeGeocodeModel::Ready);
397     emit locationsChanged();
398     if (oldCount != declarativeLocations_.count())
399         emit countChanged();
400 }
401 
402 /*!
403     \internal
404 */
geocodeError(QGeoCodeReply * reply,QGeoCodeReply::Error error,const QString & errorString)405 void 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(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 
status() const438 QDeclarativeGeocodeModel::Status QDeclarativeGeocodeModel::status() const
439 {
440     return status_;
441 }
442 
setStatus(QDeclarativeGeocodeModel::Status status)443 void 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 
error() const471 QDeclarativeGeocodeModel::GeocodeError QDeclarativeGeocodeModel::error() const
472 {
473     return error_;
474 }
475 
setError(GeocodeError error,const QString & errorString)476 void 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 
errorString() const495 QString QDeclarativeGeocodeModel::errorString() const
496 {
497     return errorString_;
498 }
499 
500 /*!
501     \internal
502 */
setLocations(const QList<QGeoLocation> & locations)503 void QDeclarativeGeocodeModel::setLocations(const QList<QGeoLocation> &locations)
504 {
505     beginResetModel();
506     qDeleteAll(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(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 
count() const523 int 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 
get(int index)538 QDeclarativeGeoLocation *QDeclarativeGeocodeModel::get(int index)
539 {
540     if (index < 0 || index >= declarativeLocations_.count()) {
541         qmlWarning(this) << QStringLiteral("Index '%1' out of range").arg(index);
542         return 0;
543     }
544     return declarativeLocations_.at(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 
limit() const558 int QDeclarativeGeocodeModel::limit() const
559 {
560     return limit_;
561 }
562 
setLimit(int limit)563 void 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 
offset() const584 int QDeclarativeGeocodeModel::offset() const
585 {
586     return offset_;
587 }
588 
setOffset(int offset)589 void 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 
reset()608 void QDeclarativeGeocodeModel::reset()
609 {
610     beginResetModel();
611     if (!declarativeLocations_.isEmpty()) {
612         setLocations(QList<QGeoLocation>());
613         emit countChanged();
614     }
615     endResetModel();
616 
617     abortRequest();
618     setError(NoError, 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 */
cancel()628 void QDeclarativeGeocodeModel::cancel()
629 {
630     abortRequest();
631     setError(NoError, 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 
query() const649 QVariant QDeclarativeGeocodeModel::query() const
650 {
651     return queryVariant_;
652 }
653 
setQuery(const QVariant & query)654 void 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(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(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(this);
678             coordinate_ = QGeoCoordinate();
679             searchString_.clear();
680 
681             address_ = address;
682             connect(address_, SIGNAL(countryChanged()), this, SLOT(queryContentChanged()));
683             connect(address_, SIGNAL(countryCodeChanged()), this, SLOT(queryContentChanged()));
684             connect(address_, SIGNAL(stateChanged()), this, SLOT(queryContentChanged()));
685             connect(address_, SIGNAL(countyChanged()), this, SLOT(queryContentChanged()));
686             connect(address_, SIGNAL(cityChanged()), this, SLOT(queryContentChanged()));
687             connect(address_, SIGNAL(districtChanged()), this, SLOT(queryContentChanged()));
688             connect(address_, SIGNAL(streetChanged()), this, SLOT(queryContentChanged()));
689             connect(address_, SIGNAL(postalCodeChanged()), this, SLOT(queryContentChanged()));
690         } else {
691             qmlWarning(this) << QStringLiteral("Unsupported query type for geocode model ")
692                           << QStringLiteral("(coordinate, string and Address supported).");
693             return;
694         }
695     } else {
696         qmlWarning(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 
autoUpdate() const721 bool QDeclarativeGeocodeModel::autoUpdate() const
722 {
723     return autoUpdate_;
724 }
725 
setAutoUpdate(bool update)726 void QDeclarativeGeocodeModel::setAutoUpdate(bool update)
727 {
728     if (autoUpdate_ == update)
729         return;
730     autoUpdate_ = update;
731     emit autoUpdateChanged();
732 }
733 
734 QT_END_NAMESPACE
735