Skip to content

Migrate RadioSetupDialog to PersistentDialog (#2679 follow-up 3/3) #2769

Description

@ten9876

Context

Part of #2679 (umbrella PersistentDialog migrations). Reference implementation: PR #2742 (migrated ProfileImportExportDialog).

Ordering note: the umbrella issue ordered this one LAST because of size — `RadioSetupDialog.cpp` is 4405 lines, by far the largest of the four migration targets. Do #2767 (PropDashboardDialog) and #2768 (TxBandDialog) first to validate the recipe on simpler dialogs before tackling this one.

What to do

Migrate `src/gui/RadioSetupDialog.{cpp,h}` from `QDialog` to inherit from `PersistentDialog`, following the recipe from PR #2742.

File sizes (for context):

  • `RadioSetupDialog.cpp` — 4405 lines (many tabs: Audio, Network, RX, TX, GPS, Calibration, etc.)
  • `RadioSetupDialog.h` — 124 lines

Recipe (same as PR #2742, applied to a bigger surface)

  1. Header — replace `: public QDialog` with `: public PersistentDialog`, drop `m_titleBar`/`m_bodyLayout` members and any standalone `setFramelessMode` declaration.
  2. Constructor — change initializer list to `: PersistentDialog("Radio Setup", "RadioSetupDialogGeometry", parent)`, drop the manual frameless-chrome setup, build dialog content into `bodyWidget()` instead of a hand-rolled body widget. The `QTabWidget` and all tab-builder calls stay unchanged — just parented to `bodyWidget()` now.
  3. Drop the standalone `setFramelessMode` method.
  4. `closeEvent` — forward to `PersistentDialog::closeEvent`.
  5. `MainWindow.cpp` — change the lazy-construct block at line 6263-6265 to `showOrRaisePersistent(m_radioSetupDialog, &m_radioModel, m_audio, &m_tgxlConn, &m_pgxlConn, &m_antennaGenius)`. Note: the existing block also wires three signals (`txBandSettingsRequested`, `serialSettingsChanged`, `sliceLetterDisplayModeChanged`) — those connections need to land AFTER the construct. Use the `wasFresh` capture pattern from PersistentDialog migrations: four remaining dialogs + wasFresh comment polish #2679's polish item to attach signals exactly once on creation:
    const bool wasFresh = !m_radioSetupDialog;
    showOrRaisePersistent(m_radioSetupDialog, ...);
    if (wasFresh && m_radioSetupDialog) {
        connect(m_radioSetupDialog, &RadioSetupDialog::txBandSettingsRequested, ...);
        connect(m_radioSetupDialog, &RadioSetupDialog::serialSettingsChanged, ...);
        connect(m_radioSetupDialog, &RadioSetupDialog::sliceLetterDisplayModeChanged, ...);
    }
  6. `MainWindow.cpp` — remove the `qobject_cast` branch from `setFramelessWindow()` — base class auto-propagates.
  7. `MainWindow.h` — change `QPointer m_radioSetupDialog;` at line 493 to `QPointer m_radioSetupDialog;`.

AppSettings geometry key

Use `RadioSetupDialogGeometry` (PascalCase).

Acceptance criteria

  • `RadioSetupDialog` inherits from `PersistentDialog`.
  • `m_radioSetupDialog` is typed `QPointer` (no `QDialog` fallback).
  • Lazy-construct site uses `showOrRaisePersistent` with `wasFresh` capture for signal wiring.
  • `setFramelessWindow()` no longer has an explicit `qobject_cast` branch.
  • Geometry persists across launches under AppSettings key `RadioSetupDialogGeometry`.
  • All tabs continue to function: Audio, Network, RX, TX (Tune Mode, RFPower, ATU), GPS, Calibration, Themes (slice letter display + others), etc.
  • No behavior change in individual tab content — just the outer chrome + lazy-construct + geometry persistence.

Risk

  • Largest of the four migrations. Many tabs to regression-test. Suggested smoke-test sequence:
    1. Open Radio Setup → click through every tab → confirm no layout breakage.
    2. Edit one setting in each tab and confirm the radio receives the command (Audio gain, Network port, RX antenna alias, TX Tune Mode, GPS reset, Calibration osc adjust, Themes slice letter toggle).
    3. Close and re-open → confirm geometry persists at last position/size.
    4. Toggle View → Use Frameless Windows → confirm Radio Setup follows.

Pickup

AetherClaude-eligible but the largest single migration. Do #2767 and #2768 first to validate the recipe and confirm `showOrRaisePersistent` + `wasFresh` patterns are well-shaken. Once both ship, this one's just "same recipe, larger surface, more tabs to test."

Once this lands, the entire umbrella #2679 can close and the explicit-cast block at `MainWindow.cpp:11541-11597` collapses to zero remaining dialogs.

73, Jeremy KK7GWY & Claude (AI dev partner)

Metadata

Metadata

Assignees

No one assigned

    Labels

    GUIUser interfaceenhancementImprovement to existing featuremaintainer-reviewRequires maintainer review before any action is takenrefactorCode cleanup, restructuring, or consolidation — no user-visible behavior change

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions