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(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
394 // current item should be first item
395 QTRY_COMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 0));
397 for (int i = 0; i < model.count(); ++i) {
398 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", i);
399 QTRY_VERIFY(name != 0);
400 QTRY_COMPARE(name->text(), model.name(i));
401 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
402 QTRY_VERIFY(number != 0);
403 QTRY_COMPARE(number->text(), model.number(i));
406 // switch to other delegate
407 testObject->setAnimate(true);
408 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
409 QTRY_VERIFY(testObject->error() == false);
410 QTRY_VERIFY(listview->currentItem());
412 // set invalid highlight
413 testObject->setInvalidHighlight(true);
414 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
415 QTRY_VERIFY(testObject->error() == false);
416 QTRY_VERIFY(listview->currentItem());
417 QTRY_VERIFY(listview->highlightItem() == 0);
419 // back to normal highlight
420 testObject->setInvalidHighlight(false);
421 QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
422 QTRY_VERIFY(testObject->error() == false);
423 QTRY_VERIFY(listview->currentItem());
424 QTRY_VERIFY(listview->highlightItem() != 0);
426 // set an empty model and confirm that items are destroyed
428 ctxt->setContextProperty("testModel", &model2);
430 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
431 QTRY_VERIFY(itemCount == 0);
433 QTRY_COMPARE(listview->highlightResizeSpeed(), 1000.0);
434 QTRY_COMPARE(listview->highlightMoveSpeed(), 1000.0);
441 void tst_QDeclarativeListView::changed()
443 QDeclarativeView *canvas = createView();
446 model.addItem("Fred", "12345");
447 model.addItem("John", "2345");
448 model.addItem("Bob", "54321");
450 QDeclarativeContext *ctxt = canvas->rootContext();
451 ctxt->setContextProperty("testModel", &model);
453 TestObject *testObject = new TestObject;
454 ctxt->setContextProperty("testObject", testObject);
456 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
457 qApp->processEvents();
459 QDeclarativeFlickable *listview = findItem<QDeclarativeFlickable>(canvas->rootObject(), "list");
460 QTRY_VERIFY(listview != 0);
462 QDeclarativeItem *contentItem = listview->contentItem();
463 QTRY_VERIFY(contentItem != 0);
465 model.modifyItem(1, "Will", "9876");
466 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
467 QTRY_VERIFY(name != 0);
468 QTRY_COMPARE(name->text(), model.name(1));
469 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
470 QTRY_VERIFY(number != 0);
471 QTRY_COMPARE(number->text(), model.number(1));
477 void tst_QDeclarativeListView::inserted()
479 QDeclarativeView *canvas = createView();
482 model.addItem("Fred", "12345");
483 model.addItem("John", "2345");
484 model.addItem("Bob", "54321");
486 QDeclarativeContext *ctxt = canvas->rootContext();
487 ctxt->setContextProperty("testModel", &model);
489 TestObject *testObject = new TestObject;
490 ctxt->setContextProperty("testObject", testObject);
492 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
493 qApp->processEvents();
495 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
496 QTRY_VERIFY(listview != 0);
498 QDeclarativeItem *contentItem = listview->contentItem();
499 QTRY_VERIFY(contentItem != 0);
501 model.insertItem(1, "Will", "9876");
503 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
505 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
506 QTRY_VERIFY(name != 0);
507 QTRY_COMPARE(name->text(), model.name(1));
508 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
509 QTRY_VERIFY(number != 0);
510 QTRY_COMPARE(number->text(), model.number(1));
512 // Confirm items positioned correctly
513 for (int i = 0; i < model.count(); ++i) {
514 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
515 QTRY_COMPARE(item->y(), i*20.0);
518 model.insertItem(0, "Foo", "1111"); // zero index, and current item
520 QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
522 name = findItem<QDeclarativeText>(contentItem, "textName", 0);
523 QTRY_VERIFY(name != 0);
524 QTRY_COMPARE(name->text(), model.name(0));
525 number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
526 QTRY_VERIFY(number != 0);
527 QTRY_COMPARE(number->text(), model.number(0));
529 QTRY_COMPARE(listview->currentIndex(), 1);
531 // Confirm items positioned correctly
532 for (int i = 0; i < model.count(); ++i) {
533 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
534 QTRY_COMPARE(item->y(), i*20.0);
537 for (int i = model.count(); i < 30; ++i)
538 model.insertItem(i, "Hello", QString::number(i));
540 listview->setContentY(80);
542 // Insert item outside visible area
543 model.insertItem(1, "Hello", "1324");
545 QTRY_VERIFY(listview->contentY() == 80);
547 // Confirm items positioned correctly
548 for (int i = 5; i < 5+15; ++i) {
549 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
550 if (!item) qWarning() << "Item" << i << "not found";
552 QTRY_COMPARE(item->y(), i*20.0 - 20.0);
555 // QTRY_COMPARE(listview->contentItemHeight(), model.count() * 20.0);
561 void tst_QDeclarativeListView::removed(bool animated)
563 QDeclarativeView *canvas = createView();
566 for (int i = 0; i < 50; i++)
567 model.addItem("Item" + QString::number(i), "");
569 QDeclarativeContext *ctxt = canvas->rootContext();
570 ctxt->setContextProperty("testModel", &model);
572 TestObject *testObject = new TestObject;
573 testObject->setAnimate(animated);
574 ctxt->setContextProperty("testObject", testObject);
576 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
577 qApp->processEvents();
579 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
580 QTRY_VERIFY(listview != 0);
582 QDeclarativeItem *contentItem = listview->contentItem();
583 QTRY_VERIFY(contentItem != 0);
587 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
588 QTRY_VERIFY(name != 0);
589 QTRY_COMPARE(name->text(), model.name(1));
590 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
591 QTRY_VERIFY(number != 0);
592 QTRY_COMPARE(number->text(), model.number(1));
594 // Confirm items positioned correctly
595 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
596 for (int i = 0; i < model.count() && i < itemCount; ++i) {
597 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
598 if (!item) qWarning() << "Item" << i << "not found";
600 QTRY_VERIFY(item->y() == i*20);
603 // Remove first item (which is the current item);
604 model.removeItem(0); // post: top item starts at 20
608 name = findItem<QDeclarativeText>(contentItem, "textName", 0);
609 QTRY_VERIFY(name != 0);
610 QTRY_COMPARE(name->text(), model.name(0));
611 number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
612 QTRY_VERIFY(number != 0);
613 QTRY_COMPARE(number->text(), model.number(0));
615 // Confirm items positioned correctly
616 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
617 for (int i = 0; i < model.count() && i < itemCount; ++i) {
618 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
619 if (!item) qWarning() << "Item" << i << "not found";
621 QTRY_COMPARE(item->y(),i*20.0 + 20.0);
624 // Remove items not visible
625 model.removeItem(18);
626 qApp->processEvents();
628 // Confirm items positioned correctly
629 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
630 for (int i = 0; i < model.count() && i < itemCount; ++i) {
631 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
632 if (!item) qWarning() << "Item" << i << "not found";
634 QTRY_COMPARE(item->y(),i*20.0+20.0);
637 // Remove items before visible
638 listview->setContentY(80);
639 listview->setCurrentIndex(10);
641 model.removeItem(1); // post: top item will be at 40
642 qApp->processEvents();
644 // Confirm items positioned correctly
645 for (int i = 2; i < 18; ++i) {
646 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
647 if (!item) qWarning() << "Item" << i << "not found";
649 QTRY_COMPARE(item->y(),40+i*20.0);
652 // Remove current index
653 QTRY_VERIFY(listview->currentIndex() == 9);
654 QDeclarativeItem *oldCurrent = listview->currentItem();
657 QTRY_COMPARE(listview->currentIndex(), 9);
658 QTRY_VERIFY(listview->currentItem() != oldCurrent);
660 listview->setContentY(40); // That's the top now
661 // let transitions settle.
664 // Confirm items positioned correctly
665 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
666 for (int i = 0; i < model.count() && i < itemCount; ++i) {
667 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
668 if (!item) qWarning() << "Item" << i << "not found";
670 QTRY_COMPARE(item->y(),40+i*20.0);
673 // remove current item beyond visible items.
674 listview->setCurrentIndex(20);
675 listview->setContentY(40);
676 model.removeItem(20);
678 QTRY_COMPARE(listview->currentIndex(), 20);
679 QTRY_VERIFY(listview->currentItem() != 0);
681 // remove item before current, but visible
682 listview->setCurrentIndex(8);
683 oldCurrent = listview->currentItem();
686 QTRY_COMPARE(listview->currentIndex(), 7);
687 QTRY_VERIFY(listview->currentItem() == oldCurrent);
689 listview->setContentY(80);
692 // remove all visible items
693 model.removeItems(1, 18);
696 // Confirm items positioned correctly
697 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
698 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
699 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i+2);
700 if (!item) qWarning() << "Item" << i+2 << "not found";
702 QTRY_COMPARE(item->y(),80+i*20.0);
705 model.removeItems(1, 17);
706 // QTest::qWait(300);
708 model.removeItems(2, 1);
709 model.addItem("New", "1");
711 QTRY_VERIFY(name = findItem<QDeclarativeText>(contentItem, "textName", model.count()-1));
712 QCOMPARE(name->text(), QString("New"));
718 void tst_QDeclarativeListView::clear()
720 QDeclarativeView *canvas = createView();
723 for (int i = 0; i < 30; i++)
724 model.addItem("Item" + QString::number(i), "");
726 QDeclarativeContext *ctxt = canvas->rootContext();
727 ctxt->setContextProperty("testModel", &model);
729 TestObject *testObject = new TestObject;
730 ctxt->setContextProperty("testObject", testObject);
732 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
733 qApp->processEvents();
735 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
736 QTRY_VERIFY(listview != 0);
738 QDeclarativeItem *contentItem = listview->contentItem();
739 QTRY_VERIFY(contentItem != 0);
743 QTRY_VERIFY(listview->count() == 0);
744 QTRY_VERIFY(listview->currentItem() == 0);
745 QTRY_VERIFY(listview->contentY() == 0);
746 QVERIFY(listview->currentIndex() == -1);
748 // confirm sanity when adding an item to cleared list
749 model.addItem("New", "1");
750 QTRY_VERIFY(listview->count() == 1);
751 QVERIFY(listview->currentItem() != 0);
752 QVERIFY(listview->currentIndex() == 0);
759 void tst_QDeclarativeListView::moved()
761 QDeclarativeView *canvas = createView();
764 for (int i = 0; i < 30; i++)
765 model.addItem("Item" + QString::number(i), "");
767 QDeclarativeContext *ctxt = canvas->rootContext();
768 ctxt->setContextProperty("testModel", &model);
770 TestObject *testObject = new TestObject;
771 ctxt->setContextProperty("testObject", testObject);
773 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
774 qApp->processEvents();
776 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
777 QTRY_VERIFY(listview != 0);
779 QDeclarativeItem *contentItem = listview->contentItem();
780 QTRY_VERIFY(contentItem != 0);
782 model.moveItem(1, 4);
784 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 1);
785 QTRY_VERIFY(name != 0);
786 QTRY_COMPARE(name->text(), model.name(1));
787 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 1);
788 QTRY_VERIFY(number != 0);
789 QTRY_COMPARE(number->text(), model.number(1));
791 name = findItem<QDeclarativeText>(contentItem, "textName", 4);
792 QTRY_VERIFY(name != 0);
793 QTRY_COMPARE(name->text(), model.name(4));
794 number = findItem<QDeclarativeText>(contentItem, "textNumber", 4);
795 QTRY_VERIFY(number != 0);
796 QTRY_COMPARE(number->text(), model.number(4));
798 // Confirm items positioned correctly
799 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
800 for (int i = 0; i < model.count() && i < itemCount; ++i) {
801 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
802 if (!item) qWarning() << "Item" << i << "not found";
804 QTRY_VERIFY(item->y() == i*20);
807 listview->setContentY(80);
809 // move outside visible area
810 model.moveItem(1, 18);
812 // Confirm items positioned correctly and indexes correct
813 for (int i = 3; i < model.count() && i < itemCount; ++i) {
814 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
815 if (!item) qWarning() << "Item" << i << "not found";
817 QTRY_COMPARE(item->y(), i*20.0 + 20);
818 name = findItem<QDeclarativeText>(contentItem, "textName", i);
819 QTRY_VERIFY(name != 0);
820 QTRY_COMPARE(name->text(), model.name(i));
821 number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
822 QTRY_VERIFY(number != 0);
823 QTRY_COMPARE(number->text(), model.number(i));
826 // move from outside visible into visible
827 model.moveItem(20, 4);
829 // Confirm items positioned correctly and indexes correct
830 for (int i = 3; i < model.count() && i < itemCount; ++i) {
831 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
832 if (!item) qWarning() << "Item" << i << "not found";
834 QTRY_COMPARE(item->y(), i*20.0 + 20);
835 name = findItem<QDeclarativeText>(contentItem, "textName", i);
836 QTRY_VERIFY(name != 0);
837 QTRY_COMPARE(name->text(), model.name(i));
838 number = findItem<QDeclarativeText>(contentItem, "textNumber", i);
839 QTRY_VERIFY(number != 0);
840 QTRY_COMPARE(number->text(), model.number(i));
846 void tst_QDeclarativeListView::enforceRange()
848 QDeclarativeView *canvas = createView();
851 for (int i = 0; i < 30; i++)
852 model.addItem("Item" + QString::number(i), "");
854 QDeclarativeContext *ctxt = canvas->rootContext();
855 ctxt->setContextProperty("testModel", &model);
857 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listview-enforcerange.qml"));
858 qApp->processEvents();
860 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
861 QTRY_VERIFY(listview != 0);
863 QTRY_COMPARE(listview->preferredHighlightBegin(), 100.0);
864 QTRY_COMPARE(listview->preferredHighlightEnd(), 100.0);
865 QTRY_COMPARE(listview->highlightRangeMode(), QDeclarativeListView::StrictlyEnforceRange);
867 QDeclarativeItem *contentItem = listview->contentItem();
868 QTRY_VERIFY(contentItem != 0);
870 // view should be positioned at the top of the range.
871 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 0);
873 QTRY_COMPARE(listview->contentY(), -100.0);
875 QDeclarativeText *name = findItem<QDeclarativeText>(contentItem, "textName", 0);
876 QTRY_VERIFY(name != 0);
877 QTRY_COMPARE(name->text(), model.name(0));
878 QDeclarativeText *number = findItem<QDeclarativeText>(contentItem, "textNumber", 0);
879 QTRY_VERIFY(number != 0);
880 QTRY_COMPARE(number->text(), model.number(0));
882 // Check currentIndex is updated when contentItem moves
883 listview->setContentY(20);
885 QTRY_COMPARE(listview->currentIndex(), 6);
889 for (int i = 0; i < 5; i++)
890 model2.addItem("Item" + QString::number(i), "");
892 ctxt->setContextProperty("testModel", &model2);
893 QCOMPARE(listview->count(), 5);
898 void tst_QDeclarativeListView::spacing()
900 QDeclarativeView *canvas = createView();
903 for (int i = 0; i < 30; i++)
904 model.addItem("Item" + QString::number(i), "");
906 QDeclarativeContext *ctxt = canvas->rootContext();
907 ctxt->setContextProperty("testModel", &model);
909 TestObject *testObject = new TestObject;
910 ctxt->setContextProperty("testObject", testObject);
912 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
913 qApp->processEvents();
915 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
916 QTRY_VERIFY(listview != 0);
918 QDeclarativeItem *contentItem = listview->contentItem();
919 QTRY_VERIFY(contentItem != 0);
921 // Confirm items positioned correctly
922 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
923 for (int i = 0; i < model.count() && i < itemCount; ++i) {
924 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
925 if (!item) qWarning() << "Item" << i << "not found";
927 QTRY_VERIFY(item->y() == i*20);
930 listview->setSpacing(10);
931 QTRY_VERIFY(listview->spacing() == 10);
933 // Confirm items positioned correctly
934 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
935 for (int i = 0; i < model.count() && i < itemCount; ++i) {
936 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
937 if (!item) qWarning() << "Item" << i << "not found";
939 QTRY_VERIFY(item->y() == i*30);
942 listview->setSpacing(0);
944 // Confirm items positioned correctly
945 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
946 for (int i = 0; i < model.count() && i < itemCount; ++i) {
947 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
948 if (!item) qWarning() << "Item" << i << "not found";
950 QTRY_COMPARE(item->y(), i*20.0);
956 void tst_QDeclarativeListView::sections()
958 QDeclarativeView *canvas = createView();
961 for (int i = 0; i < 30; i++)
962 model.addItem("Item" + QString::number(i), QString::number(i/5));
964 QDeclarativeContext *ctxt = canvas->rootContext();
965 ctxt->setContextProperty("testModel", &model);
967 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listview-sections.qml"));
968 qApp->processEvents();
970 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
971 QTRY_VERIFY(listview != 0);
973 QDeclarativeItem *contentItem = listview->contentItem();
974 QTRY_VERIFY(contentItem != 0);
976 // Confirm items positioned correctly
977 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
978 for (int i = 0; i < model.count() && i < itemCount; ++i) {
979 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
981 QTRY_COMPARE(item->y(), qreal(i*20 + ((i+4)/5) * 20));
982 QDeclarativeText *next = findItem<QDeclarativeText>(item, "nextSection");
983 QCOMPARE(next->text().toInt(), (i+1)/5);
986 QSignalSpy currentSectionChangedSpy(listview, SIGNAL(currentSectionChanged()));
988 // Remove section boundary
991 // New section header created
992 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", 5);
994 QTRY_COMPARE(item->height(), 40.0);
996 model.insertItem(3, "New Item", "0");
998 // Section header moved
999 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 5);
1001 QTRY_COMPARE(item->height(), 20.0);
1003 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 6);
1005 QTRY_COMPARE(item->height(), 40.0);
1007 // insert item which will become a section header
1008 model.insertItem(6, "Replace header", "1");
1010 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 6);
1012 QTRY_COMPARE(item->height(), 40.0);
1014 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 7);
1016 QTRY_COMPARE(item->height(), 20.0);
1018 QTRY_COMPARE(listview->currentSection(), QString("0"));
1020 listview->setContentY(140);
1021 QTRY_COMPARE(listview->currentSection(), QString("1"));
1023 QTRY_COMPARE(currentSectionChangedSpy.count(), 1);
1025 listview->setContentY(20);
1026 QTRY_COMPARE(listview->currentSection(), QString("0"));
1028 QTRY_COMPARE(currentSectionChangedSpy.count(), 2);
1030 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 1);
1032 QTRY_COMPARE(item->height(), 20.0);
1034 // check that headers change when item changes
1035 listview->setContentY(0);
1036 model.modifyItem(0, "changed", "2");
1038 item = findItem<QDeclarativeItem>(contentItem, "wrapper", 1);
1040 QTRY_COMPARE(item->height(), 40.0);
1045 void tst_QDeclarativeListView::sectionsDelegate()
1047 QDeclarativeView *canvas = createView();
1050 for (int i = 0; i < 30; i++)
1051 model.addItem("Item" + QString::number(i), QString::number(i/5));
1053 QDeclarativeContext *ctxt = canvas->rootContext();
1054 ctxt->setContextProperty("testModel", &model);
1056 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listview-sections_delegate.qml"));
1057 qApp->processEvents();
1059 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1060 QTRY_VERIFY(listview != 0);
1062 QDeclarativeItem *contentItem = listview->contentItem();
1063 QTRY_VERIFY(contentItem != 0);
1065 // Confirm items positioned correctly
1066 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1067 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1068 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1070 QTRY_COMPARE(item->y(), qreal(i*20 + ((i+5)/5) * 20));
1071 QDeclarativeText *next = findItem<QDeclarativeText>(item, "nextSection");
1072 QCOMPARE(next->text().toInt(), (i+1)/5);
1075 for (int i = 0; i < 3; ++i) {
1076 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "sect_" + QString::number(i));
1078 QTRY_COMPARE(item->y(), qreal(i*20*6));
1081 model.modifyItem(0, "One", "aaa");
1082 model.modifyItem(1, "Two", "aaa");
1083 model.modifyItem(2, "Three", "aaa");
1084 model.modifyItem(3, "Four", "aaa");
1085 model.modifyItem(4, "Five", "aaa");
1087 for (int i = 0; i < 3; ++i) {
1088 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem,
1089 "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
1091 QTRY_COMPARE(item->y(), qreal(i*20*6));
1094 // remove section boundary
1095 model.removeItem(5);
1096 qApp->processEvents();
1097 for (int i = 0; i < 3; ++i) {
1098 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem,
1099 "sect_" + (i == 0 ? QString("aaa") : QString::number(i)));
1104 QList<QDeclarativeItem*> items = findItems<QDeclarativeItem>(contentItem, "sect_1");
1105 QCOMPARE(items.count(), 1);
1108 model.modifyItem(0, "One", "aaa");
1109 model.modifyItem(1, "One", "aaa");
1110 model.modifyItem(2, "One", "aaa");
1111 model.modifyItem(3, "Four", "aaa");
1112 model.modifyItem(4, "Four", "aaa");
1113 model.modifyItem(5, "Four", "aaa");
1114 model.modifyItem(6, "Five", "aaa");
1115 model.modifyItem(7, "Five", "aaa");
1116 model.modifyItem(8, "Five", "aaa");
1117 model.modifyItem(9, "Two", "aaa");
1118 model.modifyItem(10, "Two", "aaa");
1119 model.modifyItem(11, "Two", "aaa");
1120 QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "sect_aaa").count(), 1);
1121 canvas->rootObject()->setProperty("sectionProperty", "name");
1122 // ensure view has settled.
1123 QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "sect_Four").count(), 1);
1124 for (int i = 0; i < 4; ++i) {
1125 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem,
1126 "sect_" + model.name(i*3));
1128 QTRY_COMPARE(item->y(), qreal(i*20*4));
1132 model.removeItems(10, 20);
1133 // ensure view has settled.
1134 QTRY_COMPARE(findItems<QDeclarativeItem>(contentItem, "wrapper").count(), 10);
1135 // Drag view up beyond bounds
1136 QTest::mousePress(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20,20)));
1138 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,0)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1139 QApplication::sendEvent(canvas->viewport(), &mv);
1142 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,-50)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1143 QApplication::sendEvent(canvas->viewport(), &mv);
1146 QMouseEvent mv(QEvent::MouseMove, canvas->mapFromScene(QPoint(20,-200)), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
1147 QApplication::sendEvent(canvas->viewport(), &mv);
1149 QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(20,-200)));
1150 // view should settle back at 0
1151 QTRY_COMPARE(listview->contentY(), 0.0);
1156 void tst_QDeclarativeListView::currentIndex()
1159 for (int i = 0; i < 30; i++)
1160 model.addItem("Item" + QString::number(i), QString::number(i));
1162 QDeclarativeView *canvas = new QDeclarativeView(0);
1163 canvas->setFixedSize(240,320);
1165 QDeclarativeContext *ctxt = canvas->rootContext();
1166 ctxt->setContextProperty("testModel", &model);
1167 ctxt->setContextProperty("testWrap", QVariant(false));
1169 QString filename(SRCDIR "/data/listview-initCurrent.qml");
1170 canvas->setSource(QUrl::fromLocalFile(filename));
1172 qApp->processEvents();
1174 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1175 QTRY_VERIFY(listview != 0);
1177 QDeclarativeItem *contentItem = listview->contentItem();
1178 QTRY_VERIFY(contentItem != 0);
1180 // current item should be 20th item at startup
1181 // and current item should be in view
1182 QCOMPARE(listview->currentIndex(), 20);
1183 QCOMPARE(listview->contentY(), 100.0);
1184 QCOMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 20));
1185 QCOMPARE(listview->highlightItem()->y(), listview->currentItem()->y());
1188 listview->setCurrentIndex(0);
1189 QCOMPARE(listview->currentIndex(), 0);
1190 // confirm that the velocity is updated
1191 QTRY_VERIFY(listview->verticalVelocity() != 0.0);
1193 listview->incrementCurrentIndex();
1194 QCOMPARE(listview->currentIndex(), 1);
1195 listview->decrementCurrentIndex();
1196 QCOMPARE(listview->currentIndex(), 0);
1198 listview->decrementCurrentIndex();
1199 QCOMPARE(listview->currentIndex(), 0);
1202 ctxt->setContextProperty("testWrap", QVariant(true));
1203 QVERIFY(listview->isWrapEnabled());
1205 listview->decrementCurrentIndex();
1206 QCOMPARE(listview->currentIndex(), model.count()-1);
1208 QTRY_COMPARE(listview->contentY(), 280.0);
1210 listview->incrementCurrentIndex();
1211 QCOMPARE(listview->currentIndex(), 0);
1213 QTRY_COMPARE(listview->contentY(), 0.0);
1217 qApp->setActiveWindow(canvas);
1219 // to be safe and avoid failing setFocus with window managers
1220 qt_x11_wait_for_window_manager(canvas);
1222 QTRY_VERIFY(canvas->hasFocus());
1223 QTRY_VERIFY(canvas->scene()->hasFocus());
1224 qApp->processEvents();
1226 QTest::keyClick(canvas, Qt::Key_Down);
1227 QCOMPARE(listview->currentIndex(), 1);
1229 QTest::keyClick(canvas, Qt::Key_Up);
1230 QCOMPARE(listview->currentIndex(), 0);
1232 // turn off auto highlight
1233 listview->setHighlightFollowsCurrentItem(false);
1234 QVERIFY(listview->highlightFollowsCurrentItem() == false);
1236 QVERIFY(listview->highlightItem());
1237 qreal hlPos = listview->highlightItem()->y();
1239 listview->setCurrentIndex(4);
1240 QTRY_COMPARE(listview->highlightItem()->y(), hlPos);
1242 // insert item before currentIndex
1243 listview->setCurrentIndex(28);
1244 model.insertItem(0, "Foo", "1111");
1245 QTRY_COMPARE(canvas->rootObject()->property("current").toInt(), 29);
1247 // check removing highlight by setting currentIndex to -1;
1248 listview->setCurrentIndex(-1);
1250 QCOMPARE(listview->currentIndex(), -1);
1251 QVERIFY(!listview->highlightItem());
1252 QVERIFY(!listview->currentItem());
1257 void tst_QDeclarativeListView::noCurrentIndex()
1260 for (int i = 0; i < 30; i++)
1261 model.addItem("Item" + QString::number(i), QString::number(i));
1263 QDeclarativeView *canvas = new QDeclarativeView(0);
1264 canvas->setFixedSize(240,320);
1266 QDeclarativeContext *ctxt = canvas->rootContext();
1267 ctxt->setContextProperty("testModel", &model);
1269 QString filename(SRCDIR "/data/listview-noCurrent.qml");
1270 canvas->setSource(QUrl::fromLocalFile(filename));
1272 qApp->processEvents();
1274 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1275 QTRY_VERIFY(listview != 0);
1277 QDeclarativeItem *contentItem = listview->contentItem();
1278 QTRY_VERIFY(contentItem != 0);
1280 // current index should be -1 at startup
1281 // and we should not have a currentItem or highlightItem
1282 QCOMPARE(listview->currentIndex(), -1);
1283 QCOMPARE(listview->contentY(), 0.0);
1284 QVERIFY(!listview->highlightItem());
1285 QVERIFY(!listview->currentItem());
1287 listview->setCurrentIndex(2);
1288 QCOMPARE(listview->currentIndex(), 2);
1289 QVERIFY(listview->highlightItem());
1290 QVERIFY(listview->currentItem());
1293 void tst_QDeclarativeListView::itemList()
1295 QDeclarativeView *canvas = createView();
1297 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/itemlist.qml"));
1298 qApp->processEvents();
1300 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "view");
1301 QTRY_VERIFY(listview != 0);
1303 QDeclarativeItem *contentItem = listview->contentItem();
1304 QTRY_VERIFY(contentItem != 0);
1306 QDeclarativeVisualItemModel *model = canvas->rootObject()->findChild<QDeclarativeVisualItemModel*>("itemModel");
1307 QTRY_VERIFY(model != 0);
1309 QTRY_VERIFY(model->count() == 3);
1310 QTRY_COMPARE(listview->currentIndex(), 0);
1312 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "item1");
1314 QTRY_COMPARE(item->x(), 0.0);
1315 QCOMPARE(item->height(), listview->height());
1317 QDeclarativeText *text = findItem<QDeclarativeText>(contentItem, "text1");
1319 QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
1321 listview->setCurrentIndex(2);
1323 item = findItem<QDeclarativeItem>(contentItem, "item3");
1325 QTRY_COMPARE(item->x(), 480.0);
1327 text = findItem<QDeclarativeText>(contentItem, "text3");
1329 QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
1334 void tst_QDeclarativeListView::cacheBuffer()
1336 QDeclarativeView *canvas = createView();
1339 for (int i = 0; i < 30; i++)
1340 model.addItem("Item" + QString::number(i), "");
1342 QDeclarativeContext *ctxt = canvas->rootContext();
1343 ctxt->setContextProperty("testModel", &model);
1345 TestObject *testObject = new TestObject;
1346 ctxt->setContextProperty("testObject", testObject);
1348 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
1349 qApp->processEvents();
1351 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1352 QTRY_VERIFY(listview != 0);
1354 QDeclarativeItem *contentItem = listview->contentItem();
1355 QTRY_VERIFY(contentItem != 0);
1356 QTRY_VERIFY(listview->delegate() != 0);
1357 QTRY_VERIFY(listview->model() != 0);
1358 QTRY_VERIFY(listview->highlight() != 0);
1360 // Confirm items positioned correctly
1361 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1362 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1363 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1364 if (!item) qWarning() << "Item" << i << "not found";
1366 QTRY_VERIFY(item->y() == i*20);
1369 testObject->setCacheBuffer(400);
1370 QTRY_VERIFY(listview->cacheBuffer() == 400);
1372 int newItemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1373 QTRY_VERIFY(newItemCount > itemCount);
1375 // Confirm items positioned correctly
1376 for (int i = 0; i < model.count() && i < newItemCount; ++i) {
1377 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1378 if (!item) qWarning() << "Item" << i << "not found";
1380 QTRY_VERIFY(item->y() == i*20);
1386 void tst_QDeclarativeListView::positionViewAtIndex()
1388 QDeclarativeView *canvas = createView();
1391 for (int i = 0; i < 40; i++)
1392 model.addItem("Item" + QString::number(i), "");
1394 QDeclarativeContext *ctxt = canvas->rootContext();
1395 ctxt->setContextProperty("testModel", &model);
1397 TestObject *testObject = new TestObject;
1398 ctxt->setContextProperty("testObject", testObject);
1400 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
1401 qApp->processEvents();
1403 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1404 QTRY_VERIFY(listview != 0);
1406 QDeclarativeItem *contentItem = listview->contentItem();
1407 QTRY_VERIFY(contentItem != 0);
1409 // Confirm items positioned correctly
1410 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1411 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1412 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1413 if (!item) qWarning() << "Item" << i << "not found";
1415 QTRY_COMPARE(item->y(), i*20.);
1418 // Position on a currently visible item
1419 listview->positionViewAtIndex(3, QDeclarativeListView::Beginning);
1420 QTRY_COMPARE(listview->contentY(), 60.);
1422 // Confirm items positioned correctly
1423 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1424 for (int i = 3; i < model.count() && i < itemCount-3-1; ++i) {
1425 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1426 if (!item) qWarning() << "Item" << i << "not found";
1428 QTRY_COMPARE(item->y(), i*20.);
1431 // Position on an item beyond the visible items
1432 listview->positionViewAtIndex(22, QDeclarativeListView::Beginning);
1433 QTRY_COMPARE(listview->contentY(), 440.);
1435 // Confirm items positioned correctly
1436 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1437 for (int i = 22; i < model.count() && i < itemCount-22-1; ++i) {
1438 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1439 if (!item) qWarning() << "Item" << i << "not found";
1441 QTRY_COMPARE(item->y(), i*20.);
1444 // Position on an item that would leave empty space if positioned at the top
1445 listview->positionViewAtIndex(28, QDeclarativeListView::Beginning);
1446 QTRY_COMPARE(listview->contentY(), 480.);
1448 // Confirm items positioned correctly
1449 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1450 for (int i = 24; i < model.count() && i < itemCount-24-1; ++i) {
1451 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1452 if (!item) qWarning() << "Item" << i << "not found";
1454 QTRY_COMPARE(item->y(), i*20.);
1457 // Position at the beginning again
1458 listview->positionViewAtIndex(0, QDeclarativeListView::Beginning);
1459 QTRY_COMPARE(listview->contentY(), 0.);
1461 // Confirm items positioned correctly
1462 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1463 for (int i = 0; i < model.count() && i < itemCount-1; ++i) {
1464 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1465 if (!item) qWarning() << "Item" << i << "not found";
1467 QTRY_COMPARE(item->y(), i*20.);
1470 // Position at End using last index
1471 listview->positionViewAtIndex(model.count()-1, QDeclarativeListView::End);
1472 QTRY_COMPARE(listview->contentY(), 480.);
1474 // Confirm items positioned correctly
1475 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1476 for (int i = 24; i < model.count(); ++i) {
1477 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1478 if (!item) qWarning() << "Item" << i << "not found";
1480 QTRY_COMPARE(item->y(), i*20.);
1484 listview->positionViewAtIndex(20, QDeclarativeListView::End);
1485 QTRY_COMPARE(listview->contentY(), 100.);
1487 // Position in Center
1488 listview->positionViewAtIndex(15, QDeclarativeListView::Center);
1489 QTRY_COMPARE(listview->contentY(), 150.);
1491 // Ensure at least partially visible
1492 listview->positionViewAtIndex(15, QDeclarativeListView::Visible);
1493 QTRY_COMPARE(listview->contentY(), 150.);
1495 listview->setContentY(302);
1496 listview->positionViewAtIndex(15, QDeclarativeListView::Visible);
1497 QTRY_COMPARE(listview->contentY(), 302.);
1499 listview->setContentY(320);
1500 listview->positionViewAtIndex(15, QDeclarativeListView::Visible);
1501 QTRY_COMPARE(listview->contentY(), 300.);
1503 listview->setContentY(85);
1504 listview->positionViewAtIndex(20, QDeclarativeListView::Visible);
1505 QTRY_COMPARE(listview->contentY(), 85.);
1507 listview->setContentY(75);
1508 listview->positionViewAtIndex(20, QDeclarativeListView::Visible);
1509 QTRY_COMPARE(listview->contentY(), 100.);
1511 // Ensure completely visible
1512 listview->setContentY(120);
1513 listview->positionViewAtIndex(20, QDeclarativeListView::Contain);
1514 QTRY_COMPARE(listview->contentY(), 120.);
1516 listview->setContentY(302);
1517 listview->positionViewAtIndex(15, QDeclarativeListView::Contain);
1518 QTRY_COMPARE(listview->contentY(), 300.);
1520 listview->setContentY(85);
1521 listview->positionViewAtIndex(20, QDeclarativeListView::Contain);
1522 QTRY_COMPARE(listview->contentY(), 100.);
1524 // positionAtBeginnging
1525 listview->positionViewAtBeginning();
1526 QTRY_COMPARE(listview->contentY(), 0.);
1528 listview->setContentY(80);
1529 canvas->rootObject()->setProperty("showHeader", true);
1530 listview->positionViewAtBeginning();
1531 QTRY_COMPARE(listview->contentY(), -30.);
1534 listview->positionViewAtEnd();
1535 QTRY_COMPARE(listview->contentY(), 480.); // 40*20 - 320
1537 listview->setContentY(80);
1538 canvas->rootObject()->setProperty("showFooter", true);
1539 listview->positionViewAtEnd();
1540 QTRY_COMPARE(listview->contentY(), 510.);
1545 void tst_QDeclarativeListView::resetModel()
1547 QDeclarativeView *canvas = createView();
1549 QStringList strings;
1550 strings << "one" << "two" << "three";
1551 QStringListModel model(strings);
1553 QDeclarativeContext *ctxt = canvas->rootContext();
1554 ctxt->setContextProperty("testModel", &model);
1556 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaylist.qml"));
1557 qApp->processEvents();
1559 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1560 QTRY_VERIFY(listview != 0);
1562 QDeclarativeItem *contentItem = listview->contentItem();
1563 QTRY_VERIFY(contentItem != 0);
1565 QTRY_COMPARE(listview->count(), model.rowCount());
1567 for (int i = 0; i < model.rowCount(); ++i) {
1568 QDeclarativeText *display = findItem<QDeclarativeText>(contentItem, "displayText", i);
1569 QTRY_VERIFY(display != 0);
1570 QTRY_COMPARE(display->text(), strings.at(i));
1574 strings << "four" << "five" << "six" << "seven";
1575 model.setStringList(strings);
1577 QTRY_COMPARE(listview->count(), model.rowCount());
1579 for (int i = 0; i < model.rowCount(); ++i) {
1580 QDeclarativeText *display = findItem<QDeclarativeText>(contentItem, "displayText", i);
1581 QTRY_VERIFY(display != 0);
1582 QTRY_COMPARE(display->text(), strings.at(i));
1588 void tst_QDeclarativeListView::propertyChanges()
1590 QDeclarativeView *canvas = createView();
1591 QTRY_VERIFY(canvas);
1592 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1594 QDeclarativeListView *listView = canvas->rootObject()->findChild<QDeclarativeListView*>("listView");
1595 QTRY_VERIFY(listView);
1597 QSignalSpy highlightFollowsCurrentItemSpy(listView, SIGNAL(highlightFollowsCurrentItemChanged()));
1598 QSignalSpy preferredHighlightBeginSpy(listView, SIGNAL(preferredHighlightBeginChanged()));
1599 QSignalSpy preferredHighlightEndSpy(listView, SIGNAL(preferredHighlightEndChanged()));
1600 QSignalSpy highlightRangeModeSpy(listView, SIGNAL(highlightRangeModeChanged()));
1601 QSignalSpy keyNavigationWrapsSpy(listView, SIGNAL(keyNavigationWrapsChanged()));
1602 QSignalSpy cacheBufferSpy(listView, SIGNAL(cacheBufferChanged()));
1603 QSignalSpy snapModeSpy(listView, SIGNAL(snapModeChanged()));
1605 QTRY_COMPARE(listView->highlightFollowsCurrentItem(), true);
1606 QTRY_COMPARE(listView->preferredHighlightBegin(), 0.0);
1607 QTRY_COMPARE(listView->preferredHighlightEnd(), 0.0);
1608 QTRY_COMPARE(listView->highlightRangeMode(), QDeclarativeListView::ApplyRange);
1609 QTRY_COMPARE(listView->isWrapEnabled(), true);
1610 QTRY_COMPARE(listView->cacheBuffer(), 10);
1611 QTRY_COMPARE(listView->snapMode(), QDeclarativeListView::SnapToItem);
1613 listView->setHighlightFollowsCurrentItem(false);
1614 listView->setPreferredHighlightBegin(1.0);
1615 listView->setPreferredHighlightEnd(1.0);
1616 listView->setHighlightRangeMode(QDeclarativeListView::StrictlyEnforceRange);
1617 listView->setWrapEnabled(false);
1618 listView->setCacheBuffer(3);
1619 listView->setSnapMode(QDeclarativeListView::SnapOneItem);
1621 QTRY_COMPARE(listView->highlightFollowsCurrentItem(), false);
1622 QTRY_COMPARE(listView->preferredHighlightBegin(), 1.0);
1623 QTRY_COMPARE(listView->preferredHighlightEnd(), 1.0);
1624 QTRY_COMPARE(listView->highlightRangeMode(), QDeclarativeListView::StrictlyEnforceRange);
1625 QTRY_COMPARE(listView->isWrapEnabled(), false);
1626 QTRY_COMPARE(listView->cacheBuffer(), 3);
1627 QTRY_COMPARE(listView->snapMode(), QDeclarativeListView::SnapOneItem);
1629 QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
1630 QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
1631 QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
1632 QTRY_COMPARE(highlightRangeModeSpy.count(),1);
1633 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1634 QTRY_COMPARE(cacheBufferSpy.count(),1);
1635 QTRY_COMPARE(snapModeSpy.count(),1);
1637 listView->setHighlightFollowsCurrentItem(false);
1638 listView->setPreferredHighlightBegin(1.0);
1639 listView->setPreferredHighlightEnd(1.0);
1640 listView->setHighlightRangeMode(QDeclarativeListView::StrictlyEnforceRange);
1641 listView->setWrapEnabled(false);
1642 listView->setCacheBuffer(3);
1643 listView->setSnapMode(QDeclarativeListView::SnapOneItem);
1645 QTRY_COMPARE(highlightFollowsCurrentItemSpy.count(),1);
1646 QTRY_COMPARE(preferredHighlightBeginSpy.count(),1);
1647 QTRY_COMPARE(preferredHighlightEndSpy.count(),1);
1648 QTRY_COMPARE(highlightRangeModeSpy.count(),1);
1649 QTRY_COMPARE(keyNavigationWrapsSpy.count(),1);
1650 QTRY_COMPARE(cacheBufferSpy.count(),1);
1651 QTRY_COMPARE(snapModeSpy.count(),1);
1656 void tst_QDeclarativeListView::componentChanges()
1658 QDeclarativeView *canvas = createView();
1659 QTRY_VERIFY(canvas);
1660 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1662 QDeclarativeListView *listView = canvas->rootObject()->findChild<QDeclarativeListView*>("listView");
1663 QTRY_VERIFY(listView);
1665 QDeclarativeComponent component(canvas->engine());
1666 component.setData("import QtQuick 1.0; Rectangle { color: \"blue\"; }", QUrl::fromLocalFile(""));
1668 QDeclarativeComponent delegateComponent(canvas->engine());
1669 delegateComponent.setData("import QtQuick 1.0; Text { text: '<b>Name:</b> ' + name }", QUrl::fromLocalFile(""));
1671 QSignalSpy highlightSpy(listView, SIGNAL(highlightChanged()));
1672 QSignalSpy delegateSpy(listView, SIGNAL(delegateChanged()));
1673 QSignalSpy headerSpy(listView, SIGNAL(headerChanged()));
1674 QSignalSpy footerSpy(listView, SIGNAL(footerChanged()));
1676 listView->setHighlight(&component);
1677 listView->setHeader(&component);
1678 listView->setFooter(&component);
1679 listView->setDelegate(&delegateComponent);
1681 QTRY_COMPARE(listView->highlight(), &component);
1682 QTRY_COMPARE(listView->header(), &component);
1683 QTRY_COMPARE(listView->footer(), &component);
1684 QTRY_COMPARE(listView->delegate(), &delegateComponent);
1686 QTRY_COMPARE(highlightSpy.count(),1);
1687 QTRY_COMPARE(delegateSpy.count(),1);
1688 QTRY_COMPARE(headerSpy.count(),1);
1689 QTRY_COMPARE(footerSpy.count(),1);
1691 listView->setHighlight(&component);
1692 listView->setHeader(&component);
1693 listView->setFooter(&component);
1694 listView->setDelegate(&delegateComponent);
1696 QTRY_COMPARE(highlightSpy.count(),1);
1697 QTRY_COMPARE(delegateSpy.count(),1);
1698 QTRY_COMPARE(headerSpy.count(),1);
1699 QTRY_COMPARE(footerSpy.count(),1);
1704 void tst_QDeclarativeListView::modelChanges()
1706 QDeclarativeView *canvas = createView();
1707 QTRY_VERIFY(canvas);
1708 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/propertychangestest.qml"));
1710 QDeclarativeListView *listView = canvas->rootObject()->findChild<QDeclarativeListView*>("listView");
1711 QTRY_VERIFY(listView);
1713 QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
1714 QTRY_VERIFY(alternateModel);
1715 QVariant modelVariant = QVariant::fromValue(alternateModel);
1716 QSignalSpy modelSpy(listView, SIGNAL(modelChanged()));
1718 listView->setModel(modelVariant);
1719 QTRY_COMPARE(listView->model(), modelVariant);
1720 QTRY_COMPARE(modelSpy.count(),1);
1722 listView->setModel(modelVariant);
1723 QTRY_COMPARE(modelSpy.count(),1);
1725 listView->setModel(QVariant());
1726 QTRY_COMPARE(modelSpy.count(),2);
1731 void tst_QDeclarativeListView::QTBUG_9791()
1733 QDeclarativeView *canvas = createView();
1735 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/strictlyenforcerange.qml"));
1736 qApp->processEvents();
1738 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
1739 QTRY_VERIFY(listview != 0);
1741 QDeclarativeItem *contentItem = listview->contentItem();
1742 QTRY_VERIFY(contentItem != 0);
1743 QTRY_VERIFY(listview->delegate() != 0);
1744 QTRY_VERIFY(listview->model() != 0);
1746 QMetaObject::invokeMethod(listview, "fillModel");
1747 qApp->processEvents();
1749 // Confirm items positioned correctly
1750 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1751 QCOMPARE(itemCount, 3);
1753 for (int i = 0; i < itemCount; ++i) {
1754 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1755 if (!item) qWarning() << "Item" << i << "not found";
1757 QTRY_COMPARE(item->x(), i*300.0);
1760 // check that view is positioned correctly
1761 QTRY_COMPARE(listview->contentX(), 590.0);
1766 void tst_QDeclarativeListView::manualHighlight()
1768 QDeclarativeView *canvas = new QDeclarativeView(0);
1769 canvas->setFixedSize(240,320);
1771 QString filename(SRCDIR "/data/manual-highlight.qml");
1772 canvas->setSource(QUrl::fromLocalFile(filename));
1774 qApp->processEvents();
1776 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1777 QTRY_VERIFY(listview != 0);
1779 QDeclarativeItem *contentItem = listview->contentItem();
1780 QTRY_VERIFY(contentItem != 0);
1782 QTRY_COMPARE(listview->currentIndex(), 0);
1783 QTRY_COMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 0));
1784 QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
1786 listview->setCurrentIndex(2);
1788 QTRY_COMPARE(listview->currentIndex(), 2);
1789 QTRY_COMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 2));
1790 QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
1793 listview->positionViewAtIndex(3, QDeclarativeListView::Contain);
1795 QTRY_COMPARE(listview->currentIndex(), 2);
1796 QTRY_COMPARE(listview->currentItem(), findItem<QDeclarativeItem>(contentItem, "wrapper", 2));
1797 QTRY_COMPARE(listview->highlightItem()->y() - 5, listview->currentItem()->y());
1802 void tst_QDeclarativeListView::QTBUG_11105()
1804 QDeclarativeView *canvas = createView();
1807 for (int i = 0; i < 30; i++)
1808 model.addItem("Item" + QString::number(i), "");
1810 QDeclarativeContext *ctxt = canvas->rootContext();
1811 ctxt->setContextProperty("testModel", &model);
1813 TestObject *testObject = new TestObject;
1814 ctxt->setContextProperty("testObject", testObject);
1816 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
1817 qApp->processEvents();
1819 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1820 QTRY_VERIFY(listview != 0);
1822 QDeclarativeItem *contentItem = listview->contentItem();
1823 QTRY_VERIFY(contentItem != 0);
1825 // Confirm items positioned correctly
1826 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1827 for (int i = 0; i < model.count() && i < itemCount; ++i) {
1828 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
1829 if (!item) qWarning() << "Item" << i << "not found";
1831 QTRY_VERIFY(item->y() == i*20);
1834 listview->positionViewAtIndex(20, QDeclarativeListView::Beginning);
1835 QCOMPARE(listview->contentY(), 280.);
1838 for (int i = 0; i < 5; i++)
1839 model2.addItem("Item" + QString::number(i), "");
1841 ctxt->setContextProperty("testModel", &model2);
1843 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
1844 QCOMPARE(itemCount, 5);
1849 void tst_QDeclarativeListView::header()
1852 QDeclarativeView *canvas = createView();
1855 for (int i = 0; i < 30; i++)
1856 model.addItem("Item" + QString::number(i), "");
1858 QDeclarativeContext *ctxt = canvas->rootContext();
1859 ctxt->setContextProperty("testModel", &model);
1861 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header.qml"));
1862 qApp->processEvents();
1864 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1865 QTRY_VERIFY(listview != 0);
1867 QDeclarativeItem *contentItem = listview->contentItem();
1868 QTRY_VERIFY(contentItem != 0);
1870 QDeclarativeText *header = findItem<QDeclarativeText>(contentItem, "header");
1872 QCOMPARE(header->y(), 0.0);
1873 QCOMPARE(header->height(), 20.0);
1875 QCOMPARE(listview->contentY(), 0.0);
1878 QTRY_COMPARE(header->y(), 0.0);
1880 for (int i = 0; i < 30; i++)
1881 model.addItem("Item" + QString::number(i), "");
1883 QMetaObject::invokeMethod(canvas->rootObject(), "changeHeader");
1885 header = findItem<QDeclarativeText>(contentItem, "header");
1887 header = findItem<QDeclarativeText>(contentItem, "header2");
1890 QCOMPARE(header->y(), 10.0);
1891 QCOMPARE(header->height(), 10.0);
1892 QCOMPARE(listview->contentY(), 10.0);
1897 QDeclarativeView *canvas = createView();
1901 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/header1.qml"));
1902 qApp->processEvents();
1904 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1905 QTRY_VERIFY(listview != 0);
1907 QDeclarativeItem *contentItem = listview->contentItem();
1908 QTRY_VERIFY(contentItem != 0);
1910 QDeclarativeText *header = findItem<QDeclarativeText>(contentItem, "header");
1912 QCOMPARE(header->y(), 0.0);
1914 QCOMPARE(listview->contentY(), 0.0);
1917 QTRY_COMPARE(header->y(), 0.0);
1923 void tst_QDeclarativeListView::footer()
1925 QDeclarativeView *canvas = createView();
1928 for (int i = 0; i < 3; i++)
1929 model.addItem("Item" + QString::number(i), "");
1931 QDeclarativeContext *ctxt = canvas->rootContext();
1932 ctxt->setContextProperty("testModel", &model);
1934 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/footer.qml"));
1935 qApp->processEvents();
1937 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
1938 QTRY_VERIFY(listview != 0);
1940 QDeclarativeItem *contentItem = listview->contentItem();
1941 QTRY_VERIFY(contentItem != 0);
1943 QDeclarativeText *footer = findItem<QDeclarativeText>(contentItem, "footer");
1945 QCOMPARE(footer->y(), 60.0);
1946 QCOMPARE(footer->height(), 30.0);
1948 model.removeItem(1);
1949 QTRY_COMPARE(footer->y(), 40.0);
1952 QTRY_COMPARE(footer->y(), 0.0);
1954 for (int i = 0; i < 30; i++)
1955 model.addItem("Item" + QString::number(i), "");
1957 QMetaObject::invokeMethod(canvas->rootObject(), "changeFooter");
1959 footer = findItem<QDeclarativeText>(contentItem, "footer");
1961 footer = findItem<QDeclarativeText>(contentItem, "footer2");
1964 QCOMPARE(footer->y(), 600.0);
1965 QCOMPARE(footer->height(), 20.0);
1966 QCOMPARE(listview->contentY(), 0.0);
1971 class LVAccessor : public QDeclarativeListView
1974 qreal minY() const { return minYExtent(); }
1975 qreal maxY() const { return maxYExtent(); }
1976 qreal minX() const { return minXExtent(); }
1977 qreal maxX() const { return maxXExtent(); }
1980 void tst_QDeclarativeListView::headerFooter()
1984 QDeclarativeView *canvas = createView();
1987 QDeclarativeContext *ctxt = canvas->rootContext();
1988 ctxt->setContextProperty("testModel", &model);
1990 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
1991 qApp->processEvents();
1993 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
1994 QTRY_VERIFY(listview != 0);
1996 QDeclarativeItem *contentItem = listview->contentItem();
1997 QTRY_VERIFY(contentItem != 0);
1999 QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
2001 QCOMPARE(header->y(), 0.0);
2003 QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
2005 QCOMPARE(footer->y(), 20.0);
2007 QVERIFY(static_cast<LVAccessor*>(listview)->minY() == 0);
2008 QVERIFY(static_cast<LVAccessor*>(listview)->maxY() == 0);
2014 QDeclarativeView *canvas = createView();
2017 QDeclarativeContext *ctxt = canvas->rootContext();
2018 ctxt->setContextProperty("testModel", &model);
2020 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
2021 canvas->rootObject()->setProperty("horizontal", true);
2022 qApp->processEvents();
2024 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
2025 QTRY_VERIFY(listview != 0);
2027 QDeclarativeItem *contentItem = listview->contentItem();
2028 QTRY_VERIFY(contentItem != 0);
2030 QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
2032 QCOMPARE(header->x(), 0.0);
2034 QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
2036 QCOMPARE(footer->x(), 20.0);
2038 QVERIFY(static_cast<LVAccessor*>(listview)->minX() == 0);
2039 QVERIFY(static_cast<LVAccessor*>(listview)->maxX() == 0);
2045 QDeclarativeView *canvas = createView();
2048 QDeclarativeContext *ctxt = canvas->rootContext();
2049 ctxt->setContextProperty("testModel", &model);
2051 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/headerfooter.qml"));
2052 canvas->rootObject()->setProperty("horizontal", true);
2053 canvas->rootObject()->setProperty("rtl", true);
2054 qApp->processEvents();
2056 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
2057 QTRY_VERIFY(listview != 0);
2059 QDeclarativeItem *contentItem = listview->contentItem();
2060 QTRY_VERIFY(contentItem != 0);
2062 QDeclarativeItem *header = findItem<QDeclarativeItem>(contentItem, "header");
2064 QCOMPARE(header->x(), -20.0);
2066 QDeclarativeItem *footer = findItem<QDeclarativeItem>(contentItem, "footer");
2068 QCOMPARE(footer->x(), -50.0);
2070 QCOMPARE(static_cast<LVAccessor*>(listview)->minX(), 240.);
2071 QCOMPARE(static_cast<LVAccessor*>(listview)->maxX(), 240.);
2077 void tst_QDeclarativeListView::resizeView()
2079 QDeclarativeView *canvas = createView();
2082 for (int i = 0; i < 40; i++)
2083 model.addItem("Item" + QString::number(i), "");
2085 QDeclarativeContext *ctxt = canvas->rootContext();
2086 ctxt->setContextProperty("testModel", &model);
2088 TestObject *testObject = new TestObject;
2089 ctxt->setContextProperty("testObject", testObject);
2091 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
2092 qApp->processEvents();
2094 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2095 QTRY_VERIFY(listview != 0);
2097 QDeclarativeItem *contentItem = listview->contentItem();
2098 QTRY_VERIFY(contentItem != 0);
2100 // Confirm items positioned correctly
2101 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2102 for (int i = 0; i < model.count() && i < itemCount; ++i) {
2103 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2104 if (!item) qWarning() << "Item" << i << "not found";
2106 QTRY_COMPARE(item->y(), i*20.);
2109 QVariant heightRatio;
2110 QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
2111 QCOMPARE(heightRatio.toReal(), 0.4);
2113 listview->setHeight(200);
2115 QMetaObject::invokeMethod(canvas->rootObject(), "heightRatio", Q_RETURN_ARG(QVariant, heightRatio));
2116 QCOMPARE(heightRatio.toReal(), 0.25);
2121 void tst_QDeclarativeListView::sizeLessThan1()
2123 QDeclarativeView *canvas = createView();
2126 for (int i = 0; i < 30; i++)
2127 model.addItem("Item" + QString::number(i), "");
2129 QDeclarativeContext *ctxt = canvas->rootContext();
2130 ctxt->setContextProperty("testModel", &model);
2132 TestObject *testObject = new TestObject;
2133 ctxt->setContextProperty("testObject", testObject);
2135 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/sizelessthan1.qml"));
2136 qApp->processEvents();
2138 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2139 QTRY_VERIFY(listview != 0);
2141 QDeclarativeItem *contentItem = listview->contentItem();
2142 QTRY_VERIFY(contentItem != 0);
2144 // Confirm items positioned correctly
2145 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2146 for (int i = 0; i < model.count() && i < itemCount; ++i) {
2147 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2148 if (!item) qWarning() << "Item" << i << "not found";
2150 QTRY_COMPARE(item->y(), i*0.5);
2156 void tst_QDeclarativeListView::QTBUG_14821()
2158 QDeclarativeView *canvas = createView();
2160 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/qtbug14821.qml"));
2161 qApp->processEvents();
2163 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
2164 QVERIFY(listview != 0);
2166 QDeclarativeItem *contentItem = listview->contentItem();
2167 QVERIFY(contentItem != 0);
2169 listview->decrementCurrentIndex();
2170 QCOMPARE(listview->currentIndex(), 99);
2172 listview->incrementCurrentIndex();
2173 QCOMPARE(listview->currentIndex(), 0);
2178 void tst_QDeclarativeListView::resizeDelegate()
2180 QDeclarativeView *canvas = createView();
2182 QStringList strings;
2183 for (int i = 0; i < 30; ++i)
2184 strings << QString::number(i);
2185 QStringListModel model(strings);
2187 QDeclarativeContext *ctxt = canvas->rootContext();
2188 ctxt->setContextProperty("testModel", &model);
2190 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaylist.qml"));
2191 qApp->processEvents();
2193 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2194 QTRY_VERIFY(listview != 0);
2196 QDeclarativeItem *contentItem = listview->contentItem();
2197 QTRY_VERIFY(contentItem != 0);
2199 QTRY_COMPARE(listview->count(), model.rowCount());
2201 listview->setCurrentIndex(25);
2202 listview->setContentY(0);
2204 for (int i = 0; i < 16; ++i) {
2205 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2207 QCOMPARE(item->y(), i*20.0);
2210 QCOMPARE(listview->currentItem()->y(), 500.0);
2211 QTRY_COMPARE(listview->highlightItem()->y(), 500.0);
2213 canvas->rootObject()->setProperty("delegateHeight", 30);
2214 qApp->processEvents();
2216 for (int i = 0; i < 11; ++i) {
2217 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2219 QTRY_COMPARE(item->y(), i*30.0);
2222 QTRY_COMPARE(listview->currentItem()->y(), 750.0);
2223 QTRY_COMPARE(listview->highlightItem()->y(), 750.0);
2225 listview->setCurrentIndex(1);
2226 listview->positionViewAtIndex(25, QDeclarativeListView::Beginning);
2227 listview->positionViewAtIndex(5, QDeclarativeListView::Beginning);
2229 for (int i = 5; i < 16; ++i) {
2230 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2232 QCOMPARE(item->y(), i*30.0);
2235 QTRY_COMPARE(listview->currentItem()->y(), 30.0);
2236 QTRY_COMPARE(listview->highlightItem()->y(), 30.0);
2238 canvas->rootObject()->setProperty("delegateHeight", 20);
2239 qApp->processEvents();
2241 for (int i = 5; i < 11; ++i) {
2242 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2244 QTRY_COMPARE(item->y(), 150 + (i-5)*20.0);
2247 QTRY_COMPARE(listview->currentItem()->y(), 70.0);
2248 QTRY_COMPARE(listview->highlightItem()->y(), 70.0);
2253 void tst_QDeclarativeListView::QTBUG_16037()
2255 QDeclarativeView *canvas = createView();
2257 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/qtbug16037.qml"));
2258 qApp->processEvents();
2260 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "listview");
2261 QTRY_VERIFY(listview != 0);
2263 QVERIFY(listview->contentHeight() <= 0.0);
2265 QMetaObject::invokeMethod(canvas->rootObject(), "setModel");
2267 QTRY_COMPARE(listview->contentHeight(), 80.0);
2272 void tst_QDeclarativeListView::indexAt()
2274 QDeclarativeView *canvas = createView();
2277 for (int i = 0; i < 30; i++)
2278 model.addItem("Item" + QString::number(i), "");
2280 QDeclarativeContext *ctxt = canvas->rootContext();
2281 ctxt->setContextProperty("testModel", &model);
2283 TestObject *testObject = new TestObject;
2284 ctxt->setContextProperty("testObject", testObject);
2286 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
2287 qApp->processEvents();
2289 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2290 QTRY_VERIFY(listview != 0);
2292 QDeclarativeItem *contentItem = listview->contentItem();
2293 QTRY_VERIFY(contentItem != 0);
2295 QCOMPARE(listview->indexAt(0,0), 0);
2296 QCOMPARE(listview->indexAt(0,19), 0);
2297 QCOMPARE(listview->indexAt(239,19), 0);
2298 QCOMPARE(listview->indexAt(0,20), 1);
2299 QCOMPARE(listview->indexAt(240,20), -1);
2304 void tst_QDeclarativeListView::incrementalModel()
2306 QDeclarativeView *canvas = createView();
2308 IncrementalModel model;
2309 QDeclarativeContext *ctxt = canvas->rootContext();
2310 ctxt->setContextProperty("testModel", &model);
2312 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/displaylist.qml"));
2313 qApp->processEvents();
2315 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2316 QTRY_VERIFY(listview != 0);
2318 QDeclarativeItem *contentItem = listview->contentItem();
2319 QTRY_VERIFY(contentItem != 0);
2321 QTRY_COMPARE(listview->count(), 20);
2323 listview->positionViewAtIndex(10, QDeclarativeListView::Beginning);
2325 QTRY_COMPARE(listview->count(), 25);
2330 void tst_QDeclarativeListView::onAdd()
2332 QFETCH(int, initialItemCount);
2333 QFETCH(int, itemsToAdd);
2335 const int delegateHeight = 10;
2338 // these initial items should not trigger ListView.onAdd
2339 for (int i=0; i<initialItemCount; i++)
2340 model.addItem("dummy value", "dummy value");
2342 QDeclarativeView *canvas = createView();
2343 canvas->setFixedSize(200, delegateHeight * (initialItemCount + itemsToAdd));
2344 QDeclarativeContext *ctxt = canvas->rootContext();
2345 ctxt->setContextProperty("testModel", &model);
2346 ctxt->setContextProperty("delegateHeight", delegateHeight);
2347 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
2349 QObject *object = canvas->rootObject();
2350 object->setProperty("width", canvas->width());
2351 object->setProperty("height", canvas->height());
2352 qApp->processEvents();
2354 QList<QPair<QString, QString> > items;
2355 for (int i=0; i<itemsToAdd; i++)
2356 items << qMakePair(QString("value %1").arg(i), QString::number(i));
2357 model.addItems(items);
2359 qApp->processEvents();
2361 QVariantList result = object->property("addedDelegates").toList();
2362 QCOMPARE(result.count(), items.count());
2363 for (int i=0; i<items.count(); i++)
2364 QCOMPARE(result[i].toString(), items[i].first);
2369 void tst_QDeclarativeListView::onAdd_data()
2371 QTest::addColumn<int>("initialItemCount");
2372 QTest::addColumn<int>("itemsToAdd");
2374 QTest::newRow("0, add 1") << 0 << 1;
2375 QTest::newRow("0, add 2") << 0 << 2;
2376 QTest::newRow("0, add 10") << 0 << 10;
2378 QTest::newRow("1, add 1") << 1 << 1;
2379 QTest::newRow("1, add 2") << 1 << 2;
2380 QTest::newRow("1, add 10") << 1 << 10;
2382 QTest::newRow("5, add 1") << 5 << 1;
2383 QTest::newRow("5, add 2") << 5 << 2;
2384 QTest::newRow("5, add 10") << 5 << 10;
2387 void tst_QDeclarativeListView::onRemove()
2389 QFETCH(int, initialItemCount);
2390 QFETCH(int, indexToRemove);
2391 QFETCH(int, removeCount);
2393 const int delegateHeight = 10;
2395 for (int i=0; i<initialItemCount; i++)
2396 model.addItem(QString("value %1").arg(i), "dummy value");
2398 QDeclarativeView *canvas = createView();
2399 QDeclarativeContext *ctxt = canvas->rootContext();
2400 ctxt->setContextProperty("testModel", &model);
2401 ctxt->setContextProperty("delegateHeight", delegateHeight);
2402 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
2403 QObject *object = canvas->rootObject();
2405 qApp->processEvents();
2407 model.removeItems(indexToRemove, removeCount);
2408 qApp->processEvents();
2409 QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
2414 void tst_QDeclarativeListView::onRemove_data()
2416 QTest::addColumn<int>("initialItemCount");
2417 QTest::addColumn<int>("indexToRemove");
2418 QTest::addColumn<int>("removeCount");
2420 QTest::newRow("remove first") << 1 << 0 << 1;
2421 QTest::newRow("two items, remove first") << 2 << 0 << 1;
2422 QTest::newRow("two items, remove last") << 2 << 1 << 1;
2423 QTest::newRow("two items, remove all") << 2 << 0 << 2;
2425 QTest::newRow("four items, remove first") << 4 << 0 << 1;
2426 QTest::newRow("four items, remove 0-2") << 4 << 0 << 2;
2427 QTest::newRow("four items, remove 1-3") << 4 << 1 << 2;
2428 QTest::newRow("four items, remove 2-4") << 4 << 2 << 2;
2429 QTest::newRow("four items, remove last") << 4 << 3 << 1;
2430 QTest::newRow("four items, remove all") << 4 << 0 << 4;
2432 QTest::newRow("ten items, remove 1-8") << 10 << 0 << 8;
2433 QTest::newRow("ten items, remove 2-7") << 10 << 2 << 5;
2434 QTest::newRow("ten items, remove 4-10") << 10 << 4 << 6;
2437 void tst_QDeclarativeListView::testQtQuick11Attributes()
2439 QFETCH(QString, code);
2440 QFETCH(QString, warning);
2441 QFETCH(QString, error);
2443 QDeclarativeEngine engine;
2446 QDeclarativeComponent valid(&engine);
2447 valid.setData("import QtQuick 1.1; ListView { " + code.toUtf8() + " }", QUrl(""));
2448 obj = valid.create();
2450 QVERIFY(valid.errorString().isEmpty());
2453 QDeclarativeComponent invalid(&engine);
2454 invalid.setData("import QtQuick 1.0; ListView { " + code.toUtf8() + " }", QUrl(""));
2455 QTest::ignoreMessage(QtWarningMsg, warning.toUtf8());
2456 obj = invalid.create();
2457 QCOMPARE(invalid.errorString(), error);
2461 void tst_QDeclarativeListView::testQtQuick11Attributes_data()
2463 QTest::addColumn<QString>("code");
2464 QTest::addColumn<QString>("warning");
2465 QTest::addColumn<QString>("error");
2467 QTest::newRow("positionViewAtBeginning") << "Component.onCompleted: positionViewAtBeginning()"
2468 << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtBeginning"
2471 QTest::newRow("positionViewAtEnd") << "Component.onCompleted: positionViewAtEnd()"
2472 << "<Unknown File>:1: ReferenceError: Can't find variable: positionViewAtEnd"
2476 void tst_QDeclarativeListView::rightToLeft()
2478 QDeclarativeView *canvas = createView();
2479 canvas->setFixedSize(640,320);
2480 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
2481 qApp->processEvents();
2483 QVERIFY(canvas->rootObject() != 0);
2484 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "view");
2485 QTRY_VERIFY(listview != 0);
2487 QDeclarativeItem *contentItem = listview->contentItem();
2488 QTRY_VERIFY(contentItem != 0);
2490 QDeclarativeVisualItemModel *model = canvas->rootObject()->findChild<QDeclarativeVisualItemModel*>("itemModel");
2491 QTRY_VERIFY(model != 0);
2493 QTRY_VERIFY(model->count() == 3);
2494 QTRY_COMPARE(listview->currentIndex(), 0);
2496 // initial position at first item, right edge aligned
2497 QCOMPARE(listview->contentX(), -640.);
2499 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "item1");
2501 QTRY_COMPARE(item->x(), -100.0);
2502 QCOMPARE(item->height(), listview->height());
2504 QDeclarativeText *text = findItem<QDeclarativeText>(contentItem, "text1");
2506 QTRY_COMPARE(text->text(), QLatin1String("index: 0"));
2508 listview->setCurrentIndex(2);
2510 item = findItem<QDeclarativeItem>(contentItem, "item3");
2512 QTRY_COMPARE(item->x(), -540.0);
2514 text = findItem<QDeclarativeText>(contentItem, "text3");
2516 QTRY_COMPARE(text->text(), QLatin1String("index: 2"));
2518 QCOMPARE(listview->contentX(), -640.);
2520 // Ensure resizing maintains position relative to right edge
2521 qobject_cast<QDeclarativeItem*>(canvas->rootObject())->setWidth(600);
2522 QTRY_COMPARE(listview->contentX(), -600.);
2527 void tst_QDeclarativeListView::test_mirroring()
2529 QDeclarativeView *canvasA = createView();
2530 canvasA->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
2531 QDeclarativeListView *listviewA = findItem<QDeclarativeListView>(canvasA->rootObject(), "view");
2532 QTRY_VERIFY(listviewA != 0);
2534 QDeclarativeView *canvasB = createView();
2535 canvasB->setSource(QUrl::fromLocalFile(SRCDIR "/data/rightToLeft.qml"));
2536 QDeclarativeListView *listviewB = findItem<QDeclarativeListView>(canvasB->rootObject(), "view");
2537 QTRY_VERIFY(listviewA != 0);
2538 qApp->processEvents();
2540 QList<QString> objectNames;
2541 objectNames << "item1" << "item2"; // << "item3"
2543 listviewA->setProperty("layoutDirection", Qt::LeftToRight);
2544 listviewB->setProperty("layoutDirection", Qt::RightToLeft);
2545 QCOMPARE(listviewA->layoutDirection(), listviewA->effectiveLayoutDirection());
2548 foreach(const QString objectName, objectNames)
2549 QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x());
2551 listviewA->setProperty("layoutDirection", Qt::LeftToRight);
2552 listviewB->setProperty("layoutDirection", Qt::LeftToRight);
2555 foreach(const QString objectName, objectNames)
2556 QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x());
2558 QVERIFY(listviewB->layoutDirection() == listviewB->effectiveLayoutDirection());
2559 QDeclarativeItemPrivate::get(listviewB)->setLayoutMirror(true);
2560 QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection());
2562 // LTR != LTR+mirror
2563 foreach(const QString objectName, objectNames)
2564 QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x());
2566 listviewA->setProperty("layoutDirection", Qt::RightToLeft);
2568 // RTL == LTR+mirror
2569 foreach(const QString objectName, objectNames)
2570 QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x());
2572 listviewB->setProperty("layoutDirection", Qt::RightToLeft);
2574 // RTL != RTL+mirror
2575 foreach(const QString objectName, objectNames)
2576 QVERIFY(findItem<QDeclarativeItem>(listviewA, objectName)->x() != findItem<QDeclarativeItem>(listviewB, objectName)->x());
2578 listviewA->setProperty("layoutDirection", Qt::LeftToRight);
2580 // LTR == RTL+mirror
2581 foreach(const QString objectName, objectNames)
2582 QCOMPARE(findItem<QDeclarativeItem>(listviewA, objectName)->x(), findItem<QDeclarativeItem>(listviewB, objectName)->x());
2588 void tst_QDeclarativeListView::orientationChange()
2590 QDeclarativeView *canvas = createView();
2592 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/orientchange.qml"));
2593 qApp->processEvents();
2595 QDeclarativeListView *listview = qobject_cast<QDeclarativeListView*>(canvas->rootObject());
2596 QVERIFY(listview != 0);
2598 QDeclarativeItem *contentItem = listview->contentItem();
2599 QVERIFY(contentItem != 0);
2601 listview->positionViewAtIndex(50, QDeclarativeListView::Beginning);
2603 // Confirm items positioned correctly
2604 for (int i = 50; i < 54; ++i) {
2605 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2607 QCOMPARE(item->y(), i*80.0);
2610 listview->setOrientation(QDeclarativeListView::Horizontal);
2611 QCOMPARE(listview->contentY(), 0.);
2613 // Confirm items positioned correctly
2614 for (int i = 0; i < 3; ++i) {
2615 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2617 QCOMPARE(item->x(), i*80.0);
2620 listview->positionViewAtIndex(50, QDeclarativeListView::Beginning);
2621 listview->setOrientation(QDeclarativeListView::Vertical);
2622 QCOMPARE(listview->contentX(), 0.);
2624 // Confirm items positioned correctly
2625 for (int i = 0; i < 4; ++i) {
2626 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2628 QCOMPARE(item->y(), i*80.0);
2634 void tst_QDeclarativeListView::contentPosJump()
2636 QDeclarativeView *canvas = createView();
2639 for (int i = 0; i < 50; i++)
2640 model.addItem("Item" + QString::number(i), "");
2642 QDeclarativeContext *ctxt = canvas->rootContext();
2643 ctxt->setContextProperty("testModel", &model);
2645 TestObject *testObject = new TestObject;
2646 ctxt->setContextProperty("testObject", testObject);
2648 canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
2649 qApp->processEvents();
2651 QDeclarativeListView *listview = findItem<QDeclarativeListView>(canvas->rootObject(), "list");
2652 QTRY_VERIFY(listview != 0);
2654 QDeclarativeItem *contentItem = listview->contentItem();
2655 QTRY_VERIFY(contentItem != 0);
2657 // Confirm items positioned correctly
2658 int itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2659 for (int i = 0; i < model.count() && i < itemCount; ++i) {
2660 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2661 if (!item) qWarning() << "Item" << i << "not found";
2663 QTRY_VERIFY(item->y() == i*20);
2666 // Test jumping more than a page of items.
2667 listview->setContentY(500);
2668 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2669 for (int i = 25; i < model.count() && i < itemCount; ++i) {
2670 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2671 if (!item) qWarning() << "Item" << i << "not found";
2673 QTRY_VERIFY(item->y() == i*20);
2676 listview->setContentY(-100);
2677 itemCount = findItems<QDeclarativeItem>(contentItem, "wrapper").count();
2678 QVERIFY(itemCount < 20);
2679 for (int i = 0; i < model.count() && i < itemCount; ++i) {
2680 QDeclarativeItem *item = findItem<QDeclarativeItem>(contentItem, "wrapper", i);
2681 if (!item) qWarning() << "Item" << i << "not found";
2683 QTRY_VERIFY(item->y() == i*20);
2689 void tst_QDeclarativeListView::qListModelInterface_items()
2694 void tst_QDeclarativeListView::qAbstractItemModel_items()
2696 items<TestModel2>();
2699 void tst_QDeclarativeListView::qListModelInterface_changed()
2701 changed<TestModel>();
2704 void tst_QDeclarativeListView::qAbstractItemModel_changed()
2706 changed<TestModel2>();
2709 void tst_QDeclarativeListView::qListModelInterface_inserted()
2711 inserted<TestModel>();
2714 void tst_QDeclarativeListView::qAbstractItemModel_inserted()
2716 inserted<TestModel2>();
2719 void tst_QDeclarativeListView::qListModelInterface_removed()
2721 removed<TestModel>(false);
2722 removed<TestModel>(true);
2725 void tst_QDeclarativeListView::qAbstractItemModel_removed()
2727 removed<TestModel2>(false);
2728 removed<TestModel2>(true);
2731 void tst_QDeclarativeListView::qListModelInterface_moved()
2736 void tst_QDeclarativeListView::qAbstractItemModel_moved()
2738 moved<TestModel2>();
2741 void tst_QDeclarativeListView::qListModelInterface_clear()
2746 void tst_QDeclarativeListView::qAbstractItemModel_clear()
2748 clear<TestModel2>();
2751 QDeclarativeView *tst_QDeclarativeListView::createView()
2753 QDeclarativeView *canvas = new QDeclarativeView(0);
2754 canvas->setFixedSize(240,320);
2760 Find an item with the specified objectName. If index is supplied then the
2761 item must also evaluate the {index} expression equal to index
2763 template<typename T>
2764 T *tst_QDeclarativeListView::findItem(QGraphicsObject *parent, const QString &objectName, int index)
2766 const QMetaObject &mo = T::staticMetaObject;
2767 //qDebug() << parent->childItems().count() << "children";
2768 for (int i = 0; i < parent->childItems().count(); ++i) {
2769 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
2772 //qDebug() << "try" << item;
2773 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName)) {
2775 QDeclarativeExpression e(qmlContext(item), item, "index");
2776 if (e.evaluate().toInt() == index)
2777 return static_cast<T*>(item);
2779 return static_cast<T*>(item);
2782 item = findItem<T>(item, objectName, index);
2784 return static_cast<T*>(item);
2790 template<typename T>
2791 QList<T*> tst_QDeclarativeListView::findItems(QGraphicsObject *parent, const QString &objectName)
2794 const QMetaObject &mo = T::staticMetaObject;
2795 //qDebug() << parent->childItems().count() << "children";
2796 for (int i = 0; i < parent->childItems().count(); ++i) {
2797 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
2798 if(!item || !item->isVisible())
2800 //qDebug() << "try" << item;
2801 if (mo.cast(item) && (objectName.isEmpty() || item->objectName() == objectName))
2802 items.append(static_cast<T*>(item));
2803 items += findItems<T>(item, objectName);
2809 void tst_QDeclarativeListView::dumpTree(QDeclarativeItem *parent, int depth)
2811 static QString padding(" ");
2812 for (int i = 0; i < parent->childItems().count(); ++i) {
2813 QDeclarativeItem *item = qobject_cast<QDeclarativeItem*>(parent->childItems().at(i));
2816 qDebug() << padding.left(depth*2) << item;
2817 dumpTree(item, depth+1);
2822 QTEST_MAIN(tst_QDeclarativeListView)
2824 #include "tst_qdeclarativelistview.moc"