summaryrefslogtreecommitdiff
path: root/devices/serial_device.py
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-04-20 16:55:57 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-04-20 16:55:57 -0600
commitd5acb04b88373d33b038bb59945fb5ab8b4f543b (patch)
tree21c37f2b54258ef20edc1b9b7226327d5f5b1a3a /devices/serial_device.py
parent425ba78ee1f760978b23a09fe8acbbc9b8b5dae4 (diff)
V8
Diffstat (limited to 'devices/serial_device.py')
-rw-r--r--devices/serial_device.py92
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),
)