aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den-exter@nokia.com>2011-06-28 14:19:05 +1000
committerAndrew den Exter <andrew.den-exter@nokia.com>2011-06-29 10:45:07 +1000
commit8cf428d4ebd4c8c246806243730aad3a4f325300 (patch)
tree9c7a02a7bb234b6a535b917470902eb089841362
parent136c84811acda766182e55cd69a5a17b90b7c0c9 (diff)
Insert script objects directly into the VisualModel cache.
Keeping the visual model data in the cache allows substitution and potentially retention of state in view items.
-rw-r--r--examples/declarative/modelviews/visualdatamodel/Bubble.qml2
-rw-r--r--examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml42
-rw-r--r--src/declarative/items/qsgitemsmodule.cpp1
-rw-r--r--src/declarative/items/qsgvisualitemmodel.cpp1078
-rw-r--r--src/declarative/items/qsgvisualitemmodel_p.h71
-rw-r--r--src/declarative/util/qdeclarativelistcompositor.cpp75
-rw-r--r--src/declarative/util/qdeclarativelistcompositor_p.h3
7 files changed, 727 insertions, 545 deletions
diff --git a/examples/declarative/modelviews/visualdatamodel/Bubble.qml b/examples/declarative/modelviews/visualdatamodel/Bubble.qml
index 870533ff85..de2c80763f 100644
--- a/examples/declarative/modelviews/visualdatamodel/Bubble.qml
+++ b/examples/declarative/modelviews/visualdatamodel/Bubble.qml
@@ -3,7 +3,7 @@ import QtQuick 2.0
Rectangle {
id: content
- property int contentHeight: height - senderText.implicitHeight + 2
+ property int contentHeight: height - senderText.implicitHeight - 2
x: 1;
width: 477
diff --git a/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml b/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml
index ece72198f2..4a3e511db2 100644
--- a/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml
+++ b/examples/declarative/modelviews/visualdatamodel/visualdatamodel.qml
@@ -10,28 +10,13 @@ Rectangle {
property int messageCounter: 0
function send(message) {
- messageModel.set(messageModel.count - 1, {
- "sender": root.sender,
- "message": message,
- "avatar": "",
- "outbound": true,
- "time": Qt.formatTime(Date.now()),
- "delegateState": ""
- })
visualModel.insert(visualModel.count, messageBubble)
newMessage()
messageView.positionViewAtEnd()
}
function newMessage() {
- messageModel.append({
- "sender": root.sender,
- "message": "",
- "avatar": "",
- "outbound": true,
- "time": "",
- "delegateState": "composing"
- })
+ visualModel.appendData({})
var bubble = visualModel.take(visualModel.count - 1, composer)
messageBubble = bubble
messageBubble.y = 0 // Override the position set by the view.
@@ -59,16 +44,25 @@ Rectangle {
model: VisualDataModel {
id: visualModel
+ roles: [
+ VisualRole { name: "sender"; defaultValue: root.sender },
+ VisualRole { name: "message"; defaultValue: "" },
+ VisualRole { name: "avatar"; defaultValue: "" },
+ VisualRole { name: "outbound"; defaultValue: true },
+ VisualRole { name: "time"; defaultValue: "" },
+ VisualRole { name: "delegateState"; defaultValue: "composing" }
+ ]
+
model: ListModel { id: messageModel }
delegate: Bubble {}
}
- add: Transition {
- ParentAnimation {
- via: root
- NumberAnimation { properties: "y"; duration: 3000; easing.type: Easing.InOutQuad }
- }
- }
+// add: Transition {
+// ParentAnimation {
+// via: root
+// NumberAnimation { properties: "y"; duration: 3000; easing.type: Easing.InOutQuad }
+// }
+// }
}
Timer {
@@ -78,7 +72,7 @@ Rectangle {
onTriggered: {
var message = script.get(scriptIndex);
- messageModel.insert(messageModel.count - 1, {
+ messageModel.append({
"sender": message.sender,
"message": message.message,
"avatar": message.avatar,
@@ -88,7 +82,7 @@ Rectangle {
})
scriptIndex = (scriptIndex + 1) % script.count
- interval = Math.random() * 30000
+ //interval = Math.random() * 30000
}
}
diff --git a/src/declarative/items/qsgitemsmodule.cpp b/src/declarative/items/qsgitemsmodule.cpp
index 1637d24c8c..5a62d00d07 100644
--- a/src/declarative/items/qsgitemsmodule.cpp
+++ b/src/declarative/items/qsgitemsmodule.cpp
@@ -145,6 +145,7 @@ static void qt_sgitems_defineModule(const char *uri, int major, int minor)
qmlRegisterType<QSGVisualData>(uri,major,minor,"VisualData");
qmlRegisterType<QSGVisualDataModel>(uri,major,minor,"VisualDataModel");
qmlRegisterType<QSGVisualItemModel>(uri,major,minor,"VisualItemModel");
+ qmlRegisterType<QSGVisualModelRole>(uri,major,minor,"VisualRole");
qmlRegisterType<QSGAnchors>();
qmlRegisterType<QSGKeyEvent>();
diff --git a/src/declarative/items/qsgvisualitemmodel.cpp b/src/declarative/items/qsgvisualitemmodel.cpp
index e2f7fd84c1..c2328e70e8 100644
--- a/src/declarative/items/qsgvisualitemmodel.cpp
+++ b/src/declarative/items/qsgvisualitemmodel.cpp
@@ -64,11 +64,21 @@
#include <QtCore/qhash.h>
#include <QtCore/qlist.h>
+#include <QtScript/qscriptvalue.h>
QT_BEGIN_NAMESPACE
QHash<QObject*, QSGVisualModelAttached*> QSGVisualModelAttached::attachedProperties;
+class VDMDelegateDataType : public QDeclarativeOpenMetaObjectType
+{
+public:
+ VDMDelegateDataType(const QMetaObject *base, QDeclarativeEngine *engine) : QDeclarativeOpenMetaObjectType(base, engine) {}
+
+ void propertyCreated(int, QMetaPropertyBuilder &prop) {
+ prop.setWritable(false);
+ }
+};
class QSGVisualModelPartsMetaObject : public QDeclarativeOpenMetaObject
{
@@ -111,15 +121,20 @@ QSGVisualModelParts::QSGVisualModelParts(QSGVisualModel *parent)
new QSGVisualModelPartsMetaObject(this);
}
-
+class QSGVisualModelData;
class QSGVisualModelPrivate : public QObjectPrivate, public QDeclarativeListCompositor
{
Q_DECLARE_PUBLIC(QSGVisualModel)
public:
QSGVisualModelPrivate(QDeclarativeContext *context = 0)
- : QObjectPrivate(), QDeclarativeListCompositor(0),context(context), pendingModel(0), parts(0)
+ : QObjectPrivate(), QDeclarativeListCompositor(0),context(context), delegateDataType(0)
+ , pendingModel(0), pendingComponent(0), parts(0)
, childrenChanged(false), transaction(false) {}
+ static QSGVisualModelPrivate *get(QSGVisualModel *m) {
+ return static_cast<QSGVisualModelPrivate *>(QObjectPrivate::get(m));
+ }
+
static void data_append(QDeclarativeListProperty<QObject> *prop, QObject *data) {
QSGVisualModelPrivate *d = static_cast<QSGVisualModelPrivate *>(prop->data);
QDeclarative_setParent_noEvent(data, prop->object);
@@ -144,7 +159,12 @@ public:
}
static QSGItem *children_at(QDeclarativeListProperty<QSGItem> *prop, int index) {
- return static_cast<QSGVisualModelPrivate *>(prop->data)->children.at(index).item;
+ return qobject_cast<QSGItem *>(static_cast<QSGVisualModelPrivate *>(prop->data)->children.at(index).item);
+ }
+
+ static void roles_append(QDeclarativeListProperty<QSGVisualModelRole> *prop, QSGVisualModelRole *role) {
+ QSGVisualModelPrivate *d = static_cast<QSGVisualModelPrivate *>(prop->data);
+ d->roles.append(role);
}
void appendModel(QSGVisualData *model) {
@@ -166,10 +186,6 @@ public:
q, SLOT(_q_itemsRemoved(QSGVisualData*,int,int)), Qt::UniqueConnection);
QObject::connect(model, SIGNAL(itemsMoved(QSGVisualData*,int,int,int)),
q, SLOT(_q_itemsMoved(QSGVisualData*,int,int,int)), Qt::UniqueConnection);
- QObject::connect(model, SIGNAL(createdPackage(QSGVisualData*,int,QDeclarativePackage*)),
- q, SLOT(_q_createdPackage(QSGVisualData*,int,QDeclarativePackage*)), Qt::UniqueConnection);
- QObject::connect(model, SIGNAL(destroyingPackage(QDeclarativePackage*)),
- q, SLOT(_q_destroyingPackage(QDeclarativePackage*)), Qt::UniqueConnection);
}
void itemAppended() {
@@ -186,7 +202,7 @@ public:
emit q->childrenChanged();
}
- int indexOf(QSGItem *item) const {
+ int indexOf(QObject *item) const {
for (int i = 0; i < children.count(); ++i)
if (children.at(i).item == item)
return i;
@@ -197,8 +213,9 @@ public:
Q_Q(QSGVisualModel);
foreach (const QDeclarativeChangeSet::Remove &remove, transactionChanges.removes())
emit q->itemsRemoved(remove.start, remove.count());
- foreach (const QDeclarativeChangeSet::Insert &insert, transactionChanges.inserts())
+ foreach (const QDeclarativeChangeSet::Insert &insert, transactionChanges.inserts()) {
emit q->itemsInserted(insert.start, insert.count());
+ }
foreach (const QDeclarativeChangeSet::Move &move, transactionChanges.moves())
emit q->itemsMoved(move.start, move.to, move.count());
transactionChanges.clear();
@@ -227,24 +244,34 @@ public:
}
}
+ QSGVisualModelData *createScriptData(QDeclarativeComponent *delegate, const QScriptValue &value);
+
class Item {
public:
- Item(QSGItem *i) : item(i), ref(0) {}
+ Item(QObject *i, QSGVisualModelData *data) : item(i), data(data), ref(0) {}
void addRef() { ++ref; }
bool deref() { return --ref == 0; }
- QSGItem *item;
+ QObject *item;
+ QDeclarativeGuard<QSGVisualModelData> data;
int ref;
};
+ struct ItemData {
+ QObject *object;
+ QSGVisualModelData *data;
+ };
+
QList<Item> children;
- QHash<QSGItem *, int> removedItems;
+ QList<QSGVisualModelRole *> roles;
+ QHash<QObject *, int> removedItems;
QSGVisualModelAttached::List attachedItems;
QDeclarativeChangeSet transactionChanges;
-
QDeclarativeGuard<QDeclarativeContext> context;
+ VDMDelegateDataType *delegateDataType;
QSGVisualData *pendingModel;
+ QDeclarativeComponent *pendingComponent;
QSGVisualModelParts *parts;
bool childrenChanged;
bool transaction;
@@ -256,18 +283,20 @@ protected:
bool insertInternalData(int index, const void *data)
{
childrenChanged = true;
- QSGItem *item = static_cast<QSGItem *>(const_cast<void *>(data));
- children.insert(index, Item(item));
+ const ItemData *itemData = static_cast<const ItemData *>(data);
+ children.insert(index, Item(itemData->object, itemData->data));
return true;
}
void replaceInternalData(int index, const void *data)
{
childrenChanged = true;
+ const ItemData *itemData = static_cast<const ItemData *>(data);
QSGVisualModelPrivate::Item &item = children[index];
if (item.ref > 0)
removedItems.insert(item.item, item.ref);
- item.item = static_cast<QSGItem *>(const_cast<void *>(data));
+ item.item = itemData->object;
+ item.data = itemData->data;
item.ref = 0;
}
@@ -280,7 +309,7 @@ protected:
removedItems.insert(item.item, item.ref);
}
QList<Item>::iterator first = children.begin() + index;
- QList<Item>::iterator last = first + count - 1;
+ QList<Item>::iterator last = first + count;
children.erase(first, last);
}
@@ -316,6 +345,187 @@ protected:
}
};
+class QSGVisualDataParts;
+class QSGVisualModelData;
+class QSGVisualDataPrivate : public QObjectPrivate
+{
+public:
+ QSGVisualDataPrivate(QDeclarativeContext *);
+
+ static QSGVisualDataPrivate *get(QSGVisualData *m) {
+ return static_cast<QSGVisualDataPrivate *>(QObjectPrivate::get(m));
+ }
+
+ QDeclarativeGuard<QListModelInterface> m_listModelInterface;
+ QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
+ QString m_part;
+
+ QDeclarativeComponent *m_delegate;
+ QDeclarativeGuard<QDeclarativeContext> m_context;
+ QList<int> m_roles;
+ QHash<QByteArray,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)).toUtf8(), m_roles.at(ii));
+ } 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(*it, it.key());
+ }
+ if (m_roles.count())
+ m_roleNames.insert("hasModelChildren", -1);
+ } else if (m_listAccessor) {
+ m_roleNames.insert("modelData", 0);
+ if (m_listAccessor->type() == QDeclarativeListAccessor::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(prop.name(), 0);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ QHash<int,int> m_roleToPropId;
+ int m_modelDataPropId;
+ void createMetaData() {
+ if (!m_metaDataCreated) {
+ ensureRoles();
+ QHash<QByteArray, int> roleNames = m_roleNames;
+ QSGVisualModelPrivate *parent = QSGVisualModelPrivate::get(static_cast<QSGVisualModel *>(q_ptr->parent()));
+ for (QList<QSGVisualModelRole *>::iterator it = parent->roles.begin(); it != parent->roles.end(); ++it) {
+ QByteArray name = (*it)->name().toUtf8();
+ int propId = m_delegateDataType->createProperty(name) - m_delegateDataType->propertyOffset();
+ QHash<QByteArray, int>::iterator it = roleNames.find(name);
+ if (it != roleNames.end()) {
+ m_roleToPropId.insert(*it, propId);
+ roleNames.erase(it);
+ }
+ }
+
+
+ if (m_roleNames.count()) {
+ QHash<QByteArray, int>::const_iterator it = roleNames.begin();
+ while (it != roleNames.end()) {
+ int propId = m_delegateDataType->createProperty(it.key()) - m_delegateDataType->propertyOffset();
+ m_roleToPropId.insert(*it, propId);
+ ++it;
+ }
+ // Add modelData property
+ if (m_roles.count() == 1)
+ m_modelDataPropId = m_delegateDataType->createProperty("modelData") - m_delegateDataType->propertyOffset();
+ m_metaDataCreated = true;
+ }
+ }
+ }
+
+ int modelCount() const {
+ if (m_listModelInterface)
+ return qMax(0, m_listModelInterface->count());
+ if (m_abstractItemModel)
+ return qMax(0, m_abstractItemModel->rowCount(m_root));
+ if (m_listAccessor)
+ return m_listAccessor->count();
+ return 0;
+ }
+
+ VDMDelegateDataType *m_delegateDataType;
+ friend class QSGVisualModelData;
+ bool m_metaDataCreated : 1;
+ bool m_metaDataCacheable : 1;
+ bool m_delegateValidated : 1;
+ bool m_completePending : 1;
+
+ QSGVisualModelData *data(QObject *item);
+
+ QVariant m_modelVariant;
+ QDeclarativeListAccessor *m_listAccessor;
+
+ QModelIndex m_root;
+ QList<QByteArray> watchedRoles;
+ QList<int> watchedRoleIds;
+ QList<int> changedRoles;
+};
+
+class QSGVisualModelDataMetaObject : public QDeclarativeOpenMetaObject
+{
+public:
+ QSGVisualModelDataMetaObject(QObject *parent, QDeclarativeOpenMetaObjectType *type)
+ : QDeclarativeOpenMetaObject(parent, type) {}
+
+ virtual QVariant initialValue(int);
+ virtual int createProperty(const char *, const char *);
+
+private:
+ friend class QSGVisualModelData;
+};
+
+class QSGVisualModelDataMetaObject;
+class QSGVisualModelData : public QObject
+{
+Q_OBJECT
+public:
+ QSGVisualModelData(int index, QSGVisualData *model);
+ QSGVisualModelData(QDeclarativeComponent *delegate, VDMDelegateDataType *dataType);
+ ~QSGVisualModelData();
+
+ Q_PROPERTY(int index READ index NOTIFY indexChanged)
+ int index() const;
+ void setIndex(int index);
+
+ int propForRole(int) const;
+ int modelDataPropertyId() const {
+ QSGVisualDataPrivate *model = QSGVisualDataPrivate::get(m_model);
+ return model->m_modelDataPropId;
+ }
+
+ void setValue(int, const QVariant &);
+ bool hasValue(int id) const {
+ return m_meta->hasValue(id);
+ }
+
+ QSGVisualData *model() const { return m_model; }
+ QDeclarativeComponent *delegate() const { return m_delegate; }
+
+ void ensureProperties();
+
+Q_SIGNALS:
+ void indexChanged();
+
+private:
+ friend class QSGVisualModelDataMetaObject;
+ int m_index;
+ QDeclarativeGuard<QSGVisualData> m_model;
+ QDeclarativeGuard<QDeclarativeComponent> m_delegate;
+ QSGVisualModelDataMetaObject *m_meta;
+};
+
+QSGVisualModelData *QSGVisualModelPrivate::createScriptData(QDeclarativeComponent *delegate, const QScriptValue &value)
+{
+ Q_Q(QSGVisualModel);
+ if (!delegateDataType) {
+ delegateDataType = new VDMDelegateDataType(
+ &QSGVisualModelData::staticMetaObject,
+ context ? context->engine() : qmlEngine(q));
+ for (QList<QSGVisualModelRole *>::iterator it = roles.begin(); it != roles.end(); ++it)
+ delegateDataType->createProperty((*it)->name().toUtf8());
+ }
+ QSGVisualModelData *data = new QSGVisualModelData(delegate, delegateDataType);
+ for (int i = 0; i < roles.count(); ++i) {
+ QScriptValue property = value.property(roles.at(i)->name());
+ data->setValue(i, property.isValid() ? property.toVariant() : roles.at(i)->defaultValue());
+ }
+ QDeclarative_setParent_noEvent(data, q);
+ return data;
+}
+
QSGVisualModel::QSGVisualModel(QObject *parent)
: QObject(*(new QSGVisualModelPrivate), parent)
{
@@ -339,6 +549,12 @@ QDeclarativeListProperty<QSGItem> QSGVisualModel::children()
d->children_count, d->children_at);
}
+QDeclarativeListProperty<QSGVisualModelRole> QSGVisualModel::roles()
+{
+ Q_D(QSGVisualModel);
+ return QDeclarativeListProperty<QSGVisualModelRole>(this, d, d->roles_append);
+}
+
QObject *QSGVisualModel::parts()
{
Q_D(QSGVisualModel);
@@ -353,7 +569,7 @@ int QSGVisualModel::count() const
return d->count();
}
-QSGItem *QSGVisualModel::item(int index, const QByteArray &viewId, bool complete)
+QObject *QSGVisualModel::object(int index, bool complete)
{
Q_D(QSGVisualModel);
int offset = 0;
@@ -361,7 +577,7 @@ QSGItem *QSGVisualModel::item(int index, const QByteArray &viewId, bool complete
QDeclarativeCompositeRange range = d->at(index, &offset, &internalIndex);
if (!range.internal()) {
QSGVisualData *model = static_cast<QSGVisualData *>(range.list);
- QSGItem *item = model->item(range.index + offset, viewId, complete);
+ QObject *item = model->object(range.index + offset, complete);
QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item);
attached->setModel(this);
attached->setData(model);
@@ -369,60 +585,129 @@ QSGItem *QSGVisualModel::item(int index, const QByteArray &viewId, bool complete
d->attachedItems.insert(attached);
if (model->completePending())
d->pendingModel = model;
- return item;
- } else {
- QSGVisualModelPrivate::Item &item = d->children[internalIndex];
- item.addRef();
- return item.item;
+ QSGVisualModelPrivate::ItemData itemData = { item, item->findChild<QSGVisualModelData *>() };
+ internalIndex = d->replaceAt(index, &itemData);
+ Q_ASSERT(internalIndex != -1);
+ // createdObject() instead?
+ if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(item))
+ emit createdPackage(index, package);
}
+ QSGVisualModelPrivate::Item &item = d->children[internalIndex];
+ if (!item.item) {
+ if (!item.data || !item.data->delegate()) {
+ qmlInfo(this) << "No delegate for item";
+ return 0;
+ }
+ QDeclarativeComponent *delegate = item.data->delegate();
+ QDeclarativeContext *ccontext = d->context;
+ if (!ccontext) ccontext = qmlContext(this);
+ QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
+ ctxt->setContextProperty(QLatin1String("model"), item.data);
+ ctxt->setContextObject(item.data);
+ item.item = delegate->beginCreate(ctxt);
+ if (complete) {
+ delegate->completeCreate();
+ } else {
+ d->pendingComponent = delegate;
+ }
+ if (item.item) {
+ QDeclarative_setParent_noEvent(ctxt, item.item);
+ QDeclarative_setParent_noEvent(item.data, item.item);
+ } else {
+ delete ctxt;
+ qmlInfo(this, delegate->errors()) << "Error creating delegate";
+ return 0;
+ }
+ }
+ item.addRef();
+ return item.item;
+}
+
+QSGItem *QSGVisualModel::item(int index, bool complete)
+{
+ QObject *obj = object(index, complete);
+ if (QSGItem *item = qobject_cast<QSGItem *>(obj))
+ return item;
+ release(obj);
+ return 0;
}
-QSGItem *QSGVisualModel::item(int index)
+QSGItem *QSGVisualModel::item(int index, const QByteArray &viewId, bool complete)
{
- return item(index, QByteArray());
+ QObject *pobj = object(index, complete);
+ if (QSGItem *item = qobject_cast<QSGItem *>(pobj)) {
+ return item;
+ } else if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(pobj)) {
+ QObject *iobj = package->part(QString::fromUtf8(viewId));
+ if (QSGItem *item = qobject_cast<QSGItem *>(iobj))
+ return item;
+ }
+ if (pobj)
+ release(pobj);
+ return 0;
}
QSGItem *QSGVisualModel::take(int index, QSGItem *parent)
{
- Q_D(QSGVisualModel);
QSGItem *i = item(index);
remove(index, 1);
i->setParentItem(parent);
-
return i;
}
-QSGVisualModel::ReleaseFlags QSGVisualModel::release(QSGItem *item)
+QSGVisualModel::ReleaseFlags QSGVisualModel::release(QObject *object)
{
Q_D(QSGVisualModel);
- QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item);
- if (QSGVisualData *model = attached->m_data) {
- return model->release(item);
- } else {
- int idx = d->indexOf(item);
- if (idx >= 0) {
- if (d->children[idx].deref()) {
- // XXX todo - the original did item->scene()->removeItem(). Why?
- item->setParentItem(0);
- QDeclarative_setParent_noEvent(item, this);
+ QSGVisualModel::ReleaseFlags stat = 0;
+
+ int idx = d->indexOf(object);
+ if (idx >= 0) {
+ if (d->children[idx].deref()) {
+ if (QSGVisualData *model = d->children[idx].data->model()) {
+ d->children[idx].item = 0; // Clearing the data should delete this node.
+ d->children[idx].data = 0;
+ d->clearData(idx, 1);
+ if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(object))
+ emit destroyingPackage(package);
+ model->release(object);
+ stat |= Destroyed;
+ } else {
+ if (QSGItem *item = qobject_cast<QSGItem *>(object))
+ item->setParentItem(0);
+ if (d->children[idx].data) {
+ d->children[idx].item = 0;
+ QDeclarative_setParent_noEvent(d->children[idx].data, this);
+ object->deleteLater();
+ stat |= Destroyed;
+ } else {
+ QDeclarative_setParent_noEvent(object, this);
+ stat |= Referenced;
+ }
}
} else {
- QHash<QSGItem *, int>::iterator it = d->removedItems.find(item);
- if (it != d->removedItems.end()) {
- if (--(*it) == 0) {
- delete it.key();
- d->removedItems.erase(it);
- }
+ stat |= Referenced;
+ }
+ } else {
+ QHash<QObject *, int>::iterator it = d->removedItems.find(object);
+ if (it != d->removedItems.end()) {
+ if (--(*it) == 0) {
+ if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(object))
+ emit destroyingPackage(package);
+ it.key()->deleteLater();
+ d->removedItems.erase(it);
+ return Destroyed;
+ } else {
+ stat |= Referenced;
}
}
}
- return 0;
+ return stat;
}
bool QSGVisualModel::completePending() const
{
Q_D(const QSGVisualModel);
- return d->pendingModel;
+ return d->pendingModel || d->pendingComponent;
}
void QSGVisualModel::completeItem()
@@ -431,6 +716,9 @@ void QSGVisualModel::completeItem()
if (d->pendingModel) {
d->pendingModel->completeItem();
d->pendingModel = 0;
+ } else if (d->pendingComponent) {
+ d->pendingComponent->completeCreate();
+ d->pendingComponent = 0;
}
}
@@ -442,7 +730,7 @@ QString QSGVisualModel::stringValue(int index, const QString &name)
return QDeclarativeEngine::contextForObject(d->children.at(index).item)->contextProperty(name).toString();
}
-int QSGVisualModel::indexOf(QSGItem *item, QObject *context) const
+int QSGVisualModel::indexOf(QObject *item, QObject *context) const
{
Q_D(const QSGVisualModel);
QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item);
@@ -491,9 +779,12 @@ void QSGVisualModel::append(QSGItem *item)
d->connectModel(model);
inserted = true;
}
- } else if (d->appendData(item)) {
- d->attachedItems.insert(attached);
- inserted = true;
+ } else {
+ QSGVisualModelPrivate::ItemData itemData = { item, item->findChild<QSGVisualModelData *>() };
+ if (d->appendData(&itemData)) {
+ d->attachedItems.insert(attached);
+ inserted = true;
+ }
}
if (inserted) {
QSGVisualModelAttached *attached = QSGVisualModelAttached::properties(item);
@@ -540,6 +831,35 @@ void QSGVisualModel::append(QSGVisualModel *sourceModel, int sourceIndex, int co
emit sourceModel->countChanged();
}
+void QSGVisualModel::append(QDeclarativeComponent *delegate, const QVariant &model, int sourceIndex, int count)
+{
+ Q_D(QSGVisualModel);
+ int destinationIndex = d->count();
+
+ QSGVisualData *data = new QSGVisualData(d->context ? d->context.data() : qmlContext(this), this);
+ data->setDelegate(delegate);
+ data->setModel(model);
+
+ d->connectModel(data);
+ d->appendList(data, sourceIndex, count, false);
+
+ emit itemsInserted(destinationIndex, count);
+}
+
+void QSGVisualModel::append(QDeclarativeComponent *delegate, const QScriptValue &value)
+{
+ Q_D(QSGVisualModel);
+
+ int destinationIndex = d->count();
+
+ QSGVisualModelData *data = d->createScriptData(delegate, value);
+ QSGVisualModelPrivate::ItemData itemData = { 0, data };
+ if (d->appendData(&itemData))
+ emit itemsInserted(destinationIndex, 1);
+ else
+ delete data;
+}
+
void QSGVisualModel::insert(int index, QSGItem *item)
{
Q_D(QSGVisualModel);
@@ -553,9 +873,12 @@ void QSGVisualModel::insert(int index, QSGItem *item)
d->connectModel(model);
inserted = true;
}
- } else if (d->insertData(index, item)) {
- d->attachedItems.insert(attached);
- inserted = true;
+ } else {
+ QSGVisualModelPrivate::ItemData itemData = { item, item->findChild<QSGVisualModelData *>() };
+ if (d->insertData(index, &itemData)) {
+ d->attachedItems.insert(attached);
+ inserted = true;
+ }
}
if (inserted) {
attached->setModel(this);
@@ -604,6 +927,33 @@ void QSGVisualModel::insert(int destinationIndex, QSGVisualModel *sourceModel, i
emit sourceModel->countChanged();
}
+void QSGVisualModel::insert(int destinationIndex, QDeclarativeComponent *delegate, const QVariant &model, int sourceIndex, int count)
+{
+ Q_D(QSGVisualModel);
+
+ QSGVisualData *data = new QSGVisualData(d->context ? d->context.data() : qmlContext(this), this);
+ data->setDelegate(delegate);
+ data->setModel(model);
+
+ d->connectModel(data);
+ d->insertList(destinationIndex, data, sourceIndex, count, false);
+
+ emit itemsInserted(destinationIndex, count);
+}
+
+void QSGVisualModel::insert(int index, QDeclarativeComponent *delegate, const QScriptValue &value)
+{
+ Q_D(QSGVisualModel);
+
+ QSGVisualModelData *data = d->createScriptData(delegate, value);
+ QSGVisualModelPrivate::ItemData itemData = { 0, data };
+
+ if (d->appendData(&itemData))
+ emit itemsInserted(index, 1);
+ else
+ delete data;
+}
+
void QSGVisualModel::remove(int index, int count)
{
Q_D(QSGVisualModel);
@@ -650,7 +1000,14 @@ void QSGVisualModel::_q_itemsInserted(QSGVisualData *model, int index, int count
d->listItemsInserted(model, index, index + count, &inserts);
if (inserts.count() > 0) {
- d->invalidateIndexes(index);
+ for (int i = 0; i < d->children.count(); ++i) {
+ QSGVisualModelPrivate::Item &item = d->children[i];
+ if (item.data && item.data->model() == model) {
+ if (item.data->index() >= index)
+ item.data->setIndex(item.data->index() + count);
+ }
+ }
+ d->invalidateIndexes(inserts.first().start);
QDeclarativeEngine *dengine = d->context ? d->context->engine() : qmlEngine(this);
QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(dengine);
QScriptValue insertIndexes = engine->newArray(inserts.count());
@@ -679,12 +1036,21 @@ void QSGVisualModel::_q_itemsRemoved(QSGVisualData *model, int index, int count)
QVector<QDeclarativeChangeSet::Remove> removes;
d->childrenChanged = false;
d->listItemsRemoved(model, index, index + count, &removes);
- d->transactionChanges.append(removes);
- d->invalidateIndexes(index);
- d->emitTransactionChanges();
- emit countChanged();
- if (d->childrenChanged)
- emit childrenChanged();
+ if (!removes.isEmpty()) {
+ d->transactionChanges.append(removes);
+ d->invalidateIndexes(removes.first().start);
+ for (int i = 0; i < d->children.count(); ++i) {
+ QSGVisualModelPrivate::Item &item = d->children[i];
+ if (item.data && item.data->model() == model) {
+ if (item.data->index() >= index + count)
+ item.data->setIndex(item.data->index() - count);
+ }
+ }
+ d->emitTransactionChanges();
+ emit countChanged();
+ if (d->childrenChanged)
+ emit childrenChanged();
+ }
}
void QSGVisualModel::_q_itemsMoved(QSGVisualData *model, int from, int to, int count)
@@ -693,24 +1059,48 @@ void QSGVisualModel::_q_itemsMoved(QSGVisualData *model, int from, int to, int c
QVector<QDeclarativeChangeSet::Move> moves;
d->childrenChanged = false;
d->listItemsMoved(model, from, from + count, to, &moves);
- d->transactionChanges.append(moves);
- d->invalidateIndexes(qMin(from, to), qMax(from, to) + count);
- d->emitTransactionChanges();
- if (d->childrenChanged)
- emit childrenChanged();
+ if (!moves.isEmpty()) {
+ d->transactionChanges.append(moves);
+ const int min = qMin(from, to);
+ const int max = qMax(from, to) + count;
+ const int diff = from > to ? count : -count;
+ for (int i = 0; i < d->children.count(); ++i) {
+ QSGVisualModelPrivate::Item &item = d->children[i];
+ if (item.data && item.data->model() == model) {
+ if (item.data->index() >= from && item.data->index() < from + count)
+ item.data->setIndex(item.data->index() - from + to);
+ else if (item.data->index() >= min && item.data->index() < max)
+ item.data->setIndex(item.data->index() + diff);
+ }
+ }
+ d->invalidateIndexes(0);
+ for (int i = 0; i < d->children.count(); ++i) {
+ QSGVisualModelPrivate::Item &item = d->children[i];
+ if (item.data && item.data->model() == model) {
+ model->updateData(item.data->index(), item.item);
+ }
+ }
+ d->emitTransactionChanges();
+ if (d->childrenChanged)
+ emit childrenChanged();
+ }
}
-void QSGVisualModel::_q_createdPackage(QSGVisualData *model, int index, QDeclarativePackage *package)
+void QSGVisualModel::_q_itemsChanged(QSGVisualData *model, int index, int count)
{
Q_D(QSGVisualModel);
- int absoluteIndex = d->absoluteIndexOf(model, index);
- if (absoluteIndex != -1)
- emit createdPackage(absoluteIndex, package);
-}
-
-void QSGVisualModel::_q_destroyingPackage(QDeclarativePackage *package)
-{
- emit destroyingPackage(package);
+ QVector<QDeclarativeChangeSet::Change> changes;
+ d->listItemsChanged(model, index, index + count, &changes);
+
+ if (!changes.isEmpty()) {
+ d->transactionChanges.append(changes);
+ for (int i = 0; i < d->children.count(); ++i) {
+ QSGVisualModelPrivate::Item &item = d->children[i];
+ if (item.data && item.data->model() == model)
+ model->updateData(item.data->index(), item.item);
+ }
+ d->emitTransactionChanges();
+ }
}
QSGVisualModelAttached *QSGVisualModel::qmlAttachedProperties(QObject *obj)
@@ -719,204 +1109,6 @@ QSGVisualModelAttached *QSGVisualModel::qmlAttachedProperties(QObject *obj)
}
//============================================================================
-
-class VDMDelegateDataType : public QDeclarativeOpenMetaObjectType
-{
-public:
- VDMDelegateDataType(const QMetaObject *base, QDeclarativeEngine *engine) : QDeclarativeOpenMetaObjectType(base, engine) {}
-
- void propertyCreated(int, QMetaPropertyBuilder &prop) {
- prop.setWritable(false);
- }
-};
-
-class QSGVisualDataParts;
-class QSGVisualModelData;
-class QSGVisualDataPrivate : public QObjectPrivate
-{
-public:
- QSGVisualDataPrivate(QDeclarativeContext *);
-
- static QSGVisualDataPrivate *get(QSGVisualData *m) {
- return static_cast<QSGVisualDataPrivate *>(QObjectPrivate::get(m));
- }
-
- QDeclarativeGuard<QListModelInterface> m_listModelInterface;
- QDeclarativeGuard<QAbstractItemModel> m_abstractItemModel;
- QString m_part;
-
- QDeclarativeComponent *m_delegate;
- QDeclarativeGuard<QDeclarativeContext> m_context;
- QList<int> m_roles;
- QHash<QByteArray,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)).toUtf8(), m_roles.at(ii));
- } 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(*it, it.key());
- }
- if (m_roles.count())
- m_roleNames.insert("hasModelChildren", -1);
- } else if (m_listAccessor) {
- m_roleNames.insert("modelData", 0);
- if (m_listAccessor->type() == QDeclarativeListAccessor::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(prop.name(), 0);
- }
- }
- }
- }
- }
- }
-
- QHash<int,int> m_roleToPropId;
- int m_modelDataPropId;
- void createMetaData() {
- if (!m_metaDataCreated) {
- ensureRoles();
- if (m_roleNames.count()) {
- QHash<QByteArray, int>::const_iterator it = m_roleNames.begin();
- while (it != m_roleNames.end()) {
- int propId = m_delegateDataType->createProperty(it.key()) - m_delegateDataType->propertyOffset();
- m_roleToPropId.insert(*it, propId);
- ++it;
- }
- // Add modelData property
- if (m_roles.count() == 1)
- m_modelDataPropId = m_delegateDataType->createProperty("modelData") - m_delegateDataType->propertyOffset();
- m_metaDataCreated = true;
- }
- }
- }
-
- struct ObjectRef {
- ObjectRef(QObject *object=0) : obj(object), ref(1) {}
- QObject *obj;
- int ref;
- };
- class Cache : public QHash<int, ObjectRef> {
- public:
- QObject *getItem(int index) {
- QObject *item = 0;
- QHash<int,ObjectRef>::iterator it = find(index);
- if (it != end()) {
- (*it).ref++;
- item = (*it).obj;
- }
- return item;
- }
- QObject *item(int index) {
- QObject *item = 0;
- QHash<int, ObjectRef>::const_iterator it = find(index);
- if (it != end())
- item = (*it).obj;
- return item;
- }
- void insertItem(int index, QObject *obj) {
- insert(index, ObjectRef(obj));
- }
- bool releaseItem(QObject *obj) {
- QHash<int, ObjectRef>::iterator it = begin();
- for (; it != end(); ++it) {
- ObjectRef &objRef = *it;
- if (objRef.obj == obj) {
- if (--objRef.ref == 0) {
- erase(it);
- return true;
- }
- break;
- }
- }
- return false;
- }
- };
-
- int modelCount() const {
- if (m_listModelInterface)
- return qMax(0, m_listModelInterface->count());
- if (m_abstractItemModel)
- return qMax(0, m_abstractItemModel->rowCount(m_root));
- if (m_listAccessor)
- return m_listAccessor->count();
- return 0;
- }
-
- Cache m_cache;
- QHash<QObject *, QDeclarativePackage*> m_packaged;
-
- VDMDelegateDataType *m_delegateDataType;
- friend class QSGVisualModelData;
- bool m_metaDataCreated : 1;
- bool m_metaDataCacheable : 1;
- bool m_delegateValidated : 1;
- bool m_completePending : 1;
-
- QSGVisualModelData *data(QObject *item);
-
- QVariant m_modelVariant;
- QDeclarativeListAccessor *m_listAccessor;
-
- QModelIndex m_root;
- QList<QByteArray> watchedRoles;
- QList<int> watchedRoleIds;
-};
-
-class QSGVisualModelDataMetaObject : public QDeclarativeOpenMetaObject
-{
-public:
- QSGVisualModelDataMetaObject(QObject *parent, QDeclarativeOpenMetaObjectType *type)
- : QDeclarativeOpenMetaObject(parent, type) {}
-
- virtual QVariant initialValue(int);
- virtual int createProperty(const char *, const char *);
-
-private:
- friend class QSGVisualModelData;
-};
-
-class QSGVisualModelData : public QObject
-{
-Q_OBJECT
-public:
- QSGVisualModelData(int index, QSGVisualData *model);
- ~QSGVisualModelData();
-
- Q_PROPERTY(int index READ index NOTIFY indexChanged)
- int index() const;
- void setIndex(int index);
-
- int propForRole(int) const;
- int modelDataPropertyId() const {
- QSGVisualDataPrivate *model = QSGVisualDataPrivate::get(m_model);
- return model->m_modelDataPropId;
- }
-
- void setValue(int, const QVariant &);
- bool hasValue(int id) const {
- return m_meta->hasValue(id);
- }
-
- void ensureProperties();
-
-Q_SIGNALS:
- void indexChanged();
-
-private:
- friend class QSGVisualModelDataMetaObject;
- int m_index;
- QDeclarativeGuard<QSGVisualData> m_model;
- QSGVisualModelDataMetaObject *m_meta;
-};
-
int QSGVisualModelData::propForRole(int id) const
{
QSGVisualDataPrivate *model = QSGVisualDataPrivate::get(m_model);
@@ -1001,8 +1193,9 @@ QVariant QSGVisualModelDataMetaObject::initialValue(int propId)
}
}
}
- Q_ASSERT(!"Can never be reached");
- return QVariant();
+
+ QSGVisualModelPrivate *visualModel = QSGVisualModelPrivate::get(static_cast<QSGVisualModel *>(data->m_model->parent()));
+ return visualModel->roles.at(propId)->defaultValue();
}
QSGVisualModelData::QSGVisualModelData(int index,
@@ -1013,6 +1206,12 @@ m_meta(new QSGVisualModelDataMetaObject(this, QSGVisualDataPrivate::get(model)->
ensureProperties();
}
+QSGVisualModelData::QSGVisualModelData(QDeclarativeComponent *delegate, VDMDelegateDataType *dataType)
+ : m_index(-1), m_delegate(delegate), m_meta(new QSGVisualModelDataMetaObject(this, dataType))
+{
+ m_meta->setCached(true);
+}
+
QSGVisualModelData::~QSGVisualModelData()
{
}
@@ -1231,109 +1430,59 @@ int QSGVisualData::count() const
/*
Returns ReleaseStatus flags.
*/
-QSGVisualModel::ReleaseFlags QSGVisualData::release(QSGItem *item)
+void QSGVisualData::release(QObject *obj)
{
- Q_D(QSGVisualData);
- QSGVisualModel::ReleaseFlags stat = 0;
- QObject *obj = item;
- bool inPackage = false;
-
- QHash<QObject*,QDeclarativePackage*>::iterator it = d->m_packaged.find(item);
- if (it != d->m_packaged.end()) {
- QDeclarativePackage *package = *it;
- d->m_packaged.erase(it);
- if (d->m_packaged.contains(item))
- stat |= QSGVisualModel::Referenced;
- inPackage = true;
- obj = package; // fall through and delete
- }
-
- if (d->m_cache.releaseItem(obj)) {
- // Remove any bindings to avoid warnings due to parent change.
- QObjectPrivate *p = QObjectPrivate::get(obj);
- Q_ASSERT(p->declarativeData);
- QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
- if (d->ownContext && d->context)
- d->context->clearContext();
-
- if (inPackage) {
- emit destroyingPackage(qobject_cast<QDeclarativePackage*>(obj));
- } else {
- // XXX todo - the original did item->scene()->removeItem(). Why?
- item->setParentItem(0);
- }
- stat |= QSGVisualModel::Destroyed;
- obj->deleteLater();
- } else if (!inPackage) {
- stat |= QSGVisualModel::Referenced;
- }
+ // Remove any bindings to avoid warnings due to parent change.
+ QObjectPrivate *p = QObjectPrivate::get(obj);
+ Q_ASSERT(p->declarativeData);
+ QDeclarativeData *d = static_cast<QDeclarativeData*>(p->declarativeData);
+ if (d->ownContext && d->context)
+ d->context->clearContext();
- return stat;
+ // XXX todo - the original did item->scene()->removeItem(). Why?
+ if (QSGItem *item = qobject_cast<QSGItem *>(obj))
+ item->setParentItem(0);
+ obj->deleteLater();
}
-QSGItem *QSGVisualData::item(int index, const QByteArray &viewId, bool complete)
+QObject *QSGVisualData::object(int index, bool complete)
{
Q_D(QSGVisualData);
if (d->modelCount() <= 0 || !d->m_delegate)
return 0;
- QObject *nobj = d->m_cache.getItem(index);
bool needComplete = false;
- if (!nobj) {
- QDeclarativeContext *ccontext = d->m_context;
- if (!ccontext) ccontext = qmlContext(this);
- if (!ccontext) ccontext = qmlContext(parent());
- QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
- QSGVisualModelData *data = new QSGVisualModelData(index, this);
- if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor
- && d->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
- ctxt->setContextObject(d->m_listAccessor->at(index).value<QObject*>());
- ctxt = new QDeclarativeContext(ctxt, ctxt);
- }
- ctxt->setContextProperty(QLatin1String("model"), data);
- ctxt->setContextObject(data);
- d->m_completePending = false;
- nobj = d->m_delegate->beginCreate(ctxt);
- if (complete) {
- d->m_delegate->completeCreate();
- } else {
- d->m_completePending = true;
- needComplete = true;
- }
- if (nobj) {
- QDeclarative_setParent_noEvent(ctxt, nobj);
- QDeclarative_setParent_noEvent(data, nobj);
- d->m_cache.insertItem(index, nobj);
- if (QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj))
- emit createdPackage(this, index, package);
- } else {
- delete data;
- delete ctxt;
- qmlInfo(this, d->m_delegate->errors()) << "Error creating delegate";
- }
+ QDeclarativeContext *ccontext = d->m_context;
+ if (!ccontext) ccontext = qmlContext(this);
+ if (!ccontext) ccontext = qmlContext(parent());
+ QDeclarativeContext *ctxt = new QDeclarativeContext(ccontext);
+ QSGVisualModelData *data = new QSGVisualModelData(index, this);
+ if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor
+ && d->m_listAccessor->type() == QDeclarativeListAccessor::ListProperty) {
+ ctxt->setContextObject(d->m_listAccessor->at(index).value<QObject*>());
+ ctxt = new QDeclarativeContext(ctxt, ctxt);
}
- QSGItem *item = qobject_cast<QSGItem *>(nobj);
- if (!item) {
- QDeclarativePackage *package = qobject_cast<QDeclarativePackage *>(nobj);
- if (package) {
- QObject *o = package->part(QString::fromUtf8(viewId));
- item = qobject_cast<QSGItem *>(o);
- if (item)
- d->m_packaged.insertMulti(item, package);
- }
+ ctxt->setContextProperty(QLatin1String("model"), data);
+ ctxt->setContextObject(data);
+ d->m_completePending = false;
+ QObject *nobj = d->m_delegate->beginCreate(ctxt);
+ if (complete) {
+ d->m_delegate->completeCreate();
+ } else {
+ d->m_completePending = true;
+ needComplete = true;
}
- if (!item) {
- if (needComplete)
- d->m_delegate->completeCreate();
- d->m_cache.releaseItem(nobj);
- if (!d->m_delegateValidated) {
- qmlInfo(d->m_delegate) << QSGVisualData::tr("Delegate component must be Item type.");
- d->m_delegateValidated = true;
- }
+ if (nobj) {
+ QDeclarative_setParent_noEvent(ctxt, nobj);
+ QDeclarative_setParent_noEvent(data, nobj);
+ } else {
+ delete data;
+ delete ctxt;
+ qmlInfo(this, d->m_delegate->errors()) << "Error creating delegate";
}
if (d->modelCount()-1 == index && d->m_abstractItemModel && d->m_abstractItemModel->canFetchMore(d->m_root))
d->m_abstractItemModel->fetchMore(d->m_root);
- return item;
+ return nobj;
}
bool QSGVisualData::completePending() const
@@ -1349,7 +1498,7 @@ void QSGVisualData::completeItem()
d->m_completePending = false;
}
-QString QSGVisualData::stringValue(int index, const QString &name)
+QString QSGVisualData::stringValue(int index, QObject *nobj, const QString &name)
{
Q_D(QSGVisualData);
if ((!d->m_listModelInterface || !d->m_abstractItemModel) && d->m_listAccessor) {
@@ -1364,7 +1513,7 @@ QString QSGVisualData::stringValue(int index, const QString &name)
QObject *data = 0;
bool tempData = false;
- if (QObject *nobj = d->m_cache.item(index))
+ if (nobj)
data = d->data(nobj);
if (!data) {
data = new QSGVisualModelData(index, this);
@@ -1397,9 +1546,9 @@ QString QSGVisualData::stringValue(int index, const QString &name)
return val;
}
-int QSGVisualData::indexOf(QSGItem *item, QObject *) const
+int QSGVisualData::indexOf(QObject *object, QObject *) const
{
- QVariant val = QDeclarativeEngine::contextForObject(item)->contextProperty(QLatin1String("index"));
+ QVariant val = QDeclarativeEngine::contextForObject(object)->contextProperty(QLatin1String("index"));
return val.toInt();
return -1;
}
@@ -1411,11 +1560,53 @@ void QSGVisualData::setWatchedRoles(QList<QByteArray> roles)
d->watchedRoleIds.clear();
}
-void QSGVisualData::_q_itemsChanged(int index, int count,
- const QList<int> &roles)
+bool QSGVisualData::updateData(int idx, QObject *object)
{
Q_D(QSGVisualData);
bool changed = false;
+ QSGVisualModelData *data = d->data(object);
+ for (int roleIdx = 0; roleIdx < d->changedRoles.count(); ++roleIdx) {
+ int role = d->changedRoles.at(roleIdx);
+ if (!changed && !d->watchedRoleIds.isEmpty() && d->watchedRoleIds.contains(role))
+ changed = true;
+ int propId = data->propForRole(role);
+ if (propId != -1) {
+ if (data->hasValue(propId)) {
+ if (d->m_listModelInterface) {
+ data->setValue(propId, d->m_listModelInterface->data(idx, role));
+ } else if (d->m_abstractItemModel) {
+ QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
+ data->setValue(propId, d->m_abstractItemModel->data(index, role));
+ }
+ }
+ } else {
+ QString roleName;
+ if (d->m_listModelInterface)
+ roleName = d->m_listModelInterface->toString(role);
+ else if (d->m_abstractItemModel)
+ roleName = QString::fromUtf8(d->m_abstractItemModel->roleNames().value(role));
+ qmlInfo(this) << "Changing role not present in item: " << roleName;
+ }
+ }
+ if (d->changedRoles.count() == 1) {
+ // Handle the modelData role we add if there is just one role.
+ int propId = data->modelDataPropertyId();
+ if (data->hasValue(propId)) {
+ int role = d->changedRoles.at(0);
+ if (d->m_listModelInterface) {
+ data->setValue(propId, d->m_listModelInterface->data(idx, role));
+ } else if (d->m_abstractItemModel) {
+ QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
+ data->setValue(propId, d->m_abstractItemModel->data(index, role));
+ }
+ }
+ }
+ return changed;
+}
+
+void QSGVisualData::_q_itemsChanged(int index, int count, const QList<int> &roles)
+{
+ Q_D(QSGVisualData);
if (!d->watchedRoles.isEmpty() && d->watchedRoleIds.isEmpty()) {
foreach (QByteArray r, d->watchedRoles) {
if (d->m_roleNames.contains(r))
@@ -1423,154 +1614,28 @@ void QSGVisualData::_q_itemsChanged(int index, int count,
}
}
- for (QHash<int,QSGVisualDataPrivate::ObjectRef>::ConstIterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ++iter) {
- const int idx = iter.key();
-
- if (idx >= index && idx < index+count) {
- QSGVisualDataPrivate::ObjectRef objRef = *iter;
- QSGVisualModelData *data = d->data(objRef.obj);
- for (int roleIdx = 0; roleIdx < roles.count(); ++roleIdx) {
- int role = roles.at(roleIdx);
- if (!changed && !d->watchedRoleIds.isEmpty() && d->watchedRoleIds.contains(role))
- changed = true;
- int propId = data->propForRole(role);
- if (propId != -1) {
- if (data->hasValue(propId)) {
- if (d->m_listModelInterface) {
- data->setValue(propId, d->m_listModelInterface->data(idx, role));
- } else if (d->m_abstractItemModel) {
- QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
- data->setValue(propId, d->m_abstractItemModel->data(index, role));
- }
- }
- } else {
- QString roleName;
- if (d->m_listModelInterface)
- roleName = d->m_listModelInterface->toString(role);
- else if (d->m_abstractItemModel)
- roleName = QString::fromUtf8(d->m_abstractItemModel->roleNames().value(role));
- qmlInfo(this) << "Changing role not present in item: " << roleName;
- }
- }
- if (d->m_roles.count() == 1) {
- // Handle the modelData role we add if there is just one role.
- int propId = data->modelDataPropertyId();
- if (data->hasValue(propId)) {
- int role = d->m_roles.at(0);
- if (d->m_listModelInterface) {
- data->setValue(propId, d->m_listModelInterface->data(idx, role));
- } else if (d->m_abstractItemModel) {
- QModelIndex index = d->m_abstractItemModel->index(idx, 0, d->m_root);
- data->setValue(propId, d->m_abstractItemModel->data(index, role));
- }
- }
- }
- }
- }
- if (changed)
- emit itemsChanged(this, index, count);
+ d->changedRoles = roles;
+ emit itemsChanged(this, index, count);
}
void QSGVisualData::_q_itemsInserted(int index, int count)
{
- Q_D(QSGVisualData);
if (!count)
return;
- // XXX - highly inefficient
- QHash<int,QSGVisualDataPrivate::ObjectRef> items;
- for (QHash<int,QSGVisualDataPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ) {
-
- if (iter.key() >= index) {
- QSGVisualDataPrivate::ObjectRef objRef = *iter;
- int index = iter.key() + count;
- iter = d->m_cache.erase(iter);
-
- items.insert(index, objRef);
-
- QSGVisualModelData *data = d->data(objRef.obj);
- data->setIndex(index);
- } else {
- ++iter;
- }
- }
- d->m_cache.unite(items);
-
emit itemsInserted(this, index, count);
}
void QSGVisualData::_q_itemsRemoved(int index, int count)
{
- Q_D(QSGVisualData);
if (!count)
return;
- // XXX - highly inefficient
- QHash<int, QSGVisualDataPrivate::ObjectRef> items;
- for (QHash<int, QSGVisualDataPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ) {
- if (iter.key() >= index && iter.key() < index + count) {
- QSGVisualDataPrivate::ObjectRef objRef = *iter;
- iter = d->m_cache.erase(iter);
- items.insertMulti(-1, objRef); //XXX perhaps better to maintain separately
- QSGVisualModelData *data = d->data(objRef.obj);
- data->setIndex(-1);
- } else if (iter.key() >= index + count) {
- QSGVisualDataPrivate::ObjectRef objRef = *iter;
- int index = iter.key() - count;
- iter = d->m_cache.erase(iter);
- items.insert(index, objRef);
- QSGVisualModelData *data = d->data(objRef.obj);
- data->setIndex(index);
- } else {
- ++iter;
- }
- }
-
- d->m_cache.unite(items);
emit itemsRemoved(this, index, count);
}
void QSGVisualData::_q_itemsMoved(int from, int to, int count)
{
- Q_D(QSGVisualData);
- // XXX - highly inefficient
- QHash<int,QSGVisualDataPrivate::ObjectRef> items;
- for (QHash<int,QSGVisualDataPrivate::ObjectRef>::Iterator iter = d->m_cache.begin();
- iter != d->m_cache.end(); ) {
-
- if (iter.key() >= from && iter.key() < from + count) {
- QSGVisualDataPrivate::ObjectRef objRef = *iter;
- int index = iter.key() - from + to;
- iter = d->m_cache.erase(iter);
-
- items.insert(index, objRef);
-
- QSGVisualModelData *data = d->data(objRef.obj);
- data->setIndex(index);
- } else {
- ++iter;
- }
- }
- for (QHash<int,QSGVisualDataPrivate::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)) {
- QSGVisualDataPrivate::ObjectRef objRef = *iter;
- int index = iter.key() + diff;
- iter = d->m_cache.erase(iter);
-
- items.insert(index, objRef);
-
- QSGVisualModelData *data = d->data(objRef.obj);
- data->setIndex(index);
- } else {
- ++iter;
- }
- }
- d->m_cache.unite(items);
-
+ if (!count || from == to)
+ return;
emit itemsMoved(this, from, to, count);
}
@@ -1709,7 +1774,10 @@ void QSGVisualDataModel::setRootIndex(const QVariant &root)
QVariant QSGVisualDataModel::modelIndex(int idx) const
{
Q_D(const QSGVisualDataModel);
- return d->data->modelIndex(idx);
+ int offset = 0;
+ int internalIndex = 0;
+ QDeclarativeCompositeRange range = d->at(idx, &offset, &internalIndex);
+ return range.list == d->data ? d->data->modelIndex(range.index + offset) : QVariant();
}
QVariant QSGVisualDataModel::parentModelIndex() const
@@ -1718,6 +1786,16 @@ QVariant QSGVisualDataModel::parentModelIndex() const
return d->data->parentModelIndex();
}
+void QSGVisualDataModel::appendData(const QScriptValue &value)
+{
+ append(delegate(), value);
+}
+
+void QSGVisualDataModel::insertData(int index, const QScriptValue &value)
+{
+ insert(index, delegate(), value);
+}
+
QSGVisualPartModel::QSGVisualPartModel(QSGVisualModel *model, const QByteArray &part, QObject *parent)
: QObject(parent), m_model(model), m_part(part)
{
diff --git a/src/declarative/items/qsgvisualitemmodel_p.h b/src/declarative/items/qsgvisualitemmodel_p.h
index 4267f01fe1..d4a7084fa3 100644
--- a/src/declarative/items/qsgvisualitemmodel_p.h
+++ b/src/declarative/items/qsgvisualitemmodel_p.h
@@ -67,6 +67,7 @@ class QSGVisualDataModelPrivate;
class QSGVisualData;
class QSGVisualModelAttached;
+class QSGVisualModelRole;
class QSGVisualModelPrivate;
class Q_DECLARATIVE_EXPORT QSGVisualModel : public QObject
{
@@ -76,6 +77,7 @@ class Q_DECLARATIVE_EXPORT QSGVisualModel : public QObject
Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(QDeclarativeListProperty<QObject> data READ data DESIGNABLE false)
Q_PROPERTY(QDeclarativeListProperty<QSGItem> children READ children NOTIFY childrenChanged DESIGNABLE false)
+ Q_PROPERTY(QDeclarativeListProperty<QSGVisualModelRole> roles READ roles CONSTANT)
Q_PROPERTY(QObject *parts READ parts CONSTANT)
Q_CLASSINFO("DefaultProperty", "data")
@@ -88,32 +90,38 @@ public:
virtual ~QSGVisualModel() {}
int count() const;
- QSGItem *item(int index, const QByteArray &, bool complete=true);
- ReleaseFlags release(QSGItem *item);
+ QObject *object(int index, bool complete = true);
+ ReleaseFlags release(QObject *item);
bool completePending() const;
void completeItem();
QString stringValue(int index, const QString &role);
void setWatchedRoles(QList<QByteArray>) {}
- virtual int indexOf(QSGItem *item, QObject *objectContext) const;
+ virtual int indexOf(QObject *item, QObject *objectContext) const;
Q_INVOKABLE QScriptValue getItemInfo(int index) const;
QDeclarativeListProperty<QObject> data();
QDeclarativeListProperty<QSGItem> children();
+ QDeclarativeListProperty<QSGVisualModelRole> roles();
QObject *parts();
static QSGVisualModelAttached *qmlAttachedProperties(QObject *obj);
- Q_INVOKABLE QSGItem *item(int index);
+ Q_INVOKABLE QSGItem *item(int index, bool complete = true);
+ Q_INVOKABLE QSGItem *item(int index, const QByteArray &viewId, bool complete = true);
Q_INVOKABLE QSGItem *take(int index, QSGItem *parent = 0);
public Q_SLOTS:
void append(QSGItem *item);
void append(QSGVisualModel *sourceModel, int sourceIndex, int count);
+ void append(QDeclarativeComponent *delegate, const QVariant &model, int sourceIndex, int count);
+ void append(QDeclarativeComponent *delegate, const QScriptValue &data);
void insert(int index, QSGItem *item);
void insert(int destinationIndex, QSGVisualModel *sourceModel, int sourceIndex, int count);
+ void insert(int destinationIndex, QDeclarativeComponent *delegate, const QVariant &model, int sourceIndex, int count);
+ void insert(int index, QDeclarativeComponent *delegate, const QScriptValue &data);
void remove(int index, int count);
void move(int from, int to, int count);
@@ -140,8 +148,7 @@ private Q_SLOTS:
void _q_itemsInserted(QSGVisualData *model, int index, int count);
void _q_itemsRemoved(QSGVisualData *model, int index, int count);
void _q_itemsMoved(QSGVisualData *model, int from, int to, int count);
- void _q_createdPackage(QSGVisualData *model, int index, QDeclarativePackage *package);
- void _q_destroyingPackage(QDeclarativePackage *package);
+ void _q_itemsChanged(QSGVisualData *model, int index, int count);
private:
Q_DISABLE_COPY(QSGVisualModel)
@@ -175,15 +182,16 @@ public:
Q_INVOKABLE QVariant parentModelIndex() const;
int count() const;
- QSGItem *item(int index, const QByteArray &, bool complete=true);
- QSGVisualModel::ReleaseFlags release(QSGItem *item);
+ QObject *object(int index, bool complete=true);
+ void release(QObject *object);
bool completePending() const;
void completeItem();
- QString stringValue(int index, const QString &role);
+ QString stringValue(int index, QObject *object, const QString &role);
void setWatchedRoles(QList<QByteArray> roles);
- int indexOf(QSGItem *item, QObject *objectContext) const;
+ int indexOf(QObject *item, QObject *objectContext) const;
+ bool updateData(int idx, QObject *object);
Q_SIGNALS:
void itemsInserted(QSGVisualData *data, int index, int count);
@@ -191,8 +199,6 @@ Q_SIGNALS:
void itemsMoved(QSGVisualData *data, int from, int to, int count);
void itemsChanged(QSGVisualData *data, int index, int count);
- void createdPackage(QSGVisualData *model, int index, QDeclarativePackage *package);
- void destroyingPackage(QDeclarativePackage *package);
void rootIndexChanged();
private Q_SLOTS:
@@ -211,6 +217,42 @@ private:
Q_DISABLE_COPY(QSGVisualData)
};
+class QSGVisualModelRole : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
+ Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue NOTIFY defaultValueChanged)
+public:
+ QSGVisualModelRole(QObject *parent = 0) : QObject(parent) {}
+ ~QSGVisualModelRole() {}
+
+ QString name() const { return m_name; }
+ void setName(const QString &name)
+ {
+ if (m_name == name)
+ return;
+ m_name = name;
+ emit nameChanged();
+ }
+
+ QVariant defaultValue() const { return m_defaultValue; }
+ void setDefaultValue(const QVariant &value)
+ {
+ if (m_defaultValue == value)
+ return;
+ m_defaultValue = value;
+ emit defaultValueChanged();
+ }
+
+Q_SIGNALS:
+ void nameChanged();
+ void defaultValueChanged();
+
+private:
+ QString m_name;
+ QVariant m_defaultValue;
+};
+
class QSGVisualModelAttached : public QObject
{
Q_OBJECT
@@ -300,6 +342,10 @@ public:
Q_INVOKABLE QVariant modelIndex(int idx) const;
Q_INVOKABLE QVariant parentModelIndex() const;
+public Q_SLOTS:
+ void appendData(const QScriptValue &value);
+ void insertData(int index, const QScriptValue &value);
+
Q_SIGNALS:
void rootIndexChanged();
@@ -329,6 +375,7 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QSGVisualModel)
QML_DECLARE_TYPEINFO(QSGVisualModel, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QSGVisualData)
+QML_DECLARE_TYPE(QSGVisualModelRole)
QML_DECLARE_TYPEINFO(QSGVisualDataModel, QML_HAS_ATTACHED_PROPERTIES)
QML_DECLARE_TYPE(QSGVisualItemModel)
QML_DECLARE_TYPEINFO(QSGVisualItemModel, QML_HAS_ATTACHED_PROPERTIES)
diff --git a/src/declarative/util/qdeclarativelistcompositor.cpp b/src/declarative/util/qdeclarativelistcompositor.cpp
index 5f613f811d..b081549e59 100644
--- a/src/declarative/util/qdeclarativelistcompositor.cpp
+++ b/src/declarative/util/qdeclarativelistcompositor.cpp
@@ -222,7 +222,7 @@ bool QDeclarativeListCompositor::insertData(int index, const void *data)
return true;
}
-bool QDeclarativeListCompositor::replaceAt(int index, const void *data)
+int QDeclarativeListCompositor::replaceAt(int index, const void *data)
{
Q_ASSERT(index >=0 && index < absoluteCount);
int internalIndex = 0;
@@ -238,9 +238,9 @@ bool QDeclarativeListCompositor::replaceAt(int index, const void *data)
if (range->internal()) {
replaceInternalData(internalIndex, data);
- return true;
+ return internalIndex;
} else if (!insertInternalData(internalIndex, data)) {
- return false;
+ return -1;
}
range->count -= 1;
@@ -248,7 +248,7 @@ bool QDeclarativeListCompositor::replaceAt(int index, const void *data)
int removeIndex = range->index + relativeIndex;
- if (range->count == 0) {
+ if (range->count == 0 && !range->append()) {
range->flags |= Internal;
range->count = 1;
} else {
@@ -267,15 +267,16 @@ bool QDeclarativeListCompositor::replaceAt(int index, const void *data)
}
range = insert(range, QDeclarativeCompositeRange(
range->list, removeIndex, 1, (range->flags | Internal) & ~Append));
+ range->index += 1;
}
- return true;
+ return internalIndex;
}
relativeIndex -= range->count;
if (range->internal())
internalIndex += range->count;
++range;
}
- return false;
+ return -1;
}
void QDeclarativeListCompositor::removeAt(int index, int count)
@@ -297,8 +298,10 @@ void QDeclarativeListCompositor::removeAt(int index, int count)
absoluteCount -= removeCount;
int removeIndex = range->index + relativeIndex;
- if (range->internal())
+ if (range->internal()) {
internalCount -= removeCount;
+ internalRemoveCount += removeCount;
+ }
if (range->count == 0) {
if (range->append()) {
@@ -616,6 +619,64 @@ void QDeclarativeListCompositor::clear()
internalCount = 0;
}
+void QDeclarativeListCompositor::clearData(int internalIndex, int count)
+{
+ Q_ASSERT(internalIndex >=0 && internalIndex + count <= internalCount);
+
+ int relativeIndex = internalIndex;
+ iterator range = ranges.begin();
+ while (range != ranges.end() && count > 0) {
+ if (!range->internal()) {
+ ++range;
+ continue;
+ }
+ if (relativeIndex < range->count) {
+ int removeCount = qMin(count, range->count - relativeIndex);
+ count -= removeCount;
+ if (!range->list) {
+ internalIndex += removeCount;
+ relativeIndex = 0;
+ continue;
+ }
+
+ range->count -= removeCount;
+ internalCount -= removeCount;
+
+ int removeIndex = range->index + relativeIndex;
+ if (range->count == 0) {
+ range->flags &= ~Internal;
+ range->count = removeCount;
+ // ### Merge with neighbouring nodes if appropriate.
+ } else {
+ if (relativeIndex > 0) {
+ int splitOffset = relativeIndex;
+ if (range->list)
+ splitOffset += removeCount;
+ if (splitOffset < range->count) {
+ Q_ASSERT(count == 0);
+ range = insert(range, QDeclarativeCompositeRange(
+ range->list, range->index, relativeIndex, range->flags & ~Append));
+ range->index += splitOffset;
+ range->count -= splitOffset;
+ } else {
+ range->index += relativeIndex;
+ relativeIndex = 0;
+ }
+ } else {
+ range->index += removeCount;
+ }
+ range = insert(range, QDeclarativeCompositeRange(
+ range->list, removeIndex, removeCount, range->flags & ~Internal));
+ }
+ removeInternalData(internalIndex, removeCount);
+ ++range;
+ continue;
+ }
+ relativeIndex -= range->count;
+ ++range;
+ }
+}
+
int QDeclarativeListCompositor::absoluteIndexOf(int internalIndex) const
{
int absoluteIndex = 0;
diff --git a/src/declarative/util/qdeclarativelistcompositor_p.h b/src/declarative/util/qdeclarativelistcompositor_p.h
index 207f9ae4c6..2d2123ad8c 100644
--- a/src/declarative/util/qdeclarativelistcompositor_p.h
+++ b/src/declarative/util/qdeclarativelistcompositor_p.h
@@ -102,12 +102,13 @@ public:
bool appendData(const void *data);
void insertList(int index, void *list, int start, int count, bool grow);
bool insertData(int index, const void *data);
- bool replaceAt(int index, const void *data);
+ int replaceAt(int index, const void *data);
void removeAt(int index, int count);
void removeList(void *list, QVector<QDeclarativeChangeSet::Remove> *changes);
void move(int from, int to, int count);
bool merge(int from, int to);
void clear();
+ void clearData(int internalIndex, int count);
int absoluteIndexOf(int internalIndex) const;
int absoluteIndexOf(void *list, int index, int from = 0) const;