704636fe90bf4914f065d3a7b2f6592f2d90cee9
[profile/ivi/qtdeclarative.git] / tests / auto / qtquick1 / qdeclarativevisualdatamodel / tst_qdeclarativevisualdatamodel.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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 <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>
53 #include <math.h>
54
55 static void initStandardTreeModel(QStandardItemModel *model)
56 {
57     QStandardItem *item;
58     item = new QStandardItem(QLatin1String("Row 1 Item"));
59     model->insertRow(0, item);
60
61     item = new QStandardItem(QLatin1String("Row 2 Item"));
62     item->setCheckable(true);
63     model->insertRow(1, item);
64
65     QStandardItem *childItem = new QStandardItem(QLatin1String("Row 2 Child Item"));
66     item->setChild(0, childItem);
67
68     item = new QStandardItem(QLatin1String("Row 3 Item"));
69     item->setIcon(QIcon());
70     model->insertRow(2, item);
71 }
72
73 class SingleRoleModel : public QAbstractListModel
74 {
75     Q_OBJECT
76
77 public:
78     SingleRoleModel(QObject *parent = 0) {
79         QHash<int, QByteArray> roles;
80         roles.insert(Qt::DisplayRole , "name");
81         setRoleNames(roles);
82         list << "one" << "two" << "three" << "four";
83     }
84
85 public slots:
86     void set(int idx, QString string) {
87         list[idx] = string;
88         emit dataChanged(index(idx,0), index(idx,0));
89     }
90
91 protected:
92     int rowCount(const QModelIndex &parent = QModelIndex()) const {
93         return list.count();
94     }
95     QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const {
96         if (role == Qt::DisplayRole)
97             return list.at(index.row());
98         return QVariant();
99     }
100
101 private:
102     QStringList list;
103 };
104
105
106 class tst_qdeclarativevisualdatamodel : public QObject
107 {
108     Q_OBJECT
109 public:
110     tst_qdeclarativevisualdatamodel();
111
112 private slots:
113     void rootIndex();
114     void updateLayout();
115     void childChanged();
116     void objectListModel();
117     void singleRole();
118     void modelProperties();
119     void noDelegate();
120
121 private:
122     QDeclarativeEngine engine;
123     template<typename T>
124     T *findItem(QGraphicsObject *parent, const QString &objectName, int index);
125 };
126
127 class DataObject : public QObject
128 {
129     Q_OBJECT
130
131     Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
132     Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)
133
134 public:
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) { }
138
139
140     QString name() const { return m_name; }
141     void setName(const QString &name) {
142         if (name != m_name) {
143             m_name = name;
144             emit nameChanged();
145         }
146     }
147
148     QString color() const { return m_color; }
149     void setColor(const QString &color) {
150         if (color != m_color) {
151             m_color = color;
152             emit colorChanged();
153         }
154     }
155
156 signals:
157     void nameChanged();
158     void colorChanged();
159
160 private:
161     QString m_name;
162     QString m_color;
163 };
164
165 tst_qdeclarativevisualdatamodel::tst_qdeclarativevisualdatamodel()
166 {
167 }
168
169 void tst_qdeclarativevisualdatamodel::rootIndex()
170 {
171     QDeclarativeEngine engine;
172     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/visualdatamodel.qml"));
173
174     QStandardItemModel model;
175     initStandardTreeModel(&model);
176
177     engine.rootContext()->setContextProperty("myModel", &model);
178
179     QDeclarative1VisualDataModel *obj = qobject_cast<QDeclarative1VisualDataModel*>(c.create());
180     QVERIFY(obj != 0);
181
182     QMetaObject::invokeMethod(obj, "setRoot");
183     QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == model.index(0,0));
184
185     QMetaObject::invokeMethod(obj, "setRootToParent");
186     QVERIFY(qvariant_cast<QModelIndex>(obj->rootIndex()) == QModelIndex());
187
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());
192
193     delete obj;
194 }
195
196 void tst_qdeclarativevisualdatamodel::updateLayout()
197 {
198     QDeclarativeView view;
199
200     QStandardItemModel model;
201     initStandardTreeModel(&model);
202
203     view.rootContext()->setContextProperty("myModel", &model);
204
205     view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml"));
206
207     QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
208     QVERIFY(listview != 0);
209
210     QDeclarativeItem *contentItem = listview->contentItem();
211     QVERIFY(contentItem != 0);
212
213     QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "display", 0);
214     QVERIFY(name);
215     QCOMPARE(name->text(), QString("Row 1 Item"));
216     name = findItem<QDeclarative1Text>(contentItem, "display", 1);
217     QVERIFY(name);
218     QCOMPARE(name->text(), QString("Row 2 Item"));
219     name = findItem<QDeclarative1Text>(contentItem, "display", 2);
220     QVERIFY(name);
221     QCOMPARE(name->text(), QString("Row 3 Item"));
222
223     model.invisibleRootItem()->sortChildren(0, Qt::DescendingOrder);
224
225     name = findItem<QDeclarative1Text>(contentItem, "display", 0);
226     QVERIFY(name);
227     QCOMPARE(name->text(), QString("Row 3 Item"));
228     name = findItem<QDeclarative1Text>(contentItem, "display", 1);
229     QVERIFY(name);
230     QCOMPARE(name->text(), QString("Row 2 Item"));
231     name = findItem<QDeclarative1Text>(contentItem, "display", 2);
232     QVERIFY(name);
233     QCOMPARE(name->text(), QString("Row 1 Item"));
234 }
235
236 void tst_qdeclarativevisualdatamodel::childChanged()
237 {
238     QDeclarativeView view;
239
240     QStandardItemModel model;
241     initStandardTreeModel(&model);
242
243     view.rootContext()->setContextProperty("myModel", &model);
244
245     view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml"));
246
247     QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
248     QVERIFY(listview != 0);
249
250     QDeclarativeItem *contentItem = listview->contentItem();
251     QVERIFY(contentItem != 0);
252
253     QDeclarative1VisualDataModel *vdm = listview->findChild<QDeclarative1VisualDataModel*>("visualModel");
254     vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0))));
255
256     QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "display", 0);
257     QVERIFY(name);
258     QCOMPARE(name->text(), QString("Row 2 Child Item"));
259
260     model.item(1,0)->child(0,0)->setText("Row 2 updated child");
261
262     name = findItem<QDeclarative1Text>(contentItem, "display", 0);
263     QVERIFY(name);
264     QCOMPARE(name->text(), QString("Row 2 updated child"));
265
266     model.item(1,0)->appendRow(new QStandardItem(QLatin1String("Row 2 Child Item 2")));
267     QTest::qWait(300);
268
269     name = findItem<QDeclarative1Text>(contentItem, "display", 1);
270     QVERIFY(name != 0);
271     QCOMPARE(name->text(), QString("Row 2 Child Item 2"));
272
273     model.item(1,0)->takeRow(1);
274     name = findItem<QDeclarative1Text>(contentItem, "display", 1);
275     QVERIFY(name == 0);
276
277     vdm->setRootIndex(QVariant::fromValue(QModelIndex()));
278     QTest::qWait(300);
279     name = findItem<QDeclarative1Text>(contentItem, "display", 0);
280     QVERIFY(name);
281     QCOMPARE(name->text(), QString("Row 1 Item"));
282     name = findItem<QDeclarative1Text>(contentItem, "display", 1);
283     QVERIFY(name);
284     QCOMPARE(name->text(), QString("Row 2 Item"));
285     name = findItem<QDeclarative1Text>(contentItem, "display", 2);
286     QVERIFY(name);
287     QCOMPARE(name->text(), QString("Row 3 Item"));
288 }
289
290 void tst_qdeclarativevisualdatamodel::objectListModel()
291 {
292     QDeclarativeView view;
293
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"));
299
300     QDeclarativeContext *ctxt = view.rootContext();
301     ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
302
303     view.setSource(QUrl::fromLocalFile(SRCDIR "/data/objectlist.qml"));
304
305     QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
306     QVERIFY(listview != 0);
307
308     QDeclarativeItem *contentItem = listview->contentItem();
309     QVERIFY(contentItem != 0);
310
311     QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "name", 0);
312     QCOMPARE(name->text(), QString("Item 1"));
313
314     QDeclarative1Text *section = findItem<QDeclarative1Text>(contentItem, "section", 0);
315     QCOMPARE(section->text(), QString("Item 1"));
316
317     dataList[0]->setProperty("name", QLatin1String("Changed"));
318     QCOMPARE(name->text(), QString("Changed"));
319 }
320
321 void tst_qdeclarativevisualdatamodel::singleRole()
322 {
323     {
324         QDeclarativeView view;
325
326         SingleRoleModel model;
327
328         QDeclarativeContext *ctxt = view.rootContext();
329         ctxt->setContextProperty("myModel", &model);
330
331         view.setSource(QUrl::fromLocalFile(SRCDIR "/data/singlerole1.qml"));
332
333         QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
334         QVERIFY(listview != 0);
335
336         QDeclarativeItem *contentItem = listview->contentItem();
337         QVERIFY(contentItem != 0);
338
339         QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "name", 1);
340         QCOMPARE(name->text(), QString("two"));
341
342         model.set(1, "Changed");
343         QCOMPARE(name->text(), QString("Changed"));
344     }
345     {
346         QDeclarativeView view;
347
348         SingleRoleModel model;
349
350         QDeclarativeContext *ctxt = view.rootContext();
351         ctxt->setContextProperty("myModel", &model);
352
353         view.setSource(QUrl::fromLocalFile(SRCDIR "/data/singlerole2.qml"));
354
355         QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
356         QVERIFY(listview != 0);
357
358         QDeclarativeItem *contentItem = listview->contentItem();
359         QVERIFY(contentItem != 0);
360
361         QDeclarative1Text *name = findItem<QDeclarative1Text>(contentItem, "name", 1);
362         QCOMPARE(name->text(), QString("two"));
363
364         model.set(1, "Changed");
365         QCOMPARE(name->text(), QString("Changed"));
366     }
367 }
368
369 void tst_qdeclarativevisualdatamodel::modelProperties()
370 {
371     {
372         QDeclarativeView view;
373
374         SingleRoleModel model;
375
376         QDeclarativeContext *ctxt = view.rootContext();
377         ctxt->setContextProperty("myModel", &model);
378
379         view.setSource(QUrl::fromLocalFile(SRCDIR "/data/modelproperties.qml"));
380
381         QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
382         QVERIFY(listview != 0);
383
384         QDeclarativeItem *contentItem = listview->contentItem();
385         QVERIFY(contentItem != 0);
386
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);
397     }
398
399     {
400         QDeclarativeView view;
401
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"));
407
408         QDeclarativeContext *ctxt = view.rootContext();
409         ctxt->setContextProperty("myModel", QVariant::fromValue(dataList));
410
411         view.setSource(QUrl::fromLocalFile(SRCDIR "/data/modelproperties.qml"));
412
413         QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
414         QVERIFY(listview != 0);
415
416         QDeclarativeItem *contentItem = listview->contentItem();
417         QVERIFY(contentItem != 0);
418
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);
430     }
431
432     {
433         QDeclarativeView view;
434
435         QStandardItemModel model;
436         initStandardTreeModel(&model);
437
438         view.rootContext()->setContextProperty("myModel", &model);
439
440         QUrl source(QUrl::fromLocalFile(SRCDIR "/data/modelproperties2.qml"));
441
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");
452
453         view.setSource(source);
454
455         QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
456         QVERIFY(listview != 0);
457
458         QDeclarativeItem *contentItem = listview->contentItem();
459         QVERIFY(contentItem != 0);
460
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);
471     }
472
473     //### should also test QStringList and QVariantList
474 }
475
476 void tst_qdeclarativevisualdatamodel::noDelegate()
477 {
478     QDeclarativeView view;
479
480     QStandardItemModel model;
481     initStandardTreeModel(&model);
482
483     view.rootContext()->setContextProperty("myModel", &model);
484
485     view.setSource(QUrl::fromLocalFile(SRCDIR "/data/datalist.qml"));
486
487     QDeclarative1ListView *listview = qobject_cast<QDeclarative1ListView*>(view.rootObject());
488     QVERIFY(listview != 0);
489
490     QDeclarative1VisualDataModel *vdm = listview->findChild<QDeclarative1VisualDataModel*>("visualModel");
491     QVERIFY(vdm != 0);
492     QCOMPARE(vdm->count(), 3);
493
494     vdm->setDelegate(0);
495     QCOMPARE(vdm->count(), 0);
496 }
497
498
499 template<typename T>
500 T *tst_qdeclarativevisualdatamodel::findItem(QGraphicsObject *parent, const QString &objectName, int index)
501 {
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));
506         if(!item)
507             continue;
508         //qDebug() << "try" << item;
509         if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
510             if (index != -1) {
511                 QDeclarativeExpression e(qmlContext(item), item, "index");
512                 if (e.evaluate().toInt() == index)
513                     return static_cast<T*>(item);
514             } else {
515                 return static_cast<T*>(item);
516             }
517         }
518         item = findItem<T>(item, objectName, index);
519         if (item)
520         return static_cast<T*>(item);
521     }
522
523     return 0;
524 }
525
526 QTEST_MAIN(tst_qdeclarativevisualdatamodel)
527
528 #include "tst_qdeclarativevisualdatamodel.moc"