""" Flow layout to allow widgets to be moved based around the size of the layout This should be fun to doc and write demos, I'll do it later """ __DoNotReload__ = True # Module is NOT safe to be dynamciy reloaded from PySide import QtGui, QtCore class FlowLayout(QtGui.QLayout): def __init__(self, parent=None, margin=-1, hSpacing=-1, vSpacing=-1): super(FlowLayout, self).__init__() self.setContentsMargins(margin, margin, margin, margin) if parent is not None: self.setMargin(margin) self._itemList = [] self._hSpace = hSpacing self._mSpace = vSpacing def addItem(self, item): self._itemList.append(item) def horizontalSpacing(self): if self._hSpace >= 0: return self._hSpace return self.smartSpacing(QtGui.QStyle.PM_LayoutHorizontalSpacing) def verticalSpacing(self): if self.vSpace >= 0: return self.vSpace return self.smartSpacing(QtGui.QStyle.PM_LayoutVerticalSpacing) def count(self): return len(self._itemList) def itemAt(self, index): if index >= 0 and index < len(self._itemList): return self._itemList[index] return None def takeAt(self, index): if index >= 0 and index < len(self._itemList): return self._itemList.pop(index) return 0 def expandingDirections(self): return 0 def hasHeightForWidth(self): return True def heightForWidth(self, width): return self.doLayout(QtCore.QRect(0, 0, width, 0), True) def setGeometry(self, rect): super(FlowLayout, self).setGeometry(rect) self.doLayout(rect, False) def sizeHint(self): return self.minimumSize() def minimumSize(self): size = QtCore.QSize() for item in self._itemList: size = size.expandedTo(item.minimumSize()) size += QtCore.QSize(2*self.spacing(), 2*self.spacing()) return size def doLayout(self, rect, testOnly=False): 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(QtGui.QSizePolicy.ButtonBox, QtGui.QSizePolicy.PushButton, QtCore.Qt.Horizontal) spaceY = self.horizontalSpacing() if (spaceY == -1): spaceY = wid.style().layoutSpacing(QtGui.QSizePolicy.ButtonBox, QtGui.QSizePolicy.PushButton, QtCore.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(QtCore.QRect(QtCore.QPoint(x, y), item.sizeHint())) x = nextX lineHeight = max([lineHeight, item.sizeHint().height()]) return y + lineHeight - rect.y() + bottom def smartSpacing(self, pixelMetric): parent = self.parent() if not parent: return -1 elif isinstance(parent, QtGui.QWidget): return parent.style().pixelMetric(pixelMetric) else: return parent.spacing()