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