Skip to content

Add Fahrenheit toggle for amplifier temperature#3652

Merged
ten9876 merged 1 commit into
aethersdr:mainfrom
haider855:fix/3650-amp-temp-fahrenheit
Jun 19, 2026
Merged

Add Fahrenheit toggle for amplifier temperature#3652
ten9876 merged 1 commit into
aethersdr:mainfrom
haider855:fix/3650-amp-temp-fahrenheit

Conversation

@haider855

Copy link
Copy Markdown
Contributor

Summary

Fixes #3650

Adds a clickable Celsius/Fahrenheit toggle to the Amplifier pane temperature display. The amplifier telemetry remains stored in Celsius, and the applet converts only at display time. The selected unit is persisted with AppSettings under the AmpApplet config object. Adds a widget regression test covering the default display, single-temp toggle, dual-temp toggle, and preference reload.

Constitution principle honored

Principle V — the new UI preference is persisted as part of one owned AmpApplet settings object instead of adding scattered flat settings keys.

Test plan

  • Local build passes (cmake --build build-local --target AetherSDR --parallel 4)
  • Behavior verified on a real radio if applicable
    • No PGXL hardware available; verified manually with a temporary local-only Amp pane override before removing it from the PR.
  • Existing tests pass (ctest --test-dir build-local -R amp_applet_test --output-on-failure)
  • Reproduction steps documented if user-reported bug
    • Enhancement request; behavior is covered by amp_applet_test.

Additional checks:

  • cmake --build build-local --target amp_applet_test --parallel 4
  • python tools/check_a11y.py src/gui/AmpApplet.cpp
  • git diff --check

Checklist

  • Commits are signed (docs/COMMIT-SIGNING.md)
  • No new flat-key AppSettings calls — use nested-JSON-under-one-key (Principle V)
  • Code is clean-room — not decompiled, disassembled, or reverse-engineered from a proprietary binary (Principle IV)
  • All meter UI uses MeterSmoother (AGENTS.md convention)
  • Documentation updated if user-visible behavior changed
    • No docs updated; this is a small applet display preference with tooltip and test coverage.
  • Security-sensitive changes reference a GHSA if applicable
    • Not applicable.

@haider855 haider855 requested review from a team as code owners June 18, 2026 18:32

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

Thanks for this, @haider855 — this is a well-executed contribution. The telemetry stays in Celsius and only converts at display time, the preference is persisted as one nested-JSON object under the AmpApplet key (Principle V), styling goes through ThemeManager::applyStyleSheet, and the conversion-rounding test cases (94.5/83.1 F, 32.0 F) are a nice touch. All six checks pass, including the Qt Accessibility static analysis.

A few notes, none blocking:

Verified, not a concern: The "True"/"False" string storage for the bool looked unusual at first, but it matches the established house convention — DisplaySettings.h does the exact same thing (o["leanMode"] = ... QStringLiteral("True") : QStringLiteral("False")). Consistent with the codebase, so leave it as is.

Nice catch: Adding m_hasTempA so the display shows the placeholder until the first setTemp() (instead of a misleading 0.0 C) is a real improvement over the prior behavior.

Minor — i18n consistency: The tooltip, accessible name, and nextUnit strings are wrapped in tr(), but setAccessibleDescription("Toggles amplifier temperature between Celsius and Fahrenheit") is a raw literal. For consistency with the other user-facing strings on this widget, consider wrapping it in tr() too.

Optional — theme tokens (Principle IX): The button stylesheet hardcodes #00b4d8 for the focus border (the highlight colour) and #203040/#ffffff for hover. A recent commit (0d2622c) migrated hardcoded highlight/disabled colours to ThemeManager tokens. The adjacent telemetry labels in this same file still use raw hex, so you're consistent with the surrounding code and I wouldn't hold the PR for it — just flagging in case you'd like to pull the focus/hover colours from theme tokens while you're here.

Overall this looks good to me. Thanks for the clean tests and the accessibility handling (the QAccessible::NameChanged event on toggle is the right call).


🤖 aethersdr-agent · cost: $2.7796 · 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.

Thanks for this, @haider855 — really nicely done. The scope is tight (just the applet, its header, the test, and the CMake target), telemetry stays in Celsius with conversion only at display time, the m_hasTempA placeholder handling is a good touch, and the accessibility wiring (setAccessibleName + QAccessibleEvent on NameChanged) is more thorough than most UI PRs. All six CI checks are green, including the a11y static analysis. The widget regression test covering default/single/dual/reload is exactly what this kind of change needs.

One substantive convention note, plus a minor one:

1. Store the preference as a native JSON bool, not a "True"/"False" string.

The nested-JSON-under-one-key approach is the right call (Principle V). But the value is being serialized as a string:

obj[kTempFahrenheitField] = enabled ? QStringLiteral("True") : QStringLiteral("False");
...
.value(kTempFahrenheitField).toString(QStringLiteral("False")) == QStringLiteral("True");

The codebase convention for booleans inside a JSON settings object is a native JSON bool. The directly analogous applet, EqApplet, does:

cfg["showTx"] = m_showTx;                         // write (bool)
m_showTx = cfg.value("showTx").toBool(true);      // read

and MqttSettings does the same for its nested object (.toBool(false)). The "True"/"False" string form is what AppSettings uses for top-level flat XML keys (SmartSDR/.NET style), not for values nested in a JSON blob. Your code round-trips correctly as written, so this isn't a bug — but matching EqApplet would make it obj[kTempFahrenheitField] = enabled; and .toBool(false), which is simpler and consistent.

2. (Minor, optional) Theme tokens for the new hover/focus colors.

kBtnStyle in this file uses {{color.background.2}} / {{color.text.primary}} tokens, and recent work (commit 0d2622c, Principle IX) migrated hardcoded state colors to ThemeManager tokens. The new button's :hover/:focus borders (#203040, #00b4d8) are hardcoded. The base text color matches the existing kTelStyle it replaces, so the area is already mixed — just flagging in case there are tokens that fit, no need to block on it.

Neither is blocking from my side. Nice contribution.


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

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

Approving — clean, well-tested, CI green across all six, applies cleanly to main.

Verified: display-only C→F conversion (degC*9/5+32; telemetry stays Celsius), Principle-V persistence (nested AmpApplet JSON, read-modify-write), accessible toggle, and a new registered regression test. The unsigned commit is moot on squash-merge (GitHub signs the squash).

Note: this and #3651 both touch AmpApplet.cpp — merging this first means #3651 will need a rebase (handled separately). Nice work @haider855.

@ten9876 ten9876 merged commit bfcfb75 into aethersdr:main Jun 19, 2026
6 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.

Add degrees F option in Amplifier pane

2 participants