From 3610309b1e5d83049554afe287129c99389d231d Mon Sep 17 00:00:00 2001 From: Christian Kolset Date: Wed, 3 Jun 2026 10:12:34 -0600 Subject: Fix settings/plugin window bugs; remove example plugin - Add missing QGroupBox import to settings_window (caused silent crash on open) - Remove Controls tab and _controls_tab() method from settings - Clamp child window positions to screen bounds so they don't go off-screen on Windows when main window is maximized - Apply same screen-clamp fix to Motion Capture plugin window - Delete example plugin; disable it in enabled.json Co-Authored-By: Claude Sonnet 4.6 --- ui/main_window.py | 19 ++++++++++++++++--- ui/windows/settings_window.py | 41 +---------------------------------------- 2 files changed, 17 insertions(+), 43 deletions(-) (limited to 'ui') diff --git a/ui/main_window.py b/ui/main_window.py index 4372b9f..abfd585 100644 --- a/ui/main_window.py +++ b/ui/main_window.py @@ -368,12 +368,25 @@ class MainWindow(QMainWindow): self._show_win(self._win_settings, "right") def _show_win(self, win: QWidget, position: str = "right"): - geo = self.geometry() if not win.isVisible(): + screen = QApplication.screenAt(self.geometry().center()) + if screen is None: + screen = QApplication.primaryScreen() + avail = screen.availableGeometry() + # Use normalGeometry so maximized windows don't push child off-screen + geo = self.normalGeometry() + win.adjustSize() + w, h = win.width(), win.height() if position == "right": - win.move(geo.right() + 8, geo.top() + 40) + x = geo.right() + 8 + y = geo.top() + 40 else: - win.move(geo.left(), geo.bottom() + 8) + x = geo.left() + y = geo.bottom() + 8 + # Clamp to available screen area + x = max(avail.left(), min(x, avail.right() - w)) + y = max(avail.top(), min(y, avail.bottom() - h)) + win.move(x, y) win.show(); win.raise_(); win.activateWindow() # ── Profile callbacks ───────────────────────────────────────────────── diff --git a/ui/windows/settings_window.py b/ui/windows/settings_window.py index 046cfae..422b6c9 100644 --- a/ui/windows/settings_window.py +++ b/ui/windows/settings_window.py @@ -13,7 +13,7 @@ from PyQt6.QtWidgets import ( QWidget, QVBoxLayout, QHBoxLayout, QLabel, QPushButton, QTabWidget, QFrame, QFormLayout, QComboBox, QSpinBox, QDoubleSpinBox, QCheckBox, QLineEdit, - QFileDialog, QScrollArea, + QFileDialog, QScrollArea, QGroupBox, ) from PyQt6.QtCore import Qt, pyqtSignal from PyQt6.QtGui import QCloseEvent, QFont @@ -76,7 +76,6 @@ class SettingsWindow(QWidget): tabs.addTab(self._general_tab(), " General ") tabs.addTab(self._acquisition_tab(), " Acquisition ") tabs.addTab(self._display_tab(), " Display ") - tabs.addTab(self._controls_tab(), " Controls ") tabs.addTab(self._plugins_tab(), " Plugins ") # Bottom bar @@ -163,44 +162,6 @@ class SettingsWindow(QWidget): root = QVBoxLayout(w); root.setContentsMargins(0,0,0,0); root.addWidget(scroll) return w - def _controls_tab(self): - """Output channel assignments — which device channel each control widget drives.""" - w = QWidget() - scroll = QScrollArea(); scroll.setWidgetResizable(True) - scroll.setObjectName("deviceScroll") - cont = QWidget(); lay = QVBoxLayout(cont) - lay.setContentsMargins(14,12,14,12); lay.setSpacing(8) - - info = QLabel( - "Configure which physical output channels are driven by each control widget.\n" - "Add output widget mappings below. Changes take effect on next app start." - ) - info.setObjectName("traceSource"); info.setWordWrap(True) - lay.addWidget(info) - - grp = QGroupBox("Output Assignments") - g_lay = QFormLayout(grp); g_lay.setSpacing(6) - - # Collect digital output channels - out_channels = ["— none —"] - for dev in self.registry.all_instances(): - for ch in dev.info.channels: - if ch.channel_id.startswith("do") or "out" in ch.channel_id.lower(): - out_channels.append(f"{dev.info.device_id} / {ch.channel_id} ({ch.name})") - - self._out_combos = {} - for label in ["Pump Power", "Heater", "Motor Enable", "PWM Ch 1"]: - cb = QComboBox(); cb.setObjectName("channelPickerCb") - cb.addItems(out_channels) - g_lay.addRow(f"{label}:", cb) - self._out_combos[label] = cb - - lay.addWidget(grp) - lay.addStretch() - scroll.setWidget(cont) - root = QVBoxLayout(w); root.setContentsMargins(0,0,0,0); root.addWidget(scroll) - return w - def _plugins_tab(self): w = QWidget() scroll = QScrollArea(); scroll.setWidgetResizable(True) -- cgit v1.2.3