From 14e787b7e5abc1d665ba0e0229f60525283b1e38 Mon Sep 17 00:00:00 2001 From: Warwick Allison Date: Wed, 9 Sep 2009 14:12:45 +1000 Subject: Modifying ListModel from JS: work for structured data too. --- examples/declarative/listview/dynamic.qml | 48 ++++++++++++++++++-- src/declarative/util/qmllistmodel.cpp | 75 ++++++++++++++++++++++--------- src/declarative/util/qmllistmodel.h | 8 ++-- 3 files changed, 104 insertions(+), 27 deletions(-) diff --git a/examples/declarative/listview/dynamic.qml b/examples/declarative/listview/dynamic.qml index 58ce4b4..5111cec 100644 --- a/examples/declarative/listview/dynamic.qml +++ b/examples/declarative/listview/dynamic.qml @@ -2,42 +2,74 @@ import Qt 4.6 Item { width: 300 - height: 300 + height: 500 ListModel { id: FruitModel ListElement { name: "Apple" cost: 2.45 + attributes: [ + ListElement { description: "Core" }, + ListElement { description: "Deciduous" } + ] } ListElement { name: "Banana" cost: 1.95 + attributes: [ + ListElement { description: "Tropical" }, + ListElement { description: "Seedless" } + ] } ListElement { name: "Cumquat" cost: 3.25 + types: [ "Small", "Smaller" ] + attributes: [ + ListElement { description: "Citrus" } + ] } ListElement { name: "Durian" cost: 9.95 + attributes: [ + ListElement { description: "Tropical" }, + ListElement { description: "Smelly" } + ] } ListElement { name: "Elderberry" cost: 0.05 + attributes: [ + ListElement { description: "Berry" } + ] } ListElement { name: "Fig" cost: 0.25 + attributes: [ + ListElement { description: "Flower" } + ] } } Component { id: FruitDelegate Item { - width: parent.width; height: 35 - Text { font.pixelSize: 24; text: name } + width: parent.width; height: 55 + Text { id: Label; font.pixelSize: 24; text: name } Text { font.pixelSize: 24; text: '$'+Number(cost).toFixed(2); anchors.right: ItemButtons.left } + Row { + anchors.top: Label.bottom + spacing: 5 + Repeater { + model: attributes + Component { + Text { text: description } + } + } + } Row { id: ItemButtons anchors.right: parent.right @@ -79,7 +111,15 @@ Item { anchors.bottom: parent.bottom id: Buttons Image { source: "content/pics/add.png" - MouseRegion { anchors.fill: parent; onClicked: FruitModel.append({"name":"Pizza", "cost":5.95}) } + MouseRegion { anchors.fill: parent; + onClicked: { + FruitModel.append({ + "name":"Pizza", + "cost":5.95, + "attributes":[{"description": "Supreme"},{"description": "Margarita"}] + }) + } + } } Image { source: "content/pics/add.png" MouseRegion { anchors.fill: parent; onClicked: FruitModel.insert(0,{"name":"Pizza", "cost":5.95}) } diff --git a/src/declarative/util/qmllistmodel.cpp b/src/declarative/util/qmllistmodel.cpp index a5ae60f..dc6b02b 100644 --- a/src/declarative/util/qmllistmodel.cpp +++ b/src/declarative/util/qmllistmodel.cpp @@ -47,6 +47,7 @@ #include "qmlopenmetaobject.h" #include #include "qmllistmodel.h" +#include Q_DECLARE_METATYPE(QListModelInterface *) @@ -68,6 +69,8 @@ struct ListModelData ListInstruction *instructions() const { return (ListInstruction *)((char *)this + sizeof(ListModelData)); } }; +static void dump(ModelNode *node, int ind); + /*! \qmlclass ListModel \brief The ListModel element defines a free-form list data source. @@ -140,7 +143,7 @@ struct ListModelData name: "Banana" cost: 1.95 attributes: [ - ListElement { description: "Tropical" } + ListElement { description: "Tropical" }, ListElement { description: "Seedless" } ] } @@ -238,6 +241,42 @@ struct ModelNode return objectCache; } + void setListValue(const QScriptValue& valuelist) { + QScriptValueIterator it(valuelist); + values.clear(); + while (it.hasNext()) { + it.next(); + ModelNode *value = new ModelNode; + QScriptValue v = it.value(); + if (v.isArray()) { + value->setListValue(v); + } else if (v.isObject()) { + value->setObjectValue(v); + } else { + value->values << v.toVariant(); + } + values.append(qVariantFromValue(value)); + + } + } + + void setObjectValue(const QScriptValue& valuemap) { + QScriptValueIterator it(valuemap); + while (it.hasNext()) { + it.next(); + ModelNode *value = new ModelNode; + QScriptValue v = it.value(); + if (v.isArray()) { + value->setListValue(v); + } else if (v.isObject()) { + value->setObjectValue(v); + } else { + value->values << v.toVariant(); + } + properties.insert(it.name(),value); + } + } + void setProperty(const QString& prop, const QVariant& val) { QHash::const_iterator it = properties.find(prop); if (it != properties.end()) { @@ -429,7 +468,7 @@ void QmlListModel::remove(int index) \sa set() append() */ -void QmlListModel::insert(int index, const QVariantMap& valuemap) +void QmlListModel::insert(int index, const QScriptValue& valuemap) { if (!_root) _root = new ModelNode; @@ -438,12 +477,7 @@ void QmlListModel::insert(int index, const QVariantMap& valuemap) return; } ModelNode *mn = new ModelNode; - for (QVariantMap::const_iterator it=valuemap.begin(); it!=valuemap.end(); ++it) { - addRole(it.key()); - ModelNode *value = new ModelNode; - value->values << it.value(); - mn->properties.insert(it.key(),value); - } + mn->setObjectValue(valuemap); _root->values.insert(index,qVariantFromValue(mn)); emit itemsInserted(index,1); } @@ -506,17 +540,16 @@ void QmlListModel::move(int from, int to, int n) \sa set() remove() */ -void QmlListModel::append(const QVariantMap& valuemap) +void QmlListModel::append(const QScriptValue& valuemap) { + if (!valuemap.isObject()) { + qWarning("ListModel::append: value is not an object"); + return; + } if (!_root) _root = new ModelNode; ModelNode *mn = new ModelNode; - for (QVariantMap::const_iterator it=valuemap.begin(); it!=valuemap.end(); ++it) { - addRole(it.key()); - ModelNode *value = new ModelNode; - value->values << it.value(); - mn->properties.insert(it.key(),value); - } + mn->setObjectValue(valuemap); _root->values << qVariantFromValue(mn); emit itemsInserted(count()-1,1); } @@ -536,7 +569,7 @@ void QmlListModel::append(const QVariantMap& valuemap) \sa append() */ -void QmlListModel::set(int index, const QVariantMap& valuemap) +void QmlListModel::set(int index, const QScriptValue& valuemap) { if (!_root) _root = new ModelNode; @@ -548,12 +581,14 @@ void QmlListModel::set(int index, const QVariantMap& valuemap) else { ModelNode *node = qvariant_cast(_root->values.at(index)); QList roles; - for (QVariantMap::const_iterator it=valuemap.begin(); it!=valuemap.end(); ++it) { - node->setProperty(it.key(),it.value()); - int r = roleStrings.indexOf(it.key()); + node->setObjectValue(valuemap); + QScriptValueIterator it(valuemap); + while (it.hasNext()) { + it.next(); + int r = roleStrings.indexOf(it.name()); if (r<0) { r = roleStrings.count(); - roleStrings << it.key(); + roleStrings << it.name(); } roles.append(r); } diff --git a/src/declarative/util/qmllistmodel.h b/src/declarative/util/qmllistmodel.h index 8bef347..7bb94cf 100644 --- a/src/declarative/util/qmllistmodel.h +++ b/src/declarative/util/qmllistmodel.h @@ -50,6 +50,8 @@ #include #include #include +#include + QT_BEGIN_HEADER @@ -74,9 +76,9 @@ public: Q_INVOKABLE void clear(); Q_INVOKABLE void remove(int index); - Q_INVOKABLE void append(const QVariantMap& valuemap); - Q_INVOKABLE void insert(int index, const QVariantMap& valuemap); - Q_INVOKABLE void set(int index, const QVariantMap& valuemap); + Q_INVOKABLE void append(const QScriptValue&); + Q_INVOKABLE void insert(int index, const QScriptValue&); + Q_INVOKABLE void set(int index, const QScriptValue&); Q_INVOKABLE void set(int index, const QString& property, const QVariant& value); Q_INVOKABLE void move(int from, int to, int count); -- cgit v0.12