summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAaron McCarthy <aaron.mccarthy@nokia.com>2011-08-12 11:34:01 +1000
committerAaron McCarthy <aaron.mccarthy@nokia.com>2011-08-15 09:54:32 +0200
commit4f2581c853ac01a6874b7987c5513a6157e22f9d (patch)
tree37e2fa13bfd82ddb85facd29618c9b96c27e5ea2 /src
parent02e9bc25bf811caf1b21c5ae575b0dd94e147341 (diff)
downloadqtlocation-4f2581c853ac01a6874b7987c5513a6157e22f9d.tar.gz
Hierarchical categories.
Change-Id: I5028f4a617128bb9fa95ea94efe4b1ac8722dbb2 Reviewed-on: http://codereview.qt.nokia.com/2923 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Aaron McCarthy <aaron.mccarthy@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp279
-rw-r--r--src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h42
-rw-r--r--src/location/places/qplacemanager.cpp7
-rw-r--r--src/location/places/qplacemanager.h2
-rw-r--r--src/location/places/qplacemanagerengine.h2
-rw-r--r--src/plugins/geoservices/nokia/places/places.pri8
-rw-r--r--src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.cpp11
-rw-r--r--src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.h5
-rw-r--r--src/plugins/geoservices/nokia/places/qplacecategoriesrepository.cpp16
-rw-r--r--src/plugins/geoservices/nokia/places/qplacecategoriesrepository.h4
-rw-r--r--src/plugins/geoservices/nokia/places/qplacecategorytree.cpp114
-rw-r--r--src/plugins/geoservices/nokia/places/qplacecategorytree.h63
-rw-r--r--src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.cpp121
-rw-r--r--src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.h15
-rw-r--r--src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp2
-rw-r--r--src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp16
-rw-r--r--src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h2
17 files changed, 510 insertions, 199 deletions
diff --git a/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
index 580e0602..9046b49b 100644
--- a/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
+++ b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
@@ -9,25 +9,25 @@ QT_USE_NAMESPACE
/*!
\qmlclass SupportedCategoryModel QDeclarativeSupportedCategoriesModel
- \brief The SupportedCategoryModel element provides access to suported categories list.
+ \brief The SupportedCategoryModel element provides access to supported categories list.
\inherits QAbstractListModel
\ingroup qml-places
+ \since QtLocation 5.0
- SupportedCategoryModel provides a model of categories from the supported categories list.
- The contents of the model can contains parent categories. All categories might have childrens.
+ SupportedCategoryModel provides a model of categories from the supported categories list. The
+ model can provide both a flat list of categories or a hierarchical tree representing category
+ grouping. This can be controlled by the \l hierarchy property.
- There are two ways of accessing the category data: through model by using views and delegates,
- or alternatively via \l category list property. Of the two, the model access is preferred.
-
- At the moment only data role provided by the model is \c category (\l Category).
- Through that one can access any data provided by the Category element.
+ The model provides a single data role, \c category (\l Category).
To use SupportedCategoryModel user need to create it in qml file and connect it to some view
\code
- import places 1.0
+ import QtQuick 2.0
+ import Qt.location 5.0
SupportedCategoriesModel {
id: categoriesModel
+ hierarchical: false
}
ListView {
@@ -39,14 +39,36 @@ QT_USE_NAMESPACE
}
\endcode
+ To access the hierarchical category model it is necessary to use a VisualDataModel to access
+ the child items.
+
\sa SearchResultModel, SuggestionModel, {QPlaceManager}
*/
+
+/*!
+ \qmlproperty Plugin SupportedCategoriesModel::plugin
+
+ this property holds the provider Plugin used by this model.
+*/
+
+/*!
+ \qmlproperty bool SupportedCategoriesModel::hierarchical
+
+ This property holds whether the model provides a hierarchical tree of categories or a flat
+ list. The default is true.
+*/
+
+PlaceCategoryTree::PlaceCategoryTree()
+{
+}
+
+PlaceCategoryTree::~PlaceCategoryTree()
+{
+}
+
QDeclarativeSupportedCategoriesModel::QDeclarativeSupportedCategoriesModel(QObject *parent)
-: QAbstractListModel(parent), m_plugin(0), m_complete(false)
+: QAbstractItemModel(parent), m_plugin(0), m_hierarchical(true), m_complete(false)
{
-#if defined(QT_PLACESPLUGIN_LOGGING)
- qDebug() << "QDeclarativeSupportedCategoriesModel::QDeclarativeSupportedCategoriesModel";
-#endif
QHash<int, QByteArray> roleNames;
roleNames = QAbstractItemModel::roleNames();
roleNames.insert(CategoryRole, "category");
@@ -55,13 +77,6 @@ QDeclarativeSupportedCategoriesModel::QDeclarativeSupportedCategoriesModel(QObje
QDeclarativeSupportedCategoriesModel::~QDeclarativeSupportedCategoriesModel()
{
-#if defined(QT_PLACESPLUGIN_LOGGING)
- qDebug() << "QDeclarativeSupportedCategoriesModel::~QDeclarativeSupportedCategoriesModel";
-#endif
- foreach (const QString id, m_categoryMap.keys()) {
- delete m_categoryMap.value(id);
- m_categoryMap.remove(id);
- }
}
// From QDeclarativeParserStatus
@@ -70,41 +85,74 @@ void QDeclarativeSupportedCategoriesModel::componentComplete()
m_complete = true;
}
-/*!
- \qmlsignal SupportedCategoryModel::categoriesChanged()
+int QDeclarativeSupportedCategoriesModel::rowCount(const QModelIndex& parent) const
+{
+ PlaceCategoryTree tree = findCategoryTreeByCategory(static_cast<QDeclarativeCategory *>(parent.internalPointer()), m_categoryTree);
+ return tree.subCategories.count();
+}
- This handler is called when the list of categories is changed and
- client should take new data.
-*/
+int QDeclarativeSupportedCategoriesModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
-int QDeclarativeSupportedCategoriesModel::rowCount(const QModelIndex& parent) const
+ return 1;
+}
+
+QModelIndex QDeclarativeSupportedCategoriesModel::index(int row, int column, const QModelIndex &parent) const
{
- Q_UNUSED(parent);
- return m_categories.count();
+ if (column != 0 || row < 0)
+ return QModelIndex();
+
+ PlaceCategoryTree tree = findCategoryTreeByCategory(static_cast<QDeclarativeCategory *>(parent.internalPointer()), m_categoryTree);
+
+ if (row > tree.subCategories.count())
+ return QModelIndex();
+
+ QMap<QString, QDeclarativeCategory *> sortedCategories;
+ QHashIterator<QString, PlaceCategoryTree> it(tree.subCategories);
+ while (it.hasNext()) {
+ it.next();
+ sortedCategories.insert(it.value().category->name(), it.value().category.data());
+ }
+
+ return createIndex(row, 0, sortedCategories.values().at(row));
}
-QVariant QDeclarativeSupportedCategoriesModel::data(const QModelIndex& index, int role) const
+QModelIndex QDeclarativeSupportedCategoriesModel::parent(const QModelIndex &child) const
{
- QPlaceCategory item = m_categories[index.row()];
- QDeclarativeCategory *res = NULL;
- if (m_categoryMap.contains(item.categoryId())) {
- res = m_categoryMap[item.categoryId()];
+ QDeclarativeCategory *parentCategory = findParentCategoryByCategory(static_cast<QDeclarativeCategory *>(child.internalPointer()), m_categoryTree);
+ if (!parentCategory)
+ return QModelIndex();
+
+ QDeclarativeCategory *grandParentCategory = findParentCategoryByCategory(parentCategory, m_categoryTree);
+ PlaceCategoryTree tree = findCategoryTreeByCategory(grandParentCategory, m_categoryTree);
+
+ QMap<QString, QDeclarativeCategory *> sortedCategories;
+ QHashIterator<QString, PlaceCategoryTree> it(tree.subCategories);
+ while (it.hasNext()) {
+ it.next();
+ sortedCategories.insert(it.value().category->name(), it.value().category.data());
}
+
+ return createIndex(sortedCategories.values().indexOf(parentCategory), 0, parentCategory);
+}
+
+QVariant QDeclarativeSupportedCategoriesModel::data(const QModelIndex &index, int role) const
+{
+ PlaceCategoryTree tree = findCategoryTreeByCategory(static_cast<QDeclarativeCategory *>(index.internalPointer()), m_categoryTree);
+ QDeclarativeCategory *category = tree.category.data();
+
+ if (!category)
+ return QVariant();
+
switch (role) {
- case Qt::DisplayRole:
- if (res) {
- return res->name();
- } else {
- return QString();
- }
- case CategoryRole:
- if (res) {
- return QVariant::fromValue(res);
- } else {
- return QVariant();
- }
- }
- return QVariant();
+ case Qt::DisplayRole:
+ return category->name();
+ case CategoryRole:
+ return QVariant::fromValue(category);
+ default:
+ return QVariant();
+ }
}
void QDeclarativeSupportedCategoriesModel::setPlugin(QDeclarativeGeoServiceProvider *plugin)
@@ -123,8 +171,7 @@ void QDeclarativeSupportedCategoriesModel::setPlugin(QDeclarativeGeoServiceProvi
return;
}
- m_categories = placeManager->categories();
- convertCategoriesToDeclarative();
+ m_categoryTree.subCategories = populatedCategories(placeManager);
m_response = placeManager->initializeCategories();
if (m_response) {
@@ -139,49 +186,20 @@ QDeclarativeGeoServiceProvider* QDeclarativeSupportedCategoriesModel::plugin() c
return m_plugin;
}
-/*!
- \qmlproperty QDeclarativeListProperty SupportedCategoryModel::categories
-
- This element holds the list of \l Category elements that the model currently has.
-*/
-
-QDeclarativeListProperty<QDeclarativeCategory> QDeclarativeSupportedCategoriesModel::categories()
+void QDeclarativeSupportedCategoriesModel::setHierarchical(bool hierarchical)
{
- return QDeclarativeListProperty<QDeclarativeCategory>(this,
- 0, // opaque data parameter
- categories_append,
- categories_count,
- categories_at,
- categories_clear);
-}
+ if (m_hierarchical == hierarchical)
+ return;
-void QDeclarativeSupportedCategoriesModel::categories_append(QDeclarativeListProperty<QDeclarativeCategory> *prop,
- QDeclarativeCategory* category)
-{
- Q_UNUSED(prop);
- Q_UNUSED(category);
-}
+ m_hierarchical = hierarchical;
+ emit hierarchicalChanged();
-int QDeclarativeSupportedCategoriesModel::categories_count(QDeclarativeListProperty<QDeclarativeCategory> *prop)
-{
- return static_cast<QDeclarativeSupportedCategoriesModel*>(prop->object)->m_categories.count();
+ updateCategories();
}
-QDeclarativeCategory* QDeclarativeSupportedCategoriesModel::categories_at(QDeclarativeListProperty<QDeclarativeCategory> *prop,
- int index)
+bool QDeclarativeSupportedCategoriesModel::hierarchical() const
{
- QDeclarativeSupportedCategoriesModel* model = static_cast<QDeclarativeSupportedCategoriesModel*>(prop->object);
- QPlaceCategory item = model->m_categories[index];
- QDeclarativeCategory *res = NULL;
- if (model->m_categoryMap.contains(item.categoryId())) {
- res = model->m_categoryMap[item.categoryId()];
- }
- return res;
-}
-
-void QDeclarativeSupportedCategoriesModel::categories_clear(QDeclarativeListProperty<QDeclarativeCategory> *prop)
-{
- Q_UNUSED(prop)
+ return m_hierarchical;
}
void QDeclarativeSupportedCategoriesModel::replyFinished()
@@ -192,10 +210,20 @@ void QDeclarativeSupportedCategoriesModel::replyFinished()
m_response->deleteLater();
m_response = 0;
- if (!m_plugin) {
- qmlInfo(this) << "plugin not set.";
+ updateCategories();
+}
+
+void QDeclarativeSupportedCategoriesModel::replyError(QPlaceReply::Error error,
+ const QString &errorString)
+{
+ Q_UNUSED(error);
+ Q_UNUSED(errorString);
+}
+
+void QDeclarativeSupportedCategoriesModel::updateCategories()
+{
+ if (!m_plugin)
return;
- }
QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
if (!serviceProvider)
@@ -208,29 +236,72 @@ void QDeclarativeSupportedCategoriesModel::replyFinished()
}
beginResetModel();
- m_categories = placeManager->categories();
- convertCategoriesToDeclarative();
+ m_categoryTree.subCategories = populatedCategories(placeManager);
endResetModel();
- emit categoriesChanged();
}
-void QDeclarativeSupportedCategoriesModel::replyError(QPlaceReply::Error error,
- const QString &errorString)
+QHash<QString, PlaceCategoryTree> QDeclarativeSupportedCategoriesModel::populatedCategories(QPlaceManager *manager, const QPlaceCategory &parent)
{
- Q_UNUSED(error);
- Q_UNUSED(errorString);
+ QHash<QString, PlaceCategoryTree> declarativeTree;
+
+ foreach (const QPlaceCategory &category, manager->categories(parent)) {
+ PlaceCategoryTree dt;
+ dt.category = QSharedPointer<QDeclarativeCategory>(new QDeclarativeCategory(category, this));
+ if (m_hierarchical)
+ dt.subCategories = populatedCategories(manager, category);
+ declarativeTree.insert(category.categoryId(), dt);
+
+ if (!m_hierarchical) {
+ QHash<QString, PlaceCategoryTree> sub = populatedCategories(manager, category);
+ QHashIterator<QString, PlaceCategoryTree> it(sub);
+ while (it.hasNext()) {
+ it.next();
+ dt.category = QSharedPointer<QDeclarativeCategory>(it.value().category);
+ Q_ASSERT(it.value().subCategories.isEmpty());
+ declarativeTree.insert(it.key(), dt);
+ }
+ }
+ }
+
+ return declarativeTree;
}
-void QDeclarativeSupportedCategoriesModel::convertCategoriesToDeclarative()
+PlaceCategoryTree QDeclarativeSupportedCategoriesModel::findCategoryTreeByCategory(QDeclarativeCategory *category, const PlaceCategoryTree &tree) const
{
- foreach (const QString id, m_categoryMap.keys()) {
- delete m_categoryMap.value(id);
- m_categoryMap.remove(id);
+ if (tree.category == category)
+ return tree;
+
+ QHashIterator<QString, PlaceCategoryTree> it(tree.subCategories);
+ while (it.hasNext()) {
+ it.next();
+
+ if (it.value().category == category)
+ return it.value();
+
+ PlaceCategoryTree t = findCategoryTreeByCategory(category, it.value());
+ if (t.category == category)
+ return t;
}
- m_categoryMap.clear();
- foreach (const QPlaceCategory& category, m_categories) {
- QDeclarativeCategory* declarativeCategory = new QDeclarativeCategory(category, this);
- m_categoryMap.insert(category.categoryId(), declarativeCategory);
+ return PlaceCategoryTree();
+}
+
+QDeclarativeCategory *QDeclarativeSupportedCategoriesModel::findParentCategoryByCategory(QDeclarativeCategory *category, const PlaceCategoryTree &tree) const
+{
+ if (tree.category == category)
+ return 0;
+
+ QHashIterator<QString, PlaceCategoryTree> it(tree.subCategories);
+ while (it.hasNext()) {
+ it.next();
+
+ if (it.value().category == category)
+ return tree.category.data();
+
+ QDeclarativeCategory *p = findParentCategoryByCategory(category, it.value());
+ if (p)
+ return p;
}
+
+ return 0;
}
diff --git a/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h
index 6fefa00b..982c3352 100644
--- a/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h
+++ b/src/imports/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h
@@ -17,12 +17,22 @@ QT_BEGIN_NAMESPACE
class QGeoServiceProvider;
-class QDeclarativeSupportedCategoriesModel : public QAbstractListModel, public QDeclarativeParserStatus
+class PlaceCategoryTree
+{
+public:
+ PlaceCategoryTree();
+ ~PlaceCategoryTree();
+
+ QSharedPointer<QDeclarativeCategory> category;
+ QHash<QString, PlaceCategoryTree> subCategories;
+};
+
+class QDeclarativeSupportedCategoriesModel : public QAbstractItemModel, public QDeclarativeParserStatus
{
Q_OBJECT
Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged)
- Q_PROPERTY(QDeclarativeListProperty<QDeclarativeCategory> categories READ categories NOTIFY categoriesChanged)
+ Q_PROPERTY(bool hierarchical READ hierarchical WRITE setHierarchical NOTIFY hierarchicalChanged)
Q_INTERFACES(QDeclarativeParserStatus)
@@ -34,15 +44,13 @@ public:
virtual void classBegin() {}
virtual void componentComplete();
- QDeclarativeListProperty<QDeclarativeCategory> categories();
- static void categories_append(QDeclarativeListProperty<QDeclarativeCategory> *prop,
- QDeclarativeCategory* category);
- static int categories_count(QDeclarativeListProperty<QDeclarativeCategory> *prop);
- static QDeclarativeCategory* categories_at(QDeclarativeListProperty<QDeclarativeCategory> *prop, int index);
- static void categories_clear(QDeclarativeListProperty<QDeclarativeCategory> *prop);
-
- // From QAbstractListModel
+ // From QAbstractItemModel
int rowCount(const QModelIndex &parent) const;
+ int columnCount(const QModelIndex &parent) const;
+
+ QModelIndex index(int row, int column, const QModelIndex &parent) const;
+ QModelIndex parent(const QModelIndex &child) const;
+
QVariant data(const QModelIndex &index, int role) const;
// Roles for exposing data via model. Only one role because
// everything can be accessed via QDeclarativeLandmark
@@ -53,22 +61,28 @@ public:
void setPlugin(QDeclarativeGeoServiceProvider *plugin);
QDeclarativeGeoServiceProvider* plugin() const;
+ void setHierarchical(bool hierarchical);
+ bool hierarchical() const;
+
signals:
- void categoriesChanged();
void pluginChanged();
+ void hierarchicalChanged();
private slots:
void replyFinished();
void replyError(QPlaceReply::Error error, const QString &errorString);
private:
- void convertCategoriesToDeclarative();
+ void updateCategories();
+ QHash<QString, PlaceCategoryTree> populatedCategories(QPlaceManager *manager, const QPlaceCategory &parent = QPlaceCategory());
+ PlaceCategoryTree findCategoryTreeByCategory(QDeclarativeCategory *category, const PlaceCategoryTree &tree) const;
+ QDeclarativeCategory *findParentCategoryByCategory(QDeclarativeCategory *category, const PlaceCategoryTree &tree) const;
QPlaceReply *m_response;
- QList<QPlaceCategory> m_categories;
- QMap<QString, QDeclarativeCategory*> m_categoryMap;
+ PlaceCategoryTree m_categoryTree;
QDeclarativeGeoServiceProvider *m_plugin;
+ bool m_hierarchical;
bool m_complete;
};
diff --git a/src/location/places/qplacemanager.cpp b/src/location/places/qplacemanager.cpp
index 047edc3b..b8115a17 100644
--- a/src/location/places/qplacemanager.cpp
+++ b/src/location/places/qplacemanager.cpp
@@ -231,11 +231,12 @@ QPlaceReply *QPlaceManager::initializeCategories()
}
/*!
- Returns a list of top level categories.
+ Returns a list of top level categories if \a parent is default contstructed; otherwise returns
+ a list of subcategories of \a parent.
*/
-QList<QPlaceCategory> QPlaceManager::categories() const
+QList<QPlaceCategory> QPlaceManager::categories(const QPlaceCategory &parent) const
{
- return d->engine->categories();
+ return d->engine->categories(parent);
}
/*!
diff --git a/src/location/places/qplacemanager.h b/src/location/places/qplacemanager.h
index 569c76fa..703e980d 100644
--- a/src/location/places/qplacemanager.h
+++ b/src/location/places/qplacemanager.h
@@ -131,7 +131,7 @@ public:
QPlaceReply *removePlace(const QGeoPlace &place);
QPlaceReply *initializeCategories();
- QList<QPlaceCategory> categories() const;
+ QList<QPlaceCategory> categories(const QPlaceCategory &parent = QPlaceCategory()) const;
static QStringList availableManagers();
diff --git a/src/location/places/qplacemanagerengine.h b/src/location/places/qplacemanagerengine.h
index 324ea953..0c620658 100644
--- a/src/location/places/qplacemanagerengine.h
+++ b/src/location/places/qplacemanagerengine.h
@@ -82,7 +82,7 @@ public:
virtual QPlaceReply *removePlace(const QGeoPlace &place) = 0;
virtual QPlaceReply *initializeCategories() = 0;
- virtual QList<QPlaceCategory> categories() const = 0;
+ virtual QList<QPlaceCategory> categories(const QPlaceCategory &parent) const = 0;
virtual QLocale locale() const = 0;
virtual void setLocale(const QLocale &locale) = 0;
diff --git a/src/plugins/geoservices/nokia/places/places.pri b/src/plugins/geoservices/nokia/places/places.pri
index b24b5f90..911262f3 100644
--- a/src/plugins/geoservices/nokia/places/places.pri
+++ b/src/plugins/geoservices/nokia/places/places.pri
@@ -26,7 +26,8 @@ HEADERS += \
places/qplacecategoriesrepository.h \
places/qplacerestreply.h \
places/qplacerestmanager.h \
- places/qplacesuppliersrepository.h
+ places/qplacesuppliersrepository.h \
+ places/qplacecategorytree.h
SOURCES += \
#data classes
@@ -54,6 +55,9 @@ SOURCES += \
places/qplacecategoriesrepository.cpp \
places/qplacerestreply.cpp \
places/qplacerestmanager.cpp \
- places/qplacesuppliersrepository.cpp
+ places/qplacesuppliersrepository.cpp \
+ places/qplacecategorytree.cpp
+
+
diff --git a/src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.cpp b/src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.cpp
index e312813e..c17468f7 100644
--- a/src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.cpp
+++ b/src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.cpp
@@ -31,9 +31,14 @@ QPlaceCategoriesReplyImpl::~QPlaceCategoriesReplyImpl()
{
}
-QList<QPlaceCategory> QPlaceCategoriesReplyImpl::categories()
+QPlaceCategoryTree QPlaceCategoriesReplyImpl::categories() const
{
- return m_categories;
+ return m_categoryTree;
+}
+
+QList<QPlaceCategory> QPlaceCategoriesReplyImpl::categoriesFlat() const
+{
+ return m_categoryTree.toList();
}
void QPlaceCategoriesReplyImpl::abort()
@@ -61,7 +66,7 @@ void QPlaceCategoriesReplyImpl::resultReady(const QPlaceJSonParser::Error &error
const QString &errorMessage)
{
if (errorId == QPlaceJSonParser::NoError) {
- m_categories = parser->resultCategories();
+ m_categoryTree = parser->resultCategories();
} else if (errorId == QPlaceJSonParser::ParsingError) {
setError(ParseError, errorMessage);
emit error(this->error(), this->errorString());
diff --git a/src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.h b/src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.h
index 51a0c16d..f770fde8 100644
--- a/src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.h
+++ b/src/plugins/geoservices/nokia/places/qplacecategoriesreplyimpl.h
@@ -15,7 +15,8 @@ public:
explicit QPlaceCategoriesReplyImpl(QPlaceRestReply *reply, QObject *parent = 0);
~QPlaceCategoriesReplyImpl();
- QList<QPlaceCategory> categories();
+ QPlaceCategoryTree categories() const;
+ QList<QPlaceCategory> categoriesFlat() const;
void abort();
@@ -32,7 +33,7 @@ private:
QPlaceRestReply *restReply;
QPlaceJSonCategoriesParser *parser;
- QList<QPlaceCategory> m_categories;
+ QPlaceCategoryTree m_categoryTree;
};
#endif // QPLACECATEGORIESREPLYIMPL_H
diff --git a/src/plugins/geoservices/nokia/places/qplacecategoriesrepository.cpp b/src/plugins/geoservices/nokia/places/qplacecategoriesrepository.cpp
index 4304f3c0..70facc77 100644
--- a/src/plugins/geoservices/nokia/places/qplacecategoriesrepository.cpp
+++ b/src/plugins/geoservices/nokia/places/qplacecategoriesrepository.cpp
@@ -90,9 +90,9 @@ QPlaceReply *QPlaceCategoriesRepository::initializeCategories()
return categoriesReply;
}
-QList<QPlaceCategory> QPlaceCategoriesRepository::categories() const
+QPlaceCategoryTree QPlaceCategoriesRepository::categories() const
{
- return allCategories.values();
+ return m_categoryTree;
}
QPlaceCategory QPlaceCategoriesRepository::mapCategory(const QString &number)
@@ -117,17 +117,15 @@ QString QPlaceCategoriesRepository::getCategoryTagId(const QPlaceCategory &categ
QPlaceCategory QPlaceCategoriesRepository::findCategoryById(const QString &id)
{
- return allCategories.value(id, QPlaceCategory());
+ return m_categoryTree.findCategoryById(id);
}
void QPlaceCategoriesRepository::replyFinished()
{
- if (!categoriesReply.isNull()) {
- foreach (QPlaceCategory cat, categoriesReply->categories()) {
- allCategories.insert(cat.categoryId(), cat);
- }
- }
- categoriesReply = NULL;
+ if (!categoriesReply.isNull())
+ m_categoryTree = categoriesReply->categories();
+
+ categoriesReply = 0;
}
void QPlaceCategoriesRepository::setupCategoriesMapper()
diff --git a/src/plugins/geoservices/nokia/places/qplacecategoriesrepository.h b/src/plugins/geoservices/nokia/places/qplacecategoriesrepository.h
index e0a14725..a1502187 100644
--- a/src/plugins/geoservices/nokia/places/qplacecategoriesrepository.h
+++ b/src/plugins/geoservices/nokia/places/qplacecategoriesrepository.h
@@ -70,7 +70,7 @@ public:
~QPlaceCategoriesRepository();
QPlaceReply *initializeCategories();
- QList<QPlaceCategory> categories() const;
+ QPlaceCategoryTree categories() const;
QPlaceCategory mapCategory(const QString &number);
QString getCategoryTagId(const QPlaceCategory &category);
@@ -85,7 +85,7 @@ private:
private:
QPlaceCategoriesRepository(QObject *parent = 0);
- QHash<QString, QPlaceCategory> allCategories;
+ QPlaceCategoryTree m_categoryTree;
static QPlaceCategoriesRepository *repositoryInstance;
QPointer<QPlaceCategoriesReplyImpl> categoriesReply;
};
diff --git a/src/plugins/geoservices/nokia/places/qplacecategorytree.cpp b/src/plugins/geoservices/nokia/places/qplacecategorytree.cpp
new file mode 100644
index 00000000..e8870b9d
--- /dev/null
+++ b/src/plugins/geoservices/nokia/places/qplacecategorytree.cpp
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplacecategorytree.h"
+
+QPlaceCategoryTree::QPlaceCategoryTree()
+{
+}
+
+QPlaceCategoryTree::~QPlaceCategoryTree()
+{
+}
+
+void QPlaceCategoryTree::clear()
+{
+ category = QPlaceCategory();
+ subCategories.clear();
+}
+
+QPlaceCategory QPlaceCategoryTree::findCategoryById(const QString &id) const
+{
+ if (category.categoryId() == id)
+ return category;
+
+ if (subCategories.contains(id))
+ return subCategories.value(id).category;
+
+ QHashIterator<QString, QPlaceCategoryTree> it(subCategories);
+ while (it.hasNext()) {
+ it.next();
+
+ QPlaceCategory cat = it.value().findCategoryById(id);
+ if (cat.categoryId() == id)
+ return cat;
+ }
+
+ return QPlaceCategory();
+}
+
+QPlaceCategoryTree QPlaceCategoryTree::findCategoryTreeById(const QString &id) const
+{
+ if (category.categoryId() == id)
+ return *this;
+
+ QHashIterator<QString, QPlaceCategoryTree> it(subCategories);
+ while (it.hasNext()) {
+ it.next();
+
+ if (it.value().category.categoryId() == id)
+ return it.value();
+
+ QPlaceCategoryTree t = it.value().findCategoryTreeById(id);
+ if (t.category.categoryId() == id)
+ return t;
+ }
+
+ return QPlaceCategoryTree();
+}
+
+QList<QPlaceCategory> QPlaceCategoryTree::toList() const
+{
+ QList<QPlaceCategory> results;
+
+ QHashIterator<QString, QPlaceCategoryTree> it(subCategories);
+ while (it.hasNext()) {
+ it.next();
+
+ QPlaceCategory cat = it.value().category;
+ if (!cat.categoryId().isEmpty())
+ results.append(cat);
+
+ results.append(it.value().toList());
+ }
+
+ return results;
+}
diff --git a/src/plugins/geoservices/nokia/places/qplacecategorytree.h b/src/plugins/geoservices/nokia/places/qplacecategorytree.h
new file mode 100644
index 00000000..30a61253
--- /dev/null
+++ b/src/plugins/geoservices/nokia/places/qplacecategorytree.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLACECATEGORYTREE_H
+#define QPLACECATEGORYTREE_H
+
+#include <QtLocation/QPlaceCategory>
+
+class QPlaceCategoryTree
+{
+public:
+ QPlaceCategoryTree();
+ ~QPlaceCategoryTree();
+
+ void clear();
+
+ QPlaceCategory findCategoryById(const QString &id) const;
+ QPlaceCategoryTree findCategoryTreeById(const QString &id) const;
+ QList<QPlaceCategory> toList() const;
+
+ QPlaceCategory category;
+ QHash<QString, QPlaceCategoryTree> subCategories;
+};
+
+#endif // QPLACECATEGORYTREE_H
diff --git a/src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.cpp b/src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.cpp
index 18e875a9..8939fbd4 100644
--- a/src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.cpp
+++ b/src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.cpp
@@ -74,22 +74,31 @@ QPlaceJSonCategoriesParser::QPlaceJSonCategoriesParser(QObject *parent) :
QPlaceJSonCategoriesParser::~QPlaceJSonCategoriesParser()
{
- allCategories.clear();
}
-QList<QPlaceCategory> QPlaceJSonCategoriesParser::resultCategories()
+QList<QPlaceCategory> QPlaceJSonCategoriesParser::parseFlatCategoryList(const QScriptValue &categories)
{
- return allCategories;
+ return processCategories(categories).toList();
+}
+
+QPlaceCategoryTree QPlaceJSonCategoriesParser::resultCategories() const
+{
+ return m_categoryTree;
+}
+
+QList<QPlaceCategory> QPlaceJSonCategoriesParser::resultCategoriesFlat() const
+{
+ return m_categoryTree.toList();
}
void QPlaceJSonCategoriesParser::processJSonData(const QScriptValue &sv)
{
- allCategories.clear();
+ m_categoryTree.clear();
if (sv.isValid()) {
QScriptValue sv2 = sv.property(place_categories_element);
if (sv2.isValid()) {
- allCategories = processCategories(sv2);
+ m_categoryTree = processCategories(sv2);
emit finished(NoError, QString());
} else {
emit finished(ParsingError, QString("JSON data are invalid"));
@@ -99,10 +108,10 @@ void QPlaceJSonCategoriesParser::processJSonData(const QScriptValue &sv)
}
}
-QList<QPlaceCategory> QPlaceJSonCategoriesParser::processCategories(const QScriptValue &categories)
+QPlaceCategoryTree QPlaceJSonCategoriesParser::processCategories(const QScriptValue &categories)
{
- QHash<QString, QPlaceCategory> results;
- QPlaceCategory cat;
+ QPlaceCategoryTree results;
+
QScriptValue value = categories.property(place_category_element);
if (value.isValid()) {
if (value.isArray()) {
@@ -110,27 +119,62 @@ QList<QPlaceCategory> QPlaceJSonCategoriesParser::processCategories(const QScrip
while (it.hasNext()) {
it.next();
// array contains count as last element
- if (it.name() != "length") {
- cat = processCategory(it.value());
- if (!cat.categoryId().isEmpty() && !results.contains(cat.categoryId())) {
- results.insert(cat.categoryId(), cat);
+ if (it.name() != QLatin1String("length")) {
+ QPlaceCategoryTree catTree;
+ catTree.category = processCategory(it.value());
+ if (!catTree.category.categoryId().isEmpty() &&
+ !results.subCategories.contains(catTree.category.categoryId())) {
+ results.subCategories.insert(catTree.category.categoryId(), catTree);
}
}
}
} else {
- cat = processCategory(value);
- if (!cat.categoryId().isEmpty() && !results.contains(cat.categoryId())) {
- results.insert(cat.categoryId(), cat);
+ QPlaceCategoryTree catTree;
+ catTree.category = processCategory(value);
+ if (!catTree.category.categoryId().isEmpty() &&
+ !results.subCategories.contains(catTree.category.categoryId())) {
+ results.subCategories.insert(catTree.category.categoryId(), catTree);
}
}
}
- foreach (cat, processGroups(categories)) {
- if (!results.contains(cat.categoryId())) {
- results.insert(cat.categoryId(), cat);
+
+ value = categories.property(place_group_element);
+ if (value.isValid()) {
+ if (value.isArray()) {
+ QScriptValueIterator it(value);
+ while (it.hasNext()) {
+ it.next();
+ // array contains count as last element
+ if (it.name() != QLatin1String("length")) {
+ QPlaceCategoryTree catTree = processGroup(it.value());
+ if (!results.subCategories.contains(catTree.category.categoryId())) {
+ results.subCategories.insert(catTree.category.categoryId(), catTree);
+ } else {
+ QHashIterator<QString, QPlaceCategoryTree> treeIt(catTree.subCategories);
+ while (treeIt.hasNext()) {
+ treeIt.next();
+
+ results.subCategories[catTree.category.categoryId()].subCategories.insert(treeIt.key(), treeIt.value());
+ }
+ }
+ }
+ }
+ } else {
+ QPlaceCategoryTree catTree = processGroup(value);
+ if (!results.subCategories.contains(catTree.category.categoryId())) {
+ results.subCategories.insert(catTree.category.categoryId(), catTree);
+ } else {
+ QHashIterator<QString, QPlaceCategoryTree> treeIt(catTree.subCategories);
+ while (treeIt.hasNext()) {
+ treeIt.next();
+
+ results.subCategories[catTree.category.categoryId()].subCategories.insert(treeIt.key(), treeIt.value());
+ }
+ }
}
}
- return results.values();
+ return results;
}
QPlaceCategory QPlaceJSonCategoriesParser::processCategory(const QScriptValue &categoryValue)
@@ -147,39 +191,18 @@ QPlaceCategory QPlaceJSonCategoriesParser::processCategory(const QScriptValue &c
return category;
}
-QList<QPlaceCategory> QPlaceJSonCategoriesParser::processGroups(const QScriptValue &categories)
+QPlaceCategoryTree QPlaceJSonCategoriesParser::processGroup(const QScriptValue &group)
{
- QList<QPlaceCategory> results;
- QScriptValue value = categories.property(place_group_element);
- if (value.isValid()) {
- if (value.isArray()) {
- QScriptValueIterator it(value);
- while (it.hasNext()) {
- it.next();
- // array contains count as last element
- if (it.name() != "length") {
- results.append(processGroup(it.value()));
- }
- }
- } else {
- results.append(processGroup(value));
- }
- }
- return results;
-}
+ QScriptValue value = group.property(place_groupingcategory_element);
+ if (!value.isValid())
+ return QPlaceCategoryTree();
-QList<QPlaceCategory> QPlaceJSonCategoriesParser::processGroup(const QScriptValue &group)
-{
- QList<QPlaceCategory> results;
- QPlaceCategory parentCategory;
+ QPlaceCategoryTree results;
+ results.category = processCategory(value);
+ if (results.category.categoryId().isEmpty())
+ return QPlaceCategoryTree();
- QScriptValue value = group.property(place_groupingcategory_element);
- if (value.isValid()) {
- parentCategory = processCategory(value);
- }
- if (!parentCategory.categoryId().isEmpty()) {
- results = processCategories(group);
- }
+ results.subCategories = processCategories(group).subCategories;
return results;
}
diff --git a/src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.h b/src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.h
index c6c95717..e9428476 100644
--- a/src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.h
+++ b/src/plugins/geoservices/nokia/places/qplacejsoncategoriesparser.h
@@ -55,6 +55,7 @@
#include <qplacecategory.h>
#include "qplacejsonparser_p.h"
+#include "qplacecategorytree.h"
class QScriptEngine;
class QScriptValue;
@@ -64,21 +65,25 @@ QT_BEGIN_NAMESPACE
class QPlaceJSonCategoriesParser : public QPlaceJSonParser
{
Q_OBJECT
+
public:
explicit QPlaceJSonCategoriesParser(QObject *parent = 0);
virtual ~QPlaceJSonCategoriesParser();
- static QList<QPlaceCategory> processCategories(const QScriptValue &categories);
+ QPlaceCategoryTree resultCategories() const;
+ QList<QPlaceCategory> resultCategoriesFlat() const;
- QList<QPlaceCategory> resultCategories();
+ static QList<QPlaceCategory> parseFlatCategoryList(const QScriptValue &categories);
private:
void processJSonData(const QScriptValue &sv);
+
+ static QPlaceCategoryTree processCategories(const QScriptValue &categories);
+ static QPlaceCategoryTree processGroup(const QScriptValue &group);
static QPlaceCategory processCategory(const QScriptValue &categoryValue);
- static QList<QPlaceCategory> processGroups(const QScriptValue &categories);
- static QList<QPlaceCategory> processGroup(const QScriptValue &group);
+
private:
- QList<QPlaceCategory> allCategories;
+ QPlaceCategoryTree m_categoryTree;
};
QT_END_NAMESPACE
diff --git a/src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp b/src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp
index 8b0d77f7..aafb661a 100644
--- a/src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp
+++ b/src/plugins/geoservices/nokia/places/qplacejsondetailsparser.cpp
@@ -325,7 +325,7 @@ void QPlaceJSonDetailsParser::processContacts(const QScriptValue &contactsValue,
void QPlaceJSonDetailsParser::processCategories(const QScriptValue &categories, QGeoPlace*targetPlace)
{
- targetPlace->setCategories(QPlaceJSonCategoriesParser::processCategories(categories));
+ targetPlace->setCategories(QPlaceJSonCategoriesParser::parseFlatCategoryList(categories));
}
void QPlaceJSonDetailsParser::processRatings(const QScriptValue &ratings, QGeoPlace*targetPlace)
diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp b/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp
index 5edb91df..8ecc52ef 100644
--- a/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp
+++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.cpp
@@ -250,9 +250,21 @@ QPlaceReply *QPlaceManagerEngineNokia::initializeCategories()
return reply;
}
-QList<QPlaceCategory> QPlaceManagerEngineNokia::categories() const
+QList<QPlaceCategory> QPlaceManagerEngineNokia::categories(const QPlaceCategory &parent) const
{
- return QPlaceCategoriesRepository::instance()->categories();
+ QPlaceCategoryTree tree = QPlaceCategoriesRepository::instance()->categories();
+ tree = tree.findCategoryTreeById(parent.categoryId());
+
+ QList<QPlaceCategory> results;
+
+ QHashIterator<QString, QPlaceCategoryTree> it(tree.subCategories);
+ while (it.hasNext()) {
+ it.next();
+
+ results.append(it.value().category);
+ }
+
+ return results;
}
QLocale QPlaceManagerEngineNokia::locale() const
diff --git a/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h b/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h
index 0a42a648..8962562c 100644
--- a/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h
+++ b/src/plugins/geoservices/nokia/qplacemanagerengine_nokia.h
@@ -87,7 +87,7 @@ public:
QPlaceReply *removePlace(const QGeoPlace &place);
QPlaceReply *initializeCategories();
- QList<QPlaceCategory> categories() const;
+ QList<QPlaceCategory> categories(const QPlaceCategory &parent) const;
QLocale locale() const;
void setLocale(const QLocale &locale);