8#include <QtCore/private/qobject_p.h>
10#include <QCoreApplication>
11#include <QtQml/QQmlInfo>
12#include <QtLocation/QPlaceManager>
13#include <QtLocation/QPlaceIcon>
18
19
20
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
61
62
63
64
67
68
69
70
71
74
75
76
77
78
81
82
83
84
85
86
87
88
91
92
93
94
95
96
97
100
101
102
104QDeclarativeSupportedCategoriesModel::QDeclarativeSupportedCategoriesModel(QObject *parent)
105 : QAbstractItemModel(parent)
109QDeclarativeSupportedCategoriesModel::~QDeclarativeSupportedCategoriesModel()
111 qDeleteAll(m_categoriesTree);
115
116
118void QDeclarativeSupportedCategoriesModel::componentComplete()
126
127
128int QDeclarativeSupportedCategoriesModel::rowCount(
const QModelIndex &parent)
const
130 if (m_categoriesTree.keys().isEmpty())
133 PlaceCategoryNode *node =
static_cast<PlaceCategoryNode *>(parent.internalPointer());
135 node = m_categoriesTree.value(QString());
136 else if (m_categoriesTree.keys(node).isEmpty())
139 return node->childIds.count();
143
144
145int QDeclarativeSupportedCategoriesModel::columnCount(
const QModelIndex &parent)
const
153
154
155QModelIndex QDeclarativeSupportedCategoriesModel::index(
int row,
int column,
const QModelIndex &parent)
const
157 if (column != 0 || row < 0)
158 return QModelIndex();
160 PlaceCategoryNode *node =
static_cast<PlaceCategoryNode *>(parent.internalPointer());
163 node = m_categoriesTree.value(QString());
164 else if (m_categoriesTree.keys(node).isEmpty())
165 return QModelIndex();
167 if (row > node->childIds.count())
168 return QModelIndex();
170 QString id = node->childIds.at(row);
171 Q_ASSERT(m_categoriesTree.contains(id));
173 return createIndex(row, 0, m_categoriesTree.value(id));
177
178
179QModelIndex QDeclarativeSupportedCategoriesModel::parent(
const QModelIndex &child)
const
181 PlaceCategoryNode *childNode =
static_cast<PlaceCategoryNode *>(child.internalPointer());
182 if (m_categoriesTree.keys(childNode).isEmpty())
183 return QModelIndex();
185 return index(childNode->parentId);
189
190
191QVariant QDeclarativeSupportedCategoriesModel::data(
const QModelIndex &index,
int role)
const
193 PlaceCategoryNode *node =
static_cast<PlaceCategoryNode *>(index.internalPointer());
195 node = m_categoriesTree.value(QString());
196 else if (m_categoriesTree.keys(node).isEmpty())
199 QDeclarativeCategory *category = node->declCategory.data();
202 case Qt::DisplayRole:
203 return category->name();
205 return QVariant::fromValue(category);
206 case ParentCategoryRole: {
207 if (!m_categoriesTree.keys().contains(node->parentId))
210 return QVariant::fromValue(m_categoriesTree.value(node->parentId)->declCategory.data());
217QHash<
int, QByteArray> QDeclarativeSupportedCategoriesModel::roleNames()
const
219 QHash<
int, QByteArray> roles = QAbstractItemModel::roleNames();
220 roles.insert(CategoryRole,
"category");
221 roles.insert(ParentCategoryRole,
"parentCategory");
226
227
228void QDeclarativeSupportedCategoriesModel::setPlugin(QDeclarativeGeoServiceProvider *plugin)
230 if (m_plugin == plugin)
235 disconnect(m_plugin,
nullptr,
this,
nullptr);
236 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
237 if (serviceProvider) {
238 QPlaceManager *placeManager = serviceProvider->placeManager();
240 disconnect(placeManager, &QPlaceManager::categoryAdded,
241 this, &QDeclarativeSupportedCategoriesModel::addedCategory);
242 disconnect(placeManager, &QPlaceManager::categoryUpdated,
243 this, &QDeclarativeSupportedCategoriesModel::updatedCategory);
244 disconnect(placeManager, &QPlaceManager::categoryRemoved,
245 this, &QDeclarativeSupportedCategoriesModel::removedCategory);
246 disconnect(placeManager, &QPlaceManager::dataChanged,
247 this, &QDeclarativeSupportedCategoriesModel::emitDataChanged);
256 if (m_plugin->isAttached()) {
257 connectNotificationSignals();
260 connect(m_plugin, &QDeclarativeGeoServiceProvider::attached,
261 this, &QDeclarativeSupportedCategoriesModel::update);
262 connect(m_plugin, &QDeclarativeGeoServiceProvider::attached,
263 this, &QDeclarativeSupportedCategoriesModel::connectNotificationSignals);
268 emit pluginChanged();
272
273
274QDeclarativeGeoServiceProvider *QDeclarativeSupportedCategoriesModel::plugin()
const
280
281
282void QDeclarativeSupportedCategoriesModel::setHierarchical(
bool hierarchical)
284 if (m_hierarchical == hierarchical)
287 m_hierarchical = hierarchical;
288 emit hierarchicalChanged();
294
295
296bool QDeclarativeSupportedCategoriesModel::hierarchical()
const
298 return m_hierarchical;
302
303
304void QDeclarativeSupportedCategoriesModel::replyFinished()
309 m_response->deleteLater();
311 if (m_response->error() == QPlaceReply::NoError) {
312 m_errorString.clear();
314 m_response =
nullptr;
317 setStatus(QDeclarativeSupportedCategoriesModel::Ready);
319 const QString errorString = m_response->errorString();
321 m_response =
nullptr;
323 setStatus(Error, errorString);
328
329
330void QDeclarativeSupportedCategoriesModel::addedCategory(
const QPlaceCategory &category,
331 const QString &parentId)
336 if (!m_categoriesTree.contains(parentId))
339 if (category.categoryId().isEmpty())
342 PlaceCategoryNode *parentNode = m_categoriesTree.value(parentId);
346 int rowToBeAdded = rowToAddChild(parentNode, category);
347 QModelIndex parentIndex = index(parentId);
348 beginInsertRows(parentIndex, rowToBeAdded, rowToBeAdded);
349 PlaceCategoryNode *categoryNode =
new PlaceCategoryNode;
350 categoryNode->parentId = parentId;
351 categoryNode->declCategory = QSharedPointer<QDeclarativeCategory>(
new QDeclarativeCategory(category, m_plugin,
this));
353 m_categoriesTree.insert(category.categoryId(), categoryNode);
354 parentNode->childIds.insert(rowToBeAdded,category.categoryId());
364
365
366void QDeclarativeSupportedCategoriesModel::updatedCategory(
const QPlaceCategory &category,
367 const QString &parentId)
372 QString categoryId = category.categoryId();
374 if (!m_categoriesTree.contains(parentId))
377 if (category.categoryId().isEmpty() || !m_categoriesTree.contains(categoryId))
380 PlaceCategoryNode *newParentNode = m_categoriesTree.value(parentId);
384 PlaceCategoryNode *categoryNode = m_categoriesTree.value(categoryId);
388 categoryNode->declCategory->setCategory(category);
390 if (categoryNode->parentId == parentId) {
391 QModelIndex parentIndex = index(parentId);
392 int rowToBeAdded = rowToAddChild(newParentNode, category);
393 int oldRow = newParentNode->childIds.indexOf(categoryId);
396 if (qAbs(rowToBeAdded - newParentNode->childIds.indexOf(categoryId)) > 1) {
398 beginMoveRows(parentIndex, oldRow, oldRow,
399 parentIndex, rowToBeAdded);
401 newParentNode->childIds.removeAll(categoryId);
402 newParentNode->childIds.insert(rowToBeAdded, categoryId);
405 QModelIndex categoryIndex = index(categoryId);
406 emit dataChanged(categoryIndex, categoryIndex);
409 QPlaceCategory oldCategory = categoryNode->declCategory->category();
410 PlaceCategoryNode *oldParentNode = m_categoriesTree.value(categoryNode->parentId);
413 QModelIndex oldParentIndex = index(categoryNode->parentId);
414 QModelIndex newParentIndex = index(parentId);
416 int rowToBeAdded = rowToAddChild(newParentNode, category);
417 beginMoveRows(oldParentIndex, oldParentNode->childIds.indexOf(categoryId),
418 oldParentNode->childIds.indexOf(categoryId), newParentIndex, rowToBeAdded);
419 oldParentNode->childIds.removeAll(oldCategory.categoryId());
420 newParentNode->childIds.insert(rowToBeAdded, categoryId);
421 categoryNode->parentId = parentId;
432
433
434void QDeclarativeSupportedCategoriesModel::removedCategory(
const QString &categoryId,
const QString &parentId)
439 if (!m_categoriesTree.contains(categoryId) || !m_categoriesTree.contains(parentId))
442 QModelIndex parentIndex = index(parentId);
443 QModelIndex categoryIndex = index(categoryId);
445 beginRemoveRows(parentIndex, categoryIndex.row(), categoryIndex.row());
446 PlaceCategoryNode *parentNode = m_categoriesTree.value(parentId);
447 parentNode->childIds.removeAll(categoryId);
448 delete m_categoriesTree.take(categoryId);
453
454
455void QDeclarativeSupportedCategoriesModel::connectNotificationSignals()
460 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
461 if (!serviceProvider || serviceProvider->error() != QGeoServiceProvider::NoError)
464 QPlaceManager *placeManager = serviceProvider->placeManager();
470 connect(placeManager, &QPlaceManager::categoryAdded,
471 this, &QDeclarativeSupportedCategoriesModel::addedCategory);
472 connect(placeManager, &QPlaceManager::categoryUpdated,
473 this, &QDeclarativeSupportedCategoriesModel::updatedCategory);
474 connect(placeManager, &QPlaceManager::categoryRemoved,
475 this, &QDeclarativeSupportedCategoriesModel::removedCategory);
476 connect(placeManager, &QPlaceManager::dataChanged,
477 this, &QDeclarativeSupportedCategoriesModel::emitDataChanged);
481
482
483void QDeclarativeSupportedCategoriesModel::update()
495 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROPERTY_NOT_SET));
499 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
500 if (!serviceProvider || serviceProvider->error() != QGeoServiceProvider::NoError) {
502 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROVIDER_ERROR)
503 .arg(m_plugin->name()));
507 QPlaceManager *placeManager = serviceProvider->placeManager();
510 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
511 .arg(m_plugin->name()).arg(serviceProvider->errorString()));
515 m_response = placeManager->initializeCategories();
517 connect(m_response, &QPlaceReply::finished,
518 this, &QDeclarativeSupportedCategoriesModel::replyFinished);
521 setStatus(Error, QCoreApplication::translate(CONTEXT_NAME,
522 CATEGORIES_NOT_INITIALIZED));
527
528
529void QDeclarativeSupportedCategoriesModel::updateLayout()
532 qDeleteAll(m_categoriesTree);
533 m_categoriesTree.clear();
536 QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
537 if (serviceProvider && serviceProvider->error() == QGeoServiceProvider::NoError) {
538 QPlaceManager *placeManager = serviceProvider->placeManager();
540 PlaceCategoryNode *node =
new PlaceCategoryNode;
541 node->childIds = populateCategories(placeManager, QPlaceCategory());
542 m_categoriesTree.insert(QString(), node);
543 node->declCategory = QSharedPointer<QDeclarativeCategory>
544 (
new QDeclarativeCategory(QPlaceCategory(), m_plugin,
this));
552QString QDeclarativeSupportedCategoriesModel::errorString()
const
554 return m_errorString;
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579void QDeclarativeSupportedCategoriesModel::setStatus(Status status,
const QString &errorString)
581 Status originalStatus = m_status;
583 m_errorString = errorString;
585 if (originalStatus != m_status)
586 emit statusChanged();
589QDeclarativeSupportedCategoriesModel::Status QDeclarativeSupportedCategoriesModel::status()
const
595
596
597QStringList QDeclarativeSupportedCategoriesModel::populateCategories(QPlaceManager *manager,
const QPlaceCategory &parent)
601 QStringList childIds;
603 const auto byName = [](
const QPlaceCategory &lhs,
const QPlaceCategory &rhs) {
604 return lhs.name() < rhs.name();
607 auto categories = manager->childCategories(parent.categoryId());
608 std::sort(categories.begin(), categories.end(), byName);
610 for (
const auto &category : std::as_const(categories)) {
611 auto node =
new PlaceCategoryNode;
612 node->parentId = parent.categoryId();
613 node->declCategory = QSharedPointer<QDeclarativeCategory>(
new QDeclarativeCategory(category, m_plugin ,
this));
616 node->childIds = populateCategories(manager, category);
618 m_categoriesTree.insert(node->declCategory->categoryId(), node);
619 childIds.append(category.categoryId());
621 if (!m_hierarchical) {
622 childIds.append(populateCategories(manager,node->declCategory->category()));
629
630
631QModelIndex QDeclarativeSupportedCategoriesModel::index(
const QString &categoryId)
const
633 if (categoryId.isEmpty())
634 return QModelIndex();
636 if (!m_categoriesTree.contains(categoryId))
637 return QModelIndex();
639 PlaceCategoryNode *categoryNode = m_categoriesTree.value(categoryId);
641 return QModelIndex();
643 QString parentCategoryId = categoryNode->parentId;
645 PlaceCategoryNode *parentNode = m_categoriesTree.value(parentCategoryId);
647 return createIndex(parentNode->childIds.indexOf(categoryId), 0, categoryNode);
651
652
653int QDeclarativeSupportedCategoriesModel::rowToAddChild(PlaceCategoryNode *node,
const QPlaceCategory &category)
656 for (qsizetype i = 0; i < node->childIds.count(); ++i) {
657 if (category.name() < m_categoriesTree.value(node->childIds.at(i))->declCategory->name())
660 return node->childIds.count();
664
665
666
667
668
669
670
671
672
673
674