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 --- plugins/enabled.json | 2 +- plugins/example/__pycache__/plugin.cpython-312.pyc | Bin 3549 -> 0 bytes plugins/example/manifest.json | 8 -- plugins/example/plugin.py | 105 --------------------- plugins/motion_capture/plugin.py | 11 ++- 5 files changed, 10 insertions(+), 116 deletions(-) delete mode 100644 plugins/example/__pycache__/plugin.cpython-312.pyc delete mode 100644 plugins/example/manifest.json delete mode 100644 plugins/example/plugin.py (limited to 'plugins') diff --git a/plugins/enabled.json b/plugins/enabled.json index a2216af..a33a40a 100644 --- a/plugins/enabled.json +++ b/plugins/enabled.json @@ -1,3 +1,3 @@ { - "example": true + "motion_capture": true } \ No newline at end of file diff --git a/plugins/example/__pycache__/plugin.cpython-312.pyc b/plugins/example/__pycache__/plugin.cpython-312.pyc deleted file mode 100644 index c31b466..0000000 Binary files a/plugins/example/__pycache__/plugin.cpython-312.pyc and /dev/null differ diff --git a/plugins/example/manifest.json b/plugins/example/manifest.json deleted file mode 100644 index a5af87d..0000000 --- a/plugins/example/manifest.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "plugin_id": "example", - "name": "Example Plugin", - "version": "1.0.0", - "description": "Skeleton showing all plugin integration points. Safe to delete.", - "author": "Your Name", - "entry_point": "plugin.ExamplePlugin" -} diff --git a/plugins/example/plugin.py b/plugins/example/plugin.py deleted file mode 100644 index e5fbb8e..0000000 --- a/plugins/example/plugin.py +++ /dev/null @@ -1,105 +0,0 @@ -""" -plugins/example/plugin.py - -Skeleton plugin — shows every integration point. -Copy this directory, rename it, update manifest.json, and fill in your logic. -""" - -from __future__ import annotations -from typing import Any, Dict, List, Optional, Type - -from PyQt6.QtWidgets import QLabel, QWidget - -# LabDAQ imports available at runtime -from plugins.base_plugin import LabPlugin, PluginAction, PluginContext - - -class ExamplePlugin(LabPlugin): - - # ── Metadata ────────────────────────────────────────────────────────── - - @property - def plugin_id(self) -> str: - return "example" - - @property - def name(self) -> str: - return "Example Plugin" - - @property - def version(self) -> str: - return "1.0.0" - - @property - def description(self) -> str: - return "Skeleton showing all plugin integration points." - - @property - def author(self) -> str: - return "Your Name" - - # ── Lifecycle ───────────────────────────────────────────────────────── - - def on_load(self, context: PluginContext) -> None: - self._ctx = context - # e.g. start a background thread, open a camera, etc. - - def on_unload(self) -> None: - # Release resources — called when user disables plugin - pass - - # ── Toolbar ─────────────────────────────────────────────────────────── - - def get_toolbar_actions(self) -> List[PluginAction]: - return [ - PluginAction( - label = "Example", - icon = "🔌", - tooltip = "Open example plugin window", - checkable = True, - callback = self._on_toolbar_click, - ) - ] - - def _on_toolbar_click(self, checked: bool): - # Open / close your plugin window here - pass - - # ── Devices ─────────────────────────────────────────────────────────── - - def get_devices(self) -> list: - # Return BaseDevice instances — they are auto-added to the registry - # and AcquisitionEngine so their channels appear as normal signals. - # - # Example (uncomment and adapt): - # from devices.analog_input import AnalogInputDevice - # return [AnalogInputDevice("my_plugin_ai", num_channels=2, simulate=True)] - return [] - - # ── Custom filters ──────────────────────────────────────────────────── - - def get_filter_classes(self) -> Dict[str, Type]: - # Return {type_name: FilterBase subclass} for custom pipeline filters. - # - # Example: - # from .my_filter import MyFilter - # return {"my_filter": MyFilter} - return {} - - # ── Settings widget ─────────────────────────────────────────────────── - - def get_settings_widget(self) -> Optional[QWidget]: - # Return a QWidget shown in Settings > Plugins when this plugin is enabled. - lbl = QLabel("No settings for this plugin.") - lbl.setObjectName("traceSource") - return lbl - - # ── Profile persistence ─────────────────────────────────────────────── - - def get_save_state(self) -> Dict[str, Any]: - # Return JSON-serialisable dict saved with .labdaq profiles. - return {} - - def apply_save_state(self, state: Dict[str, Any]) -> None: - # Restore plugin state when a profile is loaded. - pass diff --git a/plugins/motion_capture/plugin.py b/plugins/motion_capture/plugin.py index e5d37c7..1c655c5 100644 --- a/plugins/motion_capture/plugin.py +++ b/plugins/motion_capture/plugin.py @@ -166,9 +166,16 @@ class MotionCapturePlugin(LabPlugin): self._win.set_px_per_mm(state.get("px_per_mm", 10.0)) if checked: - geo = self._ctx.main_window.geometry() if not self._win.isVisible(): - self._win.move(geo.right() + 8, geo.top() + 40) + from PyQt6.QtWidgets import QApplication + mw = self._ctx.main_window + screen = QApplication.screenAt(mw.geometry().center()) or QApplication.primaryScreen() + avail = screen.availableGeometry() + geo = mw.normalGeometry() + self._win.adjustSize() + x = max(avail.left(), min(geo.right() + 8, avail.right() - self._win.width())) + y = max(avail.top(), min(geo.top() + 40, avail.bottom() - self._win.height())) + self._win.move(x, y) self._win.show() self._win.raise_() else: -- cgit v1.2.3