summaryrefslogtreecommitdiff
path: root/daq_system/daq_system/ui/add_device_dialog.py
diff options
context:
space:
mode:
Diffstat (limited to 'daq_system/daq_system/ui/add_device_dialog.py')
-rw-r--r--daq_system/daq_system/ui/add_device_dialog.py100
1 files changed, 100 insertions, 0 deletions
diff --git a/daq_system/daq_system/ui/add_device_dialog.py b/daq_system/daq_system/ui/add_device_dialog.py
new file mode 100644
index 0000000..30d0016
--- /dev/null
+++ b/daq_system/daq_system/ui/add_device_dialog.py
@@ -0,0 +1,100 @@
+"""
+ui/add_device_dialog.py — Dialog to add a new device at runtime.
+"""
+
+from PyQt6.QtWidgets import (
+ QDialog, QVBoxLayout, QFormLayout, QHBoxLayout,
+ QComboBox, QLineEdit, QSpinBox, QCheckBox,
+ QPushButton, QLabel, QMessageBox,
+)
+
+from devices.device_registry import DeviceRegistry
+from devices.analog_input import AnalogInputDevice
+from devices.digital_io import DigitalIODevice
+from devices.serial_device import SerialDevice
+
+
+# Map display name -> (class, extra_kwargs_defaults)
+_DEVICE_TYPES = {
+ "Analog Input — NI-DAQmx": (AnalogInputDevice, {"backend": "nidaqmx"}),
+ "Analog Input — Arduino": (AnalogInputDevice, {"backend": "arduino"}),
+ "Digital I/O — NI-DAQmx": (DigitalIODevice, {"backend": "nidaqmx"}),
+ "Digital I/O — Arduino": (DigitalIODevice, {"backend": "arduino"}),
+ "Serial / UART": (SerialDevice, {}),
+}
+
+
+class AddDeviceDialog(QDialog):
+ def __init__(self, registry: DeviceRegistry, parent=None):
+ super().__init__(parent)
+ self.registry = registry
+ self.created_device = None
+ self.setWindowTitle("Add Device")
+ self.setMinimumWidth(360)
+ self._build()
+
+ def _build(self):
+ layout = QVBoxLayout(self)
+ form = QFormLayout()
+
+ self._type_cb = QComboBox()
+ self._type_cb.addItems(list(_DEVICE_TYPES.keys()))
+ form.addRow("Device Type:", self._type_cb)
+
+ self._id_edit = QLineEdit()
+ self._id_edit.setPlaceholderText("e.g. ai_1 / ser_0")
+ form.addRow("Device ID:", self._id_edit)
+
+ self._ch_spin = QSpinBox()
+ self._ch_spin.setRange(1, 16)
+ self._ch_spin.setValue(4)
+ form.addRow("# Channels:", self._ch_spin)
+
+ self._sim_chk = QCheckBox("Simulation mode (no hardware required)")
+ self._sim_chk.setChecked(True)
+ form.addRow(self._sim_chk)
+
+ layout.addLayout(form)
+
+ btns = QHBoxLayout()
+ btns.addStretch()
+ cancel = QPushButton("Cancel")
+ cancel.clicked.connect(self.reject)
+ add = QPushButton("Add Device")
+ add.setDefault(True)
+ add.setObjectName("applyButton")
+ add.clicked.connect(self._on_add)
+ btns.addWidget(cancel)
+ btns.addWidget(add)
+ layout.addLayout(btns)
+
+ def _on_add(self):
+ label = self._type_cb.currentText()
+ cls, kw = _DEVICE_TYPES[label]
+ dev_id = self._id_edit.text().strip()
+
+ if not dev_id:
+ base = kw.get("backend", "dev")
+ existing = {d.info.device_id for d in self.registry.all_instances()}
+ for i in range(100):
+ candidate = f"{base}_{i}"
+ if candidate not in existing:
+ dev_id = candidate
+ break
+
+ if self.registry.get_instance(dev_id):
+ QMessageBox.warning(self, "Duplicate ID",
+ f"A device with ID '{dev_id}' already exists.")
+ return
+
+ try:
+ dev = cls(
+ device_id=dev_id,
+ num_channels=self._ch_spin.value(),
+ simulate=self._sim_chk.isChecked(),
+ **kw,
+ )
+ self.created_device = dev
+ self.accept()
+ except Exception as e:
+ QMessageBox.critical(self, "Error creating device", str(e))