src/declarative/util/qdeclarativelistmodel.cpp
changeset 37 758a864f9613
parent 33 3e2da88830cd
equal deleted inserted replaced
36:ef0373b55136 37:758a864f9613
    56 
    56 
    57 Q_DECLARE_METATYPE(QListModelInterface *)
    57 Q_DECLARE_METATYPE(QListModelInterface *)
    58 
    58 
    59 QT_BEGIN_NAMESPACE
    59 QT_BEGIN_NAMESPACE
    60 
    60 
    61 #define DATA_ROLE_ID 1
       
    62 #define DATA_ROLE_NAME "data"
       
    63 
       
    64 QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListModelData::instructions() const
    61 QDeclarativeListModelParser::ListInstruction *QDeclarativeListModelParser::ListModelData::instructions() const
    65 {
    62 {
    66     return (QDeclarativeListModelParser::ListInstruction *)((char *)this + sizeof(ListModelData));
    63     return (QDeclarativeListModelParser::ListInstruction *)((char *)this + sizeof(ListModelData));
    67 }
    64 }
    68 
    65 
    69 /*!
    66 /*!
    70     \qmlclass ListModel QDeclarativeListModel
    67     \qmlclass ListModel QDeclarativeListModel
       
    68     \ingroup qml-working-with-data
    71     \since 4.7
    69     \since 4.7
    72     \brief The ListModel element defines a free-form list data source.
    70     \brief The ListModel element defines a free-form list data source.
    73 
    71 
    74     The ListModel is a simple hierarchy of elements containing data roles. The contents can
    72     The ListModel is a simple hierarchy of elements containing data roles. The contents can
    75     be defined dynamically, or explicitly in QML:
    73     be defined dynamically, or explicitly in QML:
   106     The content of a ListModel may be created and modified using the clear(),
   104     The content of a ListModel may be created and modified using the clear(),
   107     append(), set() and setProperty() methods.  For example:
   105     append(), set() and setProperty() methods.  For example:
   108     
   106     
   109     \snippet doc/src/snippets/declarative/listmodel-modify.qml delegate
   107     \snippet doc/src/snippets/declarative/listmodel-modify.qml delegate
   110 
   108 
   111     When creating content dynamically, note that the set of available properties cannot be changed
   109     Note that when creating content dynamically the set of available properties cannot be changed
   112     except by first clearing the model. Whatever properties are first added to the model are then the
   110     once set. Whatever properties are first added to the model are the
   113     only permitted properties in the model until it is cleared.
   111     only permitted properties in the model.
   114 
   112 
   115 
   113 
   116     \section2 Using threaded list models with WorkerScript
   114     \section2 Using threaded list models with WorkerScript
   117 
   115 
   118     ListModel can be used together with WorkerScript access a list model
   116     ListModel can be used together with WorkerScript access a list model
   127 
   125 
   128     The included file, \tt dataloader.js, looks like this:
   126     The included file, \tt dataloader.js, looks like this:
   129 
   127 
   130     \snippet examples/declarative/threading/threadedlistmodel/dataloader.js 0
   128     \snippet examples/declarative/threading/threadedlistmodel/dataloader.js 0
   131 
   129 
   132     The application's \tt Timer object periodically sends a message to the
   130 working-with-data
   133     worker script by calling \l WorkerScript::sendMessage(). When this message
   131     worker script by calling \l WorkerScript::sendMessage(). When this message
   134     is received, \l {WorkerScript::onMessage}{WorkerScript.onMessage()} is invoked in
   132     is received, \l {WorkerScript::onMessage}{WorkerScript.onMessage()} is invoked in
   135     \tt dataloader.js, which appends the current time to the list model.
   133     \tt dataloader.js, which appends the current time to the list model.
   136 
   134 
   137     Note the call to sync() from the \l {WorkerScript::onMessage}{WorkerScript.onMessage()} handler.
   135     Note the call to sync() from the \l {WorkerScript::onMessage}{WorkerScript.onMessage()} handler.
   281 }
   279 }
   282 
   280 
   283 /*!
   281 /*!
   284     \qmlmethod ListModel::clear()
   282     \qmlmethod ListModel::clear()
   285 
   283 
   286     Deletes all content from the model. The properties are cleared such that
   284     Deletes all content from the model.
   287     different properties may be set on subsequent additions.
       
   288 
   285 
   289     \sa append() remove()
   286     \sa append() remove()
   290 */
   287 */
   291 void QDeclarativeListModel::clear()
   288 void QDeclarativeListModel::clear()
   292 {
   289 {
   568             }
   565             }
   569 
   566 
   570             QList<QDeclarativeCustomParserProperty> props = node.properties();
   567             QList<QDeclarativeCustomParserProperty> props = node.properties();
   571             for(int jj = 0; jj < props.count(); ++jj) {
   568             for(int jj = 0; jj < props.count(); ++jj) {
   572                 const QDeclarativeCustomParserProperty &nodeProp = props.at(jj);
   569                 const QDeclarativeCustomParserProperty &nodeProp = props.at(jj);
   573                 if (nodeProp.name() == "") {
   570                 if (nodeProp.name().isEmpty()) {
   574                     error(nodeProp, QDeclarativeListModel::tr("ListElement: cannot contain nested elements"));
   571                     error(nodeProp, QDeclarativeListModel::tr("ListElement: cannot contain nested elements"));
   575                     return false;
   572                     return false;
   576                 }
   573                 }
   577                 if (nodeProp.name() == "id") {
   574                 if (nodeProp.name() == "id") {
   578                     error(nodeProp, QDeclarativeListModel::tr("ListElement: cannot use reserved \"id\" property"));
   575                     error(nodeProp, QDeclarativeListModel::tr("ListElement: cannot use reserved \"id\" property"));
   656     QByteArray data;
   653     QByteArray data;
   657     listElementTypeName = QByteArray(); // unknown
   654     listElementTypeName = QByteArray(); // unknown
   658 
   655 
   659     for(int ii = 0; ii < customProps.count(); ++ii) {
   656     for(int ii = 0; ii < customProps.count(); ++ii) {
   660         const QDeclarativeCustomParserProperty &prop = customProps.at(ii);
   657         const QDeclarativeCustomParserProperty &prop = customProps.at(ii);
   661         if(prop.name() != "") { // isn't default property
   658         if(!prop.name().isEmpty()) { // isn't default property
   662             error(prop, QDeclarativeListModel::tr("ListModel: undefined property '%1'").arg(QString::fromUtf8(prop.name())));
   659             error(prop, QDeclarativeListModel::tr("ListModel: undefined property '%1'").arg(QString::fromUtf8(prop.name())));
   663             return QByteArray();
   660             return QByteArray();
   664         }
   661         }
   665 
   662 
   666         if(!compileProperty(prop, instr, data)) {
   663         if(!compileProperty(prop, instr, data)) {
   768     return false;
   765     return false;
   769 }
   766 }
   770 
   767 
   771 /*!
   768 /*!
   772     \qmlclass ListElement
   769     \qmlclass ListElement
       
   770     \ingroup qml-working-with-data
   773     \since 4.7
   771     \since 4.7
   774     \brief The ListElement element defines a data item in a ListModel.
   772     \brief The ListElement element defines a data item in a ListModel.
   775 
   773 
   776     \sa ListModel
   774     \sa ListModel
   777 */
   775 */
   943     }
   941     }
   944     return true;
   942     return true;
   945 }
   943 }
   946 
   944 
   947 NestedListModel::NestedListModel(QDeclarativeListModel *base)
   945 NestedListModel::NestedListModel(QDeclarativeListModel *base)
   948     : _root(0), m_listModel(base), _rolesOk(false)
   946     : _root(0), m_ownsRoot(false), m_listModel(base), _rolesOk(false)
   949 {
   947 {
   950 }
   948 }
   951 
   949 
   952 NestedListModel::~NestedListModel()
   950 NestedListModel::~NestedListModel()
   953 {
   951 {
   954     delete _root;
   952     if (m_ownsRoot)
       
   953         delete _root;
   955 }
   954 }
   956 
   955 
   957 QVariant NestedListModel::valueForNode(ModelNode *node, bool *hasNested) const
   956 QVariant NestedListModel::valueForNode(ModelNode *node, bool *hasNested) const
   958 {
   957 {
   959     QObject *rv = 0;
   958     QObject *rv = 0;
  1049 void NestedListModel::clear()
  1048 void NestedListModel::clear()
  1050 {
  1049 {
  1051     _rolesOk = false;
  1050     _rolesOk = false;
  1052     roleStrings.clear();
  1051     roleStrings.clear();
  1053 
  1052 
  1054     delete _root;
  1053     if (_root)
  1055     _root = 0;
  1054         _root->clear();
  1056 }
  1055 }
  1057 
  1056 
  1058 void NestedListModel::remove(int index)
  1057 void NestedListModel::remove(int index)
  1059 {
  1058 {
  1060     if (!_root)
  1059     if (!_root)
  1065         delete node;
  1064         delete node;
  1066 }
  1065 }
  1067 
  1066 
  1068 bool NestedListModel::insert(int index, const QScriptValue& valuemap)
  1067 bool NestedListModel::insert(int index, const QScriptValue& valuemap)
  1069 {
  1068 {
  1070     if (!_root)
  1069     if (!_root) {
  1071         _root = new ModelNode;
  1070         _root = new ModelNode;
       
  1071         m_ownsRoot = true;
       
  1072     }
  1072 
  1073 
  1073     ModelNode *mn = new ModelNode;
  1074     ModelNode *mn = new ModelNode;
  1074     mn->setObjectValue(valuemap);
  1075     mn->setObjectValue(valuemap);
  1075     _root->values.insert(index,qVariantFromValue(mn));
  1076     _root->values.insert(index,qVariantFromValue(mn));
  1076     return true;
  1077     return true;
  1097     }
  1098     }
  1098 }
  1099 }
  1099 
  1100 
  1100 bool NestedListModel::append(const QScriptValue& valuemap)
  1101 bool NestedListModel::append(const QScriptValue& valuemap)
  1101 {
  1102 {
  1102     if (!_root)
  1103     if (!_root) {
  1103         _root = new ModelNode;
  1104         _root = new ModelNode;
       
  1105         m_ownsRoot = true;
       
  1106     }
  1104     ModelNode *mn = new ModelNode;
  1107     ModelNode *mn = new ModelNode;
  1105     mn->setObjectValue(valuemap);
  1108     mn->setObjectValue(valuemap);
  1106     _root->values << qVariantFromValue(mn);
  1109     _root->values << qVariantFromValue(mn);
  1107     return true;
  1110     return true;
  1108 }
  1111 }
  1203 {
  1206 {
  1204 }
  1207 }
  1205 
  1208 
  1206 ModelNode::~ModelNode()
  1209 ModelNode::~ModelNode()
  1207 {
  1210 {
  1208     qDeleteAll(properties.values());
  1211     clear();
  1209 
  1212     if (modelCache) { modelCache->m_nested->_root = 0/* ==this */; delete modelCache; modelCache = 0; }
       
  1213     if (objectCache) { delete objectCache; objectCache = 0; }
       
  1214 }
       
  1215 
       
  1216 void ModelNode::clear()
       
  1217 {
  1210     ModelNode *node;
  1218     ModelNode *node;
  1211     for (int ii = 0; ii < values.count(); ++ii) {
  1219     for (int ii = 0; ii < values.count(); ++ii) {
  1212         node = qvariant_cast<ModelNode *>(values.at(ii));
  1220         node = qvariant_cast<ModelNode *>(values.at(ii));
  1213         if (node) { delete node; node = 0; }
  1221         if (node) { delete node; node = 0; }
  1214     }
  1222     }
  1215 
  1223     values.clear();
  1216     if (modelCache) { modelCache->m_nested->_root = 0/* ==this */; delete modelCache; modelCache = 0; }
  1224 
  1217     if (objectCache) { delete objectCache; objectCache = 0; }
  1225     qDeleteAll(properties.values());
       
  1226     properties.clear();
  1218 }
  1227 }
  1219 
  1228 
  1220 void ModelNode::setObjectValue(const QScriptValue& valuemap) {
  1229 void ModelNode::setObjectValue(const QScriptValue& valuemap) {
  1221     QScriptValueIterator it(valuemap);
  1230     QScriptValueIterator it(valuemap);
  1222     while (it.hasNext()) {
  1231     while (it.hasNext()) {