aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Herrmann <adrian.herrmann@qt.io>2023-11-16 20:37:13 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-11-24 19:12:29 +0000
commiteccbfd9bf3cbc9b6b497933ce9ddda90863bf046 (patch)
tree992df787cda1d1e8e08353c43ab81da5806c43b8
parentc3275fe632022b38c6ce06716f671bafb6c0bf38 (diff)
QTimer: Implement singleShot signatures w/ context
On C++, it is possible to call singleShot timers with a context object as an argument. This allows posting events to the event loop of the given context object's thread, instead of the thread of the current thread. Implement corresponding signatures to add this capability to Qt for Python. Change-Id: I0c4e3ef4b859cdfaac07415ff64c440821e7f442 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> (cherry picked from commit 671c182dce91c387037894017be314564e054c00) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--sources/pyside6/PySide6/QtCore/typesystem_core_common.xml6
-rw-r--r--sources/pyside6/PySide6/glue/qtcore.cpp37
-rw-r--r--sources/pyside6/tests/QtCore/qtimer_singleshot_test.py30
3 files changed, 71 insertions, 2 deletions
diff --git a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
index 2ef6a25e5..2011bd3e7 100644
--- a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
+++ b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
@@ -2514,12 +2514,18 @@
<include file-name="QtCore/qbuffer.h" location="global"/>
</object-type>
<object-type name="QTimer">
+ <extra-includes>
+ <include file-name="pysidestaticstrings.h" location="global"/>
+ </extra-includes>
<modify-function signature="singleShot(int,const QObject*,const char*)">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qtimer-singleshot-1"/>
</modify-function>
<add-function signature="singleShot(int,PyCallable*)" static="yes">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qtimer-singleshot-2"/>
</add-function>
+ <add-function signature="singleShot(int@msec@,const QObject*@context@,PyCallable*@functor@)" static="yes">
+ <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qtimer-singleshot-functor-context"/>
+ </add-function>
</object-type>
<object-type name="QProcess">
<configuration condition="QT_CONFIG(process)"/>
diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp
index d0f2e8d6d..52a07aa26 100644
--- a/sources/pyside6/PySide6/glue/qtcore.cpp
+++ b/sources/pyside6/PySide6/glue/qtcore.cpp
@@ -1053,6 +1053,43 @@ Py_XDECREF(pyTimer);
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<QTimer>();
+ auto *pyTimer = timerType->tp_new(Shiboken::SbkType<QTimer>(), emptyTuple, nullptr);
+ timerType->tp_init(pyTimer, emptyTuple, nullptr);
+ QTimer * timer = %CONVERTTOCPP[QTimer *](pyTimer);
+ timer->setSingleShot(true);
+ PySideSignalInstance *signalInstance = reinterpret_cast<PySideSignalInstance *>(%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<SbkObject *>(pyTimer));
+ Py_XDECREF(pyTimer);
+ timer->start(%1);
+} else {
+ auto *callable = %PYARG_3;
+ auto cppCallback = [callable]()
+ {
+ Shiboken::GilState state;
+ Shiboken::AutoDecRef arglist(PyTuple_New(0));
+ Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist));
+ Py_DECREF(callable);
+ };
+
+ Py_INCREF(callable);
+ %CPPSELF.%FUNCTION_NAME(%1, %2, cppCallback);
+}
+// @snippet qtimer-singleshot-functor-context
+
// @snippet qprocess-startdetached
qint64 pid;
%RETURN_TYPE retval = %TYPE::%FUNCTION_NAME(%1, %2, %3, &pid);
diff --git a/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py b/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py
index 770c9c1a9..1392281fa 100644
--- a/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py
+++ b/sources/pyside6/tests/QtCore/qtimer_singleshot_test.py
@@ -14,7 +14,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, QTimer, QCoreApplication, Signal
+from PySide6.QtCore import QObject, QThread, QTimer, Signal
from helper.usesqapplication import UsesQApplication
@@ -32,6 +32,19 @@ class WatchDog(QObject):
self.watched.exit_app_cb()
+class ThreadForContext(QThread):
+ def __init__(self):
+ super().__init__()
+ self.called = False
+ self.qthread = None
+ self.context = QObject()
+
+ def run(self):
+ self.called = True
+ self.qthread = QThread.currentThread()
+ self.exec()
+
+
class TestSingleShot(UsesQApplication):
'''Test case for QTimer.singleShot'''
@@ -40,6 +53,7 @@ class TestSingleShot(UsesQApplication):
UsesQApplication.setUp(self)
self.watchdog = WatchDog(self)
self.called = False
+ self.qthread = None
def tearDown(self):
# Release resources
@@ -51,6 +65,8 @@ class TestSingleShot(UsesQApplication):
def callback(self):
self.called = True
+ self.qthread = QThread.currentThread()
+ self.qthread.exit()
self.app.quit()
def testSingleShot(self):
@@ -58,6 +74,17 @@ class TestSingleShot(UsesQApplication):
self.app.exec()
self.assertTrue(self.called)
+ def testSingleShotWithContext(self):
+ thread = ThreadForContext()
+ thread.start()
+ thread.context.moveToThread(thread)
+ QTimer.singleShot(100, 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):
@@ -93,4 +120,3 @@ class TestSingleShotSignal(UsesQApplication):
if __name__ == '__main__':
unittest.main()
-