Skip to content

Reset RX slice tabs on disconnect#2279

Merged
ten9876 merged 2 commits intoten9876:mainfrom
rfoust:codex/issue-2254-rx-buttons
May 2, 2026
Merged

Reset RX slice tabs on disconnect#2279
ten9876 merged 2 commits intoten9876:mainfrom
rfoust:codex/issue-2254-rx-buttons

Conversation

@rfoust
Copy link
Copy Markdown
Contributor

@rfoust rfoust commented May 2, 2026

Bug

Fixes #2254.

The RX applet slice tab row was scoped to the process lifetime. After connecting to a radio with more slice capacity, disconnecting, then connecting to a smaller radio, the stale A-H buttons stayed in place because RxApplet::setMaxSlices() only created the row once and MainWindow's infoChanged initializer only ran once per process.

Fix

  • Add RxApplet::clearSliceButtons() to tear down the generated slice tab buttons and restore the static slice badge on disconnect.
  • Expose that through AppletPanel.
  • Replace the one-shot lambda capture in MainWindow with a per-connection member flag, reset it on disconnect, and let the next radio's infoChanged rebuild the row from its current maxSlices.
  • Guard the slice button click connection so rebuilding the row does not duplicate signal handlers.

Testing

Codex

Codex model used: GPT-5.

Dependency

For SmartLink/WAN sessions, this UI fix depends on #2278 so RadioModel emits connectionStateChanged(false) during Disconnect. Without #2278, the applet teardown hook is not reached on WAN disconnect. LAN disconnect/reconnect uses the normal model teardown path.

Copilot AI review requested due to automatic review settings May 2, 2026 10:48
@rfoust rfoust requested review from jensenpat and ten9876 as code owners May 2, 2026 10:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes the RX applet’s slice-tab UI so it can be torn down on disconnect and rebuilt for the next radio connection, instead of keeping the previous radio’s slice-capacity buttons alive for the lifetime of the process. It fits into the existing GUI/radio-model connection lifecycle by moving the tab-row initialization state from a one-shot lambda capture to per-connection state in MainWindow.

Changes:

  • Added RxApplet::clearSliceButtons() and exposed it through AppletPanel so disconnect handling can remove generated slice-tab buttons and restore the static badge.
  • Replaced the constructor-local one-shot initialization flag with a MainWindow member flag that is reset on disconnect and reused on the next connection.
  • Guarded the slice-button click signal wiring so rebuilding the row does not add duplicate handlers.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/gui/RxApplet.h Declares slice-button teardown API and tracking flag for click-signal wiring.
src/gui/RxApplet.cpp Implements guarded slice-button signal hookup and button-row teardown on disconnect.
src/gui/MainWindow.h Adds per-connection state for slice-tab initialization.
src/gui/MainWindow.cpp Reworks slice-tab initialization to use member state and clears tabs on disconnect.
src/gui/AppletPanel.h Exposes RX slice-button clearing through the panel interface.
src/gui/AppletPanel.cpp Forwards the new clear call to RxApplet.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/gui/MainWindow.cpp Outdated
Comment on lines +7117 to +7119
m_sliceTabsInitialized = false;
if (m_appletPanel) {
m_appletPanel->clearSliceButtons();
Comment thread src/gui/MainWindow.cpp Outdated
Comment on lines +2224 to +2230
if (m_sliceTabsInitialized || m_radioModel.model().isEmpty()) {
return;
}

m_appletPanel->setMaxSlices(m_radioModel.maxSlices());
m_appletPanel->updateSliceButtons(m_radioModel.slices(), m_activeSliceId);
initialized = true;
m_sliceTabsInitialized = true;
@aethersdr-agent
Copy link
Copy Markdown
Contributor

Hi @rfoust — thanks for the fix! Just a heads-up on the red ❌ you may have seen: this is not your code, and there's nothing for you to do.

What actually failed

The only failing check on f7243ba is the Cleanup artifacts job (specifically the "Delete artifacts" step) on workflow run 25250216095. That's a post-run housekeeping job that prunes old workflow artifacts via gh — it has zero interaction with the code under review. The Agent, Prepare, and Upload results steps in the same run all succeeded, and the meaningful checks (build, analyze (cpp)) were still in progress when this comment was generated. Those will report their own status when they finish.

So: this is CI infrastructure flake, not a regression introduced by your patch. No action needed from you on the red checkmark.

On the PR itself

The slice-tab teardown logic looks like a clean, targeted fix — resetting m_sliceTabsInitialized, calling AppletPanel::clearSliceButtons(), and the m_sliceButtonClicksConnected guard in RxApplet::setMaxSlices() all hang together nicely.

Two things worth flagging from Copilot's review that might be worth a follow-up (separate from CI):

  1. Disconnect signal coverage (src/gui/MainWindow.cpp:7119) — this teardown only fires on RadioModel::connectionStateChanged(false). Per the PR description, WAN/SmartLink disconnects don't currently emit that signal until Fix SmartLink disconnect teardown #2278 lands, so this PR's full benefit is gated on Fix SmartLink disconnect teardown #2278 (which is your other PR — perfect, you're already on it).

  2. maxSlices capacity sync (src/gui/MainWindow.cpp:2230) — the slice-tab init runs once on the first infoChanged. RadioModel::handleRadioStatus() can later raise maxSlices() when the radio reports a higher slices= value (src/models/RadioModel.cpp:3380-3386). If the initial guess is low, the UI stays stuck with too few buttons. Worth either re-running the sync when maxSlices() increases, or making setMaxSlices() idempotently rebuild. Up to you whether to address here or in a follow-up.

Thanks again for the careful work on this — and for picking up the SmartLink disconnect path in #2278 as well. 🙏

@rfoust
Copy link
Copy Markdown
Contributor Author

rfoust commented May 2, 2026

Addressed the capacity-sync review:

  • RxApplet::setMaxSlices() now rebuilds the slice tab row when the reported capacity changes, while remaining a no-op when the count is unchanged.
  • MainWindow now re-syncs slice tab capacity on each non-empty RadioModel::infoChanged instead of using a per-connection one-shot flag, so a later maxSlices() increase from live status can update the UI.
  • Removed the now-unneeded MainWindow slice-tabs initialized member.

The dependency note on #2278 still applies for SmartLink/WAN Disconnect, because this UI teardown needs RadioModel::connectionStateChanged(false).

Rebuilt successfully with:

cmake --build /private/tmp/AetherSDR-issue-2254-build -j8

Copy link
Copy Markdown
Contributor

@aethersdr-agent aethersdr-agent Bot left a comment

Choose a reason for hiding this comment

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

Thanks @rfoust — clean, focused fix. The approach makes sense: removing the one-shot initialized capture, making setMaxSlices() idempotent on matching counts and rebuild-on-mismatch, and tearing down the row in onConnectionStateChanged(false) is the right shape.

A couple of notes on the Copilot comments:

  • "Only initializes the slice-tab row on the first infoChanged" — I believe this is a false positive. The PR explicitly removes the initialized = false capture, so the lambda runs on every infoChanged. And RadioModel::handleRadioStatus() does emit infoChanged() (RadioModel.cpp:3469) after the slices= branch raises m_maxSlices (lines 3381–3386). With setMaxSlices() now rebuilding when m_sliceBtns.size() != maxSlices, a late capacity bump should propagate correctly. Worth confirming with a real radio that actually raises capacity post-info, but the wiring looks right.

  • WAN dependency on #2278 — valid, and you flagged it yourself in the PR body. Not a blocker for this PR since LAN disconnect/reconnect already exercises the new teardown path; merging only this one just leaves WAN unchanged from today's behavior, not worse.

Minor observations, none blocking:

  • clearSliceButtons() always sets m_sliceTabRow->setVisible(false) and m_sliceBadge->setVisible(true). For the inline (≤4) path the row was never visible to begin with, so the row line is a no-op — harmless, just slightly redundant.
  • m_sliceButtonClicksConnected guards the QButtonGroup::idClicked connection across rebuilds. That's correct because the group itself is permanent and only its buttons change, so the existing slot continues to work after a rebuild. Good catch.
  • Button cleanup (removeButtondelete btn) is safe: deleting the widget detaches it from any layout/parent, and the group is signal-blocked during teardown.

LGTM as a UI fix. Ship it alongside #2278 for full WAN coverage.

@ten9876 ten9876 merged commit a14f2fd into ten9876:main May 2, 2026
5 checks passed
ten9876 added a commit that referenced this pull request May 2, 2026
The v0.9.5.1 entry was originally cut for just the TCI TX hotfix
(#2285), but six additional fixes had already landed in main between
the v0.9.5 tag and v0.9.5.1:

- #2275 NR2 wisdom generation off the audio thread
- #2278 SmartLink disconnect teardown
- #2279 Reset RX slice tabs on disconnect (#2254)
- #2280 macOS panadapter pop-out refresh + multi-pan dock layout
- #2282 SmartLink reconnect after WAN drop
- #2284 Qt log handler serialization fixes macOS tune-time crash

CHANGELOG.md gets a per-fix entry with root cause + behavior change.
WhatsNewData.cpp regenerated via scripts/gen_whatsnew.py so the
in-app What's New dialog reflects the full v0.9.5.1 contents.

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
ten9876 added a commit that referenced this pull request May 2, 2026
Match the v0.9.5 `(#NNNN, contributor)` heading style and call out
@rfoust and @jensenpat in the summary for the bulk of this release.

Authors per PR:
- @rfoust: #2278, #2279, #2280, #2282 (SmartLink + macOS popout)
- @jensenpat: #2275, #2284 (NR2 wisdom + Qt log serialization)

WhatsNewData.cpp regenerated.

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

RX slice tab row doesn't rebuild on reconnect to a different radio model

3 participants