summaryrefslogtreecommitdiff
path: root/src/location/declarativeplaces
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2016-04-05 10:54:07 +0200
committerPaolo Angelelli <paolo.angelelli@qt.io>2017-01-26 14:46:08 +0000
commitd83f23e1ef19fe524c50b827ee408523dbb74bdc (patch)
treec04e66302e67c61c2909330ddf0e414a718f67ec /src/location/declarativeplaces
parentc062403a894a270101ae821fd73fa848f918ac54 (diff)
downloadqtlocation-d83f23e1ef19fe524c50b827ee408523dbb74bdc.tar.gz
Moving location qml implementation to location/declarative*
QtLocation quick classes and headers are moved out of the import directory. The location quick classes are now in a subdirectory inside the main qtlocation module. This is necessary in order to privately export certain classes, such as Map Items classes, and create an API to inject these objects into QGeoMap to let plugins render the Map Items directly Change-Id: Ia6ba5f07c4eddd3c4c2ce54bf34f1afcd42c2558 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
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