diff options
Diffstat (limited to 'daq_system/ui/main_window.py')
| -rw-r--r-- | daq_system/ui/main_window.py | 228 |
1 files changed, 0 insertions, 228 deletions
diff --git a/daq_system/ui/main_window.py b/daq_system/ui/main_window.py deleted file mode 100644 index 8b602d1..0000000 --- a/daq_system/ui/main_window.py +++ /dev/null @@ -1,228 +0,0 @@ -""" -ui/main_window.py - -Main application window. Hosts the left sidebar (device list), -center strip chart, right panel (numeric readouts + alarms). -""" - -from PyQt6.QtWidgets import ( - QMainWindow, QWidget, QHBoxLayout, QVBoxLayout, - QSplitter, QStatusBar, QLabel, QPushButton, - QToolBar, QMessageBox, QFileDialog -) -from PyQt6.QtCore import Qt, QTimer, pyqtSlot -from PyQt6.QtGui import QAction, QIcon, QFont - -from devices.analog_input import AnalogInputDevice -from devices.digital_io import DigitalIODevice -from devices.temperature import TemperatureDevice -from devices.serial_device import SerialDevice -from devices.device_registry import DeviceRegistry -from core.acquisition import AcquisitionEngine - -from ui.device_panel import DevicePanel -from ui.strip_chart import StripChartWidget -from ui.readout_panel import ReadoutPanel -from ui.alarm_panel import AlarmPanel -from ui.config_dialog import DeviceConfigDialog - - -class MainWindow(QMainWindow): - def __init__(self): - super().__init__() - self.setWindowTitle("LabDAQ — Data Acquisition System") - self.setMinimumSize(1280, 780) - - self.registry = DeviceRegistry() - self.engine = AcquisitionEngine(poll_interval_ms=100) - self._running = False - - self._init_default_devices() - self._build_ui() - self._connect_signals() - - # ------------------------------------------------------------------ # - # Default demo configuration # - # ------------------------------------------------------------------ # - - def _init_default_devices(self): - ai = AnalogInputDevice(device_id="ai_0", num_channels=4, simulate=True) - ai.connect() - temp = TemperatureDevice(device_id="temp_0", num_channels=3, simulate=True) - temp.connect() - dio = DigitalIODevice(device_id="dio_0", num_inputs=4, num_outputs=4, simulate=True) - dio.connect() - - for dev in [ai, temp, dio]: - self.registry.add_instance(dev) - self.engine.add_device(dev) - - # ------------------------------------------------------------------ # - # UI construction # - # ------------------------------------------------------------------ # - - def _build_ui(self): - # ---- Toolbar ---- - toolbar = QToolBar("Main") - toolbar.setMovable(False) - toolbar.setObjectName("mainToolbar") - self.addToolBar(toolbar) - - self.run_btn = QPushButton("▶ RUN") - self.run_btn.setObjectName("runButton") - self.run_btn.setCheckable(True) - self.run_btn.clicked.connect(self._toggle_run) - - self.log_btn = QPushButton("⬤ LOG") - self.log_btn.setObjectName("logButton") - self.log_btn.setCheckable(True) - self.log_btn.setEnabled(False) - self.log_btn.clicked.connect(self._toggle_log) - - add_dev_btn = QPushButton("+ Device") - add_dev_btn.setObjectName("addDeviceButton") - add_dev_btn.clicked.connect(self._add_device) - - toolbar.addWidget(self.run_btn) - toolbar.addSeparator() - toolbar.addWidget(self.log_btn) - toolbar.addSeparator() - toolbar.addWidget(add_dev_btn) - - # Spacer - spacer = QWidget() - spacer.setSizePolicy( - spacer.sizePolicy().horizontalPolicy(), - spacer.sizePolicy().verticalPolicy() - ) - from PyQt6.QtWidgets import QSizePolicy - spacer.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred) - toolbar.addWidget(spacer) - - self.time_label = QLabel("00:00:00") - self.time_label.setObjectName("timeLabel") - toolbar.addWidget(self.time_label) - - # ---- Central layout ---- - central = QWidget() - self.setCentralWidget(central) - root = QHBoxLayout(central) - root.setContentsMargins(0, 0, 0, 0) - root.setSpacing(0) - - splitter = QSplitter(Qt.Orientation.Horizontal) - splitter.setHandleWidth(4) - - # Left: device panel - self.device_panel = DevicePanel(self.registry, self.engine) - self.device_panel.setMinimumWidth(200) - splitter.addWidget(self.device_panel) - - # Center: strip chart - self.strip_chart = StripChartWidget(self.engine, self.registry) - splitter.addWidget(self.strip_chart) - - # Right: readouts + alarms - right_panel = QWidget() - right_layout = QVBoxLayout(right_panel) - right_layout.setContentsMargins(0, 0, 0, 0) - right_layout.setSpacing(0) - - self.readout_panel = ReadoutPanel(self.registry) - self.alarm_panel = AlarmPanel() - - right_splitter = QSplitter(Qt.Orientation.Vertical) - right_splitter.addWidget(self.readout_panel) - right_splitter.addWidget(self.alarm_panel) - right_layout.addWidget(right_splitter) - - right_panel.setMinimumWidth(220) - splitter.addWidget(right_panel) - - splitter.setSizes([220, 820, 240]) - root.addWidget(splitter) - - # ---- Status bar ---- - self.status_bar = QStatusBar() - self.setStatusBar(self.status_bar) - self._status_lbl = QLabel("Ready") - self.status_bar.addWidget(self._status_lbl) - - # Clock timer - self._elapsed = 0 - self._clock = QTimer() - self._clock.setInterval(1000) - self._clock.timeout.connect(self._tick_clock) - - def _connect_signals(self): - self.engine.alarm_triggered.connect(self._on_alarm) - self.engine.new_data.connect(self.readout_panel.on_new_data) - self.engine.new_data.connect(self.strip_chart.on_new_data) - self.device_panel.config_requested.connect(self._open_config) - - # ------------------------------------------------------------------ # - # Actions # - # ------------------------------------------------------------------ # - - def _toggle_run(self, checked: bool): - if checked: - self.engine.start() - self.run_btn.setText("⏹ STOP") - self.log_btn.setEnabled(True) - self._clock.start() - self._status_lbl.setText("Acquiring data…") - self._running = True - else: - self.engine.stop() - self.run_btn.setText("▶ RUN") - self.log_btn.setEnabled(False) - if self.log_btn.isChecked(): - self.log_btn.setChecked(False) - self._toggle_log(False) - self._clock.stop() - self._status_lbl.setText("Stopped") - self._running = False - - def _toggle_log(self, checked: bool): - if checked: - path = self.engine.start_logging() - self.log_btn.setText(f"⏹ LOGGING") - self._status_lbl.setText(f"Logging → {path}") - else: - self.engine.stop_logging() - self.log_btn.setText("⬤ LOG") - self._status_lbl.setText("Log saved.") - - def _add_device(self): - from ui.add_device_dialog import AddDeviceDialog - dlg = AddDeviceDialog(self.registry, self) - if dlg.exec(): - dev = dlg.created_device - if dev: - self.registry.add_instance(dev) - self.engine.add_device(dev) - dev.connect() - self.device_panel.refresh() - self.readout_panel.refresh() - self.strip_chart.refresh() - - def _open_config(self, device_id: str): - dev = self.registry.get_instance(device_id) - if dev: - dlg = DeviceConfigDialog(dev, self) - dlg.exec() - - @pyqtSlot(str, str, float, str) - def _on_alarm(self, device_id: str, channel_id: str, value: float, kind: str): - self.alarm_panel.add_alarm(device_id, channel_id, value, kind) - - def _tick_clock(self): - self._elapsed += 1 - h = self._elapsed // 3600 - m = (self._elapsed % 3600) // 60 - s = self._elapsed % 60 - self.time_label.setText(f"{h:02d}:{m:02d}:{s:02d}") - - def closeEvent(self, event): - self.engine.stop() - event.accept() |
