summaryrefslogtreecommitdiff
path: root/ui/devices_window.py
diff options
context:
space:
mode:
Diffstat (limited to 'ui/devices_window.py')
-rw-r--r--ui/devices_window.py224
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()