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 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include <QtTest/QtTest>
43 #include <QtGui/qstringlistmodel.h>
44 #include <QtDeclarative/qsgview.h>
45 #include <QtDeclarative/qdeclarativeengine.h>
46 #include <QtDeclarative/qdeclarativecomponent.h>
47 #include <QtDeclarative/qdeclarativecontext.h>
48 #include <QtDeclarative/qdeclarativeexpression.h>
49 #include <QtDeclarative/private/qsgitem_p.h>
50 #include <QtDeclarative/private/qlistmodelinterface_p.h>
51 #include <QtDeclarative/private/qsggridview_p.h>
52 #include <QtDeclarative/private/qsgtext_p.h>
53 #include <QtDeclarative/private/qdeclarativelistmodel_p.h>
54 #include "../../../shared/util.h"
57 // In Symbian OS test data is located in applications private dir
61 class tst_QSGGridView : public QObject
76 void noCurrentIndex();
79 void propertyChanges();
80 void componentChanges();
82 void positionViewAtIndex();
83 void positionViewAtIndex_rightToLeft();
88 void enforceRange_rightToLeft();
90 void manualHighlight();
98 void testQtQuick11Attributes();
99 void testQtQuick11Attributes_data();
102 QSGView *createView();
104 T *findItem(QSGItem *parent, const QString &id, int index=-1);
106 QList<T*> findItems(QSGItem *parent, const QString &objectName);
107 void dumpTree(QSGItem *parent, int depth = 0);
110 class TestModel : public QAbstractListModel
113 enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
115 TestModel(QObject *parent=0) : QAbstractListModel(parent) {
116 QHash<int, QByteArray> roles;
117 roles[Name] = "name";
118 roles[Number] = "number";
122 int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
123 QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
126 rv = list.at(index.row()).first;
127 else if (role == Number)
128 rv = list.at(index.row()).second;
133 int count() const { return rowCount(); }
134 QString name(int index) const { return list.at(index).first; }
135 QString number(int index) const { return list.at(index).second; }
137 void addItem(const QString &name, const QString &number) {
138 emit beginInsertRows(QModelIndex(), list.count(), list.count());
139 list.append(QPair<QString,QString>(name, number));
140 emit endInsertRows();
143 void addItems(const QList<QPair<QString, QString> > &items) {
144 emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1);
145 for (int i=0; i<items.count(); i++)
146 list.append(QPair<QString,QString>(items[i].first, items[i].second));
147 emit endInsertRows();
150 void insertItem(int index, const QString &name, const QString &number) {
151 emit beginInsertRows(QModelIndex(), index, index);
152 list.insert(index, QPair<QString,QString>(name, number));
153 emit endInsertRows();
156 void removeItem(int index) {
157 emit beginRemoveRows(QModelIndex(), index, index);
158 list.removeAt(index);
159 emit endRemoveRows();
162 void removeItems(int index, int count) {
163 emit beginRemoveRows(QModelIndex(), index, index+count-1);
165 list.removeAt(index);
166 emit endRemoveRows();
169 void moveItem(int from, int to) {
170 emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
175 void modifyItem(int idx, const QString &name, const QString &number) {
176 list[idx] = QPair<QString,QString>(name, number);
177 emit dataChanged(index(idx,0), index(idx,0));
181 int count = list.count();
182 emit beginRemoveRows(QModelIndex(), 0, count-1);
184 emit endRemoveRows();
189 QList<QPair<QString,QString> > list;
192 tst_QSGGridView::tst_QSGGridView()
196 void tst_QSGGridView::items()
198 QSGView *canvas = createView();
201 model.addItem("Fred", "12345");
202 model.addItem("John", "2345");
203 model.addItem("Bob", "54321");
204 model.addItem("Billy", "22345");
205 model.addItem("Sam", "2945");
206 model.addItem("Ben", "04321");
207 model.addItem("Jim", "0780");
209 QDeclarativeContext *ctxt = canvas->rootContext();
210 ctxt->setContextProperty("testModel", &model);
211 ctxt->setContextProperty("testRightToLeft", QVariant(false));
212 ctxt->setContextProperty("testTopToBottom", QVariant(false));
214 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
215 qApp->processEvents();
217 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
218 QTRY_VERIFY(gridview != 0);
220 QSGItem *contentItem = gridview->contentItem();
221 QTRY_VERIFY(contentItem != 0);
223 QTRY_COMPARE(gridview->count(), model.count());
224 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
226 for (int i = 0; i < model.count(); ++i) {
227 QSGText *name = findItem<QSGText>(contentItem, "textName", i);
228 QTRY_VERIFY(name != 0);
229 QTRY_COMPARE(name->text(), model.name(i));
230 QSGText *number = findItem<QSGText>(contentItem, "textNumber", i);
231 QTRY_VERIFY(number != 0);
232 QTRY_COMPARE(number->text(), model.number(i));
235 // set an empty model and confirm that items are destroyed
237 ctxt->setContextProperty("testModel", &model2);
239 int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
240 QTRY_VERIFY(itemCount == 0);
245 void tst_QSGGridView::changed()
247 QSGView *canvas = createView();
250 model.addItem("Fred", "12345");
251 model.addItem("John", "2345");
252 model.addItem("Bob", "54321");
253 model.addItem("Billy", "22345");
254 model.addItem("Sam", "2945");
255 model.addItem("Ben", "04321");
256 model.addItem("Jim", "0780");
258 QDeclarativeContext *ctxt = canvas->rootContext();
259 ctxt->setContextProperty("testModel", &model);
260 ctxt->setContextProperty("testRightToLeft", QVariant(false));
261 ctxt->setContextProperty("testTopToBottom", QVariant(false));
263 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
264 qApp->processEvents();
266 QSGFlickable *gridview = findItem<QSGFlickable>(canvas->rootObject(), "grid");
267 QTRY_VERIFY(gridview != 0);
269 QSGItem *contentItem = gridview->contentItem();
270 QTRY_VERIFY(contentItem != 0);
272 model.modifyItem(1, "Will", "9876");
273 QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
274 QTRY_VERIFY(name != 0);
275 QTRY_COMPARE(name->text(), model.name(1));
276 QSGText *number = findItem<QSGText>(contentItem, "textNumber", 1);
277 QTRY_VERIFY(number != 0);
278 QTRY_COMPARE(number->text(), model.number(1));
283 void tst_QSGGridView::inserted()
285 QSGView *canvas = createView();
289 model.addItem("Fred", "12345");
290 model.addItem("John", "2345");
291 model.addItem("Bob", "54321");
293 QDeclarativeContext *ctxt = canvas->rootContext();
294 ctxt->setContextProperty("testModel", &model);
295 ctxt->setContextProperty("testRightToLeft", QVariant(false));
296 ctxt->setContextProperty("testTopToBottom", QVariant(false));
298 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
299 qApp->processEvents();
301 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
302 QTRY_VERIFY(gridview != 0);
304 QSGItem *contentItem = gridview->contentItem();
305 QTRY_VERIFY(contentItem != 0);
307 model.insertItem(1, "Will", "9876");
309 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
311 QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
312 QTRY_VERIFY(name != 0);
313 QTRY_COMPARE(name->text(), model.name(1));
314 QSGText *number = findItem<QSGText>(contentItem, "textNumber", 1);
315 QTRY_VERIFY(number != 0);
316 QTRY_COMPARE(number->text(), model.number(1));
318 // Checks that onAdd is called
319 int added = canvas->rootObject()->property("added").toInt();
320 QTRY_COMPARE(added, 1);
322 // Confirm items positioned correctly
323 for (int i = 0; i < model.count(); ++i) {
324 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
325 QTRY_COMPARE(item->x(), (i%3)*80.0);
326 QTRY_COMPARE(item->y(), (i/3)*60.0);
329 model.insertItem(0, "Foo", "1111"); // zero index, and current item
331 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
333 name = findItem<QSGText>(contentItem, "textName", 0);
334 QTRY_VERIFY(name != 0);
335 QTRY_COMPARE(name->text(), model.name(0));
336 number = findItem<QSGText>(contentItem, "textNumber", 0);
337 QTRY_VERIFY(number != 0);
338 QTRY_COMPARE(number->text(), model.number(0));
340 QTRY_COMPARE(gridview->currentIndex(), 1);
342 // Confirm items positioned correctly
343 for (int i = 0; i < model.count(); ++i) {
344 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
345 QTRY_VERIFY(item->x() == (i%3)*80);
346 QTRY_VERIFY(item->y() == (i/3)*60);
349 for (int i = model.count(); i < 30; ++i)
350 model.insertItem(i, "Hello", QString::number(i));
352 gridview->setContentY(120);
354 // Insert item outside visible area
355 model.insertItem(1, "Hello", "1324");
357 QTRY_VERIFY(gridview->contentY() == 120);
362 void tst_QSGGridView::removed()
364 QSGView *canvas = createView();
368 for (int i = 0; i < 40; i++)
369 model.addItem("Item" + QString::number(i), "");
371 QDeclarativeContext *ctxt = canvas->rootContext();
372 ctxt->setContextProperty("testModel", &model);
373 ctxt->setContextProperty("testRightToLeft", QVariant(false));
374 ctxt->setContextProperty("testTopToBottom", QVariant(false));
376 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
377 qApp->processEvents();
379 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
380 QTRY_VERIFY(gridview != 0);
382 QSGItem *contentItem = gridview->contentItem();
383 QTRY_VERIFY(contentItem != 0);
387 QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
388 QTRY_VERIFY(name != 0);
389 QTRY_COMPARE(name->text(), model.name(1));
390 QSGText *number = findItem<QSGText>(contentItem, "textNumber", 1);
391 QTRY_VERIFY(number != 0);
392 QTRY_COMPARE(number->text(), model.number(1));
394 // Checks that onRemove is called
395 QString removed = canvas->rootObject()->property("removed").toString();
396 QTRY_COMPARE(removed, QString("Item1"));
398 // Confirm items positioned correctly
399 int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
400 for (int i = 0; i < model.count() && i < itemCount; ++i) {
401 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
402 if (!item) qWarning() << "Item" << i << "not found";
404 QTRY_VERIFY(item->x() == (i%3)*80);
405 QTRY_VERIFY(item->y() == (i/3)*60);
408 // Remove first item (which is the current item);
411 name = findItem<QSGText>(contentItem, "textName", 0);
412 QTRY_VERIFY(name != 0);
413 QTRY_COMPARE(name->text(), model.name(0));
414 number = findItem<QSGText>(contentItem, "textNumber", 0);
415 QTRY_VERIFY(number != 0);
416 QTRY_COMPARE(number->text(), model.number(0));
418 // Confirm items positioned correctly
419 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
420 for (int i = 0; i < model.count() && i < itemCount; ++i) {
421 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
422 if (!item) qWarning() << "Item" << i << "not found";
424 QTRY_VERIFY(item->x() == (i%3)*80);
425 QTRY_VERIFY(item->y() == (i/3)*60);
428 // Remove items not visible
429 model.removeItem(25);
431 // Confirm items positioned correctly
432 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
433 for (int i = 0; i < model.count() && i < itemCount; ++i) {
434 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
435 if (!item) qWarning() << "Item" << i << "not found";
437 QTRY_VERIFY(item->x() == (i%3)*80);
438 QTRY_VERIFY(item->y() == (i/3)*60);
441 // Remove items before visible
442 gridview->setContentY(120);
443 gridview->setCurrentIndex(10);
445 // Setting currentIndex above shouldn't cause view to scroll
446 QTRY_COMPARE(gridview->contentY(), 120.0);
450 // Confirm items positioned correctly
451 for (int i = 6; i < 18; ++i) {
452 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
453 if (!item) qWarning() << "Item" << i << "not found";
455 QTRY_VERIFY(item->x() == (i%3)*80);
456 QTRY_VERIFY(item->y() == (i/3)*60);
459 // Remove currentIndex
460 QSGItem *oldCurrent = gridview->currentItem();
463 QTRY_COMPARE(gridview->currentIndex(), 9);
464 QTRY_VERIFY(gridview->currentItem() != oldCurrent);
466 gridview->setContentY(0);
467 // let transitions settle.
470 // Confirm items positioned correctly
471 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
472 for (int i = 0; i < model.count() && i < itemCount; ++i) {
473 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
474 if (!item) qWarning() << "Item" << i << "not found";
476 QTRY_VERIFY(item->x() == (i%3)*80);
477 QTRY_VERIFY(item->y() == (i/3)*60);
480 // remove item outside current view.
481 gridview->setCurrentIndex(32);
482 gridview->setContentY(240);
484 model.removeItem(30);
485 QTRY_VERIFY(gridview->currentIndex() == 31);
487 // remove current item beyond visible items.
488 gridview->setCurrentIndex(20);
489 gridview->setContentY(0);
490 model.removeItem(20);
492 QTRY_COMPARE(gridview->currentIndex(), 20);
493 QTRY_VERIFY(gridview->currentItem() != 0);
495 // remove item before current, but visible
496 gridview->setCurrentIndex(8);
497 gridview->setContentY(240);
498 oldCurrent = gridview->currentItem();
501 QTRY_COMPARE(gridview->currentIndex(), 7);
502 QTRY_VERIFY(gridview->currentItem() == oldCurrent);
507 void tst_QSGGridView::clear()
509 QSGView *canvas = createView();
512 for (int i = 0; i < 30; i++)
513 model.addItem("Item" + QString::number(i), "");
515 QDeclarativeContext *ctxt = canvas->rootContext();
516 ctxt->setContextProperty("testModel", &model);
517 ctxt->setContextProperty("testRightToLeft", QVariant(false));
518 ctxt->setContextProperty("testTopToBottom", QVariant(false));
520 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
521 qApp->processEvents();
523 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
524 QVERIFY(gridview != 0);
526 QSGItem *contentItem = gridview->contentItem();
527 QVERIFY(contentItem != 0);
531 QVERIFY(gridview->count() == 0);
532 QVERIFY(gridview->currentItem() == 0);
533 QVERIFY(gridview->contentY() == 0);
534 QVERIFY(gridview->currentIndex() == -1);
536 // confirm sanity when adding an item to cleared list
537 model.addItem("New", "1");
538 QVERIFY(gridview->count() == 1);
539 QVERIFY(gridview->currentItem() != 0);
540 QVERIFY(gridview->currentIndex() == 0);
545 void tst_QSGGridView::moved()
547 QSGView *canvas = createView();
550 for (int i = 0; i < 30; i++)
551 model.addItem("Item" + QString::number(i), "");
553 QDeclarativeContext *ctxt = canvas->rootContext();
554 ctxt->setContextProperty("testModel", &model);
555 ctxt->setContextProperty("testRightToLeft", QVariant(false));
556 ctxt->setContextProperty("testTopToBottom", QVariant(false));
558 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
559 qApp->processEvents();
561 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
562 QTRY_VERIFY(gridview != 0);
564 QSGItem *contentItem = gridview->contentItem();
565 QTRY_VERIFY(contentItem != 0);
567 model.moveItem(1, 8);
569 QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
570 QTRY_VERIFY(name != 0);
571 QTRY_COMPARE(name->text(), model.name(1));
572 QSGText *number = findItem<QSGText>(contentItem, "textNumber", 1);
573 QTRY_VERIFY(number != 0);
574 QTRY_COMPARE(number->text(), model.number(1));
576 name = findItem<QSGText>(contentItem, "textName", 8);
577 QTRY_VERIFY(name != 0);
578 QTRY_COMPARE(name->text(), model.name(8));
579 number = findItem<QSGText>(contentItem, "textNumber", 8);
580 QTRY_VERIFY(number != 0);
581 QTRY_COMPARE(number->text(), model.number(8));
583 // Confirm items positioned correctly
584 int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
585 for (int i = 0; i < model.count() && i < itemCount; ++i) {
586 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
587 if (!item) qWarning() << "Item" << i << "not found";
589 QTRY_VERIFY(item->x() == (i%3)*80);
590 QTRY_VERIFY(item->y() == (i/3)*60);
593 gridview->setContentY(120);
595 // move outside visible area
596 model.moveItem(1, 25);
598 // Confirm items positioned correctly and indexes correct
599 itemCount = findItems<QSGItem>(contentItem, "wrapper").count()-1;
600 for (int i = 6; i < model.count()-6 && i < itemCount+6; ++i) {
601 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
602 if (!item) qWarning() << "Item" << i << "not found";
604 QTRY_COMPARE(item->x(), qreal((i%3)*80));
605 QTRY_COMPARE(item->y(), qreal((i/3)*60));
606 name = findItem<QSGText>(contentItem, "textName", i);
607 QTRY_VERIFY(name != 0);
608 QTRY_COMPARE(name->text(), model.name(i));
609 number = findItem<QSGText>(contentItem, "textNumber", i);
610 QTRY_VERIFY(number != 0);
611 QTRY_COMPARE(number->text(), model.number(i));
614 // move from outside visible into visible
615 model.moveItem(28, 8);
617 // Confirm items positioned correctly and indexes correct
618 for (int i = 6; i < model.count()-6 && i < itemCount+6; ++i) {
619 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
620 if (!item) qWarning() << "Item" << i << "not found";
622 QTRY_VERIFY(item->x() == (i%3)*80);
623 QTRY_VERIFY(item->y() == (i/3)*60);
624 name = findItem<QSGText>(contentItem, "textName", i);
625 QTRY_VERIFY(name != 0);
626 QTRY_COMPARE(name->text(), model.name(i));
627 number = findItem<QSGText>(contentItem, "textNumber", i);
628 QTRY_VERIFY(number != 0);
629 QTRY_COMPARE(number->text(), model.number(i));
632 // ensure content position is stable
633 gridview->setContentY(0);
634 model.moveItem(10, 0);
635 QTRY_VERIFY(gridview->contentY() == 0);
640 void tst_QSGGridView::currentIndex()
643 for (int i = 0; i < 60; i++)
644 model.addItem("Item" + QString::number(i), QString::number(i));
646 QSGView *canvas = new QSGView(0);
647 canvas->setFixedSize(240,320);
649 QDeclarativeContext *ctxt = canvas->rootContext();
650 ctxt->setContextProperty("testModel", &model);
652 QString filename(SRCDIR "/data/gridview-initCurrent.qml");
653 canvas->setSource(QUrl::fromLocalFile(filename));
655 qApp->processEvents();
657 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
658 QVERIFY(gridview != 0);
660 QSGItem *contentItem = gridview->contentItem();
661 QVERIFY(contentItem != 0);
663 // current item should be third item
664 QCOMPARE(gridview->currentIndex(), 35);
665 QCOMPARE(gridview->currentItem(), findItem<QSGItem>(contentItem, "wrapper", 35));
666 QCOMPARE(gridview->currentItem()->y(), gridview->highlightItem()->y());
667 QCOMPARE(gridview->contentY(), 400.0);
669 gridview->moveCurrentIndexRight();
670 QCOMPARE(gridview->currentIndex(), 36);
671 gridview->moveCurrentIndexDown();
672 QCOMPARE(gridview->currentIndex(), 39);
673 gridview->moveCurrentIndexUp();
674 QCOMPARE(gridview->currentIndex(), 36);
675 gridview->moveCurrentIndexLeft();
676 QCOMPARE(gridview->currentIndex(), 35);
679 gridview->setCurrentIndex(0);
680 QCOMPARE(gridview->currentIndex(), 0);
681 // confirm that the velocity is updated
682 QTRY_VERIFY(gridview->verticalVelocity() != 0.0);
684 gridview->moveCurrentIndexUp();
685 QCOMPARE(gridview->currentIndex(), 0);
687 gridview->moveCurrentIndexLeft();
688 QCOMPARE(gridview->currentIndex(), 0);
690 gridview->setCurrentIndex(model.count()-1);
691 QCOMPARE(gridview->currentIndex(), model.count()-1);
693 gridview->moveCurrentIndexRight();
694 QCOMPARE(gridview->currentIndex(), model.count()-1);
696 gridview->moveCurrentIndexDown();
697 QCOMPARE(gridview->currentIndex(), model.count()-1);
700 gridview->setWrapEnabled(true);
702 gridview->setCurrentIndex(0);
703 QCOMPARE(gridview->currentIndex(), 0);
705 gridview->moveCurrentIndexLeft();
706 QCOMPARE(gridview->currentIndex(), model.count()-1);
708 QTRY_COMPARE(gridview->contentY(), 880.0);
710 gridview->moveCurrentIndexRight();
711 QCOMPARE(gridview->currentIndex(), 0);
713 QTRY_COMPARE(gridview->contentY(), 0.0);
717 qApp->setActiveWindow(canvas);
719 // to be safe and avoid failing setFocus with window managers
720 qt_x11_wait_for_window_manager(canvas);
722 QTRY_VERIFY(canvas->hasFocus());
723 qApp->processEvents();
725 QTest::keyClick(canvas, Qt::Key_Down);
726 QCOMPARE(gridview->currentIndex(), 3);
728 QTest::keyClick(canvas, Qt::Key_Up);
729 QCOMPARE(gridview->currentIndex(), 0);
731 gridview->setFlow(QSGGridView::TopToBottom);
733 qApp->setActiveWindow(canvas);
735 // to be safe and avoid failing setFocus with window managers
736 qt_x11_wait_for_window_manager(canvas);
738 QTRY_VERIFY(canvas->hasFocus());
739 qApp->processEvents();
741 QTest::keyClick(canvas, Qt::Key_Right);
742 QCOMPARE(gridview->currentIndex(), 5);
744 QTest::keyClick(canvas, Qt::Key_Left);
745 QCOMPARE(gridview->currentIndex(), 0);
747 QTest::keyClick(canvas, Qt::Key_Down);
748 QCOMPARE(gridview->currentIndex(), 1);
750 QTest::keyClick(canvas, Qt::Key_Up);
751 QCOMPARE(gridview->currentIndex(), 0);
754 // turn off auto highlight
755 gridview->setHighlightFollowsCurrentItem(false);
756 QVERIFY(gridview->highlightFollowsCurrentItem() == false);
757 QVERIFY(gridview->highlightItem());
758 qreal hlPosX = gridview->highlightItem()->x();
759 qreal hlPosY = gridview->highlightItem()->y();
761 gridview->setCurrentIndex(5);
762 QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
763 QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
765 // insert item before currentIndex
766 gridview->setCurrentIndex(28);
767 model.insertItem(0, "Foo", "1111");
768 QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
770 // check removing highlight by setting currentIndex to -1;
771 gridview->setCurrentIndex(-1);
773 QCOMPARE(gridview->currentIndex(), -1);
774 QVERIFY(!gridview->highlightItem());
775 QVERIFY(!gridview->currentItem());
777 gridview->setHighlightFollowsCurrentItem(true);
779 gridview->setFlow(QSGGridView::LeftToRight);
780 gridview->setLayoutDirection(Qt::RightToLeft);
782 qApp->setActiveWindow(canvas);
784 // to be safe and avoid failing setFocus with window managers
785 qt_x11_wait_for_window_manager(canvas);
787 QTRY_VERIFY(canvas->hasFocus());
788 qApp->processEvents();
790 gridview->setCurrentIndex(35);
792 QTest::keyClick(canvas, Qt::Key_Right);
793 QCOMPARE(gridview->currentIndex(), 34);
795 QTest::keyClick(canvas, Qt::Key_Down);
796 QCOMPARE(gridview->currentIndex(), 37);
798 QTest::keyClick(canvas, Qt::Key_Up);
799 QCOMPARE(gridview->currentIndex(), 34);
801 QTest::keyClick(canvas, Qt::Key_Left);
802 QCOMPARE(gridview->currentIndex(), 35);
805 // turn off auto highlight
806 gridview->setHighlightFollowsCurrentItem(false);
807 QVERIFY(gridview->highlightFollowsCurrentItem() == false);
808 QVERIFY(gridview->highlightItem());
809 hlPosX = gridview->highlightItem()->x();
810 hlPosY = gridview->highlightItem()->y();
812 gridview->setCurrentIndex(5);
813 QTRY_COMPARE(gridview->highlightItem()->x(), hlPosX);
814 QTRY_COMPARE(gridview->highlightItem()->y(), hlPosY);
816 // insert item before currentIndex
817 gridview->setCurrentIndex(28);
818 model.insertItem(0, "Foo", "1111");
819 QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
821 // check removing highlight by setting currentIndex to -1;
822 gridview->setCurrentIndex(-1);
824 QCOMPARE(gridview->currentIndex(), -1);
825 QVERIFY(!gridview->highlightItem());
826 QVERIFY(!gridview->currentItem());
831 void tst_QSGGridView::noCurrentIndex()
834 for (int i = 0; i < 60; i++)
835 model.addItem("Item" + QString::number(i), QString::number(i));
837 QSGView *canvas = new QSGView(0);
838 canvas->setFixedSize(240,320);
840 QDeclarativeContext *ctxt = canvas->rootContext();
841 ctxt->setContextProperty("testModel", &model);
843 QString filename(SRCDIR "/data/gridview-noCurrent.qml");
844 canvas->setSource(QUrl::fromLocalFile(filename));
846 qApp->processEvents();
848 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
849 QVERIFY(gridview != 0);
851 QSGItem *contentItem = gridview->contentItem();
852 QVERIFY(contentItem != 0);
854 // current index should be -1
855 QCOMPARE(gridview->currentIndex(), -1);
856 QVERIFY(!gridview->currentItem());
857 QVERIFY(!gridview->highlightItem());
858 QCOMPARE(gridview->contentY(), 0.0);
860 gridview->setCurrentIndex(5);
861 QCOMPARE(gridview->currentIndex(), 5);
862 QVERIFY(gridview->currentItem());
863 QVERIFY(gridview->highlightItem());
868 void tst_QSGGridView::changeFlow()
870 QSGView *canvas = createView();
873 for (int i = 0; i < 30; i++)
874 model.addItem("Item" + QString::number(i), QString::number(i));
876 QDeclarativeContext *ctxt = canvas->rootContext();
877 ctxt->setContextProperty("testModel", &model);
878 ctxt->setContextProperty("testRightToLeft", QVariant(false));
879 ctxt->setContextProperty("testTopToBottom", QVariant(false));
881 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
882 qApp->processEvents();
884 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
885 QTRY_VERIFY(gridview != 0);
887 QSGItem *contentItem = gridview->contentItem();
888 QTRY_VERIFY(contentItem != 0);
890 // Confirm items positioned correctly and indexes correct
891 int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
892 for (int i = 0; i < model.count() && i < itemCount; ++i) {
893 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
894 if (!item) qWarning() << "Item" << i << "not found";
896 QTRY_COMPARE(item->x(), qreal((i%3)*80));
897 QTRY_COMPARE(item->y(), qreal((i/3)*60));
898 QSGText *name = findItem<QSGText>(contentItem, "textName", i);
899 QTRY_VERIFY(name != 0);
900 QTRY_COMPARE(name->text(), model.name(i));
901 QSGText *number = findItem<QSGText>(contentItem, "textNumber", i);
902 QTRY_VERIFY(number != 0);
903 QTRY_COMPARE(number->text(), model.number(i));
906 ctxt->setContextProperty("testTopToBottom", QVariant(true));
908 // Confirm items positioned correctly and indexes correct
909 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
910 for (int i = 0; i < model.count() && i < itemCount; ++i) {
911 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
912 if (!item) qWarning() << "Item" << i << "not found";
914 QTRY_COMPARE(item->x(), qreal((i/5)*80));
915 QTRY_COMPARE(item->y(), qreal((i%5)*60));
916 QSGText *name = findItem<QSGText>(contentItem, "textName", i);
917 QTRY_VERIFY(name != 0);
918 QTRY_COMPARE(name->text(), model.name(i));
919 QSGText *number = findItem<QSGText>(contentItem, "textNumber", i);
920 QTRY_VERIFY(number != 0);
921 QTRY_COMPARE(number->text(), model.number(i));
924 ctxt->setContextProperty("testRightToLeft", QVariant(true));
926 // Confirm items positioned correctly and indexes correct
927 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
928 for (int i = 0; i < model.count() && i < itemCount; ++i) {
929 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
930 if (!item) qWarning() << "Item" << i << "not found";
932 QTRY_COMPARE(item->x(), qreal(-(i/5)*80 - item->width()));
933 QTRY_COMPARE(item->y(), qreal((i%5)*60));
934 QSGText *name = findItem<QSGText>(contentItem, "textName", i);
935 QTRY_VERIFY(name != 0);
936 QTRY_COMPARE(name->text(), model.name(i));
937 QSGText *number = findItem<QSGText>(contentItem, "textNumber", i);
938 QTRY_VERIFY(number != 0);
939 QTRY_COMPARE(number->text(), model.number(i));
941 gridview->setContentX(100);
942 QTRY_COMPARE(gridview->contentX(), 100.);
943 ctxt->setContextProperty("testTopToBottom", QVariant(false));
944 QTRY_COMPARE(gridview->contentX(), 0.);
946 // Confirm items positioned correctly and indexes correct
947 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
948 for (int i = 0; i < model.count() && i < itemCount; ++i) {
949 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
950 if (!item) qWarning() << "Item" << i << "not found";
952 QTRY_COMPARE(item->x(), qreal(240 - (i%3+1)*80));
953 QTRY_COMPARE(item->y(), qreal((i/3)*60));
954 QSGText *name = findItem<QSGText>(contentItem, "textName", i);
955 QTRY_VERIFY(name != 0);
956 QTRY_COMPARE(name->text(), model.name(i));
957 QSGText *number = findItem<QSGText>(contentItem, "textNumber", i);
958 QTRY_VERIFY(number != 0);
959 QTRY_COMPARE(number->text(), model.number(i));
965 void tst_QSGGridView::defaultValues()
967 QDeclarativeEngine engine;
968 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/gridview3.qml"));
969 QSGGridView *obj = qobject_cast<QSGGridView*>(c.create());
971 QTRY_VERIFY(obj != 0);
972 QTRY_VERIFY(obj->model() == QVariant());
973 QTRY_VERIFY(obj->delegate() == 0);
974 QTRY_COMPARE(obj->currentIndex(), -1);
975 QTRY_VERIFY(obj->currentItem() == 0);
976 QTRY_COMPARE(obj->count(), 0);
977 QTRY_VERIFY(obj->highlight() == 0);
978 QTRY_VERIFY(obj->highlightItem() == 0);
979 QTRY_COMPARE(obj->highlightFollowsCurrentItem(), true);
980 QTRY_VERIFY(obj->flow() == 0);
981 QTRY_COMPARE(obj->isWrapEnabled(), false);
982 QTRY_COMPARE(obj->cacheBuffer(), 0);
983 QTRY_COMPARE(obj->cellWidth(), 100); //### Should 100 be the default?
984 QTRY_COMPARE(obj->cellHeight(), 100);
988 void tst_QSGGridView::properties()
990 QDeclarativeEngine engine;
991 QDeclarativeComponent c(&engine, QUrl::fromLocalFile(SRCDIR "/data/gridview2.qml"));
992 QSGGridView *obj = qobject_cast<QSGGridView*>(c.create());
994 QTRY_VERIFY(obj != 0);
995 QTRY_VERIFY(obj->model() != QVariant());
996 QTRY_VERIFY(obj->delegate() != 0);
997 QTRY_COMPARE(obj->currentIndex(), 0);
998 QTRY_VERIFY(obj->currentItem() != 0);
999 QTRY_COMPARE(obj->count(), 4);
1000 QTRY_VERIFY(obj->highlight() != 0);
1001 QTRY_VERIFY(obj->highlightItem() != 0);
1002 QTRY_COMPARE(obj->highlightFollowsCurrentItem(), false);
1003 QTRY_VERIFY(obj->flow() == 0);
1004 QTRY_COMPARE(obj->isWrapEnabled(), true);
1005 QTRY_COMPARE(obj->cacheBuffer(), 200);
1006 QTRY_COMPARE(obj->cellWidth(), 100);
1007 QTRY_COMPARE(obj->cellHeight(), 100);
1011 void tst_QSGGridView::propertyChanges()
1013 QSGView *canvas = createView();
1014 QTRY_VERIFY(canvas);
1015 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1017 QSGGridView *gridView = canvas->rootObject()->findChild<QSGGridView*>("gridView");
1018 QTRY_VERIFY(gridView);
1020 QSignalSpy keyNavigationWrapsSpy(gridView, SIGNAL(keyNavigationWrapsChanged()));
1021 QSignalSpy cacheBufferSpy(gridView, SIGNAL(cacheBufferChanged()));
1022 QSignalSpy layoutSpy(gridView, SIGNAL(layoutDirectionChanged()));
1023 QSignalSpy flowSpy(gridView, SIGNAL(flowChanged()));
1025 QTRY_COMPARE(gridView->isWrapEnabled(), true);
1026 QTRY_COMPARE(gridView->cacheBuffer(), 10);
1027 QTRY_COMPARE(gridView->flow(), QSGGridView::LeftToRight);
1029 gridView->setWrapEnabled(false);
1030 gridView->setCacheBuffer(3);
1031 gridView->setFlow(QSGGridView::TopToBottom);
1033 QTRY_COMPARE(gridView->isWrapEnabled(), false);
1034 QTRY_COMPARE(gridView->cacheBuffer(), 3);
1035 QTRY_COMPARE(gridView->flow(), QSGGridView::TopToBottom);
1037 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1038 QTRY_COMPARE(cacheBufferSpy.count(),1);
1039 QTRY_COMPARE(flowSpy.count(),1);
1041 gridView->setWrapEnabled(false);
1042 gridView->setCacheBuffer(3);
1043 gridView->setFlow(QSGGridView::TopToBottom);
1045 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1046 QTRY_COMPARE(cacheBufferSpy.count(),1);
1047 QTRY_COMPARE(flowSpy.count(),1);
1049 gridView->setFlow(QSGGridView::LeftToRight);
1050 QTRY_COMPARE(gridView->flow(), QSGGridView::LeftToRight);
1052 gridView->setWrapEnabled(true);
1053 gridView->setCacheBuffer(5);
1054 gridView->setLayoutDirection(Qt::RightToLeft);
1056 QTRY_COMPARE(gridView->isWrapEnabled(), true);
1057 QTRY_COMPARE(gridView->cacheBuffer(), 5);
1058 QTRY_COMPARE(gridView->layoutDirection(), Qt::RightToLeft);
1060 QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
1061 QTRY_COMPARE(cacheBufferSpy.count(),2);
1062 QTRY_COMPARE(layoutSpy.count(),1);
1063 QTRY_COMPARE(flowSpy.count(),2);
1065 gridView->setWrapEnabled(true);
1066 gridView->setCacheBuffer(5);
1067 gridView->setLayoutDirection(Qt::RightToLeft);
1069 QTRY_COMPARE(keyNavigationWrapsSpy.count(),2);
1070 QTRY_COMPARE(cacheBufferSpy.count(),2);
1071 QTRY_COMPARE(layoutSpy.count(),1);
1072 QTRY_COMPARE(flowSpy.count(),2);
1074 gridView->setFlow(QSGGridView::TopToBottom);
1075 QTRY_COMPARE(gridView->flow(), QSGGridView::TopToBottom);
1076 QTRY_COMPARE(flowSpy.count(),3);
1078 gridView->setFlow(QSGGridView::TopToBottom);
1079 QTRY_COMPARE(flowSpy.count(),3);
1084 void tst_QSGGridView::componentChanges()
1086 QSGView *canvas = createView();
1087 QTRY_VERIFY(canvas);
1088 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1090 QSGGridView *gridView = canvas->rootObject()->findChild<QSGGridView*>("gridView");
1091 QTRY_VERIFY(gridView);
1093 QDeclarativeComponent component(canvas->engine());
1094 component.setData("import QtQuick 1.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
1096 QDeclarativeComponent delegateComponent(canvas->engine());
1097 delegateComponent.setData("import QtQuick 1.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
1099 QSignalSpy highlightSpy(gridView, SIGNAL(highlightChanged()));
1100 QSignalSpy delegateSpy(gridView, SIGNAL(delegateChanged()));
1101 QSignalSpy headerSpy(gridView, SIGNAL(headerChanged()));
1102 QSignalSpy footerSpy(gridView, SIGNAL(footerChanged()));
1104 gridView->setHighlight(&component);
1105 gridView->setDelegate(&delegateComponent);
1106 gridView->setHeader(&component);
1107 gridView->setFooter(&component);
1109 QTRY_COMPARE(gridView->highlight(), &component);
1110 QTRY_COMPARE(gridView->delegate(), &delegateComponent);
1111 QTRY_COMPARE(gridView->header(), &component);
1112 QTRY_COMPARE(gridView->footer(), &component);
1114 QTRY_COMPARE(highlightSpy.count(),1);
1115 QTRY_COMPARE(delegateSpy.count(),1);
1116 QTRY_COMPARE(headerSpy.count(),1);
1117 QTRY_COMPARE(footerSpy.count(),1);
1119 gridView->setHighlight(&component);
1120 gridView->setDelegate(&delegateComponent);
1121 gridView->setHeader(&component);
1122 gridView->setFooter(&component);
1124 QTRY_COMPARE(highlightSpy.count(),1);
1125 QTRY_COMPARE(delegateSpy.count(),1);
1126 QTRY_COMPARE(headerSpy.count(),1);
1127 QTRY_COMPARE(footerSpy.count(),1);
1132 void tst_QSGGridView::modelChanges()
1134 QSGView *canvas = createView();
1135 QTRY_VERIFY(canvas);
1136 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1138 QSGGridView *gridView = canvas->rootObject()->findChild<QSGGridView*>("gridView");
1139 QTRY_VERIFY(gridView);
1141 QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
1142 QTRY_VERIFY(alternateModel);
1143 QVariant modelVariant = QVariant::fromValue(alternateModel);
1144 QSignalSpy modelSpy(gridView, SIGNAL(modelChanged()));
1146 gridView->setModel(modelVariant);
1147 QTRY_COMPARE(gridView->model(), modelVariant);
1148 QTRY_COMPARE(modelSpy.count(),1);
1150 gridView->setModel(modelVariant);
1151 QTRY_COMPARE(modelSpy.count(),1);
1153 gridView->setModel(QVariant());
1154 QTRY_COMPARE(modelSpy.count(),2);
1158 void tst_QSGGridView::positionViewAtIndex()
1160 QSGView *canvas = createView();
1163 for (int i = 0; i < 40; i++)
1164 model.addItem("Item" + QString::number(i), "");
1166 QDeclarativeContext *ctxt = canvas->rootContext();
1167 ctxt->setContextProperty("testModel", &model);
1168 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1169 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1171 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
1172 qApp->processEvents();
1174 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1175 QTRY_VERIFY(gridview != 0);
1177 QSGItem *contentItem = gridview->contentItem();
1178 QTRY_VERIFY(contentItem != 0);
1180 // Confirm items positioned correctly
1181 int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1182 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1183 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1184 if (!item) qWarning() << "Item" << i << "not found";
1186 QTRY_COMPARE(item->x(), (i%3)*80.);
1187 QTRY_COMPARE(item->y(), (i/3)*60.);
1190 // Position on a currently visible item
1191 gridview->positionViewAtIndex(4, QSGGridView::Beginning);
1192 QTRY_COMPARE(gridview->indexAt(120, 90), 4);
1193 QTRY_COMPARE(gridview->contentY(), 60.);
1195 // Confirm items positioned correctly
1196 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1197 for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
1198 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1199 if (!item) qWarning() << "Item" << i << "not found";
1201 QTRY_COMPARE(item->x(), (i%3)*80.);
1202 QTRY_COMPARE(item->y(), (i/3)*60.);
1205 // Position on an item beyond the visible items
1206 gridview->positionViewAtIndex(21, QSGGridView::Beginning);
1207 QTRY_COMPARE(gridview->indexAt(40, 450), 21);
1208 QTRY_COMPARE(gridview->contentY(), 420.);
1210 // Confirm items positioned correctly
1211 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1212 for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
1213 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1214 if (!item) qWarning() << "Item" << i << "not found";
1216 QTRY_COMPARE(item->x(), (i%3)*80.);
1217 QTRY_COMPARE(item->y(), (i/3)*60.);
1220 // Position on an item that would leave empty space if positioned at the top
1221 gridview->positionViewAtIndex(31, QSGGridView::Beginning);
1222 QTRY_COMPARE(gridview->indexAt(120, 630), 31);
1223 QTRY_COMPARE(gridview->contentY(), 520.);
1225 // Confirm items positioned correctly
1226 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1227 for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
1228 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1229 if (!item) qWarning() << "Item" << i << "not found";
1231 QTRY_COMPARE(item->x(), (i%3)*80.);
1232 QTRY_COMPARE(item->y(), (i/3)*60.);
1235 // Position at the beginning again
1236 gridview->positionViewAtIndex(0, QSGGridView::Beginning);
1237 QTRY_COMPARE(gridview->indexAt(0, 0), 0);
1238 QTRY_COMPARE(gridview->indexAt(40, 30), 0);
1239 QTRY_COMPARE(gridview->indexAt(80, 60), 4);
1240 QTRY_COMPARE(gridview->contentY(), 0.);
1242 // Confirm items positioned correctly
1243 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1244 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1245 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1246 if (!item) qWarning() << "Item" << i << "not found";
1248 QTRY_COMPARE(item->x(), (i%3)*80.);
1249 QTRY_COMPARE(item->y(), (i/3)*60.);
1253 gridview->positionViewAtIndex(30, QSGGridView::End);
1254 QTRY_COMPARE(gridview->contentY(), 340.);
1256 // Position in Center
1257 gridview->positionViewAtIndex(15, QSGGridView::Center);
1258 QTRY_COMPARE(gridview->contentY(), 170.);
1260 // Ensure at least partially visible
1261 gridview->positionViewAtIndex(15, QSGGridView::Visible);
1262 QTRY_COMPARE(gridview->contentY(), 170.);
1264 gridview->setContentY(302);
1265 gridview->positionViewAtIndex(15, QSGGridView::Visible);
1266 QTRY_COMPARE(gridview->contentY(), 302.);
1268 gridview->setContentY(360);
1269 gridview->positionViewAtIndex(15, QSGGridView::Visible);
1270 QTRY_COMPARE(gridview->contentY(), 300.);
1272 gridview->setContentY(60);
1273 gridview->positionViewAtIndex(20, QSGGridView::Visible);
1274 QTRY_COMPARE(gridview->contentY(), 60.);
1276 gridview->setContentY(20);
1277 gridview->positionViewAtIndex(20, QSGGridView::Visible);
1278 QTRY_COMPARE(gridview->contentY(), 100.);
1280 // Ensure completely visible
1281 gridview->setContentY(120);
1282 gridview->positionViewAtIndex(20, QSGGridView::Contain);
1283 QTRY_COMPARE(gridview->contentY(), 120.);
1285 gridview->setContentY(302);
1286 gridview->positionViewAtIndex(15, QSGGridView::Contain);
1287 QTRY_COMPARE(gridview->contentY(), 300.);
1289 gridview->setContentY(60);
1290 gridview->positionViewAtIndex(20, QSGGridView::Contain);
1291 QTRY_COMPARE(gridview->contentY(), 100.);
1293 // Test for Top To Bottom layout
1294 ctxt->setContextProperty("testTopToBottom", QVariant(true));
1296 // Confirm items positioned correctly
1297 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1298 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1299 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1300 if (!item) qWarning() << "Item" << i << "not found";
1302 QTRY_COMPARE(item->x(), (i/5)*80.);
1303 QTRY_COMPARE(item->y(), (i%5)*60.);
1307 gridview->positionViewAtIndex(30, QSGGridView::End);
1308 QTRY_COMPARE(gridview->contentX(), 320.);
1309 QTRY_COMPARE(gridview->contentY(), 0.);
1311 // Position in Center
1312 gridview->positionViewAtIndex(15, QSGGridView::Center);
1313 QTRY_COMPARE(gridview->contentX(), 160.);
1315 // Ensure at least partially visible
1316 gridview->positionViewAtIndex(15, QSGGridView::Visible);
1317 QTRY_COMPARE(gridview->contentX(), 160.);
1319 gridview->setContentX(170);
1320 gridview->positionViewAtIndex(25, QSGGridView::Visible);
1321 QTRY_COMPARE(gridview->contentX(), 170.);
1323 gridview->positionViewAtIndex(30, QSGGridView::Visible);
1324 QTRY_COMPARE(gridview->contentX(), 320.);
1326 gridview->setContentX(170);
1327 gridview->positionViewAtIndex(25, QSGGridView::Contain);
1328 QTRY_COMPARE(gridview->contentX(), 240.);
1330 // positionViewAtBeginning
1331 gridview->positionViewAtBeginning();
1332 QTRY_COMPARE(gridview->contentX(), 0.);
1334 gridview->setContentX(80);
1335 canvas->rootObject()->setProperty("showHeader", true);
1336 gridview->positionViewAtBeginning();
1337 QTRY_COMPARE(gridview->contentX(), -30.);
1339 // positionViewAtEnd
1340 gridview->positionViewAtEnd();
1341 QTRY_COMPARE(gridview->contentX(), 430.);
1343 gridview->setContentX(80);
1344 canvas->rootObject()->setProperty("showFooter", true);
1345 gridview->positionViewAtEnd();
1346 QTRY_COMPARE(gridview->contentX(), 460.);
1351 void tst_QSGGridView::snapping()
1353 QSGView *canvas = createView();
1356 for (int i = 0; i < 40; i++)
1357 model.addItem("Item" + QString::number(i), "");
1359 QDeclarativeContext *ctxt = canvas->rootContext();
1360 ctxt->setContextProperty("testModel", &model);
1361 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1362 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1364 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
1365 qApp->processEvents();
1367 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1368 QTRY_VERIFY(gridview != 0);
1370 gridview->setHeight(220);
1371 QCOMPARE(gridview->height(), 220.);
1373 gridview->positionViewAtIndex(12, QSGGridView::Visible);
1374 QCOMPARE(gridview->contentY(), 80.);
1376 gridview->setContentY(0);
1377 QCOMPARE(gridview->contentY(), 0.);
1379 gridview->setSnapMode(QSGGridView::SnapToRow);
1380 QCOMPARE(gridview->snapMode(), QSGGridView::SnapToRow);
1382 gridview->positionViewAtIndex(12, QSGGridView::Visible);
1383 QCOMPARE(gridview->contentY(), 60.);
1385 gridview->positionViewAtIndex(15, QSGGridView::End);
1386 QCOMPARE(gridview->contentY(), 120.);
1392 void tst_QSGGridView::mirroring()
1394 QSGView *canvasA = createView();
1395 canvasA->setSource(QUrl::fromLocalFile(SRCDIR "/data/mirroring.qml"));
1396 QSGGridView *gridviewA = findItem<QSGGridView>(canvasA->rootObject(), "view");
1397 QTRY_VERIFY(gridviewA != 0);
1399 QSGView *canvasB = createView();
1400 canvasB->setSource(QUrl::fromLocalFile(SRCDIR "/data/mirroring.qml"));
1401 QSGGridView *gridviewB = findItem<QSGGridView>(canvasB->rootObject(), "view");
1402 QTRY_VERIFY(gridviewA != 0);
1403 qApp->processEvents();
1405 QList<QString> objectNames;
1406 objectNames << "item1" << "item2"; // << "item3"
1408 gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
1409 gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
1410 QCOMPARE(gridviewA->layoutDirection(), gridviewA->effectiveLayoutDirection());
1413 foreach(const QString objectName, objectNames)
1414 QVERIFY(findItem<QSGItem>(gridviewA, objectName)->x() != findItem<QSGItem>(gridviewB, objectName)->x());
1416 gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
1417 gridviewB->setProperty("layoutDirection", Qt::LeftToRight);
1420 foreach(const QString objectName, objectNames)
1421 QCOMPARE(findItem<QSGItem>(gridviewA, objectName)->x(), findItem<QSGItem>(gridviewB, objectName)->x());
1423 QVERIFY(gridviewB->layoutDirection() == gridviewB->effectiveLayoutDirection());
1424 QSGItemPrivate::get(gridviewB)->setLayoutMirror(true);
1425 QVERIFY(gridviewB->layoutDirection() != gridviewB->effectiveLayoutDirection());
1427 // LTR != LTR+mirror
1428 foreach(const QString objectName, objectNames)
1429 QVERIFY(findItem<QSGItem>(gridviewA, objectName)->x() != findItem<QSGItem>(gridviewB, objectName)->x());
1431 gridviewA->setProperty("layoutDirection", Qt::RightToLeft);
1433 // RTL == LTR+mirror
1434 foreach(const QString objectName, objectNames)
1435 QCOMPARE(findItem<QSGItem>(gridviewA, objectName)->x(), findItem<QSGItem>(gridviewB, objectName)->x());
1437 gridviewB->setProperty("layoutDirection", Qt::RightToLeft);
1439 // RTL != RTL+mirror
1440 foreach(const QString objectName, objectNames)
1441 QVERIFY(findItem<QSGItem>(gridviewA, objectName)->x() != findItem<QSGItem>(gridviewB, objectName)->x());
1443 gridviewA->setProperty("layoutDirection", Qt::LeftToRight);
1445 // LTR == RTL+mirror
1446 foreach(const QString objectName, objectNames)
1447 QCOMPARE(findItem<QSGItem>(gridviewA, objectName)->x(), findItem<QSGItem>(gridviewB, objectName)->x());
1453 void tst_QSGGridView::positionViewAtIndex_rightToLeft()
1455 QSGView *canvas = createView();
1458 for (int i = 0; i < 40; i++)
1459 model.addItem("Item" + QString::number(i), "");
1461 QDeclarativeContext *ctxt = canvas->rootContext();
1462 ctxt->setContextProperty("testModel", &model);
1463 ctxt->setContextProperty("testTopToBottom", QVariant(true));
1464 ctxt->setContextProperty("testRightToLeft", QVariant(true));
1466 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
1467 qApp->processEvents();
1469 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1470 QTRY_VERIFY(gridview != 0);
1472 QSGItem *contentItem = gridview->contentItem();
1473 QTRY_VERIFY(contentItem != 0);
1475 // Confirm items positioned correctly
1476 int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1477 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1478 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1479 if (!item) qWarning() << "Item" << i << "not found";
1481 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1482 QTRY_COMPARE(item->y(), qreal((i%5)*60));
1485 // Position on a currently visible item
1486 gridview->positionViewAtIndex(6, QSGGridView::Beginning);
1487 QTRY_COMPARE(gridview->contentX(), -320.);
1489 // Confirm items positioned correctly
1490 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1491 for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
1492 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1493 if (!item) qWarning() << "Item" << i << "not found";
1495 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1496 QTRY_COMPARE(item->y(), qreal((i%5)*60));
1499 // Position on an item beyond the visible items
1500 gridview->positionViewAtIndex(21, QSGGridView::Beginning);
1501 QTRY_COMPARE(gridview->contentX(), -560.);
1503 // Confirm items positioned correctly
1504 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1505 for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
1506 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1507 if (!item) qWarning() << "Item" << i << "not found";
1509 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1510 QTRY_COMPARE(item->y(), qreal((i%5)*60));
1513 // Position on an item that would leave empty space if positioned at the top
1514 gridview->positionViewAtIndex(31, QSGGridView::Beginning);
1515 QTRY_COMPARE(gridview->contentX(), -639.);
1517 // Confirm items positioned correctly
1518 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1519 for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
1520 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1521 if (!item) qWarning() << "Item" << i << "not found";
1523 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1524 QTRY_COMPARE(item->y(), qreal((i%5)*60));
1527 // Position at the beginning again
1528 gridview->positionViewAtIndex(0, QSGGridView::Beginning);
1529 QTRY_COMPARE(gridview->contentX(), -240.);
1531 // Confirm items positioned correctly
1532 itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
1533 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1534 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
1535 if (!item) qWarning() << "Item" << i << "not found";
1537 QTRY_COMPARE(item->x(), qreal(-(i/5)*80-item->width()));
1538 QTRY_COMPARE(item->y(), qreal((i%5)*60));
1542 gridview->positionViewAtIndex(30, QSGGridView::End);
1543 QTRY_COMPARE(gridview->contentX(), -560.);
1545 // Position in Center
1546 gridview->positionViewAtIndex(15, QSGGridView::Center);
1547 QTRY_COMPARE(gridview->contentX(), -400.);
1549 // Ensure at least partially visible
1550 gridview->positionViewAtIndex(15, QSGGridView::Visible);
1551 QTRY_COMPARE(gridview->contentX(), -400.);
1553 gridview->setContentX(-555.);
1554 gridview->positionViewAtIndex(15, QSGGridView::Visible);
1555 QTRY_COMPARE(gridview->contentX(), -555.);
1557 gridview->setContentX(-239);
1558 gridview->positionViewAtIndex(15, QSGGridView::Visible);
1559 QTRY_COMPARE(gridview->contentX(), -320.);
1561 gridview->setContentX(-239);
1562 gridview->positionViewAtIndex(20, QSGGridView::Visible);
1563 QTRY_COMPARE(gridview->contentX(), -400.);
1565 gridview->setContentX(-640);
1566 gridview->positionViewAtIndex(20, QSGGridView::Visible);
1567 QTRY_COMPARE(gridview->contentX(), -560.);
1569 // Ensure completely visible
1570 gridview->setContentX(-400);
1571 gridview->positionViewAtIndex(20, QSGGridView::Contain);
1572 QTRY_COMPARE(gridview->contentX(), -400.);
1574 gridview->setContentX(-315);
1575 gridview->positionViewAtIndex(15, QSGGridView::Contain);
1576 QTRY_COMPARE(gridview->contentX(), -320.);
1578 gridview->setContentX(-640);
1579 gridview->positionViewAtIndex(20, QSGGridView::Contain);
1580 QTRY_COMPARE(gridview->contentX(), -560.);
1585 void tst_QSGGridView::resetModel()
1587 QSGView *canvas = createView();
1589 QStringList strings;
1590 strings << "one" << "two" << "three";
1591 QStringListModel model(strings);
1593 QDeclarativeContext *ctxt = canvas->rootContext();
1594 ctxt->setContextProperty("testModel", &model);
1596 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaygrid.qml"));
1597 qApp->processEvents();
1599 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1600 QTRY_VERIFY(gridview != 0);
1602 QSGItem *contentItem = gridview->contentItem();
1603 QTRY_VERIFY(contentItem != 0);
1605 QTRY_COMPARE(gridview->count(), model.rowCount());
1607 for (int i = 0; i < model.rowCount(); ++i) {
1608 QSGText *display = findItem<QSGText>(contentItem, "displayText", i);
1609 QTRY_VERIFY(display != 0);
1610 QTRY_COMPARE(display->text(), strings.at(i));
1614 strings << "four" << "five" << "six" << "seven";
1615 model.setStringList(strings);
1617 QTRY_COMPARE(gridview->count(), model.rowCount());
1619 for (int i = 0; i < model.rowCount(); ++i) {
1620 QSGText *display = findItem<QSGText>(contentItem, "displayText", i);
1621 QTRY_VERIFY(display != 0);
1622 QTRY_COMPARE(display->text(), strings.at(i));
1628 void tst_QSGGridView::enforceRange()
1630 QSGView *canvas = createView();
1633 for (int i = 0; i < 30; i++)
1634 model.addItem("Item" + QString::number(i), "");
1636 QDeclarativeContext *ctxt = canvas->rootContext();
1637 ctxt->setContextProperty("testModel", &model);
1638 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1639 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1641 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview-enforcerange.qml"));
1642 qApp->processEvents();
1643 QVERIFY(canvas->rootObject() != 0);
1645 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1646 QTRY_VERIFY(gridview != 0);
1648 QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
1649 QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
1650 QTRY_COMPARE(gridview->highlightRangeMode(), QSGGridView::StrictlyEnforceRange);
1652 QSGItem *contentItem = gridview->contentItem();
1653 QTRY_VERIFY(contentItem != 0);
1655 // view should be positioned at the top of the range.
1656 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", 0);
1658 QTRY_COMPARE(gridview->contentY(), -100.0);
1660 QSGText *name = findItem<QSGText>(contentItem, "textName", 0);
1661 QTRY_VERIFY(name != 0);
1662 QTRY_COMPARE(name->text(), model.name(0));
1663 QSGText *number = findItem<QSGText>(contentItem, "textNumber", 0);
1664 QTRY_VERIFY(number != 0);
1665 QTRY_COMPARE(number->text(), model.number(0));
1667 // Check currentIndex is updated when contentItem moves
1668 gridview->setContentY(0);
1669 QTRY_COMPARE(gridview->currentIndex(), 2);
1671 gridview->setCurrentIndex(5);
1672 QTRY_COMPARE(gridview->contentY(), 100.);
1675 for (int i = 0; i < 5; i++)
1676 model2.addItem("Item" + QString::number(i), "");
1678 ctxt->setContextProperty("testModel", &model2);
1679 QCOMPARE(gridview->count(), 5);
1684 void tst_QSGGridView::enforceRange_rightToLeft()
1686 QSGView *canvas = createView();
1689 for (int i = 0; i < 30; i++)
1690 model.addItem("Item" + QString::number(i), "");
1692 QDeclarativeContext *ctxt = canvas->rootContext();
1693 ctxt->setContextProperty("testModel", &model);
1694 ctxt->setContextProperty("testRightToLeft", QVariant(true));
1695 ctxt->setContextProperty("testTopToBottom", QVariant(true));
1697 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview-enforcerange.qml"));
1698 qApp->processEvents();
1699 QVERIFY(canvas->rootObject() != 0);
1701 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1702 QTRY_VERIFY(gridview != 0);
1704 QTRY_COMPARE(gridview->preferredHighlightBegin(), 100.0);
1705 QTRY_COMPARE(gridview->preferredHighlightEnd(), 100.0);
1706 QTRY_COMPARE(gridview->highlightRangeMode(), QSGGridView::StrictlyEnforceRange);
1708 QSGItem *contentItem = gridview->contentItem();
1709 QTRY_VERIFY(contentItem != 0);
1711 // view should be positioned at the top of the range.
1712 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", 0);
1714 QTRY_COMPARE(gridview->contentX(), -100.);
1715 QTRY_COMPARE(gridview->contentY(), 0.0);
1717 QSGText *name = findItem<QSGText>(contentItem, "textName", 0);
1718 QTRY_VERIFY(name != 0);
1719 QTRY_COMPARE(name->text(), model.name(0));
1720 QSGText *number = findItem<QSGText>(contentItem, "textNumber", 0);
1721 QTRY_VERIFY(number != 0);
1722 QTRY_COMPARE(number->text(), model.number(0));
1724 // Check currentIndex is updated when contentItem moves
1725 gridview->setContentX(-200);
1726 QTRY_COMPARE(gridview->currentIndex(), 3);
1728 gridview->setCurrentIndex(7);
1729 QTRY_COMPARE(gridview->contentX(), -300.);
1730 QTRY_COMPARE(gridview->contentY(), 0.0);
1733 for (int i = 0; i < 5; i++)
1734 model2.addItem("Item" + QString::number(i), "");
1736 ctxt->setContextProperty("testModel", &model2);
1737 QCOMPARE(gridview->count(), 5);
1742 void tst_QSGGridView::QTBUG_8456()
1744 QSGView *canvas = createView();
1746 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/setindex.qml"));
1747 qApp->processEvents();
1749 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1750 QTRY_VERIFY(gridview != 0);
1752 QTRY_COMPARE(gridview->currentIndex(), 0);
1757 void tst_QSGGridView::manualHighlight()
1759 QSGView *canvas = createView();
1761 QString filename(SRCDIR "/data/manual-highlight.qml");
1762 canvas->setSource(QUrl::fromLocalFile(filename));
1764 qApp->processEvents();
1766 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1767 QTRY_VERIFY(gridview != 0);
1769 QSGItem *contentItem = gridview->contentItem();
1770 QTRY_VERIFY(contentItem != 0);
1772 QTRY_COMPARE(gridview->currentIndex(), 0);
1773 QTRY_COMPARE(gridview->currentItem(), findItem<QSGItem>(contentItem, "wrapper", 0));
1774 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
1775 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
1777 gridview->setCurrentIndex(2);
1779 QTRY_COMPARE(gridview->currentIndex(), 2);
1780 QTRY_COMPARE(gridview->currentItem(), findItem<QSGItem>(contentItem, "wrapper", 2));
1781 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
1782 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
1784 gridview->positionViewAtIndex(8, QSGGridView::Contain);
1786 QTRY_COMPARE(gridview->currentIndex(), 2);
1787 QTRY_COMPARE(gridview->currentItem(), findItem<QSGItem>(contentItem, "wrapper", 2));
1788 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
1789 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
1791 gridview->setFlow(QSGGridView::TopToBottom);
1792 QTRY_COMPARE(gridview->flow(), QSGGridView::TopToBottom);
1794 gridview->setCurrentIndex(0);
1795 QTRY_COMPARE(gridview->currentIndex(), 0);
1796 QTRY_COMPARE(gridview->currentItem(), findItem<QSGItem>(contentItem, "wrapper", 0));
1797 QTRY_COMPARE(gridview->highlightItem()->y() - 5, gridview->currentItem()->y());
1798 QTRY_COMPARE(gridview->highlightItem()->x() - 5, gridview->currentItem()->x());
1803 void tst_QSGGridView::footer()
1805 QSGView *canvas = createView();
1809 for (int i = 0; i < 7; i++)
1810 model.addItem("Item" + QString::number(i), "");
1812 QDeclarativeContext *ctxt = canvas->rootContext();
1813 ctxt->setContextProperty("testModel", &model);
1815 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/footer.qml"));
1816 qApp->processEvents();
1818 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1819 QTRY_VERIFY(gridview != 0);
1821 QSGItem *contentItem = gridview->contentItem();
1822 QTRY_VERIFY(contentItem != 0);
1824 QSGText *footer = findItem<QSGText>(contentItem, "footer");
1827 QCOMPARE(footer->y(), 180.0);
1828 QCOMPARE(footer->height(), 30.0);
1830 model.removeItem(2);
1831 QTRY_COMPARE(footer->y(), 120.0);
1834 QTRY_COMPARE(footer->y(), 0.0);
1836 for (int i = 0; i < 30; i++)
1837 model.addItem("Item" + QString::number(i), "");
1839 QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
1841 footer = findItem<QSGText>(contentItem, "footer");
1843 footer = findItem<QSGText>(contentItem, "footer2");
1846 QCOMPARE(footer->y(), 600.0);
1847 QCOMPARE(footer->height(), 20.0);
1848 QCOMPARE(gridview->contentY(), 0.0);
1853 void tst_QSGGridView::header()
1855 QSGView *canvas = createView();
1858 for (int i = 0; i < 30; i++)
1859 model.addItem("Item" + QString::number(i), "");
1861 QDeclarativeContext *ctxt = canvas->rootContext();
1862 ctxt->setContextProperty("testModel", &model);
1864 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header.qml"));
1865 qApp->processEvents();
1867 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1868 QTRY_VERIFY(gridview != 0);
1870 QSGItem *contentItem = gridview->contentItem();
1871 QTRY_VERIFY(contentItem != 0);
1873 QSGText *header = findItem<QSGText>(contentItem, "header");
1876 QCOMPARE(header->y(), 0.0);
1877 QCOMPARE(header->height(), 30.0);
1878 QCOMPARE(gridview->contentY(), 0.0);
1880 QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", 0);
1882 QCOMPARE(item->y(), 30.0);
1885 QTRY_COMPARE(header->y(), 0.0);
1887 for (int i = 0; i < 30; i++)
1888 model.addItem("Item" + QString::number(i), "");
1890 QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
1892 header = findItem<QSGText>(contentItem, "header");
1894 header = findItem<QSGText>(contentItem, "header2");
1897 QCOMPARE(header->y(), 10.0);
1898 QCOMPARE(header->height(), 20.0);
1899 QCOMPARE(gridview->contentY(), 10.0);
1904 void tst_QSGGridView::indexAt()
1906 QSGView *canvas = createView();
1909 model.addItem("Fred", "12345");
1910 model.addItem("John", "2345");
1911 model.addItem("Bob", "54321");
1912 model.addItem("Billy", "22345");
1913 model.addItem("Sam", "2945");
1914 model.addItem("Ben", "04321");
1915 model.addItem("Jim", "0780");
1917 QDeclarativeContext *ctxt = canvas->rootContext();
1918 ctxt->setContextProperty("testModel", &model);
1919 ctxt->setContextProperty("testRightToLeft", QVariant(false));
1920 ctxt->setContextProperty("testTopToBottom", QVariant(false));
1922 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
1923 qApp->processEvents();
1925 QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
1926 QTRY_VERIFY(gridview != 0);
1928 QSGItem *contentItem = gridview->contentItem();
1929 QTRY_VERIFY(contentItem != 0);
1931 QTRY_COMPARE(gridview->count(), model.count());
1933 QCOMPARE(gridview->indexAt(0, 0), 0);
1934 QCOMPARE(gridview->indexAt(79, 59), 0);
1935 QCOMPARE(gridview->indexAt(80, 0), 1);
1936 QCOMPARE(gridview->indexAt(0, 60), 3);
1937 QCOMPARE(gridview->indexAt(240, 0), -1);
1942 void tst_QSGGridView::onAdd()
1944 QFETCH(int, initialItemCount);
1945 QFETCH(int, itemsToAdd);
1947 const int delegateWidth = 50;
1948 const int delegateHeight = 100;
1950 QSGView *canvas = createView();
1951 canvas->setFixedSize(5 * delegateWidth, 5 * delegateHeight); // just ensure all items fit
1953 // these initial items should not trigger GridView.onAdd
1954 for (int i=0; i<initialItemCount; i++)
1955 model.addItem("dummy value", "dummy value");
1957 QDeclarativeContext *ctxt = canvas->rootContext();
1958 ctxt->setContextProperty("testModel", &model);
1959 ctxt->setContextProperty("delegateWidth", delegateWidth);
1960 ctxt->setContextProperty("delegateHeight", delegateHeight);
1961 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
1963 QObject *object = canvas->rootObject();
1964 object->setProperty("width", canvas->width());
1965 object->setProperty("height", canvas->height());
1966 qApp->processEvents();
1968 QList<QPair<QString, QString> > items;
1969 for (int i=0; i<itemsToAdd; i++)
1970 items << qMakePair(QString("value %1").arg(i), QString::number(i));
1971 model.addItems(items);
1973 qApp->processEvents();
1975 QVariantList result = object->property("addedDelegates").toList();
1976 QCOMPARE(result.count(), items.count());
1977 for (int i=0; i<items.count(); i++)
1978 QCOMPARE(result[i].toString(), items[i].first);
1983 void tst_QSGGridView::onAdd_data()
1985 QTest::addColumn<int>("initialItemCount");
1986 QTest::addColumn<int>("itemsToAdd");
1988 QTest::newRow("0, add 1") << 0 << 1;
1989 QTest::newRow("0, add 2") << 0 << 2;
1990 QTest::newRow("0, add 10") << 0 << 10;
1992 QTest::newRow("1, add 1") << 1 << 1;
1993 QTest::newRow("1, add 2") << 1 << 2;
1994 QTest::newRow("1, add 10") << 1 << 10;
1996 QTest::newRow("5, add 1") << 5 << 1;
1997 QTest::newRow("5, add 2") << 5 << 2;
1998 QTest::newRow("5, add 10") << 5 << 10;
2001 void tst_QSGGridView::onRemove()
2003 QFETCH(int, initialItemCount);
2004 QFETCH(int, indexToRemove);
2005 QFETCH(int, removeCount);
2007 const int delegateWidth = 50;
2008 const int delegateHeight = 100;
2010 for (int i=0; i<initialItemCount; i++)
2011 model.addItem(QString("value %1").arg(i), "dummy value");
2013 QSGView *canvas = createView();
2014 QDeclarativeContext *ctxt = canvas->rootContext();
2015 ctxt->setContextProperty("testModel", &model);
2016 ctxt->setContextProperty("delegateWidth", delegateWidth);
2017 ctxt->setContextProperty("delegateHeight", delegateHeight);
2018 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
2019 QObject *object = canvas->rootObject();
2021 qApp->processEvents();
2023 model.removeItems(indexToRemove, removeCount);
2024 qApp->processEvents();
2025 QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
2030 void tst_QSGGridView::onRemove_data()
2032 QTest::addColumn<int>("initialItemCount");
2033 QTest::addColumn<int>("indexToRemove");
2034 QTest::addColumn<int>("removeCount");
2036 QTest::newRow("remove first") << 1 << 0 << 1;
2037 QTest::newRow("two items, remove first") << 2 << 0 << 1;
2038 QTest::newRow("two items, remove last") << 2 << 1 << 1;
2039 QTest::newRow("two items, remove all") << 2 << 0 << 2;
2041 QTest::newRow("four items, remove first") << 4 << 0 << 1;
2042 QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
2043 QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
2044 QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
2045 QTest::newRow("four items, remove last") << 4 << 3 << 1;
2046 QTest::newRow("four items, remove all") << 4 << 0 << 4;
2048 QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
2049 QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
2050 QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
2053 void tst_QSGGridView::testQtQuick11Attributes()
2055 QFETCH(QString, code);
2056 QFETCH(QString, warning);
2057 QFETCH(QString, error);
2059 QDeclarativeEngine engine;
2062 QDeclarativeComponent valid(&engine);
2063 valid.setData("import QtQuick 1.1; GridView { " + code.toUtf8() + " }", QUrl(""));
2064 obj = valid.create();
2066 QVERIFY(valid.errorString().isEmpty());
2069 QDeclarativeComponent invalid(&engine);
2070 invalid.setData("import QtQuick 1.0; GridView { " + code.toUtf8() + " }", QUrl(""));
2071 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2072 obj = invalid.create();
2073 QCOMPARE(invalid.errorString(), error);
2077 void tst_QSGGridView::testQtQuick11Attributes_data()
2079 QTest::addColumn<QString>("code");
2080 QTest::addColumn<QString>("warning");
2081 QTest::addColumn<QString>("error");
2083 QTest::newRow("positionViewAtBeginning") << "Component.onCompleted: positionViewAtBeginning()"
2084 << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtBeginning"
2087 QTest::newRow("positionViewAtEnd") << "Component.onCompleted: positionViewAtEnd()"
2088 << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtEnd"
2092 QSGView *tst_QSGGridView::createView()
2094 QSGView *canvas = new QSGView(0);
2095 canvas->setFixedSize(240,320);
2101 Find an item with the specified objectName. If index is supplied then the
2102 item must also evaluate the {index} expression equal to index
2104 template<typename T>
2105 T *tst_QSGGridView::findItem(QSGItem *parent, const QString &objectName, int index)
2107 const QMetaObject &mo = T::staticMetaObject;
2108 //qDebug() << parent->childItems().count() << "children";
2109 for (int i = 0; i < parent->childItems().count(); ++i) {
2110 QSGItem *item = qobject_cast<QSGItem*>(parent->childItems().at(i));
2113 //qDebug() << "try" << item;
2114 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
2116 QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
2118 if (context->contextProperty("index").toInt() == index) {
2119 return static_cast<T*>(item);
2123 return static_cast<T*>(item);
2126 item = findItem<T>(item, objectName, index);
2128 return static_cast<T*>(item);
2134 template<typename T>
2135 QList<T*> tst_QSGGridView::findItems(QSGItem *parent, const QString &objectName)
2138 const QMetaObject &mo = T::staticMetaObject;
2139 //qDebug() << parent->childItems().count() << "children";
2140 for (int i = 0; i < parent->childItems().count(); ++i) {
2141 QSGItem *item = qobject_cast<QSGItem*>(parent->childItems().at(i));
2144 //qDebug() << "try" << item;
2145 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
2146 items.append(static_cast<T*>(item));
2147 //qDebug() << " found:" << item;
2149 items += findItems<T>(item, objectName);
2155 void tst_QSGGridView::dumpTree(QSGItem *parent, int depth)
2157 static QString padding(" ");
2158 for (int i = 0; i < parent->childItems().count(); ++i) {
2159 QSGItem *item = qobject_cast<QSGItem*>(parent->childItems().at(i));
2162 QDeclarativeContext *context = QDeclarativeEngine::contextForObject(item);
2163 qDebug() << padding.left(depth*2) << item << (context ? context->contextProperty("index").toInt() : -1);
2164 dumpTree(item, depth+1);
2169 QTEST_MAIN(tst_QSGGridView)
2171 #include "tst_qsggridview.moc"