Skip to content

[ux] Make the VFO DSP label indicate active noise reduction#4241

Merged
ten9876 merged 3 commits into
aethersdr:mainfrom
jensenpat:aether/4237-vfo-dsp-indicator
Jul 19, 2026
Merged

[ux] Make the VFO DSP label indicate active noise reduction#4241
ten9876 merged 3 commits into
aethersdr:mainfrom
jensenpat:aether/4237-vfo-dsp-indicator

Conversation

@jensenpat

@jensenpat jensenpat commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • turn the always-visible VFO DSP label into a persistent noise-reduction indicator for both radio-side DSP and AetherSDR client-side NR
  • keep cyan as the open-panel state, use green while any DSP is engaged with the panel closed, and return to grey only when every DSP is off
  • match the ADSP and AetherVoice button heights to ANFT
  • hide the shared DSP-level row when it has no active target, removing the empty black strip below the controls
  • expose the indicator state through a stable dspTabButton object name and a dynamic accessible name

Root cause

The top-level DSP tab only had two visual states: cyan while its panel was open and grey after every close/collapse path. Radio DSP state changes and the existing aggregated AetherDSP state never updated that tab, so closing the panel erased the only visible cue.

The layout issues had separate concrete causes: radio-side buttons use a fixed 26 px height while ADSP/AetherVoice requested only a 22 px minimum, and the opacity-zero DSP-level slider remained in the layout even when it had no target.

Implementation

VfoWidget::updateDspTabAccent() aggregates all per-slice radio DSP flags with the existing global AetherDSP-active flag. It updates the closed-tab style and accessible name on initial slice sync, every radio DSP state change, every client NR state change, tab closure, and expanded-state restoration. The currently open DSP tab remains cyan so open versus active are visually distinct.

The client launchers now use the same fixed 26 px height as the radio buttons. The shared level row is explicitly shown only for a leveled active DSP, with the VFO flag refit after visibility changes.

Testing

  • cmake --build build -j8 — pass
  • git diff --check — pass
  • python3 tools/check_engine_boundary.py --strict — 0 blocking findings
  • python3 tools/check_a11y.py — warning-only existing repository findings
  • manual UI/radio verification by @jensenpat — tested clean

Related

PR #3822 added the inner ADSP launcher cue for client-side NR. This change completes the always-visible top-level DSP indication and adds radio-side DSP coverage.

Fixes #4237

👨🏼‍💻 Generated with OpenAI Codex (GPT-5.6 Sol) and tested by @jensenpat

@jensenpat
jensenpat marked this pull request as ready for review July 14, 2026 05:40
@jensenpat
jensenpat requested a review from a team as a code owner July 14, 2026 05:40
@jensenpat jensenpat changed the title Make the VFO DSP label indicate active noise reduction ux: Make the VFO DSP label indicate active noise reduction Jul 14, 2026
@jensenpat jensenpat changed the title ux: Make the VFO DSP label indicate active noise reduction [ux] Make the VFO DSP label indicate active noise reduction Jul 14, 2026

@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.

Nice, focused change — the state machine reads cleanly and coverage of the "closed panel erased the cue" paths (closeActiveTab, showTab toggle-off / switch-away, setCollapsed expand, radio-DSP and client-NR changes, syncFromSlice) looks complete. I especially like that swapping the opacity effect for hide()/show() also sidesteps the known QWidget::render()-can't-rasterize-QGraphicsOpacityEffect problem the GPU flag-sprite path has (see the makeOptLabel comment) — the level row will now render correctly in the spectrum overlay. Verified: all SliceModel accessors exist, DSP tab index 1 matches the new dspTabButton object name, no stray QGraphicsOpacityEffect references remain after the include removal, closeActiveTab's early-return keeps the new closedTab indexing in bounds, and visibilityChanged is correctly sampled before setVisible. All 7 checks green, commit signed.

Non-blocking notes

  • The aggregate flags anfOn/anflOn/anftOn (auto-notch) and apfOn (audio peak filter) but announces "noise reduction active" — a notch/peak filter isn't NR, so a screen-reader user enabling only ANF/APF hears a slightly inaccurate label. Consider narrowing the set to true NR flags, or relabeling to "DSP active". Judgment call; fine to keep as-is if the green cue is intentionally "any DSP engaged."

🤖 aethersdr-agent · cost: $5.7974 · model: claude-opus-4-8

Comment thread src/gui/VfoWidget.cpp Outdated
NF0T
NF0T previously requested changes Jul 16, 2026

@NF0T NF0T 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.

Focused, well-scoped fix for a real gap (#4237) — the closed-tab "no visible DSP cue" problem is solid work, and updateDspTabAccent()'s wiring into all the right signal paths (radio DSP toggles, client AetherDSP, tab close/collapse/expand, slice sync) is thorough. CI is green across all 7 checks and the commit is signed.

Two technical issues and one process note before this can merge:

1. The tab accent surfaces DSP state for controls the mode hides. syncFromSlice() (VfoWidget.cpp:4526-4574) hides m_nrBtn/m_nbBtn/m_nrlBtn/m_anfBtn/m_anflBtn/m_anftBtn in FM mode — the project's own design treats those six functions as not meaningful there. updateDspTabAccent() is called immediately after syncDsp() but before that mode-gating runs, and it reads the raw model flags with no mode awareness. If any of those six is true on an FM slice, the tab now shows a persistent green "active" cue for a function the user can't see or reach. Please gate the aggregate on the same mode logic (or exclude FM-inapplicable flags), so the indicator never claims something is active when its control isn't even shown.

2. "Noise reduction active" mislabels notch/peaking filters. anfOn/anflOn/anftOn are notch filters and apfOn is a CW audio peaking filter (per their own tooltips at VfoWidget.cpp:1836-1843) — none of these are noise reduction. A screen-reader user who enables only the auto-notch hears "noise reduction active," which is inaccurate. Either narrow the aggregate to the true NR flags (nb/nr/nrl/nrs/rnn/nrf) for the accessible name, or relabel to something mode-neutral like "DSP active" if the intent is genuinely "any DSP engaged."

3. Small process note. This one touches AGENTS.md's Autonomous Agent Boundaries section, which reserves visual/UX design calls (color scheme, aggregation scope, sizing) for maintainer sign-off, with a PR note when an agent's implementation reaches into that territory. I know this was your call with your tooling, Pat, not the agent freelancing — but the PR body doesn't currently show that the color scheme/aggregation choices were checked against #4237's ask (which didn't specify either). Not asking for a redesign — just flagging it so @ten9876 can give a quick nod on the design choices before merge, per the project's own escalation path for exactly this situation.

Smaller cleanup, non-blocking, worth doing in this pass since the diff already touches these spots:

  • updateDspTabAccent() fires on every one of the 10 individually-wired DSP signals; SliceModel::applyChanges() emits 9 of them unconditionally on a single status packet (SliceModel.cpp:1170-1204), so one radio update can re-run this up to 9x back-to-back, and unlike the accessible-name check five lines above it, the setStyleSheet() call has no before/after guard.
  • The if (closedTab==1) updateDspTabAccent(); else setStyleSheet(kTabLblNormal); pattern is copy-pasted three times (closeActiveTab, both branches of showTab) with an easy-to-miss precondition (m_activeTab must already be -1). A small deactivateTabButton(int) helper would remove the duplication.
  • setObjectName(QStringLiteral("dspTabButton")) is added but never referenced anywhere else in the repo — looks like scaffolding for a hook that didn't get wired in.

Happy to re-review quickly once 1–2 are addressed and 3 has a maintainer nod — this is close.

@NF0T NF0T self-assigned this Jul 16, 2026
@jensenpat jensenpat added help wanted Extra attention needed priority: low Low priority labels Jul 17, 2026
@jensenpat

Copy link
Copy Markdown
Collaborator Author

@NF0T, both requested fixes are addressed in signed commit 9bdd89ac:

  • The tab accent now considers only DSP controls available in the current mode, and refreshes after mode visibility is applied (including aligned FM/NFM/DFM initial-sync gating).
  • The accessible announcement is now the mode-neutral “DSP active,” so notch and peaking filters are no longer mislabeled as noise reduction.

Jeremy, the project owner, approved the UX design call.

Validation: full macOS build, vfo_flag_placement_test, accessibility check, and strict engine-boundary check all pass. The overlapping review thread is resolved.

Ready for re-review.

aethersdr#4241)

Three non-blocking review nits from @NF0T:

- updateDspTabAccent()'s setStyleSheet() now skips the repaint when the target
  style is unchanged, matching the accessible-name guard above it. One radio
  status packet re-runs this up to ~9x (SliceModel::applyChanges emits the DSP
  signals unconditionally), so the unguarded style recompute was wasted work on
  a per-packet path.

- Extract deactivateTabButton(int) to replace the three copy-pasted
  "reset a just-closed tab button" blocks in closeActiveTab() and both
  showTab() branches, centralizing the "m_activeTab already cleared" precondition.

- Drop the unused setObjectName("dspTabButton") scaffolding (no consumer in the
  repo).

No behavior change. Full app builds clean; offscreen smoke-launch constructs the
VFO widget without asserts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@ten9876 ten9876 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.

Maintainer approval (Tier 1) — nits fixed, design signed off

Full high-effort pass. Both of @NF0T's technical blockers are genuinely resolved in 9bdd89ac:

  • #1 (accent surfaces mode-hidden controls): activeWhenAvailable()'s !button->isHidden() guard correctly excludes FM-hidden DSP buttons (they're explicitly setVisible(false), so isHidden() is true) while still counting panel-closed buttons (ancestor hidden, own flag untouched) — exactly the distinction the fix needs.
  • #2 (mislabeled notch/peak as "noise reduction"): the accessible name is now mode-neutral "DSP active".

I also confirmed the refactored closeActiveTab/showTab keep the m_activeTab < 0 guard (no m_tabBtns[-1]) and that all three isFm sites now include DFM (this PR fixes a pre-existing gap in syncFromSlice). No correctness defect.

I pushed c28605f3 to clear @NF0T's three non-blocking cleanup notes:

  • Guard updateDspTabAccent()'s setStyleSheet() on an unchanged-style check (it re-runs up to ~9x per status packet).
  • Extract deactivateTabButton(int) to dedupe the three copy-pasted tab-reset blocks.
  • Remove the unused dspTabButton object name.

Built clean + offscreen smoke-launch (no asserts). No behavior change from those three.

Design sign-off (NF0T process note #3): as the Tier-1 maintainer I'm approving the visual/UX calls this PR makes — the green (#20a040) persistent closed-panel DSP cue, the aggregate-any-DSP scope, and the opacity→hide() level-row change (which also fixes the real QGraphicsOpacityEffect render bug in the spectrum overlay). Good work, @jensenpat; thanks for the thorough signal wiring and the careful review, @NF0T.

@ten9876
ten9876 enabled auto-merge (squash) July 18, 2026 23:45
@ten9876
ten9876 dismissed NF0T’s stale review July 18, 2026 23:57

requested changes have been applied.

@ten9876
ten9876 merged commit 0acaa21 into aethersdr:main Jul 19, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

help wanted Extra attention needed priority: low Low priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Main Spectrum Display - DSP icon in not highlighted if any of the functions are activated

3 participants