aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCristián Maureira-Fredes <Cristian.Maureira-Fredes@qt.io>2024-02-08 14:24:44 +0100
committerCristián Maureira-Fredes <Cristian.Maureira-Fredes@qt.io>2024-02-08 14:24:44 +0100
commit4bb71d324c7281bcb34c7625cd4f82ad090c95ff (patch)
tree9c9b6737cc3da150ebf771e0a48d7d769344f68e
parentf0b06aa4946f0ffa7bac59e2ed86ebd5c3d9f252 (diff)
parentbf0f779125afae2c6c995cea5dc5553da8e9da77 (diff)
Merge branch '6.6' into 6.6.2
-rw-r--r--build_scripts/platforms/windows_desktop.py3
-rw-r--r--examples/qml/usingmodel/usingmodel.py48
-rw-r--r--examples/qml/usingmodel/view.qml12
-rw-r--r--sources/pyside6/PySide6/QtCore/typesystem_core_common.xml25
-rw-r--r--sources/pyside6/PySide6/glue/qtcore.cpp56
-rw-r--r--sources/pyside6/libpyside/CMakeLists.txt4
-rw-r--r--sources/pyside6/libpyside/pysideqslotobject_p.cpp36
-rw-r--r--sources/pyside6/libpyside/pysideqslotobject_p.h39
-rw-r--r--sources/pyside6/libpyside/qobjectconnect.cpp43
-rw-r--r--sources/pyside6/libpyside/qobjectconnect.h5
-rw-r--r--sources/pyside6/plugins/designer/designercustomwidgets.cpp1
-rw-r--r--sources/pyside6/tests/QtCore/qtimer_singleshot_test.py11
-rw-r--r--sources/pyside6/tests/signals/qobject_sender_test.py7
13 files changed, 222 insertions, 68 deletions
diff --git a/build_scripts/platforms/windows_desktop.py b/build_scripts/platforms/windows_desktop.py
index 543ee9880..c3b19d5a1 100644
--- a/build_scripts/platforms/windows_desktop.py
+++ b/build_scripts/platforms/windows_desktop.py
@@ -120,7 +120,8 @@ def prepare_packages_win32(pyside_build, _vars):
src = f"{{install_dir}}/bin/{script_dir}"
target = f"{{st_build_dir}}/{{st_package_name}}/scripts/{script_dir}"
# Exclude subdirectory tests
- copydir(src, target, _filter=["*.py", "*.spec"], recursive=False, _vars=_vars)
+ copydir(src, target, _filter=["*.py", "*.spec", "*.jpg", "*.icns", "*.ico"],
+ recursive=False, _vars=_vars)
# <install>/bin/*.exe,*.dll -> {st_package_name}/
filters = ["pyside*.exe", "pyside*.dll"]
diff --git a/examples/qml/usingmodel/usingmodel.py b/examples/qml/usingmodel/usingmodel.py
index 6f8ea5a21..008a1b94b 100644
--- a/examples/qml/usingmodel/usingmodel.py
+++ b/examples/qml/usingmodel/usingmodel.py
@@ -2,24 +2,37 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import os
+from dataclasses import dataclass
from pathlib import Path
import sys
from PySide6.QtCore import QAbstractListModel, Qt, QUrl, QByteArray
from PySide6.QtGui import QGuiApplication
from PySide6.QtQuick import QQuickView
-from PySide6.QtQml import qmlRegisterSingletonType
+from PySide6.QtQml import QmlElement, QmlSingleton
+QML_IMPORT_NAME = "PersonModel"
+QML_IMPORT_MAJOR_VERSION = 1
+
+
+@dataclass
+class Person:
+ name: str
+ myrole: str
+
+
+@QmlElement
+@QmlSingleton
class PersonModel (QAbstractListModel):
MyRole = Qt.UserRole + 1
- def __init__(self, parent=None):
- QAbstractListModel.__init__(self, parent)
- self._data = []
+ def __init__(self, data, parent=None):
+ super().__init__(parent)
+ self._data = data
def roleNames(self):
roles = {
- PersonModel.MyRole: QByteArray(b'modelData'),
+ PersonModel.MyRole: QByteArray(b'myrole'),
Qt.DisplayRole: QByteArray(b'display')
}
return roles
@@ -29,26 +42,18 @@ class PersonModel (QAbstractListModel):
def data(self, index, role):
d = self._data[index.row()]
-
if role == Qt.DisplayRole:
- return d['name']
- elif role == Qt.DecorationRole:
+ return d.name
+ if role == Qt.DecorationRole:
return Qt.black
- elif role == PersonModel.MyRole:
- return d['myrole']
+ if role == PersonModel.MyRole:
+ return d.myrole
return None
- def populate(self, data=None):
- for item in data:
- self._data.append(item)
-
-
-def model_callback(engine):
- my_model = PersonModel()
- data = [{'name': 'Qt', 'myrole': 'role1'},
- {'name': 'PySide', 'myrole': 'role2'}]
- my_model.populate(data)
- return my_model
+ @staticmethod
+ def create(engine):
+ data = [Person('Qt', 'myrole'), Person('PySide', 'role2')]
+ return PersonModel(data)
if __name__ == '__main__':
@@ -56,7 +61,6 @@ if __name__ == '__main__':
view = QQuickView()
view.setResizeMode(QQuickView.SizeRootObjectToView)
- qmlRegisterSingletonType(PersonModel, "PersonModel", 1, 0, "MyModel", model_callback)
qml_file = os.fspath(Path(__file__).resolve().parent / 'view.qml')
view.setSource(QUrl.fromLocalFile(qml_file))
if view.status() == QQuickView.Error:
diff --git a/examples/qml/usingmodel/view.qml b/examples/qml/usingmodel/view.qml
index c5aa7e0fc..e8b1fb2fb 100644
--- a/examples/qml/usingmodel/view.qml
+++ b/examples/qml/usingmodel/view.qml
@@ -8,21 +8,13 @@ ListView {
width: 100
height: 100
anchors.fill: parent
- model: MyModel
+ model: PersonModel
delegate: Component {
Rectangle {
height: 25
width: 100
Text {
- function displayText() {
- var result = ""
- if (typeof display !== "undefined")
- result = display + ": "
- result += modelData
- return result
- }
-
- text: displayText()
+ text: display + ": " + myrole
}
}
}
diff --git a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
index bdaef41f4..5168373fd 100644
--- a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
+++ b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
@@ -1731,16 +1731,10 @@
<modify-argument index="1" pyi-type="Optional[PySide6.QtCore.QObject]"/>
</modify-function>
<modify-function signature="connect(const QObject*,const char*,const char*,Qt::ConnectionType)const">
- <modify-argument index="4">
- <rename to="type"/>
- </modify-argument>
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-connect-1"/>
</modify-function>
<!-- static version -->
<modify-function signature="connect(const QObject*,QMetaMethod,const QObject*,QMetaMethod,Qt::ConnectionType)">
- <modify-argument index="5">
- <rename to="type"/>
- </modify-argument>
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-connect-2"/>
</modify-function>
<modify-function signature="connect(const QObject*,const char*,const QObject*,const char*,Qt::ConnectionType)">
@@ -1750,16 +1744,20 @@
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-connect-3"/>
</modify-function>
<inject-code class="native" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-connect"/>
- <add-function signature="connect(const QObject*,const char*,PyCallable*,Qt::ConnectionType@type@=Qt::AutoConnection)"
+ <add-function signature="connect(const QObject*@sender@,const char*@signal@,PyCallable*@functor@,Qt::ConnectionType@type@=Qt::AutoConnection)"
return-type="QMetaObject::Connection" static="yes">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-connect-4"/>
</add-function>
+ <add-function signature="connect(const QObject*@sender@,const char*@signal@,const QObject*@context@,PyCallable*@functor@,Qt::ConnectionType@type@=Qt::AutoConnection)"
+ return-type="QMetaObject::Connection" static="yes">
+ <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-connect-4-context"/>
+ </add-function>
<!-- static version -->
- <add-function signature="connect(const char*,PyCallable*,Qt::ConnectionType@type@=Qt::AutoConnection)"
+ <add-function signature="connect(const char*@signal@,PyCallable*@functor@,Qt::ConnectionType@type@=Qt::AutoConnection)"
return-type="QMetaObject::Connection">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-connect-5"/>
</add-function>
- <add-function signature="connect(const char*,const QObject*,const char*,Qt::ConnectionType@type@=Qt::AutoConnection)"
+ <add-function signature="connect(const char*@signal@,const QObject*@receiver@,const char*@method@,Qt::ConnectionType@type@=Qt::AutoConnection)"
return-type="QMetaObject::Connection">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-connect-6"/>
</add-function>
@@ -1767,12 +1765,17 @@
<add-function signature="emit(const char*,...)" return-type="bool">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-emit"/>
</add-function>
- <add-function signature="disconnect(const char*,PyCallable*)" return-type="bool">
+ <add-function signature="disconnect(const char*@signal@,PyCallable*@functor@)" return-type="bool">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-disconnect-1"/>
</add-function>
- <add-function signature="disconnect(const QObject*,const char*,PyCallable*)" return-type="bool" static="yes">
+ <add-function signature="disconnect(const QObject*@sender@,const char*@signal@,PyCallable*@functor@)" return-type="bool" static="yes">
<inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-disconnect-2"/>
</add-function>
+ <modify-function signature="disconnect(QMetaObject::Connection)">
+ <modify-argument index="1">
+ <rename to="connection"/>
+ </modify-argument>
+ </modify-function>
<add-function signature="findChild(PyTypeObject*@type@,const QString&amp;@name@={},Qt::FindChildOptions@options@=Qt::FindChildrenRecursively)"
diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp
index a687d8447..94dc915a0 100644
--- a/sources/pyside6/PySide6/glue/qtcore.cpp
+++ b/sources/pyside6/PySide6/glue/qtcore.cpp
@@ -321,6 +321,12 @@ PyModule_AddStringConstant(module, "__version__", qVersion());
%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
// @snippet qobject-connect-4
+// @snippet qobject-connect-4-context
+// %FUNCTION_NAME() - disable generation of function call.
+%RETURN_TYPE %0 = PySide::qobjectConnectCallback(%1, %2, %3, %PYARG_4, %5);
+%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0);
+// @snippet qobject-connect-4-context
+
// @snippet qobject-connect-5
// %FUNCTION_NAME() - disable generation of function call.
%RETURN_TYPE %0 = PySide::qobjectConnectCallback(%CPPSELF, %1, %PYARG_2, %3);
@@ -1053,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<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 msec = %1;
+if (msec == 0) {
+ Shiboken::AutoDecRef emptyTuple(PyTuple_New(0));
auto *callable = %PYARG_3;
auto cppCallback = [callable]()
{
@@ -1085,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<QTimer>();
+ auto newFunc = timerType->tp_new;
+ auto initFunc = timerType->tp_init;
+ auto *pyTimer = newFunc(Shiboken::SbkType<QTimer>(), 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<SbkObject *>(pyTimer));
+ Py_XDECREF(pyTimer);
+ timer->start(msec);
}
// @snippet qtimer-singleshot-functor-context
diff --git a/sources/pyside6/libpyside/CMakeLists.txt b/sources/pyside6/libpyside/CMakeLists.txt
index 01a0a66b0..e9fd0d56e 100644
--- a/sources/pyside6/libpyside/CMakeLists.txt
+++ b/sources/pyside6/libpyside/CMakeLists.txt
@@ -5,7 +5,10 @@ project(libpyside)
set(libpyside_libraries Qt::Core Qt::CorePrivate)
+set(CMAKE_AUTOMOC ON)
+
set(libpyside_HEADERS # installed below
+ pysideqslotobject_p.h
class_property.h
dynamicqmetaobject.h
feature_select.h
@@ -41,6 +44,7 @@ set(libpyside_HEADERS # installed below
)
set(libpyside_SRC
+ pysideqslotobject_p.cpp
class_property.cpp
dynamicqmetaobject.cpp
feature_select.cpp
diff --git a/sources/pyside6/libpyside/pysideqslotobject_p.cpp b/sources/pyside6/libpyside/pysideqslotobject_p.cpp
new file mode 100644
index 000000000..914be898a
--- /dev/null
+++ b/sources/pyside6/libpyside/pysideqslotobject_p.cpp
@@ -0,0 +1,36 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// 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 <autodecref.h>
+#include <gilstate.h>
+
+namespace PySide
+{
+
+void PySideQSlotObject::impl(int which, QSlotObjectBase *this_, QObject *receiver,
+ void **args, bool *ret)
+{
+ 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;
+ }
+ case Compare:
+ case NumOperations:
+ Q_UNUSED(receiver);
+ Q_UNUSED(args);
+ Q_UNUSED(ret);
+ break;
+ }
+}
+
+} // namespace PySide
diff --git a/sources/pyside6/libpyside/pysideqslotobject_p.h b/sources/pyside6/libpyside/pysideqslotobject_p.h
new file mode 100644
index 000000000..d7d258505
--- /dev/null
+++ b/sources/pyside6/libpyside/pysideqslotobject_p.h
@@ -0,0 +1,39 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef PYSIDEQSLOTOBJECT_P_H
+#define PYSIDEQSLOTOBJECT_P_H
+
+#include "pysidemacros.h"
+#include <sbkpython.h>
+
+#include <QtCore/QObject>
+#include <QtCore/qobjectdefs.h>
+
+namespace PySide
+{
+
+class PySideQSlotObject : public QtPrivate::QSlotObjectBase
+{
+ PyObject *callable;
+
+ static void impl(int which, QSlotObjectBase *this_, QObject *receiver, void **args, bool *ret);
+
+public:
+ PySideQSlotObject(PyObject *callable) : QtPrivate::QSlotObjectBase(&impl), callable(callable)
+ {
+ Py_INCREF(callable);
+ }
+
+ ~PySideQSlotObject()
+ {
+ auto gstate = PyGILState_Ensure();
+ Py_DECREF(callable);
+ PyGILState_Release(gstate);
+ }
+};
+
+
+} // namespace PySide
+
+#endif // PYSIDEQSLOTOBJECT_P_H
diff --git a/sources/pyside6/libpyside/qobjectconnect.cpp b/sources/pyside6/libpyside/qobjectconnect.cpp
index 15b71766c..c47c96eb8 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))
diff --git a/sources/pyside6/libpyside/qobjectconnect.h b/sources/pyside6/libpyside/qobjectconnect.h
index 70b862233..c99b8006e 100644
--- a/sources/pyside6/libpyside/qobjectconnect.h
+++ b/sources/pyside6/libpyside/qobjectconnect.h
@@ -33,6 +33,11 @@ PYSIDE_API QMetaObject::Connection
qobjectConnectCallback(QObject *source, const char *signal,
PyObject *callback, Qt::ConnectionType type);
+/// Helpers for QObject::connect(): Make a connection to a Python callback and a context object
+PYSIDE_API QMetaObject::Connection
+ qobjectConnectCallback(QObject *source, const char *signal, QObject *context,
+ PyObject *callback, Qt::ConnectionType type);
+
/// Helpers for QObject::disconnect(): Disconnect a Python callback
PYSIDE_API bool qobjectDisconnectCallback(QObject *source, const char *signal,
PyObject *callback);
diff --git a/sources/pyside6/plugins/designer/designercustomwidgets.cpp b/sources/pyside6/plugins/designer/designercustomwidgets.cpp
index 6491251b9..ccff635a9 100644
--- a/sources/pyside6/plugins/designer/designercustomwidgets.cpp
+++ b/sources/pyside6/plugins/designer/designercustomwidgets.cpp
@@ -1,6 +1,7 @@
// Copyright (C) 2021 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+#undef slots
#include <Python.h> // Include before Qt headers due to 'slots' macro definition
#include "designercustomwidgets.h"
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()
-