aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;