summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorChristian Kolset <christian.kolset@gmail.com>2026-06-03 10:12:34 -0600
committerChristian Kolset <christian.kolset@gmail.com>2026-06-03 10:12:34 -0600
commit3610309b1e5d83049554afe287129c99389d231d (patch)
treedcf2f554aff081381d6ff60074546a1a54732c96 /ui
parent0a8d42501c1bf168bd852537bb3cd18490fac7ee (diff)
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 <noreply@anthropic.com>
Diffstat (limited to 'ui')
-rw-r--r--ui/main_window.py19
-rw-r--r--ui/windows/settings_window.py41
2 files changed, 17 insertions, 43 deletions
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)