diff options
author | Bea Lam <bea.lam@nokia.com> | 2012-01-05 09:59:30 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-01-09 07:14:31 +0100 |
commit | 6b6d99c1a218f1c46ae0151a01575de6092ba9a7 (patch) | |
tree | d68e19b73691d4119f13358b29ca17cbd084c80b /tests | |
parent | 95e720d1b63312e50be3df467973d098c4527b7d (diff) |
Fix positioning issues and change content y repositioning behaviour
Refactor the code for re-positioning the visibleItems.first() in
QSGItemView::applyModelChanges() and fix various positioning issues.
The positioning behaviour for removing items at the start of the view
has changed. This action will no longer cause the content y to move
down; previously the content y would always move down unless another
item was moving backwards to the first visible position. This will make
it easier to implement built-in removal transitions for the views, since
removed items cannot be animated if the content y jumps down past them.
Additionally, moving items from before a GridView should not cause the
top item in the view to move upwards and out of the view.
This also adds additional remove tests and fixes the
tst_QQuickGridView::moved() test which wasn't waiting for the polish
event after setting the content y, which caused some of the tests to
pass even though their test data was wrong.
Change-Id: Idad11a73a18f88208e73a52111ed839458e05f2d
Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp | 197 | ||||
-rw-r--r-- | tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp | 231 |
2 files changed, 411 insertions, 17 deletions
diff --git a/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp b/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp index fa42ddbbf1..fe469b534f 100644 --- a/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp @@ -73,6 +73,8 @@ private slots: void insertBeforeVisible(); void insertBeforeVisible_data(); void removed(); + void removed_more(); + void removed_more_data(); void addOrRemoveBeforeVisible(); void addOrRemoveBeforeVisible_data(); void clear(); @@ -629,6 +631,7 @@ void tst_QQuickGridView::insertBeforeVisible() int firstVisibleIndex = 20; // move to an index where the top item is not visible gridview->setContentY(firstVisibleIndex * 20.0); gridview->setCurrentIndex(firstVisibleIndex); + qApp->processEvents(); QTRY_COMPARE(gridview->currentIndex(), firstVisibleIndex); QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex); @@ -831,6 +834,181 @@ void tst_QQuickGridView::removed() delete canvas; } +void tst_QQuickGridView::removed_more() +{ + QFETCH(qreal, contentY); + QFETCH(int, removeIndex); + QFETCH(int, removeCount); + QFETCH(qreal, itemsOffsetAfterMove); + + QQuickText *name; + QQuickText *number; + QQuickView *canvas = createView(); + canvas->show(); + + TestModel model; + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + ctxt->setContextProperty("testRightToLeft", QVariant(false)); + ctxt->setContextProperty("testTopToBottom", QVariant(false)); + canvas->setSource(testFileUrl("gridview1.qml")); + qApp->processEvents(); + + QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid"); + QTRY_VERIFY(gridview != 0); + QQuickItem *contentItem = gridview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + gridview->setContentY(contentY); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); + + model.removeItems(removeIndex, removeCount); + QTRY_COMPARE(gridview->property("count").toInt(), model.count()); + + // check visibleItems.first() is in correct position + QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0); +// qApp->exec(); + QVERIFY(item0); + QCOMPARE(item0->y(), itemsOffsetAfterMove); + + int firstVisibleIndex = -1; + QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper"); + for (int i=0; i<items.count(); i++) { + if (items[i]->y() >= contentY) { + QDeclarativeExpression e(qmlContext(items[i]), items[i], "index"); + firstVisibleIndex = e.evaluate().toInt(); + break; + } + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // Confirm items positioned correctly and indexes correct + int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); + for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + + QTRY_COMPARE(item->x(), (i%3)*80.0); + QTRY_COMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove); + + name = findItem<QQuickText>(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + number = findItem<QQuickText>(contentItem, "textNumber", i); + QVERIFY(number != 0); + QTRY_COMPARE(number->text(), model.number(i)); + } + + delete canvas; +} + +void tst_QQuickGridView::removed_more_data() +{ + QTest::addColumn<qreal>("contentY"); + QTest::addColumn<int>("removeIndex"); + QTest::addColumn<int>("removeCount"); + QTest::addColumn<qreal>("itemsOffsetAfterMove"); + + QTest::newRow("remove 1, before visible items") + << 120.0 // show 6-23 + << 3 << 1 + << 0.0; + + QTest::newRow("remove multiple, all before visible items") + << 120.0 + << 1 << 3 + << 60.0; // removed top row, slide down by 1 row + + QTest::newRow("remove multiple, all before visible items, remove item 0") + << 120.0 + << 0 << 4 + << 60.0; // removed top row, slide down by 1 row + + + // remove 3,4,5 before the visible pos, first row moves down to just before the visible pos, + // items 6,7 are removed from view, item 8 slides up to original pos of item 6 (120px) + QTest::newRow("remove multiple, mix of items from before and within visible items") + << 120.0 + << 3 << 5 + << 60.0; // adjust for the 1 row removed before the visible + + QTest::newRow("remove multiple, mix of items from before and within visible items, remove item 0") + << 120.0 + << 0 << 8 + << 60.0 * 2; // adjust for the 2 rows removed before the visible + + + QTest::newRow("remove 1, from start of visible, content at start") + << 0.0 + << 0 << 1 + << 0.0; + + QTest::newRow("remove multiple, from start of visible, content at start") + << 0.0 + << 0 << 3 + << 0.0; + + QTest::newRow("remove 1, from start of visible, content not at start") + << 120.0 // show 6-23 + << 4 << 1 + << 0.0; + + QTest::newRow("remove multiple, from start of visible, content not at start") + << 120.0 // show 6-23 + << 4 << 3 + << 0.0; + + + QTest::newRow("remove 1, from middle of visible, content at start") + << 0.0 + << 10 << 1 + << 0.0; + + QTest::newRow("remove multiple, from middle of visible, content at start") + << 0.0 + << 10 << 5 + << 0.0; + + QTest::newRow("remove 1, from middle of visible, content not at start") + << 120.0 // show 6-23 + << 10 << 1 + << 0.0; + + QTest::newRow("remove multiple, from middle of visible, content not at start") + << 120.0 // show 6-23 + << 10 << 5 + << 0.0; + + + QTest::newRow("remove 1, after visible, content at start") + << 0.0 + << 16 << 1 + << 0.0; + + QTest::newRow("remove multiple, after visible, content at start") + << 0.0 + << 16 << 5 + << 0.0; + + QTest::newRow("remove 1, after visible, content not at start") + << 120.0 // show 6-23 + << 16+4 << 1 + << 0.0; + + QTest::newRow("remove multiple, after visible, content not at start") + << 120.0 // show 6-23 + << 16+4 << 5 + << 0.0; + + QTest::newRow("remove multiple, mix of items from within and after visible items") + << 120.0 // show 6-23 + << 20 << 5 + << 0.0; +} + void tst_QQuickGridView::addOrRemoveBeforeVisible() { // QTBUG-21588: ensure re-layout is done on grid after adding or removing @@ -956,6 +1134,11 @@ void tst_QQuickGridView::clear() void tst_QQuickGridView::moved() { + if (QTest::currentDataTag() == QLatin1String("move 1 forwards, from non-visible -> visible") + || QTest::currentDataTag() == QLatin1String("move 1 forwards, from non-visible -> visible (move first item)")) { + QSKIP("QTBUG-23455"); + } + QFETCH(qreal, contentY); QFETCH(int, from); QFETCH(int, to); @@ -989,9 +1172,9 @@ void tst_QQuickGridView::moved() QTRY_VERIFY(currentItem != 0); gridview->setContentY(contentY); - model.moveItems(from, to, count); + QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); - // wait for items to move + model.moveItems(from, to, count); QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false); // Confirm items positioned correctly and indexes correct @@ -1030,20 +1213,26 @@ void tst_QQuickGridView::moved_data() // model starts with 30 items, each 80x60, in area 240x320 // 18 items should be visible at a time + // The first visible item should not move upwards and out of the view + // if items are moved/removed before it. + + QTest::newRow("move 1 forwards, within visible items") << 0.0 << 1 << 8 << 1 << 0.0; + // skipped QTBUG-23455 QTest::newRow("move 1 forwards, from non-visible -> visible") << 120.0 // show 6-23 << 1 << 23 << 1 - << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down + << 0.0; + // skipped QTBUG-23455 QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)") << 120.0 // // show 6-23 << 0 << 6 << 1 - << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down + << 0.0; QTest::newRow("move 1 forwards, from visible -> non-visible") << 0.0 diff --git a/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp b/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp index 7312e4403d..98d4f49245 100644 --- a/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp +++ b/tests/auto/qtquick2/qquicklistview/tst_qquicklistview.cpp @@ -85,8 +85,12 @@ private slots: void qAbstractItemModel_inserted_more_data(); void qListModelInterface_removed(); + void qListModelInterface_removed_more(); + void qListModelInterface_removed_more_data(); void qListModelInterface_package_removed(); void qAbstractItemModel_removed(); + void qAbstractItemModel_removed_more(); + void qAbstractItemModel_removed_more_data(); void qListModelInterface_moved(); void qListModelInterface_moved_data(); @@ -167,6 +171,7 @@ private: template <class T> void inserted(const QUrl &source); template <class T> void inserted_more(); template <class T> void removed(const QUrl &source, bool animated); + template <class T> void removed_more(const QUrl &source); template <class T> void moved(const QUrl &source); template <class T> void clear(const QUrl &source); template <class T> void sections(const QUrl &source); @@ -180,6 +185,7 @@ private: void dumpTree(QQuickItem *parent, int depth = 0); void inserted_more_data(); + void removed_more_data(); void moved_data(); }; @@ -677,7 +683,7 @@ void tst_QQuickListView::inserted(const QUrl &source) QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0); QVERIFY(item); QCOMPARE(item->y(), 0.); - QVERIFY(listview->contentY() == 0); + QTRY_VERIFY(listview->contentY() == 0); delete canvas; delete testObject; @@ -870,6 +876,7 @@ void tst_QQuickListView::insertBeforeVisible() int firstVisibleIndex = 20; // move to an index where the top item is not visible listview->setContentY(firstVisibleIndex * 20.0); listview->setCurrentIndex(firstVisibleIndex); + qApp->processEvents(); QTRY_COMPARE(listview->currentIndex(), firstVisibleIndex); QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", firstVisibleIndex); @@ -971,7 +978,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */) } // Remove first item (which is the current item); - model.removeItem(0); // post: top item starts at 20 + model.removeItem(0); QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count()); name = findItem<QQuickText>(contentItem, "textName", 0); @@ -987,7 +994,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */) QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QTRY_VERIFY(item); - QTRY_COMPARE(item->y(),i*20.0 + 20.0); + QTRY_COMPARE(item->y(),i*20.0); } // Remove items not visible @@ -1000,14 +1007,14 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */) QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QTRY_VERIFY(item); - QTRY_COMPARE(item->y(),i*20.0+20.0); + QTRY_COMPARE(item->y(),i*20.0); } // Remove items before visible listview->setContentY(80); listview->setCurrentIndex(10); - model.removeItem(1); // post: top item will be at 40 + model.removeItem(1); // post: top item will be at 20 QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count()); // Confirm items positioned correctly @@ -1015,7 +1022,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */) QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QTRY_VERIFY(item); - QTRY_COMPARE(item->y(),40+i*20.0); + QTRY_COMPARE(item->y(),20+i*20.0); } // Remove current index @@ -1026,7 +1033,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */) QTRY_COMPARE(listview->currentIndex(), 9); QTRY_VERIFY(listview->currentItem() != oldCurrent); - listview->setContentY(40); // That's the top now + listview->setContentY(20); // That's the top now // let transitions settle. QTest::qWait(300); @@ -1036,7 +1043,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */) QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); if (!item) qWarning() << "Item" << i << "not found"; QTRY_VERIFY(item); - QTRY_COMPARE(item->y(),40+i*20.0); + QTRY_COMPARE(item->y(),20+i*20.0); } // remove current item beyond visible items. @@ -1105,6 +1112,184 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */) } template <class T> +void tst_QQuickListView::removed_more(const QUrl &source) +{ + QFETCH(qreal, contentY); + QFETCH(int, removeIndex); + QFETCH(int, removeCount); + QFETCH(qreal, itemsOffsetAfterMove); + + QQuickText *name; + QQuickText *number; + QQuickView *canvas = createView(); + canvas->show(); + + T model; + for (int i = 0; i < 30; i++) + model.addItem("Item" + QString::number(i), ""); + + QDeclarativeContext *ctxt = canvas->rootContext(); + ctxt->setContextProperty("testModel", &model); + + TestObject *testObject = new TestObject; + ctxt->setContextProperty("testObject", testObject); + + canvas->setSource(source); + qApp->processEvents(); + + QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list"); + QTRY_VERIFY(listview != 0); + QQuickItem *contentItem = listview->contentItem(); + QTRY_VERIFY(contentItem != 0); + + listview->setContentY(contentY); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); + + // wait for refill (after refill, items above the firstVisibleIndex-1 should not be rendered) + int firstVisibleIndex = contentY / 20; + if (firstVisibleIndex - 2 >= 0) + QTRY_VERIFY(!findItem<QQuickText>(contentItem, "textName", firstVisibleIndex - 2)); + + model.removeItems(removeIndex, removeCount); + QTRY_COMPARE(listview->property("count").toInt(), model.count()); + + // check visibleItems.first() is in correct position + QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0); + QVERIFY(item0); + QCOMPARE(item0->y(), itemsOffsetAfterMove); + + QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper"); + for (int i=0; i<items.count(); i++) { + if (items[i]->y() >= contentY) { + QDeclarativeExpression e(qmlContext(items[i]), items[i], "index"); + firstVisibleIndex = e.evaluate().toInt(); + break; + } + } + QVERIFY2(firstVisibleIndex >= 0, QTest::toString(firstVisibleIndex)); + + // Confirm items positioned correctly and indexes correct + int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count(); + for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) { + QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i); + QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i))); + QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove); + name = findItem<QQuickText>(contentItem, "textName", i); + QVERIFY(name != 0); + QTRY_COMPARE(name->text(), model.name(i)); + number = findItem<QQuickText>(contentItem, "textNumber", i); + QVERIFY(number != 0); + QTRY_COMPARE(number->text(), model.number(i)); + } + + delete canvas; + delete testObject; +} + +void tst_QQuickListView::removed_more_data() +{ + QTest::addColumn<qreal>("contentY"); + QTest::addColumn<int>("removeIndex"); + QTest::addColumn<int>("removeCount"); + QTest::addColumn<qreal>("itemsOffsetAfterMove"); + + QTest::newRow("remove 1, before visible items") + << 80.0 // show 4-19 + << 3 << 1 + << 20.0; // visible items slide down by 1 item so that first visible does not move + + QTest::newRow("remove multiple, all before visible items") + << 80.0 + << 1 << 3 + << 20.0 * 3; + + QTest::newRow("remove multiple, all before visible items, remove item 0") + << 80.0 + << 0 << 4 + << 20.0 * 4; + + // remove 1,2,3 before the visible pos, 0 moves down to just before the visible pos, + // items 4,5 are removed from view, item 6 slides up to original pos of item 4 (80px) + QTest::newRow("remove multiple, mix of items from before and within visible items") + << 80.0 + << 1 << 5 + << 20.0 * 3; // adjust for the 3 items removed before the visible + + QTest::newRow("remove multiple, mix of items from before and within visible items, remove item 0") + << 80.0 + << 0 << 6 + << 20.0 * 4; // adjust for the 3 items removed before the visible + + + QTest::newRow("remove 1, from start of visible, content at start") + << 0.0 + << 0 << 1 + << 0.0; + + QTest::newRow("remove multiple, from start of visible, content at start") + << 0.0 + << 0 << 3 + << 0.0; + + QTest::newRow("remove 1, from start of visible, content not at start") + << 80.0 // show 4-19 + << 4 << 1 + << 0.0; + + QTest::newRow("remove multiple, from start of visible, content not at start") + << 80.0 // show 4-19 + << 4 << 3 + << 0.0; + + + QTest::newRow("remove 1, from middle of visible, content at start") + << 0.0 + << 10 << 1 + << 0.0; + + QTest::newRow("remove multiple, from middle of visible, content at start") + << 0.0 + << 10 << 5 + << 0.0; + + QTest::newRow("remove 1, from middle of visible, content not at start") + << 80.0 // show 4-19 + << 10 << 1 + << 0.0; + + QTest::newRow("remove multiple, from middle of visible, content not at start") + << 80.0 // show 4-19 + << 10 << 5 + << 0.0; + + + QTest::newRow("remove 1, after visible, content at start") + << 0.0 + << 16 << 1 + << 0.0; + + QTest::newRow("remove multiple, after visible, content at start") + << 0.0 + << 16 << 5 + << 0.0; + + QTest::newRow("remove 1, after visible, content not at middle") + << 80.0 // show 4-19 + << 16+4 << 1 + << 0.0; + + QTest::newRow("remove multiple, after visible, content not at start") + << 80.0 // show 4-19 + << 16+4 << 5 + << 0.0; + + QTest::newRow("remove multiple, mix of items from within and after visible items") + << 80.0 + << 18 << 5 + << 0.0; +} + +template <class T> void tst_QQuickListView::clear(const QUrl &source) { QQuickView *canvas = createView(); @@ -1182,10 +1367,10 @@ void tst_QQuickListView::moved(const QUrl &source) QTRY_VERIFY(currentItem != 0); listview->setContentY(contentY); - model.moveItems(from, to, count); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); - // wait for items to move - QTest::qWait(100); + model.moveItems(from, to, count); + QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false); QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper"); int firstVisibleIndex = -1; @@ -4210,6 +4395,16 @@ void tst_QQuickListView::qListModelInterface_removed() removed<TestModel>(testFileUrl("listviewtest.qml"), true); } +void tst_QQuickListView::qListModelInterface_removed_more() +{ + removed_more<TestModel>(testFileUrl("listviewtest.qml")); +} + +void tst_QQuickListView::qListModelInterface_removed_more_data() +{ + removed_more_data(); +} + void tst_QQuickListView::qListModelInterface_package_removed() { removed<TestModel>(testFileUrl("listviewtest-package.qml"), false); @@ -4222,6 +4417,16 @@ void tst_QQuickListView::qAbstractItemModel_removed() removed<TestModel2>(testFileUrl("listviewtest.qml"), true); } +void tst_QQuickListView::qAbstractItemModel_removed_more() +{ + removed_more<TestModel2>(testFileUrl("listviewtest.qml")); +} + +void tst_QQuickListView::qAbstractItemModel_removed_more_data() +{ + removed_more_data(); +} + void tst_QQuickListView::qListModelInterface_moved() { moved<TestModel>(testFileUrl("listviewtest.qml")); @@ -4659,9 +4864,9 @@ void tst_QQuickListView::unrequestedVisibility() model.moveItems(17, 16, 1); QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false); - QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5)); + QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4)); QCOMPARE(item->isVisible(), false); - QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 6)); + QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 5)); QCOMPARE(item->isVisible(), true); QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 16)); QCOMPARE(item->isVisible(), true); |