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 "qplacemanager.h"
38 #include "qplacemanagerengine.h"
39 #include "qplacemanagerengine_p.h"
40 
41 #include <QtCore/QDebug>
42 
43 QT_BEGIN_NAMESPACE
44 
45 /*!
46     \class QPlaceManager
47     \inmodule QtLocation
48     \ingroup QtLocation-places
49     \ingroup QtLocation-places-manager
50     \since 5.6
51 
52     \brief The QPlaceManager class provides the interface which allows clients to access
53     places stored in a particular backend.
54 
55     The following table gives an overview of the functionality provided by the QPlaceManager
56     \table
57         \header
58             \li Functionality
59             \li Description
60         \row
61             \li Searching for places
62             \li Using set of parameters such as a search term and search area, relevant places
63                can be returned to the user.
64         \row
65             \li Categories
66             \li Places can be classified as belonging to different categories.  The
67                manager supports access to these categories.
68         \row
69             \li Search term suggestions
70             \li Given a partially complete search term, a list of potential
71                search terms can be given.
72         \row
73             \li Recommendations
74             \li Given an existing place, a set of similar recommended places can
75                be suggested to the user.
76         \row
77             \li Rich Content
78             \li Rich content such as images, reviews etc can be retrieved in a paged
79                fashion.
80         \row
81             \li Place or Category management
82             \li Places and categories may be saved and removed.  It is possible
83                for notifications to be given when this happens.
84         \row
85             \li Localization
86             \li Different locales may be specified to return place
87                data in different languages.
88     \endtable
89 
90     \section1 Obtaining a QPlaceManager Instance
91     Creation of a QPlaceManager is facilitated by the QGeoServiceProvider.
92     See \l {Initializing a manager} for an example on how to create a manager.
93 
94 
95     \section1 Asynchronous Interface
96     The QPlaceManager class provides an abstraction of the datastore which contains place information.
97     The functions provided by the QPlaceManager and primarily asynchronous and follow
98     a request-reply model.   Typically a request is given to the manager, consisting
99     of a various set of parameters and a reply object is created.  The reply object
100     has a signal to notify when the request is done, and once completed, the reply
101     contains the results of the request, along with any errors that occurred, if any.
102 
103     An asynchronous request is generally handled as follows:
104     \snippet places/requesthandler.h Simple search
105     \dots
106     \dots
107     \snippet places/requesthandler.h Simple search handler
108 
109     See \l {Common Operations} for a list of examples demonstrating how the QPlaceManger
110     is used.
111 
112     \section1 Category Initialization
113     Sometime during startup of an application, the initializeCategories() function should
114     be called to setup the categories.  Initializing the categories enables the usage of the
115     following functions:
116 
117     \list
118         \li QPlaceManager::childCategories()
119         \li QPlaceManager::category()
120         \li QPlaceManager::parentCategoryId()
121         \li QPlaceManager::childCategoryIds();
122     \endlist
123 
124     If the categories need to be refreshed or reloaded, the initializeCategories() function
125     may be called again.
126 
127 */
128 
129 /*!
130     Constructs a new manager with the specified \a parent and with the
131     implementation provided by \a engine.
132 
133     This constructor is used internally by QGeoServiceProviderFactory. Regular
134     users should acquire instances of QGeoRoutingManager with
135     QGeoServiceProvider::routingManager();
136 */
QPlaceManager(QPlaceManagerEngine * engine,QObject * parent)137 QPlaceManager::QPlaceManager(QPlaceManagerEngine *engine, QObject *parent)
138     : QObject(parent), d(engine)
139 {
140     if (d) {
141         d->setParent(this);
142         d->d_ptr->manager = this;
143 
144         qRegisterMetaType<QPlaceCategory>();
145 
146         connect(d, SIGNAL(finished(QPlaceReply*)), this, SIGNAL(finished(QPlaceReply*)));
147         connect(d, SIGNAL(error(QPlaceReply*,QPlaceReply::Error)),
148                 this, SIGNAL(error(QPlaceReply*,QPlaceReply::Error)));
149 
150         connect(d, SIGNAL(placeAdded(QString)),
151                 this, SIGNAL(placeAdded(QString)), Qt::QueuedConnection);
152         connect(d, SIGNAL(placeUpdated(QString)),
153                 this, SIGNAL(placeUpdated(QString)), Qt::QueuedConnection);
154         connect(d, SIGNAL(placeRemoved(QString)),
155                 this, SIGNAL(placeRemoved(QString)), Qt::QueuedConnection);
156 
157         connect(d, SIGNAL(categoryAdded(QPlaceCategory,QString)),
158                 this, SIGNAL(categoryAdded(QPlaceCategory,QString)));
159         connect(d, SIGNAL(categoryUpdated(QPlaceCategory,QString)),
160                 this, SIGNAL(categoryUpdated(QPlaceCategory,QString)));
161         connect(d, SIGNAL(categoryRemoved(QString,QString)),
162                 this, SIGNAL(categoryRemoved(QString,QString)));
163         connect(d, SIGNAL(dataChanged()),
164                 this, SIGNAL(dataChanged()), Qt::QueuedConnection);
165     } else {
166         qFatal("The place manager engine that was set for this place manager was NULL.");
167     }
168 }
169 
170 /*!
171     Destroys the manager.  This destructor is used internally by QGeoServiceProvider
172     and should never need to be called in application code.
173 */
~QPlaceManager()174 QPlaceManager::~QPlaceManager()
175 {
176     delete d;
177 }
178 
179 /*!
180     Returns the name of the manager
181 */
managerName() const182 QString QPlaceManager::managerName() const
183 {
184     return d->managerName();
185 }
186 
187 /*!
188     Returns the manager version.
189 */
managerVersion() const190 int QPlaceManager::managerVersion() const
191 {
192     return d->managerVersion();
193 }
194 
195 /*!
196     Retrieves a details of place corresponding to the given \a placeId.
197 
198     See \l {QML Places API#Fetching Place Details}{Fetching Place Details} for an example of usage.
199 */
getPlaceDetails(const QString & placeId) const200 QPlaceDetailsReply *QPlaceManager::getPlaceDetails(const QString &placeId) const
201 {
202     return d->getPlaceDetails(placeId);
203 }
204 
205 /*!
206     Retrieves content for a place according to the parameters specified in \a request.
207 
208     See \l {Fetching Rich Content} for an example of usage.
209 */
getPlaceContent(const QPlaceContentRequest & request) const210 QPlaceContentReply *QPlaceManager::getPlaceContent(const QPlaceContentRequest &request) const
211 {
212     return d->getPlaceContent(request);
213 }
214 
215 /*!
216     Searches for places according to the parameters specified in \a request.
217 
218     See \l {Discovery/Search} for an example of usage.
219 */
search(const QPlaceSearchRequest & request) const220 QPlaceSearchReply *QPlaceManager::search(const QPlaceSearchRequest &request) const
221 {
222     return d->search(request);
223 }
224 
225 /*!
226     Requests a set of search term suggestions  according to the parameters specified in \a request.
227     The \a request can hold the incomplete search term, along with other data such
228     as a search area to narrow down relevant results.
229 
230     See \l {Search Suggestions} for an example of usage.
231 */
searchSuggestions(const QPlaceSearchRequest & request) const232 QPlaceSearchSuggestionReply *QPlaceManager::searchSuggestions(const QPlaceSearchRequest &request) const
233 {
234     return d->searchSuggestions(request);
235 }
236 
237 /*!
238     Saves a specified \a place.
239 
240     See \l {Saving a place cpp} for an example of usage.
241 */
savePlace(const QPlace & place)242 QPlaceIdReply *QPlaceManager::savePlace(const QPlace &place)
243 {
244     return d->savePlace(place);
245 }
246 
247 /*!
248     Removes the place corresponding to \a placeId from the manager.
249 
250     See \l {Removing a place cpp} for an example of usage.
251 */
removePlace(const QString & placeId)252 QPlaceIdReply *QPlaceManager::removePlace(const QString &placeId)
253 {
254     return d->removePlace(placeId);
255 }
256 
257 /*!
258     Saves a \a category that is a child of the category specified by \a parentId.
259     An empty \a parentId means \a category is saved as a top level category.
260 
261     See \l {Saving a category} for an example of usage.
262 */
saveCategory(const QPlaceCategory & category,const QString & parentId)263 QPlaceIdReply *QPlaceManager::saveCategory(const QPlaceCategory &category, const QString &parentId)
264 {
265     return d->saveCategory(category, parentId);
266 }
267 
268 /*!
269     Removes the category corresponding to \a categoryId from the manager.
270 
271     See \l {Removing a category} for an example of usage.
272 */
removeCategory(const QString & categoryId)273 QPlaceIdReply *QPlaceManager::removeCategory(const QString &categoryId)
274 {
275     return d->removeCategory(categoryId);
276 }
277 
278 /*!
279     Initializes the categories of the manager.
280 
281     See \l {Using Categories} for an example of usage.
282 */
initializeCategories()283 QPlaceReply *QPlaceManager::initializeCategories()
284 {
285     return d->initializeCategories();
286 }
287 
288 /*!
289     Returns the parent category identifier of the category corresponding to \a categoryId.
290 */
parentCategoryId(const QString & categoryId) const291 QString QPlaceManager::parentCategoryId(const QString &categoryId) const
292 {
293     return d->parentCategoryId(categoryId);
294 }
295 
296 /*!
297     Returns the child category identifiers of the category corresponding to \a parentId.
298     If \a parentId is empty then all top level category identifiers are returned.
299 */
childCategoryIds(const QString & parentId) const300 QStringList QPlaceManager::childCategoryIds(const QString &parentId) const
301 {
302     return d->childCategoryIds(parentId);
303 }
304 
305 /*!
306     Returns the category corresponding to the given \a categoryId.
307 */
category(const QString & categoryId) const308 QPlaceCategory QPlaceManager::category(const QString &categoryId) const
309 {
310     return d->category(categoryId);
311 }
312 
313 /*!
314     Returns a list of categories that are children of the category corresponding to \a parentId.
315     If \a parentId is empty, all the top level categories are returned.
316 */
childCategories(const QString & parentId) const317 QList<QPlaceCategory> QPlaceManager::childCategories(const QString &parentId) const
318 {
319     return d->childCategories(parentId);
320 }
321 
322 /*!
323     Returns a list of preferred locales. The locales are used as a hint to the manager for what language
324     place and category details should be returned in.
325 
326     If the first specified locale cannot be accommodated, the manager falls back to the next and so forth.
327     Some manager backends may not support a set of locales which are rigidly defined.  An arbitrary
328     example is that some places in France could have French and English localizations, while
329     certain areas in America may only have the English localization available.  In this example,
330     the set of supported locales is context dependent on the search location.
331 
332     If the manager cannot accommodate any of the preferred locales, the manager falls
333     back to using a supported language that is backend specific.
334 
335     Support for locales may vary from provider to provider.  For those that do support it,
336     by default, the global default locale is set as the manager's only locale.
337 
338     For managers that do not support locales, the locale list is always empty.
339 */
locales() const340 QList<QLocale> QPlaceManager::locales() const
341 {
342     return d->locales();
343 }
344 
345 /*!
346     Convenience function which sets the manager's list of preferred locales
347     to a single \a locale.
348 */
setLocale(const QLocale & locale)349 void QPlaceManager::setLocale(const QLocale &locale)
350 {
351     QList<QLocale> locales;
352     locales << locale;
353     d->setLocales(locales);
354 }
355 
356 /*!
357     Set the list of preferred \a locales.
358 */
setLocales(const QList<QLocale> & locales)359 void QPlaceManager::setLocales(const QList<QLocale> &locales)
360 {
361     d->setLocales(locales);
362 }
363 
364 /*!
365     Returns a pruned or modified version of the \a original place
366     which is suitable to be saved into this manager.
367 
368     Only place details that are supported by this manager is
369     present in the modified version.  Manager specific data such
370     as the place id, is not copied over from the \a original.
371 */
compatiblePlace(const QPlace & original)372 QPlace QPlaceManager::compatiblePlace(const QPlace &original)
373 {
374     return d->compatiblePlace(original);
375 }
376 
377 /*!
378     Returns a reply which contains a list of places which correspond/match those
379     specified in the \a request.  The places specified in the request come from a
380     different manager.
381 */
matchingPlaces(const QPlaceMatchRequest & request) const382 QPlaceMatchReply *QPlaceManager::matchingPlaces(const QPlaceMatchRequest &request) const
383 {
384     return d->matchingPlaces(request);
385 }
386 
387 /*!
388     \fn void QPlaceManager::finished(QPlaceReply *reply)
389 
390     This signal is emitted when \a reply has finished processing.
391 
392     If reply->error() equals QPlaceReply::NoError then the processing
393     finished successfully.
394 
395     This signal and QPlaceReply::finished() will be emitted at the same time.
396 
397     \note Do not delete the \a reply object in the slot connected to this signal.
398     Use deleteLater() instead.
399 */
400 
401 /*!
402     \fn void QPlaceManager::error(QPlaceReply *reply, QPlaceReply::Error error, const QString &errorString)
403 
404     This signal is emitted when an error has been detected in the processing of
405     \a reply.  The QPlaceManager::finished() signal will probably follow.
406 
407     The error will be described by the error code \a error.  If \a errorString is
408     not empty it will contain a textual description of the error meant for developers
409     and not end users.
410 
411     This signal and QPlaceReply::error() will be emitted at the same time.
412 
413     \note Do not delete the \a reply object in the slot connected to this signal.
414     Use deleteLater() instead.
415 */
416 
417 /*!
418     \fn void QPlaceManager::placeAdded(const QString &placeId)
419 
420     This signal is emitted if a place has been added to the manager engine's datastore.
421     The particular added place is specified by \a placeId.
422 
423     This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature.
424     \sa dataChanged()
425 */
426 
427 /*!
428     \fn void QPlaceManager::placeUpdated(const QString &placeId)
429 
430     This signal is emitted if a place has been modified in the manager's datastore.
431     The particular modified place is specified by \a placeId.
432 
433     This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature.
434     \sa dataChanged()
435 */
436 
437 /*!
438     \fn void QPlaceManager::placeRemoved(const QString &placeId)
439 
440     This signal is emitted if a place has been removed from the manager's datastore.
441     The particular place that has been removed is specified by \a placeId.
442 
443     This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature.
444     \sa dataChanged()
445 */
446 
447 /*!
448     \fn void QPlaceManager::categoryAdded(const QPlaceCategory &category, const QString &parentId)
449 
450     This signal is emitted if a \a category has been added to the manager's datastore.
451     The parent of the \a category is specified by \a parentId.
452 
453     This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature.
454     \sa dataChanged()
455 */
456 
457 /*!
458     \fn void QPlaceManager::categoryUpdated(const QPlaceCategory &category, const QString &parentId)
459 
460     This signal is emitted if a \a category has been modified in the manager's datastore.
461     The parent of the modified category is specified by \a parentId.
462 
463     This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature.
464     \sa dataChanged()
465 */
466 
467 /*!
468     \fn void QPlaceManager::categoryRemoved(const QString &categoryId, const QString &parentId)
469 
470     This signal is emitted when the category corresponding to \a categoryId has
471     been removed from the manager's datastore.  The parent of the removed category
472     is specified by \a parentId.
473 
474     This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature.
475     \sa dataChanged()
476 */
477 
478 /*!
479     \fn QPlaceManager::dataChanged()
480     This signal is emitted by the manager if there are large scale changes to its
481     underlying datastore and the manager considers these changes radical enough
482     to require clients to reload all data.
483 
484     If the signal is emitted, no other signals will be emitted for the associated changes.
485 
486     This signal is only emitted by managers that support the QPlaceManager::NotificationsFeature.
487 */
488 
489 QT_END_NAMESPACE
490