Initial import from the monolithic Qt.
[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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file.  Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
30 **
31 **
32 **
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     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     QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
208     QVERIFY(listview != 0);
209
210     QDeclarativeItem *contentItem = listview->contentItem();
211     QVERIFY(contentItem != 0);
212
213     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "display", 0);
214     QVERIFY(name);
215     QCOMPARE(name->text(), QString("Row 1 Item"));
216     name = findItem<QDeclarativeText>(contentItem, "display", 1);
217     QVERIFY(name);
218     QCOMPARE(name->text(), QString("Row 2 Item"));
219     name = findItem<QDeclarativeText>(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<QDeclarativeText>(contentItem, "display", 0);
226     QVERIFY(name);
227     QCOMPARE(name->text(), QString("Row 3 Item"));
228     name = findItem<QDeclarativeText>(contentItem, "display", 1);
229     QVERIFY(name);
230     QCOMPARE(name->text(), QString("Row 2 Item"));
231     name = findItem<QDeclarativeText>(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     QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
248     QVERIFY(listview != 0);
249
250     QDeclarativeItem *contentItem = listview->contentItem();
251     QVERIFY(contentItem != 0);
252
253     QDeclarativeVisualDataModel *vdm = listview->findChild<QDeclarativeVisualDataModel*>("visualModel");
254     vdm->setRootIndex(QVariant::fromValue(model.indexFromItem(model.item(1,0))));
255
256     QDeclarativeText *name = findItem<QDeclarativeText>(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<QDeclarativeText>(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<QDeclarativeText>(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<QDeclarativeText>(contentItem, "display", 1);
275     QVERIFY(name == 0);
276
277     vdm->setRootIndex(QVariant::fromValue(QModelIndex()));
278     QTest::qWait(300);
279     name = findItem<QDeclarativeText>(contentItem, "display", 0);
280     QVERIFY(name);
281     QCOMPARE(name->text(), QString("Row 1 Item"));
282     name = findItem<QDeclarativeText>(contentItem, "display", 1);
283     QVERIFY(name);
284     QCOMPARE(name->text(), QString("Row 2 Item"));
285     name = findItem<QDeclarativeText>(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     QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
306     QVERIFY(listview != 0);
307
308     QDeclarativeItem *contentItem = listview->contentItem();
309     QVERIFY(contentItem != 0);
310
311     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "name", 0);
312     QCOMPARE(name->text(), QString("Item 1"));
313
314     QDeclarativeText *section = findItem<QDeclarativeText>(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         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
334         QVERIFY(listview != 0);
335
336         QDeclarativeItem *contentItem = listview->contentItem();
337         QVERIFY(contentItem != 0);
338
339         QDeclarativeText *name = findItem<QDeclarativeText>(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         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
356         QVERIFY(listview != 0);
357
358         QDeclarativeItem *contentItem = listview->contentItem();
359         QVERIFY(contentItem != 0);
360
361         QDeclarativeText *name = findItem<QDeclarativeText>(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         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(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         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(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: Result of expression 'model.modelData' [undefined] is not an object.");
450         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Result of expression 'model.modelData' [undefined] is not an object.");
451         QTest::ignoreMessage(QtWarningMsg, source.toString().toLatin1() + ":15: TypeError: Result of expression 'model.modelData' [undefined] is not an object.");
452
453         view.setSource(source);
454
455         QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(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     QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(view.rootObject());
488     QVERIFY(listview != 0);
489
490     QDeclarativeVisualDataModel *vdm = listview->findChild<QDeclarativeVisualDataModel*>("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"