diff options
author | Wang Chuan <ouchuanm@outlook.com> | 2022-03-27 15:19:11 +0800 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2023-04-19 14:49:42 +0000 |
commit | f9efa3469f9d4e5522b4b5744216b16e913a6fcc (patch) | |
tree | e85047db2e04b78a0e3b2b463805c124d79aeafe | |
parent | 6d5ed3c5857925411cc96e059f4b11ee785d297c (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.cpp | 8 | ||||
-rw-r--r-- | tests/auto/quick/qquicklistview2/data/sectionGeometryChange.qml | 58 | ||||
-rw-r--r-- | tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp | 28 |
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 §ion) 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" |