Skip to content

fix(wave): persist WaveApplet drawer collapsed state across restarts#2827

Merged
jensenpat merged 1 commit into
aethersdr:mainfrom
chibondking:fix/wave-applet-drawer-state-persistence
May 21, 2026
Merged

fix(wave): persist WaveApplet drawer collapsed state across restarts#2827
jensenpat merged 1 commit into
aethersdr:mainfrom
chibondking:fix/wave-applet-drawer-state-persistence

Conversation

@chibondking

Copy link
Copy Markdown
Collaborator

After double-clicking the Waveform applet to hide the View/Zoom/FPS/Window controls, restarting AetherSDR would re-open the drawer and restore the taller expanded size — ignoring both the collapsed state and the compacted height the user had arranged.

──────────────────────────────────────────────────────────────────────────── Root cause
──────────────────────────────────────────────────────────────────────────── WaveApplet::WaveApplet() ended with a hardcoded setSettingsExpanded(true) regardless of any saved state. Additionally, setSettingsExpanded() never wrote the new state to AppSettings, so there was nothing to restore even if the read-side had been wired up.

The compact height is fully derived from sizeHint() / minimumSizeHint(), which already account for drawer visibility — so no separate height key is needed. Restoring the drawer state at startup is sufficient to restore the correct size.

──────────────────────────────────────────────────────────────────────────── Fix
──────────────────────────────────────────────────────────────────────────── setSettingsExpanded(): write WaveApplet_DrawerExpanded ("True"/"False") to AppSettings and call save() whenever the drawer is toggled.

Constructor: read WaveApplet_DrawerExpanded (default "True" so existing users whose setting file predates this fix start expanded as before) and pass the result to setSettingsExpanded() instead of the hardcoded true.

──────────────────────────────────────────────────────────────────────────── Files changed
──────────────────────────────────────────────────────────────────────────── src/gui/WaveApplet.cpp
— setSettingsExpanded(): save WaveApplet_DrawerExpanded on every toggle
— WaveApplet(): read saved drawer state instead of hardcoding expanded

──────────────────────────────────────────────────────────────────────────── Testing notes
────────────────────────────────────────────────────────────────────────────

  1. Open AetherSDR; confirm the Waveform applet starts with controls visible.
  2. Double-click the applet body to collapse the drawer.
  3. Resize the applet to the desired compact height.
  4. Restart AetherSDR.
  5. Expected: drawer remains hidden; applet height matches the collapsed size.
  6. Re-expand with another double-click; restart again.
  7. Expected: drawer is open on next launch.

…(#XXXX)

After double-clicking the Waveform applet to hide the View/Zoom/FPS/Window
controls, restarting AetherSDR would re-open the drawer and restore the
taller expanded size — ignoring both the collapsed state and the compacted
height the user had arranged.

────────────────────────────────────────────────────────────────────────────
Root cause
────────────────────────────────────────────────────────────────────────────
`WaveApplet::WaveApplet()` ended with a hardcoded `setSettingsExpanded(true)`
regardless of any saved state. Additionally, `setSettingsExpanded()` never
wrote the new state to `AppSettings`, so there was nothing to restore even
if the read-side had been wired up.

The compact height is fully derived from `sizeHint()` / `minimumSizeHint()`,
which already account for drawer visibility — so no separate height key is
needed. Restoring the drawer state at startup is sufficient to restore the
correct size.

────────────────────────────────────────────────────────────────────────────
Fix
────────────────────────────────────────────────────────────────────────────
`setSettingsExpanded()`: write `WaveApplet_DrawerExpanded` ("True"/"False")
to `AppSettings` and call `save()` whenever the drawer is toggled.

Constructor: read `WaveApplet_DrawerExpanded` (default "True" so existing
users whose setting file predates this fix start expanded as before) and
pass the result to `setSettingsExpanded()` instead of the hardcoded `true`.

────────────────────────────────────────────────────────────────────────────
Files changed
────────────────────────────────────────────────────────────────────────────
src/gui/WaveApplet.cpp
  — setSettingsExpanded(): save WaveApplet_DrawerExpanded on every toggle
  — WaveApplet(): read saved drawer state instead of hardcoding expanded

────────────────────────────────────────────────────────────────────────────
Testing notes
────────────────────────────────────────────────────────────────────────────
1. Open AetherSDR; confirm the Waveform applet starts with controls visible.
2. Double-click the applet body to collapse the drawer.
3. Resize the applet to the desired compact height.
4. Restart AetherSDR.
5. Expected: drawer remains hidden; applet height matches the collapsed size.
6. Re-expand with another double-click; restart again.
7. Expected: drawer is open on next launch.
@chibondking

Copy link
Copy Markdown
Collaborator Author

@AetherClaude thoughts on this particular PR?

@aethersdr-agent

Copy link
Copy Markdown
Contributor

Confirmed the diagnosis by reading src/gui/WaveApplet.cpp:

  • The constructor ends with a hardcoded setSettingsExpanded(true); (line 171), overriding any prior state at every launch.
  • setSettingsExpanded() (line 333) only flips visibility and rebuilds geometry — it never touches AppSettings, so even if the read side were wired up there'd be nothing to read.

The rest of the applet already uses the auto& settings = AppSettings::instance(); settings.setValue(...); settings.save(); pattern (see the View / Zoom / FPS / Window handlers), so the drawer toggle should follow suit. Because sizeHint() / minimumSizeHint() already conditionalize on m_settingsDrawer->isHidden(), restoring just the boolean is enough — the compact height falls out automatically. Defaulting the read to "True" preserves behavior for users whose settings file predates the fix.

Suggested patch:

// In WaveApplet::WaveApplet(...), replace the hardcoded expand near line 171:
const bool drawerExpanded = AppSettings::instance()
    .value("WaveApplet_DrawerExpanded", "True").toString()
    .compare("True", Qt::CaseInsensitive) == 0;
setSettingsExpanded(drawerExpanded);
setMinimumHeight(minimumSizeHint().height());

// In WaveApplet::setSettingsExpanded(bool expanded), persist on every change:
void WaveApplet::setSettingsExpanded(bool expanded)
{
    if (!m_settingsDrawer)
        return;

    const bool currentlyExpanded = !m_settingsDrawer->isHidden();
    if (currentlyExpanded == expanded)
        return;

    m_settingsDrawer->setVisible(expanded);
    setMinimumHeight(minimumSizeHint().height());
    updateGeometry();
    adjustSize();
    if (auto* p = parentWidget())
        p->updateGeometry();

    auto& settings = AppSettings::instance();
    settings.setValue("WaveApplet_DrawerExpanded",
                      expanded ? QStringLiteral("True") : QStringLiteral("False"));
    settings.save();
}

Two small notes:

  1. Writing inside setSettingsExpanded() rather than at the toggle call site means any future caller (e.g. a menu action or keyboard shortcut) gets persistence for free, and the early-return at line 339 guarantees we never write on a no-op transition.
  2. The "True"/"False" string convention matches how AppSettings is used elsewhere in this repo for boolean-ish keys, which keeps the settings file uniform.

A maintainer can authorize the orchestrator to land this fix by adding the aetherclaude-eligible label.

73, Jeremy KK7GWY & Claude (AI dev partner)

@chibondking chibondking added the aetherclaude-eligible Issue approved for AetherClaude automated agent label May 18, 2026
@chibondking

Copy link
Copy Markdown
Collaborator Author

@AetherClaude label applied for your takeover.

@aethersdr-agent

Copy link
Copy Markdown
Contributor

Re-read src/gui/WaveApplet.cpp — the diagnosis lines up exactly:

  • Line 171: constructor ends with a hardcoded setSettingsExpanded(true); followed by setMinimumHeight(minimumSizeHint().height());. No read of saved state.
  • Lines 333–348: setSettingsExpanded() toggles visibility, recomputes geometry, and returns early on a no-op transition (line 339), but never persists anything.
  • Lines 180–196: sizeHint() / minimumSizeHint() already key off m_settingsDrawer->isHidden(), so once the boolean is restored the compact height falls out for free — no separate height key needed.
  • Surrounding handlers (View, Zoom, FPS, Window — lines 228–230, 259–261, 290–292, 324–326) all use auto& settings = AppSettings::instance(); settings.setValue(...); settings.save();, so the drawer toggle should follow the same pattern.

One small wrinkle worth calling out: on a fresh construction the drawer's QFrame is visible by default, so calling setSettingsExpanded(true) from the constructor hits the early-return at line 339 and skips the setMinimumHeight(...) inside. Today that's masked by the explicit setMinimumHeight(minimumSizeHint().height()); on line 172 — and the patch below keeps that explicit call, so the no-op-on-restore case stays correct.

Proposed patch:

// src/gui/WaveApplet.cpp — replace the hardcoded expand near line 171:
const bool drawerExpanded = AppSettings::instance()
    .value("WaveApplet_DrawerExpanded", "True").toString()
    .compare("True", Qt::CaseInsensitive) == 0;
setSettingsExpanded(drawerExpanded);
setMinimumHeight(minimumSizeHint().height());

// src/gui/WaveApplet.cpp — persist in setSettingsExpanded():
void WaveApplet::setSettingsExpanded(bool expanded)
{
    if (!m_settingsDrawer)
        return;

    const bool currentlyExpanded = !m_settingsDrawer->isHidden();
    if (currentlyExpanded == expanded)
        return;

    m_settingsDrawer->setVisible(expanded);
    setMinimumHeight(minimumSizeHint().height());
    updateGeometry();
    adjustSize();
    if (auto* p = parentWidget())
        p->updateGeometry();

    auto& settings = AppSettings::instance();
    settings.setValue("WaveApplet_DrawerExpanded",
                      expanded ? QStringLiteral("True") : QStringLiteral("False"));
    settings.save();
}

Two notes:

  1. Persisting inside setSettingsExpanded() (rather than at the double-click call site at line 176) means any future caller — menu action, keyboard shortcut, programmatic toggle — gets persistence for free. The early-return at line 339 guarantees we never write on a no-op, so the constructor's restoring call won't dirty AppSettings on launch.
  2. The "True"/"False" string convention matches how the rest of this repo serializes boolean-ish keys to AppSettings, keeping the settings file uniform.

The aetherclaude-eligible label is already applied — the orchestrator will pick this up on the next webhook cycle and open the PR.

73, Jeremy KK7GWY & Claude (AI dev partner)

@aethersdr-agent aethersdr-agent Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good — small, well-scoped fix that does exactly what the description claims.

Verified:

  • Uses AppSettings with the established "True"/"False" string convention (matches TciApplet.cpp:195, VfoWidget.cpp:2131, etc.).
  • Default of "True" preserves prior behavior for existing users whose settings predate this fix.
  • The save happens behind the early-return guard in setSettingsExpanded() (line 339-340), so toggling to the same state is a no-op — no spurious writes.
  • Relying on sizeHint() / minimumSizeHint() to derive the compact height is correct here (lines 180-196 already key off m_settingsDrawer->isHidden()), so a separate height key is genuinely unnecessary.
  • No null deref risk — setSettingsExpanded() already guards m_settingsDrawer, and AppSettings::instance() is the standard singleton accessor used throughout.

Thanks @chibondking — nicely diagnosed (the asymmetric read/write was a real gap) and the patch stays inside WaveApplet.cpp with no header churn.

@jensenpat jensenpat left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Risks: None significant. Doesn't touch slice 0 RX flow, threading, or protocol. Pure UI persistence. save() on every toggle is fine — toggling the drawer is a user-initiated rare event, not a hot path.

@jensenpat jensenpat merged commit 93f5b23 into aethersdr:main May 21, 2026
5 checks passed
G6PWY-Chris pushed a commit to G6PWY-Chris/AetherSDR that referenced this pull request Jun 22, 2026
…ethersdr#2827)

After double-clicking the Waveform applet to hide the
View/Zoom/FPS/Window controls, restarting AetherSDR would re-open the
drawer and restore the taller expanded size — ignoring both the
collapsed state and the compacted height the user had arranged.


────────────────────────────────────────────────────────────────────────────
Root cause

────────────────────────────────────────────────────────────────────────────
`WaveApplet::WaveApplet()` ended with a hardcoded
`setSettingsExpanded(true)` regardless of any saved state. Additionally,
`setSettingsExpanded()` never wrote the new state to `AppSettings`, so
there was nothing to restore even if the read-side had been wired up.

The compact height is fully derived from `sizeHint()` /
`minimumSizeHint()`, which already account for drawer visibility — so no
separate height key is needed. Restoring the drawer state at startup is
sufficient to restore the correct size.


────────────────────────────────────────────────────────────────────────────
Fix

────────────────────────────────────────────────────────────────────────────
`setSettingsExpanded()`: write `WaveApplet_DrawerExpanded`
("True"/"False") to `AppSettings` and call `save()` whenever the drawer
is toggled.

Constructor: read `WaveApplet_DrawerExpanded` (default "True" so
existing users whose setting file predates this fix start expanded as
before) and pass the result to `setSettingsExpanded()` instead of the
hardcoded `true`.


────────────────────────────────────────────────────────────────────────────
Files changed

────────────────────────────────────────────────────────────────────────────
src/gui/WaveApplet.cpp
— setSettingsExpanded(): save WaveApplet_DrawerExpanded on every toggle
  — WaveApplet(): read saved drawer state instead of hardcoding expanded


────────────────────────────────────────────────────────────────────────────
Testing notes

────────────────────────────────────────────────────────────────────────────
1. Open AetherSDR; confirm the Waveform applet starts with controls
visible.
2. Double-click the applet body to collapse the drawer.
3. Resize the applet to the desired compact height.
4. Restart AetherSDR.
5. Expected: drawer remains hidden; applet height matches the collapsed
size.
6. Re-expand with another double-click; restart again.
7. Expected: drawer is open on next launch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

aetherclaude-eligible Issue approved for AetherClaude automated agent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants