summaryrefslogtreecommitdiff
path: root/src/main/python/utils/layout.py
blob: e1354b0075d76d70231a63ad8420949299aca5dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from PyQt5.QtCore import Qt, QRect, QPoint, QSize
from PyQt5.QtWidgets import QLayout, QSizePolicy

class flowLayout(QLayout):
    """
    Custom layout that flows horizontally first, then vertically.
    From Qt examples.
    """
    def __init__(self, parent=None, margin=0, spacing=12):
        super(flowLayout, self).__init__(parent)

        if parent is not None:
            self.setContentsMargins(margin, margin, margin, margin)

        self.setSpacing(spacing)
        self.itemList = []

    def __del__(self):
        # Delete layout call
        item = self.takeAt(0)
        while item:
            item = self.takeAt(0)

    def addItem(self, item):
        # add item to layout
        self.itemList.append(item)

    def count(self):
        # return a list of items
        return len(self.itemList)

    def itemAt(self, index):
        # return item at index
        if index >= 0 and index < len(self.itemList):
            return self.itemList[index]

        return None

    def takeAt(self, index):
        # pop item at index
        if index >= 0 and index < len(self.itemList):
            return self.itemList.pop(index)

        return None

    def expandingDirections(self):
        # define orientation
        return Qt.Orientations(Qt.Orientation(0))

    def hasHeightForWidth(self):
        # height for width flag, height value for a particular width
        return True

    def heightForWidth(self, width):
        # returns the height for a given width
        height = self.doLayout(QRect(0, 0, width, 0), True)
        return height

    def setGeometry(self, rect):
        # change layout geometry
        super(flowLayout, self).setGeometry(rect)
        self.doLayout(rect, False)
        
    def sizeHint(self):
        # returns the expected size
        return self.minimumSize()

    def minimumSize(self):
        # calucalate minimum possible size below which, resize is impossible
        size = QSize()

        for item in self.itemList:
            size = size.expandedTo(item.minimumSize())

        margin, _, _, _ = self.getContentsMargins()

        size += QSize(2 * margin, 2 * margin)
        return size

    def doLayout(self, rect, testOnly):
        # build layout, testOnly defines if the geometry needs to be changed or not
        x = rect.x()
        y = rect.y()
        lineHeight = 0

        for item in self.itemList:
            wid = item.widget()
            spaceX = self.spacing() + wid.style().layoutSpacing(QSizePolicy.ToolButton, QSizePolicy.ToolButton, Qt.Horizontal)
            spaceY = self.spacing() + wid.style().layoutSpacing(QSizePolicy.ToolButton, QSizePolicy.ToolButton, 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(QRect(QPoint(x, y), item.sizeHint()))

            x = nextX
            lineHeight = max(lineHeight, item.sizeHint().height())

        return y + lineHeight - rect.y()