Source code for camelot.view.flowlayout

#  ============================================================================
#
#  Copyright (C) 2007-2013 Conceptive Engineering bvba. All rights reserved.
#  www.conceptive.be / info@conceptive.be
#
#  This file is part of the Camelot Library.
#
#  This file may be used under the terms of the GNU General Public
#  License version 2.0 as published by the Free Software Foundation
#  and appearing in the file license.txt included in the packaging of
#  this file.  Please review this information to ensure GNU
#  General Public Licensing requirements will be met.
#
#  If you are unsure which license is appropriate for your use, please
#  visit www.python-camelot.com or contact info@conceptive.be
#
#  This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
#  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
#  For use of this library in commercial applications, please contact
#  info@conceptive.be
#
#  ============================================================================
"""
PyQt4 port of the layouts/flowlayout example from Qt v4.x

The original port was copied from the PyQt layout examples.
"""

from PyQt4 import QtCore, QtGui

[docs]class FlowLayout( QtGui.QLayout ): """ Layout that arranges child widgets from left to right and top to bottom. @todo : this layout returns a height for width that is too high, it seems as if it takes into account that it should be able to expand """ def __init__( self, parent = None ): """ :param parent: a `QtGui.QWidget` """ super(FlowLayout, self).__init__(parent) if parent is not None: self.setContentsMargins( 0, 0, 0, 0 ) self.setSpacing( -1 ) self.item_list = [] def addItem( self, item ): self.item_list.append( item ) def count(self): return len(self.item_list) def itemAt( self, index ): if index >= 0 and index < len(self.item_list): return self.item_list[index] return None def takeAt( self, index ): if index >= 0 and index < len(self.item_list): return self.item_list.pop(index) return None def expandingDirections( self ): return QtCore.Qt.Orientations(QtCore.Qt.Orientation(0)) def hasHeightForWidth( self ): return True def heightForWidth( self, width ): height = self.doLayout( QtCore.QRect(0, 0, width, 0), True ) return height 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.item_list: size = size.expandedTo(item.minimumSize()) size += QtCore.QSize(2 * self.margin(), 2 * self.margin()) return size def doLayout( self, rect, testOnly ): x = rect.x() y = rect.y() lineHeight = 0 for item in self.item_list: wid = item.widget() spaceX = self.spacing() + wid.style().layoutSpacing(QtGui.QSizePolicy.PushButton, QtGui.QSizePolicy.PushButton, QtCore.Qt.Horizontal) spaceY = self.spacing() + wid.style().layoutSpacing(QtGui.QSizePolicy.PushButton, QtGui.QSizePolicy.PushButton, QtCore.Qt.Vertical) nextX = x + item.sizeHint().width() + spaceX if nextX - spaceX > rect.right() and lineHeight > 0: x = rect.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()