source: orange/Orange/OrangeCanvas/gui/toolbar.py @ 11366:7f9332b11252

Revision 11366:7f9332b11252, 3.2 KB checked in by Ales Erjavec <ales.erjavec@…>, 14 months ago (diff)

Added rst documentation for the canvas gui package.

Fixing docstrings in the process.

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