Reset RX slice tabs on disconnect#2279
Conversation
There was a problem hiding this comment.
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 throughAppletPanelso disconnect handling can remove generated slice-tab buttons and restore the static badge. - Replaced the constructor-local one-shot initialization flag with a
MainWindowmember 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.
| m_sliceTabsInitialized = false; | ||
| if (m_appletPanel) { | ||
| m_appletPanel->clearSliceButtons(); |
| 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; |
|
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 failedThe only failing check on 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 itselfThe slice-tab teardown logic looks like a clean, targeted fix — resetting Two things worth flagging from Copilot's review that might be worth a follow-up (separate from CI):
Thanks again for the careful work on this — and for picking up the SmartLink disconnect path in #2278 as well. 🙏 |
|
Addressed the capacity-sync review:
The dependency note on #2278 still applies for SmartLink/WAN Disconnect, because this UI teardown needs RadioModel::connectionStateChanged(false). Rebuilt successfully with: |
There was a problem hiding this comment.
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 theinitialized = falsecapture, so the lambda runs on everyinfoChanged. AndRadioModel::handleRadioStatus()does emitinfoChanged()(RadioModel.cpp:3469) after theslices=branch raisesm_maxSlices(lines 3381–3386). WithsetMaxSlices()now rebuilding whenm_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 setsm_sliceTabRow->setVisible(false)andm_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_sliceButtonClicksConnectedguards theQButtonGroup::idClickedconnection 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 (
removeButton→delete 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.
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]>
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]>
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
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.