diff options
| author | Adrian Herrmann <adrian.herrmann@qt.io> | 2024-01-31 18:12:41 +0100 |
|---|---|---|
| committer | Adrian Herrmann <adrian.herrmann@qt.io> | 2024-02-07 12:06:33 +0100 |
| commit | acab25a3ccb836818e5089b23d40196bc7414b7a (patch) | |
| tree | e705a05301240d34c0e4a9e68e753265ee5f76b8 /sources/pyside6/libpyside/qobjectconnect.cpp | |
| parent | 290049e9e0066c195345afaa1ec573a1abe2f953 (diff) | |
QObject: Add connect() overload with context arg
On C++, there is an overload of QObject::connect() that allows passing a
context object. This creates a connection in the context object's event
loop instead of that of the caller. This implements said overload in
Python.
Pick-to: 6.6
Change-Id: Ia6a098a04470741efd450818c31aa5bffb1bd9f8
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/pyside6/libpyside/qobjectconnect.cpp')
| -rw-r--r-- | sources/pyside6/libpyside/qobjectconnect.cpp | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/sources/pyside6/libpyside/qobjectconnect.cpp b/sources/pyside6/libpyside/qobjectconnect.cpp index ebd9c8339..3c5b75953 100644 --- a/sources/pyside6/libpyside/qobjectconnect.cpp +++ b/sources/pyside6/libpyside/qobjectconnect.cpp @@ -3,6 +3,7 @@ #include "qobjectconnect.h" #include "pysideqobject.h" +#include "pysideqslotobject_p.h" #include "pysidesignal.h" #include "pysideutils.h" #include "signalmanager.h" @@ -15,6 +16,8 @@ #include <QtCore/QMetaMethod> #include <QtCore/QObject> +#include <QtCore/private/qobject_p.h> + #include <string_view> static bool isMethodDecorator(PyObject *method, bool is_pymethod, PyObject *self) @@ -259,6 +262,46 @@ QMetaObject::Connection qobjectConnectCallback(QObject *source, const char *sign return connection; } +QMetaObject::Connection qobjectConnectCallback(QObject *source, const char *signal, QObject *context, + PyObject *callback, Qt::ConnectionType type) +{ + if (!signal || !PySide::Signal::checkQtSignal(signal)) + return {}; + + const int signalIndex = + PySide::SignalManager::registerMetaMethodGetIndex(source, signal + 1, + QMetaMethod::Signal); + if (signalIndex == -1) + return {}; + + // Extract receiver from callback + const GetReceiverResult receiver = getReceiver(source, signal + 1, callback); + if (receiver.receiver == nullptr && receiver.self == nullptr) + return {}; + + PySide::SignalManager &signalManager = PySide::SignalManager::instance(); + + PySideQSlotObject *slotObject = new PySideQSlotObject(callback); + + QMetaObject::Connection connection{}; + Py_BEGIN_ALLOW_THREADS // PYSIDE-2367, prevent threading deadlocks with connectNotify() + connection = QObjectPrivate::connect(source, signalIndex, context, slotObject, type); + Py_END_ALLOW_THREADS + if (!connection) { + if (receiver.usingGlobalReceiver) + signalManager.releaseGlobalReceiver(source, receiver.receiver); + return {}; + } + + Q_ASSERT(receiver.receiver); + if (receiver.usingGlobalReceiver) + signalManager.notifyGlobalReceiver(receiver.receiver); + + const QMetaMethod signalMethod = receiver.receiver->metaObject()->method(signalIndex); + static_cast<FriendlyQObject *>(source)->connectNotify(signalMethod); + return connection; +} + bool qobjectDisconnectCallback(QObject *source, const char *signal, PyObject *callback) { if (!PySide::Signal::checkQtSignal(signal)) |
