8#include <QtQml/QQmlEngine>
9#include <QtQml/QQmlInfo>
10#include <QtLocation/QGeoServiceProvider>
11#include <QtLocation/QPlaceSearchReply>
12#include <QtLocation/QPlaceManager>
13#include <QtLocation/QPlaceMatchRequest>
14#include <QtLocation/QPlaceMatchReply>
15#include <QtLocation/QPlaceResult>
16#include <QtLocation/QPlaceProposedSearchResult>
17#include <QtLocation/private/qplacesearchrequest_p.h>
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
138
139
140
141
144
145
146
147
148
149
150
151
152
153
154
155
158
159
160
161
162
163
164
165
166
167
168
169
170
173
174
175
176
177
178
179
180
181
182
183
184
185
188
189
190
191
194
195
196
197
198
199
202
203
204
205
206
207
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
231
232
233
234
235
236
237
238
239
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
280
281
282
283
284
285
286
287
288
289
292
293
294
295
296
299
300
301
302
303
304
305
306
309
310
311
312
313
316
317
318
319
320
322QDeclarativeSearchResultModel::QDeclarativeSearchResultModel(QObject *parent)
323 : QDeclarativeSearchModelBase(parent)
327QDeclarativeSearchResultModel::~QDeclarativeSearchResultModel()
332
333
334
335
336QString QDeclarativeSearchResultModel::searchTerm()
const
338 return m_request.searchTerm();
341void QDeclarativeSearchResultModel::setSearchTerm(
const QString &searchTerm)
343 m_request.setSearchContext(QVariant());
345 if (m_request.searchTerm() == searchTerm)
348 m_request.setSearchTerm(searchTerm);
349 emit searchTermChanged();
353
354
355
356
357
358QQmlListProperty<QDeclarativeCategory> QDeclarativeSearchResultModel::categories()
360 return QQmlListProperty<QDeclarativeCategory>(
this,
368void QDeclarativeSearchResultModel::categories_append(QQmlListProperty<QDeclarativeCategory> *list,
369 QDeclarativeCategory *declCategory)
371 QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
372 if (searchModel && declCategory) {
373 searchModel->m_request.setSearchContext(QVariant());
374 searchModel->m_categories.append(declCategory);
375 QList<QPlaceCategory> categories = searchModel->m_request.categories();
376 categories.append(declCategory->category());
377 searchModel->m_request.setCategories(categories);
378 emit searchModel->categoriesChanged();
382qsizetype QDeclarativeSearchResultModel::categories_count(QQmlListProperty<QDeclarativeCategory> *list)
384 QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
386 return searchModel->m_categories.count();
391QDeclarativeCategory *QDeclarativeSearchResultModel::category_at(QQmlListProperty<QDeclarativeCategory> *list,
394 QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
395 if (searchModel && (searchModel->m_categories.count() > index) && (index > -1))
396 return searchModel->m_categories.at(index);
400void QDeclarativeSearchResultModel::categories_clear(QQmlListProperty<QDeclarativeCategory> *list)
402 QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
406 searchModel->m_request.setSearchContext(QVariant());
407 searchModel->m_categories.clear();
408 searchModel->m_request.setCategories(QList<QPlaceCategory>());
409 emit searchModel->categoriesChanged();
414
415
416
417
418
419QString QDeclarativeSearchResultModel::recommendationId()
const
421 return m_request.recommendationId();
424void QDeclarativeSearchResultModel::setRecommendationId(
const QString &placeId)
426 if (m_request.recommendationId() == placeId)
429 m_request.setRecommendationId(placeId);
430 emit recommendationIdChanged();
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455QDeclarativeSearchResultModel::RelevanceHint QDeclarativeSearchResultModel::relevanceHint()
const
457 return static_cast<QDeclarativeSearchResultModel::RelevanceHint>(m_request.relevanceHint());
460void QDeclarativeSearchResultModel::setRelevanceHint(QDeclarativeSearchResultModel::RelevanceHint hint)
462 if (m_request.relevanceHint() !=
static_cast<QPlaceSearchRequest::RelevanceHint>(hint)) {
463 m_request.setRelevanceHint(
static_cast<QPlaceSearchRequest::RelevanceHint>(hint));
464 emit relevanceHintChanged();
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492QDeclarativePlace::Visibility QDeclarativeSearchResultModel::visibilityScope()
const
494 return QDeclarativePlace::Visibility(
int(m_visibilityScope));
497void QDeclarativeSearchResultModel::setVisibilityScope(QDeclarativePlace::Visibility visibilityScope)
499 QLocation::VisibilityScope scope = QLocation::VisibilityScope(visibilityScope);
501 if (m_visibilityScope == scope)
504 m_visibilityScope = scope;
505 emit visibilityScopeChanged();
509
510
511QDeclarativeGeoServiceProvider *QDeclarativeSearchResultModel::favoritesPlugin()
const
513 return m_favoritesPlugin;
517
518
519void QDeclarativeSearchResultModel::setFavoritesPlugin(QDeclarativeGeoServiceProvider *plugin)
522 if (m_favoritesPlugin == plugin)
525 m_favoritesPlugin = plugin;
527 if (m_favoritesPlugin) {
528 QGeoServiceProvider *serviceProvider = m_favoritesPlugin->sharedGeoServiceProvider();
529 if (serviceProvider) {
530 QPlaceManager *placeManager = serviceProvider->placeManager();
532 if (placeManager->childCategoryIds().isEmpty()) {
533 QPlaceReply *reply = placeManager->initializeCategories();
534 connect(reply, &QPlaceReply::finished, reply, &QObject::deleteLater);
540 emit favoritesPluginChanged();
544
545
546QVariantMap QDeclarativeSearchResultModel::favoritesMatchParameters()
const
548 return m_matchParameters;
552
553
554void QDeclarativeSearchResultModel::setFavoritesMatchParameters(
const QVariantMap ¶meters)
556 if (m_matchParameters == parameters)
559 m_matchParameters = parameters;
560 emit favoritesMatchParametersChanged();
564
565
566int QDeclarativeSearchResultModel::rowCount(
const QModelIndex &parent)
const
570 return m_results.count();
573void QDeclarativeSearchResultModel::clearData(
bool suppressSignal)
575 QDeclarativeSearchModelBase::clearData(suppressSignal);
577 qDeleteAll(m_places);
580 if (!m_results.isEmpty()) {
584 emit rowCountChanged();
588QVariant QDeclarativeSearchResultModel::data(
const QModelIndex &index,
int role)
const
590 if (index.row() > m_results.count())
593 const QPlaceSearchResult &result = m_results.at(index.row());
596 case SearchResultTypeRole:
597 return result.type();
598 case Qt::DisplayRole:
600 return result.title();
602 return QVariant::fromValue(m_icons.at(index.row()));
604 if (result.type() == QPlaceSearchResult::PlaceResult) {
605 QPlaceResult placeResult = result;
606 return placeResult.distance();
610 if (result.type() == QPlaceSearchResult::PlaceResult)
611 return QVariant::fromValue(
static_cast<QObject *>(m_places.at(index.row())));
614 if (result.type() == QPlaceSearchResult::PlaceResult) {
615 QPlaceResult placeResult = result;
616 return placeResult.isSponsored();
624
625
626QVariant QDeclarativeSearchResultModel::data(
int index,
const QString &role)
const
628 QModelIndex modelIndex = createIndex(index, 0);
629 return data(modelIndex, roleNames().key(role.toLatin1()));
632QHash<
int, QByteArray> QDeclarativeSearchResultModel::roleNames()
const
634 QHash<
int, QByteArray> roles = QDeclarativeSearchModelBase::roleNames();
635 roles.insert(SearchResultTypeRole,
"type");
636 roles.insert(TitleRole,
"title");
637 roles.insert(IconRole,
"icon");
638 roles.insert(DistanceRole,
"distance");
639 roles.insert(PlaceRole,
"place");
640 roles.insert(SponsoredRole,
"sponsored");
646
647
648
649
650
651
652
653
654
655
656void QDeclarativeSearchResultModel::updateWith(
int proposedSearchIndex)
658 if (m_results.at(proposedSearchIndex).type() != QPlaceSearchResult::ProposedSearchResult)
661 m_request = QPlaceProposedSearchResult(m_results.at(proposedSearchIndex)).searchRequest();
665QPlaceReply *QDeclarativeSearchResultModel::sendQuery(QPlaceManager *manager,
666 const QPlaceSearchRequest &request)
669 return manager->search(request);
673
674
675void QDeclarativeSearchResultModel::initializePlugin(QDeclarativeGeoServiceProvider *plugin)
679 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
680 if (serviceProvider) {
681 QPlaceManager *placeManager = serviceProvider->placeManager();
683 disconnect(placeManager, &QPlaceManager::placeUpdated,
684 this, &QDeclarativeSearchResultModel::placeUpdated);
685 disconnect(placeManager, &QPlaceManager::placeRemoved,
686 this, &QDeclarativeSearchResultModel::placeRemoved);
687 connect(placeManager, &QPlaceManager::dataChanged,
688 this, &QDeclarativeSearchResultModel::dataChanged);
695 QGeoServiceProvider *serviceProvider = plugin->sharedGeoServiceProvider();
696 if (serviceProvider) {
697 QPlaceManager *placeManager = serviceProvider->placeManager();
699 connect(placeManager, &QPlaceManager::placeUpdated,
700 this, &QDeclarativeSearchResultModel::placeUpdated);
701 connect(placeManager, &QPlaceManager::placeRemoved,
702 this, &QDeclarativeSearchResultModel::placeRemoved);
703 disconnect(placeManager, &QPlaceManager::dataChanged,
704 this, &QDeclarativeSearchResultModel::dataChanged);
708 QDeclarativeSearchModelBase::initializePlugin(plugin);
712
713
714void QDeclarativeSearchResultModel::queryFinished()
718 QPlaceReply *reply = m_reply;
720 reply->deleteLater();
725 if (reply->error() != QPlaceReply::NoError) {
726 m_resultsBuffer.clear();
728 setStatus(Error, reply->errorString());
732 if (reply->type() == QPlaceReply::SearchReply) {
733 QPlaceSearchReply *searchReply = qobject_cast<QPlaceSearchReply *>(reply);
734 Q_ASSERT(searchReply);
736 const QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(searchReply->request());
737 if (!rpimpl->related || !m_incremental)
739 m_resultsBuffer = searchReply->results();
740 bool alreadyLoaded =
false;
741 if (m_pages.contains(rpimpl->page) && m_resultsBuffer == m_pages.value(rpimpl->page))
742 alreadyLoaded =
true;
743 m_pages.insert(rpimpl->page, m_resultsBuffer);
744 setPreviousPageRequest(searchReply->previousPageRequest());
745 setNextPageRequest(searchReply->nextPageRequest());
748 if (!m_favoritesPlugin) {
752 QGeoServiceProvider *serviceProvider = m_favoritesPlugin->sharedGeoServiceProvider();
753 if (!serviceProvider) {
755 setStatus(Error, QStringLiteral(
"Favorites plugin returns a null QGeoServiceProvider instance"));
759 QPlaceManager *favoritesManager = serviceProvider->placeManager();
760 if (!favoritesManager) {
762 setStatus(Error, QStringLiteral(
"Favorites plugin returns a null QPlaceManager"));
766 QPlaceMatchRequest request;
767 if (m_matchParameters.isEmpty()) {
769 setStatus(Error, QStringLiteral(
"Plugin not assigned"));
774 params.insert(QPlaceMatchRequest::AlternativeId, QVariant(QString::fromLatin1(
"x_id_") + m_plugin->name()));
775 request.setParameters(params);
777 request.setParameters(m_matchParameters);
780 request.setResults(m_resultsBuffer);
782 m_resultsBuffer.clear();
783 m_reply = favoritesManager->matchingPlaces(request);
784 connect(m_reply, &QPlaceReply::finished,
785 this, &QDeclarativeSearchResultModel::queryFinished);
786 connect(m_reply, &QPlaceReply::contentUpdated,
787 this, &QDeclarativeSearchResultModel::onContentUpdated);
789 }
else if (reply->type() == QPlaceReply::MatchReply) {
790 QPlaceMatchReply *matchReply = qobject_cast<QPlaceMatchReply *>(reply);
791 Q_ASSERT(matchReply);
792 updateLayout(matchReply->places());
795 setStatus(Error, QStringLiteral(
"Unknown reply type"));
799void QDeclarativeSearchResultModel::onContentUpdated()
804 QPlaceReply *reply = m_reply;
809 if (reply->error() != QPlaceReply::NoError) {
810 m_resultsBuffer.clear();
812 setStatus(Error, reply->errorString());
816 if (reply->type() == QPlaceReply::SearchReply) {
817 QPlaceSearchReply *searchReply = qobject_cast<QPlaceSearchReply *>(reply);
818 Q_ASSERT(searchReply);
820 const QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(searchReply->request());
821 if (!rpimpl->related || !m_incremental)
823 m_resultsBuffer = searchReply->results();
824 if (!(m_pages.contains(rpimpl->page) && m_resultsBuffer == m_pages.value(rpimpl->page))) {
825 m_pages.insert(rpimpl->page, m_resultsBuffer);
828 }
else if (reply->type() == QPlaceReply::MatchReply) {
831 setStatus(Error, QStringLiteral(
"Unknown reply type"));
836
837
838
839
842
843
844
845
846
847
848
849
852
853
854
855
856void QDeclarativeSearchResultModel::updateLayout(
const QList<QPlace> &favoritePlaces)
858 const int oldRowCount = rowCount();
862 if (!m_resultsBuffer.size())
865 beginInsertRows(QModelIndex(), oldRowCount , oldRowCount + m_resultsBuffer.size() - 1);
866 m_results = resultsFromPages();
871 m_results = m_resultsBuffer;
874 m_resultsBuffer.clear();
875 for (qsizetype i = start; i < m_results.count(); ++i) {
876 const QPlaceSearchResult &result = m_results.at(i);
878 if (result.type() == QPlaceSearchResult::PlaceResult) {
879 QPlaceResult placeResult = result;
880 QDeclarativePlace *place =
new QDeclarativePlace(placeResult.place(), plugin(),
this);
881 m_places.append(place);
883 if ((favoritePlaces.count() == m_results.count()) && favoritePlaces.at(i) != QPlace())
884 m_places[i]->setFavorite(
new QDeclarativePlace(favoritePlaces.at(i),
885 m_favoritesPlugin, m_places[i]));
886 }
else if (result.type() == QPlaceSearchResult::ProposedSearchResult) {
890 if (!result.icon().isEmpty())
891 m_icons.append(result.icon());
898 if (m_results.count() != oldRowCount)
899 emit rowCountChanged();
903
904
905void QDeclarativeSearchResultModel::placeUpdated(
const QString &placeId)
907 int row = getRow(placeId);
908 if (row < 0 || row > m_places.count())
911 if (m_places.at(row))
912 m_places.at(row)->getDetails();
916
917
918void QDeclarativeSearchResultModel::placeRemoved(
const QString &placeId)
920 int row = getRow(placeId);
921 if (row < 0 || row > m_places.count())
924 beginRemoveRows(QModelIndex(), row, row);
925 delete m_places.at(row);
926 m_places.removeAt(row);
927 m_results.removeAt(row);
931 emit rowCountChanged();
934QList<QPlaceSearchResult> QDeclarativeSearchResultModel::resultsFromPages()
const
936 QList<QPlaceSearchResult> res;
937 for (
const auto &e : m_pages)
942void QDeclarativeSearchResultModel::removePageRow(
int row)
945 for (
auto i = m_pages.begin(), end = m_pages.end(); i != end; ++i) {
946 QList<QPlaceSearchResult> &page = i.value();
947 scanned += page.size();
950 page.removeAt(row - scanned + page.size());
956
957
958int QDeclarativeSearchResultModel::getRow(
const QString &placeId)
const
960 for (qsizetype i = 0; i < m_places.count(); ++i) {
963 else if (m_places.at(i)->placeId() == placeId)
971
972
973
974
975
976
977
978
979
980
981