aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWang Chuan <ouchuanm@outlook.com>2022-03-27 15:19:11 +0800
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-04-19 14:49:42 +0000
commitf9efa3469f9d4e5522b4b5744216b16e913a6fcc (patch)
treee85047db2e04b78a0e3b2b463805c124d79aeafe
parent6d5ed3c5857925411cc96e059f4b11ee785d297c (diff)
QQuickListView: relayout when section geometry changes
Section delegate items will now notify the ListView when their geometry changes. Enabling the ListView to call layoutVisibleItems to rearrange the delegate items based on the geometric changes made to the section delegate. The listener is added when the item is created or fetched from the cache. The listener is removed when the item is hidden or removed from the scene. Fixes: QTBUG-101985 Fixes: QTBUG-100002 Change-Id: Ia7617424a8447ba82f62629d93b6a000a72bfc02 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> (cherry picked from commit b994c7ffaf12373ac568a38e3968d620a07c3052) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/quick/items/qquicklistview.cpp8
-rw-r--r--tests/auto/quick/qquicklistview2/data/sectionGeometryChange.qml58
-rw-r--r--tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp28
3 files changed, 94 insertions, 0 deletions
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 050227baed..dd476c380b 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -703,6 +703,8 @@ bool QQuickListViewPrivate::releaseItem(FxViewItem *item, QQmlInstanceModel::Reu
bool released = QQuickItemViewPrivate::releaseItem(item, reusableFlag);
if (released && it && att && att->m_sectionItem) {
+ QQuickItemPrivate::get(att->m_sectionItem)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+
// We hold no more references to this item
int i = 0;
do {
@@ -1106,6 +1108,9 @@ QQuickItem * QQuickListViewPrivate::getSectionItem(const QString &section)
sectionCriteria->delegate()->completeCreate();
}
+ if (sectionItem)
+ QQuickItemPrivate::get(sectionItem)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
+
return sectionItem;
}
@@ -1114,6 +1119,9 @@ void QQuickListViewPrivate::releaseSectionItem(QQuickItem *item)
if (!item)
return;
int i = 0;
+
+ QQuickItemPrivate::get(item)->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
+
do {
if (!sectionCache[i]) {
sectionCache[i] = item;
diff --git a/tests/auto/quick/qquicklistview2/data/sectionGeometryChange.qml b/tests/auto/quick/qquicklistview2/data/sectionGeometryChange.qml
new file mode 100644
index 0000000000..6981af51ec
--- /dev/null
+++ b/tests/auto/quick/qquicklistview2/data/sectionGeometryChange.qml
@@ -0,0 +1,58 @@
+import QtQuick
+import QtQuick.Controls
+
+Rectangle {
+ width: 640
+ height: 480
+ color: "#FFFFFF"
+ ListView {
+ objectName: "list"
+ anchors.fill: parent
+
+ delegate: Rectangle {
+ objectName: value
+ implicitHeight: text.implicitHeight
+ color: "#ff3"
+
+ Text {
+ id: text
+ width: parent.width
+ padding: 5
+ font.pixelSize: 20
+ text: value
+ }
+ }
+
+ section {
+ property: "section"
+
+ delegate: Rectangle {
+ objectName: section
+ width: parent.width
+ implicitHeight: text.implicitHeight
+ color: "#3ff"
+
+ Text {
+ id: text
+ width: parent.width
+ padding: 5
+ font.pixelSize: 20
+ text: section
+ wrapMode: Text.Wrap
+ }
+ }
+ }
+
+ model: ListModel {
+ ListElement { value: "Element1"; section: "Section1" }
+ ListElement { value: "Element2"; section: "Section1" }
+ ListElement { value: "Element3"; section: "Section1" }
+ ListElement { value: "Element4"; section: "Section2" }
+ ListElement { value: "Element5"; section: "Section2" }
+ ListElement { value: "Element6"; section: "Section2" }
+ ListElement { value: "Element7"; section: "Section2" }
+ ListElement { value: "Element8"; section: "Section3" }
+ ListElement { value: "Element9"; section: "Section3" }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp
index 08b03e19d0..684a12160b 100644
--- a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp
+++ b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp
@@ -53,6 +53,7 @@ private slots:
void pullbackSparseList();
void highlightWithBound();
void sectionIsCompatibleWithBoundComponents();
+ void sectionGeometryChange();
private:
void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to);
@@ -960,6 +961,33 @@ void tst_QQuickListView2::sectionIsCompatibleWithBoundComponents()
QTRY_COMPARE(listView->currentSection(), "42");
}
+void tst_QQuickListView2::sectionGeometryChange()
+{
+ QScopedPointer<QQuickView> window(createView());
+ QTRY_VERIFY(window);
+ window->setSource(testFileUrl("sectionGeometryChange.qml"));
+ window->show();
+ QVERIFY(QTest::qWaitForWindowExposed(window.data()));
+
+ QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
+ QTRY_VERIFY(listview);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem);
+ QVERIFY(QQuickTest::qWaitForPolish(listview));
+
+ QQuickItem *section1 = findItem<QQuickItem>(contentItem, "Section1");
+ QVERIFY(section1);
+ QQuickItem *element1 = findItem<QQuickItem>(contentItem, "Element1");
+ QVERIFY(element1);
+
+ QCOMPARE(element1->y(), section1->y() + section1->height());
+
+ // Update the height of the section delegate and verify that the next element is not overlapping
+ section1->setHeight(section1->height() + 10);
+ QTRY_COMPARE(element1->y(), section1->y() + section1->height());
+}
+
QTEST_MAIN(tst_QQuickListView2)
#include "tst_qquicklistview2.moc"