summaryrefslogtreecommitdiff
path: root/core/signal_processor.py
diff options
context:
space:
mode:
authorChristian Kolset <ckolset@colostate.edu>2026-08-13 13:39:25 -0600
committerChristian Kolset <ckolset@colostate.edu>2026-08-13 13:39:25 -0600
commit34c12b2b5b280206890cd03153b1c95116acc85e (patch)
tree9b3dee7e0818d94c0bae87a35e7bf930a612ca2c /core/signal_processor.py
parenta6e812dcbf3f2fc27565e52b6c0c6f9b7e4363ee (diff)
Channels tab drag-to-reorder, Namespace absolute references, fix stale Channel ID renames
Generalized the Plot pane drag-to-reorder (_PaneDragHandle/_PlotDropContainer -> _DragHandle/_DragReorderContainer) and reused it for the Channels tab's derived-channel list; reordering also updates SignalProcessor's evaluation order (list order matters for chained Channels) via new reorder_derived(). Namespace panel: added an ID column (bare channel_id, matching the actual channels.get(...) script convention) and fixed the Source column for Channels to show resolved absolute references (dev_id/ch_id for a Signal, bare id for a chained Channel) instead of the operation kind, so a chain is traceable by eye. Fixed a real bug this surfaced: renaming a Channel's ID never propagated to other Channels' sources, leaving dangling ("derived", old_id) references that silently stopped updating. Added SignalProcessor.rename_derived() to fix up sources plus carry the ring buffer/latest-value cache to the new key, wired to DerivedBlock's Apply. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'core/signal_processor.py')
-rw-r--r--core/signal_processor.py41
1 files changed, 41 insertions, 0 deletions
diff --git a/core/signal_processor.py b/core/signal_processor.py
index 8abaff8..4781e91 100644
--- a/core/signal_processor.py
+++ b/core/signal_processor.py
@@ -437,6 +437,47 @@ class SignalProcessor(QObject):
self._derived = [d for d in self._derived if d.channel_id != channel_id]
self._derived_bufs.pop(channel_id, None)
+ def rename_derived(self, old_id: str, new_id: str):
+ """Propagate a Channel ID rename to every other derived channel's
+ sources — otherwise anything chained from it keeps a dangling
+ ("derived", old_id) reference (SignalProcessor._evaluate_derived
+ looks sources up by exact match) and silently stops updating.
+ Also carries the ring buffer and latest-value cache over under the
+ new key so the rename doesn't reset plotted history or blank the
+ Value column for a poll cycle. Does NOT touch source_names or
+ expression/script text — those are display labels / user-authored
+ code, out of scope for an automatic rewrite."""
+ if old_id == new_id:
+ return
+ with self._lock:
+ for dc in self._derived:
+ if dc.channel_id == new_id:
+ continue
+ new_sources = [
+ ("derived", new_id) if d == "derived" and c == old_id else (d, c)
+ for d, c in dc.sources
+ ]
+ if new_sources != dc.sources:
+ dc.sources = new_sources
+
+ buf = self._derived_bufs.pop(old_id, None)
+ if buf is not None:
+ self._derived_bufs[new_id] = buf
+
+ entry = self._latest.pop(("derived", old_id), None)
+ if entry is not None:
+ self._latest[("derived", new_id)] = entry
+
+ def reorder_derived(self, src_idx: int, dst_idx: int):
+ """Move the derived channel at src_idx to dst_idx — list order is
+ evaluation order (see _evaluate_derived): a Channel sourced from
+ another Channel needs that source evaluated earlier in the same
+ pass, or it reads a stale value and lags by one sample cycle."""
+ with self._lock:
+ if 0 <= src_idx < len(self._derived) and 0 <= dst_idx < len(self._derived):
+ dc = self._derived.pop(src_idx)
+ self._derived.insert(dst_idx, dc)
+
def get_derived(self) -> List[DerivedChannel]:
return list(self._derived)