7#include <QtQml/QQmlEngine>
8#include <QtQml/QQmlInfo>
9#include <QtLocation/QGeoServiceProvider>
10#include <QtLocation/QPlaceSearchReply>
11#include <QtLocation/QPlaceManager>
12#include <QtLocation/QPlaceMatchRequest>
13#include <QtLocation/QPlaceMatchReply>
14#include <QtLocation/QPlaceResult>
15#include <QtLocation/QPlaceProposedSearchResult>
16#include <QtLocation/private/qplacesearchrequest_p.h>
21
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
137
138
139
140
143
144
145
146
147
148
149
150
151
152
153
154
157
158
159
160
161
162
163
164
165
166
167
168
169
172
173
174
175
176
177
178
179
180
181
182
183
184
187
188
189
190
193
194
195
196
197
198
201
202
203
204
205
206
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
230
231
232
233
234
235
236
237
238
242
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
279
280
281
282
283
284
285
286
287
288
291
292
293
294
295
298
299
300
301
302
303
304
305
308
309
310
311
312
315
316
317
318
319
321QDeclarativeSearchResultModel::QDeclarativeSearchResultModel(QObject *parent)
322 : QDeclarativeSearchModelBase(parent)
326QDeclarativeSearchResultModel::~QDeclarativeSearchResultModel()
331
332
333
334
335QString QDeclarativeSearchResultModel::searchTerm()
const
337 return m_request.searchTerm();
340void QDeclarativeSearchResultModel::setSearchTerm(
const QString &searchTerm)
342 m_request.setSearchContext(QVariant());
344 if (m_request.searchTerm() == searchTerm)
347 m_request.setSearchTerm(searchTerm);
348 emit searchTermChanged();
352
353
354
355
356
357QQmlListProperty<QDeclarativeCategory> QDeclarativeSearchResultModel::categories()
359 return QQmlListProperty<QDeclarativeCategory>(
this,
367void QDeclarativeSearchResultModel::categories_append(QQmlListProperty<QDeclarativeCategory> *list,
368 QDeclarativeCategory *declCategory)
370 QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
371 if (searchModel && declCategory) {
372 searchModel->m_request.setSearchContext(QVariant());
373 searchModel->m_categories.append(declCategory);
374 QList<QPlaceCategory> categories = searchModel->m_request.categories();
375 categories.append(declCategory->category());
376 searchModel->m_request.setCategories(categories);
377 emit searchModel->categoriesChanged();
381qsizetype QDeclarativeSearchResultModel::categories_count(QQmlListProperty<QDeclarativeCategory> *list)
383 QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
385 return searchModel->m_categories.count();
390QDeclarativeCategory *QDeclarativeSearchResultModel::category_at(QQmlListProperty<QDeclarativeCategory> *list,
393 QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
394 if (searchModel && (searchModel->m_categories.count() > index) && (index > -1))
395 return searchModel->m_categories.at(index);
399void QDeclarativeSearchResultModel::categories_clear(QQmlListProperty<QDeclarativeCategory> *list)
401 QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
405 searchModel->m_request.setSearchContext(QVariant());
406 searchModel->m_categories.clear();
407 searchModel->m_request.setCategories(QList<QPlaceCategory>());
408 emit searchModel->categoriesChanged();
413
414
415
416
417
418QString QDeclarativeSearchResultModel::recommendationId()
const
420 return m_request.recommendationId();
423void QDeclarativeSearchResultModel::setRecommendationId(
const QString &placeId)
425 if (m_request.recommendationId() == placeId)
428 m_request.setRecommendationId(placeId);
429 emit recommendationIdChanged();
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454QDeclarativeSearchResultModel::RelevanceHint QDeclarativeSearchResultModel::relevanceHint()
const
456 return static_cast<QDeclarativeSearchResultModel::RelevanceHint>(m_request.relevanceHint());
459void QDeclarativeSearchResultModel::setRelevanceHint(QDeclarativeSearchResultModel::RelevanceHint hint)
461 if (m_request.relevanceHint() !=
static_cast<QPlaceSearchRequest::RelevanceHint>(hint)) {
462 m_request.setRelevanceHint(
static_cast<QPlaceSearchRequest::RelevanceHint>(hint));
463 emit relevanceHintChanged();
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491QDeclarativePlace::Visibility QDeclarativeSearchResultModel::visibilityScope()
const
493 return QDeclarativePlace::Visibility(
int(m_visibilityScope));
496void QDeclarativeSearchResultModel::setVisibilityScope(QDeclarativePlace::Visibility visibilityScope)
498 QLocation::VisibilityScope scope = QLocation::VisibilityScope(visibilityScope);
500 if (m_visibilityScope == scope)
503 m_visibilityScope = scope;
504 emit visibilityScopeChanged();
508
509
510QDeclarativeGeoServiceProvider *QDeclarativeSearchResultModel::favoritesPlugin()
const
512 return m_favoritesPlugin;
516
517
518void QDeclarativeSearchResultModel::setFavoritesPlugin(QDeclarativeGeoServiceProvider *plugin)
521 if (m_favoritesPlugin == plugin)
524 m_favoritesPlugin = plugin;
526 if (m_favoritesPlugin) {
527 QGeoServiceProvider *serviceProvider = m_favoritesPlugin->sharedGeoServiceProvider();
528 if (serviceProvider) {
529 QPlaceManager *placeManager = serviceProvider->placeManager();
531 if (placeManager->childCategoryIds().isEmpty()) {
532 QPlaceReply *reply = placeManager->initializeCategories();
533 connect(reply, &QPlaceReply::finished, reply, &QObject::deleteLater);
539 emit favoritesPluginChanged();
543
544
545QVariantMap QDeclarativeSearchResultModel::favoritesMatchParameters()
const
547 return m_matchParameters;
551
552
553void QDeclarativeSearchResultModel::setFavoritesMatchParameters(
const QVariantMap ¶meters)
555 if (m_matchParameters == parameters)
558 m_matchParameters = parameters;
559 emit favoritesMatchParametersChanged();
563
564
565int QDeclarativeSearchResultModel::rowCount(
const QModelIndex &parent)
const
569 return m_results.count();
572void QDeclarativeSearchResultModel::clearData(
bool suppressSignal)
574 QDeclarativeSearchModelBase::clearData(suppressSignal);
576 qDeleteAll(m_places);
579 if (!m_results.isEmpty()) {
583 emit rowCountChanged();
587QVariant QDeclarativeSearchResultModel::data(
const QModelIndex &index,
int role)
const
589 if (index.row() > m_results.count())
592 const QPlaceSearchResult &result = m_results.at(index.row());
595 case SearchResultTypeRole:
596 return result.type();
597 case Qt::DisplayRole:
599 return result.title();
601 return QVariant::fromValue(m_icons.at(index.row()));
603 if (result.type() == QPlaceSearchResult::PlaceResult) {
604 QPlaceResult placeResult = result;
605 return placeResult.distance();
609 if (result.type() == QPlaceSearchResult::PlaceResult)
610 return QVariant::fromValue(
static_cast<QObject *>(m_places.at(index.row())));
613 if (result.type() == QPlaceSearchResult::PlaceResult) {
614 QPlaceResult placeResult = result;
615 return placeResult.isSponsored();
623
624
625QVariant QDeclarativeSearchResultModel::data(
int index,
const QString &role)
const
627 QModelIndex modelIndex = createIndex(index, 0);
628 return data(modelIndex, roleNames().key(role.toLatin1()));
631QHash<
int, QByteArray> QDeclarativeSearchResultModel::roleNames()
const
633 QHash<
int, QByteArray> roles = QDeclarativeSearchModelBase::roleNames();
634 roles.insert(SearchResultTypeRole,
"type");
635 roles.insert(TitleRole,
"title");
636 roles.insert(IconRole,
"icon");
637 roles.insert(DistanceRole,
"distance");
638 roles.insert(PlaceRole,
"place");
639 roles.insert(SponsoredRole,
"sponsored");
645
646
647
648
649
650
651
652
653
654
655void QDeclarativeSearchResultModel::updateWith(
int proposedSearchIndex)
657 if (m_results.at(proposedSearchIndex).type() != QPlaceSearchResult::ProposedSearchResult)
660 m_request = QPlaceProposedSearchResult(m_results.at(proposedSearchIndex)).searchRequest();
664QPlaceReply *QDeclarativeSearchResultModel::sendQuery(QPlaceManager *manager,
665 const QPlaceSearchRequest &request)
668 return manager->search(request);
672
673
674void QDeclarativeSearchResultModel::initializePlugin(QDeclarativeGeoServiceProvider *plugin)
678 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
679 if (serviceProvider) {
680 QPlaceManager *placeManager = serviceProvider->placeManager();
682 disconnect(placeManager, &QPlaceManager::placeUpdated,
683 this, &QDeclarativeSearchResultModel::placeUpdated);
684 disconnect(placeManager, &QPlaceManager::placeRemoved,
685 this, &QDeclarativeSearchResultModel::placeRemoved);
686 connect(placeManager, &QPlaceManager::dataChanged,
687 this, &QDeclarativeSearchResultModel::dataChanged);
694 QGeoServiceProvider *serviceProvider = plugin->sharedGeoServiceProvider();
695 if (serviceProvider) {
696 QPlaceManager *placeManager = serviceProvider->placeManager();
698 connect(placeManager, &QPlaceManager::placeUpdated,
699 this, &QDeclarativeSearchResultModel::placeUpdated);
700 connect(placeManager, &QPlaceManager::placeRemoved,
701 this, &QDeclarativeSearchResultModel::placeRemoved);
702 disconnect(placeManager, &QPlaceManager::dataChanged,
703 this, &QDeclarativeSearchResultModel::dataChanged);
707 QDeclarativeSearchModelBase::initializePlugin(plugin);
711
712
713void QDeclarativeSearchResultModel::queryFinished()
717 QPlaceReply *reply = m_reply;
719 reply->deleteLater();
724 if (reply->error() != QPlaceReply::NoError) {
725 m_resultsBuffer.clear();
727 setStatus(Error, reply->errorString());
731 if (reply->type() == QPlaceReply::SearchReply) {
732 QPlaceSearchReply *searchReply = qobject_cast<QPlaceSearchReply *>(reply);
733 Q_ASSERT(searchReply);
735 const QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(searchReply->request());
736 if (!rpimpl->related || !m_incremental)
738 m_resultsBuffer = searchReply->results();
739 bool alreadyLoaded =
false;
740 if (m_pages.contains(rpimpl->page) && m_resultsBuffer == m_pages.value(rpimpl->page))
741 alreadyLoaded =
true;
742 m_pages.insert(rpimpl->page, m_resultsBuffer);
743 setPreviousPageRequest(searchReply->previousPageRequest());
744 setNextPageRequest(searchReply->nextPageRequest());
747 if (!m_favoritesPlugin) {
751 QGeoServiceProvider *serviceProvider = m_favoritesPlugin->sharedGeoServiceProvider();
752 if (!serviceProvider) {
754 setStatus(Error, QStringLiteral(
"Favorites plugin returns a null QGeoServiceProvider instance"));
758 QPlaceManager *favoritesManager = serviceProvider->placeManager();
759 if (!favoritesManager) {
761 setStatus(Error, QStringLiteral(
"Favorites plugin returns a null QPlaceManager"));
765 QPlaceMatchRequest request;
766 if (m_matchParameters.isEmpty()) {
768 setStatus(Error, QStringLiteral(
"Plugin not assigned"));
773 params.insert(QPlaceMatchRequest::AlternativeId, QVariant(QString::fromLatin1(
"x_id_") + m_plugin->name()));
774 request.setParameters(params);
776 request.setParameters(m_matchParameters);
779 request.setResults(m_resultsBuffer);
781 m_resultsBuffer.clear();
782 m_reply = favoritesManager->matchingPlaces(request);
783 connect(m_reply, &QPlaceReply::finished,
784 this, &QDeclarativeSearchResultModel::queryFinished);
785 connect(m_reply, &QPlaceReply::contentUpdated,
786 this, &QDeclarativeSearchResultModel::onContentUpdated);
788 }
else if (reply->type() == QPlaceReply::MatchReply) {
789 QPlaceMatchReply *matchReply = qobject_cast<QPlaceMatchReply *>(reply);
790 Q_ASSERT(matchReply);
791 updateLayout(matchReply->places());
794 setStatus(Error, QStringLiteral(
"Unknown reply type"));
798void QDeclarativeSearchResultModel::onContentUpdated()
803 QPlaceReply *reply = m_reply;
808 if (reply->error() != QPlaceReply::NoError) {
809 m_resultsBuffer.clear();
811 setStatus(Error, reply->errorString());
815 if (reply->type() == QPlaceReply::SearchReply) {
816 QPlaceSearchReply *searchReply = qobject_cast<QPlaceSearchReply *>(reply);
817 Q_ASSERT(searchReply);
819 const QPlaceSearchRequestPrivate *rpimpl = QPlaceSearchRequestPrivate::get(searchReply->request());
820 if (!rpimpl->related || !m_incremental)
822 m_resultsBuffer = searchReply->results();
823 if (!(m_pages.contains(rpimpl->page) && m_resultsBuffer == m_pages.value(rpimpl->page))) {
824 m_pages.insert(rpimpl->page, m_resultsBuffer);
827 }
else if (reply->type() == QPlaceReply::MatchReply) {
830 setStatus(Error, QStringLiteral(
"Unknown reply type"));
835
836
837
838
841
842
843
844
845
846
847
848
851
852
853
854
855void QDeclarativeSearchResultModel::updateLayout(
const QList<QPlace> &favoritePlaces)
857 const int oldRowCount = rowCount();
861 if (!m_resultsBuffer.size())
864 beginInsertRows(QModelIndex(), oldRowCount , oldRowCount + m_resultsBuffer.size() - 1);
865 m_results = resultsFromPages();
870 m_results = m_resultsBuffer;
873 m_resultsBuffer.clear();
874 for (qsizetype i = start; i < m_results.count(); ++i) {
875 const QPlaceSearchResult &result = m_results.at(i);
877 if (result.type() == QPlaceSearchResult::PlaceResult) {
878 QPlaceResult placeResult = result;
879 QDeclarativePlace *place =
new QDeclarativePlace(placeResult.place(), plugin(),
this);
880 m_places.append(place);
882 if ((favoritePlaces.count() == m_results.count()) && favoritePlaces.at(i) != QPlace())
883 m_places[i]->setFavorite(
new QDeclarativePlace(favoritePlaces.at(i),
884 m_favoritesPlugin, m_places[i]));
885 }
else if (result.type() == QPlaceSearchResult::ProposedSearchResult) {
889 if (!result.icon().isEmpty())
890 m_icons.append(result.icon());
897 if (m_results.count() != oldRowCount)
898 emit rowCountChanged();
902
903
904void QDeclarativeSearchResultModel::placeUpdated(
const QString &placeId)
906 int row = getRow(placeId);
907 if (row < 0 || row > m_places.count())
910 if (m_places.at(row))
911 m_places.at(row)->getDetails();
915
916
917void QDeclarativeSearchResultModel::placeRemoved(
const QString &placeId)
919 int row = getRow(placeId);
920 if (row < 0 || row > m_places.count())
923 beginRemoveRows(QModelIndex(), row, row);
924 delete m_places.at(row);
925 m_places.removeAt(row);
926 m_results.removeAt(row);
930 emit rowCountChanged();
933QList<QPlaceSearchResult> QDeclarativeSearchResultModel::resultsFromPages()
const
935 QList<QPlaceSearchResult> res;
936 for (
const auto &e : m_pages)
941void QDeclarativeSearchResultModel::removePageRow(
int row)
944 for (
auto i = m_pages.begin(), end = m_pages.end(); i != end; ++i) {
945 QList<QPlaceSearchResult> &page = i.value();
946 scanned += page.size();
949 page.removeAt(row - scanned + page.size());
955
956
957int QDeclarativeSearchResultModel::getRow(
const QString &placeId)
const
959 for (qsizetype i = 0; i < m_places.count(); ++i) {
962 else if (m_places.at(i)->placeId() == placeId)
970
971
972
973
974
975
976
977
978
979
980