diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2023-11-24 17:31:10 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2023-11-29 08:56:12 +0100 |
commit | 51636b43d90bc29996f3bbd8372f333eb1a321d0 (patch) | |
tree | 8157d035daa530d9494dd558f606591eeb88e904 /sources/pyside6/libpyside/pysidesignal.cpp | |
parent | daf77773a72980a369ba6aabcb8cf1ca835bbbe7 (diff) |
Enable connecting signals to slots with default parameters
Find the number of default parameters using PyFunction_GetDefaults()
and change the argCount() helper to return the min/max argument count.
With that, try to match the slot using the most argument.
[ChangeLog][PySide6] It is now possible to connect signals to
slots/lambdas with more arguments provided they have default
parameters.
Fixes: PYSIDE-2524
Change-Id: I134d33e3ee78b62689fa36887a9acd41951c02e1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Shyamnath Premnadh <Shyamnath.Premnadh@qt.io>
Diffstat (limited to 'sources/pyside6/libpyside/pysidesignal.cpp')
-rw-r--r-- | sources/pyside6/libpyside/pysidesignal.cpp | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/sources/pyside6/libpyside/pysidesignal.cpp b/sources/pyside6/libpyside/pysidesignal.cpp index 16e7b8411..0c6a23245 100644 --- a/sources/pyside6/libpyside/pysidesignal.cpp +++ b/sources/pyside6/libpyside/pysidesignal.cpp @@ -441,11 +441,25 @@ static FunctionArgumentsResult extractFunctionArgumentsFromSlot(PyObject *slot) return ret; } -static int argCount(const FunctionArgumentsResult &args) +struct ArgCount +{ + int min; + int max; +}; + +// Return a pair of minimum / arg count "foo(p1, p2=0)" -> {1, 2} +ArgCount argCount(const FunctionArgumentsResult &args) { Q_ASSERT(args.objCode); - return (PepCode_GET_FLAGS(args.objCode) & CO_VARARGS) != 0 - ? -1 : PepCode_GET_ARGCOUNT(args.objCode); + ArgCount result{-1, -1}; + if ((PepCode_GET_FLAGS(args.objCode) & CO_VARARGS) == 0) { + result.min = result.max = PepCode_GET_ARGCOUNT(args.objCode); + if (args.function != nullptr) { + if (auto *defaultArgs = PepFunction_GetDefaults(args.function)) + result.min -= PyTuple_Size(defaultArgs); + } + } + return result; } // Find Signal Instance for argument count. @@ -510,14 +524,19 @@ static PyObject *signalInstanceConnect(PyObject *self, PyObject *args, PyObject PySideSignalInstance *matchedSlot = nullptr; if (args.function != nullptr) { - qsizetype slotArgs = argCount(args); - if (args.isMethod) - slotArgs -= 1; + auto slotArgRange = argCount(args); + if (args.isMethod) { + slotArgRange.min -= 1; + slotArgRange.max -= 1; + } // Get signature args // Iterate the possible types of connection for this signal and compare // it with slot arguments - matchedSlot = findSignalInstance(source, slotArgs); + for (int slotArgs = slotArgRange.max; + slotArgs >= slotArgRange.min && matchedSlot == nullptr; --slotArgs) { + matchedSlot = findSignalInstance(source, slotArgs); + } } // Adding references to pyArgs @@ -1205,7 +1224,7 @@ QByteArray getCallbackSignature(const char *signal, QObject *receiver, qsizetype useSelf = slotArgs.isMethod ? 1 : 0; if (slotArgs.function != nullptr) { - numArgs = argCount(slotArgs); + numArgs = argCount(slotArgs).max; #ifdef PYPY_VERSION } else if (Py_TYPE(callback) == PepBuiltinMethod_TypePtr) { // PYSIDE-535: PyPy has a special builtin method that acts almost like PyCFunction. |