1
0
Fork 0
mirror of synced 2024-07-01 04:30:20 +12:00
Rare/rare/widgets/flow_layout.py

121 lines
3.7 KiB
Python

from typing import Optional
from PyQt5.QtCore import (
Qt,
QRect,
QSize,
QPoint,
)
from PyQt5.QtWidgets import (
QLayout,
QStyle,
QSizePolicy,
QLayoutItem,
)
class FlowLayout(QLayout):
def __init__(self, parent=None, margin=-1, hspacing=-1, vspacing=-1):
super(FlowLayout, self).__init__(parent)
self._hspacing = hspacing
self._vspacing = vspacing
self._items = []
self.setContentsMargins(margin, margin, margin, margin)
self.setObjectName(type(self).__name__)
def __del__(self):
del self._items[:]
def addItem(self, a0: QLayoutItem) -> None:
self._items.append(a0)
def horizontalSpacing(self):
if self._hspacing >= 0:
return self._hspacing
else:
return self.smartSpacing(QStyle.PM_LayoutHorizontalSpacing)
def verticalSpacing(self):
if self._vspacing >= 0:
return self._vspacing
else:
return self.smartSpacing(QStyle.PM_LayoutVerticalSpacing)
def count(self) -> int:
return len(self._items)
def itemAt(self, index: int) -> Optional[QLayoutItem]:
if 0 <= index < len(self._items):
return self._items[index]
return None
def takeAt(self, index: int) -> Optional[QLayoutItem]:
if 0 <= index < len(self._items):
return self._items.pop(index)
return None
def expandingDirections(self) -> Qt.Orientations:
return Qt.Orientations(Qt.Orientation(0))
def hasHeightForWidth(self) -> bool:
return True
def heightForWidth(self, a0: int) -> int:
return self.doLayout(QRect(0, 0, a0, 0), True)
def setGeometry(self, a0: QRect) -> None:
super(FlowLayout, self).setGeometry(a0)
self.doLayout(a0, False)
def sizeHint(self) -> QSize:
return self.minimumSize()
def minimumSize(self) -> QSize:
size = QSize()
for item in self._items:
size = size.expandedTo(item.minimumSize())
left, top, right, bottom = self.getContentsMargins()
size += QSize(left + right, top + bottom)
return size
def doLayout(self, rect, testonly):
left, top, right, bottom = self.getContentsMargins()
effective = rect.adjusted(+left, +top, -right, -bottom)
x = effective.x()
y = effective.y()
lineheight = 0
for item in self._items:
widget = item.widget()
if not widget.isVisible():
continue
hspace = self.horizontalSpacing()
if hspace == -1:
hspace = widget.style().layoutSpacing(
QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal
)
vspace = self.verticalSpacing()
if vspace == -1:
vspace = widget.style().layoutSpacing(
QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical
)
nextX = x + item.sizeHint().width() + hspace
if nextX - hspace > effective.right() and lineheight > 0:
x = effective.x()
y = y + lineheight + vspace
nextX = x + item.sizeHint().width() + hspace
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):
parent = self.parent()
if parent is None:
return -1
elif parent.isWidgetType():
return parent.style().pixelMetric(pm, None, parent)
else:
return parent.spacing()