diff options
| author | Alexey Zerkin <alexey.zerkin@qt.io> | 2026-03-20 10:58:23 +0200 |
|---|---|---|
| committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2026-04-29 16:39:38 +0000 |
| commit | 768e286ed15e8d7323122a25fc330d04ca048009 (patch) | |
| tree | db5713fd8aa9c706fd7fe729126b1709a18db41a | |
| parent | 7416a4ca2d1fad2edb3fb8c1d1077505e2f7b729 (diff) | |
Remove margins added by the helper to size hints of FlexBoxLayoutItem
QQuickLayout::effectiveSizeHints_helper() adds margins to the size hints,
which are not needed in FlexBoxLayoutItem case as the item is managed
by the Yoga layout library.
Fixes: QTBUG-142153
Pick-to: 6.10
Change-Id: Ibd243a375c0f459770688250606462485666a282
Reviewed-by: SanthoshKumar Selvaraj <santhosh.kumar.selvaraj@qt.io>
(cherry picked from commit 8ea218874eb058f1294c56ed64f705a422aa6562)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
| -rw-r--r-- | src/quicklayouts/qquickflexboxlayoutengine.cpp | 33 | ||||
| -rw-r--r-- | src/quicklayouts/qquickflexboxlayoutitem_p.h | 1 | ||||
| -rw-r--r-- | tests/auto/quick/qquicklayouts/data/tst_flexboxlayout.qml | 52 |
3 files changed, 77 insertions, 9 deletions
diff --git a/src/quicklayouts/qquickflexboxlayoutengine.cpp b/src/quicklayouts/qquickflexboxlayoutengine.cpp index d6d2451459..3fc29b5eb6 100644 --- a/src/quicklayouts/qquickflexboxlayoutengine.cpp +++ b/src/quicklayouts/qquickflexboxlayoutengine.cpp @@ -73,6 +73,15 @@ void QQuickFlexboxLayoutEngine::collectItemSizeHints(QQuickFlexboxLayoutItem *fl if (!info) return; + // remove margins from the size added by the helper + auto m = info->qMargins(); + const QSizeF margins{m.left() + m.right(), m.top() + m.bottom()}; + flexItem->cachedItemSizeHints().margins = margins; // save margins for later use + + QSizeF noMarginsHints[Qt::NSizeHints]; + for (int i = 0; i < Qt::NSizeHints; ++i) + noMarginsHints[i] = sizeHints[i] - margins; + // Set layout margins to the flex item (Layout.margins) if (info->isMarginsSet()) flexItem->setFlexMargin(QQuickFlexboxLayout::EdgeAll, info->margins()); @@ -103,8 +112,8 @@ void QQuickFlexboxLayoutEngine::collectItemSizeHints(QQuickFlexboxLayoutItem *fl // If the Layout.fillHeight not been set, the preferred height // will be set as height if (!info->fillHeight()) - flexItem->setHeight(sizeHints[Qt::PreferredSize].height()); - flexItem->setFlexBasis(sizeHints[Qt::PreferredSize].width(), !info->fillWidth()); + flexItem->setHeight(noMarginsHints[Qt::PreferredSize].height()); + flexItem->setFlexBasis(noMarginsHints[Qt::PreferredSize].width(), !info->fillWidth()); // Set child item to grow on main-axis (i.e. the flex // direction) flexItem->setItemGrowAlongMainAxis(info->fillWidth() ? 1.0f : 0.0f); @@ -116,8 +125,8 @@ void QQuickFlexboxLayoutEngine::collectItemSizeHints(QQuickFlexboxLayoutItem *fl // If the Layout.fillWidth not been set, the preferred width // will be set as width if (!info->fillWidth()) - flexItem->setWidth(sizeHints[Qt::PreferredSize].width()); - flexItem->setFlexBasis(sizeHints[Qt::PreferredSize].height(), !info->fillHeight()); + flexItem->setWidth(noMarginsHints[Qt::PreferredSize].width()); + flexItem->setFlexBasis(noMarginsHints[Qt::PreferredSize].height(), !info->fillHeight()); // Set child item to grow on main-axis (i.e. the flex // direction) flexItem->setItemGrowAlongMainAxis(info->fillHeight() ? 1.0f : 0.0f); @@ -175,8 +184,13 @@ QSizeF QQuickFlexboxLayoutEngine::sizeHint(Qt::SizeHint whichSizeHint) const const int count = itemCount(); for (int i = 0; i < count; ++i) { SizeHints &hints = cachedItemSizeHints(i); + + QSizeF noMarginsHints[Qt::NSizeHints]; + for (int i = 0; i < Qt::NSizeHints; ++i) + noMarginsHints[i] = hints.array[i] - hints.margins; + auto &flexLayoutItem = m_flexLayoutItems.at(i); - flexLayoutItem->setMinSize(hints.min()); + flexLayoutItem->setMinSize(noMarginsHints[Qt::MinimumSize]); if (flexLayoutItem->isFlexBasisUndefined()) { // If flex basis is undefined and item is still stretched, it // meant the flex child item has a const width or height but @@ -191,16 +205,16 @@ QSizeF QQuickFlexboxLayoutEngine::sizeHint(Qt::SizeHint whichSizeHint) const flexLayoutItem->resetSize(); if (qFlexLayout->direction() == QQuickFlexboxLayout::Row || qFlexLayout->direction() == QQuickFlexboxLayout::RowReverse) { - flexLayoutItem->setWidth(hints.pref().width()); + flexLayoutItem->setWidth(noMarginsHints[Qt::PreferredSize].width()); } else { - flexLayoutItem->setHeight(hints.pref().height()); + flexLayoutItem->setHeight(noMarginsHints[Qt::PreferredSize].height()); } } } else { - flexLayoutItem->setSize(hints.pref()); + flexLayoutItem->setSize(noMarginsHints[Qt::PreferredSize]); } } - flexLayoutItem->setMaxSize(hints.max()); + flexLayoutItem->setMaxSize(noMarginsHints[Qt::MaximumSize]); // The preferred size, minimum and maximum size of the parent item // will be calculated as follows // If no wrap enabled in the flex layout: @@ -312,6 +326,7 @@ void QQuickFlexboxLayoutEngine::invalidateItemSizeHint(QQuickItem *item) hints.min() = QSizeF(); hints.pref() = QSizeF(); hints.max() = QSizeF(); + hints.margins = {0,0}; } } diff --git a/src/quicklayouts/qquickflexboxlayoutitem_p.h b/src/quicklayouts/qquickflexboxlayoutitem_p.h index d0b1b7deb9..f1c8530e49 100644 --- a/src/quicklayouts/qquickflexboxlayoutitem_p.h +++ b/src/quicklayouts/qquickflexboxlayoutitem_p.h @@ -27,6 +27,7 @@ struct SizeHints { inline QSizeF &pref() { return array[Qt::PreferredSize]; } inline QSizeF &max() { return array[Qt::MaximumSize]; } QSizeF array[Qt::NSizeHints]; + QSizeF margins{0,0}; }; class QQuickFlexboxLayoutItem diff --git a/tests/auto/quick/qquicklayouts/data/tst_flexboxlayout.qml b/tests/auto/quick/qquicklayouts/data/tst_flexboxlayout.qml index 5334f7a977..e5fdbbfc99 100644 --- a/tests/auto/quick/qquicklayouts/data/tst_flexboxlayout.qml +++ b/tests/auto/quick/qquicklayouts/data/tst_flexboxlayout.qml @@ -911,5 +911,57 @@ Item { compare(flexboxLayout.Layout.maximumWidth, 300 + 5) compare(flexboxLayout.Layout.maximumHeight, 300 + 5) } + + function test_margins() { + let flexboxLayout = createTemporaryObject(dynamicFlexboxLayoutComponent, container) + waitForItemPolished(flexboxLayout) + + compare(flexboxLayout.implicitWidth, 0) + compare(flexboxLayout.implicitHeight, 0) + compare(flexboxLayout.Layout.minimumWidth, 0) + compare(flexboxLayout.Layout.minimumHeight, 0) + + let item1 = flexItem.createObject(flexboxLayout) + waitForItemPolished(flexboxLayout) + compare(item1.width, 20) + compare(item1.height, 20) + // item2 has no margins + compare(flexboxLayout.implicitWidth, 20) + compare(flexboxLayout.implicitHeight, 20) + compare(flexboxLayout.Layout.minimumWidth, 0) + compare(flexboxLayout.Layout.minimumHeight, 0) + // add margins + item1.Layout.margins = 7 + waitForItemPolished(flexboxLayout) + compare(item1.width, 20) + compare(item1.height, 20) + // margins affect the implicit size of the layout itself + // item1 (20 + 2 * item1.Layout.margins) + compare(flexboxLayout.implicitWidth, 34) + compare(flexboxLayout.implicitHeight, 34) + compare(flexboxLayout.Layout.minimumWidth, 14) + compare(flexboxLayout.Layout.minimumHeight, 14) + + + let item2 = flexItem.createObject(flexboxLayout) + waitForItemPolished(flexboxLayout) + compare(item2.width, 20) + compare(item2.height, 20) + // item2 has no margins + compare(flexboxLayout.implicitWidth, 54) + compare(flexboxLayout.implicitHeight, 34) + compare(flexboxLayout.Layout.minimumWidth, 14) + compare(flexboxLayout.Layout.minimumHeight, 14) + // add margins + item2.Layout.leftMargin = 17 + waitForItemPolished(flexboxLayout) + compare(item2.width, 20) + compare(item2.height, 20) + // item1 (34) + item2 (17 + 20 = 37) + compare(flexboxLayout.implicitWidth, 71) + compare(flexboxLayout.implicitHeight, 34) + compare(flexboxLayout.Layout.minimumWidth, 31) + compare(flexboxLayout.Layout.minimumHeight, 14) + } } } |
