Source code for msl.qt.widgets.button
"""
A :class:`~QtWidgets.QToolButton` to display text, an icon and a menu.
"""
from .. import Qt
from .. import QtCore
from .. import QtGui
from .. import QtWidgets
from .. import convert
[docs]class Button(QtWidgets.QToolButton):
def __init__(self, *, text=None, icon=None, icon_size=None, left_click=None,
right_click=None, is_text_under_icon=True, tooltip=None, parent=None):
"""A :class:`~QtWidgets.QToolButton` to display text, an icon and a menu.
Parameters
----------
text : :class:`str`, optional
The text to display on the button.
icon : :class:`object`, optional
Any icon object that is supported by :func:`~.convert.to_qicon`.
icon_size : :class:`int`, :class:`float`, :class:`tuple` of :class:`int` or :class:`QtCore.QSize`, optional
Rescale the icon to the specified `size`.
If the value is :data:`None` then do not rescale the icon.
If an :class:`int` then set the width and the height to be the `size` value.
If a :class:`float` then a scaling factor.
If a :class:`tuple` then the (width, height) values.
left_click : :obj:`callable`, optional
The function to be called for a mouse left-click event.
right_click : :obj:`callable`, optional
The function to be called for a mouse right-click event.
is_text_under_icon : :class:`bool`, optional
If displaying an icon and text then whether to place the text
under, :data:`True`, or beside, :data:`False`, the icon.
tooltip : :class:`str`, optional
The tooltip to display for the button.
parent : :class:`QtWidgets.QWidget`, optional
The parent widget.
"""
super(Button, self).__init__(parent=parent)
self._menu = None
if text and icon:
if is_text_under_icon:
self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextUnderIcon)
else:
self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
self.setText(text)
self._set_icon(icon, icon_size)
elif text and not icon:
self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextOnly)
self.setText(text)
elif not text and icon:
self.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
self._set_icon(icon, icon_size)
# the left-click event handler
if left_click is not None:
self.set_left_click(left_click)
# setContextMenuPolicy allows for right-click events
self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
if right_click is not None:
self.set_right_click(right_click)
if tooltip is not None:
self.setToolTip(tooltip)
self.setSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred,
QtWidgets.QSizePolicy.Policy.Fixed)
[docs] def set_left_click(self, fcn):
"""The function to be called for a mouse left-click event.
Parameters
----------
fcn : :obj:`callable`
The function to be called for a mouse left-click event.
"""
self.clicked.connect(fcn) # noqa: QToolButton.clicked
[docs] def set_right_click(self, fcn):
"""The function to be called for a mouse right-click event.
Parameters
----------
fcn : :obj:`callable`
The function to be called for a mouse right-click event.
"""
self.customContextMenuRequested.connect(fcn) # noqa: QToolButton.customContextMenuRequested
def _create_menu(self):
self._menu = ButtonMenu(self)
self._menu.setToolTipsVisible(True)
self.setMenu(self._menu)
self.setPopupMode(QtWidgets.QToolButton.ToolButtonPopupMode.MenuButtonPopup)
def _set_icon(self, icon, icon_size):
icon = convert.to_qicon(icon) # make sure that it's a QIcon
if icon_size is not None:
pixmap = convert.rescale_icon(icon, icon_size)
self.setIconSize(pixmap.size())
icon = convert.to_qicon(pixmap)
elif icon.availableSizes():
style = self.style()
metric = style.pixelMetric(style.PixelMetric.PM_ButtonIconSize)
s = icon.availableSizes()[0]
size = QtCore.QSize(max(s.width(), metric), max(s.height(), metric))
if self.iconSize().width() < size.width() or \
self.iconSize().height() < size.height():
self.setIconSize(size)
self.setIcon(icon)
[docs]class ButtonMenu(QtWidgets.QMenu):
"""Display the :class:`QtWidgets.QMenu` underneath the :class:`Button`."""
[docs] def showEvent(self, event):
"""Overrides :meth:`QtWidgets.QWidget.showEvent`."""
point = self.parent().mapToGlobal(QtCore.QPoint(0, 0))
offset = self.parent().width() - self.width()
self.move(point + QtCore.QPoint(offset, self.parent().height()))
super(ButtonMenu, self).showEvent(event)