aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2021-01-11 14:44:14 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-01-15 09:46:10 +0000
commit0b5ae19f733c7d59e6138c677fe432a0e6f25938 (patch)
tree55a8effe84e43c9455ec6c396a142db5337ffc73
parent0c3866a5ba406fe7d04ec19cbf8378e9b0150fb0 (diff)
QuickLayouts: fix crash when layout width depends on parent width
Some tricky cases of setting layout width based on parent layout width were leading to infinite recursive loop of layout size calculation (see the attached example in the related Jira task). Initially the QQuickGridLayoutBase::rearrange() method already had a recurse check, but it seemed to happen too late, so that the recursive calls kept happening from the ensureLayoutItemsUpdated() calls. This commit moves the recursion check up, so that it's actually executed before we have a chance to get to the next level of recursion. Fixes: QTBUG-87253 Change-Id: I473ee219e7b5b13547e33ebbd3a6d884de2c7d45 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io> (cherry picked from commit 4f8041b01445fd4eec0beb133719645d00d0b2ac) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/imports/layouts/qquicklinearlayout.cpp4
-rw-r--r--tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml37
2 files changed, 39 insertions, 2 deletions
diff --git a/src/imports/layouts/qquicklinearlayout.cpp b/src/imports/layouts/qquicklinearlayout.cpp
index 7626506c75..760700beaf 100644
--- a/src/imports/layouts/qquicklinearlayout.cpp
+++ b/src/imports/layouts/qquicklinearlayout.cpp
@@ -470,8 +470,6 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size)
if (!isReady())
return;
- ensureLayoutItemsUpdated();
-
qCDebug(lcQuickLayouts) << "QQuickGridLayoutBase::rearrange" << d->m_recurRearrangeCounter << this;
const auto refCounter = qScopeGuard([&d] {
--(d->m_recurRearrangeCounter);
@@ -483,6 +481,8 @@ void QQuickGridLayoutBase::rearrange(const QSizeF &size)
return;
}
+ ensureLayoutItemsUpdated();
+
d->m_rearranging = true;
qCDebug(lcQuickLayouts) << objectName() << "QQuickGridLayoutBase::rearrange()" << size;
Qt::LayoutDirection visualDir = effectiveLayoutDirection();
diff --git a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
index 85fe54eca6..87e0a01df2 100644
--- a/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
+++ b/tests/auto/quick/qquicklayouts/data/tst_rowlayout.qml
@@ -1233,5 +1233,42 @@ Item {
// DO NOT CRASH due to stack overflow (or loop endlessly due to updatePolish()/polish() loop)
}
+
+ Component {
+ id: layout_dependentWidth_QTBUG_87253_Component
+
+ RowLayout {
+ anchors.fill: parent;
+
+ RowLayout {
+ spacing: 10
+
+ Text {
+ id: btnOPE
+ text: qsTr("Ok")
+ Layout.fillWidth: true
+ Layout.preferredWidth: (parent.width - 20) / 2
+ }
+
+ Text {
+ id: btnSeeChanged
+ text: qsTr("Not Ok");
+ Layout.fillWidth: true
+ Layout.preferredWidth: (parent.width - 20) / 2
+ }
+ }
+ }
+ }
+
+ function test_dependentWidth_QTBUG_87253()
+ {
+ var warningMsg = new RegExp("Qt Quick Layouts: Detected recursive rearrange. "
+ + "Aborting after two iterations.")
+ for (var i = 0; i < 10; ++i) {
+ ignoreWarning(warningMsg)
+ }
+ var layout = createTemporaryObject(layout_dependentWidth_QTBUG_87253_Component, container)
+ waitForRendering(layout)
+ }
}
}