""" sn_basis/ui/base_dockwidget.py Basis-Dockwidget für alle LNO-Module. """ from sn_basis.functions.qt_wrapper import QDockWidget, QTabWidget from sn_basis.functions.message_wrapper import warning, error from sn_basis.functions.qt_wrapper import ( QDockWidget, QTabWidget, QScrollArea, FrameNoFrame, Qt, DockWidgetMovable, DockWidgetFloatable, DockWidgetClosable, DockAreaLeft, DockAreaRight, ) def _inhalt(seite): """Tab-Instanz einer Reiterseite; liegt sie in einem Scroll-Bereich, dessen Inhalt.""" if isinstance(seite, QScrollArea): return seite.widget() return seite def tabs_mit_scrollbereich(tab_widget) -> None: """Packt jeden Tab eines QTabWidget in einen mitwachsenden Scroll-Bereich (Basis #104). Ohne Scroll-Bereich verlangt Qt für das Dock mindestens die Höhe des höchsten Tabs; ist der Tab höher als der Bildschirm, schiebt QGIS seinen unteren Fensterrand aus dem Bild. Tabs, die schon in einem Scroll-Bereich liegen, bleiben unverändert. """ if not callable(getattr(tab_widget, "count", None)) or not callable(getattr(tab_widget, "insertTab", None)): return aktuell = tab_widget.currentIndex() for index in range(tab_widget.count()): seite = tab_widget.widget(index) if seite is None or isinstance(seite, QScrollArea): continue titel = tab_widget.tabText(index) bereich = QScrollArea() bereich.setWidgetResizable(True) bereich.setFrameShape(FrameNoFrame) tab_widget.removeTab(index) bereich.setWidget(seite) tab_widget.insertTab(index, bereich, titel) tab_widget.setCurrentIndex(aktuell) class BaseDockWidget(QDockWidget): """ Basis-Dockwidget für alle LNO-Module. - Titel wird automatisch aus base_title + subtitle erzeugt - Tabs werden dynamisch aus der Klassenvariable 'tabs' erzeugt - Die zugehörige Toolbar-Action wird beim Schließen zurückgesetzt - Jeder Tab liegt in einem Scroll-Bereich (``setWidget``), auch wenn ein Fachplugin seine Tabs selbst aufbaut (Basis #104) """ base_title = "LNO Sachsen" tabs = [] # Liste von Tab-Klassen action = None # Referenz auf die Toolbar-Action def __init__(self, parent=None, subtitle=""): super().__init__(parent) # ----------------------------------------------------- # Dock-Konfiguration (WICHTIG) # ----------------------------------------------------- self.setFeatures( DockWidgetMovable | DockWidgetFloatable | DockWidgetClosable ) self.setAllowedAreas( DockAreaLeft | DockAreaRight ) # ----------------------------------------------------- # Titel setzen # ----------------------------------------------------- try: title = ( self.base_title if not subtitle else f"{self.base_title} | {subtitle}" ) self.setWindowTitle(title) except Exception as e: warning("Titel konnte nicht gesetzt werden", str(e)) # ----------------------------------------------------- # Tabs erzeugen # ----------------------------------------------------- try: tab_widget = QTabWidget() for tab_class in self.tabs: try: tab_instance = tab_class() tab_title = getattr( tab_class, "tab_title", tab_class.__name__, ) tab_widget.addTab(tab_instance, tab_title) except Exception as e: error( "Tab konnte nicht geladen werden", f"{tab_class}: {e}", ) self.setWidget(tab_widget) except Exception as e: error( "Tab-Widget konnte nicht initialisiert werden", str(e), ) # --------------------------------------------------------- # Inhalt setzen # --------------------------------------------------------- def setWidget(self, widget): """Wie ``QDockWidget.setWidget``; die Tabs eines QTabWidget bekommen je einen Scroll-Bereich.""" if widget is not None: try: tabs_mit_scrollbereich(widget) except Exception as e: warning("Scroll-Bereich konnte nicht angelegt werden", str(e)) super().setWidget(widget) # --------------------------------------------------------- # Dock schließen # --------------------------------------------------------- def closeEvent(self, event): """ Wird aufgerufen, wenn das Dock geschlossen wird. Setzt die zugehörige Toolbar-Action zurück. """ try: tab_widget = self.widget() if tab_widget and hasattr(tab_widget, "count") and hasattr(tab_widget, "widget"): for index in range(tab_widget.count()): tab = _inhalt(tab_widget.widget(index)) cleanup = getattr(tab, "cleanup", None) if callable(cleanup): try: cleanup() except Exception: pass except Exception: pass try: if self.action: self.action.setChecked(False) except Exception as e: warning( "Toolbar-Status konnte nicht zurückgesetzt werden", str(e), ) super().closeEvent(event)