diff options
author | Martin Jones <martin.jones@nokia.com> | 2010-02-23 06:47:50 (GMT) |
---|---|---|
committer | Martin Jones <martin.jones@nokia.com> | 2010-02-23 06:47:50 (GMT) |
commit | cb3cd645082bda7b5142ceff31e5795f2d047c39 (patch) | |
tree | 152c67201476d81d423089cc5aef7e214bd8c85b /tests | |
parent | 5ffd6c0fba0ecc709551e414ed0649de15ac3754 (diff) | |
parent | 55fff3383b7fbac972a96c62345bc898c99eafc0 (diff) | |
download | Qt-cb3cd645082bda7b5142ceff31e5795f2d047c39.zip Qt-cb3cd645082bda7b5142ceff31e5795f2d047c39.tar.gz Qt-cb3cd645082bda7b5142ceff31e5795f2d047c39.tar.bz2 |
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt-qml
Diffstat (limited to 'tests')
6 files changed, 263 insertions, 7 deletions
diff --git a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp index ba07331..2f1a557 100644 --- a/tests/auto/declarative/qmldebug/tst_qmldebug.cpp +++ b/tests/auto/declarative/qmldebug/tst_qmldebug.cpp @@ -51,8 +51,8 @@ #include <QtDeclarative/qmlexpression.h> #include <QtDeclarative/qmlmetatype.h> #include <QtDeclarative/qmlmetaproperty.h> -#include <QtDeclarative/qmlbinding.h> +#include <private/qmlbinding_p.h> #include <private/qmldebug_p.h> #include <private/qmlenginedebug_p.h> #include <private/qmldebugclient_p.h> diff --git a/tests/auto/declarative/qmlecmascript/testtypes.h b/tests/auto/declarative/qmlecmascript/testtypes.h index 0af72cb..f511c29 100644 --- a/tests/auto/declarative/qmlecmascript/testtypes.h +++ b/tests/auto/declarative/qmlecmascript/testtypes.h @@ -173,17 +173,21 @@ QML_DECLARE_TYPE(MyQmlContainer); class MyExpression : public QmlExpression { + Q_OBJECT public: MyExpression(QmlContext *ctxt, const QString &expr) : QmlExpression(ctxt, expr, 0), changed(false) { + QObject::connect(this, SIGNAL(valueChanged()), this, SLOT(expressionValueChanged())); + setNotifyOnValueChanged(true); } - void emitValueChanged() { + bool changed; + +public slots: + void expressionValueChanged() { changed = true; - QmlExpression::emitValueChanged(); } - bool changed; }; diff --git a/tests/auto/declarative/qmlgraphicslistview/tst_qmlgraphicslistview.cpp b/tests/auto/declarative/qmlgraphicslistview/tst_qmlgraphicslistview.cpp index e535aaa..cf96ad5 100644 --- a/tests/auto/declarative/qmlgraphicslistview/tst_qmlgraphicslistview.cpp +++ b/tests/auto/declarative/qmlgraphicslistview/tst_qmlgraphicslistview.cpp @@ -1319,7 +1319,6 @@ T *tst_QmlGraphicsListView::findItem(QGraphicsObject *parent, const QString &obj if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) { if (index != -1) { QmlExpression e(qmlContext(item), "index", item); - e.setTrackChange(false); if (e.value().toInt() == index) return static_cast<T*>(item); } else { diff --git a/tests/auto/declarative/qmlgraphicspathview/tst_qmlgraphicspathview.cpp b/tests/auto/declarative/qmlgraphicspathview/tst_qmlgraphicspathview.cpp index bb1c1af..b57142e 100644 --- a/tests/auto/declarative/qmlgraphicspathview/tst_qmlgraphicspathview.cpp +++ b/tests/auto/declarative/qmlgraphicspathview/tst_qmlgraphicspathview.cpp @@ -450,7 +450,6 @@ T *tst_QmlGraphicsPathView::findItem(QGraphicsObject *parent, const QString &obj if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) { if (index != -1) { QmlExpression e(qmlContext(item), "index", item); - e.setTrackChange(false); if (e.value().toInt() == index) return static_cast<T*>(item); } else { diff --git a/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp index c289641..540d658 100644 --- a/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp +++ b/tests/auto/declarative/qmlmetaproperty/tst_qmlmetaproperty.cpp @@ -43,7 +43,7 @@ #include <QtDeclarative/qmlcomponent.h> #include <QtDeclarative/qmlmetaproperty.h> #include <private/qguard_p.h> -#include <QtDeclarative/qmlbinding.h> +#include <private/qmlbinding_p.h> #include <QtGui/QLineEdit> class MyQmlObject : public QObject diff --git a/tests/auto/declarative/qmlxmllistmodel/tst_qmlxmllistmodel.cpp b/tests/auto/declarative/qmlxmllistmodel/tst_qmlxmllistmodel.cpp index df1931f..477b661 100644 --- a/tests/auto/declarative/qmlxmllistmodel/tst_qmlxmllistmodel.cpp +++ b/tests/auto/declarative/qmlxmllistmodel/tst_qmlxmllistmodel.cpp @@ -39,6 +39,8 @@ ** ****************************************************************************/ #include <qtest.h> +#include <QtTest/qsignalspy.h> +#include <QtCore/qtimer.h> #ifdef QTEST_XMLPATTERNS #include <QtDeclarative/qmlengine.h> @@ -46,6 +48,12 @@ #include <private/qmlxmllistmodel_p.h> #include "../../../shared/util.h" +typedef QPair<int, int> QmlXmlListRange; +typedef QList<QVariantList> QmlXmlModelData; + +Q_DECLARE_METATYPE(QList<QmlXmlListRange>) +Q_DECLARE_METATYPE(QmlXmlModelData) + class tst_qmlxmllistmodel : public QObject { @@ -61,8 +69,47 @@ private slots: void roles(); void roleErrors(); void uniqueRoleNames(); + void useKeys(); + void useKeys_data(); + void noKeysValueChanges(); + void keysChanged(); private: + QString makeItemXmlAndData(const QString &data, QmlXmlModelData *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>"); + } + QmlEngine engine; }; @@ -194,6 +241,213 @@ void tst_qmlxmllistmodel::uniqueRoleNames() 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(QmlXmlModelData, newData); + QFETCH(QList<QmlXmlListRange>, insertRanges); + QFETCH(QList<QmlXmlListRange>, removeRanges); + + QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/roleKeys.qml")); + QmlXmlListModel *model = qobject_cast<QmlXmlListModel*>(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<QmlXmlModelData>("newData"); + QTest::addColumn<QList<QmlXmlListRange> >("insertRanges"); + QTest::addColumn<QList<QmlXmlListRange> >("removeRanges"); + + QmlXmlModelData 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<QmlXmlListRange>() << qMakePair(1, 1)) + << QList<QmlXmlListRange>(); + + 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<QmlXmlListRange>() << qMakePair(1, 2)) + << QList<QmlXmlListRange>(); + + 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<QmlXmlListRange>() << qMakePair(0, 1) << qMakePair(2,2)) + << QList<QmlXmlListRange>(); + + 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<QmlXmlListRange>() << qMakePair(1, 2)) + << QList<QmlXmlListRange>(); + + 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<QmlXmlListRange>() + << (QList<QmlXmlListRange>() << 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<QmlXmlListRange>() + << (QList<QmlXmlListRange>() << 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<QmlXmlListRange>() + << (QList<QmlXmlListRange>() << 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<QmlXmlListRange>() + << (QList<QmlXmlListRange>() << 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<QmlXmlListRange>() << qMakePair(0, 1)) + << (QList<QmlXmlListRange>() << 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<QmlXmlListRange>() << qMakePair(1, 1)) + << (QList<QmlXmlListRange>() << 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. + + QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/roleKeys.qml")); + QmlXmlListModel *model = qobject_cast<QmlXmlListModel*>(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). + + QmlComponent component(&engine, QUrl::fromLocalFile(SRCDIR "/data/roleKeys.qml")); + QmlXmlListModel *model = qobject_cast<QmlXmlListModel*>(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_qmlxmllistmodel.moc" |