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>
44 #include <QtDeclarative/qdeclarativeview.h>
45 #include <QtDeclarative/qdeclarativeengine.h>
46 #include <QtDeclarative/qdeclarativecontext.h>
47 #include <QtDeclarative/qdeclarativeexpression.h>
48 #include <QtDeclarative/private/qdeclarativeitem_p.h>
49 #include <QtDeclarative/private/qdeclarativelistview_p.h>
50 #include <QtDeclarative/private/qdeclarativetext_p.h>
51 #include <QtDeclarative/private/qdeclarativevisualitemmodel_p.h>
52 #include <QtDeclarative/private/qdeclarativelistmodel_p.h>
53 #include <QtDeclarative/private/qlistmodelinterface_p.h>
54 #include "../../../shared/util.h"
55 #include "incrementalmodel.h"
58 // In Symbian OS test data is located in applications private dir
62 class tst_QDeclarativeListView : public QObject
66 tst_QDeclarativeListView();
69 // Test both QListModelInterface and QAbstractItemModel model types
70 void qListModelInterface_items();
71 void qAbstractItemModel_items();
73 void qListModelInterface_changed();
74 void qAbstractItemModel_changed();
76 void qListModelInterface_inserted();
77 void qAbstractItemModel_inserted();
79 void qListModelInterface_removed();
80 void qAbstractItemModel_removed();
82 void qListModelInterface_moved();
83 void qAbstractItemModel_moved();
85 void qListModelInterface_clear();
86 void qAbstractItemModel_clear();
90 void noCurrentIndex();
94 void sectionsDelegate();
96 void positionViewAtIndex();
98 void propertyChanges();
99 void componentChanges();
102 void manualHighlight();
108 void sizeLessThan1();
110 void resizeDelegate();
113 void incrementalModel();
117 void onRemove_data();
118 void testQtQuick11Attributes();
119 void testQtQuick11Attributes_data();
121 void test_mirroring();
122 void orientationChange();
123 void contentPosJump();
126 template <class T> void items();
127 template <class T> void changed();
128 template <class T> void inserted();
129 template <class T> void removed(bool animated);
130 template <class T> void moved();
131 template <class T> void clear();
132 QDeclarativeView *createView();
134 T *findItem(QGraphicsObject *parent, const QString &id, int index=-1);
136 QList<T*> findItems(QGraphicsObject *parent, const QString &objectName);
137 void dumpTree(QDeclarativeItem *parent, int depth = 0);
140 class TestObject : public QObject
144 Q_PROPERTY(bool error READ error WRITE setError NOTIFY changedError)
145 Q_PROPERTY(bool animate READ animate NOTIFY changedAnim)
146 Q_PROPERTY(bool invalidHighlight READ invalidHighlight NOTIFY changedHl)
147 Q_PROPERTY(int cacheBuffer READ cacheBuffer NOTIFY changedCacheBuffer)
150 TestObject(QObject *parent = 0)
151 : QObject(parent), mError(true), mAnimate(false), mInvalidHighlight(false)
154 bool error() const { return mError; }
155 void setError(bool err) { mError = err; emit changedError(); }
157 bool animate() const { return mAnimate; }
158 void setAnimate(bool anim) { mAnimate = anim; emit changedAnim(); }
160 bool invalidHighlight() const { return mInvalidHighlight; }
161 void setInvalidHighlight(bool invalid) { mInvalidHighlight = invalid; emit changedHl(); }
163 int cacheBuffer() const { return mCacheBuffer; }
164 void setCacheBuffer(int buffer) { mCacheBuffer = buffer; emit changedCacheBuffer(); }
170 void changedCacheBuffer();
175 bool mInvalidHighlight;
179 class TestModel : public QListModelInterface
183 TestModel(QObject *parent = 0) : QListModelInterface(parent) {}
186 enum Roles { Name, Number };
188 QString name(int index) const { return list.at(index).first; }
189 QString number(int index) const { return list.at(index).second; }
191 int count() const { return list.count(); }
193 QList<int> roles() const { return QList<int>() << Name << Number; }
194 QString toString(int role) const {
205 QVariant data(int index, int role) const
208 return list.at(index).first;
210 return list.at(index).second;
213 QHash<int, QVariant> data(int index, const QList<int> &roles) const {
214 QHash<int,QVariant> returnHash;
216 for (int i = 0; i < roles.size(); ++i) {
217 int role = roles.at(i);
221 info = list.at(index).first;
224 info = list.at(index).second;
229 returnHash.insert(role, info);
234 void addItem(const QString &name, const QString &number) {
235 list.append(QPair<QString,QString>(name, number));
236 emit itemsInserted(list.count()-1, 1);
239 void insertItem(int index, const QString &name, const QString &number) {
240 list.insert(index, QPair<QString,QString>(name, number));
241 emit itemsInserted(index, 1);
244 void removeItem(int index) {
245 list.removeAt(index);
246 emit itemsRemoved(index, 1);
249 void removeItems(int index, int count) {
252 list.removeAt(index);
253 emit itemsRemoved(index, count);
256 void moveItem(int from, int to) {
258 emit itemsMoved(from, to, 1);
261 void modifyItem(int index, const QString &name, const QString &number) {
262 list[index] = QPair<QString,QString>(name, number);
263 emit itemsChanged(index, 1, roles());
267 int count = list.count();
269 emit itemsRemoved(0, count);
273 QList<QPair<QString,QString> > list;
277 class TestModel2 : public QAbstractListModel
280 enum Roles { Name = Qt::UserRole+1, Number = Qt::UserRole+2 };
282 TestModel2(QObject *parent=0) : QAbstractListModel(parent) {
283 QHash<int, QByteArray> roles;
284 roles[Name] = "name";
285 roles[Number] = "number";
289 int rowCount(const QModelIndex &parent=QModelIndex()) const { Q_UNUSED(parent); return list.count(); }
290 QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const {
293 rv = list.at(index.row()).first;
294 else if (role == Number)
295 rv = list.at(index.row()).second;
300 int count() const { return rowCount(); }
301 QString name(int index) const { return list.at(index).first; }
302 QString number(int index) const { return list.at(index).second; }
304 void addItem(const QString &name, const QString &number) {
305 emit beginInsertRows(QModelIndex(), list.count(), list.count());
306 list.append(QPair<QString,QString>(name, number));
307 emit endInsertRows();
310 void addItems(const QList<QPair<QString, QString> > &items) {
311 emit beginInsertRows(QModelIndex(), list.count(), list.count()+items.count()-1);
312 for (int i=0; i<items.count(); i++)
313 list.append(QPair<QString,QString>(items[i].first, items[i].second));
314 emit endInsertRows();
317 void insertItem(int index, const QString &name, const QString &number) {
318 emit beginInsertRows(QModelIndex(), index, index);
319 list.insert(index, QPair<QString,QString>(name, number));
320 emit endInsertRows();
323 void removeItem(int index) {
324 emit beginRemoveRows(QModelIndex(), index, index);
325 list.removeAt(index);
326 emit endRemoveRows();
329 void removeItems(int index, int count) {
330 emit beginRemoveRows(QModelIndex(), index, index+count-1);
332 list.removeAt(index);
333 emit endRemoveRows();
336 void moveItem(int from, int to) {
337 emit beginMoveRows(QModelIndex(), from, from, QModelIndex(), to);
342 void modifyItem(int idx, const QString &name, const QString &number) {
343 list[idx] = QPair<QString,QString>(name, number);
344 emit dataChanged(index(idx,0), index(idx,0));
348 int count = list.count();
349 emit beginRemoveRows(QModelIndex(), 0, count-1);
351 emit endRemoveRows();
355 QList<QPair<QString,QString> > list;
358 tst_QDeclarativeListView::tst_QDeclarativeListView()
363 void tst_QDeclarativeListView::items()
365 QDeclarativeView *canvas = createView();
368 model.addItem("Fred", "12345");
369 model.addItem("John", "2345");
370 model.addItem("Bob", "54321");
372 QDeclarativeContext *ctxt = canvas->rootContext();
373 ctxt->setContextProperty("testModel", &model);
375 TestObject *testObject = new TestObject;
376 ctxt->setContextProperty("testObject", testObject);
378 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
379 qApp->processEvents();
381 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
382 QTRY_VERIFY(listview != 0);
384 QDeclarativeItem *contentItem = listview->contentItem();
385 QTRY_VERIFY(contentItem != 0);
387 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
388 QTRY_VERIFY(testObject->error() == false);
390 QTRY_VERIFY(listview->highlightItem() != 0);
391 QTRY_COMPARE(listview->count(), model.count());
392 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
393 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
395 // current item should be first item
396 QTRY_COMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 0));
398 for (int i = 0; i < model.count(); ++i) {
399 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", i);
400 QTRY_VERIFY(name != 0);
401 QTRY_COMPARE(name->text(), model.name(i));
402 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
403 QTRY_VERIFY(number != 0);
404 QTRY_COMPARE(number->text(), model.number(i));
407 // switch to other delegate
408 testObject->setAnimate(true);
409 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
410 QTRY_VERIFY(testObject->error() == false);
411 QTRY_VERIFY(listview->currentItem());
413 // set invalid highlight
414 testObject->setInvalidHighlight(true);
415 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
416 QTRY_VERIFY(testObject->error() == false);
417 QTRY_VERIFY(listview->currentItem());
418 QTRY_VERIFY(listview->highlightItem() == 0);
420 // back to normal highlight
421 testObject->setInvalidHighlight(false);
422 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
423 QTRY_VERIFY(testObject->error() == false);
424 QTRY_VERIFY(listview->currentItem());
425 QTRY_VERIFY(listview->highlightItem() != 0);
427 // set an empty model and confirm that items are destroyed
429 ctxt->setContextProperty("testModel", &model2);
431 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
432 QTRY_VERIFY(itemCount == 0);
434 QTRY_COMPARE(listview->highlightResizeSpeed(), 1000.0);
435 QTRY_COMPARE(listview->highlightMoveSpeed(), 1000.0);
442 void tst_QDeclarativeListView::changed()
444 QDeclarativeView *canvas = createView();
447 model.addItem("Fred", "12345");
448 model.addItem("John", "2345");
449 model.addItem("Bob", "54321");
451 QDeclarativeContext *ctxt = canvas->rootContext();
452 ctxt->setContextProperty("testModel", &model);
454 TestObject *testObject = new TestObject;
455 ctxt->setContextProperty("testObject", testObject);
457 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
458 qApp->processEvents();
460 QDeclarativeFlickable *listview = findItem<QDeclarativeFlickable>(canvas->rootObject(), "list");
461 QTRY_VERIFY(listview != 0);
463 QDeclarativeItem *contentItem = listview->contentItem();
464 QTRY_VERIFY(contentItem != 0);
466 model.modifyItem(1, "Will", "9876");
467 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
468 QTRY_VERIFY(name != 0);
469 QTRY_COMPARE(name->text(), model.name(1));
470 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
471 QTRY_VERIFY(number != 0);
472 QTRY_COMPARE(number->text(), model.number(1));
478 void tst_QDeclarativeListView::inserted()
480 QDeclarativeView *canvas = createView();
483 model.addItem("Fred", "12345");
484 model.addItem("John", "2345");
485 model.addItem("Bob", "54321");
487 QDeclarativeContext *ctxt = canvas->rootContext();
488 ctxt->setContextProperty("testModel", &model);
490 TestObject *testObject = new TestObject;
491 ctxt->setContextProperty("testObject", testObject);
493 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
494 qApp->processEvents();
496 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
497 QTRY_VERIFY(listview != 0);
499 QDeclarativeItem *contentItem = listview->contentItem();
500 QTRY_VERIFY(contentItem != 0);
502 model.insertItem(1, "Will", "9876");
504 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
506 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
507 QTRY_VERIFY(name != 0);
508 QTRY_COMPARE(name->text(), model.name(1));
509 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
510 QTRY_VERIFY(number != 0);
511 QTRY_COMPARE(number->text(), model.number(1));
513 // Confirm items positioned correctly
514 for (int i = 0; i < model.count(); ++i) {
515 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
516 QTRY_COMPARE(item->y(), i*20.0);
519 model.insertItem(0, "Foo", "1111"); // zero index, and current item
521 QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
522 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
524 name = findItem<QDeclarativeText>(contentItem, "textName", 0);
525 QTRY_VERIFY(name != 0);
526 QTRY_COMPARE(name->text(), model.name(0));
527 number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
528 QTRY_VERIFY(number != 0);
529 QTRY_COMPARE(number->text(), model.number(0));
531 QTRY_COMPARE(listview->currentIndex(), 1);
533 // Confirm items positioned correctly
534 for (int i = 0; i < model.count(); ++i) {
535 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
536 QTRY_COMPARE(item->y(), i*20.0);
539 for (int i = model.count(); i < 30; ++i)
540 model.insertItem(i, "Hello", QString::number(i));
542 listview->setContentY(80);
544 // Insert item outside visible area
545 model.insertItem(1, "Hello", "1324");
547 QTRY_VERIFY(listview->contentY() == 80);
549 // Confirm items positioned correctly
550 for (int i = 5; i < 5+15; ++i) {
551 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
552 if (!item) qWarning() << "Item" << i << "not found";
554 QTRY_COMPARE(item->y(), i*20.0 - 20.0);
557 // QTRY_COMPARE(listview->contentItemHeight(), model.count() * 20.0);
563 void tst_QDeclarativeListView::removed(bool animated)
565 QDeclarativeView *canvas = createView();
568 for (int i = 0; i < 50; i++)
569 model.addItem("Item" + QString::number(i), "");
571 QDeclarativeContext *ctxt = canvas->rootContext();
572 ctxt->setContextProperty("testModel", &model);
574 TestObject *testObject = new TestObject;
575 testObject->setAnimate(animated);
576 ctxt->setContextProperty("testObject", testObject);
578 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
579 qApp->processEvents();
581 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
582 QTRY_VERIFY(listview != 0);
584 QDeclarativeItem *contentItem = listview->contentItem();
585 QTRY_VERIFY(contentItem != 0);
588 QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
590 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
591 QTRY_VERIFY(name != 0);
592 QTRY_COMPARE(name->text(), model.name(1));
593 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
594 QTRY_VERIFY(number != 0);
595 QTRY_COMPARE(number->text(), model.number(1));
597 // Confirm items positioned correctly
598 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
599 for (int i = 0; i < model.count() && i < itemCount; ++i) {
600 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
601 if (!item) qWarning() << "Item" << i << "not found";
603 QTRY_VERIFY(item->y() == i*20);
606 // Remove first item (which is the current item);
607 model.removeItem(0); // post: top item starts at 20
611 name = findItem<QDeclarativeText>(contentItem, "textName", 0);
612 QTRY_VERIFY(name != 0);
613 QTRY_COMPARE(name->text(), model.name(0));
614 number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
615 QTRY_VERIFY(number != 0);
616 QTRY_COMPARE(number->text(), model.number(0));
618 // Confirm items positioned correctly
619 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
620 for (int i = 0; i < model.count() && i < itemCount; ++i) {
621 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
622 if (!item) qWarning() << "Item" << i << "not found";
624 QTRY_COMPARE(item->y(),i*20.0 + 20.0);
627 // Remove items not visible
628 model.removeItem(18);
629 qApp->processEvents();
631 // Confirm items positioned correctly
632 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
633 for (int i = 0; i < model.count() && i < itemCount; ++i) {
634 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
635 if (!item) qWarning() << "Item" << i << "not found";
637 QTRY_COMPARE(item->y(),i*20.0+20.0);
640 // Remove items before visible
641 listview->setContentY(80);
642 listview->setCurrentIndex(10);
644 model.removeItem(1); // post: top item will be at 40
645 qApp->processEvents();
647 // Confirm items positioned correctly
648 for (int i = 2; i < 18; ++i) {
649 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
650 if (!item) qWarning() << "Item" << i << "not found";
652 QTRY_COMPARE(item->y(),40+i*20.0);
655 // Remove current index
656 QTRY_VERIFY(listview->currentIndex() == 9);
657 QDeclarativeItem *oldCurrent = listview->currentItem();
660 QTRY_COMPARE(listview->currentIndex(), 9);
661 QTRY_VERIFY(listview->currentItem() != oldCurrent);
663 listview->setContentY(40); // That's the top now
664 // let transitions settle.
667 // Confirm items positioned correctly
668 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
669 for (int i = 0; i < model.count() && i < itemCount; ++i) {
670 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
671 if (!item) qWarning() << "Item" << i << "not found";
673 QTRY_COMPARE(item->y(),40+i*20.0);
676 // remove current item beyond visible items.
677 listview->setCurrentIndex(20);
678 listview->setContentY(40);
679 model.removeItem(20);
681 QTRY_COMPARE(listview->currentIndex(), 20);
682 QTRY_VERIFY(listview->currentItem() != 0);
684 // remove item before current, but visible
685 listview->setCurrentIndex(8);
686 oldCurrent = listview->currentItem();
689 QTRY_COMPARE(listview->currentIndex(), 7);
690 QTRY_VERIFY(listview->currentItem() == oldCurrent);
692 listview->setContentY(80);
695 // remove all visible items
696 model.removeItems(1, 18);
699 // Confirm items positioned correctly
700 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
701 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
702 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i+2);
703 if (!item) qWarning() << "Item" << i+2 << "not found";
705 QTRY_COMPARE(item->y(),80+i*20.0);
708 model.removeItems(1, 17);
709 // QTest::qWait(300);
711 model.removeItems(2, 1);
712 model.addItem("New", "1");
714 QTRY_VERIFY(name = findItem<QDeclarativeText>(contentItem, "textName", model.count()-1));
715 QCOMPARE(name->text(), QString("New"));
721 void tst_QDeclarativeListView::clear()
723 QDeclarativeView *canvas = createView();
726 for (int i = 0; i < 30; i++)
727 model.addItem("Item" + QString::number(i), "");
729 QDeclarativeContext *ctxt = canvas->rootContext();
730 ctxt->setContextProperty("testModel", &model);
732 TestObject *testObject = new TestObject;
733 ctxt->setContextProperty("testObject", testObject);
735 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
736 qApp->processEvents();
738 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
739 QTRY_VERIFY(listview != 0);
741 QDeclarativeItem *contentItem = listview->contentItem();
742 QTRY_VERIFY(contentItem != 0);
746 QTRY_VERIFY(listview->count() == 0);
747 QTRY_VERIFY(listview->currentItem() == 0);
748 QTRY_VERIFY(listview->contentY() == 0);
749 QVERIFY(listview->currentIndex() == -1);
751 // confirm sanity when adding an item to cleared list
752 model.addItem("New", "1");
753 QTRY_VERIFY(listview->count() == 1);
754 QVERIFY(listview->currentItem() != 0);
755 QVERIFY(listview->currentIndex() == 0);
762 void tst_QDeclarativeListView::moved()
764 QDeclarativeView *canvas = createView();
767 for (int i = 0; i < 30; i++)
768 model.addItem("Item" + QString::number(i), "");
770 QDeclarativeContext *ctxt = canvas->rootContext();
771 ctxt->setContextProperty("testModel", &model);
773 TestObject *testObject = new TestObject;
774 ctxt->setContextProperty("testObject", testObject);
776 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
777 qApp->processEvents();
779 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
780 QTRY_VERIFY(listview != 0);
782 QDeclarativeItem *contentItem = listview->contentItem();
783 QTRY_VERIFY(contentItem != 0);
785 model.moveItem(1, 4);
787 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
788 QTRY_VERIFY(name != 0);
789 QTRY_COMPARE(name->text(), model.name(1));
790 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
791 QTRY_VERIFY(number != 0);
792 QTRY_COMPARE(number->text(), model.number(1));
794 name = findItem<QDeclarativeText>(contentItem, "textName", 4);
795 QTRY_VERIFY(name != 0);
796 QTRY_COMPARE(name->text(), model.name(4));
797 number = findItem<QDeclarativeText>(contentItem, "textNumber", 4);
798 QTRY_VERIFY(number != 0);
799 QTRY_COMPARE(number->text(), model.number(4));
801 // Confirm items positioned correctly
802 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
803 for (int i = 0; i < model.count() && i < itemCount; ++i) {
804 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
805 if (!item) qWarning() << "Item" << i << "not found";
807 QTRY_VERIFY(item->y() == i*20);
810 listview->setContentY(80);
812 // move outside visible area
813 model.moveItem(1, 18);
815 // Confirm items positioned correctly and indexes correct
816 for (int i = 3; i < model.count() && i < itemCount; ++i) {
817 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
818 if (!item) qWarning() << "Item" << i << "not found";
820 QTRY_COMPARE(item->y(), i*20.0 + 20);
821 name = findItem<QDeclarativeText>(contentItem, "textName", i);
822 QTRY_VERIFY(name != 0);
823 QTRY_COMPARE(name->text(), model.name(i));
824 number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
825 QTRY_VERIFY(number != 0);
826 QTRY_COMPARE(number->text(), model.number(i));
829 // move from outside visible into visible
830 model.moveItem(20, 4);
832 // Confirm items positioned correctly and indexes correct
833 for (int i = 3; i < model.count() && i < itemCount; ++i) {
834 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
835 if (!item) qWarning() << "Item" << i << "not found";
837 QTRY_COMPARE(item->y(), i*20.0 + 20);
838 name = findItem<QDeclarativeText>(contentItem, "textName", i);
839 QTRY_VERIFY(name != 0);
840 QTRY_COMPARE(name->text(), model.name(i));
841 number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
842 QTRY_VERIFY(number != 0);
843 QTRY_COMPARE(number->text(), model.number(i));
849 void tst_QDeclarativeListView::enforceRange()
851 QDeclarativeView *canvas = createView();
854 for (int i = 0; i < 30; i++)
855 model.addItem("Item" + QString::number(i), "");
857 QDeclarativeContext *ctxt = canvas->rootContext();
858 ctxt->setContextProperty("testModel", &model);
860 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listview-enforcerange.qml"));
861 qApp->processEvents();
863 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
864 QTRY_VERIFY(listview != 0);
866 QTRY_COMPARE(listview->preferredHighlightBegin(), 100.0);
867 QTRY_COMPARE(listview->preferredHighlightEnd(), 100.0);
868 QTRY_COMPARE(listview->highlightRangeMode(), QDeclarativeListView::StrictlyEnforceRange);
870 QDeclarativeItem *contentItem = listview->contentItem();
871 QTRY_VERIFY(contentItem != 0);
873 // view should be positioned at the top of the range.
874 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 0);
876 QTRY_COMPARE(listview->contentY(), -100.0);
878 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 0);
879 QTRY_VERIFY(name != 0);
880 QTRY_COMPARE(name->text(), model.name(0));
881 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
882 QTRY_VERIFY(number != 0);
883 QTRY_COMPARE(number->text(), model.number(0));
885 // Check currentIndex is updated when contentItem moves
886 listview->setContentY(20);
888 QTRY_COMPARE(listview->currentIndex(), 6);
892 for (int i = 0; i < 5; i++)
893 model2.addItem("Item" + QString::number(i), "");
895 ctxt->setContextProperty("testModel", &model2);
896 QCOMPARE(listview->count(), 5);
901 void tst_QDeclarativeListView::spacing()
903 QDeclarativeView *canvas = createView();
906 for (int i = 0; i < 30; i++)
907 model.addItem("Item" + QString::number(i), "");
909 QDeclarativeContext *ctxt = canvas->rootContext();
910 ctxt->setContextProperty("testModel", &model);
912 TestObject *testObject = new TestObject;
913 ctxt->setContextProperty("testObject", testObject);
915 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
916 qApp->processEvents();
918 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
919 QTRY_VERIFY(listview != 0);
921 QDeclarativeItem *contentItem = listview->contentItem();
922 QTRY_VERIFY(contentItem != 0);
924 // Confirm items positioned correctly
925 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
926 for (int i = 0; i < model.count() && i < itemCount; ++i) {
927 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
928 if (!item) qWarning() << "Item" << i << "not found";
930 QTRY_VERIFY(item->y() == i*20);
933 listview->setSpacing(10);
934 QTRY_VERIFY(listview->spacing() == 10);
936 // Confirm items positioned correctly
937 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
938 for (int i = 0; i < model.count() && i < itemCount; ++i) {
939 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
940 if (!item) qWarning() << "Item" << i << "not found";
942 QTRY_VERIFY(item->y() == i*30);
945 listview->setSpacing(0);
947 // Confirm items positioned correctly
948 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
949 for (int i = 0; i < model.count() && i < itemCount; ++i) {
950 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
951 if (!item) qWarning() << "Item" << i << "not found";
953 QTRY_COMPARE(item->y(), i*20.0);
959 void tst_QDeclarativeListView::sections()
961 QDeclarativeView *canvas = createView();
964 for (int i = 0; i < 30; i++)
965 model.addItem("Item" + QString::number(i), QString::number(i/5));
967 QDeclarativeContext *ctxt = canvas->rootContext();
968 ctxt->setContextProperty("testModel", &model);
970 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listview-sections.qml"));
971 qApp->processEvents();
973 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
974 QTRY_VERIFY(listview != 0);
976 QDeclarativeItem *contentItem = listview->contentItem();
977 QTRY_VERIFY(contentItem != 0);
979 // Confirm items positioned correctly
980 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
981 for (int i = 0; i < model.count() && i < itemCount; ++i) {
982 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
984 QTRY_COMPARE(item->y(), qreal(i*20 + ((i+4)/5) * 20));
985 QDeclarativeText *next = findItem<QDeclarativeText>(item, "nextSection");
986 QCOMPARE(next->text().toInt(), (i+1)/5);
989 QSignalSpy currentSectionChangedSpy(listview, SIGNAL(currentSectionChanged()));
991 // Remove section boundary
994 // New section header created
995 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 5);
997 QTRY_COMPARE(item->height(), 40.0);
999 model.insertItem(3, "New Item", "0");
1001 // Section header moved
1002 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 5);
1004 QTRY_COMPARE(item->height(), 20.0);
1006 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 6);
1008 QTRY_COMPARE(item->height(), 40.0);
1010 // insert item which will become a section header
1011 model.insertItem(6, "Replace header", "1");
1013 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 6);
1015 QTRY_COMPARE(item->height(), 40.0);
1017 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 7);
1019 QTRY_COMPARE(item->height(), 20.0);
1021 QTRY_COMPARE(listview->currentSection(), QString("0"));
1023 listview->setContentY(140);
1024 QTRY_COMPARE(listview->currentSection(), QString("1"));
1026 QTRY_COMPARE(currentSectionChangedSpy.count(), 1);
1028 listview->setContentY(20);
1029 QTRY_COMPARE(listview->currentSection(), QString("0"));
1031 QTRY_COMPARE(currentSectionChangedSpy.count(), 2);
1033 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 1);
1035 QTRY_COMPARE(item->height(), 20.0);
1037 // check that headers change when item changes
1038 listview->setContentY(0);
1039 model.modifyItem(0, "changed", "2");
1041 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 1);
1043 QTRY_COMPARE(item->height(), 40.0);
1048 void tst_QDeclarativeListView::sectionsDelegate()
1050 QDeclarativeView *canvas = createView();
1053 for (int i = 0; i < 30; i++)
1054 model.addItem("Item" + QString::number(i), QString::number(i/5));
1056 QDeclarativeContext *ctxt = canvas->rootContext();
1057 ctxt->setContextProperty("testModel", &model);
1059 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listview-sections_delegate.qml"));
1060 qApp->processEvents();
1062 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1063 QTRY_VERIFY(listview != 0);
1065 QDeclarativeItem *contentItem = listview->contentItem();
1066 QTRY_VERIFY(contentItem != 0);
1068 // Confirm items positioned correctly
1069 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1070 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1071 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1073 QTRY_COMPARE(item->y(), qreal(i*20 + ((i+5)/5) * 20));
1074 QDeclarativeText *next = findItem<QDeclarativeText>(item, "nextSection");
1075 QCOMPARE(next->text().toInt(), (i+1)/5);
1078 for (int i = 0; i < 3; ++i) {
1079 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "sect_" + QString::number(i));
1081 QTRY_COMPARE(item->y(), qreal(i*20*6));
1084 model.modifyItem(0, "One", "aaa");
1085 model.modifyItem(1, "Two", "aaa");
1086 model.modifyItem(2, "Three", "aaa");
1087 model.modifyItem(3, "Four", "aaa");
1088 model.modifyItem(4, "Five", "aaa");
1090 for (int i = 0; i < 3; ++i) {
1091 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem,
1092 "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
1094 QTRY_COMPARE(item->y(), qreal(i*20*6));
1097 // remove section boundary
1098 model.removeItem(5);
1099 qApp->processEvents();
1100 for (int i = 0; i < 3; ++i) {
1101 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem,
1102 "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
1107 QList<QDeclarativeItem*> items = findItems<QDeclarativeItem>(contentItem, "sect_1");
1108 QCOMPARE(items.count(), 1);
1111 model.modifyItem(0, "One", "aaa");
1112 model.modifyItem(1, "One", "aaa");
1113 model.modifyItem(2, "One", "aaa");
1114 model.modifyItem(3, "Four", "aaa");
1115 model.modifyItem(4, "Four", "aaa");
1116 model.modifyItem(5, "Four", "aaa");
1117 model.modifyItem(6, "Five", "aaa");
1118 model.modifyItem(7, "Five", "aaa");
1119 model.modifyItem(8, "Five", "aaa");
1120 model.modifyItem(9, "Two", "aaa");
1121 model.modifyItem(10, "Two", "aaa");
1122 model.modifyItem(11, "Two", "aaa");
1123 QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "sect_aaa").count(), 1);
1124 canvas->rootObject()->setProperty("sectionProperty", "name");
1125 // ensure view has settled.
1126 QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "sect_Four").count(), 1);
1127 for (int i = 0; i < 4; ++i) {
1128 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem,
1129 "sect_" + model.name(i*3));
1131 QTRY_COMPARE(item->y(), qreal(i*20*4));
1135 model.removeItems(10, 20);
1136 // ensure view has settled.
1137 QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "wrapper").count(), 10);
1138 // Drag view up beyond bounds
1139 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20,20)));
1141 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,0)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1142 QApplication::sendEvent(canvas->viewport(), &mv);
1145 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,-50)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1146 QApplication::sendEvent(canvas->viewport(), &mv);
1149 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,-200)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1150 QApplication::sendEvent(canvas->viewport(), &mv);
1152 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20,-200)));
1153 // view should settle back at 0
1154 QTRY_COMPARE(listview->contentY(), 0.0);
1159 void tst_QDeclarativeListView::currentIndex()
1162 for (int i = 0; i < 30; i++)
1163 model.addItem("Item" + QString::number(i), QString::number(i));
1165 QDeclarativeView *canvas = new QDeclarativeView(0);
1166 canvas->setFixedSize(240,320);
1168 QDeclarativeContext *ctxt = canvas->rootContext();
1169 ctxt->setContextProperty("testModel", &model);
1170 ctxt->setContextProperty("testWrap", QVariant(false));
1172 QString filename(SRCDIR "/data/listview-initCurrent.qml");
1173 canvas->setSource(QUrl::fromLocalFile(filename));
1175 qApp->processEvents();
1177 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1178 QTRY_VERIFY(listview != 0);
1180 QDeclarativeItem *contentItem = listview->contentItem();
1181 QTRY_VERIFY(contentItem != 0);
1183 // current item should be 20th item at startup
1184 // and current item should be in view
1185 QCOMPARE(listview->currentIndex(), 20);
1186 QCOMPARE(listview->contentY(), 100.0);
1187 QCOMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 20));
1188 QCOMPARE(listview->highlightItem()->y(), listview->currentItem()->y());
1191 listview->setCurrentIndex(0);
1192 QCOMPARE(listview->currentIndex(), 0);
1193 // confirm that the velocity is updated
1194 QTRY_VERIFY(listview->verticalVelocity() != 0.0);
1196 listview->incrementCurrentIndex();
1197 QCOMPARE(listview->currentIndex(), 1);
1198 listview->decrementCurrentIndex();
1199 QCOMPARE(listview->currentIndex(), 0);
1201 listview->decrementCurrentIndex();
1202 QCOMPARE(listview->currentIndex(), 0);
1205 ctxt->setContextProperty("testWrap", QVariant(true));
1206 QVERIFY(listview->isWrapEnabled());
1208 listview->decrementCurrentIndex();
1209 QCOMPARE(listview->currentIndex(), model.count()-1);
1211 QTRY_COMPARE(listview->contentY(), 280.0);
1213 listview->incrementCurrentIndex();
1214 QCOMPARE(listview->currentIndex(), 0);
1216 QTRY_COMPARE(listview->contentY(), 0.0);
1220 qApp->setActiveWindow(canvas);
1222 // to be safe and avoid failing setFocus with window managers
1223 qt_x11_wait_for_window_manager(canvas);
1225 QTRY_VERIFY(canvas->hasFocus());
1226 QTRY_VERIFY(canvas->scene()->hasFocus());
1227 qApp->processEvents();
1229 QTest::keyClick(canvas, Qt::Key_Down);
1230 QCOMPARE(listview->currentIndex(), 1);
1232 QTest::keyClick(canvas, Qt::Key_Up);
1233 QCOMPARE(listview->currentIndex(), 0);
1235 // turn off auto highlight
1236 listview->setHighlightFollowsCurrentItem(false);
1237 QVERIFY(listview->highlightFollowsCurrentItem() == false);
1239 QVERIFY(listview->highlightItem());
1240 qreal hlPos = listview->highlightItem()->y();
1242 listview->setCurrentIndex(4);
1243 QTRY_COMPARE(listview->highlightItem()->y(), hlPos);
1245 // insert item before currentIndex
1246 listview->setCurrentIndex(28);
1247 model.insertItem(0, "Foo", "1111");
1248 QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
1250 // check removing highlight by setting currentIndex to -1;
1251 listview->setCurrentIndex(-1);
1253 QCOMPARE(listview->currentIndex(), -1);
1254 QVERIFY(!listview->highlightItem());
1255 QVERIFY(!listview->currentItem());
1260 void tst_QDeclarativeListView::noCurrentIndex()
1263 for (int i = 0; i < 30; i++)
1264 model.addItem("Item" + QString::number(i), QString::number(i));
1266 QDeclarativeView *canvas = new QDeclarativeView(0);
1267 canvas->setFixedSize(240,320);
1269 QDeclarativeContext *ctxt = canvas->rootContext();
1270 ctxt->setContextProperty("testModel", &model);
1272 QString filename(SRCDIR "/data/listview-noCurrent.qml");
1273 canvas->setSource(QUrl::fromLocalFile(filename));
1275 qApp->processEvents();
1277 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1278 QTRY_VERIFY(listview != 0);
1280 QDeclarativeItem *contentItem = listview->contentItem();
1281 QTRY_VERIFY(contentItem != 0);
1283 // current index should be -1 at startup
1284 // and we should not have a currentItem or highlightItem
1285 QCOMPARE(listview->currentIndex(), -1);
1286 QCOMPARE(listview->contentY(), 0.0);
1287 QVERIFY(!listview->highlightItem());
1288 QVERIFY(!listview->currentItem());
1290 listview->setCurrentIndex(2);
1291 QCOMPARE(listview->currentIndex(), 2);
1292 QVERIFY(listview->highlightItem());
1293 QVERIFY(listview->currentItem());
1296 void tst_QDeclarativeListView::itemList()
1298 QDeclarativeView *canvas = createView();
1300 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/itemlist.qml"));
1301 qApp->processEvents();
1303 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "view");
1304 QTRY_VERIFY(listview != 0);
1306 QDeclarativeItem *contentItem = listview->contentItem();
1307 QTRY_VERIFY(contentItem != 0);
1309 QDeclarativeVisualItemModel *model = canvas->rootObject()->findChild<QDeclarativeVisualItemModel*>("itemModel");
1310 QTRY_VERIFY(model != 0);
1312 QTRY_VERIFY(model->count() == 3);
1313 QTRY_COMPARE(listview->currentIndex(), 0);
1315 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "item1");
1317 QTRY_COMPARE(item->x(), 0.0);
1318 QCOMPARE(item->height(), listview->height());
1320 QDeclarativeText *text = findItem<QDeclarativeText>(contentItem, "text1");
1322 QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
1324 listview->setCurrentIndex(2);
1326 item = findItem<QDeclarativeItem>(contentItem, "item3");
1328 QTRY_COMPARE(item->x(), 480.0);
1330 text = findItem<QDeclarativeText>(contentItem, "text3");
1332 QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
1337 void tst_QDeclarativeListView::cacheBuffer()
1339 QDeclarativeView *canvas = createView();
1342 for (int i = 0; i < 30; i++)
1343 model.addItem("Item" + QString::number(i), "");
1345 QDeclarativeContext *ctxt = canvas->rootContext();
1346 ctxt->setContextProperty("testModel", &model);
1348 TestObject *testObject = new TestObject;
1349 ctxt->setContextProperty("testObject", testObject);
1351 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
1352 qApp->processEvents();
1354 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1355 QTRY_VERIFY(listview != 0);
1357 QDeclarativeItem *contentItem = listview->contentItem();
1358 QTRY_VERIFY(contentItem != 0);
1359 QTRY_VERIFY(listview->delegate() != 0);
1360 QTRY_VERIFY(listview->model() != 0);
1361 QTRY_VERIFY(listview->highlight() != 0);
1363 // Confirm items positioned correctly
1364 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1365 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1366 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1367 if (!item) qWarning() << "Item" << i << "not found";
1369 QTRY_VERIFY(item->y() == i*20);
1372 testObject->setCacheBuffer(400);
1373 QTRY_VERIFY(listview->cacheBuffer() == 400);
1375 int newItemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1376 QTRY_VERIFY(newItemCount > itemCount);
1378 // Confirm items positioned correctly
1379 for (int i = 0; i < model.count() && i < newItemCount; ++i) {
1380 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1381 if (!item) qWarning() << "Item" << i << "not found";
1383 QTRY_VERIFY(item->y() == i*20);
1389 void tst_QDeclarativeListView::positionViewAtIndex()
1391 QDeclarativeView *canvas = createView();
1394 for (int i = 0; i < 40; i++)
1395 model.addItem("Item" + QString::number(i), "");
1397 QDeclarativeContext *ctxt = canvas->rootContext();
1398 ctxt->setContextProperty("testModel", &model);
1400 TestObject *testObject = new TestObject;
1401 ctxt->setContextProperty("testObject", testObject);
1403 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
1404 qApp->processEvents();
1406 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1407 QTRY_VERIFY(listview != 0);
1409 QDeclarativeItem *contentItem = listview->contentItem();
1410 QTRY_VERIFY(contentItem != 0);
1412 // Confirm items positioned correctly
1413 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1414 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1415 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1416 if (!item) qWarning() << "Item" << i << "not found";
1418 QTRY_COMPARE(item->y(), i*20.);
1421 // Position on a currently visible item
1422 listview->positionViewAtIndex(3, QDeclarativeListView::Beginning);
1423 QTRY_COMPARE(listview->contentY(), 60.);
1425 // Confirm items positioned correctly
1426 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1427 for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
1428 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1429 if (!item) qWarning() << "Item" << i << "not found";
1431 QTRY_COMPARE(item->y(), i*20.);
1434 // Position on an item beyond the visible items
1435 listview->positionViewAtIndex(22, QDeclarativeListView::Beginning);
1436 QTRY_COMPARE(listview->contentY(), 440.);
1438 // Confirm items positioned correctly
1439 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1440 for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
1441 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1442 if (!item) qWarning() << "Item" << i << "not found";
1444 QTRY_COMPARE(item->y(), i*20.);
1447 // Position on an item that would leave empty space if positioned at the top
1448 listview->positionViewAtIndex(28, QDeclarativeListView::Beginning);
1449 QTRY_COMPARE(listview->contentY(), 480.);
1451 // Confirm items positioned correctly
1452 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1453 for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
1454 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1455 if (!item) qWarning() << "Item" << i << "not found";
1457 QTRY_COMPARE(item->y(), i*20.);
1460 // Position at the beginning again
1461 listview->positionViewAtIndex(0, QDeclarativeListView::Beginning);
1462 QTRY_COMPARE(listview->contentY(), 0.);
1464 // Confirm items positioned correctly
1465 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1466 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1467 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1468 if (!item) qWarning() << "Item" << i << "not found";
1470 QTRY_COMPARE(item->y(), i*20.);
1473 // Position at End using last index
1474 listview->positionViewAtIndex(model.count()-1, QDeclarativeListView::End);
1475 QTRY_COMPARE(listview->contentY(), 480.);
1477 // Confirm items positioned correctly
1478 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1479 for (int i = 24; i < model.count(); ++i) {
1480 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1481 if (!item) qWarning() << "Item" << i << "not found";
1483 QTRY_COMPARE(item->y(), i*20.);
1487 listview->positionViewAtIndex(20, QDeclarativeListView::End);
1488 QTRY_COMPARE(listview->contentY(), 100.);
1490 // Position in Center
1491 listview->positionViewAtIndex(15, QDeclarativeListView::Center);
1492 QTRY_COMPARE(listview->contentY(), 150.);
1494 // Ensure at least partially visible
1495 listview->positionViewAtIndex(15, QDeclarativeListView::Visible);
1496 QTRY_COMPARE(listview->contentY(), 150.);
1498 listview->setContentY(302);
1499 listview->positionViewAtIndex(15, QDeclarativeListView::Visible);
1500 QTRY_COMPARE(listview->contentY(), 302.);
1502 listview->setContentY(320);
1503 listview->positionViewAtIndex(15, QDeclarativeListView::Visible);
1504 QTRY_COMPARE(listview->contentY(), 300.);
1506 listview->setContentY(85);
1507 listview->positionViewAtIndex(20, QDeclarativeListView::Visible);
1508 QTRY_COMPARE(listview->contentY(), 85.);
1510 listview->setContentY(75);
1511 listview->positionViewAtIndex(20, QDeclarativeListView::Visible);
1512 QTRY_COMPARE(listview->contentY(), 100.);
1514 // Ensure completely visible
1515 listview->setContentY(120);
1516 listview->positionViewAtIndex(20, QDeclarativeListView::Contain);
1517 QTRY_COMPARE(listview->contentY(), 120.);
1519 listview->setContentY(302);
1520 listview->positionViewAtIndex(15, QDeclarativeListView::Contain);
1521 QTRY_COMPARE(listview->contentY(), 300.);
1523 listview->setContentY(85);
1524 listview->positionViewAtIndex(20, QDeclarativeListView::Contain);
1525 QTRY_COMPARE(listview->contentY(), 100.);
1527 // positionAtBeginnging
1528 listview->positionViewAtBeginning();
1529 QTRY_COMPARE(listview->contentY(), 0.);
1531 listview->setContentY(80);
1532 canvas->rootObject()->setProperty("showHeader", true);
1533 listview->positionViewAtBeginning();
1534 QTRY_COMPARE(listview->contentY(), -30.);
1537 listview->positionViewAtEnd();
1538 QTRY_COMPARE(listview->contentY(), 480.); // 40*20 - 320
1540 listview->setContentY(80);
1541 canvas->rootObject()->setProperty("showFooter", true);
1542 listview->positionViewAtEnd();
1543 QTRY_COMPARE(listview->contentY(), 510.);
1548 void tst_QDeclarativeListView::resetModel()
1550 QDeclarativeView *canvas = createView();
1552 QStringList strings;
1553 strings << "one" << "two" << "three";
1554 QStringListModel model(strings);
1556 QDeclarativeContext *ctxt = canvas->rootContext();
1557 ctxt->setContextProperty("testModel", &model);
1559 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaylist.qml"));
1560 qApp->processEvents();
1562 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1563 QTRY_VERIFY(listview != 0);
1565 QDeclarativeItem *contentItem = listview->contentItem();
1566 QTRY_VERIFY(contentItem != 0);
1568 QTRY_COMPARE(listview->count(), model.rowCount());
1570 for (int i = 0; i < model.rowCount(); ++i) {
1571 QDeclarativeText *display = findItem<QDeclarativeText>(contentItem, "displayText", i);
1572 QTRY_VERIFY(display != 0);
1573 QTRY_COMPARE(display->text(), strings.at(i));
1577 strings << "four" << "five" << "six" << "seven";
1578 model.setStringList(strings);
1580 QTRY_COMPARE(listview->count(), model.rowCount());
1582 for (int i = 0; i < model.rowCount(); ++i) {
1583 QDeclarativeText *display = findItem<QDeclarativeText>(contentItem, "displayText", i);
1584 QTRY_VERIFY(display != 0);
1585 QTRY_COMPARE(display->text(), strings.at(i));
1591 void tst_QDeclarativeListView::propertyChanges()
1593 QDeclarativeView *canvas = createView();
1594 QTRY_VERIFY(canvas);
1595 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1597 QDeclarativeListView *listView = canvas->rootObject()->findChild<QDeclarativeListView*>("listView");
1598 QTRY_VERIFY(listView);
1600 QSignalSpy highlightFollowsCurrentItemSpy(listView, SIGNAL(highlightFollowsCurrentItemChanged()));
1601 QSignalSpy preferredHighlightBeginSpy(listView, SIGNAL(preferredHighlightBeginChanged()));
1602 QSignalSpy preferredHighlightEndSpy(listView, SIGNAL(preferredHighlightEndChanged()));
1603 QSignalSpy highlightRangeModeSpy(listView, SIGNAL(highlightRangeModeChanged()));
1604 QSignalSpy keyNavigationWrapsSpy(listView, SIGNAL(keyNavigationWrapsChanged()));
1605 QSignalSpy cacheBufferSpy(listView, SIGNAL(cacheBufferChanged()));
1606 QSignalSpy snapModeSpy(listView, SIGNAL(snapModeChanged()));
1608 QTRY_COMPARE(listView->highlightFollowsCurrentItem(), true);
1609 QTRY_COMPARE(listView->preferredHighlightBegin(), 0.0);
1610 QTRY_COMPARE(listView->preferredHighlightEnd(), 0.0);
1611 QTRY_COMPARE(listView->highlightRangeMode(), QDeclarativeListView::ApplyRange);
1612 QTRY_COMPARE(listView->isWrapEnabled(), true);
1613 QTRY_COMPARE(listView->cacheBuffer(), 10);
1614 QTRY_COMPARE(listView->snapMode(), QDeclarativeListView::SnapToItem);
1616 listView->setHighlightFollowsCurrentItem(false);
1617 listView->setPreferredHighlightBegin(1.0);
1618 listView->setPreferredHighlightEnd(1.0);
1619 listView->setHighlightRangeMode(QDeclarativeListView::StrictlyEnforceRange);
1620 listView->setWrapEnabled(false);
1621 listView->setCacheBuffer(3);
1622 listView->setSnapMode(QDeclarativeListView::SnapOneItem);
1624 QTRY_COMPARE(listView->highlightFollowsCurrentItem(), false);
1625 QTRY_COMPARE(listView->preferredHighlightBegin(), 1.0);
1626 QTRY_COMPARE(listView->preferredHighlightEnd(), 1.0);
1627 QTRY_COMPARE(listView->highlightRangeMode(), QDeclarativeListView::StrictlyEnforceRange);
1628 QTRY_COMPARE(listView->isWrapEnabled(), false);
1629 QTRY_COMPARE(listView->cacheBuffer(), 3);
1630 QTRY_COMPARE(listView->snapMode(), QDeclarativeListView::SnapOneItem);
1632 QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
1633 QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
1634 QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
1635 QTRY_COMPARE(highlightRangeModeSpy.count(),1);
1636 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1637 QTRY_COMPARE(cacheBufferSpy.count(),1);
1638 QTRY_COMPARE(snapModeSpy.count(),1);
1640 listView->setHighlightFollowsCurrentItem(false);
1641 listView->setPreferredHighlightBegin(1.0);
1642 listView->setPreferredHighlightEnd(1.0);
1643 listView->setHighlightRangeMode(QDeclarativeListView::StrictlyEnforceRange);
1644 listView->setWrapEnabled(false);
1645 listView->setCacheBuffer(3);
1646 listView->setSnapMode(QDeclarativeListView::SnapOneItem);
1648 QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
1649 QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
1650 QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
1651 QTRY_COMPARE(highlightRangeModeSpy.count(),1);
1652 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1653 QTRY_COMPARE(cacheBufferSpy.count(),1);
1654 QTRY_COMPARE(snapModeSpy.count(),1);
1659 void tst_QDeclarativeListView::componentChanges()
1661 QDeclarativeView *canvas = createView();
1662 QTRY_VERIFY(canvas);
1663 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1665 QDeclarativeListView *listView = canvas->rootObject()->findChild<QDeclarativeListView*>("listView");
1666 QTRY_VERIFY(listView);
1668 QDeclarativeComponent component(canvas->engine());
1669 component.setData("import QtQuick 1.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
1671 QDeclarativeComponent delegateComponent(canvas->engine());
1672 delegateComponent.setData("import QtQuick 1.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
1674 QSignalSpy highlightSpy(listView, SIGNAL(highlightChanged()));
1675 QSignalSpy delegateSpy(listView, SIGNAL(delegateChanged()));
1676 QSignalSpy headerSpy(listView, SIGNAL(headerChanged()));
1677 QSignalSpy footerSpy(listView, SIGNAL(footerChanged()));
1679 listView->setHighlight(&component);
1680 listView->setHeader(&component);
1681 listView->setFooter(&component);
1682 listView->setDelegate(&delegateComponent);
1684 QTRY_COMPARE(listView->highlight(), &component);
1685 QTRY_COMPARE(listView->header(), &component);
1686 QTRY_COMPARE(listView->footer(), &component);
1687 QTRY_COMPARE(listView->delegate(), &delegateComponent);
1689 QTRY_COMPARE(highlightSpy.count(),1);
1690 QTRY_COMPARE(delegateSpy.count(),1);
1691 QTRY_COMPARE(headerSpy.count(),1);
1692 QTRY_COMPARE(footerSpy.count(),1);
1694 listView->setHighlight(&component);
1695 listView->setHeader(&component);
1696 listView->setFooter(&component);
1697 listView->setDelegate(&delegateComponent);
1699 QTRY_COMPARE(highlightSpy.count(),1);
1700 QTRY_COMPARE(delegateSpy.count(),1);
1701 QTRY_COMPARE(headerSpy.count(),1);
1702 QTRY_COMPARE(footerSpy.count(),1);
1707 void tst_QDeclarativeListView::modelChanges()
1709 QDeclarativeView *canvas = createView();
1710 QTRY_VERIFY(canvas);
1711 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1713 QDeclarativeListView *listView = canvas->rootObject()->findChild<QDeclarativeListView*>("listView");
1714 QTRY_VERIFY(listView);
1716 QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
1717 QTRY_VERIFY(alternateModel);
1718 QVariant modelVariant = QVariant::fromValue(alternateModel);
1719 QSignalSpy modelSpy(listView, SIGNAL(modelChanged()));
1721 listView->setModel(modelVariant);
1722 QTRY_COMPARE(listView->model(), modelVariant);
1723 QTRY_COMPARE(modelSpy.count(),1);
1725 listView->setModel(modelVariant);
1726 QTRY_COMPARE(modelSpy.count(),1);
1728 listView->setModel(QVariant());
1729 QTRY_COMPARE(modelSpy.count(),2);
1734 void tst_QDeclarativeListView::QTBUG_9791()
1736 QDeclarativeView *canvas = createView();
1738 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/strictlyenforcerange.qml"));
1739 qApp->processEvents();
1741 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
1742 QTRY_VERIFY(listview != 0);
1744 QDeclarativeItem *contentItem = listview->contentItem();
1745 QTRY_VERIFY(contentItem != 0);
1746 QTRY_VERIFY(listview->delegate() != 0);
1747 QTRY_VERIFY(listview->model() != 0);
1749 QMetaObject::invokeMethod(listview, "fillModel");
1750 qApp->processEvents();
1752 // Confirm items positioned correctly
1753 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1754 QCOMPARE(itemCount, 3);
1756 for (int i = 0; i < itemCount; ++i) {
1757 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1758 if (!item) qWarning() << "Item" << i << "not found";
1760 QTRY_COMPARE(item->x(), i*300.0);
1763 // check that view is positioned correctly
1764 QTRY_COMPARE(listview->contentX(), 590.0);
1769 void tst_QDeclarativeListView::manualHighlight()
1771 QDeclarativeView *canvas = new QDeclarativeView(0);
1772 canvas->setFixedSize(240,320);
1774 QString filename(SRCDIR "/data/manual-highlight.qml");
1775 canvas->setSource(QUrl::fromLocalFile(filename));
1777 qApp->processEvents();
1779 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1780 QTRY_VERIFY(listview != 0);
1782 QDeclarativeItem *contentItem = listview->contentItem();
1783 QTRY_VERIFY(contentItem != 0);
1785 QTRY_COMPARE(listview->currentIndex(), 0);
1786 QTRY_COMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 0));
1787 QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
1789 listview->setCurrentIndex(2);
1791 QTRY_COMPARE(listview->currentIndex(), 2);
1792 QTRY_COMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 2));
1793 QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
1796 listview->positionViewAtIndex(3, QDeclarativeListView::Contain);
1798 QTRY_COMPARE(listview->currentIndex(), 2);
1799 QTRY_COMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 2));
1800 QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
1805 void tst_QDeclarativeListView::QTBUG_11105()
1807 QDeclarativeView *canvas = createView();
1810 for (int i = 0; i < 30; i++)
1811 model.addItem("Item" + QString::number(i), "");
1813 QDeclarativeContext *ctxt = canvas->rootContext();
1814 ctxt->setContextProperty("testModel", &model);
1816 TestObject *testObject = new TestObject;
1817 ctxt->setContextProperty("testObject", testObject);
1819 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
1820 qApp->processEvents();
1822 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1823 QTRY_VERIFY(listview != 0);
1825 QDeclarativeItem *contentItem = listview->contentItem();
1826 QTRY_VERIFY(contentItem != 0);
1828 // Confirm items positioned correctly
1829 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1830 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1831 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1832 if (!item) qWarning() << "Item" << i << "not found";
1834 QTRY_VERIFY(item->y() == i*20);
1837 listview->positionViewAtIndex(20, QDeclarativeListView::Beginning);
1838 QCOMPARE(listview->contentY(), 280.);
1841 for (int i = 0; i < 5; i++)
1842 model2.addItem("Item" + QString::number(i), "");
1844 ctxt->setContextProperty("testModel", &model2);
1846 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1847 QCOMPARE(itemCount, 5);
1852 void tst_QDeclarativeListView::header()
1855 QDeclarativeView *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 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1868 QTRY_VERIFY(listview != 0);
1870 QDeclarativeItem *contentItem = listview->contentItem();
1871 QTRY_VERIFY(contentItem != 0);
1873 QDeclarativeText *header = findItem<QDeclarativeText>(contentItem, "header");
1875 QCOMPARE(header->y(), 0.0);
1876 QCOMPARE(header->height(), 20.0);
1878 QCOMPARE(listview->contentY(), 0.0);
1881 QTRY_COMPARE(header->y(), 0.0);
1883 for (int i = 0; i < 30; i++)
1884 model.addItem("Item" + QString::number(i), "");
1886 QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
1888 header = findItem<QDeclarativeText>(contentItem, "header");
1890 header = findItem<QDeclarativeText>(contentItem, "header2");
1893 QCOMPARE(header->y(), 10.0);
1894 QCOMPARE(header->height(), 10.0);
1895 QCOMPARE(listview->contentY(), 10.0);
1900 QDeclarativeView *canvas = createView();
1904 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header1.qml"));
1905 qApp->processEvents();
1907 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1908 QTRY_VERIFY(listview != 0);
1910 QDeclarativeItem *contentItem = listview->contentItem();
1911 QTRY_VERIFY(contentItem != 0);
1913 QDeclarativeText *header = findItem<QDeclarativeText>(contentItem, "header");
1915 QCOMPARE(header->y(), 0.0);
1917 QCOMPARE(listview->contentY(), 0.0);
1920 QTRY_COMPARE(header->y(), 0.0);
1926 void tst_QDeclarativeListView::footer()
1928 QDeclarativeView *canvas = createView();
1931 for (int i = 0; i < 3; i++)
1932 model.addItem("Item" + QString::number(i), "");
1934 QDeclarativeContext *ctxt = canvas->rootContext();
1935 ctxt->setContextProperty("testModel", &model);
1937 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/footer.qml"));
1938 qApp->processEvents();
1940 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1941 QTRY_VERIFY(listview != 0);
1943 QDeclarativeItem *contentItem = listview->contentItem();
1944 QTRY_VERIFY(contentItem != 0);
1946 QDeclarativeText *footer = findItem<QDeclarativeText>(contentItem, "footer");
1948 QCOMPARE(footer->y(), 60.0);
1949 QCOMPARE(footer->height(), 30.0);
1951 model.removeItem(1);
1952 QTRY_COMPARE(footer->y(), 40.0);
1955 QTRY_COMPARE(footer->y(), 0.0);
1957 for (int i = 0; i < 30; i++)
1958 model.addItem("Item" + QString::number(i), "");
1960 QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
1962 footer = findItem<QDeclarativeText>(contentItem, "footer");
1964 footer = findItem<QDeclarativeText>(contentItem, "footer2");
1967 QCOMPARE(footer->y(), 600.0);
1968 QCOMPARE(footer->height(), 20.0);
1969 QCOMPARE(listview->contentY(), 0.0);
1974 class LVAccessor : public QDeclarativeListView
1977 qreal minY() const { return minYExtent(); }
1978 qreal maxY() const { return maxYExtent(); }
1979 qreal minX() const { return minXExtent(); }
1980 qreal maxX() const { return maxXExtent(); }
1983 void tst_QDeclarativeListView::headerFooter()
1987 QDeclarativeView *canvas = createView();
1990 QDeclarativeContext *ctxt = canvas->rootContext();
1991 ctxt->setContextProperty("testModel", &model);
1993 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
1994 qApp->processEvents();
1996 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
1997 QTRY_VERIFY(listview != 0);
1999 QDeclarativeItem *contentItem = listview->contentItem();
2000 QTRY_VERIFY(contentItem != 0);
2002 QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
2004 QCOMPARE(header->y(), 0.0);
2006 QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
2008 QCOMPARE(footer->y(), 20.0);
2010 QVERIFY(static_cast<LVAccessor*>(listview)->minY() == 0);
2011 QVERIFY(static_cast<LVAccessor*>(listview)->maxY() == 0);
2017 QDeclarativeView *canvas = createView();
2020 QDeclarativeContext *ctxt = canvas->rootContext();
2021 ctxt->setContextProperty("testModel", &model);
2023 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
2024 canvas->rootObject()->setProperty("horizontal", true);
2025 qApp->processEvents();
2027 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
2028 QTRY_VERIFY(listview != 0);
2030 QDeclarativeItem *contentItem = listview->contentItem();
2031 QTRY_VERIFY(contentItem != 0);
2033 QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
2035 QCOMPARE(header->x(), 0.0);
2037 QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
2039 QCOMPARE(footer->x(), 20.0);
2041 QVERIFY(static_cast<LVAccessor*>(listview)->minX() == 0);
2042 QVERIFY(static_cast<LVAccessor*>(listview)->maxX() == 0);
2048 QDeclarativeView *canvas = createView();
2051 QDeclarativeContext *ctxt = canvas->rootContext();
2052 ctxt->setContextProperty("testModel", &model);
2054 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
2055 canvas->rootObject()->setProperty("horizontal", true);
2056 canvas->rootObject()->setProperty("rtl", true);
2057 qApp->processEvents();
2059 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
2060 QTRY_VERIFY(listview != 0);
2062 QDeclarativeItem *contentItem = listview->contentItem();
2063 QTRY_VERIFY(contentItem != 0);
2065 QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
2067 QCOMPARE(header->x(), -20.0);
2069 QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
2071 QCOMPARE(footer->x(), -50.0);
2073 QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240.);
2074 QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240.);
2080 void tst_QDeclarativeListView::resizeView()
2082 QDeclarativeView *canvas = createView();
2085 for (int i = 0; i < 40; i++)
2086 model.addItem("Item" + QString::number(i), "");
2088 QDeclarativeContext *ctxt = canvas->rootContext();
2089 ctxt->setContextProperty("testModel", &model);
2091 TestObject *testObject = new TestObject;
2092 ctxt->setContextProperty("testObject", testObject);
2094 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
2095 qApp->processEvents();
2097 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2098 QTRY_VERIFY(listview != 0);
2100 QDeclarativeItem *contentItem = listview->contentItem();
2101 QTRY_VERIFY(contentItem != 0);
2103 // Confirm items positioned correctly
2104 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2105 for (int i = 0; i < model.count() && i < itemCount; ++i) {
2106 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2107 if (!item) qWarning() << "Item" << i << "not found";
2109 QTRY_COMPARE(item->y(), i*20.);
2112 QVariant heightRatio;
2113 QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
2114 QCOMPARE(heightRatio.toReal(), 0.4);
2116 listview->setHeight(200);
2118 QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
2119 QCOMPARE(heightRatio.toReal(), 0.25);
2124 void tst_QDeclarativeListView::sizeLessThan1()
2126 QDeclarativeView *canvas = createView();
2129 for (int i = 0; i < 30; i++)
2130 model.addItem("Item" + QString::number(i), "");
2132 QDeclarativeContext *ctxt = canvas->rootContext();
2133 ctxt->setContextProperty("testModel", &model);
2135 TestObject *testObject = new TestObject;
2136 ctxt->setContextProperty("testObject", testObject);
2138 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/sizelessthan1.qml"));
2139 qApp->processEvents();
2141 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2142 QTRY_VERIFY(listview != 0);
2144 QDeclarativeItem *contentItem = listview->contentItem();
2145 QTRY_VERIFY(contentItem != 0);
2147 // Confirm items positioned correctly
2148 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2149 for (int i = 0; i < model.count() && i < itemCount; ++i) {
2150 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2151 if (!item) qWarning() << "Item" << i << "not found";
2153 QTRY_COMPARE(item->y(), i*0.5);
2159 void tst_QDeclarativeListView::QTBUG_14821()
2161 QDeclarativeView *canvas = createView();
2163 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/qtbug14821.qml"));
2164 qApp->processEvents();
2166 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
2167 QVERIFY(listview != 0);
2169 QDeclarativeItem *contentItem = listview->contentItem();
2170 QVERIFY(contentItem != 0);
2172 listview->decrementCurrentIndex();
2173 QCOMPARE(listview->currentIndex(), 99);
2175 listview->incrementCurrentIndex();
2176 QCOMPARE(listview->currentIndex(), 0);
2181 void tst_QDeclarativeListView::resizeDelegate()
2183 QDeclarativeView *canvas = createView();
2185 QStringList strings;
2186 for (int i = 0; i < 30; ++i)
2187 strings << QString::number(i);
2188 QStringListModel model(strings);
2190 QDeclarativeContext *ctxt = canvas->rootContext();
2191 ctxt->setContextProperty("testModel", &model);
2193 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaylist.qml"));
2194 qApp->processEvents();
2196 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2197 QTRY_VERIFY(listview != 0);
2199 QDeclarativeItem *contentItem = listview->contentItem();
2200 QTRY_VERIFY(contentItem != 0);
2202 QTRY_COMPARE(listview->count(), model.rowCount());
2204 listview->setCurrentIndex(25);
2205 listview->setContentY(0);
2207 for (int i = 0; i < 16; ++i) {
2208 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2210 QCOMPARE(item->y(), i*20.0);
2213 QCOMPARE(listview->currentItem()->y(), 500.0);
2214 QTRY_COMPARE(listview->highlightItem()->y(), 500.0);
2216 canvas->rootObject()->setProperty("delegateHeight", 30);
2217 qApp->processEvents();
2219 for (int i = 0; i < 11; ++i) {
2220 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2222 QTRY_COMPARE(item->y(), i*30.0);
2225 QTRY_COMPARE(listview->currentItem()->y(), 750.0);
2226 QTRY_COMPARE(listview->highlightItem()->y(), 750.0);
2228 listview->setCurrentIndex(1);
2229 listview->positionViewAtIndex(25, QDeclarativeListView::Beginning);
2230 listview->positionViewAtIndex(5, QDeclarativeListView::Beginning);
2232 for (int i = 5; i < 16; ++i) {
2233 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2235 QCOMPARE(item->y(), i*30.0);
2238 QTRY_COMPARE(listview->currentItem()->y(), 30.0);
2239 QTRY_COMPARE(listview->highlightItem()->y(), 30.0);
2241 canvas->rootObject()->setProperty("delegateHeight", 20);
2242 qApp->processEvents();
2244 for (int i = 5; i < 11; ++i) {
2245 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2247 QTRY_COMPARE(item->y(), 150 + (i-5)*20.0);
2250 QTRY_COMPARE(listview->currentItem()->y(), 70.0);
2251 QTRY_COMPARE(listview->highlightItem()->y(), 70.0);
2256 void tst_QDeclarativeListView::QTBUG_16037()
2258 QDeclarativeView *canvas = createView();
2260 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/qtbug16037.qml"));
2261 qApp->processEvents();
2263 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "listview");
2264 QTRY_VERIFY(listview != 0);
2266 QVERIFY(listview->contentHeight() <= 0.0);
2268 QMetaObject::invokeMethod(canvas->rootObject(), "setModel");
2270 QTRY_COMPARE(listview->contentHeight(), 80.0);
2275 void tst_QDeclarativeListView::indexAt()
2277 QDeclarativeView *canvas = createView();
2280 for (int i = 0; i < 30; i++)
2281 model.addItem("Item" + QString::number(i), "");
2283 QDeclarativeContext *ctxt = canvas->rootContext();
2284 ctxt->setContextProperty("testModel", &model);
2286 TestObject *testObject = new TestObject;
2287 ctxt->setContextProperty("testObject", testObject);
2289 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
2290 qApp->processEvents();
2292 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2293 QTRY_VERIFY(listview != 0);
2295 QDeclarativeItem *contentItem = listview->contentItem();
2296 QTRY_VERIFY(contentItem != 0);
2298 QCOMPARE(listview->indexAt(0,0), 0);
2299 QCOMPARE(listview->indexAt(0,19), 0);
2300 QCOMPARE(listview->indexAt(239,19), 0);
2301 QCOMPARE(listview->indexAt(0,20), 1);
2302 QCOMPARE(listview->indexAt(240,20), -1);
2307 void tst_QDeclarativeListView::incrementalModel()
2309 QDeclarativeView *canvas = createView();
2311 IncrementalModel model;
2312 QDeclarativeContext *ctxt = canvas->rootContext();
2313 ctxt->setContextProperty("testModel", &model);
2315 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaylist.qml"));
2316 qApp->processEvents();
2318 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2319 QTRY_VERIFY(listview != 0);
2321 QDeclarativeItem *contentItem = listview->contentItem();
2322 QTRY_VERIFY(contentItem != 0);
2324 QTRY_COMPARE(listview->count(), 20);
2326 listview->positionViewAtIndex(10, QDeclarativeListView::Beginning);
2328 QTRY_COMPARE(listview->count(), 25);
2333 void tst_QDeclarativeListView::onAdd()
2335 QFETCH(int, initialItemCount);
2336 QFETCH(int, itemsToAdd);
2338 const int delegateHeight = 10;
2341 // these initial items should not trigger ListView.onAdd
2342 for (int i=0; i<initialItemCount; i++)
2343 model.addItem("dummy value", "dummy value");
2345 QDeclarativeView *canvas = createView();
2346 canvas->setFixedSize(200, delegateHeight * (initialItemCount + itemsToAdd));
2347 QDeclarativeContext *ctxt = canvas->rootContext();
2348 ctxt->setContextProperty("testModel", &model);
2349 ctxt->setContextProperty("delegateHeight", delegateHeight);
2350 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
2352 QObject *object = canvas->rootObject();
2353 object->setProperty("width", canvas->width());
2354 object->setProperty("height", canvas->height());
2355 qApp->processEvents();
2357 QList<QPair<QString, QString> > items;
2358 for (int i=0; i<itemsToAdd; i++)
2359 items << qMakePair(QString("value %1").arg(i), QString::number(i));
2360 model.addItems(items);
2362 qApp->processEvents();
2364 QVariantList result = object->property("addedDelegates").toList();
2365 QCOMPARE(result.count(), items.count());
2366 for (int i=0; i<items.count(); i++)
2367 QCOMPARE(result[i].toString(), items[i].first);
2372 void tst_QDeclarativeListView::onAdd_data()
2374 QTest::addColumn<int>("initialItemCount");
2375 QTest::addColumn<int>("itemsToAdd");
2377 QTest::newRow("0, add 1") << 0 << 1;
2378 QTest::newRow("0, add 2") << 0 << 2;
2379 QTest::newRow("0, add 10") << 0 << 10;
2381 QTest::newRow("1, add 1") << 1 << 1;
2382 QTest::newRow("1, add 2") << 1 << 2;
2383 QTest::newRow("1, add 10") << 1 << 10;
2385 QTest::newRow("5, add 1") << 5 << 1;
2386 QTest::newRow("5, add 2") << 5 << 2;
2387 QTest::newRow("5, add 10") << 5 << 10;
2390 void tst_QDeclarativeListView::onRemove()
2392 QFETCH(int, initialItemCount);
2393 QFETCH(int, indexToRemove);
2394 QFETCH(int, removeCount);
2396 const int delegateHeight = 10;
2398 for (int i=0; i<initialItemCount; i++)
2399 model.addItem(QString("value %1").arg(i), "dummy value");
2401 QDeclarativeView *canvas = createView();
2402 QDeclarativeContext *ctxt = canvas->rootContext();
2403 ctxt->setContextProperty("testModel", &model);
2404 ctxt->setContextProperty("delegateHeight", delegateHeight);
2405 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
2406 QObject *object = canvas->rootObject();
2408 qApp->processEvents();
2410 model.removeItems(indexToRemove, removeCount);
2411 qApp->processEvents();
2412 QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
2417 void tst_QDeclarativeListView::onRemove_data()
2419 QTest::addColumn<int>("initialItemCount");
2420 QTest::addColumn<int>("indexToRemove");
2421 QTest::addColumn<int>("removeCount");
2423 QTest::newRow("remove first") << 1 << 0 << 1;
2424 QTest::newRow("two items, remove first") << 2 << 0 << 1;
2425 QTest::newRow("two items, remove last") << 2 << 1 << 1;
2426 QTest::newRow("two items, remove all") << 2 << 0 << 2;
2428 QTest::newRow("four items, remove first") << 4 << 0 << 1;
2429 QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
2430 QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
2431 QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
2432 QTest::newRow("four items, remove last") << 4 << 3 << 1;
2433 QTest::newRow("four items, remove all") << 4 << 0 << 4;
2435 QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
2436 QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
2437 QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
2440 void tst_QDeclarativeListView::testQtQuick11Attributes()
2442 QFETCH(QString, code);
2443 QFETCH(QString, warning);
2444 QFETCH(QString, error);
2446 QDeclarativeEngine engine;
2449 QDeclarativeComponent valid(&engine);
2450 valid.setData("import QtQuick 1.1; ListView { " + code.toUtf8() + " }", QUrl(""));
2451 obj = valid.create();
2453 QVERIFY(valid.errorString().isEmpty());
2456 QDeclarativeComponent invalid(&engine);
2457 invalid.setData("import QtQuick 1.0; ListView { " + code.toUtf8() + " }", QUrl(""));
2458 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2459 obj = invalid.create();
2460 QCOMPARE(invalid.errorString(), error);
2464 void tst_QDeclarativeListView::testQtQuick11Attributes_data()
2466 QTest::addColumn<QString>("code");
2467 QTest::addColumn<QString>("warning");
2468 QTest::addColumn<QString>("error");
2470 QTest::newRow("positionViewAtBeginning") << "Component.onCompleted: positionViewAtBeginning()"
2471 << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtBeginning"
2474 QTest::newRow("positionViewAtEnd") << "Component.onCompleted: positionViewAtEnd()"
2475 << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtEnd"
2479 void tst_QDeclarativeListView::rightToLeft()
2481 QDeclarativeView *canvas = createView();
2482 canvas->setFixedSize(640,320);
2483 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
2484 qApp->processEvents();
2486 QVERIFY(canvas->rootObject() != 0);
2487 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "view");
2488 QTRY_VERIFY(listview != 0);
2490 QDeclarativeItem *contentItem = listview->contentItem();
2491 QTRY_VERIFY(contentItem != 0);
2493 QDeclarativeVisualItemModel *model = canvas->rootObject()->findChild<QDeclarativeVisualItemModel*>("itemModel");
2494 QTRY_VERIFY(model != 0);
2496 QTRY_VERIFY(model->count() == 3);
2497 QTRY_COMPARE(listview->currentIndex(), 0);
2499 // initial position at first item, right edge aligned
2500 QCOMPARE(listview->contentX(), -640.);
2502 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "item1");
2504 QTRY_COMPARE(item->x(), -100.0);
2505 QCOMPARE(item->height(), listview->height());
2507 QDeclarativeText *text = findItem<QDeclarativeText>(contentItem, "text1");
2509 QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
2511 listview->setCurrentIndex(2);
2513 item = findItem<QDeclarativeItem>(contentItem, "item3");
2515 QTRY_COMPARE(item->x(), -540.0);
2517 text = findItem<QDeclarativeText>(contentItem, "text3");
2519 QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
2521 QCOMPARE(listview->contentX(), -640.);
2523 // Ensure resizing maintains position relative to right edge
2524 qobject_cast<QDeclarativeItem*>(canvas->rootObject())->setWidth(600);
2525 QTRY_COMPARE(listview->contentX(), -600.);
2530 void tst_QDeclarativeListView::test_mirroring()
2532 QDeclarativeView *canvasA = createView();
2533 canvasA->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
2534 QDeclarativeListView *listviewA = findItem<QDeclarativeListView>(canvasA->rootObject(), "view");
2535 QTRY_VERIFY(listviewA != 0);
2537 QDeclarativeView *canvasB = createView();
2538 canvasB->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
2539 QDeclarativeListView *listviewB = findItem<QDeclarativeListView>(canvasB->rootObject(), "view");
2540 QTRY_VERIFY(listviewA != 0);
2541 qApp->processEvents();
2543 QList<QString> objectNames;
2544 objectNames << "item1" << "item2"; // << "item3"
2546 listviewA->setProperty("layoutDirection", Qt::LeftToRight);
2547 listviewB->setProperty("layoutDirection", Qt::RightToLeft);
2548 QCOMPARE(listviewA->layoutDirection(), listviewA->effectiveLayoutDirection());
2551 foreach(const QString objectName, objectNames)
2552 QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x());
2554 listviewA->setProperty("layoutDirection", Qt::LeftToRight);
2555 listviewB->setProperty("layoutDirection", Qt::LeftToRight);
2558 foreach(const QString objectName, objectNames)
2559 QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x());
2561 QVERIFY(listviewB->layoutDirection() == listviewB->effectiveLayoutDirection());
2562 QDeclarativeItemPrivate::get(listviewB)->setLayoutMirror(true);
2563 QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection());
2565 // LTR != LTR+mirror
2566 foreach(const QString objectName, objectNames)
2567 QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x());
2569 listviewA->setProperty("layoutDirection", Qt::RightToLeft);
2571 // RTL == LTR+mirror
2572 foreach(const QString objectName, objectNames)
2573 QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x());
2575 listviewB->setProperty("layoutDirection", Qt::RightToLeft);
2577 // RTL != RTL+mirror
2578 foreach(const QString objectName, objectNames)
2579 QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x());
2581 listviewA->setProperty("layoutDirection", Qt::LeftToRight);
2583 // LTR == RTL+mirror
2584 foreach(const QString objectName, objectNames)
2585 QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x());
2591 void tst_QDeclarativeListView::orientationChange()
2593 QDeclarativeView *canvas = createView();
2595 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/orientchange.qml"));
2596 qApp->processEvents();
2598 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
2599 QVERIFY(listview != 0);
2601 QDeclarativeItem *contentItem = listview->contentItem();
2602 QVERIFY(contentItem != 0);
2604 listview->positionViewAtIndex(50, QDeclarativeListView::Beginning);
2606 // Confirm items positioned correctly
2607 for (int i = 50; i < 54; ++i) {
2608 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2610 QCOMPARE(item->y(), i*80.0);
2613 listview->setOrientation(QDeclarativeListView::Horizontal);
2614 QCOMPARE(listview->contentY(), 0.);
2616 // Confirm items positioned correctly
2617 for (int i = 0; i < 3; ++i) {
2618 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2620 QCOMPARE(item->x(), i*80.0);
2623 listview->positionViewAtIndex(50, QDeclarativeListView::Beginning);
2624 listview->setOrientation(QDeclarativeListView::Vertical);
2625 QCOMPARE(listview->contentX(), 0.);
2627 // Confirm items positioned correctly
2628 for (int i = 0; i < 4; ++i) {
2629 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2631 QCOMPARE(item->y(), i*80.0);
2637 void tst_QDeclarativeListView::contentPosJump()
2639 QDeclarativeView *canvas = createView();
2642 for (int i = 0; i < 50; i++)
2643 model.addItem("Item" + QString::number(i), "");
2645 QDeclarativeContext *ctxt = canvas->rootContext();
2646 ctxt->setContextProperty("testModel", &model);
2648 TestObject *testObject = new TestObject;
2649 ctxt->setContextProperty("testObject", testObject);
2651 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
2652 qApp->processEvents();
2654 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2655 QTRY_VERIFY(listview != 0);
2657 QDeclarativeItem *contentItem = listview->contentItem();
2658 QTRY_VERIFY(contentItem != 0);
2660 // Confirm items positioned correctly
2661 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2662 for (int i = 0; i < model.count() && i < itemCount; ++i) {
2663 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2664 if (!item) qWarning() << "Item" << i << "not found";
2666 QTRY_VERIFY(item->y() == i*20);
2669 // Test jumping more than a page of items.
2670 listview->setContentY(500);
2671 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2672 for (int i = 25; i < model.count() && i < itemCount; ++i) {
2673 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2674 if (!item) qWarning() << "Item" << i << "not found";
2676 QTRY_VERIFY(item->y() == i*20);
2679 listview->setContentY(-100);
2680 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2681 QVERIFY(itemCount < 20);
2682 for (int i = 0; i < model.count() && i < itemCount; ++i) {
2683 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2684 if (!item) qWarning() << "Item" << i << "not found";
2686 QTRY_VERIFY(item->y() == i*20);
2692 void tst_QDeclarativeListView::qListModelInterface_items()
2697 void tst_QDeclarativeListView::qAbstractItemModel_items()
2699 items<TestModel2>();
2702 void tst_QDeclarativeListView::qListModelInterface_changed()
2704 changed<TestModel>();
2707 void tst_QDeclarativeListView::qAbstractItemModel_changed()
2709 changed<TestModel2>();
2712 void tst_QDeclarativeListView::qListModelInterface_inserted()
2714 inserted<TestModel>();
2717 void tst_QDeclarativeListView::qAbstractItemModel_inserted()
2719 inserted<TestModel2>();
2722 void tst_QDeclarativeListView::qListModelInterface_removed()
2724 removed<TestModel>(false);
2725 removed<TestModel>(true);
2728 void tst_QDeclarativeListView::qAbstractItemModel_removed()
2730 removed<TestModel2>(false);
2731 removed<TestModel2>(true);
2734 void tst_QDeclarativeListView::qListModelInterface_moved()
2739 void tst_QDeclarativeListView::qAbstractItemModel_moved()
2741 moved<TestModel2>();
2744 void tst_QDeclarativeListView::qListModelInterface_clear()
2749 void tst_QDeclarativeListView::qAbstractItemModel_clear()
2751 clear<TestModel2>();
2754 QDeclarativeView *tst_QDeclarativeListView::createView()
2756 QDeclarativeView *canvas = new QDeclarativeView(0);
2757 canvas->setFixedSize(240,320);
2763 Find an item with the specified objectName. If index is supplied then the
2764 item must also evaluate the {index} expression equal to index
2766 template<typename T>
2767 T *tst_QDeclarativeListView::findItem(QGraphicsObject *parent, const QString &objectName, int index)
2769 const QMetaObject &mo = T::staticMetaObject;
2770 //qDebug() << parent->childItems().count() << "children";
2771 for (int i = 0; i < parent->childItems().count(); ++i) {
2772 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
2775 //qDebug() << "try" << item;
2776 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
2778 QDeclarativeExpression e(qmlContext(item), item, "index");
2779 if (e.evaluate().toInt() == index)
2780 return static_cast<T*>(item);
2782 return static_cast<T*>(item);
2785 item = findItem<T>(item, objectName, index);
2787 return static_cast<T*>(item);
2793 template<typename T>
2794 QList<T*> tst_QDeclarativeListView::findItems(QGraphicsObject *parent, const QString &objectName)
2797 const QMetaObject &mo = T::staticMetaObject;
2798 //qDebug() << parent->childItems().count() << "children";
2799 for (int i = 0; i < parent->childItems().count(); ++i) {
2800 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
2801 if(!item || !item->isVisible())
2803 //qDebug() << "try" << item;
2804 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
2805 items.append(static_cast<T*>(item));
2806 items += findItems<T>(item, objectName);
2812 void tst_QDeclarativeListView::dumpTree(QDeclarativeItem *parent, int depth)
2814 static QString padding(" ");
2815 for (int i = 0; i < parent->childItems().count(); ++i) {
2816 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
2819 qDebug() << padding.left(depth*2) << item;
2820 dumpTree(item, depth+1);
2825 QTEST_MAIN(tst_QDeclarativeListView)
2827 #include "tst_qdeclarativelistview.moc"