1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
41 #include "../shared/util.h"
42 #include "../../../shared/util.h"
44 #include <QtTest/QSignalSpy>
45 #include <QStandardItemModel>
46 #include <QtDeclarative/qdeclarativeengine.h>
47 #include <QtDeclarative/qdeclarativecomponent.h>
48 #include <QtDeclarative/qdeclarativecontext.h>
49 #include <QtDeclarative/qdeclarativeexpression.h>
50 #include <QtDeclarative/qsgview.h>
51 #include <private/qsglistview_p.h>
52 #include <private/qsgtext_p.h>
53 #include <private/qsgvisualdatamodel_p.h>
54 #include <private/qdeclarativevaluetype_p.h>
55 #include <private/qdeclarativechangeset_p.h>
56 #include <private/qdeclarativeengine_p.h>
59 template <typename T, int N> int lengthOf(const T (&)[N]) { return N; }
61 static void initStandardTreeModel(QStandardItemModel *model)
64 item = new QStandardItem(QLatin1String("Row 1 Item"));
65 model->insertRow(0, item);
67 item = new QStandardItem(QLatin1String("Row 2 Item"));
68 item->setCheckable(true);
69 model->insertRow(1, item);
71 QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
72 item->setChild(0, childItem);
74 item = new QStandardItem(QLatin1String("Row 3 Item"));
75 item->setIcon(QIcon());
76 model->insertRow(2, item);
79 class SingleRoleModel : public QAbstractListModel
84 SingleRoleModel(const QByteArray &role = "name", QObject *parent = 0) {
85 QHash<int, QByteArray> roles;
86 roles.insert(Qt::DisplayRole , role);
88 list << "one" << "two" << "three" << "four";
91 void emitMove(int sourceFirst, int sourceLast, int destinationChild) {
92 emit beginMoveRows(QModelIndex(), sourceFirst, sourceLast, QModelIndex(), destinationChild);
99 void set(int idx, QString string) {
101 emit dataChanged(index(idx,0), index(idx,0));
105 int rowCount(const QModelIndex &parent = QModelIndex()) const {
108 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
109 if (role == Qt::DisplayRole)
110 return list.at(index.row());
116 class tst_qsgvisualdatamodel : public QObject
120 tst_qsgvisualdatamodel();
124 void cleanupTestCase();
128 void objectListModel();
130 void modelProperties();
132 void qaimRowsMoved();
133 void qaimRowsMoved_data();
141 template <int N> void groups_verify(
142 const SingleRoleModel &model,
143 QSGItem *contentItem,
144 const int (&mIndex)[N],
145 const int (&iIndex)[N],
146 const int (&vIndex)[N],
147 const int (&sIndex)[N],
148 const bool (&vMember)[N],
149 const bool (&sMember)[N]);
151 template <int N> void get_verify(
152 const SingleRoleModel &model,
153 QSGVisualDataModel *visualModel,
154 QSGVisualDataGroup *visibleItems,
155 QSGVisualDataGroup *selectedItems,
156 const int (&mIndex)[N],
157 const int (&iIndex)[N],
158 const int (&vIndex)[N],
159 const int (&sIndex)[N],
160 const bool (&vMember)[N],
161 const bool (&sMember)[N]);
164 QDeclarativeEngine engine;
166 T *findItem(QSGItem *parent, const QString &objectName, int index);
169 Q_DECLARE_METATYPE(QDeclarativeChangeSet)
171 void tst_qsgvisualdatamodel::initTestCase()
173 qRegisterMetaType<QDeclarativeChangeSet>();
176 void tst_qsgvisualdatamodel::cleanupTestCase()
180 class DataObject : public QObject
184 Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
185 Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
188 DataObject(QObject *parent=0) : QObject(parent) {}
189 DataObject(const QString &name, const QString &color, QObject *parent=0)
190 : QObject(parent), m_name(name), m_color(color) { }
193 QString name() const { return m_name; }
194 void setName(const QString &name) {
195 if (name != m_name) {
201 QString color() const { return m_color; }
202 void setColor(const QString &color) {
203 if (color != m_color) {
218 template <typename T> static T evaluate(QObject *scope, const QString &expression)
220 QDeclarativeExpression expr(qmlContext(scope), scope, expression);
221 T result = expr.evaluate().value<T>();
223 qWarning() << expr.error().toString();
227 template <> void evaluate<void>(QObject *scope, const QString &expression)
229 QDeclarativeExpression expr(qmlContext(scope), scope, expression);
232 qWarning() << expr.error().toString();
235 tst_qsgvisualdatamodel::tst_qsgvisualdatamodel()
239 void tst_qsgvisualdatamodel::rootIndex()
241 QDeclarativeEngine engine;
242 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("visualdatamodel.qml")));
244 QStandardItemModel model;
245 initStandardTreeModel(&model);
247 engine.rootContext()->setContextProperty("myModel", &model);
249 QSGVisualDataModel *obj = qobject_cast<QSGVisualDataModel*>(c.create());
252 QMetaObject::invokeMethod(obj, "setRoot");
253 QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
255 QMetaObject::invokeMethod(obj, "setRootToParent");
256 QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
258 QMetaObject::invokeMethod(obj, "setRoot");
259 QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
260 model.clear(); // will emit modelReset()
261 QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
266 void tst_qsgvisualdatamodel::updateLayout()
270 QStandardItemModel model;
271 initStandardTreeModel(&model);
273 view.rootContext()->setContextProperty("myModel", &model);
275 view.setSource(QUrl::fromLocalFile(TESTDATA("datalist.qml")));
277 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
278 QVERIFY(listview != 0);
280 QSGItem *contentItem = listview->contentItem();
281 QVERIFY(contentItem != 0);
283 QSGText *name = findItem<QSGText>(contentItem, "display", 0);
285 QCOMPARE(name->text(), QString("Row 1 Item"));
286 name = findItem<QSGText>(contentItem, "display", 1);
288 QCOMPARE(name->text(), QString("Row 2 Item"));
289 name = findItem<QSGText>(contentItem, "display", 2);
291 QCOMPARE(name->text(), QString("Row 3 Item"));
293 model.invisibleRootItem()->sortChildren(0, Qt::DescendingOrder);
295 name = findItem<QSGText>(contentItem, "display", 0);
297 QCOMPARE(name->text(), QString("Row 3 Item"));
298 name = findItem<QSGText>(contentItem, "display", 1);
300 QCOMPARE(name->text(), QString("Row 2 Item"));
301 name = findItem<QSGText>(contentItem, "display", 2);
303 QCOMPARE(name->text(), QString("Row 1 Item"));
306 void tst_qsgvisualdatamodel::childChanged()
310 QStandardItemModel model;
311 initStandardTreeModel(&model);
313 view.rootContext()->setContextProperty("myModel", &model);
315 view.setSource(QUrl::fromLocalFile(TESTDATA("datalist.qml")));
317 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
318 QVERIFY(listview != 0);
320 QSGItem *contentItem = listview->contentItem();
321 QVERIFY(contentItem != 0);
323 QSGVisualDataModel *vdm = listview->findChild<QSGVisualDataModel*>("visualModel");
324 vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0))));
325 QCOMPARE(listview->count(), 1);
327 QSGText *name = findItem<QSGText>(contentItem, "display", 0);
329 QCOMPARE(name->text(), QString("Row 2 Child Item"));
331 model.item(1,0)->child(0,0)->setText("Row 2 updated child");
333 name = findItem<QSGText>(contentItem, "display", 0);
335 QCOMPARE(name->text(), QString("Row 2 updated child"));
337 model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2")));
338 QCOMPARE(listview->count(), 2);
340 name = findItem<QSGText>(contentItem, "display", 1);
342 QCOMPARE(name->text(), QString("Row 2 Child Item 2"));
344 model.item(1,0)->takeRow(1);
345 name = findItem<QSGText>(contentItem, "display", 1);
348 vdm->setRootIndex(QVariant::fromValue(QModelIndex()));
349 QCOMPARE(listview->count(), 3);
350 name = findItem<QSGText>(contentItem, "display", 0);
352 QCOMPARE(name->text(), QString("Row 1 Item"));
353 name = findItem<QSGText>(contentItem, "display", 1);
355 QCOMPARE(name->text(), QString("Row 2 Item"));
356 name = findItem<QSGText>(contentItem, "display", 2);
358 QCOMPARE(name->text(), QString("Row 3 Item"));
361 void tst_qsgvisualdatamodel::objectListModel()
365 QList<QObject*> dataList;
366 dataList.append(new DataObject("Item 1", "red"));
367 dataList.append(new DataObject("Item 2", "green"));
368 dataList.append(new DataObject("Item 3", "blue"));
369 dataList.append(new DataObject("Item 4", "yellow"));
371 QDeclarativeContext *ctxt = view.rootContext();
372 ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
374 view.setSource(QUrl::fromLocalFile(TESTDATA("objectlist.qml")));
376 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
377 QVERIFY(listview != 0);
379 QSGItem *contentItem = listview->contentItem();
380 QVERIFY(contentItem != 0);
382 QSGText *name = findItem<QSGText>(contentItem, "name", 0);
383 QCOMPARE(name->text(), QString("Item 1"));
385 QSGText *section = findItem<QSGText>(contentItem, "section", 0);
386 QCOMPARE(section->text(), QString("Item 1"));
388 dataList[0]->setProperty("name", QLatin1String("Changed"));
389 QCOMPARE(name->text(), QString("Changed"));
392 void tst_qsgvisualdatamodel::singleRole()
397 SingleRoleModel model;
399 QDeclarativeContext *ctxt = view.rootContext();
400 ctxt->setContextProperty("myModel", &model);
402 view.setSource(QUrl::fromLocalFile(TESTDATA("singlerole1.qml")));
404 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
405 QVERIFY(listview != 0);
407 QSGItem *contentItem = listview->contentItem();
408 QVERIFY(contentItem != 0);
410 QSGText *name = findItem<QSGText>(contentItem, "name", 1);
411 QCOMPARE(name->text(), QString("two"));
413 model.set(1, "Changed");
414 QCOMPARE(name->text(), QString("Changed"));
419 SingleRoleModel model;
421 QDeclarativeContext *ctxt = view.rootContext();
422 ctxt->setContextProperty("myModel", &model);
424 view.setSource(QUrl::fromLocalFile(TESTDATA("singlerole2.qml")));
426 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
427 QVERIFY(listview != 0);
429 QSGItem *contentItem = listview->contentItem();
430 QVERIFY(contentItem != 0);
432 QSGText *name = findItem<QSGText>(contentItem, "name", 1);
433 QCOMPARE(name->text(), QString("two"));
435 model.set(1, "Changed");
436 QCOMPARE(name->text(), QString("Changed"));
441 SingleRoleModel model("modelData");
443 QDeclarativeContext *ctxt = view.rootContext();
444 ctxt->setContextProperty("myModel", &model);
446 view.setSource(QUrl::fromLocalFile(TESTDATA("singlerole2.qml")));
448 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
449 QVERIFY(listview != 0);
451 QSGItem *contentItem = listview->contentItem();
452 QVERIFY(contentItem != 0);
454 QSGText *name = findItem<QSGText>(contentItem, "name", 1);
455 QCOMPARE(name->text(), QString("two"));
457 model.set(1, "Changed");
458 QCOMPARE(name->text(), QString("Changed"));
462 void tst_qsgvisualdatamodel::modelProperties()
467 SingleRoleModel model;
469 QDeclarativeContext *ctxt = view.rootContext();
470 ctxt->setContextProperty("myModel", &model);
472 view.setSource(QUrl::fromLocalFile(TESTDATA("modelproperties.qml")));
474 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
475 QVERIFY(listview != 0);
477 QSGItem *contentItem = listview->contentItem();
478 QVERIFY(contentItem != 0);
480 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", 1);
482 QCOMPARE(delegate->property("test1").toString(),QString("two"));
483 QCOMPARE(delegate->property("test2").toString(),QString("two"));
484 QCOMPARE(delegate->property("test3").toString(),QString("two"));
485 QCOMPARE(delegate->property("test4").toString(),QString("two"));
486 QVERIFY(!delegate->property("test9").isValid());
487 QCOMPARE(delegate->property("test5").toString(),QString(""));
488 QVERIFY(delegate->property("test6").value<QObject*>() != 0);
489 QCOMPARE(delegate->property("test7").toInt(),1);
490 QCOMPARE(delegate->property("test8").toInt(),1);
496 QList<QObject*> dataList;
497 dataList.append(new DataObject("Item 1", "red"));
498 dataList.append(new DataObject("Item 2", "green"));
499 dataList.append(new DataObject("Item 3", "blue"));
500 dataList.append(new DataObject("Item 4", "yellow"));
502 QDeclarativeContext *ctxt = view.rootContext();
503 ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
505 view.setSource(QUrl::fromLocalFile(TESTDATA("modelproperties.qml")));
507 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
508 QVERIFY(listview != 0);
510 QSGItem *contentItem = listview->contentItem();
511 QVERIFY(contentItem != 0);
513 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", 1);
515 QCOMPARE(delegate->property("test1").toString(),QString("Item 2"));
516 QCOMPARE(delegate->property("test2").toString(),QString("Item 2"));
517 QVERIFY(qobject_cast<DataObject*>(delegate->property("test3").value<QObject*>()) != 0);
518 QVERIFY(qobject_cast<DataObject*>(delegate->property("test4").value<QObject*>()) != 0);
519 QCOMPARE(delegate->property("test5").toString(),QString("Item 2"));
520 QCOMPARE(delegate->property("test9").toString(),QString("Item 2"));
521 QVERIFY(delegate->property("test6").value<QObject*>() != 0);
522 QCOMPARE(delegate->property("test7").toInt(),1);
523 QCOMPARE(delegate->property("test8").toInt(),1);
529 QStandardItemModel model;
530 initStandardTreeModel(&model);
532 view.rootContext()->setContextProperty("myModel", &model);
534 QUrl source(QUrl::fromLocalFile(TESTDATA("modelproperties2.qml")));
536 //3 items, 3 warnings each
537 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData");
538 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData");
539 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":13: ReferenceError: Can't find variable: modelData");
540 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
541 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
542 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
543 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
544 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
545 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":17: TypeError: Cannot read property 'display' of undefined");
547 view.setSource(source);
549 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
550 QVERIFY(listview != 0);
552 QSGItem *contentItem = listview->contentItem();
553 QVERIFY(contentItem != 0);
555 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", 1);
557 QCOMPARE(delegate->property("test1").toString(),QString("Row 2 Item"));
558 QCOMPARE(delegate->property("test2").toString(),QString("Row 2 Item"));
559 QVERIFY(!delegate->property("test3").isValid());
560 QVERIFY(!delegate->property("test4").isValid());
561 QVERIFY(!delegate->property("test5").isValid());
562 QVERIFY(!delegate->property("test9").isValid());
563 QVERIFY(delegate->property("test6").value<QObject*>() != 0);
564 QCOMPARE(delegate->property("test7").toInt(),1);
565 QCOMPARE(delegate->property("test8").toInt(),1);
568 //### should also test QStringList and QVariantList
571 void tst_qsgvisualdatamodel::noDelegate()
575 QStandardItemModel model;
576 initStandardTreeModel(&model);
578 view.rootContext()->setContextProperty("myModel", &model);
580 view.setSource(QUrl::fromLocalFile(TESTDATA("datalist.qml")));
582 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
583 QVERIFY(listview != 0);
585 QSGVisualDataModel *vdm = listview->findChild<QSGVisualDataModel*>("visualModel");
587 QCOMPARE(vdm->count(), 3);
590 QCOMPARE(vdm->count(), 0);
594 void tst_qsgvisualdatamodel::qaimRowsMoved()
596 // Test parameters passed in QAIM::rowsMoved() signal are converted correctly
597 // when translated and emitted as the QListModelInterface::itemsMoved() signal
598 QFETCH(int, sourceFirst);
599 QFETCH(int, sourceLast);
600 QFETCH(int, destinationChild);
601 QFETCH(int, expectFrom);
602 QFETCH(int, expectTo);
603 QFETCH(int, expectCount);
605 QDeclarativeEngine engine;
606 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("visualdatamodel.qml")));
608 SingleRoleModel model;
610 for (int i=0; i<30; i++)
611 model.list << ("item " + i);
612 engine.rootContext()->setContextProperty("myModel", &model);
614 QSGVisualDataModel *obj = qobject_cast<QSGVisualDataModel*>(c.create());
617 QSignalSpy spy(obj, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)));
618 model.emitMove(sourceFirst, sourceLast, destinationChild);
619 // QAbstractItemModel also emits the changed signal when items are moved.
620 QCOMPARE(spy.count(), 2);
623 for (int i = 0; i < 2; ++i) {
624 QCOMPARE(spy[1].count(), 2);
625 QDeclarativeChangeSet changeSet = spy[i][0].value<QDeclarativeChangeSet>();
626 if (!changeSet.changes().isEmpty())
629 QCOMPARE(changeSet.removes().count(), 1);
630 QCOMPARE(changeSet.removes().at(0).index, expectFrom);
631 QCOMPARE(changeSet.removes().at(0).count, expectCount);
632 QCOMPARE(changeSet.inserts().count(), 1);
633 QCOMPARE(changeSet.inserts().at(0).index, expectTo);
634 QCOMPARE(changeSet.inserts().at(0).count, expectCount);
635 QCOMPARE(changeSet.removes().at(0).moveId, changeSet.inserts().at(0).moveId);
636 QCOMPARE(spy[i][1].toBool(), false);
643 void tst_qsgvisualdatamodel::qaimRowsMoved_data()
645 QTest::addColumn<int>("sourceFirst");
646 QTest::addColumn<int>("sourceLast");
647 QTest::addColumn<int>("destinationChild");
648 QTest::addColumn<int>("expectFrom");
649 QTest::addColumn<int>("expectTo");
650 QTest::addColumn<int>("expectCount");
652 QTest::newRow("move 1 forward")
656 QTest::newRow("move 1 backwards")
660 QTest::newRow("move multiple forwards")
664 QTest::newRow("move multiple forwards, with same to")
668 QTest::newRow("move multiple backwards")
673 void tst_qsgvisualdatamodel::remove()
677 SingleRoleModel model;
678 model.list = QStringList()
692 QDeclarativeContext *ctxt = view.rootContext();
693 ctxt->setContextProperty("myModel", &model);
695 view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
697 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
698 QVERIFY(listview != 0);
700 QSGItem *contentItem = listview->contentItem();
701 QVERIFY(contentItem != 0);
703 QSGVisualDataModel *visualModel = qobject_cast<QSGVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
704 QVERIFY(visualModel);
707 QCOMPARE(listview->count(), 12);
708 QCOMPARE(visualModel->items()->count(), 12);
709 static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
710 static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
712 for (int i = 0; i < lengthOf(mIndex); ++i) {
713 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", mIndex[i]);
715 QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
716 QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
717 QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
720 evaluate<void>(visualModel, "items.remove(2)");
721 QCOMPARE(listview->count(), 11);
722 QCOMPARE(visualModel->items()->count(), 11);
723 static const int mIndex[] = { 0, 1, 3, 4, 5, 6, 7, 8, 9,10,11 };
724 static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10 };
726 for (int i = 0; i < lengthOf(mIndex); ++i) {
727 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", mIndex[i]);
729 QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
730 QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
731 QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
734 evaluate<void>(visualModel, "items.remove(1, 4)");
735 QCOMPARE(listview->count(), 7);
736 QCOMPARE(visualModel->items()->count(), 7);
737 static const int mIndex[] = { 0, 6, 7, 8, 9,10,11 };
738 static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6 };
740 for (int i = 0; i < lengthOf(mIndex); ++i) {
741 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", mIndex[i]);
743 QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
744 QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
745 QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
748 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
749 evaluate<void>(visualModel, "items.remove(-8, 4)");
750 QCOMPARE(listview->count(), 7);
751 QCOMPARE(visualModel->items()->count(), 7);
753 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
754 evaluate<void>(visualModel, "items.remove(12, 2)");
755 QCOMPARE(listview->count(), 7);
756 QCOMPARE(visualModel->items()->count(), 7);
758 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: index out of range");
759 evaluate<void>(visualModel, "items.remove(5, 3)");
760 QCOMPARE(listview->count(), 7);
761 QCOMPARE(visualModel->items()->count(), 7);
763 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: remove: invalid count");
764 evaluate<void>(visualModel, "items.remove(5, -2)");
765 QCOMPARE(listview->count(), 7);
766 QCOMPARE(visualModel->items()->count(), 7);
770 void tst_qsgvisualdatamodel::move()
774 SingleRoleModel model;
775 model.list = QStringList()
789 QDeclarativeContext *ctxt = view.rootContext();
790 ctxt->setContextProperty("myModel", &model);
792 view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
794 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
795 QVERIFY(listview != 0);
797 QSGItem *contentItem = listview->contentItem();
798 QVERIFY(contentItem != 0);
800 QSGVisualDataModel *visualModel = qobject_cast<QSGVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
801 QVERIFY(visualModel);
804 QCOMPARE(listview->count(), 12);
805 QCOMPARE(visualModel->items()->count(), 12);
806 static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
807 static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
809 for (int i = 0; i < lengthOf(mIndex); ++i) {
810 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", mIndex[i]);
812 QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
813 QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
814 QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
817 evaluate<void>(visualModel, "items.move(2, 4)");
818 QCOMPARE(listview->count(), 12);
819 QCOMPARE(visualModel->items()->count(), 12);
820 static const int mIndex[] = { 0, 1, 3, 4, 2, 5, 6, 7, 8, 9,10,11 };
821 static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
823 for (int i = 0; i < lengthOf(mIndex); ++i) {
824 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", mIndex[i]);
826 QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
827 QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
828 QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
831 evaluate<void>(visualModel, "items.move(4, 2)");
832 QCOMPARE(listview->count(), 12);
833 QCOMPARE(visualModel->items()->count(), 12);
834 static const int mIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
835 static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
837 for (int i = 0; i < lengthOf(mIndex); ++i) {
838 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", mIndex[i]);
840 QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
841 QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
842 QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
845 evaluate<void>(visualModel, "items.move(8, 0, 4)");
846 QCOMPARE(listview->count(), 12);
847 QCOMPARE(visualModel->items()->count(), 12);
848 static const int mIndex[] = { 8, 9,10,11, 0, 1, 2, 3, 4, 5, 6, 7 };
849 static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
851 for (int i = 0; i < lengthOf(mIndex); ++i) {
852 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", mIndex[i]);
854 QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
855 QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
856 QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
859 evaluate<void>(visualModel, "items.move(3, 4, 5)");
860 QCOMPARE(listview->count(), 12);
861 QCOMPARE(visualModel->items()->count(), 12);
862 static const int mIndex[] = { 8, 9,10,4, 11, 0, 1, 2, 3, 5, 6, 7 };
863 static const int iIndex[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
865 for (int i = 0; i < lengthOf(mIndex); ++i) {
866 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", mIndex[i]);
868 QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
869 QCOMPARE(delegate->property("test2").toInt(), mIndex[i]);
870 QCOMPARE(delegate->property("test3").toInt(), iIndex[i]);
873 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: invalid count");
874 evaluate<void>(visualModel, "items.move(5, 2, -2)");
875 QCOMPARE(listview->count(), 12);
876 QCOMPARE(visualModel->items()->count(), 12);
878 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
879 evaluate<void>(visualModel, "items.move(-6, 2, 1)");
880 QCOMPARE(listview->count(), 12);
881 QCOMPARE(visualModel->items()->count(), 12);
883 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
884 evaluate<void>(visualModel, "items.move(15, 2, 1)");
885 QCOMPARE(listview->count(), 12);
886 QCOMPARE(visualModel->items()->count(), 12);
888 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: from index out of range");
889 evaluate<void>(visualModel, "items.move(11, 1, 3)");
890 QCOMPARE(listview->count(), 12);
891 QCOMPARE(visualModel->items()->count(), 12);
893 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
894 evaluate<void>(visualModel, "items.move(2, -5, 1)");
895 QCOMPARE(listview->count(), 12);
896 QCOMPARE(visualModel->items()->count(), 12);
898 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
899 evaluate<void>(visualModel, "items.move(2, 14, 1)");
900 QCOMPARE(listview->count(), 12);
901 QCOMPARE(visualModel->items()->count(), 12);
903 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: move: to index out of range");
904 evaluate<void>(visualModel, "items.move(2, 11, 4)");
905 QCOMPARE(listview->count(), 12);
906 QCOMPARE(visualModel->items()->count(), 12);
911 template <int N> void tst_qsgvisualdatamodel::groups_verify(
912 const SingleRoleModel &model,
913 QSGItem *contentItem,
914 const int (&mIndex)[N],
915 const int (&iIndex)[N],
916 const int (&vIndex)[N],
917 const int (&sIndex)[N],
918 const bool (&vMember)[N],
919 const bool (&sMember)[N])
922 for (int i = 0; i < N; ++i) {
923 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", mIndex[i]);
925 QCOMPARE(delegate->property("test1").toString(), model.list.at(mIndex[i]));
926 QCOMPARE(delegate->property("test2").toInt() , mIndex[i]);
927 QCOMPARE(delegate->property("test3").toInt() , iIndex[i]);
928 QCOMPARE(delegate->property("test4").toBool(), true);
929 QCOMPARE(delegate->property("test5").toInt() , vIndex[i]);
930 QCOMPARE(delegate->property("test6").toBool(), vMember[i]);
931 QCOMPARE(delegate->property("test7").toInt() , sIndex[i]);
932 QCOMPARE(delegate->property("test8").toBool(), sMember[i]);
933 QCOMPARE(delegate->property("test9").toStringList().contains("items") , QBool(true));
934 QCOMPARE(delegate->property("test9").toStringList().contains("visible") , QBool(vMember[i]));
935 QCOMPARE(delegate->property("test9").toStringList().contains("selected"), QBool(sMember[i]));
940 #define VERIFY_GROUPS \
941 groups_verify(model, contentItem, mIndex, iIndex, vIndex, sIndex, vMember, sMember); \
945 void tst_qsgvisualdatamodel::groups()
949 SingleRoleModel model;
950 model.list = QStringList()
964 QDeclarativeContext *ctxt = view.rootContext();
965 ctxt->setContextProperty("myModel", &model);
967 view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
969 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
970 QVERIFY(listview != 0);
972 QSGItem *contentItem = listview->contentItem();
973 QVERIFY(contentItem != 0);
975 QSGVisualDataModel *visualModel = qobject_cast<QSGVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
976 QVERIFY(visualModel);
978 QSGVisualDataGroup *visibleItems = visualModel->findChild<QSGVisualDataGroup *>("visibleItems");
979 QVERIFY(visibleItems);
981 QSGVisualDataGroup *selectedItems = visualModel->findChild<QSGVisualDataGroup *>("selectedItems");
982 QVERIFY(selectedItems);
984 const bool f = false;
988 QCOMPARE(listview->count(), 12);
989 QCOMPARE(visualModel->items()->count(), 12);
990 QCOMPARE(visibleItems->count(), 12);
991 QCOMPARE(selectedItems->count(), 0);
992 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
993 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
994 static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
995 static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
996 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
997 static const bool sMember[] = { f, f, f, f, f, f, f, f, f, f, f, f };
1000 evaluate<void>(visualModel, "items.addGroups(8, \"selected\")");
1001 QCOMPARE(listview->count(), 12);
1002 QCOMPARE(visualModel->items()->count(), 12);
1003 QCOMPARE(visibleItems->count(), 12);
1004 QCOMPARE(selectedItems->count(), 1);
1005 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1006 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1007 static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1008 static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
1009 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 };
1010 static const bool sMember[] = { f, f, f, f, f, f, f, f, t, f, f, f };
1013 evaluate<void>(visualModel, "items.addGroups(6, 4, [\"visible\", \"selected\"])");
1014 QCOMPARE(listview->count(), 12);
1015 QCOMPARE(visualModel->items()->count(), 12);
1016 QCOMPARE(visibleItems->count(), 12);
1017 QCOMPARE(selectedItems->count(), 4);
1018 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1019 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1020 static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1021 static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
1022 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4 };
1023 static const bool sMember[] = { f, f, f, f, f, f, t, t, t, t, f, f };
1026 evaluate<void>(visualModel, "items.setGroups(2, [\"items\", \"selected\"])");
1027 QCOMPARE(listview->count(), 12);
1028 QCOMPARE(visualModel->items()->count(), 12);
1029 QCOMPARE(visibleItems->count(), 11);
1030 QCOMPARE(selectedItems->count(), 5);
1031 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1032 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1033 static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9,10 };
1034 static const bool vMember[] = { t, t, f, t, t, t, t, t, t, t, t, t };
1035 static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 1, 2, 3, 4, 5, 5 };
1036 static const bool sMember[] = { f, f, t, f, f, f, t, t, t, t, f, f };
1039 evaluate<void>(selectedItems, "setGroups(0, 3, \"items\")");
1040 QCOMPARE(listview->count(), 12);
1041 QCOMPARE(visualModel->items()->count(), 12);
1042 QCOMPARE(visibleItems->count(), 9);
1043 QCOMPARE(selectedItems->count(), 2);
1044 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1045 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1046 static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
1047 static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t };
1048 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
1049 static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
1052 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: invalid count");
1053 evaluate<void>(visualModel, "items.addGroups(11, -4, \"items\")");
1054 QCOMPARE(listview->count(), 12);
1055 QCOMPARE(visualModel->items()->count(), 12);
1056 QCOMPARE(visibleItems->count(), 9);
1057 QCOMPARE(selectedItems->count(), 2);
1059 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
1060 evaluate<void>(visualModel, "items.addGroups(-1, 3, \"items\")");
1061 QCOMPARE(listview->count(), 12);
1062 QCOMPARE(visualModel->items()->count(), 12);
1063 QCOMPARE(visibleItems->count(), 9);
1064 QCOMPARE(selectedItems->count(), 2);
1066 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
1067 evaluate<void>(visualModel, "items.addGroups(14, 3, \"items\")");
1068 QCOMPARE(listview->count(), 12);
1069 QCOMPARE(visualModel->items()->count(), 12);
1070 QCOMPARE(visibleItems->count(), 9);
1071 QCOMPARE(selectedItems->count(), 2);
1073 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: addGroups: index out of range");
1074 evaluate<void>(visualModel, "items.addGroups(11, 5, \"items\")");
1075 QCOMPARE(listview->count(), 12);
1076 QCOMPARE(visualModel->items()->count(), 12);
1077 QCOMPARE(visibleItems->count(), 9);
1078 QCOMPARE(selectedItems->count(), 2);
1080 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: invalid count");
1081 evaluate<void>(visualModel, "items.setGroups(11, -4, \"items\")");
1082 QCOMPARE(listview->count(), 12);
1083 QCOMPARE(visualModel->items()->count(), 12);
1084 QCOMPARE(visibleItems->count(), 9);
1085 QCOMPARE(selectedItems->count(), 2);
1087 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
1088 evaluate<void>(visualModel, "items.setGroups(-1, 3, \"items\")");
1089 QCOMPARE(listview->count(), 12);
1090 QCOMPARE(visualModel->items()->count(), 12);
1091 QCOMPARE(visibleItems->count(), 9);
1092 QCOMPARE(selectedItems->count(), 2);
1094 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
1095 evaluate<void>(visualModel, "items.setGroups(14, 3, \"items\")");
1096 QCOMPARE(listview->count(), 12);
1097 QCOMPARE(visualModel->items()->count(), 12);
1098 QCOMPARE(visibleItems->count(), 9);
1099 QCOMPARE(selectedItems->count(), 2);
1101 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: setGroups: index out of range");
1102 evaluate<void>(visualModel, "items.setGroups(11, 5, \"items\")");
1103 QCOMPARE(listview->count(), 12);
1104 QCOMPARE(visualModel->items()->count(), 12);
1105 QCOMPARE(visibleItems->count(), 9);
1106 QCOMPARE(selectedItems->count(), 2);
1108 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: invalid count");
1109 evaluate<void>(visualModel, "items.removeGroups(11, -4, \"items\")");
1110 QCOMPARE(listview->count(), 12);
1111 QCOMPARE(visualModel->items()->count(), 12);
1113 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
1114 evaluate<void>(visualModel, "items.removeGroups(-1, 3, \"items\")");
1115 QCOMPARE(listview->count(), 12);
1116 QCOMPARE(visualModel->items()->count(), 12);
1117 QCOMPARE(visibleItems->count(), 9);
1118 QCOMPARE(selectedItems->count(), 2);
1120 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
1121 evaluate<void>(visualModel, "items.removeGroups(14, 3, \"items\")");
1122 QCOMPARE(listview->count(), 12);
1123 QCOMPARE(visualModel->items()->count(), 12);
1124 QCOMPARE(visibleItems->count(), 9);
1125 QCOMPARE(selectedItems->count(), 2);
1127 QTest::ignoreMessage(QtWarningMsg, "<Unknown File>: QML VisualDataGroup: removeGroups: index out of range");
1128 evaluate<void>(visualModel, "items.removeGroups(11, 5, \"items\")");
1129 QCOMPARE(listview->count(), 12);
1130 QCOMPARE(visualModel->items()->count(), 12);
1131 QCOMPARE(visibleItems->count(), 9);
1132 QCOMPARE(selectedItems->count(), 2);
1134 evaluate<void>(visualModel, "filterOnGroup = \"visible\"");
1135 QCOMPARE(listview->count(), 9);
1136 QCOMPARE(visualModel->items()->count(), 12);
1137 QCOMPARE(visibleItems->count(), 9);
1138 QCOMPARE(selectedItems->count(), 2);
1140 evaluate<void>(visualModel, "filterOnGroup = \"selected\"");
1141 QCOMPARE(listview->count(), 2);
1142 QCOMPARE(visualModel->items()->count(), 12);
1143 QCOMPARE(visibleItems->count(), 9);
1144 QCOMPARE(selectedItems->count(), 2);
1146 evaluate<void>(visualModel, "filterOnGroup = \"items\"");
1147 QCOMPARE(listview->count(), 12);
1148 QCOMPARE(visualModel->items()->count(), 12);
1149 QCOMPARE(visibleItems->count(), 9);
1150 QCOMPARE(selectedItems->count(), 2);
1152 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", 5);
1155 evaluate<void>(delegate, "hide()");
1156 QCOMPARE(listview->count(), 12);
1157 QCOMPARE(visualModel->items()->count(), 12);
1158 QCOMPARE(visibleItems->count(), 8);
1159 QCOMPARE(selectedItems->count(), 2);
1160 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1161 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1162 static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
1163 static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
1164 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
1165 static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
1168 QSGItem *delegate = findItem<QSGItem>(contentItem, "delegate", 5);
1171 evaluate<void>(delegate, "select()");
1172 QCOMPARE(listview->count(), 12);
1173 QCOMPARE(visualModel->items()->count(), 12);
1174 QCOMPARE(visibleItems->count(), 8);
1175 QCOMPARE(selectedItems->count(), 3);
1176 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1177 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1178 static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
1179 static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
1180 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 };
1181 static const bool sMember[] = { f, f, f, f, f, t, f, f, t, t, f, f };
1184 evaluate<void>(visualModel, "items.move(2, 6, 3)");
1185 QCOMPARE(listview->count(), 12);
1186 QCOMPARE(visualModel->items()->count(), 12);
1187 QCOMPARE(visibleItems->count(), 8);
1188 QCOMPARE(selectedItems->count(), 3);
1189 static const int mIndex [] = { 0, 1, 5, 6, 7, 8, 2, 3, 4, 9,10,11 };
1190 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1191 static const int vIndex [] = { 0, 1, 2, 2, 2, 2, 3, 3, 4, 5, 6, 7 };
1192 static const bool vMember[] = { t, t, f, f, f, t, f, t, t, t, t, t };
1193 static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3 };
1194 static const bool sMember[] = { f, f, t, f, f, t, f, f, f, t, f, f };
1199 template <int N> void tst_qsgvisualdatamodel::get_verify(
1200 const SingleRoleModel &model,
1201 QSGVisualDataModel *visualModel,
1202 QSGVisualDataGroup *visibleItems,
1203 QSGVisualDataGroup *selectedItems,
1204 const int (&mIndex)[N],
1205 const int (&iIndex)[N],
1206 const int (&vIndex)[N],
1207 const int (&sIndex)[N],
1208 const bool (&vMember)[N],
1209 const bool (&sMember)[N])
1212 for (int i = 0; i < N; ++i) {
1213 QCOMPARE(evaluate<QString>(visualModel, QString("items.get(%1).model.name").arg(i)), model.list.at(mIndex[i]));
1214 QCOMPARE(evaluate<QString>(visualModel, QString("items.get(%1).model.modelData").arg(i)), model.list.at(mIndex[i]));
1215 QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).model.index").arg(i)), mIndex[i]);
1216 QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).itemsIndex").arg(i)), iIndex[i]);
1217 QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inItems").arg(i)), true);
1218 QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).visibleIndex").arg(i)), vIndex[i]);
1219 QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inVisible").arg(i)), vMember[i]);
1220 QCOMPARE(evaluate<int>(visualModel, QString("items.get(%1).selectedIndex").arg(i)), sIndex[i]);
1221 QCOMPARE(evaluate<bool>(visualModel, QString("items.get(%1).inSelected").arg(i)), sMember[i]);
1222 QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"items\")").arg(i)), true);
1223 QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"visible\")").arg(i)), vMember[i]);
1224 QCOMPARE(evaluate<bool>(visualModel, QString("contains(items.get(%1).groups, \"selected\")").arg(i)), sMember[i]);
1227 QCOMPARE(evaluate<QString>(visibleItems, QString("get(%1).model.name").arg(vIndex[i])), model.list.at(mIndex[i]));
1228 QCOMPARE(evaluate<QString>(visibleItems, QString("get(%1).model.modelData").arg(vIndex[i])), model.list.at(mIndex[i]));
1229 QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).model.index").arg(vIndex[i])), mIndex[i]);
1230 QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).itemsIndex").arg(vIndex[i])), iIndex[i]);
1231 QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inItems").arg(vIndex[i])), true);
1232 QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).visibleIndex").arg(vIndex[i])), vIndex[i]);
1233 QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inVisible").arg(vIndex[i])), vMember[i]);
1234 QCOMPARE(evaluate<int>(visibleItems, QString("get(%1).selectedIndex").arg(vIndex[i])), sIndex[i]);
1235 QCOMPARE(evaluate<bool>(visibleItems, QString("get(%1).inSelected").arg(vIndex[i])), sMember[i]);
1237 QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"items\")").arg(vIndex[i])), true);
1238 QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"visible\")").arg(vIndex[i])), vMember[i]);
1239 QCOMPARE(evaluate<bool>(visibleItems, QString("contains(get(%1).groups, \"selected\")").arg(vIndex[i])), sMember[i]);
1242 QCOMPARE(evaluate<QString>(selectedItems, QString("get(%1).model.name").arg(sIndex[i])), model.list.at(mIndex[i]));
1243 QCOMPARE(evaluate<QString>(selectedItems, QString("get(%1).model.modelData").arg(sIndex[i])), model.list.at(mIndex[i]));
1244 QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).model.index").arg(sIndex[i])), mIndex[i]);
1245 QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).itemsIndex").arg(sIndex[i])), iIndex[i]);
1246 QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inItems").arg(sIndex[i])), true);
1247 QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).visibleIndex").arg(sIndex[i])), vIndex[i]);
1248 QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inVisible").arg(sIndex[i])), vMember[i]);
1249 QCOMPARE(evaluate<int>(selectedItems, QString("get(%1).selectedIndex").arg(sIndex[i])), sIndex[i]);
1250 QCOMPARE(evaluate<bool>(selectedItems, QString("get(%1).inSelected").arg(sIndex[i])), sMember[i]);
1251 QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"items\")").arg(sIndex[i])), true);
1252 QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"visible\")").arg(sIndex[i])), vMember[i]);
1253 QCOMPARE(evaluate<bool>(selectedItems, QString("contains(get(%1).groups, \"selected\")").arg(sIndex[i])), sMember[i]);
1259 #define VERIFY_GET \
1260 get_verify(model, visualModel, visibleItems, selectedItems, mIndex, iIndex, vIndex, sIndex, vMember, sMember); \
1263 void tst_qsgvisualdatamodel::get()
1267 SingleRoleModel model;
1268 model.list = QStringList()
1282 QDeclarativeContext *ctxt = view.rootContext();
1283 ctxt->setContextProperty("myModel", &model);
1285 view.setSource(QUrl::fromLocalFile(TESTDATA("groups.qml")));
1287 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
1288 QVERIFY(listview != 0);
1290 QSGItem *contentItem = listview->contentItem();
1291 QVERIFY(contentItem != 0);
1293 QSGVisualDataModel *visualModel = qobject_cast<QSGVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
1294 QVERIFY(visualModel);
1296 QSGVisualDataGroup *visibleItems = visualModel->findChild<QSGVisualDataGroup *>("visibleItems");
1297 QVERIFY(visibleItems);
1299 QSGVisualDataGroup *selectedItems = visualModel->findChild<QSGVisualDataGroup *>("selectedItems");
1300 QVERIFY(selectedItems);
1302 QV8Engine *v8Engine = QDeclarativeEnginePrivate::getV8Engine(ctxt->engine());
1305 const bool f = false;
1306 const bool t = true;
1309 QCOMPARE(listview->count(), 12);
1310 QCOMPARE(visualModel->items()->count(), 12);
1311 QCOMPARE(visibleItems->count(), 12);
1312 QCOMPARE(selectedItems->count(), 0);
1313 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1314 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1315 static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1316 static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
1317 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1318 static const bool sMember[] = { f, f, f, f, f, f, f, f, f, f, f, f };
1321 evaluate<void>(visualModel, "items.addGroups(8, \"selected\")");
1322 QCOMPARE(listview->count(), 12);
1323 QCOMPARE(visualModel->items()->count(), 12);
1324 QCOMPARE(visibleItems->count(), 12);
1325 QCOMPARE(selectedItems->count(), 1);
1326 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1327 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1328 static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1329 static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
1330 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1 };
1331 static const bool sMember[] = { f, f, f, f, f, f, f, f, t, f, f, f };
1334 evaluate<void>(visualModel, "items.addGroups(6, 4, [\"visible\", \"selected\"])");
1335 QCOMPARE(listview->count(), 12);
1336 QCOMPARE(visualModel->items()->count(), 12);
1337 QCOMPARE(visibleItems->count(), 12);
1338 QCOMPARE(selectedItems->count(), 4);
1339 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1340 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1341 static const int vIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1342 static const bool vMember[] = { t, t, t, t, t, t, t, t, t, t, t, t };
1343 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 4 };
1344 static const bool sMember[] = { f, f, f, f, f, f, t, t, t, t, f, f };
1347 evaluate<void>(visualModel, "items.setGroups(2, [\"items\", \"selected\"])");
1348 QCOMPARE(listview->count(), 12);
1349 QCOMPARE(visualModel->items()->count(), 12);
1350 QCOMPARE(visibleItems->count(), 11);
1351 QCOMPARE(selectedItems->count(), 5);
1352 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1353 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1354 static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9,10 };
1355 static const bool vMember[] = { t, t, f, t, t, t, t, t, t, t, t, t };
1356 static const int sIndex [] = { 0, 0, 0, 1, 1, 1, 1, 2, 3, 4, 5, 5 };
1357 static const bool sMember[] = { f, f, t, f, f, f, t, t, t, t, f, f };
1360 evaluate<void>(selectedItems, "setGroups(0, 3, \"items\")");
1361 QCOMPARE(listview->count(), 12);
1362 QCOMPARE(visualModel->items()->count(), 12);
1363 QCOMPARE(visibleItems->count(), 9);
1364 QCOMPARE(selectedItems->count(), 2);
1365 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1366 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1367 static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
1368 static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t };
1369 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
1370 static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
1373 evaluate<void>(visualModel, "items.get(5).inVisible = false");
1374 QCOMPARE(listview->count(), 12);
1375 QCOMPARE(visualModel->items()->count(), 12);
1376 QCOMPARE(visibleItems->count(), 8);
1377 QCOMPARE(selectedItems->count(), 2);
1378 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1379 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1380 static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
1381 static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
1382 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
1383 static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
1386 evaluate<void>(visualModel, "items.get(5).inSelected = true");
1387 QCOMPARE(listview->count(), 12);
1388 QCOMPARE(visualModel->items()->count(), 12);
1389 QCOMPARE(visibleItems->count(), 8);
1390 QCOMPARE(selectedItems->count(), 3);
1391 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1392 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1393 static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 4, 4, 4, 5, 6, 7 };
1394 static const bool vMember[] = { t, t, f, t, t, f, f, f, t, t, t, t };
1395 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 3, 3 };
1396 static const bool sMember[] = { f, f, f, f, f, t, f, f, t, t, f, f };
1399 evaluate<void>(visualModel, "items.get(5).groups = [\"visible\", \"items\"]");
1400 QCOMPARE(listview->count(), 12);
1401 QCOMPARE(visualModel->items()->count(), 12);
1402 QCOMPARE(visibleItems->count(), 9);
1403 QCOMPARE(selectedItems->count(), 2);
1404 static const int mIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1405 static const int iIndex [] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11 };
1406 static const int vIndex [] = { 0, 1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 8 };
1407 static const bool vMember[] = { t, t, f, t, t, t, f, f, t, t, t, t };
1408 static const int sIndex [] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2 };
1409 static const bool sMember[] = { f, f, f, f, f, f, f, f, t, t, f, f };
1414 void tst_qsgvisualdatamodel::create()
1418 SingleRoleModel model;
1419 model.list = QStringList()
1441 QDeclarativeContext *ctxt = view.rootContext();
1442 ctxt->setContextProperty("myModel", &model);
1444 view.setSource(QUrl::fromLocalFile(TESTDATA("create.qml")));
1446 QSGListView *listview = qobject_cast<QSGListView*>(view.rootObject());
1447 QVERIFY(listview != 0);
1449 QSGItem *contentItem = listview->contentItem();
1450 QVERIFY(contentItem != 0);
1452 QSGVisualDataModel *visualModel = qobject_cast<QSGVisualDataModel *>(qvariant_cast<QObject *>(listview->model()));
1453 QVERIFY(visualModel);
1455 QCOMPARE(listview->count(), 20);
1459 // Request an item instantiated by the view.
1460 QVERIFY(findItem<QSGItem>(contentItem, "delegate", 1));
1461 QVERIFY(delegate = qobject_cast<QSGItem *>(evaluate<QObject *>(visualModel, "items.create(1)")));
1462 QCOMPARE(delegate, findItem<QSGItem>(contentItem, "delegate", 1));
1463 QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
1464 QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
1466 evaluate<void>(delegate, "VisualDataModel.inPersistedItems = false");
1467 QCOMPARE(listview->count(), 20);
1468 QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
1469 QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
1470 QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
1472 // Request an item not instantiated by the view.
1473 QVERIFY(!findItem<QSGItem>(contentItem, "delegate", 15));
1474 QVERIFY(delegate = qobject_cast<QSGItem *>(evaluate<QObject *>(visualModel, "items.create(15)")));
1475 QCOMPARE(delegate, findItem<QSGItem>(contentItem, "delegate", 15));
1476 QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
1477 QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
1479 evaluate<void>(visualModel, "persistedItems.remove(0)");
1480 QCOMPARE(evaluate<bool>(delegate, "destroyed"), true);
1481 QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
1483 // Request an item not instantiated by the view, then scroll the view so it will request it.
1484 QVERIFY(!findItem<QSGItem>(contentItem, "delegate", 16));
1485 QVERIFY(delegate = qobject_cast<QSGItem *>(evaluate<QObject *>(visualModel, "items.create(16)")));
1486 QCOMPARE(delegate, findItem<QSGItem>(contentItem, "delegate", 16));
1487 QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
1488 QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
1490 evaluate<void>(listview, "positionViewAtIndex(19, ListView.End)");
1491 QCOMPARE(listview->count(), 20);
1492 evaluate<void>(delegate, "VisualDataModel.groups = [\"items\"]");
1493 QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
1494 QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
1495 QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
1497 // Request and release an item instantiated by the view, then scroll the view so it releases it.
1498 QVERIFY(findItem<QSGItem>(contentItem, "delegate", 17));
1499 QVERIFY(delegate = qobject_cast<QSGItem *>(evaluate<QObject *>(visualModel, "items.create(17)")));
1500 QCOMPARE(delegate, findItem<QSGItem>(contentItem, "delegate", 17));
1501 QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
1502 QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
1504 evaluate<void>(visualModel, "items.removeGroups(17, \"persistedItems\")");
1505 QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
1506 QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), false);
1507 QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 0);
1508 evaluate<void>(listview, "positionViewAtIndex(1, ListView.Beginning)");
1509 QCOMPARE(listview->count(), 20);
1510 QCOMPARE(evaluate<bool>(delegate, "destroyed"), true);
1512 // Adding an item to the persistedItems group won't instantiate it, but if later requested by
1513 // the view it will be persisted.
1514 evaluate<void>(visualModel, "items.addGroups(18, \"persistedItems\")");
1515 QCOMPARE(evaluate<int>(visualModel, "persistedItems.count"), 1);
1516 QVERIFY(!findItem<QSGItem>(contentItem, "delegate", 18));
1517 evaluate<void>(listview, "positionViewAtIndex(19, ListView.End)");
1518 QCOMPARE(listview->count(), 20);
1519 QVERIFY(delegate = findItem<QSGItem>(contentItem, "delegate", 18));
1520 QCOMPARE(evaluate<bool>(delegate, "VisualDataModel.inPersistedItems"), true);
1521 QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
1522 evaluate<void>(listview, "positionViewAtIndex(1, ListView.Beginning)");
1523 QCOMPARE(listview->count(), 20);
1524 QCOMPARE(evaluate<bool>(delegate, "destroyed"), false);
1527 template<typename T>
1528 T *tst_qsgvisualdatamodel::findItem(QSGItem *parent, const QString &objectName, int index)
1530 const QMetaObject &mo = T::staticMetaObject;
1531 //qDebug() << parent->childItems().count() << "children";
1532 for (int i = 0; i < parent->childItems().count(); ++i) {
1533 QSGItem *item = qobject_cast<QSGItem*>(parent->childItems().at(i));
1536 //qDebug() << "try" << item;
1537 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
1539 QDeclarativeExpression e(qmlContext(item), item, "index");
1540 if (e.evaluate().toInt() == index)
1541 return static_cast<T*>(item);
1543 return static_cast<T*>(item);
1546 item = findItem<T>(item, objectName, index);
1548 return static_cast<T*>(item);
1554 QTEST_MAIN(tst_qsgvisualdatamodel)
1556 #include "tst_qsgvisualdatamodel.moc"