From 8d6acf3a8ea4b37f86b321dbf430be5be01b1267 Mon Sep 17 00:00:00 2001 From: Christian Kolset Date: Mon, 13 Apr 2026 14:36:55 -0600 Subject: init --- daq_system/ui/alarm_panel.py | 85 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 daq_system/ui/alarm_panel.py (limited to 'daq_system/ui/alarm_panel.py') diff --git a/daq_system/ui/alarm_panel.py b/daq_system/ui/alarm_panel.py new file mode 100644 index 0000000..590d785 --- /dev/null +++ b/daq_system/ui/alarm_panel.py @@ -0,0 +1,85 @@ +""" +ui/alarm_panel.py — Alarm event log panel. +""" + +from datetime import datetime +from PyQt6.QtWidgets import ( + QWidget, QVBoxLayout, QHBoxLayout, QLabel, + QScrollArea, QFrame, QPushButton +) +from PyQt6.QtCore import Qt + + +class AlarmEntry(QFrame): + def __init__(self, device_id, channel_id, value, kind, timestamp): + super().__init__() + self.setObjectName("alarmEntry") + color = "#f85149" if kind == "high" else "#d29922" + self.setStyleSheet(f"border-left: 3px solid {color};") + layout = QHBoxLayout(self) + layout.setContentsMargins(8, 4, 8, 4) + icon = "▲" if kind == "high" else "▼" + msg = QLabel(f"{icon} {device_id} / {channel_id} = {value:.3f} [{kind.upper()}]") + msg.setObjectName("alarmMsg") + ts_lbl = QLabel(timestamp) + ts_lbl.setObjectName("alarmTs") + layout.addWidget(msg) + layout.addStretch() + layout.addWidget(ts_lbl) + + +class AlarmPanel(QWidget): + def __init__(self): + super().__init__() + self._build_ui() + + def _build_ui(self): + layout = QVBoxLayout(self) + layout.setContentsMargins(0, 0, 0, 0) + layout.setSpacing(0) + + hdr_row = QHBoxLayout() + hdr = QLabel(" ALARMS") + hdr.setObjectName("panelHeader") + hdr_row.addWidget(hdr) + hdr_row.addStretch() + clr = QPushButton("Clear") + clr.setObjectName("clearAlarmsBtn") + clr.clicked.connect(self.clear_alarms) + hdr_row.addWidget(clr) + hdr_widget = QWidget() + hdr_widget.setLayout(hdr_row) + hdr_widget.setObjectName("alarmHeaderWidget") + layout.addWidget(hdr_widget) + + scroll = QScrollArea() + scroll.setWidgetResizable(True) + self._container = QWidget() + self._inner = QVBoxLayout(self._container) + self._inner.setContentsMargins(4, 4, 4, 4) + self._inner.setSpacing(3) + self._inner.addStretch() + scroll.setWidget(self._container) + layout.addWidget(scroll) + + self._scroll = scroll + self._count = 0 + + def add_alarm(self, device_id, channel_id, value, kind): + ts = datetime.now().strftime("%H:%M:%S") + entry = AlarmEntry(device_id, channel_id, value, kind, ts) + self._inner.insertWidget(0, entry) + self._count += 1 + # Keep last 200 + if self._count > 200: + item = self._inner.takeAt(self._inner.count() - 2) + if item and item.widget(): + item.widget().deleteLater() + self._count -= 1 + + def clear_alarms(self): + while self._inner.count() > 1: + item = self._inner.takeAt(0) + if item and item.widget(): + item.widget().deleteLater() + self._count = 0 -- cgit v1.2.3