Source code for jvconnected.ui.utils

import sys
import asyncio
import functools
from typing import Any, Callable, Coroutine, NamedTuple
from PySide2 import QtCore


[docs]class GenericQObject(QtCore.QObject): """Utility class to remove some of the boilerplate code needed to implement :class:`~PySide2.QtCore.Property` attributes. The intended pattern uses the following naming convention:: class MyQtObject(GenericQObject): _n_fooValue = Signal() # The 'notify' signal to emit on changes def __init__(self, *args): self._fooValue = 0 # The instance attribute containing the value def _get_fooValue(self): return self._fooValue def _set_fooValue(self, value): self._generic_setter('_fooValue', value) fooValue = Property(_get_fooValue, _set_fooValue, notify=_n_fooValue) """
[docs] def _generic_property_changed(self, attr: str, old_value: Any, new_value: Any): """Fired by :meth:`_generic_setter` on value changes (after the notify signal emission) :meta public: """ pass
[docs] def _generic_setter(self, attr: str, value: Any): """To be used in the 'getter' method for a :class:`~PySide2.QtCore.Property` Arguments: attr (str): The instance attribute name containing the Property value value: The value passed from the original setter :meta public: """ cur_value = getattr(self, attr) if cur_value == value: return setattr(self, attr, value) sig_name = f'_n{attr}' sig = getattr(self, sig_name) sig.emit() self._generic_property_changed(attr, cur_value, value)
[docs]def connect_close_event(f: Callable): """Connect the app ``aboutToQuit`` signal to the provided callback function """ app = QtCore.QCoreApplication.instance() app.aboutToQuit.connect(f)
def connect_async_close_event(fn: Coroutine): app = QtCore.QCoreApplication.instance() @functools.wraps(fn) def wrapper(): task = asyncio.create_task(fn()) while not task.done(): QtCore.QCoreApplication.instance().processEvents() QtCore.QCoreApplication.instance().aboutToQuit.connect(wrapper)
[docs]def AnnotatedQtSignal(**kwargs): """Allows :external+PySide6:class:`~PySide6.QtCore.PySide6.QtCore.Signal` methods to be annotated with arguments and types The keyword arguments should be in the form of ``AnnotatedQtSignal(arg_name=arg_type)`` .. code-block:: python from PySide2.QtCore import QObject, Signal from jvconnected.ui.utils import AnnotatedQtSignal as AnnoSignal class MyObject(QObject): my_signal: AnnoSignal(name=str, value=int) = Signal(str, int) '''Description of ``my_signal``''' This allows a custom Sphinx extension to include the annotated argument names with their types (as a normal method would appear) instead of the types only. .. note:: This does not yet support type checking and will very likely fail against MyPy checks. It only exists for documentation purposes. """ try: module = sys._getframe(1).f_globals.get('__name__', '__main__') except (AttributeError, ValueError): module = None nm_tpl = NamedTuple(AnnotatedQtSignal.__qualname__, **kwargs) if module is not None: nm_tpl.__module__ = module return nm_tpl