summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-04-23 10:52:37 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-04-23 10:52:37 -0600
commit4244e5d97da0273fed70f734a4cfe822bd15c9cb (patch)
tree225943bad9854f5ee08ac8f0c122e1b42a6525b6
parent99445c6fd2fd4f15df828c79600b96b80fa1cfa6 (diff)
Fixed clear signal feature to inlcude all signals
-rw-r--r--core/__pycache__/acquisition.cpython-312.pycbin11417 -> 11456 bytes
-rw-r--r--core/__pycache__/signal_processor.cpython-312.pycbin23682 -> 24525 bytes
-rw-r--r--core/acquisition.py2
-rw-r--r--core/signal_processor.py13
-rw-r--r--ui/__pycache__/main_window.cpython-312.pycbin27500 -> 28733 bytes
-rw-r--r--ui/main_window.py19
-rw-r--r--ui/style_dark.qss72
-rw-r--r--ui/style_light.qss57
8 files changed, 160 insertions, 3 deletions
diff --git a/core/__pycache__/acquisition.cpython-312.pyc b/core/__pycache__/acquisition.cpython-312.pyc
index c593432..cb5f3f3 100644
--- a/core/__pycache__/acquisition.cpython-312.pyc
+++ b/core/__pycache__/acquisition.cpython-312.pyc
Binary files differ
diff --git a/core/__pycache__/signal_processor.cpython-312.pyc b/core/__pycache__/signal_processor.cpython-312.pyc
index e914490..4572e55 100644
--- a/core/__pycache__/signal_processor.cpython-312.pyc
+++ b/core/__pycache__/signal_processor.cpython-312.pyc
Binary files differ
diff --git a/core/acquisition.py b/core/acquisition.py
index 57fda7e..a984c71 100644
--- a/core/acquisition.py
+++ b/core/acquisition.py
@@ -176,7 +176,7 @@ class AcquisitionEngine(QObject):
for ch in dev.info.channels:
val = readings.get(ch.channel_id)
- if val is None:
+ if val is None or not ch.enabled:
log_row.append("")
continue
buf = self._buffers.get(dev.info.device_id, {}).get(ch.channel_id)
diff --git a/core/signal_processor.py b/core/signal_processor.py
index 0d4ed39..417d142 100644
--- a/core/signal_processor.py
+++ b/core/signal_processor.py
@@ -359,6 +359,14 @@ class SignalProcessor(QObject):
def all_virtual_channel_ids(self) -> List[str]:
return list(self._derived_bufs.keys())
+ def clear_history(self):
+ """Clear derived channel buffers and latest-value cache."""
+ with self._lock:
+ for t_buf, v_buf in self._derived_bufs.values():
+ t_buf.clear()
+ v_buf.clear()
+ self._latest.clear()
+
# ── Main data path ────────────────────────────────────────────────────
def on_raw_data(self, device_id: str, channel_id: str,
@@ -401,6 +409,11 @@ class SignalProcessor(QObject):
try:
result = self._compute_derived(dc, inputs, timestamp, latest)
if result is not None:
+ # Write back into local snapshot so downstream derived
+ # channels that depend on this one can see it this pass
+ latest[("derived", dc.channel_id)] = (timestamp, result)
+ with self._lock:
+ self._latest[("derived", dc.channel_id)] = (timestamp, result)
bufs = self._derived_bufs.get(dc.channel_id)
if bufs:
bufs[0].append(timestamp)
diff --git a/ui/__pycache__/main_window.cpython-312.pyc b/ui/__pycache__/main_window.cpython-312.pyc
index ceb1a97..054aa5b 100644
--- a/ui/__pycache__/main_window.cpython-312.pyc
+++ b/ui/__pycache__/main_window.cpython-312.pyc
Binary files differ
diff --git a/ui/main_window.py b/ui/main_window.py
index ec0f39d..483ca49 100644
--- a/ui/main_window.py
+++ b/ui/main_window.py
@@ -10,10 +10,23 @@ from PyQt6.QtWidgets import (
QMainWindow, QWidget, QHBoxLayout, QVBoxLayout,
QSplitter, QStatusBar, QLabel, QPushButton,
QToolBar, QSizePolicy, QApplication, QFrame,
+ QAbstractSpinBox, QComboBox,
)
-from PyQt6.QtCore import Qt, QTimer, pyqtSlot
+from PyQt6.QtCore import Qt, QTimer, QObject, QEvent, pyqtSlot
import os
+
+class _WheelBlocker(QObject):
+ """App-level event filter: blocks accidental scroll-wheel changes on
+ spin boxes, combo boxes and sliders that don't have keyboard focus."""
+ def eventFilter(self, obj, event):
+ if event.type() == QEvent.Type.Wheel:
+ if isinstance(obj, (QAbstractSpinBox, QComboBox)):
+ if not obj.hasFocus():
+ event.ignore()
+ return True
+ return super().eventFilter(obj, event)
+
from devices.analog_input import AnalogInputDevice
from devices.digital_io import DigitalIODevice
from devices.serial_device import SerialDevice
@@ -52,6 +65,9 @@ class MainWindow(QMainWindow):
self._win_plot = None
self._win_settings = None
+ self._wheel_blocker = _WheelBlocker(self)
+ QApplication.instance().installEventFilter(self._wheel_blocker)
+
self._init_demo_devices()
self._build_ui()
self._connect_signals()
@@ -345,6 +361,7 @@ class MainWindow(QMainWindow):
def _clear_history(self):
self.engine.clear_history()
+ self.processor.clear_history()
self._chart.refresh()
self._status.setText("History cleared.")
diff --git a/ui/style_dark.qss b/ui/style_dark.qss
index df48330..2c24d1c 100644
--- a/ui/style_dark.qss
+++ b/ui/style_dark.qss
@@ -18,6 +18,18 @@ QMainWindow, QDialog {
background-color: #0b0e13;
}
+QWidget {
+ color: #e2e8f0;
+}
+
+/* Containers inside scroll areas inherit dark bg */
+QAbstractScrollArea > QWidget {
+ background-color: #111620;
+}
+QAbstractScrollArea > QWidget > QWidget {
+ background-color: #111620;
+}
+
/* ── Toolbar ─────────────────────────────────────────────────────── */
QToolBar#mainToolbar {
background-color: #0b0e13;
@@ -388,7 +400,6 @@ QPushButton#applyButton:hover { background-color: #1d4ed8; color: #eff6ff; }
/* ── Control widgets ─────────────────────────────────────────────── */
QFrame#controlWidget { background-color: #161d2e; border: 1px solid #2a3558; border-radius: 6px; }
-QFrame#controlWidget:hover { border-color: #3b82f6; }
QWidget#controlWidgetHeader { background-color: #0f1521; border-radius: 5px 5px 0 0; border-bottom: 1px solid #2a3558; }
QLabel#controlWidgetIcon { font-size: 14px; color: #3b82f6; padding-right: 4px; }
QLabel#controlWidgetTitle { font-family: "IBM Plex Mono", monospace; font-size: 11px; font-weight: 700; letter-spacing: 1.5px; color: #8b9dc3; }
@@ -465,6 +476,65 @@ QLabel#traceSource {
font-size: 12px;
}
+/* ── File dialog ─────────────────────────────────────────────────── */
+QFileDialog {
+ background-color: #0b0e13;
+}
+QFileDialog QWidget {
+ background-color: #0b0e13;
+ color: #e2e8f0;
+}
+QFileDialog QTreeView,
+QFileDialog QListView {
+ background-color: #111620;
+ border: 1px solid #2a3558;
+ color: #e2e8f0;
+ alternate-background-color: #161d2e;
+}
+QFileDialog QTreeView::item:selected,
+QFileDialog QListView::item:selected {
+ background-color: #1e3a5f;
+ color: #e0f2fe;
+}
+QFileDialog QTreeView::item:hover,
+QFileDialog QListView::item:hover {
+ background-color: #1c2540;
+}
+QFileDialog QHeaderView::section {
+ background-color: #161d2e;
+ color: #8b9dc3;
+ border: none;
+ border-bottom: 1px solid #2a3558;
+ padding: 4px 8px;
+}
+QFileDialog QSplitter {
+ background-color: #0b0e13;
+}
+QFileDialog QSplitter::handle {
+ background-color: #2a3558;
+}
+QFileDialog QToolBar {
+ background-color: #0b0e13;
+ border-bottom: 1px solid #2a3558;
+}
+QFileDialog QToolButton {
+ background-color: transparent;
+ color: #8b9dc3;
+ border: 1px solid transparent;
+ border-radius: 3px;
+ padding: 2px;
+}
+QFileDialog QToolButton:hover {
+ background-color: #1c2540;
+ border-color: #2a3558;
+ color: #e2e8f0;
+}
+QFileDialog QComboBox {
+ background-color: #0b0e13;
+ border: 1px solid #2a3558;
+ color: #e2e8f0;
+}
+
/* ── Profile / File menu ─────────────────────────────────────────── */
QMenu#profileMenu {
background-color: #111620;
diff --git a/ui/style_light.qss b/ui/style_light.qss
index 8b5c8da..38b91f8 100644
--- a/ui/style_light.qss
+++ b/ui/style_light.qss
@@ -67,3 +67,60 @@ QListWidget#portList {
QListWidget#portList::item { padding:5px 8px; border-bottom:1px solid #f1f5f9; }
QListWidget#portList::item:hover { background:#f0f9ff; color:#1d4ed8; }
QListWidget#portList::item:selected { background:#dbeafe; color:#1d4ed8; border-left:3px solid #3b82f6; }
+
+/* ── Control panel widgets ───────────────────────────────────────── */
+QFrame#controlWidget { background:#ffffff; border:1px solid #cbd5e1; border-radius:6px; }
+QWidget#controlWidgetHeader { background:#f1f5f9; border-radius:5px 5px 0 0; border-bottom:1px solid #e2e8f0; }
+QLabel#controlWidgetIcon { font-size:14px; color:#3b82f6; padding-right:4px; }
+QLabel#controlWidgetTitle { font-family:"IBM Plex Mono",monospace; font-size:11px; font-weight:700; letter-spacing:1.5px; color:#64748b; }
+QWidget#controlWidgetBody { background:#ffffff; border-radius:0 0 5px 5px; }
+QFrame#controlWidgetWrapper { background:transparent; border:none; }
+
+/* Motor */
+QLabel#motorSpeedLbl { font-family:"IBM Plex Mono",monospace; font-size:28px; font-weight:700; color:#1d4ed8; }
+QLabel#motorUnitLbl { font-family:"IBM Plex Mono",monospace; font-size:12px; color:#94a3b8; padding-top:12px; }
+QLabel#motorPctLbl { font-family:"IBM Plex Mono",monospace; font-size:12px; color:#94a3b8; }
+QSlider#motorSlider::groove:horizontal, QSlider#pwmSlider::groove:horizontal { background:#e2e8f0; height:6px; border-radius:3px; }
+QSlider#motorSlider::handle:horizontal, QSlider#pwmSlider::handle:horizontal { background:#3b82f6; border:2px solid #1d4ed8; width:16px; height:16px; margin:-5px 0; border-radius:8px; }
+QSlider#motorSlider::sub-page:horizontal { background:#3b82f6; border-radius:3px; }
+QSlider#pwmSlider::sub-page:horizontal { background:#7c3aed; border-radius:3px; }
+QPushButton#motorDirBtn { background:#f1f5f9; color:#64748b; border:1px solid #cbd5e1; border-radius:4px; padding:5px 10px; font-family:"IBM Plex Mono",monospace; font-size:12px; }
+QPushButton#motorDirBtnRev { background:#ede9fe; color:#6d28d9; border:1px solid #7c3aed; border-radius:4px; padding:5px 10px; font-family:"IBM Plex Mono",monospace; font-size:12px; }
+QPushButton#motorRunBtnOff { background:#f1f5f9; color:#94a3b8; border:1px solid #cbd5e1; border-radius:4px; padding:5px 12px; font-family:"IBM Plex Mono",monospace; font-weight:700; }
+QPushButton#motorRunBtnOn { background:#dcfce7; color:#166534; border:1px solid #22c55e; border-radius:4px; padding:5px 12px; font-family:"IBM Plex Mono",monospace; font-weight:700; }
+
+/* Switch */
+QPushButton#switchBtnOff, QPushButton#switchBtn { background:#f1f5f9; color:#94a3b8; border:2px solid #cbd5e1; border-radius:6px; font-family:"IBM Plex Mono",monospace; font-size:18px; font-weight:800; letter-spacing:4px; min-height:52px; }
+QPushButton#switchBtnOn { background:#dcfce7; color:#166534; border:2px solid #22c55e; border-radius:6px; font-family:"IBM Plex Mono",monospace; font-size:18px; font-weight:800; letter-spacing:4px; min-height:52px; }
+QLabel#switchIndicatorOff { font-size:18px; color:#cbd5e1; }
+QLabel#switchIndicatorOn { font-size:18px; color:#22c55e; }
+QLabel#switchStateLbl { font-family:"IBM Plex Mono",monospace; font-size:10px; font-weight:700; letter-spacing:1px; color:#94a3b8; }
+
+/* Setpoint */
+QLabel#spLabel { font-family:"IBM Plex Mono",monospace; font-size:11px; font-weight:700; color:#3b82f6; letter-spacing:0.5px; }
+QLabel#pvLabel { font-family:"IBM Plex Mono",monospace; font-size:11px; font-weight:700; color:#16a34a; letter-spacing:0.5px; }
+QLabel#errLabel { font-family:"IBM Plex Mono",monospace; font-size:11px; font-weight:700; color:#d97706; letter-spacing:0.5px; }
+QLabel#pvValue, QLabel#errValue { font-family:"IBM Plex Mono",monospace; font-size:12px; color:#64748b; }
+QDoubleSpinBox#spSpinbox { font-family:"IBM Plex Mono",monospace; font-size:13px; font-weight:600; color:#1e293b; background:#ffffff; border:1px solid #3b82f6; border-radius:3px; padding:3px 6px; }
+QPushButton#spStepBtn { background:#dbeafe; color:#1d4ed8; border:1px solid #3b82f6; border-radius:3px; font-size:16px; font-weight:700; padding:0; }
+QPushButton#spStepBtn:hover { background:#bfdbfe; }
+
+/* PWM */
+QLabel#pwmLabel { font-family:"IBM Plex Mono",monospace; font-size:11px; color:#64748b; }
+QLabel#pwmValue { font-family:"IBM Plex Mono",monospace; font-size:13px; font-weight:700; color:#6d28d9; }
+QSpinBox#pwmFreqSpin { font-family:"IBM Plex Mono",monospace; font-size:12px; background:#ffffff; border:1px solid #cbd5e1; border-radius:3px; color:#1e293b; padding:3px 6px; }
+QPushButton#digitalOutBtn { background:#f1f5f9; color:#94a3b8; border:1px solid #cbd5e1; border-radius:4px; padding:4px 14px; font-family:"IBM Plex Mono",monospace; min-width:50px; }
+QPushButton#digitalOutBtn:checked { background:#dcfce7; border-color:#22c55e; color:#166534; }
+
+/* Misc window controls */
+QWidget#controlPanelHeader { background:#f1f5f9; border-bottom:1px solid #e2e8f0; }
+QPushButton#devicesSmallBtn { background:transparent; color:#94a3b8; border:1px solid #e2e8f0; border-radius:3px; font-size:13px; padding:0; }
+QPushButton#devicesSmallBtn:hover { background:#f0f9ff; color:#3b82f6; border-color:#3b82f6; }
+QPushButton#plotCfgButton { background:#f0f9ff; color:#1d4ed8; border:1px solid #93c5fd; border-radius:4px; padding:5px 14px; font-weight:600; }
+QPushButton#plotCfgButton:hover { background:#dbeafe; border-color:#3b82f6; }
+QPushButton#plotCfgButton:checked { background:#dbeafe; border-color:#3b82f6; }
+QComboBox#channelPickerCb { font-family:"IBM Plex Mono",monospace; font-size:12px; background:#ffffff; border:1px solid #cbd5e1; border-radius:3px; color:#1e293b; padding:4px 8px; }
+QMenu#profileMenu { background:#ffffff; border:1px solid #e2e8f0; border-radius:4px; padding:4px 0; color:#1e293b; }
+QMenu#profileMenu::item { padding:7px 20px; color:#334155; }
+QMenu#profileMenu::item:selected { background:#dbeafe; color:#1d4ed8; }
+QMenu#profileMenu::separator { height:1px; background:#e2e8f0; margin:3px 8px; }