aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/doc/developer
diff options
context:
space:
mode:
authorFriedemann Kleint <[email protected]>2024-07-05 11:58:53 +0200
committerFriedemann Kleint <[email protected]>2024-07-29 10:06:18 +0200
commit9f883211760881c64aab2138f49486edf6c9aae9 (patch)
treeeaeb3fd6f06d4f7c8a4744267d8e97ae893611b9 /sources/pyside6/doc/developer
parent51df6eb4c0a1b02cc476d1fe5a7f9f30cb60e600 (diff)
Add Signalmanager documentation
Task-number: PYSIDE-2810 Change-Id: Ibbad9d612a51a35e4b2f0c5eeb3a989d8495dd10 Reviewed-by: Christian Tismer <[email protected]>
Diffstat (limited to 'sources/pyside6/doc/developer')
-rw-r--r--sources/pyside6/doc/developer/index.rst1
-rw-r--r--sources/pyside6/doc/developer/signalmanager.md58
2 files changed, 59 insertions, 0 deletions
diff --git a/sources/pyside6/doc/developer/index.rst b/sources/pyside6/doc/developer/index.rst
index 88247a962..d158b6690 100644
--- a/sources/pyside6/doc/developer/index.rst
+++ b/sources/pyside6/doc/developer/index.rst
@@ -20,6 +20,7 @@ Development Topics
adapt_qt.rst
extras.rst
qtasyncio.rst
+ signalmanager.md
Implementation details
----------------------
diff --git a/sources/pyside6/doc/developer/signalmanager.md b/sources/pyside6/doc/developer/signalmanager.md
new file mode 100644
index 000000000..1161f6d53
--- /dev/null
+++ b/sources/pyside6/doc/developer/signalmanager.md
@@ -0,0 +1,58 @@
+# 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 `@Slot`
+- Functions of `QObject`-derived classes declared in Python. They will
+ be turned into proper slots at runtime using the private Qt class
+ `QMetaObjectBuilder`. This causes a warning to be emitted,
+ visible when activating the logging category `qt.pyside.libpyside`.
+- Methods of non-`QObject`-derived classes
+- Other 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
+`QObject`s. 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
+
+- [Receiver Leak PYSIDE-1057](https://bugreports.qt.io/browse/PYSIDE-1057)
+- [Partial function receiver Leak PYSIDE-2793](https://bugreports.qt.io/browse/PYSIDE-2793)
+- Various issues related to threading and object deletion, solved by workarounds
+ ([PYSIDE-2646](https://bugreports.qt.io/browse/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](https://codereview.qt-project.org/c/pyside/pyside-setup/+/536298)
+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.