Skip to content

fix(smartmtr): disable identity opacity effect so option rows don't render blank#3760

Merged
ten9876 merged 1 commit into
mainfrom
fix/smartmtr-blank-row
Jun 23, 2026
Merged

fix(smartmtr): disable identity opacity effect so option rows don't render blank#3760
ten9876 merged 1 commit into
mainfrom
fix/smartmtr-blank-row

Conversation

@ten9876

@ten9876 ten9876 commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Disables the identity QGraphicsOpacityEffect on fully-enabled SmartMTR option rows so they don't render blank when multiple VFO flags are GPU-composited.

A fully-enabled option row keeps its QGraphicsOpacityEffect at opacity 1.0 (identity). With the GPU-composited slice flags from #3695, an identity opacity effect can render the row's contents blank. The fix disables the effect entirely while it is at full strength (a disabled QGraphicsOpacityEffect is a no-op, so the row paints directly) and keeps it installed only while it is actually dimming the row.

Provenance

This is the net-new fix extracted from #3757. The remainder of that PR re-implemented SmartMTR #3750 hardening that already landed via #3751 (H1), #3752 (M1–M4), and #3753 (L1–L3); #3757 is being closed in favor of this focused change to avoid re-churning already-merged code. Part of #3750.

Test plan

  • Local build passes (cmake --build build --target AetherSDR)
  • Behavior verified on a real radio if applicable — visual (open the SmartMTR option panel with multiple flags up; rows render, not blank)

🤖 Generated with Claude Code

…ender blank

A fully-enabled SmartMTR option row keeps a QGraphicsOpacityEffect at opacity
1.0 (identity). When multiple VFO flags are GPU-composited (#3695), an identity
opacity effect can render the row's contents blank. Disable the effect entirely
while it is at full strength (a disabled effect is a no-op, so the row paints
directly) and keep it installed only while it is actually dimming the row.

Extracted as the net-new fix from #3757; the remainder of that PR re-implemented
SmartMTR hardening already landed in #3751/#3752/#3753. Part of #3750.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ten9876 ten9876 requested a review from a team as a code owner June 23, 2026 04:10
@github-actions

Copy link
Copy Markdown

Accessibility check findings

This PR touches src/gui/ files with 1 accessibility issue(s).
Full details appear as inline annotations on the diff above.

Files scanned : 1
Files with findings: 1
Total findings : 1

See docs/a11y.md for the canonical
Qt patterns (setAccessibleName, QAccessibleValueChangeEvent,
QAccessibleInterface subclasses, etc.). Structural remediation
(keyboard navigation, custom QAccessibleInterface subclasses)
is tracked in #3288.

Findings are warnings only — the build is not blocked.

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

Reviewed the diff and surrounding code in src/gui/VfoWidget.cpp. This is a clean, focused fix and it looks good. ✅

What it does, and why it's correct:

  • The three QGraphicsOpacityEffects are parented to their rows and installed at construction (VfoWidget.cpp:1021-1064), so they're enabled with default opacity 1.0 out of the gate — exactly the identity-effect-renders-blank condition under the #3695 GPU compositing path.
  • The new setRowOpacity lambda resolves that by setEnabled(!fullStrength): at full strength the effect is disabled (a no-op, so the row paints directly), and it's only kept active while actually dimming to 0.45. That's the right shape for the bug.
  • The null guard is preserved, the setOpacitysetEnabled ordering avoids any visible flash on the dimmed transition, and toggling setEnabled doesn't affect geometry/layout, so the existing relayout logic is unaffected.

Conventions: No AppSettings/QSettings surface here; effects remain parented (RAII intact); the no-capture lambda referencing the constexpr kDisabledOpacity is fine. Nicely de-duplicates the three near-identical blocks into one helper.

CI is fully green (build, macOS, Windows, CodeQL, Qt a11y static analysis). The only thing left is the unchecked box in your test plan — visual confirmation on a real radio with multiple flags up. Worth getting that on-hardware check before merge since the failure mode is render-only and not exercised by the build, but the code reasoning is sound.

Thanks for extracting this into a focused change, @ten9876 — the provenance note about dropping the already-landed #3751/#3752/#3753 churn is appreciated and made review easy.


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

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

Reviewed the diff against the surrounding code in VfoWidget.cpp. This looks good — clean, focused, and correct.

What's right

  • The setRowOpacity lambda folds the three near-identical blocks into one helper with a single null guard each, and the setEnabled(!fullStrength) semantics are correct: a disabled QGraphicsOpacityEffect is a no-op, so a full-strength row paints directly instead of round-tripping through the identity-opacity composite path that was rendering blank. Keeping the effect installed-but-disabled (rather than uninstalling) is the right call — it stays cheap to re-enable when dimming kicks back in.
  • These three effects (m_extremesSpeedFade / m_showValuesFade / m_txMeterFade) are created and setGraphicsEffect'd once at VfoWidget.cpp:1021-1064 and touched nowhere else, so toggling their enabled state here has no other consumers to surprise. Initial state is also handled, since syncSmartMtrSettingsState() runs the same path that disables a default-enabled/1.0 effect.
  • kDisabledOpacity is constexpr, so using it inside the empty-capture lambda is fine (value read, not odr-used). Scope is exactly the one file the title claims; no QSettings/RAII/error-handling concerns at any system boundary here.

One non-blocking note

  • The blank-row mechanism is a visual GPU-compositing interaction (#3695), and the test plan's "verified on a real radio" box is unchecked. The code change is sound regardless, but it'd be worth confirming on-hardware that a full-strength row actually renders before this is treated as fully validated — the failure mode is exactly the kind that only shows under real QRhi composition.

Thanks for the focused extraction from #3757, @ten9876 — narrowing it to just the net-new fix makes this easy to reason about.


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

@ten9876 ten9876 merged commit 19ede4a into main Jun 23, 2026
6 checks passed
@ten9876 ten9876 deleted the fix/smartmtr-blank-row branch June 23, 2026 12:08
ten9876 added a commit that referenced this pull request Jun 23, 2026
…rites (rebased #3765) (#3771)

Closes #3762. **Rebased + conflict-resolved version of #3765** by
@dsocha (original authorship preserved on all three commits). Opened
from a maintainer branch because the original is on a fork; #3765 should
be closed in favor of this.

## What it fixes (unchanged from #3765)
Two GPU-flag-sprite rendering bugs in the SmartMTR meter view (#3723):
1. **Extremes value labels never drew (#3762)** — `drawSmartMtrLabels()`
gated on `m_smartMtrWidget->isVisible()`, false in GPU-sprite mode. Now
gates on `!size().isEmpty()` (the same condition the sprite is drawn
under), so labels track the markers in both GPU and software paths.
2. **Meter selector vanished from the sprite** — `QWidget::render()`
can't rasterize a `QGraphicsEffect`. The selector now gates its
underline on an explicit `m_meterMenuOpen` flag (not the hidden row's
`isVisible()`), and the option rows drop the `QGraphicsOpacityEffect`s
in favor of `setEnabled(false)` + `:disabled` stylesheet dimming (new
`QComboBox:disabled` rule in `ComboStyle.h`), so they stay visible
**and** dimmed in the sprite.

## Rebase / conflict resolution (the reason this is a new branch)
The original #3765 conflicted with **#3760** ("disable identity opacity
effect…"), which merged into `main` after #3765 was branched. Both
target the same blank-rows-in-sprite bug, but:
- **#3760** only neutralized the effect at *identity* (opacity 1.0) —
i.e. for *enabled* rows. A *disabled* row still carried an active 0.45
effect, so it would **still render blank** in a sprite.
- **#3765** removes the effects entirely, so both enabled and disabled
rows render. **#3765#3760.**

Resolved `syncSmartMtrSettingsState` in favor of #3765's approach and
**dropped #3760's now-dead `setRowOpacity` lambda + the `m_*Fade`
members**. Verified: no dangling `m_*Fade`/`kDisabledOpacity`
references; the `QGraphicsOpacityEffect` on the DSP filter-level row
(meant to vanish in sprites) is untouched.

## Verification
- Rebased onto `main` (`437f7469`); conflict resolved; commits signed.
- Composes with the merged #3752 (M3 `syncSmartMtrSettingsControls`
re-seeds combos, then `syncSmartMtrSettingsState` disables the rows) and
#3758 (a11y — `QAccessibleInterface` reference preserved; a11y linter
passes 0 findings).
- Original hardware test (macOS / FlexRadio 6000) per #3765.

Credit: @dsocha.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Dariusz Socha <dariusz.socha.pl@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant