diff options
| author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2025-07-08 14:59:56 +0200 |
|---|---|---|
| committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2025-07-08 19:40:03 +0200 |
| commit | 9352ef3c167bf1edfc033f14027fe38df1b9bf17 (patch) | |
| tree | 34159df8321f953f8b44839b561bbfbb6a8de970 /src | |
| parent | ef75f234d2fc7125eddf8ab8c49d7a2f8ca4049f (diff) | |
Allow recursive layout of ApplicationWindow
The safe areas require recursive layouting of the ApplicationWindow
menu bar, header, and footer (in particular). We added guards preventing
that in 6dc95399797de4ec27984956df1fa587f4eb18ba, to fix QTBUG-87708,
but the fix for that can be in QQuickLayout itself.
Pick-to: 6.10
Task-number: QTBUG-87708
Change-Id: I0dc25d779fe76619591f35063826d50dff2e3d28
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io>
Diffstat (limited to 'src')
| -rw-r--r-- | src/quicklayouts/qquicklayout.cpp | 20 | ||||
| -rw-r--r-- | src/quicktemplates/qquickapplicationwindow.cpp | 21 |
2 files changed, 32 insertions, 9 deletions
diff --git a/src/quicklayouts/qquicklayout.cpp b/src/quicklayouts/qquicklayout.cpp index 3da13ba10a..0dd0d27eed 100644 --- a/src/quicklayouts/qquicklayout.cpp +++ b/src/quicklayouts/qquicklayout.cpp @@ -948,12 +948,30 @@ void QQuickLayout::itemChange(ItemChange change, const ItemChangeData &value) void QQuickLayout::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QQuickLayout); + qCDebug(lcQuickLayouts) << "QQuickLayout::geometryChange" + << oldGeometry << "-->" << newGeometry; + QQuickItem::geometryChange(newGeometry, oldGeometry); + if ((invalidated() && !qobject_cast<QQuickLayout *>(parentItem())) || d->m_disableRearrange || !isReady()) return; - qCDebug(lcQuickLayouts) << "QQuickLayout::geometryChange" << newGeometry << oldGeometry; + // The geometryChange call above might recursively update the + // geometry of this layout, via item change listeners, in which + // case the recursive call has already rearranged the layout for + // the new size. We don't want to rearrange here based on the old + // 'new geometry', as that would revert the most up to date layout. + const qreal w = d->width.valueBypassingBindings(); + const qreal h = d->height.valueBypassingBindings(); + const QSizeF currentSize(w, h); + if (currentSize != newGeometry.size()) { + qCDebug(lcQuickLayouts) << "QQuickItem::geometryChange resulted" + << "in size change from" << newGeometry.size() << "to" + << currentSize << "; layout should already be up to date."; + return; + } + rearrange(newGeometry.size()); } diff --git a/src/quicktemplates/qquickapplicationwindow.cpp b/src/quicktemplates/qquickapplicationwindow.cpp index 489dd48f47..871ae593ed 100644 --- a/src/quicktemplates/qquickapplicationwindow.cpp +++ b/src/quicktemplates/qquickapplicationwindow.cpp @@ -139,20 +139,25 @@ void QQuickApplicationWindowPrivate::updateHasBackgroundFlags() void QQuickApplicationWindowPrivate::relayout() { Q_Q(QQuickApplicationWindow); - if (!componentComplete || insideRelayout) + if (!componentComplete) return; + // Note: We track whether we are inside relayout, but we do + // allow nested relayouts, as those are necessary to compute + // the height and position of footers when using safe areas. QScopedValueRollback<bool> guard(insideRelayout, true); - qreal menuBarHeight = menuBar && menuBar->isVisible() ? menuBar->height() : 0; - qreal headerheight = header && header->isVisible() ? header->height() : 0; - qreal footerHeight = footer && footer->isVisible() ? footer->height() : 0; + // Re-evaluate component heights for each use, as they + // may change between each use due to recursive layouts. + auto menuBarHeight = [this]{ return menuBar && menuBar->isVisible() ? menuBar->height() : 0; }; + auto headerheight = [this]{ return header && header->isVisible() ? header->height() : 0; }; + auto footerHeight = [this]{ return footer && footer->isVisible() ? footer->height() : 0; }; control->setSize(q->size()); layoutItem(menuBar, 0, q->width()); - layoutItem(header, menuBarHeight, q->width()); - layoutItem(footer, control->height() - footerHeight, q->width()); + layoutItem(header, menuBarHeight(), q->width()); + layoutItem(footer, control->height() - footerHeight(), q->width()); if (background) { if (!hasBackgroundWidth && qFuzzyIsNull(background->x())) @@ -168,8 +173,8 @@ void QQuickApplicationWindowPrivate::relayout() auto *windowSafeArea = static_cast<QQuickSafeArea*>(qmlAttachedPropertiesObject<QQuickSafeArea>(q)); const auto inheritedMargins = windowSafeArea->margins(); controlSafeArea->setAdditionalMargins(QMarginsF( - 0, (menuBarHeight + headerheight) - inheritedMargins.top(), - 0, footerHeight - inheritedMargins.bottom())); + 0, (menuBarHeight() + headerheight()) - inheritedMargins.top(), + 0, footerHeight() - inheritedMargins.bottom())); } void QQuickApplicationWindowPrivate::itemGeometryChanged(QQuickItem *item, QQuickGeometryChange change, const QRectF &diff) |
