aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items/qsgvisualdatamodel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items/qsgvisualdatamodel.cpp')
-rw-r--r--src/declarative/items/qsgvisualdatamodel.cpp1772
1 files changed, 1557 insertions, 215 deletions
diff --git a/src/declarative/items/qsgvisualdatamodel.cpp b/src/declarative/items/qsgvisualdatamodel.cpp
index 09f5d5d917..72cebd70a4 100644
--- a/src/declarative/items/qsgvisualdatamodel.cpp
+++ b/src/declarative/items/qsgvisualdatamodel.cpp
@@ -58,8 +58,10 @@
#include <private/qdeclarativeglobal_p.h>
#include <private/qmetaobjectbuilder_p.h>
#include <private/qdeclarativeproperty_p.h>
-#include <private/qdeclarativechangeset_p.h>
#include <private/qsgvisualadaptormodel_p.h>
+#include <private/qdeclarativechangeset_p.h>
+#include <private/qdeclarativelistcompositor_p.h>
+#include <private/qdeclarativeengine_p.h>
#include <private/qobject_p.h>
#include <QtCore/qhash.h>
@@ -67,10 +69,56 @@
QT_BEGIN_NAMESPACE
+typedef QDeclarativeListCompositor Compositor;
+
+class QSGVisualDataGroupEmitter
+{
+public:
+ virtual void emitModelUpdated(const QDeclarativeChangeSet &changeSet, bool reset) = 0;
+ virtual void createdPackage(int, QDeclarativePackage *) {}
+ virtual void destroyingPackage(QDeclarativePackage *) {}
+
+ QIntrusiveListNode emitterNode;
+};
+
+typedef QIntrusiveList<QSGVisualDataGroupEmitter, &QSGVisualDataGroupEmitter::emitterNode> QSGVisualDataGroupEmitterList;
+
+//---------------------------------------------------------------------------
+
+class QSGVisualDataGroupPrivate : public QObjectPrivate
+{
+public:
+ Q_DECLARE_PUBLIC(QSGVisualDataGroup)
+
+ QSGVisualDataGroupPrivate() : group(Compositor::Cache), defaultInclude(false) {}
+
+ static QSGVisualDataGroupPrivate *get(QSGVisualDataGroup *group) {
+ return static_cast<QSGVisualDataGroupPrivate *>(QObjectPrivate::get(group)); }
+
+ void setModel(QSGVisualDataModel *model, Compositor::Group group);
+ void emitChanges(QV8Engine *engine);
+ void emitModelUpdated(bool reset);
+
+ void createdPackage(int index, QDeclarativePackage *package);
+ void destroyingPackage(QDeclarativePackage *package);
+
+ bool parseGroupArgs(QDeclarativeV8Function *args, int *index, int *count, int *groups) const;
+
+ Compositor::Group group;
+ QDeclarativeGuard<QSGVisualDataModel> model;
+ QSGVisualDataGroupEmitterList emitters;
+ QDeclarativeChangeSet changeSet;
+ QString name;
+ bool defaultInclude;
+};
+
+//---------------------------------------------------------------------------
+
+class QSGVisualDataModelCacheItem;
+class QSGVisualDataModelCacheMetaType;
class QSGVisualDataModelParts;
-class QSGVisualDataModelData;
-class QSGVisualDataModelDataMetaObject;
-class QSGVisualDataModelPrivate : public QObjectPrivate
+
+class QSGVisualDataModelPrivate : public QObjectPrivate, public QSGVisualDataGroupEmitter
{
Q_DECLARE_PUBLIC(QSGVisualDataModel)
public:
@@ -83,88 +131,91 @@ public:
void init();
void connectModel(QSGVisualAdaptorModel *model);
- QObject *object(int index, bool complete);
+ QObject *object(Compositor::Group group, int index, bool complete);
+ QSGItem *item(Compositor::Group group, int index, bool complete);
+ void destroy(QObject *object);
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); }
-
+ QString stringValue(Compositor::Group group, int index, const QString &name);
+ int cacheIndexOf(QObject *object) const;
+ void emitCreatedPackage(Compositor::iterator at, QDeclarativePackage *package);
+ void emitCreatedItem(int index, QSGItem *item) { emit q_func()->createdItem(index, item); }
+ void emitDestroyingPackage(QDeclarativePackage *package);
+ void emitDestroyingItem(QSGItem *item) { emit q_func()->destroyingItem(item); }
+
+ void updateFilterGroup();
+
+ void addGroups(Compositor::Group group, int index, int count, int groupFlags);
+ void removeGroups(Compositor::Group group, int index, int count, int groupFlags);
+ void setGroups(Compositor::Group group, int index, int count, int groupFlags);
+
+ void itemsInserted(
+ const QVector<Compositor::Insert> &inserts,
+ QVarLengthArray<QVector<QDeclarativeChangeSet::Insert>, Compositor::MaximumGroupCount> *translatedInserts,
+ QHash<int, QList<QSGVisualDataModelCacheItem *> > *movedItems = 0);
+ void itemsInserted(const QVector<Compositor::Insert> &inserts);
+ void itemsRemoved(
+ const QVector<Compositor::Remove> &removes,
+ QVarLengthArray<QVector<QDeclarativeChangeSet::Remove>, Compositor::MaximumGroupCount> *translatedRemoves,
+ QHash<int, QList<QSGVisualDataModelCacheItem *> > *movedItems = 0);
+ void itemsRemoved(const QVector<Compositor::Remove> &removes);
+ void itemsMoved(
+ const QVector<Compositor::Remove> &removes, const QVector<Compositor::Insert> &inserts);
+ void itemsChanged(const QVector<Compositor::Change> &changes);
+ template <typename T> static v8::Local<v8::Array> buildChangeList(const QVector<T> &changes);
void emitChanges();
+ void emitModelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
+
+
+ static void group_append(QDeclarativeListProperty<QSGVisualDataGroup> *property, QSGVisualDataGroup *group);
+ static int group_count(QDeclarativeListProperty<QSGVisualDataGroup> *property);
+ static QSGVisualDataGroup *group_at(QDeclarativeListProperty<QSGVisualDataGroup> *property, int index);
QSGVisualAdaptorModel *m_adaptorModel;
QDeclarativeComponent *m_delegate;
+ QSGVisualDataModelCacheMetaType *m_cacheMetaType;
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;
-
+ QList<QSGVisualDataModelCacheItem *> m_cache;
QSGVisualDataModelParts *m_parts;
- friend class QSGVisualItemParts;
+ QSGVisualDataGroupEmitterList m_pendingParts;
- friend class QSGVisualDataModelData;
+ QDeclarativeListCompositor m_compositor;
+ QDeclarativeListCompositor::Group m_compositorGroup;
+ bool m_complete : 1;
bool m_delegateValidated : 1;
bool m_completePending : 1;
bool m_reset : 1;
+ bool m_transaction : 1;
- QDeclarativeChangeSet m_absoluteChangeSet;
-
+ QString m_filterGroup;
QList<QByteArray> watchedRoles;
+
+ union {
+ struct {
+ QSGVisualDataGroup *m_cacheItems;
+ QSGVisualDataGroup *m_items;
+ };
+ QSGVisualDataGroup *m_groups[Compositor::MaximumGroupCount];
+ };
+ int m_groupCount;
};
//---------------------------------------------------------------------------
-class QSGVisualPartsModel : public QSGVisualModel
+class QSGVisualPartsModel : public QSGVisualModel, public QSGVisualDataGroupEmitter
{
Q_OBJECT
-
+ Q_PROPERTY(QString filterOnGroup READ filterGroup WRITE setFilterGroup NOTIFY filterGroupChanged RESET resetFilterGroup)
public:
QSGVisualPartsModel(QSGVisualDataModel *model, const QString &part, QObject *parent = 0);
~QSGVisualPartsModel();
+ QString filterGroup() const;
+ void setFilterGroup(const QString &group);
+ void resetFilterGroup();
+ void updateFilterGroup();
+ void updateFilterGroup(Compositor::Group group, const QDeclarativeChangeSet &changeSet);
+
int count() const;
bool isValid() const;
QSGItem *item(int index, bool complete=true);
@@ -176,15 +227,22 @@ public:
int indexOf(QSGItem *item, QObject *objectContext) const;
-public Q_SLOTS:
+ void emitModelUpdated(const QDeclarativeChangeSet &changeSet, bool reset);
+
void createdPackage(int index, QDeclarativePackage *package);
void destroyingPackage(QDeclarativePackage *package);
+Q_SIGNALS:
+ void filterGroupChanged();
+
private:
QSGVisualDataModel *m_model;
QHash<QObject *, QDeclarativePackage *> m_packaged;
QString m_part;
+ QString m_filterGroup;
QList<QByteArray> m_watchedRoles;
+ Compositor::Group m_compositorGroup;
+ bool m_inheritGroup;
};
class QSGVisualDataModelPartsMetaObject : public QDeclarativeOpenMetaObject
@@ -203,9 +261,8 @@ Q_OBJECT
public:
QSGVisualDataModelParts(QSGVisualDataModel *parent);
-private:
- friend class QSGVisualDataModelPartsMetaObject;
QSGVisualDataModel *model;
+ QList<QSGVisualPartsModel *> models;
};
void QSGVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilder &prop)
@@ -215,10 +272,10 @@ void QSGVisualDataModelPartsMetaObject::propertyCreated(int, QMetaPropertyBuilde
QVariant QSGVisualDataModelPartsMetaObject::initialValue(int id)
{
+ QSGVisualDataModelParts *parts = static_cast<QSGVisualDataModelParts *>(object());
QSGVisualPartsModel *m = new QSGVisualPartsModel(
- static_cast<QSGVisualDataModelParts *>(object())->model,
- QString::fromUtf8(name(id)),
- object());
+ parts->model, QString::fromUtf8(name(id)), parts);
+ parts->models.append(m);
return QVariant::fromValue(static_cast<QObject *>(m));
}
@@ -228,19 +285,77 @@ QSGVisualDataModelParts::QSGVisualDataModelParts(QSGVisualDataModel *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)
- , m_reset(false)
+//---------------------------------------------------------------------------
+
+class QSGVisualDataModelCacheMetaType : public QDeclarativeRefCount
{
-}
+public:
+ QSGVisualDataModelCacheMetaType(QSGVisualDataModel *model, const QStringList &groupNames);
+ ~QSGVisualDataModelCacheMetaType();
+
+ int parseGroups(const QStringList &groupNames) const;
+ int parseGroups(QV8Engine *engine, const v8::Local<v8::Value> &groupNames) const;
+
+ QDeclarativeGuard<QSGVisualDataModel> model;
+ const int groupCount;
+ const int memberPropertyOffset;
+ const int indexPropertyOffset;
+ QMetaObject *metaObject;
+ const QStringList groupNames;
+};
+
+class QSGVisualDataModelCacheItem
+{
+public:
+ QSGVisualDataModelCacheItem(QSGVisualDataModelCacheMetaType *metaType)
+ : metaType(metaType)
+ , object(0)
+ , attached(0)
+ , objectRef(0)
+ , groups(0)
+ {
+ metaType->addref();
+ }
+
+ ~QSGVisualDataModelCacheItem()
+ {
+ Q_ASSERT(objectRef == 0);
+ Q_ASSERT(!object);
+
+ metaType->release();
+ }
+
+ void referenceObject() { ++objectRef; }
+ bool releaseObject() { return --objectRef == 0; }
+
+ bool isReferenced() const { return objectRef; }
+
+ QSGVisualDataModelCacheMetaType * const metaType;
+ QDeclarativeGuard<QObject> object;
+ QSGVisualDataModelAttached *attached;
+ int objectRef;
+ int groups;
+ int index[Compositor::MaximumGroupCount];
+};
+
+class QSGVisualDataModelAttachedMetaObject : public QAbstractDynamicMetaObject
+{
+public:
+ QSGVisualDataModelAttachedMetaObject(
+ QSGVisualDataModelAttached *attached, QSGVisualDataModelCacheMetaType *metaType);
+ ~QSGVisualDataModelAttachedMetaObject();
+
+ int metaCall(QMetaObject::Call, int _id, void **);
+
+private:
+ QSGVisualDataModelAttached *attached;
+ QSGVisualDataModelCacheMetaType *metaType;
+};
//---------------------------------------------------------------------------
+QHash<QObject*, QSGVisualDataModelAttached*> QSGVisualDataModelAttached::attachedProperties;
+
/*!
\qmlclass VisualDataModel QSGVisualDataModel
\inqmlmodule QtQuick 2
@@ -261,6 +376,25 @@ QSGVisualDataModelPrivate::QSGVisualDataModelPrivate(QDeclarativeContext *ctxt)
\snippet doc/src/snippets/declarative/visualdatamodel.qml 0
*/
+QSGVisualDataModelPrivate::QSGVisualDataModelPrivate(QDeclarativeContext *ctxt)
+ : m_adaptorModel(0)
+ , m_delegate(0)
+ , m_cacheMetaType(0)
+ , m_context(ctxt)
+ , m_parts(0)
+ , m_compositorGroup(Compositor::Cache)
+ , m_complete(false)
+ , m_delegateValidated(false)
+ , m_completePending(false)
+ , m_reset(false)
+ , m_transaction(false)
+ , m_filterGroup(QStringLiteral("items"))
+ , m_cacheItems(0)
+ , m_items(0)
+ , m_groupCount(2)
+{
+}
+
void QSGVisualDataModelPrivate::connectModel(QSGVisualAdaptorModel *model)
{
Q_Q(QSGVisualDataModel);
@@ -277,7 +411,10 @@ void QSGVisualDataModelPrivate::init()
Q_Q(QSGVisualDataModel);
m_adaptorModel = new QSGVisualAdaptorModel;
QObject::connect(m_adaptorModel, SIGNAL(rootIndexChanged()), q, SIGNAL(rootIndexChanged()));
- connectModel(m_adaptorModel);
+
+ m_items = new QSGVisualDataGroup(QStringLiteral("items"), q, Compositor::Default, q);
+ m_items->setDefaultInclude(true);
+ QSGVisualDataGroupPrivate::get(m_items)->emitters.insert(this);
}
QSGVisualDataModel::QSGVisualDataModel()
@@ -292,12 +429,81 @@ QSGVisualDataModel::QSGVisualDataModel(QDeclarativeContext *ctxt, QObject *paren
{
Q_D(QSGVisualDataModel);
d->init();
+ componentComplete();
}
QSGVisualDataModel::~QSGVisualDataModel()
{
Q_D(QSGVisualDataModel);
+ foreach (QSGVisualDataModelCacheItem *cacheItem, d->m_cache) {
+ cacheItem->object = 0;
+ cacheItem->objectRef = 0;
+ delete cacheItem;
+ }
+
delete d->m_adaptorModel;
+ if (d->m_cacheMetaType)
+ d->m_cacheMetaType->release();
+}
+
+
+void QSGVisualDataModel::classBegin()
+{
+}
+
+void QSGVisualDataModel::componentComplete()
+{
+ Q_D(QSGVisualDataModel);
+ d->m_complete = true;
+
+ int defaultGroups = 0;
+ QStringList groupNames;
+ groupNames.append(QStringLiteral("items"));
+ if (QSGVisualDataGroupPrivate::get(d->m_items)->defaultInclude)
+ defaultGroups |= Compositor::DefaultFlag;
+ for (int i = 2; i < d->m_groupCount; ++i) {
+ QString name = d->m_groups[i]->name();
+ if (name.isEmpty()) {
+ d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
+ --d->m_groupCount;
+ --i;
+ } else if (name.at(0).isUpper()) {
+ qmlInfo(d->m_groups[i]) << QSGVisualDataGroup::tr("Group names must start with a lower case letter");
+ d->m_groups[i] = d->m_groups[d->m_groupCount - 1];
+ --d->m_groupCount;
+ --i;
+ } else {
+ groupNames.append(name);
+
+ QSGVisualDataGroupPrivate *group = QSGVisualDataGroupPrivate::get(d->m_groups[i]);
+ group->setModel(this, Compositor::Group(i));
+ if (group->defaultInclude)
+ defaultGroups |= (1 << i);
+ }
+ }
+ if (!d->m_context)
+ d->m_context = qmlContext(this);
+
+ d->m_cacheMetaType = new QSGVisualDataModelCacheMetaType(this, groupNames);
+
+ d->m_compositor.setGroupCount(d->m_groupCount);
+ d->m_compositor.setDefaultGroups(defaultGroups);
+ d->updateFilterGroup();
+
+ while (!d->m_pendingParts.isEmpty())
+ static_cast<QSGVisualPartsModel *>(d->m_pendingParts.first())->updateFilterGroup();
+
+ d->connectModel(d->m_adaptorModel);
+ QVector<Compositor::Insert> inserts;
+ d->m_reset = true;
+ d->m_compositor.append(
+ d->m_adaptorModel,
+ 0,
+ qMax(0, d->m_adaptorModel->count()),
+ defaultGroups | Compositor::AppendFlag | Compositor::PrependFlag,
+ &inserts);
+ d->itemsInserted(inserts);
+ d->emitChanges();
}
/*!
@@ -344,13 +550,26 @@ QDeclarativeComponent *QSGVisualDataModel::delegate() const
void QSGVisualDataModel::setDelegate(QDeclarativeComponent *delegate)
{
Q_D(QSGVisualDataModel);
+ if (d->m_transaction) {
+ qmlInfo(this) << tr("The delegate of a VisualDataModel cannot be changed within onUpdated.");
+ return;
+ }
bool wasValid = d->m_delegate != 0;
d->m_delegate = delegate;
d->m_delegateValidated = false;
- if (!wasValid && d->m_adaptorModel->count() && d->m_delegate)
- _q_itemsInserted(0, d->m_adaptorModel->count());
- if (wasValid && !d->m_delegate && d->m_adaptorModel->count())
- _q_itemsRemoved(0, d->m_adaptorModel->count());
+ if (wasValid && d->m_complete) {
+ for (int i = 1; i < d->m_groupCount; ++i) {
+ QSGVisualDataGroupPrivate::get(d->m_groups[i])->changeSet.remove(
+ 0, d->m_compositor.count(Compositor::Group(i)));
+ }
+ }
+ if (d->m_complete && d->m_delegate) {
+ for (int i = 1; i < d->m_groupCount; ++i) {
+ QSGVisualDataGroupPrivate::get(d->m_groups[i])->changeSet.insert(
+ 0, d->m_compositor.count(Compositor::Group(i)));
+ }
+ }
+ d->emitChanges();
}
/*!
@@ -430,31 +649,44 @@ QVariant QSGVisualDataModel::parentModelIndex() const
return d->m_adaptorModel->parentModelIndex();
}
+/*!
+ \qmlproperty int QtQuick2::VisualDataModel::count
+*/
+
int QSGVisualDataModel::count() const
{
Q_D(const QSGVisualDataModel);
if (!d->m_delegate)
return 0;
- return d->m_adaptorModel->count();
+ return d->m_compositor.count(d->m_compositorGroup);
}
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;
+ if (!object)
+ return stat;
+
+ int cacheIndex = cacheIndexOf(object);
+ if (cacheIndex != -1) {
+ QSGVisualDataModelCacheItem *cacheItem = m_cache.at(cacheIndex);
+ if (cacheItem->releaseObject()) {
+ QObjectPrivate *p = QObjectPrivate::get(object);
+ Q_ASSERT(p->declarativeData);
+ QDeclarativeData *data = static_cast<QDeclarativeData*>(p->declarativeData);
+ if (data->ownContext && data->context)
+ data->context->clearContext();
+ object->deleteLater();
+ cacheItem->object = 0;
+ stat |= QSGVisualModel::Destroyed;
+ m_compositor.clearFlags(Compositor::Cache, cacheIndex, 1, Compositor::CacheFlag);
+ m_cache.removeAt(cacheIndex);
+ delete cacheItem;
+ Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
+ } else {
+ stat |= QSGVisualDataModel::Referenced;
+ }
}
-
return stat;
}
@@ -471,6 +703,149 @@ QSGVisualDataModel::ReleaseFlags QSGVisualDataModel::release(QSGItem *item)
return stat;
}
+void QSGVisualDataModelPrivate::group_append(
+ QDeclarativeListProperty<QSGVisualDataGroup> *property, QSGVisualDataGroup *group)
+{
+ QSGVisualDataModelPrivate *d = static_cast<QSGVisualDataModelPrivate *>(property->data);
+ if (d->m_complete)
+ return;
+ if (d->m_groupCount == 10) {
+ qmlInfo(d->q_func()) << QSGVisualDataModel::tr("The maximum number of supported VisualDataGroups is 8");
+ return;
+ }
+ d->m_groups[d->m_groupCount] = group;
+ d->m_groupCount += 1;
+}
+
+int QSGVisualDataModelPrivate::group_count(
+ QDeclarativeListProperty<QSGVisualDataGroup> *property)
+{
+ QSGVisualDataModelPrivate *d = static_cast<QSGVisualDataModelPrivate *>(property->data);
+ return d->m_groupCount - 1;
+}
+
+QSGVisualDataGroup *QSGVisualDataModelPrivate::group_at(
+ QDeclarativeListProperty<QSGVisualDataGroup> *property, int index)
+{
+ QSGVisualDataModelPrivate *d = static_cast<QSGVisualDataModelPrivate *>(property->data);
+ return index >= 0 && index < d->m_groupCount - 1
+ ? d->m_groups[index - 1]
+ : 0;
+}
+
+/*!
+ \qmlproperty list<VisualDataGroup> QtQuick2::VisualDataModel::groups
+
+ This property holds a visual data model's group definitions.
+
+ Groups define a sub-set of the items in a visual data model and can be used to filter
+ a model.
+
+ For every group defined in a VisualDataModel two attached properties are added to each
+ delegate item. The first of the form VisualDataModel.in\e{GroupName} holds whether the
+ item belongs to the group and the second VisualDataModel.\e{groupName}Index holds the
+ index of the item in that group.
+
+ The following example illustrates using groups to select items in a model.
+
+ \snippet doc/src/snippets/declarative/visualdatagroup.qml 0
+*/
+
+QDeclarativeListProperty<QSGVisualDataGroup> QSGVisualDataModel::groups()
+{
+ Q_D(QSGVisualDataModel);
+ return QDeclarativeListProperty<QSGVisualDataGroup>(
+ this,
+ d,
+ QSGVisualDataModelPrivate::group_append,
+ QSGVisualDataModelPrivate::group_count,
+ QSGVisualDataModelPrivate::group_at);
+}
+
+/*!
+ \qmlproperty VisualDataGroup QtQuick2::VisualDataModel::items
+
+ This property holds visual data model's default group to which all new items are added.
+*/
+
+QSGVisualDataGroup *QSGVisualDataModel::items()
+{
+ Q_D(QSGVisualDataModel);
+ return d->m_items;
+}
+
+/*!
+ \qmlproperty string QtQuick2::VisualDataModel::filterOnGroup
+
+ This property holds the name of the group used to filter the visual data model.
+
+ Only items which belong to this group are visible to a view.
+
+ By default this is the \l items group.
+*/
+
+QString QSGVisualDataModel::filterGroup() const
+{
+ Q_D(const QSGVisualDataModel);
+ return d->m_filterGroup;
+}
+
+void QSGVisualDataModel::setFilterGroup(const QString &group)
+{
+ Q_D(QSGVisualDataModel);
+
+ if (d->m_transaction) {
+ qmlInfo(this) << tr("The group of a VisualDataModel cannot be changed within onChanged");
+ return;
+ }
+
+ if (d->m_filterGroup != group) {
+ d->m_filterGroup = group;
+ d->updateFilterGroup();
+ emit filterGroupChanged();
+ }
+}
+
+void QSGVisualDataModel::resetFilterGroup()
+{
+ setFilterGroup(QStringLiteral("items"));
+}
+
+void QSGVisualDataModelPrivate::updateFilterGroup()
+{
+ Q_Q(QSGVisualDataModel);
+ if (!m_cacheMetaType)
+ return;
+
+ QDeclarativeListCompositor::Group previousGroup = m_compositorGroup;
+ m_compositorGroup = Compositor::Default;
+ for (int i = 1; i < m_groupCount; ++i) {
+ if (m_filterGroup == m_cacheMetaType->groupNames.at(i - 1)) {
+ m_compositorGroup = Compositor::Group(i);
+ break;
+ }
+ }
+
+ QSGVisualDataGroupPrivate::get(m_groups[m_compositorGroup])->emitters.insert(this);
+ if (m_compositorGroup != previousGroup) {
+ QVector<QDeclarativeChangeSet::Remove> removes;
+ QVector<QDeclarativeChangeSet::Insert> inserts;
+ m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
+
+ QDeclarativeChangeSet changeSet;
+ changeSet.apply(removes, inserts);
+ emit q->modelUpdated(changeSet, false);
+
+ if (changeSet.difference() != 0)
+ emit q->countChanged();
+
+ if (m_parts) {
+ foreach (QSGVisualPartsModel *model, m_parts->models)
+ model->updateFilterGroup(m_compositorGroup, changeSet);
+ }
+ }
+}
+
/*!
\qmlproperty object QtQuick2::VisualDataModel::parts
@@ -507,18 +882,40 @@ QObject *QSGVisualDataModel::parts()
return d->m_parts;
}
-QObject *QSGVisualDataModelPrivate::object(int index, bool complete)
+void QSGVisualDataModelPrivate::emitCreatedPackage(Compositor::iterator at, QDeclarativePackage *package)
+{
+ for (int i = 1; i < m_groupCount; ++i)
+ QSGVisualDataGroupPrivate::get(m_groups[i])->createdPackage(at.index[i], package);
+}
+
+void QSGVisualDataModelPrivate::emitDestroyingPackage(QDeclarativePackage *package)
+{
+ for (int i = 1; i < m_groupCount; ++i)
+ QSGVisualDataGroupPrivate::get(m_groups[i])->destroyingPackage(package);
+}
+
+QObject *QSGVisualDataModelPrivate::object(Compositor::Group group, int index, bool complete)
{
Q_Q(QSGVisualDataModel);
- if (m_adaptorModel->count() <= 0 || !m_delegate)
+ if (!m_delegate || index < 0 || index >= m_compositor.count(group)) {
+ qWarning() << "VisualDataModel::item: index out range" << index << m_compositor.count(group);
return 0;
- QObject *nobj = m_cache.getItem(index);
- bool needComplete = false;
- if (!nobj) {
- QObject *data = m_adaptorModel->data(index);
+ }
+
+ Compositor::iterator it = m_compositor.find(group, index);
+ QSGVisualDataModelCacheItem *cacheItem = it->inCache() ? m_cache.at(it.cacheIndex) : 0;
+
+ if (!cacheItem) {
+ cacheItem = new QSGVisualDataModelCacheItem(m_cacheMetaType);
+ for (int i = 0; i < m_groupCount; ++i)
+ cacheItem->index[i] = it.index[i];
+ cacheItem->groups = it->flags & Compositor::GroupMask;
+ }
+
+ if (!cacheItem->object) {
+ QObject *data = m_adaptorModel->data(it.modelIndex());
- QDeclarativeContext *rootContext = new QDeclarativeContext(
- m_context ? m_context.data() : qmlContext(q));
+ QDeclarativeContext *rootContext = new QDeclarativeContext(m_context);
QDeclarativeContext *ctxt = rootContext;
if (m_adaptorModel->flags() & QSGVisualAdaptorModel::ProxiedObject) {
if (QSGVisualAdaptorModelProxyInterface *proxy = qobject_cast<QSGVisualAdaptorModelProxyInterface *>(data)) {
@@ -532,42 +929,54 @@ QObject *QSGVisualDataModelPrivate::object(int index, bool complete)
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);
+ cacheItem->object = m_delegate->beginCreate(ctxt);
+
+ if (cacheItem->object) {
+ QDeclarative_setParent_noEvent(rootContext, cacheItem->object);
+ if (!it->inCache()) {
+ m_cache.insert(it.cacheIndex, cacheItem);
+ m_compositor.setFlags(it, 1, Compositor::CacheFlag);
+ Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
+ }
+
+ cacheItem->attached = QSGVisualDataModelAttached::properties(cacheItem->object);
+ cacheItem->attached->m_cacheItem = cacheItem;
+ new QSGVisualDataModelAttachedMetaObject(cacheItem->attached, m_cacheMetaType);
+ cacheItem->attached->emitChanges();
+
+ if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(cacheItem->object))
+ emitCreatedPackage(it, package);
+
+ m_completePending = !complete;
+ if (complete)
+ m_delegate->completeCreate();
} else {
delete rootContext;
+ if (!it->inCache())
+ delete cacheItem;
qmlInfo(q, m_delegate->errors()) << "Error creating delegate";
+ return 0;
}
}
- if (index == m_adaptorModel->count() -1 && m_adaptorModel->canFetchMore())
+ if (index == m_compositor.count(group) - 1 && m_adaptorModel->canFetchMore())
QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
-
- return nobj;
+ cacheItem->referenceObject();
+ return cacheItem->object;
}
QSGItem *QSGVisualDataModel::item(int index, bool complete)
{
Q_D(QSGVisualDataModel);
- QObject *object = d->object(index, complete);
+ QObject *object = d->object(d->m_compositorGroup, index, complete);
if (QSGItem *item = qobject_cast<QSGItem *>(object))
return item;
-
- if (completePending())
+ if (d->m_completePending)
completeItem();
d->release(object);
if (!d->m_delegateValidated) {
- qmlInfo(d->m_delegate) << tr("Delegate component must be Item type.");
+ if (object)
+ qmlInfo(d->m_delegate) << QSGVisualDataModel::tr("Delegate component must be Item type.");
d->m_delegateValidated = true;
}
return 0;
@@ -586,21 +995,37 @@ void QSGVisualDataModel::completeItem()
d->m_completePending = false;
}
-QString QSGVisualDataModelPrivate::stringValue(int index, const QString &name)
+QString QSGVisualDataModelPrivate::stringValue(Compositor::Group group, int index, const QString &name)
{
- return m_adaptorModel->stringValue(index, name);
+ Compositor::iterator it = m_compositor.find(group, index);
+ if (QSGVisualAdaptorModel *model = it.list<QSGVisualAdaptorModel>()) {
+ return model->stringValue(it.modelIndex(), name);
+ }
+ return QString();
}
QString QSGVisualDataModel::stringValue(int index, const QString &name)
{
Q_D(QSGVisualDataModel);
- return d->stringValue(index, name);
+ return d->stringValue(d->m_compositorGroup, index, name);
+}
+
+int QSGVisualDataModelPrivate::cacheIndexOf(QObject *object) const
+{
+ for (int cacheIndex = 0; cacheIndex < m_cache.count(); ++cacheIndex) {
+ if (m_cache.at(cacheIndex)->object == object)
+ return cacheIndex;
+ }
+ return -1;
}
int QSGVisualDataModel::indexOf(QSGItem *item, QObject *) const
{
Q_D(const QSGVisualDataModel);
- return d->m_adaptorModel->indexOf(item);
+ const int cacheIndex = d->cacheIndexOf(item);
+ return cacheIndex != -1
+ ? d->m_cache.at(cacheIndex)->index[d->m_compositorGroup]
+ : -1;
}
void QSGVisualDataModel::setWatchedRoles(QList<QByteArray> roles)
@@ -610,6 +1035,36 @@ void QSGVisualDataModel::setWatchedRoles(QList<QByteArray> roles)
d->watchedRoles = roles;
}
+void QSGVisualDataModelPrivate::addGroups(Compositor::Group group, int index, int count, int groupFlags)
+{
+ QVector<Compositor::Insert> inserts;
+ m_compositor.setFlags(group, index, count, groupFlags, &inserts);
+ itemsInserted(inserts);
+ emitChanges();
+}
+
+void QSGVisualDataModelPrivate::removeGroups(Compositor::Group group, int index, int count, int groupFlags)
+{
+ QVector<Compositor::Remove> removes;
+ m_compositor.clearFlags(group, index, count, groupFlags, &removes);
+ itemsRemoved(removes);
+ emitChanges();
+}
+
+void QSGVisualDataModelPrivate::setGroups(Compositor::Group group, int index, int count, int groupFlags)
+{
+ QVector<Compositor::Insert> inserts;
+ m_compositor.setFlags(group, index, count, groupFlags, &inserts);
+ itemsInserted(inserts);
+
+ const int removeFlags = ~groupFlags & Compositor::GroupMask;
+ QVector<Compositor::Remove> removes;
+ m_compositor.clearFlags(group, index, count, removeFlags, &removes);
+ itemsRemoved(removes);
+
+ emitChanges();
+}
+
bool QSGVisualDataModel::event(QEvent *e)
{
Q_D(QSGVisualDataModel);
@@ -618,115 +1073,293 @@ bool QSGVisualDataModel::event(QEvent *e)
return QSGVisualModel::event(e);
}
+void QSGVisualDataModelPrivate::itemsChanged(const QVector<Compositor::Change> &changes)
+{
+ if (!m_delegate)
+ return;
+
+ QVarLengthArray<QVector<QDeclarativeChangeSet::Change>, Compositor::MaximumGroupCount> translatedChanges(m_groupCount);
+
+ foreach (const Compositor::Change &change, changes) {
+ for (int i = 1; i < m_groupCount; ++i) {
+ if (change.inGroup(i)) {
+ translatedChanges[i].append(
+ QDeclarativeChangeSet::Change(change.index[i], change.count));
+ }
+ }
+ }
+
+ for (int i = 1; i < m_groupCount; ++i)
+ QSGVisualDataGroupPrivate::get(m_groups[i])->changeSet.apply(translatedChanges.at(i));
+}
+
void QSGVisualDataModel::_q_itemsChanged(int index, int count)
{
Q_D(QSGVisualDataModel);
- if (!d->m_delegate)
+ if (count <= 0)
return;
- d->m_absoluteChangeSet.change(index, count);
+ QVector<Compositor::Change> changes;
+ d->m_compositor.listItemsChanged(d->m_adaptorModel, index, count, &changes);
+ d->itemsChanged(changes);
d->emitChanges();
}
+void QSGVisualDataModelPrivate::itemsInserted(
+ const QVector<Compositor::Insert> &inserts,
+ QVarLengthArray<QVector<QDeclarativeChangeSet::Insert>, Compositor::MaximumGroupCount> *translatedInserts,
+ QHash<int, QList<QSGVisualDataModelCacheItem *> > *movedItems)
+{
+ int cacheIndex = 0;
+
+ int inserted[Compositor::MaximumGroupCount];
+ for (int i = 1; i < m_groupCount; ++i)
+ inserted[i] = 0;
+
+ foreach (const Compositor::Insert &insert, inserts) {
+ for (; cacheIndex < insert.cacheIndex; ++cacheIndex) {
+ QSGVisualDataModelCacheItem *cacheItem = m_cache.at(cacheIndex);
+ if (!cacheItem->groups)
+ continue;
+ for (int i = 1; i < m_groupCount; ++i)
+ cacheItem->index[i] += inserted[i];
+ }
+ for (int i = 1; i < m_groupCount; ++i) {
+ if (insert.inGroup(i)) {
+ (*translatedInserts)[i].append(
+ QDeclarativeChangeSet::Insert(insert.index[i], insert.count, insert.moveId));
+ inserted[i] += insert.count;
+ }
+ }
+
+ if (!insert.inCache())
+ continue;
+
+ if (movedItems && insert.isMove()) {
+ QList<QSGVisualDataModelCacheItem *> items = movedItems->take(insert.moveId);
+ Q_ASSERT(items.count() == insert.count);
+ m_cache = m_cache.mid(0, insert.cacheIndex) + items + m_cache.mid(insert.cacheIndex);
+ }
+ if (insert.inGroup()) {
+ for (int offset = 0; cacheIndex < insert.cacheIndex + insert.count; ++cacheIndex, ++offset) {
+ QSGVisualDataModelCacheItem *cacheItem = m_cache.at(cacheIndex);
+ cacheItem->groups |= insert.flags & Compositor::GroupMask;
+ for (int i = 1; i < m_groupCount; ++i) {
+ cacheItem->index[i] = cacheItem->groups & (1 << i)
+ ? insert.index[i] + offset
+ : insert.index[i];
+ }
+ }
+ } else {
+ cacheIndex = insert.cacheIndex + insert.count;
+ }
+ }
+ for (; cacheIndex < m_cache.count(); ++cacheIndex) {
+ QSGVisualDataModelCacheItem *cacheItem = m_cache.at(cacheIndex);
+ if (!cacheItem->groups)
+ continue;
+ for (int i = 1; i < m_groupCount; ++i)
+ cacheItem->index[i] += inserted[i];
+ }
+}
+
+void QSGVisualDataModelPrivate::itemsInserted(const QVector<Compositor::Insert> &inserts)
+{
+ QVarLengthArray<QVector<QDeclarativeChangeSet::Insert>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
+ itemsInserted(inserts, &translatedInserts);
+ Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
+ if (!m_delegate)
+ return;
+
+ for (int i = 1; i < m_groupCount; ++i)
+ QSGVisualDataGroupPrivate::get(m_groups[i])->changeSet.apply(translatedInserts.at(i));
+}
+
void QSGVisualDataModel::_q_itemsInserted(int index, int count)
{
+
Q_D(QSGVisualDataModel);
- if (!d->m_delegate)
+ if (count <= 0)
return;
+ QVector<Compositor::Insert> inserts;
+ d->m_compositor.listItemsInserted(d->m_adaptorModel, index, count, &inserts);
+ d->itemsInserted(inserts);
+ d->emitChanges();
+}
- // XXX - highly inefficient
- QHash<int,QSGVisualDataModelPrivate::ObjectRef> items;
- for (QHash<int,QSGVisualDataModelPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ) {
+void QSGVisualDataModelPrivate::itemsRemoved(
+ const QVector<Compositor::Remove> &removes,
+ QVarLengthArray<QVector<QDeclarativeChangeSet::Remove>, Compositor::MaximumGroupCount> *translatedRemoves,
+ QHash<int, QList<QSGVisualDataModelCacheItem *> > *movedItems)
+{
+ int cacheIndex = 0;
+ int removedCache = 0;
+
+ int removed[Compositor::MaximumGroupCount];
+ for (int i = 1; i < m_groupCount; ++i)
+ removed[i] = 0;
+
+ foreach (const Compositor::Remove &remove, removes) {
+ for (; cacheIndex < remove.cacheIndex; ++cacheIndex) {
+ QSGVisualDataModelCacheItem *cacheItem = m_cache.at(cacheIndex);
+ if (!cacheItem->groups)
+ continue;
+ for (int i = 1; i < m_groupCount; ++i)
+ cacheItem->index[i] -= removed[i];
+ }
+ for (int i = 1; i < m_groupCount; ++i) {
+ if (remove.inGroup(i)) {
+ (*translatedRemoves)[i].append(
+ QDeclarativeChangeSet::Remove(remove.index[i], remove.count, remove.moveId));
+ removed[i] += remove.count;
+ }
+ }
- if (iter.key() >= index) {
- QSGVisualDataModelPrivate::ObjectRef objRef = *iter;
- int index = iter.key() + count;
- iter = d->m_cache.erase(iter);
+ if (!remove.inCache())
+ continue;
- items.insert(index, objRef);
+ if (movedItems && remove.isMove()) {
+ movedItems->insert(remove.moveId, m_cache.mid(remove.cacheIndex, remove.count));
+ QList<QSGVisualDataModelCacheItem *>::iterator begin = m_cache.begin() + remove.cacheIndex;
+ QList<QSGVisualDataModelCacheItem *>::iterator end = begin + remove.count;
+ m_cache.erase(begin, end);
} else {
- ++iter;
+ for (; cacheIndex < remove.cacheIndex + remove.count - removedCache; ++cacheIndex) {
+ QSGVisualDataModelCacheItem *cacheItem = m_cache.at(cacheIndex);
+ if (remove.groups() == cacheItem->groups && !cacheItem->isReferenced()) {
+ m_compositor.clearFlags(Compositor::Cache, cacheIndex, 1, Compositor::CacheFlag);
+ m_cache.removeAt(cacheIndex);
+ delete cacheItem;
+ --cacheIndex;
+ ++removedCache;
+ Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
+ } else if (remove.groups() == cacheItem->groups) {
+ cacheItem->groups = 0;
+ for (int i = 1; i < m_groupCount; ++i)
+ cacheItem->index[i] = -1;
+ } else {
+ for (int i = 1; i < m_groupCount; ++i) {
+ if (remove.inGroup(i))
+ cacheItem->index[i] = remove.index[i];
+ }
+ cacheItem->groups &= ~remove.flags & Compositor::GroupMask;
+ }
+ }
}
}
- d->m_cache.unite(items);
- d->m_absoluteChangeSet.insert(index, count);
- d->emitChanges();
- emit countChanged();
+ for (; cacheIndex < m_cache.count(); ++cacheIndex) {
+ QSGVisualDataModelCacheItem *cacheItem = m_cache.at(cacheIndex);
+ if (!cacheItem->groups)
+ continue;
+ for (int i = 1; i < m_groupCount; ++i)
+ cacheItem->index[i] -= removed[i];
+ }
+}
+
+void QSGVisualDataModelPrivate::itemsRemoved(const QVector<Compositor::Remove> &removes)
+{
+ QVarLengthArray<QVector<QDeclarativeChangeSet::Remove>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
+ itemsRemoved(removes, &translatedRemoves);
+ Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
+ if (!m_delegate)
+ return;
+
+ for (int i = 1; i < m_groupCount; ++i)
+ QSGVisualDataGroupPrivate::get(m_groups[i])->changeSet.apply(translatedRemoves.at(i));
}
void QSGVisualDataModel::_q_itemsRemoved(int index, int count)
{
Q_D(QSGVisualDataModel);
- if (!d->m_delegate)
+ if (count <= 0)
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);
- d->m_absoluteChangeSet.remove(index, count);
+ QVector<Compositor::Remove> removes;
+ d->m_compositor.listItemsRemoved(d->m_adaptorModel, index, count, &removes);
+ d->itemsRemoved(removes);
d->emitChanges();
- emit countChanged();
+}
+
+void QSGVisualDataModelPrivate::itemsMoved(
+ const QVector<Compositor::Remove> &removes, const QVector<Compositor::Insert> &inserts)
+{
+ QHash<int, QList<QSGVisualDataModelCacheItem *> > movedItems;
+
+ QVarLengthArray<QVector<QDeclarativeChangeSet::Remove>, Compositor::MaximumGroupCount> translatedRemoves(m_groupCount);
+ itemsRemoved(removes, &translatedRemoves, &movedItems);
+
+ QVarLengthArray<QVector<QDeclarativeChangeSet::Insert>, Compositor::MaximumGroupCount> translatedInserts(m_groupCount);
+ itemsInserted(inserts, &translatedInserts, &movedItems);
+ Q_ASSERT(m_cache.count() == m_compositor.count(Compositor::Cache));
+ Q_ASSERT(movedItems.isEmpty());
+ if (!m_delegate)
+ return;
+
+ for (int i = 1; i < m_groupCount; ++i) {
+ QSGVisualDataGroupPrivate::get(m_groups[i])->changeSet.apply(
+ translatedRemoves.at(i),
+ translatedInserts.at(i));
+ }
}
void QSGVisualDataModel::_q_itemsMoved(int from, int to, int count)
{
Q_D(QSGVisualDataModel);
- if (!d->m_delegate)
+ if (count <= 0)
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);
- d->m_absoluteChangeSet.move(from, to, count);
+ QVector<Compositor::Remove> removes;
+ QVector<Compositor::Insert> inserts;
+ d->m_compositor.listItemsMoved(d->m_adaptorModel, from, to, count, &removes, &inserts);
+ d->itemsMoved(removes, inserts);
d->emitChanges();
}
-void QSGVisualDataModelPrivate::emitChanges()
+template <typename T> v8::Local<v8::Array>
+QSGVisualDataModelPrivate::buildChangeList(const QVector<T> &changes)
+{
+ v8::Local<v8::Array> indexes = v8::Array::New(changes.count());
+ v8::Local<v8::String> indexKey = v8::String::New("index");
+ v8::Local<v8::String> countKey = v8::String::New("count");
+ v8::Local<v8::String> moveIdKey = v8::String::New("moveId");
+
+ for (int i = 0; i < changes.count(); ++i) {
+ v8::Local<v8::Object> object = v8::Object::New();
+ object->Set(indexKey, v8::Integer::New(changes.at(i).index));
+ object->Set(countKey, v8::Integer::New(changes.at(i).count));
+ object->Set(moveIdKey, changes.at(i).moveId != -1 ? v8::Integer::New(changes.at(i).count) : v8::Undefined());
+ indexes->Set(i, object);
+ }
+ return indexes;
+}
+
+void QSGVisualDataModelPrivate::emitModelUpdated(const QDeclarativeChangeSet &changeSet, bool reset)
{
Q_Q(QSGVisualDataModel);
- if (!m_absoluteChangeSet.isEmpty()) {
- emit q->modelUpdated(m_absoluteChangeSet, m_reset);
- m_absoluteChangeSet.clear();
- m_reset = false;
+ emit q->modelUpdated(changeSet, reset);
+ if (changeSet.difference() != 0)
+ emit q->countChanged();
+}
+
+void QSGVisualDataModelPrivate::emitChanges()
+{
+ if (m_transaction || !m_complete)
+ return;
+
+ m_transaction = true;
+ QV8Engine *engine = QDeclarativeEnginePrivate::getV8Engine(m_context->engine());
+ for (int i = 1; i < m_groupCount; ++i)
+ QSGVisualDataGroupPrivate::get(m_groups[i])->emitChanges(engine);
+ m_transaction = false;
+
+ const bool reset = m_reset;
+ m_reset = false;
+ for (int i = 1; i < m_groupCount; ++i)
+ QSGVisualDataGroupPrivate::get(m_groups[i])->emitModelUpdated(reset);
+
+ foreach (QSGVisualDataModelCacheItem *cacheItem, m_cache) {
+ if (cacheItem->object)
+ cacheItem->attached->emitChanges();
}
}
@@ -735,35 +1368,731 @@ void QSGVisualDataModel::_q_modelReset(int oldCount, int newCount)
Q_D(QSGVisualDataModel);
if (!d->m_delegate)
return;
- d->m_absoluteChangeSet.remove(0, oldCount);
- d->m_absoluteChangeSet.insert(0, newCount);
+
+ QVector<Compositor::Remove> removes;
+ QVector<Compositor::Insert> inserts;
+ if (oldCount)
+ d->m_compositor.listItemsRemoved(d->m_adaptorModel, 0, oldCount, &removes);
+ if (newCount)
+ d->m_compositor.listItemsInserted(d->m_adaptorModel, 0, newCount, &inserts);
+ d->itemsMoved(removes, inserts);
d->m_reset = true;
d->emitChanges();
- emit countChanged();
+}
+
+QSGVisualDataModelAttached *QSGVisualDataModel::qmlAttachedProperties(QObject *obj)
+{
+ return QSGVisualDataModelAttached::properties(obj);
}
//============================================================================
+QSGVisualDataModelCacheMetaType::QSGVisualDataModelCacheMetaType(
+ QSGVisualDataModel *model, const QStringList &groupNames)
+ : model(model)
+ , groupCount(groupNames.count() + 1)
+ , memberPropertyOffset(QSGVisualDataModelAttached::staticMetaObject.propertyCount())
+ , indexPropertyOffset(QSGVisualDataModelAttached::staticMetaObject.propertyCount() + groupNames.count())
+ , metaObject(0)
+ , groupNames(groupNames)
+{
+ QMetaObjectBuilder builder;
+ builder.setFlags(QMetaObjectBuilder::DynamicMetaObject);
+ builder.setClassName(QSGVisualDataModelAttached::staticMetaObject.className());
+ builder.setSuperClass(&QSGVisualDataModelAttached::staticMetaObject);
+
+ int notifierId = 0;
+ for (int i = 0; i < groupNames.count(); ++i, ++notifierId) {
+ QString propertyName = QStringLiteral("in") + groupNames.at(i);
+ propertyName.replace(2, 1, propertyName.at(2).toUpper());
+ builder.addSignal("__" + propertyName.toUtf8() + "Changed()");
+ QMetaPropertyBuilder propertyBuilder = builder.addProperty(
+ propertyName.toUtf8(), "bool", notifierId);
+ propertyBuilder.setWritable(true);
+ }
+ for (int i = 0; i < groupNames.count(); ++i, ++notifierId) {
+ const QString propertyName = groupNames.at(i) + QStringLiteral("Index");
+ builder.addSignal("__" + propertyName.toUtf8() + "Changed()");
+ QMetaPropertyBuilder propertyBuilder = builder.addProperty(
+ propertyName.toUtf8(), "int", notifierId);
+ propertyBuilder.setWritable(true);
+ }
+
+ metaObject = builder.toMetaObject();
+}
+
+QSGVisualDataModelCacheMetaType::~QSGVisualDataModelCacheMetaType()
+{
+ qFree(metaObject);
+}
+
+int QSGVisualDataModelCacheMetaType::parseGroups(const QStringList &groups) const
+{
+ int groupFlags = 0;
+ foreach (const QString &groupName, groups) {
+ int index = groupNames.indexOf(groupName);
+ if (index != -1)
+ groupFlags |= 2 << index;
+ }
+ return groupFlags;
+}
+
+int QSGVisualDataModelCacheMetaType::parseGroups(QV8Engine *engine, const v8::Local<v8::Value> &groups) const
+{
+ int groupFlags = 0;
+ if (groups->IsString()) {
+ const QString groupName = engine->toString(groups);
+ int index = groupNames.indexOf(groupName);
+ if (index != -1)
+ groupFlags |= 2 << index;
+ } else if (groups->IsArray()) {
+ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(groups);
+ for (uint i = 0; i < array->Length(); ++i) {
+ const QString groupName = engine->toString(array->Get(i));
+ int index = groupNames.indexOf(groupName);
+ if (index != -1)
+ groupFlags |= 2 << index;
+ }
+ }
+ return groupFlags;
+}
+
+//---------------------------------------------------------------------------
+
+QSGVisualDataModelAttachedMetaObject::QSGVisualDataModelAttachedMetaObject(
+ QSGVisualDataModelAttached *attached, QSGVisualDataModelCacheMetaType *metaType)
+ : attached(attached)
+ , metaType(metaType)
+{
+ metaType->addref();
+ *static_cast<QMetaObject *>(this) = *metaType->metaObject;
+ QObjectPrivate::get(attached)->metaObject = this;
+}
+
+QSGVisualDataModelAttachedMetaObject::~QSGVisualDataModelAttachedMetaObject()
+{
+ metaType->release();
+}
+
+int QSGVisualDataModelAttachedMetaObject::metaCall(QMetaObject::Call call, int _id, void **arguments)
+{
+ if (call == QMetaObject::ReadProperty) {
+ if (_id >= metaType->indexPropertyOffset) {
+ Compositor::Group group = Compositor::Group(_id - metaType->indexPropertyOffset + 1);
+ *static_cast<int *>(arguments[0]) = attached->m_cacheItem->index[group];
+ return -1;
+ } else if (_id >= metaType->memberPropertyOffset) {
+ Compositor::Group group = Compositor::Group(_id - metaType->memberPropertyOffset + 1);
+ *static_cast<bool *>(arguments[0]) = attached->m_cacheItem->groups & (1 << group);
+ return -1;
+ }
+ } else if (call == QMetaObject::WriteProperty) {
+ if (_id >= metaType->memberPropertyOffset) {
+ if (!metaType->model)
+ return -1;
+ Compositor::Group group = Compositor::Group(_id - metaType->memberPropertyOffset + 1);
+ const bool member = attached->m_cacheItem->groups & (1 << group);
+ if (member != *static_cast<bool *>(arguments[0])) {
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(metaType->model);
+ const int cacheIndex = model->m_cache.indexOf(attached->m_cacheItem);
+ if (member)
+ model->removeGroups(Compositor::Cache, cacheIndex, 1, (1 << group));
+ else
+ model->addGroups(Compositor::Cache, cacheIndex, 1, (1 << group));
+ }
+ return -1;
+ }
+ }
+ return attached->qt_metacall(call, _id, arguments);
+}
+
+/*!
+ \qmlattachedproperty int QtQuick2::VisualDataModel::model
+
+ This attached property holds the visual data model this delegate instance belongs to.
+
+ It is attached to each instance of the delegate.
+*/
+
+QSGVisualDataModel *QSGVisualDataModelAttached::model() const
+{
+ return m_cacheItem ? m_cacheItem->metaType->model : 0;
+}
+
+/*!
+ \qmlattachedproperty stringlist QtQuick2::VisualDataModel::groups
+
+ This attached property holds the name of VisualDataGroups the item belongs to.
+
+ It is attached to each instance of the delegate.
+*/
+
+QStringList QSGVisualDataModelAttached::groups() const
+{
+ QStringList groups;
+
+ if (!m_cacheItem)
+ return groups;
+ for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
+ if (m_cacheItem->groups & (1 << i))
+ groups.append(m_cacheItem->metaType->groupNames.at(i - 1));
+ }
+ return groups;
+}
+
+void QSGVisualDataModelAttached::setGroups(const QStringList &groups)
+{
+ if (!m_cacheItem)
+ return;
+
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_cacheItem->metaType->model);
+
+ const int cacheIndex = model->m_cache.indexOf(m_cacheItem);
+ const int groupFlags = model->m_cacheMetaType->parseGroups(groups);
+ model->setGroups(Compositor::Cache, cacheIndex, 1, groupFlags);
+}
+
+/*!
+ \qmlattachedproperty int QtQuick2::VisualDataModel::inItems
+
+ This attached property holds whether the item belongs to the default \l items VisualDataGroup.
+
+ Changing this property will add or remove the item from the items group.
+
+ It is attached to each instance of the delegate.
+*/
+
+/*!
+ \qmlattachedproperty int QtQuick2::VisualDataModel::itemsIndex
+
+ This attached property holds the index of the item in the default \l items VisualDataGroup.
+
+ It is attached to each instance of the delegate.
+*/
+
+void QSGVisualDataModelAttached::emitChanges()
+{
+ if (m_modelChanged) {
+ m_modelChanged = false;
+ emit modelChanged();
+ }
+
+ const int groupChanges = m_previousGroups ^ m_cacheItem->groups;
+ m_previousGroups = m_cacheItem->groups;
+
+ int indexChanges = 0;
+ for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i) {
+ if (m_previousIndex[i] != m_cacheItem->index[i]) {
+ m_previousIndex[i] = m_cacheItem->index[i];
+ indexChanges |= (1 << i);
+ }
+ }
+
+ int notifierId = 0;
+ const QMetaObject *meta = metaObject();
+ for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
+ if (groupChanges & (1 << i))
+ QMetaObject::activate(this, meta, notifierId, 0);
+ }
+ for (int i = 1; i < m_cacheItem->metaType->groupCount; ++i, ++notifierId) {
+ if (indexChanges & (1 << i))
+ QMetaObject::activate(this, meta, notifierId, 0);
+ }
+
+ if (groupChanges)
+ emit groupsChanged();
+}
+
+//============================================================================
+
+void QSGVisualDataGroupPrivate::setModel(QSGVisualDataModel *m, Compositor::Group g)
+{
+ Q_ASSERT(!model);
+ model = m;
+ group = g;
+}
+
+void QSGVisualDataGroupPrivate::emitChanges(QV8Engine *engine)
+{
+ Q_Q(QSGVisualDataGroup);
+ static int idx = signalIndex("changed(QDeclarativeV8Handle,QDeclarativeV8Handle)");
+ if (isSignalConnected(idx)) {
+ v8::HandleScope handleScope;
+ v8::Context::Scope contextScope(engine->context());
+ v8::Local<v8::Array> removed = QSGVisualDataModelPrivate::buildChangeList(changeSet.removes());
+ v8::Local<v8::Array> inserted = QSGVisualDataModelPrivate::buildChangeList(changeSet.inserts());
+ emit q->changed(
+ QDeclarativeV8Handle::fromHandle(removed), QDeclarativeV8Handle::fromHandle(inserted));
+ }
+ if (changeSet.difference() != 0)
+ emit q->countChanged();
+}
+
+void QSGVisualDataGroupPrivate::emitModelUpdated(bool reset)
+{
+ for (QSGVisualDataGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
+ it->emitModelUpdated(changeSet, reset);
+ changeSet.clear();
+}
+
+void QSGVisualDataGroupPrivate::createdPackage(int index, QDeclarativePackage *package)
+{
+ for (QSGVisualDataGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
+ it->createdPackage(index, package);
+}
+
+void QSGVisualDataGroupPrivate::destroyingPackage(QDeclarativePackage *package)
+{
+ for (QSGVisualDataGroupEmitterList::iterator it = emitters.begin(); it != emitters.end(); ++it)
+ it->destroyingPackage(package);
+}
+
+/*!
+ \qmlclass VisualDataGroup QSGVisualDataGroup
+ \inqmlmodule QtQuick 2
+ \ingroup qml-working-with-data
+ \brief The VisualDataGroup encapsulates a filtered set of visual data items.
+
+*/
+
+QSGVisualDataGroup::QSGVisualDataGroup(QObject *parent)
+ : QObject(*new QSGVisualDataGroupPrivate, parent)
+{
+}
+
+QSGVisualDataGroup::QSGVisualDataGroup(
+ const QString &name, QSGVisualDataModel *model, int index, QObject *parent)
+ : QObject(*new QSGVisualDataGroupPrivate, parent)
+{
+ Q_D(QSGVisualDataGroup);
+ d->name = name;
+ d->setModel(model, Compositor::Group(index));
+}
+
+QSGVisualDataGroup::~QSGVisualDataGroup()
+{
+}
+
+/*!
+ \qmlproperty string QtQuick2::VisualDataGroup::name
+
+ This property holds the name of the group.
+
+ Each group in a model must have a unique name starting with a lower case letter.
+*/
+
+QString QSGVisualDataGroup::name() const
+{
+ Q_D(const QSGVisualDataGroup);
+ return d->name;
+}
+
+void QSGVisualDataGroup::setName(const QString &name)
+{
+ Q_D(QSGVisualDataGroup);
+ if (d->model)
+ return;
+ if (d->name != name) {
+ d->name = name;
+ emit nameChanged();
+ }
+}
+
+/*!
+ \qmlproperty int QtQuick2::VisualDataGroup::count
+
+ This property holds the number of items in the group.
+*/
+
+int QSGVisualDataGroup::count() const
+{
+ Q_D(const QSGVisualDataGroup);
+ if (!d->model)
+ return 0;
+ return QSGVisualDataModelPrivate::get(d->model)->m_compositor.count(d->group);
+}
+
+/*!
+ \qmlproperty bool QtQuick2::VisualDataGroup::includeByDefault
+
+ This property holds whether new items are assigned to this group by default.
+*/
+
+bool QSGVisualDataGroup::defaultInclude() const
+{
+ Q_D(const QSGVisualDataGroup);
+ return d->defaultInclude;
+}
+
+void QSGVisualDataGroup::setDefaultInclude(bool include)
+{
+ Q_D(QSGVisualDataGroup);
+ if (d->defaultInclude != include) {
+ d->defaultInclude = include;
+
+ if (d->model) {
+ if (include)
+ QSGVisualDataModelPrivate::get(d->model)->m_compositor.setDefaultGroup(d->group);
+ else
+ QSGVisualDataModelPrivate::get(d->model)->m_compositor.clearDefaultGroup(d->group);
+ }
+ emit defaultIncludeChanged();
+ }
+}
+
+/*!
+ \qmlmethod QtQuick2::VisualDataGroup::remove(int index, int count)
+
+ Removes \a count items starting at \a index from the group.
+*/
+
+void QSGVisualDataGroup::remove(QDeclarativeV8Function *args)
+{
+ Q_D(QSGVisualDataGroup);
+ if (!d->model)
+ return;
+ int index = -1;
+ int count = 1;
+
+ if (args->Length() == 0)
+ return;
+
+ int i = 0;
+ v8::Local<v8::Value> v = (*args)[i];
+ if (!v->IsInt32())
+ return;
+ index = v->Int32Value();
+
+ if (++i < args->Length()) {
+ v = (*args)[i];
+ if (v->IsInt32())
+ count = v->Int32Value();
+ }
+
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(d->model);
+ if (count < 0) {
+ qmlInfo(this) << tr("remove: invalid count");
+ } else if (index < 0 || index + count > model->m_compositor.count(d->group)) {
+ qmlInfo(this) << tr("remove: index out of range");
+ } else if (count > 0) {
+ model->removeGroups(d->group, index, count, 1 << d->group);
+ }
+}
+
+bool QSGVisualDataGroupPrivate::parseGroupArgs(
+ QDeclarativeV8Function *args, int *index, int *count, int *groups) const
+{
+ if (!model)
+ return false;
+
+ if (args->Length() < 2)
+ return false;
+
+ int i = 0;
+ v8::Local<v8::Value> v = (*args)[i];
+ if (!v->IsInt32())
+ return false;
+ *index = v->Int32Value();
+
+ v = (*args)[++i];
+ if (v->IsInt32()) {
+ *count = v->Int32Value();
+
+ if (++i == args->Length())
+ return false;
+ v = (*args)[i];
+ }
+
+ *groups = QSGVisualDataModelPrivate::get(model)->m_cacheMetaType->parseGroups(args->engine(), v);
+
+ return true;
+}
+
+/*!
+ \qmlmethod QtQuick2::VisualDataGroup::addGroups(int index, int count, stringlist groups)
+
+ Adds \a count items starting at \a index to \a groups.
+*/
+
+void QSGVisualDataGroup::addGroups(QDeclarativeV8Function *args)
+{
+ Q_D(QSGVisualDataGroup);
+ int index = -1;
+ int count = 1;
+ int groups = 0;
+
+ if (!d->parseGroupArgs(args, &index, &count, &groups))
+ return;
+
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(d->model);
+ if (count < 0) {
+ qmlInfo(this) << tr("addGroups: invalid count");
+ } else if (index < 0 || index + count > model->m_compositor.count(d->group)) {
+ qmlInfo(this) << tr("addGroups: index out of range");
+ } else if (count > 0 && groups) {
+ model->addGroups(d->group, index, count, groups);
+ }
+}
+
+/*!
+ \qmlmethod QtQuick2::VisualDataGroup::removeGroups(int index, int count, stringlist groups)
+
+ Removes \a count items starting at \a index from \a groups.
+*/
+
+void QSGVisualDataGroup::removeGroups(QDeclarativeV8Function *args)
+{
+ Q_D(QSGVisualDataGroup);
+ int index = -1;
+ int count = 1;
+ int groups = 0;
+
+ if (!d->parseGroupArgs(args, &index, &count, &groups))
+ return;
+
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(d->model);
+ if (count < 0) {
+ qmlInfo(this) << tr("removeGroups: invalid count");
+ } else if (index < 0 || index + count > model->m_compositor.count(d->group)) {
+ qmlInfo(this) << tr("removeGroups: index out of range");
+ } else if (count > 0 && groups) {
+ model->removeGroups(d->group, index, count, groups);
+ }
+}
+
+/*!
+ \qmlmethod QtQuick2::VisualDataGroup::setGroups(int index, int count, stringlist groups)
+
+ Sets the \a groups \a count items starting at \a index belong to.
+*/
+
+void QSGVisualDataGroup::setGroups(QDeclarativeV8Function *args)
+{
+ Q_D(QSGVisualDataGroup);
+ int index = -1;
+ int count = 1;
+ int groups = 0;
+
+ if (!d->parseGroupArgs(args, &index, &count, &groups))
+ return;
+
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(d->model);
+ if (count < 0) {
+ qmlInfo(this) << tr("setGroups: invalid count");
+ } else if (index < 0 || index + count > model->m_compositor.count(d->group)) {
+ qmlInfo(this) << tr("setGroups: index out of range");
+ } else if (count > 0) {
+ model->setGroups(d->group, index, count, groups);
+ }
+}
+
+/*!
+ \qmlmethod QtQuick2::VisualDataGroup::setGroups(int index, int count, stringlist groups)
+
+ Sets the \a groups \a count items starting at \a index belong to.
+*/
+
+/*!
+ \qmlmethod QtQuick2::VisualDataGroup::move(int from, int to, int count)
+
+ Moves \a count at \a from in a group \a to a new position.
+*/
+
+void QSGVisualDataGroup::move(QDeclarativeV8Function *args)
+{
+ Q_D(QSGVisualDataGroup);
+
+ if (args->Length() < 2)
+ return;
+
+ Compositor::Group fromGroup = d->group;
+ Compositor::Group toGroup = d->group;
+ int from = -1;
+ int to = -1;
+ int count = 1;
+
+ int i = 0;
+ v8::Local<v8::Value> v = (*args)[i];
+ if (QSGVisualDataGroup *group = qobject_cast<QSGVisualDataGroup *>(args->engine()->toQObject(v))) {
+ QSGVisualDataGroupPrivate *g_d = QSGVisualDataGroupPrivate::get(group);
+ if (g_d->model != d->model)
+ return;
+ fromGroup = g_d->group;
+ v = (*args)[++i];
+ }
+
+ if (!v->IsInt32())
+ return;
+ from = v->Int32Value();
+
+ if (++i == args->Length())
+ return;
+ v = (*args)[i];
+
+ if (QSGVisualDataGroup *group = qobject_cast<QSGVisualDataGroup *>(args->engine()->toQObject(v))) {
+ QSGVisualDataGroupPrivate *g_d = QSGVisualDataGroupPrivate::get(group);
+ if (g_d->model != d->model)
+ return;
+ toGroup = g_d->group;
+
+ if (++i == args->Length())
+ return;
+ v = (*args)[i];
+ }
+
+ if (!v->IsInt32())
+ return;
+ to = v->Int32Value();
+
+ if (++i < args->Length()) {
+ v = (*args)[i];
+ if (v->IsInt32())
+ count = v->Int32Value();
+ }
+
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(d->model);
+
+ if (count < 0) {
+ qmlInfo(this) << tr("move: invalid count");
+ } else if (from < 0 || from + count > model->m_compositor.count(fromGroup)) {
+ qmlInfo(this) << tr("move: from index out of range");
+ } else if (!model->m_compositor.verifyMoveTo(fromGroup, from, toGroup, to, count)) {
+ qmlInfo(this) << tr("move: to index out of range");
+ } else if (count > 0) {
+ QVector<Compositor::Remove> removes;
+ QVector<Compositor::Insert> inserts;
+
+ model->m_compositor.move(fromGroup, from, toGroup, to, count, &removes, &inserts);
+ model->itemsMoved(removes, inserts);
+ model->emitChanges();
+ }
+}
+
+/*!
+ \qmlsignal QtQuick2::VisualDataGroup::onChanged(array removed, array inserted)
+
+ This handler is called when items have been removed from or inserted into the group.
+
+ Each object in the \a removed and \a inserted arrays has two values; the \e index of the first
+ item inserted or removed and a \e count of the number of consecutive items inserted or removed.
+
+ Each index is adjusted for previous changes with all removed items preceding any inserted
+ items.
+*/
+
+//============================================================================
+
QSGVisualPartsModel::QSGVisualPartsModel(QSGVisualDataModel *model, const QString &part, QObject *parent)
: QSGVisualModel(*new QObjectPrivate, parent)
, m_model(model)
, m_part(part)
+ , m_compositorGroup(Compositor::Cache)
+ , m_inheritGroup(true)
{
- connect(m_model, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)),
- this, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)));
- connect(m_model, SIGNAL(createdPackage(int,QDeclarativePackage*)),
- this, SLOT(createdPackage(int,QDeclarativePackage*)));
- connect(m_model, SIGNAL(destroyingPackage(QDeclarativePackage*)),
- this, SLOT(destroyingPackage(QDeclarativePackage*)));
+ QSGVisualDataModelPrivate *d = QSGVisualDataModelPrivate::get(m_model);
+ if (d->m_cacheMetaType) {
+ QSGVisualDataGroupPrivate::get(d->m_groups[1])->emitters.insert(this);
+ m_compositorGroup = Compositor::Default;
+ } else {
+ d->m_pendingParts.insert(this);
+ }
}
QSGVisualPartsModel::~QSGVisualPartsModel()
{
}
+QString QSGVisualPartsModel::filterGroup() const
+{
+ if (m_inheritGroup)
+ return m_model->filterGroup();
+ return m_filterGroup;
+}
+
+void QSGVisualPartsModel::setFilterGroup(const QString &group)
+{
+ if (QSGVisualDataModelPrivate::get(m_model)->m_transaction) {
+ qmlInfo(this) << tr("The group of a VisualDataModel cannot be changed within onChanged");
+ return;
+ }
+
+ if (m_filterGroup != group || m_inheritGroup) {
+ m_filterGroup = group;
+ m_inheritGroup = false;
+ updateFilterGroup();
+
+ emit filterGroupChanged();
+ }
+}
+
+void QSGVisualPartsModel::resetFilterGroup()
+{
+ if (!m_inheritGroup) {
+ m_inheritGroup = true;
+ updateFilterGroup();
+ emit filterGroupChanged();
+ }
+}
+
+void QSGVisualPartsModel::updateFilterGroup()
+{
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
+ if (!model->m_cacheMetaType)
+ return;
+
+ if (m_inheritGroup)
+ return;
+
+ QDeclarativeListCompositor::Group previousGroup = model->m_compositorGroup;
+ m_compositorGroup = Compositor::Default;
+ QSGVisualDataGroupPrivate::get(model->m_groups[Compositor::Default])->emitters.insert(this);
+ for (int i = 1; i < model->m_groupCount; ++i) {
+ if (m_filterGroup == model->m_cacheMetaType->groupNames.at(i - 1)) {
+ m_compositorGroup = Compositor::Group(i);
+ break;
+ }
+ }
+
+ QSGVisualDataGroupPrivate::get(model->m_groups[m_compositorGroup])->emitters.insert(this);
+ if (m_compositorGroup != previousGroup) {
+ QVector<QDeclarativeChangeSet::Remove> removes;
+ QVector<QDeclarativeChangeSet::Insert> inserts;
+ model->m_compositor.transition(previousGroup, m_compositorGroup, &removes, &inserts);
+
+ QDeclarativeChangeSet changeSet;
+ changeSet.apply(removes, inserts);
+ if (!changeSet.isEmpty())
+ emit modelUpdated(changeSet, false);
+
+ if (changeSet.difference() != 0)
+ emit countChanged();
+ }
+}
+
+void QSGVisualPartsModel::updateFilterGroup(
+ Compositor::Group group, const QDeclarativeChangeSet &changeSet)
+{
+ if (!m_inheritGroup)
+ return;
+
+ m_compositorGroup = group;
+ QSGVisualDataGroupPrivate::get(QSGVisualDataModelPrivate::get(m_model)->m_groups[m_compositorGroup])->emitters.insert(this);
+
+ if (!changeSet.isEmpty())
+ emit modelUpdated(changeSet, false);
+
+ if (changeSet.difference() != 0)
+ emit countChanged();
+
+ emit filterGroupChanged();
+}
+
int QSGVisualPartsModel::count() const
{
- return m_model->count();
+ QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
+ return model->m_delegate
+ ? model->m_compositor.count(m_compositorGroup)
+ : 0;
}
bool QSGVisualPartsModel::isValid() const
@@ -775,7 +2104,7 @@ QSGItem *QSGVisualPartsModel::item(int index, bool complete)
{
QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
- QObject *object = model->object(index, complete);
+ QObject *object = model->object(m_compositorGroup, index, complete);
if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(object)) {
QObject *part = package->part(m_part);
@@ -791,7 +2120,8 @@ QSGItem *QSGVisualPartsModel::item(int index, bool complete)
m_model->completeItem();
model->release(object);
if (!model->m_delegateValidated) {
- qmlInfo(model->m_delegate) << tr("Delegate component must be Package type.");
+ if (object)
+ qmlInfo(model->m_delegate) << tr("Delegate component must be Package type.");
model->m_delegateValidated = true;
}
@@ -828,7 +2158,7 @@ void QSGVisualPartsModel::completeItem()
QString QSGVisualPartsModel::stringValue(int index, const QString &role)
{
- return QSGVisualDataModelPrivate::get(m_model)->stringValue(index, role);
+ return QSGVisualDataModelPrivate::get(m_model)->stringValue(m_compositorGroup, index, role);
}
void QSGVisualPartsModel::setWatchedRoles(QList<QByteArray> roles)
@@ -840,11 +2170,15 @@ void QSGVisualPartsModel::setWatchedRoles(QList<QByteArray> 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;
+ if (it != m_packaged.end()) {
+ const QSGVisualDataModelPrivate *model = QSGVisualDataModelPrivate::get(m_model);
+ const int cacheIndex = model->cacheIndexOf(*it);
+ return cacheIndex != -1
+ ? model->m_cache.at(cacheIndex)->index[m_compositorGroup]
+ : -1;
+ }
+ return -1;
}
void QSGVisualPartsModel::createdPackage(int index, QDeclarativePackage *package)
@@ -861,6 +2195,14 @@ void QSGVisualPartsModel::destroyingPackage(QDeclarativePackage *package)
}
}
+void QSGVisualPartsModel::emitModelUpdated(const QDeclarativeChangeSet &changeSet, bool reset)
+{
+ emit modelUpdated(changeSet, reset);
+ if (changeSet.difference() != 0)
+ emit countChanged();
+}
+
+
QT_END_NAMESPACE
#include <qsgvisualdatamodel.moc>