diff -r 5dc02b23752f -r 3e2da88830cd src/declarative/util/qdeclarativelistmodel.cpp --- a/src/declarative/util/qdeclarativelistmodel.cpp Tue Jul 06 15:10:48 2010 +0300 +++ b/src/declarative/util/qdeclarativelistmodel.cpp Wed Aug 18 10:37:55 2010 +0300 @@ -76,125 +76,41 @@ For example: - \code - ListModel { - id: fruitModel - ListElement { - name: "Apple" - cost: 2.45 - } - ListElement { - name: "Orange" - cost: 3.25 - } - ListElement { - name: "Banana" - cost: 1.95 - } - } - \endcode + \snippet doc/src/snippets/declarative/listmodel.qml 0 - Roles (properties) must begin with a lower-case letter.The above example defines a + Roles (properties) must begin with a lower-case letter. The above example defines a ListModel containing three elements, with the roles "name" and "cost". - Values must be simple constants - either strings (quoted), bools (true, false), numbers, - or enum values (like Text.AlignHCenter). + Values must be simple constants - either strings (quoted and optionally within a call to QT_TR_NOOP), + bools (true, false), numbers, or enum values (like Text.AlignHCenter). The defined model can be used in views such as ListView: - \code - Component { - id: fruitDelegate - Item { - width: 200; height: 50 - Text { text: name } - Text { text: '$'+cost; anchors.right: parent.right } - } - } - ListView { - model: fruitModel - delegate: fruitDelegate - anchors.fill: parent - } - \endcode + \snippet doc/src/snippets/declarative/listmodel-simple.qml 0 + \dots 8 + \snippet doc/src/snippets/declarative/listmodel-simple.qml 1 + \image listmodel.png It is possible for roles to contain list data. In the example below we create a list of fruit attributes: - \code - ListModel { - id: fruitModel - ListElement { - name: "Apple" - cost: 2.45 - attributes: [ - ListElement { description: "Core" }, - ListElement { description: "Deciduous" } - ] - } - ListElement { - name: "Orange" - cost: 3.25 - attributes: [ - ListElement { description: "Citrus" } - ] - } - ListElement { - name: "Banana" - cost: 1.95 - attributes: [ - ListElement { description: "Tropical" }, - ListElement { description: "Seedless" } - ] - } - } - \endcode + \snippet doc/src/snippets/declarative/listmodel-nested.qml model + + The delegate below displays all the fruit attributes: - The delegate below will list all the fruit attributes: - \code - Component { - id: fruitDelegate - Item { - width: 200; height: 50 - Text { id: name; text: name } - Text { text: '$'+cost; anchors.right: parent.right } - Row { - anchors.top: name.bottom - spacing: 5 - Text { text: "Attributes:" } - Repeater { - model: attributes - Component { Text { text: description } } - } - } - } - } - \endcode + \snippet doc/src/snippets/declarative/listmodel-nested.qml delegate + \image listmodel-nested.png + \section2 Modifying list models The content of a ListModel may be created and modified using the clear(), - append(), and set() methods. For example: - - \code - Component { - id: fruitDelegate - Item { - width: 200; height: 50 - Text { text: name } - Text { text: '$'+cost; anchors.right: parent.right } - - // Double the price when clicked. - MouseArea { - anchors.fill: parent - onClicked: fruitModel.set(index, "cost", cost*2) - } - } - } - \endcode + append(), set() and setProperty() methods. For example: + + \snippet doc/src/snippets/declarative/listmodel-modify.qml delegate When creating content dynamically, note that the set of available properties cannot be changed - except by first clearing the model - whatever properties are first added are then the - only permitted properties in the model. + except by first clearing the model. Whatever properties are first added to the model are then the + only permitted properties in the model until it is cleared. \section2 Using threaded list models with WorkerScript @@ -214,11 +130,11 @@ \snippet examples/declarative/threading/threadedlistmodel/dataloader.js 0 The application's \tt Timer object periodically sends a message to the - worker script by calling \tt WorkerScript::sendMessage(). When this message - is received, \tt WorkerScript.onMessage() is invoked in + worker script by calling \l WorkerScript::sendMessage(). When this message + is received, \l {WorkerScript::onMessage}{WorkerScript.onMessage()} is invoked in \tt dataloader.js, which appends the current time to the list model. - Note the call to sync() from the \c WorkerScript.onMessage() handler. + Note the call to sync() from the \l {WorkerScript::onMessage}{WorkerScript.onMessage()} handler. You must call sync() or else the changes made to the list from the external thread will not be reflected in the list model in the main thread. @@ -244,7 +160,7 @@ In addition, the WorkerScript cannot add any list data to the model. - \sa {qmlmodels}{Data Models}, WorkerScript, QtDeclarative + \sa {qmlmodels}{Data Models}, {declarative/threading/threadedlistmodel}{Threaded ListModel example}, QtDeclarative */ @@ -454,7 +370,7 @@ to the end of the list: \code - fruitModel.move(0,fruitModel.count-3,3) + fruitModel.move(0, fruitModel.count - 3, 3) \endcode \sa append() @@ -635,9 +551,13 @@ QDeclarativeCustomParserNode node = qvariant_cast(value); - if (node.name() != "ListElement") { - error(node, QDeclarativeListModel::tr("ListElement: cannot contain nested elements")); - return false; + if (node.name() != listElementTypeName) { + const QMetaObject *mo = resolveType(node.name()); + if (mo != &QDeclarativeListElement::staticMetaObject) { + error(node, QDeclarativeListModel::tr("ListElement: cannot contain nested elements")); + return false; + } + listElementTypeName = node.name(); // cache right name for next time } { @@ -704,8 +624,13 @@ QByteArray script = variant.asScript().toUtf8(); int v = evaluateEnum(script); if (v<0) { - error(prop, QDeclarativeListModel::tr("ListElement: cannot use script for property value")); - return false; + if (script.startsWith("QT_TR_NOOP(\"") && script.endsWith("\")")) { + d[0] = char(QDeclarativeParser::Variant::String); + d += script.mid(12,script.length()-14); + } else { + error(prop, QDeclarativeListModel::tr("ListElement: cannot use script for property value")); + return false; + } } else { d[0] = char(QDeclarativeParser::Variant::Number); d += QByteArray::number(v); @@ -729,6 +654,7 @@ { QList instr; QByteArray data; + listElementTypeName = QByteArray(); // unknown for(int ii = 0; ii < customProps.count(); ++ii) { const QDeclarativeCustomParserProperty &prop = customProps.at(ii); @@ -1096,6 +1022,8 @@ Q_ASSERT(_root && index >= 0 && index < _root->values.count()); checkRoles(); QVariant rv; + if (roleStrings.count() < role) + return rv; ModelNode *node = qvariant_cast(_root->values.at(index)); if (!node)