1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
43 #include <QtCore/qstringlistmodel.h>
44 #include <QtQuick/qquickview.h>
45 #include <QtDeclarative/qdeclarativeengine.h>
46 #include <QtDeclarative/qdeclarativecomponent.h>
47 #include <QtDeclarative/qdeclarativecontext.h>
48 #include <QtDeclarative/qdeclarativeexpression.h>
49 #include <QtDeclarative/qdeclarativeincubator.h>
50 #include <QtQuick/private/qquickitem_p.h>
51 #include <QtDeclarative/private/qlistmodelinterface_p.h>
52 #include <QtQuick/private/qquickgridview_p.h>
53 #include <QtQuick/private/qquicktext_p.h>
54 #include <QtDeclarative/private/qdeclarativelistmodel_p.h>
55 #include "../../shared/util.h"
56 #include <QtGui/qguiapplication.h>
58 Q_DECLARE_METATYPE(Qt::LayoutDirection)
59 Q_DECLARE_METATYPE(QQuickGridView::Flow)
61 class tst_QQuickGridView : public QDeclarativeDataTest
72 void inserted_more_data();
73 void insertBeforeVisible();
74 void insertBeforeVisible_data();
76 void addOrRemoveBeforeVisible();
77 void addOrRemoveBeforeVisible_data();
81 void multipleChanges();
82 void multipleChanges_data();
83 void swapWithFirstItem();
86 void noCurrentIndex();
89 void propertyChanges();
90 void componentChanges();
92 void positionViewAtIndex();
93 void positionViewAtIndex_rightToLeft();
98 void enforceRange_rightToLeft();
100 void manualHighlight();
105 void resizeViewAndRepaint();
110 void onRemove_data();
113 void creationContext();
114 void snapToRow_data();
116 void snapOneRow_data();
121 void unrequestedVisibility();
124 QQuickView *createView();
125 void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
127 T *findItem(QQuickItem *parent, const QString &id, int index=-1);
129 QList<T*> findItems(QQuickItem *parent, const QString &objectName);
130 void dumpTree(QQuickItem *parent, int depth = 0);
134 void tst_qquickgridview_move(int from, int to, int n, T *items)
137 // Only move forwards - flip if backwards moving
147 typename T::ConstIterator it=items->begin(); it += from+n;
148 for (; i<to-from; ++i,++it)
149 replaced.append(*it);
151 it=items->begin(); it += from;
152 for (; i<n; ++i,++it)
153 replaced.append(*it);
154 typename T::ConstIterator f=replaced.begin();
155 typename T::Iterator t=items->begin(); t += from;
156 for (; f != replaced.end(); ++f, ++t)
160 class TestModel : public QAbstractListModel
163 enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
165 TestModel(QObject *parent=0) : QAbstractListModel(parent) {
166 QHash<int, QByteArray> roles;
167 roles[Name] = "name";
168 roles[Number] = "number";
172 int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
173 QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
176 rv = list.at(index.row()).first;
177 else if (role == Number)
178 rv = list.at(index.row()).second;
183 int count() const { return rowCount(); }
184 QString name(int index) const { return list.at(index).first; }
185 QString number(int index) const { return list.at(index).second; }
187 void addItem(const QString &name, const QString &number) {
188 emit beginInsertRows(QModelIndex(), list.count(), list.count());
189 list.append(QPair<QString,QString>(name, number));
190 emit endInsertRows();
193 void addItems(const QList<QPair<QString, QString> > &items) {
194 emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1);
195 for (int i=0; i<items.count(); i++)
196 list.append(QPair<QString,QString>(items[i].first, items[i].second));
197 emit endInsertRows();
200 void insertItem(int index, const QString &name, const QString &number) {
201 emit beginInsertRows(QModelIndex(), index, index);
202 list.insert(index, QPair<QString,QString>(name, number));
203 emit endInsertRows();
206 void insertItems(int index, const QList<QPair<QString, QString> > &items) {
207 emit beginInsertRows(QModelIndex(), index, index + items.count() - 1);
208 for (int i=0; i<items.count(); i++)
209 list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
210 emit endInsertRows();
213 void removeItem(int index) {
214 emit beginRemoveRows(QModelIndex(), index, index);
215 list.removeAt(index);
216 emit endRemoveRows();
219 void removeItems(int index, int count) {
220 emit beginRemoveRows(QModelIndex(), index, index+count-1);
222 list.removeAt(index);
223 emit endRemoveRows();
226 void moveItem(int from, int to) {
227 emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
232 void moveItems(int from, int to, int count) {
233 emit beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
234 tst_qquickgridview_move(from, to, count, &list);
238 void modifyItem(int idx, const QString &name, const QString &number) {
239 list[idx] = QPair<QString,QString>(name, number);
240 emit dataChanged(index(idx,0), index(idx,0));
244 int count = list.count();
245 emit beginRemoveRows(QModelIndex(), 0, count-1);
247 emit endRemoveRows();
252 QList<QPair<QString,QString> > list;
255 tst_QQuickGridView::tst_QQuickGridView()
259 void tst_QQuickGridView::items()
261 QQuickView *canvas = createView();
264 model.addItem("Fred", "12345");
265 model.addItem("John", "2345");
266 model.addItem("Bob", "54321");
267 model.addItem("Billy", "22345");
268 model.addItem("Sam", "2945");
269 model.addItem("Ben", "04321");
270 model.addItem("Jim", "0780");
272 QDeclarativeContext *ctxt = canvas->rootContext();
273 ctxt->setContextProperty("testModel", &model);
274 ctxt->setContextProperty("testRightToLeft", QVariant(false));
275 ctxt->setContextProperty("testTopToBottom", QVariant(false));
277 canvas->setSource(testFileUrl("gridview1.qml"));
278 qApp->processEvents();
280 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
281 QTRY_VERIFY(gridview != 0);
283 QQuickItem *contentItem = gridview->contentItem();
284 QTRY_VERIFY(contentItem != 0);
286 QTRY_COMPARE(gridview->count(), model.count());
287 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
288 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
290 for (int i = 0; i < model.count(); ++i) {
291 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
292 QTRY_VERIFY(name != 0);
293 QTRY_COMPARE(name->text(), model.name(i));
294 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
295 QTRY_VERIFY(number != 0);
296 QTRY_COMPARE(number->text(), model.number(i));
299 // set an empty model and confirm that items are destroyed
301 ctxt->setContextProperty("testModel", &model2);
303 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
304 QTRY_VERIFY(itemCount == 0);
309 void tst_QQuickGridView::changed()
311 QQuickView *canvas = createView();
314 model.addItem("Fred", "12345");
315 model.addItem("John", "2345");
316 model.addItem("Bob", "54321");
317 model.addItem("Billy", "22345");
318 model.addItem("Sam", "2945");
319 model.addItem("Ben", "04321");
320 model.addItem("Jim", "0780");
322 QDeclarativeContext *ctxt = canvas->rootContext();
323 ctxt->setContextProperty("testModel", &model);
324 ctxt->setContextProperty("testRightToLeft", QVariant(false));
325 ctxt->setContextProperty("testTopToBottom", QVariant(false));
327 canvas->setSource(testFileUrl("gridview1.qml"));
328 qApp->processEvents();
330 QQuickFlickable *gridview = findItem<QQuickFlickable>(canvas->rootObject(), "grid");
331 QTRY_VERIFY(gridview != 0);
333 QQuickItem *contentItem = gridview->contentItem();
334 QTRY_VERIFY(contentItem != 0);
336 model.modifyItem(1, "Will", "9876");
337 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
338 QTRY_VERIFY(name != 0);
339 QTRY_COMPARE(name->text(), model.name(1));
340 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
341 QTRY_VERIFY(number != 0);
342 QTRY_COMPARE(number->text(), model.number(1));
347 void tst_QQuickGridView::inserted()
349 QQuickView *canvas = createView();
353 model.addItem("Fred", "12345");
354 model.addItem("John", "2345");
355 model.addItem("Bob", "54321");
357 QDeclarativeContext *ctxt = canvas->rootContext();
358 ctxt->setContextProperty("testModel", &model);
359 ctxt->setContextProperty("testRightToLeft", QVariant(false));
360 ctxt->setContextProperty("testTopToBottom", QVariant(false));
362 canvas->setSource(testFileUrl("gridview1.qml"));
363 qApp->processEvents();
365 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
366 QTRY_VERIFY(gridview != 0);
368 QQuickItem *contentItem = gridview->contentItem();
369 QTRY_VERIFY(contentItem != 0);
371 model.insertItem(1, "Will", "9876");
373 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
374 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
376 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
377 QTRY_VERIFY(name != 0);
378 QTRY_COMPARE(name->text(), model.name(1));
379 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
380 QTRY_VERIFY(number != 0);
381 QTRY_COMPARE(number->text(), model.number(1));
383 // Checks that onAdd is called
384 int added = canvas->rootObject()->property("added").toInt();
385 QTRY_COMPARE(added, 1);
387 // Confirm items positioned correctly
388 for (int i = 0; i < model.count(); ++i) {
389 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
390 QTRY_COMPARE(item->x(), (i%3)*80.0);
391 QTRY_COMPARE(item->y(), (i/3)*60.0);
394 model.insertItem(0, "Foo", "1111"); // zero index, and current item
396 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
398 name = findItem<QQuickText>(contentItem, "textName", 0);
399 QTRY_VERIFY(name != 0);
400 QTRY_COMPARE(name->text(), model.name(0));
401 number = findItem<QQuickText>(contentItem, "textNumber", 0);
402 QTRY_VERIFY(number != 0);
403 QTRY_COMPARE(number->text(), model.number(0));
405 QTRY_COMPARE(gridview->currentIndex(), 1);
407 // Confirm items positioned correctly
408 for (int i = 0; i < model.count(); ++i) {
409 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
410 QTRY_VERIFY(item->x() == (i%3)*80);
411 QTRY_VERIFY(item->y() == (i/3)*60);
414 for (int i = model.count(); i < 30; ++i)
415 model.insertItem(i, "Hello", QString::number(i));
417 gridview->setContentY(120);
419 // Insert item outside visible area
420 model.insertItem(1, "Hello", "1324");
422 QTRY_VERIFY(gridview->contentY() == 120);
427 void tst_QQuickGridView::inserted_more()
429 QFETCH(qreal, contentY);
430 QFETCH(int, insertIndex);
431 QFETCH(int, insertCount);
432 QFETCH(qreal, itemsOffsetAfterMove);
436 QQuickView *canvas = createView();
440 for (int i = 0; i < 30; i++)
441 model.addItem("Item" + QString::number(i), "");
443 QDeclarativeContext *ctxt = canvas->rootContext();
444 ctxt->setContextProperty("testModel", &model);
445 ctxt->setContextProperty("testRightToLeft", QVariant(false));
446 ctxt->setContextProperty("testTopToBottom", QVariant(false));
448 canvas->setSource(testFileUrl("gridview1.qml"));
449 qApp->processEvents();
451 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
452 QTRY_VERIFY(gridview != 0);
453 QQuickItem *contentItem = gridview->contentItem();
454 QTRY_VERIFY(contentItem != 0);
456 gridview->setContentY(contentY);
458 QList<QPair<QString, QString> > newData;
459 for (int i=0; i<insertCount; i++)
460 newData << qMakePair(QString("value %1").arg(i), QString::number(i));
461 model.insertItems(insertIndex, newData);
462 QTRY_COMPARE(gridview->property("count").toInt(), model.count());
464 // check visibleItems.first() is in correct position
465 QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
467 QCOMPARE(item0->y(), itemsOffsetAfterMove);
469 QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
470 int firstVisibleIndex = -1;
471 for (int i=0; i<items.count(); i++) {
472 if (items[i]->y() >= contentY) {
473 QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
474 firstVisibleIndex = e.evaluate().toInt();
478 QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
480 // Confirm items positioned correctly and indexes correct
481 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
482 for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
483 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
484 QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
486 QCOMPARE(item->x(), (i%3)*80.0);
487 QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
489 name = findItem<QQuickText>(contentItem, "textName", i);
491 QCOMPARE(name->text(), model.name(i));
492 number = findItem<QQuickText>(contentItem, "textNumber", i);
493 QVERIFY(number != 0);
494 QCOMPARE(number->text(), model.number(i));
500 void tst_QQuickGridView::inserted_more_data()
502 QTest::addColumn<qreal>("contentY");
503 QTest::addColumn<int>("insertIndex");
504 QTest::addColumn<int>("insertCount");
505 QTest::addColumn<qreal>("itemsOffsetAfterMove");
507 QTest::newRow("add 1, before visible items")
508 << 120.0 // show 6-23
510 << 0.0; // insert 1 above first visible, grid is rearranged; first visible moves forward within its row
511 // new 1st visible item is at 0
513 QTest::newRow("add 2, before visible items")
514 << 120.0 // show 6-23
516 << 0.0; // insert 2 above first visible, grid is rearranged; first visible moves forward within its row
518 QTest::newRow("add 3, before visible items")
519 << 120.0 // show 6-23
521 << -60.0; // insert 3 (1 row) above first visible in negative pos, first visible does not move
523 QTest::newRow("add 5, before visible items")
524 << 120.0 // show 6-23
526 << -60.0; // insert 1 row + 2 items above first visible, 1 row added at negative pos,
527 // grid is rearranged and first visible moves forward within its row
529 QTest::newRow("add 6, before visible items")
530 << 120.0 // show 6-23
532 << -60.0 * 2; // insert 2 rows above first visible in negative pos, first visible does not move
536 QTest::newRow("add 1, at start of visible, content at start")
541 QTest::newRow("add multiple, at start of visible, content at start")
546 QTest::newRow("add 1, at start of visible, content not at start")
547 << 120.0 // show 6-23
551 QTest::newRow("add multiple, at start of visible, content not at start")
552 << 120.0 // show 6-23
557 QTest::newRow("add 1, at end of visible, content at start")
562 QTest::newRow("add 1, at end of visible, content at start")
567 QTest::newRow("add 1, at end of visible, content not at start")
568 << 120.0 // show 6-23
572 QTest::newRow("add multiple, at end of visible, content not at start")
573 << 120.0 // show 6-23
578 QTest::newRow("add 1, after visible, content at start")
583 QTest::newRow("add 1, after visible, content at start")
588 QTest::newRow("add 1, after visible, content not at start")
589 << 120.0 // show 6-23
593 QTest::newRow("add multiple, after visible, content not at start")
594 << 120.0 // show 6-23
599 void tst_QQuickGridView::insertBeforeVisible()
601 QFETCH(int, insertIndex);
602 QFETCH(int, insertCount);
603 QFETCH(int, cacheBuffer);
606 QQuickView *canvas = createView();
610 for (int i = 0; i < 30; i++)
611 model.addItem("Item" + QString::number(i), "");
613 QDeclarativeContext *ctxt = canvas->rootContext();
614 ctxt->setContextProperty("testModel", &model);
615 ctxt->setContextProperty("testRightToLeft", QVariant(false));
616 ctxt->setContextProperty("testTopToBottom", QVariant(false));
617 canvas->setSource(testFileUrl("gridview1.qml"));
618 qApp->processEvents();
620 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
621 QTRY_VERIFY(gridview != 0);
622 QQuickItem *contentItem = gridview->contentItem();
623 QTRY_VERIFY(contentItem != 0);
625 gridview->setCacheBuffer(cacheBuffer);
627 // trigger a refill (not just setting contentY) so that the visibleItems grid is updated
628 int firstVisibleIndex = 20; // move to an index where the top item is not visible
629 gridview->setContentY(firstVisibleIndex * 20.0);
630 gridview->setCurrentIndex(firstVisibleIndex);
631 qApp->processEvents();
632 QTRY_COMPARE(gridview->currentIndex(), firstVisibleIndex);
633 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
635 QCOMPARE(item->y(), gridview->contentY());
637 QList<QPair<QString, QString> > newData;
638 for (int i=0; i<insertCount; i++)
639 newData << qMakePair(QString("value %1").arg(i), QString::number(i));
640 model.insertItems(insertIndex, newData);
641 QTRY_COMPARE(gridview->property("count").toInt(), model.count());
643 // now, moving to the top of the view should position the inserted items correctly
644 int itemsOffsetAfterMove = (insertCount / 3) * -60.0;
645 gridview->setCurrentIndex(0);
646 QTRY_COMPARE(gridview->currentIndex(), 0);
647 QTRY_COMPARE(gridview->contentY(), 0.0 + itemsOffsetAfterMove);
649 // Confirm items positioned correctly and indexes correct
650 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
651 for (int i = 0; i < model.count() && i < itemCount; ++i) {
652 item = findItem<QQuickItem>(contentItem, "wrapper", i);
653 QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
654 QCOMPARE(item->x(), (i%3)*80.0);
655 QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
656 name = findItem<QQuickText>(contentItem, "textName", i);
658 QTRY_COMPARE(name->text(), model.name(i));
664 void tst_QQuickGridView::insertBeforeVisible_data()
666 QTest::addColumn<int>("insertIndex");
667 QTest::addColumn<int>("insertCount");
668 QTest::addColumn<int>("cacheBuffer");
670 QTest::newRow("insert 1 at 0, 0 buffer") << 0 << 1 << 0;
671 QTest::newRow("insert 1 at 0, 100 buffer") << 0 << 1 << 100;
672 QTest::newRow("insert 1 at 0, 500 buffer") << 0 << 1 << 500;
674 QTest::newRow("insert 1 at 1, 0 buffer") << 1 << 1 << 0;
675 QTest::newRow("insert 1 at 1, 100 buffer") << 1 << 1 << 100;
676 QTest::newRow("insert 1 at 1, 500 buffer") << 1 << 1 << 500;
678 QTest::newRow("insert multiple at 0, 0 buffer") << 0 << 6 << 0;
679 QTest::newRow("insert multiple at 0, 100 buffer") << 0 << 6 << 100;
680 QTest::newRow("insert multiple at 0, 500 buffer") << 0 << 6 << 500;
682 QTest::newRow("insert multiple at 1, 0 buffer") << 1 << 6 << 0;
683 QTest::newRow("insert multiple at 1, 100 buffer") << 1 << 6 << 100;
684 QTest::newRow("insert multiple at 1, 500 buffer") << 1 << 6 << 500;
687 void tst_QQuickGridView::removed()
689 QQuickView *canvas = createView();
693 for (int i = 0; i < 40; i++)
694 model.addItem("Item" + QString::number(i), "");
696 QDeclarativeContext *ctxt = canvas->rootContext();
697 ctxt->setContextProperty("testModel", &model);
698 ctxt->setContextProperty("testRightToLeft", QVariant(false));
699 ctxt->setContextProperty("testTopToBottom", QVariant(false));
701 canvas->setSource(testFileUrl("gridview1.qml"));
702 qApp->processEvents();
704 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
705 QTRY_VERIFY(gridview != 0);
707 QQuickItem *contentItem = gridview->contentItem();
708 QTRY_VERIFY(contentItem != 0);
711 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
713 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
714 QTRY_VERIFY(name != 0);
715 QTRY_COMPARE(name->text(), model.name(1));
716 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
717 QTRY_VERIFY(number != 0);
718 QTRY_COMPARE(number->text(), model.number(1));
721 // Checks that onRemove is called
722 QString removed = canvas->rootObject()->property("removed").toString();
723 QTRY_COMPARE(removed, QString("Item1"));
725 // Confirm items positioned correctly
726 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
727 for (int i = 0; i < model.count() && i < itemCount; ++i) {
728 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
729 if (!item) qWarning() << "Item" << i << "not found";
730 QTRY_VERIFY(item->x() == (i%3)*80);
731 QTRY_VERIFY(item->y() == (i/3)*60);
734 // Remove first item (which is the current item);
736 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
738 name = findItem<QQuickText>(contentItem, "textName", 0);
739 QTRY_VERIFY(name != 0);
740 QTRY_COMPARE(name->text(), model.name(0));
741 number = findItem<QQuickText>(contentItem, "textNumber", 0);
742 QTRY_VERIFY(number != 0);
743 QTRY_COMPARE(number->text(), model.number(0));
746 // Confirm items positioned correctly
747 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
748 for (int i = 0; i < model.count() && i < itemCount; ++i) {
749 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
750 if (!item) qWarning() << "Item" << i << "not found";
751 QTRY_VERIFY(item->x() == (i%3)*80);
752 QTRY_VERIFY(item->y() == (i/3)*60);
755 // Remove items not visible
756 model.removeItem(25);
757 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
759 // Confirm items positioned correctly
760 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
761 for (int i = 0; i < model.count() && i < itemCount; ++i) {
762 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
763 if (!item) qWarning() << "Item" << i << "not found";
764 QTRY_VERIFY(item->x() == (i%3)*80);
765 QTRY_VERIFY(item->y() == (i/3)*60);
768 // Remove items before visible
769 gridview->setContentY(120);
770 gridview->setCurrentIndex(10);
772 // Setting currentIndex above shouldn't cause view to scroll
773 QTRY_COMPARE(gridview->contentY(), 120.0);
776 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
778 // Confirm items positioned correctly
779 for (int i = 6; i < 18; ++i) {
780 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
781 if (!item) qWarning() << "Item" << i << "not found";
782 QTRY_VERIFY(item->x() == (i%3)*80);
783 QTRY_VERIFY(item->y() == (i/3)*60);
786 // Remove currentIndex
787 QQuickItem *oldCurrent = gridview->currentItem();
789 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
791 QTRY_COMPARE(gridview->currentIndex(), 9);
792 QTRY_VERIFY(gridview->currentItem() != oldCurrent);
794 gridview->setContentY(0);
795 // let transitions settle.
798 // Confirm items positioned correctly
799 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
800 for (int i = 0; i < model.count() && i < itemCount; ++i) {
801 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
802 QTRY_VERIFY(item->x() == (i%3)*80);
803 QTRY_VERIFY(item->y() == (i/3)*60);
806 // remove item outside current view.
807 gridview->setCurrentIndex(32);
808 gridview->setContentY(240);
810 model.removeItem(30);
811 QTRY_VERIFY(gridview->currentIndex() == 31);
813 // remove current item beyond visible items.
814 gridview->setCurrentIndex(20);
815 gridview->setContentY(0);
816 model.removeItem(20);
818 QTRY_COMPARE(gridview->currentIndex(), 20);
819 QTRY_VERIFY(gridview->currentItem() != 0);
821 // remove item before current, but visible
822 gridview->setCurrentIndex(8);
823 gridview->setContentY(240);
824 oldCurrent = gridview->currentItem();
827 QTRY_COMPARE(gridview->currentIndex(), 7);
828 QTRY_VERIFY(gridview->currentItem() == oldCurrent);
833 void tst_QQuickGridView::addOrRemoveBeforeVisible()
835 // QTBUG-21588: ensure re-layout is done on grid after adding or removing
836 // items from before the visible area
839 QFETCH(qreal, newTopContentY);
841 QQuickView *canvas = createView();
845 for (int i = 0; i < 30; i++)
846 model.addItem("Item" + QString::number(i), "");
848 QDeclarativeContext *ctxt = canvas->rootContext();
849 ctxt->setContextProperty("testModel", &model);
850 ctxt->setContextProperty("testRightToLeft", QVariant(false));
851 ctxt->setContextProperty("testTopToBottom", QVariant(false));
852 canvas->setSource(testFileUrl("gridview1.qml"));
854 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
855 QTRY_VERIFY(gridview != 0);
856 QQuickItem *contentItem = gridview->contentItem();
857 QTRY_VERIFY(contentItem != 0);
859 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
860 QTRY_COMPARE(name->text(), QString("Item0"));
862 gridview->setCurrentIndex(0);
863 qApp->processEvents();
865 // scroll down until item 0 is no longer drawn
866 // (bug not triggered if we just move using content y, since that doesn't
867 // refill and change the visible items)
868 gridview->setCurrentIndex(24);
869 qApp->processEvents();
871 QTRY_COMPARE(gridview->currentIndex(), 24);
872 QTRY_COMPARE(gridview->contentY(), 220.0);
874 QTest::qWait(100); // wait for refill to complete
875 QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 0)); // 0 shouldn't be visible
878 model.insertItem(0, "New Item", "New Item number");
879 QTRY_COMPARE(gridview->count(), 31);
882 QTRY_COMPARE(gridview->count(), 29);
885 // scroll back up and item 0 should be gone
886 gridview->setCurrentIndex(0);
887 qApp->processEvents();
888 QTRY_COMPARE(gridview->currentIndex(), 0);
889 QTRY_COMPARE(gridview->contentY(), newTopContentY);
891 name = findItem<QQuickText>(contentItem, "textName", 0);
893 QCOMPARE(name->text(), QString("New Item"));
895 QCOMPARE(name->text(), QString("Item1"));
897 // Confirm items positioned correctly
898 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
899 for (int i = 0; i < model.count() && i < itemCount; ++i) {
900 QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", i));
901 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
902 QTRY_VERIFY(item->x() == (i%3)*80);
903 QTRY_VERIFY(item->y() == (i/3)*60 + newTopContentY);
909 void tst_QQuickGridView::addOrRemoveBeforeVisible_data()
911 QTest::addColumn<bool>("doAdd");
912 QTest::addColumn<qreal>("newTopContentY");
914 QTest::newRow("add") << true << -60.0;
915 QTest::newRow("remove") << false << 0.0;
918 void tst_QQuickGridView::clear()
920 QQuickView *canvas = createView();
923 for (int i = 0; i < 30; i++)
924 model.addItem("Item" + QString::number(i), "");
926 QDeclarativeContext *ctxt = canvas->rootContext();
927 ctxt->setContextProperty("testModel", &model);
928 ctxt->setContextProperty("testRightToLeft", QVariant(false));
929 ctxt->setContextProperty("testTopToBottom", QVariant(false));
931 canvas->setSource(testFileUrl("gridview1.qml"));
932 qApp->processEvents();
934 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
935 QVERIFY(gridview != 0);
937 QQuickItem *contentItem = gridview->contentItem();
938 QVERIFY(contentItem != 0);
942 QVERIFY(gridview->count() == 0);
943 QVERIFY(gridview->currentItem() == 0);
944 QVERIFY(gridview->contentY() == 0);
945 QVERIFY(gridview->currentIndex() == -1);
947 // confirm sanity when adding an item to cleared list
948 model.addItem("New", "1");
949 QTRY_COMPARE(gridview->count(), 1);
950 QVERIFY(gridview->currentItem() != 0);
951 QVERIFY(gridview->currentIndex() == 0);
956 void tst_QQuickGridView::moved()
958 QFETCH(qreal, contentY);
962 QFETCH(qreal, itemsOffsetAfterMove);
966 QScopedPointer<QQuickView> canvas(createView());
970 for (int i = 0; i < 30; i++)
971 model.addItem("Item" + QString::number(i), "");
973 QDeclarativeContext *ctxt = canvas->rootContext();
974 ctxt->setContextProperty("testModel", &model);
975 ctxt->setContextProperty("testRightToLeft", QVariant(false));
976 ctxt->setContextProperty("testTopToBottom", QVariant(false));
978 canvas->setSource(testFileUrl("gridview1.qml"));
979 qApp->processEvents();
981 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
982 QTRY_VERIFY(gridview != 0);
984 QQuickItem *contentItem = gridview->contentItem();
985 QTRY_VERIFY(contentItem != 0);
987 QQuickItem *currentItem = gridview->currentItem();
988 QTRY_VERIFY(currentItem != 0);
990 gridview->setContentY(contentY);
991 model.moveItems(from, to, count);
993 // wait for items to move
994 QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
996 // Confirm items positioned correctly and indexes correct
997 int firstVisibleIndex = qCeil(contentY / 60.0) * 3;
998 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
999 for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
1000 if (i >= firstVisibleIndex + 18) // index has moved out of view
1002 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1003 QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
1005 QTRY_COMPARE(item->x(), (i%3)*80.0);
1006 QTRY_COMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
1008 name = findItem<QQuickText>(contentItem, "textName", i);
1010 QTRY_COMPARE(name->text(), model.name(i));
1011 number = findItem<QQuickText>(contentItem, "textNumber", i);
1012 QVERIFY(number != 0);
1013 QTRY_COMPARE(number->text(), model.number(i));
1015 // current index should have been updated
1016 if (item == currentItem)
1017 QTRY_COMPARE(gridview->currentIndex(), i);
1021 void tst_QQuickGridView::moved_data()
1023 QTest::addColumn<qreal>("contentY");
1024 QTest::addColumn<int>("from");
1025 QTest::addColumn<int>("to");
1026 QTest::addColumn<int>("count");
1027 QTest::addColumn<qreal>("itemsOffsetAfterMove");
1029 // model starts with 30 items, each 80x60, in area 240x320
1030 // 18 items should be visible at a time
1032 QTest::newRow("move 1 forwards, within visible items")
1037 QTest::newRow("move 1 forwards, from non-visible -> visible")
1038 << 120.0 // show 6-23
1040 << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
1042 QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
1043 << 120.0 // // show 6-23
1045 << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
1047 QTest::newRow("move 1 forwards, from visible -> non-visible")
1052 QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
1058 QTest::newRow("move 1 backwards, within visible items")
1063 QTest::newRow("move 1 backwards, within visible items (to first index)")
1068 QTest::newRow("move 1 backwards, from non-visible -> visible")
1073 QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
1078 QTest::newRow("move 1 backwards, from visible -> non-visible")
1079 << 120.0 // show 6-23
1081 << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
1083 QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
1084 << 120.0 // show 6-23
1086 << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
1089 QTest::newRow("move multiple forwards, within visible items")
1094 QTest::newRow("move multiple backwards, within visible items (move first item)")
1099 QTest::newRow("move multiple forwards, before visible items")
1100 << 120.0 // show 6-23
1101 << 3 << 4 << 3 // 3, 4, 5 move to after 6
1102 << 60.0; // row of 3,4,5 has moved down
1104 QTest::newRow("move multiple forwards, from non-visible -> visible")
1105 << 120.0 // show 6-23
1107 << 60.0; // 1st row (it's above visible area) disappears, 0 drops down 1 row, first visible item (6) stays where it is
1109 QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
1110 << 120.0 // show 6-23
1112 << 60.0; // top row moved and shifted to below 3rd row, all items should shift down by 1 row
1114 QTest::newRow("move multiple forwards, from visible -> non-visible")
1119 QTest::newRow("move multiple forwards, from visible -> non-visible (move first item)")
1125 QTest::newRow("move multiple backwards, within visible items")
1130 QTest::newRow("move multiple backwards, from non-visible -> visible")
1135 QTest::newRow("move multiple backwards, from non-visible -> visible (move last item)")
1140 QTest::newRow("move multiple backwards, from visible -> non-visible")
1141 << 120.0 // show 6-23
1143 << -60.0; // to minimize movement, items are added above visible area, all items move up by 1 row
1145 QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
1146 << 120.0 // show 6-23
1148 << -60.0; // 16,17,18 move to above item 0, all items move up by 1 row
1152 enum { Inserted, Removed, Moved, SetCurrent } type;
1157 static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; }
1158 static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; }
1159 static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; }
1160 static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; }
1162 Q_DECLARE_METATYPE(QList<ListChange>)
1164 void tst_QQuickGridView::multipleChanges()
1166 QFETCH(int, startCount);
1167 QFETCH(QList<ListChange>, changes);
1168 QFETCH(int, newCount);
1169 QFETCH(int, newCurrentIndex);
1171 QQuickView *canvas = createView();
1175 for (int i = 0; i < startCount; i++)
1176 model.addItem("Item" + QString::number(i), "");
1178 QDeclarativeContext *ctxt = canvas->rootContext();
1179 ctxt->setContextProperty("testModel", &model);
1180 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1181 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1183 canvas->setSource(testFileUrl("gridview1.qml"));
1184 qApp->processEvents();
1186 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1187 QTRY_VERIFY(gridview != 0);
1189 for (int i=0; i<changes.count(); i++) {
1190 switch (changes[i].type) {
1191 case ListChange::Inserted:
1193 QList<QPair<QString, QString> > items;
1194 for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
1195 items << qMakePair(QString("new item " + j), QString::number(j));
1196 model.insertItems(changes[i].index, items);
1199 case ListChange::Removed:
1200 model.removeItems(changes[i].index, changes[i].count);
1202 case ListChange::Moved:
1203 model.moveItems(changes[i].index, changes[i].to, changes[i].count);
1205 case ListChange::SetCurrent:
1206 gridview->setCurrentIndex(changes[i].index);
1211 QTRY_COMPARE(gridview->count(), newCount);
1212 QCOMPARE(gridview->count(), model.count());
1213 QTRY_COMPARE(gridview->currentIndex(), newCurrentIndex);
1217 QQuickItem *contentItem = gridview->contentItem();
1218 QTRY_VERIFY(contentItem != 0);
1219 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1220 for (int i=0; i < model.count() && i < itemCount; ++i) {
1221 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1222 QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
1223 name = findItem<QQuickText>(contentItem, "textName", i);
1225 QTRY_COMPARE(name->text(), model.name(i));
1226 number = findItem<QQuickText>(contentItem, "textNumber", i);
1227 QVERIFY(number != 0);
1228 QTRY_COMPARE(number->text(), model.number(i));
1234 void tst_QQuickGridView::multipleChanges_data()
1236 QTest::addColumn<int>("startCount");
1237 QTest::addColumn<QList<ListChange> >("changes");
1238 QTest::addColumn<int>("newCount");
1239 QTest::addColumn<int>("newCurrentIndex");
1241 QList<ListChange> changes;
1243 for (int i=1; i<30; i++)
1244 changes << ListChange::remove(0);
1245 QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
1247 changes << ListChange::remove(0);
1248 QTest::newRow("remove all") << 30 << changes << 0 << -1;
1251 changes << ListChange::setCurrent(29);
1252 for (int i=29; i>0; i--)
1253 changes << ListChange::remove(i);
1254 QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
1256 QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
1257 << ListChange::remove(0, 1)
1258 << ListChange::insert(0, 1)
1261 QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
1262 << ListChange::setCurrent(2)
1263 << ListChange::remove(2, 1)
1264 << ListChange::insert(2, 1)
1267 QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
1268 << ListChange::setCurrent(1)
1269 << ListChange::remove(1, 3)
1270 << ListChange::insert(2, 2)
1273 QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
1274 << ListChange::setCurrent(2)
1275 << ListChange::remove(1, 3)
1276 << ListChange::move(1, 5, 1)
1279 QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
1280 << ListChange::setCurrent(5)
1281 << ListChange::remove(4, 3)
1282 << ListChange::move(4, 1, 1)
1286 QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
1287 << ListChange::insert(0, 2)
1288 << ListChange::insert(0, 4)
1289 << ListChange::insert(0, 6)
1292 QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
1293 << ListChange::insert(0, 2)
1294 << ListChange::insert(0, 4)
1295 << ListChange::insert(0, 6)
1296 << ListChange::setCurrent(3)
1297 << ListChange::insert(3, 2)
1300 QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
1301 << ListChange::insert(0, 30)
1302 << ListChange::remove(0, 30)
1305 QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
1306 << ListChange::insert(1)
1307 << ListChange::setCurrent(1)
1308 << ListChange::remove(1)
1311 QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
1312 << ListChange::insert(0, 10)
1313 << ListChange::remove(5, 10)
1316 QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
1317 << ListChange::insert(0, 3)
1318 << ListChange::move(0, 10, 3)
1321 QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
1322 << ListChange::insert(0, 3)
1323 << ListChange::move(0, 8, 5)
1326 QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
1327 << ListChange::setCurrent(9)
1328 << ListChange::insert(10, 3)
1329 << ListChange::move(8, 0, 5)
1333 QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
1334 << ListChange::setCurrent(1)
1335 << ListChange::move(1, 2, 2)
1336 << ListChange::move(2, 1, 2)
1339 QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
1340 << ListChange::setCurrent(2)
1341 << ListChange::move(1, 2, 3)
1342 << ListChange::move(3, 0, 5)
1345 QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
1346 << ListChange::setCurrent(5)
1347 << ListChange::move(5, 0, 1)
1348 << ListChange::remove(0)
1351 QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
1352 << ListChange::setCurrent(5)
1353 << ListChange::move(5, 0, 1)
1354 << ListChange::insert(0)
1357 QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
1358 << ListChange::setCurrent(1)
1359 << ListChange::move(5, 1, 3)
1360 << ListChange::remove(1, 3)
1363 QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
1364 << ListChange::setCurrent(5)
1365 << ListChange::move(5, 1, 3)
1366 << ListChange::insert(1, 5)
1369 QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
1370 << ListChange::setCurrent(3)
1371 << ListChange::move(0, 1, 2)
1372 << ListChange::insert(3, 5)
1376 QTest::newRow("clear current") << 0 << (QList<ListChange>()
1377 << ListChange::insert(0, 5)
1378 << ListChange::setCurrent(-1)
1379 << ListChange::remove(0, 5)
1380 << ListChange::insert(0, 5)
1385 void tst_QQuickGridView::swapWithFirstItem()
1388 QQuickView *canvas = createView();
1392 for (int i = 0; i < 30; i++)
1393 model.addItem("Item" + QString::number(i), "");
1395 QDeclarativeContext *ctxt = canvas->rootContext();
1396 ctxt->setContextProperty("testModel", &model);
1397 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1398 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1400 canvas->setSource(testFileUrl("gridview1.qml"));
1401 qApp->processEvents();
1403 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1404 QTRY_VERIFY(gridview != 0);
1406 // ensure content position is stable
1407 gridview->setContentY(0);
1408 model.moveItem(10, 0);
1409 QTRY_VERIFY(gridview->contentY() == 0);
1414 void tst_QQuickGridView::currentIndex()
1417 for (int i = 0; i < 60; i++)
1418 model.addItem("Item" + QString::number(i), QString::number(i));
1420 QQuickView *canvas = new QQuickView(0);
1421 canvas->setGeometry(0,0,240,320);
1424 QDeclarativeContext *ctxt = canvas->rootContext();
1425 ctxt->setContextProperty("testModel", &model);
1427 QString filename(testFile("gridview-initCurrent.qml"));
1428 canvas->setSource(QUrl::fromLocalFile(filename));
1430 qApp->processEvents();
1432 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1433 QVERIFY(gridview != 0);
1434 QTRY_VERIFY(!QQuickItemPrivate::get(gridview)->polishScheduled);
1436 QQuickItem *contentItem = gridview->contentItem();
1437 QVERIFY(contentItem != 0);
1439 // current item should be third item
1440 QCOMPARE(gridview->currentIndex(), 35);
1441 QCOMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 35));
1442 QCOMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
1443 QCOMPARE(gridview->contentY(), 400.0);
1445 gridview->moveCurrentIndexRight();
1446 QCOMPARE(gridview->currentIndex(), 36);
1447 gridview->moveCurrentIndexDown();
1448 QCOMPARE(gridview->currentIndex(), 39);
1449 gridview->moveCurrentIndexUp();
1450 QCOMPARE(gridview->currentIndex(), 36);
1451 gridview->moveCurrentIndexLeft();
1452 QCOMPARE(gridview->currentIndex(), 35);
1454 // wait until motion stops
1455 QTRY_VERIFY(gridview->verticalVelocity() == 0.0);
1458 gridview->setCurrentIndex(0);
1459 QCOMPARE(gridview->currentIndex(), 0);
1460 // confirm that the velocity is updated
1461 QTRY_VERIFY(gridview->verticalVelocity() != 0.0);
1463 gridview->moveCurrentIndexUp();
1464 QCOMPARE(gridview->currentIndex(), 0);
1466 gridview->moveCurrentIndexLeft();
1467 QCOMPARE(gridview->currentIndex(), 0);
1469 gridview->setCurrentIndex(model.count()-1);
1470 QCOMPARE(gridview->currentIndex(), model.count()-1);
1472 gridview->moveCurrentIndexRight();
1473 QCOMPARE(gridview->currentIndex(), model.count()-1);
1475 gridview->moveCurrentIndexDown();
1476 QCOMPARE(gridview->currentIndex(), model.count()-1);
1479 gridview->setWrapEnabled(true);
1481 gridview->setCurrentIndex(0);
1482 QCOMPARE(gridview->currentIndex(), 0);
1484 gridview->moveCurrentIndexLeft();
1485 QCOMPARE(gridview->currentIndex(), model.count()-1);
1487 qApp->processEvents();
1488 QTRY_COMPARE(gridview->contentY(), 880.0);
1490 gridview->moveCurrentIndexRight();
1491 QCOMPARE(gridview->currentIndex(), 0);
1493 QTRY_COMPARE(gridview->contentY(), 0.0);
1496 // footer should become visible if it is out of view, and then current index moves to the first row
1497 canvas->rootObject()->setProperty("showFooter", true);
1498 QTRY_VERIFY(gridview->footerItem());
1499 gridview->setCurrentIndex(model.count()-3);
1500 QTRY_VERIFY(gridview->footerItem()->y() > gridview->contentY() + gridview->height());
1501 gridview->setCurrentIndex(model.count()-2);
1502 QTRY_COMPARE(gridview->contentY() + gridview->height(), (60.0 * model.count()/3) + gridview->footerItem()->height());
1503 canvas->rootObject()->setProperty("showFooter", false);
1505 // header should become visible if it is out of view, and then current index moves to the last row
1506 canvas->rootObject()->setProperty("showHeader", true);
1507 QTRY_VERIFY(gridview->headerItem());
1508 gridview->setCurrentIndex(3);
1509 QTRY_VERIFY(gridview->headerItem()->y() + gridview->headerItem()->height() < gridview->contentY());
1510 gridview->setCurrentIndex(1);
1511 QTRY_COMPARE(gridview->contentY(), -gridview->headerItem()->height());
1512 canvas->rootObject()->setProperty("showHeader", false);
1516 canvas->requestActivateWindow();
1517 QTest::qWaitForWindowShown(canvas);
1518 QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
1520 gridview->setCurrentIndex(0);
1522 QTest::keyClick(canvas, Qt::Key_Down);
1523 QCOMPARE(gridview->currentIndex(), 3);
1525 QTest::keyClick(canvas, Qt::Key_Up);
1526 QCOMPARE(gridview->currentIndex(), 0);
1528 // hold down Key_Down
1529 for (int i=0; i<(model.count() / 3) - 1; i++) {
1530 QTest::simulateEvent(canvas, true, Qt::Key_Down, Qt::NoModifier, "", true);
1531 QTRY_COMPARE(gridview->currentIndex(), i*3 + 3);
1533 QTest::keyRelease(canvas, Qt::Key_Down);
1534 QTRY_COMPARE(gridview->currentIndex(), 57);
1535 QTRY_COMPARE(gridview->contentY(), 880.0);
1538 for (int i=(model.count() / 3) - 1; i > 0; i--) {
1539 QTest::simulateEvent(canvas, true, Qt::Key_Up, Qt::NoModifier, "", true);
1540 QTRY_COMPARE(gridview->currentIndex(), i*3 - 3);
1542 QTest::keyRelease(canvas, Qt::Key_Up);
1543 QTRY_COMPARE(gridview->currentIndex(), 0);
1544 QTRY_COMPARE(gridview->contentY(), 0.0);
1547 gridview->setFlow(QQuickGridView::TopToBottom);
1549 canvas->requestActivateWindow();
1550 QTest::qWaitForWindowShown(canvas);
1551 QVERIFY(qGuiApp->focusWindow() == canvas);
1552 qApp->processEvents();
1554 QTest::keyClick(canvas, Qt::Key_Right);
1555 QCOMPARE(gridview->currentIndex(), 5);
1557 QTest::keyClick(canvas, Qt::Key_Left);
1558 QCOMPARE(gridview->currentIndex(), 0);
1560 QTest::keyClick(canvas, Qt::Key_Down);
1561 QCOMPARE(gridview->currentIndex(), 1);
1563 QTest::keyClick(canvas, Qt::Key_Up);
1564 QCOMPARE(gridview->currentIndex(), 0);
1566 // hold down Key_Right
1567 for (int i=0; i<(model.count() / 5) - 1; i++) {
1568 QTest::simulateEvent(canvas, true, Qt::Key_Right, Qt::NoModifier, "", true);
1569 QTRY_COMPARE(gridview->currentIndex(), i*5 + 5);
1572 QTest::keyRelease(canvas, Qt::Key_Right);
1573 QTRY_COMPARE(gridview->currentIndex(), 55);
1574 QTRY_COMPARE(gridview->contentX(), 720.0);
1576 // hold down Key_Left
1577 for (int i=(model.count() / 5) - 1; i > 0; i--) {
1578 QTest::simulateEvent(canvas, true, Qt::Key_Left, Qt::NoModifier, "", true);
1579 QTRY_COMPARE(gridview->currentIndex(), i*5 - 5);
1581 QTest::keyRelease(canvas, Qt::Key_Left);
1582 QTRY_COMPARE(gridview->currentIndex(), 0);
1583 QTRY_COMPARE(gridview->contentX(), 0.0);
1586 // turn off auto highlight
1587 gridview->setHighlightFollowsCurrentItem(false);
1588 QVERIFY(gridview->highlightFollowsCurrentItem() == false);
1589 QVERIFY(gridview->highlightItem());
1590 qreal hlPosX = gridview->highlightItem()->x();
1591 qreal hlPosY = gridview->highlightItem()->y();
1593 gridview->setCurrentIndex(5);
1594 QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
1595 QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
1597 // insert item before currentIndex
1598 gridview->setCurrentIndex(28);
1599 model.insertItem(0, "Foo", "1111");
1600 QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
1602 // check removing highlight by setting currentIndex to -1;
1603 gridview->setCurrentIndex(-1);
1605 QCOMPARE(gridview->currentIndex(), -1);
1606 QVERIFY(!gridview->highlightItem());
1607 QVERIFY(!gridview->currentItem());
1609 gridview->setHighlightFollowsCurrentItem(true);
1611 gridview->setFlow(QQuickGridView::LeftToRight);
1612 gridview->setLayoutDirection(Qt::RightToLeft);
1614 canvas->requestActivateWindow();
1615 QTest::qWaitForWindowShown(canvas);
1616 QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
1617 qApp->processEvents();
1619 gridview->setCurrentIndex(35);
1621 QTest::keyClick(canvas, Qt::Key_Right);
1622 QCOMPARE(gridview->currentIndex(), 34);
1624 QTest::keyClick(canvas, Qt::Key_Down);
1625 QCOMPARE(gridview->currentIndex(), 37);
1627 QTest::keyClick(canvas, Qt::Key_Up);
1628 QCOMPARE(gridview->currentIndex(), 34);
1630 QTest::keyClick(canvas, Qt::Key_Left);
1631 QCOMPARE(gridview->currentIndex(), 35);
1634 // turn off auto highlight
1635 gridview->setHighlightFollowsCurrentItem(false);
1636 QVERIFY(gridview->highlightFollowsCurrentItem() == false);
1637 QVERIFY(gridview->highlightItem());
1638 hlPosX = gridview->highlightItem()->x();
1639 hlPosY = gridview->highlightItem()->y();
1641 gridview->setCurrentIndex(5);
1642 QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
1643 QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
1645 // insert item before currentIndex
1646 gridview->setCurrentIndex(28);
1647 model.insertItem(0, "Foo", "1111");
1648 QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
1650 // check removing highlight by setting currentIndex to -1;
1651 gridview->setCurrentIndex(-1);
1653 QCOMPARE(gridview->currentIndex(), -1);
1654 QVERIFY(!gridview->highlightItem());
1655 QVERIFY(!gridview->currentItem());
1660 void tst_QQuickGridView::noCurrentIndex()
1663 for (int i = 0; i < 60; i++)
1664 model.addItem("Item" + QString::number(i), QString::number(i));
1666 QQuickView *canvas = new QQuickView(0);
1667 canvas->setGeometry(0,0,240,320);
1669 QDeclarativeContext *ctxt = canvas->rootContext();
1670 ctxt->setContextProperty("testModel", &model);
1672 QString filename(testFile("gridview-noCurrent.qml"));
1673 canvas->setSource(QUrl::fromLocalFile(filename));
1675 qApp->processEvents();
1677 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1678 QVERIFY(gridview != 0);
1680 QQuickItem *contentItem = gridview->contentItem();
1681 QVERIFY(contentItem != 0);
1683 // current index should be -1
1684 QCOMPARE(gridview->currentIndex(), -1);
1685 QVERIFY(!gridview->currentItem());
1686 QVERIFY(!gridview->highlightItem());
1687 QCOMPARE(gridview->contentY(), 0.0);
1689 gridview->setCurrentIndex(5);
1690 QCOMPARE(gridview->currentIndex(), 5);
1691 QVERIFY(gridview->currentItem());
1692 QVERIFY(gridview->highlightItem());
1697 void tst_QQuickGridView::changeFlow()
1699 QQuickView *canvas = createView();
1702 for (int i = 0; i < 30; i++)
1703 model.addItem("Item" + QString::number(i), QString::number(i));
1705 QDeclarativeContext *ctxt = canvas->rootContext();
1706 ctxt->setContextProperty("testModel", &model);
1707 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1708 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1710 canvas->setSource(testFileUrl("gridview1.qml"));
1711 qApp->processEvents();
1713 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1714 QTRY_VERIFY(gridview != 0);
1716 QQuickItem *contentItem = gridview->contentItem();
1717 QTRY_VERIFY(contentItem != 0);
1719 // Confirm items positioned correctly and indexes correct
1720 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1721 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1722 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1723 if (!item) qWarning() << "Item" << i << "not found";
1725 QTRY_COMPARE(item->x(), qreal((i%3)*80));
1726 QTRY_COMPARE(item->y(), qreal((i/3)*60));
1727 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
1728 QTRY_VERIFY(name != 0);
1729 QTRY_COMPARE(name->text(), model.name(i));
1730 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
1731 QTRY_VERIFY(number != 0);
1732 QTRY_COMPARE(number->text(), model.number(i));
1735 ctxt->setContextProperty("testTopToBottom", QVariant(true));
1737 // Confirm items positioned correctly and indexes correct
1738 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1739 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1740 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1741 if (!item) qWarning() << "Item" << i << "not found";
1743 QTRY_COMPARE(item->x(), qreal((i/5)*80));
1744 QTRY_COMPARE(item->y(), qreal((i%5)*60));
1745 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
1746 QTRY_VERIFY(name != 0);
1747 QTRY_COMPARE(name->text(), model.name(i));
1748 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
1749 QTRY_VERIFY(number != 0);
1750 QTRY_COMPARE(number->text(), model.number(i));
1753 ctxt->setContextProperty("testRightToLeft", QVariant(true));
1755 // Confirm items positioned correctly and indexes correct
1756 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1757 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1758 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1759 if (!item) qWarning() << "Item" << i << "not found";
1761 QTRY_COMPARE(item->x(), qreal(-(i/5)*80 - item->width()));
1762 QTRY_COMPARE(item->y(), qreal((i%5)*60));
1763 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
1764 QTRY_VERIFY(name != 0);
1765 QTRY_COMPARE(name->text(), model.name(i));
1766 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
1767 QTRY_VERIFY(number != 0);
1768 QTRY_COMPARE(number->text(), model.number(i));
1770 gridview->setContentX(100);
1771 QTRY_COMPARE(gridview->contentX(), 100.);
1772 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1773 QTRY_COMPARE(gridview->contentX(), 0.);
1775 // Confirm items positioned correctly and indexes correct
1776 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1777 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1778 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1779 if (!item) qWarning() << "Item" << i << "not found";
1781 QTRY_COMPARE(item->x(), qreal(240 - (i%3+1)*80));
1782 QTRY_COMPARE(item->y(), qreal((i/3)*60));
1783 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
1784 QTRY_VERIFY(name != 0);
1785 QTRY_COMPARE(name->text(), model.name(i));
1786 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
1787 QTRY_VERIFY(number != 0);
1788 QTRY_COMPARE(number->text(), model.number(i));
1794 void tst_QQuickGridView::defaultValues()
1796 QDeclarativeEngine engine;
1797 QDeclarativeComponent c(&engine, testFileUrl("gridview3.qml"));
1798 QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
1800 QTRY_VERIFY(obj != 0);
1801 QTRY_VERIFY(obj->model() == QVariant());
1802 QTRY_VERIFY(obj->delegate() == 0);
1803 QTRY_COMPARE(obj->currentIndex(), -1);
1804 QTRY_VERIFY(obj->currentItem() == 0);
1805 QTRY_COMPARE(obj->count(), 0);
1806 QTRY_VERIFY(obj->highlight() == 0);
1807 QTRY_VERIFY(obj->highlightItem() == 0);
1808 QTRY_COMPARE(obj->highlightFollowsCurrentItem(), true);
1809 QTRY_VERIFY(obj->flow() == 0);
1810 QTRY_COMPARE(obj->isWrapEnabled(), false);
1811 QTRY_COMPARE(obj->cacheBuffer(), 0);
1812 QTRY_COMPARE(obj->cellWidth(), qreal(100)); //### Should 100 be the default?
1813 QTRY_COMPARE(obj->cellHeight(), qreal(100));
1817 void tst_QQuickGridView::properties()
1819 QDeclarativeEngine engine;
1820 QDeclarativeComponent c(&engine, testFileUrl("gridview2.qml"));
1821 QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
1823 QTRY_VERIFY(obj != 0);
1824 QTRY_VERIFY(obj->model() != QVariant());
1825 QTRY_VERIFY(obj->delegate() != 0);
1826 QTRY_COMPARE(obj->currentIndex(), 0);
1827 QTRY_VERIFY(obj->currentItem() != 0);
1828 QTRY_COMPARE(obj->count(), 4);
1829 QTRY_VERIFY(obj->highlight() != 0);
1830 QTRY_VERIFY(obj->highlightItem() != 0);
1831 QTRY_COMPARE(obj->highlightFollowsCurrentItem(), false);
1832 QTRY_VERIFY(obj->flow() == 0);
1833 QTRY_COMPARE(obj->isWrapEnabled(), true);
1834 QTRY_COMPARE(obj->cacheBuffer(), 200);
1835 QTRY_COMPARE(obj->cellWidth(), qreal(100));
1836 QTRY_COMPARE(obj->cellHeight(), qreal(100));
1840 void tst_QQuickGridView::propertyChanges()
1842 QQuickView *canvas = createView();
1843 QTRY_VERIFY(canvas);
1844 canvas->setSource(testFileUrl("propertychangestest.qml"));
1846 QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
1847 QTRY_VERIFY(gridView);
1849 QSignalSpy keyNavigationWrapsSpy(gridView, SIGNAL(keyNavigationWrapsChanged()));
1850 QSignalSpy cacheBufferSpy(gridView, SIGNAL(cacheBufferChanged()));
1851 QSignalSpy layoutSpy(gridView, SIGNAL(layoutDirectionChanged()));
1852 QSignalSpy flowSpy(gridView, SIGNAL(flowChanged()));
1854 QTRY_COMPARE(gridView->isWrapEnabled(), true);
1855 QTRY_COMPARE(gridView->cacheBuffer(), 10);
1856 QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
1858 gridView->setWrapEnabled(false);
1859 gridView->setCacheBuffer(3);
1860 gridView->setFlow(QQuickGridView::TopToBottom);
1862 QTRY_COMPARE(gridView->isWrapEnabled(), false);
1863 QTRY_COMPARE(gridView->cacheBuffer(), 3);
1864 QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
1866 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1867 QTRY_COMPARE(cacheBufferSpy.count(),1);
1868 QTRY_COMPARE(flowSpy.count(),1);
1870 gridView->setWrapEnabled(false);
1871 gridView->setCacheBuffer(3);
1872 gridView->setFlow(QQuickGridView::TopToBottom);
1874 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1875 QTRY_COMPARE(cacheBufferSpy.count(),1);
1876 QTRY_COMPARE(flowSpy.count(),1);
1878 gridView->setFlow(QQuickGridView::LeftToRight);
1879 QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
1881 gridView->setWrapEnabled(true);
1882 gridView->setCacheBuffer(5);
1883 gridView->setLayoutDirection(Qt::RightToLeft);
1885 QTRY_COMPARE(gridView->isWrapEnabled(), true);
1886 QTRY_COMPARE(gridView->cacheBuffer(), 5);
1887 QTRY_COMPARE(gridView->layoutDirection(), Qt::RightToLeft);
1889 QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
1890 QTRY_COMPARE(cacheBufferSpy.count(),2);
1891 QTRY_COMPARE(layoutSpy.count(),1);
1892 QTRY_COMPARE(flowSpy.count(),2);
1894 gridView->setWrapEnabled(true);
1895 gridView->setCacheBuffer(5);
1896 gridView->setLayoutDirection(Qt::RightToLeft);
1898 QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
1899 QTRY_COMPARE(cacheBufferSpy.count(),2);
1900 QTRY_COMPARE(layoutSpy.count(),1);
1901 QTRY_COMPARE(flowSpy.count(),2);
1903 gridView->setFlow(QQuickGridView::TopToBottom);
1904 QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
1905 QTRY_COMPARE(flowSpy.count(),3);
1907 gridView->setFlow(QQuickGridView::TopToBottom);
1908 QTRY_COMPARE(flowSpy.count(),3);
1913 void tst_QQuickGridView::componentChanges()
1915 QQuickView *canvas = createView();
1916 QTRY_VERIFY(canvas);
1917 canvas->setSource(testFileUrl("propertychangestest.qml"));
1919 QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
1920 QTRY_VERIFY(gridView);
1922 QDeclarativeComponent component(canvas->engine());
1923 component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
1925 QDeclarativeComponent delegateComponent(canvas->engine());
1926 delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
1928 QSignalSpy highlightSpy(gridView, SIGNAL(highlightChanged()));
1929 QSignalSpy delegateSpy(gridView, SIGNAL(delegateChanged()));
1930 QSignalSpy headerSpy(gridView, SIGNAL(headerChanged()));
1931 QSignalSpy footerSpy(gridView, SIGNAL(footerChanged()));
1933 gridView->setHighlight(&component);
1934 gridView->setDelegate(&delegateComponent);
1935 gridView->setHeader(&component);
1936 gridView->setFooter(&component);
1938 QTRY_COMPARE(gridView->highlight(), &component);
1939 QTRY_COMPARE(gridView->delegate(), &delegateComponent);
1940 QTRY_COMPARE(gridView->header(), &component);
1941 QTRY_COMPARE(gridView->footer(), &component);
1943 QTRY_COMPARE(highlightSpy.count(),1);
1944 QTRY_COMPARE(delegateSpy.count(),1);
1945 QTRY_COMPARE(headerSpy.count(),1);
1946 QTRY_COMPARE(footerSpy.count(),1);
1948 gridView->setHighlight(&component);
1949 gridView->setDelegate(&delegateComponent);
1950 gridView->setHeader(&component);
1951 gridView->setFooter(&component);
1953 QTRY_COMPARE(highlightSpy.count(),1);
1954 QTRY_COMPARE(delegateSpy.count(),1);
1955 QTRY_COMPARE(headerSpy.count(),1);
1956 QTRY_COMPARE(footerSpy.count(),1);
1961 void tst_QQuickGridView::modelChanges()
1963 QQuickView *canvas = createView();
1964 QTRY_VERIFY(canvas);
1965 canvas->setSource(testFileUrl("propertychangestest.qml"));
1967 QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
1968 QTRY_VERIFY(gridView);
1970 QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
1971 QTRY_VERIFY(alternateModel);
1972 QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
1973 QSignalSpy modelSpy(gridView, SIGNAL(modelChanged()));
1975 gridView->setModel(modelVariant);
1976 QTRY_COMPARE(gridView->model(), modelVariant);
1977 QTRY_COMPARE(modelSpy.count(),1);
1979 gridView->setModel(modelVariant);
1980 QTRY_COMPARE(modelSpy.count(),1);
1982 gridView->setModel(QVariant());
1983 QTRY_COMPARE(modelSpy.count(),2);
1987 void tst_QQuickGridView::positionViewAtIndex()
1989 QQuickView *canvas = createView();
1992 for (int i = 0; i < 40; i++)
1993 model.addItem("Item" + QString::number(i), "");
1995 QDeclarativeContext *ctxt = canvas->rootContext();
1996 ctxt->setContextProperty("testModel", &model);
1997 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1998 ctxt->setContextProperty("testTopToBottom", QVariant(false));
2000 canvas->setSource(testFileUrl("gridview1.qml"));
2001 qApp->processEvents();
2003 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2004 QTRY_VERIFY(gridview != 0);
2006 QQuickItem *contentItem = gridview->contentItem();
2007 QTRY_VERIFY(contentItem != 0);
2009 // Confirm items positioned correctly
2010 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2011 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2012 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2013 if (!item) qWarning() << "Item" << i << "not found";
2015 QTRY_COMPARE(item->x(), (i%3)*80.);
2016 QTRY_COMPARE(item->y(), (i/3)*60.);
2019 // Position on a currently visible item
2020 gridview->positionViewAtIndex(4, QQuickGridView::Beginning);
2021 QTRY_COMPARE(gridview->indexAt(120, 90), 4);
2022 QTRY_COMPARE(gridview->contentY(), 60.);
2024 // Confirm items positioned correctly
2025 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2026 for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
2027 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2028 if (!item) qWarning() << "Item" << i << "not found";
2030 QTRY_COMPARE(item->x(), (i%3)*80.);
2031 QTRY_COMPARE(item->y(), (i/3)*60.);
2034 // Position on an item beyond the visible items
2035 gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
2036 QTRY_COMPARE(gridview->indexAt(40, 450), 21);
2037 QTRY_COMPARE(gridview->contentY(), 420.);
2039 // Confirm items positioned correctly
2040 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2041 for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
2042 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2043 if (!item) qWarning() << "Item" << i << "not found";
2045 QTRY_COMPARE(item->x(), (i%3)*80.);
2046 QTRY_COMPARE(item->y(), (i/3)*60.);
2049 // Position on an item that would leave empty space if positioned at the top
2050 gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
2051 QTRY_COMPARE(gridview->indexAt(120, 630), 31);
2052 QTRY_COMPARE(gridview->contentY(), 520.);
2054 // Confirm items positioned correctly
2055 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2056 for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
2057 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2058 if (!item) qWarning() << "Item" << i << "not found";
2060 QTRY_COMPARE(item->x(), (i%3)*80.);
2061 QTRY_COMPARE(item->y(), (i/3)*60.);
2064 // Position at the beginning again
2065 gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
2066 QTRY_COMPARE(gridview->indexAt(0, 0), 0);
2067 QTRY_COMPARE(gridview->indexAt(40, 30), 0);
2068 QTRY_COMPARE(gridview->indexAt(80, 60), 4);
2069 QTRY_COMPARE(gridview->contentY(), 0.);
2071 // Confirm items positioned correctly
2072 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2073 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2074 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2075 if (!item) qWarning() << "Item" << i << "not found";
2077 QTRY_COMPARE(item->x(), (i%3)*80.);
2078 QTRY_COMPARE(item->y(), (i/3)*60.);
2082 gridview->positionViewAtIndex(30, QQuickGridView::End);
2083 QTRY_COMPARE(gridview->contentY(), 340.);
2085 // Position in Center
2086 gridview->positionViewAtIndex(15, QQuickGridView::Center);
2087 QTRY_COMPARE(gridview->contentY(), 170.);
2089 // Ensure at least partially visible
2090 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2091 QTRY_COMPARE(gridview->contentY(), 170.);
2093 gridview->setContentY(302);
2094 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2095 QTRY_COMPARE(gridview->contentY(), 302.);
2097 gridview->setContentY(360);
2098 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2099 QTRY_COMPARE(gridview->contentY(), 300.);
2101 gridview->setContentY(60);
2102 gridview->positionViewAtIndex(20, QQuickGridView::Visible);
2103 QTRY_COMPARE(gridview->contentY(), 60.);
2105 gridview->setContentY(20);
2106 gridview->positionViewAtIndex(20, QQuickGridView::Visible);
2107 QTRY_COMPARE(gridview->contentY(), 100.);
2109 // Ensure completely visible
2110 gridview->setContentY(120);
2111 gridview->positionViewAtIndex(20, QQuickGridView::Contain);
2112 QTRY_COMPARE(gridview->contentY(), 120.);
2114 gridview->setContentY(302);
2115 gridview->positionViewAtIndex(15, QQuickGridView::Contain);
2116 QTRY_COMPARE(gridview->contentY(), 300.);
2118 gridview->setContentY(60);
2119 gridview->positionViewAtIndex(20, QQuickGridView::Contain);
2120 QTRY_COMPARE(gridview->contentY(), 100.);
2122 // Test for Top To Bottom layout
2123 ctxt->setContextProperty("testTopToBottom", QVariant(true));
2125 // Confirm items positioned correctly
2126 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2127 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2128 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2129 if (!item) qWarning() << "Item" << i << "not found";
2131 QTRY_COMPARE(item->x(), (i/5)*80.);
2132 QTRY_COMPARE(item->y(), (i%5)*60.);
2136 gridview->positionViewAtIndex(30, QQuickGridView::End);
2137 QTRY_COMPARE(gridview->contentX(), 320.);
2138 QTRY_COMPARE(gridview->contentY(), 0.);
2140 // Position in Center
2141 gridview->positionViewAtIndex(15, QQuickGridView::Center);
2142 QTRY_COMPARE(gridview->contentX(), 160.);
2144 // Ensure at least partially visible
2145 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2146 QTRY_COMPARE(gridview->contentX(), 160.);
2148 gridview->setContentX(170);
2149 gridview->positionViewAtIndex(25, QQuickGridView::Visible);
2150 QTRY_COMPARE(gridview->contentX(), 170.);
2152 gridview->positionViewAtIndex(30, QQuickGridView::Visible);
2153 QTRY_COMPARE(gridview->contentX(), 320.);
2155 gridview->setContentX(170);
2156 gridview->positionViewAtIndex(25, QQuickGridView::Contain);
2157 QTRY_COMPARE(gridview->contentX(), 240.);
2159 // positionViewAtBeginning
2160 gridview->positionViewAtBeginning();
2161 QTRY_COMPARE(gridview->contentX(), 0.);
2163 gridview->setContentX(80);
2164 canvas->rootObject()->setProperty("showHeader", true);
2165 gridview->positionViewAtBeginning();
2166 QTRY_COMPARE(gridview->contentX(), -30.);
2168 // positionViewAtEnd
2169 gridview->positionViewAtEnd();
2170 QTRY_COMPARE(gridview->contentX(), 400.); // 8*80 - 240 (8 columns)
2172 gridview->setContentX(80);
2173 canvas->rootObject()->setProperty("showFooter", true);
2174 gridview->positionViewAtEnd();
2175 QTRY_COMPARE(gridview->contentX(), 430.);
2177 // set current item to outside visible view, position at beginning
2178 // and ensure highlight moves to current item
2179 gridview->setCurrentIndex(6);
2180 gridview->positionViewAtBeginning();
2181 QTRY_COMPARE(gridview->contentX(), -30.);
2182 QVERIFY(gridview->highlightItem());
2183 QCOMPARE(gridview->highlightItem()->x(), 80.);
2188 void tst_QQuickGridView::snapping()
2190 QQuickView *canvas = createView();
2193 for (int i = 0; i < 40; i++)
2194 model.addItem("Item" + QString::number(i), "");
2196 QDeclarativeContext *ctxt = canvas->rootContext();
2197 ctxt->setContextProperty("testModel", &model);
2198 ctxt->setContextProperty("testTopToBottom", QVariant(false));
2199 ctxt->setContextProperty("testRightToLeft", QVariant(false));
2201 canvas->setSource(testFileUrl("gridview1.qml"));
2202 qApp->processEvents();
2204 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2205 QTRY_VERIFY(gridview != 0);
2207 gridview->setHeight(220);
2208 QCOMPARE(gridview->height(), 220.);
2210 gridview->positionViewAtIndex(12, QQuickGridView::Visible);
2211 QCOMPARE(gridview->contentY(), 80.);
2213 gridview->setContentY(0);
2214 QCOMPARE(gridview->contentY(), 0.);
2216 gridview->setSnapMode(QQuickGridView::SnapToRow);
2217 QCOMPARE(gridview->snapMode(), QQuickGridView::SnapToRow);
2219 gridview->positionViewAtIndex(12, QQuickGridView::Visible);
2220 QCOMPARE(gridview->contentY(), 60.);
2222 gridview->positionViewAtIndex(15, QQuickGridView::End);
2223 QCOMPARE(gridview->contentY(), 120.);
2229 void tst_QQuickGridView::mirroring()
2231 QQuickView *canvasA = createView();
2232 canvasA->setSource(testFileUrl("mirroring.qml"));
2233 QQuickGridView *gridviewA = findItem<QQuickGridView>(canvasA->rootObject(), "view");
2234 QTRY_VERIFY(gridviewA != 0);
2236 QQuickView *canvasB = createView();
2237 canvasB->setSource(testFileUrl("mirroring.qml"));
2238 QQuickGridView *gridviewB = findItem<QQuickGridView>(canvasB->rootObject(), "view");
2239 QTRY_VERIFY(gridviewA != 0);
2240 qApp->processEvents();
2242 QList<QString> objectNames;
2243 objectNames << "item1" << "item2"; // << "item3"
2245 gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
2246 gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
2247 QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection());
2250 foreach (const QString objectName, objectNames)
2251 QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
2253 gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
2254 gridviewB->setProperty("layoutDirection", Qt::LeftToRight);
2257 foreach (const QString objectName, objectNames)
2258 QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
2260 QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection());
2261 QQuickItemPrivate::get(gridviewB)->setLayoutMirror(true);
2262 QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
2264 // LTR != LTR+mirror
2265 foreach (const QString objectName, objectNames)
2266 QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
2268 gridviewA->setProperty("layoutDirection", Qt::RightToLeft);
2270 // RTL == LTR+mirror
2271 foreach (const QString objectName, objectNames)
2272 QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
2274 gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
2276 // RTL != RTL+mirror
2277 foreach (const QString objectName, objectNames)
2278 QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
2280 gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
2282 // LTR == RTL+mirror
2283 foreach (const QString objectName, objectNames)
2284 QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
2290 void tst_QQuickGridView::positionViewAtIndex_rightToLeft()
2292 QQuickView *canvas = createView();
2295 for (int i = 0; i < 40; i++)
2296 model.addItem("Item" + QString::number(i), "");
2298 QDeclarativeContext *ctxt = canvas->rootContext();
2299 ctxt->setContextProperty("testModel", &model);
2300 ctxt->setContextProperty("testTopToBottom", QVariant(true));
2301 ctxt->setContextProperty("testRightToLeft", QVariant(true));
2303 canvas->setSource(testFileUrl("gridview1.qml"));
2304 qApp->processEvents();
2306 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2307 QTRY_VERIFY(gridview != 0);
2309 QQuickItem *contentItem = gridview->contentItem();
2310 QTRY_VERIFY(contentItem != 0);
2312 // Confirm items positioned correctly
2313 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2314 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2315 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2316 if (!item) qWarning() << "Item" << i << "not found";
2318 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2319 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2322 // Position on a currently visible item
2323 gridview->positionViewAtIndex(6, QQuickGridView::Beginning);
2324 QTRY_COMPARE(gridview->contentX(), -320.);
2326 // Confirm items positioned correctly
2327 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2328 for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
2329 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2330 if (!item) qWarning() << "Item" << i << "not found";
2332 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2333 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2336 // Position on an item beyond the visible items
2337 gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
2338 QTRY_COMPARE(gridview->contentX(), -560.);
2340 // Confirm items positioned correctly
2341 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2342 for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
2343 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2344 if (!item) qWarning() << "Item" << i << "not found";
2346 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2347 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2350 // Position on an item that would leave empty space if positioned at the top
2351 gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
2352 QTRY_COMPARE(gridview->contentX(), -640.);
2354 // Confirm items positioned correctly
2355 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2356 for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
2357 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2358 if (!item) qWarning() << "Item" << i << "not found";
2360 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2361 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2364 // Position at the beginning again
2365 gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
2366 QTRY_COMPARE(gridview->contentX(), -240.);
2368 // Confirm items positioned correctly
2369 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2370 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2371 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2372 if (!item) qWarning() << "Item" << i << "not found";
2374 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2375 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2379 gridview->positionViewAtIndex(30, QQuickGridView::End);
2380 QTRY_COMPARE(gridview->contentX(), -560.);
2382 // Position in Center
2383 gridview->positionViewAtIndex(15, QQuickGridView::Center);
2384 QTRY_COMPARE(gridview->contentX(), -400.);
2386 // Ensure at least partially visible
2387 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2388 QTRY_COMPARE(gridview->contentX(), -400.);
2390 gridview->setContentX(-555.);
2391 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2392 QTRY_COMPARE(gridview->contentX(), -555.);
2394 gridview->setContentX(-239);
2395 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2396 QTRY_COMPARE(gridview->contentX(), -320.);
2398 gridview->setContentX(-239);
2399 gridview->positionViewAtIndex(20, QQuickGridView::Visible);
2400 QTRY_COMPARE(gridview->contentX(), -400.);
2402 gridview->setContentX(-640);
2403 gridview->positionViewAtIndex(20, QQuickGridView::Visible);
2404 QTRY_COMPARE(gridview->contentX(), -560.);
2406 // Ensure completely visible
2407 gridview->setContentX(-400);
2408 gridview->positionViewAtIndex(20, QQuickGridView::Contain);
2409 QTRY_COMPARE(gridview->contentX(), -400.);
2411 gridview->setContentX(-315);
2412 gridview->positionViewAtIndex(15, QQuickGridView::Contain);
2413 QTRY_COMPARE(gridview->contentX(), -320.);
2415 gridview->setContentX(-640);
2416 gridview->positionViewAtIndex(20, QQuickGridView::Contain);
2417 QTRY_COMPARE(gridview->contentX(), -560.);
2422 void tst_QQuickGridView::resetModel()
2424 QQuickView *canvas = createView();
2426 QStringList strings;
2427 strings << "one" << "two" << "three";
2428 QStringListModel model(strings);
2430 QDeclarativeContext *ctxt = canvas->rootContext();
2431 ctxt->setContextProperty("testModel", &model);
2433 canvas->setSource(testFileUrl("displaygrid.qml"));
2434 qApp->processEvents();
2436 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2437 QTRY_VERIFY(gridview != 0);
2439 QQuickItem *contentItem = gridview->contentItem();
2440 QTRY_VERIFY(contentItem != 0);
2442 QTRY_COMPARE(gridview->count(), model.rowCount());
2444 for (int i = 0; i < model.rowCount(); ++i) {
2445 QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
2446 QTRY_VERIFY(display != 0);
2447 QTRY_COMPARE(display->text(), strings.at(i));
2451 strings << "four" << "five" << "six" << "seven";
2452 model.setStringList(strings);
2454 QTRY_COMPARE(gridview->count(), model.rowCount());
2456 for (int i = 0; i < model.rowCount(); ++i) {
2457 QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
2458 QTRY_VERIFY(display != 0);
2459 QTRY_COMPARE(display->text(), strings.at(i));
2465 void tst_QQuickGridView::enforceRange()
2467 QQuickView *canvas = createView();
2470 for (int i = 0; i < 30; i++)
2471 model.addItem("Item" + QString::number(i), "");
2473 QDeclarativeContext *ctxt = canvas->rootContext();
2474 ctxt->setContextProperty("testModel", &model);
2475 ctxt->setContextProperty("testRightToLeft", QVariant(false));
2476 ctxt->setContextProperty("testTopToBottom", QVariant(false));
2478 canvas->setSource(testFileUrl("gridview-enforcerange.qml"));
2479 qApp->processEvents();
2480 QVERIFY(canvas->rootObject() != 0);
2482 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2483 QTRY_VERIFY(gridview != 0);
2485 QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
2486 QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
2487 QTRY_COMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
2489 QQuickItem *contentItem = gridview->contentItem();
2490 QTRY_VERIFY(contentItem != 0);
2492 // view should be positioned at the top of the range.
2493 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2495 QTRY_COMPARE(gridview->contentY(), -100.0);
2497 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
2498 QTRY_VERIFY(name != 0);
2499 QTRY_COMPARE(name->text(), model.name(0));
2500 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
2501 QTRY_VERIFY(number != 0);
2502 QTRY_COMPARE(number->text(), model.number(0));
2504 // Check currentIndex is updated when contentItem moves
2505 gridview->setContentY(0);
2506 QTRY_COMPARE(gridview->currentIndex(), 2);
2508 gridview->setCurrentIndex(5);
2509 QTRY_COMPARE(gridview->contentY(), 100.);
2512 for (int i = 0; i < 5; i++)
2513 model2.addItem("Item" + QString::number(i), "");
2515 ctxt->setContextProperty("testModel", &model2);
2516 QCOMPARE(gridview->count(), 5);
2521 void tst_QQuickGridView::enforceRange_rightToLeft()
2523 QQuickView *canvas = createView();
2526 for (int i = 0; i < 30; i++)
2527 model.addItem("Item" + QString::number(i), "");
2529 QDeclarativeContext *ctxt = canvas->rootContext();
2530 ctxt->setContextProperty("testModel", &model);
2531 ctxt->setContextProperty("testRightToLeft", QVariant(true));
2532 ctxt->setContextProperty("testTopToBottom", QVariant(true));
2534 canvas->setSource(testFileUrl("gridview-enforcerange.qml"));
2535 qApp->processEvents();
2536 QVERIFY(canvas->rootObject() != 0);
2538 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2539 QTRY_VERIFY(gridview != 0);
2541 QCOMPARE(gridview->preferredHighlightBegin(), 100.0);
2542 QCOMPARE(gridview->preferredHighlightEnd(), 100.0);
2543 QCOMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
2545 QQuickItem *contentItem = gridview->contentItem();
2546 QVERIFY(contentItem != 0);
2548 // view should be positioned at the top of the range.
2549 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2551 QTRY_COMPARE(gridview->contentX(), -140.);
2552 QTRY_COMPARE(gridview->contentY(), 0.0);
2554 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
2555 QTRY_VERIFY(name != 0);
2556 QTRY_COMPARE(name->text(), model.name(0));
2557 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
2558 QTRY_VERIFY(number != 0);
2559 QTRY_COMPARE(number->text(), model.number(0));
2561 // Check currentIndex is updated when contentItem moves
2562 gridview->setContentX(-240);
2563 QTRY_COMPARE(gridview->currentIndex(), 3);
2565 gridview->setCurrentIndex(7);
2566 QTRY_COMPARE(gridview->contentX(), -340.);
2567 QTRY_COMPARE(gridview->contentY(), 0.0);
2570 for (int i = 0; i < 5; i++)
2571 model2.addItem("Item" + QString::number(i), "");
2573 ctxt->setContextProperty("testModel", &model2);
2574 QCOMPARE(gridview->count(), 5);
2579 void tst_QQuickGridView::QTBUG_8456()
2581 QQuickView *canvas = createView();
2583 canvas->setSource(testFileUrl("setindex.qml"));
2584 qApp->processEvents();
2586 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2587 QTRY_VERIFY(gridview != 0);
2589 QTRY_COMPARE(gridview->currentIndex(), 0);
2594 void tst_QQuickGridView::manualHighlight()
2596 QQuickView *canvas = createView();
2598 QString filename(testFile("manual-highlight.qml"));
2599 canvas->setSource(QUrl::fromLocalFile(filename));
2601 qApp->processEvents();
2603 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2604 QTRY_VERIFY(gridview != 0);
2606 QQuickItem *contentItem = gridview->contentItem();
2607 QTRY_VERIFY(contentItem != 0);
2609 QTRY_COMPARE(gridview->currentIndex(), 0);
2610 QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
2611 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
2612 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
2614 gridview->setCurrentIndex(2);
2616 QTRY_COMPARE(gridview->currentIndex(), 2);
2617 QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
2618 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
2619 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
2621 gridview->positionViewAtIndex(8, QQuickGridView::Contain);
2623 QTRY_COMPARE(gridview->currentIndex(), 2);
2624 QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
2625 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
2626 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
2628 gridview->setFlow(QQuickGridView::TopToBottom);
2629 QTRY_COMPARE(gridview->flow(), QQuickGridView::TopToBottom);
2631 gridview->setCurrentIndex(0);
2632 QTRY_COMPARE(gridview->currentIndex(), 0);
2633 QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
2634 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
2635 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
2641 void tst_QQuickGridView::footer()
2643 QFETCH(QQuickGridView::Flow, flow);
2644 QFETCH(Qt::LayoutDirection, layoutDirection);
2645 QFETCH(QPointF, initialFooterPos);
2646 QFETCH(QPointF, changedFooterPos);
2647 QFETCH(QPointF, initialContentPos);
2648 QFETCH(QPointF, changedContentPos);
2649 QFETCH(QPointF, firstDelegatePos);
2650 QFETCH(QPointF, resizeContentPos);
2652 QQuickView *canvas = createView();
2656 for (int i = 0; i < 7; i++)
2657 model.addItem("Item" + QString::number(i), "");
2659 QDeclarativeContext *ctxt = canvas->rootContext();
2660 ctxt->setContextProperty("testModel", &model);
2662 canvas->setSource(testFileUrl("footer.qml"));
2663 qApp->processEvents();
2665 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2666 QTRY_VERIFY(gridview != 0);
2667 gridview->setFlow(flow);
2668 gridview->setLayoutDirection(layoutDirection);
2670 QQuickItem *contentItem = gridview->contentItem();
2671 QTRY_VERIFY(contentItem != 0);
2673 QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
2676 QVERIFY(footer == gridview->footerItem());
2678 QCOMPARE(footer->pos(), initialFooterPos);
2679 QCOMPARE(footer->width(), 100.);
2680 QCOMPARE(footer->height(), 30.);
2681 QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
2683 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2685 QCOMPARE(item->pos(), firstDelegatePos);
2687 if (flow == QQuickGridView::LeftToRight) {
2688 // shrink by one row
2689 model.removeItem(2);
2690 QTRY_COMPARE(footer->y(), initialFooterPos.y() - gridview->cellHeight());
2692 // shrink by one column
2693 model.removeItem(2);
2694 model.removeItem(3);
2695 if (layoutDirection == Qt::LeftToRight)
2696 QTRY_COMPARE(footer->x(), initialFooterPos.x() - gridview->cellWidth());
2698 QTRY_COMPARE(footer->x(), initialFooterPos.x() + gridview->cellWidth());
2704 QPointF posWhenNoItems(0, 0);
2705 if (layoutDirection == Qt::RightToLeft)
2706 posWhenNoItems.setX(flow == QQuickGridView::LeftToRight ? gridview->width() - footer->width() : -footer->width());
2707 QTRY_COMPARE(footer->pos(), posWhenNoItems);
2709 // if header is present, it's at a negative pos, so the footer should not move
2710 canvas->rootObject()->setProperty("showHeader", true);
2711 QVERIFY(findItem<QQuickItem>(contentItem, "header") != 0);
2712 QTRY_COMPARE(footer->pos(), posWhenNoItems);
2713 canvas->rootObject()->setProperty("showHeader", false);
2716 for (int i = 0; i < 30; i++)
2717 model.addItem("Item" + QString::number(i), "");
2719 QSignalSpy footerItemSpy(gridview, SIGNAL(footerItemChanged()));
2720 QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
2722 QCOMPARE(footerItemSpy.count(), 1);
2724 footer = findItem<QQuickText>(contentItem, "footer");
2726 footer = findItem<QQuickText>(contentItem, "footer2");
2729 QVERIFY(footer == gridview->footerItem());
2731 QCOMPARE(footer->pos(), changedFooterPos);
2732 QCOMPARE(footer->width(), 50.);
2733 QCOMPARE(footer->height(), 20.);
2734 QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
2736 item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2738 QCOMPARE(item->pos(), firstDelegatePos);
2740 gridview->positionViewAtEnd();
2741 footer->setHeight(10);
2742 footer->setWidth(40);
2743 QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
2748 void tst_QQuickGridView::footer_data()
2750 QTest::addColumn<QQuickGridView::Flow>("flow");
2751 QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
2752 QTest::addColumn<QPointF>("initialFooterPos");
2753 QTest::addColumn<QPointF>("changedFooterPos");
2754 QTest::addColumn<QPointF>("initialContentPos");
2755 QTest::addColumn<QPointF>("changedContentPos");
2756 QTest::addColumn<QPointF>("firstDelegatePos");
2757 QTest::addColumn<QPointF>("resizeContentPos");
2759 // footer1 = 100 x 30
2760 // footer2 = 50 x 20
2763 // view height = 320
2765 // footer below items, bottom left
2766 QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
2767 << QPointF(0, 3 * 60) // 180 = height of 3 rows (cell height is 60)
2768 << QPointF(0, 10 * 60) // 30 items = 10 rows
2772 << QPointF(0, 10 * 60 - 320 + 10);
2774 // footer below items, bottom right
2775 QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
2776 << QPointF(240 - 100, 3 * 60)
2777 << QPointF((240 - 100) + 50, 10 * 60) // 50 = width diff between old and new footers
2780 << QPointF(240 - 80, 0)
2781 << QPointF(0, 10 * 60 - 320 + 10);
2783 // footer to right of items
2784 QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
2785 << QPointF(2 * 80, 0) // 2 columns, cell width 80
2786 << QPointF(6 * 80, 0) // 30 items = 6 columns
2790 << QPointF(6 * 80 - 240 + 40, 0);
2792 // footer to left of items
2793 QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
2794 << QPointF(-(2 * 80) - 100, 0)
2795 << QPointF(-(6 * 80) - 50, 0) // 50 = new footer width
2797 << QPointF(-240, 0) // unchanged, footer change doesn't change content pos
2799 << QPointF(-(6 * 80) - 40, 0);
2802 void tst_QQuickGridView::header()
2804 QFETCH(QQuickGridView::Flow, flow);
2805 QFETCH(Qt::LayoutDirection, layoutDirection);
2806 QFETCH(QPointF, initialHeaderPos);
2807 QFETCH(QPointF, changedHeaderPos);
2808 QFETCH(QPointF, initialContentPos);
2809 QFETCH(QPointF, changedContentPos);
2810 QFETCH(QPointF, firstDelegatePos);
2811 QFETCH(QPointF, resizeContentPos);
2814 for (int i = 0; i < 30; i++)
2815 model.addItem("Item" + QString::number(i), "");
2817 QQuickView *canvas = createView();
2818 canvas->rootContext()->setContextProperty("testModel", &model);
2819 canvas->rootContext()->setContextProperty("initialViewWidth", 240);
2820 canvas->rootContext()->setContextProperty("initialViewHeight", 320);
2821 canvas->setSource(testFileUrl("header.qml"));
2823 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2824 QTRY_VERIFY(gridview != 0);
2825 gridview->setFlow(flow);
2826 gridview->setLayoutDirection(layoutDirection);
2828 QQuickItem *contentItem = gridview->contentItem();
2829 QTRY_VERIFY(contentItem != 0);
2831 QQuickText *header = findItem<QQuickText>(contentItem, "header");
2834 QVERIFY(header == gridview->headerItem());
2836 QCOMPARE(header->pos(), initialHeaderPos);
2837 QCOMPARE(header->width(), 100.);
2838 QCOMPARE(header->height(), 30.);
2839 QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
2841 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2843 QCOMPARE(item->pos(), firstDelegatePos);
2846 QCOMPARE(header->pos(), initialHeaderPos); // header should stay where it is
2848 for (int i = 0; i < 30; i++)
2849 model.addItem("Item" + QString::number(i), "");
2851 QSignalSpy headerItemSpy(gridview, SIGNAL(headerItemChanged()));
2852 QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
2854 QCOMPARE(headerItemSpy.count(), 1);
2856 header = findItem<QQuickText>(contentItem, "header");
2858 header = findItem<QQuickText>(contentItem, "header2");
2861 QVERIFY(header == gridview->headerItem());
2863 QCOMPARE(header->pos(), changedHeaderPos);
2864 QCOMPARE(header->width(), 50.);
2865 QCOMPARE(header->height(), 20.);
2866 QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
2868 item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2870 QCOMPARE(item->pos(), firstDelegatePos);
2872 header->setHeight(10);
2873 header->setWidth(40);
2874 QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
2879 // QTBUG-21207 header should become visible if view resizes from initial empty size
2881 canvas = createView();
2882 canvas->rootContext()->setContextProperty("testModel", &model);
2883 canvas->rootContext()->setContextProperty("initialViewWidth", 240);
2884 canvas->rootContext()->setContextProperty("initialViewHeight", 320);
2885 canvas->setSource(testFileUrl("header.qml"));
2887 gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2888 QTRY_VERIFY(gridview != 0);
2889 gridview->setFlow(flow);
2890 gridview->setLayoutDirection(layoutDirection);
2892 gridview->setWidth(240);
2893 gridview->setHeight(320);
2894 QTRY_COMPARE(gridview->headerItem()->pos(), initialHeaderPos);
2895 QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
2900 void tst_QQuickGridView::header_data()
2902 QTest::addColumn<QQuickGridView::Flow>("flow");
2903 QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
2904 QTest::addColumn<QPointF>("initialHeaderPos");
2905 QTest::addColumn<QPointF>("changedHeaderPos");
2906 QTest::addColumn<QPointF>("initialContentPos");
2907 QTest::addColumn<QPointF>("changedContentPos");
2908 QTest::addColumn<QPointF>("firstDelegatePos");
2909 QTest::addColumn<QPointF>("resizeContentPos");
2911 // header1 = 100 x 30
2912 // header2 = 50 x 20
2916 // header above items, top left
2917 QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
2925 // header above items, top right
2926 QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
2927 << QPointF(240 - 100, -30)
2928 << QPointF((240 - 100) + 50, -20) // 50 = width diff between old and new headers
2934 // header to left of items
2935 QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
2943 // header to right of items
2944 QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
2947 << QPointF(-(240 - 100), 0)
2948 << QPointF(-(240 - 50), 0)
2950 << QPointF(-(240 - 40), 0);
2953 void tst_QQuickGridView::resizeViewAndRepaint()
2955 QQuickView *canvas = createView();
2959 for (int i = 0; i < 40; i++)
2960 model.addItem("Item" + QString::number(i), "");
2962 QDeclarativeContext *ctxt = canvas->rootContext();
2963 ctxt->setContextProperty("testModel", &model);
2964 ctxt->setContextProperty("initialHeight", 100);
2966 canvas->setSource(testFileUrl("resizeview.qml"));
2967 qApp->processEvents();
2969 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2970 QTRY_VERIFY(gridview != 0);
2971 QQuickItem *contentItem = gridview->contentItem();
2972 QTRY_VERIFY(contentItem != 0);
2974 // item at index 10 should not be currently visible
2975 QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
2977 gridview->setHeight(320);
2978 QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", 10));
2980 gridview->setHeight(100);
2981 QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
2986 void tst_QQuickGridView::indexAt()
2988 QQuickView *canvas = createView();
2991 model.addItem("Fred", "12345");
2992 model.addItem("John", "2345");
2993 model.addItem("Bob", "54321");
2994 model.addItem("Billy", "22345");
2995 model.addItem("Sam", "2945");
2996 model.addItem("Ben", "04321");
2997 model.addItem("Jim", "0780");
2999 QDeclarativeContext *ctxt = canvas->rootContext();
3000 ctxt->setContextProperty("testModel", &model);
3001 ctxt->setContextProperty("testRightToLeft", QVariant(false));
3002 ctxt->setContextProperty("testTopToBottom", QVariant(false));
3004 canvas->setSource(testFileUrl("gridview1.qml"));
3005 qApp->processEvents();
3007 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3008 QTRY_VERIFY(gridview != 0);
3010 QQuickItem *contentItem = gridview->contentItem();
3011 QTRY_VERIFY(contentItem != 0);
3013 QTRY_COMPARE(gridview->count(), model.count());
3015 QCOMPARE(gridview->indexAt(0, 0), 0);
3016 QCOMPARE(gridview->indexAt(79, 59), 0);
3017 QCOMPARE(gridview->indexAt(80, 0), 1);
3018 QCOMPARE(gridview->indexAt(0, 60), 3);
3019 QCOMPARE(gridview->indexAt(240, 0), -1);
3024 void tst_QQuickGridView::onAdd()
3026 QFETCH(int, initialItemCount);
3027 QFETCH(int, itemsToAdd);
3029 const int delegateWidth = 50;
3030 const int delegateHeight = 100;
3032 QQuickView *canvas = createView();
3033 canvas->setGeometry(0,0,5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit
3035 // these initial items should not trigger GridView.onAdd
3036 for (int i=0; i<initialItemCount; i++)
3037 model.addItem("dummy value", "dummy value");
3039 QDeclarativeContext *ctxt = canvas->rootContext();
3040 ctxt->setContextProperty("testModel", &model);
3041 ctxt->setContextProperty("delegateWidth", delegateWidth);
3042 ctxt->setContextProperty("delegateHeight", delegateHeight);
3043 canvas->setSource(testFileUrl("attachedSignals.qml"));
3045 QObject *object = canvas->rootObject();
3046 object->setProperty("width", canvas->width());
3047 object->setProperty("height", canvas->height());
3048 qApp->processEvents();
3050 QList<QPair<QString, QString> > items;
3051 for (int i=0; i<itemsToAdd; i++)
3052 items << qMakePair(QString("value %1").arg(i), QString::number(i));
3053 model.addItems(items);
3055 QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
3056 qApp->processEvents();
3058 QVariantList result = object->property("addedDelegates").toList();
3059 QTRY_COMPARE(result.count(), items.count());
3060 for (int i=0; i<items.count(); i++)
3061 QCOMPARE(result[i].toString(), items[i].first);
3066 void tst_QQuickGridView::onAdd_data()
3068 QTest::addColumn<int>("initialItemCount");
3069 QTest::addColumn<int>("itemsToAdd");
3071 QTest::newRow("0, add 1") << 0 << 1;
3072 QTest::newRow("0, add 2") << 0 << 2;
3073 QTest::newRow("0, add 10") << 0 << 10;
3075 QTest::newRow("1, add 1") << 1 << 1;
3076 QTest::newRow("1, add 2") << 1 << 2;
3077 QTest::newRow("1, add 10") << 1 << 10;
3079 QTest::newRow("5, add 1") << 5 << 1;
3080 QTest::newRow("5, add 2") << 5 << 2;
3081 QTest::newRow("5, add 10") << 5 << 10;
3084 void tst_QQuickGridView::onRemove()
3086 QFETCH(int, initialItemCount);
3087 QFETCH(int, indexToRemove);
3088 QFETCH(int, removeCount);
3090 const int delegateWidth = 50;
3091 const int delegateHeight = 100;
3093 for (int i=0; i<initialItemCount; i++)
3094 model.addItem(QString("value %1").arg(i), "dummy value");
3096 QQuickView *canvas = createView();
3097 QDeclarativeContext *ctxt = canvas->rootContext();
3098 ctxt->setContextProperty("testModel", &model);
3099 ctxt->setContextProperty("delegateWidth", delegateWidth);
3100 ctxt->setContextProperty("delegateHeight", delegateHeight);
3101 canvas->setSource(testFileUrl("attachedSignals.qml"));
3102 QObject *object = canvas->rootObject();
3104 model.removeItems(indexToRemove, removeCount);
3105 QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
3106 QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
3111 void tst_QQuickGridView::onRemove_data()
3113 QTest::addColumn<int>("initialItemCount");
3114 QTest::addColumn<int>("indexToRemove");
3115 QTest::addColumn<int>("removeCount");
3117 QTest::newRow("remove first") << 1 << 0 << 1;
3118 QTest::newRow("two items, remove first") << 2 << 0 << 1;
3119 QTest::newRow("two items, remove last") << 2 << 1 << 1;
3120 QTest::newRow("two items, remove all") << 2 << 0 << 2;
3122 QTest::newRow("four items, remove first") << 4 << 0 << 1;
3123 QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
3124 QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
3125 QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
3126 QTest::newRow("four items, remove last") << 4 << 3 << 1;
3127 QTest::newRow("four items, remove all") << 4 << 0 << 4;
3129 QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
3130 QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
3131 QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
3134 void tst_QQuickGridView::columnCount()
3137 canvas.setSource(testFileUrl("gridview4.qml"));
3139 canvas.requestActivateWindow();
3140 QTest::qWaitForWindowShown(&canvas);
3142 QQuickGridView *view = qobject_cast<QQuickGridView*>(canvas.rootObject());
3144 QCOMPARE(view->cellWidth(), qreal(405)/qreal(9));
3145 QCOMPARE(view->cellHeight(), qreal(100));
3147 QList<QQuickItem*> items = findItems<QQuickItem>(view, "delegate");
3148 QCOMPARE(items.size(), 18);
3149 QCOMPARE(items.at(8)->y(), qreal(0));
3150 QCOMPARE(items.at(9)->y(), qreal(100));
3153 void tst_QQuickGridView::margins()
3156 QQuickView *canvas = createView();
3160 for (int i = 0; i < 40; i++)
3161 model.addItem("Item" + QString::number(i), "");
3163 QDeclarativeContext *ctxt = canvas->rootContext();
3164 ctxt->setContextProperty("testModel", &model);
3165 ctxt->setContextProperty("testRightToLeft", QVariant(false));
3167 canvas->setSource(testFileUrl("margins.qml"));
3168 qApp->processEvents();
3170 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3171 QTRY_VERIFY(gridview != 0);
3173 QQuickItem *contentItem = gridview->contentItem();
3174 QTRY_VERIFY(contentItem != 0);
3176 QCOMPARE(gridview->contentX(), -30.);
3177 QCOMPARE(gridview->xOrigin(), 0.);
3180 gridview->positionViewAtEnd();
3181 qreal pos = gridview->contentX();
3182 gridview->setContentX(pos + 80);
3183 gridview->returnToBounds();
3184 QTRY_COMPARE(gridview->contentX(), pos + 50);
3186 // remove item before visible and check that left margin is maintained
3187 // and xOrigin is updated
3188 gridview->setContentX(200);
3189 model.removeItems(0, 4);
3191 gridview->setContentX(-50);
3192 gridview->returnToBounds();
3193 QCOMPARE(gridview->xOrigin(), 100.);
3194 QTRY_COMPARE(gridview->contentX(), 70.);
3196 // reduce left margin
3197 gridview->setLeftMargin(20);
3198 QCOMPARE(gridview->xOrigin(), 100.);
3199 QTRY_COMPARE(gridview->contentX(), 80.);
3202 gridview->positionViewAtEnd();
3203 QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
3204 pos = gridview->contentX();
3205 gridview->setContentX(pos + 80);
3206 gridview->returnToBounds();
3207 QTRY_COMPARE(gridview->contentX(), pos + 50);
3209 // reduce right margin
3210 pos = gridview->contentX();
3211 gridview->setRightMargin(40);
3212 QCOMPARE(gridview->xOrigin(), 0.);
3213 QTRY_COMPARE(gridview->contentX(), pos-10);
3219 QQuickView *canvas = createView();
3223 for (int i = 0; i < 40; i++)
3224 model.addItem("Item" + QString::number(i), "");
3226 QDeclarativeContext *ctxt = canvas->rootContext();
3227 ctxt->setContextProperty("testModel", &model);
3228 ctxt->setContextProperty("testRightToLeft", QVariant(true));
3230 canvas->setSource(testFileUrl("margins.qml"));
3231 qApp->processEvents();
3233 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3234 QTRY_VERIFY(gridview != 0);
3236 QQuickItem *contentItem = gridview->contentItem();
3237 QTRY_VERIFY(contentItem != 0);
3239 QCOMPARE(gridview->contentX(), -240+30.);
3240 QCOMPARE(gridview->xOrigin(), 0.);
3243 gridview->positionViewAtEnd();
3244 qreal pos = gridview->contentX();
3245 gridview->setContentX(pos - 80);
3246 gridview->returnToBounds();
3247 QTRY_COMPARE(gridview->contentX(), pos - 50);
3249 // remove item before visible and check that left margin is maintained
3250 // and xOrigin is updated
3251 gridview->setContentX(-400);
3252 model.removeItems(0, 4);
3254 gridview->setContentX(-240+50);
3255 gridview->returnToBounds();
3256 QCOMPARE(gridview->xOrigin(), -100.);
3257 QTRY_COMPARE(gridview->contentX(), -240-70.);
3259 // reduce left margin (i.e. right side due to RTL)
3260 pos = gridview->contentX();
3261 gridview->setLeftMargin(20);
3262 QCOMPARE(gridview->xOrigin(), -100.);
3263 QTRY_COMPARE(gridview->contentX(), -240-80.);
3266 gridview->positionViewAtEnd();
3267 QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
3268 pos = gridview->contentX();
3269 gridview->setContentX(pos - 80);
3270 gridview->returnToBounds();
3271 QTRY_COMPARE(gridview->contentX(), pos - 50);
3273 // reduce right margin (i.e. left side due to RTL)
3274 pos = gridview->contentX();
3275 gridview->setRightMargin(40);
3276 QCOMPARE(gridview->xOrigin(), 0.);
3277 QTRY_COMPARE(gridview->contentX(), pos+10);
3283 void tst_QQuickGridView::creationContext()
3286 canvas.setGeometry(0,0,240,320);
3287 canvas.setSource(testFileUrl("creationContext.qml"));
3288 qApp->processEvents();
3290 QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
3292 QVERIFY(rootItem->property("count").toInt() > 0);
3295 QVERIFY(item = rootItem->findChild<QQuickItem *>("listItem"));
3296 QCOMPARE(item->property("text").toString(), QString("Hello!"));
3297 QVERIFY(item = rootItem->findChild<QQuickItem *>("header"));
3298 QCOMPARE(item->property("text").toString(), QString("Hello!"));
3299 QVERIFY(item = rootItem->findChild<QQuickItem *>("footer"));
3300 QCOMPARE(item->property("text").toString(), QString("Hello!"));
3303 void tst_QQuickGridView::snapToRow_data()
3305 QTest::addColumn<QQuickGridView::Flow>("flow");
3306 QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
3307 QTest::addColumn<int>("highlightRangeMode");
3308 QTest::addColumn<QPoint>("flickStart");
3309 QTest::addColumn<QPoint>("flickEnd");
3310 QTest::addColumn<qreal>("snapAlignment");
3311 QTest::addColumn<qreal>("endExtent");
3312 QTest::addColumn<qreal>("startExtent");
3314 QTest::newRow("vertical, left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
3315 << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
3317 QTest::newRow("horizontal, left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
3318 << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
3320 QTest::newRow("horizontal, right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
3321 << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
3323 QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
3324 << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
3326 QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
3327 << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
3329 QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
3330 << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
3333 void tst_QQuickGridView::snapToRow()
3335 QFETCH(QQuickGridView::Flow, flow);
3336 QFETCH(Qt::LayoutDirection, layoutDirection);
3337 QFETCH(int, highlightRangeMode);
3338 QFETCH(QPoint, flickStart);
3339 QFETCH(QPoint, flickEnd);
3340 QFETCH(qreal, snapAlignment);
3341 QFETCH(qreal, endExtent);
3342 QFETCH(qreal, startExtent);
3344 QQuickView *canvas = createView();
3346 canvas->setSource(testFileUrl("snapToRow.qml"));
3348 qApp->processEvents();
3350 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3351 QTRY_VERIFY(gridview != 0);
3353 gridview->setFlow(flow);
3354 gridview->setLayoutDirection(layoutDirection);
3355 gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
3357 QQuickItem *contentItem = gridview->contentItem();
3358 QTRY_VERIFY(contentItem != 0);
3360 // confirm that a flick hits an item boundary
3361 flick(canvas, flickStart, flickEnd, 180);
3362 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3363 if (flow == QQuickGridView::LeftToRight)
3364 QCOMPARE(qreal(fmod(gridview->contentY(),80.0)), snapAlignment);
3366 QCOMPARE(qreal(fmod(gridview->contentX(),80.0)), snapAlignment);
3370 flick(canvas, flickStart, flickEnd, 180);
3371 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3372 } while (flow == QQuickGridView::LeftToRight
3373 ? !gridview->isAtYEnd()
3374 : layoutDirection == Qt::LeftToRight ? !gridview->isAtXEnd() : !gridview->isAtXBeginning());
3376 if (flow == QQuickGridView::LeftToRight)
3377 QCOMPARE(gridview->contentY(), endExtent);
3379 QCOMPARE(gridview->contentX(), endExtent);
3383 flick(canvas, flickEnd, flickStart, 180);
3384 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3385 } while (flow == QQuickGridView::LeftToRight
3386 ? !gridview->isAtYBeginning()
3387 : layoutDirection == Qt::LeftToRight ? !gridview->isAtXBeginning() : !gridview->isAtXEnd());
3389 if (flow == QQuickGridView::LeftToRight)
3390 QCOMPARE(gridview->contentY(), startExtent);
3392 QCOMPARE(gridview->contentX(), startExtent);
3397 void tst_QQuickGridView::snapOneRow_data()
3399 QTest::addColumn<QQuickGridView::Flow>("flow");
3400 QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
3401 QTest::addColumn<int>("highlightRangeMode");
3402 QTest::addColumn<QPoint>("flickStart");
3403 QTest::addColumn<QPoint>("flickEnd");
3404 QTest::addColumn<qreal>("snapAlignment");
3405 QTest::addColumn<qreal>("endExtent");
3406 QTest::addColumn<qreal>("startExtent");
3408 QTest::newRow("vertical, left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
3409 << QPoint(20, 200) << QPoint(20, 20) << 100.0 << 360.0 << 0.0;
3411 QTest::newRow("horizontal, left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
3412 << QPoint(200, 20) << QPoint(20, 20) << 100.0 << 360.0 << 0.0;
3414 QTest::newRow("horizontal, right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
3415 << QPoint(20, 20) << QPoint(200, 20) << -340.0 << -360.0 - 240.0 << -240.0;
3417 QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
3418 << QPoint(20, 200) << QPoint(20, 20) << 100.0 << 460.0 << -20.0;
3420 QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
3421 << QPoint(200, 20) << QPoint(20, 20) << 100.0 << 460.0 << -20.0;
3423 QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
3424 << QPoint(20, 20) << QPoint(200, 20) << -340.0 << -360.0 - 240.0 - 100.0 << -220.0;
3427 void tst_QQuickGridView::snapOneRow()
3429 QFETCH(QQuickGridView::Flow, flow);
3430 QFETCH(Qt::LayoutDirection, layoutDirection);
3431 QFETCH(int, highlightRangeMode);
3432 QFETCH(QPoint, flickStart);
3433 QFETCH(QPoint, flickEnd);
3434 QFETCH(qreal, snapAlignment);
3435 QFETCH(qreal, endExtent);
3436 QFETCH(qreal, startExtent);
3438 QQuickView *canvas = createView();
3440 canvas->setSource(testFileUrl("snapOneRow.qml"));
3442 qApp->processEvents();
3444 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3445 QTRY_VERIFY(gridview != 0);
3447 gridview->setFlow(flow);
3448 gridview->setLayoutDirection(layoutDirection);
3449 gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
3451 QQuickItem *contentItem = gridview->contentItem();
3452 QTRY_VERIFY(contentItem != 0);
3454 QSignalSpy currentIndexSpy(gridview, SIGNAL(currentIndexChanged()));
3456 // confirm that a flick hits next row boundary
3457 flick(canvas, flickStart, flickEnd, 180);
3458 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3459 if (flow == QQuickGridView::LeftToRight)
3460 QCOMPARE(gridview->contentY(), snapAlignment);
3462 QCOMPARE(gridview->contentX(), snapAlignment);
3464 if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
3465 QCOMPARE(gridview->currentIndex(), 2);
3466 QCOMPARE(currentIndexSpy.count(), 1);
3471 flick(canvas, flickStart, flickEnd, 180);
3472 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3473 } while (flow == QQuickGridView::LeftToRight
3474 ? !gridview->isAtYEnd()
3475 : layoutDirection == Qt::LeftToRight ? !gridview->isAtXEnd() : !gridview->isAtXBeginning());
3477 if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
3478 QCOMPARE(gridview->currentIndex(), 8);
3479 QCOMPARE(currentIndexSpy.count(), 4);
3482 if (flow == QQuickGridView::LeftToRight)
3483 QCOMPARE(gridview->contentY(), endExtent);
3485 QCOMPARE(gridview->contentX(), endExtent);
3489 flick(canvas, flickEnd, flickStart, 180);
3490 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3491 } while (flow == QQuickGridView::LeftToRight
3492 ? !gridview->isAtYBeginning()
3493 : layoutDirection == Qt::LeftToRight ? !gridview->isAtXBeginning() : !gridview->isAtXEnd());
3495 if (flow == QQuickGridView::LeftToRight)
3496 QCOMPARE(gridview->contentY(), startExtent);
3498 QCOMPARE(gridview->contentX(), startExtent);
3500 if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
3501 QCOMPARE(gridview->currentIndex(), 0);
3502 QCOMPARE(currentIndexSpy.count(), 8);
3509 void tst_QQuickGridView::unaligned()
3511 QQuickView *canvas = createView();
3515 for (int i = 0; i < 10; i++)
3516 model.addItem("Item" + QString::number(i), "");
3518 QDeclarativeContext *ctxt = canvas->rootContext();
3519 ctxt->setContextProperty("testModel", &model);
3521 canvas->setSource(testFileUrl("unaligned.qml"));
3522 qApp->processEvents();
3524 QQuickGridView *gridview = qobject_cast<QQuickGridView*>(canvas->rootObject());
3525 QVERIFY(gridview != 0);
3527 QQuickItem *contentItem = gridview->contentItem();
3528 QVERIFY(contentItem != 0);
3530 for (int i = 0; i < 10; ++i) {
3531 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3532 if (!item) qWarning() << "Item" << i << "not found";
3534 QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
3535 QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
3539 for (int i = 10; i < 18; ++i) {
3540 model.addItem("Item" + QString::number(i), "");
3541 QQuickItem *item = 0;
3542 QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
3543 QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
3544 QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
3548 for (int i = 0; i < 10; ++i) {
3549 model.insertItem(i, "Item" + QString::number(i), "");
3550 QQuickItem *item = 0;
3551 QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
3552 QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
3553 QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
3557 model.removeItems(7, 10);
3558 QTRY_COMPARE(model.count(), gridview->count());
3559 for (int i = 0; i < 18; ++i) {
3560 QQuickItem *item = 0;
3561 QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
3562 QCOMPARE(item->x(), qreal(i%9)*gridview->cellWidth());
3563 QCOMPARE(item->y(), qreal(i/9)*gridview->cellHeight());
3569 QQuickView *tst_QQuickGridView::createView()
3571 QQuickView *canvas = new QQuickView(0);
3572 canvas->setGeometry(0,0,240,320);
3577 void tst_QQuickGridView::flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration)
3579 const int pointCount = 5;
3580 QPoint diff = to - from;
3582 // send press, five equally spaced moves, and release.
3583 QTest::mousePress(canvas, Qt::LeftButton, 0, from);
3585 for (int i = 0; i < pointCount; ++i) {
3586 QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
3587 QApplication::sendEvent(canvas, &mv);
3588 QTest::qWait(duration/pointCount);
3589 QCoreApplication::processEvents();
3592 QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
3595 void tst_QQuickGridView::cacheBuffer()
3597 QQuickView *canvas = createView();
3600 for (int i = 0; i < 90; i++)
3601 model.addItem("Item" + QString::number(i), "");
3603 QDeclarativeContext *ctxt = canvas->rootContext();
3604 ctxt->setContextProperty("testModel", &model);
3605 ctxt->setContextProperty("testRightToLeft", QVariant(false));
3606 ctxt->setContextProperty("testTopToBottom", QVariant(false));
3608 canvas->setSource(testFileUrl("gridview1.qml"));
3610 qApp->processEvents();
3612 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3613 QVERIFY(gridview != 0);
3615 QQuickItem *contentItem = gridview->contentItem();
3616 QVERIFY(contentItem != 0);
3617 QVERIFY(gridview->delegate() != 0);
3618 QVERIFY(gridview->model() != 0);
3620 // Confirm items positioned correctly
3621 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
3622 for (int i = 0; i < model.count() && i < itemCount; ++i) {
3623 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3624 QTRY_COMPARE(item->x(), (i%3)*80.0);
3625 QTRY_COMPARE(item->y(), (i/3)*60.0);
3628 QDeclarativeIncubationController controller;
3629 canvas->engine()->setIncubationController(&controller);
3631 canvas->rootObject()->setProperty("cacheBuffer", 200);
3632 QTRY_VERIFY(gridview->cacheBuffer() == 200);
3634 // items will be created one at a time
3635 for (int i = itemCount; i < qMin(itemCount+9,model.count()); ++i) {
3636 QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
3637 QQuickItem *item = 0;
3640 controller.incubateWhile(&b);
3641 item = findItem<QQuickItem>(gridview, "wrapper", i);
3647 controller.incubateWhile(&b);
3650 int newItemCount = 0;
3651 newItemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
3653 // Confirm items positioned correctly
3654 for (int i = 0; i < model.count() && i < newItemCount; ++i) {
3655 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3657 QTRY_COMPARE(item->x(), (i%3)*80.0);
3658 QTRY_COMPARE(item->y(), (i/3)*60.0);
3661 // move view and confirm items in view are visible immediately and outside are created async
3662 gridview->setContentY(300);
3664 for (int i = 15; i < 34; ++i) { // 34 due to staggered item creation
3665 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3667 QTRY_COMPARE(item->x(), (i%3)*80.0);
3668 QTRY_COMPARE(item->y(), (i/3)*60.0);
3671 QVERIFY(findItem<QQuickItem>(gridview, "wrapper", 34) == 0);
3673 // ensure buffered items are created
3674 for (int i = 34; i < qMin(44,model.count()); ++i) {
3675 QQuickItem *item = 0;
3677 qGuiApp->processEvents(); // allow refill to happen
3679 controller.incubateWhile(&b);
3680 item = findItem<QQuickItem>(gridview, "wrapper", i);
3686 controller.incubateWhile(&b);
3692 void tst_QQuickGridView::asynchronous()
3694 QQuickView *canvas = createView();
3696 QDeclarativeIncubationController controller;
3697 canvas->engine()->setIncubationController(&controller);
3699 canvas->setSource(testFile("asyncloader.qml"));
3701 QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
3702 QVERIFY(rootObject);
3704 QQuickGridView *gridview = 0;
3707 controller.incubateWhile(&b);
3708 gridview = rootObject->findChild<QQuickGridView*>("view");
3711 // items will be created one at a time
3712 for (int i = 0; i < 12; ++i) {
3713 QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
3714 QQuickItem *item = 0;
3717 controller.incubateWhile(&b);
3718 item = findItem<QQuickItem>(gridview, "wrapper", i);
3724 controller.incubateWhile(&b);
3727 // verify positioning
3728 QQuickItem *contentItem = gridview->contentItem();
3729 for (int i = 0; i < 12; ++i) {
3730 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3731 if (!item) qWarning() << "Item" << i << "not found";
3732 QVERIFY(item->x() == (i%3)*100);
3733 QVERIFY(item->y() == (i/3)*100);
3739 void tst_QQuickGridView::unrequestedVisibility()
3742 for (int i = 0; i < 30; i++)
3743 model.addItem("Item" + QString::number(i), QString::number(i));
3745 QQuickView *canvas = new QQuickView(0);
3746 canvas->setGeometry(0,0,240,320);
3748 QDeclarativeContext *ctxt = canvas->rootContext();
3749 ctxt->setContextProperty("testModel", &model);
3750 ctxt->setContextProperty("testWrap", QVariant(false));
3752 canvas->setSource(testFileUrl("unrequestedItems.qml"));
3756 qApp->processEvents();
3758 QQuickGridView *leftview = findItem<QQuickGridView>(canvas->rootObject(), "leftGrid");
3759 QTRY_VERIFY(leftview != 0);
3761 QQuickGridView *rightview = findItem<QQuickGridView>(canvas->rootObject(), "rightGrid");
3762 QTRY_VERIFY(rightview != 0);
3764 QQuickItem *leftContent = leftview->contentItem();
3765 QTRY_VERIFY(leftContent != 0);
3767 QQuickItem *rightContent = rightview->contentItem();
3768 QTRY_VERIFY(rightContent != 0);
3770 rightview->setCurrentIndex(12);
3772 QTRY_COMPARE(leftview->contentY(), 0.0);
3773 QTRY_COMPARE(rightview->contentY(), 240.0);
3777 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3778 QCOMPARE(item->isVisible(), true);
3779 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
3780 QCOMPARE(item->isVisible(), false);
3782 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
3783 QCOMPARE(item->isVisible(), false);
3784 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
3785 QCOMPARE(item->isVisible(), true);
3787 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 9));
3788 QCOMPARE(item->isVisible(), true);
3789 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 10));
3790 QCOMPARE(item->isVisible(), false);
3791 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 3));
3792 QCOMPARE(item->isVisible(), false);
3793 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 4));
3794 QCOMPARE(item->isVisible(), true);
3796 rightview->setCurrentIndex(0);
3798 QTRY_COMPARE(leftview->contentY(), 0.0);
3799 QTRY_COMPARE(rightview->contentY(), 0.0);
3801 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3802 QCOMPARE(item->isVisible(), true);
3803 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
3804 QTRY_COMPARE(item->isVisible(), true);
3806 QVERIFY(!findItem<QQuickItem>(leftContent, "wrapper", 11));
3807 QVERIFY(!findItem<QQuickItem>(rightContent, "wrapper", 11));
3809 leftview->setCurrentIndex(12);
3811 QTRY_COMPARE(leftview->contentY(), 240.0);
3812 QTRY_COMPARE(rightview->contentY(), 0.0);
3814 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3815 QTRY_COMPARE(item->isVisible(), false);
3816 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
3817 QCOMPARE(item->isVisible(), true);
3819 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
3820 QCOMPARE(item->isVisible(), true);
3821 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
3822 QCOMPARE(item->isVisible(), false);
3824 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
3825 QCOMPARE(item->isVisible(), false);
3826 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
3827 QCOMPARE(item->isVisible(), true);
3828 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3829 QCOMPARE(item->isVisible(), true);
3830 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3831 QCOMPARE(item->isVisible(), false);
3833 model.moveItems(19, 1, 1);
3834 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3836 QTRY_VERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3837 QCOMPARE(item->isVisible(), false);
3838 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
3839 QCOMPARE(item->isVisible(), true);
3841 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
3842 QCOMPARE(item->isVisible(), true);
3843 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
3844 QCOMPARE(item->isVisible(), false);
3846 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
3847 QCOMPARE(item->isVisible(), false);
3848 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
3849 QCOMPARE(item->isVisible(), true);
3850 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3851 QCOMPARE(item->isVisible(), true);
3852 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3853 QCOMPARE(item->isVisible(), false);
3855 model.moveItems(3, 4, 1);
3856 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3858 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3859 QCOMPARE(item->isVisible(), false);
3860 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
3861 QCOMPARE(item->isVisible(), true);
3862 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3863 QCOMPARE(item->isVisible(), true);
3864 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3865 QCOMPARE(item->isVisible(), false);
3867 model.moveItems(4, 5, 1);
3868 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3870 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3871 QCOMPARE(item->isVisible(), false);
3872 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
3873 QCOMPARE(item->isVisible(), true);
3874 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3875 QCOMPARE(item->isVisible(), true);
3876 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3877 QCOMPARE(item->isVisible(), false);
3879 model.moveItems(9, 10, 1);
3880 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3882 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3883 QCOMPARE(item->isVisible(), false);
3884 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
3885 QCOMPARE(item->isVisible(), true);
3886 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3887 QCOMPARE(item->isVisible(), true);
3888 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3889 QCOMPARE(item->isVisible(), false);
3891 model.moveItems(10, 9, 1);
3892 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3894 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3895 QCOMPARE(item->isVisible(), false);
3896 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
3897 QCOMPARE(item->isVisible(), true);
3898 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3899 QCOMPARE(item->isVisible(), true);
3900 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3901 QCOMPARE(item->isVisible(), false);
3907 Find an item with the specified objectName. If index is supplied then the
3908 item must also evaluate the {index} expression equal to index
3910 template<typename T>
3911 T *tst_QQuickGridView::findItem(QQuickItem *parent, const QString &objectName, int index)
3913 const QMetaObject &mo = T::staticMetaObject;
3914 //qDebug() << parent->childItems().count() << "children";
3915 for (int i = 0; i < parent->childItems().count(); ++i) {
3916 QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
3919 //qDebug() << "try" << item;
3920 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
3922 QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
3924 if (context->contextProperty("index").toInt() == index) {
3925 return static_cast<T*>(item);
3929 return static_cast<T*>(item);
3932 item = findItem<T>(item, objectName, index);
3934 return static_cast<T*>(item);
3940 template<typename T>
3941 QList<T*> tst_QQuickGridView::findItems(QQuickItem *parent, const QString &objectName)
3944 const QMetaObject &mo = T::staticMetaObject;
3945 //qDebug() << parent->childItems().count() << "children";
3946 for (int i = 0; i < parent->childItems().count(); ++i) {
3947 QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
3950 //qDebug() << "try" << item;
3951 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
3952 items.append(static_cast<T*>(item));
3953 //qDebug() << " found:" << item;
3955 items += findItems<T>(item, objectName);
3961 void tst_QQuickGridView::dumpTree(QQuickItem *parent, int depth)
3963 static QString padding(" ");
3964 for (int i = 0; i < parent->childItems().count(); ++i) {
3965 QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
3968 QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
3969 qDebug() << padding.left(depth*2) << item << (context ? context->contextProperty("index").toInt() : -1);
3970 dumpTree(item, depth+1);
3975 QTEST_MAIN(tst_QQuickGridView)
3977 #include "tst_qquickgridview.moc"