fix(smartmtr): show no-data on the needle for uncalibrated sources (#3750 H1)#3751
Conversation
…3750 H1) The SmartMTR needle hardcodes the FLEX dBm scale (-127 S0 .. -13 S9+60) for every source. A KiwiSDR slice without a calibrated meter sets the sentinel m_signalDbm = -130 and the dBm label reads "Meter ---", but the needle clamped -130 to S0 and rendered a confident S0 — and the numeric value labels printed the bogus sub-S0 dBm. Track whether the signal reading is a real calibrated dBm (m_signalHasDbm: always true for FLEX, set from the KiwiSDR meter capability) and feed it into MeterInput::hasValue for the Signal kind. The widget already parks/ fades the indicator and suppresses the value labels when hasValue is false, so the SmartMTR view now matches the "Meter ---" label instead of showing a false S0. The contributor wasn't aware of the KiwiSDR public-receiver feed (#3679), so this interaction was on us to fix. Part of the #3750 fast-follow. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Accessibility check findingsThis PR touches
See Findings are warnings only — the build is not blocked. |
There was a problem hiding this comment.
Reviewed the diff against VfoWidget and SmartMtrWidget/SmartMtrConfig — the fix is correct, minimal, and the "no widget change needed" reasoning holds up end to end. ✅
I traced each consumer of hasValue for the Signal kind and confirmed the no-data path the PR relies on:
indicatorPosition()parks the needle atkScaleMinwhen!hasValue(SmartMtrConfig.cpp:163), so it no longer pegs the hardcoded S0.signalFade()drives towardkSignalFadeLoDbmwhen!hasValue(SmartMtrWidget.cpp:459) — the indicator fades to its at-rest state.- The value-label render (
SmartMtrWidget.cpp:566) and the extremes record (:114) are both already gated onhasValue, so the bogus sub-S0 numbers are suppressed.
The flag is kept in sync on every write of m_signalDbm: setSignalLevel (FLEX → true) and setReceiveMeterReading (→ hasDisplayDbm), and the m_signalHasDbm{true} default correctly matches the FLEX-always-calibrated assumption for the at-rest seed. The in.hasValue = true move into the mic branch keeps the TX path unchanged. Behavior-neutral for FLEX, as stated.
Nice tight fix — the comments explaining why the flag exists and what the widget does downstream are exactly the right level of detail for a future reader. Thanks for catching the KiwiSDR interaction and folding in the #3679 context. LGTM.
🤖 aethersdr-agent · cost: $6.4725 · model: claude-opus-4-8
There was a problem hiding this comment.
Reviewed the diff and traced the claimed widget behavior end-to-end. The fix is correct, minimal, and well-targeted. Thanks @ten9876 — and nice that this reuses the existing no-data plumbing rather than adding a parallel path.
Verified the no-data path actually fires on hasValue == false:
indicatorPosition()returnskScaleMin(needle parks) —src/gui/SmartMtrConfig.cpp- value-label marker is suppressed —
src/gui/SmartMtrWidget.cpp:566 signalFade()falls back tokSignalFadeLoDbmso the needle fades out —src/gui/SmartMtrWidget.cpp:459
So the PR's "no widget change needed" claim holds: a KiwiSDR slice with no calibrated meter now parks instead of rendering a confident S0, matching the Meter --- dBm label. The three flag sites (FLEX setSignalLevel, mic TX path, and setReceiveMeterReading) are all covered, default-true keeps FLEX behavior-neutral, and the member is brace-initialized in the header per house style. Clean.
One minor, non-blocking observation (pre-existing, not introduced here): m_signalHasDbm is tied to hasDisplayDbm, which checks capability + hasDbm but not reading.valid. The legacy meter-fraction path (updateSignalMeterTarget() → usesUnavailableSignalMeter() at VfoWidget.cpp:3569) does additionally gate on m_receiveMeterReading.valid. So if a reading were ever valid == false but Calibrated+hasDbm, the SmartMTR needle (and the dBm label) would show a value while the legacy meter parks. Tying m_signalHasDbm to the same condition as the dBm label is arguably the right call here (the goal is to match Meter ---), so this is fine as-is — just flagging the valid asymmetry in case it bites a future reading source. No change requested.
LGTM.
🤖 aethersdr-agent · cost: $5.2443 · model: claude-opus-4-8
…ender blank (#3760) ## 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 - [x] 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](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Fixes the H1 item from #3750 (SmartMTR fast-follow), introduced with the SmartMTR meter view in #3723.
Problem
VfoWidget::pushSmartMtrInput()hardcodes the FLEX dBm scale (-127S0 ..-13S9+60) for every source. When a KiwiSDR slice has no calibrated meter, the receive path sets the sentinelm_signalDbm = -130and the dBm label correctly shows "Meter ---" — but the SmartMTR needle clamped-130to S0 and rendered a confident S0, and the numeric value labels printed the bogus sub-S0 dBm.The PR author wasn't aware of our KiwiSDR public-receiver feed (#3679), so this interaction was on us (maintainers) to fix.
Fix
Track whether the current signal reading is a real calibrated dBm:
m_signalHasDbm—truefor FLEX (setSignalLevel), set from the KiwiSDR meter capability insetReceiveMeterReading;MeterInput::hasValuefor theSignalkind.The widget already parks/fades the indicator and suppresses the value labels when
hasValue == false(seeindicatorPosition()→kScaleMin, thekSignalFadeLoDbmneedle target, and theif (m_input.hasValue)value-label guard). So no widget change is needed — the SmartMTR view now shows no-data, matching the "Meter ---" label, instead of a false S0. The mic (TX) path keepshasValue = true.Scope
3 small edits in
VfoWidget.{cpp,h}, behavior-neutral for FLEX (the flag is alwaystruethere). No change to the S-meter path.🤖 Generated with Claude Code