Skip to content

fix(smartmtr): render extremes labels + meter selector in GPU flag sprites#3765

Closed
dsocha wants to merge 3 commits into
aethersdr:mainfrom
dsocha:fix/smartmtr-extremes-value-fade
Closed

fix(smartmtr): render extremes labels + meter selector in GPU flag sprites#3765
dsocha wants to merge 3 commits into
aethersdr:mainfrom
dsocha:fix/smartmtr-extremes-value-fade

Conversation

@dsocha

@dsocha dsocha commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Closes #3762.

Two GPU-flag-sprite rendering bugs in the SmartMTR meter view (from #3723). When the cursor leaves a VFO flag it's rasterized into a static GPU sprite via QWidget::render(), and two things didn't survive that path.

1. Extremes value labels never drew (#3762) — 37a05526

drawSmartMtrLabels() gated on m_smartMtrWidget->isVisible(), which is false in GPU flag mode (the flag QWidget is hidden and drawn as a sprite). The triangle markers ride along inside the grabbed sprite, but the value numbers are drawn separately in the spectrum overlay and were skipped — so the min/max numbers appeared only on the brief "live"/hover frames, or not at all. Gate on the meter having a real size instead (the same condition the flag sprite is drawn under). Labels use the same extremesOpacity() as the markers, so they fade/disappear together.

2. Meter selector vanished from the sprite — 87e73757

QWidget::render() can't draw widgets carrying a QGraphicsEffect. The selector dimmed its option rows with QGraphicsOpacityEffect and the underline gated on the (hidden) row's isVisible(), so the option combos and the underline disappeared from the sprite — unlike tab underlines / filter buttons, which stay. Made the selector render-compatible:

  • the underline gates on an explicit m_meterMenuOpen flag, not isVisible();
  • the option rows drop the opacity effects and dim via :disabled stylesheet rules, disabled as a unit, so combos + labels stay visible and keep their disabled dimming in the sprite.

Effect-based controls that are meant to disappear in the sprite (e.g. the DSP filter-level slider) keep their QGraphicsOpacityEffect and are unaffected.

Note for reviewer

The QComboBox:disabled rule lives in the shared combo template (ComboStyle.h), so disabled combos dim app-wide. Today the base rule sets an explicit colour that overrides Qt's native disabled greying, so disabled combos render as if enabled — this corrects that latent inconsistency. Small and additive, but flagging it since it's not SmartMTR-scoped.

Test

macOS, against a FlexRadio (6000-series). Built clean; verified by hand: value labels track the markers in the sprite; selector + underline stay visible and correctly dimmed when inapplicable; DSP NRS level slider still disappears as before.

🤖 Generated with Claude Code

@dsocha dsocha requested a review from a team as a code owner June 23, 2026 09:19

@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 fix — both bugs are correctly diagnosed and the chosen approach (swap QGraphicsEffect-based dimming for render()-compatible :disabled stylesheets + an explicit open-state flag) is exactly right for the GPU-sprite path, since QWidget::render() can't rasterize graphics effects. The reasoning in the diff comments is excellent, CI is green across all platforms, and I appreciate the transparent call-out of the app-wide ComboStyle.h change in the PR body. A few observations:

1. Stale comment left behind in VfoWidget.h (minor)

The block that documented the removed opacity effects is retained above the new row pointers (src/gui/VfoWidget.h:317-320):

// Opacity effects over each select row (label + combo), dimmed when the
// row is disabled so the disabled state is obvious (the custom combo
// stylesheet has no :disabled variant).  Matched to the disabled-checkbox
// label dimming.
// The three SmartMTR option rows (label + combo). Disabled as a unit ...
QWidget* m_speedRow{nullptr};

It's now doubly inaccurate: there are no more opacity effects, and "the custom combo stylesheet has no :disabled variant" is contradicted by this very PR (you added one in ComboStyle.h). Worth deleting the old four lines so only the new comment remains.

2. Rows are now genuinely disabled, not just dimmed (intentional, calling it out)

Switching from setOpacity(0.45) on an enabled row to setEnabled(false) means the inapplicable combos are now non-interactive, not merely dimmed-but-clickable. That's the more correct behavior for an inapplicable option, so this is an improvement — just flagging it since it's a real interaction change beyond the visual fix.

3. ComboStyle.h app-wide change looks sound

Adding QComboBox:disabled { color: ...; } to override the base rule's explicit colour is the right call and is the only way the disabled rows actually dim. Since it's global, a quick eyeball of any other normally-disabled combos in the app is worthwhile, but I don't see a risk — Qt's native greying was being suppressed before, so this corrects a latent inconsistency as you noted.

Nothing blocking here — only item (1) is worth a touch-up. Thanks for the thorough writeup and the hardware verification, @dsocha.


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

dsocha added a commit to dsocha/AetherSDR that referenced this pull request Jun 23, 2026
The comment above the option-row pointers still described the removed
QGraphicsOpacityEffect members and claimed the combo stylesheet has no
:disabled variant — both untrue after the render-compatible rework (the
:disabled rule was added in this branch). Delete it; the accurate comment
on the m_*Row pointers remains. Review nit on aethersdr#3765.

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

ten9876 commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Superseded by #3771 — a rebased + conflict-resolved version of this branch (your three commits, authorship preserved).

This branch conflicted with #3760 ("disable identity opacity effect…"), which merged after you branched. They target the same blank-rows-in-sprite bug, but #3760 only neutralized the identity (enabled) effect — a disabled row still carried an active 0.45 effect and would still render blank in a sprite. Your approach (remove the effects entirely, dim via :disabled) covers both cases, so it supersedes #3760. I resolved syncSmartMtrSettingsState in favor of your version and dropped #3760's now-dead setRowOpacity lambda + m_*Fade members.

Nothing needed on your end — #3771 will carry it through CI + merge. Thanks @dsocha.

dsocha and others added 3 commits June 23, 2026 14:57
The min/max value numbers (Show values = Extremes) appeared only
intermittently, or not at all, while their triangle markers stayed
visible. drawSmartMtrLabels() gated on m_smartMtrWidget->isVisible(),
but in the default GPU flag mode the flag QWidget is hidden
(setVisible(false)) and drawn as a grabbed sprite — so the in-meter
markers ride along in the sprite while isVisible() is false, which
skipped these separately-overlay-drawn labels entirely (they only
showed on the brief "live"/hover frames where the flag is a real
widget). Gate on the meter having a real size instead — the same
condition the flag sprite itself is drawn under — so the labels track
the markers in both GPU and software flag modes, at the same opacity.

Fixes aethersdr#3762.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When the cursor leaves a flag it's rasterized into a static GPU sprite via
QWidget::render(), which can't draw widgets carrying a QGraphicsEffect.
The meter-view selector dimmed its option rows with QGraphicsOpacityEffect
and the underline gated on the (now-hidden) row's isVisible(), so the
selector's combos and underline vanished from the sprite — unlike tab
underlines / filter buttons, which stay. The selector should stay too.

Make the selector render-compatible:
- underline gates on an explicit m_meterMenuOpen flag, not isVisible();
- option rows drop the opacity effects and dim via :disabled stylesheet
  rules (QComboBox:disabled in the shared combo template, QLabel:disabled
  on the option labels), disabling each row as a unit;
- so the combos + labels stay visible AND keep their disabled dimming in
  the sprite.

Effect-based controls that are meant to disappear (e.g. the DSP
filter-level slider) keep their QGraphicsOpacityEffect and are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The comment above the option-row pointers still described the removed
QGraphicsOpacityEffect members and claimed the combo stylesheet has no
:disabled variant — both untrue after the render-compatible rework (the
:disabled rule was added in this branch). Delete it; the accurate comment
on the m_*Row pointers remains. Review nit on aethersdr#3765.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@dsocha dsocha force-pushed the fix/smartmtr-extremes-value-fade branch from a5ea8cd to b27c894 Compare June 23, 2026 13:02
@dsocha

dsocha commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

Heads-up on the rebase: I just rebased onto current main, which now includes #3760. Since this PR reworks the same syncSmartMtrSettingsState path, I resolved the conflict by keeping this PR's approach — which supersedes #3760's identity-effect-disable.

The reasoning: #3760 keeps the QGraphicsOpacityEffect active while a row is dimming, so a disabled option row (e.g. when the S-Meter view is selected) still renders blank in the GPU sprite. This PR drops the effects entirely and dims via QComboBox:disabled / QLabel:disabled stylesheets, which render() can rasterize — so enabled and disabled rows stay visible (and correctly dimmed) in the sprite. The resolution removes #3760's setRowOpacity lambda. Happy to layer it differently if you'd prefer.

Verified on-hardware after the rebase: all selector controls + the underline persist when the cursor leaves the flag; the DSP NRS level slider still disappears as designed; the a11y additions from #3754 merged cleanly.

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

ten9876 commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Superseded by #3771 (now merged), which is this PR rebased onto current main with the #3760 conflict resolved — #3760 only neutralized the opacity effect at identity (enabled rows), so disabled rows would still blank in a GPU sprite; this PR removes the effects entirely and dims via setEnabled(false) + :disabled stylesheet, covering both. All three commits' original authorship is preserved on #3771.

Thank you @dsocha — the fix landed intact, credited to you. Closing in favor of #3771.

@ten9876 ten9876 closed this Jun 23, 2026
ten9876 added a commit that referenced this pull request Jun 23, 2026
#3765 was closed unmerged in favor of #3771 (its rebased form), which has now
landed. Update the v26.6.4 SmartMTR ref so the changelog points at the PR that
is actually in the history.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ten9876 added a commit that referenced this pull request Jun 23, 2026
…#3772)

Release-prep for **v26.6.4**. Docs/metadata only — no code changes.

## CHANGELOG
New `## [v26.6.4]` entry built from the **80 commits** since v26.6.3, in
the house style (headline + New features / CAT-rigctld parity / Fixes &
hardening / Internal / Governance / Packaging). Headlines: KiwiSDR
public-receiver browser, SmartMTR meter view, agent automation/test
bridge, GPU-composite slice flags + multi-GPU selector, accessibility
pass, CAT/rigctld parity, Constitution v2.0.0. `[Unreleased]` preserved
above it.

## Version bump → 26.6.4
`CMakeLists.txt`, `README.md`, `AGENTS.md` (kept in sync), plus a new
`<release version="26.6.4">` in the AppStream metainfo.

## Doc refresh
- **README**: KiwiSDR highlight added; SmartMTR +
multi-GPU/GPU-composite folded into existing highlights.
- **ROADMAP**: retargeted to post-v26.6.4; dropped already-shipped items
wrongly listed in-flight/queued (H1 Phase 2, L1–L4, RigctlPty);
"Recently shipped" refreshed with the v26.6.4 set; added Flathub +
KiwiSDR-followup forward items.
- **AGENTS**: KiwiSDR subsystem pointer added (the one new subsystem
with no mention); constitution principle numbering verified intact
post-v2.0.0.

## Notes
- Release date stamped **2026-06-23** in CHANGELOG + metainfo — adjust
if tagged on another day.
- Provenance language kept out of the release-facing docs
(CHANGELOG/README/ROADMAP) intentionally; the internal clean-room
practice stays documented in CONSTITUTION/AGENTS/CONTRIBUTING.
- The CHANGELOG SmartMTR line lists #3765 — land #3771 (its rebased
form) before tagging so that ref is accurate.

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

---------

Co-authored-by: Claude Opus 4.8 <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.

bug(smartmtr): extremes value numbers fade out before their markers

2 participants