Line data Source code
1 : # SPDX-FileCopyrightText: 2025 Pairinteraction Developers 2 : # SPDX-License-Identifier: LGPL-3.0-or-later 3 : 4 0 : from typing import TYPE_CHECKING, Generic, Optional, TypeVar 5 : 6 0 : from PySide6.QtCore import QObject, Qt 7 0 : from PySide6.QtWidgets import QFormLayout, QHBoxLayout, QLayout, QVBoxLayout, QWidget 8 : 9 : if TYPE_CHECKING: 10 : ChildType = TypeVar("ChildType", bound=QObject) 11 : from pairinteraction_gui.main_window import MainWindow 12 : 13 0 : LayoutType = TypeVar("LayoutType", bound=QLayout) 14 : 15 : 16 0 : class Widget(QWidget, Generic[LayoutType]): 17 : """Custom Widget class.""" 18 : 19 0 : layout_type: type[LayoutType] 20 0 : margin: tuple[int, int, int, int] = (0, 0, 0, 0) 21 0 : spacing: int = 0 22 : 23 0 : def __init__( 24 : self, 25 : parent: Optional[QWidget] = None, 26 : *, 27 : name: Optional[str] = None, 28 : margin: Optional[tuple[int, int, int, int]] = None, 29 : spacing: Optional[int] = None, 30 : ) -> None: 31 : """Initialize the base section.""" 32 0 : super().__init__(parent) 33 : 34 0 : if name is not None: 35 0 : self.setObjectName(name) 36 0 : if margin is not None: 37 0 : self.margin = margin 38 0 : if spacing is not None: 39 0 : self.spacing = spacing 40 : 41 0 : layout = self.layout_type(self) # can be accessed as self.layout() 42 0 : layout.setContentsMargins(*self.margin) 43 0 : layout.setSpacing(self.spacing) 44 : 45 0 : self.setupWidget() 46 0 : self.postSetupWidget() 47 : 48 0 : def layout(self) -> LayoutType: 49 0 : return super().layout() # type: ignore [return-value] # explicitly override type hints 50 : 51 0 : def window(self) -> "MainWindow": 52 0 : return super().window() # type: ignore [return-value] # explicitly override type hints 53 : 54 0 : def findChild( # type: ignore [override] # explicitly override type hints 55 : self, type_: type["ChildType"], name: str, options: Optional["Qt.FindChildOption"] = None 56 : ) -> "ChildType": 57 0 : if options is None: 58 0 : options = Qt.FindChildOption.FindChildrenRecursively 59 0 : return super().findChild(type_, name, options) # type: ignore [return-value] # explicitly override type hints 60 : 61 0 : def setupWidget(self) -> None: 62 : """Set up the UI components. 63 : 64 : This method should be overwritten by subclasses to set up the UI components. 65 : """ 66 : 67 0 : def postSetupWidget(self) -> None: 68 : """Post-process the UI components. 69 : 70 : This method should be overwritten by subclasses to post-process the UI components. 71 : """ 72 : 73 : 74 0 : class WidgetV(Widget[QVBoxLayout]): 75 : """Custom Widget class with vertical (QVBoxLayout) layout.""" 76 : 77 0 : layout_type = QVBoxLayout 78 : 79 : 80 0 : class WidgetH(Widget[QHBoxLayout]): 81 : """Custom Widget class with horizontal (QHBoxLayout) layout.""" 82 : 83 0 : layout_type = QHBoxLayout 84 : 85 : 86 0 : class WidgetForm(Widget[QFormLayout]): 87 : """Custom Widget class with form (QFormLayout) layout.""" 88 : 89 0 : layout_type = QFormLayout 90 0 : margin = (5, 15, 5, 5) 91 0 : spacing = 10