From bf0f779125afae2c6c995cea5dc5553da8e9da77 Mon Sep 17 00:00:00 2001 From: Adrian Herrmann Date: Wed, 31 Jan 2024 18:13:00 +0100 Subject: QTimer: Fix singleShot overload with context The singleShot overload with context had a problem where if the functor was a slot of a QObject, it would not have a sender when it should. To fix this, the newly added QObject.connect() overload with context is used. Change-Id: I654c09efb0d1b37ea0c014e9f17cd5e1913d1a96 Reviewed-by: Cristian Maureira-Fredes (cherry picked from commit 6b227000f28c82e189f3cc26275ca7a930f75e2f) Reviewed-by: Friedemann Kleint Reviewed-by: Qt CI Bot --- sources/pyside6/PySide6/glue/qtcore.cpp | 50 ++++++++++++---------- .../pyside6/tests/QtCore/qtimer_singleshot_test.py | 11 +++++ .../pyside6/tests/signals/qobject_sender_test.py | 7 ++- 3 files changed, 44 insertions(+), 24 deletions(-) diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp index ed1cb100f..94dc915a0 100644 --- a/sources/pyside6/PySide6/glue/qtcore.cpp +++ b/sources/pyside6/PySide6/glue/qtcore.cpp @@ -1059,28 +1059,9 @@ timer->start(%1); // @snippet qtimer-singleshot-2 // @snippet qtimer-singleshot-functor-context -Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); -if (PyObject_TypeCheck(%3, PySideSignalInstance_TypeF())) { - auto *timerType = Shiboken::SbkType(); - auto *pyTimer = timerType->tp_new(Shiboken::SbkType(), emptyTuple, nullptr); - timerType->tp_init(pyTimer, emptyTuple, nullptr); - QTimer * timer = %CONVERTTOCPP[QTimer *](pyTimer); - timer->setSingleShot(true); - PySideSignalInstance *signalInstance = reinterpret_cast(%2); - Shiboken::AutoDecRef signalSignature(Shiboken::String::fromFormat("2%s", PySide::Signal::getSignature(signalInstance))); - Shiboken::AutoDecRef result( - PyObject_CallFunction(PySide::PySideName::qtConnect(), "OsOO", - pyTimer, - SIGNAL(timeout()), - %3, - PySide::Signal::getObject(signalInstance), - signalSignature.object()) - ); - timer->connect(timer, &QTimer::timeout, timer, &QObject::deleteLater, Qt::DirectConnection); - Shiboken::Object::releaseOwnership(reinterpret_cast(pyTimer)); - Py_XDECREF(pyTimer); - timer->start(%1); -} else { +auto msec = %1; +if (msec == 0) { + Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); auto *callable = %PYARG_3; auto cppCallback = [callable]() { @@ -1091,7 +1072,30 @@ if (PyObject_TypeCheck(%3, PySideSignalInstance_TypeF())) { }; Py_INCREF(callable); - %CPPSELF.%FUNCTION_NAME(%1, %2, cppCallback); + %CPPSELF.%FUNCTION_NAME(msec, %2, cppCallback); +} else { + Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); + auto *timerType = Shiboken::SbkType(); + auto newFunc = timerType->tp_new; + auto initFunc = timerType->tp_init; + auto *pyTimer = newFunc(Shiboken::SbkType(), emptyTuple, nullptr); + initFunc(pyTimer, emptyTuple, nullptr); + + QTimer * timer = %CONVERTTOCPP[QTimer *](pyTimer); + timer->setSingleShot(true); + + Shiboken::AutoDecRef result( + PyObject_CallMethod(pyTimer, "connect", "OsOO", + pyTimer, + SIGNAL(timeout()), + %PYARG_2, + %PYARG_3) + ); + + timer->connect(timer, &QTimer::timeout, timer, &QObject::deleteLater, Qt::DirectConnection); + Shiboken::Object::releaseOwnership(reinterpret_cast(pyTimer)); + Py_XDECREF(pyTimer); + timer->start(msec); } // @snippet qtimer-singleshot-functor-context diff --git a/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py b/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py index 1392281fa..9718a2427 100644 --- a/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py +++ b/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py @@ -85,6 +85,17 @@ class TestSingleShot(UsesQApplication): self.assertTrue(thread.called) self.assertEqual(self.qthread, thread.qthread) + def testSingleShotWithContextZero(self): + thread = ThreadForContext() + thread.start() + thread.context.moveToThread(thread) + QTimer.singleShot(0, thread.context, self.callback) + self.app.exec() + thread.wait() + self.assertTrue(self.called) + self.assertTrue(thread.called) + self.assertEqual(self.qthread, thread.qthread) + class SigEmitter(QObject): diff --git a/sources/pyside6/tests/signals/qobject_sender_test.py b/sources/pyside6/tests/signals/qobject_sender_test.py index a7cda69f7..485584ec2 100644 --- a/sources/pyside6/tests/signals/qobject_sender_test.py +++ b/sources/pyside6/tests/signals/qobject_sender_test.py @@ -73,6 +73,12 @@ class ObjectSenderWithQAppTest(UsesQApplication): self.app.exec() self.assertTrue(isinstance(recv.the_sender, QObject)) + def testSenderCppSignalSingleShotTimerWithContext(self): + recv = Receiver() + QTimer.singleShot(10, recv, recv.callback) + self.app.exec() + self.assertTrue(isinstance(recv.the_sender, QObject)) + def testSenderCppSignalWithPythonExtendedClass(self): sender = ExtQTimer() recv = Receiver() @@ -105,4 +111,3 @@ class ObjectSenderWithQAppCheckOnReceiverTest(UsesQApplication): if __name__ == '__main__': unittest.main() - -- cgit v1.2.3