Initial import from the monolithic Qt.
[profile/ivi/qtdeclarative.git] / tests / auto / declarative / qdeclarativegridview / tst_qdeclarativegridview.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
42 #include <QtTest/QtTest>
43 #include <QtGui/qstringlistmodel.h>
44 #include <QtDeclarative/qdeclarativeview.h>
45 #include <QtDeclarative/qdeclarativeengine.h>
46 #include <QtDeclarative/qdeclarativecomponent.h>
47 #include <QtDeclarative/qdeclarativecontext.h>
48 #include <QtDeclarative/qdeclarativeexpression.h>
49 #include <QtDeclarative/private/qdeclarativeitem_p.h>
50 #include <QtDeclarative/private/qlistmodelinterface_p.h>
51 #include <QtDeclarative/private/qdeclarativegridview_p.h>
52 #include <QtDeclarative/private/qdeclarativetext_p.h>
53 #include <QtDeclarative/private/qdeclarativelistmodel_p.h>
54 #include "../../../shared/util.h"
55
56 #ifdef Q_OS_SYMBIAN
57 // In Symbian OS test data is located in applications private dir
58 #define SRCDIR "."
59 #endif
60
61 class tst_QDeclarativeGridView : public QObject
62 {
63     Q_OBJECT
64 public:
65     tst_QDeclarativeGridView();
66
67 private slots:
68     void items();
69     void changed();
70     void inserted();
71     void removed();
72     void clear();
73     void moved();
74     void changeFlow();
75     void currentIndex();
76     void noCurrentIndex();
77     void defaultValues();
78     void properties();
79     void propertyChanges();
80     void componentChanges();
81     void modelChanges();
82     void positionViewAtIndex();
83     void positionViewAtIndex_rightToLeft();
84     void mirroring();
85     void snapping();
86     void resetModel();
87     void enforceRange();
88     void enforceRange_rightToLeft();
89     void QTBUG_8456();
90     void manualHighlight();
91     void footer();
92     void header();
93     void indexAt();
94     void onAdd();
95     void onAdd_data();
96     void onRemove();
97     void onRemove_data();
98     void testQtQuick11Attributes();
99     void testQtQuick11Attributes_data();
100     void contentPosJump();
101
102 private:
103     QDeclarativeView *createView();
104     template<typename T>
105     T *findItem(QGraphicsObject *parent, const QString &id, int index=-1);
106     template<typename T>
107     QList<T*> findItems(QGraphicsObject *parent, const QString &objectName);
108     void dumpTree(QDeclarativeItem *parent, int depth = 0);
109 };
110
111 class TestModel : public QAbstractListModel
112 {
113 public:
114     enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
115
116     TestModel(QObject *parent=0) : QAbstractListModel(parent) {
117         QHash<int, QByteArray> roles;
118         roles[Name] = "name";
119         roles[Number] = "number";
120         setRoleNames(roles);
121     }
122
123     int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
124     QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
125         QVariant rv;
126         if (role == Name)
127             rv = list.at(index.row()).first;
128         else if (role == Number)
129             rv = list.at(index.row()).second;
130
131         return rv;
132     }
133
134     int count() const { return rowCount(); }
135     QString name(int index) const { return list.at(index).first; }
136     QString number(int index) const { return list.at(index).second; }
137
138     void addItem(const QString &name, const QString &number) {
139         emit beginInsertRows(QModelIndex(), list.count(), list.count());
140         list.append(QPair<QString,QString>(name, number));
141         emit endInsertRows();
142     }
143
144     void addItems(const QList<QPair<QString, QString> > &items) {
145         emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1);
146         for (int i=0; i<items.count(); i++)
147             list.append(QPair<QString,QString>(items[i].first, items[i].second));
148         emit endInsertRows();
149     }
150
151     void insertItem(int index, const QString &name, const QString &number) {
152         emit beginInsertRows(QModelIndex(), index, index);
153         list.insert(index, QPair<QString,QString>(name, number));
154         emit endInsertRows();
155     }
156
157     void removeItem(int index) {
158         emit beginRemoveRows(QModelIndex(), index, index);
159         list.removeAt(index);
160         emit endRemoveRows();
161     }
162
163     void removeItems(int index, int count) {
164         emit beginRemoveRows(QModelIndex(), index, index+count-1);
165         while (count--)
166             list.removeAt(index);
167         emit endRemoveRows();
168     }
169
170     void moveItem(int from, int to) {
171         emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
172         list.move(from, to);
173         emit endMoveRows();
174     }
175
176     void modifyItem(int idx, const QString &name, const QString &number) {
177         list[idx] = QPair<QString,QString>(name, number);
178         emit dataChanged(index(idx,0), index(idx,0));
179     }
180
181     void clear() {
182         int count = list.count();
183         emit beginRemoveRows(QModelIndex(), 0, count-1);
184         list.clear();
185         emit endRemoveRows();
186     }
187
188
189 private:
190     QList<QPair<QString,QString> > list;
191 };
192
193 tst_QDeclarativeGridView::tst_QDeclarativeGridView()
194 {
195 }
196
197 void tst_QDeclarativeGridView::items()
198 {
199     QDeclarativeView *canvas = createView();
200
201     TestModel model;
202     model.addItem("Fred", "12345");
203     model.addItem("John", "2345");
204     model.addItem("Bob", "54321");
205     model.addItem("Billy", "22345");
206     model.addItem("Sam", "2945");
207     model.addItem("Ben", "04321");
208     model.addItem("Jim", "0780");
209
210     QDeclarativeContext *ctxt = canvas->rootContext();
211     ctxt->setContextProperty("testModel", &model);
212     ctxt->setContextProperty("testRightToLeft", QVariant(false));
213     ctxt->setContextProperty("testTopToBottom", QVariant(false));
214
215     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
216     qApp->processEvents();
217
218     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
219     QTRY_VERIFY(gridview != 0);
220
221     QDeclarativeItem *contentItem = gridview->contentItem();
222     QTRY_VERIFY(contentItem != 0);
223
224     QTRY_COMPARE(gridview->count(), model.count());
225     QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
226
227     for (int i = 0; i < model.count(); ++i) {
228         QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", i);
229         QTRY_VERIFY(name != 0);
230         QTRY_COMPARE(name->text(), model.name(i));
231         QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
232         QTRY_VERIFY(number != 0);
233         QTRY_COMPARE(number->text(), model.number(i));
234     }
235
236     // set an empty model and confirm that items are destroyed
237     TestModel model2;
238     ctxt->setContextProperty("testModel", &model2);
239
240     int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
241     QTRY_VERIFY(itemCount == 0);
242
243     delete canvas;
244 }
245
246 void tst_QDeclarativeGridView::changed()
247 {
248     QDeclarativeView *canvas = createView();
249
250     TestModel model;
251     model.addItem("Fred", "12345");
252     model.addItem("John", "2345");
253     model.addItem("Bob", "54321");
254     model.addItem("Billy", "22345");
255     model.addItem("Sam", "2945");
256     model.addItem("Ben", "04321");
257     model.addItem("Jim", "0780");
258
259     QDeclarativeContext *ctxt = canvas->rootContext();
260     ctxt->setContextProperty("testModel", &model);
261     ctxt->setContextProperty("testRightToLeft", QVariant(false));
262     ctxt->setContextProperty("testTopToBottom", QVariant(false));
263
264     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
265     qApp->processEvents();
266
267     QDeclarativeFlickable *gridview = findItem<QDeclarativeFlickable>(canvas->rootObject(), "grid");
268     QTRY_VERIFY(gridview != 0);
269
270     QDeclarativeItem *contentItem = gridview->contentItem();
271     QTRY_VERIFY(contentItem != 0);
272
273     model.modifyItem(1, "Will", "9876");
274     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
275     QTRY_VERIFY(name != 0);
276     QTRY_COMPARE(name->text(), model.name(1));
277     QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
278     QTRY_VERIFY(number != 0);
279     QTRY_COMPARE(number->text(), model.number(1));
280
281     delete canvas;
282 }
283
284 void tst_QDeclarativeGridView::inserted()
285 {
286     QDeclarativeView *canvas = createView();
287
288     TestModel model;
289     model.addItem("Fred", "12345");
290     model.addItem("John", "2345");
291     model.addItem("Bob", "54321");
292
293     QDeclarativeContext *ctxt = canvas->rootContext();
294     ctxt->setContextProperty("testModel", &model);
295     ctxt->setContextProperty("testRightToLeft", QVariant(false));
296     ctxt->setContextProperty("testTopToBottom", QVariant(false));
297
298     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
299     qApp->processEvents();
300
301     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
302     QTRY_VERIFY(gridview != 0);
303
304     QDeclarativeItem *contentItem = gridview->contentItem();
305     QTRY_VERIFY(contentItem != 0);
306
307     model.insertItem(1, "Will", "9876");
308
309     QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
310
311     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
312     QTRY_VERIFY(name != 0);
313     QTRY_COMPARE(name->text(), model.name(1));
314     QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
315     QTRY_VERIFY(number != 0);
316     QTRY_COMPARE(number->text(), model.number(1));
317
318     // Checks that onAdd is called
319     int added = canvas->rootObject()->property("added").toInt();
320     QTRY_COMPARE(added, 1);
321
322     // Confirm items positioned correctly
323     for (int i = 0; i < model.count(); ++i) {
324         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
325         QTRY_COMPARE(item->x(), (i%3)*80.0);
326         QTRY_COMPARE(item->y(), (i/3)*60.0);
327     }
328
329     model.insertItem(0, "Foo", "1111"); // zero index, and current item
330
331     QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
332
333     name = findItem<QDeclarativeText>(contentItem, "textName", 0);
334     QTRY_VERIFY(name != 0);
335     QTRY_COMPARE(name->text(), model.name(0));
336     number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
337     QTRY_VERIFY(number != 0);
338     QTRY_COMPARE(number->text(), model.number(0));
339
340     QTRY_COMPARE(gridview->currentIndex(), 1);
341
342     // Confirm items positioned correctly
343     for (int i = 0; i < model.count(); ++i) {
344         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
345         QTRY_VERIFY(item->x() == (i%3)*80);
346         QTRY_VERIFY(item->y() == (i/3)*60);
347     }
348
349     for (int i = model.count(); i < 30; ++i)
350         model.insertItem(i, "Hello", QString::number(i));
351
352     gridview->setContentY(120);
353
354     // Insert item outside visible area
355     model.insertItem(1, "Hello", "1324");
356
357     QTRY_VERIFY(gridview->contentY() == 120);
358
359     delete canvas;
360 }
361
362 void tst_QDeclarativeGridView::removed()
363 {
364     QDeclarativeView *canvas = createView();
365
366     TestModel model;
367     for (int i = 0; i < 40; i++)
368         model.addItem("Item" + QString::number(i), "");
369
370     QDeclarativeContext *ctxt = canvas->rootContext();
371     ctxt->setContextProperty("testModel", &model);
372     ctxt->setContextProperty("testRightToLeft", QVariant(false));
373     ctxt->setContextProperty("testTopToBottom", QVariant(false));
374
375     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
376     qApp->processEvents();
377
378     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
379     QTRY_VERIFY(gridview != 0);
380
381     QDeclarativeItem *contentItem = gridview->contentItem();
382     QTRY_VERIFY(contentItem != 0);
383
384     model.removeItem(1);
385
386     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
387     QTRY_VERIFY(name != 0);
388     QTRY_COMPARE(name->text(), model.name(1));
389     QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
390     QTRY_VERIFY(number != 0);
391     QTRY_COMPARE(number->text(), model.number(1));
392
393     // Checks that onRemove is called
394     QString removed = canvas->rootObject()->property("removed").toString();
395     QTRY_COMPARE(removed, QString("Item1"));
396
397     // Confirm items positioned correctly
398     int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
399     for (int i = 0; i < model.count() && i < itemCount; ++i) {
400         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
401         if (!item) qWarning() << "Item" << i << "not found";
402         QTRY_VERIFY(item);
403         QTRY_VERIFY(item->x() == (i%3)*80);
404         QTRY_VERIFY(item->y() == (i/3)*60);
405     }
406
407     // Remove first item (which is the current item);
408     model.removeItem(0);
409
410     name = findItem<QDeclarativeText>(contentItem, "textName", 0);
411     QTRY_VERIFY(name != 0);
412     QTRY_COMPARE(name->text(), model.name(0));
413     number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
414     QTRY_VERIFY(number != 0);
415     QTRY_COMPARE(number->text(), model.number(0));
416
417     // Confirm items positioned correctly
418     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
419     for (int i = 0; i < model.count() && i < itemCount; ++i) {
420         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
421         if (!item) qWarning() << "Item" << i << "not found";
422         QTRY_VERIFY(item);
423         QTRY_VERIFY(item->x() == (i%3)*80);
424         QTRY_VERIFY(item->y() == (i/3)*60);
425     }
426
427     // Remove items not visible
428     model.removeItem(25);
429
430     // Confirm items positioned correctly
431     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
432     for (int i = 0; i < model.count() && i < itemCount; ++i) {
433         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
434         if (!item) qWarning() << "Item" << i << "not found";
435         QTRY_VERIFY(item);
436         QTRY_VERIFY(item->x() == (i%3)*80);
437         QTRY_VERIFY(item->y() == (i/3)*60);
438     }
439
440     // Remove items before visible
441     gridview->setContentY(120);
442     gridview->setCurrentIndex(10);
443
444     // Setting currentIndex above shouldn't cause view to scroll
445     QTRY_COMPARE(gridview->contentY(), 120.0);
446
447     model.removeItem(1);
448
449     // Confirm items positioned correctly
450     for (int i = 6; i < 18; ++i) {
451         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
452         if (!item) qWarning() << "Item" << i << "not found";
453         QTRY_VERIFY(item);
454         QTRY_VERIFY(item->x() == (i%3)*80);
455         QTRY_VERIFY(item->y() == (i/3)*60);
456     }
457
458     // Remove currentIndex
459     QDeclarativeItem *oldCurrent = gridview->currentItem();
460     model.removeItem(9);
461
462     QTRY_COMPARE(gridview->currentIndex(), 9);
463     QTRY_VERIFY(gridview->currentItem() != oldCurrent);
464
465     gridview->setContentY(0);
466     // let transitions settle.
467     QTest::qWait(100);
468
469     // Confirm items positioned correctly
470     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
471     for (int i = 0; i < model.count() && i < itemCount; ++i) {
472         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
473         if (!item) qWarning() << "Item" << i << "not found";
474         QTRY_VERIFY(item);
475         QTRY_VERIFY(item->x() == (i%3)*80);
476         QTRY_VERIFY(item->y() == (i/3)*60);
477     }
478
479     // remove item outside current view.
480     gridview->setCurrentIndex(32);
481     gridview->setContentY(240);
482
483     model.removeItem(30);
484     QTRY_VERIFY(gridview->currentIndex() == 31);
485
486     // remove current item beyond visible items.
487     gridview->setCurrentIndex(20);
488     gridview->setContentY(0);
489     model.removeItem(20);
490
491     QTRY_COMPARE(gridview->currentIndex(), 20);
492     QTRY_VERIFY(gridview->currentItem() != 0);
493
494     // remove item before current, but visible
495     gridview->setCurrentIndex(8);
496     gridview->setContentY(240);
497     oldCurrent = gridview->currentItem();
498     model.removeItem(6);
499
500     QTRY_COMPARE(gridview->currentIndex(), 7);
501     QTRY_VERIFY(gridview->currentItem() == oldCurrent);
502
503     delete canvas;
504 }
505
506 void tst_QDeclarativeGridView::clear()
507 {
508     QDeclarativeView *canvas = createView();
509
510     TestModel model;
511     for (int i = 0; i < 30; i++)
512         model.addItem("Item" + QString::number(i), "");
513
514     QDeclarativeContext *ctxt = canvas->rootContext();
515     ctxt->setContextProperty("testModel", &model);
516     ctxt->setContextProperty("testRightToLeft", QVariant(false));
517     ctxt->setContextProperty("testTopToBottom", QVariant(false));
518
519     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
520     qApp->processEvents();
521
522     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
523     QVERIFY(gridview != 0);
524
525     QDeclarativeItem *contentItem = gridview->contentItem();
526     QVERIFY(contentItem != 0);
527
528     model.clear();
529
530     QVERIFY(gridview->count() == 0);
531     QVERIFY(gridview->currentItem() == 0);
532     QVERIFY(gridview->contentY() == 0);
533     QVERIFY(gridview->currentIndex() == -1);
534
535     // confirm sanity when adding an item to cleared list
536     model.addItem("New", "1");
537     QVERIFY(gridview->count() == 1);
538     QVERIFY(gridview->currentItem() != 0);
539     QVERIFY(gridview->currentIndex() == 0);
540
541     delete canvas;
542 }
543
544 void tst_QDeclarativeGridView::moved()
545 {
546     QDeclarativeView *canvas = createView();
547
548     TestModel model;
549     for (int i = 0; i < 30; i++)
550         model.addItem("Item" + QString::number(i), "");
551
552     QDeclarativeContext *ctxt = canvas->rootContext();
553     ctxt->setContextProperty("testModel", &model);
554     ctxt->setContextProperty("testRightToLeft", QVariant(false));
555     ctxt->setContextProperty("testTopToBottom", QVariant(false));
556
557     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
558     qApp->processEvents();
559
560     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
561     QTRY_VERIFY(gridview != 0);
562
563     QDeclarativeItem *contentItem = gridview->contentItem();
564     QTRY_VERIFY(contentItem != 0);
565
566     model.moveItem(1, 8);
567
568     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
569     QTRY_VERIFY(name != 0);
570     QTRY_COMPARE(name->text(), model.name(1));
571     QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
572     QTRY_VERIFY(number != 0);
573     QTRY_COMPARE(number->text(), model.number(1));
574
575     name = findItem<QDeclarativeText>(contentItem, "textName", 8);
576     QTRY_VERIFY(name != 0);
577     QTRY_COMPARE(name->text(), model.name(8));
578     number = findItem<QDeclarativeText>(contentItem, "textNumber", 8);
579     QTRY_VERIFY(number != 0);
580     QTRY_COMPARE(number->text(), model.number(8));
581
582     // Confirm items positioned correctly
583     int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
584     for (int i = 0; i < model.count() && i < itemCount; ++i) {
585         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
586         if (!item) qWarning() << "Item" << i << "not found";
587         QTRY_VERIFY(item);
588         QTRY_VERIFY(item->x() == (i%3)*80);
589         QTRY_VERIFY(item->y() == (i/3)*60);
590     }
591
592     gridview->setContentY(120);
593
594     // move outside visible area
595     model.moveItem(1, 25);
596
597     // Confirm items positioned correctly and indexes correct
598     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count()-1;
599     for (int i = 6; i < model.count()-6 && i < itemCount+6; ++i) {
600         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
601         if (!item) qWarning() << "Item" << i << "not found";
602         QTRY_VERIFY(item);
603         QTRY_COMPARE(item->x(), qreal((i%3)*80));
604         QTRY_COMPARE(item->y(), qreal((i/3)*60));
605         name = findItem<QDeclarativeText>(contentItem, "textName", i);
606         QTRY_VERIFY(name != 0);
607         QTRY_COMPARE(name->text(), model.name(i));
608         number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
609         QTRY_VERIFY(number != 0);
610         QTRY_COMPARE(number->text(), model.number(i));
611     }
612
613     // move from outside visible into visible
614     model.moveItem(28, 8);
615
616     // Confirm items positioned correctly and indexes correct
617     for (int i = 6; i < model.count()-6 && i < itemCount+6; ++i) {
618         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
619         if (!item) qWarning() << "Item" << i << "not found";
620         QTRY_VERIFY(item);
621         QTRY_VERIFY(item->x() == (i%3)*80);
622         QTRY_VERIFY(item->y() == (i/3)*60);
623         name = findItem<QDeclarativeText>(contentItem, "textName", i);
624         QTRY_VERIFY(name != 0);
625         QTRY_COMPARE(name->text(), model.name(i));
626         number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
627         QTRY_VERIFY(number != 0);
628         QTRY_COMPARE(number->text(), model.number(i));
629     }
630
631     // ensure content position is stable
632     gridview->setContentY(0);
633     model.moveItem(10, 0);
634     QTRY_VERIFY(gridview->contentY() == 0);
635
636     delete canvas;
637 }
638
639 void tst_QDeclarativeGridView::currentIndex()
640 {
641     TestModel model;
642     for (int i = 0; i < 60; i++)
643         model.addItem("Item" + QString::number(i), QString::number(i));
644
645     QDeclarativeView *canvas = new QDeclarativeView(0);
646     canvas->setFixedSize(240,320);
647
648     QDeclarativeContext *ctxt = canvas->rootContext();
649     ctxt->setContextProperty("testModel", &model);
650
651     QString filename(SRCDIR "/data/gridview-initCurrent.qml");
652     canvas->setSource(QUrl::fromLocalFile(filename));
653
654     qApp->processEvents();
655
656     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
657     QVERIFY(gridview != 0);
658
659     QDeclarativeItem *contentItem = gridview->contentItem();
660     QVERIFY(contentItem != 0);
661
662     // current item should be third item
663     QCOMPARE(gridview->currentIndex(), 35);
664     QCOMPARE(gridview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 35));
665     QCOMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
666     QCOMPARE(gridview->contentY(), 400.0);
667
668     gridview->moveCurrentIndexRight();
669     QCOMPARE(gridview->currentIndex(), 36);
670     gridview->moveCurrentIndexDown();
671     QCOMPARE(gridview->currentIndex(), 39);
672     gridview->moveCurrentIndexUp();
673     QCOMPARE(gridview->currentIndex(), 36);
674     gridview->moveCurrentIndexLeft();
675     QCOMPARE(gridview->currentIndex(), 35);
676
677     // no wrap
678     gridview->setCurrentIndex(0);
679     QCOMPARE(gridview->currentIndex(), 0);
680     // confirm that the velocity is updated
681     QTRY_VERIFY(gridview->verticalVelocity() != 0.0);
682
683     gridview->moveCurrentIndexUp();
684     QCOMPARE(gridview->currentIndex(), 0);
685
686     gridview->moveCurrentIndexLeft();
687     QCOMPARE(gridview->currentIndex(), 0);
688
689     gridview->setCurrentIndex(model.count()-1);
690     QCOMPARE(gridview->currentIndex(), model.count()-1);
691
692     gridview->moveCurrentIndexRight();
693     QCOMPARE(gridview->currentIndex(), model.count()-1);
694
695     gridview->moveCurrentIndexDown();
696     QCOMPARE(gridview->currentIndex(), model.count()-1);
697
698     // with wrap
699     gridview->setWrapEnabled(true);
700
701     gridview->setCurrentIndex(0);
702     QCOMPARE(gridview->currentIndex(), 0);
703
704     gridview->moveCurrentIndexLeft();
705     QCOMPARE(gridview->currentIndex(), model.count()-1);
706
707     QTRY_COMPARE(gridview->contentY(), 880.0);
708
709     gridview->moveCurrentIndexRight();
710     QCOMPARE(gridview->currentIndex(), 0);
711
712     QTRY_COMPARE(gridview->contentY(), 0.0);
713
714     // Test keys
715     canvas->show();
716     qApp->setActiveWindow(canvas);
717 #ifdef Q_WS_X11
718     // to be safe and avoid failing setFocus with window managers
719     qt_x11_wait_for_window_manager(canvas);
720 #endif
721     QTRY_VERIFY(canvas->hasFocus());
722     QTRY_VERIFY(canvas->scene()->hasFocus());
723     qApp->processEvents();
724
725     QTest::keyClick(canvas, Qt::Key_Down);
726     QCOMPARE(gridview->currentIndex(), 3);
727
728     QTest::keyClick(canvas, Qt::Key_Up);
729     QCOMPARE(gridview->currentIndex(), 0);
730
731     gridview->setFlow(QDeclarativeGridView::TopToBottom);
732
733     qApp->setActiveWindow(canvas);
734 #ifdef Q_WS_X11
735     // to be safe and avoid failing setFocus with window managers
736     qt_x11_wait_for_window_manager(canvas);
737 #endif
738     QTRY_VERIFY(canvas->hasFocus());
739     QTRY_VERIFY(canvas->scene()->hasFocus());
740     qApp->processEvents();
741
742     QTest::keyClick(canvas, Qt::Key_Right);
743     QCOMPARE(gridview->currentIndex(), 5);
744
745     QTest::keyClick(canvas, Qt::Key_Left);
746     QCOMPARE(gridview->currentIndex(), 0);
747
748     QTest::keyClick(canvas, Qt::Key_Down);
749     QCOMPARE(gridview->currentIndex(), 1);
750
751     QTest::keyClick(canvas, Qt::Key_Up);
752     QCOMPARE(gridview->currentIndex(), 0);
753
754
755     // turn off auto highlight
756     gridview->setHighlightFollowsCurrentItem(false);
757     QVERIFY(gridview->highlightFollowsCurrentItem() == false);
758     QVERIFY(gridview->highlightItem());
759     qreal hlPosX = gridview->highlightItem()->x();
760     qreal hlPosY = gridview->highlightItem()->y();
761
762     gridview->setCurrentIndex(5);
763     QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
764     QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
765
766     // insert item before currentIndex
767     gridview->setCurrentIndex(28);
768     model.insertItem(0, "Foo", "1111");
769     QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
770
771     // check removing highlight by setting currentIndex to -1;
772     gridview->setCurrentIndex(-1);
773
774     QCOMPARE(gridview->currentIndex(), -1);
775     QVERIFY(!gridview->highlightItem());
776     QVERIFY(!gridview->currentItem());
777
778     gridview->setHighlightFollowsCurrentItem(true);
779
780     gridview->setFlow(QDeclarativeGridView::LeftToRight);
781     gridview->setLayoutDirection(Qt::RightToLeft);
782
783     qApp->setActiveWindow(canvas);
784 #ifdef Q_WS_X11
785     // to be safe and avoid failing setFocus with window managers
786     qt_x11_wait_for_window_manager(canvas);
787 #endif
788     QTRY_VERIFY(canvas->hasFocus());
789     QTRY_VERIFY(canvas->scene()->hasFocus());
790     qApp->processEvents();
791
792     gridview->setCurrentIndex(35);
793
794     QTest::keyClick(canvas, Qt::Key_Right);
795     QCOMPARE(gridview->currentIndex(), 34);
796
797     QTest::keyClick(canvas, Qt::Key_Down);
798     QCOMPARE(gridview->currentIndex(), 37);
799
800     QTest::keyClick(canvas, Qt::Key_Up);
801     QCOMPARE(gridview->currentIndex(), 34);
802
803     QTest::keyClick(canvas, Qt::Key_Left);
804     QCOMPARE(gridview->currentIndex(), 35);
805
806
807     // turn off auto highlight
808     gridview->setHighlightFollowsCurrentItem(false);
809     QVERIFY(gridview->highlightFollowsCurrentItem() == false);
810     QVERIFY(gridview->highlightItem());
811     hlPosX = gridview->highlightItem()->x();
812     hlPosY = gridview->highlightItem()->y();
813
814     gridview->setCurrentIndex(5);
815     QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
816     QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
817
818     // insert item before currentIndex
819     gridview->setCurrentIndex(28);
820     model.insertItem(0, "Foo", "1111");
821     QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
822
823     // check removing highlight by setting currentIndex to -1;
824     gridview->setCurrentIndex(-1);
825
826     QCOMPARE(gridview->currentIndex(), -1);
827     QVERIFY(!gridview->highlightItem());
828     QVERIFY(!gridview->currentItem());
829
830     delete canvas;
831 }
832
833 void tst_QDeclarativeGridView::noCurrentIndex()
834 {
835     TestModel model;
836     for (int i = 0; i < 60; i++)
837         model.addItem("Item" + QString::number(i), QString::number(i));
838
839     QDeclarativeView *canvas = new QDeclarativeView(0);
840     canvas->setFixedSize(240,320);
841
842     QDeclarativeContext *ctxt = canvas->rootContext();
843     ctxt->setContextProperty("testModel", &model);
844
845     QString filename(SRCDIR "/data/gridview-noCurrent.qml");
846     canvas->setSource(QUrl::fromLocalFile(filename));
847
848     qApp->processEvents();
849
850     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
851     QVERIFY(gridview != 0);
852
853     QDeclarativeItem *contentItem = gridview->contentItem();
854     QVERIFY(contentItem != 0);
855
856     // current index should be -1
857     QCOMPARE(gridview->currentIndex(), -1);
858     QVERIFY(!gridview->currentItem());
859     QVERIFY(!gridview->highlightItem());
860     QCOMPARE(gridview->contentY(), 0.0);
861
862     gridview->setCurrentIndex(5);
863     QCOMPARE(gridview->currentIndex(), 5);
864     QVERIFY(gridview->currentItem());
865     QVERIFY(gridview->highlightItem());
866 }
867
868 void tst_QDeclarativeGridView::changeFlow()
869 {
870     QDeclarativeView *canvas = createView();
871
872     TestModel model;
873     for (int i = 0; i < 30; i++)
874         model.addItem("Item" + QString::number(i), QString::number(i));
875
876     QDeclarativeContext *ctxt = canvas->rootContext();
877     ctxt->setContextProperty("testModel", &model);
878     ctxt->setContextProperty("testRightToLeft", QVariant(false));
879     ctxt->setContextProperty("testTopToBottom", QVariant(false));
880
881     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
882     qApp->processEvents();
883
884     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
885     QTRY_VERIFY(gridview != 0);
886
887     QDeclarativeItem *contentItem = gridview->contentItem();
888     QTRY_VERIFY(contentItem != 0);
889
890     // Confirm items positioned correctly and indexes correct
891     int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
892     for (int i = 0; i < model.count() && i < itemCount; ++i) {
893         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
894         if (!item) qWarning() << "Item" << i << "not found";
895         QTRY_VERIFY(item);
896         QTRY_COMPARE(item->x(), qreal((i%3)*80));
897         QTRY_COMPARE(item->y(), qreal((i/3)*60));
898         QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", i);
899         QTRY_VERIFY(name != 0);
900         QTRY_COMPARE(name->text(), model.name(i));
901         QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
902         QTRY_VERIFY(number != 0);
903         QTRY_COMPARE(number->text(), model.number(i));
904     }
905
906     ctxt->setContextProperty("testTopToBottom", QVariant(true));
907
908     // Confirm items positioned correctly and indexes correct
909     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
910     for (int i = 0; i < model.count() && i < itemCount; ++i) {
911         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
912         if (!item) qWarning() << "Item" << i << "not found";
913         QTRY_VERIFY(item);
914         QTRY_COMPARE(item->x(), qreal((i/5)*80));
915         QTRY_COMPARE(item->y(), qreal((i%5)*60));
916         QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", i);
917         QTRY_VERIFY(name != 0);
918         QTRY_COMPARE(name->text(), model.name(i));
919         QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
920         QTRY_VERIFY(number != 0);
921         QTRY_COMPARE(number->text(), model.number(i));
922     }
923
924     ctxt->setContextProperty("testRightToLeft", QVariant(true));
925
926     // Confirm items positioned correctly and indexes correct
927     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
928     for (int i = 0; i < model.count() && i < itemCount; ++i) {
929         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
930         if (!item) qWarning() << "Item" << i << "not found";
931         QTRY_VERIFY(item);
932         QTRY_COMPARE(item->x(), qreal(-(i/5)*80 - item->width()));
933         QTRY_COMPARE(item->y(), qreal((i%5)*60));
934         QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", i);
935         QTRY_VERIFY(name != 0);
936         QTRY_COMPARE(name->text(), model.name(i));
937         QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
938         QTRY_VERIFY(number != 0);
939         QTRY_COMPARE(number->text(), model.number(i));
940     }
941     gridview->setContentX(100);
942     QTRY_COMPARE(gridview->contentX(), 100.);
943     ctxt->setContextProperty("testTopToBottom", QVariant(false));
944     QTRY_COMPARE(gridview->contentX(), 0.);
945
946     // Confirm items positioned correctly and indexes correct
947     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
948     for (int i = 0; i < model.count() && i < itemCount; ++i) {
949         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
950         if (!item) qWarning() << "Item" << i << "not found";
951         QTRY_VERIFY(item);
952         QTRY_COMPARE(item->x(), qreal(240 - (i%3+1)*80));
953         QTRY_COMPARE(item->y(), qreal((i/3)*60));
954         QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", i);
955         QTRY_VERIFY(name != 0);
956         QTRY_COMPARE(name->text(), model.name(i));
957         QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
958         QTRY_VERIFY(number != 0);
959         QTRY_COMPARE(number->text(), model.number(i));
960     }
961
962     delete canvas;
963 }
964
965 void tst_QDeclarativeGridView::defaultValues()
966 {
967     QDeclarativeEngine engine;
968     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/gridview3.qml"));
969     QDeclarativeGridView *obj = qobject_cast<QDeclarativeGridView*>(c.create());
970
971     QTRY_VERIFY(obj != 0);
972     QTRY_VERIFY(obj->model() == QVariant());
973     QTRY_VERIFY(obj->delegate() == 0);
974     QTRY_COMPARE(obj->currentIndex(), -1);
975     QTRY_VERIFY(obj->currentItem() == 0);
976     QTRY_COMPARE(obj->count(), 0);
977     QTRY_VERIFY(obj->highlight() == 0);
978     QTRY_VERIFY(obj->highlightItem() == 0);
979     QTRY_COMPARE(obj->highlightFollowsCurrentItem(), true);
980     QTRY_VERIFY(obj->flow() == 0);
981     QTRY_COMPARE(obj->isWrapEnabled(), false);
982     QTRY_COMPARE(obj->cacheBuffer(), 0);
983     QTRY_COMPARE(obj->cellWidth(), 100); //### Should 100 be the default?
984     QTRY_COMPARE(obj->cellHeight(), 100);
985     delete obj;
986 }
987
988 void tst_QDeclarativeGridView::properties()
989 {
990     QDeclarativeEngine engine;
991     QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/gridview2.qml"));
992     QDeclarativeGridView *obj = qobject_cast<QDeclarativeGridView*>(c.create());
993
994     QTRY_VERIFY(obj != 0);
995     QTRY_VERIFY(obj->model() != QVariant());
996     QTRY_VERIFY(obj->delegate() != 0);
997     QTRY_COMPARE(obj->currentIndex(), 0);
998     QTRY_VERIFY(obj->currentItem() != 0);
999     QTRY_COMPARE(obj->count(), 4);
1000     QTRY_VERIFY(obj->highlight() != 0);
1001     QTRY_VERIFY(obj->highlightItem() != 0);
1002     QTRY_COMPARE(obj->highlightFollowsCurrentItem(), false);
1003     QTRY_VERIFY(obj->flow() == 0);
1004     QTRY_COMPARE(obj->isWrapEnabled(), true);
1005     QTRY_COMPARE(obj->cacheBuffer(), 200);
1006     QTRY_COMPARE(obj->cellWidth(), 100);
1007     QTRY_COMPARE(obj->cellHeight(), 100);
1008     delete obj;
1009 }
1010
1011 void tst_QDeclarativeGridView::propertyChanges()
1012 {
1013     QDeclarativeView *canvas = createView();
1014     QTRY_VERIFY(canvas);
1015     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1016
1017     QDeclarativeGridView *gridView = canvas->rootObject()->findChild<QDeclarativeGridView*>("gridView");
1018     QTRY_VERIFY(gridView);
1019
1020     QSignalSpy keyNavigationWrapsSpy(gridView, SIGNAL(keyNavigationWrapsChanged()));
1021     QSignalSpy cacheBufferSpy(gridView, SIGNAL(cacheBufferChanged()));
1022     QSignalSpy layoutSpy(gridView, SIGNAL(layoutDirectionChanged()));
1023     QSignalSpy flowSpy(gridView, SIGNAL(flowChanged()));
1024
1025     QTRY_COMPARE(gridView->isWrapEnabled(), true);
1026     QTRY_COMPARE(gridView->cacheBuffer(), 10);
1027     QTRY_COMPARE(gridView->flow(), QDeclarativeGridView::LeftToRight);
1028
1029     gridView->setWrapEnabled(false);
1030     gridView->setCacheBuffer(3);
1031     gridView->setFlow(QDeclarativeGridView::TopToBottom);
1032
1033     QTRY_COMPARE(gridView->isWrapEnabled(), false);
1034     QTRY_COMPARE(gridView->cacheBuffer(), 3);
1035     QTRY_COMPARE(gridView->flow(), QDeclarativeGridView::TopToBottom);
1036
1037     QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1038     QTRY_COMPARE(cacheBufferSpy.count(),1);
1039     QTRY_COMPARE(flowSpy.count(),1);
1040
1041     gridView->setWrapEnabled(false);
1042     gridView->setCacheBuffer(3);
1043     gridView->setFlow(QDeclarativeGridView::TopToBottom);
1044
1045     QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1046     QTRY_COMPARE(cacheBufferSpy.count(),1);
1047     QTRY_COMPARE(flowSpy.count(),1);
1048
1049     gridView->setFlow(QDeclarativeGridView::LeftToRight);
1050     QTRY_COMPARE(gridView->flow(), QDeclarativeGridView::LeftToRight);
1051
1052     gridView->setWrapEnabled(true);
1053     gridView->setCacheBuffer(5);
1054     gridView->setLayoutDirection(Qt::RightToLeft);
1055
1056     QTRY_COMPARE(gridView->isWrapEnabled(), true);
1057     QTRY_COMPARE(gridView->cacheBuffer(), 5);
1058     QTRY_COMPARE(gridView->layoutDirection(), Qt::RightToLeft);
1059
1060     QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
1061     QTRY_COMPARE(cacheBufferSpy.count(),2);
1062     QTRY_COMPARE(layoutSpy.count(),1);
1063     QTRY_COMPARE(flowSpy.count(),2);
1064
1065     gridView->setWrapEnabled(true);
1066     gridView->setCacheBuffer(5);
1067     gridView->setLayoutDirection(Qt::RightToLeft);
1068
1069     QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
1070     QTRY_COMPARE(cacheBufferSpy.count(),2);
1071     QTRY_COMPARE(layoutSpy.count(),1);
1072     QTRY_COMPARE(flowSpy.count(),2);
1073
1074     gridView->setFlow(QDeclarativeGridView::TopToBottom);
1075     QTRY_COMPARE(gridView->flow(), QDeclarativeGridView::TopToBottom);
1076     QTRY_COMPARE(flowSpy.count(),3);
1077
1078     gridView->setFlow(QDeclarativeGridView::TopToBottom);
1079     QTRY_COMPARE(flowSpy.count(),3);
1080
1081     delete canvas;
1082 }
1083
1084 void tst_QDeclarativeGridView::componentChanges()
1085 {
1086     QDeclarativeView *canvas = createView();
1087     QTRY_VERIFY(canvas);
1088     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1089
1090     QDeclarativeGridView *gridView = canvas->rootObject()->findChild<QDeclarativeGridView*>("gridView");
1091     QTRY_VERIFY(gridView);
1092
1093     QDeclarativeComponent component(canvas->engine());
1094     component.setData("import QtQuick 1.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
1095
1096     QDeclarativeComponent delegateComponent(canvas->engine());
1097     delegateComponent.setData("import QtQuick 1.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
1098
1099     QSignalSpy highlightSpy(gridView, SIGNAL(highlightChanged()));
1100     QSignalSpy delegateSpy(gridView, SIGNAL(delegateChanged()));
1101     QSignalSpy headerSpy(gridView, SIGNAL(headerChanged()));
1102     QSignalSpy footerSpy(gridView, SIGNAL(footerChanged()));
1103
1104     gridView->setHighlight(&component);
1105     gridView->setDelegate(&delegateComponent);
1106     gridView->setHeader(&component);
1107     gridView->setFooter(&component);
1108
1109     QTRY_COMPARE(gridView->highlight(), &component);
1110     QTRY_COMPARE(gridView->delegate(), &delegateComponent);
1111     QTRY_COMPARE(gridView->header(), &component);
1112     QTRY_COMPARE(gridView->footer(), &component);
1113
1114     QTRY_COMPARE(highlightSpy.count(),1);
1115     QTRY_COMPARE(delegateSpy.count(),1);
1116     QTRY_COMPARE(headerSpy.count(),1);
1117     QTRY_COMPARE(footerSpy.count(),1);
1118
1119     gridView->setHighlight(&component);
1120     gridView->setDelegate(&delegateComponent);
1121     gridView->setHeader(&component);
1122     gridView->setFooter(&component);
1123
1124     QTRY_COMPARE(highlightSpy.count(),1);
1125     QTRY_COMPARE(delegateSpy.count(),1);
1126     QTRY_COMPARE(headerSpy.count(),1);
1127     QTRY_COMPARE(footerSpy.count(),1);
1128
1129     delete canvas;
1130 }
1131
1132 void tst_QDeclarativeGridView::modelChanges()
1133 {
1134     QDeclarativeView *canvas = createView();
1135     QTRY_VERIFY(canvas);
1136     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1137
1138     QDeclarativeGridView *gridView = canvas->rootObject()->findChild<QDeclarativeGridView*>("gridView");
1139     QTRY_VERIFY(gridView);
1140
1141     QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
1142     QTRY_VERIFY(alternateModel);
1143     QVariant modelVariant = QVariant::fromValue(alternateModel);
1144     QSignalSpy modelSpy(gridView, SIGNAL(modelChanged()));
1145
1146     gridView->setModel(modelVariant);
1147     QTRY_COMPARE(gridView->model(), modelVariant);
1148     QTRY_COMPARE(modelSpy.count(),1);
1149
1150     gridView->setModel(modelVariant);
1151     QTRY_COMPARE(modelSpy.count(),1);
1152
1153     gridView->setModel(QVariant());
1154     QTRY_COMPARE(modelSpy.count(),2);
1155     delete canvas;
1156 }
1157
1158 void tst_QDeclarativeGridView::positionViewAtIndex()
1159 {
1160     QDeclarativeView *canvas = createView();
1161
1162     TestModel model;
1163     for (int i = 0; i < 40; i++)
1164         model.addItem("Item" + QString::number(i), "");
1165
1166     QDeclarativeContext *ctxt = canvas->rootContext();
1167     ctxt->setContextProperty("testModel", &model);
1168     ctxt->setContextProperty("testRightToLeft", QVariant(false));
1169     ctxt->setContextProperty("testTopToBottom", QVariant(false));
1170
1171     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
1172     qApp->processEvents();
1173
1174     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1175     QTRY_VERIFY(gridview != 0);
1176
1177     QDeclarativeItem *contentItem = gridview->contentItem();
1178     QTRY_VERIFY(contentItem != 0);
1179
1180     // Confirm items positioned correctly
1181     int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1182     for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1183         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1184         if (!item) qWarning() << "Item" << i << "not found";
1185         QTRY_VERIFY(item);
1186         QTRY_COMPARE(item->x(), (i%3)*80.);
1187         QTRY_COMPARE(item->y(), (i/3)*60.);
1188     }
1189
1190     // Position on a currently visible item
1191     gridview->positionViewAtIndex(4, QDeclarativeGridView::Beginning);
1192     QTRY_COMPARE(gridview->indexAt(120, 90), 4);
1193     QTRY_COMPARE(gridview->contentY(), 60.);
1194
1195     // Confirm items positioned correctly
1196     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1197     for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
1198         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1199         if (!item) qWarning() << "Item" << i << "not found";
1200         QTRY_VERIFY(item);
1201         QTRY_COMPARE(item->x(), (i%3)*80.);
1202         QTRY_COMPARE(item->y(), (i/3)*60.);
1203     }
1204
1205     // Position on an item beyond the visible items
1206     gridview->positionViewAtIndex(21, QDeclarativeGridView::Beginning);
1207     QTRY_COMPARE(gridview->indexAt(40, 450), 21);
1208     QTRY_COMPARE(gridview->contentY(), 420.);
1209
1210     // Confirm items positioned correctly
1211     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1212     for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
1213         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1214         if (!item) qWarning() << "Item" << i << "not found";
1215         QTRY_VERIFY(item);
1216         QTRY_COMPARE(item->x(), (i%3)*80.);
1217         QTRY_COMPARE(item->y(), (i/3)*60.);
1218     }
1219
1220     // Position on an item that would leave empty space if positioned at the top
1221     gridview->positionViewAtIndex(31, QDeclarativeGridView::Beginning);
1222     QTRY_COMPARE(gridview->indexAt(120, 630), 31);
1223     QTRY_COMPARE(gridview->contentY(), 520.);
1224
1225     // Confirm items positioned correctly
1226     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1227     for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
1228         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1229         if (!item) qWarning() << "Item" << i << "not found";
1230         QTRY_VERIFY(item);
1231         QTRY_COMPARE(item->x(), (i%3)*80.);
1232         QTRY_COMPARE(item->y(), (i/3)*60.);
1233     }
1234
1235     // Position at the beginning again
1236     gridview->positionViewAtIndex(0, QDeclarativeGridView::Beginning);
1237     QTRY_COMPARE(gridview->indexAt(0, 0), 0);
1238     QTRY_COMPARE(gridview->indexAt(40, 30), 0);
1239     QTRY_COMPARE(gridview->indexAt(80, 60), 4);
1240     QTRY_COMPARE(gridview->contentY(), 0.);
1241
1242     // Confirm items positioned correctly
1243     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1244     for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1245         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1246         if (!item) qWarning() << "Item" << i << "not found";
1247         QTRY_VERIFY(item);
1248         QTRY_COMPARE(item->x(), (i%3)*80.);
1249         QTRY_COMPARE(item->y(), (i/3)*60.);
1250     }
1251
1252     // Position at End
1253     gridview->positionViewAtIndex(30, QDeclarativeGridView::End);
1254     QTRY_COMPARE(gridview->contentY(), 340.);
1255
1256     // Position in Center
1257     gridview->positionViewAtIndex(15, QDeclarativeGridView::Center);
1258     QTRY_COMPARE(gridview->contentY(), 170.);
1259
1260     // Ensure at least partially visible
1261     gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible);
1262     QTRY_COMPARE(gridview->contentY(), 170.);
1263
1264     gridview->setContentY(302);
1265     gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible);
1266     QTRY_COMPARE(gridview->contentY(), 302.);
1267
1268     gridview->setContentY(360);
1269     gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible);
1270     QTRY_COMPARE(gridview->contentY(), 300.);
1271
1272     gridview->setContentY(60);
1273     gridview->positionViewAtIndex(20, QDeclarativeGridView::Visible);
1274     QTRY_COMPARE(gridview->contentY(), 60.);
1275
1276     gridview->setContentY(20);
1277     gridview->positionViewAtIndex(20, QDeclarativeGridView::Visible);
1278     QTRY_COMPARE(gridview->contentY(), 100.);
1279
1280     // Ensure completely visible
1281     gridview->setContentY(120);
1282     gridview->positionViewAtIndex(20, QDeclarativeGridView::Contain);
1283     QTRY_COMPARE(gridview->contentY(), 120.);
1284
1285     gridview->setContentY(302);
1286     gridview->positionViewAtIndex(15, QDeclarativeGridView::Contain);
1287     QTRY_COMPARE(gridview->contentY(), 300.);
1288
1289     gridview->setContentY(60);
1290     gridview->positionViewAtIndex(20, QDeclarativeGridView::Contain);
1291     QTRY_COMPARE(gridview->contentY(), 100.);
1292
1293     // Test for Top To Bottom layout
1294     ctxt->setContextProperty("testTopToBottom", QVariant(true));
1295
1296     // Confirm items positioned correctly
1297     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1298     for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1299         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1300         if (!item) qWarning() << "Item" << i << "not found";
1301         QTRY_VERIFY(item);
1302         QTRY_COMPARE(item->x(), (i/5)*80.);
1303         QTRY_COMPARE(item->y(), (i%5)*60.);
1304     }
1305
1306     // Position at End
1307     gridview->positionViewAtIndex(30, QDeclarativeGridView::End);
1308     QTRY_COMPARE(gridview->contentX(), 320.);
1309     QTRY_COMPARE(gridview->contentY(), 0.);
1310
1311     // Position in Center
1312     gridview->positionViewAtIndex(15, QDeclarativeGridView::Center);
1313     QTRY_COMPARE(gridview->contentX(), 160.);
1314
1315     // Ensure at least partially visible
1316     gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible);
1317     QTRY_COMPARE(gridview->contentX(), 160.);
1318
1319     gridview->setContentX(170);
1320     gridview->positionViewAtIndex(25, QDeclarativeGridView::Visible);
1321     QTRY_COMPARE(gridview->contentX(), 170.);
1322
1323     gridview->positionViewAtIndex(30, QDeclarativeGridView::Visible);
1324     QTRY_COMPARE(gridview->contentX(), 320.);
1325
1326     gridview->setContentX(170);
1327     gridview->positionViewAtIndex(25, QDeclarativeGridView::Contain);
1328     QTRY_COMPARE(gridview->contentX(), 240.);
1329
1330     // positionViewAtBeginning
1331     gridview->positionViewAtBeginning();
1332     QTRY_COMPARE(gridview->contentX(), 0.);
1333
1334     gridview->setContentX(80);
1335     canvas->rootObject()->setProperty("showHeader", true);
1336     gridview->positionViewAtBeginning();
1337     QTRY_COMPARE(gridview->contentX(), -30.);
1338
1339     // positionViewAtEnd
1340     gridview->positionViewAtEnd();
1341     QTRY_COMPARE(gridview->contentX(), 430.);
1342
1343     gridview->setContentX(80);
1344     canvas->rootObject()->setProperty("showFooter", true);
1345     gridview->positionViewAtEnd();
1346     QTRY_COMPARE(gridview->contentX(), 460.);
1347
1348     delete canvas;
1349 }
1350
1351 void tst_QDeclarativeGridView::snapping()
1352 {
1353     QDeclarativeView *canvas = createView();
1354
1355     TestModel model;
1356     for (int i = 0; i < 40; i++)
1357         model.addItem("Item" + QString::number(i), "");
1358
1359     QDeclarativeContext *ctxt = canvas->rootContext();
1360     ctxt->setContextProperty("testModel", &model);
1361     ctxt->setContextProperty("testTopToBottom", QVariant(false));
1362     ctxt->setContextProperty("testRightToLeft", QVariant(false));
1363
1364     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
1365     qApp->processEvents();
1366
1367     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1368     QTRY_VERIFY(gridview != 0);
1369
1370     gridview->setHeight(220);
1371     QCOMPARE(gridview->height(), 220.);
1372
1373     gridview->positionViewAtIndex(12, QDeclarativeGridView::Visible);
1374     QCOMPARE(gridview->contentY(), 80.);
1375
1376     gridview->setContentY(0);
1377     QCOMPARE(gridview->contentY(), 0.);
1378
1379     gridview->setSnapMode(QDeclarativeGridView::SnapToRow);
1380     QCOMPARE(gridview->snapMode(), QDeclarativeGridView::SnapToRow);
1381
1382     gridview->positionViewAtIndex(12, QDeclarativeGridView::Visible);
1383     QCOMPARE(gridview->contentY(), 60.);
1384
1385     gridview->positionViewAtIndex(15, QDeclarativeGridView::End);
1386     QCOMPARE(gridview->contentY(), 120.);
1387
1388     delete canvas;
1389
1390 }
1391
1392 void tst_QDeclarativeGridView::mirroring()
1393 {
1394     QDeclarativeView *canvasA = createView();
1395     canvasA->setSource(QUrl::fromLocalFile(SRCDIR "/data/mirroring.qml"));
1396     QDeclarativeGridView *gridviewA = findItem<QDeclarativeGridView>(canvasA->rootObject(), "view");
1397     QTRY_VERIFY(gridviewA != 0);
1398
1399     QDeclarativeView *canvasB = createView();
1400     canvasB->setSource(QUrl::fromLocalFile(SRCDIR "/data/mirroring.qml"));
1401     QDeclarativeGridView *gridviewB = findItem<QDeclarativeGridView>(canvasB->rootObject(), "view");
1402     QTRY_VERIFY(gridviewA != 0);
1403     qApp->processEvents();
1404
1405     QList<QString> objectNames;
1406     objectNames << "item1" << "item2"; // << "item3"
1407
1408     gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
1409     gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
1410     QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection());
1411
1412     // LTR != RTL
1413     foreach(const QString objectName, objectNames)
1414         QVERIFY(findItem<QDeclarativeItem>(gridviewA, objectName)->x() != findItem<QDeclarativeItem>(gridviewB, objectName)->x());
1415
1416     gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
1417     gridviewB->setProperty("layoutDirection", Qt::LeftToRight);
1418
1419     // LTR == LTR
1420     foreach(const QString objectName, objectNames)
1421         QCOMPARE(findItem<QDeclarativeItem>(gridviewA, objectName)->x(), findItem<QDeclarativeItem>(gridviewB, objectName)->x());
1422
1423     QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection());
1424     QDeclarativeItemPrivate::get(gridviewB)->setLayoutMirror(true);
1425     QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
1426
1427     // LTR != LTR+mirror
1428     foreach(const QString objectName, objectNames)
1429         QVERIFY(findItem<QDeclarativeItem>(gridviewA, objectName)->x() != findItem<QDeclarativeItem>(gridviewB, objectName)->x());
1430
1431     gridviewA->setProperty("layoutDirection", Qt::RightToLeft);
1432
1433     // RTL == LTR+mirror
1434     foreach(const QString objectName, objectNames)
1435         QCOMPARE(findItem<QDeclarativeItem>(gridviewA, objectName)->x(), findItem<QDeclarativeItem>(gridviewB, objectName)->x());
1436
1437     gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
1438
1439     // RTL != RTL+mirror
1440     foreach(const QString objectName, objectNames)
1441         QVERIFY(findItem<QDeclarativeItem>(gridviewA, objectName)->x() != findItem<QDeclarativeItem>(gridviewB, objectName)->x());
1442
1443     gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
1444
1445     // LTR == RTL+mirror
1446     foreach(const QString objectName, objectNames)
1447         QCOMPARE(findItem<QDeclarativeItem>(gridviewA, objectName)->x(), findItem<QDeclarativeItem>(gridviewB, objectName)->x());
1448
1449     delete canvasA;
1450     delete canvasB;
1451 }
1452
1453 void tst_QDeclarativeGridView::positionViewAtIndex_rightToLeft()
1454 {
1455     QDeclarativeView *canvas = createView();
1456
1457     TestModel model;
1458     for (int i = 0; i < 40; i++)
1459         model.addItem("Item" + QString::number(i), "");
1460
1461     QDeclarativeContext *ctxt = canvas->rootContext();
1462     ctxt->setContextProperty("testModel", &model);
1463     ctxt->setContextProperty("testTopToBottom", QVariant(true));
1464     ctxt->setContextProperty("testRightToLeft", QVariant(true));
1465
1466     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
1467     qApp->processEvents();
1468
1469     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1470     QTRY_VERIFY(gridview != 0);
1471
1472     QDeclarativeItem *contentItem = gridview->contentItem();
1473     QTRY_VERIFY(contentItem != 0);
1474
1475     // Confirm items positioned correctly
1476     int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1477     for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1478         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1479         if (!item) qWarning() << "Item" << i << "not found";
1480         QTRY_VERIFY(item);
1481         QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1482         QTRY_COMPARE(item->y(), qreal((i%5)*60));
1483     }
1484
1485     // Position on a currently visible item
1486     gridview->positionViewAtIndex(6, QDeclarativeGridView::Beginning);
1487     QTRY_COMPARE(gridview->contentX(), -320.);
1488
1489     // Confirm items positioned correctly
1490     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1491     for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
1492         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1493         if (!item) qWarning() << "Item" << i << "not found";
1494         QTRY_VERIFY(item);
1495         QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1496         QTRY_COMPARE(item->y(), qreal((i%5)*60));
1497     }
1498
1499     // Position on an item beyond the visible items
1500     gridview->positionViewAtIndex(21, QDeclarativeGridView::Beginning);
1501     QTRY_COMPARE(gridview->contentX(), -560.);
1502
1503     // Confirm items positioned correctly
1504     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1505     for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
1506         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1507         if (!item) qWarning() << "Item" << i << "not found";
1508         QTRY_VERIFY(item);
1509         QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1510         QTRY_COMPARE(item->y(), qreal((i%5)*60));
1511     }
1512
1513     // Position on an item that would leave empty space if positioned at the top
1514     gridview->positionViewAtIndex(31, QDeclarativeGridView::Beginning);
1515     QTRY_COMPARE(gridview->contentX(), -639.);
1516
1517     // Confirm items positioned correctly
1518     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1519     for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
1520         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1521         if (!item) qWarning() << "Item" << i << "not found";
1522         QTRY_VERIFY(item);
1523         QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1524         QTRY_COMPARE(item->y(), qreal((i%5)*60));
1525     }
1526
1527     // Position at the beginning again
1528     gridview->positionViewAtIndex(0, QDeclarativeGridView::Beginning);
1529     QTRY_COMPARE(gridview->contentX(), -240.);
1530
1531     // Confirm items positioned correctly
1532     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1533     for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1534         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1535         if (!item) qWarning() << "Item" << i << "not found";
1536         QTRY_VERIFY(item);
1537         QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1538         QTRY_COMPARE(item->y(), qreal((i%5)*60));
1539     }
1540
1541     // Position at End
1542     gridview->positionViewAtIndex(30, QDeclarativeGridView::End);
1543     QTRY_COMPARE(gridview->contentX(), -560.);
1544
1545     // Position in Center
1546     gridview->positionViewAtIndex(15, QDeclarativeGridView::Center);
1547     QTRY_COMPARE(gridview->contentX(), -400.);
1548
1549     // Ensure at least partially visible
1550     gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible);
1551     QTRY_COMPARE(gridview->contentX(), -400.);
1552
1553     gridview->setContentX(-555.);
1554     gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible);
1555     QTRY_COMPARE(gridview->contentX(), -555.);
1556
1557     gridview->setContentX(-239);
1558     gridview->positionViewAtIndex(15, QDeclarativeGridView::Visible);
1559     QTRY_COMPARE(gridview->contentX(), -320.);
1560
1561     gridview->setContentX(-239);
1562     gridview->positionViewAtIndex(20, QDeclarativeGridView::Visible);
1563     QTRY_COMPARE(gridview->contentX(), -400.);
1564
1565     gridview->setContentX(-640);
1566     gridview->positionViewAtIndex(20, QDeclarativeGridView::Visible);
1567     QTRY_COMPARE(gridview->contentX(), -560.);
1568
1569     // Ensure completely visible
1570     gridview->setContentX(-400);
1571     gridview->positionViewAtIndex(20, QDeclarativeGridView::Contain);
1572     QTRY_COMPARE(gridview->contentX(), -400.);
1573
1574     gridview->setContentX(-315);
1575     gridview->positionViewAtIndex(15, QDeclarativeGridView::Contain);
1576     QTRY_COMPARE(gridview->contentX(), -320.);
1577
1578     gridview->setContentX(-640);
1579     gridview->positionViewAtIndex(20, QDeclarativeGridView::Contain);
1580     QTRY_COMPARE(gridview->contentX(), -560.);
1581
1582     delete canvas;
1583 }
1584
1585 void tst_QDeclarativeGridView::resetModel()
1586 {
1587     QDeclarativeView *canvas = createView();
1588
1589     QStringList strings;
1590     strings << "one" << "two" << "three";
1591     QStringListModel model(strings);
1592
1593     QDeclarativeContext *ctxt = canvas->rootContext();
1594     ctxt->setContextProperty("testModel", &model);
1595
1596     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaygrid.qml"));
1597     qApp->processEvents();
1598
1599     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1600     QTRY_VERIFY(gridview != 0);
1601
1602     QDeclarativeItem *contentItem = gridview->contentItem();
1603     QTRY_VERIFY(contentItem != 0);
1604
1605     QTRY_COMPARE(gridview->count(), model.rowCount());
1606
1607     for (int i = 0; i < model.rowCount(); ++i) {
1608         QDeclarativeText *display = findItem<QDeclarativeText>(contentItem, "displayText", i);
1609         QTRY_VERIFY(display != 0);
1610         QTRY_COMPARE(display->text(), strings.at(i));
1611     }
1612
1613     strings.clear();
1614     strings << "four" << "five" << "six" << "seven";
1615     model.setStringList(strings);
1616
1617     QTRY_COMPARE(gridview->count(), model.rowCount());
1618
1619     for (int i = 0; i < model.rowCount(); ++i) {
1620         QDeclarativeText *display = findItem<QDeclarativeText>(contentItem, "displayText", i);
1621         QTRY_VERIFY(display != 0);
1622         QTRY_COMPARE(display->text(), strings.at(i));
1623     }
1624 }
1625
1626 void tst_QDeclarativeGridView::enforceRange()
1627 {
1628     QDeclarativeView *canvas = createView();
1629
1630     TestModel model;
1631     for (int i = 0; i < 30; i++)
1632         model.addItem("Item" + QString::number(i), "");
1633
1634     QDeclarativeContext *ctxt = canvas->rootContext();
1635     ctxt->setContextProperty("testModel", &model);
1636     ctxt->setContextProperty("testRightToLeft", QVariant(false));
1637     ctxt->setContextProperty("testTopToBottom", QVariant(false));
1638
1639     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview-enforcerange.qml"));
1640     qApp->processEvents();
1641     QVERIFY(canvas->rootObject() != 0);
1642
1643     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1644     QTRY_VERIFY(gridview != 0);
1645
1646     QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
1647     QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
1648     QTRY_COMPARE(gridview->highlightRangeMode(), QDeclarativeGridView::StrictlyEnforceRange);
1649
1650     QDeclarativeItem *contentItem = gridview->contentItem();
1651     QTRY_VERIFY(contentItem != 0);
1652
1653     // view should be positioned at the top of the range.
1654     QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 0);
1655     QTRY_VERIFY(item);
1656     QTRY_COMPARE(gridview->contentY(), -100.0);
1657
1658     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 0);
1659     QTRY_VERIFY(name != 0);
1660     QTRY_COMPARE(name->text(), model.name(0));
1661     QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
1662     QTRY_VERIFY(number != 0);
1663     QTRY_COMPARE(number->text(), model.number(0));
1664
1665     // Check currentIndex is updated when contentItem moves
1666     gridview->setContentY(0);
1667     QTRY_COMPARE(gridview->currentIndex(), 2);
1668
1669     gridview->setCurrentIndex(5);
1670     QTRY_COMPARE(gridview->contentY(), 100.);
1671
1672     TestModel model2;
1673     for (int i = 0; i < 5; i++)
1674         model2.addItem("Item" + QString::number(i), "");
1675
1676     ctxt->setContextProperty("testModel", &model2);
1677     QCOMPARE(gridview->count(), 5);
1678
1679     delete canvas;
1680 }
1681
1682 void tst_QDeclarativeGridView::enforceRange_rightToLeft()
1683 {
1684     QDeclarativeView *canvas = createView();
1685
1686     TestModel model;
1687     for (int i = 0; i < 30; i++)
1688         model.addItem("Item" + QString::number(i), "");
1689
1690     QDeclarativeContext *ctxt = canvas->rootContext();
1691     ctxt->setContextProperty("testModel", &model);
1692     ctxt->setContextProperty("testRightToLeft", QVariant(true));
1693     ctxt->setContextProperty("testTopToBottom", QVariant(true));
1694
1695     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview-enforcerange.qml"));
1696     qApp->processEvents();
1697     QVERIFY(canvas->rootObject() != 0);
1698
1699     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1700     QTRY_VERIFY(gridview != 0);
1701
1702     QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
1703     QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
1704     QTRY_COMPARE(gridview->highlightRangeMode(), QDeclarativeGridView::StrictlyEnforceRange);
1705
1706     QDeclarativeItem *contentItem = gridview->contentItem();
1707     QTRY_VERIFY(contentItem != 0);
1708
1709     // view should be positioned at the top of the range.
1710     QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 0);
1711     QTRY_VERIFY(item);
1712     QTRY_COMPARE(gridview->contentX(), -100.);
1713     QTRY_COMPARE(gridview->contentY(), 0.0);
1714
1715     QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 0);
1716     QTRY_VERIFY(name != 0);
1717     QTRY_COMPARE(name->text(), model.name(0));
1718     QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
1719     QTRY_VERIFY(number != 0);
1720     QTRY_COMPARE(number->text(), model.number(0));
1721
1722     // Check currentIndex is updated when contentItem moves
1723     gridview->setContentX(-200);
1724     QTRY_COMPARE(gridview->currentIndex(), 3);
1725
1726     gridview->setCurrentIndex(7);
1727     QTRY_COMPARE(gridview->contentX(), -300.);
1728     QTRY_COMPARE(gridview->contentY(), 0.0);
1729
1730     TestModel model2;
1731     for (int i = 0; i < 5; i++)
1732         model2.addItem("Item" + QString::number(i), "");
1733
1734     ctxt->setContextProperty("testModel", &model2);
1735     QCOMPARE(gridview->count(), 5);
1736
1737     delete canvas;
1738 }
1739
1740 void tst_QDeclarativeGridView::QTBUG_8456()
1741 {
1742     QDeclarativeView *canvas = createView();
1743
1744     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/setindex.qml"));
1745     qApp->processEvents();
1746
1747     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1748     QTRY_VERIFY(gridview != 0);
1749
1750     QTRY_COMPARE(gridview->currentIndex(), 0);
1751 }
1752
1753 void tst_QDeclarativeGridView::manualHighlight()
1754 {
1755     QDeclarativeView *canvas = createView();
1756
1757     QString filename(SRCDIR "/data/manual-highlight.qml");
1758     canvas->setSource(QUrl::fromLocalFile(filename));
1759
1760     qApp->processEvents();
1761
1762     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1763     QTRY_VERIFY(gridview != 0);
1764
1765     QDeclarativeItem *contentItem = gridview->contentItem();
1766     QTRY_VERIFY(contentItem != 0);
1767
1768     QTRY_COMPARE(gridview->currentIndex(), 0);
1769     QTRY_COMPARE(gridview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 0));
1770     QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
1771     QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
1772
1773     gridview->setCurrentIndex(2);
1774
1775     QTRY_COMPARE(gridview->currentIndex(), 2);
1776     QTRY_COMPARE(gridview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 2));
1777     QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
1778     QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
1779
1780     gridview->positionViewAtIndex(8, QDeclarativeGridView::Contain);
1781
1782     QTRY_COMPARE(gridview->currentIndex(), 2);
1783     QTRY_COMPARE(gridview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 2));
1784     QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
1785     QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
1786
1787     gridview->setFlow(QDeclarativeGridView::TopToBottom);
1788     QTRY_COMPARE(gridview->flow(), QDeclarativeGridView::TopToBottom);
1789
1790     gridview->setCurrentIndex(0);
1791     QTRY_COMPARE(gridview->currentIndex(), 0);
1792     QTRY_COMPARE(gridview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 0));
1793     QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
1794     QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
1795 }
1796
1797 void tst_QDeclarativeGridView::footer()
1798 {
1799     QDeclarativeView *canvas = createView();
1800
1801     TestModel model;
1802     for (int i = 0; i < 7; i++)
1803         model.addItem("Item" + QString::number(i), "");
1804
1805     QDeclarativeContext *ctxt = canvas->rootContext();
1806     ctxt->setContextProperty("testModel", &model);
1807
1808     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/footer.qml"));
1809     qApp->processEvents();
1810
1811     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1812     QTRY_VERIFY(gridview != 0);
1813
1814     QDeclarativeItem *contentItem = gridview->contentItem();
1815     QTRY_VERIFY(contentItem != 0);
1816
1817     QDeclarativeText *footer = findItem<QDeclarativeText>(contentItem, "footer");
1818     QVERIFY(footer);
1819
1820     QCOMPARE(footer->y(), 180.0);
1821     QCOMPARE(footer->height(), 30.0);
1822
1823     model.removeItem(2);
1824     QTRY_COMPARE(footer->y(), 120.0);
1825
1826     model.clear();
1827     QTRY_COMPARE(footer->y(), 0.0);
1828
1829     for (int i = 0; i < 30; i++)
1830         model.addItem("Item" + QString::number(i), "");
1831
1832     QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
1833
1834     footer = findItem<QDeclarativeText>(contentItem, "footer");
1835     QVERIFY(!footer);
1836     footer = findItem<QDeclarativeText>(contentItem, "footer2");
1837     QVERIFY(footer);
1838
1839     QCOMPARE(footer->y(), 600.0);
1840     QCOMPARE(footer->height(), 20.0);
1841     QCOMPARE(gridview->contentY(), 0.0);
1842 }
1843
1844 void tst_QDeclarativeGridView::header()
1845 {
1846     QDeclarativeView *canvas = createView();
1847
1848     TestModel model;
1849     for (int i = 0; i < 30; i++)
1850         model.addItem("Item" + QString::number(i), "");
1851
1852     QDeclarativeContext *ctxt = canvas->rootContext();
1853     ctxt->setContextProperty("testModel", &model);
1854
1855     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header.qml"));
1856     qApp->processEvents();
1857
1858     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1859     QTRY_VERIFY(gridview != 0);
1860
1861     QDeclarativeItem *contentItem = gridview->contentItem();
1862     QTRY_VERIFY(contentItem != 0);
1863
1864     QDeclarativeText *header = findItem<QDeclarativeText>(contentItem, "header");
1865     QVERIFY(header);
1866
1867     QCOMPARE(header->y(), 0.0);
1868     QCOMPARE(header->height(), 30.0);
1869     QCOMPARE(gridview->contentY(), 0.0);
1870
1871     QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 0);
1872     QVERIFY(item);
1873     QCOMPARE(item->y(), 30.0);
1874
1875     model.clear();
1876     QTRY_COMPARE(header->y(), 0.0);
1877
1878     for (int i = 0; i < 30; i++)
1879         model.addItem("Item" + QString::number(i), "");
1880
1881     QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
1882
1883     header = findItem<QDeclarativeText>(contentItem, "header");
1884     QVERIFY(!header);
1885     header = findItem<QDeclarativeText>(contentItem, "header2");
1886     QVERIFY(header);
1887
1888     QCOMPARE(header->y(), 10.0);
1889     QCOMPARE(header->height(), 20.0);
1890     QCOMPARE(gridview->contentY(), 10.0);
1891 }
1892
1893 void tst_QDeclarativeGridView::indexAt()
1894 {
1895     QDeclarativeView *canvas = createView();
1896
1897     TestModel model;
1898     model.addItem("Fred", "12345");
1899     model.addItem("John", "2345");
1900     model.addItem("Bob", "54321");
1901     model.addItem("Billy", "22345");
1902     model.addItem("Sam", "2945");
1903     model.addItem("Ben", "04321");
1904     model.addItem("Jim", "0780");
1905
1906     QDeclarativeContext *ctxt = canvas->rootContext();
1907     ctxt->setContextProperty("testModel", &model);
1908     ctxt->setContextProperty("testRightToLeft", QVariant(false));
1909     ctxt->setContextProperty("testTopToBottom", QVariant(false));
1910
1911     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
1912     qApp->processEvents();
1913
1914     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
1915     QTRY_VERIFY(gridview != 0);
1916
1917     QDeclarativeItem *contentItem = gridview->contentItem();
1918     QTRY_VERIFY(contentItem != 0);
1919
1920     QTRY_COMPARE(gridview->count(), model.count());
1921
1922     QCOMPARE(gridview->indexAt(0, 0), 0);
1923     QCOMPARE(gridview->indexAt(79, 59), 0);
1924     QCOMPARE(gridview->indexAt(80, 0), 1);
1925     QCOMPARE(gridview->indexAt(0, 60), 3);
1926     QCOMPARE(gridview->indexAt(240, 0), -1);
1927
1928     delete canvas;
1929 }
1930
1931 void tst_QDeclarativeGridView::onAdd()
1932 {
1933     QFETCH(int, initialItemCount);
1934     QFETCH(int, itemsToAdd);
1935
1936     const int delegateWidth = 50;
1937     const int delegateHeight = 100;
1938     TestModel model;
1939     QDeclarativeView *canvas = createView();
1940     canvas->setFixedSize(5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit
1941
1942     // these initial items should not trigger GridView.onAdd
1943     for (int i=0; i<initialItemCount; i++)
1944         model.addItem("dummy value", "dummy value");
1945
1946     QDeclarativeContext *ctxt = canvas->rootContext();
1947     ctxt->setContextProperty("testModel", &model);
1948     ctxt->setContextProperty("delegateWidth", delegateWidth);
1949     ctxt->setContextProperty("delegateHeight", delegateHeight);
1950     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
1951
1952     QObject *object = canvas->rootObject();
1953     object->setProperty("width", canvas->width());
1954     object->setProperty("height", canvas->height());
1955     qApp->processEvents();
1956
1957     QList<QPair<QString, QString> > items;
1958     for (int i=0; i<itemsToAdd; i++)
1959         items << qMakePair(QString("value %1").arg(i), QString::number(i));
1960     model.addItems(items);
1961
1962     qApp->processEvents();
1963
1964     QVariantList result = object->property("addedDelegates").toList();
1965     QCOMPARE(result.count(), items.count());
1966     for (int i=0; i<items.count(); i++)
1967         QCOMPARE(result[i].toString(), items[i].first);
1968
1969     delete canvas;
1970 }
1971
1972 void tst_QDeclarativeGridView::onAdd_data()
1973 {
1974     QTest::addColumn<int>("initialItemCount");
1975     QTest::addColumn<int>("itemsToAdd");
1976
1977     QTest::newRow("0, add 1") << 0 << 1;
1978     QTest::newRow("0, add 2") << 0 << 2;
1979     QTest::newRow("0, add 10") << 0 << 10;
1980
1981     QTest::newRow("1, add 1") << 1 << 1;
1982     QTest::newRow("1, add 2") << 1 << 2;
1983     QTest::newRow("1, add 10") << 1 << 10;
1984
1985     QTest::newRow("5, add 1") << 5 << 1;
1986     QTest::newRow("5, add 2") << 5 << 2;
1987     QTest::newRow("5, add 10") << 5 << 10;
1988 }
1989
1990 void tst_QDeclarativeGridView::onRemove()
1991 {
1992     QFETCH(int, initialItemCount);
1993     QFETCH(int, indexToRemove);
1994     QFETCH(int, removeCount);
1995
1996     const int delegateWidth = 50;
1997     const int delegateHeight = 100;
1998     TestModel model;
1999     for (int i=0; i<initialItemCount; i++)
2000         model.addItem(QString("value %1").arg(i), "dummy value");
2001
2002     QDeclarativeView *canvas = createView();
2003     QDeclarativeContext *ctxt = canvas->rootContext();
2004     ctxt->setContextProperty("testModel", &model);
2005     ctxt->setContextProperty("delegateWidth", delegateWidth);
2006     ctxt->setContextProperty("delegateHeight", delegateHeight);
2007     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
2008     QObject *object = canvas->rootObject();
2009
2010     qApp->processEvents();
2011
2012     model.removeItems(indexToRemove, removeCount);
2013     qApp->processEvents();
2014     QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
2015
2016     delete canvas;
2017 }
2018
2019 void tst_QDeclarativeGridView::onRemove_data()
2020 {
2021     QTest::addColumn<int>("initialItemCount");
2022     QTest::addColumn<int>("indexToRemove");
2023     QTest::addColumn<int>("removeCount");
2024
2025     QTest::newRow("remove first") << 1 << 0 << 1;
2026     QTest::newRow("two items, remove first") << 2 << 0 << 1;
2027     QTest::newRow("two items, remove last") << 2 << 1 << 1;
2028     QTest::newRow("two items, remove all") << 2 << 0 << 2;
2029
2030     QTest::newRow("four items, remove first") << 4 << 0 << 1;
2031     QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
2032     QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
2033     QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
2034     QTest::newRow("four items, remove last") << 4 << 3 << 1;
2035     QTest::newRow("four items, remove all") << 4 << 0 << 4;
2036
2037     QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
2038     QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
2039     QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
2040 }
2041
2042 void tst_QDeclarativeGridView::testQtQuick11Attributes()
2043 {
2044     QFETCH(QString, code);
2045     QFETCH(QString, warning);
2046     QFETCH(QString, error);
2047
2048     QDeclarativeEngine engine;
2049     QObject *obj;
2050
2051     QDeclarativeComponent valid(&engine);
2052     valid.setData("import QtQuick 1.1; GridView { " + code.toUtf8() + " }", QUrl(""));
2053     obj = valid.create();
2054     QVERIFY(obj);
2055     QVERIFY(valid.errorString().isEmpty());
2056     delete obj;
2057
2058     QDeclarativeComponent invalid(&engine);
2059     invalid.setData("import QtQuick 1.0; GridView { " + code.toUtf8() + " }", QUrl(""));
2060     QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2061     obj = invalid.create();
2062     QCOMPARE(invalid.errorString(), error);
2063     delete obj;
2064 }
2065
2066 void tst_QDeclarativeGridView::testQtQuick11Attributes_data()
2067 {
2068     QTest::addColumn<QString>("code");
2069     QTest::addColumn<QString>("warning");
2070     QTest::addColumn<QString>("error");
2071
2072     QTest::newRow("positionViewAtBeginning") << "Component.onCompleted: positionViewAtBeginning()"
2073         << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtBeginning"
2074         << "";
2075
2076     QTest::newRow("positionViewAtEnd") << "Component.onCompleted: positionViewAtEnd()"
2077         << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtEnd"
2078         << "";
2079 }
2080
2081 void tst_QDeclarativeGridView::contentPosJump()
2082 {
2083     QDeclarativeView *canvas = createView();
2084
2085     TestModel model;
2086     for (int i = 0; i < 100; i++)
2087         model.addItem("Item" + QString::number(i), "");
2088
2089     QDeclarativeContext *ctxt = canvas->rootContext();
2090     ctxt->setContextProperty("testModel", &model);
2091     ctxt->setContextProperty("testRightToLeft", QVariant(false));
2092     ctxt->setContextProperty("testTopToBottom", QVariant(false));
2093
2094     canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
2095     qApp->processEvents();
2096
2097     QDeclarativeGridView *gridview = findItem<QDeclarativeGridView>(canvas->rootObject(), "grid");
2098     QVERIFY(gridview != 0);
2099
2100     QDeclarativeItem *contentItem = gridview->contentItem();
2101     QVERIFY(contentItem != 0);
2102
2103     // Test jumping more than a page of items.
2104     gridview->setContentY(500);
2105
2106     // Confirm items positioned correctly
2107     int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2108     for (int i = 24; i < model.count() && i < itemCount; ++i) {
2109         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2110         if (!item) qWarning() << "Item" << i << "not found";
2111         QVERIFY(item);
2112         QVERIFY(item->x() == (i%3)*80);
2113         QVERIFY(item->y() == (i/3)*60);
2114     }
2115
2116     gridview->setContentY(-100);
2117     itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2118     QVERIFY(itemCount < 15);
2119     // Confirm items positioned correctly
2120     for (int i = 0; i < model.count() && i < itemCount; ++i) {
2121         QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2122         if (!item) qWarning() << "Item" << i << "not found";
2123         QVERIFY(item);
2124         QVERIFY(item->x() == (i%3)*80);
2125         QVERIFY(item->y() == (i/3)*60);
2126     }
2127
2128     delete canvas;
2129 }
2130
2131 QDeclarativeView *tst_QDeclarativeGridView::createView()
2132 {
2133     QDeclarativeView *canvas = new QDeclarativeView(0);
2134     canvas->setFixedSize(240,320);
2135
2136     return canvas;
2137 }
2138
2139 /*
2140    Find an item with the specified objectName.  If index is supplied then the
2141    item must also evaluate the {index} expression equal to index
2142 */
2143 template<typename T>
2144 T *tst_QDeclarativeGridView::findItem(QGraphicsObject *parent, const QString &objectName, int index)
2145 {
2146     const QMetaObject &mo = T::staticMetaObject;
2147     //qDebug() << parent->childItems().count() << "children";
2148     for (int i = 0; i < parent->childItems().count(); ++i) {
2149         QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
2150         if(!item)
2151             continue;
2152         //qDebug() << "try" << item;
2153         if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
2154             if (index != -1) {
2155                 QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
2156                 if (context) {
2157                     if (context->contextProperty("index").toInt() == index) {
2158                         return static_cast<T*>(item);
2159                     }
2160                 }
2161             } else {
2162                 return static_cast<T*>(item);
2163             }
2164         }
2165         item = findItem<T>(item, objectName, index);
2166         if (item)
2167             return static_cast<T*>(item);
2168     }
2169
2170     return 0;
2171 }
2172
2173 template<typename T>
2174 QList<T*> tst_QDeclarativeGridView::findItems(QGraphicsObject *parent, const QString &objectName)
2175 {
2176     QList<T*> items;
2177     const QMetaObject &mo = T::staticMetaObject;
2178     //qDebug() << parent->childItems().count() << "children";
2179     for (int i = 0; i < parent->childItems().count(); ++i) {
2180         QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
2181         if(!item)
2182             continue;
2183         //qDebug() << "try" << item;
2184         if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
2185             items.append(static_cast<T*>(item));
2186             //qDebug() << " found:" << item;
2187         }
2188         items += findItems<T>(item, objectName);
2189     }
2190
2191     return items;
2192 }
2193
2194 void tst_QDeclarativeGridView::dumpTree(QDeclarativeItem *parent, int depth)
2195 {
2196     static QString padding("                       ");
2197     for (int i = 0; i < parent->childItems().count(); ++i) {
2198         QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
2199         if(!item)
2200             continue;
2201         QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
2202         qDebug() << padding.left(depth*2) << item << (context ? context->contextProperty("index").toInt() : -1);
2203         dumpTree(item, depth+1);
2204     }
2205 }
2206
2207
2208 QTEST_MAIN(tst_QDeclarativeGridView)
2209
2210 #include "tst_qdeclarativegridview.moc"