aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquicklistview
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick/qquicklistview')
-rw-r--r--tests/auto/quick/qquicklistview/BLACKLIST4
-rw-r--r--tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml46
-rw-r--r--tests/auto/quick/qquicklistview/data/listview-initCurrent.qml3
-rw-r--r--tests/auto/quick/qquicklistview/data/objectmodel.qml24
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug48044.qml144
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug48870.qml24
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug50097.qml47
-rw-r--r--tests/auto/quick/qquicklistview/data/qtbug50105.qml130
-rw-r--r--tests/auto/quick/qquicklistview/data/snapOneItemCurrentIndexRemoveAnimation.qml39
-rw-r--r--tests/auto/quick/qquicklistview/data/snapOneItemResize.qml16
-rw-r--r--tests/auto/quick/qquicklistview/tst_qquicklistview.cpp529
11 files changed, 944 insertions, 62 deletions
diff --git a/tests/auto/quick/qquicklistview/BLACKLIST b/tests/auto/quick/qquicklistview/BLACKLIST
new file mode 100644
index 0000000000..269696ce8c
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/BLACKLIST
@@ -0,0 +1,4 @@
+[QTBUG_38209]
+*
+[enforceRange_withoutHighlight]
+osx
diff --git a/tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml b/tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml
new file mode 100644
index 0000000000..06011519b2
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/contentHeightWithDelayRemove.qml
@@ -0,0 +1,46 @@
+import QtQuick 2.1
+
+Item {
+ width: 400
+ height: 600
+ function takeOne()
+ {
+ listView.model.remove(2)
+ }
+ function takeThree()
+ {
+ listView.model.remove(4)
+ listView.model.remove(2)
+ listView.model.remove(0)
+ }
+ function takeAll()
+ {
+ listView.model.clear()
+ }
+
+ ListView {
+ id: listView
+
+ property bool useDelayRemove
+
+ height: parent.height
+ width: 400
+ model: ListModel {
+ ListElement { name: "A" }
+ ListElement { name: "B" }
+ ListElement { name: "C" }
+ ListElement { name: "D" }
+ ListElement { name: "E" }
+ }
+ delegate: Text {
+ id: wrapper
+ height: 100
+ text: index + listView.count
+ ListView.delayRemove: listView.useDelayRemove
+ ListView.onRemove: SequentialAnimation {
+ PauseAnimation { duration: wrapper.ListView.delayRemove ? 100 : 0 }
+ PropertyAction { target: wrapper; property: "ListView.delayRemove"; value: false }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/listview-initCurrent.qml b/tests/auto/quick/qquicklistview/data/listview-initCurrent.qml
index a02b66b8af..8aff649a67 100644
--- a/tests/auto/quick/qquicklistview/data/listview-initCurrent.qml
+++ b/tests/auto/quick/qquicklistview/data/listview-initCurrent.qml
@@ -6,6 +6,7 @@ Rectangle {
property int current: list.currentIndex
property bool showHeader: false
property bool showFooter: false
+ property int currentItemChangedCount: 0
width: 240
height: 320
@@ -60,5 +61,7 @@ Rectangle {
model: testModel
header: root.showHeader ? headerFooter : null
footer: root.showFooter ? headerFooter : null
+
+ onCurrentItemChanged: { root.currentItemChangedCount++ }
}
}
diff --git a/tests/auto/quick/qquicklistview/data/objectmodel.qml b/tests/auto/quick/qquicklistview/data/objectmodel.qml
new file mode 100644
index 0000000000..5c23d64cd3
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/objectmodel.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.0
+import QtQml.Models 2.1
+
+ListView {
+ width: 360
+ height: 360
+ model: ObjectModel {
+ Rectangle {
+ width: 20
+ height: 20
+ color: "red"
+ }
+ Rectangle {
+ width: 20
+ height: 20
+ color: "green"
+ }
+ Rectangle {
+ width: 20
+ height: 20
+ color: "blue"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/qtbug48044.qml b/tests/auto/quick/qquicklistview/data/qtbug48044.qml
new file mode 100644
index 0000000000..d318643c1c
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/qtbug48044.qml
@@ -0,0 +1,144 @@
+import QtQuick 2.0
+
+Item {
+ width: 200
+ height: 442
+
+ ListModel {
+ id: listModel
+ ListElement {
+ name: "h1"
+ txt: "Header 1"
+ header: true
+ collapsed: true
+ }
+ ListElement {
+ name: "h2"
+ txt: "Header 2"
+ header: true
+ collapsed: true
+ }
+ ListElement {
+ name: "h3"
+ txt: "Header 3"
+ header: true
+ collapsed: true
+ }
+
+ function indexFromName(name) {
+ for (var i = 0; i < count; i++)
+ if (get(i).name === name)
+ return i
+
+ console.warn("Did not find index for name " + name)
+ return -1
+ }
+ }
+
+ function populateModel(prefix, index, n) {
+ for (var k = 1; k <= n; k++) {
+ var name = prefix + k
+ var data = {
+ "collapsed": false,
+ "name": name,
+ "txt": name,
+ "header": false
+ }
+ listModel.insert(index + k, data)
+ }
+ }
+
+ function h2(open) {
+ var i = listModel.indexFromName("h2")
+ if (listModel.get(i).collapsed === !open)
+ return
+
+ listModel.setProperty(i, "collapsed", !open)
+
+ var n = 15
+ if (open) {
+ h3(false)
+ populateModel("c2_", listModel.indexFromName("h2"), n)
+ } else {
+ listModel.remove(i + 1, n)
+ }
+
+ }
+
+ function h3(open) {
+ var i = listModel.indexFromName("h3")
+ if (listModel.get(i).collapsed === !open)
+ return
+
+ listModel.setProperty(i, "collapsed", !open)
+
+ var n = 6
+ if (open) {
+ h2(false)
+ populateModel("c3_", listModel.indexFromName("h3"), n)
+ } else {
+ listModel.remove(i + 1, n)
+ }
+ }
+
+ ListView {
+ id: listView
+ width: parent.width
+ height: parent.height
+ cacheBuffer: 0
+ model: listModel
+
+ property bool transitionsDone: false
+ property int runningTransitions: 0
+ onRunningTransitionsChanged: {
+ if (runningTransitions === 0)
+ transitionsDone = true
+ }
+
+ displaced: Transition {
+ id: dispTrans
+ SequentialAnimation {
+ ScriptAction {
+ script: listView.runningTransitions++
+ }
+ NumberAnimation {
+ property: "y";
+ duration: 250
+ }
+ ScriptAction {
+ script: listView.runningTransitions--
+ }
+ }
+ }
+
+ delegate: Rectangle {
+ id: rect
+ color: header ? "yellow" : "cyan"
+ border.color: "black"
+ height: 50
+ width: parent.width
+
+ Text {
+ anchors.centerIn: parent
+ font.pixelSize: 20
+ text: txt
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ onClicked: {
+ listView.currentIndex = index
+ var i = listModel.indexFromName("h3")
+ if (i === -1)
+ return;
+ var isCollapsed = listModel.get(i).collapsed
+ if (name === "h2")
+ h2(isCollapsed)
+ else if (name === "h3")
+ h3(isCollapsed)
+ }
+ }
+ }
+ }
+}
+
diff --git a/tests/auto/quick/qquicklistview/data/qtbug48870.qml b/tests/auto/quick/qquicklistview/data/qtbug48870.qml
new file mode 100644
index 0000000000..217f58af48
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/qtbug48870.qml
@@ -0,0 +1,24 @@
+import QtQuick 2.6
+
+Rectangle {
+ width: 500
+ height: 500
+ color: "blue"
+
+ ListView {
+ objectName: "list"
+ anchors.fill: parent
+ model: testModel
+
+ delegate: Rectangle {
+ height: 50
+ width: ListView.view ? ListView.view.width : height
+ color: "green"
+
+ Text {
+ anchors.centerIn: parent
+ text: "Item " + index
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/qtbug50097.qml b/tests/auto/quick/qquicklistview/data/qtbug50097.qml
new file mode 100644
index 0000000000..24d506b804
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/qtbug50097.qml
@@ -0,0 +1,47 @@
+import QtQuick 2.6
+
+ListView {
+ id: lv
+
+ // How many rows per page
+ property int pageSize: 5
+
+ // The current page number
+ property int currentPage: 1
+
+ // How large a single item is
+ property int itemSize: 100
+
+ // Arbitrary
+ property int totalPages: 5
+
+ height: itemSize * pageSize // display one full page at a time
+ width: 500 // arbitrary.
+ model: pageSize * totalPages
+ delegate: Text {
+ height: itemSize
+ text: "Item " + (index + 1) + " of " + lv.count
+ }
+
+ // contentY should be < 0 to account for header visibility
+ onContentYChanged: console.log(contentY)
+
+ headerPositioning: ListView.OverlayHeader
+ header: Rectangle {
+ height: itemSize
+ width: 500
+ z: 1000
+ visible: false
+ color: "black"
+
+ Text {
+ anchors.centerIn: parent
+ color: "red"
+ text: "List header"
+ }
+ }
+
+ onCurrentPageChanged: {
+ lv.positionViewAtIndex((currentPage - 1) * pageSize, ListView.Beginning);
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/qtbug50105.qml b/tests/auto/quick/qquicklistview/data/qtbug50105.qml
new file mode 100644
index 0000000000..a48a881a21
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/qtbug50105.qml
@@ -0,0 +1,130 @@
+import QtQuick 2.4
+import QtQuick.Window 2.2
+
+Window {
+ id : mainWindow
+ visible: true
+ width: 800
+ height: 480
+
+ property real gridListWidth : (width * 0.60)
+ property real gridListHeight : (height * 0.50)
+
+ property real gridCellSpacing : (height * 0.004)
+ property real gridCellHeight : (height * 0.039)
+ property real gridCellWidth : (width * 0.20)
+
+ Rectangle {
+ id : rectBackground
+ anchors.fill: parent
+ color : "white"
+
+ ListView {
+ id : ls
+ width: mainWindow.gridListWidth
+ height: mainWindow.gridListHeight
+ clip : true
+ headerPositioning: ListView.OverlayHeader
+ spacing : mainWindow.gridCellSpacing
+
+ model: ListModel {
+ ListElement {
+ name: "Bill Smith"
+ number: "555 3264"
+ hairColor: "red"
+ }
+ ListElement {
+ name: "John Brown"
+ number: "484 7789"
+ hairColor: "blue"
+ }
+ ListElement {
+ name: "Sam Wise"
+ number: "284 1547"
+ hairColor: "yellow"
+ }
+ }
+
+ header : Row {
+ spacing : mainWindow.gridCellSpacing
+
+ Rectangle {
+ width : mainWindow.gridCellWidth
+ height : mainWindow.gridCellHeight
+ color : "blue"
+
+ Text {
+ anchors.centerIn: parent
+ color : "white"
+ text: "Name"
+ }
+ }
+
+ Rectangle {
+ width : mainWindow.gridCellWidth
+ height : mainWindow.gridCellHeight
+ color : "blue"
+
+ Text {
+ anchors.centerIn: parent
+ color : "white"
+ text: "Number"
+ }
+
+ }
+
+ Rectangle {
+ width : mainWindow.gridCellWidth
+ height : mainWindow.gridCellHeight
+ color : "blue"
+
+ Text {
+ anchors.centerIn: parent
+ color : "white"
+ text: "Hair Color"
+ }
+ }
+ }
+
+ delegate: Row {
+ spacing : mainWindow.gridCellSpacing
+
+ Rectangle {
+ width : mainWindow.gridCellWidth
+ height : mainWindow.gridCellHeight
+ color : "red"
+
+ Text {
+ anchors.centerIn: parent
+ color : "white"
+ text: name
+ }
+ }
+
+ Rectangle {
+ width : mainWindow.gridCellWidth
+ height : mainWindow.gridCellHeight
+ color : "red"
+
+ Text {
+ anchors.centerIn: parent
+ color : "white"
+ text: number
+ }
+ }
+
+ Rectangle {
+ width : mainWindow.gridCellWidth
+ height : mainWindow.gridCellHeight
+ color : "red"
+
+ Text {
+ anchors.centerIn: parent
+ color : "white"
+ text: hairColor
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/data/snapOneItemCurrentIndexRemoveAnimation.qml b/tests/auto/quick/qquicklistview/data/snapOneItemCurrentIndexRemoveAnimation.qml
new file mode 100644
index 0000000000..215467f0cc
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/snapOneItemCurrentIndexRemoveAnimation.qml
@@ -0,0 +1,39 @@
+import QtQuick 2.4
+
+ListView {
+ id: root
+ height: 400
+ width: height
+ model: ListModel {
+ id: lmodel
+ ListElement { dummy: 0 }
+ ListElement { dummy: 0 }
+ ListElement { dummy: 0 }
+ ListElement { dummy: 0 }
+ ListElement { dummy: 0 }
+ ListElement { dummy: 0 }
+ }
+
+ function removeItemZero()
+ {
+ lmodel.remove(0);
+ }
+
+ orientation: ListView.Horizontal
+ snapMode: ListView.SnapOneItem
+ highlightRangeMode: ListView.StrictlyEnforceRange
+
+ property int transitionsRun: 0
+
+ removeDisplaced: Transition {
+ id: transition
+ PropertyAnimation { property: "x"; duration: 500 }
+ onRunningChanged: if (!running) transitionsRun++;
+ }
+
+ delegate: Text {
+ text: index + " of " + lmodel.count
+ width: root.width
+ height: root.height
+ }
+} \ No newline at end of file
diff --git a/tests/auto/quick/qquicklistview/data/snapOneItemResize.qml b/tests/auto/quick/qquicklistview/data/snapOneItemResize.qml
new file mode 100644
index 0000000000..7ecc833a64
--- /dev/null
+++ b/tests/auto/quick/qquicklistview/data/snapOneItemResize.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.0
+
+ListView {
+ id: list
+ currentIndex: 5
+ snapMode: ListView.SnapOneItem
+ orientation: ListView.Horizontal
+ highlightRangeMode: ListView.StrictlyEnforceRange
+ highlightFollowsCurrentItem: true
+ model: 10
+ spacing: 10
+ delegate: Item {
+ width: ListView.view.width
+ height: ListView.view.height
+ }
+}
diff --git a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
index c93aac456d..12405e32c0 100644
--- a/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
+++ b/tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
@@ -40,6 +40,7 @@
#include <QtQml/qqmlcontext.h>
#include <QtQml/qqmlexpression.h>
#include <QtQml/qqmlincubator.h>
+#include <QtQuick/private/qquickitemview_p_p.h>
#include <QtQuick/private/qquicklistview_p.h>
#include <QtQuick/private/qquicktext_p.h>
#include <QtQml/private/qqmlobjectmodel_p.h>
@@ -179,8 +180,10 @@ private slots:
void creationContext();
void snapToItem_data();
void snapToItem();
+ void snapOneItemResize_QTBUG_43555();
void snapOneItem_data();
void snapOneItem();
+ void snapOneItemCurrentIndexRemoveAnimation();
void QTBUG_9791();
void QTBUG_11105();
@@ -241,6 +244,16 @@ private slots:
void QTBUG_39492();
void jsArrayChange();
+ void objectModel();
+
+ void contentHeightWithDelayRemove();
+ void contentHeightWithDelayRemove_data();
+
+ void QTBUG_48044_currentItemNotVisibleAfterTransition();
+ void QTBUG_48870_fastModelUpdates();
+
+ void QTBUG_50105();
+ void QTBUG_50097_stickyHeader_positionViewAtIndex();
private:
template <class T> void items(const QUrl &source);
@@ -391,7 +404,7 @@ void tst_QQuickListView::items(const QUrl &source)
QTRY_VERIFY(contentItem != 0);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(!testObject->error());
QTRY_VERIFY(listview->highlightItem() != 0);
QTRY_COMPARE(listview->count(), model.count());
@@ -414,20 +427,20 @@ void tst_QQuickListView::items(const QUrl &source)
// switch to other delegate
testObject->setAnimate(true);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(!testObject->error());
QTRY_VERIFY(listview->currentItem());
// set invalid highlight
testObject->setInvalidHighlight(true);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(!testObject->error());
QTRY_VERIFY(listview->currentItem());
- QTRY_VERIFY(listview->highlightItem() == 0);
+ QTRY_VERIFY(!listview->highlightItem());
// back to normal highlight
testObject->setInvalidHighlight(false);
QMetaObject::invokeMethod(window->rootObject(), "checkProperties");
- QTRY_VERIFY(testObject->error() == false);
+ QTRY_VERIFY(!testObject->error());
QTRY_VERIFY(listview->currentItem());
QTRY_VERIFY(listview->highlightItem() != 0);
@@ -439,7 +452,7 @@ void tst_QQuickListView::items(const QUrl &source)
listview->forceLayout();
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
- QTRY_VERIFY(itemCount == 0);
+ QTRY_COMPARE(itemCount, 0);
QTRY_COMPARE(listview->highlightResizeVelocity(), 1000.0);
QTRY_COMPARE(listview->highlightMoveVelocity(), 100000.0);
@@ -563,7 +576,7 @@ void tst_QQuickListView::inserted(const QUrl &source)
// Insert item outside visible area
model.insertItem(1, "Hello", "1324");
- QTRY_VERIFY(listview->contentY() == 80);
+ QTRY_COMPARE(listview->contentY(), qreal(80));
// Confirm items positioned correctly
for (int i = 5; i < 5+15; ++i) {
@@ -582,8 +595,7 @@ void tst_QQuickListView::inserted(const QUrl &source)
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", 0);
QVERIFY(item);
- QCOMPARE(item->y(), 0.);
- QTRY_VERIFY(listview->contentY() == 0);
+ QTRY_COMPARE(item->y() - listview->contentY(), 0.);
delete window;
delete testObject;
@@ -634,7 +646,8 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
QTRY_COMPARE(listview->property("count").toInt(), model.count());
-
+ // FIXME This is NOT checking anything about visibleItems.first()
+#if 0
// check visibleItems.first() is in correct position
QQuickItem *item0 = findItem<QQuickItem>(contentItem, "wrapper", 0);
QVERIFY(item0);
@@ -642,6 +655,7 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
QCOMPARE(item0->y(), -item0->height() - itemsOffsetAfterMove);
else
QCOMPARE(item0->y(), itemsOffsetAfterMove);
+#endif
QList<QQuickItem*> items = findItems<QQuickItem>(contentItem, "wrapper");
int firstVisibleIndex = -1;
@@ -657,12 +671,21 @@ void tst_QQuickListView::inserted_more(QQuickItemView::VerticalLayoutDirection v
// Confirm items positioned correctly and indexes correct
QQuickText *name;
QQuickText *number;
+ const qreal visibleFromPos = listview->contentY() - listview->displayMarginBeginning() - listview->cacheBuffer();
+ const qreal visibleToPos = listview->contentY() + listview->height() + listview->displayMarginEnd() + listview->cacheBuffer();
for (int i = firstVisibleIndex; i < model.count() && i < items.count(); ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
qreal pos = i*20.0 + itemsOffsetAfterMove;
if (verticalLayoutDirection == QQuickItemView::BottomToTop)
- pos = -item0->height() - pos;
+ pos = -item->height() - pos;
+ // Items outside the visible area (including cache buffer) should be skipped
+ if (pos > visibleToPos || pos < visibleFromPos) {
+ QTRY_VERIFY2(QQuickItemPrivate::get(item)->culled || item->y() < visibleFromPos || item->y() > visibleToPos,
+ QTest::toString(QString("index %5, y %1, from %2, to %3, expected pos %4, culled %6").
+ arg(item->y()).arg(visibleFromPos).arg(visibleToPos).arg(pos).arg(i).arg(bool(QQuickItemPrivate::get(item)->culled))));
+ continue;
+ }
QTRY_COMPARE(item->y(), pos);
name = findItem<QQuickText>(contentItem, "textName", i);
QVERIFY(name != 0);
@@ -916,7 +939,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_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
// Remove first item (which is the current item);
@@ -968,7 +991,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
}
// Remove current index
- QTRY_VERIFY(listview->currentIndex() == 9);
+ QTRY_COMPARE(listview->currentIndex(), 9);
QQuickItem *oldCurrent = listview->currentItem();
model.removeItem(9);
@@ -1004,7 +1027,7 @@ void tst_QQuickListView::removed(const QUrl &source, bool /* animated */)
model.removeItem(6);
QTRY_COMPARE(listview->currentIndex(), 7);
- QTRY_VERIFY(listview->currentItem() == oldCurrent);
+ QTRY_COMPARE(listview->currentItem(), oldCurrent);
listview->setContentY(80);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
@@ -1272,22 +1295,22 @@ void tst_QQuickListView::clear(const QUrl &source, QQuickItemView::VerticalLayou
model.clear();
QTRY_COMPARE(findItems<QQuickListView>(contentItem, "wrapper").count(), 0);
- QTRY_VERIFY(listview->count() == 0);
- QTRY_VERIFY(listview->currentItem() == 0);
+ QTRY_COMPARE(listview->count(), 0);
+ QTRY_VERIFY(!listview->currentItem());
if (verticalLayoutDirection == QQuickItemView::TopToBottom)
QTRY_COMPARE(listview->contentY(), 0.0);
else
QTRY_COMPARE(listview->contentY(), -listview->height());
- QVERIFY(listview->currentIndex() == -1);
+ QCOMPARE(listview->currentIndex(), -1);
QCOMPARE(listview->contentHeight(), 0.0);
// confirm sanity when adding an item to cleared list
model.addItem("New", "1");
listview->forceLayout();
- QTRY_VERIFY(listview->count() == 1);
+ QTRY_COMPARE(listview->count(), 1);
QVERIFY(listview->currentItem() != 0);
- QVERIFY(listview->currentIndex() == 0);
+ QCOMPARE(listview->currentIndex(), 0);
delete window;
delete testObject;
@@ -1805,7 +1828,7 @@ void tst_QQuickListView::swapWithFirstItem()
// ensure content position is stable
listview->setContentY(0);
model.moveItem(1, 0);
- QTRY_VERIFY(listview->contentY() == 0);
+ QTRY_COMPARE(listview->contentY(), qreal(0));
delete testObject;
delete window;
@@ -1943,11 +1966,11 @@ void tst_QQuickListView::spacing()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
listview->setSpacing(10);
- QTRY_VERIFY(listview->spacing() == 10);
+ QTRY_COMPARE(listview->spacing(), qreal(10));
// Confirm items positioned correctly
QTRY_VERIFY(findItems<QQuickItem>(contentItem, "wrapper").count() == 11);
@@ -1955,7 +1978,7 @@ void tst_QQuickListView::spacing()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*30);
+ QTRY_COMPARE(item->y(), qreal(i*30));
}
listview->setSpacing(0);
@@ -2261,7 +2284,7 @@ void tst_QQuickListView::sectionsDelegate_headerVisibility()
listview->setCurrentIndex(20);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
QTRY_VERIFY(qFuzzyCompare(listview->contentY(), 200.0));
- QTRY_VERIFY(listview->isMoving() == false);
+ QTRY_VERIFY(!listview->isMoving());
listview->setCurrentIndex(0);
QTRY_VERIFY(qFuzzyIsNull(listview->contentY()));
@@ -2682,7 +2705,7 @@ void tst_QQuickListView::currentIndex()
listview->setCurrentIndex(20);
QTRY_VERIFY(listview->verticalVelocity() != 0.0);
listview->setCurrentIndex(0);
- QTRY_VERIFY(listview->verticalVelocity() == 0.0);
+ QTRY_COMPARE(listview->verticalVelocity(), 0.0);
// footer should become visible if it is out of view, and then current index is set to count-1
window->rootObject()->setProperty("showFooter", true);
@@ -2704,7 +2727,7 @@ void tst_QQuickListView::currentIndex()
// turn off auto highlight
listview->setHighlightFollowsCurrentItem(false);
- QVERIFY(listview->highlightFollowsCurrentItem() == false);
+ QVERIFY(!listview->highlightFollowsCurrentItem());
QVERIFY(listview->highlightItem());
qreal hlPos = listview->highlightItem()->y();
@@ -2713,9 +2736,12 @@ void tst_QQuickListView::currentIndex()
QTRY_COMPARE(listview->highlightItem()->y(), hlPos);
// insert item before currentIndex
+ window->rootObject()->setProperty("currentItemChangedCount", QVariant(0));
listview->setCurrentIndex(28);
+ QTRY_COMPARE(window->rootObject()->property("currentItemChangedCount").toInt(), 1);
model.insertItem(0, "Foo", "1111");
QTRY_COMPARE(window->rootObject()->property("current").toInt(), 29);
+ QCOMPARE(window->rootObject()->property("currentItemChangedCount").toInt(), 1);
// check removing highlight by setting currentIndex to -1;
listview->setCurrentIndex(-1);
@@ -2808,7 +2834,7 @@ void tst_QQuickListView::keyNavigation()
window->requestActivate();
QTest::qWaitForWindowActive(window);
- QTRY_VERIFY(qGuiApp->focusWindow() == window);
+ QTRY_COMPARE(qGuiApp->focusWindow(), window);
QTest::keyClick(window, forwardsKey);
QCOMPARE(listview->currentIndex(), 1);
@@ -2917,7 +2943,7 @@ void tst_QQuickListView::itemList()
QQmlObjectModel *model = window->rootObject()->findChild<QQmlObjectModel*>("itemModel");
QTRY_VERIFY(model != 0);
- QTRY_VERIFY(model->count() == 3);
+ QTRY_COMPARE(model->count(), 3);
QTRY_COMPARE(listview->currentIndex(), 0);
QQuickItem *item = findItem<QQuickItem>(contentItem, "item1");
@@ -2958,7 +2984,7 @@ void tst_QQuickListView::itemListFlicker()
QQmlObjectModel *model = window->rootObject()->findChild<QQmlObjectModel*>("itemModel");
QTRY_VERIFY(model != 0);
- QTRY_VERIFY(model->count() == 3);
+ QTRY_COMPARE(model->count(), 3);
QTRY_COMPARE(listview->currentIndex(), 0);
QQuickItem *item;
@@ -3024,14 +3050,14 @@ void tst_QQuickListView::cacheBuffer()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
QQmlIncubationController controller;
window->engine()->setIncubationController(&controller);
testObject->setCacheBuffer(200);
- QTRY_VERIFY(listview->cacheBuffer() == 200);
+ QTRY_COMPARE(listview->cacheBuffer(), 200);
// items will be created one at a time
for (int i = itemCount; i < qMin(itemCount+10,model.count()); ++i) {
@@ -3057,7 +3083,7 @@ void tst_QQuickListView::cacheBuffer()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
// move view and confirm items in view are visible immediately and outside are created async
@@ -3067,7 +3093,7 @@ void tst_QQuickListView::cacheBuffer()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QVERIFY(item);
- QVERIFY(item->y() == i*20);
+ QCOMPARE(item->y(), qreal(i*20));
}
QVERIFY(findItem<QQuickItem>(listview, "wrapper", 32) == 0);
@@ -3528,7 +3554,7 @@ void tst_QQuickListView::QTBUG_11105()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
+ QTRY_COMPARE(item->y(), qreal(i*20));
}
listview->positionViewAtIndex(20, QQuickListView::Beginning);
@@ -3622,7 +3648,7 @@ void tst_QQuickListView::header()
QQuickText *header = 0;
QTRY_VERIFY(header = findItem<QQuickText>(contentItem, "header"));
- QVERIFY(header == listview->headerItem());
+ QCOMPARE(header, listview->headerItem());
QCOMPARE(header->width(), 100.);
QCOMPARE(header->height(), 30.);
@@ -3660,7 +3686,7 @@ void tst_QQuickListView::header()
header = findItem<QQuickText>(contentItem, "header2");
QVERIFY(header);
- QVERIFY(header == listview->headerItem());
+ QCOMPARE(header, listview->headerItem());
QCOMPARE(header->position(), changedHeaderPos);
QCOMPARE(header->width(), 50.);
@@ -3811,7 +3837,7 @@ void tst_QQuickListView::headerChangesViewport()
QQuickText *header = 0;
QTRY_VERIFY(header = findItem<QQuickText>(contentItem, "header"));
- QVERIFY(header == listview->headerItem());
+ QCOMPARE(header, listview->headerItem());
QCOMPARE(header->height(), 20.);
QCOMPARE(listview->contentHeight(), 20.);
@@ -3862,7 +3888,7 @@ void tst_QQuickListView::footer()
QQuickText *footer = findItem<QQuickText>(contentItem, "footer");
QVERIFY(footer);
- QVERIFY(footer == listview->footerItem());
+ QCOMPARE(footer, listview->footerItem());
QCOMPARE(footer->position(), initialFooterPos);
QCOMPARE(footer->width(), 100.);
@@ -3922,7 +3948,7 @@ void tst_QQuickListView::footer()
footer = findItem<QQuickText>(contentItem, "footer2");
QVERIFY(footer);
- QVERIFY(footer == listview->footerItem());
+ QCOMPARE(footer, listview->footerItem());
QCOMPARE(footer->position(), changedFooterPos);
QCOMPARE(footer->width(), 50.);
@@ -4155,11 +4181,11 @@ void tst_QQuickListView::resetModel_headerFooter()
// A reset should not force a new header or footer to be created.
QQuickItem *newHeader = findItem<QQuickItem>(contentItem, "header");
- QVERIFY(newHeader == header);
+ QCOMPARE(newHeader, header);
QCOMPARE(header->y(), -header->height());
QQuickItem *newFooter = findItem<QQuickItem>(contentItem, "footer");
- QVERIFY(newFooter == footer);
+ QCOMPARE(newFooter, footer);
QCOMPARE(footer->y(), 30.*4);
delete window;
@@ -4664,7 +4690,7 @@ void tst_QQuickListView::indexAt_itemAt()
QVERIFY(item);
}
QCOMPARE(listview->indexAt(x,y), index);
- QVERIFY(listview->itemAt(x,y) == item);
+ QCOMPARE(listview->itemAt(x,y), item);
releaseView(window);
delete testObject;
@@ -4828,7 +4854,7 @@ void tst_QQuickListView::rightToLeft()
QQmlObjectModel *model = window->rootObject()->findChild<QQmlObjectModel*>("itemModel");
QTRY_VERIFY(model != 0);
- QTRY_VERIFY(model->count() == 3);
+ QTRY_COMPARE(model->count(), 3);
QTRY_COMPARE(listview->currentIndex(), 0);
// initial position at first item, right edge aligned
@@ -4893,7 +4919,7 @@ void tst_QQuickListView::test_mirroring()
foreach (const QString objectName, objectNames)
QCOMPARE(findItem<QQuickItem>(listviewA, objectName)->x(), findItem<QQuickItem>(listviewB, objectName)->x());
- QVERIFY(listviewB->layoutDirection() == listviewB->effectiveLayoutDirection());
+ QCOMPARE(listviewB->layoutDirection(), listviewB->effectiveLayoutDirection());
QQuickItemPrivate::get(listviewB)->setLayoutMirror(true);
QVERIFY(listviewB->layoutDirection() != listviewB->effectiveLayoutDirection());
@@ -5034,7 +5060,7 @@ void tst_QQuickListView::marginsResize()
// flick past the end and check content pos still settles on correct extents
flick(window, flickStart, flickEnd, 180);
- QTRY_VERIFY(listview->isMoving() == false);
+ QTRY_VERIFY(!listview->isMoving());
if (orientation == QQuickListView::Vertical)
QTRY_COMPARE(listview->contentY(), end);
else
@@ -5049,7 +5075,7 @@ void tst_QQuickListView::marginsResize()
// flick past the beginning and check content pos still settles on correct extents
flick(window, flickEnd, flickStart, 180);
- QTRY_VERIFY(listview->isMoving() == false);
+ QTRY_VERIFY(!listview->isMoving());
if (orientation == QQuickListView::Vertical)
QTRY_COMPARE(listview->contentY(), start);
else
@@ -5199,6 +5225,37 @@ void tst_QQuickListView::snapToItem()
releaseView(window);
}
+void tst_QQuickListView::snapOneItemResize_QTBUG_43555()
+{
+ QQuickView *window = createView();
+ window->resize(QSize(100, 320));
+ window->setResizeMode(QQuickView::SizeRootObjectToView);
+ QQuickViewTestUtil::moveMouseAway(window);
+
+ window->setSource(testFileUrl("snapOneItemResize.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QSignalSpy currentIndexSpy(listview, SIGNAL(currentIndexChanged()));
+
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_COMPARE(listview->currentIndex(), 5);
+ currentIndexSpy.clear();
+
+ window->resize(QSize(400, 320));
+
+ QTRY_COMPARE(int(listview->width()), 400);
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+
+ QTRY_COMPARE(listview->currentIndex(), 5);
+ QCOMPARE(currentIndexSpy.count(), 0);
+
+ delete window;
+}
+
void tst_QQuickListView::qAbstractItemModel_package_items()
{
items<QaimModel>(testFileUrl("listviewtest-package.qml"));
@@ -5546,6 +5603,32 @@ void tst_QQuickListView::snapOneItem()
releaseView(window);
}
+void tst_QQuickListView::snapOneItemCurrentIndexRemoveAnimation()
+{
+ QQuickView *window = createView();
+
+ window->setSource(testFileUrl("snapOneItemCurrentIndexRemoveAnimation.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QTRY_VERIFY(listview != 0);
+
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ QTRY_COMPARE(listview->currentIndex(), 0);
+ QSignalSpy currentIndexSpy(listview, SIGNAL(currentIndexChanged()));
+
+ QMetaObject::invokeMethod(window->rootObject(), "removeItemZero");
+ QTRY_COMPARE(listview->property("transitionsRun").toInt(), 1);
+
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+
+ QCOMPARE(listview->currentIndex(), 0);
+ QCOMPARE(currentIndexSpy.count(), 0);
+
+ delete window;
+}
+
void tst_QQuickListView::attachedProperties_QTBUG_32836()
{
QQuickView *window = createView();
@@ -7006,7 +7089,7 @@ void tst_QQuickListView::matchIndexLists(const QVariantList &indexLists, const Q
void tst_QQuickListView::matchItemsAndIndexes(const QVariantMap &items, const QaimModel &model, const QList<int> &expectedIndexes)
{
for (QVariantMap::const_iterator it = items.begin(); it != items.end(); ++it) {
- QVERIFY(it.value().type() == QVariant::Int);
+ QCOMPARE(it.value().type(), QVariant::Int);
QString name = it.key();
int itemIndex = it.value().toInt();
QVERIFY2(expectedIndexes.contains(itemIndex), QTest::toString(QString("Index %1 not found in expectedIndexes").arg(itemIndex)));
@@ -7020,7 +7103,7 @@ void tst_QQuickListView::matchItemsAndIndexes(const QVariantMap &items, const Qa
void tst_QQuickListView::matchItemLists(const QVariantList &itemLists, const QList<QQuickItem *> &expectedItems)
{
for (int i=0; i<itemLists.count(); i++) {
- QVERIFY(itemLists[i].type() == QVariant::List);
+ QCOMPARE(itemLists[i].type(), QVariant::List);
QVariantList current = itemLists[i].toList();
for (int j=0; j<current.count(); j++) {
QQuickItem *o = qobject_cast<QQuickItem*>(current[j].value<QObject*>());
@@ -7062,7 +7145,7 @@ void tst_QQuickListView::flickBeyondBounds()
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
if (!item) qWarning() << "Item" << i << "not found";
QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*45);
+ QTRY_COMPARE(item->y(), qreal(i*45));
}
delete window;
@@ -7398,7 +7481,7 @@ void tst_QQuickListView::stickyPositioning()
QFETCH(QPointF, headerPos);
QFETCH(QPointF, footerPos);
- QQuickView *window = createView();
+ QQuickView *window = getView();
QaimModel model;
for (int i = 0; i < 20; i++)
@@ -7441,7 +7524,7 @@ void tst_QQuickListView::stickyPositioning()
QCOMPARE(actualPos, footerPos);
}
- delete window;
+ releaseView(window);
}
void tst_QQuickListView::stickyPositioning_data()
@@ -7468,7 +7551,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("top header") << "stickyPositioning-header.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
<< 0 << QQuickItemView::Beginning << QList<QPointF>()
- << QPointF(0,-10) << QPointF();
+ << QPointF(0,0) << QPointF();
QTest::newRow("top header: 1/2 up") << "stickyPositioning-header.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
@@ -7495,7 +7578,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("top footer") << "stickyPositioning-footer.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
<< 19 << QQuickItemView::End << QList<QPointF>()
- << QPointF() << QPointF(0,-10);
+ << QPointF() << QPointF(0,0);
QTest::newRow("top footer: 1/2 up") << "stickyPositioning-footer.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
@@ -7522,7 +7605,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("bottom header") << "stickyPositioning-header.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
<< 0 << QQuickItemView::Beginning << QList<QPointF>()
- << QPointF(0,100) << QPointF();
+ << QPointF(0,90) << QPointF();
QTest::newRow("bottom header: 1/2 down") << "stickyPositioning-header.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::BottomToTop
@@ -7549,7 +7632,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("bottom footer") << "stickyPositioning-footer.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
<< 19 << QQuickItemView::End << QList<QPointF>()
- << QPointF() << QPointF(0,100);
+ << QPointF() << QPointF(0,90);
QTest::newRow("bottom footer: 1/2 down") << "stickyPositioning-footer.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
@@ -7576,7 +7659,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("top header & bottom footer") << "stickyPositioning-both.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
<< 0 << QQuickItemView::Beginning << QList<QPointF>()
- << QPointF(0,-10) << QPointF(0,90);
+ << QPointF(0,0) << QPointF(0,100);
QTest::newRow("top header & bottom footer: 1/2 up") << "stickyPositioning-both.qml"
<< Qt::Vertical << Qt::LeftToRight << QQuickListView::TopToBottom
@@ -7629,7 +7712,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("left header") << "stickyPositioning-header.qml"
<< Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
<< 0 << QQuickItemView::Beginning << QList<QPointF>()
- << QPointF(-10,0) << QPointF();
+ << QPointF(0,0) << QPointF();
QTest::newRow("left header: 1/2 left") << "stickyPositioning-header.qml"
<< Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
@@ -7656,7 +7739,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("left footer") << "stickyPositioning-footer.qml"
<< Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
<< 19 << QQuickItemView::End << QList<QPointF>()
- << QPointF() << QPointF(-10,0);
+ << QPointF() << QPointF(0,0);
QTest::newRow("left footer: 1/2 left") << "stickyPositioning-footer.qml"
<< Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
@@ -7683,7 +7766,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("right header") << "stickyPositioning-header.qml"
<< Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
<< 0 << QQuickItemView::Beginning << QList<QPointF>()
- << QPointF(100,0) << QPointF();
+ << QPointF(90,0) << QPointF();
QTest::newRow("right header: 1/2 right") << "stickyPositioning-header.qml"
<< Qt::Horizontal << Qt::RightToLeft << QQuickListView::TopToBottom
@@ -7710,7 +7793,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("right footer") << "stickyPositioning-footer.qml"
<< Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
<< 19 << QQuickItemView::End << QList<QPointF>()
- << QPointF() << QPointF(100,0);
+ << QPointF() << QPointF(90,0);
QTest::newRow("right footer: 1/2 right") << "stickyPositioning-footer.qml"
<< Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
@@ -7737,7 +7820,7 @@ void tst_QQuickListView::stickyPositioning_data()
QTest::newRow("left header & right footer") << "stickyPositioning-both.qml"
<< Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
<< 0 << QQuickItemView::Beginning << QList<QPointF>()
- << QPointF(-10,0) << QPointF(90,0);
+ << QPointF(0,0) << QPointF(100,0);
QTest::newRow("left header & right footer: 1/2 left") << "stickyPositioning-both.qml"
<< Qt::Horizontal << Qt::LeftToRight << QQuickListView::TopToBottom
@@ -7856,7 +7939,7 @@ void tst_QQuickListView::QTBUG_38209()
// simulate mouse flick
flick(window.data(), QPoint(200, 200), QPoint(200, 50), 100);
- QTRY_VERIFY(listview->isMoving() == false);
+ QTRY_VERIFY(!listview->isMoving());
qreal contentY = listview->contentY();
// flick down
@@ -8063,6 +8146,328 @@ void tst_QQuickListView::jsArrayChange()
QCOMPARE(spy.count(), 1);
}
+static bool compareObjectModel(QQuickListView *listview, QQmlObjectModel *model)
+{
+ if (listview->count() != model->count())
+ return false;
+ for (int i = 0; i < listview->count(); ++i) {
+ listview->setCurrentIndex(i);
+ if (listview->currentItem() != model->get(i))
+ return false;
+ }
+ return true;
+}
+
+void tst_QQuickListView::objectModel()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("objectmodel.qml"));
+
+ QQuickListView *listview = qobject_cast<QQuickListView *>(component.create());
+ QVERIFY(listview);
+
+ QQmlObjectModel *model = listview->model().value<QQmlObjectModel *>();
+ QVERIFY(model);
+
+ listview->setCurrentIndex(0);
+ QVERIFY(listview->currentItem());
+ QCOMPARE(listview->currentItem()->property("color").toString(), QColor("red").name());
+
+ listview->setCurrentIndex(1);
+ QVERIFY(listview->currentItem());
+ QCOMPARE(listview->currentItem()->property("color").toString(), QColor("green").name());
+
+ listview->setCurrentIndex(2);
+ QVERIFY(listview->currentItem());
+ QCOMPARE(listview->currentItem()->property("color").toString(), QColor("blue").name());
+
+ QQuickItem *item0 = new QQuickItem(listview);
+ item0->setSize(QSizeF(20, 20));
+ model->append(item0);
+ QCOMPARE(model->count(), 4);
+ QVERIFY(compareObjectModel(listview, model));
+
+ QQuickItem *item1 = new QQuickItem(listview);
+ item1->setSize(QSizeF(20, 20));
+ model->insert(0, item1);
+ QCOMPARE(model->count(), 5);
+ QVERIFY(compareObjectModel(listview, model));
+
+ model->move(1, 2, 3);
+ QVERIFY(compareObjectModel(listview, model));
+
+ model->remove(2, 2);
+ QCOMPARE(model->count(), 3);
+ QVERIFY(compareObjectModel(listview, model));
+
+ model->clear();
+ QCOMPARE(model->count(), 0);
+ QCOMPARE(listview->count(), 0);
+
+ delete listview;
+}
+
+void tst_QQuickListView::contentHeightWithDelayRemove_data()
+{
+ QTest::addColumn<bool>("useDelayRemove");
+ QTest::addColumn<QByteArray>("removeFunc");
+ QTest::addColumn<int>("countDelta");
+ QTest::addColumn<qreal>("contentHeightDelta");
+
+ QTest::newRow("remove without delayRemove")
+ << false
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with delayRemove")
+ << true
+ << QByteArray("takeOne")
+ << -1
+ << qreal(-1 * 100.0);
+
+ QTest::newRow("remove with multiple delayRemove")
+ << true
+ << QByteArray("takeThree")
+ << -3
+ << qreal(-3 * 100.0);
+
+ QTest::newRow("clear with delayRemove")
+ << true
+ << QByteArray("takeAll")
+ << -5
+ << qreal(-5 * 100.0);
+}
+
+void tst_QQuickListView::contentHeightWithDelayRemove()
+{
+ QFETCH(bool, useDelayRemove);
+ QFETCH(QByteArray, removeFunc);
+ QFETCH(int, countDelta);
+ QFETCH(qreal, contentHeightDelta);
+
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("contentHeightWithDelayRemove.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
+ QTRY_VERIFY(listview != 0);
+
+ const int initialCount(listview->count());
+ const int eventualCount(initialCount + countDelta);
+
+ const qreal initialContentHeight(listview->contentHeight());
+ const int eventualContentHeight(qRound(initialContentHeight + contentHeightDelta));
+
+ listview->setProperty("useDelayRemove", useDelayRemove);
+ QMetaObject::invokeMethod(window->rootObject(), removeFunc.constData());
+ QTest::qWait(50);
+ QCOMPARE(listview->count(), eventualCount);
+
+ if (useDelayRemove) {
+ QCOMPARE(qRound(listview->contentHeight()), qRound(initialContentHeight));
+ QTRY_COMPARE(qRound(listview->contentHeight()), eventualContentHeight);
+ } else {
+ QCOMPARE(qRound(listview->contentHeight()), eventualContentHeight);
+ }
+
+ delete window;
+}
+
+void tst_QQuickListView::QTBUG_48044_currentItemNotVisibleAfterTransition()
+{
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("qtbug48044.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = window->rootObject()->findChild<QQuickListView*>();
+ QTRY_VERIFY(listview != 0);
+
+ // Expand 2nd header
+ listview->setProperty("transitionsDone", QVariant(false));
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, 75));
+ QTRY_VERIFY(listview->property("transitionsDone").toBool());
+
+ // Flick listview to the bottom
+ flick(window, QPoint(window->width() / 2, 400), QPoint(window->width() / 2, 0), 100);
+ QTRY_VERIFY(!listview->isMoving());
+
+ // Expand 3rd header
+ listview->setProperty("transitionsDone", QVariant(false));
+ QTest::mouseClick(window, Qt::LeftButton, Qt::NoModifier, QPoint(window->width() / 2, window->height() - 25));
+ QTRY_VERIFY(listview->property("transitionsDone").toBool());
+
+ // Check current item is what we expect
+ QCOMPARE(listview->currentIndex(), 2);
+ QQuickItem *currentItem = listview->currentItem();
+ QVERIFY(currentItem);
+ QVERIFY(currentItem->isVisible());
+
+ // This is the actual test
+ QQuickItemPrivate *currentPriv = QQuickItemPrivate::get(currentItem);
+ QVERIFY(!currentPriv->culled);
+}
+
+static bool testVisibleItems(const QQuickItemViewPrivate *priv, bool *nonUnique, FxViewItem **failItem, int *expectedIdx)
+{
+ QHash<QQuickItem*, int> uniqueItems;
+
+ int skip = 0;
+ for (int i = 0; i < priv->visibleItems.count(); ++i) {
+ FxViewItem *item = priv->visibleItems.at(i);
+ if (!item) {
+ *failItem = Q_NULLPTR;
+ return false;
+ }
+#if 0
+ qDebug() << "\t" << item->index
+ << item->item
+ << item->position()
+ << (!item->item || QQuickItemPrivate::get(item->item)->culled ? "hidden" : "visible");
+#endif
+ if (item->index == -1) {
+ ++skip;
+ } else if (item->index != priv->visibleIndex + i - skip) {
+ *nonUnique = false;
+ *failItem = item;
+ *expectedIdx = priv->visibleIndex + i - skip;
+ return false;
+ } else if (uniqueItems.contains(item->item)) {
+ *nonUnique = true;
+ *failItem = item;
+ *expectedIdx = uniqueItems.find(item->item).value();
+ return false;
+ }
+
+ uniqueItems.insert(item->item, item->index);
+ }
+
+ return true;
+}
+
+class QTBUG_48870_Model : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+
+ QTBUG_48870_Model()
+ : QAbstractListModel()
+ , m_rowCount(20)
+ {
+ QTimer *t = new QTimer(this);
+ t->setInterval(500);
+ t->start();
+
+ qsrand(qHash(QDateTime::currentDateTime()));
+ connect(t, &QTimer::timeout, this, &QTBUG_48870_Model::updateModel);
+ }
+
+ int rowCount(const QModelIndex &) const
+ {
+ return m_rowCount;
+ }
+
+ QVariant data(const QModelIndex &, int) const
+ {
+ return QVariant();
+ }
+
+public Q_SLOTS:
+ void updateModel()
+ {
+ if (m_rowCount > 10) {
+ for (int i = 0; i < 10; ++i) {
+ int rnum = qrand() % m_rowCount;
+ beginRemoveRows(QModelIndex(), rnum, rnum);
+ m_rowCount--;
+ endRemoveRows();
+ }
+ }
+ if (m_rowCount < 20) {
+ for (int i = 0; i < 10; ++i) {
+ int rnum = qrand() % m_rowCount;
+ beginInsertRows(QModelIndex(), rnum, rnum);
+ m_rowCount++;
+ endInsertRows();
+ }
+ }
+ }
+
+private:
+ int m_rowCount;
+};
+
+void tst_QQuickListView::QTBUG_48870_fastModelUpdates()
+{
+ QTBUG_48870_Model model;
+
+ QQuickView *window = createView();
+ QVERIFY(window);
+ QQmlContext *ctxt = window->rootContext();
+ QVERIFY(ctxt);
+ ctxt->setContextProperty("testModel", &model);
+
+ window->setSource(testFileUrl("qtbug48870.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+
+ QQuickItemViewPrivate *priv = QQuickItemViewPrivate::get(listview);
+ bool nonUnique;
+ FxViewItem *item = Q_NULLPTR;
+ int expectedIdx;
+ QVERIFY(testVisibleItems(priv, &nonUnique, &item, &expectedIdx));
+
+ for (int i = 0; i < 10; i++) {
+ QTest::qWait(100);
+ QVERIFY2(testVisibleItems(priv, &nonUnique, &item, &expectedIdx),
+ qPrintable(!item ? QString("Unexpected null item")
+ : nonUnique ? QString("Non-unique item at %1 and %2").arg(item->index).arg(expectedIdx)
+ : QString("Found index %1, expected index is %3").arg(item->index).arg(expectedIdx)));
+ if (i % 3 != 0) {
+ if (i & 1)
+ flick(window, QPoint(100, 200), QPoint(100, 0), 100);
+ else
+ flick(window, QPoint(100, 200), QPoint(100, 400), 100);
+ }
+ }
+
+ delete window;
+}
+
+// infinite loop in overlay header positioning due to undesired rounding in QQuickFlickablePrivate::fixup()
+void tst_QQuickListView::QTBUG_50105()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine);
+ component.loadUrl(testFileUrl("qtbug50105.qml"));
+
+ QScopedPointer<QQuickWindow> window(qobject_cast<QQuickWindow *>(component.create()));
+ QVERIFY(window.data());
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+}
+
+void tst_QQuickListView::QTBUG_50097_stickyHeader_positionViewAtIndex()
+{
+ QQuickView *window = createView();
+ window->setSource(testFileUrl("qtbug50097.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ QQuickListView *listview = qobject_cast<QQuickListView*>(window->rootObject());
+ QVERIFY(listview != 0);
+ QTRY_COMPARE(listview->contentY(), -100.0); // the header size, since the header is overlaid
+ listview->setProperty("currentPage", 2);
+ QTRY_COMPARE(listview->contentY(), 400.0); // a full page of items down, sans the original negative header position
+ listview->setProperty("currentPage", 1);
+ QTRY_COMPARE(listview->contentY(), -100.0); // back to the same position: header visible, items not under the header.
+}
+
QTEST_MAIN(tst_QQuickListView)
#include "tst_qquicklistview.moc"