schrodinger.utils.qt_utils module

Utility classes and functions for use with Qt objects (such as QObjects). Note that contrary to schrodinger.ui.qt.utils, these utilities do not rely on QtGui or QtWidgets. This allows these utilities to be used on headless servers which shouldn’t import QtGui or QtWidgets.

class schrodinger.utils.qt_utils.suppress_signals(*args, suppress=True)

Bases: object

A context manager to prevent signals from being emitted from the specified widget(s). All widgets to be suppressed should be passed as arguments.

__init__(*args, suppress=True)

Create a suppress_signals instance to suppress signals for all the widgets given as arguments.

Parameters

bool (suppress) – If True, suppress signals. If False, don’t.

Allows constructs such as

with suppress_signal(mywidget, suppress=self.resetting)
exception schrodinger.utils.qt_utils.SignalTimeoutException

Bases: RuntimeError

__init__(*args, **kwargs)
args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

schrodinger.utils.qt_utils.wait_for_signal(signal, timeout=None)

Uses an event loop to wait until a signal is emitted. If the signal is not emitted within a specified timeout duration, a SignalTimeoutException is raised.

Parameters
  • signal – the signal to wait for

  • timeout (float) – number of seconds to wait for the signal before timing out

Returns

the args emitted with the signal, if any. If there is only one arg emitted, it will be returned directly. If there are more, they will be return as a tuple.

schrodinger.utils.qt_utils.call_func_and_wait_for_signal(func, signal, timeout=None)

Calls the specified function and then waits for the signal. The function is called in such a way that the signal is guaranteed to be caught, even if the signal is emitted before the function returns.

Parameters

func – the function to call

See wait_for_signal for additional parameter documentation.

class schrodinger.utils.qt_utils.ABCMetaQObject(name, bases, namespace, **kwargs)

Bases: abc.ABCMeta, PyQt6.sip.wrappertype

Metaclass to allow a derived object to be a QObject and an abc.

Usage:

class MyClass(QtCore.QObject, metaclass=ABCMetaQObject):

__init__(name, bases, attrs)
mro()

Return a type’s method resolution order.

register(subclass)

Register a virtual subclass of an ABC.

Returns the subclass, to allow usage as a class decorator.

schrodinger.utils.qt_utils.get_signals(source)

Utility method for iterating through the signals on a QObject.

Parameters

source (Type[QtCore.QObject] or QtCore.QObject) – Any object or class with signals

Returns

A dictionary of {name: signal}

Return type

dict[str, QtCore.pyqtSignal]

class schrodinger.utils.qt_utils.SignalAndSlot(signal, slot)

Bases: object

A composite object to manage a single signal/slot pair. Usage:

class ClassName(QtWidgets.QWidget):

    fooChangedSignal = QtCore.pyqtSignal()

    def __init__(self, parent=None):
        super(ClassName, self).__init__(parent)
        self.fooChanged = qt_utils.SignalAndSlot(self.fooChangedSignal,
                                                 self.fooChangedSlot)

    def fooChangedSlot(self):
        pass
__init__(signal, slot)

Create an object that acts as both a signal and a slot

Parameters
  • signal (PyQt5.QtCore.pyqtSignal) – The signal object

  • slot (function) – The slot object

emit(*args, **kwargs)
connect(*args, **kwargs)
disconnect(*args, **kwargs)
schrodinger.utils.qt_utils.add_enums_as_attributes(enum_)

A class decorator that takes in an enum and aliases its members on the decorated class. For example:

Shape = enum.Enum('Shape', 'SQUARE TRIANGLE CIRCLE')
@qt_utils.add_enums_as_attributes(Shape)
class Foo:
    pass

assert Foo.SQUARE is Shape.SQUARE
assert Foo.TRIANGLE is Shape.TRIANGLE
assert Foo.CIRCLE is Shape.CIRCLE
schrodinger.utils.qt_utils.exit_event_loop_on_exception(func, *args, **kwargs)

Decorates a function that passes an event_loop keyword so if func throws an exception, the event loop will exit. The exception is accesible in get_last_exception. Example usage:

@exit_event_loop_on_exception
def slot(event_loop=None):
    ...
    event_loop.quit()

event_loop = schrodinger.QtCore.QEventLoop()
timer = schrodinger.QtCore.QTimer()
timer.timeout.connect(functools.partial(event_loop=event_loop))
timer.start(1)
event_loop.exec()
exc = get_last_exception()
if exc:
    raise exc
schrodinger.utils.qt_utils.get_last_exception()

Returns an exception if one was thrown previously in exit_event_loop_on_exception. Returns None if no exception was thrown. Calling this function resets the exception state.

class schrodinger.utils.qt_utils.EventLoop(parent=None, exit_on_exception=True, reraise_exception=True, timeout=None)

Bases: PyQt6.QtCore.QEventLoop

A modified QEventLoop that catches exceptions that occur in any slot while the event loop is running, stores that exception and optionally exits the event loop and/or re-raises that exception from EventLoop.exec() call.

__init__(parent=None, exit_on_exception=True, reraise_exception=True, timeout=None)
Parameters
  • exit_on_exception – Whether to exit the running event loop if an exception is raised in a slot

  • reraise_exception – Whether to reraise the last detected exception from the exec() method (making it catchable in the calling code).

  • timeout – if specified, the event loop will exit after this many seconds. This is useful as a failsafe so the event loop doesn’t hang indefinitely, especially in unit tests

exec(self, flags: QEventLoop.ProcessEventsFlag = QEventLoop.AllEvents) int
handleException(typ, value, tb)
AllEvents = 0
ExcludeSocketNotifiers = 2
ExcludeUserInputEvents = 1
class ProcessEventsFlag(value)

Bases: enum.Flag

An enumeration.

AllEvents = 0
ExcludeUserInputEvents = 1
ExcludeSocketNotifiers = 2
WaitForMoreEvents = 4
WaitForMoreEvents = 4
blockSignals(self, b: bool) bool
childEvent(self, a0: QChildEvent)
children(self) List[QObject]
connectNotify(self, signal: QMetaMethod)
customEvent(self, a0: QEvent)
deleteLater(self)
destroyed

destroyed(self, object: typing.Optional[QObject] = None) [signal]

disconnect(a0: QMetaObject.Connection) bool
disconnect(self) None
disconnectNotify(self, signal: QMetaMethod)
dumpObjectInfo(self)
dumpObjectTree(self)
dynamicPropertyNames(self) List[QByteArray]
event(self, event: QEvent) bool
eventFilter(self, a0: QObject, a1: QEvent) bool
exit(self, returnCode: int = 0)
findChild(self, type: type, name: str = '', options: Qt.FindChildOption = Qt.FindChildrenRecursively) QObject
findChild(self, types: Tuple, name: str = '', options: Qt.FindChildOption = Qt.FindChildrenRecursively) QObject
findChildren(self, type: type, name: str = '', options: Qt.FindChildOption = Qt.FindChildrenRecursively) List[QObject]
findChildren(self, types: Tuple, name: str = '', options: Qt.FindChildOption = Qt.FindChildrenRecursively) List[QObject]
findChildren(self, type: type, re: QRegularExpression, options: Qt.FindChildOption = Qt.FindChildrenRecursively) List[QObject]
findChildren(self, types: Tuple, re: QRegularExpression, options: Qt.FindChildOption = Qt.FindChildrenRecursively) List[QObject]
inherits(self, classname: str) bool
installEventFilter(self, a0: QObject)
isRunning(self) bool
isSignalConnected(self, signal: QMetaMethod) bool
isWidgetType(self) bool
isWindowType(self) bool
killTimer(self, id: int)
metaObject(self) QMetaObject
moveToThread(self, thread: QThread)
objectName(self) str
objectNameChanged

objectNameChanged(self, objectName: str) [signal]

parent(self) QObject
printException()
processEvents(self, flags: QEventLoop.ProcessEventsFlag = QEventLoop.AllEvents) bool
processEvents(self, flags: QEventLoop.ProcessEventsFlag, maximumTime: int) None
property(self, name: str) Any
pyqtConfigure(...)

Each keyword argument is either the name of a Qt property or a Qt signal. For properties the property is set to the given value which should be of an appropriate type. For signals the signal is connected to the given value which should be a callable.

quit(self)
receivers(self, signal: PYQT_SIGNAL) int
removeEventFilter(self, a0: QObject)
sender(self) QObject
senderSignalIndex(self) int
setObjectName(self, name: str)
setParent(self, a0: QObject)
setProperty(self, name: str, value: Any) bool
signalsBlocked(self) bool
startTimer(self, interval: int, timerType: Qt.TimerType = Qt.CoarseTimer) int
staticMetaObject = <PyQt6.QtCore.QMetaObject object>
thread(self) QThread
timerEvent(self, a0: QTimerEvent)
tr(sourceText: str, disambiguation: typing.Optional[str] = None, n: int = - 1) str
wakeUp(self)