diff options
Diffstat (limited to 'ui/devices_window.py')
| -rw-r--r-- | ui/devices_window.py | 224 |
1 files changed, 0 insertions, 224 deletions
diff --git a/ui/devices_window.py b/ui/devices_window.py deleted file mode 100644 index 0548330..0000000 --- a/ui/devices_window.py +++ /dev/null @@ -1,224 +0,0 @@ -""" -ui/devices_window.py - -Floating "Devices" settings window. -Opens from the toolbar ⚙ DEVICES button; can stay open alongside the main window. -Contains: device status cards, Add Device, and per-device Configure. -""" - -from PyQt6.QtWidgets import ( - QWidget, QVBoxLayout, QHBoxLayout, QLabel, - QPushButton, QScrollArea, QFrame, QSizePolicy, - QDialog, -) -from PyQt6.QtCore import Qt, pyqtSignal, QTimer -from PyQt6.QtGui import QCloseEvent - -from devices.base_device import DeviceStatus -from devices.device_registry import DeviceRegistry -from core.acquisition import AcquisitionEngine - - -_STATUS_STYLE = { - DeviceStatus.CONNECTED: "color:#22c55e;", - DeviceStatus.SIMULATED: "color:#3b82f6;", - DeviceStatus.DISCONNECTED: "color:#475569;", - DeviceStatus.CONNECTING: "color:#f59e0b;", - DeviceStatus.ERROR: "color:#ef4444;", -} -_STATUS_LABEL = { - DeviceStatus.CONNECTED: "CONNECTED", - DeviceStatus.SIMULATED: "SIMULATED", - DeviceStatus.DISCONNECTED: "OFFLINE", - DeviceStatus.CONNECTING: "CONNECTING", - DeviceStatus.ERROR: "ERROR", -} - - -class DeviceCard(QFrame): - config_requested = pyqtSignal(str) - - def __init__(self, device): - super().__init__() - self.device = device - self.setObjectName("deviceCard") - self._build() - - def _build(self): - layout = QVBoxLayout(self) - layout.setContentsMargins(10, 10, 10, 10) - layout.setSpacing(5) - - # Header: icon + name + status dot - hdr = QHBoxLayout() - icon_lbl = QLabel(self.device.info.icon) - icon_lbl.setObjectName("deviceIcon") - hdr.addWidget(icon_lbl) - - name_lbl = QLabel(self.device.info.name) - name_lbl.setObjectName("deviceName") - hdr.addWidget(name_lbl, 1) - - self._dot = QLabel("●") - self._dot.setStyleSheet( - _STATUS_STYLE.get(self.device.status, "color:#475569;") + " font-size:10px;" - ) - hdr.addWidget(self._dot) - layout.addLayout(hdr) - - # ID - id_lbl = QLabel(self.device.info.device_id) - id_lbl.setObjectName("deviceSub") - layout.addWidget(id_lbl) - - # Status text - self._status_lbl = QLabel(_STATUS_LABEL.get(self.device.status, "UNKNOWN")) - self._apply_status_style() - layout.addWidget(self._status_lbl) - - # Channel count · type - n = sum(1 for c in self.device.info.channels if c.enabled) - ch_lbl = QLabel(f"{n} ch · {self.device.info.device_type}") - ch_lbl.setObjectName("deviceChannelCount") - layout.addWidget(ch_lbl) - - # Configure button - cfg = QPushButton("Configure") - cfg.setObjectName("configButton") - cfg.clicked.connect(lambda: self.config_requested.emit(self.device.info.device_id)) - layout.addWidget(cfg) - - def refresh(self): - dot_style = _STATUS_STYLE.get(self.device.status, "color:#475569;") + " font-size:10px;" - self._dot.setStyleSheet(dot_style) - self._status_lbl.setText(_STATUS_LABEL.get(self.device.status, "UNKNOWN")) - self._apply_status_style() - - def _apply_status_style(self): - s = _STATUS_STYLE.get(self.device.status, "color:#475569;") - self._status_lbl.setStyleSheet( - s + " font-family:'IBM Plex Mono',monospace;" - " font-size:10px; font-weight:700; letter-spacing:1px;" - ) - - -class DevicesWindow(QWidget): - """ - Standalone floating window for device management. - - Signals - ------- - config_requested(device_id) — user clicked Configure on a card - device_added() — a new device was added via the dialog - closed() — window was closed (so toolbar btn can untoggle) - """ - - config_requested = pyqtSignal(str) - device_added = pyqtSignal() - closed = pyqtSignal() - - def __init__(self, registry: DeviceRegistry, engine: AcquisitionEngine, parent=None): - super().__init__( - parent, - # Acts like a real standalone window but stays on top of parent - Qt.WindowType.Window | - Qt.WindowType.Tool, - ) - self.registry = registry - self.engine = engine - self._cards: dict = {} - - self.setWindowTitle("Devices") - self.setMinimumSize(300, 480) - self.resize(320, 600) - self._build() - self.refresh() - - self._timer = QTimer(self) - self._timer.setInterval(2000) - self._timer.timeout.connect(self._refresh_status) - self._timer.start() - - # ── Build ───────────────────────────────────────────────────────────── - - def _build(self): - root = QVBoxLayout(self) - root.setContentsMargins(0, 0, 0, 0) - root.setSpacing(0) - - # ── Title bar row ────────────────────────────────────────────── - title_bar = QWidget() - title_bar.setObjectName("devWindowTitleBar") - title_bar.setFixedHeight(40) - tb_lay = QHBoxLayout(title_bar) - tb_lay.setContentsMargins(12, 0, 8, 0) - - title_lbl = QLabel("⚙ DEVICES") - title_lbl.setObjectName("devWindowTitle") - tb_lay.addWidget(title_lbl, 1) - - self._add_btn = QPushButton("+ Add") - self._add_btn.setObjectName("addDeviceButton") - self._add_btn.clicked.connect(self._on_add) - tb_lay.addWidget(self._add_btn) - - root.addWidget(title_bar) - - # ── Divider ──────────────────────────────────────────────────── - div = QFrame() - div.setFrameShape(QFrame.Shape.HLine) - div.setObjectName("devWindowDivider") - root.addWidget(div) - - # ── Scrollable device cards ──────────────────────────────────── - scroll = QScrollArea() - scroll.setObjectName("deviceScroll") - scroll.setWidgetResizable(True) - scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) - - self._container = QWidget() - self._inner = QVBoxLayout(self._container) - self._inner.setContentsMargins(10, 10, 10, 10) - self._inner.setSpacing(10) - self._inner.addStretch() - - scroll.setWidget(self._container) - root.addWidget(scroll) - - # ── Public API ──────────────────────────────────────────────────────── - - def refresh(self): - """Rebuild all device cards from current registry state.""" - for card in self._cards.values(): - self._inner.removeWidget(card) - card.deleteLater() - self._cards.clear() - - for dev in self.registry.all_instances(): - card = DeviceCard(dev) - card.config_requested.connect(self.config_requested.emit) - self._inner.insertWidget(self._inner.count() - 1, card) - self._cards[dev.info.device_id] = card - - # ── Slots ──────────────────────────────────────────────────────────── - - def _on_add(self): - from ui.add_device_dialog import AddDeviceDialog - from ui.config_dialog import DeviceConfigDialog - dlg = AddDeviceDialog(self.registry, self) - if dlg.exec(): - dev = dlg.created_device - if dev: - dev.connect() - self.registry.add_instance(dev) - self.engine.add_device(dev) - self.refresh() - self.device_added.emit() - - def _refresh_status(self): - for card in self._cards.values(): - card.refresh() - - def closeEvent(self, event: QCloseEvent): - self.closed.emit() - event.accept() |
