aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-05-17 15:48:39 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2023-05-22 14:48:57 +0000
commita5ff9fa2cf2abbfd316b21518a7193b1594212b8 (patch)
tree417128d3c29312db89e84970122ed5576f23269b
parent449369643e144c636b96f1ec465bbea855a68a0e (diff)
PySide6: Fix connecting signals with arguments by constructor kwargs
The search was only implemented for signals without arguments by appending "()" to the signal name to form the search signature. Implement a search by signal name only. Fixes: PYSIDE-2329 Change-Id: I295150cdebe60c886891553c9f31d14011a004d6 Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io> Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io> (cherry picked from commit 64bacdf74cc7a32cd5bd60ed50bf5cbe998483ff) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--sources/pyside6/libpyside/pyside.cpp27
-rw-r--r--sources/pyside6/tests/QtCore/signal_sender.py30
2 files changed, 51 insertions, 6 deletions
diff --git a/sources/pyside6/libpyside/pyside.cpp b/sources/pyside6/libpyside/pyside.cpp
index 29a3d2884..33a05cc0d 100644
--- a/sources/pyside6/libpyside/pyside.cpp
+++ b/sources/pyside6/libpyside/pyside.cpp
@@ -37,6 +37,7 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
+#include <QtCore/QMetaMethod>
#include <QtCore/QMutex>
#include <QtCore/QStack>
#include <QtCore/QThread>
@@ -45,6 +46,7 @@
#include <cstring>
#include <cctype>
#include <memory>
+#include <optional>
#include <typeinfo>
using namespace Qt::StringLiterals;
@@ -299,6 +301,21 @@ static bool _setProperty(PyObject *qObj, PyObject *name, PyObject *value, bool *
return true;
}
+// PYSIDE-2329: Search a signal by name (Note: QMetaObject::indexOfSignal()
+// searches by signature).
+static std::optional<QMetaMethod> findSignal(const QMetaObject *mo,
+ const QByteArray &name)
+{
+ const auto count = mo->methodCount();
+ for (int i = mo->methodOffset(); i < count; ++i) {
+ const auto method = mo->method(i);
+ if (method.methodType() == QMetaMethod::Signal && method.name() == name)
+ return method;
+ }
+ auto *base = mo->superClass();
+ return base != nullptr ? findSignal(base, name) : std::nullopt;
+}
+
bool fillQtProperties(PyObject *qObj, const QMetaObject *metaObj,
PyObject *kwds, bool allowErrors)
{
@@ -309,7 +326,7 @@ bool fillQtProperties(PyObject *qObj, const QMetaObject *metaObj,
int snake_flag = flags & 0x01;
while (PyDict_Next(kwds, &pos, &key, &value)) {
- QByteArray propName(Shiboken::String::toCString(key));
+ const QByteArray propName = Shiboken::String::toCString(key);
QByteArray unmangledName = _sigWithOrigName(propName, snake_flag);
bool accept = false;
// PYSIDE-1705: Make sure that un-mangled names are not recognized in snake_case mode.
@@ -318,11 +335,11 @@ bool fillQtProperties(PyObject *qObj, const QMetaObject *metaObj,
if (!_setProperty(qObj, key, value, &accept))
return false;
} else {
- propName.append("()");
- if (metaObj->indexOfSignal(propName) != -1) {
+ const auto methodO = findSignal(metaObj, propName);
+ if (methodO.has_value()) {
+ const auto signature = "2"_ba + methodO->methodSignature();
accept = true;
- propName.prepend('2');
- if (!PySide::Signal::connect(qObj, propName, value))
+ if (!PySide::Signal::connect(qObj, signature, value))
return false;
}
}
diff --git a/sources/pyside6/tests/QtCore/signal_sender.py b/sources/pyside6/tests/QtCore/signal_sender.py
index c85dc6da9..2552591e5 100644
--- a/sources/pyside6/tests/QtCore/signal_sender.py
+++ b/sources/pyside6/tests/QtCore/signal_sender.py
@@ -12,7 +12,8 @@ init_test_paths(False)
from helper.usesqapplication import UsesQApplication
-from PySide6.QtCore import QCoreApplication, QObject, QTimer, Signal, Slot
+from PySide6.QtCore import (QCoreApplication, QObject, QStringListModel,
+ QTimer, Signal, Slot, Qt)
class Sender(QObject):
@@ -59,5 +60,32 @@ class TestSignalSender(UsesQApplication):
self.assertEqual(derived_receiver._sender, sender)
+class TestConstructorConnection(UsesQApplication):
+ """PYSIDE-2329: Check constructor connections for signals from the
+ base as well as signals with arguments."""
+ def testConstructorConnection(self):
+
+ was_destroyed = False
+ was_changed = False
+
+ def destroyed_handler():
+ nonlocal was_destroyed
+ was_destroyed = True
+
+ def changed_handler():
+ nonlocal was_changed
+ was_changed = True
+
+ data_list = ["blub"]
+ model = QStringListModel(data_list,
+ destroyed=destroyed_handler,
+ dataChanged=changed_handler)
+ model.setData(model.index(0, 0), "bla", Qt.EditRole)
+ del model
+
+ self.assertTrue(was_changed)
+ self.assertTrue(was_destroyed)
+
+
if __name__ == '__main__':
unittest.main()