cleaned up ui added exporter

This commit is contained in:
Martino Ferrari committed 2026-10-01 16:16:17 +02:00
1 parent 8059b90de7
commit ea560ed272
4 files changed
+225 -3

No files matched your search

+40 -3
View File
@@ -44,6 +44,7 @@ src/channel.* ChannelBuffer (a ring pair as a plot::data::Series) and SlotS
src/acquisition.* the UDPStreamer client, the producer thread, frame decoding
src/trigger.* the trigger configuration and the producer-side state machine
src/plot_host.* the one plot::Figure, its rows' traces and cursors, the x link group
src/export.* the visible range as a table, and the .npy / .csv writers
src/ui.* the GTK4 window: toolbar, trigger panel, signal panel, plot box
```
@@ -188,8 +189,8 @@ assumed.
pause/resume, the trigger toggle, the side-panel toggle and an overflow menu. Those
four buttons are icons with tooltips; nine text buttons was a wall of words to read
past every time you wanted the one you needed. The overflow menu holds **Fit to
data**, **Cursors**, **Reset cursors** and the **Signal list** toggle — the things
you set up once. The side column and the two panel toggles stay hidden until a
data**, **Cursors**, **Reset cursors**, **Export visible range…** and the
**Signal list** toggle — the things you set up once. The side column and the two panel toggles stay hidden until a
CONFIG arrives — there is nothing to configure before the stream describes itself —
and the first CONFIG reveals the signal panel (the trigger panel stays behind its
own toggle).
@@ -239,7 +240,19 @@ latch, which the status line reports.
The signal panel is one line per signal: a colour chip naming the trace it is drawn
as, a checkbox that acquires it, its name, its unit, and a `⋯` menu holding the
information popup and the gain/offset calibration popup. A `GtkSwitch` and two
information popup and the gain/offset calibration popup.
**The chip's colour belongs to the signal, not to the slot it landed in.** The
palette is indexed by position in the signal list (`signal_color_index()`), so a
signal dropped on two rows is the same colour in both and the chip names a trace
unambiguously; indexing by trace slot made the same signal blue on row 1 and orange
on row 2, and then the chip named neither. A signal that is on no plot — acquired or
not — gets a **grey** chip rather than no chip, so every row of the panel is the same
shape and the column of chips reads as a legend. Because `plot::Plot` fixes a trace's
colour at `add_trace()`, the index is stored on the row (`Row::color_index`) and a
colour change goes through a figure rebuild, which a drop already forces.
A `GtkSwitch` and two
always-visible buttons made a row about twice as tall (46 px against 26 px now),
which is what turned a four-signal stream into a panel you have to scroll; Adwaita's
button and list-row minimums, not the widgets themselves, set that height, so the
@@ -342,6 +355,30 @@ the widget keeps its context. A displayed event survives the rebuild because the
pinned `[-pre, +post]` window is restated rather than re-derived from the live
edge.
**Export visible range…** (overflow menu) writes every signal bound to a visible row,
over the shared x window, at the **stored** sample rate — never the LOD pyramid's
buckets, which are the envelope the renderer drew rather than the acquisition. A
signal on several rows is one column; the columns come out in channel order, so the
file reads in the same order as the signal panel. The table has two time columns:
`time` is the axis as displayed (stream seconds live, `[-pre, +post]` while an event
is held) and `stream_time` is always the stream's own clock, so two exports taken in
different modes line up.
Two formats, picked by the extension the save dialog ends up with:
| file | what it is |
|---|---|
| `.npy` | one NumPy structured array, `time`/`stream_time` as `<f8` and every signal as `<f4` — the width the ring stores, so the file invents no precision and is about half an all-`f8` one. `pd.DataFrame(np.load(path))` is the whole reader. |
| `.csv` | the same table as text, `%.17g` for the times and `%.9g` for the values: the shortest widths that round-trip each type exactly. |
Parquet (the original ask) would have meant linking Arrow — tens of megabytes of
dependency for a feature whose output a three-line reader already handles.
The table is collected when the menu item is clicked, not when the dialog is
answered: a live view keeps scrolling while the file chooser is up. The live cut goes
through `ScopeModel::live_window_locked()`, the same index range `publish_event()`
uses, so an export and a capture of the same window hold the same samples.
## Review findings not (yet) implemented
These are known deviations, found by a spec/code review, that are deliberate for