diff options
Diffstat (limited to 'examples/widgets/layouts/borderlayout/borderlayout.py')
-rw-r--r-- | examples/widgets/layouts/borderlayout/borderlayout.py | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/examples/widgets/layouts/borderlayout/borderlayout.py b/examples/widgets/layouts/borderlayout/borderlayout.py new file mode 100644 index 000000000..3268d7034 --- /dev/null +++ b/examples/widgets/layouts/borderlayout/borderlayout.py @@ -0,0 +1,248 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +"""PySide6 port of the widgets/layouts/borderlayout example from Qt v5.x""" + +from dataclasses import dataclass +from enum import IntEnum, auto + +from PySide6.QtCore import QRect, QSize, Qt +from PySide6.QtWidgets import ( + QApplication, + QFrame, + QLabel, + QLayout, + QLayoutItem, + QTextBrowser, + QWidget, + QWidgetItem, +) +import sys + + +class Position(IntEnum): + West = auto() + North = auto() + South = auto() + East = auto() + Center = auto() + + +class SizeType(IntEnum): + MinimumSize = auto() + SizeHint = auto() + + +@dataclass +class ItemWrapper: + item: QLayoutItem + position: Position + + +class BorderLayout(QLayout): + def __init__(self, parent=None, spacing: int = -1): + super().__init__(parent) + + self._list: list[ItemWrapper] = [] + + self.setSpacing(spacing) + + if parent is not None: + self.setParent(parent) + + def __del__(self): + item = self.takeAt(0) + while item: + item = self.takeAt(0) + + def addItem(self, item: QLayoutItem): + self.add(item, Position.West) + + def addWidget(self, widget: QWidget, position: Position): + self.add(QWidgetItem(widget), position) + + def expandingDirections(self) -> Qt.Orientations: + return Qt.Horizontal | Qt.Vertical + + def hasHeightForWidth(self) -> bool: + return False + + def count(self) -> int: + return len(self._list) + + def itemAt(self, index: int) -> QLayoutItem: + if index < len(self._list): + wrapper: ItemWrapper = self._list[index] + return wrapper.item + return None + + def minimumSize(self) -> QSize: + return self.calculate_size(SizeType.MinimumSize) + + def setGeometry(self, rect: QRect): + center: ItemWrapper = None + east_width = 0 + west_width = 0 + north_height = 0 + south_height = 0 + + super().setGeometry(rect) + + for wrapper in self._list: + item: QLayoutItem = wrapper.item + position: Position = wrapper.position + + if position == Position.North: + item.setGeometry( + QRect( + rect.x(), north_height, rect.width(), item.sizeHint().height() + ) + ) + + north_height += item.geometry().height() + self.spacing() + + elif position == Position.South: + item.setGeometry( + QRect( + item.geometry().x(), + item.geometry().y(), + rect.width(), + item.sizeHint().height(), + ) + ) + + south_height += item.geometry().height() + self.spacing() + + item.setGeometry( + QRect( + rect.x(), + rect.y() + rect.height() - south_height + self.spacing(), + item.geometry().width(), + item.geometry().height(), + ) + ) + elif position == Position.Center: + center = wrapper + + center_height = rect.height() - north_height - south_height + + for wrapper in self._list: + item: QLayoutItem = wrapper.item + position: Position = wrapper.position + + if position == Position.West: + item.setGeometry( + QRect( + rect.x() + west_width, + north_height, + item.sizeHint().width(), + center_height, + ) + ) + + west_width += item.geometry().width() + self.spacing() + + elif position == Position.East: + item.setGeometry( + QRect( + item.geometry().x(), + item.geometry().y(), + item.sizeHint().width(), + center_height, + ) + ) + + east_width += item.geometry().width() + self.spacing() + + item.setGeometry( + QRect( + rect.x() + rect.width() - east_width + self.spacing(), + north_height, + item.geometry().width(), + item.geometry().height(), + ) + ) + + if center: + center.item.setGeometry( + QRect( + west_width, + north_height, + rect.width() - east_width - west_width, + center_height, + ) + ) + + def sizeHint(self) -> QSize: + return self.calculate_size(SizeType.SizeHint) + + def takeAt(self, index: int): + if 0 <= index < len(self._list): + layout_struct: ItemWrapper = self._list.pop(index) + return layout_struct.item + return None + + def add(self, item: QLayoutItem, position: Position): + self._list.append(ItemWrapper(item, position)) + + def calculate_size(self, size_type: SizeType): + total_size = QSize() + + for wrapper in self._list: + position = wrapper.position + + item_size: QSize + if size_type == SizeType.MinimumSize: + item_size = wrapper.item.minimumSize() + else: + item_size = wrapper.item.sizeHint() + + if position in (Position.North, Position.South, Position.Center): + total_size.setHeight(total_size.height() + item_size.height()) + + if position in (Position.West, Position.East, Position.Center): + total_size.setWidth(total_size.width() + item_size.width()) + + return total_size + + +class Window(QWidget): + def __init__(self): + super().__init__() + self.central_widget = QTextBrowser() + self.central_widget.setPlainText("Central widget") + + border_layout = BorderLayout() + border_layout.addWidget(self.central_widget, Position.Center) + + label_north = self.create_label("North") + border_layout.addWidget(label_north, Position.North) + + label_west = self.create_label("West") + border_layout.addWidget(label_west, Position.West) + + label_east1 = self.create_label("East 1") + border_layout.addWidget(label_east1, Position.East) + + label_east2 = self.create_label("East 2") + border_layout.addWidget(label_east2, Position.East) + + label_south = self.create_label("South") + border_layout.addWidget(label_south, Position.South) + + self.setLayout(border_layout) + + self.setWindowTitle("Border Layout") + + @staticmethod + def create_label(text: str): + label = QLabel(text) + label.setFrameStyle(QFrame.Box | QFrame.Raised) + return label + + +if __name__ == "__main__": + app = QApplication(sys.argv) + window = Window() + window.show() + sys.exit(app.exec()) |