diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-07-02 10:38:45 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2024-07-04 11:55:52 +0200 |
commit | 08d61b56fa9e901b807b67b07f187e0f54e7551c (patch) | |
tree | 2408c7fb6ebb7fcb4267871e9ab0c34c861d1a56 /sources | |
parent | 0e920a721830ca0ed900492756335ceafea1fedd (diff) |
libpyside: Fix parameters for connections with contexts
Use the new SignalManager::callPythonMetaMethod() overload
introduced by ed8fc457e04f4ead8a3b2a2da797bdc14bd5b210 in
PySideQSlotObject to convert the void ** arguments to Python.
Amends acab25a3ccb836818e5089b23d40196bc7414b7a.
Change-Id: I024bc7f8df7fa65b8b1761f517a99a854de2cec8
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources')
-rw-r--r-- | sources/pyside6/libpyside/pysideqslotobject_p.cpp | 34 | ||||
-rw-r--r-- | sources/pyside6/libpyside/pysideqslotobject_p.h | 22 | ||||
-rw-r--r-- | sources/pyside6/libpyside/qobjectconnect.cpp | 6 | ||||
-rw-r--r-- | sources/pyside6/tests/signals/signal_emission_test.py | 26 |
4 files changed, 64 insertions, 24 deletions
diff --git a/sources/pyside6/libpyside/pysideqslotobject_p.cpp b/sources/pyside6/libpyside/pysideqslotobject_p.cpp index 914be898a..40b011fcf 100644 --- a/sources/pyside6/libpyside/pysideqslotobject_p.cpp +++ b/sources/pyside6/libpyside/pysideqslotobject_p.cpp @@ -2,28 +2,46 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "pysideqslotobject_p.h" +#include "signalmanager.h" -#include <autodecref.h> #include <gilstate.h> namespace PySide { +PySideQSlotObject::PySideQSlotObject(PyObject *callable, + const QByteArrayList ¶meterTypes, + const char *returnType) : + QtPrivate::QSlotObjectBase(&impl), + m_callable(callable), + m_parameterTypes(parameterTypes), + m_returnType(returnType) +{ + Py_INCREF(callable); +} + +PySideQSlotObject::~PySideQSlotObject() +{ + Shiboken::GilState state; + Py_DECREF(m_callable); +} + +void PySideQSlotObject::call(void **args) +{ + SignalManager::callPythonMetaMethod(m_parameterTypes, m_returnType, args, m_callable); +} + void PySideQSlotObject::impl(int which, QSlotObjectBase *this_, QObject *receiver, void **args, bool *ret) { - auto self = static_cast<PySideQSlotObject *>(this_); + auto *self = static_cast<PySideQSlotObject *>(this_); switch (which) { case Destroy: delete self; break; case Call: - { - Shiboken::GilState state; - Shiboken::AutoDecRef arglist(PyTuple_New(0)); - Shiboken::AutoDecRef ret(PyObject_CallObject(self->callable, arglist)); - break; - } + self->call(args); + break; case Compare: case NumOperations: Q_UNUSED(receiver); diff --git a/sources/pyside6/libpyside/pysideqslotobject_p.h b/sources/pyside6/libpyside/pysideqslotobject_p.h index d7d258505..827f0193c 100644 --- a/sources/pyside6/libpyside/pysideqslotobject_p.h +++ b/sources/pyside6/libpyside/pysideqslotobject_p.h @@ -15,22 +15,18 @@ namespace PySide class PySideQSlotObject : public QtPrivate::QSlotObjectBase { - PyObject *callable; +public: + explicit PySideQSlotObject(PyObject *callable, const QByteArrayList ¶meterTypes, + const char *returnType = nullptr); + ~PySideQSlotObject(); +private: static void impl(int which, QSlotObjectBase *this_, QObject *receiver, void **args, bool *ret); + void call(void **args); -public: - PySideQSlotObject(PyObject *callable) : QtPrivate::QSlotObjectBase(&impl), callable(callable) - { - Py_INCREF(callable); - } - - ~PySideQSlotObject() - { - auto gstate = PyGILState_Ensure(); - Py_DECREF(callable); - PyGILState_Release(gstate); - } + PyObject *m_callable; + const QByteArrayList m_parameterTypes; + const char *m_returnType; }; diff --git a/sources/pyside6/libpyside/qobjectconnect.cpp b/sources/pyside6/libpyside/qobjectconnect.cpp index d0a1a2c50..e27827ce4 100644 --- a/sources/pyside6/libpyside/qobjectconnect.cpp +++ b/sources/pyside6/libpyside/qobjectconnect.cpp @@ -282,7 +282,10 @@ QMetaObject::Connection qobjectConnectCallback(QObject *source, const char *sign PySide::SignalManager &signalManager = PySide::SignalManager::instance(); - auto *slotObject = new PySideQSlotObject(callback); + const QMetaMethod signalMethod = source->metaObject()->method(signalIndex); + auto *slotObject = new PySideQSlotObject(callback, + signalMethod.parameterTypes(), + signalMethod.typeName()); QMetaObject::Connection connection{}; Py_BEGIN_ALLOW_THREADS // PYSIDE-2367, prevent threading deadlocks with connectNotify() @@ -298,7 +301,6 @@ QMetaObject::Connection qobjectConnectCallback(QObject *source, const char *sign if (receiver.usingGlobalReceiver) signalManager.notifyGlobalReceiver(receiver.receiver); - const QMetaMethod signalMethod = source->metaObject()->method(signalIndex); static_cast<FriendlyQObject *>(source)->connectNotify(signalMethod); return connection; } diff --git a/sources/pyside6/tests/signals/signal_emission_test.py b/sources/pyside6/tests/signals/signal_emission_test.py index 769b1839a..b0c02b084 100644 --- a/sources/pyside6/tests/signals/signal_emission_test.py +++ b/sources/pyside6/tests/signals/signal_emission_test.py @@ -15,7 +15,7 @@ sys.path.append(os.fspath(Path(__file__).resolve().parents[1])) from init_paths import init_test_paths init_test_paths(False) -from PySide6.QtCore import QObject, Signal, SIGNAL, QProcess, QTimeLine +from PySide6.QtCore import QObject, Signal, SIGNAL, QProcess, QTimeLine, Slot from helper.usesqapplication import UsesQApplication @@ -45,6 +45,18 @@ class Sender(QObject): dummy_int = Signal(int) +class Receiver(QObject): + '''Receiver class''' + + def __init__(self, p=None): + super().__init__(p) + self.n = 0 + + @Slot(int) + def intSlot(self, n): + self.n = n + + class PythonSignalToCppSlots(UsesQApplication): '''Connect python signals to C++ slots''' @@ -75,6 +87,18 @@ class PythonSignalToCppSlots(UsesQApplication): self.assertEqual(timeline.currentTime(), current + 42) +class ConnectWithContext(UsesQApplication): + '''Test whether a connection with context QObject passes parameters.''' + + def testIt(self): + sender = Sender() + receiver = Receiver() + context = sender + QObject.connect(sender, SIGNAL("dummy_int(int)"), context, receiver.intSlot) + sender.dummy_int.emit(42) + self.assertEqual(receiver.n, 42) + + class CppSignalsToCppSlots(UsesQApplication): '''Connection between C++ slots and signals''' |