Signalmanager¶
Description¶
The class Signalmanager in p/sources/pyside6/libpyside takes care of routing
Qt signals to the receivers (files signalmanager.cpp, qobjectconnect.cpp,
pysidesignal.cpp).
There are several kinds of receivers:
Slots of C++ classes
Slots of
QObject-derived classes declared in Python using@SlotFunctions of
QObject-derived classes declared in Python. They will be turned into proper slots at runtime using the private Qt classQMetaObjectBuilder. This causes a warning to be emitted, visible when activating the logging categoryqt.pyside.libpyside.Methods of non-
QObject-derived classesOther callables (free functions, lambdas, partially bound functions)
Proper Qt connections where QObject.disconnect(), QObject.sender() and
QObject.connectNotify() work are desirable also for receivers that are not
QObjects. This is achieved by using a QObject-derived class
GlobalReceiverV2 for a receiver which has a dynamic slot created by
QMetaObjectBuilder to route connected signals to the Python receiver (based
on internal class DynamicSlotDataV2).
The instances of GlobalReceiverV2 are stored in a hash on the receiver
Python objects in Signalmanager.
QMetaObject::connect(QObject*,int,QObject*,int) is used to make the
connections based on meta method indexes.
Normally, a reference should be kept on the receiver callable. However, in the
case of a method of a non-QObject-derived class, the connection should be
automatically severed when the instance is deleted. The callable passed in this
case (signal.connect(foo.slot)) is a partially bound function which has the
self parameter. It is decomposed into the self parameter and the method. A
reference is kept on the method. A weak reference with destruction callback is
kept for self.
Issues¶
Various issues related to threading and object deletion, solved by workarounds (PYSIDE-2646)
Complicated code, hard to maintain
Disconnect does not work for
QObject.connect()with context argument; it also leaks methods
Plans¶
Change
QObject: Add connect() overload with context arg acab25a3ccb836818e5089b23d40196bc7414b7a
implements a connection based on QtPrivate::QSlotObjectBase and
QObjectPrivate::connect(QObject*,int,QObject*,QtPrivate::QSlotObjectBase*)
(pysideqslotobject.cpp). This could in principle enable removing
GlobalReceiverV2, but requires keeping the QMetaObject::Connection for
disconnecting.