diff options
| author | Christian Kolset <christian.kolset@gmail.com> | 2026-04-13 14:36:55 -0600 |
|---|---|---|
| committer | Christian Kolset <christian.kolset@gmail.com> | 2026-04-13 14:36:55 -0600 |
| commit | 8d6acf3a8ea4b37f86b321dbf430be5be01b1267 (patch) | |
| tree | 923251b7ee88c7b5c89500883154bad32a2ecca5 /daq_system/ui/config_dialog.py | |
init
Diffstat (limited to 'daq_system/ui/config_dialog.py')
| -rw-r--r-- | daq_system/ui/config_dialog.py | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/daq_system/ui/config_dialog.py b/daq_system/ui/config_dialog.py new file mode 100644 index 0000000..a7b0cdf --- /dev/null +++ b/daq_system/ui/config_dialog.py @@ -0,0 +1,174 @@ +""" +ui/config_dialog.py — Per-device configuration dialog. +""" + +from PyQt6.QtWidgets import ( + QDialog, QVBoxLayout, QHBoxLayout, QLabel, + QPushButton, QTabWidget, QWidget, QFormLayout, + QLineEdit, QDoubleSpinBox, QCheckBox, QScrollArea +) +from PyQt6.QtCore import Qt + + +class DeviceConfigDialog(QDialog): + def __init__(self, device, parent=None): + super().__init__(parent) + self.device = device + self.setWindowTitle(f"Configure: {device.info.name} [{device.info.device_id}]") + self.setMinimumSize(500, 400) + self._build() + + def _build(self): + layout = QVBoxLayout(self) + + tabs = QTabWidget() + + # Tab 1: Device-specific config widget + dev_tab = QScrollArea() + dev_tab.setWidgetResizable(True) + dev_tab.setWidget(self.device.get_config_widget()) + tabs.addTab(dev_tab, "Device Settings") + + # Tab 2: Channel config + ch_tab = self._build_channel_tab() + tabs.addTab(ch_tab, "Channels") + + layout.addWidget(tabs) + + # Buttons + btn_row = QHBoxLayout() + btn_row.addStretch() + ok = QPushButton("Close") + ok.setDefault(True) + ok.clicked.connect(self.accept) + btn_row.addWidget(ok) + layout.addLayout(btn_row) + + def _build_channel_tab(self): + w = QWidget() + layout = QVBoxLayout(w) + for ch in self.device.info.channels: + grp_layout = QFormLayout() + name_edit = QLineEdit(ch.name) + unit_edit = QLineEdit(ch.unit) + en_check = QCheckBox() + en_check.setChecked(ch.enabled) + + lo_spin = QDoubleSpinBox() + lo_spin.setRange(-1e9, 1e9) + lo_spin.setValue(ch.alarm_low or 0.0) + + hi_spin = QDoubleSpinBox() + hi_spin.setRange(-1e9, 1e9) + hi_spin.setValue(ch.alarm_high or 100.0) + + grp_layout.addRow(f"[{ch.channel_id}] Name:", name_edit) + grp_layout.addRow("Unit:", unit_edit) + grp_layout.addRow("Enabled:", en_check) + grp_layout.addRow("Alarm Low:", lo_spin) + grp_layout.addRow("Alarm High:", hi_spin) + + def make_apply(c, ne, ue, ec, ls, hs): + def apply(): + c.name = ne.text() + c.unit = ue.text() + c.enabled = ec.isChecked() + c.alarm_low = ls.value() + c.alarm_high = hs.value() + return apply + + apply_btn = QPushButton("Apply") + apply_btn.clicked.connect(make_apply(ch, name_edit, unit_edit, en_check, lo_spin, hi_spin)) + grp_layout.addRow(apply_btn) + layout.addLayout(grp_layout) + + layout.addStretch() + return w + + +# ------------------------------------------------------------------ # +# Add Device Dialog # +# ------------------------------------------------------------------ # + +""" +ui/add_device_dialog.py — Dialog for adding a new device to the system. +""" + +from PyQt6.QtWidgets import ( + QDialog, QVBoxLayout, QFormLayout, QComboBox, + QLineEdit, QCheckBox, QSpinBox, QPushButton, QHBoxLayout, QLabel +) + +from devices.device_registry import DeviceRegistry +from devices.analog_input import AnalogInputDevice +from devices.digital_io import DigitalIODevice +from devices.temperature import TemperatureDevice +from devices.serial_device import SerialDevice + + +DEVICE_CONSTRUCTORS = { + "Analog Input": AnalogInputDevice, + "Digital I/O": DigitalIODevice, + "Temperature": TemperatureDevice, + "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(340) + self._build() + + def _build(self): + layout = QVBoxLayout(self) + form = QFormLayout() + + self.type_cb = QComboBox() + self.type_cb.addItems(list(DEVICE_CONSTRUCTORS.keys())) + form.addRow("Device Type:", self.type_cb) + + self.id_edit = QLineEdit() + self.id_edit.setPlaceholderText("e.g. ai_1") + 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_check = QCheckBox("Simulation Mode") + self.sim_check.setChecked(True) + form.addRow(self.sim_check) + + layout.addLayout(form) + + btns = QHBoxLayout() + btns.addStretch() + cancel = QPushButton("Cancel") + cancel.clicked.connect(self.reject) + add = QPushButton("Add") + add.setDefault(True) + add.clicked.connect(self._on_add) + btns.addWidget(cancel) + btns.addWidget(add) + layout.addLayout(btns) + + def _on_add(self): + dev_type = self.type_cb.currentText() + dev_id = self.id_edit.text().strip() or f"dev_{len(self.registry)}" + cls = DEVICE_CONSTRUCTORS[dev_type] + try: + dev = cls( + device_id=dev_id, + num_channels=self.ch_spin.value(), + simulate=self.sim_check.isChecked() + ) + self.created_device = dev + self.accept() + except Exception as e: + from PyQt6.QtWidgets import QMessageBox + QMessageBox.critical(self, "Error", str(e)) |
