Feature/source plugins #1

Merged
martino merged 130 commits from feature/source-plugins into main 2026-11-04 07:35:21 +01:00
6 changed files with 23 additions and 12 deletions
Showing only changes of commit f315c677f3 - Show all commits

No files matched your search

+4 -5
View File
@@ -2931,11 +2931,10 @@ now — they are listed so they are not mistaken for anything else:
controls** are pages of the slide-over, reached from the badge bar. Both panes also have a **locked** mode, which is what a returning user gets: the controls** are pages of the slide-over, reached from the badge bar. Both panes also have a **locked** mode, which is what a returning user gets: the
trigger pane shows one line saying what it is set to, the signal list shows only the signals that are trigger pane shows one line saying what it is set to, the signal list shows only the signals that are
on, and neither offers a control that changes the configuration -- each heading has an `[edit]` button on, and neither offers a control that changes the configuration -- each heading has an `[edit]` button
to switch to the full pane, and back. Dragging a signal onto a plot still works while locked -- filling to switch to the full pane, and back. Dragging a signal's badge onto a plot still works while locked --
plots is what the list is for, not configuration -- and a locked row can be dragged from anywhere on it, filling plots is not configuration. A signal's badge is dragged onto a plot, or onto another badge to
the colour chip included. In a window too narrow to show both, where the dock is *overlaid on* the reorder the badges (the order is kept for the session only); the slide-over closes for the length of the
plot, the dock steps aside for the length of the drag so there is something under the pointer to drop drag so there is something under the pointer to drop onto. A **first run** (no session file for that source) comes up
onto. A **first run** (no session file for that source) comes up
unlocked, because configuring the host is what a first run is for. Each pane's heading also carries its **own switch**, the same control as the unlocked, because configuring the host is what a first run is for. Each pane's heading also carries its **own switch**, the same control as the
header bar's button -- clicking either moves both -- because a pane that is *disabled* while its header bar's button -- clicking either moves both -- because a pane that is *disabled* while its
feature is off is a pane whose controls you would otherwise have to leave to turn it back on. With the math feature is off is a pane whose controls you would otherwise have to leave to turn it back on. With the math
+1 -1
View File
@@ -24,7 +24,7 @@
<title>How to reach it</title> <title>How to reach it</title>
<steps> <steps>
<item> <item>
<p>Drag a signal's chip out of the side panel (<key>s</key>) and drop it on a row to <p>Drag a signal's badge from the badge bar onto a row to
add a trace.</p> add a trace.</p>
</item> </item>
<item> <item>
+1 -1
View File
@@ -92,7 +92,7 @@
derived from it; <gui>Signals</gui> holds the trigger and the channel list, where a derived from it; <gui>Signals</gui> holds the trigger and the channel list, where a
math channel is a row of that one list under a <gui>MATH</gui> heading whose math channel is a row of that one list under a <gui>MATH</gui> heading whose
<gui>+</gui> creates one. One row per channel: its colour, an enable switch, its name <gui>+</gui> creates one. One row per channel: its colour, an enable switch, its name
and its unit. Channels are dragged from here onto a plot row.</p> and its unit. A channel's badge in the badge bar is dragged onto a plot row.</p>
</item> </item>
<item> <item>
<title>The plot</title> <title>The plot</title>
+1 -1
View File
@@ -53,7 +53,7 @@
<property name="spacing">6</property> <property name="spacing">6</property>
<child> <child>
<object class="GtkLabel" id="signals_hint"> <object class="GtkLabel" id="signals_hint">
<property name="label" translatable="yes">drag a signal onto a plot</property> <property name="label" translatable="yes">click a signal for its page; drag its badge onto a plot</property>
<property name="halign">start</property> <property name="halign">start</property>
<property name="hexpand">1</property> <property name="hexpand">1</property>
<property name="css-classes">dim-label</property> <property name="css-classes">dim-label</property>
+12 -3
View File
@@ -102,14 +102,23 @@ gboolean on_badge_drop(GtkDropTarget*, const GValue* value, double, double, gpoi
if (prev != moved->button) { // already directly in front: nothing to move if (prev != moved->button) { // already directly in front: nothing to move
gtk_box_reorder_child_after(GTK_BOX(app->badges.signals_row), moved->button, prev); gtk_box_reorder_child_after(GTK_BOX(app->badges.signals_row), moved->button, prev);
} }
// The order, as the widgets now stand. // The order, as the widgets now stand; the names that are not shown (signals switched off) keep their old
app->badge_order.clear(); // relative order after the visible ones, so switching one back on finds it where it was remembered.
std::vector<std::string> order;
for (GtkWidget* c = gtk_widget_get_first_child(app->badges.signals_row); c != nullptr; for (GtkWidget* c = gtk_widget_get_first_child(app->badges.signals_row); c != nullptr;
c = gtk_widget_get_next_sibling(c)) { c = gtk_widget_get_next_sibling(c)) {
for (auto& b : app->badges.signal_badges) { for (auto& b : app->badges.signal_badges) {
if (b->button == c) app->badge_order.push_back(b->signal_name); if (b->button == c) order.push_back(b->signal_name);
} }
} }
const std::size_t shown_count = order.size();
for (const std::string& n : app->badge_order) {
if (std::find(order.begin(), order.begin() + static_cast<std::ptrdiff_t>(shown_count), n) ==
order.begin() + static_cast<std::ptrdiff_t>(shown_count)) {
order.push_back(n);
}
}
app->badge_order = std::move(order);
return TRUE; return TRUE;
} }
+4 -1
View File
@@ -569,6 +569,9 @@ void rebuild_signal_panels(App& app) {
// GTK calls (a use-after-free of the name strings otherwise). // GTK calls (a use-after-free of the name strings otherwise).
std::vector<SignalInfo> signals; std::vector<SignalInfo> signals;
bool have_signals = false; bool have_signals = false;
// The generation this build answers to is read *before* the snapshot: a CONFIG landing between the two
// would otherwise be stamped as seen without having been, and the tick would never rebuild for it.
const unsigned generation = app.model->generation();
{ {
std::lock_guard<std::mutex> lock(app.model->mutex()); std::lock_guard<std::mutex> lock(app.model->mutex());
signals = app.model->signals(); signals = app.model->signals();
@@ -585,7 +588,7 @@ void rebuild_signal_panels(App& app) {
} }
signal_pages_sync(app); signal_pages_sync(app);
sync_signal_badges(app); sync_signal_badges(app);
app.signal_generation = app.model->generation(); app.signal_generation = generation;
} }
GtkWidget* build_signal_panel(App& app) { GtkWidget* build_signal_panel(App& app) {