Source code for orangecanvas.gui.toolbar

"""
A custom toolbar with linear uniform size layout.

"""
from typing import List

from AnyQt.QtCore import Qt, QSize, QEvent, QRect
from AnyQt.QtGui import QResizeEvent, QActionEvent
from AnyQt.QtWidgets import QToolBar, QWidget


[docs]class DynamicResizeToolBar(QToolBar): """ A :class:`QToolBar` subclass that dynamically resizes its tool buttons to fit available space (this is done by setting fixed size on the button instances). .. note:: the class does not support `QWidgetAction`, separators, etc. """
[docs] def resizeEvent(self, event): # type: (QResizeEvent) -> None super().resizeEvent(event) size = event.size() self.__layout(size)
[docs] def actionEvent(self, event): # type: (QActionEvent) -> None super().actionEvent(event) if event.type() == QEvent.ActionAdded or \ event.type() == QEvent.ActionRemoved: self.__layout(self.size())
[docs] def sizeHint(self): # type: () -> QSize hint = super().sizeHint() width, height = hint.width(), hint.height() m1 = self.contentsMargins() m2 = self.layout().contentsMargins() dx1, dy1, dw1, dh1 = m1.left(), m1.top(), m1.right(), m1.bottom() dx2, dy2, dw2, dh2 = m2.left(), m2.top(), m2.right(), m2.bottom() dx, dy = dx1 + dx2, dy1 + dy2 dw, dh = dw1 + dw2, dh1 + dh2 count = len(self.actions()) spacing = self.layout().spacing() space_spacing = max(count - 1, 0) * spacing if self.orientation() == Qt.Horizontal: width = int(height * 1.618) * count + space_spacing + dw + dx else: height = int(width * 1.618) * count + space_spacing + dh + dy return QSize(width, height)
def __layout(self, size): # type: (QSize) -> None """Layout the buttons to fit inside size. """ mygeom = self.geometry() mygeom.setSize(size) # Adjust for margins (both the widgets and the layouts). mygeom = mygeom.marginsRemoved(self.contentsMargins()) mygeom = mygeom.marginsRemoved(self.layout().contentsMargins()) actions = self.actions() widgets_it = map(self.widgetForAction, actions) orientation = self.orientation() if orientation == Qt.Horizontal: widgets = sorted(widgets_it, key=lambda w: w.pos().x()) else: widgets = sorted(widgets_it, key=lambda w: w.pos().y()) spacing = self.layout().spacing() uniform_layout_helper(widgets, mygeom, orientation, spacing=spacing)
def uniform_layout_helper(items, contents_rect, expanding, spacing): # type: (List[QWidget], QRect, Qt.Orientation, int) -> None """Set fixed sizes on 'items' so they can be lay out in contents rect anf fil the whole space. """ if len(items) == 0: return spacing_space = (len(items) - 1) * spacing if expanding == Qt.Horizontal: def setter(w, s): # type: (QWidget, int) -> None w.setFixedWidth(max(s, 0)) space = contents_rect.width() - spacing_space else: def setter(w, s): # type: (QWidget, int) -> None w.setFixedHeight(max(s, 0)) space = contents_rect.height() - spacing_space base_size = space // len(items) remainder = space % len(items) for i, item in enumerate(items): item_size = base_size + (1 if i < remainder else 0) setter(item, item_size)