feat(gui): Waveforms dialog under File menu for WFP status and management#2779
Conversation
…nagement Surfaces the data already collected by FlexWaveformModel (PR aethersdr#2759) in a non-modal, geometry-persistent dialog accessible via File → Waveforms. The dialog shows the WFP power/ready/IP status bar at the top and a scrollable list of installed waveforms and Docker containers. Each row has a Restart button (fire-and-forget, no confirmation) and a Remove/Uninstall button (asks for confirmation before sending the command). Mirrors the SmartSDR File → Waveforms panel in location and function; Install is intentionally omitted as Docker containers are managed at the radio level. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Clean, focused PR — thanks @NF0T! The dialog correctly uses PersistentDialog + showOrRaisePersistent, all model accessors and signals match FlexWaveformModel's API, and commandReady is already wired in RadioModel so the Restart/Remove/Uninstall buttons land on the radio. The disconnect path is handled because FlexWaveformModel::clear() emits both waveformsChanged and wfpStatusChanged.
A couple of small, optional polish suggestions — not blocking:
-
Disable action buttons when WFP isn't ready. Right now
Restart/Remove/Uninstallare always enabled, even when WFP is off or the radio is disconnected. The radio will just ignore the command, but greying them out (e.g.restartBtn->setEnabled(m_model->wfpPowered() && m_model->wfpReady());insiderefreshWaveformList(), and re-running it fromrefreshStatus()or hookingwfpStatusChangedto a single enabled-state update) would give clearer feedback that nothing's going to happen. -
Full rebuild on every
waveformsChanged.refreshWaveformList()deleteLaters every row and rebuilds it whenever the model changes. That's fine for the common case (rare waveform mutations), but if a WFP eventually emits high-frequency status updates that get coalesced intowaveformsChanged, you may want to diff-update instead. Not a problem today.
Nothing else to flag — looks good to me.
|
Claude here — landed at 01:44 UTC. Nine PRs today, Ryan. 🎉 Closing the loop from #2759 (protocol layer captures FlexLib v4.2.18 waveform status) to this PR (user can see and manage them) within hours is the right kind of arc — you built the data layer first, validated it ships clean, then built the UI consumer on top with no MainWindow refresh plumbing because the model emits the right targeted signals (`wfpStatusChanged`, `waveformsChanged`) and the dialog wires directly. Clean separation, easy to maintain. The pattern choices were all the right ones:
The "no install" decision was right — Docker container images live on the radio's internal registry; the client doesn't push them. Matches what SmartSDR does and avoids inventing a surface that conflicts with the radio-side container management. Today's tally: #2745, #2747, #2752, #2754, #2759, #2771, #2773, #2776, #2779. Nine PRs, nine distinct concerns. Consistently excellent. 73, Jeremy KK7GWY & Claude (AI dev partner) |
Summary
Surfaces the data already collected by
FlexWaveformModel(merged in #2759) in a non-modal, geometry-persistent dialog at File → Waveforms, mirroring SmartSDR's layout and location.FlexWaveformModel::wfpStatusChangedFlexWaveformModel::waveformsChangedwaveform restart <name>QMessageBox::questionconfirmation before sendingwaveform remove_container <name>orwaveform uninstall <name>Implementation
WaveformsDialoginheritsPersistentDialog(geometry-persist + frameless-chrome handling) and takes aFlexWaveformModel*in its constructor. No refresh logic inMainWindow— the dialog wiresFlexWaveformModelsignals directly.showOrRaisePersistenthandles lazy-construct, raise-if-open, and frameless toggle registration automatically.Test plan
freedv-flex(or other container) appears in the list with version and[Container]badgewaveform restart freedv-flex— visible in radio logwaveform remove_container freedv-flexFlexWaveformModel::clear())🤖 Generated with Claude Code