Extract TxBandDialog to its own class + migrate to PersistentDialog (#2768). Principle I.#2774
Conversation
…2768). Principle I. Phase A — extract the 119-line inline construction at MainWindow.cpp:6548 into src/gui/TxBandDialog.{cpp,h} as a real class, parameterized on RadioModel*. The active TX-profile is snapshotted into the window title at construction (WA_DeleteOnClose means the dialog is reconstructed on every open, so the title stays current without a profileChanged signal). Phase B — inherit from PersistentDialog so the geometry persists across launches under AppSettings key TxBandDialogGeometry, and the frameless title-bar / FramelessResizer plumbing comes from the base class. The lazy-construct site in MainWindow becomes a one-liner showOrRaisePersistent call, and the m_txBandDialog branch in setFramelessWindow() is removed because the m_persistentDialogs registry handles propagation. FlexLib semantics preserved verbatim — every transmit bandset / interlock bandset command (rfpower, tunepower, inhibit, hwalc_enabled, acc_tx_enabled, rca_txreq_enable, acc_txreq_enable, tx{1,2,3}_enabled) is sent exactly as the inline code did. Principle I: FlexLib is the protocol authority, and these are the canonical setter forms in transmit-bandset / interlock-bandset parsers — do not paraphrase. Follow-up to #2742 (ProfileImportExportDialog migration) and second of three under the #2679 umbrella (PropDashboardDialog #2767 first, RadioSetupDialog to follow). Blast radius: risk_score=0.363, 5 high-risk affected (top: AetherSDR::MainWindow::MainWindow, AetherSDR::AppSettings::instance, AetherSDR::MainWindow::buildMenuBar). All high-risk hits are structural bridges (MainWindow ctor, buildMenuBar, AppSettings) reached only through the existing setFramelessWindow + showOrRaisePersistent pattern that PR #2742 already validated; no new structural edges introduced. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
There was a problem hiding this comment.
Clean mechanical extraction — the new TxBandDialog mirrors the established ProfileManagerDialog / MemoryDialog pattern on top of PersistentDialog, and the removal of the inline setDialogFramelessMode(m_txBandDialog, on) call in setFramelessWindow is correct because frameless propagation now runs through m_persistentDialogs (MainWindow.cpp:11520) where showOrRaisePersistent registered the dialog. Geometry persistence under "TxBandDialogGeometry" is a nice free upgrade over the original setMinimumSize-only dialog. The behavior change worth flagging — same as the original, but now sticky — is that the title bakes activeProfile() at construction time, so the dialog can outlive a profile change with a stale (Current TX Profile: %1) string until close/reopen. Before, you also got the stale title since the dialog was reused, so this isn't a regression, just preserved behavior.
One minor observation:
TxBandDialog.cpp:18-22, 38-42— the null guards onmodelare dead code:showOrRaisePersistent(m_txBandDialog, &m_radioModel)always passes the address of aMainWindowmember, which can't be null. The otherRadioModel*-taking persistent dialogs (ProfileManagerDialog,MemoryDialog) don't bother. Not a bug, just unnecessary — consider dropping themodel ?ternary and the early-return, or change the parameter toRadioModel&to make non-null part of the type. Worth a minor follow-up at most.
CMakeLists.txt addition is fine (the existing list isn't strictly sorted, so no nit there).
Thanks @aethersdr-agent for the clean refactor.
Summary
Fixes #2768
What was changed
Extract TxBandDialog to its own class + migrate to PersistentDialog (#2768). Principle I.
Files modified
CMakeLists.txtsrc/gui/MainWindow.cppsrc/gui/MainWindow.hsrc/gui/TxBandDialog.cppsrc/gui/TxBandDialog.hGenerated by AetherClaude (automated agent for AetherSDR)