mirror of
https://github.com/283375/arcaea-offline-pyside-ui.git
synced 2025-04-22 02:30:18 +00:00
127 lines
4.0 KiB
Python
127 lines
4.0 KiB
Python
# Adapted from https://doc.qt.io/qt-6/qtwidgets-layouts-flowlayout-example.html
|
|
|
|
from PySide6.QtCore import QPoint, QRect, QSize, Qt
|
|
from PySide6.QtWidgets import QLayout, QLayoutItem, QSizePolicy, QStyle, QWidget
|
|
|
|
|
|
class FlowLayout(QLayout):
|
|
def __init__(self, parent=None, margin=0, hSpacing=0, vSpacing=0):
|
|
super().__init__(parent)
|
|
self.hSpace = hSpacing
|
|
self.vSpace = vSpacing
|
|
self.setContentsMargins(margin, margin, margin, margin)
|
|
self.itemList: list[QLayoutItem] = []
|
|
|
|
def __del__(self):
|
|
item = self.takeAt(0)
|
|
while item:
|
|
del item
|
|
item = self.takeAt(0)
|
|
|
|
def addItem(self, item: QLayoutItem):
|
|
self.itemList.append(item)
|
|
|
|
def horizontalSpacing(self):
|
|
return (
|
|
self.hSpace
|
|
if self.hSpace >= 0
|
|
else self.smartSpacing(QStyle.PixelMetric.PM_LayoutHorizontalSpacing)
|
|
)
|
|
|
|
def verticalSpacing(self):
|
|
return (
|
|
self.vSpace
|
|
if self.vSpace >= 0
|
|
else self.smartSpacing(QStyle.PixelMetric.PM_LayoutVerticalSpacing)
|
|
)
|
|
|
|
def count(self):
|
|
return len(self.itemList)
|
|
|
|
def itemAt(self, index: int):
|
|
return self.itemList[index] if 0 <= index < len(self.itemList) else None
|
|
|
|
def takeAt(self, index):
|
|
return self.itemList.pop(index) if 0 <= index < len(self.itemList) else None
|
|
|
|
# Qt::Orientations FlowLayout::expandingDirections() const
|
|
# {
|
|
# return { };
|
|
# }
|
|
def expandingDirections(self):
|
|
return Qt.Orientations(0)
|
|
|
|
def hasHeightForWidth(self):
|
|
return True
|
|
|
|
def heightForWidth(self, width: int):
|
|
return self.doLayout(QRect(0, 0, width, 0), True)
|
|
|
|
def setGeometry(self, rect: QRect):
|
|
super().setGeometry(rect)
|
|
self.doLayout(rect, False)
|
|
|
|
def sizeHint(self):
|
|
return self.minimumSize()
|
|
|
|
def minimumSize(self):
|
|
size = QSize()
|
|
for item in self.itemList:
|
|
size = size.expandedTo(item.minimumSize())
|
|
|
|
margins = self.contentsMargins()
|
|
size += QSize(
|
|
margins.left() + margins.right(), margins.top() + margins.bottom()
|
|
)
|
|
return size
|
|
|
|
def doLayout(self, rect: QRect, testOnly: bool):
|
|
margins = self.contentsMargins()
|
|
left = margins.left()
|
|
top = margins.top()
|
|
right = margins.right()
|
|
bottom = margins.bottom()
|
|
effectiveRect = rect.adjusted(+left, +top, -right, -bottom)
|
|
x = effectiveRect.x()
|
|
y = effectiveRect.y()
|
|
lineHeight = 0
|
|
for item in self.itemList:
|
|
widget = item.widget()
|
|
spaceX = self.horizontalSpacing()
|
|
if spaceX == -1:
|
|
spaceX = widget.style().layoutSpacing(
|
|
QSizePolicy.ControlType.PushButton,
|
|
QSizePolicy.ControlType.PushButton,
|
|
)
|
|
spaceY = self.verticalSpacing()
|
|
if spaceY == -1:
|
|
spaceY = widget.style().layoutSpacing(
|
|
QSizePolicy.ControlType.PushButton,
|
|
QSizePolicy.ControlType.PushButton,
|
|
)
|
|
|
|
nextX = x + item.sizeHint().width() + spaceX
|
|
if nextX - spaceX > effectiveRect.right() and lineHeight > 0:
|
|
x = effectiveRect.x()
|
|
y = y + lineHeight + spaceY
|
|
nextX = x + item.sizeHint().width() + spaceX
|
|
lineHeight = 0
|
|
|
|
if not testOnly:
|
|
item.setGeometry(QRect(QPoint(x, y), item.sizeHint()))
|
|
|
|
x = nextX
|
|
lineHeight = max(lineHeight, item.sizeHint().height())
|
|
return y + lineHeight - rect.y() + bottom
|
|
|
|
def smartSpacing(self, pm: QStyle.PixelMetric):
|
|
parent = self.parent()
|
|
if not parent:
|
|
return -1
|
|
elif parent.isWidgetType():
|
|
parent: QWidget
|
|
return parent.style().pixelMetric(pm, None, parent)
|
|
else:
|
|
parent: QLayout
|
|
return parent.spacing()
|