self._restore_cursor()
# adapted from Qt flow layout C++ example
+# stripped down and optimized for speed in our special use case
class zFlowLayout(QLayout):
- def __init__(self, parent: QWidget=None, margin: int=-1, hSpacing: int=-1, vSpacing: int=-1):
+ def __init__(self, parent=None):
super().__init__(parent)
self.itemList = list()
- self.m_hSpace = hSpacing
- self.m_vSpace = vSpacing
- self.setContentsMargins(margin, margin, margin, margin)
def addItem(self, item):
self.itemList.append(item)
except:
return None
- def horizontalSpacing(self):
- if self.m_hSpace >= 0:
- return self.m_hSpace
- else:
- return self.smartSpacing(QStyle.PM_LayoutHorizontalSpacing)
-
- def verticalSpacing(self):
- if self.m_vSpace >= 0:
- return self.m_vSpace
- else:
- return self.smartSpacing(QStyle.PM_LayoutVerticalSpacing)
-
- def smartSpacing(self, pm):
- parent = self.parent()
- if not parent:
- return -1
- elif parent.isWidgetType():
- return parent.style().pixelMetric(pm, None, parent)
- else:
- return parent.spacing()
-
- def expandingDirections(self):
- return Qt.Orientations(Qt.Orientation(0))
-
def hasHeightForWidth(self):
return True
return height
def setGeometry(self, rect):
- 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, testOnly):
- left, top, right, bottom = self.getContentsMargins()
- effectiveRect = rect.adjusted(+left, +top, -right, -bottom)
- x = effectiveRect.x()
- y = effectiveRect.y()
- lineHeight = 0
- for item in self.itemList:
- wid = item.widget()
- spaceX = self.horizontalSpacing()
- if spaceX == -1:
- spaceX = wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Horizontal)
- spaceY = self.verticalSpacing()
- if spaceY == -1:
- spaceY = wid.style().layoutSpacing(QSizePolicy.PushButton, QSizePolicy.PushButton, Qt.Vertical)
- 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()))
+ return QSize()
+
+ def doLayout(self, rect, testonly):
+ if not self.count():
+ return 0
+ x = rect.x()
+ y = rect.y()
+ right = rect.right() + 1
+ iszhint = self.itemList[0].widget().sizeHint()
+ iwidth = iszhint.width()
+ iheight = iszhint.height()
+ ngaps = int(right / iwidth)
+ gap = 0 if ngaps < 1 else int((right % iwidth) / ngaps)
+ for i in range(self.count()):
+ nextX = x + iwidth
+ if nextX > right:
+ x = rect.x()
+ y = y + iheight
+ nextX = x + iwidth + gap
+ else:
+ nextX += gap
+ if not testonly:
+ self.itemList[i].setGeometry(QRect(QPoint(x, y), iszhint))
x = nextX
- lineHeight = max(lineHeight, item.sizeHint().height())
- return y + lineHeight - rect.y() + bottom
+ return y + iheight - rect.y()
class zFlowScrollArea(QScrollArea):
self.clear()
pane = QWidget()
self.setWidget(pane)
- layout = zFlowLayout(pane, 0, 0, 0)
+ layout = zFlowLayout(pane)
layout.setEnabled(False)
for tl in tiles:
layout.addWidget(tl)
else:
pane = QWidget()
self.setWidget(pane)
- layout = zFlowLayout(pane, 0, 0, 0)
+ layout = zFlowLayout(pane)
for idx in range(layout.count()):
if layout.itemAt(idx).widget().text() == w.text():
layout.takeAt(idx)