1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtLocation module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:BSD$
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 https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** BSD License Usage
18** Alternatively, you may use this file under the terms of the BSD license
19** as follows:
20**
21** "Redistribution and use in source and binary forms, with or without
22** modification, are permitted provided that the following conditions are
23** met:
24** * Redistributions of source code must retain the above copyright
25** notice, this list of conditions and the following disclaimer.
26** * Redistributions in binary form must reproduce the above copyright
27** notice, this list of conditions and the following disclaimer in
28** the documentation and/or other materials provided with the
29** distribution.
30** * Neither the name of The Qt Company Ltd nor the names of its
31** contributors may be used to endorse or promote products derived
32** from this software without specific prior written permission.
33**
34**
35** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
39** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
42** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
45** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
46**
47** $QT_END_LICENSE$
48**
49****************************************************************************/
50
51#include <QDebug>
52#include <QGeoCircle>
53#include <QGeoServiceProvider>
54#include <QPlaceDetailsReply>
55#include <QPlaceIdReply>
56#include <QPlaceManager>
57#include <QPlaceSearchReply>
58#include <QPlaceResult>
59#include <QPlaceImage>
60#include <QtCore/QMetaObject>
61
62class RequestHandler : public QObject
63{
64public:
65 void initializeManager() {
66 //! [Initialize Manager]
67 //The "provider name" is used to select a particular provider
68 QGeoServiceProvider *provider = new QGeoServiceProvider("provider name");
69 QPlaceManager *manager = provider->placeManager();
70 //! [Initialize Manager]
71 Q_UNUSED(provider);
72 Q_UNUSED(manager);
73 }
74
75 void simpleSearch()
76 {
77 //! [Simple search]
78 //1) Make an appropriate request
79 QPlaceSearchRequest searchRequest;
80 searchRequest.setSearchTerm("ice cream");
81 searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(12.34, 56.78)));
82
83 //2) Use the manager to initiate a request and retrieve a reply object
84 QPlaceSearchReply * searchReply = manager->search(query: searchRequest);
85
86 //3) Connect the reply object to a slot which is invoked upon operation completion
87 connect(sender: searchReply, SIGNAL(finished()), receiver: this, SLOT(processSearchReply()));
88 //! [Simple search]
89 }
90
91 void search()
92 {
93 //! [Search for places cpp]
94
95 //instantiate request and set parameters
96 QPlaceSearchRequest searchRequest;
97 searchRequest.setSearchTerm("ice cream");
98 searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(12.34, 56.78)));
99
100 //send off a search request
101 /*QPlaceSearchReply * */ searchReply = manager->search(query: searchRequest);
102
103 //connect a slot to handle the reply
104 connect(sender: searchReply, SIGNAL(finished()), receiver: this, SLOT(handleSearchReply()));
105
106 //! [Search for places cpp]
107 }
108
109 void searchPaging()
110 {
111 //! [Search paging]
112 QPlaceSearchRequest searchRequest;
113 searchRequest.setLimit(15); //specify how many results are to be retrieved.
114 //! [Search paging]
115 }
116
117 void details()
118 {
119 QPlace place;
120 //! [Details check]
121 if (!place.detailsFetched()) {
122 /*QPlaceDetailsReply * */ detailsReply = manager->getPlaceDetails(placeId: place.placeId());
123 connect(sender: detailsReply, SIGNAL(finished()), receiver: this, SLOT(handleDetailsReply()));
124 }
125 //! [Details check]
126 }
127
128 void images()
129 {
130 QPlace place;
131
132 //! [Image request]
133 QPlaceContentRequest request;
134 request.setContentType(QPlaceContent::ImageType);
135 request.setPlaceId(place.placeId());
136 request.setLimit(5);
137 /*QPlaceContentReply * */ contentReply = manager->getPlaceContent(request);
138 connect(sender: contentReply, SIGNAL(finished()), receiver: this, SLOT(handleImagesReply()));
139 //! [Image request]
140 }
141
142
143 void suggestion()
144 {
145 //! [Suggestion request]
146 QPlaceSearchRequest request;
147 request.setSearchTerm("piz");
148 request.setSearchArea(QGeoCircle(QGeoCoordinate(12.34, 56.78)));
149 /* QPlaceSearchSuggestion * */suggestionReply = manager->searchSuggestions(request);
150 connect(sender: suggestionReply, SIGNAL(finished()), receiver: this, SLOT(handleSuggestionReply()));
151 //! [Suggestion request]
152 }
153
154 void savePlace()
155 {
156 //! [Save place pt1]
157 QPlace place;
158 place.setName( "Fred's Ice Cream Parlor" );
159
160 QGeoLocation location;
161 location.setCoordinate(QGeoCoordinate(12.34, 56.78));
162
163 QGeoAddress address;
164 address.setStreet("111 Nother Street");
165 //! [Save place pt1]
166
167 //! [Save place pt2]
168 location.setAddress(address);
169 place.setLocation(location);
170
171 /* QPlaceIdReply * */savePlaceReply = manager->savePlace(place);
172 connect(sender: savePlaceReply, SIGNAL(finished()), receiver: this, SLOT(handleSavePlaceReply()));
173 //! [Save place pt2]
174 }
175
176 void removePlace()
177 {
178 QPlace place;
179 //! [Remove place]
180 /* QPlaceIdReply * */removePlaceReply = manager->removePlace(placeId: place.placeId());
181 connect(sender: removePlaceReply, SIGNAL(finished()), receiver: this, SLOT(handleRemovePlaceReply()));
182 //! [Remove place]
183 }
184
185 void initializeCategories()
186 {
187 //! [Initialize categories]
188 /* QPlaceReply * */initCatReply = manager->initializeCategories();
189 connect(sender: initCatReply, SIGNAL(finished()), receiver: this, SLOT(handleInitCatReply()));
190 //! [Initialize categories]
191 }
192
193 void saveCategory()
194 {
195 //! [Save category]
196 QPlaceCategory fastFood;
197
198 QPlaceCategory category;
199 category.setName("pizza");
200 /*QPlaceIdReply */ saveCategoryReply = manager->saveCategory(category);
201 connect(sender: saveCategoryReply, SIGNAL(finished()), receiver: this, SLOT(handleSaveCategoryReply()));
202
203 //we could have saved a category as a child by supplying a parent identifier.
204 saveCategoryReply = manager->saveCategory(category, parentId: fastFood.categoryId());
205 //! [Save category]
206 }
207
208 void removeCategory()
209 {
210 QPlaceCategory category;
211 //! [Remove category]
212 /* QPlaceIdReply * */removeCategoryReply = manager->removeCategory(categoryId: place.placeId());
213 connect(sender: removeCategoryReply, SIGNAL(finished()), receiver: this, SLOT(handleRemoveCategoryReply()));
214 //! [Remove category]
215 }
216
217 void searchRequest() {
218 QPlaceCategory diner;
219 QPlaceCategory restaurant;
220
221 //! [Search request]
222 QPlaceSearchRequest searchRequest;
223 searchRequest.setSearchTerm("Fast food"); //search term for what we are interested in
224
225 //set a search center
226 searchRequest.setSearchArea(QGeoCircle(QGeoCoordinate(2.3, 48.87)));
227
228 //set a distance hint as a relevancy hint.
229 //closer places have greater weighting in the ranking of results.
230 searchRequest.setRelevanceHint(QPlaceSearchRequest::DistanceHint);
231
232 //use limit to adjust pagination.
233 //this limits the number of place results to 5 per page.
234 searchRequest.setLimit(5);
235
236 //provide some categories to narrow down search
237 QList<QPlaceCategory> categories;
238 categories << diner << restaurant;
239 searchRequest.setCategories(categories);
240 //! [Search request]
241 }
242
243 void content() {
244 QPlace place;
245 //! [Content request]
246 QPlaceContentRequest request;
247 request.setContentType(QPlaceContent::ImageType);
248 request.setPlaceId(place.placeId());
249 request.setLimit(5);
250
251 QPlaceContentReply *contentReply = manager->getPlaceContent(request);
252 //..connect signals..//
253
254 //! [Content request]
255 Q_UNUSED(contentReply);
256 }
257
258 void contentConversion()
259 {
260 //! [Content conversion]
261 QPlaceImage image;
262 image.setUrl(QUrl("www.example.com"));
263
264 QPlaceContent content = image;
265
266 QPlaceImage image2;
267 image2 = content;
268 qDebug() << image2.url(); //image2.url() == "www.example.com"
269 //! [Content conversion]
270 }
271
272 void icon() {
273 QPlace place;
274 //! [icon]
275 QUrl iconSourceUrl = place.icon().url(size: QSize(32,32));
276
277 //A default icon may also be requested like so
278 iconSourceUrl = place.icon().url();
279 //! [icon]
280 }
281
282 void saveBetweenManagers() {
283 QPlaceResult result;
284 QPlaceIdReply *saveReply;
285 //! [ Save to different manager]
286 //result retrieved from a different manager)
287 QPlace place = manager->compatiblePlace(place: result.place());
288 saveReply = manager->savePlace(place);
289 //! [ Save to different manager]
290 saveReply->abort();//needed to avoid warnings
291 }
292
293 void ratings() {
294 //! [Ratings]
295 qDebug() << QString("This place rated ") + place.ratings().average()
296 + "out of " + place.ratings().maximum() + "stars";
297 //! [Ratings]
298 }
299
300 void matchPlaces() {
301 QList<QPlaceSearchResult> results;
302 //! [Match places]
303 QPlaceMatchRequest request;
304 request.setResults(results);
305 QVariantMap parameters;
306 parameters.insert(akey: QPlaceMatchRequest::AlternativeId, avalue: "x_id_here");
307 request.setParameters(parameters);
308 matchReply = manager->matchingPlaces(request);
309 //! [Match places]
310 }
311
312public slots:
313 // ![Simple search handler]
314 //4) Have the slot appropriately process the results of the operation
315 void processSearchReply() {
316 if (searchReply->error() == QPlaceReply::NoError) {
317 foreach (const QPlaceSearchResult &result, searchReply->results()) {
318 if (result.type() == QPlaceSearchResult::PlaceResult)
319 qDebug() << "Title:" << result.title();
320 }
321 }
322
323 //5) Discard the rely object when done.
324 searchReply->deleteLater();
325 searchReply = 0;
326 }
327 // ![Simple search handler]
328
329 //! [Search for places handler cpp]
330 void handleSearchReply() {
331 if (searchReply->error() == QPlaceReply::NoError) {
332 foreach (const QPlaceSearchResult &result, searchReply->results()) {
333 if (result.type() == QPlaceSearchResult::PlaceResult) {
334 QPlaceResult placeResult = result;
335 qDebug() << "Name: " << placeResult.place().name();
336 qDebug() << "Coordinate " << placeResult.place().location().coordinate().toString();
337 qDebug() << "Street: " << placeResult.place().location().address().street();
338 qDebug() << "Distance: " << placeResult.distance();
339 }
340 }
341 }
342 searchReply->deleteLater(); //discard reply
343 searchReply = 0;
344 }
345 //! [Search for places handler cpp]
346
347 //! [Details handler cpp]
348 void handleDetailsReply() {
349 QPlace place;
350 if (detailsReply->error() == QPlaceReply::NoError)
351 place = detailsReply->place();
352
353 detailsReply->deleteLater(); //discard reply
354 detailsReply = 0;
355 }
356 //! [Details handler cpp]
357
358 //! [Image handler]
359 void handleImagesReply() {
360 if (contentReply->error() == QPlaceReply::NoError) {
361 const auto content = contentReply->content();
362 for (auto iter = content.cbegin(), end = content.cend(); iter != end; ++iter) {
363 qDebug() << "Index: " << iter.key();
364 QPlaceImage image = iter.value();
365 qDebug() << image.url();
366 qDebug() << image.mimeType();
367 }
368
369 //alternatively if indexes are irrelevant
370 foreach (const QPlaceImage &image, contentReply->content()) {
371 qDebug() << image.url();
372 qDebug() << image.mimeType();
373 }
374
375 //we can assign content to the place that it belongs to.
376 //the place object serves as a container where we can retrieve
377 //content that has already been fetched
378 place.insertContent(type: contentReply->request().contentType(), content: contentReply->content());
379 place.setTotalContentCount(type: contentReply->request().contentType(), total: contentReply->totalCount());
380 }
381
382 contentReply->deleteLater();
383 contentReply = 0;
384 }
385 //! [Image handler]
386
387 //! [Suggestion handler]
388 void handleSuggestionReply() {
389 if (suggestionReply->error() == QPlaceReply::NoError) {
390 foreach (const QString &suggestion, suggestionReply->suggestions())
391 qDebug() << suggestion;
392 }
393
394 suggestionReply->deleteLater(); //discard reply
395 suggestionReply = 0;
396 }
397
398 //! [Suggestion handler]
399
400 //! [Save place handler]
401 void handleSavePlaceReply() {
402 if (savePlaceReply->error() == QPlaceReply::NoError)
403 qDebug() << savePlaceReply->id();
404
405 savePlaceReply->deleteLater(); //discard reply
406 savePlaceReply = 0;
407 }
408 //! [Save place handler]
409
410 //! [Remove place handler]
411 void handleRemovePlaceReply() {
412 if (removePlaceReply->error() == QPlaceReply::NoError)
413 qDebug() << "Removal of place identified by"
414 << removePlaceReply->id() << "was successful";
415
416 removePlaceReply->deleteLater(); //discard reply
417 removePlaceReply = 0;
418 }
419 //! [Remove place handler]
420
421 //! [Initialize categories reply]
422 void handleInitCatReply() {
423 if (initCatReply->error() == QPlaceReply::NoError)
424 qDebug() << "Categories initialized";
425 else
426 qDebug() << "Failed to initialize categories";
427
428 initCatReply->deleteLater();
429 initCatReply = 0;
430 }
431 //! [Initialize categories reply]
432
433 void categories() {
434 QPlaceCategory pizza;
435 //! [Top level categories]
436 QList<QPlaceCategory> topLevelCategories = manager->childCategories();
437 foreach (const QPlaceCategory &category, topLevelCategories)
438 qDebug() << category.name();
439 //! [Top level categories]
440
441 //! [Child categories]
442 QList<QPlaceCategory> childCategories = manager->childCategories(parentId: pizza.categoryId());
443 //! [Child categories]
444 }
445
446 //! [Save category handler]
447 void handleSaveCategoryReply() {
448 if (saveCategoryReply->error() == QPlaceReply::NoError) {
449 qDebug() << "Saved category id =" << saveCategoryReply->id();
450 }
451
452 saveCategoryReply->deleteLater();
453 saveCategoryReply = 0;
454 }
455 //! [Save category handler]
456
457 //! [Remove category handler]
458 void handleRemoveCategoryReply() {
459 if (removeCategoryReply->error() == QPlaceReply::NoError)
460 qDebug() << "Removal of category identified by"
461 << removeCategoryReply->id() << "was successful";
462
463 removeCategoryReply->deleteLater(); //discard reply
464 removeCategoryReply = 0;
465 }
466 //! [Remove category handler]
467
468 //! [Content handler]
469 void contentHandler() {
470 if (contentReply->error() == QPlaceReply::NoError) {
471 place.insertContent(type: contentReply->request().contentType(),
472 content: contentReply->content());
473 }
474 }
475 //! [Content handler]
476
477 void phoneNumbers() {
478 //! [Phone numbers]
479 if (place.contactTypes().contains(str: QPlaceContactDetail::Phone)) {
480 foreach (const QPlaceContactDetail &number, place.contactDetails(QPlaceContactDetail::Phone))
481 qDebug() << number.label() << ":" << number.value();
482 }
483 //! [Phone numbers]
484 }
485
486
487 void openingHours() {
488 //! [Opening hours]
489 if (place.extendedAttributeTypes().contains(str: QPlaceAttribute::OpeningHours))
490 qDebug() << place.extendedAttribute(attributeType: QPlaceAttribute::OpeningHours).text();
491 //! [Opening hours]
492 }
493
494 //! [Match places handler]
495 void matchHandler() {
496 if (matchReply->error() == QPlaceReply::NoError) {
497 foreach (const QPlace place, matchReply->places()) {
498 if (place != QPlace())
499 qDebug() << "Place is a favorite with name" << place.name();
500 else
501 qDebug() << "Place is not a favorite";
502 }
503 }
504
505 matchReply->deleteLater();
506 matchReply = 0;
507 }
508 //! [Match places handler]
509
510 void convertSearchResult() {
511 QPlaceSearchResult result;
512 //! [Convert search result]
513 if (result.type() == QPlaceSearchResult::PlaceResult) {
514 QPlaceResult placeResult = result;
515 qDebug() << placeResult.place().name();
516 qDebug() << placeResult.place().location().coordinate();
517 qDebug() << placeResult.distance();
518 }
519 //! [Convert search result]
520 }
521
522QPlaceSearchReply *searchReply;
523QPlaceManager *manager;
524QPlaceDetailsReply *detailsReply;
525QPlaceContentReply *contentReply;
526QPlaceSearchSuggestionReply *suggestionReply;
527QPlaceIdReply *savePlaceReply;
528QPlaceIdReply *removePlaceReply;
529QPlaceIdReply *saveCategoryReply;
530QPlaceIdReply *removeCategoryReply;
531QPlaceReply *initCatReply;
532QPlaceMatchReply *matchReply;
533QPlace place;
534};
535
536class ManagerEngine : public QObject
537{
538};
539
540//! [Implement reply pt1]
541class SearchReply : public QPlaceSearchReply
542{
543public:
544 explicit SearchReply(ManagerEngine *engine)
545 : QPlaceSearchReply(engine), m_engine(engine){}
546
547 ~SearchReply();
548 void setResults(const QList<QPlaceSearchResult> &results);
549 void setRequest(const QPlaceSearchRequest &request);
550//! [Implement reply pt1]
551
552//! [Implement reply pt2]
553 void triggerDone(QPlaceReply::Error error = QPlaceReply::NoError,
554 const QString &errorString = QString());
555
556 ManagerEngine *m_engine;
557};
558//! [Implement reply pt2]
559
560class SearchSuggestionReply : public QPlaceSearchSuggestionReply
561{
562public:
563 void triggerDone(QPlaceReply::Error error = QPlaceReply::NoError,
564 const QString &errorString = QString());
565
566 ManagerEngine *m_engine;
567
568};
569
570//! [Trigger done]
571void SearchSuggestionReply::triggerDone(QPlaceReply::Error error,
572 const QString &errorString)
573{
574 if (error != QPlaceReply::NoError) {
575 this->setError(error,errorString);
576 QMetaObject::invokeMethod(obj: m_engine, member: "error", type: Qt::QueuedConnection,
577 Q_ARG(QPlaceReply *,this),
578 Q_ARG(QPlaceReply::Error, error),
579 Q_ARG(QString, errorString));
580 QMetaObject::invokeMethod(obj: this, member: "error", type: Qt::QueuedConnection,
581 Q_ARG(QPlaceReply::Error, error),
582 Q_ARG(QString, errorString));
583 }
584
585 this->setFinished(true);
586 QMetaObject::invokeMethod(obj: m_engine, member: "finished", type: Qt::QueuedConnection,
587 Q_ARG(QPlaceReply *,this));
588 QMetaObject::invokeMethod(obj: this, member: "finished", type: Qt::QueuedConnection);
589}
590//! [Trigger done]
591

source code of qtlocation/src/location/doc/snippets/places/requesthandler.h