from PyQt6.QtCore import pyqtSignal from PyQt6.QtWidgets import QWidget, QRadioButton, QVBoxLayout, QHBoxLayout, QPushButton, QSpinBox, QFileDialog, QLabel from PyQt6.QtWidgets import QFormLayout, QDoubleSpinBox, QCheckBox, QLineEdit, QGroupBox from os import path from cpdctrl_gui.utility.config import AppConfig from .base import SettingsForm class DeviceSelection(QGroupBox): def __init__(self, parent=None): super().__init__(parent=parent, title="Devices") self.layout = QFormLayout() self.setLayout(self.layout) self.devices_widgets = {} self._add_device("voltage_measurement", "Voltage Measurement", "N.C.") self._add_device("led_controller", "Led Controller", "N.C.") self._add_device("led", "Led Lamp", "Unknown") # self.layout.addStretch(1) def _add_device(self, key, label, name): self.devices_widgets[key] = QLabel(name) self.layout.addRow(QLabel(label), self.devices_widgets[key]) def set_value(self, key, value): key = key.replace("device_", "") if key in self.devices_widgets: self.devices_widgets[key].setText(value) else: raise KeyError(f"Unknown device '{key}'") class ScriptSelection(QGroupBox): loadScript = pyqtSignal() def __init__(self, parent=None): super().__init__(parent=parent, title="LED Script") self.layout = QVBoxLayout() # Radio buttons self.radio_script_file = QRadioButton("Script file") self.radio_constant_value = QRadioButton("Constant value") self.radio_script_file.toggled.connect(self.on_radio_button_toggled) self.radio_constant_value.toggled.connect(self.on_radio_button_toggled) # Load from file button self.btn_load_script = QPushButton("Load from file") self.btn_load_script.clicked.connect(self.load_file) self.w_script_file = QLineEdit() self.w_script_file.setEnabled(False) # QSpinBox for constant value self.w_constant_value = QSpinBox() self.w_constant_value.setRange(0, 100) # signal when changed self.w_constant_value.valueChanged.connect(lambda: self.loadScript.emit()) # Layouts l_constant_value = QVBoxLayout() l_constant_value.addWidget(self.radio_constant_value) l_constant_value.addWidget(self.w_constant_value) l_file = QVBoxLayout() l_file.addWidget(self.radio_script_file) l_file.addWidget(self.btn_load_script) l_file.addWidget(self.w_script_file) # Add layouts to main layout self.layout.addLayout(l_constant_value) self.layout.addLayout(l_file) self.setLayout(self.layout) # Initial state self.radio_constant_value.setChecked(True) self.on_radio_button_toggled() self.layout.addStretch(1) self.file_path = None def on_radio_button_toggled(self): if self.radio_script_file.isChecked(): self.btn_load_script.setEnabled(True) self.w_constant_value.setEnabled(False) else: self.btn_load_script.setEnabled(False) self.w_constant_value.setEnabled(True) def load_file(self): # options = QFileDialog.Options() last_dir = AppConfig.MAIN_CFG.get_or("tmp_last_script_dir", "") file_path, _ = QFileDialog.getOpenFileName(self, "Open Script File", last_dir, "All Files (*);;Text files (*.led)") if file_path: dir_name = path.dirname(file_path) AppConfig.MAIN_CFG.set("tmp_last_script_dir", dir_name) self.file_path = file_path self.w_script_file.setText(self.file_path) # signal the change self.loadScript.emit() def get_script(self): if self.radio_script_file.isChecked(): return self.file_path else: return int(self.w_constant_value.value()) def get_script_type(self): if self.radio_script_file.isChecked(): return "file" else: return "constant" class MeasurementSettings(QWidget): """ Widget allowing the user to set the measurement settings. It loads the values from AppConfig.MEAS_CFG and automatically updates the values in AppConfig.MEAS_CFG when the user changes them. """ def __init__(self, parent=None): super().__init__(parent) self.l_vbox = QVBoxLayout() # self.label = QLabel("Measurement Settings") # self.layout.addWidget(self.label) self.setLayout(self.l_vbox) # devices self.w_device_selection = DeviceSelection() self.l_vbox.addWidget(self.w_device_selection) # - script self.w_led_script_load = ScriptSelection() self.l_vbox.addWidget(self.w_led_script_load) # key-value stuff in a form self.w_form = SettingsForm(AppConfig.MEAS_CFG) self.l_vbox.addWidget(self.w_form) self.w_form.add_form_row("name", "Name", "", QLineEdit(self), "Name of the measurement") w_box_interval = QDoubleSpinBox(self) w_box_interval.setDecimals(2) w_box_interval.setMinimum(0.01) w_box_interval.setSingleStep(0.1) self.w_form.add_form_row("interval", "Interval [s]", 1.0, w_box_interval, "Amount of seconds to wait between voltage measurements and LED device updates") w_box_max_measurements = QSpinBox(self) w_box_max_measurements.setMaximum(2147483647) # max int32 w_box_max_measurements.setMinimum(0) # 0 for infinite measurements self.w_form.add_form_row("max_measurements", "Max Measurements", 0, w_box_max_measurements, "Number of measurements to take. Set to 0 for infinite measurements") self.w_form.add_form_row("stop_on_script_end", "Stop on Script End", False, QCheckBox(self), "Stop measurement when LED script ends") self.w_form.add_form_row("use_buffer", "Use Buffer", False, QCheckBox(self), "If available, use the voltage device buffer for more accurate measurement timings.\nLeads to a lower accuracy of LED update timings, up to 1*interval") w_box_flush_after = QSpinBox(self) w_box_flush_after.setMaximum(2147483647) # max int32 w_box_flush_after.setSingleStep(500) self.w_form.add_form_row("flush_after", "Flush-Data Interval", 0, w_box_flush_after, "Number of measurements to take before writing the data to an intermediate file") self.w_form.add_form_row("auto_add_metadata", "Auto-add Metadata", True, QCheckBox(self), "Automatically add measurement metadata to the data file.\nThis includes: device names, measurement mode, measurement interval, start and stop times, led script") self.l_vbox.addStretch(1) def set_value(self, key, value): if key in self.w_form: self.w_form.set_value(key, value) elif key.startswith("device_"): self.w_device_selection.set_value(key, value) else: raise ValueError(f"Unknown key: {key}") def get_value(self, key): if key in self.w_form: return self.w_form.get_value(key) elif key == "led_script": return self.w_led_script_load.get_script() elif key == "led_script_type": return self.w_led_script_load.get_script_type() else: raise ValueError(f"Unknown key: {key}")