1
0
Fork 0
mirror of synced 2024-06-02 18:54:41 +12:00
Rare/rare/widgets/flow_layout.py

155 lines
4.8 KiB
Python
Raw Permalink Normal View History

from typing import Optional, List, overload
from PyQt5.QtCore import Qt, QRect, QSize, QPoint
from PyQt5.QtWidgets import QLayout, QStyle, QSizePolicy, QLayoutItem, QWidget
2022-06-22 11:38:04 +12:00
class FlowLayout(QLayout):
def __init__(self, parent=None):
2022-06-22 11:38:04 +12:00
super(FlowLayout, self).__init__(parent)
self.setObjectName(type(self).__name__)
self._hspacing = -1
self._vspacing = -1
self._items: List[QLayoutItem] = []
2022-06-22 11:38:04 +12:00
def __del__(self):
del self._items[:]
@overload
def indexOf(self, a0: QWidget) -> int:
try:
return next(idx for idx, item in enumerate(self._items) if item.widget() is a0)
except:
return -1
def indexOf(self, a0: QLayoutItem) -> int:
try:
return self._items.index(a0)
except:
return -1
def addItem(self, a0: QLayoutItem) -> None:
self._items.append(a0)
self.invalidate()
def removeItem(self, a0: QLayoutItem) -> None:
self._items.remove(a0)
self.invalidate()
def spacing(self) -> int:
hspacing = self.horizontalSpacing()
if hspacing == self.verticalSpacing():
return hspacing
else:
return -1
def setSpacing(self, a0: int) -> None:
self._hspacing = self._vspacing = a0
self.invalidate()
def setHorizontalSpacing(self, a0: int) -> None:
self._hspacing = a0
self.invalidate()
2022-06-22 11:38:04 +12:00
def horizontalSpacing(self):
if self._hspacing >= 0:
return self._hspacing
else:
return self.smartSpacing(QStyle.PM_LayoutHorizontalSpacing)
def setVerticalSpacing(self, a0: int) -> None:
self._vspacing = a0
self.invalidate()
2022-06-22 11:38:04 +12:00
def verticalSpacing(self):
if self._vspacing >= 0:
return self._vspacing
else:
return self.smartSpacing(QStyle.PM_LayoutVerticalSpacing)
def count(self) -> int:
2022-06-22 11:38:04 +12:00
return len(self._items)
def itemAt(self, index: int) -> Optional[QLayoutItem]:
2022-06-22 11:38:04 +12:00
if 0 <= index < len(self._items):
return self._items[index]
return None
2022-06-22 11:38:04 +12:00
def takeAt(self, index: int) -> Optional[QLayoutItem]:
2022-06-22 11:38:04 +12:00
if 0 <= index < len(self._items):
item = self._items.pop(index)
self.invalidate()
return item
return None
2022-06-22 11:38:04 +12:00
def expandingDirections(self) -> Qt.Orientations:
return Qt.Orientations(Qt.Orientation(0))
# return Qt.Horizontal | Qt.Vertical
2022-06-22 11:38:04 +12:00
def hasHeightForWidth(self) -> bool:
2022-06-22 11:38:04 +12:00
return True
def heightForWidth(self, a0: int) -> int:
return self.doLayout(QRect(0, 0, a0, 0), True)
2022-06-22 11:38:04 +12:00
def setGeometry(self, a0: QRect) -> None:
super(FlowLayout, self).setGeometry(a0)
self.doLayout(a0, False)
2022-06-22 11:38:04 +12:00
def sizeHint(self) -> QSize:
return QSize(
self.parent().contentsRect().size().width(),
self.minimumSize().height()
)
2022-06-22 11:38:04 +12:00
def minimumSize(self) -> QSize:
2022-06-22 11:38:04 +12:00
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
if not self._items:
return y + lineheight - rect.y() + bottom
2022-06-22 11:38:04 +12:00
for item in self._items:
if item.isEmpty():
continue
2022-06-22 11:38:04 +12:00
widget = item.widget()
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()