1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QSignalSpy>
43 #include <QStandardItemModel>
44 #include <QtDeclarative/qdeclarativeengine.h>
45 #include <QtDeclarative/qdeclarativecomponent.h>
46 #include <QtDeclarative/qdeclarativecontext.h>
47 #include <QtDeclarative/qdeclarativeexpression.h>
48 #include <QtQuick1/qdeclarativeview.h>
49 #include <QtQuick1/private/qdeclarativelistview_p.h>
50 #include <QtQuick1/private/qdeclarativetext_p.h>
51 #include <QtQuick1/private/qdeclarativevisualitemmodel_p.h>
52 #include <private/qdeclarativevaluetype_p.h>
55 static void initStandardTreeModel(QStandardItemModel *model)
58 item = new QStandardItem(QLatin1String("Row 1 Item"));
59 model->insertRow(0, item);
61 item = new QStandardItem(QLatin1String("Row 2 Item"));
62 item->setCheckable(true);
63 model->insertRow(1, item);
65 QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
66 item->setChild(0, childItem);
68 item = new QStandardItem(QLatin1String("Row 3 Item"));
69 item->setIcon(QIcon());
70 model->insertRow(2, item);
73 class SingleRoleModel : public QAbstractListModel
78 SingleRoleModel(QObject *parent = 0) {
79 QHash<int, QByteArray> roles;
80 roles.insert(Qt::DisplayRole , "name");
82 list << "one" << "two" << "three" << "four";
86 void set(int idx, QString string) {
88 emit dataChanged(index(idx,0), index(idx,0));
92 int rowCount(const QModelIndex &parent = QModelIndex()) const {
95 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
96 if (role == Qt::DisplayRole)
97 return list.at(index.row());
106 class tst_qdeclarativevisualdatamodel : public QObject
110 tst_qdeclarativevisualdatamodel();
116 void objectListModel();
118 void modelProperties();
122 QDeclarativeEngine engine;
124 T *findItem(QGraphicsObject *parent, const QString &objectName, int index);
127 class DataObject : public QObject
131 Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
132 Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
135 DataObject(QObject *parent=0) : QObject(parent) {}
136 DataObject(const QString &name, const QString &color, QObject *parent=0)
137 : QObject(parent), m_name(name), m_color(color) { }
140 QString name() const { return m_name; }
141 void setName(const QString &name) {
142 if (name != m_name) {
148 QString color() const { return m_color; }
149 void setColor(const QString &color) {
150 if (color != m_color) {
165 tst_qdeclarativevisualdatamodel::tst_qdeclarativevisualdatamodel()
169 void tst_qdeclarativevisualdatamodel::rootIndex()
171 QDeclarativeEngine engine;
172 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/visualdatamodel.qml"));
174 QStandardItemModel model;
175 initStandardTreeModel(&model);
177 engine.rootContext()->setContextProperty("myModel", &model);
179 QDeclarative1VisualDataModel *obj = qobject_cast<QDeclarative1VisualDataModel*>(c.create());
182 QMetaObject::invokeMethod(obj, "setRoot");
183 QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
185 QMetaObject::invokeMethod(obj, "setRootToParent");
186 QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
188 QMetaObject::invokeMethod(obj, "setRoot");
189 QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
190 model.clear(); // will emit modelReset()
191 QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
196 void tst_qdeclarativevisualdatamodel::updateLayout()
198 QDeclarativeView view;
200 QStandardItemModel model;
201 initStandardTreeModel(&model);
203 view.rootContext()->setContextProperty("myModel", &model);
205 view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml"));
207 QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
208 QVERIFY(listview != 0);
210 QDeclarativeItem *contentItem = listview->contentItem();
211 QVERIFY(contentItem != 0);
213 QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "display", 0);
215 QCOMPARE(name->text(), QString("Row 1 Item"));
216 name = findItem<QDeclarative1Text>(contentItem, "display", 1);
218 QCOMPARE(name->text(), QString("Row 2 Item"));
219 name = findItem<QDeclarative1Text>(contentItem, "display", 2);
221 QCOMPARE(name->text(), QString("Row 3 Item"));
223 model.invisibleRootItem()->sortChildren(0, Qt::DescendingOrder);
225 name = findItem<QDeclarative1Text>(contentItem, "display", 0);
227 QCOMPARE(name->text(), QString("Row 3 Item"));
228 name = findItem<QDeclarative1Text>(contentItem, "display", 1);
230 QCOMPARE(name->text(), QString("Row 2 Item"));
231 name = findItem<QDeclarative1Text>(contentItem, "display", 2);
233 QCOMPARE(name->text(), QString("Row 1 Item"));
236 void tst_qdeclarativevisualdatamodel::childChanged()
238 QDeclarativeView view;
240 QStandardItemModel model;
241 initStandardTreeModel(&model);
243 view.rootContext()->setContextProperty("myModel", &model);
245 view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml"));
247 QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
248 QVERIFY(listview != 0);
250 QDeclarativeItem *contentItem = listview->contentItem();
251 QVERIFY(contentItem != 0);
253 QDeclarative1VisualDataModel *vdm = listview->findChild<QDeclarative1VisualDataModel*>("visualModel");
254 vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0))));
256 QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "display", 0);
258 QCOMPARE(name->text(), QString("Row 2 Child Item"));
260 model.item(1,0)->child(0,0)->setText("Row 2 updated child");
262 name = findItem<QDeclarative1Text>(contentItem, "display", 0);
264 QCOMPARE(name->text(), QString("Row 2 updated child"));
266 model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2")));
269 name = findItem<QDeclarative1Text>(contentItem, "display", 1);
271 QCOMPARE(name->text(), QString("Row 2 Child Item 2"));
273 model.item(1,0)->takeRow(1);
274 name = findItem<QDeclarative1Text>(contentItem, "display", 1);
277 vdm->setRootIndex(QVariant::fromValue(QModelIndex()));
279 name = findItem<QDeclarative1Text>(contentItem, "display", 0);
281 QCOMPARE(name->text(), QString("Row 1 Item"));
282 name = findItem<QDeclarative1Text>(contentItem, "display", 1);
284 QCOMPARE(name->text(), QString("Row 2 Item"));
285 name = findItem<QDeclarative1Text>(contentItem, "display", 2);
287 QCOMPARE(name->text(), QString("Row 3 Item"));
290 void tst_qdeclarativevisualdatamodel::objectListModel()
292 QDeclarativeView view;
294 QList<QObject*> dataList;
295 dataList.append(new DataObject("Item 1", "red"));
296 dataList.append(new DataObject("Item 2", "green"));
297 dataList.append(new DataObject("Item 3", "blue"));
298 dataList.append(new DataObject("Item 4", "yellow"));
300 QDeclarativeContext *ctxt = view.rootContext();
301 ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
303 view.setSource(QUrl::fromLocalFile(SRCDIR "/data/objectlist.qml"));
305 QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
306 QVERIFY(listview != 0);
308 QDeclarativeItem *contentItem = listview->contentItem();
309 QVERIFY(contentItem != 0);
311 QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "name", 0);
312 QCOMPARE(name->text(), QString("Item 1"));
314 QDeclarative1Text *section = findItem<QDeclarative1Text>(contentItem, "section", 0);
315 QCOMPARE(section->text(), QString("Item 1"));
317 dataList[0]->setProperty("name", QLatin1String("Changed"));
318 QCOMPARE(name->text(), QString("Changed"));
321 void tst_qdeclarativevisualdatamodel::singleRole()
324 QDeclarativeView view;
326 SingleRoleModel model;
328 QDeclarativeContext *ctxt = view.rootContext();
329 ctxt->setContextProperty("myModel", &model);
331 view.setSource(QUrl::fromLocalFile(SRCDIR "/data/singlerole1.qml"));
333 QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
334 QVERIFY(listview != 0);
336 QDeclarativeItem *contentItem = listview->contentItem();
337 QVERIFY(contentItem != 0);
339 QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "name", 1);
340 QCOMPARE(name->text(), QString("two"));
342 model.set(1, "Changed");
343 QCOMPARE(name->text(), QString("Changed"));
346 QDeclarativeView view;
348 SingleRoleModel model;
350 QDeclarativeContext *ctxt = view.rootContext();
351 ctxt->setContextProperty("myModel", &model);
353 view.setSource(QUrl::fromLocalFile(SRCDIR "/data/singlerole2.qml"));
355 QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
356 QVERIFY(listview != 0);
358 QDeclarativeItem *contentItem = listview->contentItem();
359 QVERIFY(contentItem != 0);
361 QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "name", 1);
362 QCOMPARE(name->text(), QString("two"));
364 model.set(1, "Changed");
365 QCOMPARE(name->text(), QString("Changed"));
369 void tst_qdeclarativevisualdatamodel::modelProperties()
372 QDeclarativeView view;
374 SingleRoleModel model;
376 QDeclarativeContext *ctxt = view.rootContext();
377 ctxt->setContextProperty("myModel", &model);
379 view.setSource(QUrl::fromLocalFile(SRCDIR "/data/modelproperties.qml"));
381 QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
382 QVERIFY(listview != 0);
384 QDeclarativeItem *contentItem = listview->contentItem();
385 QVERIFY(contentItem != 0);
387 QDeclarativeItem *delegate = findItem<QDeclarativeItem>(contentItem, "delegate", 1);
388 QCOMPARE(delegate->property("test1").toString(),QString("two"));
389 QCOMPARE(delegate->property("test2").toString(),QString("two"));
390 QCOMPARE(delegate->property("test3").toString(),QString("two"));
391 QCOMPARE(delegate->property("test4").toString(),QString("two"));
392 QVERIFY(!delegate->property("test9").isValid());
393 QCOMPARE(delegate->property("test5").toString(),QString(""));
394 QVERIFY(delegate->property("test6").value<QObject*>() != 0);
395 QCOMPARE(delegate->property("test7").toInt(),1);
396 QCOMPARE(delegate->property("test8").toInt(),1);
400 QDeclarativeView view;
402 QList<QObject*> dataList;
403 dataList.append(new DataObject("Item 1", "red"));
404 dataList.append(new DataObject("Item 2", "green"));
405 dataList.append(new DataObject("Item 3", "blue"));
406 dataList.append(new DataObject("Item 4", "yellow"));
408 QDeclarativeContext *ctxt = view.rootContext();
409 ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
411 view.setSource(QUrl::fromLocalFile(SRCDIR "/data/modelproperties.qml"));
413 QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
414 QVERIFY(listview != 0);
416 QDeclarativeItem *contentItem = listview->contentItem();
417 QVERIFY(contentItem != 0);
419 QDeclarativeItem *delegate = findItem<QDeclarativeItem>(contentItem, "delegate", 1);
420 QCOMPARE(delegate->property("test1").toString(),QString("Item 2"));
421 QEXPECT_FAIL("", "QTBUG-13576", Continue);
422 QCOMPARE(delegate->property("test2").toString(),QString("Item 2"));
423 QVERIFY(qobject_cast<DataObject*>(delegate->property("test3").value<QObject*>()) != 0);
424 QVERIFY(qobject_cast<DataObject*>(delegate->property("test4").value<QObject*>()) != 0);
425 QCOMPARE(delegate->property("test5").toString(),QString("Item 2"));
426 QCOMPARE(delegate->property("test9").toString(),QString("Item 2"));
427 QVERIFY(delegate->property("test6").value<QObject*>() != 0);
428 QCOMPARE(delegate->property("test7").toInt(),1);
429 QCOMPARE(delegate->property("test8").toInt(),1);
433 QDeclarativeView view;
435 QStandardItemModel model;
436 initStandardTreeModel(&model);
438 view.rootContext()->setContextProperty("myModel", &model);
440 QUrl source(QUrl::fromLocalFile(SRCDIR "/data/modelproperties2.qml"));
442 //3 items, 3 warnings each
443 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
444 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
445 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
446 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":9: ReferenceError: Can't find variable: modelData");
447 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":9: ReferenceError: Can't find variable: modelData");
448 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":9: ReferenceError: Can't find variable: modelData");
449 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Cannot read property 'display' of undefined");
450 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Cannot read property 'display' of undefined");
451 QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Cannot read property 'display' of undefined");
453 view.setSource(source);
455 QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
456 QVERIFY(listview != 0);
458 QDeclarativeItem *contentItem = listview->contentItem();
459 QVERIFY(contentItem != 0);
461 QDeclarativeItem *delegate = findItem<QDeclarativeItem>(contentItem, "delegate", 1);
462 QCOMPARE(delegate->property("test1").toString(),QString("Row 2 Item"));
463 QCOMPARE(delegate->property("test2").toString(),QString("Row 2 Item"));
464 QVERIFY(!delegate->property("test3").isValid());
465 QVERIFY(!delegate->property("test4").isValid());
466 QVERIFY(!delegate->property("test5").isValid());
467 QVERIFY(!delegate->property("test9").isValid());
468 QVERIFY(delegate->property("test6").value<QObject*>() != 0);
469 QCOMPARE(delegate->property("test7").toInt(),1);
470 QCOMPARE(delegate->property("test8").toInt(),1);
473 //### should also test QStringList and QVariantList
476 void tst_qdeclarativevisualdatamodel::noDelegate()
478 QDeclarativeView view;
480 QStandardItemModel model;
481 initStandardTreeModel(&model);
483 view.rootContext()->setContextProperty("myModel", &model);
485 view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml"));
487 QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
488 QVERIFY(listview != 0);
490 QDeclarative1VisualDataModel *vdm = listview->findChild<QDeclarative1VisualDataModel*>("visualModel");
492 QCOMPARE(vdm->count(), 3);
495 QCOMPARE(vdm->count(), 0);
500 T *tst_qdeclarativevisualdatamodel::findItem(QGraphicsObject *parent, const QString &objectName, int index)
502 const QMetaObject &mo = T::staticMetaObject;
503 //qDebug() << parent->childItems().count() << "children";
504 for (int i = 0; i < parent->childItems().count(); ++i) {
505 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
508 //qDebug() << "try" << item;
509 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
511 QDeclarativeExpression e(qmlContext(item), item, "index");
512 if (e.evaluate().toInt() == index)
513 return static_cast<T*>(item);
515 return static_cast<T*>(item);
518 item = findItem<T>(item, objectName, index);
520 return static_cast<T*>(item);
526 QTEST_MAIN(tst_qdeclarativevisualdatamodel)
528 #include "tst_qdeclarativevisualdatamodel.moc"