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