fix(vfo): fix QStackedWidget cross-tab height inflation via TabStack subclass#2821
fix(vfo): fix QStackedWidget cross-tab height inflation via TabStack subclass#2821NF0T wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Clean, minimal fix. The TabStack subclass is the correct approach — sizeHint() and minimumSizeHint() are virtual on QWidget, so polymorphic dispatch works even though m_tabStack remains typed as QStackedWidget* in the header. The null-guard against currentWidget() is appropriate. The class is placed at file scope alongside the existing TriBtn helper, matching local convention.
Root-cause analysis in the PR body is excellent — explaining why the previous setSizePolicy(Ignored, Ignored) loop couldn't possibly work (because QStackedLayout::sizeHint() calls widget->sizeHint() directly, bypassing the page's size policy) is the kind of write-up that makes this trivially reviewable.
One minor description nit: the body says "the now-ineffective sizePolicy loop in showTab() is removed," but the diff doesn't contain that removal — showTab() on main is already clean (no sizePolicy loop). Likely just a stale sentence in the description; no code action needed.
Thanks for the thorough fix and writeup, @NF0T.
…subclass QStackedLayout::sizeHint() returns the maximum height across all pages, not the current page's height. When the DSP tab is taller than the Mode tab (m_digContainer visible in DIGU/DIGL mode, ~41 px difference), VfoWidget::adjustSize() over-allocates height to m_tabStack, which QStackedWidget passes entirely to the Mode tab page. The Mode tab's VBoxLayout distributes the surplus into filterContainer (Preferred policy), producing a gap between the mode-row and filter-preset buttons. The previous attempt patched showTab() with a per-page setSizePolicy() loop, which does not affect QStackedLayout::sizeHint() — that function calls widget->sizeHint() on each page directly, bypassing size policy. The loop appeared to work only because initial testing used RADE (FDVU) mode, where m_digContainer is hidden, making both tabs the same height. The bug reproduced immediately in DIGU/DIGL mode and on any resize path that does not go through showTab(): modeChanged signal, setRadeActive(), diversity callbacks, and band-change-triggered syncFromSlice(). Fix: introduce TabStack, a QStackedWidget subclass that overrides sizeHint() and minimumSizeHint() to delegate to currentWidget() instead of the QStackedLayout maximum. Every existing adjustSize() / resize(sizeHint()) call site is now correct without modification. The sizePolicy loop in showTab() is removed as it was both ineffective and misleading. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
f44bc94 to
0735e75
Compare
Summary
Fixes the recurring gap between the mode-selection row and filter-preset buttons visible when the Mode tab is open in DIGU or DIGL mode, particularly after switching tabs, changing bands, activating RADE, or starting with RADE as the last-used mode.
Root cause
QStackedLayout::sizeHint()returns the maximum height across all pages, not the current page's height. When the DSP tab is taller than the Mode tab — which occurs in DIGU and DIGL mode becausem_digContainer(the DIGU offset control row) is visible, adding ~41 px —VfoWidget::adjustSize()over-allocates that height tom_tabStack. QStackedWidget hands the full allocation to the currently-displayed Mode tab page. The Mode tab's internal VBoxLayout distributes the surplus intofilterContainer(which hasQSizePolicy::Preferredand no fixed height), producing the gap between the mode buttons and the filter preset buttons.Why the previous fix was insufficient
An earlier attempt patched
showTab()with a per-pagesetSizePolicy(Ignored, Ignored)loop. This does not affectQStackedLayout::sizeHint()— that function callswidget->sizeHint()on each page directly, bypassing each page's size policy. The loop appeared to work because initial testing was performed in RADE (FDVU) mode, wherem_digContaineris hidden (isDigis false for FDV-family modes), making both tabs equal height. The bug was not structurally present in that test. It reproduced immediately under DIGU/DIGL mode and on any resize path that bypassesshowTab():modeChangedlambda, line 2619setRadeActive(), line 4024divBtntoggled, line 1023diversityChangedsignal, line 2664setDiversityAllowed(), line 2061Fix
Introduce
TabStack, aQStackedWidgetsubclass that overridessizeHint()andminimumSizeHint()to delegate tocurrentWidget()rather than theQStackedLayoutmaximum. The subclass is defined locally inVfoWidget.cpp; no header changes are required (m_tabStackremainsQStackedWidget*and the override dispatches polymorphically).The now-ineffective sizePolicy loop in
showTab()is removed. All existingadjustSize()andresize(sizeHint())call sites throughout the widget are correct without modification.Test plan
🤖 Generated with Claude Code