summaryrefslogtreecommitdiff
path: root/src/location/declarativeplaces
diff options
context:
space:
mode:
Diffstat (limited to 'src/location/declarativeplaces')
-rw-r--r--src/location/declarativeplaces/declarativeplaces.pri51
-rw-r--r--src/location/declarativeplaces/qdeclarativecategory.cpp458
-rw-r--r--src/location/declarativeplaces/qdeclarativecategory_p.h153
-rw-r--r--src/location/declarativeplaces/qdeclarativecontactdetail.cpp223
-rw-r--r--src/location/declarativeplaces/qdeclarativecontactdetail_p.h104
-rw-r--r--src/location/declarativeplaces/qdeclarativeperiod_p.h98
-rw-r--r--src/location/declarativeplaces/qdeclarativeplace.cpp1229
-rw-r--r--src/location/declarativeplaces/qdeclarativeplace_p.h262
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceattribute.cpp221
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceattribute_p.h95
-rw-r--r--src/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp397
-rw-r--r--src/location/declarativeplaces/qdeclarativeplacecontentmodel_p.h126
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceeditorialmodel.cpp169
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceeditorialmodel_p.h65
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceicon.cpp250
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceicon_p.h104
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceimagemodel.cpp170
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h78
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceuser.cpp139
-rw-r--r--src/location/declarativeplaces/qdeclarativeplaceuser_p.h92
-rw-r--r--src/location/declarativeplaces/qdeclarativeratings.cpp153
-rw-r--r--src/location/declarativeplaces/qdeclarativeratings_p.h98
-rw-r--r--src/location/declarativeplaces/qdeclarativereviewmodel.cpp183
-rw-r--r--src/location/declarativeplaces/qdeclarativereviewmodel_p.h78
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchmodelbase.cpp362
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchmodelbase_p.h148
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp917
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h179
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchsuggestionmodel.cpp353
-rw-r--r--src/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h104
-rw-r--r--src/location/declarativeplaces/qdeclarativesupplier.cpp221
-rw-r--r--src/location/declarativeplaces/qdeclarativesupplier_p.h111
-rw-r--r--src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp689
-rw-r--r--src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h166
34 files changed, 8246 insertions, 0 deletions
diff --git a/src/location/declarativeplaces/declarativeplaces.pri b/src/location/declarativeplaces/declarativeplaces.pri
new file mode 100644
index 00000000..82f60c23
--- /dev/null
+++ b/src/location/declarativeplaces/declarativeplaces.pri
@@ -0,0 +1,51 @@
+INCLUDEPATH += declarativeplaces
+
+SOURCES += \
+#models
+ declarativeplaces/qdeclarativeplacecontentmodel.cpp \
+ declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp \
+ declarativeplaces/qdeclarativesearchsuggestionmodel.cpp \
+ declarativeplaces/qdeclarativesearchresultmodel.cpp \
+ declarativeplaces/qdeclarativereviewmodel.cpp \
+ declarativeplaces/qdeclarativeplaceimagemodel.cpp \
+ declarativeplaces/qdeclarativeplaceeditorialmodel.cpp \
+#data
+ declarativeplaces/qdeclarativecontactdetail.cpp \
+ declarativeplaces/qdeclarativecategory.cpp \
+ declarativeplaces/qdeclarativeplace.cpp \
+ declarativeplaces/qdeclarativeplaceattribute.cpp \
+ declarativeplaces/qdeclarativeplaceicon.cpp \
+ declarativeplaces/qdeclarativeplaceuser.cpp \
+ declarativeplaces/qdeclarativeratings.cpp \
+ declarativeplaces/qdeclarativesupplier.cpp \
+ declarativeplaces/qdeclarativesearchmodelbase.cpp
+
+PRIVATE_HEADERS += \
+#models
+ declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h \
+ declarativeplaces/qdeclarativesearchsuggestionmodel_p.h \
+ declarativeplaces/qdeclarativesearchresultmodel_p.h \
+ declarativeplaces/qdeclarativereviewmodel_p.h \
+ declarativeplaces/qdeclarativeplaceimagemodel_p.h \
+#data
+ declarativeplaces/qdeclarativecontactdetail_p.h \
+ declarativeplaces/qdeclarativecategory_p.h \
+ declarativeplaces/qdeclarativeplace_p.h \
+ declarativeplaces/qdeclarativeplaceattribute_p.h \
+ declarativeplaces/qdeclarativeplaceicon_p.h \
+ declarativeplaces/qdeclarativeplaceuser_p.h \
+ declarativeplaces/qdeclarativeratings_p.h \
+ declarativeplaces/qdeclarativesupplier_p.h \
+ declarativeplaces/qdeclarativesearchmodelbase_p.h \
+ declarativeplaces/qdeclarativeplacecontentmodel_p.h \
+ declarativeplaces/qdeclarativeplaceeditorialmodel_p.h
+
+
+
+
+
+
+
+
+
+
diff --git a/src/location/declarativeplaces/qdeclarativecategory.cpp b/src/location/declarativeplaces/qdeclarativecategory.cpp
new file mode 100644
index 00000000..c58ec3a2
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativecategory.cpp
@@ -0,0 +1,458 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativecategory_p.h"
+#include "qdeclarativeplaceicon_p.h"
+#include "qdeclarativegeoserviceprovider_p.h"
+#include "error_messages.h"
+
+#include <QtQml/QQmlInfo>
+#include <QtLocation/QGeoServiceProvider>
+#include <QtLocation/QPlaceManager>
+#include <QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Category
+ \instantiates QDeclarativeCategory
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+
+ \since Qt Location 5.5
+
+ \brief The Category type represents a category that a \l Place can be associated with.
+
+ Categories are used to search for places based on the categories they are associated with. The
+ list of available categories can be obtained from the \l CategoryModel. The
+ \l PlaceSearchModel has a \l {PlaceSearchModel::categories}{categories} property that is used
+ to limit the search results to places with the specified categories.
+
+ If the \l Plugin supports it, categories can be created or removed. To create a new category
+ construct a new Category object and set its properties, then invoke the \l save() method.
+
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml Category
+ \dots 0
+ \snippet declarative/places.qml Category save
+
+ To remove a category ensure that the \l plugin and categoryId properties are set and call the
+ \l remove() method.
+
+ \sa CategoryModel
+*/
+
+QDeclarativeCategory::QDeclarativeCategory(QObject *parent)
+: QObject(parent), m_icon(0), m_plugin(0), m_reply(0), m_complete(false), m_status(Ready)
+{
+}
+
+QDeclarativeCategory::QDeclarativeCategory(const QPlaceCategory &category,
+ QDeclarativeGeoServiceProvider *plugin,
+ QObject *parent)
+: QObject(parent), m_category(category), m_icon(0), m_plugin(plugin), m_reply(0),
+ m_complete(false), m_status(Ready)
+{
+ setCategory(category);
+}
+
+QDeclarativeCategory::~QDeclarativeCategory() {}
+
+// From QQmlParserStatus
+void QDeclarativeCategory::componentComplete()
+{
+ // delayed instantiation of QObject based properties.
+ if (!m_icon) {
+ m_icon = new QDeclarativePlaceIcon(this);
+ m_icon->setPlugin(m_plugin);
+ }
+
+ m_complete = true;
+}
+
+/*!
+ \qmlproperty Plugin Category::plugin
+
+ This property holds the location based service to which the category belongs.
+*/
+void QDeclarativeCategory::setPlugin(QDeclarativeGeoServiceProvider *plugin)
+{
+ if (m_plugin == plugin)
+ return;
+
+ m_plugin = plugin;
+ if (m_complete)
+ emit pluginChanged();
+
+ if (m_icon && m_icon->parent() == this && !m_icon->plugin())
+ m_icon->setPlugin(m_plugin);
+
+ if (!m_plugin)
+ return;
+
+ if (m_plugin->isAttached()) {
+ pluginReady();
+ } else {
+ connect(m_plugin, SIGNAL(attached()),
+ this, SLOT(pluginReady()));
+ }
+}
+
+QDeclarativeGeoServiceProvider *QDeclarativeCategory::plugin() const
+{
+ return m_plugin;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeCategory::pluginReady()
+{
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (!placeManager || serviceProvider->error() != QGeoServiceProvider::NoError) {
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
+ .arg(m_plugin->name()).arg(serviceProvider->errorString()));
+ return;
+ }
+}
+
+
+/*!
+ \qmlproperty QPlaceCategory Category::category
+ \keyword Category::category
+
+ For details on how to use this property to interface between C++ and QML see
+ "\l {Category - QPlaceCategory} {Interfaces between C++ and QML Code}".
+*/
+void QDeclarativeCategory::setCategory(const QPlaceCategory &category)
+{
+ QPlaceCategory previous = m_category;
+ m_category = category;
+
+ if (category.name() != previous.name())
+ emit nameChanged();
+
+ if (category.categoryId() != previous.categoryId())
+ emit categoryIdChanged();
+
+ if (m_icon && m_icon->parent() == this) {
+ m_icon->setPlugin(m_plugin);
+ m_icon->setIcon(m_category.icon());
+ } else if (!m_icon || m_icon->parent() != this) {
+ m_icon = new QDeclarativePlaceIcon(m_category.icon(), m_plugin, this);
+ emit iconChanged();
+ }
+}
+
+QPlaceCategory QDeclarativeCategory::category()
+{
+ m_category.setIcon(m_icon ? m_icon->icon() : QPlaceIcon());
+ return m_category;
+}
+
+/*!
+ \qmlproperty string Category::categoryId
+
+ This property holds the identifier of the category. The categoryId is a string which uniquely
+ identifies this category within the categories \l plugin.
+*/
+void QDeclarativeCategory::setCategoryId(const QString &id)
+{
+ if (m_category.categoryId() != id) {
+ m_category.setCategoryId(id);
+ emit categoryIdChanged();
+ }
+}
+
+QString QDeclarativeCategory::categoryId() const
+{
+ return m_category.categoryId();
+}
+
+/*!
+ \qmlproperty string Category::name
+
+ This property holds string based name of the category.
+*/
+void QDeclarativeCategory::setName(const QString &name)
+{
+ if (m_category.name() != name) {
+ m_category.setName(name);
+ emit nameChanged();
+ }
+}
+
+QString QDeclarativeCategory::name() const
+{
+ return m_category.name();
+}
+
+/*!
+ \qmlproperty enumeration Category::visibility
+
+ This property holds the visibility of the category. It can be one of:
+
+ \table
+ \row
+ \li Category.UnspecifiedVisibility
+ \li The visibility of the category is unspecified. If saving a category, the
+ plugin will automatically set a default visibility to the category saved in the backend.
+ This default is dependent on the plugin implementation.
+ \row
+ \li Category.DeviceVisibility
+ \li The category is limited to the current device. The category will not be transferred
+ off of the device.
+ \row
+ \li Category.PrivateVisibility
+ \li The category is private to the current user. The category may be transferred to an
+ online service but is only ever visible to the current user.
+ \row
+ \li Category.PublicVisibility
+ \li The category is public.
+ \endtable
+
+ Note that visibility does not affect how \l{Place}s associated with
+ the category are displayed in the user-interface of an application
+ on the device. Instead, it defines the sharing semantics of the
+ category.
+*/
+QDeclarativeCategory::Visibility QDeclarativeCategory::visibility() const
+{
+ return static_cast<QDeclarativeCategory::Visibility>(m_category.visibility());
+}
+
+void QDeclarativeCategory::setVisibility(Visibility visibility)
+{
+ if (static_cast<QDeclarativeCategory::Visibility>(m_category.visibility()) == visibility)
+ return;
+
+ m_category.setVisibility(static_cast<QLocation::Visibility>(visibility));
+ emit visibilityChanged();
+}
+
+/*!
+ \qmlproperty PlaceIcon Category::icon
+
+ This property holds the image source associated with the category. To display the icon you can use
+ the \l Image type.
+*/
+QDeclarativePlaceIcon *QDeclarativeCategory::icon() const
+{
+ return m_icon;
+}
+
+void QDeclarativeCategory::setIcon(QDeclarativePlaceIcon *icon)
+{
+ if (m_icon == icon)
+ return;
+
+ if (m_icon && m_icon->parent() == this)
+ delete m_icon;
+
+ m_icon = icon;
+ emit iconChanged();
+}
+
+/*!
+ \qmlmethod string Category::errorString()
+
+ Returns a string description of the error of the last operation.
+ If the last operation completed successfully then the string is empty.
+*/
+QString QDeclarativeCategory::errorString() const
+{
+ return m_errorString;
+}
+
+void QDeclarativeCategory::setStatus(Status status, const QString &errorString)
+{
+ Status originalStatus = m_status;
+ m_status = status;
+ m_errorString = errorString;
+
+ if (originalStatus != m_status)
+ emit statusChanged();
+}
+
+/*!
+ \qmlproperty enumeration Category::status
+
+ This property holds the status of the category. It can be one of:
+
+ \table
+ \row
+ \li Category.Ready
+ \li No error occurred during the last operation, further operations may be performed on
+ the category.
+ \row
+ \li Category.Saving
+ \li The category is currently being saved, no other operations may be performed until the
+ current operation completes.
+ \row
+ \li Category.Removing
+ \li The category is currently being removed, no other operations can be performed until
+ the current operation completes.
+ \row
+ \li Category.Error
+ \li An error occurred during the last operation, further operations can still be
+ performed on the category.
+ \endtable
+*/
+QDeclarativeCategory::Status QDeclarativeCategory::status() const
+{
+ return m_status;
+}
+
+/*!
+ \qmlmethod void Category::save()
+
+ This method saves the category to the backend service.
+*/
+void QDeclarativeCategory::save(const QString &parentId)
+{
+ QPlaceManager *placeManager = manager();
+ if (!placeManager)
+ return;
+
+ m_reply = placeManager->saveCategory(category(), parentId);
+ connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ setStatus(QDeclarativeCategory::Saving);
+}
+
+/*!
+ \qmlmethod void Category::remove()
+
+ This method permanently removes the category from the backend service.
+*/
+void QDeclarativeCategory::remove()
+{
+ QPlaceManager *placeManager = manager();
+ if (!placeManager)
+ return;
+
+ m_reply = placeManager->removeCategory(m_category.categoryId());
+ connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished()));
+ setStatus(QDeclarativeCategory::Removing);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeCategory::replyFinished()
+{
+ if (!m_reply)
+ return;
+
+ if (m_reply->error() == QPlaceReply::NoError) {
+ switch (m_reply->type()) {
+ case (QPlaceReply::IdReply) : {
+ QPlaceIdReply *idReply = qobject_cast<QPlaceIdReply *>(m_reply);
+
+ switch (idReply->operationType()) {
+ case QPlaceIdReply::SaveCategory:
+ setCategoryId(idReply->id());
+ break;
+ case QPlaceIdReply::RemoveCategory:
+ setCategoryId(QString());
+ break;
+ default:
+ //Other operation types shouldn't ever be received.
+ break;
+ }
+ break;
+ }
+ default:
+ //other types of replies shouldn't ever be received.
+ break;
+ }
+
+ m_errorString.clear();
+
+ m_reply->deleteLater();
+ m_reply = 0;
+
+ setStatus(QDeclarativeCategory::Ready);
+ } else {
+ QString errorString = m_reply->errorString();
+
+ m_reply->deleteLater();
+ m_reply = 0;
+
+ setStatus(QDeclarativeCategory::Error, errorString);
+ }
+}
+
+/*!
+ \internal
+ Helper function to return the manager, this manager is intended to be used to perform the next
+ operation. Sets status to Error and an appropriate m_errorString if the manager cannot be
+ obtained.
+*/
+QPlaceManager *QDeclarativeCategory::manager()
+{
+ if (m_status != QDeclarativeCategory::Ready && m_status != QDeclarativeCategory::Error)
+ return 0;
+
+ if (m_reply) {
+ m_reply->abort();
+ m_reply->deleteLater();
+ m_reply = 0;
+ }
+
+ if (!m_plugin) {
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROPERTY_NOT_SET));
+ return 0;
+ }
+
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (!serviceProvider) {
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_NOT_VALID));
+ return 0;
+ }
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (!placeManager) {
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
+ .arg(m_plugin->name()).arg(serviceProvider->errorString()));
+ return 0;
+ }
+
+ return placeManager;
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativecategory_p.h b/src/location/declarativeplaces/qdeclarativecategory_p.h
new file mode 100644
index 00000000..c32072f4
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativecategory_p.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVECATEGORY_P_H
+#define QDECLARATIVECATEGORY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtQml/qqml.h>
+#include <QtQml/QQmlParserStatus>
+#include <QObject>
+
+#include <QtLocation/qplacecategory.h>
+
+#include <QtLocation/private/qdeclarativegeoserviceprovider_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativePlaceIcon;
+class QPlaceReply;
+class QPlaceManager;
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeCategory : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+
+ Q_ENUMS(Status Visibility)
+
+
+ Q_PROPERTY(QPlaceCategory category READ category WRITE setCategory)
+ Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged)
+ Q_PROPERTY(QString categoryId READ categoryId WRITE setCategoryId NOTIFY categoryIdChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged)
+ Q_PROPERTY(QDeclarativePlaceIcon *icon READ icon WRITE setIcon NOTIFY iconChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+
+ Q_INTERFACES(QQmlParserStatus)
+
+public:
+ explicit QDeclarativeCategory(QObject *parent = 0);
+ QDeclarativeCategory(const QPlaceCategory &category, QDeclarativeGeoServiceProvider *plugin, QObject *parent = 0);
+ ~QDeclarativeCategory();
+
+ enum Visibility {
+ UnspecifiedVisibility = QLocation::UnspecifiedVisibility,
+ DeviceVisibility = QLocation::DeviceVisibility,
+ PrivateVisibility = QLocation::PrivateVisibility,
+ PublicVisibility = QLocation::PublicVisibility
+ };
+ enum Status {Ready, Saving, Removing, Error};
+
+ //From QQmlParserStatus
+ virtual void classBegin() {}
+ virtual void componentComplete();
+
+ void setPlugin(QDeclarativeGeoServiceProvider *plugin);
+ QDeclarativeGeoServiceProvider *plugin() const;
+
+ QPlaceCategory category();
+ void setCategory(const QPlaceCategory &category);
+
+ QString categoryId() const;
+ void setCategoryId(const QString &catID);
+ QString name() const;
+ void setName(const QString &name);
+
+ Visibility visibility() const;
+ void setVisibility(Visibility visibility);
+
+ QDeclarativePlaceIcon *icon() const;
+ void setIcon(QDeclarativePlaceIcon *icon);
+
+ Q_INVOKABLE QString errorString() const;
+
+ Status status() const;
+ void setStatus(Status status, const QString &errorString = QString());
+
+ Q_INVOKABLE void save(const QString &parentId = QString());
+ Q_INVOKABLE void remove();
+
+Q_SIGNALS:
+ void pluginChanged();
+ void categoryIdChanged();
+ void nameChanged();
+ void visibilityChanged();
+ void iconChanged();
+ void statusChanged();
+
+private Q_SLOTS:
+ void replyFinished();
+ void pluginReady();
+
+private:
+ QPlaceManager *manager();
+
+ QPlaceCategory m_category;
+ QDeclarativePlaceIcon *m_icon;
+ QDeclarativeGeoServiceProvider *m_plugin;
+ QPlaceReply *m_reply;
+ bool m_complete;
+ Status m_status;
+ QString m_errorString;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeCategory)
+
+#endif // QDECLARATIVECATEGORY_P_H
diff --git a/src/location/declarativeplaces/qdeclarativecontactdetail.cpp b/src/location/declarativeplaces/qdeclarativecontactdetail.cpp
new file mode 100644
index 00000000..7a7a4c33
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativecontactdetail.cpp
@@ -0,0 +1,223 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativecontactdetail_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ContactDetails
+ \instantiates QDeclarativeContactDetails
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+ \since Qt Location 5.5
+
+ \brief The ContactDetails type holds contact details for a \l Place.
+
+ The ContactDetails type is a map of \l {QtLocation::ContactDetail}{ContactDetail} objects.
+ To access contact details in the map use the \l keys() method to get the list of keys stored in
+ the map and then use the \c {[]} operator to access the
+ \l {QtLocation::ContactDetail}{ContactDetail} items.
+
+ The following keys are defined in the API. \l Plugin implementations are free to define
+ additional keys.
+
+ \list
+ \li phone
+ \li fax
+ \li email
+ \li website
+ \endlist
+
+ ContactDetails instances are only ever used in the context of \l {Place}{Places}. It is not possible
+ to create a ContactDetails instance directly or re-assign ContactDetails instances to \l {Place}{Places}.
+ Modification of ContactDetails can only be accomplished via Javascript.
+
+ \section1 Examples
+
+ The following example shows how to access all \l {QtLocation::ContactDetail}{ContactDetails}
+ and print them to the console:
+
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml ContactDetails read
+
+ The returned list of contact details is an \l {QObjectList-based model}{object list} and so can be used directly as a data model. For example, the
+ following demonstrates how to display a list of contact phone numbers in a list view:
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml ContactDetails phoneList
+
+ The following example demonstrates how to assign a single phone number to a place in JavaScript:
+ \snippet declarative/places.qml ContactDetails write single
+
+ The following demonstrates how to assign multiple phone numbers to a place in JavaScript:
+ \snippet declarative/places.qml ContactDetails write multiple
+*/
+
+/*!
+ \qmlmethod variant ContactDetails::keys()
+
+ Returns an array of contact detail keys currently stored in the map.
+*/
+QDeclarativeContactDetails::QDeclarativeContactDetails(QObject *parent)
+ : QQmlPropertyMap(parent)
+{
+}
+
+QVariant QDeclarativeContactDetails::updateValue(const QString &, const QVariant &input)
+{
+ if (input.userType() == QMetaType::QObjectStar) {
+ QDeclarativeContactDetail *detail =
+ qobject_cast<QDeclarativeContactDetail *>(input.value<QObject *>());
+ if (detail) {
+ QVariantList varList;
+ varList.append(input);
+ return varList;
+ }
+ }
+
+ return input;
+}
+
+/*!
+ \qmltype ContactDetail
+ \instantiates QDeclarativeContactDetail
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+ \since Qt Location 5.5
+
+ \brief The ContactDetail type holds a contact detail such as a phone number or a website
+ address.
+
+ The ContactDetail provides a single detail on how one could contact a \l Place. The
+ ContactDetail consists of a \l label, which is a localized string describing the contact
+ method, and a \l value representing the actual contact detail.
+
+ \section1 Examples
+
+ The following example demonstrates how to assign a single phone number to a place in JavaScript:
+ \snippet declarative/places.qml ContactDetails write single
+
+ The following demonstrates how to assign multiple phone numbers to a place in JavaScript:
+ \snippet declarative/places.qml ContactDetails write multiple
+
+ Note, due to limitations of the QQmlPropertyMap, it is not possible
+ to declaratively specify the contact details in QML, it can only be accomplished
+ via JavaScript.
+*/
+QDeclarativeContactDetail::QDeclarativeContactDetail(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QDeclarativeContactDetail::QDeclarativeContactDetail(const QPlaceContactDetail &src, QObject *parent)
+ : QObject(parent), m_contactDetail(src)
+{
+}
+
+QDeclarativeContactDetail::~QDeclarativeContactDetail()
+{
+}
+
+/*!
+ \qmlproperty QPlaceContactDetail QtLocation::ContactDetail::contactDetail
+
+ For details on how to use this property to interface between C++ and QML see
+ "\l {ContactDetail - QDeclarativeContactDetail} {Interfaces between C++ and QML Code}".
+*/
+void QDeclarativeContactDetail::setContactDetail(const QPlaceContactDetail &src)
+{
+ QPlaceContactDetail prevContactDetail = m_contactDetail;
+ m_contactDetail = src;
+
+ if (m_contactDetail.label() != prevContactDetail.label())
+ emit labelChanged();
+ if (m_contactDetail.value() != prevContactDetail.value())
+ emit valueChanged();
+}
+
+QPlaceContactDetail QDeclarativeContactDetail::contactDetail() const
+{
+ return m_contactDetail;
+}
+
+/*!
+ \qmlproperty string QtLocation::ContactDetail::label
+
+ This property holds a label describing the contact detail.
+
+ The label can potentially be localized. The language is dependent on the entity that sets it,
+ typically this is the \l {Plugin}. The \l {Plugin::locales} property defines
+ what language is used.
+*/
+QString QDeclarativeContactDetail::label() const
+{
+ return m_contactDetail.label();
+}
+
+void QDeclarativeContactDetail::setLabel(const QString &label)
+{
+ if (m_contactDetail.label() != label) {
+ m_contactDetail.setLabel(label);
+ emit labelChanged();
+ }
+}
+
+/*!
+ \qmlproperty string QtLocation::ContactDetail::value
+
+ This property holds the value of the contact detail which may be a phone number, an email
+ address, a website url and so on.
+*/
+QString QDeclarativeContactDetail::value() const
+{
+ return m_contactDetail.value();
+}
+
+void QDeclarativeContactDetail::setValue(const QString &value)
+{
+ if (m_contactDetail.value() != value) {
+ m_contactDetail.setValue(value);
+ emit valueChanged();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativecontactdetail_p.h b/src/location/declarativeplaces/qdeclarativecontactdetail_p.h
new file mode 100644
index 00000000..ad60c3b5
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativecontactdetail_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVECONTACTDETAIL_P_H
+#define QDECLARATIVECONTACTDETAIL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtCore/QObject>
+#include <QtLocation/QPlaceContactDetail>
+#include <QtQml/QQmlPropertyMap>
+#include <QtQml/qqml.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeContactDetails : public QQmlPropertyMap
+{
+ Q_OBJECT
+
+public:
+ explicit QDeclarativeContactDetails(QObject *parent = 0);
+ virtual QVariant updateValue(const QString &key, const QVariant &input);
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeContactDetail : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPlaceContactDetail contactDetail READ contactDetail WRITE setContactDetail)
+ Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
+ Q_PROPERTY(QString value READ value WRITE setValue NOTIFY valueChanged)
+
+public:
+ explicit QDeclarativeContactDetail(QObject *parent = 0);
+ explicit QDeclarativeContactDetail(const QPlaceContactDetail &src, QObject *parent = 0);
+ ~QDeclarativeContactDetail();
+
+ QPlaceContactDetail contactDetail() const;
+ void setContactDetail(const QPlaceContactDetail &contactDetail);
+
+ QString label() const;
+ void setLabel(const QString &label);
+
+ QString value() const;
+ void setValue(const QString &value);
+
+Q_SIGNALS:
+ void labelChanged();
+ void valueChanged();
+
+private:
+ QPlaceContactDetail m_contactDetail;
+
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeContactDetail)
+QML_DECLARE_TYPE(QDeclarativeContactDetails)
+
+#endif
diff --git a/src/location/declarativeplaces/qdeclarativeperiod_p.h b/src/location/declarativeplaces/qdeclarativeperiod_p.h
new file mode 100644
index 00000000..3ded0109
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeperiod_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPERIOD_P_H
+#define QDECLARATIVEPERIOD_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qplaceperiod.h>
+#include <QtQml/qqml.h>
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativePeriod : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDate startDate READ startDate WRITE setStartDate NOTIFY startDateChanged)
+ Q_PROPERTY(QTime startTime READ startTime WRITE setStartTime NOTIFY startTimeChanged)
+ Q_PROPERTY(QDate endDate READ endDate WRITE setEndDate NOTIFY endDateChanged)
+ Q_PROPERTY(QTime endTime READ endTime WRITE setEndTime NOTIFY endTimeChanged)
+
+public:
+ explicit QDeclarativePeriod(QObject *parent = 0);
+ explicit QDeclarativePeriod(const QPlacePeriod &period, QObject *parent = 0);
+ ~QDeclarativePeriod();
+
+ QPlacePeriod period() const;
+ void setPeriod(const QPlacePeriod &period);
+
+ QDate startDate() const;
+ void setStartDate(const QDate &data);
+ QTime startTime() const;
+ void setStartTime(const QTime &data);
+ QDate endDate() const;
+ void setEndDate(const QDate &data);
+ QTime endTime() const;
+ void setEndTime(const QTime &data);
+
+Q_SIGNALS:
+ void startDateChanged();
+ void startTimeChanged();
+ void endDateChanged();
+ void endTimeChanged();
+
+private:
+ QPlacePeriod m_period;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QT_PREPEND_NAMESPACE(QDeclarativePeriod));
+
+#endif // QDECLARATIVEPERIOD_P_H
diff --git a/src/location/declarativeplaces/qdeclarativeplace.cpp b/src/location/declarativeplaces/qdeclarativeplace.cpp
new file mode 100644
index 00000000..91ef2026
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplace.cpp
@@ -0,0 +1,1229 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeplace_p.h"
+#include "qdeclarativecontactdetail_p.h"
+#include "qdeclarativegeoserviceprovider_p.h"
+#include "qdeclarativeplaceattribute_p.h"
+#include "qdeclarativeplaceicon_p.h"
+#include "error_messages.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QMetaObject>
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlInfo>
+#include <QtLocation/QGeoServiceProvider>
+#include <QtLocation/QPlaceManager>
+#include <QtLocation/QPlaceDetailsReply>
+#include <QtLocation/QPlaceReply>
+#include <QtLocation/QPlaceIdReply>
+#include <QtLocation/QPlaceContactDetail>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Place
+ \instantiates QDeclarativePlace
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+ \since Qt Location 5.5
+
+ \brief The Place type represents a location that is a position of interest.
+
+ The Place type represents a physical location with additional metadata describing that
+ location. Contrasted with \l Location, \l Address, and
+ \l {coordinate} type which are used to describe where a location is.
+ The basic properties of a Place are its \l name and \l location.
+
+ Place objects are typically obtained from a search model and will generally only have their
+ basic properties set. The \l detailsFetched property can be used to test if further property
+ values need to be fetched from the \l Plugin. This can be done by invoking the \l getDetails()
+ method. Progress of the fetching operation can be monitored with the \l status property, which
+ will be set to Place.Fetching when the details are being fetched.
+
+ The Place type has many properties holding information about the location. Details on how to
+ contact the place are available from the \l contactDetails property. Convenience properties
+ for obtaining the primary \l {primaryPhone}{phone}, \l {primaryFax}{fax},
+ \l {primaryEmail}{email} and \l {primaryWebsite}{website} are also available.
+
+ Each place is assigned zero or more \l categories. Categories are typically used when
+ searching for a particular kind of place, such as a restaurant or hotel. Some places have a
+ \l ratings object, which gives an indication of the quality of the place.
+
+ Place metadata is provided by a \l supplier who may require that an \l attribution message be
+ displayed to the user when the place details are viewed.
+
+ Places have an associated \l icon which can be used to represent a place on a map or to
+ decorate a delegate in a view.
+
+ Places may have additional rich content associated with them. The currently supported rich
+ content include editorial descriptions, reviews and images. These are exposed as a set of
+ models for retrieving the content. Editorial descriptions of the place are available from the
+ \l editorialModel property. Reviews of the place are available from the \l reviewModel
+ property. A gallery of pictures of the place can be accessed using the \l imageModel property.
+
+ Places may have additional attributes which are not covered in the formal API. The
+ \l extendedAttributes property provides access to these. The type of extended attributes
+ available is specific to each \l Plugin.
+
+ A Place is almost always tied to a \l plugin. The \l plugin property must be set before it is
+ possible to call \l save(), \l remove() or \l getDetails(). The \l reviewModel, \l imageModel
+ and \l editorialModel are only valid then the \l plugin property is set.
+
+ \section2 Saving a Place
+
+ If the \l Plugin supports it, the Place type can be used to save a place. First create a new
+ Place and set its properties:
+
+ \snippet declarative/places.qml Place savePlace def
+
+ Then invoke the \l save() method:
+
+ \snippet declarative/places.qml Place savePlace
+
+ The \l status property will change to Place.Saving and then to Place.Ready if the save was
+ successful or to Place.Error if an error occurs.
+
+ If the \l placeId property is set, the backend will update an existing place otherwise it will
+ create a new place. On success the \l placeId property will be updated with the identifier of the newly
+ saved place.
+
+ \section3 Caveats
+ \input place-caveats.qdocinc
+
+ \section3 Saving Between Plugins
+ When saving places between plugins, there are a few things to be aware of.
+ Some fields of a place such as the id, categories and icons are plugin specific entities. For example
+ the categories in one manager may not be recognised in another.
+ Therefore trying to save a place directly from one plugin to another is not possible.
+
+ It is generally recommended that saving across plugins be handled as saving \l {Favorites}{favorites}
+ as explained in the Favorites section. However there is another approach which is to create a new place,
+ set its (destination) plugin and then use the \l copyFrom() method to copy the details of the original place.
+ Using \l copyFrom() only copies data that is supported by the destination plugin,
+ plugin specific data such as the place identifier is not copied over. Once the copy is done,
+ the place is in a suitable state to be saved.
+
+ The following snippet provides an example of saving a place to a different plugin
+ using the \l copyFrom method:
+
+ \snippet declarative/places.qml Place save to different plugin
+
+ \section2 Removing a Place
+
+ To remove a place, ensure that a Place object with a valid \l placeId property exists and call
+ its \l remove() method. The \l status property will change to Place.Removing and then to
+ Place.Ready if the save was successful or to Place.Error if an error occurs.
+
+ \section2 Favorites
+ The Places API supports the concept of favorites. Favorites are generally implemented
+ by using two plugins, the first plugin is typically a read-only source of places (origin plugin) and a second
+ read/write plugin (destination plugin) is used to store places from the origin as favorites.
+
+ Each Place has a favorite property which is intended to contain the corresponding place
+ from the destination plugin (the place itself is sourced from the origin plugin). Because both the original
+ place and favorite instances are available, the developer can choose which
+ properties to show to the user. For example the favorite may have a modified name which should
+ be displayed rather than the original name.
+
+ \snippet declarative/places.qml Place favorite
+
+ The following demonstrates how to save a new favorite instance. A call is made
+ to create/initialize the favorite instance and then the instance is saved.
+
+ \snippet declarative/places.qml Place saveFavorite
+
+ The following demonstrates favorite removal:
+
+ \snippet declarative/places.qml Place removeFavorite 1
+ \dots
+ \snippet declarative/places.qml Place removeFavorite 2
+
+ The PlaceSearchModel has a favoritesPlugin property. If the property is set, any places found
+ during a search are checked against the favoritesPlugin to see if there is a corresponding
+ favorite place. If so, the favorite property of the Place is set, otherwise the favorite
+ property is remains null.
+
+ \sa PlaceSearchModel
+*/
+
+QDeclarativePlace::QDeclarativePlace(QObject *parent)
+: QObject(parent), m_location(0), m_ratings(0), m_supplier(0), m_icon(0),
+ m_reviewModel(0), m_imageModel(0), m_editorialModel(0),
+ m_extendedAttributes(new QQmlPropertyMap(this)),
+ m_contactDetails(new QDeclarativeContactDetails(this)), m_reply(0), m_plugin(0),
+ m_complete(false), m_favorite(0), m_status(QDeclarativePlace::Ready)
+{
+ connect(m_contactDetails, SIGNAL(valueChanged(QString,QVariant)),
+ this, SLOT(contactsModified(QString,QVariant)));
+
+ setPlace(QPlace());
+}
+
+QDeclarativePlace::QDeclarativePlace(const QPlace &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent)
+: QObject(parent), m_location(0), m_ratings(0), m_supplier(0), m_icon(0),
+ m_reviewModel(0), m_imageModel(0), m_editorialModel(0),
+ m_extendedAttributes(new QQmlPropertyMap(this)),
+ m_contactDetails(new QDeclarativeContactDetails(this)), m_reply(0), m_plugin(plugin),
+ m_complete(false), m_favorite(0), m_status(QDeclarativePlace::Ready)
+{
+ Q_ASSERT(plugin);
+
+ connect(m_contactDetails, SIGNAL(valueChanged(QString,QVariant)),
+ this, SLOT(contactsModified(QString,QVariant)));
+
+ setPlace(src);
+}
+
+QDeclarativePlace::~QDeclarativePlace()
+{
+}
+
+// From QQmlParserStatus
+void QDeclarativePlace::componentComplete()
+{
+ m_complete = true;
+}
+
+/*!
+ \qmlproperty Plugin Place::plugin
+
+ This property holds the \l Plugin that provided this place which can be used to retrieve more information about the service.
+*/
+void QDeclarativePlace::setPlugin(QDeclarativeGeoServiceProvider *plugin)
+{
+ if (m_plugin == plugin)
+ return;
+
+ m_plugin = plugin;
+ if (m_complete)
+ emit pluginChanged();
+
+ if (m_plugin->isAttached()) {
+ pluginReady();
+ } else {
+ connect(m_plugin, SIGNAL(attached()),
+ this, SLOT(pluginReady()));
+ }
+}
+
+void QDeclarativePlace::pluginReady()
+{
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (!placeManager || serviceProvider->error() != QGeoServiceProvider::NoError) {
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
+ .arg(m_plugin->name()).arg(serviceProvider->errorString()));
+ return;
+ }
+}
+
+QDeclarativeGeoServiceProvider *QDeclarativePlace::plugin() const
+{
+ return m_plugin;
+}
+
+/*!
+ \qmlproperty ReviewModel Place::reviewModel
+
+ This property holds a model which can be used to retrieve reviews about the place.
+*/
+QDeclarativeReviewModel *QDeclarativePlace::reviewModel()
+{
+ if (!m_reviewModel) {
+ m_reviewModel = new QDeclarativeReviewModel(this);
+ m_reviewModel->setPlace(this);
+ }
+
+ return m_reviewModel;
+}
+
+/*!
+ \qmlproperty ImageModel Place::imageModel
+
+ This property holds a model which can be used to retrieve images of the place.
+*/
+QDeclarativePlaceImageModel *QDeclarativePlace::imageModel()
+{
+ if (!m_imageModel) {
+ m_imageModel = new QDeclarativePlaceImageModel(this);
+ m_imageModel->setPlace(this);
+ }
+
+ return m_imageModel;
+}
+
+/*!
+ \qmlproperty EditorialModel Place::editorialModel
+
+ This property holds a model which can be used to retrieve editorial descriptions of the place.
+*/
+QDeclarativePlaceEditorialModel *QDeclarativePlace::editorialModel()
+{
+ if (!m_editorialModel) {
+ m_editorialModel = new QDeclarativePlaceEditorialModel(this);
+ m_editorialModel->setPlace(this);
+ }
+
+ return m_editorialModel;
+}
+
+/*!
+ \qmlproperty QPlace Place::place
+
+ For details on how to use this property to interface between C++ and QML see
+ "\l {Place - QPlace} {Interfaces between C++ and QML Code}".
+*/
+void QDeclarativePlace::setPlace(const QPlace &src)
+{
+ QPlace previous = m_src;
+ m_src = src;
+
+ if (previous.categories() != m_src.categories()) {
+ synchronizeCategories();
+ emit categoriesChanged();
+ }
+
+ if (m_location && m_location->parent() == this) {
+ m_location->setLocation(m_src.location());
+ } else if (!m_location || m_location->parent() != this) {
+ m_location = new QDeclarativeGeoLocation(m_src.location(), this);
+ emit locationChanged();
+ }
+
+ if (m_ratings && m_ratings->parent() == this) {
+ m_ratings->setRatings(m_src.ratings());
+ } else if (!m_ratings || m_ratings->parent() != this) {
+ m_ratings = new QDeclarativeRatings(m_src.ratings(), this);
+ emit ratingsChanged();
+ }
+
+ if (m_supplier && m_supplier->parent() == this) {
+ m_supplier->setSupplier(m_src.supplier(), m_plugin);
+ } else if (!m_supplier || m_supplier->parent() != this) {
+ m_supplier = new QDeclarativeSupplier(m_src.supplier(), m_plugin, this);
+ emit supplierChanged();
+ }
+
+ if (m_icon && m_icon->parent() == this) {
+ m_icon->setPlugin(m_plugin);
+ m_icon->setIcon(m_src.icon());
+ } else if (!m_icon || m_icon->parent() != this) {
+ m_icon = new QDeclarativePlaceIcon(m_src.icon(), m_plugin, this);
+ emit iconChanged();
+ }
+
+ if (previous.name() != m_src.name()) {
+ emit nameChanged();
+ }
+ if (previous.placeId() != m_src.placeId()) {
+ emit placeIdChanged();
+ }
+ if (previous.attribution() != m_src.attribution()) {
+ emit attributionChanged();
+ }
+ if (previous.detailsFetched() != m_src.detailsFetched()) {
+ emit detailsFetchedChanged();
+ }
+ if (previous.primaryPhone() != m_src.primaryPhone()) {
+ emit primaryPhoneChanged();
+ }
+ if (previous.primaryFax() != m_src.primaryFax()) {
+ emit primaryFaxChanged();
+ }
+ if (previous.primaryEmail() != m_src.primaryEmail()) {
+ emit primaryEmailChanged();
+ }
+ if (previous.primaryWebsite() != m_src.primaryWebsite()) {
+ emit primaryWebsiteChanged();
+ }
+
+ if (m_reviewModel && m_src.totalContentCount(QPlaceContent::ReviewType) >= 0) {
+ m_reviewModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ReviewType),
+ m_src.content(QPlaceContent::ReviewType));
+ }
+ if (m_imageModel && m_src.totalContentCount(QPlaceContent::ImageType) >= 0) {
+ m_imageModel->initializeCollection(m_src.totalContentCount(QPlaceContent::ImageType),
+ m_src.content(QPlaceContent::ImageType));
+ }
+ if (m_editorialModel && m_src.totalContentCount(QPlaceContent::EditorialType) >= 0) {
+ m_editorialModel->initializeCollection(m_src.totalContentCount(QPlaceContent::EditorialType),
+ m_src.content(QPlaceContent::EditorialType));
+ }
+
+ synchronizeExtendedAttributes();
+ synchronizeContacts();
+}
+
+QPlace QDeclarativePlace::place()
+{
+ // The following properties are not stored in m_src but instead stored in QDeclarative* objects
+
+ QPlace result = m_src;
+
+ // Categories
+ QList<QPlaceCategory> categories;
+ foreach (QDeclarativeCategory *value, m_categories)
+ categories.append(value->category());
+
+ result.setCategories(categories);
+
+ // Location
+ result.setLocation(m_location ? m_location->location() : QGeoLocation());
+
+ // Rating
+ result.setRatings(m_ratings ? m_ratings->ratings() : QPlaceRatings());
+
+ // Supplier
+ result.setSupplier(m_supplier ? m_supplier->supplier() : QPlaceSupplier());
+
+ // Icon
+ result.setIcon(m_icon ? m_icon->icon() : QPlaceIcon());
+
+ //contact details
+ QList<QPlaceContactDetail> cppDetails;
+ foreach (const QString &key, m_contactDetails->keys()) {
+ cppDetails.clear();
+ if (m_contactDetails->value(key).type() == QVariant::List) {
+ QVariantList detailsVarList = m_contactDetails->value(key).toList();
+ foreach (const QVariant &detailVar, detailsVarList) {
+ QDeclarativeContactDetail *detail = qobject_cast<QDeclarativeContactDetail *>(detailVar.value<QObject *>());
+ if (detail)
+ cppDetails.append(detail->contactDetail());
+ }
+ } else {
+ QDeclarativeContactDetail *detail = qobject_cast<QDeclarativeContactDetail *>(m_contactDetails->value(key).value<QObject *>());
+ if (detail)
+ cppDetails.append(detail->contactDetail());
+ }
+ result.setContactDetails(key, cppDetails);
+ }
+
+ return result;
+}
+
+/*!
+ \qmlproperty QtPositioning::Location Place::location
+
+ This property holds the location of the place which can be used to retrieve the coordinate,
+ address and the bounding box.
+*/
+void QDeclarativePlace::setLocation(QDeclarativeGeoLocation *location)
+{
+ if (m_location == location)
+ return;
+
+ if (m_location && m_location->parent() == this)
+ delete m_location;
+
+ m_location = location;
+ emit locationChanged();
+}
+
+QDeclarativeGeoLocation *QDeclarativePlace::location()
+{
+ return m_location;
+}
+
+/*!
+ \qmlproperty Ratings Place::ratings
+
+ This property holds ratings of the place. The ratings provide an indication of the quality of a
+ place.
+*/
+void QDeclarativePlace::setRatings(QDeclarativeRatings *rating)
+{
+ if (m_ratings == rating)
+ return;
+
+ if (m_ratings && m_ratings->parent() == this)
+ delete m_ratings;
+
+ m_ratings = rating;
+ emit ratingsChanged();
+}
+
+QDeclarativeRatings *QDeclarativePlace::ratings()
+{
+
+ return m_ratings;
+}
+
+/*!
+ \qmlproperty Supplier Place::supplier
+
+ This property holds the supplier of the place data.
+ The supplier is typically a business or organization that collected the data about the place.
+*/
+void QDeclarativePlace::setSupplier(QDeclarativeSupplier *supplier)
+{
+ if (m_supplier == supplier)
+ return;
+
+ if (m_supplier && m_supplier->parent() == this)
+ delete m_supplier;
+
+ m_supplier = supplier;
+ emit supplierChanged();
+}
+
+QDeclarativeSupplier *QDeclarativePlace::supplier() const
+{
+ return m_supplier;
+}
+
+/*!
+ \qmlproperty Icon Place::icon
+
+ This property holds a graphical icon which can be used to represent the place.
+*/
+QDeclarativePlaceIcon *QDeclarativePlace::icon() const
+{
+ return m_icon;
+}
+
+void QDeclarativePlace::setIcon(QDeclarativePlaceIcon *icon)
+{
+ if (m_icon == icon)
+ return;
+
+ if (m_icon && m_icon->parent() == this)
+ delete m_icon;
+
+ m_icon = icon;
+ emit iconChanged();
+}
+
+/*!
+ \qmlproperty string Place::name
+
+ This property holds the name of the place which can be used to represent the place.
+*/
+void QDeclarativePlace::setName(const QString &name)
+{
+ if (m_src.name() != name) {
+ m_src.setName(name);
+ emit nameChanged();
+ }
+}
+
+QString QDeclarativePlace::name() const
+{
+ return m_src.name();
+}
+
+/*!
+ \qmlproperty string Place::placeId
+
+ This property holds the unique identifier of the place. The place identifier is only meaningful to the
+ \l Plugin that generated it and is not transferable between \l {Plugin}{Plugins}. The place id
+ is not guaranteed to be universally unique, but unique within the \l Plugin that generated it.
+
+ If only the place identifier is known, all other place data can fetched from the \l Plugin.
+
+ \snippet declarative/places.qml Place placeId
+*/
+void QDeclarativePlace::setPlaceId(const QString &placeId)
+{
+ if (m_src.placeId() != placeId) {
+ m_src.setPlaceId(placeId);
+ emit placeIdChanged();
+ }
+}
+
+QString QDeclarativePlace::placeId() const
+{
+ return m_src.placeId();
+}
+
+/*!
+ \qmlproperty string Place::attribution
+
+ This property holds a rich text attribution string for the place.
+ Some providers may require that the attribution be shown to the user
+ whenever a place is displayed. The contents of this property should
+ be shown to the user if it is not empty.
+*/
+void QDeclarativePlace::setAttribution(const QString &attribution)
+{
+ if (m_src.attribution() != attribution) {
+ m_src.setAttribution(attribution);
+ emit attributionChanged();
+ }
+}
+
+QString QDeclarativePlace::attribution() const
+{
+ return m_src.attribution();
+}
+
+/*!
+ \qmlproperty bool Place::detailsFetched
+
+ This property indicates whether the details of the place have been fetched. If this property
+ is false, the place details have not yet been fetched. Fetching can be done by invoking the
+ \l getDetails() method.
+
+ \sa getDetails()
+*/
+bool QDeclarativePlace::detailsFetched() const
+{
+ return m_src.detailsFetched();
+}
+
+/*!
+ \qmlproperty enumeration Place::status
+
+ This property holds the status of the place. It can be one of:
+
+ \table
+ \row
+ \li Place.Ready
+ \li No error occurred during the last operation, further operations may be performed on
+ the place.
+ \row
+ \li Place.Saving
+ \li The place is currently being saved, no other operation may be performed until
+ complete.
+ \row
+ \li Place.Fetching
+ \li The place details are currently being fetched, no other operations may be performed
+ until complete.
+ \row
+ \li Place.Removing
+ \li The place is currently being removed, no other operations can be performed until
+ complete.
+ \row
+ \li Place.Error
+ \li An error occurred during the last operation, further operations can still be
+ performed on the place.
+ \endtable
+
+ The status of a place can be checked by connecting the status property
+ to a handler function, and then have the handler function process the change
+ in status.
+
+ \snippet declarative/places.qml Place checkStatus
+ \dots
+ \snippet declarative/places.qml Place checkStatus handler
+
+*/
+void QDeclarativePlace::setStatus(Status status, const QString &errorString)
+{
+ Status originalStatus = m_status;
+ m_status = status;
+ m_errorString = errorString;
+
+ if (originalStatus != m_status)
+ emit statusChanged();
+}
+
+QDeclarativePlace::Status QDeclarativePlace::status() const
+{
+ return m_status;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlace::finished()
+{
+ if (!m_reply)
+ return;
+
+ if (m_reply->error() == QPlaceReply::NoError) {
+ switch (m_reply->type()) {
+ case (QPlaceReply::IdReply) : {
+ QPlaceIdReply *idReply = qobject_cast<QPlaceIdReply *>(m_reply);
+
+ switch (idReply->operationType()) {
+ case QPlaceIdReply::SavePlace:
+ setPlaceId(idReply->id());
+ break;
+ case QPlaceIdReply::RemovePlace:
+ break;
+ default:
+ //Other operation types shouldn't ever be received.
+ break;
+ }
+ break;
+ }
+ case (QPlaceReply::DetailsReply): {
+ QPlaceDetailsReply *detailsReply = qobject_cast<QPlaceDetailsReply *>(m_reply);
+ setPlace(detailsReply->place());
+ break;
+ }
+ default:
+ //other types of replies shouldn't ever be received.
+ break;
+ }
+
+ m_errorString.clear();
+
+ m_reply->deleteLater();
+ m_reply = 0;
+
+ setStatus(QDeclarativePlace::Ready);
+ } else {
+ QString errorString = m_reply->errorString();
+
+ m_reply->deleteLater();
+ m_reply = 0;
+
+ setStatus(QDeclarativePlace::Error, errorString);
+ }
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlace::contactsModified(const QString &key, const QVariant &)
+{
+ primarySignalsEmission(key);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlace::cleanupDeletedCategories()
+{
+ foreach (QDeclarativeCategory * category, m_categoriesToBeDeleted) {
+ if (category->parent() == this)
+ delete category;
+ }
+ m_categoriesToBeDeleted.clear();
+}
+
+/*!
+ \qmlmethod void Place::getDetails()
+
+ This method starts fetching place details.
+
+ The \l status property will change to Place.Fetching while the fetch is in progress. On
+ success the object's properties will be updated, \l status will be set to Place.Ready and
+ \l detailsFetched will be set to true. On error \l status will be set to Place.Error. The
+ \l errorString() method can be used to get the details of the error.
+*/
+void QDeclarativePlace::getDetails()
+{
+ QPlaceManager *placeManager = manager();
+ if (!placeManager)
+ return;
+
+ m_reply = placeManager->getPlaceDetails(placeId());
+ connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ setStatus(QDeclarativePlace::Fetching);
+}
+
+/*!
+ \qmlmethod void Place::save()
+
+ This method performs a save operation on the place.
+
+ The \l status property will change to Place.Saving while the save operation is in progress. On
+ success the \l status will be set to Place.Ready. On error \l status will be set to Place.Error.
+ The \l errorString() method can be used to get the details of the error.
+
+ If the \l placeId property was previously empty, it will be assigned a valid value automatically
+ during a successful save operation.
+
+ Note that a \l PlaceSearchModel will call Place::getDetails on any place that it detects an update
+ on. A consequence of this is that whenever a Place from a \l PlaceSearchModel is successfully saved,
+ it will be followed by a fetch of place details, leading to a sequence of state changes
+ of \c Saving, \c Ready, \c Fetching, \c Ready.
+
+*/
+void QDeclarativePlace::save()
+{
+ QPlaceManager *placeManager = manager();
+ if (!placeManager)
+ return;
+
+ m_reply = placeManager->savePlace(place());
+ connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ setStatus(QDeclarativePlace::Saving);
+}
+
+/*!
+ \qmlmethod void Place::remove()
+
+ This method performs a remove operation on the place.
+
+ The \l status property will change to Place.Removing while the save operation is in progress.
+ On success \l status will be set to Place.Ready. On error \l status will be set to
+ Place.Error. The \l errorString() method can be used to get the details of the error.
+*/
+void QDeclarativePlace::remove()
+{
+ QPlaceManager *placeManager = manager();
+ if (!placeManager)
+ return;
+
+ m_reply = placeManager->removePlace(place().placeId());
+ connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ setStatus(QDeclarativePlace::Removing);
+}
+
+/*!
+ \qmlmethod string Place::errorString()
+
+ Returns a string description of the error of the last operation. If the last operation
+ completed successfully then the string is empty.
+*/
+QString QDeclarativePlace::errorString() const
+{
+ return m_errorString;
+}
+
+/*!
+ \qmlproperty string Place::primaryPhone
+
+ This property holds the primary phone number of the place. If no "phone" contact detail is
+ defined for this place, this property will be an empty string. It is equivalent to:
+
+
+ \snippet declarative/places.qml Place primaryPhone
+*/
+QString QDeclarativePlace::primaryPhone() const
+{
+ return primaryValue(QPlaceContactDetail::Phone);
+}
+
+/*!
+ \qmlproperty string Place::primaryFax
+
+ This property holds the primary fax number of the place. If no "fax" contact detail is
+ defined for this place this property will be an empty string. It is equivalent to
+
+ \snippet declarative/places.qml Place primaryFax
+*/
+QString QDeclarativePlace::primaryFax() const
+{
+ return primaryValue(QPlaceContactDetail::Fax);
+}
+
+/*!
+ \qmlproperty string Place::primaryEmail
+
+ This property holds the primary email address of the place. If no "email" contact detail is
+ defined for this place this property will be an empty string. It is equivalent to
+
+ \snippet declarative/places.qml Place primaryEmail
+*/
+QString QDeclarativePlace::primaryEmail() const
+{
+ return primaryValue(QPlaceContactDetail::Email);
+}
+
+/*!
+ \qmlproperty string Place::primaryWebsite
+
+ This property holds the primary website url of the place. If no "website" contact detail is
+ defined for this place this property will be an empty string. It is equivalent to
+
+ \snippet declarative/places.qml Place primaryWebsite
+*/
+
+QUrl QDeclarativePlace::primaryWebsite() const
+{
+ return QUrl(primaryValue(QPlaceContactDetail::Website));
+}
+
+/*!
+ \qmlproperty ExtendedAttributes Place::extendedAttributes
+
+ This property holds the extended attributes of a place. Extended attributes are additional
+ information about a place not covered by the place's properties.
+*/
+QQmlPropertyMap *QDeclarativePlace::extendedAttributes() const
+{
+ return m_extendedAttributes;
+}
+
+/*!
+ \qmlproperty ContactDetails Place::contactDetails
+
+ This property holds the contact information for this place, for example a phone number or
+ a website URL. This property is a map of \l ContactDetail objects.
+*/
+QDeclarativeContactDetails *QDeclarativePlace::contactDetails() const
+{
+ return m_contactDetails;
+}
+
+/*!
+ \qmlproperty list<Category> Place::categories
+
+ This property holds the list of categories this place is a member of. The categories that can
+ be assigned to a place are specific to each \l plugin.
+*/
+QQmlListProperty<QDeclarativeCategory> QDeclarativePlace::categories()
+{
+ return QQmlListProperty<QDeclarativeCategory>(this,
+ 0, // opaque data parameter
+ category_append,
+ category_count,
+ category_at,
+ category_clear);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlace::category_append(QQmlListProperty<QDeclarativeCategory> *prop,
+ QDeclarativeCategory *value)
+{
+ QDeclarativePlace *object = static_cast<QDeclarativePlace *>(prop->object);
+
+ if (object->m_categoriesToBeDeleted.contains(value))
+ object->m_categoriesToBeDeleted.removeAll(value);
+
+ if (!object->m_categories.contains(value)) {
+ object->m_categories.append(value);
+ QList<QPlaceCategory> list = object->m_src.categories();
+ list.append(value->category());
+ object->m_src.setCategories(list);
+
+ emit object->categoriesChanged();
+ }
+}
+
+/*!
+ \internal
+*/
+int QDeclarativePlace::category_count(QQmlListProperty<QDeclarativeCategory> *prop)
+{
+ return static_cast<QDeclarativePlace *>(prop->object)->m_categories.count();
+}
+
+/*!
+ \internal
+*/
+QDeclarativeCategory *QDeclarativePlace::category_at(QQmlListProperty<QDeclarativeCategory> *prop,
+ int index)
+{
+ QDeclarativePlace *object = static_cast<QDeclarativePlace *>(prop->object);
+ QDeclarativeCategory *res = NULL;
+ if (object->m_categories.count() > index && index > -1) {
+ res = object->m_categories[index];
+ }
+ return res;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlace::category_clear(QQmlListProperty<QDeclarativeCategory> *prop)
+{
+ QDeclarativePlace *object = static_cast<QDeclarativePlace *>(prop->object);
+ if (object->m_categories.isEmpty())
+ return;
+
+ for (int i = 0; i < object->m_categories.count(); ++i) {
+ if (object->m_categories.at(i)->parent() == object)
+ object->m_categoriesToBeDeleted.append(object->m_categories.at(i));
+ }
+
+ object->m_categories.clear();
+ object->m_src.setCategories(QList<QPlaceCategory>());
+ emit object->categoriesChanged();
+ QMetaObject::invokeMethod(object, "cleanupDeletedCategories", Qt::QueuedConnection);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlace::synchronizeCategories()
+{
+ qDeleteAll(m_categories);
+ m_categories.clear();
+ foreach (const QPlaceCategory &value, m_src.categories()) {
+ QDeclarativeCategory *declarativeValue = new QDeclarativeCategory(value, m_plugin, this);
+ m_categories.append(declarativeValue);
+ }
+}
+
+/*!
+ \qmlproperty enumeration Place::visibility
+
+ This property holds the visibility of the place. It can be one of:
+
+ \table
+ \row
+ \li Place.UnspecifiedVisibility
+ \li The visibility of the place is unspecified, the default visibility of the \l Plugin
+ will be used.
+ \row
+ \li Place.DeviceVisibility
+ \li The place is limited to the current device. The place will not be transferred off
+ of the device.
+ \row
+ \li Place.PrivateVisibility
+ \li The place is private to the current user. The place may be transferred to an online
+ service but is only ever visible to the current user.
+ \row
+ \li Place.PublicVisibility
+ \li The place is public.
+ \endtable
+
+ Note that visibility does not affect how the place is displayed
+ in the user-interface of an application on the device. Instead,
+ it defines the sharing semantics of the place.
+*/
+QDeclarativePlace::Visibility QDeclarativePlace::visibility() const
+{
+ return static_cast<QDeclarativePlace::Visibility>(m_src.visibility());
+}
+
+void QDeclarativePlace::setVisibility(Visibility visibility)
+{
+ if (static_cast<QDeclarativePlace::Visibility>(m_src.visibility()) == visibility)
+ return;
+
+ m_src.setVisibility(static_cast<QLocation::Visibility>(visibility));
+ emit visibilityChanged();
+}
+
+/*!
+ \qmlproperty Place Place::favorite
+
+ This property holds the favorite instance of a place.
+*/
+QDeclarativePlace *QDeclarativePlace::favorite() const
+{
+ return m_favorite;
+}
+
+void QDeclarativePlace::setFavorite(QDeclarativePlace *favorite)
+{
+
+ if (m_favorite == favorite)
+ return;
+
+ if (m_favorite && m_favorite->parent() == this)
+ delete m_favorite;
+
+ m_favorite = favorite;
+ emit favoriteChanged();
+}
+
+/*!
+ \qmlmethod void Place::copyFrom(Place original)
+
+ Copies data from an \a original place into this place. Only data that is supported by this
+ place's plugin is copied over and plugin specific data such as place identifier is not copied over.
+*/
+void QDeclarativePlace::copyFrom(QDeclarativePlace *original)
+{
+ QPlaceManager *placeManager = manager();
+ if (!placeManager)
+ return;
+
+ setPlace(placeManager->compatiblePlace(original->place()));
+}
+
+/*!
+ \qmlmethod void Place::initializeFavorite(Plugin destinationPlugin)
+
+ Creates a favorite instance for the place which is to be saved into the
+ \a destination plugin. This method does nothing if the favorite property is
+ not null.
+*/
+void QDeclarativePlace::initializeFavorite(QDeclarativeGeoServiceProvider *plugin)
+{
+ if (m_favorite == 0) {
+ QDeclarativePlace *place = new QDeclarativePlace(this);
+ place->setPlugin(plugin);
+ place->copyFrom(this);
+ setFavorite(place);
+ }
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlace::synchronizeExtendedAttributes()
+{
+ QStringList keys = m_extendedAttributes->keys();
+ foreach (const QString &key, keys)
+ m_extendedAttributes->clear(key);
+
+ QStringList attributeTypes = m_src.extendedAttributeTypes();
+ foreach (const QString &attributeType, attributeTypes) {
+ m_extendedAttributes->insert(attributeType,
+ qVariantFromValue(new QDeclarativePlaceAttribute(m_src.extendedAttribute(attributeType))));
+ }
+
+ emit extendedAttributesChanged();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlace::synchronizeContacts()
+{
+ //clear out contact data
+ foreach (const QString &contactType, m_contactDetails->keys()) {
+ QList<QVariant> contacts = m_contactDetails->value(contactType).toList();
+ foreach (const QVariant &var, contacts) {
+ QObject *obj = var.value<QObject *>();
+ if (obj->parent() == this)
+ delete obj;
+ }
+ m_contactDetails->insert(contactType, QVariantList());
+ }
+
+ //insert new contact data from source place
+ foreach (const QString &contactType, m_src.contactTypes()) {
+ QList<QPlaceContactDetail> sourceContacts = m_src.contactDetails(contactType);
+ QVariantList declContacts;
+ foreach (const QPlaceContactDetail &sourceContact, sourceContacts) {
+ QDeclarativeContactDetail *declContact = new QDeclarativeContactDetail(this);
+ declContact->setContactDetail(sourceContact);
+ declContacts.append(QVariant::fromValue(qobject_cast<QObject *>(declContact)));
+ }
+ m_contactDetails->insert(contactType, declContacts);
+ }
+ primarySignalsEmission();
+}
+
+/*!
+ \internal
+ Helper function to emit the signals for the primary___()
+ fields. It is expected that the values of the primary___()
+ functions have already been modified to new values.
+*/
+void QDeclarativePlace::primarySignalsEmission(const QString &type)
+{
+ if (type.isEmpty() || type == QPlaceContactDetail::Phone) {
+ if (m_prevPrimaryPhone != primaryPhone()) {
+ m_prevPrimaryPhone = primaryPhone();
+ emit primaryPhoneChanged();
+ }
+ if (!type.isEmpty())
+ return;
+ }
+
+ if (type.isEmpty() || type == QPlaceContactDetail::Email) {
+ if (m_prevPrimaryEmail != primaryEmail()) {
+ m_prevPrimaryEmail = primaryEmail();
+ emit primaryEmailChanged();
+ }
+ if (!type.isEmpty())
+ return;
+ }
+
+ if (type.isEmpty() || type == QPlaceContactDetail::Website) {
+ if (m_prevPrimaryWebsite != primaryWebsite()) {
+ m_prevPrimaryWebsite = primaryWebsite();
+ emit primaryWebsiteChanged();
+ }
+ if (!type.isEmpty())
+ return;
+ }
+
+ if (type.isEmpty() || type == QPlaceContactDetail::Fax) {
+ if (m_prevPrimaryFax != primaryFax()) {
+ m_prevPrimaryFax = primaryFax();
+ emit primaryFaxChanged();
+ }
+ }
+}
+
+/*!
+ \internal
+ Helper function to return the manager, this manager is intended to be used
+ to perform the next operation. If a an operation is currently underway
+ then return a null pointer.
+*/
+QPlaceManager *QDeclarativePlace::manager()
+{
+ if (m_status != QDeclarativePlace::Ready && m_status != QDeclarativePlace::Error)
+ return 0;
+
+ if (m_reply) {
+ m_reply->abort();
+ m_reply->deleteLater();
+ m_reply = 0;
+ }
+
+ if (!m_plugin) {
+ qmlWarning(this) << QStringLiteral("Plugin is not assigned to place.");
+ return 0;
+ }
+
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (!serviceProvider)
+ return 0;
+
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+
+ if (!placeManager) {
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
+ .arg(m_plugin->name()).arg(serviceProvider->errorString()));
+ return 0;
+ }
+
+ return placeManager;
+}
+
+/*!
+ \internal
+*/
+QString QDeclarativePlace::primaryValue(const QString &contactType) const
+{
+ QVariant value = m_contactDetails->value(contactType);
+ if (value.userType() == qMetaTypeId<QJSValue>())
+ value = value.value<QJSValue>().toVariant();
+
+ if (value.userType() == QVariant::List) {
+ QVariantList detailList = m_contactDetails->value(contactType).toList();
+ if (!detailList.isEmpty()) {
+ QDeclarativeContactDetail *primaryDetail = qobject_cast<QDeclarativeContactDetail *>(detailList.at(0).value<QObject *>());
+ if (primaryDetail)
+ return primaryDetail->value();
+ }
+ } else if (value.userType() == QMetaType::QObjectStar) {
+ QDeclarativeContactDetail *primaryDetail = qobject_cast<QDeclarativeContactDetail *>(m_contactDetails->value(contactType).value<QObject *>());
+ if (primaryDetail)
+ return primaryDetail->value();
+ }
+
+ return QString();
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativeplace_p.h b/src/location/declarativeplaces/qdeclarativeplace_p.h
new file mode 100644
index 00000000..5a1470fe
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplace_p.h
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPLACE_P_H
+#define QDECLARATIVEPLACE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtCore/QObject>
+#include <QtQml/QQmlListProperty>
+#include <QtQml/QQmlParserStatus>
+#include <QtQml/QQmlPropertyMap>
+#include <QtLocation/QPlace>
+
+#include <QtPositioning/private/qdeclarativegeolocation_p.h>
+#include <QtLocation/private/qdeclarativecategory_p.h>
+#include <QtLocation/private/qdeclarativecontactdetail_p.h>
+#include <QtLocation/private/qdeclarativesupplier_p.h>
+#include <QtLocation/private/qdeclarativeratings_p.h>
+#include <QtLocation/private/qdeclarativereviewmodel_p.h>
+#include <QtLocation/private/qdeclarativeplaceimagemodel_p.h>
+#include <QtLocation/private/qdeclarativeplaceeditorialmodel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPlaceReply;
+
+class QPlaceManager;
+class QDeclarativePlaceIcon;
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePlace : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+
+ Q_ENUMS(Status Visibility)
+
+ Q_PROPERTY(QPlace place READ place WRITE setPlace)
+ Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged)
+ Q_PROPERTY(QQmlListProperty<QDeclarativeCategory> categories READ categories NOTIFY categoriesChanged)
+ Q_PROPERTY(QDeclarativeGeoLocation *location READ location WRITE setLocation NOTIFY locationChanged)
+ Q_PROPERTY(QDeclarativeRatings *ratings READ ratings WRITE setRatings NOTIFY ratingsChanged)
+ Q_PROPERTY(QDeclarativeSupplier *supplier READ supplier WRITE setSupplier NOTIFY supplierChanged)
+ Q_PROPERTY(QDeclarativePlaceIcon *icon READ icon WRITE setIcon NOTIFY iconChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QString placeId READ placeId WRITE setPlaceId NOTIFY placeIdChanged)
+ Q_PROPERTY(QString attribution READ attribution WRITE setAttribution NOTIFY attributionChanged)
+
+ Q_PROPERTY(QDeclarativeReviewModel *reviewModel READ reviewModel NOTIFY reviewModelChanged)
+ Q_PROPERTY(QDeclarativePlaceImageModel *imageModel READ imageModel NOTIFY imageModelChanged)
+ Q_PROPERTY(QDeclarativePlaceEditorialModel *editorialModel READ editorialModel NOTIFY editorialModelChanged)
+
+ Q_PROPERTY(QObject *extendedAttributes READ extendedAttributes NOTIFY extendedAttributesChanged)
+ Q_PROPERTY(QObject *contactDetails READ contactDetails NOTIFY contactDetailsChanged)
+ Q_PROPERTY(bool detailsFetched READ detailsFetched NOTIFY detailsFetchedChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+
+ Q_PROPERTY(QString primaryPhone READ primaryPhone NOTIFY primaryPhoneChanged)
+ Q_PROPERTY(QString primaryFax READ primaryFax NOTIFY primaryFaxChanged)
+ Q_PROPERTY(QString primaryEmail READ primaryEmail NOTIFY primaryEmailChanged)
+ Q_PROPERTY(QUrl primaryWebsite READ primaryWebsite NOTIFY primaryWebsiteChanged)
+
+ Q_PROPERTY(Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged)
+ Q_PROPERTY(QDeclarativePlace *favorite READ favorite WRITE setFavorite NOTIFY favoriteChanged)
+
+ Q_INTERFACES(QQmlParserStatus)
+
+public:
+ explicit QDeclarativePlace(QObject *parent = 0);
+ QDeclarativePlace(const QPlace &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent = 0);
+ ~QDeclarativePlace();
+
+ enum Status {Ready, Saving, Fetching, Removing, Error};
+ enum Visibility {
+ UnspecifiedVisibility = QLocation::UnspecifiedVisibility,
+ DeviceVisibility = QLocation::DeviceVisibility,
+ PrivateVisibility = QLocation::PrivateVisibility,
+ PublicVisibility = QLocation::PublicVisibility
+ };
+
+ //From QQmlParserStatus
+ virtual void classBegin() {}
+ virtual void componentComplete();
+
+ void setPlugin(QDeclarativeGeoServiceProvider *plugin);
+ QDeclarativeGeoServiceProvider *plugin() const;
+
+ QDeclarativeReviewModel *reviewModel();
+ QDeclarativePlaceImageModel *imageModel();
+ QDeclarativePlaceEditorialModel *editorialModel();
+
+ QPlace place();
+ void setPlace(const QPlace &src);
+
+ QQmlListProperty<QDeclarativeCategory> categories();
+ static void category_append(QQmlListProperty<QDeclarativeCategory> *prop,
+ QDeclarativeCategory *value);
+ static int category_count(QQmlListProperty<QDeclarativeCategory> *prop);
+ static QDeclarativeCategory *category_at(QQmlListProperty<QDeclarativeCategory> *prop, int index);
+ static void category_clear(QQmlListProperty<QDeclarativeCategory> *prop);
+
+ QDeclarativeGeoLocation *location();
+ void setLocation(QDeclarativeGeoLocation *location);
+ QDeclarativeRatings *ratings();
+ void setRatings(QDeclarativeRatings *ratings);
+ QDeclarativeSupplier *supplier() const;
+ void setSupplier(QDeclarativeSupplier *supplier);
+ QDeclarativePlaceIcon *icon() const;
+ void setIcon(QDeclarativePlaceIcon *icon);
+ QString name() const;
+ void setName(const QString &name);
+ QString placeId() const;
+ void setPlaceId(const QString &placeId);
+ QString attribution() const;
+ void setAttribution(const QString &attribution);
+ bool detailsFetched() const;
+
+ Status status() const;
+ void setStatus(Status status, const QString &errorString = QString());
+
+ Q_INVOKABLE void getDetails();
+ Q_INVOKABLE void save();
+ Q_INVOKABLE void remove();
+ Q_INVOKABLE QString errorString() const;
+
+ QString primaryPhone() const;
+ QString primaryFax() const;
+ QString primaryEmail() const;
+ QUrl primaryWebsite() const;
+
+ QQmlPropertyMap *extendedAttributes() const;
+
+ QDeclarativeContactDetails *contactDetails() const;
+
+ Visibility visibility() const;
+ void setVisibility(Visibility visibility);
+
+ QDeclarativePlace *favorite() const;
+ void setFavorite(QDeclarativePlace *favorite);
+
+ Q_INVOKABLE void copyFrom(QDeclarativePlace *original);
+ Q_INVOKABLE void initializeFavorite(QDeclarativeGeoServiceProvider *plugin);
+
+Q_SIGNALS:
+ void pluginChanged();
+ void categoriesChanged();
+ void locationChanged();
+ void ratingsChanged();
+ void supplierChanged();
+ void iconChanged();
+ void nameChanged();
+ void placeIdChanged();
+ void attributionChanged();
+ void detailsFetchedChanged();
+ void reviewModelChanged();
+ void imageModelChanged();
+ void editorialModelChanged();
+
+ void primaryPhoneChanged();
+ void primaryFaxChanged();
+ void primaryEmailChanged();
+ void primaryWebsiteChanged();
+
+ void extendedAttributesChanged();
+ void contactDetailsChanged();
+ void statusChanged();
+ void visibilityChanged();
+ void favoriteChanged();
+
+private Q_SLOTS:
+ void finished();
+ void contactsModified(const QString &, const QVariant &);
+ void pluginReady();
+ void cleanupDeletedCategories();
+private:
+ void synchronizeCategories();
+ void synchronizeExtendedAttributes();
+ void synchronizeContacts();
+ void primarySignalsEmission(const QString &type = QString());
+ QString primaryValue(const QString &contactType) const;
+
+private:
+ QPlaceManager *manager();
+
+ QList<QDeclarativeCategory *> m_categories;
+ QDeclarativeGeoLocation *m_location;
+ QDeclarativeRatings *m_ratings;
+ QDeclarativeSupplier *m_supplier;
+ QDeclarativePlaceIcon *m_icon;
+ QDeclarativeReviewModel *m_reviewModel;
+ QDeclarativePlaceImageModel *m_imageModel;
+ QDeclarativePlaceEditorialModel *m_editorialModel;
+ QQmlPropertyMap *m_extendedAttributes;
+ QDeclarativeContactDetails *m_contactDetails;
+
+ QPlace m_src;
+
+ QPlaceReply *m_reply;
+
+ QDeclarativeGeoServiceProvider *m_plugin;
+ bool m_complete;
+
+ QString m_prevPrimaryPhone;
+ QString m_prevPrimaryEmail;
+ QString m_prevPrimaryFax;
+ QUrl m_prevPrimaryWebsite;
+
+ QDeclarativePlace *m_favorite;
+
+ Status m_status;
+ QString m_errorString;
+
+ QList<QDeclarativeCategory *>m_categoriesToBeDeleted;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativePlace)
+
+#endif // QDECLARATIVEPLACE_P_H
diff --git a/src/location/declarativeplaces/qdeclarativeplaceattribute.cpp b/src/location/declarativeplaces/qdeclarativeplaceattribute.cpp
new file mode 100644
index 00000000..20adbafb
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceattribute.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeplaceattribute_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ExtendedAttributes
+ \instantiates QQmlPropertyMap
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+ \since Qt Location 5.5
+
+ \brief The ExtendedAttributes type holds additional data about a \l Place.
+
+ The ExtendedAttributes type is a map of \l {PlaceAttribute}{PlaceAttributes}. To access
+ attributes in the map use the \l keys() method to get the list of keys stored in the map and
+ use the \c {[]} operator to access the \l PlaceAttribute items.
+
+ The following are standard keys that are defined by the API. \l Plugin
+ implementations are free to define additional keys. Custom keys should
+ be qualified by a unique prefix to avoid clashes.
+ \table
+ \header
+ \li key
+ \li description
+ \row
+ \li openingHours
+ \li The trading hours of the place
+ \row
+ \li payment
+ \li The types of payment the place accepts, for example visa, mastercard.
+ \row
+ \li x_provider
+ \li The name of the provider that a place is sourced from
+ \row
+ \li x_id_<provider> (for example x_id_here)
+ \li An alternative identifier which identifies the place from the
+ perspective of the specified provider.
+ \endtable
+
+ Some plugins may not support attributes at all, others may only support a
+ certain set, others still may support a dynamically changing set of attributes
+ over time or even allow attributes to be arbitrarily defined by the client
+ application. The attributes could also vary on a place by place basis,
+ for example one place may have opening hours while another does not.
+ Consult the \l {Plugin References and Parameters}{plugin
+ references} for details.
+
+ Some attributes may not be intended to be readable by end users, the label field
+ of such attributes is empty to indicate this fact.
+
+ \note ExtendedAttributes instances are only ever used in the context of \l {Place}s. It is not
+ possible to create an ExtendedAttributes instance directly or re-assign a \l {Place}'s
+ ExtendedAttributes property. Modification of ExtendedAttributes can only be accomplished
+ via Javascript.
+
+ The following example shows how to access all \l {PlaceAttribute}{PlaceAttributes} and print
+ them to the console:
+
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml ExtendedAttributes read
+
+ The following example shows how to assign and modify an attribute:
+ \snippet declarative/places.qml ExtendedAttributes write
+
+ \sa PlaceAttribute, QQmlPropertyMap
+*/
+
+/*!
+ \qmlmethod variant ExtendedAttributes::keys()
+
+ Returns an array of place attribute keys currently stored in the map.
+*/
+
+/*!
+ \qmlsignal void ExtendedAttributes::valueChanged(string key, variant value)
+
+ This signal is emitted when the set of attributes changes. \a key is the key
+ corresponding to the \a value that was changed.
+
+ The corresponding handler is \c onValueChanged.
+*/
+
+/*!
+ \qmltype PlaceAttribute
+ \instantiates QDeclarativePlaceAttribute
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+ \since Qt Location 5.5
+
+ \brief The PlaceAttribute type holds generic place attribute information.
+
+ A place attribute stores an additional piece of information about a \l Place that is not
+ otherwise exposed through the \l Place type. A PlaceAttribute is a textual piece of data,
+ accessible through the \l text property, and a \l label. Both the \l text and \l label
+ properties are intended to be displayed to the user. PlaceAttributes are stored in an
+ \l ExtendedAttributes map with a unique key.
+
+ The following example shows how to display all attributes in a list:
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml ExtendedAttributes
+
+ The following example shows how to assign and modify an attribute:
+ \snippet declarative/places.qml ExtendedAttributes write
+*/
+
+QDeclarativePlaceAttribute::QDeclarativePlaceAttribute(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QDeclarativePlaceAttribute::QDeclarativePlaceAttribute(const QPlaceAttribute &src, QObject *parent)
+ : QObject(parent),m_attribute(src)
+{
+}
+
+QDeclarativePlaceAttribute::~QDeclarativePlaceAttribute()
+{
+}
+
+/*!
+ \qmlproperty QPlaceAttribute PlaceAttribute::attribute
+
+ For details on how to use this property to interface between C++ and QML see
+ "\l {PlaceAttribute - QPlaceAttribute} {Interfaces between C++ and QML Code}".
+*/
+void QDeclarativePlaceAttribute::setAttribute(const QPlaceAttribute &src)
+{
+ QPlaceAttribute prevAttribute = m_attribute;
+ m_attribute = src;
+
+ if (m_attribute.label() != prevAttribute.label())
+ emit labelChanged();
+ if (m_attribute.text() != prevAttribute.text())
+ emit textChanged();
+}
+
+QPlaceAttribute QDeclarativePlaceAttribute::attribute() const
+{
+ return m_attribute;
+}
+
+/*!
+ \qmlproperty string PlaceAttribute::label
+
+ This property holds the attribute label which is a user visible string
+ describing the attribute.
+*/
+void QDeclarativePlaceAttribute::setLabel(const QString &label)
+{
+ if (m_attribute.label() != label) {
+ m_attribute.setLabel(label);
+ emit labelChanged();
+ }
+}
+
+QString QDeclarativePlaceAttribute::label() const
+{
+ return m_attribute.label();
+}
+
+/*!
+ \qmlproperty string PlaceAttribute::text
+
+ This property holds the attribute text which can be used to show additional information about the place.
+*/
+void QDeclarativePlaceAttribute::setText(const QString &text)
+{
+ if (m_attribute.text() != text) {
+ m_attribute.setText(text);
+ emit textChanged();
+ }
+}
+
+QString QDeclarativePlaceAttribute::text() const
+{
+ return m_attribute.text();
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativeplaceattribute_p.h b/src/location/declarativeplaces/qdeclarativeplaceattribute_p.h
new file mode 100644
index 00000000..8079df9c
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceattribute_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPLACEATTRIBUTE_P_H
+#define QDECLARATIVEPLACEATTRIBUTE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QObject>
+#include <QtQml/qqml.h>
+#include <QString>
+
+#include <QtLocation/qplaceattribute.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePlaceAttribute : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPlaceAttribute attribute READ attribute WRITE setAttribute)
+ Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
+ Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
+
+public:
+ explicit QDeclarativePlaceAttribute(QObject *parent = 0);
+ explicit QDeclarativePlaceAttribute(const QPlaceAttribute &src, QObject *parent = 0);
+ ~QDeclarativePlaceAttribute();
+
+ QPlaceAttribute attribute() const;
+ void setAttribute(const QPlaceAttribute &place);
+
+ QString text() const;
+ void setText(const QString &text);
+
+
+ QString label() const;
+ void setLabel(const QString &label);
+
+Q_SIGNALS:
+ void labelChanged();
+ void textChanged();
+
+private:
+ QPlaceAttribute m_attribute;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativePlaceAttribute)
+
+#endif
diff --git a/src/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp b/src/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp
new file mode 100644
index 00000000..faf7e418
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplacecontentmodel.cpp
@@ -0,0 +1,397 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeplacecontentmodel_p.h"
+#include "qdeclarativeplace_p.h"
+#include "qdeclarativegeoserviceprovider_p.h"
+#include "qdeclarativeplaceuser_p.h"
+#include "error_messages.h"
+
+#include <QtQml/QQmlInfo>
+#include <QtLocation/QGeoServiceProvider>
+#include <QtLocation/QPlaceManager>
+#include <QtLocation/QPlaceContentRequest>
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativePlaceContentModel::QDeclarativePlaceContentModel(QPlaceContent::Type type,
+ QObject *parent)
+: QAbstractListModel(parent), m_place(0), m_type(type), m_batchSize(1), m_contentCount(-1),
+ m_reply(0), m_complete(false)
+{
+}
+
+QDeclarativePlaceContentModel::~QDeclarativePlaceContentModel()
+{
+}
+
+/*!
+ \internal
+*/
+QDeclarativePlace *QDeclarativePlaceContentModel::place() const
+{
+ return m_place;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlaceContentModel::setPlace(QDeclarativePlace *place)
+{
+ if (m_place != place) {
+ beginResetModel();
+
+ int initialCount = m_contentCount;
+ clearData();
+ m_place = place;
+ endResetModel();
+
+ emit placeChanged();
+ if (initialCount != -1)
+ emit totalCountChanged();
+
+ fetchMore(QModelIndex());
+ }
+}
+
+/*!
+ \internal
+*/
+int QDeclarativePlaceContentModel::batchSize() const
+{
+ return m_batchSize;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlaceContentModel::setBatchSize(int batchSize)
+{
+ if (m_batchSize != batchSize) {
+ m_batchSize = batchSize;
+ emit batchSizeChanged();
+ }
+}
+
+/*!
+ \internal
+*/
+int QDeclarativePlaceContentModel::totalCount() const
+{
+ return m_contentCount;
+}
+
+/*!
+ \internal
+ Clears the model data but does not reset it.
+*/
+void QDeclarativePlaceContentModel::clearData()
+{
+ qDeleteAll(m_users);
+ m_users.clear();
+
+ qDeleteAll(m_suppliers);
+ m_suppliers.clear();
+
+ m_content.clear();
+
+ m_contentCount = -1;
+
+ if (m_reply) {
+ m_reply->abort();
+ m_reply->deleteLater();
+ m_reply = 0;
+ }
+
+ m_nextRequest.clear();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlaceContentModel::initializeCollection(int totalCount, const QPlaceContent::Collection &collection)
+{
+ beginResetModel();
+
+ int initialCount = m_contentCount;
+ clearData();
+
+ QMapIterator<int, QPlaceContent> i(collection);
+ while (i.hasNext()) {
+ i.next();
+
+ const QPlaceContent &content = i.value();
+ if (content.type() != m_type)
+ continue;
+
+ m_content.insert(i.key(), content);
+ if (!m_suppliers.contains(content.supplier().supplierId())) {
+ m_suppliers.insert(content.supplier().supplierId(),
+ new QDeclarativeSupplier(content.supplier(), m_place->plugin(), this));
+ }
+ if (!m_users.contains(content.user().userId())) {
+ m_users.insert(content.user().userId(),
+ new QDeclarativePlaceUser(content.user(), this));
+ }
+ }
+
+ m_contentCount = totalCount;
+
+ if (initialCount != totalCount)
+ emit totalCountChanged();
+
+ endResetModel();
+}
+
+/*!
+ \internal
+*/
+int QDeclarativePlaceContentModel::rowCount(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return 0;
+
+ return m_content.count();
+}
+
+/*!
+ \internal
+*/
+QVariant QDeclarativePlaceContentModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (index.row() >= rowCount(index.parent()) || index.row() < 0)
+ return QVariant();
+
+ const QPlaceContent &content = m_content.value(index.row());
+
+ switch (role) {
+ case SupplierRole:
+ return QVariant::fromValue(static_cast<QObject *>(m_suppliers.value(content.supplier().supplierId())));
+ case PlaceUserRole:
+ return QVariant::fromValue(static_cast<QObject *>(m_users.value(content.user().userId())));
+ case AttributionRole:
+ return content.attribution();
+ default:
+ return QVariant();
+ }
+}
+
+QHash<int, QByteArray> QDeclarativePlaceContentModel::roleNames() const
+{
+ QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
+ roles.insert(SupplierRole, "supplier");
+ roles.insert(PlaceUserRole, "user");
+ roles.insert(AttributionRole, "attribution");
+ return roles;
+}
+
+/*!
+ \internal
+*/
+bool QDeclarativePlaceContentModel::canFetchMore(const QModelIndex &parent) const
+{
+ if (parent.isValid())
+ return false;
+
+ if (!m_place)
+ return false;
+
+ if (m_contentCount == -1)
+ return true;
+
+ return m_content.count() != m_contentCount;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlaceContentModel::fetchMore(const QModelIndex &parent)
+{
+ if (parent.isValid())
+ return;
+
+ if (!m_place)
+ return;
+
+ if (m_reply)
+ return;
+
+ if (!m_place->plugin())
+ return;
+
+ QDeclarativeGeoServiceProvider *plugin = m_place->plugin();
+
+ QGeoServiceProvider *serviceProvider = plugin->sharedGeoServiceProvider();
+ if (!serviceProvider)
+ return;
+
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (!placeManager)
+ return;
+
+ if (m_nextRequest == QPlaceContentRequest()) {
+ QPlaceContentRequest request;
+ request.setContentType(m_type);
+ request.setPlaceId(m_place->place().placeId());
+ request.setLimit(m_batchSize);
+
+ m_reply = placeManager->getPlaceContent(request);
+ } else {
+ m_reply = placeManager->getPlaceContent(m_nextRequest);
+ }
+
+ connect(m_reply, SIGNAL(finished()), this, SLOT(fetchFinished()), Qt::QueuedConnection);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlaceContentModel::classBegin()
+{
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlaceContentModel::componentComplete()
+{
+ m_complete = true;
+ fetchMore(QModelIndex());
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlaceContentModel::fetchFinished()
+{
+ if (!m_reply)
+ return;
+
+ QPlaceContentReply *reply = m_reply;
+ m_reply = 0;
+
+ m_nextRequest = reply->nextPageRequest();
+
+ if (m_contentCount != reply->totalCount()) {
+ m_contentCount = reply->totalCount();
+ emit totalCountChanged();
+ }
+
+ if (!reply->content().isEmpty()) {
+ QPlaceContent::Collection contents = reply->content();
+
+ //find out which indexes are new and which ones have changed.
+ QMapIterator<int, QPlaceContent> it(contents);
+ QList<int> changedIndexes;
+ QList<int> newIndexes;
+ while (it.hasNext()) {
+ it.next();
+ if (!m_content.contains(it.key()))
+ newIndexes.append(it.key());
+ else if (it.value() != m_content.value(it.key()))
+ changedIndexes.append(it.key());
+ }
+
+ //insert new indexes in blocks where within each
+ //block, the indexes are consecutive.
+ QListIterator<int> newIndexesIter(newIndexes);
+ int startIndex = -1;
+ while (newIndexesIter.hasNext()) {
+ int currentIndex = newIndexesIter.next();
+ if (startIndex == -1)
+ startIndex = currentIndex;
+
+ if (!newIndexesIter.hasNext() || (newIndexesIter.hasNext() && (newIndexesIter.peekNext() > (currentIndex + 1)))) {
+ beginInsertRows(QModelIndex(),startIndex,currentIndex);
+ for (int i = startIndex; i <= currentIndex; ++i) {
+ const QPlaceContent &content = contents.value(i);
+
+ m_content.insert(i, content);
+ if (!m_suppliers.contains(content.supplier().supplierId())) {
+ m_suppliers.insert(content.supplier().supplierId(),
+ new QDeclarativeSupplier(content.supplier(), m_place->plugin(), this));
+ }
+ if (!m_users.contains(content.user().userId())) {
+ m_users.insert(content.user().userId(),
+ new QDeclarativePlaceUser(content.user(), this));
+ }
+ }
+ endInsertRows();
+ startIndex = -1;
+ }
+ }
+
+ //modify changed indexes in blocks where within each
+ //block, the indexes are consecutive.
+ startIndex = -1;
+ QListIterator<int> changedIndexesIter(changedIndexes);
+ while (changedIndexesIter.hasNext()) {
+ int currentIndex = changedIndexesIter.next();
+ if (startIndex == -1)
+ startIndex = currentIndex;
+
+ if (!changedIndexesIter.hasNext() || (changedIndexesIter.hasNext() && changedIndexesIter.peekNext() > (currentIndex + 1))) {
+ for (int i = startIndex; i <= currentIndex; ++i) {
+ const QPlaceContent &content = contents.value(i);
+ m_content.insert(i, content);
+ if (!m_suppliers.contains(content.supplier().supplierId())) {
+ m_suppliers.insert(content.supplier().supplierId(),
+ new QDeclarativeSupplier(content.supplier(), m_place->plugin(), this));
+ }
+ if (!m_users.contains(content.user().userId())) {
+ m_users.insert(content.user().userId(),
+ new QDeclarativePlaceUser(content.user(), this));
+ }
+ }
+ emit dataChanged(index(startIndex),index(currentIndex));
+ startIndex = -1;
+ }
+ }
+
+ // The fetch didn't add any new content and we haven't fetched all content yet. This is
+ // likely due to the model being prepopulated by Place::getDetails(). Keep fetching more
+ // data until new content is available.
+ if (newIndexes.isEmpty() && m_content.count() != m_contentCount)
+ fetchMore(QModelIndex());
+ }
+
+ reply->deleteLater();
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativeplacecontentmodel_p.h b/src/location/declarativeplaces/qdeclarativeplacecontentmodel_p.h
new file mode 100644
index 00000000..a8ed2fdb
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplacecontentmodel_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPLACECONTENTMODEL_H
+#define QDECLARATIVEPLACECONTENTMODEL_H
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtCore/QAbstractListModel>
+#include <QtQml/QQmlParserStatus>
+#include <QtLocation/QPlaceContent>
+#include <QtLocation/QPlaceContentReply>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativePlace;
+class QDeclarativeGeoServiceProvider;
+class QGeoServiceProvider;
+class QDeclarativeSupplier;
+class QDeclarativePlaceUser;
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePlaceContentModel : public QAbstractListModel, public QQmlParserStatus
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarativePlace *place READ place WRITE setPlace NOTIFY placeChanged)
+ Q_PROPERTY(int batchSize READ batchSize WRITE setBatchSize NOTIFY batchSizeChanged)
+ Q_PROPERTY(int totalCount READ totalCount NOTIFY totalCountChanged)
+
+ Q_INTERFACES(QQmlParserStatus)
+
+public:
+ explicit QDeclarativePlaceContentModel(QPlaceContent::Type type, QObject *parent = 0);
+ ~QDeclarativePlaceContentModel();
+
+ QDeclarativePlace *place() const;
+ void setPlace(QDeclarativePlace *place);
+
+ int batchSize() const;
+ void setBatchSize(int batchSize);
+
+ int totalCount() const;
+
+ void clearData();
+
+ void initializeCollection(int totalCount, const QPlaceContent::Collection &collection);
+
+ // from QAbstractListModel
+ int rowCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+ QHash<int, QByteArray> roleNames() const;
+
+ enum Roles {
+ SupplierRole = Qt::UserRole,
+ PlaceUserRole,
+ AttributionRole,
+ UserRole //indicator for next conten type specific role
+ };
+
+ bool canFetchMore(const QModelIndex &parent) const;
+ void fetchMore(const QModelIndex &parent);
+
+ // from QQmlParserStatus
+ void classBegin();
+ void componentComplete();
+
+Q_SIGNALS:
+ void placeChanged();
+ void batchSizeChanged();
+ void totalCountChanged();
+
+private Q_SLOTS:
+ void fetchFinished();
+
+protected:
+ QPlaceContent::Collection m_content;
+ QMap<QString, QDeclarativeSupplier *> m_suppliers;
+ QMap<QString, QDeclarativePlaceUser *>m_users;
+
+private:
+ QDeclarativePlace *m_place;
+ QPlaceContent::Type m_type;
+ int m_batchSize;
+ int m_contentCount;
+
+ QPlaceContentReply *m_reply;
+ QPlaceContentRequest m_nextRequest;
+
+ bool m_complete;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEPLACECONTENTMODEL_H
diff --git a/src/location/declarativeplaces/qdeclarativeplaceeditorialmodel.cpp b/src/location/declarativeplaces/qdeclarativeplaceeditorialmodel.cpp
new file mode 100644
index 00000000..dbc23737
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceeditorialmodel.cpp
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeplaceeditorialmodel_p.h"
+
+#include <QtCore/QUrl>
+#include <QtLocation/QPlaceEditorial>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype EditorialModel
+ \instantiates QDeclarativePlaceEditorialModel
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-models
+ \since Qt Location 5.5
+
+ \brief The EditorialModel type provides a model of place editorials.
+
+ The EditorialModel is a read-only model used to fetch editorials related to a \l Place.
+ Binding a \l Place via \l EditorialModel::place initiates an initial fetch of editorials.
+ The model performs fetches incrementally and is intended to be used in conjunction
+ with a View such as a \l ListView. When the View reaches the last of the editorials
+ currently in the model, a fetch is performed to retrieve more if they are available.
+ The View is automatically updated as the editorials are received. The number of
+ editorials which are fetched at a time is specified by the \l batchSize property.
+ The total number of editorials available can be accessed via the \l totalCount property.
+
+ The model returns data for the following roles:
+
+ \table
+ \header
+ \li Role
+ \li Type
+ \li Description
+ \row
+ \li text
+ \li string
+ \li The editorial's textual description of the place. It can be either rich (HTML based) text or plain text
+ depending upon the provider.
+ \row
+ \li title
+ \li string
+ \li The title of the editorial.
+ \row
+ \li language
+ \li string
+ \li The language that the editorial is written in.
+ \row
+ \li supplier
+ \li \l Supplier
+ \li The supplier of the editorial.
+ \row
+ \li user
+ \li \l {QtLocation::User}{User}
+ \li The user who contributed the editorial.
+ \row
+ \li attribution
+ \li string
+ \li Attribution text which must be displayed when displaying the editorial.
+ \endtable
+
+ \section1 Example
+
+ The following example shows how to display editorials for a place:
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml EditorialModel
+
+*/
+
+/*!
+ \qmlproperty Place EditorialModel::place
+
+ This property holds the Place that the editorials are for.
+*/
+
+/*!
+ \qmlproperty int EditorialModel::batchSize
+
+ This property holds the batch size to use when fetching more editorials items.
+*/
+
+/*!
+ \qmlproperty int EditorialModel::totalCount
+
+ This property holds the total number of editorial items for the place.
+*/
+
+QDeclarativePlaceEditorialModel::QDeclarativePlaceEditorialModel(QObject *parent)
+: QDeclarativePlaceContentModel(QPlaceContent::EditorialType, parent)
+{
+}
+
+QDeclarativePlaceEditorialModel::~QDeclarativePlaceEditorialModel()
+{
+}
+
+/*!
+ \internal
+*/
+QVariant QDeclarativePlaceEditorialModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (index.row() >= rowCount(index.parent()) || index.row() < 0)
+ return QVariant();
+
+ const QPlaceEditorial &description = m_content.value(index.row());
+
+ switch (role) {
+ case TextRole:
+ return description.text();
+ case TitleRole:
+ return description.title();
+ case LanguageRole:
+ return description.language();
+ }
+
+ return QDeclarativePlaceContentModel::data(index, role);
+}
+
+QHash<int, QByteArray> QDeclarativePlaceEditorialModel::roleNames() const
+{
+ QHash<int, QByteArray> roleNames = QDeclarativePlaceContentModel::roleNames();
+ roleNames.insert(TextRole, "text");
+ roleNames.insert(TitleRole, "title");
+ roleNames.insert(LanguageRole, "language");
+ return roleNames;
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativeplaceeditorialmodel_p.h b/src/location/declarativeplaces/qdeclarativeplaceeditorialmodel_p.h
new file mode 100644
index 00000000..f574677a
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceeditorialmodel_p.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPLACEEDITORIALMODEL_H
+#define QDECLARATIVEPLACEEDITORIALMODEL_H
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativeplacecontentmodel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePlaceEditorialModel : public QDeclarativePlaceContentModel
+{
+ Q_OBJECT
+
+public:
+ explicit QDeclarativePlaceEditorialModel(QObject *parent = 0);
+ ~QDeclarativePlaceEditorialModel();
+
+ QVariant data(const QModelIndex &index, int role) const;
+ QHash<int, QByteArray> roleNames() const;
+
+ enum Roles {
+ TextRole = UserRole,
+ TitleRole,
+ LanguageRole
+ };
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEPLACEEDITORIALMODEL_H
diff --git a/src/location/declarativeplaces/qdeclarativeplaceicon.cpp b/src/location/declarativeplaces/qdeclarativeplaceicon.cpp
new file mode 100644
index 00000000..24891138
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceicon.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeplaceicon_p.h"
+#include "error_messages.h"
+
+#include <QtLocation/QGeoServiceProvider>
+#include <QtLocation/QPlaceManager>
+#include <QtQml/QQmlInfo>
+#include <QCoreApplication>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Icon
+ \instantiates QDeclarativePlaceIcon
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+ \since Qt Location 5.5
+
+ \brief The Icon type represents an icon image source which can have multiple sizes.
+
+ The Icon type can be used in conjunction with an \l Image type to display an icon.
+ The \l url() function is used to construct an icon URL of a requested size,
+ the icon which most closely matches the requested size is returned.
+
+ The Icon type also has a parameters map which is a set of key value pairs. The precise
+ keys to use depend on the
+ \l {Qt Location#Plugin References and Parameters}{plugin} being used.
+ The parameters map is used by the \l Plugin to determine which URL to return.
+
+ In the case where an icon can only possibly have one image URL, the
+ parameter key of \c "singleUrl" can be used with a QUrl value. Any Icon with this
+ parameter will always return the specified URL regardless of the requested icon
+ size and not defer to any Plugin.
+
+ The following code shows how to display a 64x64 pixel icon:
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml Icon
+
+ Alternatively, a default sized icon can be specified like so:
+ \snippet declarative/places.qml Icon default
+*/
+
+QDeclarativePlaceIcon::QDeclarativePlaceIcon(QObject *parent)
+: QObject(parent), m_plugin(0), m_parameters(new QQmlPropertyMap(this))
+{
+}
+
+QDeclarativePlaceIcon::QDeclarativePlaceIcon(const QPlaceIcon &icon, QDeclarativeGeoServiceProvider *plugin, QObject *parent)
+: QObject(parent), m_parameters(new QQmlPropertyMap(this))
+{
+ if (icon.isEmpty())
+ m_plugin = 0;
+ else
+ m_plugin = plugin;
+
+ initParameters(icon.parameters());
+}
+
+QDeclarativePlaceIcon::~QDeclarativePlaceIcon()
+{
+}
+
+/*!
+ \qmlproperty QPlaceIcon Icon::icon
+
+ For details on how to use this property to interface between C++ and QML see
+ "\l {Icon - QPlaceIcon} {Interfaces between C++ and QML Code}".
+*/
+QPlaceIcon QDeclarativePlaceIcon::icon() const
+{
+ QPlaceIcon result;
+
+ if (m_plugin)
+ result.setManager(manager());
+ else
+ result.setManager(0);
+
+ QVariantMap params;
+ foreach (const QString &key, m_parameters->keys()) {
+ const QVariant value = m_parameters->value(key);
+ if (value.isValid()) {
+ params.insert(key, value);
+ }
+ }
+
+ result.setParameters(params);
+
+ return result;
+}
+
+void QDeclarativePlaceIcon::setIcon(const QPlaceIcon &src)
+{
+ initParameters(src.parameters());
+}
+
+/*!
+ \qmlmethod url Icon::url(size size)
+
+ Returns a URL for the icon image that most closely matches the given \a size.
+
+ If no plugin has been assigned to the icon, and the parameters do not contain the 'singleUrl' key, a default constructed URL
+ is returned.
+
+*/
+QUrl QDeclarativePlaceIcon::url(const QSize &size) const
+{
+ return icon().url(size);
+}
+
+/*!
+ \qmlproperty Object Icon::parameters
+
+ This property holds the parameters of the icon and is a map. These parameters
+ are used by the plugin to return the appropriate URL when url() is called and to
+ specify locations to save to when saving icons.
+
+ Consult the \l {Qt Location#Plugin References and Parameters}{plugin documentation}
+ for what parameters are supported and how they should be used.
+
+ Note, due to limitations of the QQmlPropertyMap, it is not possible
+ to declaratively specify the parameters in QML, assignment of parameters keys
+ and values can only be accomplished by JavaScript.
+
+*/
+QQmlPropertyMap *QDeclarativePlaceIcon::parameters() const
+{
+ return m_parameters;
+}
+
+/*!
+ \qmlproperty Plugin Icon::plugin
+
+ The property holds the plugin that is responsible for managing this icon.
+*/
+QDeclarativeGeoServiceProvider *QDeclarativePlaceIcon::plugin() const
+{
+ return m_plugin;
+}
+
+void QDeclarativePlaceIcon::setPlugin(QDeclarativeGeoServiceProvider *plugin)
+{
+ if (m_plugin == plugin)
+ return;
+
+ m_plugin = plugin;
+ emit pluginChanged();
+
+ if (!m_plugin)
+ return;
+
+ if (m_plugin->isAttached()) {
+ pluginReady();
+ } else {
+ connect(m_plugin, SIGNAL(attached()),
+ this, SLOT(pluginReady()));
+ }
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlaceIcon::pluginReady()
+{
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (!placeManager || serviceProvider->error() != QGeoServiceProvider::NoError) {
+ qmlWarning(this) << QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
+ .arg(m_plugin->name()).arg(serviceProvider->errorString());
+ return;
+ }
+}
+
+/*!
+ \internal
+ Helper function to return the manager from the plugin
+*/
+QPlaceManager *QDeclarativePlaceIcon::manager() const
+{
+ if (!m_plugin) {
+ qmlWarning(this) << QStringLiteral("Plugin is not assigned to place.");
+ return 0;
+ }
+
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (!serviceProvider)
+ return 0;
+
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+
+ if (!placeManager)
+ return 0;
+
+ return placeManager;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativePlaceIcon::initParameters(const QVariantMap &parameterMap)
+{
+ //clear out old parameters
+ foreach (const QString &key, m_parameters->keys())
+ m_parameters->clear(key);
+
+ foreach (const QString &key, parameterMap.keys()) {
+ QVariant value = parameterMap.value(key);
+ m_parameters->insert(key, value);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativeplaceicon_p.h b/src/location/declarativeplaces/qdeclarativeplaceicon_p.h
new file mode 100644
index 00000000..535d98eb
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceicon_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPLACEICON_P_H
+#define QDECLARATIVEPLACEICON_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativegeoserviceprovider_p.h>
+
+#include <QtLocation/qplaceicon.h>
+#include <QtQml/qqml.h>
+#include <QtQml/QQmlPropertyMap>
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlPropertyMap;
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePlaceIcon : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPlaceIcon icon READ icon WRITE setIcon)
+ Q_PROPERTY(QObject *parameters READ parameters NOTIFY parametersChanged)
+ Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged)
+
+public:
+ explicit QDeclarativePlaceIcon(QObject *parent = 0);
+ QDeclarativePlaceIcon(const QPlaceIcon &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent = 0);
+ ~QDeclarativePlaceIcon();
+
+ QPlaceIcon icon() const;
+ void setIcon(const QPlaceIcon &src);
+
+ Q_INVOKABLE QUrl url(const QSize &size = QSize()) const;
+
+ QQmlPropertyMap *parameters() const;
+
+ void setPlugin(QDeclarativeGeoServiceProvider *plugin);
+ QDeclarativeGeoServiceProvider *plugin() const;
+
+Q_SIGNALS:
+ void pluginChanged();
+ void parametersChanged(); //in practice is never emitted since parameters cannot be re-assigned
+ //the declaration is needed to avoid warnings about non-notifyable properties
+
+private Q_SLOTS:
+ void pluginReady();
+
+private:
+ QPlaceManager *manager() const;
+ void initParameters(const QVariantMap &parameterMap);
+ QDeclarativeGeoServiceProvider *m_plugin;
+ QQmlPropertyMap *m_parameters;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/location/declarativeplaces/qdeclarativeplaceimagemodel.cpp b/src/location/declarativeplaces/qdeclarativeplaceimagemodel.cpp
new file mode 100644
index 00000000..4da37081
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceimagemodel.cpp
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeplaceimagemodel_p.h"
+#include "qdeclarativesupplier_p.h"
+
+#include <QtCore/QUrl>
+#include <QtLocation/QPlaceImage>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ImageModel
+ \instantiates QDeclarativePlaceImageModel
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-models
+ \since Qt Location 5.5
+
+ \brief The ImageModel type provides a model of place images.
+
+ The ImageModel is a read-only model used to fetch images related to a \l Place.
+ Binding a \l Place via \l ImageModel::place initiates an initial fetch of images.
+ The model performs fetches incrementally and is intended to be used in conjunction
+ with a View such as a \l ListView. When the View reaches the last of the images
+ currently in the model, a fetch is performed to retrieve more if they are available.
+ The View is automatically updated as the images are received. The number of images
+ which are fetched at a time is specified by the \l batchSize property. The total number
+ of images available can be accessed via the \l totalCount property.
+
+ The model returns data for the following roles:
+
+ \table
+ \header
+ \li Role
+ \li Type
+ \li Description
+ \row
+ \li url
+ \li url
+ \li The URL of the image.
+ \row
+ \li imageId
+ \li string
+ \li The identifier of the image.
+ \row
+ \li mimeType
+ \li string
+ \li The MIME type of the image.
+ \row
+ \li supplier
+ \li \l Supplier
+ \li The supplier of the image.
+ \row
+ \li user
+ \li \l {QtLocation::User}{User}
+ \li The user who contributed the image.
+ \row
+ \li attribution
+ \li string
+ \li Attribution text which must be displayed when displaying the image.
+ \endtable
+
+
+ \section1 Example
+
+ The following example shows how to display images for a place:
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml ImageModel
+*/
+
+/*!
+ \qmlproperty Place ImageModel::place
+
+ This property holds the Place that the images are for.
+*/
+
+/*!
+ \qmlproperty int ImageModel::batchSize
+
+ This property holds the batch size to use when fetching more image items.
+*/
+
+/*!
+ \qmlproperty int ImageModel::totalCount
+
+ This property holds the total number of image items for the place.
+*/
+
+QDeclarativePlaceImageModel::QDeclarativePlaceImageModel(QObject *parent)
+: QDeclarativePlaceContentModel(QPlaceContent::ImageType, parent)
+{
+}
+
+QDeclarativePlaceImageModel::~QDeclarativePlaceImageModel()
+{
+ qDeleteAll(m_suppliers);
+}
+
+/*!
+ \internal
+*/
+QVariant QDeclarativePlaceImageModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (index.row() >= rowCount(index.parent()) || index.row() < 0)
+ return QVariant();
+
+ const QPlaceImage &image = m_content.value(index.row());
+
+ switch (role) {
+ case UrlRole:
+ return image.url();
+ case ImageIdRole:
+ return image.imageId();
+ case MimeTypeRole:
+ return image.mimeType();
+ }
+
+ return QDeclarativePlaceContentModel::data(index, role);
+}
+
+QHash<int, QByteArray> QDeclarativePlaceImageModel::roleNames() const
+{
+ QHash<int, QByteArray> roles = QDeclarativePlaceContentModel::roleNames();
+ roles.insert(UrlRole, "url");
+ roles.insert(ImageIdRole, "imageId");
+ roles.insert(MimeTypeRole, "mimeType");
+ return roles;
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h b/src/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h
new file mode 100644
index 00000000..2c244219
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceimagemodel_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPLACEIMAGEMODEL_P_H
+#define QDECLARATIVEPLACEIMAGEMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativeplacecontentmodel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeSupplier;
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePlaceImageModel : public QDeclarativePlaceContentModel
+{
+ Q_OBJECT
+
+public:
+ explicit QDeclarativePlaceImageModel(QObject *parent = 0);
+ ~QDeclarativePlaceImageModel();
+
+ QVariant data(const QModelIndex &index, int role) const;
+ QHash<int, QByteArray> roleNames() const;
+
+ enum Roles {
+ UrlRole = UserRole,
+ ImageIdRole,
+ MimeTypeRole
+ };
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/location/declarativeplaces/qdeclarativeplaceuser.cpp b/src/location/declarativeplaces/qdeclarativeplaceuser.cpp
new file mode 100644
index 00000000..86901a98
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceuser.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeplaceuser_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype User
+ \instantiates QDeclarativePlaceUser
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+ \since Qt Location 5.5
+
+ \brief The User type identifies a user who contributed a particular \l Place content item.
+
+ Each \l Place content item has an associated user who contributed the content. This type
+ provides information about that user.
+
+ \sa ImageModel, ReviewModel, EditorialModel
+
+ \section1 Example
+
+ The following example shows how to display information about the user who
+ submitted an editorial:
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml EditorialModel
+*/
+
+QDeclarativePlaceUser::QDeclarativePlaceUser(QObject *parent)
+ : QObject(parent) {}
+
+QDeclarativePlaceUser::QDeclarativePlaceUser(const QPlaceUser &user,
+ QObject *parent)
+ : QObject(parent),
+ m_user(user) {}
+
+QDeclarativePlaceUser::~QDeclarativePlaceUser() {}
+
+/*!
+ \qmlproperty QPlaceUser QtLocation::User::user
+
+ For details on how to use this property to interface between C++ and QML see
+ "\l {User - QPlaceUser} {Interfaces between C++ and QML Code}".
+*/
+void QDeclarativePlaceUser::setUser(const QPlaceUser &user)
+{
+ QPlaceUser previousUser = m_user;
+ m_user = user;
+
+ if (m_user.userId() != previousUser.userId())
+ emit userIdChanged();
+
+ if (m_user.name() != previousUser.name())
+ emit nameChanged();
+}
+
+QPlaceUser QDeclarativePlaceUser::user() const
+{
+ return m_user;
+}
+
+/*!
+ \qmlproperty string QtLocation::User::userId
+
+ This property holds the unique identifier of the user.
+*/
+
+void QDeclarativePlaceUser::setUserId(const QString &id)
+{
+ if (m_user.userId() == id)
+ return;
+
+ m_user.setUserId(id);
+ emit userIdChanged();
+}
+
+QString QDeclarativePlaceUser::userId() const
+{
+ return m_user.userId();
+}
+
+/*!
+ \qmlproperty string QtLocation::User::name
+
+ This property holds the name of a user.
+*/
+void QDeclarativePlaceUser::setName(const QString &name)
+{
+ if (m_user.name() == name)
+ return;
+
+ m_user.setName(name);
+ emit nameChanged();
+}
+
+QString QDeclarativePlaceUser::name() const
+{
+ return m_user.name();
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativeplaceuser_p.h b/src/location/declarativeplaces/qdeclarativeplaceuser_p.h
new file mode 100644
index 00000000..8cd64493
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeplaceuser_p.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPLACEUSER_P_H
+#define QDECLARATIVEPLACEUSER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtCore/QObject>
+#include <QtQml/qqml.h>
+#include <QtLocation/QPlaceUser>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePlaceUser : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPlaceUser user READ user WRITE setUser)
+ Q_PROPERTY(QString userId READ userId WRITE setUserId NOTIFY userIdChanged)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+
+public:
+ explicit QDeclarativePlaceUser(QObject *parent = 0);
+ explicit QDeclarativePlaceUser(const QPlaceUser &src, QObject *parent = 0);
+ ~QDeclarativePlaceUser();
+
+ QPlaceUser user() const;
+ void setUser(const QPlaceUser &src);
+
+ QString userId() const;
+ void setUserId(const QString &id);
+
+ QString name() const;
+ void setName(const QString &name);
+
+Q_SIGNALS:
+ void userIdChanged();
+ void nameChanged();
+
+private:
+ QPlaceUser m_user;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativePlaceUser)
+
+#endif
diff --git a/src/location/declarativeplaces/qdeclarativeratings.cpp b/src/location/declarativeplaces/qdeclarativeratings.cpp
new file mode 100644
index 00000000..150e5966
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeratings.cpp
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeratings_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Ratings
+ \instantiates QDeclarativeRatings
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+ \since Qt Location 5.5
+
+ \brief The Ratings type holds place rating information.
+
+ Rating information is used to describe how \e good a place is conceived to be. Typically this
+ information is visualized as a number of stars. The \l average property gives an aggregated
+ ratings value out of a possible maximum as given by the \l maximum property.
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml Ratings
+*/
+
+QDeclarativeRatings::QDeclarativeRatings(QObject *parent)
+ : QObject(parent) {}
+
+QDeclarativeRatings::QDeclarativeRatings(const QPlaceRatings &rating,
+ QObject *parent)
+ : QObject(parent),
+ m_ratings(rating) {}
+
+QDeclarativeRatings::~QDeclarativeRatings() {}
+
+/*!
+ \qmlproperty QPlaceRatings Ratings::ratings
+
+ For details on how to use this property to interface between C++ and QML see
+ "\l {Ratings - QPlaceRatings} {Interfaces between C++ and QML Code}".
+*/
+void QDeclarativeRatings::setRatings(const QPlaceRatings &ratings)
+{
+ QPlaceRatings previous = m_ratings;
+ m_ratings = ratings;
+
+ if (ratings.average() != previous.average()) {
+ emit averageChanged();
+ }
+ if (ratings.count() != previous.count()) {
+ emit countChanged();
+ }
+}
+
+QPlaceRatings QDeclarativeRatings::ratings() const
+{
+ return m_ratings;
+}
+
+/*!
+ \qmlproperty real Ratings::average
+
+ This property holds the average of the individual ratings.
+
+ \sa maximum
+*/
+void QDeclarativeRatings::setAverage(qreal average)
+{
+ if (m_ratings.average() != average) {
+ m_ratings.setAverage(average);
+ emit averageChanged();
+ }
+}
+
+qreal QDeclarativeRatings::average() const
+{
+ return m_ratings.average();
+}
+
+/*!
+ \qmlproperty real Ratings::maximum
+
+ This property holds the maximum rating value.
+*/
+void QDeclarativeRatings::setMaximum(qreal max)
+{
+ if (m_ratings.maximum() == max)
+ return;
+
+ m_ratings.setMaximum(max);
+ emit maximumChanged();
+}
+
+qreal QDeclarativeRatings::maximum() const
+{
+ return m_ratings.maximum();
+}
+
+/*!
+ \qmlproperty int Ratings::count
+
+ This property holds the total number of individual user ratings
+ used in determining the overall ratings \l average.
+*/
+void QDeclarativeRatings::setCount(int count)
+{
+ if (m_ratings.count() != count) {
+ m_ratings.setCount(count);
+ emit countChanged();
+ }
+}
+
+int QDeclarativeRatings::count() const
+{
+ return m_ratings.count();
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativeratings_p.h b/src/location/declarativeplaces/qdeclarativeratings_p.h
new file mode 100644
index 00000000..5ee530dc
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativeratings_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVERATINGS_P_H
+#define QDECLARATIVERATINGS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/qplaceratings.h>
+#include <QtQml/qqml.h>
+
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeRatings : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPlaceRatings ratings READ ratings WRITE setRatings)
+ Q_PROPERTY(qreal average READ average WRITE setAverage NOTIFY averageChanged)
+ Q_PROPERTY(qreal maximum READ maximum WRITE setMaximum NOTIFY maximumChanged)
+ Q_PROPERTY(int count READ count WRITE setCount NOTIFY countChanged)
+
+public:
+ explicit QDeclarativeRatings(QObject *parent = 0);
+ explicit QDeclarativeRatings(const QPlaceRatings &src, QObject *parent = 0);
+ ~QDeclarativeRatings();
+
+ QPlaceRatings ratings() const;
+ void setRatings(const QPlaceRatings &src);
+
+ qreal average() const;
+ void setAverage(qreal average);
+
+ qreal maximum() const;
+ void setMaximum(qreal max);
+
+ int count() const;
+ void setCount(int count);
+
+Q_SIGNALS:
+ void averageChanged();
+ void maximumChanged();
+ void countChanged();
+
+private:
+ QPlaceRatings m_ratings;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeRatings)
+
+#endif // QDECLARATIVERATING_P_H
diff --git a/src/location/declarativeplaces/qdeclarativereviewmodel.cpp b/src/location/declarativeplaces/qdeclarativereviewmodel.cpp
new file mode 100644
index 00000000..b7237bc9
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativereviewmodel.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativereviewmodel_p.h"
+#include "qdeclarativesupplier_p.h"
+
+#include <QtCore/QDateTime>
+#include <QtLocation/QPlaceReview>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype ReviewModel
+ \instantiates QDeclarativeReviewModel
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-models
+ \since Qt Location 5.5
+
+ \brief Provides access to reviews of a \l Place.
+
+ The ReviewModel is a read-only model used to fetch reviews about a \l Place. The model
+ incrementally fetches. The number of reviews which are fetched at a time is specified
+ by the \l batchSize property. The total number of reviews available can be accessed via the
+ \l totalCount property.
+
+ To use the ReviewModel we need a view and a delegate. In this snippet we
+ see the setting up of a ListView with a ReviewModel model and a delegate.
+
+ \snippet places/views/ReviewView.qml ReviewModel delegate
+
+ The model returns data for the following roles:
+
+ \table
+ \header
+ \li Role
+ \li Type
+ \li Description
+ \row
+ \li dateTime
+ \li datetime
+ \li The date and time that the review was posted.
+ \row
+ \li text
+ \li string
+ \li The review's textual description of the place. It can be either rich (HTML based) text or plain text
+ depending on the provider.
+ \row
+ \li language
+ \li string
+ \li The language that the review is written in.
+ \row
+ \li rating
+ \li real
+ \li The rating that the reviewer gave to the place.
+ \row
+ \li reviewId
+ \li string
+ \li The identifier of the review.
+ \row
+ \li title
+ \li string
+ \li The title of the review.
+ \row
+ \li supplier
+ \li \l Supplier
+ \li The supplier of the review.
+ \row
+ \li user
+ \li \l {QtLocation::User}{User}
+ \li The user who contributed the review.
+ \row
+ \li attribution
+ \li string
+ \li Attribution text which must be displayed when displaying the review.
+ \endtable
+*/
+
+/*!
+ \qmlproperty Place QtLocation::ReviewModel::place
+
+ This property holds the Place that the reviews are for.
+*/
+
+/*!
+ \qmlproperty int QtLocation::ReviewModel::batchSize
+
+ This property holds the batch size to use when fetching more reviews.
+*/
+
+/*!
+ \qmlproperty int QtLocation::ReviewModel::totalCount
+
+ This property holds the total number of reviews for the place.
+*/
+
+QDeclarativeReviewModel::QDeclarativeReviewModel(QObject *parent)
+: QDeclarativePlaceContentModel(QPlaceContent::ReviewType, parent)
+{
+}
+
+QDeclarativeReviewModel::~QDeclarativeReviewModel()
+{
+ qDeleteAll(m_suppliers);
+}
+
+/*!
+ \internal
+*/
+QVariant QDeclarativeReviewModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (index.row() >= rowCount(index.parent()) || index.row() < 0)
+ return QVariant();
+
+ const QPlaceReview &review = m_content.value(index.row());
+
+ switch (role) {
+ case DateTimeRole:
+ return review.dateTime();
+ case TextRole:
+ return review.text();
+ case LanguageRole:
+ return review.language();
+ case RatingRole:
+ return review.rating();
+ case ReviewIdRole:
+ return review.reviewId();
+ case TitleRole:
+ return review.title();
+ }
+
+ return QDeclarativePlaceContentModel::data(index, role);
+}
+
+QHash<int, QByteArray> QDeclarativeReviewModel::roleNames() const
+{
+ QHash<int, QByteArray> roles = QDeclarativePlaceContentModel::roleNames();
+ roles.insert(DateTimeRole, "dateTime");
+ roles.insert(TextRole, "text");
+ roles.insert(LanguageRole, "language");
+ roles.insert(RatingRole, "rating");
+ roles.insert(ReviewIdRole, "reviewId");
+ roles.insert(TitleRole, "title");
+ return roles;
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativereviewmodel_p.h b/src/location/declarativeplaces/qdeclarativereviewmodel_p.h
new file mode 100644
index 00000000..e6d2bd95
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativereviewmodel_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEREVIEWMODEL_P_H
+#define QDECLARATIVEREVIEWMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativeplacecontentmodel_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeReviewModel : public QDeclarativePlaceContentModel
+{
+ Q_OBJECT
+
+public:
+ explicit QDeclarativeReviewModel(QObject *parent = 0);
+ ~QDeclarativeReviewModel();
+
+ QVariant data(const QModelIndex &index, int role) const;
+ QHash<int, QByteArray> roleNames() const;
+ enum Roles {
+ DateTimeRole = UserRole,
+ TextRole,
+ LanguageRole,
+ RatingRole,
+ ReviewIdRole,
+ TitleRole
+ };
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEREVIEWMODEL_P_H
diff --git a/src/location/declarativeplaces/qdeclarativesearchmodelbase.cpp b/src/location/declarativeplaces/qdeclarativesearchmodelbase.cpp
new file mode 100644
index 00000000..3a3faa56
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesearchmodelbase.cpp
@@ -0,0 +1,362 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativesearchmodelbase_p.h"
+#include "qdeclarativeplace_p.h"
+#include "error_messages.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtQml/QQmlInfo>
+#include <QtLocation/QGeoServiceProvider>
+#include <QtLocation/QPlaceManager>
+#include <QtLocation/QPlaceSearchRequest>
+#include <QtLocation/QPlaceSearchReply>
+#include <QtPositioning/QGeoCircle>
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeSearchModelBase::QDeclarativeSearchModelBase(QObject *parent)
+: QAbstractListModel(parent), m_plugin(0), m_reply(0), m_complete(false), m_status(Null)
+{
+}
+
+QDeclarativeSearchModelBase::~QDeclarativeSearchModelBase()
+{
+}
+
+/*!
+ \internal
+*/
+QDeclarativeGeoServiceProvider *QDeclarativeSearchModelBase::plugin() const
+{
+ return m_plugin;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::setPlugin(QDeclarativeGeoServiceProvider *plugin)
+{
+ if (m_plugin == plugin)
+ return;
+
+ initializePlugin(plugin);
+
+ if (m_complete)
+ emit pluginChanged();
+}
+
+/*!
+ \internal
+*/
+QVariant QDeclarativeSearchModelBase::searchArea() const
+{
+ QGeoShape s = m_request.searchArea();
+ if (s.type() == QGeoShape::RectangleType)
+ return QVariant::fromValue(QGeoRectangle(s));
+ else if (s.type() == QGeoShape::CircleType)
+ return QVariant::fromValue(QGeoCircle(s));
+ else
+ return QVariant::fromValue(s);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::setSearchArea(const QVariant &searchArea)
+{
+ QGeoShape s;
+
+ if (searchArea.userType() == qMetaTypeId<QGeoRectangle>())
+ s = searchArea.value<QGeoRectangle>();
+ else if (searchArea.userType() == qMetaTypeId<QGeoCircle>())
+ s = searchArea.value<QGeoCircle>();
+ else if (searchArea.userType() == qMetaTypeId<QGeoShape>())
+ s = searchArea.value<QGeoShape>();
+
+ if (m_request.searchArea() == s)
+ return;
+
+ m_request.setSearchArea(s);
+ emit searchAreaChanged();
+}
+
+/*!
+ \internal
+*/
+int QDeclarativeSearchModelBase::limit() const
+{
+ return m_request.limit();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::setLimit(int limit)
+{
+ if (m_request.limit() == limit)
+ return;
+
+ m_request.setLimit(limit);
+ emit limitChanged();
+}
+
+/*!
+ \internal
+*/
+bool QDeclarativeSearchModelBase::previousPagesAvailable() const
+{
+ return m_previousPageRequest != QPlaceSearchRequest();
+}
+
+/*!
+ \internal
+*/
+bool QDeclarativeSearchModelBase::nextPagesAvailable() const
+{
+ return m_nextPageRequest != QPlaceSearchRequest();
+}
+
+/*!
+ \internal
+*/
+QDeclarativeSearchModelBase::Status QDeclarativeSearchModelBase::status() const
+{
+ return m_status;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::setStatus(Status status, const QString &errorString)
+{
+ Status prevStatus = m_status;
+
+ m_status = status;
+ m_errorString = errorString;
+
+ if (prevStatus != m_status)
+ emit statusChanged();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::update()
+{
+ if (m_reply)
+ return;
+
+ setStatus(Loading);
+
+ if (!m_plugin) {
+ clearData();
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROPERTY_NOT_SET));
+ return;
+ }
+
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (!serviceProvider) {
+ clearData();
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROVIDER_ERROR)
+ .arg(m_plugin->name()));
+ return;
+ }
+
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (!placeManager) {
+ clearData();
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
+ .arg(m_plugin->name()).arg(serviceProvider->errorString()));
+ return;
+ }
+
+ m_reply = sendQuery(placeManager, m_request);
+ if (!m_reply) {
+ clearData();
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, UNABLE_TO_MAKE_REQUEST));
+ return;
+ }
+
+ m_reply->setParent(this);
+ connect(m_reply, SIGNAL(finished()), this, SLOT(queryFinished()));
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::cancel()
+{
+ if (!m_reply)
+ return;
+
+ if (!m_reply->isFinished())
+ m_reply->abort();
+
+ if (m_reply) {
+ m_reply->deleteLater();
+ m_reply = 0;
+ }
+
+ setStatus(Ready);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::reset()
+{
+ beginResetModel();
+ clearData();
+ setStatus(Null);
+ endResetModel();
+}
+
+/*!
+ \internal
+*/
+QString QDeclarativeSearchModelBase::errorString() const
+{
+ return m_errorString;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::previousPage()
+{
+ if (m_previousPageRequest == QPlaceSearchRequest())
+ return;
+
+ m_request = m_previousPageRequest;
+ update();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::nextPage()
+{
+ if (m_nextPageRequest == QPlaceSearchRequest())
+ return;
+
+ m_request = m_nextPageRequest;
+ update();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::clearData(bool suppressSignal)
+{
+ Q_UNUSED(suppressSignal)
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::classBegin()
+{
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::componentComplete()
+{
+ m_complete = true;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::initializePlugin(QDeclarativeGeoServiceProvider *plugin)
+{
+ beginResetModel();
+ if (plugin != m_plugin) {
+ if (m_plugin)
+ disconnect(m_plugin, SIGNAL(nameChanged(QString)), this, SLOT(pluginNameChanged()));
+ if (plugin)
+ connect(plugin, SIGNAL(nameChanged(QString)), this, SLOT(pluginNameChanged()));
+ m_plugin = plugin;
+ }
+
+ if (m_plugin) {
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (serviceProvider) {
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (placeManager) {
+ if (placeManager->childCategoryIds().isEmpty()) {
+ QPlaceReply *reply = placeManager->initializeCategories();
+ connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater()));
+ }
+ }
+ }
+ }
+
+ endResetModel();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::pluginNameChanged()
+{
+ initializePlugin(m_plugin);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchModelBase::setPreviousPageRequest(const QPlaceSearchRequest &previous)
+{
+ if (m_previousPageRequest == previous)
+ return;
+
+ m_previousPageRequest = previous;
+ emit previousPagesAvailableChanged();
+}
+
+void QDeclarativeSearchModelBase::setNextPageRequest(const QPlaceSearchRequest &next)
+{
+ if (m_nextPageRequest == next)
+ return;
+
+ m_nextPageRequest = next;
+ emit nextPagesAvailableChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativesearchmodelbase_p.h b/src/location/declarativeplaces/qdeclarativesearchmodelbase_p.h
new file mode 100644
index 00000000..cb8e4032
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesearchmodelbase_p.h
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESEARCHMODELBASE_H
+#define QDECLARATIVESEARCHMODELBASE_H
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativegeoserviceprovider_p.h>
+#include <QtCore/QAbstractListModel>
+#include <QtQml/QQmlParserStatus>
+#include <QtLocation/QPlaceSearchRequest>
+#include <QtLocation/QPlaceSearchResult>
+#include <QtLocation/QPlaceReply>
+
+QT_BEGIN_NAMESPACE
+
+class QPlaceManager;
+class QPlaceSearchRequest;
+class QPlaceSearchReply;
+class QDeclarativePlace;
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeSearchModelBase : public QAbstractListModel, public QQmlParserStatus
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged)
+ Q_PROPERTY(QVariant searchArea READ searchArea WRITE setSearchArea NOTIFY searchAreaChanged)
+ Q_PROPERTY(int limit READ limit WRITE setLimit NOTIFY limitChanged)
+ Q_PROPERTY(bool previousPagesAvailable READ previousPagesAvailable NOTIFY previousPagesAvailableChanged)
+ Q_PROPERTY(bool nextPagesAvailable READ nextPagesAvailable NOTIFY nextPagesAvailableChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+
+ Q_ENUMS(Status)
+
+ Q_INTERFACES(QQmlParserStatus)
+
+public:
+ enum Status {
+ Null,
+ Ready,
+ Loading,
+ Error
+ };
+
+ explicit QDeclarativeSearchModelBase(QObject *parent = 0);
+ ~QDeclarativeSearchModelBase();
+
+ QDeclarativeGeoServiceProvider *plugin() const;
+ void setPlugin(QDeclarativeGeoServiceProvider *plugin);
+
+ QVariant searchArea() const;
+ void setSearchArea(const QVariant &searchArea);
+
+ int limit() const;
+ void setLimit(int limit);
+
+ bool previousPagesAvailable() const;
+ bool nextPagesAvailable() const;
+
+ Status status() const;
+ void setStatus(Status status, const QString &errorString = QString());
+
+ Q_INVOKABLE void update();
+
+ Q_INVOKABLE void cancel();
+ Q_INVOKABLE void reset();
+
+ Q_INVOKABLE QString errorString() const;
+
+ Q_INVOKABLE void previousPage();
+ Q_INVOKABLE void nextPage();
+
+ virtual void clearData(bool suppressSignal = false);
+
+ // From QQmlParserStatus
+ virtual void classBegin();
+ virtual void componentComplete();
+
+Q_SIGNALS:
+ void pluginChanged();
+ void searchAreaChanged();
+ void limitChanged();
+ void previousPagesAvailableChanged();
+ void nextPagesAvailableChanged();
+ void statusChanged();
+
+protected:
+ virtual void initializePlugin(QDeclarativeGeoServiceProvider *plugin);
+
+protected Q_SLOTS:
+ virtual void queryFinished() = 0;
+
+private Q_SLOTS:
+ void pluginNameChanged();
+
+protected:
+ virtual QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request) = 0;
+ void setPreviousPageRequest(const QPlaceSearchRequest &previous);
+ void setNextPageRequest(const QPlaceSearchRequest &next);
+
+ QPlaceSearchRequest m_request;
+ QDeclarativeGeoServiceProvider *m_plugin;
+ QPlaceReply *m_reply;
+
+private:
+ bool m_complete;
+ Status m_status;
+ QString m_errorString;
+ QPlaceSearchRequest m_previousPageRequest;
+ QPlaceSearchRequest m_nextPageRequest;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVESEARCHMODELBASE_H
diff --git a/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
new file mode 100644
index 00000000..31d152db
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesearchresultmodel.cpp
@@ -0,0 +1,917 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativesearchresultmodel_p.h"
+#include "qdeclarativeplace_p.h"
+#include "qdeclarativeplaceicon_p.h"
+
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlInfo>
+#include <QtLocation/QGeoServiceProvider>
+#include <QtLocation/QPlaceSearchReply>
+#include <QtLocation/QPlaceManager>
+#include <QtLocation/QPlaceMatchRequest>
+#include <QtLocation/QPlaceMatchReply>
+#include <QtLocation/QPlaceResult>
+#include <QtLocation/QPlaceProposedSearchResult>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype PlaceSearchModel
+ \instantiates QDeclarativeSearchResultModel
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-models
+ \since Qt Location 5.5
+
+ \brief Provides access to place search results.
+
+ PlaceSearchModel provides a model of place search results within the \l searchArea. The
+ \l searchTerm and \l categories properties can be set to restrict the search results to
+ places matching those criteria.
+
+ The PlaceSearchModel returns both sponsored and
+ \l {http://en.wikipedia.org/wiki/Organic_search}{organic search results}. Sponsored search
+ results will have the \c sponsored role set to true.
+
+ \target PlaceSearchModel Roles
+ The model returns data for the following roles:
+
+ \table
+ \header
+ \li Role
+ \li Type
+ \li Description
+ \row
+ \li type
+ \li enum
+ \li The type of search result.
+ \row
+ \li title
+ \li string
+ \li A string describing the search result.
+ \row
+ \li icon
+ \li PlaceIcon
+ \li Icon representing the search result.
+ \row
+ \li distance
+ \li real
+ \li Valid only when the \c type role is \c PlaceResult, the distance to the place
+ from the center of the \l searchArea. If no \l searchArea
+ has been specified, the distance is NaN.
+ \row
+ \li place
+ \li \l Place
+ \li Valid only when the \c type role is \c PlaceResult, an object representing the
+ place.
+ \row
+ \li sponsored
+ \li bool
+ \li Valid only when the \c type role is \c PlaceResult, true if the search result is a
+ sponsored result.
+ \endtable
+
+ \section2 Search Result Types
+
+ The \c type role can take on the following values:
+
+ \table
+ \row
+ \li PlaceSearchModel.UnknownSearchResult
+ \li The contents of the search result are unknown.
+ \row
+ \li PlaceSearchModel.PlaceResult
+ \li The search result contains a place.
+ \row
+ \li PlaceSearchModel.ProposedSearchResult
+ \li The search result contains a proposed search which may be relevant.
+ \endtable
+
+
+ It can often be helpful to use a \l Loader to create a delegate
+ that will choose different \l {Component}s based on the search result type.
+
+ \snippet declarative/places_loader.qml Handle Result Types
+
+ \section1 Detection of Updated and Removed Places
+
+ The PlaceSearchModel listens for places that have been updated or removed from its plugin's backend.
+ If it detects that a place has been updated and that place is currently present in the model, then
+ it will call \l Place::getDetails to refresh the details. If it detects that a place has been
+ removed, then correspondingly the place will be removed from the model if it is currently
+ present.
+
+ \section1 Example
+
+ The following example shows how to use the PlaceSearchModel to search for Pizza restaurants in
+ close proximity of a given position. A \l searchTerm and \l searchArea are provided to the model
+ and \l update() is used to perform a lookup query. Note that the model does not incrementally
+ fetch search results, but rather performs a single fetch when \l update() is run. The \l count
+ is set to the number of search results returned during the fetch.
+
+ \snippet places_list/places_list.qml Imports
+ \codeline
+ \snippet places_list/places_list.qml PlaceSearchModel
+
+ \sa CategoryModel, {QPlaceManager}
+
+ \section1 Paging
+ The PlaceSearchModel API has some limited support
+ for paging. The \l nextPage() and \l previousPage() functions as well as
+ the \l limit property can be used to access
+ paged search results. When the \l limit property is set
+ the search result page contains at most \l limit entries (of type place result).
+ For example, if the backend has 5 search results in total
+ [a,b,c,d,e], and assuming the first page is shown and limit of 3 has been set
+ then a,b,c is returned. The \l nextPage() would return d,e. The
+ \l nextPagesAvailable and \l previousPagesAvailable properties
+ can be used to check for further pages. At the moment the API does not
+ support the means to retrieve the total number of items available from the
+ backed. Note that support for \l nextPage(), previousPage() and \l limit can vary
+ according to the \l plugin.
+*/
+
+/*!
+ \qmlproperty Plugin PlaceSearchModel::plugin
+
+ This property holds the \l Plugin which will be used to perform the search.
+*/
+
+/*!
+ \qmlproperty Plugin PlaceSearchModel::favoritesPlugin
+
+ This property holds the \l Plugin which will be used to search for favorites.
+ Any places from the search which can be cross-referenced or matched
+ in the favoritesPlugin will have their \l {Place::favorite}{favorite} property
+ set to the corresponding \l Place from the favoritesPlugin.
+
+ If the favoritesPlugin is not set, the \l {Place::favorite}{favorite} property
+ of the places in the results will always be null.
+
+ \sa Favorites
+*/
+
+/*!
+ \qmlproperty VariantMap PlaceSearchModel::favoritesMatchParameters
+
+ This property holds a set of parameters used to specify how search result places
+ are matched to favorites in the favoritesPlugin.
+
+ By default the parameter map is empty and implies that the favorites plugin
+ matches by \l {Alternative Identifier Cross-Referencing}{alternative identifiers}. Generally,
+ an application developer will not need to set this property.
+
+ In cases where the favorites plugin does not support matching by alternative identifiers,
+ then the \l {Qt Location#Plugin References and Parameters}{plugin documentation} should
+ be consulted to see precisely what key-value parameters to set.
+*/
+
+/*!
+ \qmlproperty variant PlaceSearchModel::searchArea
+
+ This property holds the search area. The search result returned by the model will be within
+ the search area.
+
+ If this property is set to a \l {geocircle} its
+ \l {geocircle}{radius} property may be left unset, in which case the \l Plugin
+ will choose an appropriate radius for the search.
+
+ Support for specifying a search area can vary according to the \l plugin backend
+ implementation. For example, some may support a search center only while others may only
+ support geo rectangles.
+*/
+
+/*!
+ \qmlproperty int PlaceSearchModel::limit
+
+ This property holds the limit of the number of items that will be returned.
+*/
+
+/*!
+ \qmlproperty bool PlaceSearchModel::previousPagesAvailable
+
+ This property holds whether there is one or more previous pages of search results available.
+
+ \sa previousPage()
+*/
+
+/*!
+ \qmlproperty bool PlaceSearchModel::nextPagesAvailable
+
+ This property holds whether there is one or more additional pages of search results available.
+
+ \sa nextPage()
+*/
+
+/*!
+ \qmlproperty enum PlaceSearchModel::status
+
+ This property holds the status of the model. It can be one of:
+
+ \table
+ \row
+ \li PlaceSearchModel.Null
+ \li No search query has been executed. The model is empty.
+ \row
+ \li PlaceSearchModel.Ready
+ \li The search query has completed, and the results are available.
+ \row
+ \li PlaceSearchModel.Loading
+ \li A search query is currently being executed.
+ \row
+ \li PlaceSearchModel.Error
+ \li An error occurred when executing the previous search query.
+ \endtable
+*/
+
+/*!
+ \qmlmethod void PlaceSearchModel::update()
+
+ Updates the model based on the provided query parameters. The model will be populated with a
+ list of places matching the search parameters specified by the type's properties. Search
+ criteria is specified by setting properties such as the \l searchTerm, \l categories, \l searchArea and \l limit.
+ Support for these properties may vary according to \l plugin. \c update() then
+ submits the set of criteria to the \l plugin to process.
+
+ While the model is updating the \l status of the model is set to
+ \c PlaceSearchModel.Loading. If the model is successfully updated the \l status is set to
+ \c PlaceSearchModel.Ready, while if it unsuccessfully completes, the \l status is set to
+ \c PlaceSearchModel.Error and the model cleared.
+
+ \code
+ PlaceSearchModel {
+ id: model
+ plugin: backendPlugin
+ searchArea: QtPositioning.circle(QtPositioning.coordinate(10, 10))
+ ...
+ }
+
+ MouseArea {
+ ...
+ onClicked: {
+ model.searchTerm = "pizza";
+ model.categories = null; //not searching by any category
+ model.searchArea.center.latitude = -27.5;
+ model.searchArea.center.longitude = 153;
+ model.update();
+ }
+ }
+ \endcode
+
+ \sa cancel(), status
+*/
+
+/*!
+ \qmlmethod void PlaceSearchModel::cancel()
+
+ Cancels an ongoing search operation immediately and sets the model
+ status to PlaceSearchModel.Ready. The model retains any search
+ results it had before the operation was started.
+
+ If an operation is not ongoing, invoking cancel() has no effect.
+
+ \sa update(), status
+*/
+
+/*!
+ \qmlmethod void PlaceSearchModel::reset()
+
+ Resets the model. All search results are cleared, any outstanding requests are aborted and
+ possible errors are cleared. Model status will be set to PlaceSearchModel.Null.
+*/
+
+/*!
+ \qmlmethod string PlaceSearchModel::errorString() const
+
+ This read-only property holds the textual presentation of the latest place search model error.
+ If no error has occurred or if the model was cleared, an empty string is returned.
+
+ An empty string may also be returned if an error occurred which has no associated
+ textual representation.
+*/
+
+/*!
+ \qmlmethod void PlaceSearchModel::previousPage()
+
+ Updates the model to display the previous page of search results. If there is no previous page
+ then this method does nothing.
+*/
+
+/*!
+ \qmlmethod void PlaceSearchModel::nextPage()
+
+ Updates the model to display the next page of search results. If there is no next page then
+ this method does nothing.
+*/
+
+QDeclarativeSearchResultModel::QDeclarativeSearchResultModel(QObject *parent)
+ : QDeclarativeSearchModelBase(parent), m_favoritesPlugin(0)
+{
+}
+
+QDeclarativeSearchResultModel::~QDeclarativeSearchResultModel()
+{
+}
+
+/*!
+ \qmlproperty string PlaceSearchModel::searchTerm
+
+ This property holds search term used in query. The search term is a free-form text string.
+*/
+QString QDeclarativeSearchResultModel::searchTerm() const
+{
+ return m_request.searchTerm();
+}
+
+void QDeclarativeSearchResultModel::setSearchTerm(const QString &searchTerm)
+{
+ m_request.setSearchContext(QVariant());
+
+ if (m_request.searchTerm() == searchTerm)
+ return;
+
+ m_request.setSearchTerm(searchTerm);
+ emit searchTermChanged();
+}
+
+/*!
+ \qmlproperty list<Category> PlaceSearchModel::categories
+
+ This property holds a list of categories to be used when searching. Returned search results
+ will be for places that match at least one of the categories.
+*/
+QQmlListProperty<QDeclarativeCategory> QDeclarativeSearchResultModel::categories()
+{
+ return QQmlListProperty<QDeclarativeCategory>(this,
+ 0, // opaque data parameter
+ categories_append,
+ categories_count,
+ category_at,
+ categories_clear);
+}
+
+void QDeclarativeSearchResultModel::categories_append(QQmlListProperty<QDeclarativeCategory> *list,
+ QDeclarativeCategory *declCategory)
+{
+ QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
+ if (searchModel && declCategory) {
+ searchModel->m_request.setSearchContext(QVariant());
+ searchModel->m_categories.append(declCategory);
+ QList<QPlaceCategory> categories = searchModel->m_request.categories();
+ categories.append(declCategory->category());
+ searchModel->m_request.setCategories(categories);
+ emit searchModel->categoriesChanged();
+ }
+}
+
+int QDeclarativeSearchResultModel::categories_count(QQmlListProperty<QDeclarativeCategory> *list)
+{
+ QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
+ if (searchModel)
+ return searchModel->m_categories.count();
+ else
+ return -1;
+}
+
+QDeclarativeCategory *QDeclarativeSearchResultModel::category_at(QQmlListProperty<QDeclarativeCategory> *list,
+ int index)
+{
+ QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
+ if (searchModel && (searchModel->m_categories.count() > index) && (index > -1))
+ return searchModel->m_categories.at(index);
+ else
+ return 0;
+}
+
+void QDeclarativeSearchResultModel::categories_clear(QQmlListProperty<QDeclarativeCategory> *list)
+{
+ QDeclarativeSearchResultModel *searchModel = qobject_cast<QDeclarativeSearchResultModel *>(list->object);
+ if (searchModel) {
+ //note: we do not need to delete each of the objects in m_categories since the search model
+ //should never be the parent of the categories anyway.
+ searchModel->m_request.setSearchContext(QVariant());
+ searchModel->m_categories.clear();
+ searchModel->m_request.setCategories(QList<QPlaceCategory>());
+ emit searchModel->categoriesChanged();
+ }
+}
+
+/*!
+ \qmlproperty string PlaceSearchModel::recommendationId
+
+ This property holds the placeId to be used in order to find recommendations
+ for similar places.
+*/
+QString QDeclarativeSearchResultModel::recommendationId() const
+{
+ return m_request.recommendationId();
+}
+
+void QDeclarativeSearchResultModel::setRecommendationId(const QString &placeId)
+{
+ if (m_request.recommendationId() == placeId)
+ return;
+
+ m_request.setRecommendationId(placeId);
+ emit recommendationIdChanged();
+}
+
+/*!
+ \qmlproperty enumeration PlaceSearchModel::relevanceHint
+
+ This property holds a relevance hint used in the search query. The hint is given to the
+ provider to help but not dictate the ranking of results. For example, the distance hint may
+ give closer places a higher ranking but it does not necessarily mean the results will be
+ strictly ordered according to distance. A provider may ignore the hint altogether.
+
+ \table
+ \row
+ \li SearchResultModel.UnspecifiedHint
+ \li No relevance hint is given to the provider.
+ \row
+ \li SearchResultModel.DistanceHint
+ \li The distance of the place from the user's current location is important to the user.
+ This hint is only meaningful when a circular search area is used.
+ \row
+ \li SearchResultModel.LexicalPlaceNameHint
+ \li The lexical ordering of place names (in ascending alphabetical order) is relevant to
+ the user. This hint is useful for providers based on a local data store.
+ \endtable
+*/
+QDeclarativeSearchResultModel::RelevanceHint QDeclarativeSearchResultModel::relevanceHint() const
+{
+ return static_cast<QDeclarativeSearchResultModel::RelevanceHint>(m_request.relevanceHint());
+}
+
+void QDeclarativeSearchResultModel::setRelevanceHint(QDeclarativeSearchResultModel::RelevanceHint hint)
+{
+ if (m_request.relevanceHint() != static_cast<QPlaceSearchRequest::RelevanceHint>(hint)) {
+ m_request.setRelevanceHint(static_cast<QPlaceSearchRequest::RelevanceHint>(hint));
+ emit relevanceHintChanged();
+ }
+}
+
+/*!
+ \qmlproperty enum PlaceSearchModel::visibilityScope
+
+ This property holds the visibility scope of the places to search. Only places with the
+ specified visibility will be returned in the search results.
+
+ The visibility scope can be one of:
+
+ \table
+ \row
+ \li Place.UnspecifiedVisibility
+ \li No explicit visibility scope specified, places with any visibility may be part of
+ search results.
+ \row
+ \li Place.DeviceVisibility
+ \li Only places stored on the local device will be part of the search results.
+ \row
+ \li Place.PrivateVisibility
+ \li Only places that are private to the current user will be part of the search results.
+ \row
+ \li Place.PublicVisibility
+ \li Only places that are public will be part of the search results.
+ \endtable
+*/
+QDeclarativePlace::Visibility QDeclarativeSearchResultModel::visibilityScope() const
+{
+ return QDeclarativePlace::Visibility(int(m_visibilityScope));
+}
+
+void QDeclarativeSearchResultModel::setVisibilityScope(QDeclarativePlace::Visibility visibilityScope)
+{
+ QLocation::VisibilityScope scope = QLocation::VisibilityScope(visibilityScope);
+
+ if (m_visibilityScope == scope)
+ return;
+
+ m_visibilityScope = scope;
+ emit visibilityScopeChanged();
+}
+
+/*!
+ \internal
+*/
+QDeclarativeGeoServiceProvider *QDeclarativeSearchResultModel::favoritesPlugin() const
+{
+ return m_favoritesPlugin;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchResultModel::setFavoritesPlugin(QDeclarativeGeoServiceProvider *plugin)
+{
+
+ if (m_favoritesPlugin == plugin)
+ return;
+
+ m_favoritesPlugin = plugin;
+
+ if (m_favoritesPlugin) {
+ QGeoServiceProvider *serviceProvider = m_favoritesPlugin->sharedGeoServiceProvider();
+ if (serviceProvider) {
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (placeManager) {
+ if (placeManager->childCategoryIds().isEmpty()) {
+ QPlaceReply *reply = placeManager->initializeCategories();
+ connect(reply, SIGNAL(finished()), reply, SLOT(deleteLater()));
+ }
+ }
+ }
+ }
+
+ emit favoritesPluginChanged();
+}
+
+/*!
+ \internal
+*/
+QVariantMap QDeclarativeSearchResultModel::favoritesMatchParameters() const
+{
+ return m_matchParameters;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchResultModel::setFavoritesMatchParameters(const QVariantMap &parameters)
+{
+ if (m_matchParameters == parameters)
+ return;
+
+ m_matchParameters = parameters;
+ emit favoritesMatchParametersChanged();
+}
+
+/*!
+ \internal
+*/
+int QDeclarativeSearchResultModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return m_results.count();
+}
+
+void QDeclarativeSearchResultModel::clearData(bool suppressSignal)
+{
+ QDeclarativeSearchModelBase::clearData(suppressSignal);
+
+ qDeleteAll(m_places);
+ m_places.clear();
+ qDeleteAll(m_icons);
+ m_icons.clear();
+ if (!m_results.isEmpty()) {
+ m_results.clear();
+
+ if (!suppressSignal)
+ emit rowCountChanged();
+ }
+}
+
+QVariant QDeclarativeSearchResultModel::data(const QModelIndex &index, int role) const
+{
+ if (index.row() > m_results.count())
+ return QVariant();
+
+ const QPlaceSearchResult &result = m_results.at(index.row());
+
+ switch (role) {
+ case SearchResultTypeRole:
+ return result.type();
+ case Qt::DisplayRole:
+ case TitleRole:
+ return result.title();
+ case IconRole:
+ return QVariant::fromValue(static_cast<QObject *>(m_icons.at(index.row())));
+ case DistanceRole:
+ if (result.type() == QPlaceSearchResult::PlaceResult) {
+ QPlaceResult placeResult = result;
+ return placeResult.distance();
+ }
+ break;
+ case PlaceRole:
+ if (result.type() == QPlaceSearchResult::PlaceResult)
+ return QVariant::fromValue(static_cast<QObject *>(m_places.at(index.row())));
+ case SponsoredRole:
+ if (result.type() == QPlaceSearchResult::PlaceResult) {
+ QPlaceResult placeResult = result;
+ return placeResult.isSponsored();
+ }
+ break;
+ }
+ return QVariant();
+}
+
+/*!
+ \internal
+*/
+QVariant QDeclarativeSearchResultModel::data(int index, const QString &role) const
+{
+ QModelIndex modelIndex = createIndex(index, 0);
+ return data(modelIndex, roleNames().key(role.toLatin1()));
+}
+
+QHash<int, QByteArray> QDeclarativeSearchResultModel::roleNames() const
+{
+ QHash<int, QByteArray> roles = QDeclarativeSearchModelBase::roleNames();
+ roles.insert(SearchResultTypeRole, "type");
+ roles.insert(TitleRole, "title");
+ roles.insert(IconRole, "icon");
+ roles.insert(DistanceRole, "distance");
+ roles.insert(PlaceRole, "place");
+ roles.insert(SponsoredRole, "sponsored");
+
+ return roles;
+}
+
+/*!
+ \qmlmethod void PlaceSearchModel::updateWith(int proposedSearchIndex)
+
+ Updates the model based on the ProposedSearchResult at index \a proposedSearchIndex. The model
+ will be populated with a list of places matching the proposed search. Model status will be set
+ to PlaceSearchModel.Loading. If the model is updated successfully status will be set to
+ PlaceSearchModel.Ready. If an error occurs status will be set to PlaceSearchModel.Error and the
+ model cleared.
+
+ If \a proposedSearchIndex does not reference a ProposedSearchResult this method does nothing.
+*/
+void QDeclarativeSearchResultModel::updateWith(int proposedSearchIndex)
+{
+ if (m_results.at(proposedSearchIndex).type() != QPlaceSearchResult::ProposedSearchResult)
+ return;
+
+ m_request = QPlaceProposedSearchResult(m_results.at(proposedSearchIndex)).searchRequest();
+ update();
+}
+
+QPlaceReply *QDeclarativeSearchResultModel::sendQuery(QPlaceManager *manager,
+ const QPlaceSearchRequest &request)
+{
+ Q_ASSERT(manager);
+ return manager->search(request);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchResultModel::initializePlugin(QDeclarativeGeoServiceProvider *plugin)
+{
+ //disconnect the manager of the old plugin if we have one
+ if (m_plugin) {
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (serviceProvider) {
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (placeManager) {
+ disconnect(placeManager, SIGNAL(placeUpdated(QString)), this, SLOT(placeUpdated(QString)));
+ disconnect(placeManager, SIGNAL(placeRemoved(QString)), this, SLOT(placeRemoved(QString)));
+ connect(placeManager, SIGNAL(dataChanged()), this, SIGNAL(dataChanged()));
+ }
+ }
+ }
+
+ //connect to the manager of the new plugin.
+ if (plugin) {
+ QGeoServiceProvider *serviceProvider = plugin->sharedGeoServiceProvider();
+ if (serviceProvider) {
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (placeManager) {
+ connect(placeManager, SIGNAL(placeUpdated(QString)), this, SLOT(placeUpdated(QString)));
+ connect(placeManager, SIGNAL(placeRemoved(QString)), this, SLOT(placeRemoved(QString)));
+ disconnect(placeManager, SIGNAL(dataChanged()), this, SIGNAL(dataChanged()));
+ }
+ }
+ }
+ QDeclarativeSearchModelBase::initializePlugin(plugin);
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchResultModel::queryFinished()
+{
+ if (!m_reply)
+ return;
+ QPlaceReply *reply = m_reply;
+ m_reply = 0;
+ if (reply->error() != QPlaceReply::NoError) {
+ m_resultsBuffer.clear();
+ updateLayout();
+ setStatus(Error, reply->errorString());
+ reply->deleteLater();
+ return;
+ }
+
+ if (reply->type() == QPlaceReply::SearchReply) {
+ QPlaceSearchReply *searchReply = qobject_cast<QPlaceSearchReply *>(reply);
+ Q_ASSERT(searchReply);
+
+ m_resultsBuffer = searchReply->results();
+ setPreviousPageRequest(searchReply->previousPageRequest());
+ setNextPageRequest(searchReply->nextPageRequest());
+
+ reply->deleteLater();
+
+ if (!m_favoritesPlugin) {
+ updateLayout();
+ setStatus(Ready);
+ } else {
+ QGeoServiceProvider *serviceProvider = m_favoritesPlugin->sharedGeoServiceProvider();
+ if (!serviceProvider) {
+ updateLayout();
+ setStatus(Error, QStringLiteral("Favorites plugin returns a null QGeoServiceProvider instance"));
+ return;
+ }
+
+ QPlaceManager *favoritesManager = serviceProvider->placeManager();
+ if (!favoritesManager) {
+ updateLayout();
+ setStatus(Error, QStringLiteral("Favorites plugin returns a null QPlaceManager"));
+ return;
+ }
+
+ QPlaceMatchRequest request;
+ if (m_matchParameters.isEmpty()) {
+ if (!m_plugin) {
+ reply->deleteLater();
+ setStatus(Error, QStringLiteral("Plugin not assigned"));
+ return;
+ }
+
+ QVariantMap params;
+ params.insert(QPlaceMatchRequest::AlternativeId, QVariant(QString::fromLatin1("x_id_") + m_plugin->name()));
+ request.setParameters(params);
+ } else {
+ request.setParameters(m_matchParameters);
+ }
+
+ request.setResults(m_resultsBuffer);
+ m_reply = favoritesManager->matchingPlaces(request);
+ connect(m_reply, SIGNAL(finished()), this, SLOT(queryFinished()));
+ }
+ } else if (reply->type() == QPlaceReply::MatchReply) {
+ QPlaceMatchReply *matchReply = qobject_cast<QPlaceMatchReply *>(reply);
+ Q_ASSERT(matchReply);
+ updateLayout(matchReply->places());
+ setStatus(Ready);
+ reply->deleteLater();
+ } else {
+ setStatus(Error, QStringLiteral("Unknown reply type"));
+ reply->deleteLater();
+ }
+}
+
+/*!
+ \qmlmethod void PlaceSearchModel::data(int index, string role)
+
+ Returns the data for a given \a role at the specified row \a index.
+*/
+
+/*!
+ \qmlproperty int PlaceSearchModel::count
+
+ This property holds the number of results the model has.
+
+ Note that it does not refer to the total number of search results
+ available in the backend. The total number of search results
+ is not currently supported by the API.
+*/
+
+/*!
+ \internal
+ Note: m_results buffer should be correctly populated before
+ calling this function
+*/
+void QDeclarativeSearchResultModel::updateLayout(const QList<QPlace> &favoritePlaces)
+{
+ int oldRowCount = rowCount();
+
+ beginResetModel();
+ clearData(true);
+ m_results = m_resultsBuffer;
+ m_resultsBuffer.clear();
+
+ for (int i = 0; i < m_results.count(); ++i) {
+ const QPlaceSearchResult &result = m_results.at(i);
+
+ if (result.type() == QPlaceSearchResult::PlaceResult) {
+ QPlaceResult placeResult = result;
+ QDeclarativePlace *place = new QDeclarativePlace(placeResult.place(), plugin(), this);
+ m_places.append(place);
+
+ if ((favoritePlaces.count() == m_results.count()) && favoritePlaces.at(i) != QPlace())
+ m_places[i]->setFavorite(new QDeclarativePlace(favoritePlaces.at(i),
+ m_favoritesPlugin, m_places[i]));
+ } else if (result.type() == QPlaceSearchResult::ProposedSearchResult) {
+ m_places.append(0);
+ }
+
+ QDeclarativePlaceIcon *icon = 0;
+ if (!result.icon().isEmpty())
+ icon = new QDeclarativePlaceIcon(result.icon(), plugin(), this);
+ m_icons.append(icon);
+ }
+
+ endResetModel();
+ if (m_results.count() != oldRowCount)
+ emit rowCountChanged();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchResultModel::placeUpdated(const QString &placeId)
+{
+ int row = getRow(placeId);
+ if (row < 0 || row > m_places.count())
+ return;
+
+ if (m_places.at(row))
+ m_places.at(row)->getDetails();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchResultModel::placeRemoved(const QString &placeId)
+{
+ int row = getRow(placeId);
+ if (row < 0 || row > m_places.count())
+ return;
+
+ beginRemoveRows(QModelIndex(), row, row);
+ delete m_places.at(row);
+ m_places.removeAt(row);
+ m_results.removeAt(row);
+ endRemoveRows();
+
+ emit rowCountChanged();
+}
+
+/*!
+ \internal
+*/
+int QDeclarativeSearchResultModel::getRow(const QString &placeId) const
+{
+ for (int i = 0; i < m_places.count(); ++i) {
+ if (!m_places.at(i))
+ continue;
+ else if (m_places.at(i)->placeId() == placeId)
+ return i;
+ }
+
+ return -1;
+}
+
+/*!
+ \qmlsignal PlaceSearchResultModel::dataChanged()
+
+ This signal is emitted when significant changes have been made to the underlying datastore.
+
+ Applications should act on this signal at their own discretion. The data
+ provided by the model could be out of date and so the model should be reupdated
+ sometime, however an immediate reupdate may be disconcerting to users if the results
+ change without any action on their part.
+
+ The corresponding handler is \c onDataChanged.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h b/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h
new file mode 100644
index 00000000..77526fd0
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesearchresultmodel_p.h
@@ -0,0 +1,179 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESEARCHRESULTMODEL_P_H
+#define QDECLARATIVESEARCHRESULTMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativesearchmodelbase_p.h>
+#include <QtLocation/private/qdeclarativecategory_p.h>
+#include <QtLocation/private/qdeclarativeplace_p.h>
+#include <QtLocation/private/qdeclarativeplaceicon_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeGeoServiceProvider;
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeSearchResultModel : public QDeclarativeSearchModelBase
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString searchTerm READ searchTerm WRITE setSearchTerm NOTIFY searchTermChanged)
+ Q_PROPERTY(QQmlListProperty<QDeclarativeCategory> categories READ categories NOTIFY categoriesChanged)
+ Q_PROPERTY(QString recommendationId READ recommendationId WRITE setRecommendationId NOTIFY recommendationIdChanged)
+ Q_PROPERTY(RelevanceHint relevanceHint READ relevanceHint WRITE setRelevanceHint NOTIFY relevanceHintChanged)
+ Q_PROPERTY(QDeclarativePlace::Visibility visibilityScope READ visibilityScope WRITE setVisibilityScope NOTIFY visibilityScopeChanged)
+
+ Q_PROPERTY(int count READ rowCount NOTIFY rowCountChanged)
+ Q_PROPERTY(QDeclarativeGeoServiceProvider *favoritesPlugin READ favoritesPlugin WRITE setFavoritesPlugin NOTIFY favoritesPluginChanged)
+ Q_PROPERTY(QVariantMap favoritesMatchParameters READ favoritesMatchParameters WRITE setFavoritesMatchParameters NOTIFY favoritesMatchParametersChanged)
+
+ Q_ENUMS(SearchResultType RelevanceHint)
+
+public:
+ enum SearchResultType {
+ UnknownSearchResult = QPlaceSearchResult::UnknownSearchResult,
+ PlaceResult = QPlaceSearchResult::PlaceResult,
+ ProposedSearchResult = QPlaceSearchResult::ProposedSearchResult
+ };
+
+ enum RelevanceHint {
+ UnspecifiedHint = QPlaceSearchRequest::UnspecifiedHint,
+ DistanceHint = QPlaceSearchRequest::DistanceHint,
+ LexicalPlaceNameHint = QPlaceSearchRequest::LexicalPlaceNameHint
+ };
+
+ explicit QDeclarativeSearchResultModel(QObject *parent = 0);
+ ~QDeclarativeSearchResultModel();
+
+ QString searchTerm() const;
+ void setSearchTerm(const QString &searchTerm);
+
+ QQmlListProperty<QDeclarativeCategory> categories();
+ static void categories_append(QQmlListProperty<QDeclarativeCategory> *list,
+ QDeclarativeCategory *category);
+ static int categories_count(QQmlListProperty<QDeclarativeCategory> *list);
+ static QDeclarativeCategory *category_at(QQmlListProperty<QDeclarativeCategory> *list, int index);
+ static void categories_clear(QQmlListProperty<QDeclarativeCategory> *list);
+
+ QString recommendationId() const;
+ void setRecommendationId(const QString &recommendationId);
+
+ QDeclarativeSearchResultModel::RelevanceHint relevanceHint() const;
+ void setRelevanceHint(QDeclarativeSearchResultModel::RelevanceHint hint);
+
+ QDeclarativePlace::Visibility visibilityScope() const;
+ void setVisibilityScope(QDeclarativePlace::Visibility visibilityScope);
+
+ QDeclarativeGeoServiceProvider *favoritesPlugin() const;
+ void setFavoritesPlugin(QDeclarativeGeoServiceProvider *plugin);
+
+ QVariantMap favoritesMatchParameters() const;
+ void setFavoritesMatchParameters(const QVariantMap &parameters);
+
+ int rowCount(const QModelIndex &parent = QModelIndex()) const;
+
+ virtual void clearData(bool suppressSignal = false);
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ Q_INVOKABLE QVariant data(int index, const QString &roleName) const;
+ QHash<int, QByteArray> roleNames() const;
+
+ Q_INVOKABLE void updateWith(int proposedSearchIndex);
+
+ void updateSearchRequest();
+
+Q_SIGNALS:
+ void searchTermChanged();
+ void categoriesChanged();
+ void recommendationIdChanged();
+ void relevanceHintChanged();
+ void visibilityScopeChanged();
+
+ void rowCountChanged();
+ void favoritesPluginChanged();
+ void favoritesMatchParametersChanged();
+ void dataChanged();
+
+protected:
+ QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request);
+ virtual void initializePlugin(QDeclarativeGeoServiceProvider *plugin);
+
+protected Q_SLOTS:
+ virtual void queryFinished();
+
+private Q_SLOTS:
+ void updateLayout(const QList<QPlace> &favoritePlaces = QList<QPlace>());
+
+ void placeUpdated(const QString &placeId);
+ void placeRemoved(const QString &placeId);
+
+private:
+ enum Roles {
+ SearchResultTypeRole = Qt::UserRole,
+ TitleRole,
+ IconRole,
+ DistanceRole,
+ PlaceRole,
+ SponsoredRole
+ };
+
+ int getRow(const QString &placeId) const;
+ QList<QDeclarativeCategory *> m_categories;
+ QLocation::VisibilityScope m_visibilityScope;
+
+ QList<QPlaceSearchResult> m_results;
+ QList<QPlaceSearchResult> m_resultsBuffer;
+ QList<QDeclarativePlace *> m_places;
+ QList<QDeclarativePlaceIcon *> m_icons;
+
+ QDeclarativeGeoServiceProvider *m_favoritesPlugin;
+ QVariantMap m_matchParameters;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVESEARCHRESULTMODEL_P_H
diff --git a/src/location/declarativeplaces/qdeclarativesearchsuggestionmodel.cpp b/src/location/declarativeplaces/qdeclarativesearchsuggestionmodel.cpp
new file mode 100644
index 00000000..95cd3277
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesearchsuggestionmodel.cpp
@@ -0,0 +1,353 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativesearchsuggestionmodel_p.h"
+#include "qdeclarativegeoserviceprovider_p.h"
+
+#include <QtQml/QQmlInfo>
+#include <QtLocation/QGeoServiceProvider>
+
+#include <qplacemanager.h>
+#include <qplacesearchrequest.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype PlaceSearchSuggestionModel
+ \instantiates QDeclarativeSearchSuggestionModel
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-models
+ \since Qt Location 5.5
+
+ \brief Provides access to search term suggestions.
+
+ The PlaceSearchSuggestionModel can be used to provide search term suggestions as the user enters their
+ search term. The properties of this model should match that of the \l PlaceSearchModel, which
+ will be used to perform the actual search query, to ensure that the search suggestion results are
+ relevant.
+
+ There are two ways of accessing the data provided by this model, either through the
+ \l suggestions property or through views and delegates. The latter is the preferred
+ method.
+
+ The \l offset and \l limit properties can be used to access paged suggestions. When the
+ \l offset and \l limit properties are set the suggestions between \l offset and
+ (\l offset + \l limit - 1) will be returned. Support for paging may vary
+ from plugin to plugin.
+
+ The model returns data for the following roles:
+
+ \table
+ \header
+ \li Role
+ \li Type
+ \li Description
+ \row
+ \li suggestion
+ \li string
+ \li Suggested search term.
+ \endtable
+
+ The following example shows how to use the PlaceSearchSuggestionModel to get suggested search terms
+ from a partial search term. The \l searchArea is set to match what would be used to perform the
+ actual place search with \l PlaceSearchModel.
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml SearchSuggestionModel
+
+ \sa PlaceSearchModel, {QPlaceManager}
+*/
+
+/*!
+ \qmlproperty Plugin PlaceSearchSuggestionModel::plugin
+
+ This property holds the provider \l Plugin which will be used to perform the search.
+*/
+
+/*!
+ \qmlproperty geoshape PlaceSearchSuggestionModel::searchArea
+
+ This property holds the search area. Search suggestion results returned by the model will be
+ relevant to the given search area.
+
+ If this property is set to a \l {geocircle} its
+ \l {geocircle}{radius} property may be left unset, in which case the \l Plugin
+ will choose an appropriate radius for the search.
+*/
+
+/*!
+ \qmlproperty int PlaceSearchSuggestionModel::offset
+
+ This property holds the index of the first item in the model.
+
+ \sa limit
+*/
+
+/*!
+ \qmlproperty int PlaceSearchSuggestionModel::limit
+
+ This property holds the limit of the number of items that will be returned.
+
+ \sa offset
+*/
+
+/*!
+ \qmlproperty enum PlaceSearchSuggestionModel::status
+
+ This property holds the status of the model. It can be one of:
+
+ \table
+ \row
+ \li PlaceSearchSuggestionModel.Null
+ \li No search query has been executed. The model is empty.
+ \row
+ \li PlaceSearchSuggestionModel.Ready
+ \li The search query has completed, and the results are available.
+ \row
+ \li PlaceSearchSuggestionModel.Loading
+ \li A search query is currently being executed.
+ \row
+ \li PlaceSearchSuggestionModel.Error
+ \li An error occurred when executing the previous search query.
+ \endtable
+*/
+
+/*!
+ \qmlmethod void PlaceSearchSuggestionModel::update()
+
+ Updates the model based on the provided query parameters. The model will be populated with a
+ list of search suggestions for the partial \l searchTerm and \l searchArea. If the \l plugin
+ supports it, other parameters such as \l limit and \l offset may be specified. \c update()
+ submits the set of parameters to the \l plugin to process.
+
+
+ While the model is updating the \l status of the model is set to
+ \c PlaceSearchSuggestionModel.Loading. If the model is successfully updated, the \l status is
+ set to \c PlaceSearchSuggestionModel.Ready, while if it unsuccessfully completes, the \l status
+ is set to \c PlaceSearchSuggestionModel.Error and the model cleared.
+
+ This example shows use of the model
+ \code
+ PlaceSeachSuggestionModel {
+ id: model
+ plugin: backendPlugin
+ searchArea: QtPositioning.circle(QtPositioning.coordinate(10, 10))
+ ...
+ }
+
+ MouseArea {
+ ...
+ onClicked: {
+ model.searchTerm = "piz"
+ model.searchArea.center.latitude = -27.5;
+ model.searchArea.cetner.longitude = 153;
+ model.update();
+ }
+ }
+ \endcode
+
+ A more detailed example can be found in the in
+ \l {Places (QML)#Presenting-Search-Suggestions}{Places (QML)} example.
+
+ \sa cancel(), status
+*/
+
+/*!
+ \qmlmethod void PlaceSearchSuggestionModel::cancel()
+
+ Cancels an ongoing search suggestion operation immediately and sets the model
+ status to PlaceSearchSuggestionModel.Ready. The model retains any search
+ suggestions it had before the operation was started.
+
+ If an operation is not ongoing, invoking cancel() has no effect.
+
+ \sa update(), status
+*/
+
+/*!
+ \qmlmethod void PlaceSearchSuggestionModel::reset()
+
+ Resets the model. All search suggestions are cleared, any outstanding requests are aborted and
+ possible errors are cleared. Model status will be set to PlaceSearchSuggestionModel.Null.
+*/
+
+
+/*!
+ \qmlmethod string QtLocation::PlaceSearchSuggestionModel::errorString() const
+
+ This read-only property holds the textual presentation of the latest search suggestion model error.
+ If no error has occurred, or if the model was cleared, an empty string is returned.
+
+ An empty string may also be returned if an error occurred which has no associated
+ textual representation.
+*/
+
+QDeclarativeSearchSuggestionModel::QDeclarativeSearchSuggestionModel(QObject *parent)
+: QDeclarativeSearchModelBase(parent)
+{
+}
+
+QDeclarativeSearchSuggestionModel::~QDeclarativeSearchSuggestionModel()
+{
+}
+
+/*!
+ \qmlproperty string PlaceSearchSuggestionModel::searchTerm
+
+ This property holds the partial search term used in query.
+*/
+QString QDeclarativeSearchSuggestionModel::searchTerm() const
+{
+ return m_request.searchTerm();
+}
+
+void QDeclarativeSearchSuggestionModel::setSearchTerm(const QString &searchTerm)
+{
+ if (m_request.searchTerm() == searchTerm)
+ return;
+
+ m_request.setSearchTerm(searchTerm);
+ emit searchTermChanged();
+}
+
+/*!
+ \qmlproperty stringlist PlaceSearchSuggestionModel::suggestions
+
+ This property holds the list of predicted search terms that the model currently has.
+*/
+QStringList QDeclarativeSearchSuggestionModel::suggestions() const
+{
+ return m_suggestions;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchSuggestionModel::clearData(bool suppressSignal)
+{
+ QDeclarativeSearchModelBase::clearData(suppressSignal);
+
+ if (!m_suggestions.isEmpty()) {
+ m_suggestions.clear();
+
+ if (!suppressSignal)
+ emit suggestionsChanged();
+ }
+}
+
+/*!
+ \internal
+*/
+int QDeclarativeSearchSuggestionModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+
+ return m_suggestions.count();
+}
+
+/*!
+ \internal
+*/
+QVariant QDeclarativeSearchSuggestionModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (index.row() >= rowCount(index.parent()) || index.row() < 0)
+ return QVariant();
+
+ switch (role) {
+ case Qt::DisplayRole:
+ case SearchSuggestionRole:
+ return m_suggestions.at(index.row());
+ }
+
+ return QVariant();
+}
+
+QHash<int, QByteArray> QDeclarativeSearchSuggestionModel::roleNames() const
+{
+ QHash<int, QByteArray> roleNames = QDeclarativeSearchModelBase::roleNames();
+ roleNames.insert(SearchSuggestionRole, "suggestion");
+ return roleNames;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSearchSuggestionModel::queryFinished()
+{
+ if (!m_reply)
+ return;
+
+ QPlaceReply *reply = m_reply;
+ m_reply = 0;
+
+ int initialCount = m_suggestions.count();
+ beginResetModel();
+
+ clearData(true);
+
+ QPlaceSearchSuggestionReply *suggestionReply = qobject_cast<QPlaceSearchSuggestionReply *>(reply);
+ m_suggestions = suggestionReply->suggestions();
+
+ if (initialCount != m_suggestions.count())
+ emit suggestionsChanged();
+
+ endResetModel();
+
+ if (suggestionReply->error() != QPlaceReply::NoError)
+ setStatus(Error, suggestionReply->errorString());
+ else
+ setStatus(Ready);
+
+
+ reply->deleteLater();
+}
+
+/*!
+ \internal
+*/
+QPlaceReply *QDeclarativeSearchSuggestionModel::sendQuery(QPlaceManager *manager,
+ const QPlaceSearchRequest &request)
+{
+ return manager->searchSuggestions(request);
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h b/src/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h
new file mode 100644
index 00000000..5d75ee4b
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesearchsuggestionmodel_p.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESEARCHSUGGESTIONMODEL_P_H
+#define QDECLARATIVESEARCHSUGGESTIONMODEL_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativesearchmodelbase_p.h>
+
+#include <QtCore/QStringList>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeGeoServiceProvider;
+class QGeoServiceProvider;
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeSearchSuggestionModel : public QDeclarativeSearchModelBase
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QString searchTerm READ searchTerm WRITE setSearchTerm NOTIFY searchTermChanged)
+ Q_PROPERTY(QStringList suggestions READ suggestions NOTIFY suggestionsChanged)
+
+public:
+ explicit QDeclarativeSearchSuggestionModel(QObject *parent = 0);
+ ~QDeclarativeSearchSuggestionModel();
+
+ QString searchTerm() const;
+ void setSearchTerm(const QString &searchTerm);
+
+ QStringList suggestions() const;
+
+ void clearData(bool suppressSignal = false);
+
+ // From QAbstractListModel
+ int rowCount(const QModelIndex &parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+ QHash<int, QByteArray> roleNames() const;
+
+ enum Roles {
+ SearchSuggestionRole = Qt::UserRole
+ };
+
+protected Q_SLOTS:
+ virtual void queryFinished();
+
+Q_SIGNALS:
+ void searchTermChanged();
+ void suggestionsChanged();
+
+protected:
+ QPlaceReply *sendQuery(QPlaceManager *manager, const QPlaceSearchRequest &request);
+
+private:
+ QStringList m_suggestions;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/location/declarativeplaces/qdeclarativesupplier.cpp b/src/location/declarativeplaces/qdeclarativesupplier.cpp
new file mode 100644
index 00000000..92e9a8fd
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesupplier.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativesupplier_p.h"
+
+#include <QtCore/QUrl>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype Supplier
+ \instantiates QDeclarativeSupplier
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-data
+ \since Qt Location 5.5
+
+ \brief Holds data regarding the supplier of a place, a place's image, review, or editorial.
+
+ Each instance represents a set of data about a supplier, which can include
+ supplier's name, url and icon. The supplier is typically a business or organization.
+
+ Note: The Places API only supports suppliers as 'retrieve-only' objects. Submitting
+ suppliers to a provider is not a supported use case.
+
+ \sa ImageModel, ReviewModel, EditorialModel
+
+ \section1 Example
+
+ The following example shows how to create and display a supplier in QML:
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml Supplier
+*/
+
+QDeclarativeSupplier::QDeclarativeSupplier(QObject *parent)
+ : QObject(parent), m_icon(0)
+{
+}
+
+QDeclarativeSupplier::QDeclarativeSupplier(const QPlaceSupplier &src,
+ QDeclarativeGeoServiceProvider *plugin,
+ QObject *parent)
+ : QObject(parent),
+ m_src(src),
+ m_icon(0)
+{
+ setSupplier(src, plugin);
+}
+
+QDeclarativeSupplier::~QDeclarativeSupplier()
+{
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupplier::componentComplete()
+{
+ // delayed instantiation of QObject based properties.
+ if (!m_icon)
+ m_icon = new QDeclarativePlaceIcon(this);
+}
+
+/*!
+ \qmlproperty QPlaceSupplier Supplier::supplier
+
+ For details on how to use this property to interface between C++ and QML see
+ "\l {Supplier - QPlaceSupplier} {Interfaces between C++ and QML Code}".
+*/
+void QDeclarativeSupplier::setSupplier(const QPlaceSupplier &src, QDeclarativeGeoServiceProvider *plugin)
+{
+ QPlaceSupplier previous = m_src;
+ m_src = src;
+
+ if (previous.name() != m_src.name())
+ emit nameChanged();
+
+ if (previous.supplierId() != m_src.supplierId())
+ emit supplierIdChanged();
+
+ if (previous.url() != m_src.url())
+ emit urlChanged();
+
+ if (m_icon && m_icon->parent() == this) {
+ m_icon->setPlugin(plugin);
+ m_icon->setIcon(m_src.icon());
+ } else if (!m_icon || m_icon->parent() != this) {
+ m_icon = new QDeclarativePlaceIcon(m_src.icon(), plugin, this);
+ emit iconChanged();
+ }
+}
+
+QPlaceSupplier QDeclarativeSupplier::supplier()
+{
+ m_src.setIcon(m_icon ? m_icon->icon() : QPlaceIcon());
+ return m_src;
+}
+
+/*!
+ \qmlproperty string Supplier::supplierId
+
+ This property holds the identifier of the supplier. The identifier is unique
+ to the Plugin backend which provided the supplier and is generally
+ not suitable for displaying to the user.
+*/
+
+void QDeclarativeSupplier::setSupplierId(const QString &supplierId)
+{
+ if (m_src.supplierId() != supplierId) {
+ m_src.setSupplierId(supplierId);
+ emit supplierIdChanged();
+ }
+}
+
+QString QDeclarativeSupplier::supplierId() const
+{
+ return m_src.supplierId();
+}
+
+/*!
+ \qmlproperty string Supplier::name
+
+ This property holds the name of the supplier which can be displayed
+ to the user.
+
+ The name can potentially be localized. The language is dependent on the
+ entity that sets it, typically this is the \l Plugin. The \l {Plugin::locales}
+ property defines what language is used.
+*/
+
+void QDeclarativeSupplier::setName(const QString &name)
+{
+ if (m_src.name() != name) {
+ m_src.setName(name);
+ emit nameChanged();
+ }
+}
+
+QString QDeclarativeSupplier::name() const
+{
+ return m_src.name();
+}
+
+/*!
+ \qmlproperty url Supplier::url
+
+ This property holds the URL of the supplier's website.
+*/
+
+void QDeclarativeSupplier::setUrl(const QUrl &url)
+{
+ if (m_src.url() != url) {
+ m_src.setUrl(url);
+ emit urlChanged();
+ }
+}
+
+QUrl QDeclarativeSupplier::url() const
+{
+ return m_src.url();
+}
+
+/*!
+ \qmlproperty PlaceIcon Supplier::icon
+
+ This property holds the icon of the supplier.
+*/
+QDeclarativePlaceIcon *QDeclarativeSupplier::icon() const
+{
+ return m_icon;
+}
+
+void QDeclarativeSupplier::setIcon(QDeclarativePlaceIcon *icon)
+{
+ if (m_icon == icon)
+ return;
+
+ if (m_icon && m_icon->parent() == this)
+ delete m_icon;
+
+ m_icon = icon;
+ emit iconChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativesupplier_p.h b/src/location/declarativeplaces/qdeclarativesupplier_p.h
new file mode 100644
index 00000000..b344d674
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesupplier_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESUPPLIER_P_H
+#define QDECLARATIVESUPPLIER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QObject>
+#include <QtCore/QUrl>
+#include <QtQml/qqml.h>
+#include <QtQml/QQmlParserStatus>
+#include <QtLocation/qplacesupplier.h>
+
+#include <QtLocation/private/qdeclarativeplaceicon_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeSupplier : public QObject, public QQmlParserStatus
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QPlaceSupplier supplier READ supplier WRITE setSupplier)
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QString supplierId READ supplierId WRITE setSupplierId NOTIFY supplierIdChanged)
+ Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
+ Q_PROPERTY(QDeclarativePlaceIcon *icon READ icon WRITE setIcon NOTIFY iconChanged)
+
+ Q_INTERFACES(QQmlParserStatus)
+
+public:
+ explicit QDeclarativeSupplier(QObject *parent = 0);
+ explicit QDeclarativeSupplier(const QPlaceSupplier &src, QDeclarativeGeoServiceProvider *plugin, QObject *parent = 0);
+ ~QDeclarativeSupplier();
+
+ // From QQmlParserStatus
+ void classBegin() { }
+ void componentComplete();
+
+ QPlaceSupplier supplier();
+ void setSupplier(const QPlaceSupplier &src, QDeclarativeGeoServiceProvider *plugin = 0);
+
+ QString name() const;
+ void setName(const QString &data);
+ QString supplierId() const;
+ void setSupplierId(const QString &data);
+ QUrl url() const;
+ void setUrl(const QUrl &data);
+
+ QDeclarativePlaceIcon *icon() const;
+ void setIcon(QDeclarativePlaceIcon *icon);
+
+Q_SIGNALS:
+ void nameChanged();
+ void supplierIdChanged();
+ void urlChanged();
+ void iconChanged();
+
+private:
+ QPlaceSupplier m_src;
+ QDeclarativePlaceIcon *m_icon;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeSupplier)
+
+#endif // QDECLARATIVESUPPLIER_P_H
diff --git a/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp b/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
new file mode 100644
index 00000000..d832ff40
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel.cpp
@@ -0,0 +1,689 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Aaron McCarthy <mccarthy.aaron@gmail.com>
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativesupportedcategoriesmodel_p.h"
+#include "qdeclarativeplaceicon_p.h"
+#include "qgeoserviceprovider.h"
+#include "error_messages.h"
+
+#include <QCoreApplication>
+#include <QtQml/QQmlInfo>
+#include <QtLocation/QPlaceManager>
+#include <QtLocation/QPlaceIcon>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype CategoryModel
+ \instantiates QDeclarativeSupportedCategoriesModel
+ \inqmlmodule QtLocation
+ \ingroup qml-QtLocation5-places
+ \ingroup qml-QtLocation5-places-models
+ \since Qt Location 5.5
+
+ \brief The CategoryModel type provides a model of the categories supported by a \l Plugin.
+
+ The CategoryModel type provides a model of the categories that are available from the
+ current \l Plugin. The model supports both a flat list of categories and a hierarchical tree
+ representing category groupings. This can be controlled by the \l hierarchical property.
+
+ The model supports the following roles:
+
+ \table
+ \header
+ \li Role
+ \li Type
+ \li Description
+ \row
+ \li category
+ \li \l Category
+ \li Category object for the current item.
+ \row
+ \li parentCategory
+ \li \l Category
+ \li Parent category object for the current item.
+ If there is no parent, null is returned.
+ \endtable
+
+ The following example displays a flat list of all available categories:
+
+ \snippet declarative/places.qml QtQuick import
+ \snippet declarative/maps.qml QtLocation import
+ \codeline
+ \snippet declarative/places.qml CategoryView
+
+ To access the hierarchical category model it is necessary to use a \l DelegateModel to access
+ the child items.
+*/
+
+/*!
+ \qmlproperty Plugin CategoryModel::plugin
+
+ This property holds the provider \l Plugin used by this model.
+*/
+
+/*!
+ \qmlproperty bool CategoryModel::hierarchical
+
+ This property holds whether the model provides a hierarchical tree of categories or a flat
+ list. The default is true.
+*/
+
+/*!
+ \qmlmethod string QtLocation::CategoryModel::data(ModelIndex index, int role)
+ \internal
+
+ This method retrieves the model's data per \a index and \a role.
+*/
+
+/*!
+ \qmlmethod string QtLocation::CategoryModel::errorString() const
+
+ This read-only property holds the textual presentation of the latest category model error.
+ If no error has occurred, an empty string is returned.
+
+ An empty string may also be returned if an error occurred which has no associated
+ textual representation.
+*/
+
+/*!
+ \internal
+ \enum QDeclarativeSupportedCategoriesModel::Roles
+*/
+
+QDeclarativeSupportedCategoriesModel::QDeclarativeSupportedCategoriesModel(QObject *parent)
+: QAbstractItemModel(parent), m_response(0), m_plugin(0), m_hierarchical(true),
+ m_complete(false), m_status(Null)
+{
+}
+
+QDeclarativeSupportedCategoriesModel::~QDeclarativeSupportedCategoriesModel()
+{
+ qDeleteAll(m_categoriesTree);
+}
+
+/*!
+ \internal
+*/
+// From QQmlParserStatus
+void QDeclarativeSupportedCategoriesModel::componentComplete()
+{
+ m_complete = true;
+}
+
+/*!
+ \internal
+*/
+int QDeclarativeSupportedCategoriesModel::rowCount(const QModelIndex &parent) const
+{
+ if (m_categoriesTree.keys().isEmpty())
+ return 0;
+
+ PlaceCategoryNode *node = static_cast<PlaceCategoryNode *>(parent.internalPointer());
+ if (!node)
+ node = m_categoriesTree.value(QString());
+ else if (m_categoriesTree.keys(node).isEmpty())
+ return 0;
+
+ return node->childIds.count();
+}
+
+/*!
+ \internal
+*/
+int QDeclarativeSupportedCategoriesModel::columnCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent)
+
+ return 1;
+}
+
+/*!
+ \internal
+*/
+QModelIndex QDeclarativeSupportedCategoriesModel::index(int row, int column, const QModelIndex &parent) const
+{
+ if (column != 0 || row < 0)
+ return QModelIndex();
+
+ PlaceCategoryNode *node = static_cast<PlaceCategoryNode *>(parent.internalPointer());
+
+ if (!node)
+ node = m_categoriesTree.value(QString());
+ else if (m_categoriesTree.keys(node).isEmpty()) //return root index if parent is non-existent
+ return QModelIndex();
+
+ if (row > node->childIds.count())
+ return QModelIndex();
+
+ QString id = node->childIds.at(row);
+ Q_ASSERT(m_categoriesTree.contains(id));
+
+ return createIndex(row, 0, m_categoriesTree.value(id));
+}
+
+/*!
+ \internal
+*/
+QModelIndex QDeclarativeSupportedCategoriesModel::parent(const QModelIndex &child) const
+{
+ PlaceCategoryNode *childNode = static_cast<PlaceCategoryNode *>(child.internalPointer());
+ if (m_categoriesTree.keys(childNode).isEmpty())
+ return QModelIndex();
+
+ return index(childNode->parentId);
+}
+
+/*!
+ \internal
+*/
+QVariant QDeclarativeSupportedCategoriesModel::data(const QModelIndex &index, int role) const
+{
+ PlaceCategoryNode *node = static_cast<PlaceCategoryNode *>(index.internalPointer());
+ if (!node)
+ node = m_categoriesTree.value(QString());
+ else if (m_categoriesTree.keys(node).isEmpty())
+ return QVariant();
+
+ QDeclarativeCategory *category = node->declCategory.data();
+
+ switch (role) {
+ case Qt::DisplayRole:
+ return category->name();
+ case CategoryRole:
+ return QVariant::fromValue(category);
+ case ParentCategoryRole: {
+ if (!m_categoriesTree.keys().contains(node->parentId))
+ return QVariant();
+ else
+ return QVariant::fromValue(m_categoriesTree.value(node->parentId)->declCategory.data());
+ }
+ default:
+ return QVariant();
+ }
+}
+
+QHash<int, QByteArray> QDeclarativeSupportedCategoriesModel::roleNames() const
+{
+ QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
+ roles.insert(CategoryRole, "category");
+ roles.insert(ParentCategoryRole, "parentCategory");
+ return roles;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupportedCategoriesModel::setPlugin(QDeclarativeGeoServiceProvider *plugin)
+{
+ if (m_plugin == plugin)
+ return;
+
+ //disconnect the manager of the old plugin if we have one
+ if (m_plugin) {
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (serviceProvider) {
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (placeManager) {
+ disconnect(placeManager, SIGNAL(categoryAdded(QPlaceCategory,QString)),
+ this, SLOT(addedCategory(QPlaceCategory,QString)));
+ disconnect(placeManager, SIGNAL(categoryUpdated(QPlaceCategory,QString)),
+ this, SLOT(updatedCategory(QPlaceCategory,QString)));
+ disconnect(placeManager, SIGNAL(categoryRemoved(QString,QString)),
+ this, SLOT(removedCategory(QString,QString)));
+ disconnect(placeManager, SIGNAL(dataChanged()),
+ this, SIGNAL(dataChanged()));
+ }
+ }
+ }
+
+ m_plugin = plugin;
+
+ // handle plugin name changes -> update categories
+ if (m_plugin) {
+ connect(m_plugin, SIGNAL(nameChanged(QString)), this, SLOT(connectNotificationSignals()));
+ connect(m_plugin, SIGNAL(nameChanged(QString)), this, SLOT(update()));
+ }
+
+ connectNotificationSignals();
+
+ if (m_complete)
+ emit pluginChanged();
+}
+
+/*!
+ \internal
+*/
+QDeclarativeGeoServiceProvider *QDeclarativeSupportedCategoriesModel::plugin() const
+{
+ return m_plugin;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupportedCategoriesModel::setHierarchical(bool hierarchical)
+{
+ if (m_hierarchical == hierarchical)
+ return;
+
+ m_hierarchical = hierarchical;
+ emit hierarchicalChanged();
+
+ updateLayout();
+}
+
+/*!
+ \internal
+*/
+bool QDeclarativeSupportedCategoriesModel::hierarchical() const
+{
+ return m_hierarchical;
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupportedCategoriesModel::replyFinished()
+{
+ if (!m_response)
+ return;
+
+ m_response->deleteLater();
+
+ if (m_response->error() == QPlaceReply::NoError) {
+ m_errorString.clear();
+
+ m_response = 0;
+
+ updateLayout();
+ setStatus(QDeclarativeSupportedCategoriesModel::Ready);
+ } else {
+ const QString errorString = m_response->errorString();
+
+ m_response = 0;
+
+ setStatus(Error, errorString);
+ }
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupportedCategoriesModel::addedCategory(const QPlaceCategory &category,
+ const QString &parentId)
+{
+ if (m_response)
+ return;
+
+ if (!m_categoriesTree.contains(parentId))
+ return;
+
+ if (category.categoryId().isEmpty())
+ return;
+
+ PlaceCategoryNode *parentNode = m_categoriesTree.value(parentId);
+ if (!parentNode)
+ return;
+
+ int rowToBeAdded = rowToAddChild(parentNode, category);
+ QModelIndex parentIndex = index(parentId);
+ beginInsertRows(parentIndex, rowToBeAdded, rowToBeAdded);
+ PlaceCategoryNode *categoryNode = new PlaceCategoryNode;
+ categoryNode->parentId = parentId;
+ categoryNode->declCategory = QSharedPointer<QDeclarativeCategory>(new QDeclarativeCategory(category, m_plugin, this));
+
+ m_categoriesTree.insert(category.categoryId(), categoryNode);
+ parentNode->childIds.insert(rowToBeAdded,category.categoryId());
+ endInsertRows();
+
+ //this is a workaround to deal with the fact that the hasModelChildren field of DelegateModel
+ //does not get updated when a child is added to a model
+ beginResetModel();
+ endResetModel();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupportedCategoriesModel::updatedCategory(const QPlaceCategory &category,
+ const QString &parentId)
+{
+ if (m_response)
+ return;
+
+ QString categoryId = category.categoryId();
+
+ if (!m_categoriesTree.contains(parentId))
+ return;
+
+ if (category.categoryId().isEmpty() || !m_categoriesTree.contains(categoryId))
+ return;
+
+ PlaceCategoryNode *newParentNode = m_categoriesTree.value(parentId);
+ if (!newParentNode)
+ return;
+
+ PlaceCategoryNode *categoryNode = m_categoriesTree.value(categoryId);
+ if (!categoryNode)
+ return;
+
+ categoryNode->declCategory->setCategory(category);
+
+ if (categoryNode->parentId == parentId) { //reparenting to same parent
+ QModelIndex parentIndex = index(parentId);
+ int rowToBeAdded = rowToAddChild(newParentNode, category);
+ int oldRow = newParentNode->childIds.indexOf(categoryId);
+
+ //check if we are changing the position of the category
+ if (qAbs(rowToBeAdded - newParentNode->childIds.indexOf(categoryId)) > 1) {
+ //if the position has changed we are moving rows
+ beginMoveRows(parentIndex, oldRow, oldRow,
+ parentIndex, rowToBeAdded);
+
+ newParentNode->childIds.removeAll(categoryId);
+ newParentNode->childIds.insert(rowToBeAdded, categoryId);
+ endMoveRows();
+ } else {// if the position has not changed we modifying an existing row
+ QModelIndex categoryIndex = index(categoryId);
+ emit dataChanged(categoryIndex, categoryIndex);
+ }
+ } else { //reparenting to different parents
+ QPlaceCategory oldCategory = categoryNode->declCategory->category();
+ PlaceCategoryNode *oldParentNode = m_categoriesTree.value(categoryNode->parentId);
+ if (!oldParentNode)
+ return;
+ QModelIndex oldParentIndex = index(categoryNode->parentId);
+ QModelIndex newParentIndex = index(parentId);
+
+ int rowToBeAdded = rowToAddChild(newParentNode, category);
+ beginMoveRows(oldParentIndex, oldParentNode->childIds.indexOf(categoryId),
+ oldParentNode->childIds.indexOf(categoryId), newParentIndex, rowToBeAdded);
+ oldParentNode->childIds.removeAll(oldCategory.categoryId());
+ newParentNode->childIds.insert(rowToBeAdded, categoryId);
+ categoryNode->parentId = parentId;
+ endMoveRows();
+
+ //this is a workaround to deal with the fact that the hasModelChildren field of DelegateModel
+ //does not get updated when an index is updated to contain children
+ beginResetModel();
+ endResetModel();
+ }
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupportedCategoriesModel::removedCategory(const QString &categoryId, const QString &parentId)
+{
+ if (m_response)
+ return;
+
+ if (!m_categoriesTree.contains(categoryId) || !m_categoriesTree.contains(parentId))
+ return;
+
+ QModelIndex parentIndex = index(parentId);
+ QModelIndex categoryIndex = index(categoryId);
+
+ beginRemoveRows(parentIndex, categoryIndex.row(), categoryIndex.row());
+ PlaceCategoryNode *parentNode = m_categoriesTree.value(parentId);
+ parentNode->childIds.removeAll(categoryId);
+ delete m_categoriesTree.take(categoryId);
+ endRemoveRows();
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupportedCategoriesModel::connectNotificationSignals()
+{
+ if (!m_plugin)
+ return;
+
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (!serviceProvider || serviceProvider->error() != QGeoServiceProvider::NoError)
+ return;
+
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (!placeManager)
+ return;
+
+ // listen for any category notifications so that we can reupdate the categories
+ // model.
+ connect(placeManager, SIGNAL(categoryAdded(QPlaceCategory,QString)),
+ this, SLOT(addedCategory(QPlaceCategory,QString)));
+ connect(placeManager, SIGNAL(categoryUpdated(QPlaceCategory,QString)),
+ this, SLOT(updatedCategory(QPlaceCategory,QString)));
+ connect(placeManager, SIGNAL(categoryRemoved(QString,QString)),
+ this, SLOT(removedCategory(QString,QString)));
+ connect(placeManager, SIGNAL(dataChanged()),
+ this, SIGNAL(dataChanged()));
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupportedCategoriesModel::update()
+{
+ if (m_response)
+ return;
+
+ setStatus(Loading);
+
+ if (!m_plugin) {
+ updateLayout();
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROPERTY_NOT_SET));
+ return;
+ }
+
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (!serviceProvider || serviceProvider->error() != QGeoServiceProvider::NoError) {
+ updateLayout();
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_PROVIDER_ERROR)
+ .arg(m_plugin->name()));
+ return;
+ }
+
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (!placeManager) {
+ updateLayout();
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME, PLUGIN_ERROR)
+ .arg(m_plugin->name()).arg(serviceProvider->errorString()));
+ return;
+ }
+
+ m_response = placeManager->initializeCategories();
+ if (m_response) {
+ connect(m_response, SIGNAL(finished()), this, SLOT(replyFinished()));
+ } else {
+ updateLayout();
+ setStatus(Error, QCoreApplication::translate(CONTEXT_NAME,
+ CATEGORIES_NOT_INITIALIZED));
+ }
+}
+
+/*!
+ \internal
+*/
+void QDeclarativeSupportedCategoriesModel::updateLayout()
+{
+ beginResetModel();
+ qDeleteAll(m_categoriesTree);
+ m_categoriesTree.clear();
+
+ if (m_plugin) {
+ QGeoServiceProvider *serviceProvider = m_plugin->sharedGeoServiceProvider();
+ if (serviceProvider && serviceProvider->error() == QGeoServiceProvider::NoError) {
+ QPlaceManager *placeManager = serviceProvider->placeManager();
+ if (placeManager) {
+ PlaceCategoryNode *node = new PlaceCategoryNode;
+ node->childIds = populateCategories(placeManager, QPlaceCategory());
+ m_categoriesTree.insert(QString(), node);
+ node->declCategory = QSharedPointer<QDeclarativeCategory>
+ (new QDeclarativeCategory(QPlaceCategory(), m_plugin, this));
+ }
+ }
+ }
+
+ endResetModel();
+}
+
+QString QDeclarativeSupportedCategoriesModel::errorString() const
+{
+ return m_errorString;
+}
+
+/*!
+ \qmlproperty enumeration CategoryModel::status
+
+ This property holds the status of the model. It can be one of:
+
+ \table
+ \row
+ \li CategoryModel.Null
+ \li No category fetch query has been executed. The model is empty.
+ \row
+ \li CategoryModel.Ready
+ \li No error occurred during the last operation, further operations may be performed on
+ the model.
+ \row
+ \li CategoryModel.Loading
+ \li The model is being updated, no other operations may be performed until complete.
+ \row
+ \li CategoryModel.Error
+ \li An error occurred during the last operation, further operations can still be
+ performed on the model.
+ \endtable
+*/
+void QDeclarativeSupportedCategoriesModel::setStatus(Status status, const QString &errorString)
+{
+ Status originalStatus = m_status;
+ m_status = status;
+ m_errorString = errorString;
+
+ if (originalStatus != m_status)
+ emit statusChanged();
+}
+
+QDeclarativeSupportedCategoriesModel::Status QDeclarativeSupportedCategoriesModel::status() const
+{
+ return m_status;
+}
+
+/*!
+ \internal
+*/
+QStringList QDeclarativeSupportedCategoriesModel::populateCategories(QPlaceManager *manager, const QPlaceCategory &parent)
+{
+ Q_ASSERT(manager);
+
+ QStringList childIds;
+ PlaceCategoryNode *node;
+
+ QMap<QString, QPlaceCategory> sortedCategories;
+ foreach ( const QPlaceCategory &category, manager->childCategories(parent.categoryId()))
+ sortedCategories.insert(category.name(), category);
+
+ QMapIterator<QString, QPlaceCategory> iter(sortedCategories);
+ while (iter.hasNext()) {
+ iter.next();
+ node = new PlaceCategoryNode;
+ node->parentId = parent.categoryId();
+ node->declCategory = QSharedPointer<QDeclarativeCategory>(new QDeclarativeCategory(iter.value(), m_plugin ,this));
+
+ if (m_hierarchical)
+ node->childIds = populateCategories(manager, iter.value());
+
+ m_categoriesTree.insert(node->declCategory->categoryId(), node);
+ childIds.append(iter.value().categoryId());
+
+ if (!m_hierarchical) {
+ childIds.append(populateCategories(manager,node->declCategory->category()));
+ }
+ }
+ return childIds;
+}
+
+/*!
+ \internal
+*/
+QModelIndex QDeclarativeSupportedCategoriesModel::index(const QString &categoryId) const
+{
+ if (categoryId.isEmpty())
+ return QModelIndex();
+
+ if (!m_categoriesTree.contains(categoryId))
+ return QModelIndex();
+
+ PlaceCategoryNode *categoryNode = m_categoriesTree.value(categoryId);
+ if (!categoryNode)
+ return QModelIndex();
+
+ QString parentCategoryId = categoryNode->parentId;
+
+ PlaceCategoryNode *parentNode = m_categoriesTree.value(parentCategoryId);
+
+ return createIndex(parentNode->childIds.indexOf(categoryId), 0, categoryNode);
+}
+
+/*!
+ \internal
+*/
+int QDeclarativeSupportedCategoriesModel::rowToAddChild(PlaceCategoryNode *node, const QPlaceCategory &category)
+{
+ Q_ASSERT(node);
+ for (int i = 0; i < node->childIds.count(); ++i) {
+ if (category.name() < m_categoriesTree.value(node->childIds.at(i))->declCategory->name())
+ return i;
+ }
+ return node->childIds.count();
+}
+
+/*!
+ \qmlsignal CategoryModel::dataChanged()
+
+ This signal is emitted when significant changes have been made to the underlying datastore.
+
+ Applications should act on this signal at their own discretion. The data
+ provided by the model could be out of date and so the model should be reupdated
+ sometime, however an immediate reupdate may be disconcerting to users if the categories
+ change without any action on their part.
+
+ The corresponding handler is \c onDataChanged.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h b/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h
new file mode 100644
index 00000000..9f17ab4d
--- /dev/null
+++ b/src/location/declarativeplaces/qdeclarativesupportedcategoriesmodel_p.h
@@ -0,0 +1,166 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later 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 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESUPPORTEDCATEGORIESMODEL_H
+#define QDECLARATIVESUPPORTEDCATEGORIESMODEL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativegeoserviceprovider_p.h>
+
+#include <QObject>
+#include <QtCore/QStringList>
+#include <QtCore/QSharedPointer>
+#include <QAbstractListModel>
+#include <QQmlListProperty>
+#include <QtQml/QQmlParserStatus>
+
+#include <QtLocation/QPlaceCategory>
+
+#include <QtLocation/private/qdeclarativecategory_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGeoServiceProvider;
+class QPlaceManager;
+class QPlaceReply;
+
+class PlaceCategoryNode
+{
+public:
+ QString parentId;
+ QStringList childIds;
+ QSharedPointer<QDeclarativeCategory> declCategory;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeSupportedCategoriesModel : public QAbstractItemModel, public QQmlParserStatus
+{
+ Q_OBJECT
+
+ Q_ENUMS(Status)
+
+ Q_PROPERTY(QDeclarativeGeoServiceProvider *plugin READ plugin WRITE setPlugin NOTIFY pluginChanged)
+ Q_PROPERTY(bool hierarchical READ hierarchical WRITE setHierarchical NOTIFY hierarchicalChanged)
+ Q_PROPERTY(Status status READ status NOTIFY statusChanged)
+
+ Q_INTERFACES(QQmlParserStatus)
+ Q_ENUMS(Roles) //The Roles enum is for internal usage only.
+
+public:
+ explicit QDeclarativeSupportedCategoriesModel(QObject *parent = 0);
+ virtual ~QDeclarativeSupportedCategoriesModel();
+
+ // From QQmlParserStatus
+ virtual void classBegin() {}
+ virtual void componentComplete();
+
+ // 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;
+
+ Q_INVOKABLE QVariant data(const QModelIndex &index, int role) const;
+ QHash<int, QByteArray> roleNames() const;
+
+ enum Roles {
+ CategoryRole = Qt::UserRole,
+ ParentCategoryRole
+ }; //for internal usage only
+
+ enum Status {Null, Ready, Loading, Error};
+
+ void setPlugin(QDeclarativeGeoServiceProvider *plugin);
+ QDeclarativeGeoServiceProvider *plugin() const;
+
+ void setHierarchical(bool hierarchical);
+ bool hierarchical() const;
+
+ Q_INVOKABLE QString errorString() const;
+
+ Status status() const;
+ void setStatus(Status status, const QString &errorString = QString());
+
+ using QAbstractItemModel::dataChanged;
+Q_SIGNALS:
+ void pluginChanged();
+ void hierarchicalChanged();
+ void statusChanged();
+ void dataChanged();
+
+public Q_SLOTS:
+ void update();
+
+private Q_SLOTS:
+ void replyFinished();
+ void addedCategory(const QPlaceCategory &category, const QString &parentId);
+ void updatedCategory(const QPlaceCategory &category, const QString &parentId);
+ void removedCategory(const QString &categoryId, const QString &parentId);
+ void connectNotificationSignals();
+
+private:
+ QStringList populateCategories(QPlaceManager *, const QPlaceCategory &parent);
+ QModelIndex index(const QString &categoryId) const;
+ int rowToAddChild(PlaceCategoryNode *, const QPlaceCategory &category);
+ void updateLayout();
+
+ QPlaceReply *m_response;
+
+ QDeclarativeGeoServiceProvider *m_plugin;
+ bool m_hierarchical;
+ bool m_complete;
+ Status m_status;
+ QString m_errorString;
+
+ QHash<QString, PlaceCategoryNode *> m_categoriesTree;
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeSupportedCategoriesModel)
+
+#endif // QDECLARATIVESUPPORTEDCATEGORIESMODEL_H