Merge branch 'qtquick2' of scm.dev.nokia.troll.no:qt/qtdeclarative-staging into qtquick2
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativevisualdatamodel / tst_qdeclarativevisualdatamodel.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
7 ** This file is part of the test suite of the Qt Toolkit.
8 **
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.
17 **
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.
21 **
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.
29 **
30 ** Other Usage
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.
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 #include <qtest.h>
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 <QtDeclarative/qdeclarativeview.h>
49 #include <private/qdeclarativelistview_p.h>
50 #include <private/qdeclarativetext_p.h>
51 #include <private/qdeclarativevisualitemmodel_p.h>
52 #include <private/qdeclarativevaluetype_p.h>
53 #include <math.h>
54
55 #ifdef Q_OS_SYMBIAN
56 // In Symbian OS test data is located in applications private dir
57 #define SRCDIR "."
58 #endif
59
60 static void initStandardTreeModel(QStandardItemModel *model)
61 {
62     QStandardItem *item;
63     item = new QStandardItem(QLatin1String("Row 1 Item"));
64     model->insertRow(0, item);
65
66     item = new QStandardItem(QLatin1String("Row 2 Item"));
67     item->setCheckable(true);
68     model->insertRow(1, item);
69
70     QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
71     item->setChild(0, childItem);
72
73     item = new QStandardItem(QLatin1String("Row 3 Item"));
74     item->setIcon(QIcon());
75     model->insertRow(2, item);
76 }
77
78 class SingleRoleModel : public QAbstractListModel
79 {
80     Q_OBJECT
81
82 public:
83     SingleRoleModel(QObject *parent = 0) {
84         QHash<int, QByteArray> roles;
85         roles.insert(Qt::DisplayRole , "name");
86         setRoleNames(roles);
87         list << "one" << "two" << "three" << "four";
88     }
89
90 public slots:
91     void set(int idx, QString string) {
92         list[idx] = string;
93         emit dataChanged(index(idx,0), index(idx,0));
94     }
95
96 protected:
97     int rowCount(const QModelIndex &parent = QModelIndex()) const {
98         return list.count();
99     }
100     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
101         if (role == Qt::DisplayRole)
102             return list.at(index.row());
103         return QVariant();
104     }
105
106 private:
107     QStringList list;
108 };
109
110
111 class tst_qdeclarativevisualdatamodel : public QObject
112 {
113     Q_OBJECT
114 public:
115     tst_qdeclarativevisualdatamodel();
116
117 private slots:
118     void rootIndex();
119     void updateLayout();
120     void childChanged();
121     void objectListModel();
122     void singleRole();
123     void modelProperties();
124     void noDelegate();
125
126 private:
127     QDeclarativeEngine engine;
128     template<typename T>
129     T *findItem(QGraphicsObject *parent, const QString &objectName, int index);
130 };
131
132 class DataObject : public QObject
133 {
134     Q_OBJECT
135
136     Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
137     Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
138
139 public:
140     DataObject(QObject *parent=0) : QObject(parent) {}
141     DataObject(const QString &name, const QString &color, QObject *parent=0)
142         : QObject(parent), m_name(name), m_color(color) { }
143
144
145     QString name() const { return m_name; }
146     void setName(const QString &name) {
147         if (name != m_name) {
148             m_name = name;
149             emit nameChanged();
150         }
151     }
152
153     QString color() const { return m_color; }
154     void setColor(const QString &color) {
155         if (color != m_color) {
156             m_color = color;
157             emit colorChanged();
158         }
159     }
160
161 signals:
162     void nameChanged();
163     void colorChanged();
164
165 private:
166     QString m_name;
167     QString m_color;
168 };
169
170 tst_qdeclarativevisualdatamodel::tst_qdeclarativevisualdatamodel()
171 {
172 }
173
174 void tst_qdeclarativevisualdatamodel::rootIndex()
175 {
176     QDeclarativeEngine engine;
177     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/visualdatamodel.qml"));
178
179     QStandardItemModel model;
180     initStandardTreeModel(&model);
181
182     engine.rootContext()->setContextProperty("myModel", &model);
183
184     QDeclarativeVisualDataModel *obj = qobject_cast<QDeclarativeVisualDataModel*>(c.create());
185     QVERIFY(obj != 0);
186
187     QMetaObject::invokeMethod(obj, "setRoot");
188     QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
189
190     QMetaObject::invokeMethod(obj, "setRootToParent");
191     QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
192
193     QMetaObject::invokeMethod(obj, "setRoot");
194     QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
195     model.clear(); // will emit modelReset()
196     QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
197
198     delete obj;
199 }
200
201 void tst_qdeclarativevisualdatamodel::updateLayout()
202 {
203     QDeclarativeView view;
204
205     QStandardItemModel model;
206     initStandardTreeModel(&model);
207
208     view.rootContext()->setContextProperty("myModel", &model);
209
210     view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml"));
211
212     QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
213     QVERIFY(listview != 0);
214
215     QDeclarativeItem *contentItem = listview->contentItem();
216     QVERIFY(contentItem != 0);
217
218     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "display", 0);
219     QVERIFY(name);
220     QCOMPARE(name->text(), QString("Row 1 Item"));
221     name = findItem<QDeclarativeText>(contentItem, "display", 1);
222     QVERIFY(name);
223     QCOMPARE(name->text(), QString("Row 2 Item"));
224     name = findItem<QDeclarativeText>(contentItem, "display", 2);
225     QVERIFY(name);
226     QCOMPARE(name->text(), QString("Row 3 Item"));
227
228     model.invisibleRootItem()->sortChildren(0, Qt::DescendingOrder);
229
230     name = findItem<QDeclarativeText>(contentItem, "display", 0);
231     QVERIFY(name);
232     QCOMPARE(name->text(), QString("Row 3 Item"));
233     name = findItem<QDeclarativeText>(contentItem, "display", 1);
234     QVERIFY(name);
235     QCOMPARE(name->text(), QString("Row 2 Item"));
236     name = findItem<QDeclarativeText>(contentItem, "display", 2);
237     QVERIFY(name);
238     QCOMPARE(name->text(), QString("Row 1 Item"));
239 }
240
241 void tst_qdeclarativevisualdatamodel::childChanged()
242 {
243     QDeclarativeView view;
244
245     QStandardItemModel model;
246     initStandardTreeModel(&model);
247
248     view.rootContext()->setContextProperty("myModel", &model);
249
250     view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml"));
251
252     QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
253     QVERIFY(listview != 0);
254
255     QDeclarativeItem *contentItem = listview->contentItem();
256     QVERIFY(contentItem != 0);
257
258     QDeclarativeVisualDataModel *vdm = listview->findChild<QDeclarativeVisualDataModel*>("visualModel");
259     vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0))));
260
261     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "display", 0);
262     QVERIFY(name);
263     QCOMPARE(name->text(), QString("Row 2 Child Item"));
264
265     model.item(1,0)->child(0,0)->setText("Row 2 updated child");
266
267     name = findItem<QDeclarativeText>(contentItem, "display", 0);
268     QVERIFY(name);
269     QCOMPARE(name->text(), QString("Row 2 updated child"));
270
271     model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2")));
272     QTest::qWait(300);
273
274     name = findItem<QDeclarativeText>(contentItem, "display", 1);
275     QVERIFY(name != 0);
276     QCOMPARE(name->text(), QString("Row 2 Child Item 2"));
277
278     model.item(1,0)->takeRow(1);
279     name = findItem<QDeclarativeText>(contentItem, "display", 1);
280     QVERIFY(name == 0);
281
282     vdm->setRootIndex(QVariant::fromValue(QModelIndex()));
283     QTest::qWait(300);
284     name = findItem<QDeclarativeText>(contentItem, "display", 0);
285     QVERIFY(name);
286     QCOMPARE(name->text(), QString("Row 1 Item"));
287     name = findItem<QDeclarativeText>(contentItem, "display", 1);
288     QVERIFY(name);
289     QCOMPARE(name->text(), QString("Row 2 Item"));
290     name = findItem<QDeclarativeText>(contentItem, "display", 2);
291     QVERIFY(name);
292     QCOMPARE(name->text(), QString("Row 3 Item"));
293 }
294
295 void tst_qdeclarativevisualdatamodel::objectListModel()
296 {
297     QDeclarativeView view;
298
299     QList<QObject*> dataList;
300     dataList.append(new DataObject("Item 1", "red"));
301     dataList.append(new DataObject("Item 2", "green"));
302     dataList.append(new DataObject("Item 3", "blue"));
303     dataList.append(new DataObject("Item 4", "yellow"));
304
305     QDeclarativeContext *ctxt = view.rootContext();
306     ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
307
308     view.setSource(QUrl::fromLocalFile(SRCDIR "/data/objectlist.qml"));
309
310     QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
311     QVERIFY(listview != 0);
312
313     QDeclarativeItem *contentItem = listview->contentItem();
314     QVERIFY(contentItem != 0);
315
316     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "name", 0);
317     QCOMPARE(name->text(), QString("Item 1"));
318
319     QDeclarativeText *section = findItem<QDeclarativeText>(contentItem, "section", 0);
320     QCOMPARE(section->text(), QString("Item 1"));
321
322     dataList[0]->setProperty("name", QLatin1String("Changed"));
323     QCOMPARE(name->text(), QString("Changed"));
324 }
325
326 void tst_qdeclarativevisualdatamodel::singleRole()
327 {
328     {
329         QDeclarativeView view;
330
331         SingleRoleModel model;
332
333         QDeclarativeContext *ctxt = view.rootContext();
334         ctxt->setContextProperty("myModel", &model);
335
336         view.setSource(QUrl::fromLocalFile(SRCDIR "/data/singlerole1.qml"));
337
338         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
339         QVERIFY(listview != 0);
340
341         QDeclarativeItem *contentItem = listview->contentItem();
342         QVERIFY(contentItem != 0);
343
344         QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "name", 1);
345         QCOMPARE(name->text(), QString("two"));
346
347         model.set(1, "Changed");
348         QCOMPARE(name->text(), QString("Changed"));
349     }
350     {
351         QDeclarativeView view;
352
353         SingleRoleModel model;
354
355         QDeclarativeContext *ctxt = view.rootContext();
356         ctxt->setContextProperty("myModel", &model);
357
358         view.setSource(QUrl::fromLocalFile(SRCDIR "/data/singlerole2.qml"));
359
360         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
361         QVERIFY(listview != 0);
362
363         QDeclarativeItem *contentItem = listview->contentItem();
364         QVERIFY(contentItem != 0);
365
366         QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "name", 1);
367         QCOMPARE(name->text(), QString("two"));
368
369         model.set(1, "Changed");
370         QCOMPARE(name->text(), QString("Changed"));
371     }
372 }
373
374 void tst_qdeclarativevisualdatamodel::modelProperties()
375 {
376     {
377         QDeclarativeView view;
378
379         SingleRoleModel model;
380
381         QDeclarativeContext *ctxt = view.rootContext();
382         ctxt->setContextProperty("myModel", &model);
383
384         view.setSource(QUrl::fromLocalFile(SRCDIR "/data/modelproperties.qml"));
385
386         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
387         QVERIFY(listview != 0);
388
389         QDeclarativeItem *contentItem = listview->contentItem();
390         QVERIFY(contentItem != 0);
391
392         QDeclarativeItem *delegate = findItem<QDeclarativeItem>(contentItem, "delegate", 1);
393         QCOMPARE(delegate->property("test1").toString(),QString("two"));
394         QCOMPARE(delegate->property("test2").toString(),QString("two"));
395         QCOMPARE(delegate->property("test3").toString(),QString("two"));
396         QCOMPARE(delegate->property("test4").toString(),QString("two"));
397         QVERIFY(!delegate->property("test9").isValid());
398         QCOMPARE(delegate->property("test5").toString(),QString(""));
399         QVERIFY(delegate->property("test6").value<QObject*>() != 0);
400         QCOMPARE(delegate->property("test7").toInt(),1);
401         QCOMPARE(delegate->property("test8").toInt(),1);
402     }
403
404     {
405         QDeclarativeView view;
406
407         QList<QObject*> dataList;
408         dataList.append(new DataObject("Item 1", "red"));
409         dataList.append(new DataObject("Item 2", "green"));
410         dataList.append(new DataObject("Item 3", "blue"));
411         dataList.append(new DataObject("Item 4", "yellow"));
412
413         QDeclarativeContext *ctxt = view.rootContext();
414         ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
415
416         view.setSource(QUrl::fromLocalFile(SRCDIR "/data/modelproperties.qml"));
417
418         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
419         QVERIFY(listview != 0);
420
421         QDeclarativeItem *contentItem = listview->contentItem();
422         QVERIFY(contentItem != 0);
423
424         QDeclarativeItem *delegate = findItem<QDeclarativeItem>(contentItem, "delegate", 1);
425         QCOMPARE(delegate->property("test1").toString(),QString("Item 2"));
426         QEXPECT_FAIL("", "QTBUG-13576", Continue);
427         QCOMPARE(delegate->property("test2").toString(),QString("Item 2"));
428         QVERIFY(qobject_cast<DataObject*>(delegate->property("test3").value<QObject*>()) != 0);
429         QVERIFY(qobject_cast<DataObject*>(delegate->property("test4").value<QObject*>()) != 0);
430         QCOMPARE(delegate->property("test5").toString(),QString("Item 2"));
431         QCOMPARE(delegate->property("test9").toString(),QString("Item 2"));
432         QVERIFY(delegate->property("test6").value<QObject*>() != 0);
433         QCOMPARE(delegate->property("test7").toInt(),1);
434         QCOMPARE(delegate->property("test8").toInt(),1);
435     }
436
437     {
438         QDeclarativeView view;
439
440         QStandardItemModel model;
441         initStandardTreeModel(&model);
442
443         view.rootContext()->setContextProperty("myModel", &model);
444
445         QUrl source(QUrl::fromLocalFile(SRCDIR "/data/modelproperties2.qml"));
446
447         //3 items, 3 warnings each
448         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
449         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
450         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":11: ReferenceError: Can't find variable: modelData");
451         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":9: ReferenceError: Can't find variable: modelData");
452         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":9: ReferenceError: Can't find variable: modelData");
453         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":9: ReferenceError: Can't find variable: modelData");
454         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Result of expression 'model.modelData' [undefined] is not an object.");
455         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Result of expression 'model.modelData' [undefined] is not an object.");
456         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Result of expression 'model.modelData' [undefined] is not an object.");
457
458         view.setSource(source);
459
460         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
461         QVERIFY(listview != 0);
462
463         QDeclarativeItem *contentItem = listview->contentItem();
464         QVERIFY(contentItem != 0);
465
466         QDeclarativeItem *delegate = findItem<QDeclarativeItem>(contentItem, "delegate", 1);
467         QCOMPARE(delegate->property("test1").toString(),QString("Row 2 Item"));
468         QCOMPARE(delegate->property("test2").toString(),QString("Row 2 Item"));
469         QVERIFY(!delegate->property("test3").isValid());
470         QVERIFY(!delegate->property("test4").isValid());
471         QVERIFY(!delegate->property("test5").isValid());
472         QVERIFY(!delegate->property("test9").isValid());
473         QVERIFY(delegate->property("test6").value<QObject*>() != 0);
474         QCOMPARE(delegate->property("test7").toInt(),1);
475         QCOMPARE(delegate->property("test8").toInt(),1);
476     }
477
478     //### should also test QStringList and QVariantList
479 }
480
481 void tst_qdeclarativevisualdatamodel::noDelegate()
482 {
483     QDeclarativeView view;
484
485     QStandardItemModel model;
486     initStandardTreeModel(&model);
487
488     view.rootContext()->setContextProperty("myModel", &model);
489
490     view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml"));
491
492     QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
493     QVERIFY(listview != 0);
494
495     QDeclarativeVisualDataModel *vdm = listview->findChild<QDeclarativeVisualDataModel*>("visualModel");
496     QVERIFY(vdm != 0);
497     QCOMPARE(vdm->count(), 3);
498
499     vdm->setDelegate(0);
500     QCOMPARE(vdm->count(), 0);
501 }
502
503
504 template<typename T>
505 T *tst_qdeclarativevisualdatamodel::findItem(QGraphicsObject *parent, const QString &objectName, int index)
506 {
507     const QMetaObject &mo = T::staticMetaObject;
508     //qDebug() << parent->childItems().count() << "children";
509     for (int i = 0; i < parent->childItems().count(); ++i) {
510         QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
511         if(!item)
512             continue;
513         //qDebug() << "try" << item;
514         if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
515             if (index != -1) {
516                 QDeclarativeExpression e(qmlContext(item), item, "index");
517                 if (e.evaluate().toInt() == index)
518                     return static_cast<T*>(item);
519             } else {
520                 return static_cast<T*>(item);
521             }
522         }
523         item = findItem<T>(item, objectName, index);
524         if (item)
525         return static_cast<T*>(item);
526     }
527
528     return 0;
529 }
530
531 QTEST_MAIN(tst_qdeclarativevisualdatamodel)
532
533 #include "tst_qdeclarativevisualdatamodel.moc"