Files
udpscope/todo.md
T
Martino Ferrari 68743a7d7f feat: the host form, and the help window, are UI files
src/ui/source-form.ui is the form a source is added or edited with: an AdwDialog of
AdwPreferencesGroup rows (AdwEntryRow, AdwSpinRow, AdwSwitchRow) with its action in the header bar,
where the label says which mode the form is in -- Connect for a new host, Save for an existing
configuration. The grid of labels and bare entries it replaces had its hints in placeholders, which
vanish as soon as there is a value; they are the groups' descriptions now.

src/ui/help.ui is the help window's chrome: an AdwWindow with a header bar and an
AdwNavigationSplitView whose sidebar is the page list. The rows stay in C++ because the fourteen
pages are data, not template.

Four UI files now, 653 lines of template that used to be widget construction. Two libadwaita traps
cost a run each and are in docs/claude/invariants-gtk-and-chrome.md: an AdwDialog has no content
property (its child is a plain <child>, unlike an AdwToolbarView), and AdwEntryRow has no subtitle
(it is an AdwPreferencesRow, not an AdwActionRow). The unused form_field() helper went with them.

Every probe reading is unchanged -- [sources] form:, [sources] edit form:, [help] -- which is what
refactoring a shape rather than a behaviour should look like.
2026-10-11 17:27:05 +02:00

4.8 KiB

  • (1) fix vertical lines to small to be seen: in some cases (e.g. rect waveform in @mock_upstreamer.py) the vertical lines are to thin to be visible (sometime they glitch in and out of existence):
    1. the antialisaing strategy with phosphore effect should be applied with more stregth
    2. the lines should be more tick
    3. the sample points should be bigger
  • (2) relative timing done: --relative-time; see README and SPECS.md for the measured history cost.
    • in order to avoid problem with time jitter user can decide to go in relative time mode
    • in this mode absolute signal time is only use for export
    • the plot time depends just on signal sample rate and frame number, e.g.:
      • user is acquiring a signal with 1MSps and 100_000 samples per udp frame
      • last frame as number and previous in this case a 100_000 indexes must be skipped
      • time is simply: ((<N_frame> - <N_last>) * <n_samples_per_frame> - <sample_index>) / <sample rate> (or something like that)
  • (3) named configurations done: one directory per source holding <name>.toml per configuration plus active; a configuration carries a note and the startup settings (buffer_mb, relative_time, capture_packets); the chooser lists them and the menu's Configurations… opens/saves/deletes them.
  • (4) optional udp frame storage for debugging of strange behaviours done: --capture-packets N; see README and the design note in docs/superpowers/specs/ for the ring file, the popover toggle and tools/capture_to_pcap.py.
  • (5) open exported binary waveforms to view/analyse done: --open FILE and the chooser's Waveforms page (the files opened before, newest first, plus Open…); the .npy's dtype names the columns, so a load restores the signals, the samples and the axis the export had, and every instrument works on it — see README and docs/claude/invariants-data-path.md.
  • (6) imporve right click menu on the plots done: the plot's context menu uses the main menu's row style (menu_button + .udpscope-menu, asserted by UDPSCOPE_PROBE_ROWMENU_MS: uniform label_x=26, h=18, the shortcut flush right), and deleting a signal is a Remove signal submenu listing that plot's traces plus All traces on this plot.
  • (7) in layout edit mode add the option to drag plot border to resize them (sizing should be persistant between sessesions as the layout)
  • (8) add option to automatic save the last triggered acquisitions in a cache folder and let the user replay them done: every latch is written to <cache>/<source>/events/ as a .npy (the export format), a .txt sidecar and a .bmp preview drawn from the samples; the events pane (revealed with trigger mode, switchable) lists them with time, duration, signals and rate, shows the preview, replays one through the --open loader and has Live to go back -- see README and docs/claude/invariants-trigger-and-pinning.md.
  • (9) preferences dialog done: src/settings.{hpp,cpp} (the store: load/save/defaults, GTK-free) + src/ui_prefs.cpp (the dialog, opened from the overflow menu); the cache directory and keep count reach EventStore, the cache directory (one events/ directory for every source, each source a folder inside) and the keep count reach EventStore, and relative time is a start-up default; whether anything is cached at all stays the trigger pane's own switch. The same dialog opens from the host selection dialog too (a PrefsForm has no owner, so both windows hold one), where a change still reaches the run about to start.
    • user can choose evnt cache directory (default /.cache/udpscope//events/)
    • maximum number of events to cache
    • disable completly the events storage option
    • enable/disable relative time mode
    • interface dark/light/auto color
    • defaults
    • other parameters
  1. move the interface into .ui resources, and to current GTK4/libadwaita widgets while doing it:
  • the shortcut overview is done (src/ui/shortcuts.ui, with the mouse gestures drawn as icons, and [help]'s ui= against tables= as the guard)
  • the preferences are done (src/ui/preferences.ui: AdwPreferencesDialog with AdwEntryRow/AdwSpinRow/AdwSwitchRow/AdwComboRow, applying as they change, no Apply button)
  • the help window's chrome is done (src/ui/help.ui: AdwWindow + header bar + AdwNavigationSplitView)
  • the host form is done (src/ui/source-form.ui); the source chooser's own window is next
  • next: the preferences (AdwPreferencesDialog + AdwEntryRow/AdwSpinRow/AdwSwitchRow), the help window's chrome, the source chooser and its host form, then the main window's skeleton
  • plan, conventions and acceptance for each slice: docs/superpowers/plans/2026-10-11-ui-files-and-gtk4-practice.md