1 /****************************************************************************
3 ** Copyright (C) 2011 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 QObject
69 void cleanupTestCase();
74 void inserted_more_data();
75 void insertBeforeVisible();
76 void insertBeforeVisible_data();
78 void addOrRemoveBeforeVisible();
79 void addOrRemoveBeforeVisible_data();
83 void multipleChanges();
84 void multipleChanges_data();
85 void swapWithFirstItem();
88 void noCurrentIndex();
91 void propertyChanges();
92 void componentChanges();
94 void positionViewAtIndex();
95 void positionViewAtIndex_rightToLeft();
100 void enforceRange_rightToLeft();
102 void manualHighlight();
107 void resizeViewAndRepaint();
112 void onRemove_data();
115 void creationContext();
116 void snapToRow_data();
118 void snapOneRow_data();
123 void unrequestedVisibility();
126 QQuickView *createView();
127 void flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration);
129 T *findItem(QQuickItem *parent, const QString &id, int index=-1);
131 QList<T*> findItems(QQuickItem *parent, const QString &objectName);
132 void dumpTree(QQuickItem *parent, int depth = 0);
136 void tst_qquickgridview_move(int from, int to, int n, T *items)
139 // Only move forwards - flip if backwards moving
149 typename T::ConstIterator it=items->begin(); it += from+n;
150 for (; i<to-from; ++i,++it)
151 replaced.append(*it);
153 it=items->begin(); it += from;
154 for (; i<n; ++i,++it)
155 replaced.append(*it);
156 typename T::ConstIterator f=replaced.begin();
157 typename T::Iterator t=items->begin(); t += from;
158 for (; f != replaced.end(); ++f, ++t)
162 void tst_QQuickGridView::initTestCase()
166 void tst_QQuickGridView::cleanupTestCase()
172 class TestModel : public QAbstractListModel
175 enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
177 TestModel(QObject *parent=0) : QAbstractListModel(parent) {
178 QHash<int, QByteArray> roles;
179 roles[Name] = "name";
180 roles[Number] = "number";
184 int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
185 QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
188 rv = list.at(index.row()).first;
189 else if (role == Number)
190 rv = list.at(index.row()).second;
195 int count() const { return rowCount(); }
196 QString name(int index) const { return list.at(index).first; }
197 QString number(int index) const { return list.at(index).second; }
199 void addItem(const QString &name, const QString &number) {
200 emit beginInsertRows(QModelIndex(), list.count(), list.count());
201 list.append(QPair<QString,QString>(name, number));
202 emit endInsertRows();
205 void addItems(const QList<QPair<QString, QString> > &items) {
206 emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1);
207 for (int i=0; i<items.count(); i++)
208 list.append(QPair<QString,QString>(items[i].first, items[i].second));
209 emit endInsertRows();
212 void insertItem(int index, const QString &name, const QString &number) {
213 emit beginInsertRows(QModelIndex(), index, index);
214 list.insert(index, QPair<QString,QString>(name, number));
215 emit endInsertRows();
218 void insertItems(int index, const QList<QPair<QString, QString> > &items) {
219 emit beginInsertRows(QModelIndex(), index, index + items.count() - 1);
220 for (int i=0; i<items.count(); i++)
221 list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
222 emit endInsertRows();
225 void removeItem(int index) {
226 emit beginRemoveRows(QModelIndex(), index, index);
227 list.removeAt(index);
228 emit endRemoveRows();
231 void removeItems(int index, int count) {
232 emit beginRemoveRows(QModelIndex(), index, index+count-1);
234 list.removeAt(index);
235 emit endRemoveRows();
238 void moveItem(int from, int to) {
239 emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
244 void moveItems(int from, int to, int count) {
245 emit beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
246 tst_qquickgridview_move(from, to, count, &list);
250 void modifyItem(int idx, const QString &name, const QString &number) {
251 list[idx] = QPair<QString,QString>(name, number);
252 emit dataChanged(index(idx,0), index(idx,0));
256 int count = list.count();
257 emit beginRemoveRows(QModelIndex(), 0, count-1);
259 emit endRemoveRows();
264 QList<QPair<QString,QString> > list;
267 tst_QQuickGridView::tst_QQuickGridView()
271 void tst_QQuickGridView::items()
273 QQuickView *canvas = createView();
276 model.addItem("Fred", "12345");
277 model.addItem("John", "2345");
278 model.addItem("Bob", "54321");
279 model.addItem("Billy", "22345");
280 model.addItem("Sam", "2945");
281 model.addItem("Ben", "04321");
282 model.addItem("Jim", "0780");
284 QDeclarativeContext *ctxt = canvas->rootContext();
285 ctxt->setContextProperty("testModel", &model);
286 ctxt->setContextProperty("testRightToLeft", QVariant(false));
287 ctxt->setContextProperty("testTopToBottom", QVariant(false));
289 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
290 qApp->processEvents();
292 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
293 QTRY_VERIFY(gridview != 0);
295 QQuickItem *contentItem = gridview->contentItem();
296 QTRY_VERIFY(contentItem != 0);
298 QTRY_COMPARE(gridview->count(), model.count());
299 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
300 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
302 for (int i = 0; i < model.count(); ++i) {
303 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
304 QTRY_VERIFY(name != 0);
305 QTRY_COMPARE(name->text(), model.name(i));
306 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
307 QTRY_VERIFY(number != 0);
308 QTRY_COMPARE(number->text(), model.number(i));
311 // set an empty model and confirm that items are destroyed
313 ctxt->setContextProperty("testModel", &model2);
315 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
316 QTRY_VERIFY(itemCount == 0);
321 void tst_QQuickGridView::changed()
323 QQuickView *canvas = createView();
326 model.addItem("Fred", "12345");
327 model.addItem("John", "2345");
328 model.addItem("Bob", "54321");
329 model.addItem("Billy", "22345");
330 model.addItem("Sam", "2945");
331 model.addItem("Ben", "04321");
332 model.addItem("Jim", "0780");
334 QDeclarativeContext *ctxt = canvas->rootContext();
335 ctxt->setContextProperty("testModel", &model);
336 ctxt->setContextProperty("testRightToLeft", QVariant(false));
337 ctxt->setContextProperty("testTopToBottom", QVariant(false));
339 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
340 qApp->processEvents();
342 QQuickFlickable *gridview = findItem<QQuickFlickable>(canvas->rootObject(), "grid");
343 QTRY_VERIFY(gridview != 0);
345 QQuickItem *contentItem = gridview->contentItem();
346 QTRY_VERIFY(contentItem != 0);
348 model.modifyItem(1, "Will", "9876");
349 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
350 QTRY_VERIFY(name != 0);
351 QTRY_COMPARE(name->text(), model.name(1));
352 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
353 QTRY_VERIFY(number != 0);
354 QTRY_COMPARE(number->text(), model.number(1));
359 void tst_QQuickGridView::inserted()
361 QQuickView *canvas = createView();
365 model.addItem("Fred", "12345");
366 model.addItem("John", "2345");
367 model.addItem("Bob", "54321");
369 QDeclarativeContext *ctxt = canvas->rootContext();
370 ctxt->setContextProperty("testModel", &model);
371 ctxt->setContextProperty("testRightToLeft", QVariant(false));
372 ctxt->setContextProperty("testTopToBottom", QVariant(false));
374 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
375 qApp->processEvents();
377 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
378 QTRY_VERIFY(gridview != 0);
380 QQuickItem *contentItem = gridview->contentItem();
381 QTRY_VERIFY(contentItem != 0);
383 model.insertItem(1, "Will", "9876");
385 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
386 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
388 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
389 QTRY_VERIFY(name != 0);
390 QTRY_COMPARE(name->text(), model.name(1));
391 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
392 QTRY_VERIFY(number != 0);
393 QTRY_COMPARE(number->text(), model.number(1));
395 // Checks that onAdd is called
396 int added = canvas->rootObject()->property("added").toInt();
397 QTRY_COMPARE(added, 1);
399 // Confirm items positioned correctly
400 for (int i = 0; i < model.count(); ++i) {
401 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
402 QTRY_COMPARE(item->x(), (i%3)*80.0);
403 QTRY_COMPARE(item->y(), (i/3)*60.0);
406 model.insertItem(0, "Foo", "1111"); // zero index, and current item
408 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
410 name = findItem<QQuickText>(contentItem, "textName", 0);
411 QTRY_VERIFY(name != 0);
412 QTRY_COMPARE(name->text(), model.name(0));
413 number = findItem<QQuickText>(contentItem, "textNumber", 0);
414 QTRY_VERIFY(number != 0);
415 QTRY_COMPARE(number->text(), model.number(0));
417 QTRY_COMPARE(gridview->currentIndex(), 1);
419 // Confirm items positioned correctly
420 for (int i = 0; i < model.count(); ++i) {
421 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
422 QTRY_VERIFY(item->x() == (i%3)*80);
423 QTRY_VERIFY(item->y() == (i/3)*60);
426 for (int i = model.count(); i < 30; ++i)
427 model.insertItem(i, "Hello", QString::number(i));
429 gridview->setContentY(120);
431 // Insert item outside visible area
432 model.insertItem(1, "Hello", "1324");
434 QTRY_VERIFY(gridview->contentY() == 120);
439 void tst_QQuickGridView::inserted_more()
441 QFETCH(qreal, contentY);
442 QFETCH(int, insertIndex);
443 QFETCH(int, insertCount);
444 QFETCH(qreal, itemsOffsetAfterMove);
448 QQuickView *canvas = createView();
452 for (int i = 0; i < 30; i++)
453 model.addItem("Item" + QString::number(i), "");
455 QDeclarativeContext *ctxt = canvas->rootContext();
456 ctxt->setContextProperty("testModel", &model);
457 ctxt->setContextProperty("testRightToLeft", QVariant(false));
458 ctxt->setContextProperty("testTopToBottom", QVariant(false));
460 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
461 qApp->processEvents();
463 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
464 QTRY_VERIFY(gridview != 0);
465 QQuickItem *contentItem = gridview->contentItem();
466 QTRY_VERIFY(contentItem != 0);
468 gridview->setContentY(contentY);
470 QList<QPair<QString, QString> > newData;
471 for (int i=0; i<insertCount; i++)
472 newData << qMakePair(QString("value %1").arg(i), QString::number(i));
473 model.insertItems(insertIndex, newData);
474 QTRY_COMPARE(gridview->property("count").toInt(), model.count());
476 // check visibleItems.first() is in correct position
477 QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
479 QCOMPARE(item0->y(), itemsOffsetAfterMove);
481 QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
482 int firstVisibleIndex = -1;
483 for (int i=0; i<items.count(); i++) {
484 if (items[i]->y() >= contentY) {
485 QDeclarativeExpression e(qmlContext(items[i]), items[i], "index");
486 firstVisibleIndex = e.evaluate().toInt();
490 QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex));
492 // Confirm items positioned correctly and indexes correct
493 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
494 for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
495 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
496 QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
498 QCOMPARE(item->x(), (i%3)*80.0);
499 QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
501 name = findItem<QQuickText>(contentItem, "textName", i);
503 QCOMPARE(name->text(), model.name(i));
504 number = findItem<QQuickText>(contentItem, "textNumber", i);
505 QVERIFY(number != 0);
506 QCOMPARE(number->text(), model.number(i));
512 void tst_QQuickGridView::inserted_more_data()
514 QTest::addColumn<qreal>("contentY");
515 QTest::addColumn<int>("insertIndex");
516 QTest::addColumn<int>("insertCount");
517 QTest::addColumn<qreal>("itemsOffsetAfterMove");
519 QTest::newRow("add 1, before visible items")
520 << 120.0 // show 6-23
522 << 0.0; // insert 1 above first visible, grid is rearranged; first visible moves forward within its row
523 // new 1st visible item is at 0
525 QTest::newRow("add 2, before visible items")
526 << 120.0 // show 6-23
528 << 0.0; // insert 2 above first visible, grid is rearranged; first visible moves forward within its row
530 QTest::newRow("add 3, before visible items")
531 << 120.0 // show 6-23
533 << -60.0; // insert 3 (1 row) above first visible in negative pos, first visible does not move
535 QTest::newRow("add 5, before visible items")
536 << 120.0 // show 6-23
538 << -60.0; // insert 1 row + 2 items above first visible, 1 row added at negative pos,
539 // grid is rearranged and first visible moves forward within its row
541 QTest::newRow("add 6, before visible items")
542 << 120.0 // show 6-23
544 << -60.0 * 2; // insert 2 rows above first visible in negative pos, first visible does not move
548 QTest::newRow("add 1, at start of visible, content at start")
553 QTest::newRow("add multiple, at start of visible, content at start")
558 QTest::newRow("add 1, at start of visible, content not at start")
559 << 120.0 // show 6-23
563 QTest::newRow("add multiple, at start of visible, content not at start")
564 << 120.0 // show 6-23
569 QTest::newRow("add 1, at end of visible, content at start")
574 QTest::newRow("add 1, at end of visible, content at start")
579 QTest::newRow("add 1, at end of visible, content not at start")
580 << 120.0 // show 6-23
584 QTest::newRow("add multiple, at end of visible, content not at start")
585 << 120.0 // show 6-23
590 QTest::newRow("add 1, after visible, content at start")
595 QTest::newRow("add 1, after visible, content at start")
600 QTest::newRow("add 1, after visible, content not at start")
601 << 120.0 // show 6-23
605 QTest::newRow("add multiple, after visible, content not at start")
606 << 120.0 // show 6-23
611 void tst_QQuickGridView::insertBeforeVisible()
613 QFETCH(int, insertIndex);
614 QFETCH(int, insertCount);
615 QFETCH(int, cacheBuffer);
618 QQuickView *canvas = createView();
622 for (int i = 0; i < 30; i++)
623 model.addItem("Item" + QString::number(i), "");
625 QDeclarativeContext *ctxt = canvas->rootContext();
626 ctxt->setContextProperty("testModel", &model);
627 ctxt->setContextProperty("testRightToLeft", QVariant(false));
628 ctxt->setContextProperty("testTopToBottom", QVariant(false));
629 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
630 qApp->processEvents();
632 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
633 QTRY_VERIFY(gridview != 0);
634 QQuickItem *contentItem = gridview->contentItem();
635 QTRY_VERIFY(contentItem != 0);
637 gridview->setCacheBuffer(cacheBuffer);
639 // trigger a refill (not just setting contentY) so that the visibleItems grid is updated
640 int firstVisibleIndex = 20; // move to an index where the top item is not visible
641 gridview->setContentY(firstVisibleIndex * 20.0);
642 gridview->setCurrentIndex(firstVisibleIndex);
643 qApp->processEvents();
644 QTRY_COMPARE(gridview->currentIndex(), firstVisibleIndex);
645 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex);
647 QCOMPARE(item->y(), gridview->contentY());
649 QList<QPair<QString, QString> > newData;
650 for (int i=0; i<insertCount; i++)
651 newData << qMakePair(QString("value %1").arg(i), QString::number(i));
652 model.insertItems(insertIndex, newData);
653 QTRY_COMPARE(gridview->property("count").toInt(), model.count());
655 // now, moving to the top of the view should position the inserted items correctly
656 int itemsOffsetAfterMove = (insertCount / 3) * -60.0;
657 gridview->setCurrentIndex(0);
658 QTRY_COMPARE(gridview->currentIndex(), 0);
659 QTRY_COMPARE(gridview->contentY(), 0.0 + itemsOffsetAfterMove);
661 // Confirm items positioned correctly and indexes correct
662 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
663 for (int i = 0; i < model.count() && i < itemCount; ++i) {
664 item = findItem<QQuickItem>(contentItem, "wrapper", i);
665 QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
666 QCOMPARE(item->x(), (i%3)*80.0);
667 QCOMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
668 name = findItem<QQuickText>(contentItem, "textName", i);
670 QTRY_COMPARE(name->text(), model.name(i));
676 void tst_QQuickGridView::insertBeforeVisible_data()
678 QTest::addColumn<int>("insertIndex");
679 QTest::addColumn<int>("insertCount");
680 QTest::addColumn<int>("cacheBuffer");
682 QTest::newRow("insert 1 at 0, 0 buffer") << 0 << 1 << 0;
683 QTest::newRow("insert 1 at 0, 100 buffer") << 0 << 1 << 100;
684 QTest::newRow("insert 1 at 0, 500 buffer") << 0 << 1 << 500;
686 QTest::newRow("insert 1 at 1, 0 buffer") << 1 << 1 << 0;
687 QTest::newRow("insert 1 at 1, 100 buffer") << 1 << 1 << 100;
688 QTest::newRow("insert 1 at 1, 500 buffer") << 1 << 1 << 500;
690 QTest::newRow("insert multiple at 0, 0 buffer") << 0 << 6 << 0;
691 QTest::newRow("insert multiple at 0, 100 buffer") << 0 << 6 << 100;
692 QTest::newRow("insert multiple at 0, 500 buffer") << 0 << 6 << 500;
694 QTest::newRow("insert multiple at 1, 0 buffer") << 1 << 6 << 0;
695 QTest::newRow("insert multiple at 1, 100 buffer") << 1 << 6 << 100;
696 QTest::newRow("insert multiple at 1, 500 buffer") << 1 << 6 << 500;
699 void tst_QQuickGridView::removed()
701 QQuickView *canvas = createView();
705 for (int i = 0; i < 40; i++)
706 model.addItem("Item" + QString::number(i), "");
708 QDeclarativeContext *ctxt = canvas->rootContext();
709 ctxt->setContextProperty("testModel", &model);
710 ctxt->setContextProperty("testRightToLeft", QVariant(false));
711 ctxt->setContextProperty("testTopToBottom", QVariant(false));
713 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
714 qApp->processEvents();
716 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
717 QTRY_VERIFY(gridview != 0);
719 QQuickItem *contentItem = gridview->contentItem();
720 QTRY_VERIFY(contentItem != 0);
723 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
725 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 1);
726 QTRY_VERIFY(name != 0);
727 QTRY_COMPARE(name->text(), model.name(1));
728 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 1);
729 QTRY_VERIFY(number != 0);
730 QTRY_COMPARE(number->text(), model.number(1));
733 // Checks that onRemove is called
734 QString removed = canvas->rootObject()->property("removed").toString();
735 QTRY_COMPARE(removed, QString("Item1"));
737 // Confirm items positioned correctly
738 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
739 for (int i = 0; i < model.count() && i < itemCount; ++i) {
740 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
741 if (!item) qWarning() << "Item" << i << "not found";
742 QTRY_VERIFY(item->x() == (i%3)*80);
743 QTRY_VERIFY(item->y() == (i/3)*60);
746 // Remove first item (which is the current item);
748 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
750 name = findItem<QQuickText>(contentItem, "textName", 0);
751 QTRY_VERIFY(name != 0);
752 QTRY_COMPARE(name->text(), model.name(0));
753 number = findItem<QQuickText>(contentItem, "textNumber", 0);
754 QTRY_VERIFY(number != 0);
755 QTRY_COMPARE(number->text(), model.number(0));
758 // Confirm items positioned correctly
759 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
760 for (int i = 0; i < model.count() && i < itemCount; ++i) {
761 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
762 if (!item) qWarning() << "Item" << i << "not found";
763 QTRY_VERIFY(item->x() == (i%3)*80);
764 QTRY_VERIFY(item->y() == (i/3)*60);
767 // Remove items not visible
768 model.removeItem(25);
769 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
771 // Confirm items positioned correctly
772 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
773 for (int i = 0; i < model.count() && i < itemCount; ++i) {
774 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
775 if (!item) qWarning() << "Item" << i << "not found";
776 QTRY_VERIFY(item->x() == (i%3)*80);
777 QTRY_VERIFY(item->y() == (i/3)*60);
780 // Remove items before visible
781 gridview->setContentY(120);
782 gridview->setCurrentIndex(10);
784 // Setting currentIndex above shouldn't cause view to scroll
785 QTRY_COMPARE(gridview->contentY(), 120.0);
788 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
790 // Confirm items positioned correctly
791 for (int i = 6; i < 18; ++i) {
792 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
793 if (!item) qWarning() << "Item" << i << "not found";
794 QTRY_VERIFY(item->x() == (i%3)*80);
795 QTRY_VERIFY(item->y() == (i/3)*60);
798 // Remove currentIndex
799 QQuickItem *oldCurrent = gridview->currentItem();
801 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
803 QTRY_COMPARE(gridview->currentIndex(), 9);
804 QTRY_VERIFY(gridview->currentItem() != oldCurrent);
806 gridview->setContentY(0);
807 // let transitions settle.
810 // Confirm items positioned correctly
811 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
812 for (int i = 0; i < model.count() && i < itemCount; ++i) {
813 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
814 QTRY_VERIFY(item->x() == (i%3)*80);
815 QTRY_VERIFY(item->y() == (i/3)*60);
818 // remove item outside current view.
819 gridview->setCurrentIndex(32);
820 gridview->setContentY(240);
822 model.removeItem(30);
823 QTRY_VERIFY(gridview->currentIndex() == 31);
825 // remove current item beyond visible items.
826 gridview->setCurrentIndex(20);
827 gridview->setContentY(0);
828 model.removeItem(20);
830 QTRY_COMPARE(gridview->currentIndex(), 20);
831 QTRY_VERIFY(gridview->currentItem() != 0);
833 // remove item before current, but visible
834 gridview->setCurrentIndex(8);
835 gridview->setContentY(240);
836 oldCurrent = gridview->currentItem();
839 QTRY_COMPARE(gridview->currentIndex(), 7);
840 QTRY_VERIFY(gridview->currentItem() == oldCurrent);
845 void tst_QQuickGridView::addOrRemoveBeforeVisible()
847 // QTBUG-21588: ensure re-layout is done on grid after adding or removing
848 // items from before the visible area
851 QFETCH(qreal, newTopContentY);
853 QQuickView *canvas = createView();
857 for (int i = 0; i < 30; i++)
858 model.addItem("Item" + QString::number(i), "");
860 QDeclarativeContext *ctxt = canvas->rootContext();
861 ctxt->setContextProperty("testModel", &model);
862 ctxt->setContextProperty("testRightToLeft", QVariant(false));
863 ctxt->setContextProperty("testTopToBottom", QVariant(false));
864 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
866 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
867 QTRY_VERIFY(gridview != 0);
868 QQuickItem *contentItem = gridview->contentItem();
869 QTRY_VERIFY(contentItem != 0);
871 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
872 QTRY_COMPARE(name->text(), QString("Item0"));
874 gridview->setCurrentIndex(0);
875 qApp->processEvents();
877 // scroll down until item 0 is no longer drawn
878 // (bug not triggered if we just move using content y, since that doesn't
879 // refill and change the visible items)
880 gridview->setCurrentIndex(24);
881 qApp->processEvents();
883 QTRY_COMPARE(gridview->currentIndex(), 24);
884 QTRY_COMPARE(gridview->contentY(), 220.0);
886 QTest::qWait(100); // wait for refill to complete
887 QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 0)); // 0 shouldn't be visible
890 model.insertItem(0, "New Item", "New Item number");
891 QTRY_COMPARE(gridview->count(), 31);
894 QTRY_COMPARE(gridview->count(), 29);
897 // scroll back up and item 0 should be gone
898 gridview->setCurrentIndex(0);
899 qApp->processEvents();
900 QTRY_COMPARE(gridview->currentIndex(), 0);
901 QTRY_COMPARE(gridview->contentY(), newTopContentY);
903 name = findItem<QQuickText>(contentItem, "textName", 0);
905 QCOMPARE(name->text(), QString("New Item"));
907 QCOMPARE(name->text(), QString("Item1"));
909 // Confirm items positioned correctly
910 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
911 for (int i = 0; i < model.count() && i < itemCount; ++i) {
912 QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", i));
913 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
914 QTRY_VERIFY(item->x() == (i%3)*80);
915 QTRY_VERIFY(item->y() == (i/3)*60 + newTopContentY);
921 void tst_QQuickGridView::addOrRemoveBeforeVisible_data()
923 QTest::addColumn<bool>("doAdd");
924 QTest::addColumn<qreal>("newTopContentY");
926 QTest::newRow("add") << true << -60.0;
927 QTest::newRow("remove") << false << 0.0;
930 void tst_QQuickGridView::clear()
932 QQuickView *canvas = createView();
935 for (int i = 0; i < 30; i++)
936 model.addItem("Item" + QString::number(i), "");
938 QDeclarativeContext *ctxt = canvas->rootContext();
939 ctxt->setContextProperty("testModel", &model);
940 ctxt->setContextProperty("testRightToLeft", QVariant(false));
941 ctxt->setContextProperty("testTopToBottom", QVariant(false));
943 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
944 qApp->processEvents();
946 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
947 QVERIFY(gridview != 0);
949 QQuickItem *contentItem = gridview->contentItem();
950 QVERIFY(contentItem != 0);
954 QVERIFY(gridview->count() == 0);
955 QVERIFY(gridview->currentItem() == 0);
956 QVERIFY(gridview->contentY() == 0);
957 QVERIFY(gridview->currentIndex() == -1);
959 // confirm sanity when adding an item to cleared list
960 model.addItem("New", "1");
961 QTRY_COMPARE(gridview->count(), 1);
962 QVERIFY(gridview->currentItem() != 0);
963 QVERIFY(gridview->currentIndex() == 0);
968 void tst_QQuickGridView::moved()
970 QFETCH(qreal, contentY);
974 QFETCH(qreal, itemsOffsetAfterMove);
978 QScopedPointer<QQuickView> canvas(createView());
982 for (int i = 0; i < 30; i++)
983 model.addItem("Item" + QString::number(i), "");
985 QDeclarativeContext *ctxt = canvas->rootContext();
986 ctxt->setContextProperty("testModel", &model);
987 ctxt->setContextProperty("testRightToLeft", QVariant(false));
988 ctxt->setContextProperty("testTopToBottom", QVariant(false));
990 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
991 qApp->processEvents();
993 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
994 QTRY_VERIFY(gridview != 0);
996 QQuickItem *contentItem = gridview->contentItem();
997 QTRY_VERIFY(contentItem != 0);
999 QQuickItem *currentItem = gridview->currentItem();
1000 QTRY_VERIFY(currentItem != 0);
1002 gridview->setContentY(contentY);
1003 model.moveItems(from, to, count);
1005 // wait for items to move
1006 QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
1008 // Confirm items positioned correctly and indexes correct
1009 int firstVisibleIndex = qCeil(contentY / 60.0) * 3;
1010 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1011 for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
1012 if (i >= firstVisibleIndex + 18) // index has moved out of view
1014 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1015 QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
1017 QTRY_COMPARE(item->x(), (i%3)*80.0);
1018 QTRY_COMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
1020 name = findItem<QQuickText>(contentItem, "textName", i);
1022 QTRY_COMPARE(name->text(), model.name(i));
1023 number = findItem<QQuickText>(contentItem, "textNumber", i);
1024 QVERIFY(number != 0);
1025 QTRY_COMPARE(number->text(), model.number(i));
1027 // current index should have been updated
1028 if (item == currentItem)
1029 QTRY_COMPARE(gridview->currentIndex(), i);
1033 void tst_QQuickGridView::moved_data()
1035 QTest::addColumn<qreal>("contentY");
1036 QTest::addColumn<int>("from");
1037 QTest::addColumn<int>("to");
1038 QTest::addColumn<int>("count");
1039 QTest::addColumn<qreal>("itemsOffsetAfterMove");
1041 // model starts with 30 items, each 80x60, in area 240x320
1042 // 18 items should be visible at a time
1044 QTest::newRow("move 1 forwards, within visible items")
1049 QTest::newRow("move 1 forwards, from non-visible -> visible")
1050 << 120.0 // show 6-23
1052 << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
1054 QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
1055 << 120.0 // // show 6-23
1057 << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
1059 QTest::newRow("move 1 forwards, from visible -> non-visible")
1064 QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
1070 QTest::newRow("move 1 backwards, within visible items")
1075 QTest::newRow("move 1 backwards, within visible items (to first index)")
1080 QTest::newRow("move 1 backwards, from non-visible -> visible")
1085 QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
1090 QTest::newRow("move 1 backwards, from visible -> non-visible")
1091 << 120.0 // show 6-23
1093 << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
1095 QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
1096 << 120.0 // show 6-23
1098 << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
1101 QTest::newRow("move multiple forwards, within visible items")
1106 QTest::newRow("move multiple backwards, within visible items (move first item)")
1111 QTest::newRow("move multiple forwards, before visible items")
1112 << 120.0 // show 6-23
1113 << 3 << 4 << 3 // 3, 4, 5 move to after 6
1114 << 60.0; // row of 3,4,5 has moved down
1116 QTest::newRow("move multiple forwards, from non-visible -> visible")
1117 << 120.0 // show 6-23
1119 << 60.0; // 1st row (it's above visible area) disappears, 0 drops down 1 row, first visible item (6) stays where it is
1121 QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
1122 << 120.0 // show 6-23
1124 << 60.0; // top row moved and shifted to below 3rd row, all items should shift down by 1 row
1126 QTest::newRow("move multiple forwards, from visible -> non-visible")
1131 QTest::newRow("move multiple forwards, from visible -> non-visible (move first item)")
1137 QTest::newRow("move multiple backwards, within visible items")
1142 QTest::newRow("move multiple backwards, from non-visible -> visible")
1147 QTest::newRow("move multiple backwards, from non-visible -> visible (move last item)")
1152 QTest::newRow("move multiple backwards, from visible -> non-visible")
1153 << 120.0 // show 6-23
1155 << -60.0; // to minimize movement, items are added above visible area, all items move up by 1 row
1157 QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
1158 << 120.0 // show 6-23
1160 << -60.0; // 16,17,18 move to above item 0, all items move up by 1 row
1164 enum { Inserted, Removed, Moved, SetCurrent } type;
1169 static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; }
1170 static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; }
1171 static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; }
1172 static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; }
1174 Q_DECLARE_METATYPE(QList<ListChange>)
1176 void tst_QQuickGridView::multipleChanges()
1178 QFETCH(int, startCount);
1179 QFETCH(QList<ListChange>, changes);
1180 QFETCH(int, newCount);
1181 QFETCH(int, newCurrentIndex);
1183 QQuickView *canvas = createView();
1187 for (int i = 0; i < startCount; i++)
1188 model.addItem("Item" + QString::number(i), "");
1190 QDeclarativeContext *ctxt = canvas->rootContext();
1191 ctxt->setContextProperty("testModel", &model);
1192 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1193 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1195 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
1196 qApp->processEvents();
1198 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1199 QTRY_VERIFY(gridview != 0);
1201 for (int i=0; i<changes.count(); i++) {
1202 switch (changes[i].type) {
1203 case ListChange::Inserted:
1205 QList<QPair<QString, QString> > items;
1206 for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
1207 items << qMakePair(QString("new item " + j), QString::number(j));
1208 model.insertItems(changes[i].index, items);
1211 case ListChange::Removed:
1212 model.removeItems(changes[i].index, changes[i].count);
1214 case ListChange::Moved:
1215 model.moveItems(changes[i].index, changes[i].to, changes[i].count);
1217 case ListChange::SetCurrent:
1218 gridview->setCurrentIndex(changes[i].index);
1223 QTRY_COMPARE(gridview->count(), newCount);
1224 QCOMPARE(gridview->count(), model.count());
1225 QTRY_COMPARE(gridview->currentIndex(), newCurrentIndex);
1229 QQuickItem *contentItem = gridview->contentItem();
1230 QTRY_VERIFY(contentItem != 0);
1231 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1232 for (int i=0; i < model.count() && i < itemCount; ++i) {
1233 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1234 QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
1235 name = findItem<QQuickText>(contentItem, "textName", i);
1237 QTRY_COMPARE(name->text(), model.name(i));
1238 number = findItem<QQuickText>(contentItem, "textNumber", i);
1239 QVERIFY(number != 0);
1240 QTRY_COMPARE(number->text(), model.number(i));
1246 void tst_QQuickGridView::multipleChanges_data()
1248 QTest::addColumn<int>("startCount");
1249 QTest::addColumn<QList<ListChange> >("changes");
1250 QTest::addColumn<int>("newCount");
1251 QTest::addColumn<int>("newCurrentIndex");
1253 QList<ListChange> changes;
1255 for (int i=1; i<30; i++)
1256 changes << ListChange::remove(0);
1257 QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
1259 changes << ListChange::remove(0);
1260 QTest::newRow("remove all") << 30 << changes << 0 << -1;
1263 changes << ListChange::setCurrent(29);
1264 for (int i=29; i>0; i--)
1265 changes << ListChange::remove(i);
1266 QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
1268 QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
1269 << ListChange::remove(0, 1)
1270 << ListChange::insert(0, 1)
1273 QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
1274 << ListChange::setCurrent(2)
1275 << ListChange::remove(2, 1)
1276 << ListChange::insert(2, 1)
1279 QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
1280 << ListChange::setCurrent(1)
1281 << ListChange::remove(1, 3)
1282 << ListChange::insert(2, 2)
1285 QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
1286 << ListChange::setCurrent(2)
1287 << ListChange::remove(1, 3)
1288 << ListChange::move(1, 5, 1)
1291 QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
1292 << ListChange::setCurrent(5)
1293 << ListChange::remove(4, 3)
1294 << ListChange::move(4, 1, 1)
1298 QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
1299 << ListChange::insert(0, 2)
1300 << ListChange::insert(0, 4)
1301 << ListChange::insert(0, 6)
1304 QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
1305 << ListChange::insert(0, 2)
1306 << ListChange::insert(0, 4)
1307 << ListChange::insert(0, 6)
1308 << ListChange::setCurrent(3)
1309 << ListChange::insert(3, 2)
1312 QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
1313 << ListChange::insert(0, 30)
1314 << ListChange::remove(0, 30)
1317 QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
1318 << ListChange::insert(1)
1319 << ListChange::setCurrent(1)
1320 << ListChange::remove(1)
1323 QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
1324 << ListChange::insert(0, 10)
1325 << ListChange::remove(5, 10)
1328 QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
1329 << ListChange::insert(0, 3)
1330 << ListChange::move(0, 10, 3)
1333 QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
1334 << ListChange::insert(0, 3)
1335 << ListChange::move(0, 8, 5)
1338 QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
1339 << ListChange::setCurrent(9)
1340 << ListChange::insert(10, 3)
1341 << ListChange::move(8, 0, 5)
1345 QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
1346 << ListChange::setCurrent(1)
1347 << ListChange::move(1, 2, 2)
1348 << ListChange::move(2, 1, 2)
1351 QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
1352 << ListChange::setCurrent(2)
1353 << ListChange::move(1, 2, 3)
1354 << ListChange::move(3, 0, 5)
1357 QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
1358 << ListChange::setCurrent(5)
1359 << ListChange::move(5, 0, 1)
1360 << ListChange::remove(0)
1363 QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
1364 << ListChange::setCurrent(5)
1365 << ListChange::move(5, 0, 1)
1366 << ListChange::insert(0)
1369 QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
1370 << ListChange::setCurrent(1)
1371 << ListChange::move(5, 1, 3)
1372 << ListChange::remove(1, 3)
1375 QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
1376 << ListChange::setCurrent(5)
1377 << ListChange::move(5, 1, 3)
1378 << ListChange::insert(1, 5)
1381 QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
1382 << ListChange::setCurrent(3)
1383 << ListChange::move(0, 1, 2)
1384 << ListChange::insert(3, 5)
1388 QTest::newRow("clear current") << 0 << (QList<ListChange>()
1389 << ListChange::insert(0, 5)
1390 << ListChange::setCurrent(-1)
1391 << ListChange::remove(0, 5)
1392 << ListChange::insert(0, 5)
1397 void tst_QQuickGridView::swapWithFirstItem()
1400 QQuickView *canvas = createView();
1404 for (int i = 0; i < 30; i++)
1405 model.addItem("Item" + QString::number(i), "");
1407 QDeclarativeContext *ctxt = canvas->rootContext();
1408 ctxt->setContextProperty("testModel", &model);
1409 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1410 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1412 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
1413 qApp->processEvents();
1415 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1416 QTRY_VERIFY(gridview != 0);
1418 // ensure content position is stable
1419 gridview->setContentY(0);
1420 model.moveItem(10, 0);
1421 QTRY_VERIFY(gridview->contentY() == 0);
1426 void tst_QQuickGridView::currentIndex()
1429 for (int i = 0; i < 60; i++)
1430 model.addItem("Item" + QString::number(i), QString::number(i));
1432 QQuickView *canvas = new QQuickView(0);
1433 canvas->setGeometry(0,0,240,320);
1436 QDeclarativeContext *ctxt = canvas->rootContext();
1437 ctxt->setContextProperty("testModel", &model);
1439 QString filename(TESTDATA("gridview-initCurrent.qml"));
1440 canvas->setSource(QUrl::fromLocalFile(filename));
1442 qApp->processEvents();
1444 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1445 QVERIFY(gridview != 0);
1446 QTRY_VERIFY(!QQuickItemPrivate::get(gridview)->polishScheduled);
1448 QQuickItem *contentItem = gridview->contentItem();
1449 QVERIFY(contentItem != 0);
1451 // current item should be third item
1452 QCOMPARE(gridview->currentIndex(), 35);
1453 QCOMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 35));
1454 QCOMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
1455 QCOMPARE(gridview->contentY(), 400.0);
1457 gridview->moveCurrentIndexRight();
1458 QCOMPARE(gridview->currentIndex(), 36);
1459 gridview->moveCurrentIndexDown();
1460 QCOMPARE(gridview->currentIndex(), 39);
1461 gridview->moveCurrentIndexUp();
1462 QCOMPARE(gridview->currentIndex(), 36);
1463 gridview->moveCurrentIndexLeft();
1464 QCOMPARE(gridview->currentIndex(), 35);
1466 // wait until motion stops
1467 QTRY_VERIFY(gridview->verticalVelocity() == 0.0);
1470 gridview->setCurrentIndex(0);
1471 QCOMPARE(gridview->currentIndex(), 0);
1472 // confirm that the velocity is updated
1473 QTRY_VERIFY(gridview->verticalVelocity() != 0.0);
1475 gridview->moveCurrentIndexUp();
1476 QCOMPARE(gridview->currentIndex(), 0);
1478 gridview->moveCurrentIndexLeft();
1479 QCOMPARE(gridview->currentIndex(), 0);
1481 gridview->setCurrentIndex(model.count()-1);
1482 QCOMPARE(gridview->currentIndex(), model.count()-1);
1484 gridview->moveCurrentIndexRight();
1485 QCOMPARE(gridview->currentIndex(), model.count()-1);
1487 gridview->moveCurrentIndexDown();
1488 QCOMPARE(gridview->currentIndex(), model.count()-1);
1491 gridview->setWrapEnabled(true);
1493 gridview->setCurrentIndex(0);
1494 QCOMPARE(gridview->currentIndex(), 0);
1496 gridview->moveCurrentIndexLeft();
1497 QCOMPARE(gridview->currentIndex(), model.count()-1);
1499 qApp->processEvents();
1500 QTRY_COMPARE(gridview->contentY(), 880.0);
1502 gridview->moveCurrentIndexRight();
1503 QCOMPARE(gridview->currentIndex(), 0);
1505 QTRY_COMPARE(gridview->contentY(), 0.0);
1508 // footer should become visible if it is out of view, and then current index moves to the first row
1509 canvas->rootObject()->setProperty("showFooter", true);
1510 QTRY_VERIFY(gridview->footerItem());
1511 gridview->setCurrentIndex(model.count()-3);
1512 QTRY_VERIFY(gridview->footerItem()->y() > gridview->contentY() + gridview->height());
1513 gridview->setCurrentIndex(model.count()-2);
1514 QTRY_COMPARE(gridview->contentY() + gridview->height(), (60.0 * model.count()/3) + gridview->footerItem()->height());
1515 canvas->rootObject()->setProperty("showFooter", false);
1517 // header should become visible if it is out of view, and then current index moves to the last row
1518 canvas->rootObject()->setProperty("showHeader", true);
1519 QTRY_VERIFY(gridview->headerItem());
1520 gridview->setCurrentIndex(3);
1521 QTRY_VERIFY(gridview->headerItem()->y() + gridview->headerItem()->height() < gridview->contentY());
1522 gridview->setCurrentIndex(1);
1523 QTRY_COMPARE(gridview->contentY(), -gridview->headerItem()->height());
1524 canvas->rootObject()->setProperty("showHeader", false);
1528 canvas->requestActivateWindow();
1529 QTest::qWaitForWindowShown(canvas);
1530 QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
1532 gridview->setCurrentIndex(0);
1534 QTest::keyClick(canvas, Qt::Key_Down);
1535 QCOMPARE(gridview->currentIndex(), 3);
1537 QTest::keyClick(canvas, Qt::Key_Up);
1538 QCOMPARE(gridview->currentIndex(), 0);
1540 // hold down Key_Down
1541 for (int i=0; i<(model.count() / 3) - 1; i++) {
1542 QTest::simulateEvent(canvas, true, Qt::Key_Down, Qt::NoModifier, "", true);
1543 QTRY_COMPARE(gridview->currentIndex(), i*3 + 3);
1545 QTest::keyRelease(canvas, Qt::Key_Down);
1546 QTRY_COMPARE(gridview->currentIndex(), 57);
1547 QTRY_COMPARE(gridview->contentY(), 880.0);
1550 for (int i=(model.count() / 3) - 1; i > 0; i--) {
1551 QTest::simulateEvent(canvas, true, Qt::Key_Up, Qt::NoModifier, "", true);
1552 QTRY_COMPARE(gridview->currentIndex(), i*3 - 3);
1554 QTest::keyRelease(canvas, Qt::Key_Up);
1555 QTRY_COMPARE(gridview->currentIndex(), 0);
1556 QTRY_COMPARE(gridview->contentY(), 0.0);
1559 gridview->setFlow(QQuickGridView::TopToBottom);
1561 canvas->requestActivateWindow();
1562 QTest::qWaitForWindowShown(canvas);
1563 QVERIFY(qGuiApp->focusWindow() == canvas);
1564 qApp->processEvents();
1566 QTest::keyClick(canvas, Qt::Key_Right);
1567 QCOMPARE(gridview->currentIndex(), 5);
1569 QTest::keyClick(canvas, Qt::Key_Left);
1570 QCOMPARE(gridview->currentIndex(), 0);
1572 QTest::keyClick(canvas, Qt::Key_Down);
1573 QCOMPARE(gridview->currentIndex(), 1);
1575 QTest::keyClick(canvas, Qt::Key_Up);
1576 QCOMPARE(gridview->currentIndex(), 0);
1578 // hold down Key_Right
1579 for (int i=0; i<(model.count() / 5) - 1; i++) {
1580 QTest::simulateEvent(canvas, true, Qt::Key_Right, Qt::NoModifier, "", true);
1581 QTRY_COMPARE(gridview->currentIndex(), i*5 + 5);
1584 QTest::keyRelease(canvas, Qt::Key_Right);
1585 QTRY_COMPARE(gridview->currentIndex(), 55);
1586 QTRY_COMPARE(gridview->contentX(), 720.0);
1588 // hold down Key_Left
1589 for (int i=(model.count() / 5) - 1; i > 0; i--) {
1590 QTest::simulateEvent(canvas, true, Qt::Key_Left, Qt::NoModifier, "", true);
1591 QTRY_COMPARE(gridview->currentIndex(), i*5 - 5);
1593 QTest::keyRelease(canvas, Qt::Key_Left);
1594 QTRY_COMPARE(gridview->currentIndex(), 0);
1595 QTRY_COMPARE(gridview->contentX(), 0.0);
1598 // turn off auto highlight
1599 gridview->setHighlightFollowsCurrentItem(false);
1600 QVERIFY(gridview->highlightFollowsCurrentItem() == false);
1601 QVERIFY(gridview->highlightItem());
1602 qreal hlPosX = gridview->highlightItem()->x();
1603 qreal hlPosY = gridview->highlightItem()->y();
1605 gridview->setCurrentIndex(5);
1606 QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
1607 QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
1609 // insert item before currentIndex
1610 gridview->setCurrentIndex(28);
1611 model.insertItem(0, "Foo", "1111");
1612 QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
1614 // check removing highlight by setting currentIndex to -1;
1615 gridview->setCurrentIndex(-1);
1617 QCOMPARE(gridview->currentIndex(), -1);
1618 QVERIFY(!gridview->highlightItem());
1619 QVERIFY(!gridview->currentItem());
1621 gridview->setHighlightFollowsCurrentItem(true);
1623 gridview->setFlow(QQuickGridView::LeftToRight);
1624 gridview->setLayoutDirection(Qt::RightToLeft);
1626 canvas->requestActivateWindow();
1627 QTest::qWaitForWindowShown(canvas);
1628 QTRY_VERIFY(qGuiApp->focusWindow() == canvas);
1629 qApp->processEvents();
1631 gridview->setCurrentIndex(35);
1633 QTest::keyClick(canvas, Qt::Key_Right);
1634 QCOMPARE(gridview->currentIndex(), 34);
1636 QTest::keyClick(canvas, Qt::Key_Down);
1637 QCOMPARE(gridview->currentIndex(), 37);
1639 QTest::keyClick(canvas, Qt::Key_Up);
1640 QCOMPARE(gridview->currentIndex(), 34);
1642 QTest::keyClick(canvas, Qt::Key_Left);
1643 QCOMPARE(gridview->currentIndex(), 35);
1646 // turn off auto highlight
1647 gridview->setHighlightFollowsCurrentItem(false);
1648 QVERIFY(gridview->highlightFollowsCurrentItem() == false);
1649 QVERIFY(gridview->highlightItem());
1650 hlPosX = gridview->highlightItem()->x();
1651 hlPosY = gridview->highlightItem()->y();
1653 gridview->setCurrentIndex(5);
1654 QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
1655 QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
1657 // insert item before currentIndex
1658 gridview->setCurrentIndex(28);
1659 model.insertItem(0, "Foo", "1111");
1660 QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
1662 // check removing highlight by setting currentIndex to -1;
1663 gridview->setCurrentIndex(-1);
1665 QCOMPARE(gridview->currentIndex(), -1);
1666 QVERIFY(!gridview->highlightItem());
1667 QVERIFY(!gridview->currentItem());
1672 void tst_QQuickGridView::noCurrentIndex()
1675 for (int i = 0; i < 60; i++)
1676 model.addItem("Item" + QString::number(i), QString::number(i));
1678 QQuickView *canvas = new QQuickView(0);
1679 canvas->setGeometry(0,0,240,320);
1681 QDeclarativeContext *ctxt = canvas->rootContext();
1682 ctxt->setContextProperty("testModel", &model);
1684 QString filename(TESTDATA("gridview-noCurrent.qml"));
1685 canvas->setSource(QUrl::fromLocalFile(filename));
1687 qApp->processEvents();
1689 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1690 QVERIFY(gridview != 0);
1692 QQuickItem *contentItem = gridview->contentItem();
1693 QVERIFY(contentItem != 0);
1695 // current index should be -1
1696 QCOMPARE(gridview->currentIndex(), -1);
1697 QVERIFY(!gridview->currentItem());
1698 QVERIFY(!gridview->highlightItem());
1699 QCOMPARE(gridview->contentY(), 0.0);
1701 gridview->setCurrentIndex(5);
1702 QCOMPARE(gridview->currentIndex(), 5);
1703 QVERIFY(gridview->currentItem());
1704 QVERIFY(gridview->highlightItem());
1709 void tst_QQuickGridView::changeFlow()
1711 QQuickView *canvas = createView();
1714 for (int i = 0; i < 30; i++)
1715 model.addItem("Item" + QString::number(i), QString::number(i));
1717 QDeclarativeContext *ctxt = canvas->rootContext();
1718 ctxt->setContextProperty("testModel", &model);
1719 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1720 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1722 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
1723 qApp->processEvents();
1725 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
1726 QTRY_VERIFY(gridview != 0);
1728 QQuickItem *contentItem = gridview->contentItem();
1729 QTRY_VERIFY(contentItem != 0);
1731 // Confirm items positioned correctly and indexes correct
1732 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1733 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1734 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1735 if (!item) qWarning() << "Item" << i << "not found";
1737 QTRY_COMPARE(item->x(), qreal((i%3)*80));
1738 QTRY_COMPARE(item->y(), qreal((i/3)*60));
1739 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
1740 QTRY_VERIFY(name != 0);
1741 QTRY_COMPARE(name->text(), model.name(i));
1742 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
1743 QTRY_VERIFY(number != 0);
1744 QTRY_COMPARE(number->text(), model.number(i));
1747 ctxt->setContextProperty("testTopToBottom", QVariant(true));
1749 // Confirm items positioned correctly and indexes correct
1750 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1751 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1752 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1753 if (!item) qWarning() << "Item" << i << "not found";
1755 QTRY_COMPARE(item->x(), qreal((i/5)*80));
1756 QTRY_COMPARE(item->y(), qreal((i%5)*60));
1757 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
1758 QTRY_VERIFY(name != 0);
1759 QTRY_COMPARE(name->text(), model.name(i));
1760 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
1761 QTRY_VERIFY(number != 0);
1762 QTRY_COMPARE(number->text(), model.number(i));
1765 ctxt->setContextProperty("testRightToLeft", QVariant(true));
1767 // Confirm items positioned correctly and indexes correct
1768 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1769 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1770 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1771 if (!item) qWarning() << "Item" << i << "not found";
1773 QTRY_COMPARE(item->x(), qreal(-(i/5)*80 - item->width()));
1774 QTRY_COMPARE(item->y(), qreal((i%5)*60));
1775 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
1776 QTRY_VERIFY(name != 0);
1777 QTRY_COMPARE(name->text(), model.name(i));
1778 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
1779 QTRY_VERIFY(number != 0);
1780 QTRY_COMPARE(number->text(), model.number(i));
1782 gridview->setContentX(100);
1783 QTRY_COMPARE(gridview->contentX(), 100.);
1784 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1785 QTRY_COMPARE(gridview->contentX(), 0.);
1787 // Confirm items positioned correctly and indexes correct
1788 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
1789 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1790 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
1791 if (!item) qWarning() << "Item" << i << "not found";
1793 QTRY_COMPARE(item->x(), qreal(240 - (i%3+1)*80));
1794 QTRY_COMPARE(item->y(), qreal((i/3)*60));
1795 QQuickText *name = findItem<QQuickText>(contentItem, "textName", i);
1796 QTRY_VERIFY(name != 0);
1797 QTRY_COMPARE(name->text(), model.name(i));
1798 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", i);
1799 QTRY_VERIFY(number != 0);
1800 QTRY_COMPARE(number->text(), model.number(i));
1806 void tst_QQuickGridView::defaultValues()
1808 QDeclarativeEngine engine;
1809 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("gridview3.qml")));
1810 QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
1812 QTRY_VERIFY(obj != 0);
1813 QTRY_VERIFY(obj->model() == QVariant());
1814 QTRY_VERIFY(obj->delegate() == 0);
1815 QTRY_COMPARE(obj->currentIndex(), -1);
1816 QTRY_VERIFY(obj->currentItem() == 0);
1817 QTRY_COMPARE(obj->count(), 0);
1818 QTRY_VERIFY(obj->highlight() == 0);
1819 QTRY_VERIFY(obj->highlightItem() == 0);
1820 QTRY_COMPARE(obj->highlightFollowsCurrentItem(), true);
1821 QTRY_VERIFY(obj->flow() == 0);
1822 QTRY_COMPARE(obj->isWrapEnabled(), false);
1823 QTRY_COMPARE(obj->cacheBuffer(), 0);
1824 QTRY_COMPARE(obj->cellWidth(), qreal(100)); //### Should 100 be the default?
1825 QTRY_COMPARE(obj->cellHeight(), qreal(100));
1829 void tst_QQuickGridView::properties()
1831 QDeclarativeEngine engine;
1832 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(TESTDATA("gridview2.qml")));
1833 QQuickGridView *obj = qobject_cast<QQuickGridView*>(c.create());
1835 QTRY_VERIFY(obj != 0);
1836 QTRY_VERIFY(obj->model() != QVariant());
1837 QTRY_VERIFY(obj->delegate() != 0);
1838 QTRY_COMPARE(obj->currentIndex(), 0);
1839 QTRY_VERIFY(obj->currentItem() != 0);
1840 QTRY_COMPARE(obj->count(), 4);
1841 QTRY_VERIFY(obj->highlight() != 0);
1842 QTRY_VERIFY(obj->highlightItem() != 0);
1843 QTRY_COMPARE(obj->highlightFollowsCurrentItem(), false);
1844 QTRY_VERIFY(obj->flow() == 0);
1845 QTRY_COMPARE(obj->isWrapEnabled(), true);
1846 QTRY_COMPARE(obj->cacheBuffer(), 200);
1847 QTRY_COMPARE(obj->cellWidth(), qreal(100));
1848 QTRY_COMPARE(obj->cellHeight(), qreal(100));
1852 void tst_QQuickGridView::propertyChanges()
1854 QQuickView *canvas = createView();
1855 QTRY_VERIFY(canvas);
1856 canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
1858 QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
1859 QTRY_VERIFY(gridView);
1861 QSignalSpy keyNavigationWrapsSpy(gridView, SIGNAL(keyNavigationWrapsChanged()));
1862 QSignalSpy cacheBufferSpy(gridView, SIGNAL(cacheBufferChanged()));
1863 QSignalSpy layoutSpy(gridView, SIGNAL(layoutDirectionChanged()));
1864 QSignalSpy flowSpy(gridView, SIGNAL(flowChanged()));
1866 QTRY_COMPARE(gridView->isWrapEnabled(), true);
1867 QTRY_COMPARE(gridView->cacheBuffer(), 10);
1868 QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
1870 gridView->setWrapEnabled(false);
1871 gridView->setCacheBuffer(3);
1872 gridView->setFlow(QQuickGridView::TopToBottom);
1874 QTRY_COMPARE(gridView->isWrapEnabled(), false);
1875 QTRY_COMPARE(gridView->cacheBuffer(), 3);
1876 QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
1878 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1879 QTRY_COMPARE(cacheBufferSpy.count(),1);
1880 QTRY_COMPARE(flowSpy.count(),1);
1882 gridView->setWrapEnabled(false);
1883 gridView->setCacheBuffer(3);
1884 gridView->setFlow(QQuickGridView::TopToBottom);
1886 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1887 QTRY_COMPARE(cacheBufferSpy.count(),1);
1888 QTRY_COMPARE(flowSpy.count(),1);
1890 gridView->setFlow(QQuickGridView::LeftToRight);
1891 QTRY_COMPARE(gridView->flow(), QQuickGridView::LeftToRight);
1893 gridView->setWrapEnabled(true);
1894 gridView->setCacheBuffer(5);
1895 gridView->setLayoutDirection(Qt::RightToLeft);
1897 QTRY_COMPARE(gridView->isWrapEnabled(), true);
1898 QTRY_COMPARE(gridView->cacheBuffer(), 5);
1899 QTRY_COMPARE(gridView->layoutDirection(), Qt::RightToLeft);
1901 QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
1902 QTRY_COMPARE(cacheBufferSpy.count(),2);
1903 QTRY_COMPARE(layoutSpy.count(),1);
1904 QTRY_COMPARE(flowSpy.count(),2);
1906 gridView->setWrapEnabled(true);
1907 gridView->setCacheBuffer(5);
1908 gridView->setLayoutDirection(Qt::RightToLeft);
1910 QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
1911 QTRY_COMPARE(cacheBufferSpy.count(),2);
1912 QTRY_COMPARE(layoutSpy.count(),1);
1913 QTRY_COMPARE(flowSpy.count(),2);
1915 gridView->setFlow(QQuickGridView::TopToBottom);
1916 QTRY_COMPARE(gridView->flow(), QQuickGridView::TopToBottom);
1917 QTRY_COMPARE(flowSpy.count(),3);
1919 gridView->setFlow(QQuickGridView::TopToBottom);
1920 QTRY_COMPARE(flowSpy.count(),3);
1925 void tst_QQuickGridView::componentChanges()
1927 QQuickView *canvas = createView();
1928 QTRY_VERIFY(canvas);
1929 canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
1931 QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
1932 QTRY_VERIFY(gridView);
1934 QDeclarativeComponent component(canvas->engine());
1935 component.setData("import QtQuick 2.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
1937 QDeclarativeComponent delegateComponent(canvas->engine());
1938 delegateComponent.setData("import QtQuick 2.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
1940 QSignalSpy highlightSpy(gridView, SIGNAL(highlightChanged()));
1941 QSignalSpy delegateSpy(gridView, SIGNAL(delegateChanged()));
1942 QSignalSpy headerSpy(gridView, SIGNAL(headerChanged()));
1943 QSignalSpy footerSpy(gridView, SIGNAL(footerChanged()));
1945 gridView->setHighlight(&component);
1946 gridView->setDelegate(&delegateComponent);
1947 gridView->setHeader(&component);
1948 gridView->setFooter(&component);
1950 QTRY_COMPARE(gridView->highlight(), &component);
1951 QTRY_COMPARE(gridView->delegate(), &delegateComponent);
1952 QTRY_COMPARE(gridView->header(), &component);
1953 QTRY_COMPARE(gridView->footer(), &component);
1955 QTRY_COMPARE(highlightSpy.count(),1);
1956 QTRY_COMPARE(delegateSpy.count(),1);
1957 QTRY_COMPARE(headerSpy.count(),1);
1958 QTRY_COMPARE(footerSpy.count(),1);
1960 gridView->setHighlight(&component);
1961 gridView->setDelegate(&delegateComponent);
1962 gridView->setHeader(&component);
1963 gridView->setFooter(&component);
1965 QTRY_COMPARE(highlightSpy.count(),1);
1966 QTRY_COMPARE(delegateSpy.count(),1);
1967 QTRY_COMPARE(headerSpy.count(),1);
1968 QTRY_COMPARE(footerSpy.count(),1);
1973 void tst_QQuickGridView::modelChanges()
1975 QQuickView *canvas = createView();
1976 QTRY_VERIFY(canvas);
1977 canvas->setSource(QUrl::fromLocalFile(TESTDATA("propertychangestest.qml")));
1979 QQuickGridView *gridView = canvas->rootObject()->findChild<QQuickGridView*>("gridView");
1980 QTRY_VERIFY(gridView);
1982 QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
1983 QTRY_VERIFY(alternateModel);
1984 QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
1985 QSignalSpy modelSpy(gridView, SIGNAL(modelChanged()));
1987 gridView->setModel(modelVariant);
1988 QTRY_COMPARE(gridView->model(), modelVariant);
1989 QTRY_COMPARE(modelSpy.count(),1);
1991 gridView->setModel(modelVariant);
1992 QTRY_COMPARE(modelSpy.count(),1);
1994 gridView->setModel(QVariant());
1995 QTRY_COMPARE(modelSpy.count(),2);
1999 void tst_QQuickGridView::positionViewAtIndex()
2001 QQuickView *canvas = createView();
2004 for (int i = 0; i < 40; i++)
2005 model.addItem("Item" + QString::number(i), "");
2007 QDeclarativeContext *ctxt = canvas->rootContext();
2008 ctxt->setContextProperty("testModel", &model);
2009 ctxt->setContextProperty("testRightToLeft", QVariant(false));
2010 ctxt->setContextProperty("testTopToBottom", QVariant(false));
2012 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
2013 qApp->processEvents();
2015 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2016 QTRY_VERIFY(gridview != 0);
2018 QQuickItem *contentItem = gridview->contentItem();
2019 QTRY_VERIFY(contentItem != 0);
2021 // Confirm items positioned correctly
2022 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2023 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2024 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2025 if (!item) qWarning() << "Item" << i << "not found";
2027 QTRY_COMPARE(item->x(), (i%3)*80.);
2028 QTRY_COMPARE(item->y(), (i/3)*60.);
2031 // Position on a currently visible item
2032 gridview->positionViewAtIndex(4, QQuickGridView::Beginning);
2033 QTRY_COMPARE(gridview->indexAt(120, 90), 4);
2034 QTRY_COMPARE(gridview->contentY(), 60.);
2036 // Confirm items positioned correctly
2037 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2038 for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
2039 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2040 if (!item) qWarning() << "Item" << i << "not found";
2042 QTRY_COMPARE(item->x(), (i%3)*80.);
2043 QTRY_COMPARE(item->y(), (i/3)*60.);
2046 // Position on an item beyond the visible items
2047 gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
2048 QTRY_COMPARE(gridview->indexAt(40, 450), 21);
2049 QTRY_COMPARE(gridview->contentY(), 420.);
2051 // Confirm items positioned correctly
2052 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2053 for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
2054 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2055 if (!item) qWarning() << "Item" << i << "not found";
2057 QTRY_COMPARE(item->x(), (i%3)*80.);
2058 QTRY_COMPARE(item->y(), (i/3)*60.);
2061 // Position on an item that would leave empty space if positioned at the top
2062 gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
2063 QTRY_COMPARE(gridview->indexAt(120, 630), 31);
2064 QTRY_COMPARE(gridview->contentY(), 520.);
2066 // Confirm items positioned correctly
2067 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2068 for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
2069 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2070 if (!item) qWarning() << "Item" << i << "not found";
2072 QTRY_COMPARE(item->x(), (i%3)*80.);
2073 QTRY_COMPARE(item->y(), (i/3)*60.);
2076 // Position at the beginning again
2077 gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
2078 QTRY_COMPARE(gridview->indexAt(0, 0), 0);
2079 QTRY_COMPARE(gridview->indexAt(40, 30), 0);
2080 QTRY_COMPARE(gridview->indexAt(80, 60), 4);
2081 QTRY_COMPARE(gridview->contentY(), 0.);
2083 // Confirm items positioned correctly
2084 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2085 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2086 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2087 if (!item) qWarning() << "Item" << i << "not found";
2089 QTRY_COMPARE(item->x(), (i%3)*80.);
2090 QTRY_COMPARE(item->y(), (i/3)*60.);
2094 gridview->positionViewAtIndex(30, QQuickGridView::End);
2095 QTRY_COMPARE(gridview->contentY(), 340.);
2097 // Position in Center
2098 gridview->positionViewAtIndex(15, QQuickGridView::Center);
2099 QTRY_COMPARE(gridview->contentY(), 170.);
2101 // Ensure at least partially visible
2102 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2103 QTRY_COMPARE(gridview->contentY(), 170.);
2105 gridview->setContentY(302);
2106 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2107 QTRY_COMPARE(gridview->contentY(), 302.);
2109 gridview->setContentY(360);
2110 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2111 QTRY_COMPARE(gridview->contentY(), 300.);
2113 gridview->setContentY(60);
2114 gridview->positionViewAtIndex(20, QQuickGridView::Visible);
2115 QTRY_COMPARE(gridview->contentY(), 60.);
2117 gridview->setContentY(20);
2118 gridview->positionViewAtIndex(20, QQuickGridView::Visible);
2119 QTRY_COMPARE(gridview->contentY(), 100.);
2121 // Ensure completely visible
2122 gridview->setContentY(120);
2123 gridview->positionViewAtIndex(20, QQuickGridView::Contain);
2124 QTRY_COMPARE(gridview->contentY(), 120.);
2126 gridview->setContentY(302);
2127 gridview->positionViewAtIndex(15, QQuickGridView::Contain);
2128 QTRY_COMPARE(gridview->contentY(), 300.);
2130 gridview->setContentY(60);
2131 gridview->positionViewAtIndex(20, QQuickGridView::Contain);
2132 QTRY_COMPARE(gridview->contentY(), 100.);
2134 // Test for Top To Bottom layout
2135 ctxt->setContextProperty("testTopToBottom", QVariant(true));
2137 // Confirm items positioned correctly
2138 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2139 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2140 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2141 if (!item) qWarning() << "Item" << i << "not found";
2143 QTRY_COMPARE(item->x(), (i/5)*80.);
2144 QTRY_COMPARE(item->y(), (i%5)*60.);
2148 gridview->positionViewAtIndex(30, QQuickGridView::End);
2149 QTRY_COMPARE(gridview->contentX(), 320.);
2150 QTRY_COMPARE(gridview->contentY(), 0.);
2152 // Position in Center
2153 gridview->positionViewAtIndex(15, QQuickGridView::Center);
2154 QTRY_COMPARE(gridview->contentX(), 160.);
2156 // Ensure at least partially visible
2157 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2158 QTRY_COMPARE(gridview->contentX(), 160.);
2160 gridview->setContentX(170);
2161 gridview->positionViewAtIndex(25, QQuickGridView::Visible);
2162 QTRY_COMPARE(gridview->contentX(), 170.);
2164 gridview->positionViewAtIndex(30, QQuickGridView::Visible);
2165 QTRY_COMPARE(gridview->contentX(), 320.);
2167 gridview->setContentX(170);
2168 gridview->positionViewAtIndex(25, QQuickGridView::Contain);
2169 QTRY_COMPARE(gridview->contentX(), 240.);
2171 // positionViewAtBeginning
2172 gridview->positionViewAtBeginning();
2173 QTRY_COMPARE(gridview->contentX(), 0.);
2175 gridview->setContentX(80);
2176 canvas->rootObject()->setProperty("showHeader", true);
2177 gridview->positionViewAtBeginning();
2178 QTRY_COMPARE(gridview->contentX(), -30.);
2180 // positionViewAtEnd
2181 gridview->positionViewAtEnd();
2182 QTRY_COMPARE(gridview->contentX(), 400.); // 8*80 - 240 (8 columns)
2184 gridview->setContentX(80);
2185 canvas->rootObject()->setProperty("showFooter", true);
2186 gridview->positionViewAtEnd();
2187 QTRY_COMPARE(gridview->contentX(), 430.);
2189 // set current item to outside visible view, position at beginning
2190 // and ensure highlight moves to current item
2191 gridview->setCurrentIndex(6);
2192 gridview->positionViewAtBeginning();
2193 QTRY_COMPARE(gridview->contentX(), -30.);
2194 QVERIFY(gridview->highlightItem());
2195 QCOMPARE(gridview->highlightItem()->x(), 80.);
2200 void tst_QQuickGridView::snapping()
2202 QQuickView *canvas = createView();
2205 for (int i = 0; i < 40; i++)
2206 model.addItem("Item" + QString::number(i), "");
2208 QDeclarativeContext *ctxt = canvas->rootContext();
2209 ctxt->setContextProperty("testModel", &model);
2210 ctxt->setContextProperty("testTopToBottom", QVariant(false));
2211 ctxt->setContextProperty("testRightToLeft", QVariant(false));
2213 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
2214 qApp->processEvents();
2216 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2217 QTRY_VERIFY(gridview != 0);
2219 gridview->setHeight(220);
2220 QCOMPARE(gridview->height(), 220.);
2222 gridview->positionViewAtIndex(12, QQuickGridView::Visible);
2223 QCOMPARE(gridview->contentY(), 80.);
2225 gridview->setContentY(0);
2226 QCOMPARE(gridview->contentY(), 0.);
2228 gridview->setSnapMode(QQuickGridView::SnapToRow);
2229 QCOMPARE(gridview->snapMode(), QQuickGridView::SnapToRow);
2231 gridview->positionViewAtIndex(12, QQuickGridView::Visible);
2232 QCOMPARE(gridview->contentY(), 60.);
2234 gridview->positionViewAtIndex(15, QQuickGridView::End);
2235 QCOMPARE(gridview->contentY(), 120.);
2241 void tst_QQuickGridView::mirroring()
2243 QQuickView *canvasA = createView();
2244 canvasA->setSource(QUrl::fromLocalFile(TESTDATA("mirroring.qml")));
2245 QQuickGridView *gridviewA = findItem<QQuickGridView>(canvasA->rootObject(), "view");
2246 QTRY_VERIFY(gridviewA != 0);
2248 QQuickView *canvasB = createView();
2249 canvasB->setSource(QUrl::fromLocalFile(TESTDATA("mirroring.qml")));
2250 QQuickGridView *gridviewB = findItem<QQuickGridView>(canvasB->rootObject(), "view");
2251 QTRY_VERIFY(gridviewA != 0);
2252 qApp->processEvents();
2254 QList<QString> objectNames;
2255 objectNames << "item1" << "item2"; // << "item3"
2257 gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
2258 gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
2259 QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection());
2262 foreach (const QString objectName, objectNames)
2263 QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
2265 gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
2266 gridviewB->setProperty("layoutDirection", Qt::LeftToRight);
2269 foreach (const QString objectName, objectNames)
2270 QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
2272 QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection());
2273 QQuickItemPrivate::get(gridviewB)->setLayoutMirror(true);
2274 QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
2276 // LTR != LTR+mirror
2277 foreach (const QString objectName, objectNames)
2278 QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
2280 gridviewA->setProperty("layoutDirection", Qt::RightToLeft);
2282 // RTL == LTR+mirror
2283 foreach (const QString objectName, objectNames)
2284 QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
2286 gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
2288 // RTL != RTL+mirror
2289 foreach (const QString objectName, objectNames)
2290 QVERIFY(findItem<QQuickItem>(gridviewA, objectName)->x() != findItem<QQuickItem>(gridviewB, objectName)->x());
2292 gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
2294 // LTR == RTL+mirror
2295 foreach (const QString objectName, objectNames)
2296 QCOMPARE(findItem<QQuickItem>(gridviewA, objectName)->x(), findItem<QQuickItem>(gridviewB, objectName)->x());
2302 void tst_QQuickGridView::positionViewAtIndex_rightToLeft()
2304 QQuickView *canvas = createView();
2307 for (int i = 0; i < 40; i++)
2308 model.addItem("Item" + QString::number(i), "");
2310 QDeclarativeContext *ctxt = canvas->rootContext();
2311 ctxt->setContextProperty("testModel", &model);
2312 ctxt->setContextProperty("testTopToBottom", QVariant(true));
2313 ctxt->setContextProperty("testRightToLeft", QVariant(true));
2315 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
2316 qApp->processEvents();
2318 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2319 QTRY_VERIFY(gridview != 0);
2321 QQuickItem *contentItem = gridview->contentItem();
2322 QTRY_VERIFY(contentItem != 0);
2324 // Confirm items positioned correctly
2325 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2326 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2327 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2328 if (!item) qWarning() << "Item" << i << "not found";
2330 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2331 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2334 // Position on a currently visible item
2335 gridview->positionViewAtIndex(6, QQuickGridView::Beginning);
2336 QTRY_COMPARE(gridview->contentX(), -320.);
2338 // Confirm items positioned correctly
2339 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2340 for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
2341 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2342 if (!item) qWarning() << "Item" << i << "not found";
2344 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2345 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2348 // Position on an item beyond the visible items
2349 gridview->positionViewAtIndex(21, QQuickGridView::Beginning);
2350 QTRY_COMPARE(gridview->contentX(), -560.);
2352 // Confirm items positioned correctly
2353 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2354 for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
2355 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2356 if (!item) qWarning() << "Item" << i << "not found";
2358 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2359 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2362 // Position on an item that would leave empty space if positioned at the top
2363 gridview->positionViewAtIndex(31, QQuickGridView::Beginning);
2364 QTRY_COMPARE(gridview->contentX(), -640.);
2366 // Confirm items positioned correctly
2367 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2368 for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
2369 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2370 if (!item) qWarning() << "Item" << i << "not found";
2372 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2373 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2376 // Position at the beginning again
2377 gridview->positionViewAtIndex(0, QQuickGridView::Beginning);
2378 QTRY_COMPARE(gridview->contentX(), -240.);
2380 // Confirm items positioned correctly
2381 itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
2382 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
2383 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
2384 if (!item) qWarning() << "Item" << i << "not found";
2386 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
2387 QTRY_COMPARE(item->y(), qreal((i%5)*60));
2391 gridview->positionViewAtIndex(30, QQuickGridView::End);
2392 QTRY_COMPARE(gridview->contentX(), -560.);
2394 // Position in Center
2395 gridview->positionViewAtIndex(15, QQuickGridView::Center);
2396 QTRY_COMPARE(gridview->contentX(), -400.);
2398 // Ensure at least partially visible
2399 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2400 QTRY_COMPARE(gridview->contentX(), -400.);
2402 gridview->setContentX(-555.);
2403 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2404 QTRY_COMPARE(gridview->contentX(), -555.);
2406 gridview->setContentX(-239);
2407 gridview->positionViewAtIndex(15, QQuickGridView::Visible);
2408 QTRY_COMPARE(gridview->contentX(), -320.);
2410 gridview->setContentX(-239);
2411 gridview->positionViewAtIndex(20, QQuickGridView::Visible);
2412 QTRY_COMPARE(gridview->contentX(), -400.);
2414 gridview->setContentX(-640);
2415 gridview->positionViewAtIndex(20, QQuickGridView::Visible);
2416 QTRY_COMPARE(gridview->contentX(), -560.);
2418 // Ensure completely visible
2419 gridview->setContentX(-400);
2420 gridview->positionViewAtIndex(20, QQuickGridView::Contain);
2421 QTRY_COMPARE(gridview->contentX(), -400.);
2423 gridview->setContentX(-315);
2424 gridview->positionViewAtIndex(15, QQuickGridView::Contain);
2425 QTRY_COMPARE(gridview->contentX(), -320.);
2427 gridview->setContentX(-640);
2428 gridview->positionViewAtIndex(20, QQuickGridView::Contain);
2429 QTRY_COMPARE(gridview->contentX(), -560.);
2434 void tst_QQuickGridView::resetModel()
2436 QQuickView *canvas = createView();
2438 QStringList strings;
2439 strings << "one" << "two" << "three";
2440 QStringListModel model(strings);
2442 QDeclarativeContext *ctxt = canvas->rootContext();
2443 ctxt->setContextProperty("testModel", &model);
2445 canvas->setSource(QUrl::fromLocalFile(TESTDATA("displaygrid.qml")));
2446 qApp->processEvents();
2448 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2449 QTRY_VERIFY(gridview != 0);
2451 QQuickItem *contentItem = gridview->contentItem();
2452 QTRY_VERIFY(contentItem != 0);
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));
2463 strings << "four" << "five" << "six" << "seven";
2464 model.setStringList(strings);
2466 QTRY_COMPARE(gridview->count(), model.rowCount());
2468 for (int i = 0; i < model.rowCount(); ++i) {
2469 QQuickText *display = findItem<QQuickText>(contentItem, "displayText", i);
2470 QTRY_VERIFY(display != 0);
2471 QTRY_COMPARE(display->text(), strings.at(i));
2477 void tst_QQuickGridView::enforceRange()
2479 QQuickView *canvas = createView();
2482 for (int i = 0; i < 30; i++)
2483 model.addItem("Item" + QString::number(i), "");
2485 QDeclarativeContext *ctxt = canvas->rootContext();
2486 ctxt->setContextProperty("testModel", &model);
2487 ctxt->setContextProperty("testRightToLeft", QVariant(false));
2488 ctxt->setContextProperty("testTopToBottom", QVariant(false));
2490 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview-enforcerange.qml")));
2491 qApp->processEvents();
2492 QVERIFY(canvas->rootObject() != 0);
2494 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2495 QTRY_VERIFY(gridview != 0);
2497 QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
2498 QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
2499 QTRY_COMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
2501 QQuickItem *contentItem = gridview->contentItem();
2502 QTRY_VERIFY(contentItem != 0);
2504 // view should be positioned at the top of the range.
2505 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2507 QTRY_COMPARE(gridview->contentY(), -100.0);
2509 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
2510 QTRY_VERIFY(name != 0);
2511 QTRY_COMPARE(name->text(), model.name(0));
2512 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
2513 QTRY_VERIFY(number != 0);
2514 QTRY_COMPARE(number->text(), model.number(0));
2516 // Check currentIndex is updated when contentItem moves
2517 gridview->setContentY(0);
2518 QTRY_COMPARE(gridview->currentIndex(), 2);
2520 gridview->setCurrentIndex(5);
2521 QTRY_COMPARE(gridview->contentY(), 100.);
2524 for (int i = 0; i < 5; i++)
2525 model2.addItem("Item" + QString::number(i), "");
2527 ctxt->setContextProperty("testModel", &model2);
2528 QCOMPARE(gridview->count(), 5);
2533 void tst_QQuickGridView::enforceRange_rightToLeft()
2535 QQuickView *canvas = createView();
2538 for (int i = 0; i < 30; i++)
2539 model.addItem("Item" + QString::number(i), "");
2541 QDeclarativeContext *ctxt = canvas->rootContext();
2542 ctxt->setContextProperty("testModel", &model);
2543 ctxt->setContextProperty("testRightToLeft", QVariant(true));
2544 ctxt->setContextProperty("testTopToBottom", QVariant(true));
2546 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview-enforcerange.qml")));
2547 qApp->processEvents();
2548 QVERIFY(canvas->rootObject() != 0);
2550 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2551 QTRY_VERIFY(gridview != 0);
2553 QCOMPARE(gridview->preferredHighlightBegin(), 100.0);
2554 QCOMPARE(gridview->preferredHighlightEnd(), 100.0);
2555 QCOMPARE(gridview->highlightRangeMode(), QQuickGridView::StrictlyEnforceRange);
2557 QQuickItem *contentItem = gridview->contentItem();
2558 QVERIFY(contentItem != 0);
2560 // view should be positioned at the top of the range.
2561 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2563 QTRY_COMPARE(gridview->contentX(), -140.);
2564 QTRY_COMPARE(gridview->contentY(), 0.0);
2566 QQuickText *name = findItem<QQuickText>(contentItem, "textName", 0);
2567 QTRY_VERIFY(name != 0);
2568 QTRY_COMPARE(name->text(), model.name(0));
2569 QQuickText *number = findItem<QQuickText>(contentItem, "textNumber", 0);
2570 QTRY_VERIFY(number != 0);
2571 QTRY_COMPARE(number->text(), model.number(0));
2573 // Check currentIndex is updated when contentItem moves
2574 gridview->setContentX(-240);
2575 QTRY_COMPARE(gridview->currentIndex(), 3);
2577 gridview->setCurrentIndex(7);
2578 QTRY_COMPARE(gridview->contentX(), -340.);
2579 QTRY_COMPARE(gridview->contentY(), 0.0);
2582 for (int i = 0; i < 5; i++)
2583 model2.addItem("Item" + QString::number(i), "");
2585 ctxt->setContextProperty("testModel", &model2);
2586 QCOMPARE(gridview->count(), 5);
2591 void tst_QQuickGridView::QTBUG_8456()
2593 QQuickView *canvas = createView();
2595 canvas->setSource(QUrl::fromLocalFile(TESTDATA("setindex.qml")));
2596 qApp->processEvents();
2598 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2599 QTRY_VERIFY(gridview != 0);
2601 QTRY_COMPARE(gridview->currentIndex(), 0);
2606 void tst_QQuickGridView::manualHighlight()
2608 QQuickView *canvas = createView();
2610 QString filename(TESTDATA("manual-highlight.qml"));
2611 canvas->setSource(QUrl::fromLocalFile(filename));
2613 qApp->processEvents();
2615 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2616 QTRY_VERIFY(gridview != 0);
2618 QQuickItem *contentItem = gridview->contentItem();
2619 QTRY_VERIFY(contentItem != 0);
2621 QTRY_COMPARE(gridview->currentIndex(), 0);
2622 QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
2623 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
2624 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
2626 gridview->setCurrentIndex(2);
2628 QTRY_COMPARE(gridview->currentIndex(), 2);
2629 QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
2630 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
2631 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
2633 gridview->positionViewAtIndex(8, QQuickGridView::Contain);
2635 QTRY_COMPARE(gridview->currentIndex(), 2);
2636 QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 2));
2637 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
2638 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
2640 gridview->setFlow(QQuickGridView::TopToBottom);
2641 QTRY_COMPARE(gridview->flow(), QQuickGridView::TopToBottom);
2643 gridview->setCurrentIndex(0);
2644 QTRY_COMPARE(gridview->currentIndex(), 0);
2645 QTRY_COMPARE(gridview->currentItem(), findItem<QQuickItem>(contentItem, "wrapper", 0));
2646 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
2647 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
2653 void tst_QQuickGridView::footer()
2655 QFETCH(QQuickGridView::Flow, flow);
2656 QFETCH(Qt::LayoutDirection, layoutDirection);
2657 QFETCH(QPointF, initialFooterPos);
2658 QFETCH(QPointF, changedFooterPos);
2659 QFETCH(QPointF, initialContentPos);
2660 QFETCH(QPointF, changedContentPos);
2661 QFETCH(QPointF, firstDelegatePos);
2662 QFETCH(QPointF, resizeContentPos);
2664 QQuickView *canvas = createView();
2668 for (int i = 0; i < 7; i++)
2669 model.addItem("Item" + QString::number(i), "");
2671 QDeclarativeContext *ctxt = canvas->rootContext();
2672 ctxt->setContextProperty("testModel", &model);
2674 canvas->setSource(QUrl::fromLocalFile(TESTDATA("footer.qml")));
2675 qApp->processEvents();
2677 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2678 QTRY_VERIFY(gridview != 0);
2679 gridview->setFlow(flow);
2680 gridview->setLayoutDirection(layoutDirection);
2682 QQuickItem *contentItem = gridview->contentItem();
2683 QTRY_VERIFY(contentItem != 0);
2685 QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
2688 QVERIFY(footer == gridview->footerItem());
2690 QCOMPARE(footer->pos(), initialFooterPos);
2691 QCOMPARE(footer->width(), 100.);
2692 QCOMPARE(footer->height(), 30.);
2693 QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
2695 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2697 QCOMPARE(item->pos(), firstDelegatePos);
2699 if (flow == QQuickGridView::LeftToRight) {
2700 // shrink by one row
2701 model.removeItem(2);
2702 QTRY_COMPARE(footer->y(), initialFooterPos.y() - gridview->cellHeight());
2704 // shrink by one column
2705 model.removeItem(2);
2706 model.removeItem(3);
2707 if (layoutDirection == Qt::LeftToRight)
2708 QTRY_COMPARE(footer->x(), initialFooterPos.x() - gridview->cellWidth());
2710 QTRY_COMPARE(footer->x(), initialFooterPos.x() + gridview->cellWidth());
2716 QPointF posWhenNoItems(0, 0);
2717 if (layoutDirection == Qt::RightToLeft)
2718 posWhenNoItems.setX(flow == QQuickGridView::LeftToRight ? gridview->width() - footer->width() : -footer->width());
2719 QTRY_COMPARE(footer->pos(), posWhenNoItems);
2721 // if header is present, it's at a negative pos, so the footer should not move
2722 canvas->rootObject()->setProperty("showHeader", true);
2723 QVERIFY(findItem<QQuickItem>(contentItem, "header") != 0);
2724 QTRY_COMPARE(footer->pos(), posWhenNoItems);
2725 canvas->rootObject()->setProperty("showHeader", false);
2728 for (int i = 0; i < 30; i++)
2729 model.addItem("Item" + QString::number(i), "");
2731 QSignalSpy footerItemSpy(gridview, SIGNAL(footerItemChanged()));
2732 QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
2734 QCOMPARE(footerItemSpy.count(), 1);
2736 footer = findItem<QQuickText>(contentItem, "footer");
2738 footer = findItem<QQuickText>(contentItem, "footer2");
2741 QVERIFY(footer == gridview->footerItem());
2743 QCOMPARE(footer->pos(), changedFooterPos);
2744 QCOMPARE(footer->width(), 50.);
2745 QCOMPARE(footer->height(), 20.);
2746 QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
2748 item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2750 QCOMPARE(item->pos(), firstDelegatePos);
2752 gridview->positionViewAtEnd();
2753 footer->setHeight(10);
2754 footer->setWidth(40);
2755 QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
2760 void tst_QQuickGridView::footer_data()
2762 QTest::addColumn<QQuickGridView::Flow>("flow");
2763 QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
2764 QTest::addColumn<QPointF>("initialFooterPos");
2765 QTest::addColumn<QPointF>("changedFooterPos");
2766 QTest::addColumn<QPointF>("initialContentPos");
2767 QTest::addColumn<QPointF>("changedContentPos");
2768 QTest::addColumn<QPointF>("firstDelegatePos");
2769 QTest::addColumn<QPointF>("resizeContentPos");
2771 // footer1 = 100 x 30
2772 // footer2 = 50 x 20
2775 // view height = 320
2777 // footer below items, bottom left
2778 QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
2779 << QPointF(0, 3 * 60) // 180 = height of 3 rows (cell height is 60)
2780 << QPointF(0, 10 * 60) // 30 items = 10 rows
2784 << QPointF(0, 10 * 60 - 320 + 10);
2786 // footer below items, bottom right
2787 QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
2788 << QPointF(240 - 100, 3 * 60)
2789 << QPointF((240 - 100) + 50, 10 * 60) // 50 = width diff between old and new footers
2792 << QPointF(240 - 80, 0)
2793 << QPointF(0, 10 * 60 - 320 + 10);
2795 // footer to right of items
2796 QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
2797 << QPointF(2 * 80, 0) // 2 columns, cell width 80
2798 << QPointF(6 * 80, 0) // 30 items = 6 columns
2802 << QPointF(6 * 80 - 240 + 40, 0);
2804 // footer to left of items
2805 QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
2806 << QPointF(-(2 * 80) - 100, 0)
2807 << QPointF(-(6 * 80) - 50, 0) // 50 = new footer width
2809 << QPointF(-240, 0) // unchanged, footer change doesn't change content pos
2811 << QPointF(-(6 * 80) - 40, 0);
2814 void tst_QQuickGridView::header()
2816 QFETCH(QQuickGridView::Flow, flow);
2817 QFETCH(Qt::LayoutDirection, layoutDirection);
2818 QFETCH(QPointF, initialHeaderPos);
2819 QFETCH(QPointF, changedHeaderPos);
2820 QFETCH(QPointF, initialContentPos);
2821 QFETCH(QPointF, changedContentPos);
2822 QFETCH(QPointF, firstDelegatePos);
2823 QFETCH(QPointF, resizeContentPos);
2826 for (int i = 0; i < 30; i++)
2827 model.addItem("Item" + QString::number(i), "");
2829 QQuickView *canvas = createView();
2830 canvas->rootContext()->setContextProperty("testModel", &model);
2831 canvas->rootContext()->setContextProperty("initialViewWidth", 240);
2832 canvas->rootContext()->setContextProperty("initialViewHeight", 320);
2833 canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
2835 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2836 QTRY_VERIFY(gridview != 0);
2837 gridview->setFlow(flow);
2838 gridview->setLayoutDirection(layoutDirection);
2840 QQuickItem *contentItem = gridview->contentItem();
2841 QTRY_VERIFY(contentItem != 0);
2843 QQuickText *header = findItem<QQuickText>(contentItem, "header");
2846 QVERIFY(header == gridview->headerItem());
2848 QCOMPARE(header->pos(), initialHeaderPos);
2849 QCOMPARE(header->width(), 100.);
2850 QCOMPARE(header->height(), 30.);
2851 QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
2853 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2855 QCOMPARE(item->pos(), firstDelegatePos);
2858 QCOMPARE(header->pos(), initialHeaderPos); // header should stay where it is
2860 for (int i = 0; i < 30; i++)
2861 model.addItem("Item" + QString::number(i), "");
2863 QSignalSpy headerItemSpy(gridview, SIGNAL(headerItemChanged()));
2864 QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
2866 QCOMPARE(headerItemSpy.count(), 1);
2868 header = findItem<QQuickText>(contentItem, "header");
2870 header = findItem<QQuickText>(contentItem, "header2");
2873 QVERIFY(header == gridview->headerItem());
2875 QCOMPARE(header->pos(), changedHeaderPos);
2876 QCOMPARE(header->width(), 50.);
2877 QCOMPARE(header->height(), 20.);
2878 QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), changedContentPos);
2880 item = findItem<QQuickItem>(contentItem, "wrapper", 0);
2882 QCOMPARE(item->pos(), firstDelegatePos);
2884 header->setHeight(10);
2885 header->setWidth(40);
2886 QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
2891 // QTBUG-21207 header should become visible if view resizes from initial empty size
2893 canvas = createView();
2894 canvas->rootContext()->setContextProperty("testModel", &model);
2895 canvas->rootContext()->setContextProperty("initialViewWidth", 240);
2896 canvas->rootContext()->setContextProperty("initialViewHeight", 320);
2897 canvas->setSource(QUrl::fromLocalFile(TESTDATA("header.qml")));
2899 gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2900 QTRY_VERIFY(gridview != 0);
2901 gridview->setFlow(flow);
2902 gridview->setLayoutDirection(layoutDirection);
2904 gridview->setWidth(240);
2905 gridview->setHeight(320);
2906 QTRY_COMPARE(gridview->headerItem()->pos(), initialHeaderPos);
2907 QCOMPARE(QPointF(gridview->contentX(), gridview->contentY()), initialContentPos);
2912 void tst_QQuickGridView::header_data()
2914 QTest::addColumn<QQuickGridView::Flow>("flow");
2915 QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
2916 QTest::addColumn<QPointF>("initialHeaderPos");
2917 QTest::addColumn<QPointF>("changedHeaderPos");
2918 QTest::addColumn<QPointF>("initialContentPos");
2919 QTest::addColumn<QPointF>("changedContentPos");
2920 QTest::addColumn<QPointF>("firstDelegatePos");
2921 QTest::addColumn<QPointF>("resizeContentPos");
2923 // header1 = 100 x 30
2924 // header2 = 50 x 20
2928 // header above items, top left
2929 QTest::newRow("flow left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight
2937 // header above items, top right
2938 QTest::newRow("flow left to right, layout right to left") << QQuickGridView::LeftToRight << Qt::RightToLeft
2939 << QPointF(240 - 100, -30)
2940 << QPointF((240 - 100) + 50, -20) // 50 = width diff between old and new headers
2946 // header to left of items
2947 QTest::newRow("flow top to bottom, layout left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight
2955 // header to right of items
2956 QTest::newRow("flow top to bottom, layout right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft
2959 << QPointF(-(240 - 100), 0)
2960 << QPointF(-(240 - 50), 0)
2962 << QPointF(-(240 - 40), 0);
2965 void tst_QQuickGridView::resizeViewAndRepaint()
2967 QQuickView *canvas = createView();
2971 for (int i = 0; i < 40; i++)
2972 model.addItem("Item" + QString::number(i), "");
2974 QDeclarativeContext *ctxt = canvas->rootContext();
2975 ctxt->setContextProperty("testModel", &model);
2976 ctxt->setContextProperty("initialHeight", 100);
2978 canvas->setSource(QUrl::fromLocalFile(TESTDATA("resizeview.qml")));
2979 qApp->processEvents();
2981 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
2982 QTRY_VERIFY(gridview != 0);
2983 QQuickItem *contentItem = gridview->contentItem();
2984 QTRY_VERIFY(contentItem != 0);
2986 // item at index 10 should not be currently visible
2987 QVERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
2989 gridview->setHeight(320);
2990 QTRY_VERIFY(findItem<QQuickItem>(contentItem, "wrapper", 10));
2992 gridview->setHeight(100);
2993 QTRY_VERIFY(!findItem<QQuickItem>(contentItem, "wrapper", 10));
2998 void tst_QQuickGridView::indexAt()
3000 QQuickView *canvas = createView();
3003 model.addItem("Fred", "12345");
3004 model.addItem("John", "2345");
3005 model.addItem("Bob", "54321");
3006 model.addItem("Billy", "22345");
3007 model.addItem("Sam", "2945");
3008 model.addItem("Ben", "04321");
3009 model.addItem("Jim", "0780");
3011 QDeclarativeContext *ctxt = canvas->rootContext();
3012 ctxt->setContextProperty("testModel", &model);
3013 ctxt->setContextProperty("testRightToLeft", QVariant(false));
3014 ctxt->setContextProperty("testTopToBottom", QVariant(false));
3016 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
3017 qApp->processEvents();
3019 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3020 QTRY_VERIFY(gridview != 0);
3022 QQuickItem *contentItem = gridview->contentItem();
3023 QTRY_VERIFY(contentItem != 0);
3025 QTRY_COMPARE(gridview->count(), model.count());
3027 QCOMPARE(gridview->indexAt(0, 0), 0);
3028 QCOMPARE(gridview->indexAt(79, 59), 0);
3029 QCOMPARE(gridview->indexAt(80, 0), 1);
3030 QCOMPARE(gridview->indexAt(0, 60), 3);
3031 QCOMPARE(gridview->indexAt(240, 0), -1);
3036 void tst_QQuickGridView::onAdd()
3038 QFETCH(int, initialItemCount);
3039 QFETCH(int, itemsToAdd);
3041 const int delegateWidth = 50;
3042 const int delegateHeight = 100;
3044 QQuickView *canvas = createView();
3045 canvas->setGeometry(0,0,5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit
3047 // these initial items should not trigger GridView.onAdd
3048 for (int i=0; i<initialItemCount; i++)
3049 model.addItem("dummy value", "dummy value");
3051 QDeclarativeContext *ctxt = canvas->rootContext();
3052 ctxt->setContextProperty("testModel", &model);
3053 ctxt->setContextProperty("delegateWidth", delegateWidth);
3054 ctxt->setContextProperty("delegateHeight", delegateHeight);
3055 canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
3057 QObject *object = canvas->rootObject();
3058 object->setProperty("width", canvas->width());
3059 object->setProperty("height", canvas->height());
3060 qApp->processEvents();
3062 QList<QPair<QString, QString> > items;
3063 for (int i=0; i<itemsToAdd; i++)
3064 items << qMakePair(QString("value %1").arg(i), QString::number(i));
3065 model.addItems(items);
3067 QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
3068 qApp->processEvents();
3070 QVariantList result = object->property("addedDelegates").toList();
3071 QTRY_COMPARE(result.count(), items.count());
3072 for (int i=0; i<items.count(); i++)
3073 QCOMPARE(result[i].toString(), items[i].first);
3078 void tst_QQuickGridView::onAdd_data()
3080 QTest::addColumn<int>("initialItemCount");
3081 QTest::addColumn<int>("itemsToAdd");
3083 QTest::newRow("0, add 1") << 0 << 1;
3084 QTest::newRow("0, add 2") << 0 << 2;
3085 QTest::newRow("0, add 10") << 0 << 10;
3087 QTest::newRow("1, add 1") << 1 << 1;
3088 QTest::newRow("1, add 2") << 1 << 2;
3089 QTest::newRow("1, add 10") << 1 << 10;
3091 QTest::newRow("5, add 1") << 5 << 1;
3092 QTest::newRow("5, add 2") << 5 << 2;
3093 QTest::newRow("5, add 10") << 5 << 10;
3096 void tst_QQuickGridView::onRemove()
3098 QFETCH(int, initialItemCount);
3099 QFETCH(int, indexToRemove);
3100 QFETCH(int, removeCount);
3102 const int delegateWidth = 50;
3103 const int delegateHeight = 100;
3105 for (int i=0; i<initialItemCount; i++)
3106 model.addItem(QString("value %1").arg(i), "dummy value");
3108 QQuickView *canvas = createView();
3109 QDeclarativeContext *ctxt = canvas->rootContext();
3110 ctxt->setContextProperty("testModel", &model);
3111 ctxt->setContextProperty("delegateWidth", delegateWidth);
3112 ctxt->setContextProperty("delegateHeight", delegateHeight);
3113 canvas->setSource(QUrl::fromLocalFile(TESTDATA("attachedSignals.qml")));
3114 QObject *object = canvas->rootObject();
3116 model.removeItems(indexToRemove, removeCount);
3117 QTRY_COMPARE(model.count(), qobject_cast<QQuickGridView*>(canvas->rootObject())->count());
3118 QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
3123 void tst_QQuickGridView::onRemove_data()
3125 QTest::addColumn<int>("initialItemCount");
3126 QTest::addColumn<int>("indexToRemove");
3127 QTest::addColumn<int>("removeCount");
3129 QTest::newRow("remove first") << 1 << 0 << 1;
3130 QTest::newRow("two items, remove first") << 2 << 0 << 1;
3131 QTest::newRow("two items, remove last") << 2 << 1 << 1;
3132 QTest::newRow("two items, remove all") << 2 << 0 << 2;
3134 QTest::newRow("four items, remove first") << 4 << 0 << 1;
3135 QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
3136 QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
3137 QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
3138 QTest::newRow("four items, remove last") << 4 << 3 << 1;
3139 QTest::newRow("four items, remove all") << 4 << 0 << 4;
3141 QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
3142 QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
3143 QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
3146 void tst_QQuickGridView::columnCount()
3149 canvas.setSource(QUrl::fromLocalFile(TESTDATA("gridview4.qml")));
3151 canvas.requestActivateWindow();
3152 QTest::qWaitForWindowShown(&canvas);
3154 QQuickGridView *view = qobject_cast<QQuickGridView*>(canvas.rootObject());
3156 QCOMPARE(view->cellWidth(), qreal(405)/qreal(9));
3157 QCOMPARE(view->cellHeight(), qreal(100));
3159 QList<QQuickItem*> items = findItems<QQuickItem>(view, "delegate");
3160 QCOMPARE(items.size(), 18);
3161 QCOMPARE(items.at(8)->y(), qreal(0));
3162 QCOMPARE(items.at(9)->y(), qreal(100));
3165 void tst_QQuickGridView::margins()
3168 QQuickView *canvas = createView();
3172 for (int i = 0; i < 40; i++)
3173 model.addItem("Item" + QString::number(i), "");
3175 QDeclarativeContext *ctxt = canvas->rootContext();
3176 ctxt->setContextProperty("testModel", &model);
3177 ctxt->setContextProperty("testRightToLeft", QVariant(false));
3179 canvas->setSource(QUrl::fromLocalFile(TESTDATA("margins.qml")));
3180 qApp->processEvents();
3182 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3183 QTRY_VERIFY(gridview != 0);
3185 QQuickItem *contentItem = gridview->contentItem();
3186 QTRY_VERIFY(contentItem != 0);
3188 QCOMPARE(gridview->contentX(), -30.);
3189 QCOMPARE(gridview->xOrigin(), 0.);
3192 gridview->positionViewAtEnd();
3193 qreal pos = gridview->contentX();
3194 gridview->setContentX(pos + 80);
3195 gridview->returnToBounds();
3196 QTRY_COMPARE(gridview->contentX(), pos + 50);
3198 // remove item before visible and check that left margin is maintained
3199 // and xOrigin is updated
3200 gridview->setContentX(200);
3201 model.removeItems(0, 4);
3203 gridview->setContentX(-50);
3204 gridview->returnToBounds();
3205 QCOMPARE(gridview->xOrigin(), 100.);
3206 QTRY_COMPARE(gridview->contentX(), 70.);
3208 // reduce left margin
3209 gridview->setLeftMargin(20);
3210 QCOMPARE(gridview->xOrigin(), 100.);
3211 QTRY_COMPARE(gridview->contentX(), 80.);
3214 gridview->positionViewAtEnd();
3215 QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
3216 pos = gridview->contentX();
3217 gridview->setContentX(pos + 80);
3218 gridview->returnToBounds();
3219 QTRY_COMPARE(gridview->contentX(), pos + 50);
3221 // reduce right margin
3222 pos = gridview->contentX();
3223 gridview->setRightMargin(40);
3224 QCOMPARE(gridview->xOrigin(), 0.);
3225 QTRY_COMPARE(gridview->contentX(), pos-10);
3231 QQuickView *canvas = createView();
3235 for (int i = 0; i < 40; i++)
3236 model.addItem("Item" + QString::number(i), "");
3238 QDeclarativeContext *ctxt = canvas->rootContext();
3239 ctxt->setContextProperty("testModel", &model);
3240 ctxt->setContextProperty("testRightToLeft", QVariant(true));
3242 canvas->setSource(QUrl::fromLocalFile(TESTDATA("margins.qml")));
3243 qApp->processEvents();
3245 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3246 QTRY_VERIFY(gridview != 0);
3248 QQuickItem *contentItem = gridview->contentItem();
3249 QTRY_VERIFY(contentItem != 0);
3251 QCOMPARE(gridview->contentX(), -240+30.);
3252 QCOMPARE(gridview->xOrigin(), 0.);
3255 gridview->positionViewAtEnd();
3256 qreal pos = gridview->contentX();
3257 gridview->setContentX(pos - 80);
3258 gridview->returnToBounds();
3259 QTRY_COMPARE(gridview->contentX(), pos - 50);
3261 // remove item before visible and check that left margin is maintained
3262 // and xOrigin is updated
3263 gridview->setContentX(-400);
3264 model.removeItems(0, 4);
3266 gridview->setContentX(-240+50);
3267 gridview->returnToBounds();
3268 QCOMPARE(gridview->xOrigin(), -100.);
3269 QTRY_COMPARE(gridview->contentX(), -240-70.);
3271 // reduce left margin (i.e. right side due to RTL)
3272 pos = gridview->contentX();
3273 gridview->setLeftMargin(20);
3274 QCOMPARE(gridview->xOrigin(), -100.);
3275 QTRY_COMPARE(gridview->contentX(), -240-80.);
3278 gridview->positionViewAtEnd();
3279 QCOMPARE(gridview->xOrigin(), 0.); // positionViewAtEnd() resets origin
3280 pos = gridview->contentX();
3281 gridview->setContentX(pos - 80);
3282 gridview->returnToBounds();
3283 QTRY_COMPARE(gridview->contentX(), pos - 50);
3285 // reduce right margin (i.e. left side due to RTL)
3286 pos = gridview->contentX();
3287 gridview->setRightMargin(40);
3288 QCOMPARE(gridview->xOrigin(), 0.);
3289 QTRY_COMPARE(gridview->contentX(), pos+10);
3295 void tst_QQuickGridView::creationContext()
3298 canvas.setGeometry(0,0,240,320);
3299 canvas.setSource(QUrl::fromLocalFile(TESTDATA("creationContext.qml")));
3300 qApp->processEvents();
3302 QQuickItem *rootItem = qobject_cast<QQuickItem *>(canvas.rootObject());
3304 QVERIFY(rootItem->property("count").toInt() > 0);
3307 QVERIFY(item = rootItem->findChild<QQuickItem *>("listItem"));
3308 QCOMPARE(item->property("text").toString(), QString("Hello!"));
3309 QVERIFY(item = rootItem->findChild<QQuickItem *>("header"));
3310 QCOMPARE(item->property("text").toString(), QString("Hello!"));
3311 QVERIFY(item = rootItem->findChild<QQuickItem *>("footer"));
3312 QCOMPARE(item->property("text").toString(), QString("Hello!"));
3315 void tst_QQuickGridView::snapToRow_data()
3317 QTest::addColumn<QQuickGridView::Flow>("flow");
3318 QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
3319 QTest::addColumn<int>("highlightRangeMode");
3320 QTest::addColumn<QPoint>("flickStart");
3321 QTest::addColumn<QPoint>("flickEnd");
3322 QTest::addColumn<qreal>("snapAlignment");
3323 QTest::addColumn<qreal>("endExtent");
3324 QTest::addColumn<qreal>("startExtent");
3326 QTest::newRow("vertical, left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
3327 << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
3329 QTest::newRow("horizontal, left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
3330 << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1200.0 << 0.0;
3332 QTest::newRow("horizontal, right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
3333 << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 << -240.0;
3335 QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
3336 << QPoint(20, 200) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
3338 QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
3339 << QPoint(200, 20) << QPoint(20, 20) << 60.0 << 1340.0 << -20.0;
3341 QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
3342 << QPoint(20, 20) << QPoint(200, 20) << -60.0 << -1200.0 - 240.0 - 140.0 << -220.0;
3345 void tst_QQuickGridView::snapToRow()
3347 QFETCH(QQuickGridView::Flow, flow);
3348 QFETCH(Qt::LayoutDirection, layoutDirection);
3349 QFETCH(int, highlightRangeMode);
3350 QFETCH(QPoint, flickStart);
3351 QFETCH(QPoint, flickEnd);
3352 QFETCH(qreal, snapAlignment);
3353 QFETCH(qreal, endExtent);
3354 QFETCH(qreal, startExtent);
3356 QQuickView *canvas = createView();
3358 canvas->setSource(QUrl::fromLocalFile(TESTDATA("snapToRow.qml")));
3360 qApp->processEvents();
3362 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3363 QTRY_VERIFY(gridview != 0);
3365 gridview->setFlow(flow);
3366 gridview->setLayoutDirection(layoutDirection);
3367 gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
3369 QQuickItem *contentItem = gridview->contentItem();
3370 QTRY_VERIFY(contentItem != 0);
3372 // confirm that a flick hits an item boundary
3373 flick(canvas, flickStart, flickEnd, 180);
3374 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3375 if (flow == QQuickGridView::LeftToRight)
3376 QCOMPARE(qreal(fmod(gridview->contentY(),80.0)), snapAlignment);
3378 QCOMPARE(qreal(fmod(gridview->contentX(),80.0)), snapAlignment);
3382 flick(canvas, flickStart, flickEnd, 180);
3383 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3384 } while (flow == QQuickGridView::LeftToRight
3385 ? !gridview->isAtYEnd()
3386 : layoutDirection == Qt::LeftToRight ? !gridview->isAtXEnd() : !gridview->isAtXBeginning());
3388 if (flow == QQuickGridView::LeftToRight)
3389 QCOMPARE(gridview->contentY(), endExtent);
3391 QCOMPARE(gridview->contentX(), endExtent);
3395 flick(canvas, flickEnd, flickStart, 180);
3396 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3397 } while (flow == QQuickGridView::LeftToRight
3398 ? !gridview->isAtYBeginning()
3399 : layoutDirection == Qt::LeftToRight ? !gridview->isAtXBeginning() : !gridview->isAtXEnd());
3401 if (flow == QQuickGridView::LeftToRight)
3402 QCOMPARE(gridview->contentY(), startExtent);
3404 QCOMPARE(gridview->contentX(), startExtent);
3409 void tst_QQuickGridView::snapOneRow_data()
3411 QTest::addColumn<QQuickGridView::Flow>("flow");
3412 QTest::addColumn<Qt::LayoutDirection>("layoutDirection");
3413 QTest::addColumn<int>("highlightRangeMode");
3414 QTest::addColumn<QPoint>("flickStart");
3415 QTest::addColumn<QPoint>("flickEnd");
3416 QTest::addColumn<qreal>("snapAlignment");
3417 QTest::addColumn<qreal>("endExtent");
3418 QTest::addColumn<qreal>("startExtent");
3420 QTest::newRow("vertical, left to right") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
3421 << QPoint(20, 200) << QPoint(20, 20) << 100.0 << 360.0 << 0.0;
3423 QTest::newRow("horizontal, left to right") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange)
3424 << QPoint(200, 20) << QPoint(20, 20) << 100.0 << 360.0 << 0.0;
3426 QTest::newRow("horizontal, right to left") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange)
3427 << QPoint(20, 20) << QPoint(200, 20) << -340.0 << -360.0 - 240.0 << -240.0;
3429 QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::LeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
3430 << QPoint(20, 200) << QPoint(20, 20) << 100.0 << 460.0 << -20.0;
3432 QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::TopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange)
3433 << QPoint(200, 20) << QPoint(20, 20) << 100.0 << 460.0 << -20.0;
3435 QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::TopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange)
3436 << QPoint(20, 20) << QPoint(200, 20) << -340.0 << -360.0 - 240.0 - 100.0 << -220.0;
3439 void tst_QQuickGridView::snapOneRow()
3441 QFETCH(QQuickGridView::Flow, flow);
3442 QFETCH(Qt::LayoutDirection, layoutDirection);
3443 QFETCH(int, highlightRangeMode);
3444 QFETCH(QPoint, flickStart);
3445 QFETCH(QPoint, flickEnd);
3446 QFETCH(qreal, snapAlignment);
3447 QFETCH(qreal, endExtent);
3448 QFETCH(qreal, startExtent);
3450 QQuickView *canvas = createView();
3452 canvas->setSource(QUrl::fromLocalFile(TESTDATA("snapOneRow.qml")));
3454 qApp->processEvents();
3456 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3457 QTRY_VERIFY(gridview != 0);
3459 gridview->setFlow(flow);
3460 gridview->setLayoutDirection(layoutDirection);
3461 gridview->setHighlightRangeMode(QQuickItemView::HighlightRangeMode(highlightRangeMode));
3463 QQuickItem *contentItem = gridview->contentItem();
3464 QTRY_VERIFY(contentItem != 0);
3466 QSignalSpy currentIndexSpy(gridview, SIGNAL(currentIndexChanged()));
3468 // confirm that a flick hits next row boundary
3469 flick(canvas, flickStart, flickEnd, 180);
3470 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3471 if (flow == QQuickGridView::LeftToRight)
3472 QCOMPARE(gridview->contentY(), snapAlignment);
3474 QCOMPARE(gridview->contentX(), snapAlignment);
3476 if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
3477 QCOMPARE(gridview->currentIndex(), 2);
3478 QCOMPARE(currentIndexSpy.count(), 1);
3483 flick(canvas, flickStart, flickEnd, 180);
3484 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3485 } while (flow == QQuickGridView::LeftToRight
3486 ? !gridview->isAtYEnd()
3487 : layoutDirection == Qt::LeftToRight ? !gridview->isAtXEnd() : !gridview->isAtXBeginning());
3489 if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
3490 QCOMPARE(gridview->currentIndex(), 8);
3491 QCOMPARE(currentIndexSpy.count(), 4);
3494 if (flow == QQuickGridView::LeftToRight)
3495 QCOMPARE(gridview->contentY(), endExtent);
3497 QCOMPARE(gridview->contentX(), endExtent);
3501 flick(canvas, flickEnd, flickStart, 180);
3502 QTRY_VERIFY(gridview->isMoving() == false); // wait until it stops
3503 } while (flow == QQuickGridView::LeftToRight
3504 ? !gridview->isAtYBeginning()
3505 : layoutDirection == Qt::LeftToRight ? !gridview->isAtXBeginning() : !gridview->isAtXEnd());
3507 if (flow == QQuickGridView::LeftToRight)
3508 QCOMPARE(gridview->contentY(), startExtent);
3510 QCOMPARE(gridview->contentX(), startExtent);
3512 if (QQuickItemView::HighlightRangeMode(highlightRangeMode) == QQuickItemView::StrictlyEnforceRange) {
3513 QCOMPARE(gridview->currentIndex(), 0);
3514 QCOMPARE(currentIndexSpy.count(), 8);
3521 void tst_QQuickGridView::unaligned()
3523 QQuickView *canvas = createView();
3527 for (int i = 0; i < 10; i++)
3528 model.addItem("Item" + QString::number(i), "");
3530 QDeclarativeContext *ctxt = canvas->rootContext();
3531 ctxt->setContextProperty("testModel", &model);
3533 canvas->setSource(QUrl::fromLocalFile(TESTDATA("unaligned.qml")));
3534 qApp->processEvents();
3536 QQuickGridView *gridview = qobject_cast<QQuickGridView*>(canvas->rootObject());
3537 QVERIFY(gridview != 0);
3539 QQuickItem *contentItem = gridview->contentItem();
3540 QVERIFY(contentItem != 0);
3542 for (int i = 0; i < 10; ++i) {
3543 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3544 if (!item) qWarning() << "Item" << i << "not found";
3546 QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
3547 QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
3551 for (int i = 10; i < 18; ++i) {
3552 model.addItem("Item" + QString::number(i), "");
3553 QQuickItem *item = 0;
3554 QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
3555 QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
3556 QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
3560 for (int i = 0; i < 10; ++i) {
3561 model.insertItem(i, "Item" + QString::number(i), "");
3562 QQuickItem *item = 0;
3563 QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
3564 QCOMPARE(item->x(), qreal((i%9)*gridview->cellWidth()));
3565 QCOMPARE(item->y(), qreal((i/9)*gridview->cellHeight()));
3569 model.removeItems(7, 10);
3570 QTRY_COMPARE(model.count(), gridview->count());
3571 for (int i = 0; i < 18; ++i) {
3572 QQuickItem *item = 0;
3573 QTRY_VERIFY(item = findItem<QQuickItem>(contentItem, "wrapper", i));
3574 QCOMPARE(item->x(), qreal(i%9)*gridview->cellWidth());
3575 QCOMPARE(item->y(), qreal(i/9)*gridview->cellHeight());
3581 QQuickView *tst_QQuickGridView::createView()
3583 QQuickView *canvas = new QQuickView(0);
3584 canvas->setGeometry(0,0,240,320);
3589 void tst_QQuickGridView::flick(QQuickView *canvas, const QPoint &from, const QPoint &to, int duration)
3591 const int pointCount = 5;
3592 QPoint diff = to - from;
3594 // send press, five equally spaced moves, and release.
3595 QTest::mousePress(canvas, Qt::LeftButton, 0, from);
3597 for (int i = 0; i < pointCount; ++i) {
3598 QMouseEvent mv(QEvent::MouseMove, from + (i+1)*diff/pointCount, Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
3599 QApplication::sendEvent(canvas, &mv);
3600 QTest::qWait(duration/pointCount);
3601 QCoreApplication::processEvents();
3604 QTest::mouseRelease(canvas, Qt::LeftButton, 0, to);
3607 void tst_QQuickGridView::cacheBuffer()
3609 QQuickView *canvas = createView();
3612 for (int i = 0; i < 90; i++)
3613 model.addItem("Item" + QString::number(i), "");
3615 QDeclarativeContext *ctxt = canvas->rootContext();
3616 ctxt->setContextProperty("testModel", &model);
3617 ctxt->setContextProperty("testRightToLeft", QVariant(false));
3618 ctxt->setContextProperty("testTopToBottom", QVariant(false));
3620 canvas->setSource(QUrl::fromLocalFile(TESTDATA("gridview1.qml")));
3622 qApp->processEvents();
3624 QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
3625 QVERIFY(gridview != 0);
3627 QQuickItem *contentItem = gridview->contentItem();
3628 QVERIFY(contentItem != 0);
3629 QVERIFY(gridview->delegate() != 0);
3630 QVERIFY(gridview->model() != 0);
3632 // Confirm items positioned correctly
3633 int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
3634 for (int i = 0; i < model.count() && i < itemCount; ++i) {
3635 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3636 QTRY_COMPARE(item->x(), (i%3)*80.0);
3637 QTRY_COMPARE(item->y(), (i/3)*60.0);
3640 QDeclarativeIncubationController controller;
3641 canvas->engine()->setIncubationController(&controller);
3643 canvas->rootObject()->setProperty("cacheBuffer", 200);
3644 QTRY_VERIFY(gridview->cacheBuffer() == 200);
3646 // items will be created one at a time
3647 for (int i = itemCount; i < qMin(itemCount+9,model.count()); ++i) {
3648 QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
3649 QQuickItem *item = 0;
3652 controller.incubateWhile(&b);
3653 item = findItem<QQuickItem>(gridview, "wrapper", i);
3659 controller.incubateWhile(&b);
3662 int newItemCount = 0;
3663 newItemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
3665 // Confirm items positioned correctly
3666 for (int i = 0; i < model.count() && i < newItemCount; ++i) {
3667 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3669 QTRY_COMPARE(item->x(), (i%3)*80.0);
3670 QTRY_COMPARE(item->y(), (i/3)*60.0);
3673 // move view and confirm items in view are visible immediately and outside are created async
3674 gridview->setContentY(300);
3676 for (int i = 15; i < 34; ++i) { // 34 due to staggered item creation
3677 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3679 QTRY_COMPARE(item->x(), (i%3)*80.0);
3680 QTRY_COMPARE(item->y(), (i/3)*60.0);
3683 QVERIFY(findItem<QQuickItem>(gridview, "wrapper", 34) == 0);
3685 // ensure buffered items are created
3686 for (int i = 34; i < qMin(44,model.count()); ++i) {
3687 QQuickItem *item = 0;
3689 qGuiApp->processEvents(); // allow refill to happen
3691 controller.incubateWhile(&b);
3692 item = findItem<QQuickItem>(gridview, "wrapper", i);
3698 controller.incubateWhile(&b);
3704 void tst_QQuickGridView::asynchronous()
3706 QQuickView *canvas = createView();
3708 QDeclarativeIncubationController controller;
3709 canvas->engine()->setIncubationController(&controller);
3711 canvas->setSource(TESTDATA("asyncloader.qml"));
3713 QQuickItem *rootObject = qobject_cast<QQuickItem*>(canvas->rootObject());
3714 QVERIFY(rootObject);
3716 QQuickGridView *gridview = 0;
3719 controller.incubateWhile(&b);
3720 gridview = rootObject->findChild<QQuickGridView*>("view");
3723 // items will be created one at a time
3724 for (int i = 0; i < 12; ++i) {
3725 QVERIFY(findItem<QQuickItem>(gridview, "wrapper", i) == 0);
3726 QQuickItem *item = 0;
3729 controller.incubateWhile(&b);
3730 item = findItem<QQuickItem>(gridview, "wrapper", i);
3736 controller.incubateWhile(&b);
3739 // verify positioning
3740 QQuickItem *contentItem = gridview->contentItem();
3741 for (int i = 0; i < 12; ++i) {
3742 QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
3743 if (!item) qWarning() << "Item" << i << "not found";
3744 QVERIFY(item->x() == (i%3)*100);
3745 QVERIFY(item->y() == (i/3)*100);
3751 void tst_QQuickGridView::unrequestedVisibility()
3754 for (int i = 0; i < 30; i++)
3755 model.addItem("Item" + QString::number(i), QString::number(i));
3757 QQuickView *canvas = new QQuickView(0);
3758 canvas->setGeometry(0,0,240,320);
3760 QDeclarativeContext *ctxt = canvas->rootContext();
3761 ctxt->setContextProperty("testModel", &model);
3762 ctxt->setContextProperty("testWrap", QVariant(false));
3764 QString filename(TESTDATA("unrequestedItems.qml"));
3765 canvas->setSource(QUrl::fromLocalFile(filename));
3769 qApp->processEvents();
3771 QQuickGridView *leftview = findItem<QQuickGridView>(canvas->rootObject(), "leftGrid");
3772 QTRY_VERIFY(leftview != 0);
3774 QQuickGridView *rightview = findItem<QQuickGridView>(canvas->rootObject(), "rightGrid");
3775 QTRY_VERIFY(rightview != 0);
3777 QQuickItem *leftContent = leftview->contentItem();
3778 QTRY_VERIFY(leftContent != 0);
3780 QQuickItem *rightContent = rightview->contentItem();
3781 QTRY_VERIFY(rightContent != 0);
3783 rightview->setCurrentIndex(12);
3785 QTRY_COMPARE(leftview->contentY(), 0.0);
3786 QTRY_COMPARE(rightview->contentY(), 240.0);
3790 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3791 QCOMPARE(item->isVisible(), true);
3792 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
3793 QCOMPARE(item->isVisible(), false);
3795 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
3796 QCOMPARE(item->isVisible(), false);
3797 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
3798 QCOMPARE(item->isVisible(), true);
3800 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 9));
3801 QCOMPARE(item->isVisible(), true);
3802 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 10));
3803 QCOMPARE(item->isVisible(), false);
3804 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 3));
3805 QCOMPARE(item->isVisible(), false);
3806 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 4));
3807 QCOMPARE(item->isVisible(), true);
3809 rightview->setCurrentIndex(0);
3811 QTRY_COMPARE(leftview->contentY(), 0.0);
3812 QTRY_COMPARE(rightview->contentY(), 0.0);
3814 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3815 QCOMPARE(item->isVisible(), true);
3816 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
3817 QTRY_COMPARE(item->isVisible(), true);
3819 QVERIFY(!findItem<QQuickItem>(leftContent, "wrapper", 11));
3820 QVERIFY(!findItem<QQuickItem>(rightContent, "wrapper", 11));
3822 leftview->setCurrentIndex(12);
3824 QTRY_COMPARE(leftview->contentY(), 240.0);
3825 QTRY_COMPARE(rightview->contentY(), 0.0);
3827 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3828 QTRY_COMPARE(item->isVisible(), false);
3829 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
3830 QCOMPARE(item->isVisible(), true);
3832 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
3833 QCOMPARE(item->isVisible(), true);
3834 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
3835 QCOMPARE(item->isVisible(), false);
3837 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
3838 QCOMPARE(item->isVisible(), false);
3839 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
3840 QCOMPARE(item->isVisible(), true);
3841 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3842 QCOMPARE(item->isVisible(), true);
3843 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3844 QCOMPARE(item->isVisible(), false);
3846 model.moveItems(19, 1, 1);
3847 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3849 QTRY_VERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3850 QCOMPARE(item->isVisible(), false);
3851 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
3852 QCOMPARE(item->isVisible(), true);
3854 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
3855 QCOMPARE(item->isVisible(), true);
3856 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
3857 QCOMPARE(item->isVisible(), false);
3859 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
3860 QCOMPARE(item->isVisible(), false);
3861 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
3862 QCOMPARE(item->isVisible(), true);
3863 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3864 QCOMPARE(item->isVisible(), true);
3865 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3866 QCOMPARE(item->isVisible(), false);
3868 model.moveItems(3, 4, 1);
3869 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3871 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3872 QCOMPARE(item->isVisible(), false);
3873 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
3874 QCOMPARE(item->isVisible(), true);
3875 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3876 QCOMPARE(item->isVisible(), true);
3877 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3878 QCOMPARE(item->isVisible(), false);
3880 model.moveItems(4, 5, 1);
3881 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3883 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3884 QCOMPARE(item->isVisible(), false);
3885 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
3886 QCOMPARE(item->isVisible(), true);
3887 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3888 QCOMPARE(item->isVisible(), true);
3889 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3890 QCOMPARE(item->isVisible(), false);
3892 model.moveItems(9, 10, 1);
3893 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3895 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3896 QCOMPARE(item->isVisible(), false);
3897 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
3898 QCOMPARE(item->isVisible(), true);
3899 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3900 QCOMPARE(item->isVisible(), true);
3901 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3902 QCOMPARE(item->isVisible(), false);
3904 model.moveItems(10, 9, 1);
3905 QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);
3907 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
3908 QCOMPARE(item->isVisible(), false);
3909 QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
3910 QCOMPARE(item->isVisible(), true);
3911 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
3912 QCOMPARE(item->isVisible(), true);
3913 QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
3914 QCOMPARE(item->isVisible(), false);
3920 Find an item with the specified objectName. If index is supplied then the
3921 item must also evaluate the {index} expression equal to index
3923 template<typename T>
3924 T *tst_QQuickGridView::findItem(QQuickItem *parent, const QString &objectName, int index)
3926 const QMetaObject &mo = T::staticMetaObject;
3927 //qDebug() << parent->childItems().count() << "children";
3928 for (int i = 0; i < parent->childItems().count(); ++i) {
3929 QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
3932 //qDebug() << "try" << item;
3933 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
3935 QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
3937 if (context->contextProperty("index").toInt() == index) {
3938 return static_cast<T*>(item);
3942 return static_cast<T*>(item);
3945 item = findItem<T>(item, objectName, index);
3947 return static_cast<T*>(item);
3953 template<typename T>
3954 QList<T*> tst_QQuickGridView::findItems(QQuickItem *parent, const QString &objectName)
3957 const QMetaObject &mo = T::staticMetaObject;
3958 //qDebug() << parent->childItems().count() << "children";
3959 for (int i = 0; i < parent->childItems().count(); ++i) {
3960 QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
3963 //qDebug() << "try" << item;
3964 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
3965 items.append(static_cast<T*>(item));
3966 //qDebug() << " found:" << item;
3968 items += findItems<T>(item, objectName);
3974 void tst_QQuickGridView::dumpTree(QQuickItem *parent, int depth)
3976 static QString padding(" ");
3977 for (int i = 0; i < parent->childItems().count(); ++i) {
3978 QQuickItem *item = qobject_cast<QQuickItem*>(parent->childItems().at(i));
3981 QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
3982 qDebug() << padding.left(depth*2) << item << (context ? context->contextProperty("index").toInt() : -1);
3983 dumpTree(item, depth+1);
3988 QTEST_MAIN(tst_QQuickGridView)
3990 #include "tst_qquickgridview.moc"