aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2011-08-30 15:00:30 +1000
committerQt by Nokia <qt-info@nokia.com>2011-09-21 08:23:52 +0200
commitce7b66871ce342b4cc62969ec0a3a9d90cee49e9 (patch)
tree9aed7d793f9b8d653ce3820b3adafc6a540b9313
parentd0ed3d21c471088c103859f1e94085b27754a424 (diff)
Refactor QSGVisualDataModel.
Split the wrapper for Package models out into its own visual model class, add a QSGVisualAdaptorModel class which encapsulates the creation and maintenance of delegate context data, and move QSGVisualDataModel to its own source files. Task-number: QTBUG-20107 Change-Id: Icdea2756a119c327ec2c748be893daf622bc1356 Reviewed-on: http://codereview.qt-project.org/4033 Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com> Reviewed-by: Martin Jones <martin.jones@nokia.com>
-rw-r--r--src/declarative/items/items.pri4
-rw-r--r--src/declarative/items/qsgitemsmodule.cpp1
-rw-r--r--src/declarative/items/qsgitemview_p_p.h2
-rw-r--r--src/declarative/items/qsgpathview_p_p.h2
-rw-r--r--src/declarative/items/qsgrepeater.cpp2
-rw-r--r--src/declarative/items/qsgvisualadaptormodel.cpp889
-rw-r--r--src/declarative/items/qsgvisualadaptormodel_p.h129
-rw-r--r--src/declarative/items/qsgvisualdatamodel.cpp849
-rw-r--r--src/declarative/items/qsgvisualdatamodel_p.h122
-rw-r--r--src/declarative/items/qsgvisualitemmodel.cpp1323
-rw-r--r--src/declarative/items/qsgvisualitemmodel_p.h76
-rw-r--r--tests/auto/declarative/qsgvisualdatamodel/data/visualdatamodel.qml1
-rw-r--r--tests/auto/declarative/qsgvisualdatamodel/tst_qsgvisualdatamodel.cpp2
13 files changed, 2000 insertions, 1402 deletions
diff --git a/src/declarative/items/items.pri b/src/declarative/items/items.pri
index 9880dd8dc6..04330748e1 100644
--- a/src/declarative/items/items.pri
+++ b/src/declarative/items/items.pri
@@ -37,6 +37,8 @@ HEADERS += \
$$PWD/qsgflickable_p.h \
$$PWD/qsgflickable_p_p.h \
$$PWD/qsglistview_p.h \
+ $$PWD/qsgvisualadaptormodel_p.h \
+ $$PWD/qsgvisualdatamodel_p.h \
$$PWD/qsgvisualitemmodel_p.h \
$$PWD/qsgrepeater_p.h \
$$PWD/qsgrepeater_p_p.h \
@@ -89,6 +91,8 @@ SOURCES += \
$$PWD/qsgpincharea.cpp \
$$PWD/qsgflickable.cpp \
$$PWD/qsglistview.cpp \
+ $$PWD/qsgvisualadaptormodel.cpp \
+ $$PWD/qsgvisualdatamodel.cpp \
$$PWD/qsgvisualitemmodel.cpp \
$$PWD/qsgrepeater.cpp \
$$PWD/qsggridview.cpp \
diff --git a/src/declarative/items/qsgitemsmodule.cpp b/src/declarative/items/qsgitemsmodule.cpp
index 2ad7e592f3..41823c1a4d 100644
--- a/src/declarative/items/qsgitemsmodule.cpp
+++ b/src/declarative/items/qsgitemsmodule.cpp
@@ -58,6 +58,7 @@
#include "qsgflickable_p_p.h"
#include "qsglistview_p.h"
#include "qsgvisualitemmodel_p.h"
+#include "qsgvisualdatamodel_p.h"
#include "qsggridview_p.h"
#include "qsgpathview_p.h"
#include <private/qdeclarativepath_p.h>
diff --git a/src/declarative/items/qsgitemview_p_p.h b/src/declarative/items/qsgitemview_p_p.h
index 2164dd60f4..afa50af952 100644
--- a/src/declarative/items/qsgitemview_p_p.h
+++ b/src/declarative/items/qsgitemview_p_p.h
@@ -44,7 +44,7 @@
#include "qsgitemview_p.h"
#include "qsgflickable_p_p.h"
-#include "qsgvisualitemmodel_p.h"
+#include "qsgvisualdatamodel_p.h"
#include <private/qdeclarativechangeset_p.h>
diff --git a/src/declarative/items/qsgpathview_p_p.h b/src/declarative/items/qsgpathview_p_p.h
index 30bb74a984..520de429fe 100644
--- a/src/declarative/items/qsgpathview_p_p.h
+++ b/src/declarative/items/qsgpathview_p_p.h
@@ -56,7 +56,7 @@
#include "qsgpathview_p.h"
#include "qsgitem_p.h"
-#include "qsgvisualitemmodel_p.h"
+#include "qsgvisualdatamodel_p.h"
#include <QtDeclarative/qdeclarative.h>
#include <QtCore/qdatetime.h>
diff --git a/src/declarative/items/qsgrepeater.cpp b/src/declarative/items/qsgrepeater.cpp
index bdb3a3d98a..4e2fa63548 100644
--- a/src/declarative/items/qsgrepeater.cpp
+++ b/src/declarative/items/qsgrepeater.cpp
@@ -41,7 +41,7 @@
#include "qsgrepeater_p.h"
#include "qsgrepeater_p_p.h"
-#include "qsgvisualitemmodel_p.h"
+#include "qsgvisualdatamodel_p.h"
#include <private/qdeclarativeglobal_p.h>
#include <private/qdeclarativelistaccessor_p.h>
diff --git a/src/declarative/items/qsgvisualadaptormodel.cpp b/src/declarative/items/qsgvisualadaptormodel.cpp
new file mode 100644
index 0000000000..3eb6214e47
--- /dev/null
+++ b/src/declarative/items/qsgvisualadaptormodel.cpp
@@ -0,0 +1,889 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgvisualadaptormodel_p.h"
+#include "qsgitem.h"
+
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <private/qdeclarativecontext_p.h>
+#include <private/qdeclarativepackage_p.h>
+#include <private/qdeclarativeopenmetaobject_p.h>
+#include <private/qdeclarativelistaccessor_p.h>
+#include <private/qdeclarativedata_p.h>
+#include <private/qdeclarativepropertycache_p.h>
+#include <private/qdeclarativeguard_p.h>
+#include <private/qdeclarativeglobal_p.h>
+#include <private/qlistmodelinterface_p.h>
+#include <private/qmetaobjectbuilder_p.h>
+#include <private/qdeclarativeproperty_p.h>
+#include <private/qintrusivelist_p.h>
+#include <private/qobject_p.h>
+
+#include <QtCore/qhash.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+class VDMDelegateDataType : public QDeclarativeRefCount
+{
+public:
+ VDMDelegateDataType()
+ : metaObject(0)
+ , propertyCache(0)
+ , propertyOffset(0)
+ , signalOffset(0)
+ , shared(true)
+ {
+ }
+
+ VDMDelegateDataType(const VDMDelegateDataType &type)
+ : metaObject(0)
+ , propertyCache(0)
+ , propertyOffset(type.propertyOffset)
+ , signalOffset(type.signalOffset)
+ , shared(false)
+ , builder(type.metaObject, QMetaObjectBuilder::Properties
+ | QMetaObjectBuilder::Signals
+ | QMetaObjectBuilder::SuperClass
+ | QMetaObjectBuilder::ClassName)
+ {
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ }
+
+ ~VDMDelegateDataType()
+ {
+ if (propertyCache)
+ propertyCache->release();
+ qFree(metaObject);
+ }
+
+ QMetaObject *metaObject;
+ QDeclarativePropertyCache *propertyCache;
+ int propertyOffset;
+ int signalOffset;
+ bool shared : 1;
+ QMetaObjectBuilder builder;
+};
+
+class QSGVisualAdaptorModelData : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+public:
+ QSGVisualAdaptorModelData(int index, QSGVisualAdaptorModel *model);
+ ~QSGVisualAdaptorModelData();
+
+ int index() const;
+ void setIndex(int index);
+
+Q_SIGNALS:
+ void indexChanged();
+
+public:
+ int m_index;
+ QDeclarativeGuard<QSGVisualAdaptorModel> m_model;
+ QIntrusiveListNode m_cacheNode;
+};
+
+typedef QIntrusiveList<QSGVisualAdaptorModelData, &QSGVisualAdaptorModelData::m_cacheNode> QSGVisualAdaptorModelDataCache;
+
+class QSGVisualAdaptorModelDataMetaObject;
+class QSGVisualAdaptorModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSGVisualAdaptorModel)
+public:
+ QSGVisualAdaptorModelPrivate()
+ : m_engine(0)
+ , m_listAccessor(0)
+ , m_delegateDataType(0)
+ , createModelData(&initializeModelData)
+ , m_ref(0)
+ , m_count(0)
+ , m_objectList(false)
+ {
+ }
+
+
+ static QSGVisualAdaptorModelPrivate *get(QSGVisualAdaptorModel *m) {
+ return static_cast<QSGVisualAdaptorModelPrivate *>(QObjectPrivate::get(m));
+ }
+
+ void addProperty(int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData = false);
+ template <typename T> void setModelDataType()
+ {
+ createModelData = &T::create;
+ m_delegateDataType->builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ m_delegateDataType->builder.setClassName(T::staticMetaObject.className());
+ m_delegateDataType->builder.setSuperClass(&T::staticMetaObject);
+ m_delegateDataType->propertyOffset = T::staticMetaObject.propertyCount();
+ m_delegateDataType->signalOffset = T::staticMetaObject.methodCount();
+ }
+ QSGVisualAdaptorModelData *createMetaObject(int index, QSGVisualAdaptorModel *model);
+
+ static QSGVisualAdaptorModelData *initializeModelData(int index, QSGVisualAdaptorModel *model) {
+ return get(model)->createMetaObject(index, model);
+ }
+
+ typedef QSGVisualAdaptorModelData *(*CreateModelData)(int index, QSGVisualAdaptorModel *model);
+
+ struct PropertyData {
+ int role;
+ bool isModelData : 1;
+ };
+
+ int modelCount() const {
+ if (m_listModelInterface)
+ return m_listModelInterface->count();
+ if (m_abstractItemModel)
+ return m_abstractItemModel->rowCount(m_root);
+ if (m_listAccessor)
+ return m_listAccessor->count();
+ return 0;
+ }
+
+ QDeclarativeGuard<QDeclarativeEngine> m_engine;
+ QDeclarativeGuard<QListModelInterface> m_listModelInterface;
+ QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
+ QDeclarativeListAccessor *m_listAccessor;
+ VDMDelegateDataType *m_delegateDataType;
+ CreateModelData createModelData;
+
+ int m_ref;
+ int m_count;
+ QSGVisualAdaptorModel::Flags m_flags;
+ bool m_objectList : 1;
+
+ QVariant m_modelVariant;
+ QModelIndex m_root;
+
+ QList<int> m_roles;
+ QList<int> watchedRoleIds;
+ QList<QByteArray> watchedRoles;
+ QHash<QByteArray,int> m_roleNames;
+ QVector<PropertyData> m_propertyData;
+ QSGVisualAdaptorModelDataCache m_cache;
+};
+
+class QSGVisualAdaptorModelDataMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QSGVisualAdaptorModelDataMetaObject(QSGVisualAdaptorModelData *data, VDMDelegateDataType *type)
+ : m_data(data)
+ , m_type(type)
+ {
+ QObjectPrivate *op = QObjectPrivate::get(m_data);
+ *static_cast<QMetaObject *>(this) = *type->metaObject;
+ op->metaObject = this;
+ m_type->addref();
+ }
+
+ ~QSGVisualAdaptorModelDataMetaObject() { m_type->release(); }
+
+ QSGVisualAdaptorModelData *m_data;
+ VDMDelegateDataType *m_type;
+};
+
+class QSGVDMAbstractItemModelDataMetaObject : public QSGVisualAdaptorModelDataMetaObject
+{
+public:
+ QSGVDMAbstractItemModelDataMetaObject(QSGVisualAdaptorModelData *object, VDMDelegateDataType *type)
+ : QSGVisualAdaptorModelDataMetaObject(object, type) {}
+
+ int metaCall(QMetaObject::Call call, int id, void **arguments)
+ {
+ if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
+ QSGVisualAdaptorModelPrivate *model = QSGVisualAdaptorModelPrivate::get(m_data->m_model);
+ if (m_data->m_index == -1 || !model->m_abstractItemModel)
+ return -1;
+ *static_cast<QVariant *>(arguments[0]) = model->m_abstractItemModel->index(
+ m_data->m_index, 0, model->m_root).data(model->m_propertyData.at(id - m_type->propertyOffset).role);
+ return -1;
+ } else {
+ return m_data->qt_metacall(call, id, arguments);
+ }
+ }
+};
+
+class QSGVDMAbstractItemModelData : public QSGVisualAdaptorModelData
+{
+ Q_OBJECT
+ Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
+public:
+ bool hasModelChildren() const
+ {
+ QSGVisualAdaptorModelPrivate *model = QSGVisualAdaptorModelPrivate::get(m_model);
+ return model->m_abstractItemModel->hasChildren(model->m_abstractItemModel->index(m_index, 0, model->m_root));
+ }
+
+ static QSGVisualAdaptorModelData *create(int index, QSGVisualAdaptorModel *model) {
+ return new QSGVDMAbstractItemModelData(index, model); }
+private:
+ QSGVDMAbstractItemModelData(int index, QSGVisualAdaptorModel *model)
+ : QSGVisualAdaptorModelData(index, model)
+ {
+ new QSGVDMAbstractItemModelDataMetaObject(
+ this, QSGVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType);
+ }
+};
+
+class QSGVDMListModelInterfaceDataMetaObject : public QSGVisualAdaptorModelDataMetaObject
+{
+public:
+ QSGVDMListModelInterfaceDataMetaObject(QSGVisualAdaptorModelData *object, VDMDelegateDataType *type)
+ : QSGVisualAdaptorModelDataMetaObject(object, type) {}
+
+ int metaCall(QMetaObject::Call call, int id, void **arguments)
+ {
+ if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
+ QSGVisualAdaptorModelPrivate *model = QSGVisualAdaptorModelPrivate::get(m_data->m_model);
+ if (m_data->m_index == -1 || !model->m_listModelInterface)
+ return -1;
+ *static_cast<QVariant *>(arguments[0]) = model->m_listModelInterface->data(
+ m_data->m_index, model->m_propertyData.at(id - m_type->propertyOffset).role);
+ return -1;
+ } else {
+ return m_data->qt_metacall(call, id, arguments);
+ }
+ }
+};
+
+class QSGVDMListModelInterfaceData : public QSGVisualAdaptorModelData
+{
+public:
+ static QSGVisualAdaptorModelData *create(int index, QSGVisualAdaptorModel *model) {
+ return new QSGVDMListModelInterfaceData(index, model); }
+private:
+ QSGVDMListModelInterfaceData(int index, QSGVisualAdaptorModel *model)
+ : QSGVisualAdaptorModelData(index, model)
+ {
+ new QSGVDMListModelInterfaceDataMetaObject(
+ this, QSGVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType);
+ }
+};
+
+class QSGVDMListAccessorData : public QSGVisualAdaptorModelData
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant modelData READ modelData CONSTANT)
+public:
+ QVariant modelData() const {
+ return QSGVisualAdaptorModelPrivate::get(m_model)->m_listAccessor->at(m_index); }
+
+ static QSGVisualAdaptorModelData *create(int index, QSGVisualAdaptorModel *model) {
+ return new QSGVDMListAccessorData(index, model); }
+private:
+ QSGVDMListAccessorData(int index, QSGVisualAdaptorModel *model)
+ : QSGVisualAdaptorModelData(index, model)
+ {
+ }
+};
+
+class QSGVDMObjectDataMetaObject : public QSGVisualAdaptorModelDataMetaObject
+{
+public:
+ QSGVDMObjectDataMetaObject(QSGVisualAdaptorModelData *data, VDMDelegateDataType *type)
+ : QSGVisualAdaptorModelDataMetaObject(data, type)
+ , m_object(QSGVisualAdaptorModelPrivate::get(data->m_model)->m_listAccessor->at(data->m_index).value<QObject *>())
+ {}
+
+ int metaCall(QMetaObject::Call call, int id, void **arguments)
+ {
+ if (id >= m_type->propertyOffset
+ && (call == QMetaObject::ReadProperty
+ || call == QMetaObject::WriteProperty
+ || call == QMetaObject::ResetProperty)) {
+ if (m_object)
+ QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + 1, arguments);
+ return -1;
+ } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
+ QMetaObject::activate(m_data, this, id, 0);
+ return -1;
+ } else {
+ return m_data->qt_metacall(call, id, arguments);
+ }
+ }
+
+ int createProperty(const char *name, const char *)
+ {
+ if (!m_object)
+ return -1;
+ const QMetaObject *metaObject = m_object->metaObject();
+
+ const int previousPropertyCount = propertyCount() - propertyOffset();
+ int propertyIndex = metaObject->indexOfProperty(name);
+ if (propertyIndex == -1)
+ return -1;
+ if (previousPropertyCount + 1 == metaObject->propertyCount())
+ return propertyIndex + m_type->propertyOffset - 1;
+
+ if (m_type->shared) {
+ VDMDelegateDataType *type = m_type;
+ m_type = new VDMDelegateDataType(*m_type);
+ type->release();
+ }
+
+ const int previousMethodCount = methodCount();
+ int notifierId = previousMethodCount;
+ for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - 1; ++propertyId) {
+ QMetaProperty property = metaObject->property(propertyId + 1);
+ QMetaPropertyBuilder propertyBuilder;
+ if (property.hasNotifySignal()) {
+ m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
+ propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
+ ++notifierId;
+ } else {
+ propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
+ }
+ propertyBuilder.setWritable(property.isWritable());
+ propertyBuilder.setResettable(property.isResettable());
+ propertyBuilder.setConstant(property.isConstant());
+ }
+
+ if (m_type->metaObject)
+ qFree(m_type->metaObject);
+ m_type->metaObject = m_type->builder.toMetaObject();
+ *static_cast<QMetaObject *>(this) = *m_type->metaObject;
+
+ notifierId = previousMethodCount;
+ for (int i = previousPropertyCount; i < metaObject->propertyCount(); ++i) {
+ QMetaProperty property = metaObject->property(i);
+ if (property.hasNotifySignal()) {
+ QDeclarativePropertyPrivate::connect(
+ m_object, property.notifySignalIndex(), m_data, notifierId);
+ ++notifierId;
+ }
+ }
+ return propertyIndex + m_type->propertyOffset - 1;
+ }
+
+ QDeclarativeGuard<QObject> m_object;
+};
+
+class QSGVDMObjectData : public QSGVisualAdaptorModelData, public QSGVisualAdaptorModelProxyInterface
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
+ Q_INTERFACES(QSGVisualAdaptorModelProxyInterface)
+public:
+ QObject *modelData() const { return m_metaObject->m_object; }
+ QObject *proxiedObject() { return m_metaObject->m_object; }
+
+ static QSGVisualAdaptorModelData *create(int index, QSGVisualAdaptorModel *model) {
+ return new QSGVDMObjectData(index, model); }
+
+private:
+ QSGVDMObjectData(int index, QSGVisualAdaptorModel *model)
+ : QSGVisualAdaptorModelData(index, model)
+ , m_metaObject(new QSGVDMObjectDataMetaObject(this, QSGVisualAdaptorModelPrivate::get(m_model)->m_delegateDataType))
+ {
+ }
+
+ QSGVDMObjectDataMetaObject *m_metaObject;
+};
+
+void QSGVisualAdaptorModelPrivate::addProperty(
+ int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData)
+{
+ PropertyData propertyData;
+ propertyData.role = role;
+ propertyData.isModelData = isModelData;
+ m_delegateDataType->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
+ QMetaPropertyBuilder property = m_delegateDataType->builder.addProperty(
+ propertyName, propertyType, propertyId);
+ property.setWritable(false);
+
+ m_propertyData.append(propertyData);
+}
+
+QSGVisualAdaptorModelData *QSGVisualAdaptorModelPrivate::createMetaObject(int index, QSGVisualAdaptorModel *model)
+{
+ Q_ASSERT(!m_delegateDataType);
+
+ m_objectList = false;
+ m_propertyData.clear();
+ if (m_listAccessor
+ && m_listAccessor->type() != QDeclarativeListAccessor::ListProperty
+ && m_listAccessor->type() != QDeclarativeListAccessor::Instance) {
+ createModelData = &QSGVDMListAccessorData::create;
+ m_flags = QSGVisualAdaptorModel::MetaObjectCacheable;
+ return QSGVDMListAccessorData::create(index, model);
+ }
+
+ m_delegateDataType = new VDMDelegateDataType;
+ if (m_listModelInterface) {
+ setModelDataType<QSGVDMListModelInterfaceData>();
+ QList<int> roles = m_listModelInterface->roles();
+ for (int propertyId = 0; propertyId < roles.count(); ++propertyId) {
+ const int role = roles.at(propertyId);
+ const QByteArray propertyName = m_listModelInterface->toString(role).toUtf8();
+ addProperty(role, propertyId, propertyName, "QVariant");
+ m_roleNames.insert(propertyName, role);
+ }
+ if (m_propertyData.count() == 1)
+ addProperty(roles.first(), 1, "modelData", "QVariant", true);
+ m_flags = QSGVisualAdaptorModel::MetaObjectCacheable;
+ } else if (m_abstractItemModel) {
+ setModelDataType<QSGVDMAbstractItemModelData>();
+ QHash<int, QByteArray> roleNames = m_abstractItemModel->roleNames();
+ for (QHash<int, QByteArray>::const_iterator it = roleNames.begin(); it != roleNames.end(); ++it) {
+ addProperty(it.key(), m_propertyData.count(), it.value(), "QVariant");
+ m_roleNames.insert(it.value(), it.key());
+ }
+ if (m_propertyData.count() == 1)
+ addProperty(roleNames.begin().key(), 1, "modelData", "QVariant", true);
+ m_flags = QSGVisualAdaptorModel::MetaObjectCacheable;
+ } else if (m_listAccessor) {
+ setModelDataType<QSGVDMObjectData>();
+ m_objectList = true;
+ m_flags = QSGVisualAdaptorModel::ProxiedObject;
+ } else {
+ Q_ASSERT(!"No model set on VisualDataModel");
+ return 0;
+ }
+ m_delegateDataType->metaObject = m_delegateDataType->builder.toMetaObject();
+ if (!m_objectList) {
+ m_delegateDataType->propertyCache = new QDeclarativePropertyCache(
+ m_engine, m_delegateDataType->metaObject);
+ }
+ return createModelData(index, model);
+}
+
+QSGVisualAdaptorModelData::QSGVisualAdaptorModelData(int index, QSGVisualAdaptorModel *model)
+ : m_index(index)
+ , m_model(model)
+{
+}
+
+QSGVisualAdaptorModelData::~QSGVisualAdaptorModelData()
+{
+}
+
+int QSGVisualAdaptorModelData::index() const
+{
+ return m_index;
+}
+
+// This is internal only - it should not be set from qml
+void QSGVisualAdaptorModelData::setIndex(int index)
+{
+ m_index = index;
+ emit indexChanged();
+}
+
+//---------------------------------------------------------------------------
+
+QSGVisualAdaptorModel::QSGVisualAdaptorModel(QObject *parent)
+ : QObject(*(new QSGVisualAdaptorModelPrivate), parent)
+{
+}
+
+QSGVisualAdaptorModel::~QSGVisualAdaptorModel()
+{
+ Q_D(QSGVisualAdaptorModel);
+ if (d->m_listAccessor)
+ delete d->m_listAccessor;
+ if (d->m_delegateDataType)
+ d->m_delegateDataType->release();
+}
+
+QSGVisualAdaptorModel::Flags QSGVisualAdaptorModel::flags() const
+{
+ Q_D(const QSGVisualAdaptorModel);
+ return d->m_flags;
+}
+
+QVariant QSGVisualAdaptorModel::model() const
+{
+ Q_D(const QSGVisualAdaptorModel);
+ return d->m_modelVariant;
+}
+
+void QSGVisualAdaptorModel::setModel(const QVariant &model, QDeclarativeEngine *engine)
+{
+ Q_D(QSGVisualAdaptorModel);
+ delete d->m_listAccessor;
+ d->m_engine = engine;
+ d->m_listAccessor = 0;
+ d->m_modelVariant = model;
+ if (d->m_listModelInterface) {
+ // Assume caller has released all items.
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+ d->m_listModelInterface = 0;
+ } else if (d->m_abstractItemModel) {
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+ this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
+ d->m_abstractItemModel = 0;
+ }
+
+ d->m_roles.clear();
+ d->m_roleNames.clear();
+ d->m_flags = QSGVisualAdaptorModel::Flags();
+ if (d->m_delegateDataType)
+ d->m_delegateDataType->release();
+ d->m_delegateDataType = 0;
+ d->createModelData = &QSGVisualAdaptorModelPrivate::initializeModelData;
+
+ if (d->m_count)
+ emit itemsRemoved(0, d->m_count);
+
+ QObject *object = qvariant_cast<QObject *>(model);
+ if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
+ this, SLOT(_q_itemsChanged(int,int,QList<int>)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
+ this, SLOT(_q_itemsInserted(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
+ this, SLOT(_q_itemsRemoved(int,int)));
+ QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
+ this, SLOT(_q_itemsMoved(int,int,int)));
+ if ((d->m_count = d->m_listModelInterface->count()))
+ emit itemsInserted(0, d->m_count);
+ return;
+ } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
+ this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
+ this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+ this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
+
+ if ((d->m_count = d->m_abstractItemModel->rowCount(d->m_root)))
+ emit itemsInserted(0, d->m_count);
+ return;
+ }
+
+ d->m_listAccessor = new QDeclarativeListAccessor;
+ d->m_listAccessor->setList(model, d->m_engine);
+ if ((d->m_count = d->m_listAccessor->count()))
+ emit itemsInserted(0, d->m_count);
+}
+
+QVariant QSGVisualAdaptorModel::rootIndex() const
+{
+ Q_D(const QSGVisualAdaptorModel);
+ return QVariant::fromValue(d->m_root);
+}
+
+void QSGVisualAdaptorModel::setRootIndex(const QVariant &root)
+{
+ Q_D(QSGVisualAdaptorModel);
+ QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
+ if (d->m_root != modelIndex) {
+ int oldCount = d->modelCount();
+ d->m_root = modelIndex;
+ if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(modelIndex))
+ d->m_abstractItemModel->fetchMore(modelIndex);
+ int newCount = d->modelCount();
+ if (oldCount)
+ emit itemsRemoved(0, oldCount);
+ if (newCount)
+ emit itemsInserted(0, newCount);
+ emit rootIndexChanged();
+ }
+}
+
+QVariant QSGVisualAdaptorModel::modelIndex(int idx) const
+{
+ Q_D(const QSGVisualAdaptorModel);
+ if (d->m_abstractItemModel)
+ return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root));
+ return QVariant::fromValue(QModelIndex());
+}
+
+QVariant QSGVisualAdaptorModel::parentModelIndex() const
+{
+ Q_D(const QSGVisualAdaptorModel);
+ if (d->m_abstractItemModel)
+ return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root));
+ return QVariant::fromValue(QModelIndex());
+}
+
+int QSGVisualAdaptorModel::count() const
+{
+ Q_D(const QSGVisualAdaptorModel);
+ return d->modelCount();
+}
+
+QObject *QSGVisualAdaptorModel::data(int index)
+{
+ Q_D(QSGVisualAdaptorModel);
+ QSGVisualAdaptorModelData *data = d->createModelData(index, this);
+ d->m_cache.insert(data);
+ return data;
+}
+
+QString QSGVisualAdaptorModel::stringValue(int index, const QString &name)
+{
+ Q_D(QSGVisualAdaptorModel);
+ if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor) {
+ if (QObject *object = d->m_listAccessor->at(index).value<QObject*>())
+ return object->property(name.toUtf8()).toString();
+ }
+
+ QString val;
+ QSGVisualAdaptorModelData *data = d->createModelData(index, this);
+
+ QDeclarativeData *ddata = QDeclarativeData::get(data);
+ if (ddata && ddata->propertyCache) {
+ QDeclarativePropertyCache::Data *prop = ddata->propertyCache->property(name);
+ if (prop) {
+ if (prop->propType == QVariant::String) {
+ void *args[] = { &val, 0 };
+ QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
+ } else if (prop->propType == qMetaTypeId<QVariant>()) {
+ QVariant v;
+ void *args[] = { &v, 0 };
+ QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
+ val = v.toString();
+ }
+ } else {
+ val = data->property(name.toUtf8()).toString();
+ }
+ } else {
+ val = data->property(name.toUtf8()).toString();
+ }
+
+ delete data;
+
+ return val;
+}
+
+int QSGVisualAdaptorModel::indexOf(QObject *object) const
+{
+ if (QSGVisualAdaptorModelData *data = qobject_cast<QSGVisualAdaptorModelData *>(object))
+ return data->index();
+ return -1;
+}
+
+bool QSGVisualAdaptorModel::canFetchMore() const
+{
+ Q_D(const QSGVisualAdaptorModel);
+ return d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root);
+}
+
+void QSGVisualAdaptorModel::fetchMore()
+{
+ Q_D(QSGVisualAdaptorModel);
+ if (d->m_abstractItemModel)
+ d->m_abstractItemModel->fetchMore(d->m_root);
+}
+
+void QSGVisualAdaptorModel::replaceWatchedRoles(const QList<QByteArray> &oldRoles, const QList<QByteArray> &newRoles)
+{
+ Q_D(QSGVisualAdaptorModel);
+ d->watchedRoleIds.clear();
+ foreach (const QByteArray &oldRole, oldRoles)
+ d->watchedRoles.removeOne(oldRole);
+ d->watchedRoles += newRoles;
+}
+
+void QSGVisualAdaptorModel::_q_itemsChanged(int index, int count, const QList<int> &roles)
+{
+ Q_D(QSGVisualAdaptorModel);
+ bool changed = roles.isEmpty();
+ if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) {
+ foreach (QByteArray r, d->watchedRoles) {
+ if (d->m_roleNames.contains(r))
+ d->watchedRoleIds << d->m_roleNames.value(r);
+ }
+ }
+
+ QVector<int> signalIndexes;
+ for (int i = 0; i < roles.count(); ++i) {
+ const int role = roles.at(i);
+ if (!changed && d->watchedRoleIds.contains(role))
+ changed = true;
+ for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId) {
+ if (d->m_propertyData.at(propertyId).role == role)
+ signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
+ }
+ }
+ if (roles.isEmpty()) {
+ for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId)
+ signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
+ }
+
+ typedef QSGVisualAdaptorModelDataCache::iterator iterator;
+ for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
+ const int idx = it->index();
+ if (idx >= index && idx < index + count) {
+ QSGVisualAdaptorModelData *data = *it;
+ for (int i = 0; i < signalIndexes.count(); ++i)
+ QMetaObject::activate(data, signalIndexes.at(i), 0);
+ }
+ }
+ if (changed)
+ emit itemsChanged(index, count);
+}
+
+void QSGVisualAdaptorModel::_q_itemsInserted(int index, int count)
+{
+ Q_D(QSGVisualAdaptorModel);
+ if (count <= 0)
+ return;
+ d->m_count += count;
+
+ typedef QSGVisualAdaptorModelDataCache::iterator iterator;
+ for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
+ if (it->index() >= index)
+ it->setIndex(it->index() + count);
+ }
+
+ emit itemsInserted(index, count);
+}
+
+void QSGVisualAdaptorModel::_q_itemsRemoved(int index, int count)
+{
+ Q_D(QSGVisualAdaptorModel);
+ if (count <= 0)
+ return;
+ d->m_count -= count;
+
+ typedef QSGVisualAdaptorModelDataCache::iterator iterator;
+ for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
+ if (it->index() >= index + count)
+ it->setIndex(it->index() - count);
+ else if (it->index() >= index)
+ it->setIndex(-1);
+ }
+
+ emit itemsRemoved(index, count);
+}
+
+void QSGVisualAdaptorModel::_q_itemsMoved(int from, int to, int count)
+{
+ Q_D(QSGVisualAdaptorModel);
+ const int minimum = qMin(from, to);
+ const int maximum = qMax(from, to) + count;
+ const int difference = from > to ? count : -count;
+
+ typedef QSGVisualAdaptorModelDataCache::iterator iterator;
+ for (iterator it = d->m_cache.begin(); it != d->m_cache.end(); ++it) {
+ if (it->index() >= from && it->index() < from + count)
+ it->setIndex(it->index() - from + to);
+ else if (it->index() >= minimum && it->index() < maximum)
+ it->setIndex(it->index() + difference);
+ }
+ emit itemsMoved(from, to, count);
+}
+
+void QSGVisualAdaptorModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
+{
+ Q_D(QSGVisualAdaptorModel);
+ if (parent == d->m_root)
+ _q_itemsInserted(begin, end - begin + 1);
+}
+
+void QSGVisualAdaptorModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
+{
+ Q_D(QSGVisualAdaptorModel);
+ if (parent == d->m_root)
+ _q_itemsRemoved(begin, end - begin + 1);
+}
+
+void QSGVisualAdaptorModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
+{
+ Q_D(QSGVisualAdaptorModel);
+ const int count = sourceEnd - sourceStart + 1;
+ if (destinationParent == d->m_root && sourceParent == d->m_root) {
+ _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-count, count);
+ } else if (sourceParent == d->m_root) {
+ _q_itemsRemoved(sourceStart, count);
+ } else if (destinationParent == d->m_root) {
+ _q_itemsInserted(destinationRow, count);
+ }
+}
+
+void QSGVisualAdaptorModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
+{
+ Q_D(QSGVisualAdaptorModel);
+ if (begin.parent() == d->m_root)
+ _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
+}
+
+void QSGVisualAdaptorModel::_q_layoutChanged()
+{
+ Q_D(QSGVisualAdaptorModel);
+ _q_itemsChanged(0, count(), d->m_roles);
+}
+
+void QSGVisualAdaptorModel::_q_modelReset()
+{
+ Q_D(QSGVisualAdaptorModel);
+ int oldCount = d->m_count;
+ d->m_root = QModelIndex();
+ d->m_count = d->modelCount();
+ emit modelReset(oldCount, d->m_count);
+ emit rootIndexChanged();
+ if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
+ d->m_abstractItemModel->fetchMore(d->m_root);
+}
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QListModelInterface)
+
+#include <qsgvisualadaptormodel.moc>
diff --git a/src/declarative/items/qsgvisualadaptormodel_p.h b/src/declarative/items/qsgvisualadaptormodel_p.h
new file mode 100644
index 0000000000..bc9d3881fc
--- /dev/null
+++ b/src/declarative/items/qsgvisualadaptormodel_p.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGVISUALADAPTORMODEL_P_H
+#define QSGVISUALADAPTORMODEL_P_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qabstractitemmodel.h>
+
+#include <QtDeclarative/private/qdeclarativerefcount_p.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeEngine;
+
+class QSGVisualAdaptorModelPrivate;
+class QSGVisualAdaptorModel : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSGVisualAdaptorModel)
+public:
+ enum Flag
+ {
+ MetaObjectCacheable = 0x01,
+ ProxiedObject = 0x02
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QSGVisualAdaptorModel(QObject *parent = 0);
+ virtual ~QSGVisualAdaptorModel();
+
+ Flags flags() const;
+
+ QVariant model() const;
+ void setModel(const QVariant &, QDeclarativeEngine *);
+
+ QVariant rootIndex() const;
+ void setRootIndex(const QVariant &root);
+
+ QVariant modelIndex(int idx) const;
+ QVariant parentModelIndex() const;
+
+ int count() const;
+ QObject *data(int index);
+ QString stringValue(int index, const QString &role);
+ void replaceWatchedRoles(const QList<QByteArray> &oldRoles, const QList<QByteArray> &newRoles);
+ int indexOf(QObject *object) const;
+
+ bool canFetchMore() const;
+ void fetchMore();
+
+Q_SIGNALS:
+ void rootIndexChanged();
+ void modelReset(int oldCount, int newCount);
+
+ void itemsInserted(int index, int count);
+ void itemsRemoved(int index, int count);
+ void itemsMoved(int from, int to, int count);
+ void itemsChanged(int index, int count);
+
+private Q_SLOTS:
+ void _q_itemsChanged(int, int, const QList<int> &);
+ void _q_itemsInserted(int index, int count);
+ void _q_itemsRemoved(int index, int count);
+ void _q_itemsMoved(int from, int to, int count);
+ void _q_rowsInserted(const QModelIndex &,int,int);
+ void _q_rowsRemoved(const QModelIndex &,int,int);
+ void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
+ void _q_dataChanged(const QModelIndex&,const QModelIndex&);
+ void _q_layoutChanged();
+ void _q_modelReset();
+
+private:
+ Q_DISABLE_COPY(QSGVisualAdaptorModel)
+};
+
+class QSGVisualAdaptorModelProxyInterface
+{
+public:
+ virtual ~QSGVisualAdaptorModelProxyInterface() {}
+
+ virtual QObject *proxiedObject() = 0;
+};
+
+Q_DECLARE_INTERFACE(QSGVisualAdaptorModelProxyInterface, "com.trolltech.qml.QSGVisualAdaptorModelProxyInterface")
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/declarative/items/qsgvisualdatamodel.cpp b/src/declarative/items/qsgvisualdatamodel.cpp
new file mode 100644
index 0000000000..219d1dc495
--- /dev/null
+++ b/src/declarative/items/qsgvisualdatamodel.cpp
@@ -0,0 +1,849 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgvisualdatamodel_p.h"
+#include "qsgitem.h"
+
+#include <QtCore/qcoreapplication.h>
+#include <QtDeclarative/qdeclarativecontext.h>
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativeexpression.h>
+#include <QtDeclarative/qdeclarativeinfo.h>
+
+#include <private/qdeclarativecontext_p.h>
+#include <private/qdeclarativepackage_p.h>
+#include <private/qdeclarativeopenmetaobject_p.h>
+#include <private/qdeclarativelistaccessor_p.h>
+#include <private/qdeclarativedata_p.h>
+#include <private/qdeclarativepropertycache_p.h>
+#include <private/qdeclarativeguard_p.h>
+#include <private/qdeclarativeglobal_p.h>
+#include <private/qmetaobjectbuilder_p.h>
+#include <private/qdeclarativeproperty_p.h>
+#include <private/qsgvisualadaptormodel_p.h>
+#include <private/qobject_p.h>
+
+#include <QtCore/qhash.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSGVisualDataModelParts;
+class QSGVisualDataModelData;
+class QSGVisualDataModelDataMetaObject;
+class QSGVisualDataModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QSGVisualDataModel)
+public:
+ QSGVisualDataModelPrivate(QDeclarativeContext *);
+
+ static QSGVisualDataModelPrivate *get(QSGVisualDataModel *m) {
+ return static_cast<QSGVisualDataModelPrivate *>(QObjectPrivate::get(m));
+ }
+
+ void init();
+ void connectModel(QSGVisualAdaptorModel *model);
+
+ QObject *object(int index, bool complete);
+ QSGVisualDataModel::ReleaseFlags release(QObject *object);
+ QString stringValue(int index, const QString &name);
+ void emitCreatedPackage(int index, QDeclarativePackage *package) {
+ emit q_func()->createdPackage(index, package); }
+ void emitDestroyingPackage(QDeclarativePackage *package) {
+ emit q_func()->destroyingPackage(package); }
+
+ QSGVisualAdaptorModel *m_adaptorModel;
+ QDeclarativeComponent *m_delegate;
+ QDeclarativeGuard<QDeclarativeContext> m_context;
+
+ struct ObjectRef {
+ ObjectRef(QObject *object=0) : obj(object), ref(1) {}
+ QObject *obj;
+ int ref;
+ };
+ class Cache : public QHash<int, ObjectRef> {
+ public:
+ QObject *getItem(int index) {
+ QObject *item = 0;
+ QHash<int,ObjectRef>::iterator it = find(index);
+ if (it != end()) {
+ (*it).ref++;
+ item = (*it).obj;
+ }
+ return item;
+ }
+ QObject *item(int index) {
+ QObject *item = 0;
+ QHash<int, ObjectRef>::const_iterator it = find(index);
+ if (it != end())
+ item = (*it).obj;
+ return item;
+ }
+ void insertItem(int index, QObject *obj) {
+ insert(index, ObjectRef(obj));
+ }
+ bool releaseItem(QObject *obj) {
+ QHash<int, ObjectRef>::iterator it = begin();
+ for (; it != end(); ++it) {
+ ObjectRef &objRef = *it;
+ if (objRef.obj == obj) {
+ if (--objRef.ref == 0) {
+ erase(it);
+ return true;
+ }
+ break;
+ }
+ }
+ return false;
+ }
+ };
+
+ Cache m_cache;
+ QHash<QObject *, QDeclarativePackage*> m_packaged;
+
+ QSGVisualDataModelParts *m_parts;
+ friend class QSGVisualItemParts;
+
+ friend class QSGVisualDataModelData;
+ bool m_delegateValidated : 1;
+ bool m_completePending : 1;
+
+ QList<QByteArray> watchedRoles;
+};
+
+//---------------------------------------------------------------------------
+
+class QSGVisualPartsModel : public QSGVisualModel
+{
+ Q_OBJECT
+
+public:
+ QSGVisualPartsModel(QSGVisualDataModel *model, const QString &part, QObject *parent = 0);
+ ~QSGVisualPartsModel();
+
+ int count() const;
+ bool isValid() const;
+ QSGItem *item(int index, bool complete=true);
+ ReleaseFlags release(QSGItem *item);
+ bool completePending() const;
+ void completeItem();
+ QString stringValue(int index, const QString &role);
+ void setWatchedRoles(QList<QByteArray> roles);
+
+ int indexOf(QSGItem *item, QObject *objectContext) const;
+
+public Q_SLOTS:
+ void createdPackage(int index, QDeclarativePackage *package);
+ void destroyingPackage(QDeclarativePackage *package);
+
+private:
+ QSGVisualDataModel *m_model;
+ QHash<QObject *, QDeclarativePackage *> m_packaged;
+ QString m_part;
+ QList<QByteArray> m_watchedRoles;
+};
+
+class QSGVisualDataModelPartsMetaObject : public QDeclarativeOpenMetaObject
+{
+public:
+ QSGVisualDataModelPartsMetaObject(QObject *parent)
+ : QDeclarativeOpenMetaObject(parent) {}
+
+ virtual void propertyCreated(int, QMetaPropertyBuilder &);
+ virtual QVariant initialValue(int);
+};
+
+class QSGVisualDataModelParts : public QObject
+{
+Q_OBJECT
+public:
+ QSGVisualDataModelParts(QSGVisualDataModel *parent);
+
+private:
+ friend class QSGVisualDataModelPartsMetaObject;
+ QSGVisualDataModel *model;
+};
+
+void QSGVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
+{
+ prop.setWritable(false);
+}
+
+QVariant QSGVisualDataModelPartsMetaObject::initialValue(int id)
+{
+ QSGVisualPartsModel *m = new QSGVisualPartsModel(
+ static_cast<QSGVisualDataModelParts *>(object())->model,
+ QString::fromUtf8(name(id)),
+ object());
+ return QVariant::fromValue(static_cast<QObject *>(m));
+}
+
+QSGVisualDataModelParts::QSGVisualDataModelParts(QSGVisualDataModel *parent)
+: QObject(parent), model(parent)
+{
+ new QSGVisualDataModelPartsMetaObject(this);
+}
+
+QSGVisualDataModelPrivate::QSGVisualDataModelPrivate(QDeclarativeContext *ctxt)
+ : m_adaptorModel(0)
+ , m_delegate(0)
+ , m_context(ctxt)
+ , m_parts(0)
+ , m_delegateValidated(false)
+ , m_completePending(false)
+{
+}
+
+//---------------------------------------------------------------------------
+
+/*!
+ \qmlclass VisualDataModel QSGVisualDataModel
+ \inqmlmodule QtQuick 2
+ \ingroup qml-working-with-data
+ \brief The VisualDataModel encapsulates a model and delegate
+
+ A VisualDataModel encapsulates a model and the delegate that will
+ be instantiated for items in the model.
+
+ It is usually not necessary to create VisualDataModel elements.
+ However, it can be useful for manipulating and accessing the \l modelIndex
+ when a QAbstractItemModel subclass is used as the
+ model. Also, VisualDataModel is used together with \l Package to
+ provide delegates to multiple views.
+
+ The example below illustrates using a VisualDataModel with a ListView.
+
+ \snippet doc/src/snippets/declarative/visualdatamodel.qml 0
+*/
+
+void QSGVisualDataModelPrivate::connectModel(QSGVisualAdaptorModel *model)
+{
+ Q_Q(QSGVisualDataModel);
+
+ QObject::connect(model, SIGNAL(itemsInserted(int,int)), q, SLOT(_q_itemsInserted(int,int)));
+ QObject::connect(model, SIGNAL(itemsRemoved(int,int)), q, SLOT(_q_itemsRemoved(int,int)));
+ QObject::connect(model, SIGNAL(itemsMoved(int,int,int)), q, SLOT(_q_itemsMoved(int,int,int)));
+ QObject::connect(model, SIGNAL(itemsChanged(int,int)), q, SLOT(_q_itemsChanged(int,int)));
+ QObject::connect(model, SIGNAL(modelReset(int,int)), q, SLOT(_q_modelReset(int,int)));
+}
+
+void QSGVisualDataModelPrivate::init()
+{
+ Q_Q(QSGVisualDataModel);
+ m_adaptorModel = new QSGVisualAdaptorModel;
+ QObject::connect(m_adaptorModel, SIGNAL(rootIndexChanged()), q, SIGNAL(rootIndexChanged()));
+ connectModel(m_adaptorModel);
+}
+
+QSGVisualDataModel::QSGVisualDataModel()
+: QSGVisualModel(*(new QSGVisualDataModelPrivate(0)))
+{
+ Q_D(QSGVisualDataModel);
+ d->init();
+}
+
+QSGVisualDataModel::QSGVisualDataModel(QDeclarativeContext *ctxt, QObject *parent)
+: QSGVisualModel(*(new QSGVisualDataModelPrivate(ctxt)), parent)
+{
+ Q_D(QSGVisualDataModel);
+ d->init();
+}
+
+QSGVisualDataModel::~QSGVisualDataModel()
+{
+ Q_D(QSGVisualDataModel);
+ delete d->m_adaptorModel;
+}
+
+/*!
+ \qmlproperty model QtQuick2::VisualDataModel::model
+ This property holds the model providing data for the VisualDataModel.
+
+ The model provides a set of data that is used to create the items
+ for a view. For large or dynamic datasets the model is usually
+ provided by a C++ model object. The C++ model object must be a \l
+ {QAbstractItemModel} subclass or a simple list.
+
+ Models can also be created directly in QML, using a \l{ListModel} or
+ \l{XmlListModel}.
+
+ \sa {qmlmodels}{Data Models}
+*/
+QVariant QSGVisualDataModel::model() const
+{
+ Q_D(const QSGVisualDataModel);
+ return d->m_adaptorModel->model();
+}
+
+void QSGVisualDataModel::setModel(const QVariant &model)
+{
+ Q_D(QSGVisualDataModel);
+ d->m_adaptorModel->setModel(model, d->m_context ? d->m_context->engine() : qmlEngine(this));
+ if (d->m_adaptorModel->canFetchMore())
+ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
+}
+
+/*!
+ \qmlproperty Component QtQuick2::VisualDataModel::delegate
+
+ The delegate provides a template defining each item instantiated by a view.
+ The index is exposed as an accessible \c index property. Properties of the
+ model are also available depending upon the type of \l {qmlmodels}{Data Model}.
+*/
+QDeclarativeComponent *QSGVisualDataModel::delegate() const
+{
+ Q_D(const QSGVisualDataModel);
+ return d->m_delegate;
+}
+
+void QSGVisualDataModel::setDelegate(QDeclarativeComponent *delegate)
+{
+ Q_D(QSGVisualDataModel);
+ bool wasValid = d->m_delegate != 0;
+ d->m_delegate = delegate;
+ d->m_delegateValidated = false;
+ if (!wasValid && d->m_adaptorModel->count() && d->m_delegate) {
+ emit itemsInserted(0, d->m_adaptorModel->count());
+ emit countChanged();
+ }
+ if (wasValid && !d->m_delegate && d->m_adaptorModel->count()) {
+ _q_itemsRemoved(0, d->m_adaptorModel->count());
+ emit countChanged();
+ }
+}
+
+/*!
+ \qmlproperty QModelIndex QtQuick2::VisualDataModel::rootIndex
+
+ QAbstractItemModel provides a hierarchical tree of data, whereas
+ QML only operates on list data. \c rootIndex allows the children of
+ any node in a QAbstractItemModel to be provided by this model.
+
+ This property only affects models of type QAbstractItemModel that
+ are hierarchical (e.g, a tree model).
+
+ For example, here is a simple interactive file system browser.
+ When a directory name is clicked, the view's \c rootIndex is set to the
+ QModelIndex node of the clicked directory, thus updating the view to show
+ the new directory's contents.
+
+ \c main.cpp:
+ \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/main.cpp 0
+
+ \c view.qml:
+ \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/view.qml 0
+
+ If the \l model is a QAbstractItemModel subclass, the delegate can also
+ reference a \c hasModelChildren property (optionally qualified by a
+ \e model. prefix) that indicates whether the delegate's model item has
+ any child nodes.
+
+
+ \sa modelIndex(), parentModelIndex()
+*/
+QVariant QSGVisualDataModel::rootIndex() const
+{
+ Q_D(const QSGVisualDataModel);
+ return d->m_adaptorModel->rootIndex();
+}
+
+void QSGVisualDataModel::setRootIndex(const QVariant &root)
+{
+ Q_D(QSGVisualDataModel);
+ d->m_adaptorModel->setRootIndex(root);
+}
+
+/*!
+ \qmlmethod QModelIndex QtQuick2::VisualDataModel::modelIndex(int index)
+
+ QAbstractItemModel provides a hierarchical tree of data, whereas
+ QML only operates on list data. This function assists in using
+ tree models in QML.
+
+ Returns a QModelIndex for the specified index.
+ This value can be assigned to rootIndex.
+
+ \sa rootIndex
+*/
+QVariant QSGVisualDataModel::modelIndex(int idx) const
+{
+ Q_D(const QSGVisualDataModel);
+ return d->m_adaptorModel->modelIndex(idx);
+}
+
+/*!
+ \qmlmethod QModelIndex QtQuick2::VisualDataModel::parentModelIndex()
+
+ QAbstractItemModel provides a hierarchical tree of data, whereas
+ QML only operates on list data. This function assists in using
+ tree models in QML.
+
+ Returns a QModelIndex for the parent of the current rootIndex.
+ This value can be assigned to rootIndex.
+
+ \sa rootIndex
+*/
+QVariant QSGVisualDataModel::parentModelIndex() const
+{
+ Q_D(const QSGVisualDataModel);
+ return d->m_adaptorModel->parentModelIndex();
+}
+
+int QSGVisualDataModel::count() const
+{
+ Q_D(const QSGVisualDataModel);
+ if (!d->m_delegate)
+ return 0;
+ return d->m_adaptorModel->count();
+}
+
+QSGVisualDataModel::ReleaseFlags QSGVisualDataModelPrivate::release(QObject *object)
+{
+ QSGVisualDataModel::ReleaseFlags stat = 0;
+
+ if (m_cache.releaseItem(object)) {
+ // Remove any bindings to avoid warnings due to parent change.
+ QObjectPrivate *p = QObjectPrivate::get(object);
+ Q_ASSERT(p->declarativeData);
+ QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
+ if (d->ownContext && d->context)
+ d->context->clearContext();
+ stat |= QSGVisualDataModel::Destroyed;
+ object->deleteLater();
+ } else {
+ stat |= QSGVisualDataModel::Referenced;
+ }
+
+ return stat;
+}
+
+/*
+ Returns ReleaseStatus flags.
+*/
+
+QSGVisualDataModel::ReleaseFlags QSGVisualDataModel::release(QSGItem *item)
+{
+ Q_D(QSGVisualDataModel);
+ QSGVisualModel::ReleaseFlags stat = d->release(item);
+ if (stat & Destroyed)
+ item->setParentItem(0);
+ return stat;
+}
+
+/*!
+ \qmlproperty object QtQuick2::VisualDataModel::parts
+
+ The \a parts property selects a VisualDataModel which creates
+ delegates from the part named. This is used in conjunction with
+ the \l Package element.
+
+ For example, the code below selects a model which creates
+ delegates named \e list from a \l Package:
+
+ \code
+ VisualDataModel {
+ id: visualModel
+ delegate: Package {
+ Item { Package.name: "list" }
+ }
+ model: myModel
+ }
+
+ ListView {
+ width: 200; height:200
+ model: visualModel.parts.list
+ }
+ \endcode
+
+ \sa Package
+*/
+
+QObject *QSGVisualDataModel::parts()
+{
+ Q_D(QSGVisualDataModel);
+ if (!d->m_parts)
+ d->m_parts = new QSGVisualDataModelParts(this);
+ return d->m_parts;
+}
+
+QObject *QSGVisualDataModelPrivate::object(int index, bool complete)
+{
+ Q_Q(QSGVisualDataModel);
+ if (m_adaptorModel->count() <= 0 || !m_delegate)
+ return 0;
+ QObject *nobj = m_cache.getItem(index);
+ bool needComplete = false;
+ if (!nobj) {
+ QObject *data = m_adaptorModel->data(index);
+
+ QDeclarativeContext *rootContext = new QDeclarativeContext(
+ m_context ? m_context.data() : qmlContext(q));
+ QDeclarativeContext *ctxt = rootContext;
+ if (m_adaptorModel->flags() & QSGVisualAdaptorModel::ProxiedObject) {
+ if (QSGVisualAdaptorModelProxyInterface *proxy = qobject_cast<QSGVisualAdaptorModelProxyInterface *>(data)) {
+ ctxt->setContextObject(proxy->proxiedObject());
+ ctxt = new QDeclarativeContext(ctxt, ctxt);
+ }
+ }
+
+ QDeclarative_setParent_noEvent(data, ctxt);
+ ctxt->setContextProperty(QLatin1String("model"), data);
+ ctxt->setContextObject(data);
+
+ m_completePending = false;
+ nobj = m_delegate->beginCreate(ctxt);
+ if (complete) {
+ m_delegate->completeCreate();
+ } else {
+ m_completePending = true;
+ needComplete = true;
+ }
+ if (nobj) {
+ QDeclarative_setParent_noEvent(rootContext, nobj);
+ m_cache.insertItem(index, nobj);
+ if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj))
+ emitCreatedPackage(index, package);
+ } else {
+ delete rootContext;
+ qmlInfo(q, m_delegate->errors()) << "Error creating delegate";
+ }
+ }
+
+ if (index == m_adaptorModel->count() -1 && m_adaptorModel->canFetchMore())
+ QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
+
+ return nobj;
+}
+
+QSGItem *QSGVisualDataModel::item(int index, bool complete)
+{
+ Q_D(QSGVisualDataModel);
+ QObject *object = d->object(index, complete);
+ if (QSGItem *item = qobject_cast<QSGItem *>(object))
+ return item;
+
+ if (completePending())
+ completeItem();
+ d->release(object);
+ if (!d->m_delegateValidated) {
+ qmlInfo(d->m_delegate) << tr("Delegate component must be Item type.");
+ d->m_delegateValidated = true;
+ }
+ return 0;
+}
+
+bool QSGVisualDataModel::completePending() const
+{
+ Q_D(const QSGVisualDataModel);
+ return d->m_completePending;
+}
+
+void QSGVisualDataModel::completeItem()
+{
+ Q_D(QSGVisualDataModel);
+ d->m_delegate->completeCreate();
+ d->m_completePending = false;
+}
+
+QString QSGVisualDataModelPrivate::stringValue(int index, const QString &name)
+{
+ return m_adaptorModel->stringValue(index, name);
+}
+
+QString QSGVisualDataModel::stringValue(int index, const QString &name)
+{
+ Q_D(QSGVisualDataModel);
+ return d->stringValue(index, name);
+}
+
+int QSGVisualDataModel::indexOf(QSGItem *item, QObject *) const
+{
+ Q_D(const QSGVisualDataModel);
+ return d->m_adaptorModel->indexOf(item);
+}
+
+void QSGVisualDataModel::setWatchedRoles(QList<QByteArray> roles)
+{
+ Q_D(QSGVisualDataModel);
+ d->m_adaptorModel->replaceWatchedRoles(d->watchedRoles, roles);
+ d->watchedRoles = roles;
+}
+
+bool QSGVisualDataModel::event(QEvent *e)
+{
+ Q_D(QSGVisualDataModel);
+ if (e->type() == QEvent::UpdateRequest)
+ d->m_adaptorModel->fetchMore();
+ return QSGVisualModel::event(e);
+}
+
+void QSGVisualDataModel::_q_itemsChanged(int index, int count)
+{
+ Q_D(QSGVisualDataModel);
+ if (!d->m_delegate)
+ return;
+ emit itemsChanged(index, count);
+}
+
+void QSGVisualDataModel::_q_itemsInserted(int index, int count)
+{
+ Q_D(QSGVisualDataModel);
+ if (!d->m_delegate)
+ return;
+
+ // XXX - highly inefficient
+ QHash<int,QSGVisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= index) {
+ QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() + count;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsInserted(index, count);
+ emit countChanged();
+}
+
+void QSGVisualDataModel::_q_itemsRemoved(int index, int count)
+{
+ Q_D(QSGVisualDataModel);
+ if (!d->m_delegate)
+ return;
+ // XXX - highly inefficient
+ QHash<int, QSGVisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int, QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+ if (iter.key() >= index && iter.key() < index + count) {
+ QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
+ iter = d->m_cache.erase(iter);
+ items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
+ } else if (iter.key() >= index + count) {
+ QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - count;
+ iter = d->m_cache.erase(iter);
+ items.insert(index, objRef);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsRemoved(index, count);
+ emit countChanged();
+}
+
+void QSGVisualDataModel::_q_itemsMoved(int from, int to, int count)
+{
+ Q_D(QSGVisualDataModel);
+ if (!d->m_delegate)
+ return;
+
+ // XXX - highly inefficient
+ QHash<int,QSGVisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+ if (iter.key() >= from && iter.key() < from + count) {
+ QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - from + to;
+ items.insert(index, objRef);
+ iter = d->m_cache.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+ for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+ int diff = from > to ? count : -count;
+ if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) {
+ QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() + diff;
+ iter = d->m_cache.erase(iter);
+ items.insert(index, objRef);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+ emit itemsMoved(from, to, count);
+}
+
+void QSGVisualDataModel::_q_modelReset(int, int)
+{
+ Q_D(QSGVisualDataModel);
+ if (!d->m_delegate)
+ return;
+ emit modelReset();
+ emit countChanged();
+}
+
+//============================================================================
+
+QSGVisualPartsModel::QSGVisualPartsModel(QSGVisualDataModel *model, const QString &part, QObject *parent)
+ : QSGVisualModel(*new QObjectPrivate, parent)
+ , m_model(model)
+ , m_part(part)
+{
+ connect(m_model, SIGNAL(modelReset()), this, SIGNAL(modelReset()));
+ connect(m_model, SIGNAL(itemsInserted(int,int)), this, SIGNAL(itemsInserted(int,int)));
+ connect(m_model, SIGNAL(itemsRemoved(int,int)), this, SIGNAL(itemsRemoved(int,int)));
+ connect(m_model, SIGNAL(itemsChanged(int,int)), this, SIGNAL(itemsChanged(int,int)));
+ connect(m_model, SIGNAL(itemsMoved(int,int,int)), this, SIGNAL(itemsMoved(int,int,int)));
+ connect(m_model, SIGNAL(createdPackage(int,QDeclarativePackage*)),
+ this, SLOT(createdPackage(int,QDeclarativePackage*)));
+ connect(m_model, SIGNAL(destroyingPackage(QDeclarativePackage*)),
+ this, SLOT(destroyingPackage(QDeclarativePackage*)));
+}
+
+QSGVisualPartsModel::~QSGVisualPartsModel()
+{
+}
+
+int QSGVisualPartsModel::count() const
+{
+ return m_model->count();
+}
+
+bool QSGVisualPartsModel::isValid() const
+{
+ return m_model->isValid();
+}
+
+QSGItem *QSGVisualPartsModel::item(int index, bool complete)
+{
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
+
+ QObject *object = model->object(index, complete);
+
+ if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(object)) {
+ QObject *part = package->part(m_part);
+ if (!part)
+ return 0;
+ if (QSGItem *item = qobject_cast<QSGItem *>(part)) {
+ m_packaged.insertMulti(item, package);
+ return item;
+ }
+ }
+
+ if (m_model->completePending())
+ m_model->completeItem();
+ model->release(object);
+ if (!model->m_delegateValidated) {
+ qmlInfo(model->m_delegate) << tr("Delegate component must be Package type.");
+ model->m_delegateValidated = true;
+ }
+
+ return 0;
+}
+
+QSGVisualModel::ReleaseFlags QSGVisualPartsModel::release(QSGItem *item)
+{
+ QSGVisualModel::ReleaseFlags flags = 0;
+
+ QHash<QObject *, QDeclarativePackage *>::iterator it = m_packaged.find(item);
+ if (it != m_packaged.end()) {
+ QDeclarativePackage *package = *it;
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
+ flags = model->release(package);
+ m_packaged.erase(it);
+ if (!m_packaged.contains(item))
+ flags &= ~Referenced;
+ if (flags & Destroyed)
+ QSGVisualDataModelPrivate::get(m_model)->emitDestroyingPackage(package);
+ }
+ return flags;
+}
+
+bool QSGVisualPartsModel::completePending() const
+{
+ return m_model->completePending();
+}
+
+void QSGVisualPartsModel::completeItem()
+{
+ m_model->completeItem();
+}
+
+QString QSGVisualPartsModel::stringValue(int index, const QString &role)
+{
+ return QSGVisualDataModelPrivate::get(m_model)->stringValue(index, role);
+}
+
+void QSGVisualPartsModel::setWatchedRoles(QList<QByteArray> roles)
+{
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
+ model->m_adaptorModel->replaceWatchedRoles(m_watchedRoles, roles);
+ m_watchedRoles = roles;
+}
+
+int QSGVisualPartsModel::indexOf(QSGItem *item, QObject *) const
+{
+ const QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
+ QHash<QObject *, QDeclarativePackage *>::const_iterator it = m_packaged.find(item);
+ return it != m_packaged.end()
+ ? model->m_adaptorModel->indexOf(*it)
+ : -1;
+}
+
+void QSGVisualPartsModel::createdPackage(int index, QDeclarativePackage *package)
+{
+ if (QSGItem *item = qobject_cast<QSGItem *>(package->part(m_part)))
+ emit createdItem(index, item);
+}
+
+void QSGVisualPartsModel::destroyingPackage(QDeclarativePackage *package)
+{
+ if (QSGItem *item = qobject_cast<QSGItem *>(package->part(m_part))) {
+ Q_ASSERT(!m_packaged.contains(item));
+ emit destroyingItem(item);
+ }
+}
+
+QT_END_NAMESPACE
+
+#include <qsgvisualdatamodel.moc>
diff --git a/src/declarative/items/qsgvisualdatamodel_p.h b/src/declarative/items/qsgvisualdatamodel_p.h
new file mode 100644
index 0000000000..d3f1d18f65
--- /dev/null
+++ b/src/declarative/items/qsgvisualdatamodel_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGVISUALDATAMODEL_P_H
+#define QSGVISUALDATAMODEL_P_H
+
+#include <private/qsgvisualitemmodel_p.h>
+#include <QtCore/qabstractitemmodel.h>
+
+QT_BEGIN_HEADER
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeComponent;
+class QDeclarativePackage;
+class QSGVisualDataModelPrivate;
+class Q_DECLARATIVE_EXPORT QSGVisualDataModel : public QSGVisualModel
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSGVisualDataModel)
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate)
+ Q_PROPERTY(QObject *parts READ parts CONSTANT)
+ Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
+ Q_CLASSINFO("DefaultProperty", "delegate")
+public:
+ QSGVisualDataModel();
+ QSGVisualDataModel(QDeclarativeContext *, QObject *parent=0);
+ virtual ~QSGVisualDataModel();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ QVariant rootIndex() const;
+ void setRootIndex(const QVariant &root);
+
+ Q_INVOKABLE QVariant modelIndex(int idx) const;
+ Q_INVOKABLE QVariant parentModelIndex() const;
+
+ int count() const;
+ bool isValid() const { return delegate() != 0; }
+ QSGItem *item(int index, bool complete=true);
+ ReleaseFlags release(QSGItem *item);
+ bool completePending() const;
+ void completeItem();
+ virtual QString stringValue(int index, const QString &role);
+ virtual void setWatchedRoles(QList<QByteArray> roles);
+
+ int indexOf(QSGItem *item, QObject *objectContext) const;
+
+ QObject *parts();
+
+ bool event(QEvent *);
+
+Q_SIGNALS:
+ void createdPackage(int index, QDeclarativePackage *package);
+ void destroyingPackage(QDeclarativePackage *package);
+ void rootIndexChanged();
+
+private Q_SLOTS:
+ void _q_itemsChanged(int index, int count);
+ void _q_itemsInserted(int index, int count);
+ void _q_itemsRemoved(int index, int count);
+ void _q_itemsMoved(int from, int to, int count);
+ void _q_modelReset(int oldCount, int newCount);
+private:
+ Q_DISABLE_COPY(QSGVisualDataModel)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QSGVisualDataModel)
+
+QT_END_HEADER
+
+#endif // QSGVISUALDATAMODEL_P_H
diff --git a/src/declarative/items/qsgvisualitemmodel.cpp b/src/declarative/items/qsgvisualitemmodel.cpp
index c6e5896373..fbc8a1abf2 100644
--- a/src/declarative/items/qsgvisualitemmodel.cpp
+++ b/src/declarative/items/qsgvisualitemmodel.cpp
@@ -42,22 +42,11 @@
#include "qsgvisualitemmodel_p.h"
#include "qsgitem.h"
+#include <QtCore/qcoreapplication.h>
#include <QtDeclarative/qdeclarativecontext.h>
#include <QtDeclarative/qdeclarativeengine.h>
-#include <QtDeclarative/qdeclarativeexpression.h>
-#include <QtDeclarative/qdeclarativeinfo.h>
-#include <private/qdeclarativecontext_p.h>
-#include <private/qdeclarativepackage_p.h>
-#include <private/qdeclarativeopenmetaobject_p.h>
-#include <private/qdeclarativelistaccessor_p.h>
-#include <private/qdeclarativedata_p.h>
-#include <private/qdeclarativepropertycache_p.h>
-#include <private/qdeclarativeguard_p.h>
#include <private/qdeclarativeglobal_p.h>
-#include <private/qlistmodelinterface_p.h>
-#include <private/qmetaobjectbuilder_p.h>
-#include <private/qdeclarativeproperty_p.h>
#include <private/qobject_p.h>
#include <QtCore/qhash.h>
@@ -247,1315 +236,5 @@ QSGVisualItemModelAttached *QSGVisualItemModel::qmlAttachedProperties(QObject *o
return QSGVisualItemModelAttached::properties(obj);
}
-//============================================================================
-
-class VDMDelegateDataType : public QDeclarativeRefCount
-{
-public:
- VDMDelegateDataType()
- : metaObject(0)
- , propertyCache(0)
- , propertyOffset(0)
- , signalOffset(0)
- , shared(true)
- {
- }
-
- VDMDelegateDataType(const VDMDelegateDataType &type)
- : metaObject(0)
- , propertyCache(0)
- , propertyOffset(type.propertyOffset)
- , signalOffset(type.signalOffset)
- , shared(false)
- , builder(type.metaObject, QMetaObjectBuilder::Properties
- | QMetaObjectBuilder::Signals
- | QMetaObjectBuilder::SuperClass
- | QMetaObjectBuilder::ClassName)
- {
- builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- }
-
- ~VDMDelegateDataType()
- {
- if (propertyCache)
- propertyCache->release();
- qFree(metaObject);
- }
-
- QMetaObject *metaObject;
- QDeclarativePropertyCache *propertyCache;
- int propertyOffset;
- int signalOffset;
- bool shared : 1;
- QMetaObjectBuilder builder;
-};
-
-class QSGVisualDataModelParts;
-class QSGVisualDataModelData;
-class QSGVisualDataModelDataMetaObject;
-class QSGVisualDataModelPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QSGVisualDataModel)
-public:
- QSGVisualDataModelPrivate(QDeclarativeContext *);
-
- static QSGVisualDataModelPrivate *get(QSGVisualDataModel *m) {
- return static_cast<QSGVisualDataModelPrivate *>(QObjectPrivate::get(m));
- }
-
- QDeclarativeGuard<QListModelInterface> m_listModelInterface;
- QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
- QDeclarativeGuard<QSGVisualDataModel> m_visualItemModel;
- QString m_part;
-
- QDeclarativeComponent *m_delegate;
- QDeclarativeGuard<QDeclarativeContext> m_context;
- QList<int> m_roles;
- QHash<QByteArray,int> m_roleNames;
-
- void addProperty(int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData = false);
- template <typename T> void setModelDataType()
- {
- createModelData = &T::create;
- m_delegateDataType->builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
- m_delegateDataType->builder.setClassName(T::staticMetaObject.className());
- m_delegateDataType->builder.setSuperClass(&T::staticMetaObject);
- m_delegateDataType->propertyOffset = T::staticMetaObject.propertyCount();
- m_delegateDataType->signalOffset = T::staticMetaObject.methodCount();
- }
- QSGVisualDataModelData *createMetaObject(int index, QSGVisualDataModel *model);
-
- static QSGVisualDataModelData *initializeModelData(int index, QSGVisualDataModel *model) {
- return get(model)->createMetaObject(index, model);
- }
-
- typedef QSGVisualDataModelData *(*CreateModelData)(int index, QSGVisualDataModel *model);
-
- struct PropertyData {
- int role;
- bool isModelData : 1;
- };
-
- struct ObjectRef {
- ObjectRef(QObject *object=0) : obj(object), ref(1) {}
- QObject *obj;
- int ref;
- };
- class Cache : public QHash<int, ObjectRef> {
- public:
- QObject *getItem(int index) {
- QObject *item = 0;
- QHash<int,ObjectRef>::iterator it = find(index);
- if (it != end()) {
- (*it).ref++;
- item = (*it).obj;
- }
- return item;
- }
- QObject *item(int index) {
- QObject *item = 0;
- QHash<int, ObjectRef>::const_iterator it = find(index);
- if (it != end())
- item = (*it).obj;
- return item;
- }
- void insertItem(int index, QObject *obj) {
- insert(index, ObjectRef(obj));
- }
- bool releaseItem(QObject *obj) {
- QHash<int, ObjectRef>::iterator it = begin();
- for (; it != end(); ++it) {
- ObjectRef &objRef = *it;
- if (objRef.obj == obj) {
- if (--objRef.ref == 0) {
- erase(it);
- return true;
- }
- break;
- }
- }
- return false;
- }
- };
-
- int modelCount() const {
- if (m_visualItemModel)
- return m_visualItemModel->count();
- if (m_listModelInterface)
- return m_listModelInterface->count();
- if (m_abstractItemModel)
- return m_abstractItemModel->rowCount(m_root);
- if (m_listAccessor)
- return m_listAccessor->count();
- return 0;
- }
-
- Cache m_cache;
- QHash<QObject *, QDeclarativePackage*> m_packaged;
-
- QSGVisualDataModelParts *m_parts;
- friend class QSGVisualItemParts;
-
- VDMDelegateDataType *m_delegateDataType;
- CreateModelData createModelData;
-
- friend class QSGVisualDataModelData;
- bool m_delegateValidated : 1;
- bool m_completePending : 1;
- bool m_objectList : 1;
-
- QSGVisualDataModelData *data(QObject *item);
-
- QVariant m_modelVariant;
- QDeclarativeListAccessor *m_listAccessor;
-
- QModelIndex m_root;
- QList<QByteArray> watchedRoles;
- QList<int> watchedRoleIds;
-
- QVector<PropertyData> m_propertyData;
-};
-
-class QSGVisualDataModelData : public QObject
-{
- Q_OBJECT
- Q_PROPERTY(int index READ index NOTIFY indexChanged)
-public:
- QSGVisualDataModelData(int index, QSGVisualDataModel *model);
- ~QSGVisualDataModelData();
-
- int index() const;
- void setIndex(int index);
-
-Q_SIGNALS:
- void indexChanged();
-
-public:
- int m_index;
- QDeclarativeGuard<QSGVisualDataModel> m_model;
-};
-
-class QSGVisualDataModelDataMetaObject : public QAbstractDynamicMetaObject
-{
-public:
- QSGVisualDataModelDataMetaObject(QSGVisualDataModelData *data, VDMDelegateDataType *type)
- : m_data(data)
- , m_type(type)
- {
- QObjectPrivate *op = QObjectPrivate::get(m_data);
- *static_cast<QMetaObject *>(this) = *type->metaObject;
- op->metaObject = this;
- m_type->addref();
- }
-
- ~QSGVisualDataModelDataMetaObject() { m_type->release(); }
-
- QSGVisualDataModelData *m_data;
- VDMDelegateDataType *m_type;
-};
-
-class QSGVDMAbstractItemModelDataMetaObject : public QSGVisualDataModelDataMetaObject
-{
-public:
- QSGVDMAbstractItemModelDataMetaObject(QSGVisualDataModelData *object, VDMDelegateDataType *type)
- : QSGVisualDataModelDataMetaObject(object, type) {}
-
- int metaCall(QMetaObject::Call call, int id, void **arguments)
- {
- if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
- QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_data->m_model);
- if (m_data->m_index == -1 || !model->m_abstractItemModel)
- return -1;
- *static_cast<QVariant *>(arguments[0]) = model->m_abstractItemModel->index(
- m_data->m_index, 0, model->m_root).data(model->m_propertyData.at(id - m_type->propertyOffset).role);
- return -1;
- } else {
- return m_data->qt_metacall(call, id, arguments);
- }
- }
-};
-
-class QSGVDMAbstractItemModelData : public QSGVisualDataModelData
-{
- Q_OBJECT
- Q_PROPERTY(bool hasModelChildren READ hasModelChildren CONSTANT)
-public:
- bool hasModelChildren() const
- {
- QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
- return model->m_abstractItemModel->hasChildren(model->m_abstractItemModel->index(m_index, 0, model->m_root));
- }
-
- static QSGVisualDataModelData *create(int index, QSGVisualDataModel *model) {
- return new QSGVDMAbstractItemModelData(index, model); }
-private:
- QSGVDMAbstractItemModelData(int index, QSGVisualDataModel *model)
- : QSGVisualDataModelData(index, model)
- {
- new QSGVDMAbstractItemModelDataMetaObject(
- this, QSGVisualDataModelPrivate::get(m_model)->m_delegateDataType);
- }
-};
-
-class QSGVDMListModelInterfaceDataMetaObject : public QSGVisualDataModelDataMetaObject
-{
-public:
- QSGVDMListModelInterfaceDataMetaObject(QSGVisualDataModelData *object, VDMDelegateDataType *type)
- : QSGVisualDataModelDataMetaObject(object, type) {}
-
- int metaCall(QMetaObject::Call call, int id, void **arguments)
- {
- if (call == QMetaObject::ReadProperty && id >= m_type->propertyOffset) {
- QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_data->m_model);
- if (m_data->m_index == -1 || !model->m_listModelInterface)
- return -1;
- *static_cast<QVariant *>(arguments[0]) = model->m_listModelInterface->data(
- m_data->m_index, model->m_propertyData.at(id - m_type->propertyOffset).role);
- return -1;
- } else {
- return m_data->qt_metacall(call, id, arguments);
- }
- }
-};
-
-class QSGVDMListModelInterfaceData : public QSGVisualDataModelData
-{
-public:
- static QSGVisualDataModelData *create(int index, QSGVisualDataModel *model) {
- return new QSGVDMListModelInterfaceData(index, model); }
-private:
- QSGVDMListModelInterfaceData(int index, QSGVisualDataModel *model)
- : QSGVisualDataModelData(index, model)
- {
- new QSGVDMListModelInterfaceDataMetaObject(
- this, QSGVisualDataModelPrivate::get(m_model)->m_delegateDataType);
- }
-};
-
-class QSGVDMListAccessorData : public QSGVisualDataModelData
-{
- Q_OBJECT
- Q_PROPERTY(QVariant modelData READ modelData CONSTANT)
-public:
- QVariant modelData() const {
- return QSGVisualDataModelPrivate::get(m_model)->m_listAccessor->at(m_index); }
-
- static QSGVisualDataModelData *create(int index, QSGVisualDataModel *model) {
- return new QSGVDMListAccessorData(index, model); }
-private:
- QSGVDMListAccessorData(int index, QSGVisualDataModel *model)
- : QSGVisualDataModelData(index, model)
- {
- }
-};
-
-class QSGVDMObjectDataMetaObject : public QSGVisualDataModelDataMetaObject
-{
-public:
- QSGVDMObjectDataMetaObject(QSGVisualDataModelData *data, VDMDelegateDataType *type)
- : QSGVisualDataModelDataMetaObject(data, type)
- , m_object(QSGVisualDataModelPrivate::get(data->m_model)->m_listAccessor->at(data->m_index).value<QObject *>())
- {}
-
- int metaCall(QMetaObject::Call call, int id, void **arguments)
- {
- if (id >= m_type->propertyOffset
- && (call == QMetaObject::ReadProperty
- || call == QMetaObject::WriteProperty
- || call == QMetaObject::ResetProperty)) {
- if (m_object)
- QMetaObject::metacall(m_object, call, id - m_type->propertyOffset + 1, arguments);
- return -1;
- } else if (id >= m_type->signalOffset && call == QMetaObject::InvokeMetaMethod) {
- QMetaObject::activate(m_data, this, id, 0);
- return -1;
- } else {
- return m_data->qt_metacall(call, id, arguments);
- }
- }
-
- int createProperty(const char *name, const char *)
- {
- if (!m_object)
- return -1;
- const QMetaObject *metaObject = m_object->metaObject();
-
- const int previousPropertyCount = propertyCount() - propertyOffset();
- int propertyIndex = metaObject->indexOfProperty(name);
- if (propertyIndex == -1)
- return -1;
- if (previousPropertyCount + 1 == metaObject->propertyCount())
- return propertyIndex + m_type->propertyOffset - 1;
-
- if (m_type->shared) {
- VDMDelegateDataType *type = m_type;
- m_type = new VDMDelegateDataType(*m_type);
- type->release();
- }
-
- const int previousMethodCount = methodCount();
- int notifierId = previousMethodCount;
- for (int propertyId = previousPropertyCount; propertyId < metaObject->propertyCount() - 1; ++propertyId) {
- QMetaProperty property = metaObject->property(propertyId + 1);
- QMetaPropertyBuilder propertyBuilder;
- if (property.hasNotifySignal()) {
- m_type->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
- propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName(), notifierId);
- ++notifierId;
- } else {
- propertyBuilder = m_type->builder.addProperty(property.name(), property.typeName());
- }
- propertyBuilder.setWritable(property.isWritable());
- propertyBuilder.setResettable(property.isResettable());
- propertyBuilder.setConstant(property.isConstant());
- }
-
- if (m_type->metaObject)
- qFree(m_type->metaObject);
- m_type->metaObject = m_type->builder.toMetaObject();
- *static_cast<QMetaObject *>(this) = *m_type->metaObject;
-
- notifierId = previousMethodCount;
- for (int i = previousPropertyCount; i < metaObject->propertyCount(); ++i) {
- QMetaProperty property = metaObject->property(i);
- if (property.hasNotifySignal()) {
- QDeclarativePropertyPrivate::connect(
- m_object, property.notifySignalIndex(), m_data, notifierId);
- ++notifierId;
- }
- }
- return propertyIndex + m_type->propertyOffset - 1;
- }
-
- QDeclarativeGuard<QObject> m_object;
-};
-
-class QSGVDMObjectData : public QSGVisualDataModelData
-{
- Q_OBJECT
- Q_PROPERTY(QObject *modelData READ modelData CONSTANT)
-public:
- QObject *modelData() const { return m_metaObject->m_object; }
-
- static QSGVisualDataModelData *create(int index, QSGVisualDataModel *model) {
- return new QSGVDMObjectData(index, model); }
-
-private:
- QSGVDMObjectData(int index, QSGVisualDataModel *model)
- : QSGVisualDataModelData(index, model)
- , m_metaObject(new QSGVDMObjectDataMetaObject(this, QSGVisualDataModelPrivate::get(m_model)->m_delegateDataType))
- {
- }
-
- QSGVDMObjectDataMetaObject *m_metaObject;
-};
-
-void QSGVisualDataModelPrivate::addProperty(
- int role, int propertyId, const char *propertyName, const char *propertyType, bool isModelData)
-{
- PropertyData propertyData;
- propertyData.role = role;
- propertyData.isModelData = isModelData;
- m_delegateDataType->builder.addSignal("__" + QByteArray::number(propertyId) + "()");
- QMetaPropertyBuilder property = m_delegateDataType->builder.addProperty(
- propertyName, propertyType, propertyId);
- property.setWritable(false);
-
- m_propertyData.append(propertyData);
-}
-
-QSGVisualDataModelData *QSGVisualDataModelPrivate::createMetaObject(int index, QSGVisualDataModel *model)
-{
- Q_ASSERT(!m_delegateDataType);
-
- m_objectList = false;
- m_propertyData.clear();
- if (m_listAccessor
- && m_listAccessor->type() != QDeclarativeListAccessor::ListProperty
- && m_listAccessor->type() != QDeclarativeListAccessor::Instance) {
- createModelData = &QSGVDMListAccessorData::create;
- return QSGVDMListAccessorData::create(index, model);
- }
-
- m_delegateDataType = new VDMDelegateDataType;
- if (m_listModelInterface) {
- setModelDataType<QSGVDMListModelInterfaceData>();
- QList<int> roles = m_listModelInterface->roles();
- for (int propertyId = 0; propertyId < roles.count(); ++propertyId) {
- const int role = roles.at(propertyId);
- const QByteArray propertyName = m_listModelInterface->toString(role).toUtf8();
- addProperty(role, propertyId, propertyName, "QVariant");
- m_roleNames.insert(propertyName, role);
- }
- if (m_propertyData.count() == 1)
- addProperty(roles.first(), 1, "modelData", "QVariant", true);
- } else if (m_abstractItemModel) {
- setModelDataType<QSGVDMAbstractItemModelData>();
- QHash<int, QByteArray> roleNames = m_abstractItemModel->roleNames();
- for (QHash<int, QByteArray>::const_iterator it = roleNames.begin(); it != roleNames.end(); ++it) {
- addProperty(it.key(), m_propertyData.count(), it.value(), "QVariant");
- m_roleNames.insert(it.value(), it.key());
- }
- if (m_propertyData.count() == 1)
- addProperty(roleNames.begin().key(), 1, "modelData", "QVariant", true);
- } else if (m_listAccessor) {
- setModelDataType<QSGVDMObjectData>();
- m_objectList = true;
- } else {
- Q_ASSERT(!"No model set on VisualDataModel");
- return 0;
- }
- m_delegateDataType->metaObject = m_delegateDataType->builder.toMetaObject();
- if (!m_objectList) {
- m_delegateDataType->propertyCache = new QDeclarativePropertyCache(
- m_context ? m_context->engine() : qmlEngine(q_func()), m_delegateDataType->metaObject);
- }
- return createModelData(index, model);
-}
-
-QSGVisualDataModelData::QSGVisualDataModelData(int index, QSGVisualDataModel *model)
- : m_index(index)
- , m_model(model)
-{
-}
-
-QSGVisualDataModelData::~QSGVisualDataModelData()
-{
-}
-
-int QSGVisualDataModelData::index() const
-{
- return m_index;
-}
-
-// This is internal only - it should not be set from qml
-void QSGVisualDataModelData::setIndex(int index)
-{
- m_index = index;
- emit indexChanged();
-}
-
-//---------------------------------------------------------------------------
-
-class QSGVisualDataModelPartsMetaObject : public QDeclarativeOpenMetaObject
-{
-public:
- QSGVisualDataModelPartsMetaObject(QObject *parent)
- : QDeclarativeOpenMetaObject(parent) {}
-
- virtual void propertyCreated(int, QMetaPropertyBuilder &);
- virtual QVariant initialValue(int);
-};
-
-class QSGVisualDataModelParts : public QObject
-{
-Q_OBJECT
-public:
- QSGVisualDataModelParts(QSGVisualDataModel *parent);
-
-private:
- friend class QSGVisualDataModelPartsMetaObject;
- QSGVisualDataModel *model;
-};
-
-void QSGVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
-{
- prop.setWritable(false);
-}
-
-QVariant QSGVisualDataModelPartsMetaObject::initialValue(int id)
-{
- QSGVisualDataModel *m = new QSGVisualDataModel;
- m->setParent(object());
- m->setPart(QString::fromUtf8(name(id)));
- m->setModel(QVariant::fromValue(static_cast<QSGVisualDataModelParts *>(object())->model));
-
- QVariant var = QVariant::fromValue((QObject *)m);
- return var;
-}
-
-QSGVisualDataModelParts::QSGVisualDataModelParts(QSGVisualDataModel *parent)
-: QObject(parent), model(parent)
-{
- new QSGVisualDataModelPartsMetaObject(this);
-}
-
-QSGVisualDataModelPrivate::QSGVisualDataModelPrivate(QDeclarativeContext *ctxt)
-: m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
-, m_context(ctxt), m_parts(0), m_delegateDataType(0), createModelData(&initializeModelData)
-, m_delegateValidated(false), m_completePending(false), m_objectList(false), m_listAccessor(0)
-{
-}
-
-QSGVisualDataModelData *QSGVisualDataModelPrivate::data(QObject *item)
-{
- QSGVisualDataModelData *dataItem =
- item->findChild<QSGVisualDataModelData *>();
- Q_ASSERT(dataItem);
- return dataItem;
-}
-
-//---------------------------------------------------------------------------
-
-/*!
- \qmlclass VisualDataModel QSGVisualDataModel
- \inqmlmodule QtQuick 2
- \ingroup qml-working-with-data
- \brief The VisualDataModel encapsulates a model and delegate
-
- A VisualDataModel encapsulates a model and the delegate that will
- be instantiated for items in the model.
-
- It is usually not necessary to create VisualDataModel elements.
- However, it can be useful for manipulating and accessing the \l modelIndex
- when a QAbstractItemModel subclass is used as the
- model. Also, VisualDataModel is used together with \l Package to
- provide delegates to multiple views.
-
- The example below illustrates using a VisualDataModel with a ListView.
-
- \snippet doc/src/snippets/declarative/visualdatamodel.qml 0
-*/
-
-QSGVisualDataModel::QSGVisualDataModel()
-: QSGVisualModel(*(new QSGVisualDataModelPrivate(0)))
-{
-}
-
-QSGVisualDataModel::QSGVisualDataModel(QDeclarativeContext *ctxt, QObject *parent)
-: QSGVisualModel(*(new QSGVisualDataModelPrivate(ctxt)), parent)
-{
-}
-
-QSGVisualDataModel::~QSGVisualDataModel()
-{
- Q_D(QSGVisualDataModel);
- if (d->m_listAccessor)
- delete d->m_listAccessor;
- if (d->m_delegateDataType)
- d->m_delegateDataType->release();
-}
-
-/*!
- \qmlproperty model QtQuick2::VisualDataModel::model
- This property holds the model providing data for the VisualDataModel.
-
- The model provides a set of data that is used to create the items
- for a view. For large or dynamic datasets the model is usually
- provided by a C++ model object. The C++ model object must be a \l
- {QAbstractItemModel} subclass or a simple list.
-
- Models can also be created directly in QML, using a \l{ListModel} or
- \l{XmlListModel}.
-
- \sa {qmlmodels}{Data Models}
-*/
-QVariant QSGVisualDataModel::model() const
-{
- Q_D(const QSGVisualDataModel);
- return d->m_modelVariant;
-}
-
-void QSGVisualDataModel::setModel(const QVariant &model)
-{
- Q_D(QSGVisualDataModel);
- delete d->m_listAccessor;
- d->m_listAccessor = 0;
- d->m_modelVariant = model;
- if (d->m_listModelInterface) {
- // Assume caller has released all items.
- QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
- this, SLOT(_q_itemsChanged(int,int,QList<int>)));
- QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
- this, SLOT(_q_itemsInserted(int,int)));
- QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
- this, SLOT(_q_itemsRemoved(int,int)));
- QObject::disconnect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
- this, SLOT(_q_itemsMoved(int,int,int)));
- d->m_listModelInterface = 0;
- } else if (d->m_abstractItemModel) {
- QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::disconnect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
- QObject::disconnect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
- d->m_abstractItemModel = 0;
- } else if (d->m_visualItemModel) {
- QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
- this, SIGNAL(itemsInserted(int,int)));
- QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
- this, SIGNAL(itemsRemoved(int,int)));
- QObject::disconnect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
- this, SIGNAL(itemsMoved(int,int,int)));
- QObject::disconnect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarativePackage*)),
- this, SLOT(_q_createdPackage(int,QDeclarativePackage*)));
- QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarativePackage*)),
- this, SLOT(_q_destroyingPackage(QDeclarativePackage*)));
- d->m_visualItemModel = 0;
- }
-
- d->m_roles.clear();
- d->m_roleNames.clear();
- if (d->m_delegateDataType)
- d->m_delegateDataType->release();
- d->m_delegateDataType = 0;
- d->createModelData = &QSGVisualDataModelPrivate::initializeModelData;
-
- QObject *object = qvariant_cast<QObject *>(model);
- if (object && (d->m_listModelInterface = qobject_cast<QListModelInterface *>(object))) {
- QObject::connect(d->m_listModelInterface, SIGNAL(itemsChanged(int,int,QList<int>)),
- this, SLOT(_q_itemsChanged(int,int,QList<int>)));
- QObject::connect(d->m_listModelInterface, SIGNAL(itemsInserted(int,int)),
- this, SLOT(_q_itemsInserted(int,int)));
- QObject::connect(d->m_listModelInterface, SIGNAL(itemsRemoved(int,int)),
- this, SLOT(_q_itemsRemoved(int,int)));
- QObject::connect(d->m_listModelInterface, SIGNAL(itemsMoved(int,int,int)),
- this, SLOT(_q_itemsMoved(int,int,int)));
- if (d->m_delegate && d->m_listModelInterface->count())
- emit itemsInserted(0, d->m_listModelInterface->count());
- return;
- } else if (object && (d->m_abstractItemModel = qobject_cast<QAbstractItemModel *>(object))) {
- QObject::connect(d->m_abstractItemModel, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(_q_rowsInserted(QModelIndex,int,int)));
- QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_rowsRemoved(QModelIndex,int,int)));
- QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- QObject::connect(d->m_abstractItemModel, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
- this, SLOT(_q_rowsMoved(QModelIndex,int,int,QModelIndex,int)));
- QObject::connect(d->m_abstractItemModel, SIGNAL(modelReset()), this, SLOT(_q_modelReset()));
- QObject::connect(d->m_abstractItemModel, SIGNAL(layoutChanged()), this, SLOT(_q_layoutChanged()));
- if (d->m_abstractItemModel->canFetchMore(d->m_root))
- d->m_abstractItemModel->fetchMore(d->m_root);
- return;
- }
- if ((d->m_visualItemModel = qvariant_cast<QSGVisualDataModel *>(model))) {
- QObject::connect(d->m_visualItemModel, SIGNAL(countChanged()),
- this, SIGNAL(countChanged()));
- QObject::connect(d->m_visualItemModel, SIGNAL(itemsInserted(int,int)),
- this, SIGNAL(itemsInserted(int,int)));
- QObject::connect(d->m_visualItemModel, SIGNAL(itemsRemoved(int,int)),
- this, SIGNAL(itemsRemoved(int,int)));
- QObject::connect(d->m_visualItemModel, SIGNAL(itemsMoved(int,int,int)),
- this, SIGNAL(itemsMoved(int,int,int)));
- QObject::connect(d->m_visualItemModel, SIGNAL(createdPackage(int,QDeclarativePackage*)),
- this, SLOT(_q_createdPackage(int,QDeclarativePackage*)));
- QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QDeclarativePackage*)),
- this, SLOT(_q_destroyingPackage(QDeclarativePackage*)));
- return;
- }
- d->m_listAccessor = new QDeclarativeListAccessor;
- d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this));
- if (d->m_listAccessor->type() != QDeclarativeListAccessor::ListProperty)
- if (d->m_delegate && d->modelCount()) {
- emit itemsInserted(0, d->modelCount());
- emit countChanged();
- }
-}
-
-/*!
- \qmlproperty Component QtQuick2::VisualDataModel::delegate
-
- The delegate provides a template defining each item instantiated by a view.
- The index is exposed as an accessible \c index property. Properties of the
- model are also available depending upon the type of \l {qmlmodels}{Data Model}.
-*/
-QDeclarativeComponent *QSGVisualDataModel::delegate() const
-{
- Q_D(const QSGVisualDataModel);
- if (d->m_visualItemModel)
- return d->m_visualItemModel->delegate();
- return d->m_delegate;
-}
-
-void QSGVisualDataModel::setDelegate(QDeclarativeComponent *delegate)
-{
- Q_D(QSGVisualDataModel);
- bool wasValid = d->m_delegate != 0;
- d->m_delegate = delegate;
- d->m_delegateValidated = false;
- if (!wasValid && d->modelCount() && d->m_delegate) {
- emit itemsInserted(0, d->modelCount());
- emit countChanged();
- }
- if (wasValid && !d->m_delegate && d->modelCount()) {
- _q_itemsRemoved(0, d->modelCount());
- emit countChanged();
- }
-}
-
-/*!
- \qmlproperty QModelIndex QtQuick2::VisualDataModel::rootIndex
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. \c rootIndex allows the children of
- any node in a QAbstractItemModel to be provided by this model.
-
- This property only affects models of type QAbstractItemModel that
- are hierarchical (e.g, a tree model).
-
- For example, here is a simple interactive file system browser.
- When a directory name is clicked, the view's \c rootIndex is set to the
- QModelIndex node of the clicked directory, thus updating the view to show
- the new directory's contents.
-
- \c main.cpp:
- \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/main.cpp 0
-
- \c view.qml:
- \snippet doc/src/snippets/declarative/visualdatamodel_rootindex/view.qml 0
-
- If the \l model is a QAbstractItemModel subclass, the delegate can also
- reference a \c hasModelChildren property (optionally qualified by a
- \e model. prefix) that indicates whether the delegate's model item has
- any child nodes.
-
-
- \sa modelIndex(), parentModelIndex()
-*/
-QVariant QSGVisualDataModel::rootIndex() const
-{
- Q_D(const QSGVisualDataModel);
- return QVariant::fromValue(d->m_root);
-}
-
-void QSGVisualDataModel::setRootIndex(const QVariant &root)
-{
- Q_D(QSGVisualDataModel);
- QModelIndex modelIndex = qvariant_cast<QModelIndex>(root);
- if (d->m_root != modelIndex) {
- int oldCount = d->modelCount();
- d->m_root = modelIndex;
- if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(modelIndex))
- d->m_abstractItemModel->fetchMore(modelIndex);
- int newCount = d->modelCount();
- if (d->m_delegate && oldCount)
- _q_itemsRemoved(0, oldCount);
- if (d->m_delegate && newCount)
- emit itemsInserted(0, newCount);
- if (newCount != oldCount)
- emit countChanged();
- emit rootIndexChanged();
- }
-}
-
-/*!
- \qmlmethod QModelIndex QtQuick2::VisualDataModel::modelIndex(int index)
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. This function assists in using
- tree models in QML.
-
- Returns a QModelIndex for the specified index.
- This value can be assigned to rootIndex.
-
- \sa rootIndex
-*/
-QVariant QSGVisualDataModel::modelIndex(int idx) const
-{
- Q_D(const QSGVisualDataModel);
- if (d->m_abstractItemModel)
- return QVariant::fromValue(d->m_abstractItemModel->index(idx, 0, d->m_root));
- return QVariant::fromValue(QModelIndex());
-}
-
-/*!
- \qmlmethod QModelIndex QtQuick2::VisualDataModel::parentModelIndex()
-
- QAbstractItemModel provides a hierarchical tree of data, whereas
- QML only operates on list data. This function assists in using
- tree models in QML.
-
- Returns a QModelIndex for the parent of the current rootIndex.
- This value can be assigned to rootIndex.
-
- \sa rootIndex
-*/
-QVariant QSGVisualDataModel::parentModelIndex() const
-{
- Q_D(const QSGVisualDataModel);
- if (d->m_abstractItemModel)
- return QVariant::fromValue(d->m_abstractItemModel->parent(d->m_root));
- return QVariant::fromValue(QModelIndex());
-}
-
-/*!
- \qmlproperty object QtQuick2::VisualDataModel::parts
-
- The \a parts property selects a VisualDataModel which creates
- delegates from the part named. This is used in conjunction with
- the \l Package element.
-
- For example, the code below selects a model which creates
- delegates named \e list from a \l Package:
-
- \code
- VisualDataModel {
- id: visualModel
- delegate: Package {
- Item { Package.name: "list" }
- }
- model: myModel
- }
-
- ListView {
- width: 200; height:200
- model: visualModel.parts.list
- }
- \endcode
-
- \sa Package
-*/
-QString QSGVisualDataModel::part() const
-{
- Q_D(const QSGVisualDataModel);
- return d->m_part;
-}
-
-void QSGVisualDataModel::setPart(const QString &part)
-{
- Q_D(QSGVisualDataModel);
- d->m_part = part;
-}
-
-int QSGVisualDataModel::count() const
-{
- Q_D(const QSGVisualDataModel);
- if (d->m_visualItemModel)
- return d->m_visualItemModel->count();
- if (!d->m_delegate)
- return 0;
- return d->modelCount();
-}
-
-QSGItem *QSGVisualDataModel::item(int index, bool complete)
-{
- Q_D(QSGVisualDataModel);
- if (d->m_visualItemModel)
- return d->m_visualItemModel->item(index, d->m_part.toUtf8(), complete);
- return item(index, QByteArray(), complete);
-}
-
-/*
- Returns ReleaseStatus flags.
-*/
-QSGVisualDataModel::ReleaseFlags QSGVisualDataModel::release(QSGItem *item)
-{
- Q_D(QSGVisualDataModel);
- if (d->m_visualItemModel)
- return d->m_visualItemModel->release(item);
-
- ReleaseFlags stat = 0;
- QObject *obj = item;
- bool inPackage = false;
-
- QHash<QObject*,QDeclarativePackage*>::iterator it = d->m_packaged.find(item);
- if (it != d->m_packaged.end()) {
- QDeclarativePackage *package = *it;
- d->m_packaged.erase(it);
- if (d->m_packaged.contains(item))
- stat |= Referenced;
- inPackage = true;
- obj = package; // fall through and delete
- }
-
- if (d->m_cache.releaseItem(obj)) {
- // Remove any bindings to avoid warnings due to parent change.
- QObjectPrivate *p = QObjectPrivate::get(obj);
- Q_ASSERT(p->declarativeData);
- QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
- if (d->ownContext && d->context)
- d->context->clearContext();
-
- if (inPackage) {
- emit destroyingPackage(qobject_cast<QDeclarativePackage*>(obj));
- } else {
- // XXX todo - the original did item->scene()->removeItem(). Why?
- item->setParentItem(0);
- }
- stat |= Destroyed;
- obj->deleteLater();
- } else if (!inPackage) {
- stat |= Referenced;
- }
-
- return stat;
-}
-
-QObject *QSGVisualDataModel::parts()
-{
- Q_D(QSGVisualDataModel);
- if (!d->m_parts)
- d->m_parts = new QSGVisualDataModelParts(this);
- return d->m_parts;
-}
-
-QSGItem *QSGVisualDataModel::item(int index, const QByteArray &viewId, bool complete)
-{
- Q_D(QSGVisualDataModel);
- if (d->m_visualItemModel)
- return d->m_visualItemModel->item(index, viewId, complete);
-
- if (d->modelCount() <= 0 || !d->m_delegate)
- return 0;
- QObject *nobj = d->m_cache.getItem(index);
- bool needComplete = false;
- if (!nobj) {
- QDeclarativeContext *ccontext = d->m_context;
- if (!ccontext) ccontext = qmlContext(this);
- QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
- if (d->m_objectList) {
- ctxt->setContextObject(d->m_listAccessor->at(index).value<QObject *>());
- ctxt = new QDeclarativeContext(ctxt);
- }
- QSGVisualDataModelData *data = d->createModelData(index, this);
- ctxt->setContextProperty(QLatin1String("model"), data);
- ctxt->setContextObject(data);
- d->m_completePending = false;
- nobj = d->m_delegate->beginCreate(ctxt);
- if (complete) {
- d->m_delegate->completeCreate();
- } else {
- d->m_completePending = true;
- needComplete = true;
- }
- if (nobj) {
- QDeclarative_setParent_noEvent(ctxt, nobj);
- QDeclarative_setParent_noEvent(data, nobj);
- d->m_cache.insertItem(index, nobj);
- if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj))
- emit createdPackage(index, package);
- } else {
- delete data;
- delete ctxt;
- qmlInfo(this, d->m_delegate->errors()) << "Error creating delegate";
- }
- }
- QSGItem *item = qobject_cast<QSGItem *>(nobj);
- if (!item) {
- QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj);
- if (package) {
- QObject *o = package->part(QString::fromUtf8(viewId));
- item = qobject_cast<QSGItem *>(o);
- if (item)
- d->m_packaged.insertMulti(item, package);
- }
- }
- if (!item) {
- if (needComplete)
- d->m_delegate->completeCreate();
- d->m_cache.releaseItem(nobj);
- if (!d->m_delegateValidated) {
- qmlInfo(d->m_delegate) << QSGVisualDataModel::tr("Delegate component must be Item type.");
- d->m_delegateValidated = true;
- }
- }
- if (d->modelCount()-1 == index && d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
- d->m_abstractItemModel->fetchMore(d->m_root);
-
- return item;
-}
-
-bool QSGVisualDataModel::completePending() const
-{
- Q_D(const QSGVisualDataModel);
- if (d->m_visualItemModel)
- return d->m_visualItemModel->completePending();
- return d->m_completePending;
-}
-
-void QSGVisualDataModel::completeItem()
-{
- Q_D(QSGVisualDataModel);
- if (d->m_visualItemModel) {
- d->m_visualItemModel->completeItem();
- return;
- }
-
- d->m_delegate->completeCreate();
- d->m_completePending = false;
-}
-
-QString QSGVisualDataModel::stringValue(int index, const QString &name)
-{
- Q_D(QSGVisualDataModel);
- if (d->m_visualItemModel)
- return d->m_visualItemModel->stringValue(index, name);
-
- if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor) {
- if (QObject *object = d->m_listAccessor->at(index).value<QObject*>())
- return object->property(name.toUtf8()).toString();
- }
-
- if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
- return QString();
-
- QString val;
- QObject *data = 0;
- bool tempData = false;
-
- if (QObject *nobj = d->m_cache.item(index))
- data = d->data(nobj);
- if (!data) {
- data = d->createModelData(index, this);
- tempData = true;
- }
-
- QDeclarativeData *ddata = QDeclarativeData::get(data);
- if (ddata && ddata->propertyCache) {
- QDeclarativePropertyCache::Data *prop = ddata->propertyCache->property(name);
- if (prop) {
- if (prop->propType == QVariant::String) {
- void *args[] = { &val, 0 };
- QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
- } else if (prop->propType == qMetaTypeId<QVariant>()) {
- QVariant v;
- void *args[] = { &v, 0 };
- QMetaObject::metacall(data, QMetaObject::ReadProperty, prop->coreIndex, args);
- val = v.toString();
- }
- } else {
- val = data->property(name.toUtf8()).toString();
- }
- } else {
- val = data->property(name.toUtf8()).toString();
- }
-
- if (tempData)
- delete data;
-
- return val;
-}
-
-int QSGVisualDataModel::indexOf(QSGItem *item, QObject *) const
-{
- QVariant val = QDeclarativeEngine::contextForObject(item)->contextProperty(QLatin1String("index"));
- return val.toInt();
- return -1;
-}
-
-void QSGVisualDataModel::setWatchedRoles(QList<QByteArray> roles)
-{
- Q_D(QSGVisualDataModel);
- d->watchedRoles = roles;
- d->watchedRoleIds.clear();
-}
-
-void QSGVisualDataModel::_q_itemsChanged(int index, int count,
- const QList<int> &roles)
-{
- Q_D(QSGVisualDataModel);
- bool changed = false;
- if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) {
- foreach (QByteArray r, d->watchedRoles) {
- if (d->m_roleNames.contains(r))
- d->watchedRoleIds << d->m_roleNames.value(r);
- }
- }
-
- QVector<int> signalIndexes;
- for (int i = 0; i < roles.count(); ++i) {
- const int role = roles.at(i);
- if (!changed && d->watchedRoleIds.contains(role))
- changed = true;
- for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId) {
- if (d->m_propertyData.at(propertyId).role == role)
- signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
- }
- }
- if (roles.isEmpty()) {
- for (int propertyId = 0; propertyId < d->m_propertyData.count(); ++propertyId)
- signalIndexes.append(propertyId + d->m_delegateDataType->signalOffset);
- }
-
- for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::ConstIterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ++iter) {
- const int idx = iter.key();
-
- if (idx >= index && idx < index+count) {
- QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
- QSGVisualDataModelData *data = d->data(objRef.obj);
- for (int i = 0; i < signalIndexes.count(); ++i)
- QMetaObject::activate(data, signalIndexes.at(i), 0);
- }
- }
- if (changed)
- emit itemsChanged(index, count);
-}
-
-void QSGVisualDataModel::_q_itemsInserted(int index, int count)
-{
- Q_D(QSGVisualDataModel);
- if (!count)
- return;
- // XXX - highly inefficient
- QHash<int,QSGVisualDataModelPrivate::ObjectRef> items;
- for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ) {
-
- if (iter.key() >= index) {
- QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
- int index = iter.key() + count;
- iter = d->m_cache.erase(iter);
-
- items.insert(index, objRef);
-
- QSGVisualDataModelData *data = d->data(objRef.obj);
- data->setIndex(index);
- } else {
- ++iter;
- }
- }
- d->m_cache.unite(items);
-
- emit itemsInserted(index, count);
- emit countChanged();
-}
-
-void QSGVisualDataModel::_q_itemsRemoved(int index, int count)
-{
- Q_D(QSGVisualDataModel);
- if (!count)
- return;
- // XXX - highly inefficient
- QHash<int, QSGVisualDataModelPrivate::ObjectRef> items;
- for (QHash<int, QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ) {
- if (iter.key() >= index && iter.key() < index + count) {
- QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
- iter = d->m_cache.erase(iter);
- items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
- QSGVisualDataModelData *data = d->data(objRef.obj);
- data->setIndex(-1);
- } else if (iter.key() >= index + count) {
- QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
- int index = iter.key() - count;
- iter = d->m_cache.erase(iter);
- items.insert(index, objRef);
- QSGVisualDataModelData *data = d->data(objRef.obj);
- data->setIndex(index);
- } else {
- ++iter;
- }
- }
-
- d->m_cache.unite(items);
- emit itemsRemoved(index, count);
- emit countChanged();
-}
-
-void QSGVisualDataModel::_q_itemsMoved(int from, int to, int count)
-{
- Q_D(QSGVisualDataModel);
- // XXX - highly inefficient
- QHash<int,QSGVisualDataModelPrivate::ObjectRef> items;
- for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ) {
-
- if (iter.key() >= from && iter.key() < from + count) {
- QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
- int index = iter.key() - from + to;
- iter = d->m_cache.erase(iter);
-
- items.insert(index, objRef);
-
- QSGVisualDataModelData *data = d->data(objRef.obj);
- data->setIndex(index);
- } else {
- ++iter;
- }
- }
- for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ) {
-
- int diff = from > to ? count : -count;
- if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) {
- QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
- int index = iter.key() + diff;
- iter = d->m_cache.erase(iter);
-
- items.insert(index, objRef);
-
- QSGVisualDataModelData *data = d->data(objRef.obj);
- data->setIndex(index);
- } else {
- ++iter;
- }
- }
- d->m_cache.unite(items);
-
- emit itemsMoved(from, to, count);
-}
-
-void QSGVisualDataModel::_q_rowsInserted(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QSGVisualDataModel);
- if (parent == d->m_root)
- _q_itemsInserted(begin, end - begin + 1);
-}
-
-void QSGVisualDataModel::_q_rowsRemoved(const QModelIndex &parent, int begin, int end)
-{
- Q_D(QSGVisualDataModel);
- if (parent == d->m_root)
- _q_itemsRemoved(begin, end - begin + 1);
-}
-
-void QSGVisualDataModel::_q_rowsMoved(const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow)
-{
- Q_D(QSGVisualDataModel);
- const int count = sourceEnd - sourceStart + 1;
- if (destinationParent == d->m_root && sourceParent == d->m_root) {
- _q_itemsMoved(sourceStart, sourceStart > destinationRow ? destinationRow : destinationRow-count, count);
- } else if (sourceParent == d->m_root) {
- _q_itemsRemoved(sourceStart, count);
- } else if (destinationParent == d->m_root) {
- _q_itemsInserted(destinationRow, count);
- }
-}
-
-void QSGVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
-{
- Q_D(QSGVisualDataModel);
- if (begin.parent() == d->m_root)
- _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
-}
-
-void QSGVisualDataModel::_q_layoutChanged()
-{
- Q_D(QSGVisualDataModel);
- _q_itemsChanged(0, count(), d->m_roles);
-}
-
-void QSGVisualDataModel::_q_modelReset()
-{
- Q_D(QSGVisualDataModel);
- d->m_root = QModelIndex();
- emit modelReset();
- emit rootIndexChanged();
- if (d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
- d->m_abstractItemModel->fetchMore(d->m_root);
-}
-
-void QSGVisualDataModel::_q_createdPackage(int index, QDeclarativePackage *package)
-{
- Q_D(QSGVisualDataModel);
- emit createdItem(index, qobject_cast<QSGItem*>(package->part(d->m_part)));
-}
-
-void QSGVisualDataModel::_q_destroyingPackage(QDeclarativePackage *package)
-{
- Q_D(QSGVisualDataModel);
- emit destroyingItem(qobject_cast<QSGItem*>(package->part(d->m_part)));
-}
-
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QListModelInterface)
-
-#include <qsgvisualitemmodel.moc>
diff --git a/src/declarative/items/qsgvisualitemmodel_p.h b/src/declarative/items/qsgvisualitemmodel_p.h
index 9acaab63ed..2eeff3c9c2 100644
--- a/src/declarative/items/qsgvisualitemmodel_p.h
+++ b/src/declarative/items/qsgvisualitemmodel_p.h
@@ -45,20 +45,14 @@
#include <QtDeclarative/qdeclarative.h>
#include <QtCore/qobject.h>
-#include <QtCore/qabstractitemmodel.h>
QT_BEGIN_HEADER
-Q_DECLARE_METATYPE(QModelIndex)
-
QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QSGItem;
-class QDeclarativeComponent;
-class QDeclarativePackage;
-class QSGVisualDataModelPrivate;
class Q_DECLARATIVE_EXPORT QSGVisualModel : public QObject
{
@@ -137,75 +131,6 @@ private:
Q_DISABLE_COPY(QSGVisualItemModel)
};
-
-class Q_DECLARATIVE_EXPORT QSGVisualDataModel : public QSGVisualModel
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QSGVisualDataModel)
-
- Q_PROPERTY(QVariant model READ model WRITE setModel)
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate)
- Q_PROPERTY(QString part READ part WRITE setPart)
- Q_PROPERTY(QObject *parts READ parts CONSTANT)
- Q_PROPERTY(QVariant rootIndex READ rootIndex WRITE setRootIndex NOTIFY rootIndexChanged)
- Q_CLASSINFO("DefaultProperty", "delegate")
-public:
- QSGVisualDataModel();
- QSGVisualDataModel(QDeclarativeContext *, QObject *parent=0);
- virtual ~QSGVisualDataModel();
-
- QVariant model() const;
- void setModel(const QVariant &);
-
- QDeclarativeComponent *delegate() const;
- void setDelegate(QDeclarativeComponent *);
-
- QVariant rootIndex() const;
- void setRootIndex(const QVariant &root);
-
- Q_INVOKABLE QVariant modelIndex(int idx) const;
- Q_INVOKABLE QVariant parentModelIndex() const;
-
- QString part() const;
- void setPart(const QString &);
-
- int count() const;
- bool isValid() const { return delegate() != 0; }
- QSGItem *item(int index, bool complete=true);
- QSGItem *item(int index, const QByteArray &, bool complete=true);
- ReleaseFlags release(QSGItem *item);
- bool completePending() const;
- void completeItem();
- virtual QString stringValue(int index, const QString &role);
- virtual void setWatchedRoles(QList<QByteArray> roles);
-
- int indexOf(QSGItem *item, QObject *objectContext) const;
-
- QObject *parts();
-
-Q_SIGNALS:
- void createdPackage(int index, QDeclarativePackage *package);
- void destroyingPackage(QDeclarativePackage *package);
- void rootIndexChanged();
-
-private Q_SLOTS:
- void _q_itemsChanged(int, int, const QList<int> &);
- void _q_itemsInserted(int index, int count);
- void _q_itemsRemoved(int index, int count);
- void _q_itemsMoved(int from, int to, int count);
- void _q_rowsInserted(const QModelIndex &,int,int);
- void _q_rowsRemoved(const QModelIndex &,int,int);
- void _q_rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int);
- void _q_dataChanged(const QModelIndex&,const QModelIndex&);
- void _q_layoutChanged();
- void _q_modelReset();
- void _q_createdPackage(int index, QDeclarativePackage *package);
- void _q_destroyingPackage(QDeclarativePackage *package);
-
-private:
- Q_DISABLE_COPY(QSGVisualDataModel)
-};
-
class QSGVisualItemModelAttached : public QObject
{
Q_OBJECT
@@ -250,7 +175,6 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QSGVisualModel)
QML_DECLARE_TYPE(QSGVisualItemModel)
QML_DECLARE_TYPEINFO(QSGVisualItemModel, QML_HAS_ATTACHED_PROPERTIES)
-QML_DECLARE_TYPE(QSGVisualDataModel)
QT_END_HEADER
diff --git a/tests/auto/declarative/qsgvisualdatamodel/data/visualdatamodel.qml b/tests/auto/declarative/qsgvisualdatamodel/data/visualdatamodel.qml
index 0bb5cd13e0..0d4d9e2e46 100644
--- a/tests/auto/declarative/qsgvisualdatamodel/data/visualdatamodel.qml
+++ b/tests/auto/declarative/qsgvisualdatamodel/data/visualdatamodel.qml
@@ -8,4 +8,5 @@ VisualDataModel {
rootIndex = parentModelIndex();
}
model: myModel
+ delegate: Item {}
}
diff --git a/tests/auto/declarative/qsgvisualdatamodel/tst_qsgvisualdatamodel.cpp b/tests/auto/declarative/qsgvisualdatamodel/tst_qsgvisualdatamodel.cpp
index 61a63147b5..a2e6d95a41 100644
--- a/tests/auto/declarative/qsgvisualdatamodel/tst_qsgvisualdatamodel.cpp
+++ b/tests/auto/declarative/qsgvisualdatamodel/tst_qsgvisualdatamodel.cpp
@@ -49,7 +49,7 @@
#include <QtDeclarative/qsgview.h>
#include <private/qsglistview_p.h>
#include <private/qsgtext_p.h>
-#include <private/qsgvisualitemmodel_p.h>
+#include <private/qsgvisualdatamodel_p.h>
#include <private/qdeclarativevaluetype_p.h>
#include <math.h>
#include <QtOpenGL/QGLShaderProgram>