From 1604dc02a29c5dd032cf203bf91cca4bfe7b74c0 Mon Sep 17 00:00:00 2001 From: Malte Langkabel Date: Fri, 7 Aug 2026 19:28:15 +0200 Subject: [PATCH] measure the controls panel against its content, not its old geometry The previous fix went too far: it activated the panel's own layout before resizing, which lays the heading and the rows out inside the geometry left over from the previous context. The panel then took that stale frame as its answer and collapsed to almost nothing whenever the mode changed. Only the rows layout is activated now -- that part was right, and is what makes freshly added rows visible and so measurable. The size comes from layout()->totalSizeHint(), which says how big the content needs to be without reference to how big the panel currently is; setGeometry re-runs the outer layout afterwards on its own. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01YHcUerKAZKWNvSKJxYKbnG --- src/ui/ControlsPanel.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/ui/ControlsPanel.cpp b/src/ui/ControlsPanel.cpp index 7de9ed8..78f8898 100644 --- a/src/ui/ControlsPanel.cpp +++ b/src/ui/ControlsPanel.cpp @@ -239,27 +239,28 @@ void ControlsPanel::refit() { if (m_bandRect.isNull()) { return; } - // Both layouts, innermost first, and both invalidated before being re-run. Rows are - // created and destroyed wholesale, so the rows layout's cached size hint describes - // the previous context until it is discarded; asking the panel for its hint without - // this returns the size the last context needed, which is why a first selection - // used to draw a card one rebuild behind. - // - // The polish is part of the same problem: a freshly created label reports an - // unstyled size hint until the stylesheet has been applied to it, and the badge - // chips carry border and padding that change their width. + // Rows are torn down and rebuilt wholesale, and a widget added to a layout is only + // shown once that layout runs -- without this the new rows count for nothing and + // the card is measured for the context before it. The polish belongs to the same + // step: a freshly created label reports an unstyled size hint until the stylesheet + // has reached it, and the badge chips carry border and padding that change it. m_rows->ensurePolished(); m_rowsLayout->invalidate(); m_rowsLayout->activate(); + + // Deliberately not activating the panel's own layout here. That lays the heading + // and the rows out inside the geometry the panel still has from the previous + // context, which is the wrong frame of reference for choosing the new one. + // totalSizeHint answers "how big does this need to be" without reference to how big + // it currently is; setGeometry below then re-runs the outer layout on its own. layout()->invalidate(); - layout()->activate(); + const QSize needed = layout()->totalSizeHint(); const QRect band = m_bandRect.adjusted(kMarginPx, kMarginPx, -kMarginPx, -kMarginPx); if (band.width() <= 0 || band.height() <= 0) { return; } - const QSize hint = sizeHint(); - const int widthPx = qMin(hint.width(), band.width()); - const int heightPx = qMin(hint.height(), band.height()); + const int widthPx = qMin(needed.width(), band.width()); + const int heightPx = qMin(needed.height(), band.height()); // Left edge of the band, sitting on its bottom edge, so the panel grows upward as // rows are added (REQ-UI-CONTROLS-PANEL).