# Standard Library from dataclasses import dataclass from typing import List, Callable, Protocol # External Library from PySide6.QtWidgets import (QToolBar, QMainWindow, QWidget, QMdiArea, QMdiSubWindow) from PySide6.QtGui import (QAction) class UIComponent(Protocol): def build(self, app: QMainWindow): pass @dataclass class ToolbarAction: name: str callback: Callable[[QMainWindow], None] @dataclass class Toolbar(UIComponent): name: str actions: List[ToolbarAction] def build(self, app: QMainWindow): toolbar = QToolBar(self.name) for action in self.actions: qt_action = QAction(action.name, app) qt_action.triggered.connect(lambda checked=False, cb=action.callback: cb(app)) toolbar.addAction(qt_action) app.addToolBar(toolbar) @dataclass class SubWindow(UIComponent): name: str content_factory: Callable[[], QWidget] def build(self, app: QMainWindow): if not hasattr(app, 'mdi_area'): raise AttributeError("MDI area not found in app") mdi_area: QMdiArea = getattr(app, 'mdi_area') sub_window = QMdiSubWindow() sub_window.setWidget(self.content_factory()) sub_window.setWindowTitle(self.name) mdi_area.addSubWindow(sub_window) sub_window.show() @dataclass class Window(UIComponent): title: str def build(self, app: QMainWindow): app.setWindowTitle(self.title) @dataclass class Characteristics: components: List[UIComponent]