Source code for edifice.base_components.scroll_bar
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 import QtWidgets
from PyQt6.QtCore import Qt
else:
from PySide6 import QtWidgets
from PySide6.QtCore import Qt
from collections.abc import Callable # noqa: TC003
import edifice as ed
from edifice.engine import CommandType, PropsDiff, _WidgetTree
[docs]
class ScrollBar(ed.QtWidgetElement[QtWidgets.QScrollBar]):
"""
Scroll bar widget.
Render a scroll bar widget that allows the user to scroll through a range of values.
.. highlights::
- Underlying Qt Widget:
`QScrollBar <https://doc.qt.io/qtforpython-6/PySide6/QtWidgets/QScrollBar.html>`_
.. rubric:: Props
All **props** from :class:`QtWidgetElement` plus:
Args:
value: The current value of the scroll bar.
minimum: The minimum value of the scroll bar.
maximum: The maximum value of the scroll bar.
step_single: The step size for arrow keys.
step_page: The step size for PgUp/PgDown keys.
orientation: The scroll bar `Orientation <https://doc.qt.io/qtforpython-6/PySide6/QtCore/Qt.html#Qt.Orientation>`_.
on_value_changed: Callback for when the value of the scroll bar changes.
on_slider_pressed: Callback for when the slider is pressed.
on_slider_released: Callback for when the slider is released.
"""
[docs]
def __init__(
self,
value: int = 0,
minimum: int = 0,
maximum: int = 100,
step_single: int | None = None,
step_page: int | None = None,
orientation: Qt.Orientation = Qt.Orientation.Vertical,
on_value_changed: Callable[[int], None] | None = None,
on_slider_pressed: Callable[[], None] | None = None,
on_slider_released: Callable[[], None] | None = None,
**kwargs: tp.Any,
) -> None:
super().__init__(**kwargs)
self._register_props(
{
"value": value,
"minimum": minimum,
"maximum": maximum,
"step_single": step_single,
"step_page": step_page,
"orientation": orientation,
"on_value_changed": on_value_changed,
"on_slider_pressed": on_slider_pressed,
"on_slider_released": on_slider_released,
},
)
self._register_props(kwargs)
def _on_value_changed_handler(self, value: int) -> None:
if self.props["on_value_changed"] is not None:
self.props["on_value_changed"](value)
def _on_slider_pressed(self) -> None:
if self.props["on_slider_pressed"] is not None:
self.props["on_slider_pressed"]()
def _on_slider_released(self) -> None:
if self.props["on_slider_released"] is not None:
self.props["on_slider_released"]()
def _initialize(self) -> None:
self.underlying = QtWidgets.QScrollBar()
self.underlying.setObjectName(str(id(self)))
self.underlying.valueChanged.connect(self._on_value_changed_handler)
self.underlying.sliderPressed.connect(self._on_slider_pressed)
self.underlying.sliderReleased.connect(self._on_slider_released)
# TODO It would be nice if the slider state were a pure function
# of props. Right now it has internal value which will change
# independently of the props value.
def _qt_update_commands(
self,
widget_trees: dict[ed.Element, _WidgetTree],
diff_props: PropsDiff,
) -> list[CommandType]:
if self.underlying is None:
self._initialize()
assert self.underlying is not None
commands = super()._qt_update_commands_super(widget_trees, diff_props, self.underlying)
match diff_props.get("value"):
case _, propnew:
commands.append(CommandType(self.underlying.setValue, propnew))
match diff_props.get("minimum"):
case _, propnew:
commands.append(CommandType(self.underlying.setMinimum, propnew))
match diff_props.get("maximum"):
case _, propnew:
commands.append(CommandType(self.underlying.setMaximum, propnew))
match diff_props.get("step_single"):
case _, propnew:
commands.append(CommandType(self.underlying.setSingleStep, propnew))
match diff_props.get("step_page"):
case _, propnew:
commands.append(CommandType(self.underlying.setPageStep, propnew))
match diff_props.get("orientation"):
case _, propnew:
commands.append(CommandType(self.underlying.setOrientation, propnew))
return commands