Preflight
Problem
The Tuner applet's OPERATE/BYPASS/STANDBY control is a single button that cycles through the three states on each click, rather than setting a specific mode directly. Reaching a given mode can take up to two extra clicks depending on current state, and the button only displays the current mode, not the mode a click will produce — so it's easy to overshoot past the mode you meant to select.
This isn't just a UX preference — it's tied to a real bug history. I reported a label-desync issue in #3355 (button text falling out of sync with actual tuner state during the cycle), which was addressed by #3423, but #3594 showed the underlying problem persisted. I opened #4225 proposing direct-entry buttons as the fix, on the reasoning that eliminating the cycling state machine removes the whole class of desync bug rather than patching it again.
Proposal
Replace the single cycling button with three separate buttons — OPER, BYP, STBY — placed directly under the ANT1/ANT2/ANT3 antenna row so the two rows read as one aligned 3-column control group. Each button sets its mode directly via the existing TunerModel::setOperate()/setBypass() calls — no intermediate state tracking, no cycling logic. syncFromModel() highlights whichever button matches the tuner's actual current state (green/OPERATE, orange/BYPASS, blue/STANDBY) so the active mode is visible at a glance, and updates correctly regardless of what triggered the state change (this button, another client, Maestro, etc.).
Cross-platform impact
Linux: no change in behavior expected — pure Qt Widgets code (QPushButton, QHBoxLayout), no platform-conditional branches touched.
macOS: same as Linux.
Windows: built and tested directly (MSVC 2022, Qt 6.8.3) — builds and runs cleanly.
No platform-specific code was added or modified; the change is entirely within shared Qt widget layout code.
Alternatives considered
Implementation scope
Files affected: src/gui/TunerApplet.cpp, src/gui/TunerApplet.h
New dependencies: none
Known risks: none identified — no model-layer changes, only widget wiring. Tested against a real Tuner Genius XL: all three modes command correctly on a single click; relay bars and SWR readout continue to reflect real hardware state as before.
Preflight
Problem
The Tuner applet's OPERATE/BYPASS/STANDBY control is a single button that cycles through the three states on each click, rather than setting a specific mode directly. Reaching a given mode can take up to two extra clicks depending on current state, and the button only displays the current mode, not the mode a click will produce — so it's easy to overshoot past the mode you meant to select.
This isn't just a UX preference — it's tied to a real bug history. I reported a label-desync issue in #3355 (button text falling out of sync with actual tuner state during the cycle), which was addressed by #3423, but #3594 showed the underlying problem persisted. I opened #4225 proposing direct-entry buttons as the fix, on the reasoning that eliminating the cycling state machine removes the whole class of desync bug rather than patching it again.
Proposal
Replace the single cycling button with three separate buttons — OPER, BYP, STBY — placed directly under the ANT1/ANT2/ANT3 antenna row so the two rows read as one aligned 3-column control group. Each button sets its mode directly via the existing TunerModel::setOperate()/setBypass() calls — no intermediate state tracking, no cycling logic. syncFromModel() highlights whichever button matches the tuner's actual current state (green/OPERATE, orange/BYPASS, blue/STANDBY) so the active mode is visible at a glance, and updates correctly regardless of what triggered the state change (this button, another client, Maestro, etc.).
Cross-platform impact
Linux: no change in behavior expected — pure Qt Widgets code (QPushButton, QHBoxLayout), no platform-conditional branches touched.
macOS: same as Linux.
Windows: built and tested directly (MSVC 2022, Qt 6.8.3) — builds and runs cleanly.
No platform-specific code was added or modified; the change is entirely within shared Qt widget layout code.
Alternatives considered
Implementation scope
Files affected: src/gui/TunerApplet.cpp, src/gui/TunerApplet.h
New dependencies: none
Known risks: none identified — no model-layer changes, only widget wiring. Tested against a real Tuner Genius XL: all three modes command correctly on a single click; relay bars and SWR readout continue to reflect real hardware state as before.