""" ui/alarm_panel.py — Alarm event log. """ from datetime import datetime from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QScrollArea, QFrame, QPushButton, ) from PyQt6.QtCore import Qt class AlarmRow(QFrame): def __init__(self, dev_id: str, ch_id: str, value: float, kind: str): super().__init__() self.setObjectName("alarmEntry") color = "#ef4444" if kind == "high" else "#f59e0b" arrow = "▲" if kind == "high" else "▼" self.setStyleSheet(f"QFrame#alarmEntry {{ border-left: 3px solid {color}; }}") ts_str = datetime.now().strftime("%H:%M:%S.%f")[:11] layout = QHBoxLayout(self) layout.setContentsMargins(8, 3, 8, 3) msg = QLabel(f"{arrow} {dev_id} / {ch_id} = {value:.4f} [{kind.upper()}]") msg.setObjectName("alarmMsg") ts = QLabel(ts_str) ts.setObjectName("alarmTs") layout.addWidget(msg, 1) layout.addWidget(ts) class AlarmPanel(QWidget): def __init__(self): super().__init__() self._count = 0 self._build() def _build(self): layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) hdr_w = QWidget() hdr_w.setObjectName("alarmHeaderWidget") hdr_lay = QHBoxLayout(hdr_w) hdr_lay.setContentsMargins(0, 0, 4, 0) hdr = QLabel(" ALARMS") hdr.setObjectName("panelHeader") hdr.setMinimumHeight(28) hdr_lay.addWidget(hdr, 1) clr = QPushButton("Clear") clr.setObjectName("clearAlarmsBtn") clr.clicked.connect(self.clear) hdr_lay.addWidget(clr) layout.addWidget(hdr_w) self._scroll = QScrollArea() self._scroll.setWidgetResizable(True) self._container = QWidget() self._inner = QVBoxLayout(self._container) self._inner.setContentsMargins(4, 4, 4, 4) self._inner.setSpacing(2) self._inner.addStretch() self._scroll.setWidget(self._container) layout.addWidget(self._scroll) def add_alarm(self, dev_id: str, ch_id: str, value: float, kind: str): row = AlarmRow(dev_id, ch_id, value, kind) self._inner.insertWidget(0, row) self._count += 1 # Cap at 300 entries if self._count > 300: item = self._inner.takeAt(self._inner.count() - 2) if item and item.widget(): item.widget().deleteLater() self._count -= 1 def clear(self): while self._inner.count() > 1: item = self._inner.takeAt(0) if item and item.widget(): item.widget().deleteLater() self._count = 0