summaryrefslogtreecommitdiff
path: root/ui/add_device_dialog.py
blob: 30d0016e4752c8ade3b6f3827ccdfb0fbeb54e20 (plain)
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
"""
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))