aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanthosh Kumar <santhosh.kumar.selvaraj@qt.io>2023-10-25 16:29:07 +0200
committerSanthosh Kumar <santhosh.kumar.selvaraj@qt.io>2023-12-21 17:27:29 +0100
commit9ad9d05f26184a79ad3fe09abdc662949088d19d (patch)
treedddee2d4bfacec95e9adbdcea77e778cd83b7f5e
parent321110041143065a6939b157a0e85510ec5a0841 (diff)
Fix binding loop and polish issue in quick layout
The quick layout item cause binding loop issue when layout item size were updated in-between polish. This has been fixed by not updating layout size hint during rearrange. But there is polish issue due to child item not being invalidated and this skips corresponding item box size calculation. This patch invalidate all the items in the rearrange list of the layout and finally, invalidate engine and layout. Fixes: QTBUG-117899 Fixes: QTBUG-118511 Pick-to: 6.7 6.6 6.5 Change-Id: I1e318335ce8b5268d878b48a02a089d703bb90ad Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r--src/quicklayouts/qquicklayout.cpp2
-rw-r--r--src/quicklayouts/qquicklinearlayout.cpp15
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml72
3 files changed, 81 insertions, 8 deletions
diff --git a/src/quicklayouts/qquicklayout.cpp b/src/quicklayouts/qquicklayout.cpp
index 5a6b30ff38..28a99ced9e 100644
--- a/src/quicklayouts/qquicklayout.cpp
+++ b/src/quicklayouts/qquicklayout.cpp
@@ -925,7 +925,7 @@ void QQuickLayout::geometryChange(const QRectF &newGeometry, const QRectF &oldGe
{
Q_D(QQuickLayout);
QQuickItem::geometryChange(newGeometry, oldGeometry);
- if (d->m_disableRearrange || !isReady())
+ if (invalidated() || d->m_disableRearrange || !isReady())
return;
qCDebug(lcQuickLayouts) << "QQuickLayout::geometryChange" << newGeometry << oldGeometry;
diff --git a/src/quicklayouts/qquicklinearlayout.cpp b/src/quicklayouts/qquicklinearlayout.cpp
index 31c1857d9f..e6c5a1261b 100644
--- a/src/quicklayouts/qquicklinearlayout.cpp
+++ b/src/quicklayouts/qquicklinearlayout.cpp
@@ -457,10 +457,6 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size)
return;
}
- // Should normally not be needed, but there might be an incoming window resize event that we
- // will process before we process updatePolish()
- ensureLayoutItemsUpdated(QQuickLayout::ApplySizeHints | QQuickLayout::Recursive);
-
d->m_rearranging = true;
qCDebug(lcQuickLayouts) << objectName() << "QQuickGridLayoutBase::rearrange()" << size;
Qt::LayoutDirection visualDir = effectiveLayoutDirection();
@@ -479,9 +475,14 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size)
d->engine.setGeometries(QRectF(QPointF(0,0), size), d->styleInfo);
d->m_rearranging = false;
- for (QQuickItem *invalid : std::as_const(d->m_invalidateAfterRearrange))
- invalidate(invalid);
- d->m_invalidateAfterRearrange.clear();
+ if (d->m_invalidateAfterRearrange.size() > 0) {
+ for (QQuickItem *invalid : std::as_const(d->m_invalidateAfterRearrange)) {
+ if (QQuickGridLayoutItem *layoutItem = d->engine.findLayoutItem(invalid))
+ layoutItem->invalidate();
+ }
+ invalidate();
+ d->m_invalidateAfterRearrange.clear();
+ }
}
/**********************************
diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
index 92ceb2e95a..2a3b5b10e3 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
@@ -1290,6 +1290,78 @@ Item {
}
Component {
+ id: sizeHintBindingLoopComp
+ Item {
+        id: root
+        anchors.fill: parent
+ property var customWidth: 100
+        RowLayout {
+            id: col
+ Item {
+                id: item
+                implicitHeight: 80
+                implicitWidth: Math.max(col2.implicitWidth, root.customWidth + 20)
+ ColumnLayout {
+                    id: col2
+                    width: parent.width
+                 Item {
+                        id: rect
+                        implicitWidth: root.customWidth
+                        implicitHeight: 80
+                   }
+                }
+            }
+ }
+ }
+ }
+
+ function test_sizeHintBindingLoopIssue() {
+ var item = createTemporaryObject(sizeHintBindingLoopComp, container)
+ waitForRendering(item)
+ item.customWidth += 10
+ waitForRendering(item)
+ verify(!BindingLoopDetector.bindingLoopDetected, "Detected binding loop")
+ BindingLoopDetector.reset()
+ }
+
+ Component {
+ id: polishLayoutItemComp
+ Item {
+ anchors.fill: parent
+ implicitHeight: contentLayout.implicitHeight
+ implicitWidth: contentLayout.implicitWidth
+ property alias textLayout: contentLayout
+ RowLayout {
+ width: parent.width
+ height: parent.height
+ ColumnLayout {
+ id: contentLayout
+ Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
+ Layout.maximumWidth: 200
+ Repeater {
+ model: 2
+ Text {
+ Layout.fillWidth: true
+ text: "This is a long text causing line breaks to show the bug."
+ wrapMode: Text.Wrap
+ }
+ }
+ Item {
+ Layout.fillHeight: true
+ }
+ }
+ }
+ }
+ }
+
+ function test_polishLayoutItemIssue() {
+ var rootItem = createTemporaryObject(polishLayoutItemComp, container)
+ waitForRendering(rootItem)
+ var textItem = rootItem.textLayout.children[1]
+ verify(textItem.y >= rootItem.textLayout.children[0].height)
+ }
+
+ Component {
id: rearrangeNestedLayouts_Component
RowLayout {
id: layout