1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
"""
ui/device_panel.py
Left sidebar showing all registered devices with status indicators.
"""
from PyQt6.QtWidgets import (
QWidget, QVBoxLayout, QLabel, QPushButton,
QHBoxLayout, QScrollArea, QFrame
)
from PyQt6.QtCore import Qt, pyqtSignal
from devices.base_device import DeviceStatus
from devices.device_registry import DeviceRegistry
from core.acquisition import AcquisitionEngine
class DeviceCard(QFrame):
config_clicked = pyqtSignal(str)
toggle_clicked = pyqtSignal(str, bool)
STATUS_COLORS = {
DeviceStatus.CONNECTED: "#3fb950",
DeviceStatus.SIMULATED: "#58a6ff",
DeviceStatus.DISCONNECTED: "#8b949e",
DeviceStatus.CONNECTING: "#d29922",
DeviceStatus.ERROR: "#f85149",
}
def __init__(self, device, parent=None):
super().__init__(parent)
self.device = device
self.setObjectName("deviceCard")
self._build()
def _build(self):
layout = QVBoxLayout(self)
layout.setContentsMargins(8, 8, 8, 8)
layout.setSpacing(4)
# Header row
hdr = QHBoxLayout()
icon = QLabel(self.device.info.icon)
icon.setObjectName("deviceIcon")
hdr.addWidget(icon)
name = QLabel(self.device.info.name)
name.setObjectName("deviceName")
hdr.addWidget(name)
hdr.addStretch()
color = self.STATUS_COLORS.get(self.device.status, "#8b949e")
self.status_dot = QLabel("●")
self.status_dot.setStyleSheet(f"color: {color}; font-size: 10px;")
hdr.addWidget(self.status_dot)
layout.addLayout(hdr)
# ID + type
sub = QLabel(f"{self.device.info.device_id} · {self.device.info.device_type}")
sub.setObjectName("deviceSub")
layout.addWidget(sub)
# Channel count
ch_count = sum(1 for ch in self.device.info.channels if ch.enabled)
ch_lbl = QLabel(f"{ch_count} channel{'s' if ch_count != 1 else ''}")
ch_lbl.setObjectName("deviceChannelCount")
layout.addWidget(ch_lbl)
# Config button
cfg_btn = QPushButton("Configure")
cfg_btn.setObjectName("configButton")
cfg_btn.clicked.connect(lambda: self.config_clicked.emit(self.device.info.device_id))
layout.addWidget(cfg_btn)
def refresh_status(self):
color = self.STATUS_COLORS.get(self.device.status, "#8b949e")
self.status_dot.setStyleSheet(f"color: {color}; font-size: 10px;")
class DevicePanel(QWidget):
config_requested = pyqtSignal(str)
def __init__(self, registry: DeviceRegistry, engine: AcquisitionEngine):
super().__init__()
self.registry = registry
self.engine = engine
self._cards = {}
self._build_ui()
self.refresh()
def _build_ui(self):
layout = QVBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
layout.setSpacing(0)
header = QLabel(" DEVICES")
header.setObjectName("panelHeader")
layout.addWidget(header)
scroll = QScrollArea()
scroll.setWidgetResizable(True)
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff)
scroll.setObjectName("deviceScroll")
self._container = QWidget()
self._inner = QVBoxLayout(self._container)
self._inner.setContentsMargins(8, 8, 8, 8)
self._inner.setSpacing(8)
self._inner.addStretch()
scroll.setWidget(self._container)
layout.addWidget(scroll)
def refresh(self):
# Remove old cards
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_clicked.connect(self.config_requested.emit)
# Insert before the stretch
self._inner.insertWidget(self._inner.count() - 1, card)
self._cards[dev.info.device_id] = card
|