Skip to content

fix(theme): migrate hardcoded highlight and disabled-state colours to ThemeManager tokens. Principle IX.#3645

Merged
ten9876 merged 1 commit into
aethersdr:mainfrom
NF0T:feat/theme-token-gaps
Jun 19, 2026
Merged

fix(theme): migrate hardcoded highlight and disabled-state colours to ThemeManager tokens. Principle IX.#3645
ten9876 merged 1 commit into
aethersdr:mainfrom
NF0T:feat/theme-token-gaps

Conversation

@NF0T

@NF0T NF0T commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #3439 and #3441. Fills three hardcoded-colour gaps in the theme token system — the last surfaces in the FreeDV Reporter dialog and Radio Setup dialog that hadn't been migrated to ThemeManager.

FreeDvReporterModel — row highlight colours

  • Removes four hardcoded QColor constants (kTxBg / kRxBg / kMsgBg / kHlFg) and replaces their three use sites in data() with ThemeManager::instance().color(token) calls.
  • Adds a themeChangeddataChanged{BackgroundRole, ForegroundRole} connection in the constructor so highlighted rows repaint immediately on a theme switch instead of waiting for the next 250 ms highlight tick.
  • Note: color.background.tx (#3a2a0e) is a chrome-panel tint used in 35+ surfaces and could not be reused here. The TX-row highlight (#fc4500) is a distinct high-visibility colour matching the freedv-gui reference palette, so new tokens were required for all four constants.

RadioSetupDialog — button disabled states

  • Migrates three QPushButton:disabled CSS blocks to tokens.
  • Reboot Radio button (buildRadioTab ~line 601): uses new color.button.danger.*disabled tokens — preserves the intentional danger-red colouring in the disabled state.
  • Upload Firmware button (buildRadioTab ~line 838): was using {{color.meter.bar.fill}} and {{color.background.1}} as disabled-state stand-ins (semantically wrong tokens from a prior partial migration). Now uses correct color.button.*disabled tokens.
  • Serial tab Open/Close port buttons (buildSerialTab ~line 4054): hardcoded hex replaced with color.button.*disabled tokens; setStyleSheet calls replaced with applyStyleSheet so the template engine resolves tokens and the widgets participate in live theme switching.

New tokens — 10 total across both theme files

Token Dark Light
color.highlight.tx #fc4500 #fc4500
color.highlight.rx #379baf #379baf
color.highlight.message #e58be5 #e58be5
color.highlight.fg #000000 #000000
color.button.background.disabled #203040 {color.gray.700}
color.button.foreground.disabled {color.gray.500} {color.gray.500}
color.button.border.disabled {color.gray.700} {color.gray.600}
color.button.danger.background.disabled #2a1818 #f0d8d8
color.button.danger.foreground.disabled #8a6055 #b08080
color.button.danger.border.disabled #4a2828 #d0a8a8

Highlight colours are kept identical between dark and light themes — they are high-saturation reference palette colours from freedv-gui that provide adequate contrast with the black foreground on both backgrounds. A future theme author can override them via the token.

Fixes #3446.

Test plan

  • Build clean on Windows (MinGW), no new warnings
  • FreeDV Reporter: open dialog, observe another station transmitting — TX row shows orange background with black text
  • FreeDV Reporter: RX highlight (teal) and message highlight (purple) appear and expire after ~5 s
  • FreeDV Reporter: switch theme while a highlight is active — row repaints immediately (does not wait for the 250 ms tick)
  • Radio Setup → General tab: disconnect radio, confirm Reboot Radio button disabled state is dark red-tinted (not generic grey)
  • Radio Setup → General tab: Upload Firmware button renders correct disabled state when no firmware check has run
  • Radio Setup → Serial tab: open a port config, confirm Open/Close buttons show correct disabled styling when not applicable
  • Light theme: open FreeDV Reporter and Radio Setup, confirm all three token groups (highlight, button, danger) render legibly

🤖 Generated with Claude Code

… ThemeManager tokens. Principle IX.

Fills three hardcoded-colour gaps left after aethersdr#3439 and aethersdr#3441.

FreeDvReporterModel: removes kTxBg/kRxBg/kMsgBg/kHlFg constants and
replaces their use sites with ThemeManager::instance().color(token).
Adds a themeChanged->dataChanged{Background,Foreground} connection so
highlighted rows repaint immediately on theme switch rather than waiting
for the next 250ms highlight tick. Four new color.highlight.* tokens
added to both theme files (values match the freedv-gui reference palette;
color.background.tx is a chrome tint and could not be reused).

RadioSetupDialog: migrates three QPushButton:disabled CSS blocks.
Reboot Radio button uses new color.button.danger.*disabled tokens to
preserve its intentional danger-red disabled appearance. Upload Firmware
button corrects a prior partial migration that was using
color.meter.bar.fill and color.background.1 as disabled-state stand-ins.
Serial tab Open/Close buttons fix a silent bug: the style string contained
{{token}} placeholders but was applied via plain setStyleSheet(), which
does not run the template engine — tokens were silently discarded. Changed
to applyStyleSheet() so tokens resolve and widgets participate in live
theme switching. Six new color.button.* tokens added to both theme files.

Fixes aethersdr#3446.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@NF0T NF0T requested a review from a team as a code owner June 18, 2026 00:33

@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 source. This is clean and well-scoped — thanks for the careful migration, @NF0T. 👍

Verified:

  • All four color.highlight.* and six color.button.* token names used in C++ match exactly the JSON keys added to both theme files (scopes.root.tokens.color.{highlight,button}), and both files parse. Dotted keys (background.disabled, danger.background.disabled) follow the existing slider/toggle/knob convention.
  • The consumed APIs all exist: ThemeManager::color(const QString&), the themeChanged signal, and applyStyleSheet.
  • The themeChanged → dataChanged({BackgroundRole, ForegroundRole}) connection in the constructor is correct and lifetime-safe (this as context object), and index(m_rows.size()-1, Col::Count-1) spans the right range. Replacing the four static QColor constants with live color(token) lookups in data() correctly closes the gap where a theme switch only repainted on the next 250 ms tick.
  • Serial-tab Open/Close move from setStyleSheet to applyStyleSheet so they now participate in live theme switching — consistent with how Reboot/Upload-Firmware already work. The remaining hardcoded hex in those templates is the non-disabled (normal/hover) state, which is out of this PR's scope; leaving it untouched is fine.

Non-blocking notes:

  • Light-theme color.button.background.disabled resolves to {color.gray.700} while border.disabled is {color.gray.600} — just confirming that's the intended ordering (700 darker than 600 for the fill behind a 600 border); reads fine, only flagging so it's a conscious choice rather than a swap.
  • The highlight tokens being identical across dark/light is acknowledged in the description and is reasonable — a future theme author can override per-scope.

No correctness, scope, or resource concerns. LGTM.


🤖 aethersdr-agent · cost: $6.2725 · 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, value-correct theming migration (Principle IX).

Verified:

  • The high-visibility FreeDV row highlights are exact relocations (kTxBg #fc4500 → color.highlight.tx, kRxBg #379baf → .rx, kMsgBg #e58be5 → .message, kHlFg #000000 → .fg) — no visual change, just hardcoded → token.
  • Token symmetry: all 10 new tokens defined in both default-dark.json and default-light.json; every token the two .cpp files reference resolves (no orphans).
  • themeChanged → dataChanged(Background/ForegroundRole) gives immediate repaint on theme switch.
  • Reboot (danger) disabled dark values are exact relocations preserving the red tint; serial Open/Close correctly moved setStyleSheet → applyStyleSheet so tokens resolve + live theme switching works.

Minor/intentional: the generic button.*.disabled tokens introduce small deliberate changes on two low-visibility disabled states (fixing the semantically-wrong Upload Firmware tokens; standardizing serial buttons on the gray scale) — documented in the PR. CI green across all six. Nice work @NF0T.

@ten9876 ten9876 merged commit 0d2622c into aethersdr:main Jun 19, 2026
6 checks passed
@NF0T NF0T deleted the feat/theme-token-gaps branch June 20, 2026 01:19
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.

[gui] FreeDvReporterModel: migrate hardcoded TX/RX/Msg highlight colors to ThemeManager tokens

2 participants