aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdrian Herrmann <adrian.herrmann@qt.io>2023-11-16 20:37:13 +0100
committerAdrian Herrmann <adrian.herrmann@qt.io>2023-11-24 17:32:48 +0100
commit671c182dce91c387037894017be314564e054c00 (patch)
tree5d8061c027acb70c6fc904ada56176acad3e7628
parent3a058afcd7ae497c085ea0b0891d164caa38f1fe (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. Pick-to: 6.6 Change-Id: I0c4e3ef4b859cdfaac07415ff64c440821e7f442 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
-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()
-