diff options
| author | Christian Kolset <christian.kolset@gmail.com> | 2026-04-20 16:55:57 -0600 |
|---|---|---|
| committer | Christian Kolset <christian.kolset@gmail.com> | 2026-04-20 16:55:57 -0600 |
| commit | d5acb04b88373d33b038bb59945fb5ab8b4f543b (patch) | |
| tree | 21c37f2b54258ef20edc1b9b7226327d5f5b1a3a /devices/serial_device.py | |
| parent | 425ba78ee1f760978b23a09fe8acbbc9b8b5dae4 (diff) | |
V8
Diffstat (limited to 'devices/serial_device.py')
| -rw-r--r-- | devices/serial_device.py | 92 |
1 files changed, 76 insertions, 16 deletions
diff --git a/devices/serial_device.py b/devices/serial_device.py index 6bb7bf1..a5bf08c 100644 --- a/devices/serial_device.py +++ b/devices/serial_device.py @@ -132,17 +132,25 @@ class SerialDevice(BaseDevice): class SerialConfigWidget(QWidget): def __init__(self, device: SerialDevice): super().__init__() - self.device = device + self.device = device + self._scanner = None self._build() def _build(self): + from PyQt6.QtWidgets import QListWidget, QListWidgetItem + from PyQt6.QtCore import Qt as _Qt + root = QVBoxLayout(self) - root.setContentsMargins(0, 0, 0, 0) + root.setContentsMargins(8, 8, 8, 8) + root.setSpacing(8) + self.setMinimumWidth(420) + # ── Port settings ───────────────────────────────────────────── grp = QGroupBox("Port Settings") form = QFormLayout(grp) self.port_edit = QLineEdit(self.device._port) + self.port_edit.setPlaceholderText("e.g. COM3 or /dev/ttyUSB0") form.addRow("Port:", self.port_edit) self.baud_cb = QComboBox() @@ -155,19 +163,43 @@ class SerialConfigWidget(QWidget): self.fmt_cb.setCurrentText(self.device._parse_format) form.addRow("Parse Format:", self.fmt_cb) - self.sim_chk = QComboBox() - self.sim_chk.addItems(["Simulate", "Real Hardware"]) - self.sim_chk.setCurrentIndex(0 if self.device.simulate else 1) - form.addRow("Mode:", self.sim_chk) - - scan_btn = QPushButton("Scan Ports") - scan_btn.clicked.connect(self._scan) - form.addRow(scan_btn) - self.port_lbl = QLabel("") - form.addRow(self.port_lbl) + self.sim_cb = QComboBox() + self.sim_cb.addItems(["Simulate", "Real Hardware"]) + self.sim_cb.setCurrentIndex(0 if self.device.simulate else 1) + form.addRow("Mode:", self.sim_cb) root.addWidget(grp) + # ── Port scanner ────────────────────────────────────────────── + scan_grp = QGroupBox("Available Serial Ports") + scan_lay = QVBoxLayout(scan_grp) + scan_lay.setSpacing(4) + + scan_top = QHBoxLayout() + self._scan_btn = QPushButton("🔍 Scan Ports") + self._scan_btn.setObjectName("addTraceBtn") + self._scan_btn.clicked.connect(self._scan) + self._scan_lbl = QLabel("Click Scan to detect ports") + self._scan_lbl.setObjectName("traceSource") + scan_top.addWidget(self._scan_btn) + scan_top.addWidget(self._scan_lbl, 1) + scan_lay.addLayout(scan_top) + + self._port_list = QListWidget() + self._port_list.setObjectName("portList") + self._port_list.setMaximumHeight(110) + self._port_list.itemClicked.connect( + lambda item: self.port_edit.setText( + item.data(_Qt.ItemDataRole.UserRole) or "" + ) if item.data(_Qt.ItemDataRole.UserRole) else None + ) + hint = QLabel("↑ Click a port above to select it") + hint.setObjectName("traceSource") + scan_lay.addWidget(self._port_list) + scan_lay.addWidget(hint) + root.addWidget(scan_grp) + + # ── Apply ───────────────────────────────────────────────────── apply_btn = QPushButton("Apply & Reconnect") apply_btn.setObjectName("applyButton") apply_btn.clicked.connect(self._apply) @@ -175,13 +207,41 @@ class SerialConfigWidget(QWidget): root.addStretch() def _scan(self): - ports = ArduinoLayer.list_ports() - self.port_lbl.setText(", ".join(ports) if ports else "None found") + self._scan_btn.setEnabled(False) + self._scan_lbl.setText("Scanning…") + self._port_list.clear() + from PyQt6.QtCore import QThread, pyqtSignal as _sig + class _Scanner(QThread): + done = _sig(list) + def run(self): + self.done.emit(ArduinoLayer.list_ports()) + self._scanner = _Scanner() + self._scanner.done.connect(self._on_scan_done) + self._scanner.start() + + def _on_scan_done(self, ports): + from PyQt6.QtWidgets import QListWidgetItem + self._scan_btn.setEnabled(True) + self._port_list.clear() + if not ports: + self._scan_lbl.setText("No ports found") + item = QListWidgetItem(" No serial ports detected — check USB / permissions") + item.setFlags(item.flags() & ~Qt.ItemFlag.ItemIsSelectable) + self._port_list.addItem(item) + else: + self._scan_lbl.setText(f"{len(ports)} port(s) — click to select") + for device, desc in ports: + label = f" {device}" + if desc and desc.strip() and desc.strip() != device: + label += f" — {desc}" + item = QListWidgetItem(label) + item.setData(Qt.ItemDataRole.UserRole, device) + self._port_list.addItem(item) def _apply(self): self.device.reconfigure( - port=self.port_edit.text(), + port=self.port_edit.text().strip() or "COM3", baud=int(self.baud_cb.currentText()), fmt=self.fmt_cb.currentText(), - simulate=(self.sim_chk.currentIndex() == 0), + simulate=(self.sim_cb.currentIndex() == 0), ) |
