Skip to content

Fix RX slice tab capacity initialization#2243

Merged
ten9876 merged 1 commit intoten9876:mainfrom
rfoust:codex/rx-controls-h-slice
May 1, 2026
Merged

Fix RX slice tab capacity initialization#2243
ten9876 merged 1 commit intoten9876:mainfrom
rfoust:codex/rx-controls-h-slice

Conversation

@rfoust
Copy link
Copy Markdown
Contributor

@rfoust rfoust commented May 1, 2026

Summary

  • Recompute radio slice capacity when the TCP info response supplies the radio model
  • Delay RX Controls slice tab creation until the radio model is known, avoiding transient availability counts such as A-G on an 8-slice FLEX-6700
  • Refresh slice tab enabled/checked state immediately after creating the selector so already-open slices are highlighted

Testing

  • cmake --build build
  • ctest --test-dir build --output-on-failure

@rfoust rfoust requested a review from ten9876 as a code owner May 1, 2026 12:21
Copilot AI review requested due to automatic review settings May 1, 2026 12:21
@rfoust rfoust requested a review from jensenpat as a code owner May 1, 2026 12:21
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 incorrect RX slice-tab capacity initialization by ensuring the UI doesn’t create slice selector buttons until the radio’s actual model (and therefore slice capacity) is known, and by refreshing the selector state immediately after creation.

Changes:

  • Recompute m_maxSlices when the TCP info response provides the radio model.
  • Delay RX slice-tab button creation until the radio model is known.
  • Immediately refresh slice button enabled/checked state after creating the selector to reflect already-open slices.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/models/RadioModel.cpp Updates max slice capacity when model is parsed from the info response.
src/gui/RxApplet.cpp Minor guard formatting in setMaxSlices (no behavior change).
src/gui/MainWindow.cpp Defers slice-tab initialization until model is known and refreshes button state after creation.

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

Comment thread src/gui/MainWindow.cpp Outdated
Comment on lines +2216 to +2220
connect(&m_radioModel, &RadioModel::infoChanged, this, [this]() {
m_appletPanel->setMaxSlices(m_radioModel.maxSlices());
if (!m_radioModel.model().isEmpty()) {
m_appletPanel->setMaxSlices(m_radioModel.maxSlices());
m_appletPanel->updateSliceButtons(m_radioModel.slices(), m_activeSliceId);
}
Copy link

Copilot AI May 1, 2026

Choose a reason for hiding this comment

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

The new infoChanged handler calls updateSliceButtons(...) on every RadioModel::infoChanged emission once model() is non-empty. Since infoChanged is emitted for many unrelated radio status updates (e.g., oscillator, licensing, filter settings), this introduces repeated UI work that isn’t needed after the initial slice-tab creation. Consider disconnecting this specific connection after the first successful setMaxSlices(...)/updateSliceButtons(...), or gating so updateSliceButtons only runs when the slice-tab buttons were just created (or when maxSlices/model actually changes).

Copilot uses AI. Check for mistakes.
@aethersdr-agent
Copy link
Copy Markdown
Contributor

Hey @rfoust — thanks for the contribution! I took a look at the CI failure on commit 1556c85 and wanted to share what I found.

CI Failure Analysis

The failure is not in your code. It's a CI infrastructure issue.

The failed job is "Cleanup artifacts" (link), specifically the "Delete artifacts" step. This is a post-build housekeeping job that cleans up temporary CI artifacts — it has nothing to do with your changes.

The other jobs look fine:

  • Prepare — ✅ passed
  • Agent — ✅ passed
  • Upload results — ✅ passed
  • check-paths — ✅ passed
  • build — 🔄 still running at time of check
  • analyze (cpp) — 🔄 still running at time of check

This kind of transient failure usually resolves on a re-run. You can trigger one from the Actions tab, or a maintainer can re-run the failed job.

Separate note: Copilot review feedback

Copilot flagged something worth considering in src/gui/MainWindow.cpp:2220 — the new infoChanged handler calls updateSliceButtons(...) on every RadioModel::infoChanged emission once model() is non-empty. Since infoChanged fires for many unrelated radio status updates (oscillator, licensing, filter settings, etc.), this could introduce unnecessary repeated UI work. Consider either:

  • Disconnecting the connection after the first successful setMaxSlices()/updateSliceButtons() call, or
  • Gating the call so updateSliceButtons only runs when maxSlices or the model value actually changes

This isn't related to the CI failure, but it's worth addressing before merge to avoid unnecessary UI churn.

Thanks again for your time on this — appreciate the contribution! 🎙️

@rfoust rfoust force-pushed the codex/rx-controls-h-slice branch from 1556c85 to 226496e Compare May 1, 2026 13:25
@rfoust
Copy link
Copy Markdown
Contributor Author

rfoust commented May 1, 2026

Addressed the infoChanged concern in the latest push.

The RX slice-tab initialization handler now captures an initialized flag and returns after the first successful initialization, so unrelated later RadioModel::infoChanged emissions no longer call updateSliceButtons repeatedly. It still waits until RadioModel::model is known before creating the selector, then immediately refreshes updateSliceButtons once so slices that arrived earlier, such as slice A during startup, are enabled and checked as soon as the tabs appear.

Re-ran:

  • git diff --check
  • cmake --build build
  • ctest --test-dir build --output-on-failure

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 for the fix, @rfoust — this is a clean, well-scoped change. A few notes:

Looks good:

  • The maxSlicesForModel() call in registerAsGuiClient's info handler is correct and consistent with the existing patterns in handleRadioStatus (line 3210) and setRadioInfo (line 453). Previously m_maxSlices wasn't being set in this code path, so the tab count could be wrong until a later radio status message arrived.

  • The [this, initialized = false]() mutable one-shot pattern in MainWindow.cpp is a nice use of C++14 init-capture to gate the handler. It fires setMaxSlices + updateSliceButtons exactly once (on first infoChanged where model() is non-empty), which avoids the repeated-work concern that Copilot flagged. Both setMaxSlices and updateSliceButtons also have their own early-return guards (m_sliceBtns.isEmpty()), so there's defense in depth.

  • Adding updateSliceButtons right after setMaxSlices ensures slices that were already opened before the model string arrived get their tabs highlighted immediately — good catch.

  • The RxApplet.cpp change is a no-op brace-style fix, fine.

Re: Copilot's comment — the concern about infoChanged firing repeatedly is valid in the abstract, but the initialized flag in this PR already handles it. The handler short-circuits after the first successful run. No further action needed there.

One minor thought (non-blocking): The initialized flag lives in the lambda capture, so if infoChanged is ever disconnected and reconnected (e.g., across a reconnect cycle), the one-shot won't re-arm. This seems fine for the current connection lifecycle, but worth keeping in mind if reconnect logic changes later.

All three files are within scope. No bugs, null-pointer risks, or convention issues spotted. Tests passing per the PR description. Nice contribution!

Copy link
Copy Markdown
Owner

@ten9876 ten9876 left a comment

Choose a reason for hiding this comment

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

Reviewed — small, focused, correct. Three layers (model parser, MainWindow listener, RxApplet brace cleanup) are mutually reinforcing rather than redundant. Approving.

@ten9876 ten9876 merged commit 20bf31d into ten9876:main May 1, 2026
5 checks passed
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.

3 participants