summaryrefslogtreecommitdiffstats
path: root/src/declarative/fx/qmlgraphicsvisualitemmodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/fx/qmlgraphicsvisualitemmodel.cpp')
-rw-r--r--src/declarative/fx/qmlgraphicsvisualitemmodel.cpp1032
1 files changed, 1032 insertions, 0 deletions
diff --git a/src/declarative/fx/qmlgraphicsvisualitemmodel.cpp b/src/declarative/fx/qmlgraphicsvisualitemmodel.cpp
new file mode 100644
index 0000000..b9b0237
--- /dev/null
+++ b/src/declarative/fx/qmlgraphicsvisualitemmodel.cpp
@@ -0,0 +1,1032 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.0, 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.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlistmodelinterface.h"
+#include "qmlgraphicsitem.h"
+#include <qmlcontext.h>
+#include <qmlexpression.h>
+#include "qmlpackage.h"
+#include "qhash.h"
+#include "qlist.h"
+#include "private/qobject_p.h"
+#include "private/qmetaobjectbuilder_p.h"
+#include "qmlopenmetaobject.h"
+#include "qmllistaccessor.h"
+#include "qmlinfo.h"
+#include "qmlgraphicsvisualitemmodel.h"
+#include "private/qguard_p.h"
+#include <QtCore/qdebug.h>
+
+QML_DECLARE_TYPE(QListModelInterface)
+
+QT_BEGIN_NAMESPACE
+
+class QmlGraphicsVisualItemModelAttached : public QObject
+{
+ Q_OBJECT
+
+public:
+ QmlGraphicsVisualItemModelAttached(QObject *parent)
+ : QObject(parent), m_index(0) {}
+ ~QmlGraphicsVisualItemModelAttached() {
+ attachedProperties.remove(parent());
+ }
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ int index() const { return m_index; }
+ void setIndex(int idx) {
+ if (m_index != idx) {
+ m_index = idx;
+ emit indexChanged();
+ }
+ }
+
+ static QmlGraphicsVisualItemModelAttached *properties(QObject *obj) {
+ QmlGraphicsVisualItemModelAttached *rv = attachedProperties.value(obj);
+ if (!rv) {
+ rv = new QmlGraphicsVisualItemModelAttached(obj);
+ attachedProperties.insert(obj, rv);
+ }
+ return rv;
+ }
+
+Q_SIGNALS:
+ void indexChanged();
+
+public:
+ int m_index;
+
+ static QHash<QObject*, QmlGraphicsVisualItemModelAttached*> attachedProperties;
+};
+
+QHash<QObject*, QmlGraphicsVisualItemModelAttached*> QmlGraphicsVisualItemModelAttached::attachedProperties;
+
+
+class QmlGraphicsVisualItemModelPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QmlGraphicsVisualItemModel)
+public:
+ QmlGraphicsVisualItemModelPrivate() : QObjectPrivate(), children(this) {}
+
+ struct ItemList : public QmlConcreteList<QmlGraphicsItem *>
+ {
+ ItemList(QmlGraphicsVisualItemModelPrivate *m) : QmlConcreteList<QmlGraphicsItem *>(), model(m) {}
+
+ void append(QmlGraphicsItem *item);
+
+ QmlGraphicsVisualItemModelPrivate *model;
+ };
+
+ void itemAppended() {
+ Q_Q(QmlGraphicsVisualItemModel);
+ QmlGraphicsVisualItemModelAttached *attached = QmlGraphicsVisualItemModelAttached::properties(children.last());
+ attached->setIndex(children.count()-1);
+ emit q->itemsInserted(children.count()-1, 1);
+ emit q->countChanged();
+ }
+
+ void emitChildrenChanged() {
+ Q_Q(QmlGraphicsVisualItemModel);
+ emit q->childrenChanged();
+ }
+ ItemList children;
+};
+
+
+/*!
+ \qmlclass VisualItemModel QmlGraphicsVisualItemModel
+ \brief The VisualItemModel allows items to be provided to a view.
+
+ The children of the VisualItemModel are provided in a model which
+ can be used in a view. Note that no delegate should be
+ provided to a view since the VisualItemModel contains the
+ visual delegate (items).
+
+ An item can determine its index within the
+ model via the VisualItemModel.index attached property.
+
+ The example below places three colored rectangles in a ListView.
+ \code
+ Item {
+ VisualItemModel {
+ id: itemModel
+ Rectangle { height: 30; width: 80; color: "red" }
+ Rectangle { height: 30; width: 80; color: "green" }
+ Rectangle { height: 30; width: 80; color: "blue" }
+ }
+
+ ListView {
+ anchors.fill: parent
+ model: itemModel
+ }
+ }
+ \endcode
+*/
+QmlGraphicsVisualItemModel::QmlGraphicsVisualItemModel()
+ : QmlGraphicsVisualModel(*(new QmlGraphicsVisualItemModelPrivate))
+{
+}
+
+QmlList<QmlGraphicsItem *> *QmlGraphicsVisualItemModel::children()
+{
+ Q_D(QmlGraphicsVisualItemModel);
+ return &(d->children);
+}
+
+/*!
+ \qmlproperty int VisualItemModel::count
+
+ The number of items in the model. This property is readonly.
+*/
+int QmlGraphicsVisualItemModel::count() const
+{
+ Q_D(const QmlGraphicsVisualItemModel);
+ return d->children.count();
+}
+
+bool QmlGraphicsVisualItemModel::isValid() const
+{
+ return true;
+}
+
+QmlGraphicsItem *QmlGraphicsVisualItemModel::item(int index, bool)
+{
+ Q_D(QmlGraphicsVisualItemModel);
+ return d->children.at(index);
+}
+
+QmlGraphicsVisualModel::ReleaseFlags QmlGraphicsVisualItemModel::release(QmlGraphicsItem *)
+{
+ // Nothing to do
+ return 0;
+}
+
+void QmlGraphicsVisualItemModel::completeItem()
+{
+ // Nothing to do
+}
+
+QVariant QmlGraphicsVisualItemModel::evaluate(int index, const QString &expression, QObject *objectContext)
+{
+ Q_D(QmlGraphicsVisualItemModel);
+ QmlContext *ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ ctxt->addDefaultObject(d->children.at(index));
+ QmlExpression e(ctxt, expression, objectContext);
+ e.setTrackChange(false);
+ QVariant value = e.value();
+ delete ctxt;
+ return value;
+}
+
+int QmlGraphicsVisualItemModel::indexOf(QmlGraphicsItem *item, QObject *) const
+{
+ Q_D(const QmlGraphicsVisualItemModel);
+ return d->children.indexOf(item);
+}
+
+void QmlGraphicsVisualItemModelPrivate::ItemList::append(QmlGraphicsItem *item)
+{
+ QmlConcreteList<QmlGraphicsItem*>::append(item);
+ item->QObject::setParent(model->q_ptr);
+ model->itemAppended();
+
+ model->emitChildrenChanged();
+}
+
+QmlGraphicsVisualItemModelAttached *QmlGraphicsVisualItemModel::qmlAttachedProperties(QObject *obj)
+{
+ return QmlGraphicsVisualItemModelAttached::properties(obj);
+}
+
+
+class QmlGraphicsVisualDataModelParts;
+class QmlGraphicsVisualDataModelData;
+class QmlGraphicsVisualDataModelPrivate : public QObjectPrivate
+{
+public:
+ QmlGraphicsVisualDataModelPrivate(QmlContext *);
+
+ static QmlGraphicsVisualDataModelPrivate *get(QmlGraphicsVisualDataModel *m) {
+ return static_cast<QmlGraphicsVisualDataModelPrivate *>(QObjectPrivate::get(m));
+ }
+
+ QGuard<QListModelInterface> m_listModelInterface;
+ QGuard<QAbstractItemModel> m_abstractItemModel;
+ QGuard<QmlGraphicsVisualDataModel> m_visualItemModel;
+ QString m_part;
+
+ QmlComponent *m_delegate;
+ QmlContext *m_context;
+ QList<int> m_roles;
+ QHash<QString,int> m_roleNames;
+ void ensureRoles() {
+ if (m_roleNames.isEmpty()) {
+ if (m_listModelInterface) {
+ m_roles = m_listModelInterface->roles();
+ for (int ii = 0; ii < m_roles.count(); ++ii)
+ m_roleNames.insert(m_listModelInterface->toString(m_roles.at(ii)), m_roles.at(ii));
+ if (m_roles.count() == 1)
+ m_roleNames.insert(QLatin1String("modelData"), m_roles.at(0));
+ } else if (m_abstractItemModel) {
+ for (QHash<int,QByteArray>::const_iterator it = m_abstractItemModel->roleNames().begin();
+ it != m_abstractItemModel->roleNames().end(); ++it) {
+ m_roles.append(it.key());
+ m_roleNames.insert(QString::fromUtf8(*it), it.key());
+ }
+ if (m_roles.count() == 1)
+ m_roleNames.insert(QLatin1String("modelData"), m_roles.at(0));
+ } else if (m_listAccessor) {
+ m_roleNames.insert(QLatin1String("modelData"), 0);
+ if (m_listAccessor->type() == QmlListAccessor::Instance) {
+ if (QObject *object = m_listAccessor->at(0).value<QObject*>()) {
+ int count = object->metaObject()->propertyCount();
+ for (int ii = 1; ii < count; ++ii) {
+ const QMetaProperty &prop = object->metaObject()->property(ii);
+ m_roleNames.insert(QString::fromUtf8(prop.name()), 0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ 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 *, QmlPackage*> m_packaged;
+
+ QmlGraphicsVisualDataModelParts *m_parts;
+ friend class QmlGraphicsVisualItemParts;
+
+ QmlGraphicsVisualDataModelData *data(QObject *item);
+
+ QVariant m_modelVariant;
+ QmlListAccessor *m_listAccessor;
+
+ int modelCount() const {
+ if (m_visualItemModel)
+ return m_visualItemModel->count();
+ if (m_listModelInterface)
+ return m_listModelInterface->count();
+ if (m_abstractItemModel)
+ return m_abstractItemModel->rowCount();
+ if (m_listAccessor)
+ return m_listAccessor->count();
+ return 0;
+ }
+};
+
+class QmlGraphicsVisualDataModelDataMetaObject : public QmlOpenMetaObject
+{
+public:
+ QmlGraphicsVisualDataModelDataMetaObject(QObject *parent)
+ : QmlOpenMetaObject(parent) {}
+
+ virtual QVariant propertyCreated(int, QMetaPropertyBuilder &);
+ virtual int createProperty(const char *, const char *);
+
+private:
+ friend class QmlGraphicsVisualDataModelData;
+ QList<int> roles;
+};
+
+class QmlGraphicsVisualDataModelData : public QObject
+{
+Q_OBJECT
+public:
+ QmlGraphicsVisualDataModelData(int index, QmlGraphicsVisualDataModel *model);
+ ~QmlGraphicsVisualDataModelData();
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ int index() const;
+ void setIndex(int index);
+
+ int count() const;
+ int role(int) const;
+ void setValue(int, const QVariant &);
+
+Q_SIGNALS:
+ void indexChanged();
+
+private:
+ friend class QmlGraphicsVisualDataModelDataMetaObject;
+ int m_index;
+ QGuard<QmlGraphicsVisualDataModel> m_model;
+ QmlGraphicsVisualDataModelDataMetaObject *m_meta;
+};
+
+int QmlGraphicsVisualDataModelData::count() const
+{
+ return m_meta->count();
+}
+
+int QmlGraphicsVisualDataModelData::role(int id) const
+{
+ Q_ASSERT(id >= 0 && id < count());
+ return m_meta->roles.at(id);
+}
+
+void QmlGraphicsVisualDataModelData::setValue(int id, const QVariant &val)
+{
+ m_meta->setValue(id, val);
+}
+
+int QmlGraphicsVisualDataModelDataMetaObject::createProperty(const char *name, const char *type)
+{
+ QmlGraphicsVisualDataModelData *data =
+ static_cast<QmlGraphicsVisualDataModelData *>(object());
+
+ if (!data->m_model)
+ return -1;
+
+ QmlGraphicsVisualDataModelPrivate *model = QmlGraphicsVisualDataModelPrivate::get(data->m_model);
+
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
+ model->ensureRoles();
+ if (model->m_roleNames.contains(QString::fromUtf8(name))) {
+ return QmlOpenMetaObject::createProperty(name, type);
+ } else if (model->m_listAccessor->type() == QmlListAccessor::QmlList) {
+ QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
+ if (object && object->property(name).isValid())
+ return QmlOpenMetaObject::createProperty(name, type);
+ }
+ } else {
+ model->ensureRoles();
+ QString sname = QString::fromUtf8(name);
+ if (model->m_roleNames.contains(sname))
+ return QmlOpenMetaObject::createProperty(name, type);
+ }
+ return -1;
+}
+
+QVariant
+QmlGraphicsVisualDataModelDataMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
+{
+ prop.setWritable(false);
+
+ QmlGraphicsVisualDataModelData *data =
+ static_cast<QmlGraphicsVisualDataModelData *>(object());
+
+ Q_ASSERT(data->m_model);
+ QmlGraphicsVisualDataModelPrivate *model = QmlGraphicsVisualDataModelPrivate::get(data->m_model);
+
+ QString name = QString::fromUtf8(prop.name());
+ if ((!model->m_listModelInterface || !model->m_abstractItemModel) && model->m_listAccessor) {
+ if (name == QLatin1String("modelData")) {
+ if (model->m_listAccessor->type() == QmlListAccessor::Instance) {
+ QObject *object = model->m_listAccessor->at(0).value<QObject*>();
+ return object->metaObject()->property(1).read(object); // the first property after objectName
+ }
+ return model->m_listAccessor->at(data->m_index);
+ } else {
+ // return any property of a single object instance.
+ QObject *object = model->m_listAccessor->at(data->m_index).value<QObject*>();
+ return object->property(prop.name());
+ }
+ } else if (model->m_listModelInterface) {
+ model->ensureRoles();
+ QHash<QString,int>::const_iterator it = model->m_roleNames.find(name);
+ if (it != model->m_roleNames.end()) {
+ roles.append(*it);
+ QHash<int,QVariant> values = model->m_listModelInterface->data(data->m_index, QList<int>() << *it);
+ if (values.isEmpty())
+ return QVariant();
+ else
+ return values.value(*it);
+ } else if (model->m_roles.count() == 1 && name == QLatin1String("modelData")) {
+ //for compatability with other lists, assign modelData if there is only a single role
+ QHash<int,QVariant> values = model->m_listModelInterface->data(data->m_index, QList<int>() << model->m_roles.first());
+ if (values.isEmpty())
+ return QVariant();
+ else
+ return *values.begin();
+ }
+ } else if (model->m_abstractItemModel) {
+ model->ensureRoles();
+ QHash<QString,int>::const_iterator it = model->m_roleNames.find(name);
+ if (it != model->m_roleNames.end()) {
+ roles.append(*it);
+ QModelIndex index = model->m_abstractItemModel->index(data->m_index, 0);
+ return model->m_abstractItemModel->data(index, *it);
+ }
+ }
+ Q_ASSERT(!"Can never be reached");
+ return QVariant();
+}
+
+QmlGraphicsVisualDataModelData::QmlGraphicsVisualDataModelData(int index,
+ QmlGraphicsVisualDataModel *model)
+: m_index(index), m_model(model),
+ m_meta(new QmlGraphicsVisualDataModelDataMetaObject(this))
+{
+}
+
+QmlGraphicsVisualDataModelData::~QmlGraphicsVisualDataModelData()
+{
+}
+
+int QmlGraphicsVisualDataModelData::index() const
+{
+ return m_index;
+}
+
+// This is internal only - it should not be set from qml
+void QmlGraphicsVisualDataModelData::setIndex(int index)
+{
+ m_index = index;
+ emit indexChanged();
+}
+
+class QmlGraphicsVisualDataModelPartsMetaObject : public QmlOpenMetaObject
+{
+public:
+ QmlGraphicsVisualDataModelPartsMetaObject(QObject *parent)
+ : QmlOpenMetaObject(parent) {}
+
+ virtual QVariant propertyCreated(int, QMetaPropertyBuilder &);
+};
+
+class QmlGraphicsVisualDataModelParts : public QObject
+{
+Q_OBJECT
+public:
+ QmlGraphicsVisualDataModelParts(QmlGraphicsVisualDataModel *parent);
+
+private:
+ friend class QmlGraphicsVisualDataModelPartsMetaObject;
+ QmlGraphicsVisualDataModel *model;
+};
+
+QVariant
+QmlGraphicsVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
+{
+ prop.setWritable(false);
+
+ QmlGraphicsVisualDataModel *m = new QmlGraphicsVisualDataModel;
+ m->setParent(object());
+ m->setPart(QString::fromUtf8(prop.name()));
+ m->setModel(QVariant::fromValue(static_cast<QmlGraphicsVisualDataModelParts *>(object())->model));
+
+ QVariant var = QVariant::fromValue((QObject *)m);
+ return var;
+}
+
+QmlGraphicsVisualDataModelParts::QmlGraphicsVisualDataModelParts(QmlGraphicsVisualDataModel *parent)
+: QObject(parent), model(parent)
+{
+ new QmlGraphicsVisualDataModelPartsMetaObject(this);
+}
+
+QmlGraphicsVisualDataModelPrivate::QmlGraphicsVisualDataModelPrivate(QmlContext *ctxt)
+: m_listModelInterface(0), m_abstractItemModel(0), m_visualItemModel(0), m_delegate(0)
+, m_context(ctxt), m_parts(0), m_listAccessor(0)
+{
+}
+
+QmlGraphicsVisualDataModelData *QmlGraphicsVisualDataModelPrivate::data(QObject *item)
+{
+ QmlGraphicsVisualDataModelData *dataItem =
+ item->findChild<QmlGraphicsVisualDataModelData *>();
+ Q_ASSERT(dataItem);
+ return dataItem;
+}
+
+QmlGraphicsVisualDataModel::QmlGraphicsVisualDataModel()
+: QmlGraphicsVisualModel(*(new QmlGraphicsVisualDataModelPrivate(0)))
+{
+}
+
+QmlGraphicsVisualDataModel::QmlGraphicsVisualDataModel(QmlContext *ctxt)
+: QmlGraphicsVisualModel(*(new QmlGraphicsVisualDataModelPrivate(ctxt)))
+{
+}
+
+QmlGraphicsVisualDataModel::~QmlGraphicsVisualDataModel()
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_listAccessor)
+ delete d->m_listAccessor;
+}
+
+QVariant QmlGraphicsVisualDataModel::model() const
+{
+ Q_D(const QmlGraphicsVisualDataModel);
+ return d->m_modelVariant;
+}
+
+void QmlGraphicsVisualDataModel::setModel(const QVariant &model)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ 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(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
+ QObject::disconnect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
+ this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
+ } 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,QmlPackage*)),
+ this, SLOT(_q_createdPackage(int,QmlPackage*)));
+ QObject::disconnect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
+ this, SLOT(_q_destroyingPackage(QmlPackage*)));
+ d->m_visualItemModel = 0;
+ }
+
+ d->m_roles.clear();
+ d->m_roleNames.clear();
+
+ 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(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsInserted(const QModelIndex &,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(rowsRemoved(const QModelIndex &,int,int)),
+ this, SLOT(_q_rowsRemoved(const QModelIndex &,int,int)));
+ QObject::connect(d->m_abstractItemModel, SIGNAL(dataChanged(const QModelIndex&,const QModelIndex&)),
+ this, SLOT(_q_dataChanged(const QModelIndex&,const QModelIndex&)));
+ return;
+ }
+ if ((d->m_visualItemModel = qvariant_cast<QmlGraphicsVisualDataModel *>(model))) {
+ 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,QmlPackage*)),
+ this, SLOT(_q_createdPackage(int,QmlPackage*)));
+ QObject::connect(d->m_visualItemModel, SIGNAL(destroyingPackage(QmlPackage*)),
+ this, SLOT(_q_destroyingPackage(QmlPackage*)));
+ return;
+ }
+ d->m_listAccessor = new QmlListAccessor;
+ d->m_listAccessor->setList(model, d->m_context?d->m_context->engine():qmlEngine(this));
+ if (d->m_delegate && d->modelCount()) {
+ emit itemsInserted(0, d->modelCount());
+ emit countChanged();
+ }
+}
+
+QmlComponent *QmlGraphicsVisualDataModel::delegate() const
+{
+ Q_D(const QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->delegate();
+ return d->m_delegate;
+}
+
+void QmlGraphicsVisualDataModel::setDelegate(QmlComponent *delegate)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ d->m_delegate = delegate;
+ if (d->modelCount()) {
+ emit itemsInserted(0, d->modelCount());
+ emit countChanged();
+ }
+}
+
+QString QmlGraphicsVisualDataModel::part() const
+{
+ Q_D(const QmlGraphicsVisualDataModel);
+ return d->m_part;
+}
+
+void QmlGraphicsVisualDataModel::setPart(const QString &part)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ d->m_part = part;
+}
+
+int QmlGraphicsVisualDataModel::count() const
+{
+ Q_D(const QmlGraphicsVisualDataModel);
+ return d->modelCount();
+}
+
+QmlGraphicsItem *QmlGraphicsVisualDataModel::item(int index, bool complete)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->item(index, d->m_part.toUtf8(), complete);
+ return item(index, QByteArray(), complete);
+}
+
+/*
+ Returns ReleaseStatus flags.
+*/
+QmlGraphicsVisualDataModel::ReleaseFlags QmlGraphicsVisualDataModel::release(QmlGraphicsItem *item)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->release(item);
+
+ ReleaseFlags stat = 0;
+ QObject *obj = item;
+ bool inPackage = false;
+
+ QHash<QObject*,QmlPackage*>::iterator it = d->m_packaged.find(item);
+ if (it != d->m_packaged.end()) {
+ QmlPackage *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)) {
+ if (inPackage)
+ emit destroyingPackage(qobject_cast<QmlPackage*>(obj));
+ stat |= Destroyed;
+ obj->setParent(0);
+ obj->deleteLater();
+ } else if (!inPackage) {
+ stat |= Referenced;
+ }
+
+ return stat;
+}
+
+QObject *QmlGraphicsVisualDataModel::parts()
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (!d->m_parts)
+ d->m_parts = new QmlGraphicsVisualDataModelParts(this);
+ return d->m_parts;
+}
+
+QmlGraphicsItem *QmlGraphicsVisualDataModel::item(int index, const QByteArray &viewId, bool complete)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ 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);
+ if (!nobj) {
+ QmlContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ QmlGraphicsVisualDataModelData *data = new QmlGraphicsVisualDataModelData(index, this);
+ ctxt->setContextProperty(QLatin1String("model"), data);
+ ctxt->addDefaultObject(data);
+ nobj = d->m_delegate->beginCreate(ctxt);
+ if (complete)
+ d->m_delegate->completeCreate();
+ if (nobj) {
+ ctxt->setParent(nobj);
+ data->setParent(nobj);
+ d->m_cache.insertItem(index, nobj);
+ if (QmlPackage *package = qobject_cast<QmlPackage *>(nobj))
+ emit createdPackage(index, package);
+ } else {
+ delete data;
+ delete ctxt;
+ qWarning() << d->m_delegate->errors();
+ }
+ }
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (!item) {
+ QmlPackage *package = qobject_cast<QmlPackage *>(nobj);
+ if (package) {
+ QObject *o = package->part(QString::fromUtf8(viewId));
+ item = qobject_cast<QmlGraphicsItem *>(o);
+ if (item)
+ d->m_packaged.insertMulti(item, package);
+ }
+ }
+ if (!item) {
+ d->m_cache.releaseItem(nobj);
+ qmlInfo(QmlGraphicsVisualDataModel::tr("Delegate component must be Item type."), d->m_delegate);
+ }
+
+ return item;
+}
+
+void QmlGraphicsVisualDataModel::completeItem()
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel) {
+ d->m_visualItemModel->completeItem();
+ return;
+ }
+
+ d->m_delegate->completeCreate();
+}
+
+QVariant QmlGraphicsVisualDataModel::evaluate(int index, const QString &expression, QObject *objectContext)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ if (d->m_visualItemModel)
+ return d->m_visualItemModel->evaluate(index, expression, objectContext);
+
+ if ((!d->m_listModelInterface && !d->m_abstractItemModel) || !d->m_delegate)
+ return QVariant();
+
+ QVariant value;
+ QObject *nobj = d->m_cache.item(index);
+ if (nobj) {
+ QmlGraphicsItem *item = qobject_cast<QmlGraphicsItem *>(nobj);
+ if (item) {
+ QmlExpression e(qmlContext(item), expression, objectContext);
+ e.setTrackChange(false);
+ value = e.value();
+ }
+ } else {
+ QmlContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QmlContext *ctxt = new QmlContext(ccontext);
+ QmlGraphicsVisualDataModelData *data = new QmlGraphicsVisualDataModelData(index, this);
+ ctxt->addDefaultObject(data);
+ QmlExpression e(ctxt, expression, objectContext);
+ e.setTrackChange(false);
+ value = e.value();
+ delete data;
+ delete ctxt;
+ }
+
+ return value;
+}
+
+int QmlGraphicsVisualDataModel::indexOf(QmlGraphicsItem *item, QObject *objectContext) const
+{
+ QmlExpression e(qmlContext(item), QLatin1String("index"), objectContext);
+ e.setTrackChange(false);
+ QVariant value = e.value();
+ if (value.isValid())
+ return value.toInt();
+ return -1;
+}
+
+void QmlGraphicsVisualDataModel::_q_itemsChanged(int index, int count,
+ const QList<int> &roles)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ // XXX - highly inefficient
+ for (int ii = index; ii < index + count; ++ii) {
+
+ if (QObject *item = d->m_cache.item(ii)) {
+ QmlGraphicsVisualDataModelData *data = d->data(item);
+
+ for (int prop = 0; prop < data->count(); ++prop) {
+
+ int role = data->role(prop);
+ if (roles.contains(role)) {
+ if (d->m_listModelInterface) {
+ data->setValue(prop, d->m_listModelInterface->data(ii, QList<int>() << role).value(role));
+ } else if (d->m_abstractItemModel) {
+ QModelIndex index = d->m_abstractItemModel->index(ii, 0);
+ data->setValue(prop, d->m_abstractItemModel->data(index, role));
+ }
+ }
+ }
+ }
+
+ }
+}
+
+void QmlGraphicsVisualDataModel::_q_itemsInserted(int index, int count)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ // XXX - highly inefficient
+ QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= index) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() + count;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsInserted(index, count);
+ emit countChanged();
+}
+
+void QmlGraphicsVisualDataModel::_q_itemsRemoved(int index, int count)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ // XXX - highly inefficient
+ QHash<int, QmlGraphicsVisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int, QmlGraphicsVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+ if (iter.key() >= index && iter.key() < index + count) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ iter = d->m_cache.erase(iter);
+ items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(-1);
+ } else if (iter.key() >= index + count) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - count;
+ iter = d->m_cache.erase(iter);
+ items.insert(index, objRef);
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+
+ d->m_cache.unite(items);
+ emit itemsRemoved(index, count);
+ emit countChanged();
+}
+
+void QmlGraphicsVisualDataModel::_q_itemsMoved(int from, int to, int count)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ // XXX - highly inefficient
+ QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef> items;
+ for (QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= from && iter.key() < from + count) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() - from + to;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ for (QHash<int,QmlGraphicsVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
+ iter != d->m_cache.end(); ) {
+
+ if (iter.key() >= qMin(from,to) && iter.key() < qMax(from+count,to+count)) {
+ QmlGraphicsVisualDataModelPrivate::ObjectRef objRef = *iter;
+ int index = iter.key() + from - to;
+ iter = d->m_cache.erase(iter);
+
+ items.insert(index, objRef);
+
+ QmlGraphicsVisualDataModelData *data = d->data(objRef.obj);
+ data->setIndex(index);
+ } else {
+ ++iter;
+ }
+ }
+ d->m_cache.unite(items);
+
+ emit itemsMoved(from, to, count);
+}
+
+void QmlGraphicsVisualDataModel::_q_rowsInserted(const QModelIndex &, int begin, int end)
+{
+ _q_itemsInserted(begin, end - begin + 1);
+}
+
+void QmlGraphicsVisualDataModel::_q_rowsRemoved(const QModelIndex &, int begin, int end)
+{
+ _q_itemsRemoved(begin, end - begin + 1);
+}
+
+void QmlGraphicsVisualDataModel::_q_dataChanged(const QModelIndex &begin, const QModelIndex &end)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ _q_itemsChanged(begin.row(), end.row() - begin.row() + 1, d->m_roles);
+}
+
+void QmlGraphicsVisualDataModel::_q_createdPackage(int index, QmlPackage *package)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ emit createdItem(index, qobject_cast<QmlGraphicsItem*>(package->part(d->m_part)));
+}
+
+void QmlGraphicsVisualDataModel::_q_destroyingPackage(QmlPackage *package)
+{
+ Q_D(QmlGraphicsVisualDataModel);
+ emit destroyingItem(qobject_cast<QmlGraphicsItem*>(package->part(d->m_part)));
+}
+
+QML_DEFINE_NOCREATE_TYPE(QmlGraphicsVisualModel);
+QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,VisualItemModel,QmlGraphicsVisualItemModel)
+QML_DEFINE_TYPE(Qt,4,6,(QT_VERSION&0x00ff00)>>8,VisualDataModel,QmlGraphicsVisualDataModel)
+
+QT_END_NAMESPACE
+#include "qfxvisualitemmodel.moc"