1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
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** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#ifndef QPLACEMANAGERENGINE_TEST_H
30#define QPLACEMANAGERENGINE_TEST_H
31
32#include <QtCore/QDateTime>
33#include <QtCore/QFile>
34#include <QtCore/QJsonDocument>
35#include <QtCore/QJsonObject>
36#include <QtCore/QJsonArray>
37#include <QtCore/QUuid>
38#include <QtPositioning/QGeoCoordinate>
39#include <QtPositioning/QGeoLocation>
40#include <QtLocation/QPlaceContentReply>
41#include <QtLocation/QPlaceManager>
42#include <QtLocation/QPlaceManagerEngine>
43#include <QtLocation/QPlaceReply>
44#include <QtLocation/QPlaceDetailsReply>
45#include <QtLocation/QPlaceEditorial>
46#include <QtLocation/QPlaceIdReply>
47#include <QtLocation/QPlaceImage>
48#include <QtLocation/QPlaceSearchSuggestionReply>
49#include <QtLocation/QPlaceSearchReply>
50#include <QtLocation/QPlaceResult>
51#include <QtLocation/QPlaceCategory>
52#include <QtLocation/QPlace>
53#include <QtLocation/QPlaceReview>
54#include <QtLocation/private/qplace_p.h>
55#include <QtTest/QTest>
56
57QT_BEGIN_NAMESPACE
58
59inline uint qHash(const QPlaceCategory &category)
60{
61 return qHash(uuid: QUuid(category.categoryId().toLatin1()));
62}
63
64QT_END_NAMESPACE
65
66QT_USE_NAMESPACE
67
68class QPlacePrivateDefaultAlt : public QPlacePrivateDefault
69{
70public:
71 QPlacePrivateDefaultAlt() {}
72 QPlacePrivateDefaultAlt(const QPlacePrivateDefaultAlt &other)
73 : QPlacePrivateDefault(other)
74 {
75 }
76 ~QPlacePrivateDefaultAlt() {}
77
78 QPlaceAttribute extendedAttribute(const QString &attributeType) const override
79 {
80 if (attributeType == QStringLiteral("x_provider")) {
81 QPlaceAttribute a;
82 a.setLabel(QStringLiteral("x_provider"));
83 a.setText(QStringLiteral("QPlacePrivateDefaultAlt"));
84 return a;
85 } else {
86 return QPlacePrivateDefault::extendedAttribute(attributeType);
87 }
88 }
89};
90
91class QPlaceAlt : public QPlace
92{
93public:
94 QPlaceAlt() : QPlace(QSharedDataPointer<QPlacePrivate>(new QPlacePrivateDefaultAlt()))
95 {
96 }
97};
98
99class PlaceReply : public QPlaceReply
100{
101 Q_OBJECT
102
103 friend class QPlaceManagerEngineTest;
104
105public:
106 PlaceReply(QObject *parent = 0)
107 : QPlaceReply(parent)
108 { }
109
110 Q_INVOKABLE void emitFinished()
111 {
112 emit finished();
113 }
114};
115
116class ContentReply : public QPlaceContentReply
117{
118 Q_OBJECT
119
120 friend class QPlaceManagerEngineTest;
121
122public:
123 ContentReply(QObject *parent = 0)
124 : QPlaceContentReply(parent)
125 {}
126
127 Q_INVOKABLE void emitError()
128 {
129 emit error(error: error(), errorString: errorString());
130 }
131
132 Q_INVOKABLE void emitFinished()
133 {
134 emit finished();
135 }
136};
137
138class DetailsReply : public QPlaceDetailsReply
139{
140 Q_OBJECT
141
142 friend class QPlaceManagerEngineTest;
143
144public:
145 DetailsReply(QObject *parent = 0)
146 : QPlaceDetailsReply(parent)
147 { }
148
149 Q_INVOKABLE void emitError()
150 {
151 emit error(error: error(), errorString: errorString());
152 }
153
154 Q_INVOKABLE void emitFinished()
155 {
156 emit finished();
157 }
158};
159
160class IdReply : public QPlaceIdReply
161{
162 Q_OBJECT
163
164 friend class QPlaceManagerEngineTest;
165
166public:
167 IdReply(QPlaceIdReply::OperationType type, QObject *parent = 0)
168 : QPlaceIdReply(type, parent)
169 { }
170
171 Q_INVOKABLE void emitError()
172 {
173 emit error(error: error(), errorString: errorString());
174 }
175
176 Q_INVOKABLE void emitFinished()
177 {
178 emit finished();
179 }
180};
181
182class PlaceSearchReply : public QPlaceSearchReply
183{
184 Q_OBJECT
185
186public:
187 PlaceSearchReply(const QList<QPlaceSearchResult> &results, QObject *parent = 0)
188 : QPlaceSearchReply(parent)
189 {
190 setResults(results);
191 }
192
193 Q_INVOKABLE void emitError()
194 {
195 emit error(error: error(), errorString: errorString());
196 }
197
198 Q_INVOKABLE void emitFinished()
199 {
200 emit finished();
201 }
202};
203
204class SuggestionReply : public QPlaceSearchSuggestionReply
205{
206 Q_OBJECT
207
208public:
209 SuggestionReply(const QStringList &suggestions, QObject *parent = 0)
210 : QPlaceSearchSuggestionReply(parent)
211 {
212 setSuggestions(suggestions);
213 }
214
215 Q_INVOKABLE void emitError()
216 {
217 emit error(error: error(), errorString: errorString());
218 }
219
220 Q_INVOKABLE void emitFinished()
221 {
222 emit finished();
223 }
224};
225
226class QPlaceManagerEngineTest : public QPlaceManagerEngine
227{
228 Q_OBJECT
229public:
230 QPlaceManagerEngineTest(const QVariantMap &parameters)
231 : QPlaceManagerEngine(parameters)
232 {
233 m_locales << QLocale();
234 if (parameters.value(QStringLiteral("initializePlaceData"), adefaultValue: false).toBool()) {
235 QFile placeData(QFINDTESTDATA("place_data.json"));
236 QVERIFY(placeData.exists());
237 if (placeData.open(flags: QIODevice::ReadOnly)) {
238 QJsonDocument document = QJsonDocument::fromJson(json: placeData.readAll());
239
240 if (document.isObject()) {
241 QJsonObject o = document.object();
242
243 if (o.contains(QStringLiteral("categories"))) {
244 QJsonArray categories = o.value(QStringLiteral("categories")).toArray();
245
246 for (int i = 0; i < categories.count(); ++i) {
247 QJsonObject c = categories.at(i).toObject();
248
249 QPlaceCategory category;
250
251 category.setName(c.value(QStringLiteral("name")).toString());
252 category.setCategoryId(c.value(QStringLiteral("id")).toString());
253
254 m_categories.insert(akey: category.categoryId(), avalue: category);
255
256 const QString parentId = c.value(QStringLiteral("parentId")).toString();
257 m_childCategories[parentId].append(t: category.categoryId());
258 }
259 }
260
261 if (o.contains(QStringLiteral("places"))) {
262 QJsonArray places = o.value(QStringLiteral("places")).toArray();
263
264 for (int i = 0; i < places.count(); ++i) {
265 QJsonObject p = places.at(i).toObject();
266
267 QPlace place;
268 if (p.value(QStringLiteral("alternateImplementation")).toBool(defaultValue: false)) {
269 place = QPlaceAlt();
270 QPlaceAttribute att;
271 att.setLabel(QStringLiteral("x_provider"));
272 att.setText(QStringLiteral("42")); // Doesn't matter, wont be used.
273 place.setExtendedAttribute(QStringLiteral("x_provider"), attribute: att);
274 }
275
276 place.setName(p.value(QStringLiteral("name")).toString());
277 place.setPlaceId(p.value(QStringLiteral("id")).toString());
278
279 QList<QPlaceCategory> categories;
280 QJsonArray ca = p.value(QStringLiteral("categories")).toArray();
281 for (int j = 0; j < ca.count(); ++j) {
282 QPlaceCategory c = m_categories.value(akey: ca.at(i: j).toString());
283 if (!c.isEmpty())
284 categories.append(t: c);
285 }
286 place.setCategories(categories);
287
288 QGeoCoordinate coordinate;
289 QJsonObject lo = p.value(QStringLiteral("location")).toObject();
290 coordinate.setLatitude(lo.value(QStringLiteral("latitude")).toDouble());
291 coordinate.setLongitude(lo.value(QStringLiteral("longitude")).toDouble());
292
293 QGeoLocation location;
294 location.setCoordinate(coordinate);
295
296 place.setLocation(location);
297
298 m_places.insert(akey: place.placeId(), avalue: place);
299
300 QStringList recommendations;
301 QJsonArray ra = p.value(QStringLiteral("recommendations")).toArray();
302 for (int j = 0; j < ra.count(); ++j)
303 recommendations.append(t: ra.at(i: j).toString());
304 m_placeRecommendations.insert(akey: place.placeId(), avalue: recommendations);
305
306 QJsonArray revArray = p.value(QStringLiteral("reviews")).toArray();
307 QList<QPlaceReview> reviews;
308 for (int j = 0; j < revArray.count(); ++j) {
309 QJsonObject ro = revArray.at(i: j).toObject();
310 QPlaceReview review;
311 if (ro.contains(QStringLiteral("title")))
312 review.setTitle(ro.value(QStringLiteral("title")).toString());
313 if (ro.contains(QStringLiteral("text")))
314 review.setText(ro.value(QStringLiteral("text")).toString());
315
316 if (ro.contains(QStringLiteral("language")))
317 review.setLanguage(ro.value(key: "language").toString());
318
319 if (ro.contains(QStringLiteral("rating")))
320 review.setRating(ro.value(key: "rating").toDouble());
321
322 if (ro.contains(QStringLiteral("dateTime")))
323 review.setDateTime(QDateTime::fromString(
324 s: ro.value(QStringLiteral("dateTime")).toString(),
325 QStringLiteral("hh:mm dd-MM-yyyy")));
326 if (ro.contains(QStringLiteral("reviewId")))
327 review.setReviewId(ro.value(key: "reviewId").toString());
328
329 reviews << review;
330 }
331 m_placeReviews.insert(akey: place.placeId(), avalue: reviews);
332
333 QJsonArray imgArray = p.value(QStringLiteral("images")).toArray();
334 QList<QPlaceImage> images;
335 for (int j = 0; j < imgArray.count(); ++j) {
336 QJsonObject imgo = imgArray.at(i: j).toObject();
337 QPlaceImage image;
338 if (imgo.contains(QStringLiteral("url")))
339 image.setUrl(imgo.value(QStringLiteral("url")).toString());
340
341 if (imgo.contains(key: "imageId"))
342 image.setImageId(imgo.value(QStringLiteral("imageId")).toString());
343
344 if (imgo.contains(key: "mimeType"))
345 image.setMimeType(imgo.value(QStringLiteral("mimeType")).toString());
346
347 images << image;
348 }
349
350 m_placeImages.insert(akey: place.placeId(), avalue: images);
351
352 QJsonArray edArray = p.value(QStringLiteral("editorials")).toArray();
353 QList<QPlaceEditorial> editorials;
354 for (int j = 0; j < edArray.count(); ++j) {
355 QJsonObject edo = edArray.at(i: j).toObject();
356 QPlaceEditorial editorial;
357 if (edo.contains(QStringLiteral("title")))
358 editorial.setTitle(edo.value(QStringLiteral("title")).toString());
359
360 if (edo.contains(QStringLiteral("text")))
361 editorial.setText(edo.value(QStringLiteral("text")).toString());
362
363 if (edo.contains(QStringLiteral("language")))
364 editorial.setLanguage(edo.value(QStringLiteral("language")).toString());
365
366 editorials << editorial;
367 }
368
369 m_placeEditorials.insert(akey: place.placeId(), avalue: editorials);
370 }
371 }
372 }
373 }
374 }
375 }
376
377 QPlaceDetailsReply *getPlaceDetails(const QString &placeId) override
378 {
379 DetailsReply *reply = new DetailsReply(this);
380
381 if (placeId.isEmpty() || !m_places.contains(akey: placeId)) {
382 reply->setError(error: QPlaceReply::PlaceDoesNotExistError, errorString: tr(s: "Place does not exist"));
383 QMetaObject::invokeMethod(obj: reply, member: "emitError", type: Qt::QueuedConnection);
384 } else {
385 reply->setPlace(m_places.value(akey: placeId));
386 }
387
388 QMetaObject::invokeMethod(obj: reply, member: "emitFinished", type: Qt::QueuedConnection);
389
390 return reply;
391 }
392
393 QPlaceContentReply *getPlaceContent(const QPlaceContentRequest &query) override
394 {
395 ContentReply *reply = new ContentReply(this);
396 if (query.placeId().isEmpty() || !m_places.contains(akey: query.placeId())) {
397 reply->setError(error: QPlaceReply::PlaceDoesNotExistError, errorString: tr(s: "Place does not exist"));
398 QMetaObject::invokeMethod(obj: reply, member: "emitError", type: Qt::QueuedConnection);
399
400 } else {
401 QPlaceContent::Collection collection;
402 int totalCount = 0;
403 switch (query.contentType()) {
404 case QPlaceContent::ReviewType:
405 totalCount = m_placeReviews.value(akey: query.placeId()).count();
406 break;
407 case QPlaceContent::ImageType:
408 totalCount = m_placeImages.value(akey: query.placeId()).count();
409 break;
410 case QPlaceContent::EditorialType:
411 totalCount = m_placeEditorials.value(akey: query.placeId()).count();
412 default:
413 //do nothing
414 break;
415 }
416
417 QVariantMap context = query.contentContext().toMap();
418
419 int offset = context.value(QStringLiteral("offset"), adefaultValue: 0).toInt();
420 int max = (query.limit() == -1) ? totalCount
421 : qMin(a: offset + query.limit(), b: totalCount);
422 for (int i = offset; i < max; ++i) {
423 switch (query.contentType()) {
424 case QPlaceContent::ReviewType:
425 collection.insert(akey: i, avalue: m_placeReviews.value(akey: query.placeId()).at(i));
426 break;
427 case QPlaceContent::ImageType:
428 collection.insert(akey: i, avalue: m_placeImages.value(akey: query.placeId()).at(i));
429 break;
430 case QPlaceContent::EditorialType:
431 collection.insert(akey: i, avalue: m_placeEditorials.value(akey: query.placeId()).at(i));
432 default:
433 //do nothing
434 break;
435 }
436 }
437
438 reply->setContent(collection);
439 reply->setTotalCount(totalCount);
440
441 if (max != totalCount) {
442 context.clear();
443 context.insert(QStringLiteral("offset"), avalue: offset + query.limit());
444 QPlaceContentRequest request = query;
445 request.setContentContext(context);
446 reply->setNextPageRequest(request);
447 }
448 if (offset > 0) {
449 context.clear();
450 context.insert(QStringLiteral("offset"), avalue: qMin(a: 0, b: offset - query.limit()));
451 QPlaceContentRequest request = query;
452 request.setContentContext(context);
453 reply->setPreviousPageRequest(request);
454 }
455 }
456
457 QMetaObject::invokeMethod(obj: reply, member: "emitFinished", type: Qt::QueuedConnection);
458 return reply;
459 }
460
461 QPlaceSearchReply *search(const QPlaceSearchRequest &query) override
462 {
463 QList<QPlaceSearchResult> results;
464
465 if (!query.searchTerm().isEmpty()) {
466 foreach (const QPlace &place, m_places) {
467 if (!place.name().contains(s: query.searchTerm(), cs: Qt::CaseInsensitive))
468 continue;
469
470 QPlaceResult r;
471 r.setPlace(place);
472 r.setTitle(place.name());
473
474 results.append(t: r);
475 }
476 } else if (!query.categories().isEmpty()) {
477 const auto &categoryList = query.categories();
478 const QSet<QPlaceCategory> categories(categoryList.cbegin(), categoryList.cend());
479 for (const QPlace &place : qAsConst(t&: m_places)) {
480 const auto &placeCategoryList = place.categories();
481 const QSet<QPlaceCategory> placeCategories(placeCategoryList.cbegin(), placeCategoryList.cend());
482 if (!placeCategories.intersects(other: categories))
483 continue;
484
485 QPlaceResult r;
486 r.setPlace(place);
487 r.setTitle(place.name());
488
489 results.append(t: r);
490 }
491 } else if (!query.recommendationId().isEmpty()) {
492 QStringList recommendations = m_placeRecommendations.value(akey: query.recommendationId());
493 foreach (const QString &id, recommendations) {
494 QPlaceResult r;
495 r.setPlace(m_places.value(akey: id));
496 r.setTitle(r.place().name());
497
498 results.append(t: r);
499 }
500 }
501
502 PlaceSearchReply *reply = new PlaceSearchReply(results, this);
503
504 QMetaObject::invokeMethod(obj: reply, member: "emitFinished", type: Qt::QueuedConnection);
505
506 return reply;
507 }
508
509 QPlaceSearchSuggestionReply *searchSuggestions(const QPlaceSearchRequest &query) override
510 {
511 QStringList suggestions;
512 if (query.searchTerm() == QLatin1String("test")) {
513 suggestions << QStringLiteral("test1");
514 suggestions << QStringLiteral("test2");
515 suggestions << QStringLiteral("test3");
516 }
517
518 SuggestionReply *reply = new SuggestionReply(suggestions, this);
519
520 QMetaObject::invokeMethod(obj: reply, member: "emitFinished", type: Qt::QueuedConnection);
521
522 return reply;
523 }
524
525 QPlaceIdReply *savePlace(const QPlace &place) override
526 {
527 IdReply *reply = new IdReply(QPlaceIdReply::SavePlace, this);
528
529 if (!place.placeId().isEmpty() && !m_places.contains(akey: place.placeId())) {
530 reply->setError(error: QPlaceReply::PlaceDoesNotExistError, errorString: tr(s: "Place does not exist"));
531 QMetaObject::invokeMethod(obj: reply, member: "emitError", type: Qt::QueuedConnection);
532 } else if (!place.placeId().isEmpty()) {
533 m_places.insert(akey: place.placeId(), avalue: place);
534 reply->setId(place.placeId());
535 } else {
536 QPlace p = place;
537 p.setPlaceId(QUuid::createUuid().toString());
538 m_places.insert(akey: p.placeId(), avalue: p);
539
540 reply->setId(p.placeId());
541 }
542
543 QMetaObject::invokeMethod(obj: reply, member: "emitFinished", type: Qt::QueuedConnection);
544
545 return reply;
546 }
547
548 QPlaceIdReply *removePlace(const QString &placeId) override
549 {
550 IdReply *reply = new IdReply(QPlaceIdReply::RemovePlace, this);
551 reply->setId(placeId);
552
553 if (!m_places.contains(akey: placeId)) {
554 reply->setError(error: QPlaceReply::PlaceDoesNotExistError, errorString: tr(s: "Place does not exist"));
555 QMetaObject::invokeMethod(obj: reply, member: "emitError", type: Qt::QueuedConnection);
556 } else {
557 m_places.remove(akey: placeId);
558 }
559
560 QMetaObject::invokeMethod(obj: reply, member: "emitFinished", type: Qt::QueuedConnection);
561
562 return reply;
563 }
564
565 QPlaceIdReply *saveCategory(const QPlaceCategory &category, const QString &parentId) override
566 {
567 IdReply *reply = new IdReply(QPlaceIdReply::SaveCategory, this);
568
569 if ((!category.categoryId().isEmpty() && !m_categories.contains(akey: category.categoryId())) ||
570 (!parentId.isEmpty() && !m_categories.contains(akey: parentId))) {
571 reply->setError(error: QPlaceReply::CategoryDoesNotExistError, errorString: tr(s: "Category does not exist"));
572 QMetaObject::invokeMethod(obj: reply, member: "emitError", type: Qt::QueuedConnection);
573 } else if (!category.categoryId().isEmpty()) {
574 m_categories.insert(akey: category.categoryId(), avalue: category);
575 QStringList children = m_childCategories.value(akey: parentId);
576
577 for (QStringList &c : m_childCategories)
578 c.removeAll(t: category.categoryId());
579
580 if (!children.contains(str: category.categoryId())) {
581 children.append(t: category.categoryId());
582 m_childCategories.insert(akey: parentId, avalue: children);
583 }
584 reply->setId(category.categoryId());
585 } else {
586 QPlaceCategory c = category;
587 c.setCategoryId(QUuid::createUuid().toString());
588 m_categories.insert(akey: c.categoryId(), avalue: c);
589 QStringList children = m_childCategories.value(akey: parentId);
590 if (!children.contains(str: c.categoryId())) {
591 children.append(t: c.categoryId());
592 m_childCategories.insert(akey: parentId, avalue: children);
593 }
594
595 reply->setId(c.categoryId());
596 }
597
598 QMetaObject::invokeMethod(obj: reply, member: "emitFinished", type: Qt::QueuedConnection);
599
600 return reply;
601 }
602
603 QPlaceIdReply *removeCategory(const QString &categoryId) override
604 {
605 IdReply *reply = new IdReply(QPlaceIdReply::RemoveCategory, this);
606 reply->setId(categoryId);
607
608 if (!m_categories.contains(akey: categoryId)) {
609 reply->setError(error: QPlaceReply::CategoryDoesNotExistError, errorString: tr(s: "Category does not exist"));
610 QMetaObject::invokeMethod(obj: reply, member: "emitError", type: Qt::QueuedConnection);
611 } else {
612 m_categories.remove(akey: categoryId);
613
614 for (auto &c : m_childCategories)
615 c.removeAll(t: categoryId);
616 }
617
618 QMetaObject::invokeMethod(obj: reply, member: "emitFinished", type: Qt::QueuedConnection);
619
620 return reply;
621 }
622
623 QPlaceReply *initializeCategories() override
624 {
625 QPlaceReply *reply = new PlaceReply(this);
626
627 QMetaObject::invokeMethod(obj: reply, member: "emitFinished", type: Qt::QueuedConnection);
628
629 return reply;
630 }
631
632 QString parentCategoryId(const QString &categoryId) const override
633 {
634 for (auto i = m_childCategories.cbegin(), end = m_childCategories.cend(); i != end; ++i) {
635 if (i.value().contains(str: categoryId))
636 return i.key();
637 }
638
639 return QString();
640 }
641
642 virtual QStringList childCategoryIds(const QString &categoryId) const override
643 {
644 return m_childCategories.value(akey: categoryId);
645 }
646
647 virtual QPlaceCategory category(const QString &categoryId) const override
648 {
649 return m_categories.value(akey: categoryId);
650 }
651
652 QList<QPlaceCategory> childCategories(const QString &parentId) const override
653 {
654 QList<QPlaceCategory> categories;
655
656 foreach (const QString &id, m_childCategories.value(parentId))
657 categories.append(t: m_categories.value(akey: id));
658
659 return categories;
660 }
661
662 QList<QLocale> locales() const override
663 {
664 return m_locales;
665 }
666
667 void setLocales(const QList<QLocale> &locales) override
668 {
669 m_locales = locales;
670 }
671
672 QUrl constructIconUrl(const QPlaceIcon &icon, const QSize &size) const override
673 {
674 QList<QPair<int, QUrl> > candidates;
675
676 QMap<QString, int> sizeDictionary;
677 sizeDictionary.insert(QStringLiteral("s"), avalue: 20);
678 sizeDictionary.insert(QStringLiteral("m"), avalue: 30);
679 sizeDictionary.insert(QStringLiteral("l"), avalue: 50);
680
681 QStringList sizeKeys;
682 sizeKeys << QStringLiteral("s") << QStringLiteral("m") << QStringLiteral("l");
683
684 foreach (const QString &sizeKey, sizeKeys)
685 {
686 if (icon.parameters().contains(akey: sizeKey))
687 candidates.append(t: QPair<int, QUrl>(sizeDictionary.value(akey: sizeKey),
688 icon.parameters().value(akey: sizeKey).toUrl()));
689 }
690
691 if (candidates.isEmpty())
692 return QUrl();
693 else if (candidates.count() == 1) {
694 return candidates.first().second;
695 } else {
696 //we assume icons are squarish so we can use height to
697 //determine which particular icon to return
698 int requestedHeight = size.height();
699
700 for (int i = 0; i < candidates.count() - 1; ++i) {
701 int thresholdHeight = (candidates.at(i).first + candidates.at(i: i+1).first) / 2;
702 if (requestedHeight < thresholdHeight)
703 return candidates.at(i).second;
704 }
705 return candidates.last().second;
706 }
707 }
708
709 QPlace compatiblePlace(const QPlace &original) const override
710 {
711 QPlace place;
712 place.setName(original.name());
713 return place;
714 }
715
716private:
717 QList<QLocale> m_locales;
718 QHash<QString, QPlace> m_places;
719 QHash<QString, QPlaceCategory> m_categories;
720 QHash<QString, QStringList> m_childCategories;
721 QHash<QString, QStringList> m_placeRecommendations;
722 QHash<QString, QList<QPlaceReview> > m_placeReviews;
723 QHash<QString, QList<QPlaceImage> > m_placeImages;
724 QHash<QString, QList<QPlaceEditorial> > m_placeEditorials;
725};
726
727#endif
728

source code of qtlocation/tests/auto/geotestplugin/qplacemanagerengine_test.h