From f3327d56d48d63b21ffc03a55fa5e7db753d1707 Mon Sep 17 00:00:00 2001 From: Christian Kolset Date: Sat, 19 Sep 2026 17:38:07 -0600 Subject: Redesign Signal/Channel naming and fix pin-remap breaking references Arduino analog Signal ids used to be the pin name itself, so fixing a wrong pin silently changed the id and orphaned any plot trace, control, or filter pipeline pointing at it. Analog Signal ids are now positional (ai0, ai1, ...) and decoupled from the underlying pin, matching how digital I/O already worked. More broadly, formalizes a Device -> Signal -> Channel -> Plot naming model (SignalConfig for physical device channels, Channel for derived/ computed ones) and adds core/reference_registry.py to propagate any Signal or Channel id rename through plot traces, controls, and filter pipelines instead of leaving them dangling. Signal ids are now editable in the Signals tab with the same propagation. .labui profile schema bumped to v2.0 with a transparent migration for old files, including remapping old pin-name Signal ids to the new positional ones. Removed six confirmed-dead files (two legacy device classes, four superseded top-level ui/ duplicates). --- ui/windows/channels_window.py | 105 ++++++++++++++++++++++-------------------- ui/windows/config_window.py | 69 ++++++++++++++++++++++----- ui/windows/devices_window.py | 20 ++++---- ui/windows/plot_window.py | 16 +++---- 4 files changed, 131 insertions(+), 79 deletions(-) (limited to 'ui/windows') diff --git a/ui/windows/channels_window.py b/ui/windows/channels_window.py index 87d7840..f581851 100644 --- a/ui/windows/channels_window.py +++ b/ui/windows/channels_window.py @@ -15,7 +15,7 @@ Classes: PipelineTab — splitter content (physical + virtual sections) ChannelPipelineBlock — collapsible filter+math stack for one physical channel ChannelPickerDialog — checkbox dialog for selecting channels to add - DerivedBlock — editor for one virtual/derived channel + ChannelBlock — editor for one virtual/derived channel FilterRow — single filter stage row inside a pipeline block SignalsListTab — unused; kept for profile-load compatibility """ @@ -35,7 +35,7 @@ from PyQt6.QtGui import QCloseEvent, QFont, QFontMetrics from devices.device_registry import DeviceRegistry from core.signal_processor import ( - SignalProcessor, ChannelPipeline, DerivedChannel, + SignalProcessor, ChannelPipeline, Channel, FilterBase, FILTER_CLASSES, ) from ui.windows.plot_window import _DragHandle, _DragReorderContainer @@ -60,8 +60,8 @@ def _channel_display_name(registry: DeviceRegistry, else: for dev in registry.all_instances(): if dev.info.device_id == dev_id: - for ch in dev.info.channels: - if ch.channel_id == ch_id: + for ch in dev.info.signals: + if ch.signal_id == ch_id: return ch.name if ch.name else ch_id return ch_id @@ -72,16 +72,16 @@ def _channel_combo(registry: DeviceRegistry, show_unit: bool = False) -> QComboBox: cb = QComboBox(); cb.setObjectName("channelPickerCb") for dev in registry.all_instances(): - for ch in dev.info.channels: + for ch in dev.info.signals: if not ch.enabled: continue - label = f"{ch.name} ({dev.info.device_id}/{ch.channel_id})" + label = f"Signal: {ch.name} ({dev.info.device_id}/{ch.signal_id})" if show_unit and ch.unit: label += f" [{ch.unit}]" - cb.addItem(label, userData=(dev.info.device_id, ch.channel_id)) + cb.addItem(label, userData=(dev.info.device_id, ch.signal_id)) if include_derived and processor: for dc in processor.get_derived(): - label = f"[derived] {dc.channel_id} ({dc.name})" + label = f"Channel: {dc.channel_id} ({dc.name})" if show_unit and dc.unit: label += f" [{dc.unit}]" cb.addItem(label, userData=("derived", dc.channel_id)) @@ -110,17 +110,17 @@ class ChannelPickerDialog(QDialog): any_available = False for dev in registry.all_instances(): - for ch in dev.info.channels: + for ch in dev.info.signals: if not ch.enabled: continue - if (dev.info.device_id, ch.channel_id) in already_shown: + if (dev.info.device_id, ch.signal_id) in already_shown: continue any_available = True - label = f"{ch.name} ({dev.info.device_id}/{ch.channel_id})" + label = f"{ch.name} ({dev.info.device_id}/{ch.signal_id})" if ch.unit: label += f" [{ch.unit}]" chk = QCheckBox(label) - self._checks.append((chk, dev.info.device_id, ch.channel_id)) + self._checks.append((chk, dev.info.device_id, ch.signal_id)) cl.addWidget(chk) if not any_available: @@ -237,7 +237,7 @@ class ChannelPipelineBlock(QFrame): self._unit = unit outer = QVBoxLayout(self); outer.setContentsMargins(0, 0, 0, 0); outer.setSpacing(0) - # Header (omitted when embedded in another block, e.g. DerivedBlock's + # Header (omitted when embedded in another block, e.g. ChannelBlock's # Filters section — the parent already provides a header/toggle) if self._show_header: hdr = QWidget(); hdr.setObjectName("plotBlockHeader"); hdr.setFixedHeight(32) @@ -405,6 +405,7 @@ class ChannelPipelineBlock(QFrame): class PipelineTab(QWidget): changed = pyqtSignal() derived_changed = pyqtSignal() + channel_renamed = pyqtSignal(str, str, str, str) # old_dev, old_id, new_dev, new_id def __init__(self, registry: DeviceRegistry, processor: SignalProcessor): super().__init__() @@ -412,7 +413,7 @@ class PipelineTab(QWidget): self.processor = processor self._shown: Set[Tuple[str, str]] = set() self._blocks: dict[Tuple[str, str], ChannelPipelineBlock] = {} - self._derived_blocks: List[DerivedBlock] = [] + self._derived_blocks: List[ChannelBlock] = [] self._color_idx = 0 self._build() @@ -494,9 +495,9 @@ class PipelineTab(QWidget): QTimer.singleShot(0, _init_split) for dev in self.registry.all_instances(): - for ch in dev.info.channels: + for ch in dev.info.signals: if ch.enabled: - self._add_block(dev.info.device_id, ch.channel_id, ch.name, ch.unit) + self._add_block(dev.info.device_id, ch.signal_id, ch.name, ch.unit) # ── Physical channel block management ────────────────────────────────────── @@ -516,7 +517,7 @@ class PipelineTab(QWidget): if key not in self._shown: dev = self.registry.get_instance(dev_id) if dev: - ch = dev.get_channel(ch_id) + ch = dev.get_signal(ch_id) if ch: self._add_block(dev_id, ch_id, ch.name, ch.unit) else: @@ -541,7 +542,7 @@ class PipelineTab(QWidget): if dev is None: self.on_device_removed(dev_id) return - valid = {ch.channel_id for ch in dev.info.channels} + valid = {ch.signal_id for ch in dev.info.signals} keys = [(d, c) for (d, c) in list(self._shown) if d == dev_id and c not in valid] for key in keys: @@ -560,7 +561,7 @@ class PipelineTab(QWidget): else: dev = self.registry.get_instance(dev_id) if dev: - ch = dev.get_channel(ch_id) + ch = dev.get_signal(ch_id) if ch and ch.enabled: self._add_block(dev_id, ch_id, ch_name, ch.unit) self._refresh_src_cb() @@ -580,13 +581,13 @@ class PipelineTab(QWidget): self._src_cb.clear() self._src_cb.insertItem(0, "Signal: none (empty channel)", userData=None) for dev in self.registry.all_instances(): - for ch in dev.info.channels: + for ch in dev.info.signals: if not ch.enabled: continue - label = f"{ch.name} ({dev.info.device_id}/{ch.channel_id})" - self._src_cb.addItem(label, userData=(dev.info.device_id, ch.channel_id)) + label = f"Signal: {ch.name} ({dev.info.device_id}/{ch.signal_id})" + self._src_cb.addItem(label, userData=(dev.info.device_id, ch.signal_id)) for dc in self.processor.get_derived(): - label = f"[derived] {dc.channel_id} ({dc.name})" + label = f"Channel: {dc.channel_id} ({dc.name})" self._src_cb.addItem(label, userData=("derived", dc.channel_id)) if current: for i in range(self._src_cb.count()): @@ -607,7 +608,7 @@ class PipelineTab(QWidget): dev = self.registry.get_instance(dev_id) if not dev: continue - ch = dev.get_channel(ch_id) + ch = dev.get_signal(ch_id) if not ch: continue self._add_block(dev_id, ch_id, ch.name, ch.unit) @@ -635,23 +636,27 @@ class PipelineTab(QWidget): src_name = f"Channel {len(self._derived_blocks) + 1}" name = _dedupe_name(src_name, existing_names) channel_id = _slug_id(name, existing_ids) - dc = DerivedChannel(channel_id=channel_id, name=name, + dc = Channel(channel_id=channel_id, name=name, kind="expression", color=color) blk = self._make_derived_block(dc) self._virt_inner.insertWidget(self._virt_inner.count() - 1, blk) if src: blk._add_src(src) - def _make_derived_block(self, dc: DerivedChannel) -> DerivedBlock: - blk = DerivedBlock(dc, self.registry, self.processor) + def _make_derived_block(self, dc: Channel) -> ChannelBlock: + blk = ChannelBlock(dc, self.registry, self.processor) blk.removed.connect(self._rm_virtual) blk.applied.connect(lambda _: self.derived_changed.emit()) - blk.id_renamed.connect(self.refresh_derived) + blk.id_renamed.connect(self._on_block_id_renamed) blk._drag_handle.set_drag_source(self, blk) self._derived_blocks.append(blk) return blk - def _rm_virtual(self, blk: DerivedBlock): + def _on_block_id_renamed(self, old_id: str, new_id: str): + self.refresh_derived() + self.channel_renamed.emit("derived", old_id, "derived", new_id) + + def _rm_virtual(self, blk: ChannelBlock): self.processor.remove_derived(blk.dc.channel_id) self._derived_blocks.remove(blk) self._virt_inner.removeWidget(blk); blk.deleteLater() @@ -659,7 +664,7 @@ class PipelineTab(QWidget): # ── Drag-to-reorder — see _DragReorderContainer in ui/windows/plot_window.py - def _index_of(self, block: DerivedBlock) -> int: + def _index_of(self, block: ChannelBlock) -> int: return self._derived_blocks.index(block) def _drop_index(self, y: float) -> int: @@ -708,7 +713,7 @@ class PipelineTab(QWidget): self.derived_changed.emit() def refresh_derived(self): - """Rebuild DerivedBlock widgets from processor state (called after profile load).""" + """Rebuild ChannelBlock widgets from processor state (called after profile load).""" for blk in self._derived_blocks: self._virt_inner.removeWidget(blk); blk.deleteLater() self._derived_blocks.clear() @@ -723,7 +728,7 @@ class PipelineTab(QWidget): # ══════════════════════════════════════════════════════════════════════════════ -# Derived editor for one DerivedChannel +# Derived editor for one Channel # ══════════════════════════════════════════════════════════════════════════════ _BUILTIN = ["none", "scale_offset", "derivative", "second_derivative", "power", "rms", "difference", "sum"] @@ -806,13 +811,17 @@ def _sub_xrefs(code: str, names: list) -> str: return re.sub(r'\bx\[(\d+)\]', repl, code) -class DerivedBlock(QFrame): +class ChannelBlock(QFrame): removed = pyqtSignal(object) - applied = pyqtSignal(object) # DerivedChannel - id_renamed = pyqtSignal() # this Channel's ID changed — other blocks' - # source pickers may now be stale - - def __init__(self, dc: DerivedChannel, registry: DeviceRegistry, + applied = pyqtSignal(object) # Channel + id_renamed = pyqtSignal(str, str) # old_id, new_id — this Channel's ID + # changed; other blocks' source + # pickers, and everything outside + # this processor referencing it + # (plot traces, controls), may now + # be stale — see propagate_rename() + + def __init__(self, dc: Channel, registry: DeviceRegistry, processor: SignalProcessor): super().__init__() self.dc = dc; self.registry = registry; self.processor = processor @@ -1192,12 +1201,8 @@ class DerivedBlock(QFrame): self._st.setStyleSheet("color:#ef4444;") return renamed = channel_id != self._orig_id + old_id = self._orig_id if renamed: - # Other channels sourced from this one under the old ID would - # otherwise keep pointing at a reference that no longer exists — - # fix their sources up front, carry the ring buffer + latest - # value over so the rename doesn't reset their plotted history. - self.processor.rename_derived(self._orig_id, channel_id) self._orig_id = channel_id sources = [cb.currentData() for cb in self._src_combos if cb.currentData()] if self.dc.kind in ("derivative", "second_derivative"): @@ -1215,11 +1220,11 @@ class DerivedBlock(QFrame): elif self.dc.kind in ("function", "custom_script"): self.dc.script = self._code.toPlainText() err = self.processor.add_derived(self.dc) - # The rename above already committed regardless of whether this - # channel's own expression/script compiles — other blocks' source - # pickers need to refresh either way. + # Emitted regardless of whether this channel's own expression/script + # compiles — propagate_rename() (via id_renamed) still needs to run + # so other channels' sources / plot traces / controls don't dangle. if renamed: - self.id_renamed.emit() + self.id_renamed.emit(old_id, channel_id) if err: self._st.setText(f"⚠ {err[:100]}") self._st.setStyleSheet("color:#ef4444;") @@ -1261,12 +1266,12 @@ class SignalsListTab(QWidget): if it.widget(): it.widget().deleteLater() for dev in self.registry.all_instances(): - for ch in dev.info.channels: + for ch in dev.info.signals: dev_id_cap = dev.info.device_id - ch_id_cap = ch.channel_id + ch_id_cap = ch.signal_id self._lay.addWidget(self._make_row( color = ch.color, - name = f"{ch.channel_id} — {ch.name}", + name = f"{ch.signal_id} — {ch.name}", unit = ch.unit, source = dev_id_cap, enabled = ch.enabled, diff --git a/ui/windows/config_window.py b/ui/windows/config_window.py index 604b6ed..62789f1 100644 --- a/ui/windows/config_window.py +++ b/ui/windows/config_window.py @@ -28,9 +28,9 @@ from PyQt6.QtGui import QCloseEvent, QColor, QShowEvent from devices.device_registry import DeviceRegistry from core.acquisition import AcquisitionEngine -from core.signal_processor import SignalProcessor, DerivedChannel +from core.signal_processor import SignalProcessor, Channel -from ui.windows.devices_window import DeviceRow, ChannelsTab +from ui.windows.devices_window import DeviceRow, SignalsTab from ui.windows.channels_window import PipelineTab, _slug_id, _dedupe_name from ui.windows.plot_window import ( PlotWindow, LayoutConfig, LayoutCanvas, PaneBlock, @@ -43,8 +43,8 @@ from ui.namespace_panel import NamespacePanel # Enhanced signals table — adds Dir badge and pipeline ⚙ button # ══════════════════════════════════════════════════════════════════════════════ -class _SignalsTab(ChannelsTab): - """ChannelsTab with a Dir (READ/WRITE) badge. Operations (filters/calibration/math) +class _SignalsTab(SignalsTab): + """SignalsTab with a Dir (READ/WRITE) badge. Operations (filters/calibration/math) are configured per Channel in the Channels pane, not here.""" _C_DEVICE = 0 @@ -58,6 +58,7 @@ class _SignalsTab(ChannelsTab): _C_MKCH = 8 # "+ Channel" button channel_created = pyqtSignal() + channel_renamed = pyqtSignal(str, str, str, str) # old_dev, old_id, new_dev, new_id def __init__(self, registry: DeviceRegistry, processor: SignalProcessor): self._processor = processor @@ -91,7 +92,7 @@ class _SignalsTab(ChannelsTab): self._table.setRowCount(0) row = 0 for dev in self.registry.all_instances(): - for ch in dev.info.channels: + for ch in dev.info.signals: self._table.insertRow(row) dev_item = QTableWidgetItem(f"{dev.info.icon} {dev.info.device_id}") @@ -99,8 +100,8 @@ class _SignalsTab(ChannelsTab): dev_item.setForeground(QColor("#64748b")) self._table.setItem(row, self._C_DEVICE, dev_item) - ch_item = QTableWidgetItem(ch.channel_id) - ch_item.setFlags(ch_item.flags() & ~Qt.ItemFlag.ItemIsEditable) + ch_item = QTableWidgetItem(ch.signal_id) + ch_item.setData(Qt.ItemDataRole.UserRole, (dev.info.device_id, ch.signal_id)) ch_item.setForeground(QColor(ch.color)) self._table.setItem(row, self._C_CH_ID, ch_item) @@ -122,7 +123,7 @@ class _SignalsTab(ChannelsTab): chk.setEnabled(False) else: dev_id_cap = dev.info.device_id - ch_id_cap = ch.channel_id + ch_id_cap = ch.signal_id chk.toggled.connect( lambda checked, d=dev_id_cap, c=ch_id_cap: self._on_enabled(d, c, checked) @@ -131,7 +132,7 @@ class _SignalsTab(ChannelsTab): self._table.setCellWidget(row, self._C_ENABLED, chk_w) name_item = QTableWidgetItem(ch.name) - name_item.setData(Qt.ItemDataRole.UserRole, (dev.info.device_id, ch.channel_id)) + name_item.setData(Qt.ItemDataRole.UserRole, (dev.info.device_id, ch.signal_id)) self._table.setItem(row, self._C_NAME, name_item) self._table.setItem(row, self._C_UNIT, QTableWidgetItem(ch.unit)) @@ -148,7 +149,7 @@ class _SignalsTab(ChannelsTab): mkch_btn.setFixedSize(24, 22) mkch_btn.setToolTip("Create a Channel from this Signal") d_cap, c_cap, n_cap, u_cap, col_cap = ( - dev.info.device_id, ch.channel_id, ch.name, ch.unit, ch.color + dev.info.device_id, ch.signal_id, ch.name, ch.unit, ch.color ) mkch_btn.clicked.connect( lambda _=False, d=d_cap, c=c_cap, n=n_cap, u=u_cap, col=col_cap: @@ -161,6 +162,49 @@ class _SignalsTab(ChannelsTab): self._table.blockSignals(False) + def _on_cell_changed(self, row: int, col: int): + if col == self._C_CH_ID: + self._on_id_edited(row) + return + super()._on_cell_changed(row, col) + + def _on_id_edited(self, row: int): + """Signal IDs are stable/backend-facing by default (see + devices/base_device.py::SignalConfig) but user-editable here, same + as a derived Channel's ID — renaming propagates through + reference_registry.propagate_rename() (wired via channel_renamed) + so plot traces / controls / pipelines pointing at the old id follow + it instead of going dangling (the bug that motivated this feature: + an Arduino analog pin remap used to change the id outright).""" + id_item = self._table.item(row, self._C_CH_ID) + if id_item is None: + return + ref = id_item.data(Qt.ItemDataRole.UserRole) + if ref is None: + return + dev_id, old_id = ref + new_id = id_item.text().strip() + if not new_id or new_id == old_id: + self._table.blockSignals(True) + id_item.setText(old_id) + self._table.blockSignals(False) + return + dev = self.registry.get_instance(dev_id) + if not dev or any(s.signal_id == new_id for s in dev.info.signals if s.signal_id != old_id): + self._table.blockSignals(True) + id_item.setText(old_id) + self._table.blockSignals(False) + return + ch = dev.get_signal(old_id) + if not ch: + return + ch.signal_id = new_id + id_item.setData(Qt.ItemDataRole.UserRole, (dev_id, new_id)) + name_item = self._table.item(row, self._C_NAME) + if name_item is not None: + name_item.setData(Qt.ItemDataRole.UserRole, (dev_id, new_id)) + self.channel_renamed.emit(dev_id, old_id, dev_id, new_id) + def _on_create_channel(self, dev_id: str, ch_id: str, ch_name: str, unit: str, color: str): """Create a passthrough Channel (kind="none") from this Signal, named after it — the "1 Signal -> 1 Channel" quick path. No-ops if @@ -173,7 +217,7 @@ class _SignalsTab(ChannelsTab): existing_ids = {d.channel_id for d in existing} name = _dedupe_name(ch_name, existing_names) channel_id = _slug_id(name, existing_ids) - dc = DerivedChannel(channel_id=channel_id, name=name, kind="none", + dc = Channel(channel_id=channel_id, name=name, kind="none", sources=[(dev_id, ch_id)], source_names=[ch_name], unit=unit, color=color or "#00d4ff") err = self._processor.add_derived(dc) @@ -275,6 +319,7 @@ class ConfigWindow(QWidget): channel_unit_changed = pyqtSignal(str, str, str) pipeline_changed = pyqtSignal() derived_changed = pyqtSignal() + channel_renamed = pyqtSignal(str, str, str, str) # old_dev, old_id, new_dev, new_id layout_applied = pyqtSignal(object) closed = pyqtSignal() @@ -360,6 +405,7 @@ class ConfigWindow(QWidget): self._signals_tab.channel_visibility_changed.connect(self._on_sig_visibility) self._signals_tab.channel_name_changed.connect(self._on_sig_name) self._signals_tab.channel_unit_changed.connect(self._on_sig_unit) + self._signals_tab.channel_renamed.connect(self.channel_renamed) sig_l.addWidget(self._signals_tab, 1) splitter.addWidget(sig_w) @@ -468,6 +514,7 @@ class ConfigWindow(QWidget): self._pipeline_tab = PipelineTab(self.registry, self.processor) self._pipeline_tab.changed.connect(self.pipeline_changed) self._pipeline_tab.derived_changed.connect(self.derived_changed) + self._pipeline_tab.channel_renamed.connect(self.channel_renamed) self._pipeline_tab.refresh_derived() # load derived channels already in processor # (e.g. window built fresh after profile load) inner_splitters = self._pipeline_tab.findChildren(QSplitter) diff --git a/ui/windows/devices_window.py b/ui/windows/devices_window.py index ae88c6b..5d47681 100644 --- a/ui/windows/devices_window.py +++ b/ui/windows/devices_window.py @@ -5,7 +5,7 @@ DEVICES window — toolbar section 2. Tabs: Physical Devices — add / remove / connect devices; shows status cards - Channels — per-device channel list: rename, set unit, enable/disable + Signals — per-device signal list: rename, set unit, enable/disable """ from PyQt6.QtWidgets import ( @@ -84,7 +84,7 @@ class DeviceRow(QFrame): self._status_lbl = QLabel(_STATUS_TEXT.get(self.device.status, "?")) self._status_lbl.setObjectName("deviceSub") self._set_status_style() - n = sum(1 for c in self.device.info.channels if c.enabled) + n = sum(1 for c in self.device.info.signals if c.enabled) ch_lbl = QLabel(f"{n} ch") ch_lbl.setObjectName("deviceChannelCount") stat_col.addWidget(self._status_lbl) @@ -129,7 +129,7 @@ class DeviceRow(QFrame): ) -class ChannelsTab(QWidget): +class SignalsTab(QWidget): """Shows all channels across all devices in an editable table.""" channel_visibility_changed = pyqtSignal(str, str, bool) # dev_id, ch_id, enabled @@ -174,12 +174,12 @@ class ChannelsTab(QWidget): self._table.setRowCount(0) row = 0 for dev in self.registry.all_instances(): - for ch in dev.info.channels: + for ch in dev.info.signals: self._table.insertRow(row) # Device + signal ID folded into one non-editable column — # the separate "Signal ID" column was removed as redundant. - dev_item = QTableWidgetItem(f"{dev.info.icon} {dev.info.device_id} / {ch.channel_id}") + dev_item = QTableWidgetItem(f"{dev.info.icon} {dev.info.device_id} / {ch.signal_id}") dev_item.setFlags(dev_item.flags() & ~Qt.ItemFlag.ItemIsEditable) dev_item.setForeground(QColor("#64748b")) self._table.setItem(row, self._C_DEVICE, dev_item) @@ -192,7 +192,7 @@ class ChannelsTab(QWidget): chk = QCheckBox() chk.setChecked(ch.enabled) dev_id_cap = dev.info.device_id - ch_id_cap = ch.channel_id + ch_id_cap = ch.signal_id chk.toggled.connect( lambda checked, d=dev_id_cap, c=ch_id_cap: self._on_enabled(d, c, checked) ) @@ -200,7 +200,7 @@ class ChannelsTab(QWidget): self._table.setCellWidget(row, self._C_ENABLED, chk_container) name_item = QTableWidgetItem(ch.name) - name_item.setData(Qt.ItemDataRole.UserRole, (dev.info.device_id, ch.channel_id)) + name_item.setData(Qt.ItemDataRole.UserRole, (dev.info.device_id, ch.signal_id)) self._table.setItem(row, self._C_NAME, name_item) unit_item = QTableWidgetItem(ch.unit) @@ -218,7 +218,7 @@ class ChannelsTab(QWidget): def _on_enabled(self, dev_id: str, ch_id: str, checked: bool): dev = self.registry.get_instance(dev_id) if dev: - ch = dev.get_channel(ch_id) + ch = dev.get_signal(ch_id) if ch: ch.enabled = checked self.channel_visibility_changed.emit(dev_id, ch_id, checked) @@ -234,7 +234,7 @@ class ChannelsTab(QWidget): dev = self.registry.get_instance(dev_id) if not dev: return - ch = dev.get_channel(ch_id) + ch = dev.get_signal(ch_id) if not ch: return if col == self._C_NAME: @@ -318,7 +318,7 @@ class DevicesWindow(QWidget): tabs.addTab(dev_tab, " Physical Devices ") # Tab 2: Channels - self._ch_tab = ChannelsTab(self.registry) + self._ch_tab = SignalsTab(self.registry) self._ch_tab.channel_visibility_changed.connect(self.channel_visibility_changed) self._ch_tab.channel_name_changed.connect(self.channel_name_changed) self._ch_tab.channel_unit_changed.connect(self.channel_unit_changed) diff --git a/ui/windows/plot_window.py b/ui/windows/plot_window.py index e810365..c0aea4e 100644 --- a/ui/windows/plot_window.py +++ b/ui/windows/plot_window.py @@ -341,18 +341,18 @@ class TraceChannelPickerDialog(QDialog): any_available = False for dev in registry.all_instances(): - for ch in dev.info.channels: + for ch in dev.info.signals: if not ch.enabled: continue any_available = True - chk = QCheckBox(f"{ch.name} ({dev.info.device_id}/{ch.channel_id})") - self._checks.append((chk, dev.info.device_id, ch.channel_id, ch.name, ch.color)) + chk = QCheckBox(f"Signal: {ch.name} ({dev.info.device_id}/{ch.signal_id})") + self._checks.append((chk, dev.info.device_id, ch.signal_id, ch.name, ch.color)) cl.addWidget(chk) for dc in processor.get_derived(): if not dc.enabled: continue any_available = True - chk = QCheckBox(f"{dc.name} ([virtual]/{dc.channel_id})") + chk = QCheckBox(f"Channel: {dc.name} ([virtual]/{dc.channel_id})") self._checks.append((chk, "derived", dc.channel_id, dc.name, dc.color)) cl.addWidget(chk) @@ -498,15 +498,15 @@ class PaneBlock(QFrame): self._x_cb.setMinimumWidth(150) self._x_cb.addItem("⏱ Time (elapsed s)", userData="time") for dev in self.registry.all_instances(): - for ch in dev.info.channels: + for ch in dev.info.signals: if not ch.enabled: continue - self._x_cb.addItem(f"{ch.name} ({dev.info.device_id}/{ch.channel_id})", - userData=f"{dev.info.device_id}/{ch.channel_id}") + self._x_cb.addItem(f"Signal: {ch.name} ({dev.info.device_id}/{ch.signal_id})", + userData=f"{dev.info.device_id}/{ch.signal_id}") for dc in self.processor.get_derived(): if not dc.enabled: continue - self._x_cb.addItem(f"{dc.name} ([virtual]/{dc.channel_id})", + self._x_cb.addItem(f"Channel: {dc.name} ([virtual]/{dc.channel_id})", userData=f"derived/{dc.channel_id}") for i in range(self._x_cb.count()): if self._x_cb.itemData(i) == self.spec.x_source: -- cgit v1.2.3