Summary
The panadapter's split-pair visualization — red SPLIT on the RX VFO, SWAP on the TX VFO, and the spectrum split-pair — only appears when split is enabled from the GUI. When split is enabled by an external controller (rigctld, SmartCAT TS-2000/Flex, TCI), the panadapter doesn't reflect it, even though TX is correctly on the split slice.
Split via panadapter:
Split via rigctld:
Repro
- One radio, slice A (RX) + slice B.
- Enable split externally, e.g. over rigctld:
set_split_vfo 1 VFOB. TX moves to slice B.
- Observe: slice B shows the red TX badge (correct), but both VFOs keep the default grey
SPLIT badge and the spectrum doesn't pair them.
- Compare: enabling split via the GUI SPLIT button shows red SPLIT on the RX VFO and SWAP on the TX VFO, with the spectrum paired.
Root cause — src/gui/MainWindow.cpp:6146
updateSplitState() gates the split-pair styling on the private GUI flag m_splitActive:
bool isTxSlice = (m_splitActive && s->sliceId() == m_splitTxSliceId);
bool isRxSplit = (m_splitActive && s->sliceId() == m_splitRxSliceId);
w->updateSplitBadge(isTxSlice, isRxSplit);
m_splitActive is set true only by GUI-initiated split (MainWindow_Wiring.cpp:2857, MainWindow_Controllers.cpp:442, MainWindow_Shortcuts.cpp:777). An external split sets the model's TX slice (SliceModel::setTxSlice(true)) but never touches m_splitActive, so updateSplitState() sees no split. The TX badge is correct because it's derived from model state (isTxSlice()); only the SPLIT/SWAP pair badges and the spectrum pairing are flag-driven — so every externally-initiated split is invisible to the panadapter.
Fix direction
- Derive the pair from model truth in
updateSplitState(): a slice is "TX-in-split" if isTxSlice() and a distinct RX slice exists on its pan; the other is "RX-in-split" — instead of the m_splitActive/m_splitTxSliceId/m_splitRxSliceId flags.
- Drive
updateSplitState() from model changes — SliceModel::txSliceChanged (RadioModel re-emits at RadioModel.cpp:5126) plus RadioModel::sliceAdded/sliceRemoved — not only the GUI actions.
This makes the panadapter reflect split regardless of initiator and shrinks the GUI's private split state. (Badge logic: VfoWidget.cpp:3157 updateSplitBadge(isTxSlice, isRxSplit).) It's a concrete instance of the slice-lifecycle RFC #3715 — consumers should derive from model truth, not per-consumer state.
Refs #3715.
Summary
The panadapter's split-pair visualization — red SPLIT on the RX VFO, SWAP on the TX VFO, and the spectrum split-pair — only appears when split is enabled from the GUI. When split is enabled by an external controller (rigctld, SmartCAT TS-2000/Flex, TCI), the panadapter doesn't reflect it, even though TX is correctly on the split slice.
Split via panadapter:
Split via rigctld:
Repro
set_split_vfo 1 VFOB. TX moves to slice B.SPLITbadge and the spectrum doesn't pair them.Root cause —
src/gui/MainWindow.cpp:6146updateSplitState()gates the split-pair styling on the private GUI flagm_splitActive:m_splitActiveis set true only by GUI-initiated split (MainWindow_Wiring.cpp:2857,MainWindow_Controllers.cpp:442,MainWindow_Shortcuts.cpp:777). An external split sets the model's TX slice (SliceModel::setTxSlice(true)) but never touchesm_splitActive, soupdateSplitState()sees no split. The TX badge is correct because it's derived from model state (isTxSlice()); only theSPLIT/SWAPpair badges and the spectrum pairing are flag-driven — so every externally-initiated split is invisible to the panadapter.Fix direction
updateSplitState(): a slice is "TX-in-split" ifisTxSlice()and a distinct RX slice exists on its pan; the other is "RX-in-split" — instead of them_splitActive/m_splitTxSliceId/m_splitRxSliceIdflags.updateSplitState()from model changes —SliceModel::txSliceChanged(RadioModel re-emits atRadioModel.cpp:5126) plusRadioModel::sliceAdded/sliceRemoved— not only the GUI actions.This makes the panadapter reflect split regardless of initiator and shrinks the GUI's private split state. (Badge logic:
VfoWidget.cpp:3157updateSplitBadge(isTxSlice, isRxSplit).) It's a concrete instance of the slice-lifecycle RFC #3715 — consumers should derive from model truth, not per-consumer state.Refs #3715.