summaryrefslogtreecommitdiffstats
path: root/tests/auto/declarative/qdeclarativexmllistmodel
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2010-02-24 02:42:00 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2010-02-24 02:42:00 (GMT)
commit7c76abb0dc4204043bec9b6fa315f9753a7986ae (patch)
treecee303672cfd138790645e731f2d69472564d4b7 /tests/auto/declarative/qdeclarativexmllistmodel
parent4066e60e859853cfe3240245ba05271e79839506 (diff)
downloadQt-7c76abb0dc4204043bec9b6fa315f9753a7986ae.zip
Qt-7c76abb0dc4204043bec9b6fa315f9753a7986ae.tar.gz
Qt-7c76abb0dc4204043bec9b6fa315f9753a7986ae.tar.bz2
Change class prefix to from QmlXXX to QDeclarativeXXX, QmlGraphicsXXX to QDeclarativeXXX.
Diffstat (limited to 'tests/auto/declarative/qdeclarativexmllistmodel')
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/data/model.qml10
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/data/model.xml54
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml11
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.qml10
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.xml90
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/data/roleErrors.qml10
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/data/roleKeys.qml13
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/data/unique.qml8
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro11
-rw-r--r--tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp457
10 files changed, 674 insertions, 0 deletions
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/model.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/model.qml
new file mode 100644
index 0000000..2cbb027
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/model.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "model.xml"
+ query: "/Pets/Pet"
+ XmlRole { name: "name"; query: "name/string()" }
+ XmlRole { name: "type"; query: "type/string()" }
+ XmlRole { name: "age"; query: "age/number()" }
+ XmlRole { name: "size"; query: "size/string()" }
+}
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/model.xml b/tests/auto/declarative/qdeclarativexmllistmodel/data/model.xml
new file mode 100644
index 0000000..40cd6d0
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/model.xml
@@ -0,0 +1,54 @@
+<Pets>
+ <Pet>
+ <name>Polly</name>
+ <type>Parrot</type>
+ <age>12</age>
+ <size>Small</size>
+ </Pet>
+ <Pet>
+ <name>Penny</name>
+ <type>Turtle</type>
+ <age>4</age>
+ <size>Small</size>
+ </Pet>
+ <Pet>
+ <name>Warren</name>
+ <type>Rabbit</type>
+ <age>2</age>
+ <size>Small</size>
+ </Pet>
+ <Pet>
+ <name>Spot</name>
+ <type>Dog</type>
+ <age>9</age>
+ <size>Medium</size>
+ </Pet>
+ <Pet>
+ <name>Whiskers</name>
+ <type>Cat</type>
+ <age>2</age>
+ <size>Medium</size>
+ </Pet>
+ <Pet>
+ <name>Joey</name>
+ <type>Kangaroo</type>
+ <age>1</age>
+ </Pet>
+ <Pet>
+ <name>Kimba</name>
+ <type>Bunny</type>
+ <age>65</age>
+ <size>Large</size>
+ </Pet>
+ <Pet>
+ <name>Rover</name>
+ <type>Dog</type>
+ <size>Large</size>
+ </Pet>
+ <Pet>
+ <name>Tiny</name>
+ <type>Elephant</type>
+ <age>15</age>
+ <size>Large</size>
+ </Pet>
+</Pets>
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml
new file mode 100644
index 0000000..140e0ad
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/model2.qml
@@ -0,0 +1,11 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "model.xml"
+ query: "/Pets/Pet"
+ XmlRole { name: "name"; query: "name/string()" }
+ XmlRole { name: "type"; query: "type/string()" }
+ XmlRole { name: "age"; query: "age/number()" }
+ XmlRole { name: "size"; query: "size/string()" }
+ XmlRole { name: "tricks"; query: "tricks/string()" }
+}
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.qml
new file mode 100644
index 0000000..13dea91
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "recipes.xml"
+ query: "/recipes/recipe"
+ XmlRole { name: "title"; query: "@title/string()" }
+ XmlRole { name: "picture"; query: "picture/string()" }
+ XmlRole { name: "ingredients"; query: "ingredients/string()" }
+ XmlRole { name: "preparation"; query: "method/string()" }
+}
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.xml b/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.xml
new file mode 100644
index 0000000..d71de60
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/recipes.xml
@@ -0,0 +1,90 @@
+<recipes>
+ <recipe title="Pancakes">
+ <picture>content/pics/pancakes.jpg</picture>
+ <ingredients><![CDATA[<html>
+ <ul>
+ <li> 1 cup (150g) self-raising flour
+ <li> 1 tbs caster sugar
+ <li> 3/4 cup (185ml) milk
+ <li> 1 egg
+ </ul>
+ </html>
+ ]]></ingredients>
+ <method><![CDATA[<html>
+ <ol>
+ <li> Sift flour and sugar together into a bowl. Add a pinch of salt.
+ <li> Beat milk and egg together, then add to dry ingredients. Beat until smooth.
+ <li> Pour mixture into a pan on medium heat and cook until bubbles appear on the surface.
+ <li> Turn over and cook other side until golden.
+ </ol>
+ </html>
+ ]]></method>
+ </recipe>
+ <recipe title="Fruit Salad">
+ <picture>content/pics/fruit-salad.jpg</picture>
+ <ingredients><![CDATA[* Seasonal Fruit]]></ingredients>
+ <method><![CDATA[* Chop fruit and place in a bowl.]]></method>
+ </recipe>
+ <recipe title="Vegetable Soup">
+ <picture>content/pics/vegetable-soup.jpg</picture>
+ <ingredients><![CDATA[<html>
+ <ul>
+ <li> 1 onion
+ <li> 1 turnip
+ <li> 1 potato
+ <li> 1 carrot
+ <li> 1 head of celery
+ <li> 1 1/2 litres of water
+ </ul>
+ </html>
+ ]]></ingredients>
+ <method><![CDATA[<html>
+ <ol>
+ <li> Chop vegetables.
+ <li> Boil in water until vegetables soften.
+ <li> Season with salt and pepper to taste.
+ </ol>
+ </html>
+ ]]></method>
+ </recipe>
+ <recipe title="Hamburger">
+ <picture>content/pics/hamburger.jpg</picture>
+ <ingredients><![CDATA[<html>
+ <ul>
+ <li> 500g minced beef
+ <li> Seasoning
+ <li> lettuce, tomato, onion, cheese
+ <li> 1 hamburger bun for each burger
+ </ul>
+ </html>
+ ]]></ingredients>
+ <method><![CDATA[<html>
+ <ol>
+ <li> Mix the beef, together with seasoning, in a food processor.
+ <li> Shape the beef into burgers.
+ <li> Grill the burgers for about 5 mins on each side (until cooked through)
+ <li> Serve each burger on a bun with ketchup, cheese, lettuce, tomato and onion.
+ </ol>
+ </html>
+ ]]></method>
+ </recipe>
+ <recipe title="Lemonade">
+ <picture>content/pics/lemonade.jpg</picture>
+ <ingredients><![CDATA[<html>
+ <ul>
+ <li> 1 cup Lemon Juice
+ <li> 1 cup Sugar
+ <li> 6 Cups of Water (2 cups warm water, 4 cups cold water)
+ </ul>
+ </html>
+ ]]></ingredients>
+ <method><![CDATA[<html>
+ <ol>
+ <li> Pour 2 cups of warm water into a pitcher and stir in sugar until it dissolves.
+ <li> Pour in lemon juice, stir again, and add 4 cups of cold water.
+ <li> Chill or serve over ice cubes.
+ </ol>
+ </html>
+ ]]></method>
+ </recipe>
+</recipes>
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/roleErrors.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/roleErrors.qml
new file mode 100644
index 0000000..26c533f
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/roleErrors.qml
@@ -0,0 +1,10 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "model.xml"
+ query: "/Pets/Pet"
+ XmlRole { name: "name"; query: "/name/string()" } //starts with '/'
+ XmlRole { name: "type"; query: "type" } //no type
+ XmlRole { name: "age"; query: "age/" } //ends with '/'
+ XmlRole { name: "size"; query: "size/number()" } //wrong type
+}
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/roleKeys.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/roleKeys.qml
new file mode 100644
index 0000000..b90e57e
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/roleKeys.qml
@@ -0,0 +1,13 @@
+import Qt 4.6
+
+XmlListModel {
+ query: "/data/item"
+ XmlRole { id: nameRole; name: "name"; query: "name/string()"; isKey: true }
+ XmlRole { name: "age"; query: "age/number()"; isKey: true }
+ XmlRole { name: "sport"; query: "sport/string()" }
+
+ function disableNameKey() {
+ nameRole.isKey = false;
+ }
+}
+
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/data/unique.qml b/tests/auto/declarative/qdeclarativexmllistmodel/data/unique.qml
new file mode 100644
index 0000000..ed0f293
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/data/unique.qml
@@ -0,0 +1,8 @@
+import Qt 4.6
+
+XmlListModel {
+ source: "model.xml"
+ query: "/Pets/Pet"
+ XmlRole { name: "name"; query: "name/string()" }
+ XmlRole { name: "name"; query: "type/string()" }
+}
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro b/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro
new file mode 100644
index 0000000..88832dc
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/qdeclarativexmllistmodel.pro
@@ -0,0 +1,11 @@
+load(qttest_p4)
+contains(QT_CONFIG,declarative): QT += declarative gui
+contains(QT_CONFIG,xmlpatterns) {
+ QT += xmlpatterns
+ DEFINES += QTEST_XMLPATTERNS
+}
+macx:CONFIG -= app_bundle
+
+SOURCES += tst_qdeclarativexmllistmodel.cpp
+
+DEFINES += SRCDIR=\\\"$$PWD\\\"
diff --git a/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp
new file mode 100644
index 0000000..9ef1298
--- /dev/null
+++ b/tests/auto/declarative/qdeclarativexmllistmodel/tst_qdeclarativexmllistmodel.cpp
@@ -0,0 +1,457 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <qtest.h>
+#include <QtTest/qsignalspy.h>
+#include <QtCore/qtimer.h>
+
+#ifdef QTEST_XMLPATTERNS
+#include <QtDeclarative/qdeclarativeengine.h>
+#include <QtDeclarative/qdeclarativecomponent.h>
+#include <private/qdeclarativexmllistmodel_p.h>
+#include "../../../shared/util.h"
+
+typedef QPair<int, int> QDeclarativeXmlListRange;
+typedef QList<QVariantList> QDeclarativeXmlModelData;
+
+Q_DECLARE_METATYPE(QList<QDeclarativeXmlListRange>)
+Q_DECLARE_METATYPE(QDeclarativeXmlModelData)
+
+class tst_qmlxmllistmodel : public QObject
+
+{
+ Q_OBJECT
+public:
+ tst_qmlxmllistmodel() {}
+
+private slots:
+ void buildModel();
+ void missingFields();
+ void cdata();
+ void attributes();
+ void roles();
+ void roleErrors();
+ void uniqueRoleNames();
+ void useKeys();
+ void useKeys_data();
+ void noKeysValueChanges();
+ void keysChanged();
+
+private:
+ QString makeItemXmlAndData(const QString &data, QDeclarativeXmlModelData *modelData = 0) const
+ {
+ if (modelData)
+ modelData->clear();
+ QString xml;
+
+ if (!data.isEmpty()) {
+ QStringList items = data.split(";");
+ foreach(const QString &item, items) {
+ QVariantList variants;
+ xml += QLatin1String("<item>");
+ QStringList fields = item.split(",");
+ foreach(const QString &field, fields) {
+ QStringList values = field.split("=");
+ Q_ASSERT(values.count() == 2);
+ xml += QString("<%1>%2</%1>").arg(values[0], values[1]);
+ if (!modelData)
+ continue;
+ bool isNum = false;
+ int number = values[1].toInt(&isNum);
+ if (isNum)
+ variants << number;
+ else
+ variants << values[1];
+ }
+ xml += QLatin1String("</item>");
+ if (modelData)
+ modelData->append(variants);
+ }
+ }
+
+ QString decl = "<?xml version=\"1.0\" encoding=\"iso-8859-1\" ?>";
+ return decl + QLatin1String("<data>") + xml + QLatin1String("</data>");
+ }
+
+ QDeclarativeEngine engine;
+};
+
+void tst_qmlxmllistmodel::buildModel()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model.qml"));
+ QDeclarativeXmlListModel *listModel = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles;
+ roles << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 << Qt::UserRole + 3;
+ QHash<int, QVariant> data = listModel->data(3, roles);
+ QVERIFY(data.count() == 4);
+ QCOMPARE(data.value(Qt::UserRole).toString(), QLatin1String("Spot"));
+ QCOMPARE(data.value(Qt::UserRole+1).toString(), QLatin1String("Dog"));
+ QCOMPARE(data.value(Qt::UserRole+2).toInt(), 9);
+ QCOMPARE(data.value(Qt::UserRole+3).toString(), QLatin1String("Medium"));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::missingFields()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model2.qml"));
+ QDeclarativeXmlListModel *listModel = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles;
+ roles << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 << Qt::UserRole + 3 << Qt::UserRole + 4;
+ QHash<int, QVariant> data = listModel->data(5, roles);
+ QVERIFY(data.count() == 5);
+ QCOMPARE(data.value(Qt::UserRole+3).toString(), QLatin1String(""));
+ QCOMPARE(data.value(Qt::UserRole+4).toString(), QLatin1String(""));
+
+ data = listModel->data(7, roles);
+ QVERIFY(data.count() == 5);
+ QCOMPARE(data.value(Qt::UserRole+2).toString(), QLatin1String(""));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::cdata()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/recipes.qml"));
+ QDeclarativeXmlListModel *listModel = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 5);
+
+ QList<int> roles;
+ roles << Qt::UserRole + 2;
+ QHash<int, QVariant> data = listModel->data(2, roles);
+ QVERIFY(data.count() == 1);
+ QVERIFY(data.value(Qt::UserRole+2).toString().startsWith(QLatin1String("<html>")));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::attributes()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/recipes.qml"));
+ QDeclarativeXmlListModel *listModel = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 5);
+
+ QList<int> roles;
+ roles << Qt::UserRole;
+ QHash<int, QVariant> data = listModel->data(2, roles);
+ QVERIFY(data.count() == 1);
+ QCOMPARE(data.value(Qt::UserRole).toString(), QLatin1String("Vegetable Soup"));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::roles()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/model.qml"));
+ QDeclarativeXmlListModel *listModel = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles = listModel->roles();
+ QCOMPARE(roles.count(), 4);
+ QCOMPARE(listModel->toString(roles.at(0)), QLatin1String("name"));
+ QCOMPARE(listModel->toString(roles.at(1)), QLatin1String("type"));
+ QCOMPARE(listModel->toString(roles.at(2)), QLatin1String("age"));
+ QCOMPARE(listModel->toString(roles.at(3)), QLatin1String("size"));
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::roleErrors()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/roleErrors.qml"));
+ QTest::ignoreMessage(QtWarningMsg, QString("QML XmlRole (" + QUrl::fromLocalFile(SRCDIR "/data/roleErrors.qml").toString() + ":6:5) An XmlRole query must not start with '/'").toUtf8().constData());
+ //### make sure we receive all expected warning messages.
+ QDeclarativeXmlListModel *listModel = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles;
+ roles << Qt::UserRole << Qt::UserRole + 1 << Qt::UserRole + 2 << Qt::UserRole + 3;
+ QHash<int, QVariant> data = listModel->data(3, roles);
+ QVERIFY(data.count() == 4);
+
+ //### should any of these return valid values?
+ QCOMPARE(data.value(Qt::UserRole), QVariant());
+ QCOMPARE(data.value(Qt::UserRole+1), QVariant());
+ QCOMPARE(data.value(Qt::UserRole+2), QVariant());
+
+ QEXPECT_FAIL("", "QT-2456", Continue);
+ QCOMPARE(data.value(Qt::UserRole+3), QVariant());
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::uniqueRoleNames()
+{
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/unique.qml"));
+ QTest::ignoreMessage(QtWarningMsg, QString("QML XmlRole (" + QUrl::fromLocalFile(SRCDIR "/data/unique.qml").toString() + ":7:5) \"name\" duplicates a previous role name and will be disabled.").toUtf8().constData());
+ QDeclarativeXmlListModel *listModel = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(listModel != 0);
+ QTRY_COMPARE(listModel->count(), 9);
+
+ QList<int> roles = listModel->roles();
+ QCOMPARE(roles.count(), 1);
+
+ delete listModel;
+}
+
+void tst_qmlxmllistmodel::useKeys()
+{
+ // If using incremental updates through keys, the model should only
+ // insert & remove some of the items, instead of throwing everything
+ // away and causing the view to repaint the whole view.
+
+ QFETCH(QString, oldXml);
+ QFETCH(int, oldCount);
+ QFETCH(QString, newXml);
+ QFETCH(QDeclarativeXmlModelData, newData);
+ QFETCH(QList<QDeclarativeXmlListRange>, insertRanges);
+ QFETCH(QList<QDeclarativeXmlListRange>, removeRanges);
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/roleKeys.qml"));
+ QDeclarativeXmlListModel *model = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(model != 0);
+
+ model->setXml(oldXml);
+ QTRY_COMPARE(model->count(), oldCount);
+
+ QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
+ QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
+ QSignalSpy spyCount(model, SIGNAL(countChanged()));
+
+ model->setXml(newXml);
+
+ if (oldCount != newData.count()) {
+ QTRY_COMPARE(model->count(), newData.count());
+ QCOMPARE(spyCount.count(), 1);
+ } else {
+ QTRY_VERIFY(spyInsert.count() > 0 || spyRemove.count() > 0);
+ QCOMPARE(spyCount.count(), 0);
+ }
+
+ QList<int> roles = model->roles();
+ for (int i=0; i<model->count(); i++) {
+ for (int j=0; j<roles.count(); j++)
+ QCOMPARE(model->data(i, roles[j]), newData[i][j]);
+ }
+
+ QCOMPARE(spyInsert.count(), insertRanges.count());
+ for (int i=0; i<spyInsert.count(); i++) {
+ QCOMPARE(spyInsert[i][0].toInt(), insertRanges[i].first);
+ QCOMPARE(spyInsert[i][1].toInt(), insertRanges[i].second);
+ }
+
+ QCOMPARE(spyRemove.count(), removeRanges.count());
+ for (int i=0; i<spyRemove.count(); i++) {
+ QCOMPARE(spyRemove[i][0].toInt(), removeRanges[i].first);
+ QCOMPARE(spyRemove[i][1].toInt(), removeRanges[i].second);
+ }
+}
+
+void tst_qmlxmllistmodel::useKeys_data()
+{
+ QTest::addColumn<QString>("oldXml");
+ QTest::addColumn<int>("oldCount");
+ QTest::addColumn<QString>("newXml");
+ QTest::addColumn<QDeclarativeXmlModelData>("newData");
+ QTest::addColumn<QList<QDeclarativeXmlListRange> >("insertRanges");
+ QTest::addColumn<QList<QDeclarativeXmlListRange> >("removeRanges");
+
+ QDeclarativeXmlModelData modelData;
+
+ QTest::newRow("append 1")
+ << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1))
+ << QList<QDeclarativeXmlListRange>();
+
+ QTest::newRow("append multiple")
+ << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2))
+ << QList<QDeclarativeXmlListRange>();
+
+ QTest::newRow("insert in different spots")
+ << makeItemXmlAndData("name=B,age=35,sport=Athletics") << 1
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1) << qMakePair(2,2))
+ << QList<QDeclarativeXmlListRange>();
+
+ QTest::newRow("insert in middle")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=D,age=55,sport=Golf") << 2
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 2))
+ << QList<QDeclarativeXmlListRange>();
+
+ QTest::newRow("remove first")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics") << 2
+ << makeItemXmlAndData("name=B,age=35,sport=Athletics", &modelData)
+ << modelData
+ << QList<QDeclarativeXmlListRange>()
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1));
+
+ QTest::newRow("remove last")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics") << 2
+ << makeItemXmlAndData("name=A,age=25,sport=Football", &modelData)
+ << modelData
+ << QList<QDeclarativeXmlListRange>()
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1));
+
+ QTest::newRow("remove from multiple spots")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf;name=E,age=65,sport=Fencing") << 5
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=C,age=45,sport=Curling", &modelData)
+ << modelData
+ << QList<QDeclarativeXmlListRange>()
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1) << qMakePair(3,2));
+
+ QTest::newRow("remove all")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling") << 3
+ << makeItemXmlAndData("", &modelData)
+ << modelData
+ << QList<QDeclarativeXmlListRange>()
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 3));
+
+ QTest::newRow("replace item")
+ << makeItemXmlAndData("name=A,age=25,sport=Football") << 1
+ << makeItemXmlAndData("name=ZZZ,age=25,sport=Football", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1))
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1));
+
+ QTest::newRow("add and remove simultaneously")
+ << makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics;name=C,age=45,sport=Curling;name=D,age=55,sport=Golf") << 4
+ << makeItemXmlAndData("name=B,age=35,sport=Athletics;name=E,age=65,sport=Fencing", &modelData)
+ << modelData
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(1, 1))
+ << (QList<QDeclarativeXmlListRange>() << qMakePair(0, 1) << qMakePair(2,2));
+}
+
+void tst_qmlxmllistmodel::noKeysValueChanges()
+{
+ // The 'key' roles are 'name' and 'age', as defined in roleKeys.qml.
+ // If a 'sport' value is changed, the model should not be reloaded,
+ // since 'sport' is not marked as a key.
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/roleKeys.qml"));
+ QDeclarativeXmlListModel *model = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(model != 0);
+
+ QString xml;
+
+ xml = makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics");
+ model->setXml(xml);
+ QTRY_COMPARE(model->count(), 2);
+
+ QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
+ QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
+ QSignalSpy spyCount(model, SIGNAL(countChanged()));
+
+ xml = makeItemXmlAndData("name=A,age=25,sport=AussieRules;name=B,age=35,sport=Athletics");
+ model->setXml(xml);
+
+ // wait for the new xml data to be set, and verify no signals were emitted
+ for (int i=0; i<50; i++) {
+ QTest::qWait(100);
+ if (model->data(0, model->roles()[2]).toString() != QLatin1String("AussieRules"))
+ break;
+ }
+ QCOMPARE(model->data(0, model->roles()[2]).toString(), QLatin1String("AussieRules"));
+
+ QVERIFY(spyInsert.count() == 0);
+ QVERIFY(spyRemove.count() == 0);
+ QVERIFY(spyCount.count() == 0);
+
+ QCOMPARE(model->count(), 2);
+}
+
+void tst_qmlxmllistmodel::keysChanged()
+{
+ // If the key roles change, the next time the data is reloaded, it should
+ // delete all its data and build a clean model (i.e. same behaviour as
+ // if no keys are set).
+
+ QDeclarativeComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/roleKeys.qml"));
+ QDeclarativeXmlListModel *model = qobject_cast<QDeclarativeXmlListModel*>(component.create());
+ QVERIFY(model != 0);
+
+ QString xml = makeItemXmlAndData("name=A,age=25,sport=Football;name=B,age=35,sport=Athletics");
+ model->setXml(xml);
+ QTRY_COMPARE(model->count(), 2);
+
+ QSignalSpy spyInsert(model, SIGNAL(itemsInserted(int,int)));
+ QSignalSpy spyRemove(model, SIGNAL(itemsRemoved(int,int)));
+ QSignalSpy spyCount(model, SIGNAL(countChanged()));
+
+ QVERIFY(QMetaObject::invokeMethod(model, "disableNameKey"));
+ model->setXml(xml);
+
+ QTRY_VERIFY(spyInsert.count() > 0 && spyRemove.count() > 0);
+
+ QCOMPARE(spyInsert.count(), 1);
+ QCOMPARE(spyInsert[0][0].toInt(), 0);
+ QCOMPARE(spyInsert[0][1].toInt(), 2);
+
+ QCOMPARE(spyRemove.count(), 1);
+ QCOMPARE(spyRemove[0][0].toInt(), 0);
+ QCOMPARE(spyRemove[0][1].toInt(), 2);
+
+ QCOMPARE(spyCount.count(), 0);
+}
+
+QTEST_MAIN(tst_qmlxmllistmodel)
+
+#include "tst_qdeclarativexmllistmodel.moc"
+
+#else
+QTEST_NOOP_MAIN
+#endif