source: orange/Orange/OrangeCanvas/gui/toolbar.py @ 11179:f7ee1338a997

Revision 11179:f7ee1338a997, 3.2 KB checked in by Ales Erjavec <ales.erjavec@…>, 18 months ago (diff)

More code cleanup.

Line 
1"""
2A custom toolbar.
3
4"""
5from __future__ import division
6
7import logging
8
9from PyQt4.QtGui import QToolBar
10
11from PyQt4.QtCore import Qt, QSize, QEvent
12
13log = logging.getLogger(__name__)
14
15
16class DynamicResizeToolBar(QToolBar):
17    """A QToolBar subclass that dynamically resizes its tool buttons
18    to fit available space (this is done by setting fixed size on the
19    button instances).
20
21    .. note:: the class does not support `QWidgetAction`s, separators, etc.
22
23    """
24
25    def __init__(self, parent=None, *args, **kwargs):
26        QToolBar.__init__(self, *args, **kwargs)
27
28    def resizeEvent(self, event):
29        QToolBar.resizeEvent(self, event)
30        size = event.size()
31        self.__layout(size)
32
33    def actionEvent(self, event):
34        QToolBar.actionEvent(self, event)
35        if event.type() == QEvent.ActionAdded or \
36                event.type() == QEvent.ActionRemoved:
37            self.__layout(self.size())
38
39    def sizeHint(self):
40        hint = QToolBar.sizeHint(self)
41        width, height = hint.width(), hint.height()
42        dx1, dy1, dw1, dh1 = self.getContentsMargins()
43        dx2, dy2, dw2, dh2 = self.layout().getContentsMargins()
44        dx, dy = dx1 + dx2, dy1 + dy2
45        dw, dh = dw1 + dw2, dh1 + dh2
46
47        count = len(self.actions())
48        spacing = self.layout().spacing()
49        space_spacing = max(count - 1, 0) * spacing
50
51        if self.orientation() == Qt.Horizontal:
52            width = int(height * 1.618) * count + space_spacing + dw + dx
53        else:
54            height = int(width * 1.618) * count + space_spacing + dh + dy
55        return QSize(width, height)
56
57    def __layout(self, size):
58        """Layout the buttons to fit inside size.
59        """
60        mygeom = self.geometry()
61        mygeom.setSize(size)
62
63        # Adjust for margins (both the widgets and the layouts.
64        dx, dy, dw, dh = self.getContentsMargins()
65        mygeom.adjust(dx, dy, -dw, -dh)
66
67        dx, dy, dw, dh = self.layout().getContentsMargins()
68        mygeom.adjust(dx, dy, -dw, -dh)
69
70        actions = self.actions()
71        widgets = map(self.widgetForAction, actions)
72
73        orientation = self.orientation()
74        if orientation == Qt.Horizontal:
75            widgets = sorted(widgets, key=lambda w: w.pos().x())
76        else:
77            widgets = sorted(widgets, key=lambda w: w.pos().y())
78
79        spacing = self.layout().spacing()
80        uniform_layout_helper(widgets, mygeom, orientation,
81                              spacing=spacing)
82
83
84def uniform_layout_helper(items, contents_rect, expanding, spacing):
85    """Set fixed sizes on 'items' so they can be lay out in
86    contents rect anf fil the whole space.
87
88    """
89    if len(items) == 0:
90        return
91
92    spacing_space = (len(items) - 1) * spacing
93
94    if expanding == Qt.Horizontal:
95        space = contents_rect.width() - spacing_space
96        setter = lambda w, s: w.setFixedWidth(max(s, 0))
97    else:
98        space = contents_rect.height() - spacing_space
99        setter = lambda w, s: w.setFixedHeight(max(s, 0))
100
101    base_size = space / len(items)
102    remainder = space % len(items)
103
104    for i, item in enumerate(items):
105        item_size = base_size + (1 if i < remainder else 0)
106        setter(item, item_size)
Note: See TracBrowser for help on using the repository browser.