Source code for edifice.base_components.button_view

from __future__ import annotations

import typing as tp

from edifice.qt import QT_VERSION

if QT_VERSION == "PyQt6" and not tp.TYPE_CHECKING:
    from PyQt6.QtCore import QSize, Qt
    from PyQt6.QtGui import QKeyEvent, QMouseEvent
    from PyQt6.QtWidgets import QHBoxLayout, QPushButton
else:
    from PySide6.QtCore import QSize, Qt
    from PySide6.QtGui import QKeyEvent, QMouseEvent
    from PySide6.QtWidgets import QHBoxLayout, QPushButton

from .base_components import CommandType, Element, HBoxView, _WidgetTree


class _PushButton(QPushButton):
    def __init__(self):
        super().__init__()

    # https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QLayout.html#detailed-description
    def sizeHint(self) -> QSize:
        return self.layout().sizeHint()

    def hasHeightForWidth(self) -> bool:
        return self.layout().hasHeightForWidth()

    def heightForWidth(self, width: int) -> int:
        return self.layout().heightForWidth(width)

    def minimumSizeHint(self) -> QSize:
        return self.layout().totalMinimumSize()


[docs] class ButtonView(HBoxView): """ A Button where the label is the Button’s children rendered in a :class:`edifice.HBoxView`. * Underlying Qt Widget `QPushButton <https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QPushButton.html>`_ Example:: with ButtonView( on_click=handle_click, ): Icon(name="share") Label(text="<i>Share the Content</i>") .. figure:: /image/button_view.png Args: on_trigger: Event fires when the button is triggered by mouse or the Spacebar or Enter key. Event type is either :code:`QMouseEvent` or :code:`QKeyEvent`. Use either this or :code:`on_click`, not both. """
[docs] def __init__( self, on_trigger: tp.Callable[[QKeyEvent], None] | tp.Callable[[QMouseEvent], None] | None = None, **kwargs, ): super().__init__(**kwargs) self._register_props( { "on_trigger": on_trigger, }, )
def _initialize(self): self.underlying = _PushButton() self.underlying_layout = QHBoxLayout() self.underlying.setObjectName(str(id(self))) self.underlying.setLayout(self.underlying_layout) self.underlying_layout.setContentsMargins(0, 0, 0, 0) self.underlying_layout.setSpacing(0) def _add_child(self, i, child_component): super()._add_child(i, child_component) # All children must be transparent to mouse events child_component.setAttribute(Qt.WidgetAttribute.WA_TransparentForMouseEvents) def _set_on_trigger(self, underlying, on_trigger): if on_trigger is not None: def on_click(ev: QMouseEvent): on_trigger(ev) def on_key(ev: QKeyEvent): if ev.key() == Qt.Key.Key_Enter or ev.key() == Qt.Key.Key_Return or ev.key() == Qt.Key.Key_Space: on_trigger(ev) else: ev.ignore() self._set_on_click(underlying, on_click) self._set_on_key_up(underlying, on_key) def _qt_update_commands( self, widget_trees: dict[Element, _WidgetTree], newprops, ): if self.underlying is None: self._initialize() assert self.underlying is not None commands = super()._qt_update_commands(widget_trees, newprops) for prop in newprops: if prop == "on_trigger": commands.append(CommandType(self._set_on_trigger, self.underlying, newprops.on_trigger)) commands.append(CommandType(self.underlying.setCursor, Qt.CursorShape.PointingHandCursor)) return commands