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