diff options
Diffstat (limited to 'sources/pyside6/PySide6/glue')
25 files changed, 1961 insertions, 1519 deletions
diff --git a/sources/pyside6/PySide6/glue/qhttpserver.cpp b/sources/pyside6/PySide6/glue/qhttpserver.cpp new file mode 100644 index 000000000..b6e485e2c --- /dev/null +++ b/sources/pyside6/PySide6/glue/qhttpserver.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2022 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 + +/********************************************************************* + * INJECT CODE + ********************************************************************/ + +// Note: Lambdas need to be inline, QTBUG-104481 +// @snippet qhttpserver-route +QString rule = %CONVERTTOCPP[QString](%PYARG_1); +auto *callable = %PYARG_2; + +bool cppResult = %CPPSELF.%FUNCTION_NAME(rule, + [callable](const QHttpServerRequest &request) -> QString { + Shiboken::GilState state; + auto *requestPtr = &request; + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + PyTuple_SET_ITEM(arglist, 0, + %CONVERTTOPYTHON[QHttpServerRequest *](requestPtr)); + PyObject *ret = PyObject_CallObject(callable, arglist); + if (PyErr_Occurred()) + PyErr_Print(); + if (ret == nullptr) + return QString{}; + QString cppResult = %CONVERTTOCPP[QString](ret); + return cppResult; +}); + +%PYARG_0 = %CONVERTTOPYTHON[bool](cppResult); +// @snippet qhttpserver-route + +// @snippet qhttpserver-afterrequest +auto *callable = %PYARG_1; + +%CPPSELF.%FUNCTION_NAME([callable](QHttpServerResponse &&response, + const QHttpServerRequest &request) { + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(2)); + auto *responsePtr = &response; + auto *requestPtr = &request; + PyTuple_SET_ITEM(arglist, 0, + %CONVERTTOPYTHON[QHttpServerResponse *](responsePtr)); + PyTuple_SET_ITEM(arglist, 1, + %CONVERTTOPYTHON[QHttpServerRequest *](requestPtr)); + PyObject_CallObject(callable, arglist); + if (PyErr_Occurred()) + PyErr_Print(); + return std::move(response); +}); +// @snippet qhttpserver-afterrequest diff --git a/sources/pyside6/PySide6/glue/qtcharts.cpp b/sources/pyside6/PySide6/glue/qtcharts.cpp index 7171f19df..a99dbbb8a 100644 --- a/sources/pyside6/PySide6/glue/qtcharts.cpp +++ b/sources/pyside6/PySide6/glue/qtcharts.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 // @snippet qchart-releaseownership Shiboken::Object::releaseOwnership(%PYARG_1); diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp index 76b0ec0d7..0c206db72 100644 --- a/sources/pyside6/PySide6/glue/qtcore.cpp +++ b/sources/pyside6/PySide6/glue/qtcore.cpp @@ -1,51 +1,174 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 /********************************************************************* * INJECT CODE ********************************************************************/ // @snippet include-pyside -#include <pyside.h> +#include <pysideinit.h> #include <limits> +#include "glue/core_snippets_p.h" // @snippet include-pyside +// @snippet core-snippets-p-h +#include "glue/core_snippets_p.h" +// @snippet core-snippets-p-h + +// @snippet qarg_helper + +// Helper for the Q_ARG/Q_RETURN_ARG functions, creating a meta type +// and instance. +struct QArgData +{ + operator bool() const { return metaType.isValid() && data != nullptr; } + + QMetaType metaType; + void *data = nullptr; +}; + +QArgData qArgDataFromPyType(PyObject *t) +{ + QArgData result; + const char *typeName{}; + if (PyType_Check(t)) { + auto *pyType = reinterpret_cast<PyTypeObject *>(t); + typeName = pyType->tp_name; + result.metaType = PySide::qMetaTypeFromPyType(pyType); + } else if (PyUnicode_Check(t)) { + typeName = Shiboken::String::toCString(t); + result.metaType = QMetaType::fromName(typeName); + } else { + PyErr_Format(PyExc_RuntimeError, "%s: Parameter should be a type or type string.", + __FUNCTION__); + return result; + } + + if (!result.metaType.isValid()) { + PyErr_Format(PyExc_RuntimeError, "%s: Unable to find a QMetaType for \"%s\".", + __FUNCTION__, typeName); + return result; + } + + result.data = result.metaType.create(); + if (result.data == nullptr) { + PyErr_Format(PyExc_RuntimeError, "%s: Unable to create an instance of \"%s\" (%s).", + __FUNCTION__, typeName, result.metaType.name()); + return result; + } + return result; +} +// @snippet qarg_helper + +// @snippet settings-value-helpers +// Convert a QVariant to a desired primitive type +static PyObject *convertToPrimitiveType(const QVariant &out, int metaTypeId) +{ + switch (metaTypeId) { + case QMetaType::QByteArray: + return PyBytes_FromString(out.toByteArray().constData()); + case QMetaType::QString: + return PyUnicode_FromString(out.toByteArray().constData()); + case QMetaType::Short: + case QMetaType::Long: + case QMetaType::LongLong: + case QMetaType::UShort: + case QMetaType::ULong: + case QMetaType::ULongLong: + case QMetaType::Int: + case QMetaType::UInt: + return PyLong_FromDouble(out.toFloat()); + case QMetaType::Double: + case QMetaType::Float: + case QMetaType::Float16: + return PyFloat_FromDouble(out.toFloat()); + case QMetaType::Bool: + if (out.toBool()) { + Py_RETURN_TRUE; + } + Py_RETURN_FALSE; + default: + break; + } + return nullptr; +} + +// Helper for QSettings::value() to convert a value to the desired type +static PyObject *settingsTypeCoercion(const QVariant &out, PyTypeObject *typeObj) +{ + if (typeObj == &PyList_Type) { + // Convert any string, etc, to a list of 1 element + if (auto *primitiveValue = convertToPrimitiveType(out, out.typeId())) { + PyObject *list = PyList_New(1); + PyList_SET_ITEM(list, 0, primitiveValue); + return list; + } + + const QByteArray out_ba = out.toByteArray(); + if (out_ba.isEmpty()) + return PyList_New(0); + + const QByteArrayList valuesList = out_ba.split(','); + const Py_ssize_t valuesSize = valuesList.size(); + PyObject *list = PyList_New(valuesSize); + for (Py_ssize_t i = 0; i < valuesSize; ++i) { + PyObject *item = PyUnicode_FromString(valuesList.at(i).constData()); + PyList_SET_ITEM(list, i, item); + } + return list; + } + + if (typeObj == &PyBytes_Type) + return convertToPrimitiveType(out, QMetaType::QByteArray); + if (typeObj == &PyUnicode_Type) + return convertToPrimitiveType(out, QMetaType::QString); + if (typeObj == &PyLong_Type) + return convertToPrimitiveType(out, QMetaType::Int); + if (typeObj == &PyFloat_Type) + return convertToPrimitiveType(out, QMetaType::Double); + if (typeObj == &PyBool_Type) + return convertToPrimitiveType(out, QMetaType::Bool); + + // TODO: PyDict_Type and PyTuple_Type + PyErr_SetString(PyExc_TypeError, + "Invalid type parameter.\n" + "\tUse 'list', 'bytes', 'str', 'int', 'float', 'bool', " + "or a Qt-derived type"); + return nullptr; +} + +static bool isEquivalentSettingsType(PyTypeObject *typeObj, int metaTypeId) +{ + switch (metaTypeId) { + case QMetaType::QVariantList: + case QMetaType::QStringList: + return typeObj == &PyList_Type; + case QMetaType::QByteArray: + return typeObj == &PyBytes_Type; + case QMetaType::QString: + return typeObj == &PyUnicode_Type; + case QMetaType::Short: + case QMetaType::Long: + case QMetaType::LongLong: + case QMetaType::UShort: + case QMetaType::ULong: + case QMetaType::ULongLong: + case QMetaType::Int: + case QMetaType::UInt: + return typeObj == &PyLong_Type; + case QMetaType::Double: + case QMetaType::Float: + case QMetaType::Float16: + return typeObj == &PyFloat_Type; + case QMetaType::Bool: + return typeObj == &PyBool_Type; + default: + break; + } + return false; +} +// @snippet settings-value-helpers + // @snippet qsettings-value // If we enter the kwds, means that we have a defaultValue or // at least a type. @@ -66,78 +189,32 @@ if ((kwds && PyDict_Size(kwds) > 0) || numArgs > 1) { PyTypeObject *typeObj = reinterpret_cast<PyTypeObject*>(%PYARG_3); -if (typeObj && !Shiboken::ObjectType::checkType(typeObj)) { - if (typeObj == &PyList_Type) { - QByteArray out_ba = out.toByteArray(); - if (!out_ba.isEmpty()) { - QByteArrayList valuesList = out_ba.split(','); - const Py_ssize_t valuesSize = valuesList.size(); - if (valuesSize > 0) { - PyObject *list = PyList_New(valuesSize); - for (Py_ssize_t i = 0; i < valuesSize; ++i) { - PyObject *item = PyUnicode_FromString(valuesList.at(i).constData()); - PyList_SET_ITEM(list, i, item); - } - %PYARG_0 = list; - - } else { - %PYARG_0 = %CONVERTTOPYTHON[QVariant](out); - } - } else { - %PYARG_0 = PyList_New(0); - } - } else if (typeObj == &PyBytes_Type) { - QByteArray asByteArray = out.toByteArray(); - %PYARG_0 = PyBytes_FromString(asByteArray.constData()); - } else if (typeObj == &PyUnicode_Type) { - QByteArray asByteArray = out.toByteArray(); - %PYARG_0 = PyUnicode_FromString(asByteArray.constData()); - } else if (typeObj == &PyLong_Type) { - float asFloat = out.toFloat(); - pyResult = PyLong_FromDouble(asFloat); - } else if (typeObj == &PyFloat_Type) { - float asFloat = out.toFloat(); - %PYARG_0 = PyFloat_FromDouble(asFloat); - } else if (typeObj == &PyBool_Type) { - if (out.toBool()) { - Py_INCREF(Py_True); - %PYARG_0 = Py_True; - } else { - Py_INCREF(Py_False); - %PYARG_0 = Py_False; - } +if (typeObj && !Shiboken::ObjectType::checkType(typeObj) + && !isEquivalentSettingsType(typeObj, out.typeId())) { + %PYARG_0 = settingsTypeCoercion(out, typeObj); +} else { + if (out.isValid()) { + %PYARG_0 = %CONVERTTOPYTHON[QVariant](out); } else { - // TODO: PyDict_Type and PyTuple_Type - PyErr_SetString(PyExc_TypeError, - "Invalid type parameter.\n" - "\tUse 'list', 'bytes', 'str', 'int', 'float', 'bool', " - "or a Qt-derived type"); - return nullptr; - } -} -else { - if (!out.isValid()) { Py_INCREF(Py_None); %PYARG_0 = Py_None; - } else { - %PYARG_0 = %CONVERTTOPYTHON[QVariant](out); } } // @snippet qsettings-value +// @snippet metatype-from-type +%0 = new %TYPE(PySide::qMetaTypeFromPyType(reinterpret_cast<PyTypeObject *>(%1))); +// @snippet metatype-from-type + +// @snippet metatype-from-metatype-type +Shiboken::AutoDecRef intArg(PyObject_GetAttrString(%PYARG_1, "value")); +%0 = new %TYPE(PyLong_AsLong(intArg)); +// @snippet metatype-from-metatype-type + // @snippet conversion-pytypeobject-qmetatype -auto *pyType = reinterpret_cast<PyTypeObject *&>(%in); -if (Shiboken::String::checkType(pyType)) - %out = QMetaType(QMetaType::QString); -else if (%in == reinterpret_cast<PyObject *>(&PyFloat_Type)) - %out = QMetaType(QMetaType::Double); -else if (%in == reinterpret_cast<PyObject *>(&PyLong_Type)) - %out = QMetaType(QMetaType::Int); -else if (Py_TYPE(%in) == SbkObjectType_TypeF()) - %out = QMetaType::fromName(Shiboken::ObjectType::getOriginalName(pyType)); -else - %out = QMetaType::fromName(pyType->tp_name); +auto *pyType = reinterpret_cast<PyTypeObject *>(%in); +%out = PySide::qMetaTypeFromPyType(pyType); // @snippet conversion-pytypeobject-qmetatype // @snippet conversion-qmetatype-pytypeobject @@ -148,96 +225,12 @@ return %out; // @snippet conversion-qmetatype-pytypeobject // @snippet qvariant-conversion -static QMetaType QVariant_resolveMetaType(PyTypeObject *type) -{ - if (PyObject_TypeCheck(type, SbkObjectType_TypeF())) { - const char *typeName = Shiboken::ObjectType::getOriginalName(type); - if (!typeName) - return {}; - const bool valueType = '*' != typeName[qstrlen(typeName) - 1]; - // Do not convert user type of value - if (valueType && Shiboken::ObjectType::isUserType(type)) - return {}; - QMetaType metaType = QMetaType::fromName(typeName); - if (metaType.isValid()) - return metaType; - // Do not resolve types to value type - if (valueType) - return {}; - // Find in base types. First check tp_bases, and only after check tp_base, because - // tp_base does not always point to the first base class, but rather to the first - // that has added any python fields or slots to its object layout. - // See https://mail.python.org/pipermail/python-list/2009-January/520733.html - if (type->tp_bases) { - for (int i = 0, size = PyTuple_GET_SIZE(type->tp_bases); i < size; ++i) { - auto baseType = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(type->tp_bases, i)); - const QMetaType derived = QVariant_resolveMetaType(baseType); - if (derived.isValid()) - return derived; - } - } else if (type->tp_base) { - return QVariant_resolveMetaType(type->tp_base); - } - } - return {}; -} -static QVariant QVariant_convertToValueList(PyObject *list) -{ - if (PySequence_Size(list) < 0) { - // clear the error if < 0 which means no length at all - PyErr_Clear(); - return QVariant(); - } - - Shiboken::AutoDecRef element(PySequence_GetItem(list, 0)); - - const QMetaType metaType = QVariant_resolveMetaType(element.cast<PyTypeObject *>()); - if (metaType.isValid()) { - QByteArray listTypeName("QList<"); - listTypeName += metaType.name(); - listTypeName += '>'; - QMetaType metaType = QMetaType::fromName(listTypeName); - if (metaType.isValid()) { - Shiboken::Conversions::SpecificConverter converter(listTypeName); - if (converter) { - QVariant var(metaType); - converter.toCpp(list, &var); - return var; - } - qWarning() << "Type converter for :" << listTypeName << "not registered."; - } - } - return QVariant(); -} -static bool QVariant_isStringList(PyObject *list) -{ - if (!PySequence_Check(list)) { - // If it is not a list or a derived list class - // we assume that will not be a String list neither. - return false; - } - - if (PySequence_Size(list) < 0) { - // clear the error if < 0 which means no length at all - PyErr_Clear(); - return false; - } - - Shiboken::AutoDecRef fast(PySequence_Fast(list, "Failed to convert QVariantList")); - const Py_ssize_t size = PySequence_Fast_GET_SIZE(fast.object()); - for (Py_ssize_t i = 0; i < size; ++i) { - PyObject *item = PySequence_Fast_GET_ITEM(fast.object(), i); - if (!%CHECKTYPE[QString](item)) - return false; - } - return true; -} static QVariant QVariant_convertToVariantMap(PyObject *map) { Py_ssize_t pos = 0; Shiboken::AutoDecRef keys(PyDict_Keys(map)); if (!QVariant_isStringList(keys)) - return QVariant(); + return {}; PyObject *key; PyObject *value; QMap<QString,QVariant> ret; @@ -261,7 +254,7 @@ static QVariant QVariant_convertToVariantList(PyObject *list) if (PySequence_Size(list) < 0) { // clear the error if < 0 which means no length at all PyErr_Clear(); - return QVariant(); + return {}; } QList<QVariant> lst; @@ -274,6 +267,30 @@ static QVariant QVariant_convertToVariantList(PyObject *list) } return QVariant(lst); } + +using SpecificConverter = Shiboken::Conversions::SpecificConverter; + +static std::optional<SpecificConverter> converterForQtType(const char *typeNameC) +{ + // Fix typedef "QGenericMatrix<3,3,float>" -> QMatrix3x3". The reverse + // conversion happens automatically in QMetaType::fromName() in + // QVariant_resolveMetaType(). + QByteArrayView typeNameV(typeNameC); + if (typeNameV.startsWith("QGenericMatrix<") && typeNameV.endsWith(",float>")) { + QByteArray typeName = typeNameV.toByteArray(); + typeName.remove(1, 7); + typeName.remove(7, 1); // '<' + typeName.chop(7); + typeName.replace(',', 'x'); + SpecificConverter matrixConverter(typeName.constData()); + if (matrixConverter) + return matrixConverter; + } + SpecificConverter converter(typeNameC); + if (converter) + return converter; + return std::nullopt; +} // @snippet qvariant-conversion // @snippet qt-qabs @@ -281,30 +298,6 @@ double _abs = qAbs(%1); %PYARG_0 = %CONVERTTOPYTHON[double](_abs); // @snippet qt-qabs -// @snippet qt-postroutine -namespace PySide { -static QStack<PyObject *> globalPostRoutineFunctions; -void globalPostRoutineCallback() -{ - Shiboken::GilState state; - for (auto *callback : globalPostRoutineFunctions) { - Shiboken::AutoDecRef result(PyObject_CallObject(callback, nullptr)); - Py_DECREF(callback); - } - globalPostRoutineFunctions.clear(); -} -void addPostRoutine(PyObject *callback) -{ - if (PyCallable_Check(callback)) { - globalPostRoutineFunctions << callback; - Py_INCREF(callback); - } else { - PyErr_SetString(PyExc_TypeError, "qAddPostRoutine: The argument must be a callable object."); - } -} -} // namespace -// @snippet qt-postroutine - // @snippet qt-addpostroutine PySide::addPostRoutine(%1); // @snippet qt-addpostroutine @@ -313,6 +306,18 @@ PySide::addPostRoutine(%1); qAddPostRoutine(PySide::globalPostRoutineCallback); // @snippet qt-qaddpostroutine +// @snippet qcompress-buffer +auto *ptr = reinterpret_cast<uchar*>(Shiboken::Buffer::getPointer(%PYARG_1)); +QByteArray compressed = %FUNCTION_NAME(ptr, %2, %3); +%PYARG_0 = %CONVERTTOPYTHON[QByteArray](compressed); +// @snippet qcompress-buffer + +// @snippet quncompress-buffer +auto *ptr = reinterpret_cast<uchar*>(Shiboken::Buffer::getPointer(%PYARG_1)); +QByteArray uncompressed = %FUNCTION_NAME(ptr, %2); +%PYARG_0 = %CONVERTTOPYTHON[QByteArray](uncompressed); +// @snippet quncompress-buffer + // @snippet qt-version QList<QByteArray> version = QByteArray(qVersion()).split('.'); PyObject *pyQtVersion = PyTuple_New(3); @@ -323,265 +328,48 @@ PyModule_AddStringConstant(module, "__version__", qVersion()); // @snippet qt-version // @snippet qobject-connect -static bool isMethodDecorator(PyObject *method, bool is_pymethod, PyObject *self) -{ - Shiboken::AutoDecRef methodName(PyObject_GetAttr(method, Shiboken::PyMagicName::name())); - if (!PyObject_HasAttr(self, methodName)) - return true; - Shiboken::AutoDecRef otherMethod(PyObject_GetAttr(self, methodName)); - - PyObject *function1, *function2; - - // PYSIDE-1523: Each could be a compiled method or a normal method here, for the - // compiled ones we can use the attributes. - if (PyMethod_Check(otherMethod.object())) { - function1 = PyMethod_GET_FUNCTION(otherMethod.object()); - } else { - function1 = PyObject_GetAttr(otherMethod.object(), Shiboken::PyName::im_func()); - Py_DECREF(function1); - // Not retaining a reference inline with what PyMethod_GET_FUNCTION does. - } - - if (is_pymethod) { - function2 = PyMethod_GET_FUNCTION(method); - } else { - function2 = PyObject_GetAttr(method, Shiboken::PyName::im_func()); - Py_DECREF(function2); - // Not retaining a reference inline with what PyMethod_GET_FUNCTION does. - } - - return function1 != function2; -} - -static bool getReceiver(QObject *source, - const char *signal, - PyObject *callback, - QObject **receiver, - PyObject **self, - QByteArray *callbackSig) -{ - bool forceGlobalReceiver = false; - if (PyMethod_Check(callback)) { - *self = PyMethod_GET_SELF(callback); - if (%CHECKTYPE[QObject *](*self)) - *receiver = %CONVERTTOCPP[QObject *](*self); - forceGlobalReceiver = isMethodDecorator(callback, true, *self); - } else if (PyCFunction_Check(callback)) { - *self = PyCFunction_GET_SELF(callback); - if (*self && %CHECKTYPE[QObject *](*self)) - *receiver = %CONVERTTOCPP[QObject *](*self); - } else if (PyObject_HasAttr(callback, Shiboken::PyName::im_func()) - && PyObject_HasAttr(callback, Shiboken::PyName::im_self())) { - *self = PyObject_GetAttr(callback, Shiboken::PyName::im_self()); - Py_DECREF(*self); - - if (%CHECKTYPE[QObject *](*self)) - *receiver = %CONVERTTOCPP[QObject *](*self); - forceGlobalReceiver = isMethodDecorator(callback, false, *self); - } else if (PyCallable_Check(callback)) { - // Ok, just a callable object - *receiver = nullptr; - *self = nullptr; - } - - bool usingGlobalReceiver = !*receiver || forceGlobalReceiver; - - // Check if this callback is a overwrite of a non-virtual Qt slot. - if (!usingGlobalReceiver && receiver && self) { - *callbackSig = PySide::Signal::getCallbackSignature(signal, *receiver, callback, usingGlobalReceiver).toLatin1(); - const QMetaObject *metaObject = (*receiver)->metaObject(); - int slotIndex = metaObject->indexOfSlot(callbackSig->constData()); - if (slotIndex != -1 && slotIndex < metaObject->methodOffset() && PyMethod_Check(callback)) - usingGlobalReceiver = true; - } - - const auto receiverThread = *receiver ? (*receiver)->thread() : nullptr; - - if (usingGlobalReceiver) { - PySide::SignalManager &signalManager = PySide::SignalManager::instance(); - *receiver = signalManager.globalReceiver(source, callback); - // PYSIDE-1354: Move the global receiver to the original receivers's thread - // so that autoconnections work correctly. - if (receiverThread && receiverThread != (*receiver)->thread()) - (*receiver)->moveToThread(receiverThread); - *callbackSig = PySide::Signal::getCallbackSignature(signal, *receiver, callback, usingGlobalReceiver).toLatin1(); - } - - return usingGlobalReceiver; -} - -static QMetaObject::Connection qobjectConnect(QObject *source, const char *signal, - QObject *receiver, const char *slot, - Qt::ConnectionType type) -{ - if (!signal || !slot) - return {}; - - if (!PySide::Signal::checkQtSignal(signal)) - return {}; - signal++; - - if (!PySide::SignalManager::registerMetaMethod(source, signal, QMetaMethod::Signal)) - return {}; - - bool isSignal = PySide::Signal::isQtSignal(slot); - slot++; - PySide::SignalManager::registerMetaMethod(receiver, slot, isSignal ? QMetaMethod::Signal : QMetaMethod::Slot); - return QObject::connect(source, signal - 1, receiver, slot - 1, type); -} - -static QMetaObject::Connection qobjectConnect(QObject *source, QMetaMethod signal, - QObject *receiver, QMetaMethod slot, - Qt::ConnectionType type) -{ - return qobjectConnect(source, signal.methodSignature(), receiver, slot.methodSignature(), type); -} - -static QMetaObject::Connection qobjectConnectCallback(QObject *source, const char *signal, - PyObject *callback, Qt::ConnectionType type) -{ - if (!signal || !PySide::Signal::checkQtSignal(signal)) - return {}; - signal++; - - int signalIndex = PySide::SignalManager::registerMetaMethodGetIndex(source, signal, QMetaMethod::Signal); - if (signalIndex == -1) - return {}; - - PySide::SignalManager &signalManager = PySide::SignalManager::instance(); - - // Extract receiver from callback - QObject *receiver = nullptr; - PyObject *self = nullptr; - QByteArray callbackSig; - bool usingGlobalReceiver = getReceiver(source, signal, callback, &receiver, &self, &callbackSig); - if (receiver == nullptr && self == nullptr) - return {}; - - const QMetaObject *metaObject = receiver->metaObject(); - const char *slot = callbackSig.constData(); - int slotIndex = metaObject->indexOfSlot(slot); - QMetaMethod signalMethod = metaObject->method(signalIndex); - - if (slotIndex == -1) { - if (!usingGlobalReceiver && self && !Shiboken::Object::hasCppWrapper(reinterpret_cast<SbkObject *>(self))) { - qWarning("You can't add dynamic slots on an object originated from C++."); - if (usingGlobalReceiver) - signalManager.releaseGlobalReceiver(source, receiver); - - return {}; - } - - if (usingGlobalReceiver) - slotIndex = signalManager.globalReceiverSlotIndex(receiver, slot); - else - slotIndex = PySide::SignalManager::registerMetaMethodGetIndex(receiver, slot, QMetaMethod::Slot); - - if (slotIndex == -1) { - if (usingGlobalReceiver) - signalManager.releaseGlobalReceiver(source, receiver); - - return {}; - } - } - auto connection = QMetaObject::connect(source, signalIndex, receiver, slotIndex, type); - if (connection) { - if (usingGlobalReceiver) - signalManager.notifyGlobalReceiver(receiver); - #ifndef AVOID_PROTECTED_HACK - source->connectNotify(signalMethod); //Qt5: QMetaMethod instead of char * - #else - // Need to cast to QObjectWrapper * and call the public version of - // connectNotify when avoiding the protected hack. - reinterpret_cast<QObjectWrapper *>(source)->connectNotify(signalMethod); //Qt5: QMetaMethod instead of char * - #endif - - return connection; - } - - if (usingGlobalReceiver) - signalManager.releaseGlobalReceiver(source, receiver); - - return {}; -} - - -static bool qobjectDisconnectCallback(QObject *source, const char *signal, PyObject *callback) -{ - if (!PySide::Signal::checkQtSignal(signal)) - return false; - - PySide::SignalManager &signalManager = PySide::SignalManager::instance(); - - // Extract receiver from callback - QObject *receiver = nullptr; - PyObject *self = nullptr; - QByteArray callbackSig; - QMetaMethod slotMethod; - bool usingGlobalReceiver = getReceiver(nullptr, signal, callback, &receiver, &self, &callbackSig); - if (receiver == nullptr && self == nullptr) - return false; - - const QMetaObject *metaObject = receiver->metaObject(); - int signalIndex = source->metaObject()->indexOfSignal(++signal); - int slotIndex = -1; - - slotIndex = metaObject->indexOfSlot(callbackSig); - slotMethod = metaObject->method(slotIndex); - - bool disconnected; - disconnected = QMetaObject::disconnectOne(source, signalIndex, receiver, slotIndex); - - if (disconnected) { - if (usingGlobalReceiver) - signalManager.releaseGlobalReceiver(source, receiver); - - #ifndef AVOID_PROTECTED_HACK - source->disconnectNotify(slotMethod); //Qt5: QMetaMethod instead of char * - #else - // Need to cast to QObjectWrapper * and call the public version of - // connectNotify when avoiding the protected hack. - reinterpret_cast<QObjectWrapper *>(source)->disconnectNotify(slotMethod); //Qt5: QMetaMethod instead of char * - #endif - return true; - } - return false; -} +#include <qobjectconnect.h> // @snippet qobject-connect // @snippet qobject-connect-1 // %FUNCTION_NAME() - disable generation of function call. -%RETURN_TYPE %0 = qobjectConnect(%1, %2, %CPPSELF, %3, %4); +%RETURN_TYPE %0 = PySide::qobjectConnect(%1, %2, %CPPSELF, %3, %4); %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); // @snippet qobject-connect-1 // @snippet qobject-connect-2 // %FUNCTION_NAME() - disable generation of function call. -%RETURN_TYPE %0 = qobjectConnect(%1, %2, %3, %4, %5); +%RETURN_TYPE %0 = PySide::qobjectConnect(%1, %2, %3, %4, %5); %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); // @snippet qobject-connect-2 // @snippet qobject-connect-3 // %FUNCTION_NAME() - disable generation of function call. -%RETURN_TYPE %0 = qobjectConnect(%1, %2, %3, %4, %5); +%RETURN_TYPE %0 = PySide::qobjectConnect(%1, %2, %3, %4, %5); %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); // @snippet qobject-connect-3 // @snippet qobject-connect-4 // %FUNCTION_NAME() - disable generation of function call. -%RETURN_TYPE %0 = qobjectConnectCallback(%1, %2, %PYARG_3, %4); +%RETURN_TYPE %0 = PySide::qobjectConnectCallback(%1, %2, %PYARG_3, %4); %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 = qobjectConnectCallback(%CPPSELF, %1, %PYARG_2, %3); +%RETURN_TYPE %0 = PySide::qobjectConnectCallback(%CPPSELF, %1, %PYARG_2, %3); %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); // @snippet qobject-connect-5 // @snippet qobject-connect-6 // %FUNCTION_NAME() - disable generation of function call. -%RETURN_TYPE %0 = qobjectConnect(%CPPSELF, %1, %2, %3, %4); +%RETURN_TYPE %0 = PySide::qobjectConnect(%CPPSELF, %1, %2, %3, %4); %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); // @snippet qobject-connect-6 @@ -592,13 +380,13 @@ static bool qobjectDisconnectCallback(QObject *source, const char *signal, PyObj // @snippet qobject-disconnect-1 // %FUNCTION_NAME() - disable generation of function call. -%RETURN_TYPE %0 = qobjectDisconnectCallback(%CPPSELF, %1, %2); +%RETURN_TYPE %0 = PySide::qobjectDisconnectCallback(%CPPSELF, %1, %2); %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); // @snippet qobject-disconnect-1 // @snippet qobject-disconnect-2 // %FUNCTION_NAME() - disable generation of function call. -%RETURN_TYPE %0 = qobjectDisconnectCallback(%1, %2, %3); +%RETURN_TYPE %0 = PySide::qobjectDisconnectCallback(%1, %2, %3); %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); // @snippet qobject-disconnect-2 @@ -629,10 +417,10 @@ PySide::Feature::init(); // @snippet qt-init-feature // @snippet qt-pysideinit -Shiboken::Conversions::registerConverterName(SbkPySide6_QtCoreTypeConverters[SBK_QSTRING_IDX], "unicode"); -Shiboken::Conversions::registerConverterName(SbkPySide6_QtCoreTypeConverters[SBK_QSTRING_IDX], "str"); -Shiboken::Conversions::registerConverterName(SbkPySide6_QtCoreTypeConverters[SBK_QTCORE_QLIST_QVARIANT_IDX], "QVariantList"); -Shiboken::Conversions::registerConverterName(SbkPySide6_QtCoreTypeConverters[SBK_QTCORE_QMAP_QSTRING_QVARIANT_IDX], "QVariantMap"); +Shiboken::Conversions::registerConverterName(SbkPySide6_QtCoreTypeConverters[SBK_QString_IDX], "unicode"); +Shiboken::Conversions::registerConverterName(SbkPySide6_QtCoreTypeConverters[SBK_QString_IDX], "str"); +Shiboken::Conversions::registerConverterName(SbkPySide6_QtCoreTypeConverters[SBK_QtCore_QList_QVariant_IDX], "QVariantList"); +Shiboken::Conversions::registerConverterName(SbkPySide6_QtCoreTypeConverters[SBK_QtCore_QMap_QString_QVariant_IDX], "QVariantMap"); PySide::registerInternalQtConf(); PySide::init(module); @@ -682,8 +470,7 @@ if (%PYARG_0 == Py_None) namespace PySide { template<> inline Py_ssize_t hash(const QLine &l) { - const int v[4] = {l.x1(), l.y1(), l.x2(), l.y2()}; - return qHashRange(v, v + 4); + return qHashMulti(0, l.x1(), l.y1(), l.x2(), l.y2()); } }; // @snippet qline-hash @@ -741,6 +528,12 @@ QTime time(%4, %5, %6); %0 = new %TYPE(date, time); // @snippet qdatetime-2 +// @snippet qdatetime-3 +QDate date(%1, %2, %3); +QTime time(%4, %5, %6, %7); +%0 = new %TYPE(date, time, %8); +// @snippet qdatetime-3 + // @snippet qdatetime-topython QDate date = %CPPSELF.date(); QTime time = %CPPSELF.time(); @@ -749,31 +542,6 @@ if (!PyDateTimeAPI) %PYARG_0 = PyDateTime_FromDateAndTime(date.year(), date.month(), date.day(), time.hour(), time.minute(), time.second(), time.msec()*1000); // @snippet qdatetime-topython -// @snippet qpoint -namespace PySide { - template<> inline Py_ssize_t hash(const QPoint &v) { - return qHash(qMakePair(v.x(), v.y())); - } -}; -// @snippet qpoint - -// @snippet qrect -namespace PySide { - template<> inline Py_ssize_t hash(const QRect &r) { - const int v[4] = {r.x(), r.y(), r.width(), r.height()}; - return qHashRange(v, v + 4); - } -}; -// @snippet qrect - -// @snippet qsize -namespace PySide { - template<> inline Py_ssize_t hash(const QSize &v) { - return qHash(qMakePair(v.width(), v.height())); - } -}; -// @snippet qsize - // @snippet qtime-topython if (!PyDateTimeAPI) PyDateTime_IMPORT; @@ -801,6 +569,11 @@ Py_XDECREF(result); return !result ? -1 : 0; // @snippet qbitarray-setitem +// @snippet default-enter +Py_INCREF(%PYSELF); +pyResult = %PYSELF; +// @snippet default-enter + // @snippet qsignalblocker-unblock %CPPSELF.unblock(); // @snippet qsignalblocker-unblock @@ -823,174 +596,83 @@ qRegisterMetaType<QList<int> >("QList<int>"); %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); // @snippet qobject-metaobject -// @snippet qobject-findchild-1 -static bool _findChildTypeMatch(const QObject *child, PyTypeObject *desiredType) -{ - auto *pyChildType = PySide::getTypeForQObject(child); - return pyChildType != nullptr && PyType_IsSubtype(pyChildType, desiredType); -} - -static inline bool _findChildrenComparator(const QObject *child, - const QRegularExpression &name) -{ - return name.match(child->objectName()).hasMatch(); -} - -static inline bool _findChildrenComparator(const QObject *child, - const QString &name) -{ - return name.isNull() || name == child->objectName(); -} - -static QObject *_findChildHelper(const QObject *parent, const QString &name, - PyTypeObject *desiredType, - Qt::FindChildOptions options) -{ - for (auto *child : parent->children()) { - if (_findChildrenComparator(child, name) - && _findChildTypeMatch(child, desiredType)) { - return child; - } - } - - if (options.testFlag(Qt::FindChildrenRecursively)) { - for (auto *child : parent->children()) { - QObject *obj = _findChildHelper(child, name, desiredType, options); - if (obj) - return obj; - } - } - return nullptr; -} - -template<typename T> // QString/QRegularExpression -static void _findChildrenHelper(const QObject *parent, const T& name, PyTypeObject *desiredType, - Qt::FindChildOptions options, - PyObject *result) -{ - for (const auto *child : parent->children()) { - if (_findChildrenComparator(child, name) && - _findChildTypeMatch(child, desiredType)) { - Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QObject *](child)); - PyList_Append(result, pyChild.object()); - } - if (options.testFlag(Qt::FindChildrenRecursively)) - _findChildrenHelper(child, name, desiredType, options, result); - } -} -// @snippet qobject-findchild-1 - // @snippet qobject-findchild-2 -QObject *child = _findChildHelper(%CPPSELF, %2, reinterpret_cast<PyTypeObject *>(%PYARG_1), %3); +QObject *child = qObjectFindChild(%CPPSELF, %2, reinterpret_cast<PyTypeObject *>(%PYARG_1), %3); %PYARG_0 = %CONVERTTOPYTHON[QObject *](child); // @snippet qobject-findchild-2 // @snippet qobject-findchildren %PYARG_0 = PyList_New(0); -_findChildrenHelper(%CPPSELF, %2, reinterpret_cast<PyTypeObject *>(%PYARG_1), %3, %PYARG_0); +qObjectFindChildren(%CPPSELF, %2, reinterpret_cast<PyTypeObject *>(%PYARG_1), %3, + [%PYARG_0](QObject *child) { + Shiboken::AutoDecRef pyChild(%CONVERTTOPYTHON[QObject *](child)); + PyList_Append(%PYARG_0, pyChild.object()); + }); // @snippet qobject-findchildren -////////////////////////////////////////////////////////////////////////////// -// PYSIDE-131: Use the class name as context where the calling function is -// living. Derived Python classes have the wrong context. -// -// The original patch uses Python introspection to look up the current -// function (from the frame stack) in the class __dict__ along the mro. -// -// The problem is that looking into the frame stack works for Python -// functions, only. For including builtin function callers, the following -// approach turned out to be much simpler: -// -// Walk the __mro__ -// - translate the string -// - if the translated string is changed: -// - return the translation. - // @snippet qobject-tr -PyTypeObject *type = reinterpret_cast<PyTypeObject *>(%PYSELF); -PyObject *mro = type->tp_mro; -auto len = PyTuple_GET_SIZE(mro); -QString result = QString::fromUtf8(%1); -QString oldResult = result; -static auto *sbkObjectType = reinterpret_cast<PyTypeObject *>(SbkObject_TypeF()); -for (Py_ssize_t idx = 0; idx < len - 1; ++idx) { - // Skip the last class which is `object`. - auto *type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx)); - if (type == sbkObjectType) - continue; - const char *context = type->tp_name; - const char *dotpos = strrchr(context, '.'); - if (dotpos != nullptr) - context = dotpos + 1; - result = QCoreApplication::translate(context, %1, %2, %3); - if (result != oldResult) - break; -} +const QString result = qObjectTr(reinterpret_cast<PyTypeObject *>(%PYSELF), %1, %2, %3); %PYARG_0 = %CONVERTTOPYTHON[QString](result); // @snippet qobject-tr -// @snippet qobject-receivers -// Avoid return +1 because SignalManager connect to "destroyed()" signal to control object timelife -int ret = %CPPSELF.%FUNCTION_NAME(%1); -if (ret > 0 && ((strcmp(%1, SIGNAL(destroyed())) == 0) || (strcmp(%1, SIGNAL(destroyed(QObject*))) == 0))) - ret -= PySide::SignalManager::instance().countConnectionsWith(%CPPSELF); - -%PYARG_0 = %CONVERTTOPYTHON[int](ret); -// @snippet qobject-receivers +// @snippet qobject-sender +// Retrieve the sender from a dynamic property set by GlobalReceiverV2 in case of a +// non-C++ slot (Python callback). +auto *ret = %CPPSELF.%FUNCTION_NAME(); +if (ret == nullptr) { + auto senderV = %CPPSELF.property("_q_pyside_sender"); + if (senderV.typeId() == QMetaType::QObjectStar) + ret = senderV.value<QObject *>(); +} +%PYARG_0 = %CONVERTTOPYTHON[QObject*](ret); +// @snippet qobject-sender // @snippet qbytearray-mgetitem if (PyIndex_Check(_key)) { - Py_ssize_t _i; - _i = PyNumber_AsSsize_t(_key, PyExc_IndexError); - if (_i < 0 || _i >= %CPPSELF.size()) { - PyErr_SetString(PyExc_IndexError, "index out of bounds"); - return 0; - } else { - char res[2]; - res[0] = %CPPSELF.at(_i); - res[1] = 0; - return PyBytes_FromStringAndSize(res, 1); - } -} else if (PySlice_Check(_key)) { - Py_ssize_t start, stop, step, slicelength, cur; - if (PySlice_GetIndicesEx(_key, %CPPSELF.count(), &start, &stop, &step, &slicelength) < 0) { - return nullptr; - } + const Py_ssize_t _i = PyNumber_AsSsize_t(_key, PyExc_IndexError); + if (_i < 0 || _i >= %CPPSELF.size()) + return PyErr_Format(PyExc_IndexError, "index out of bounds"); + char res[2] = {%CPPSELF.at(_i), '\0'}; + return PyBytes_FromStringAndSize(res, 1); +} - QByteArray ba; - if (slicelength <= 0) { - return %CONVERTTOPYTHON[QByteArray](ba); - } else if (step == 1) { - Py_ssize_t max = %CPPSELF.count(); - start = qBound(Py_ssize_t(0), start, max); - stop = qBound(Py_ssize_t(0), stop, max); - QByteArray ba; - if (start < stop) - ba = %CPPSELF.mid(start, stop - start); - return %CONVERTTOPYTHON[QByteArray](ba); - } else { - QByteArray ba; - for (cur = start; slicelength > 0; cur += static_cast<size_t>(step), slicelength--) { - ba.append(%CPPSELF.at(cur)); - } - return %CONVERTTOPYTHON[QByteArray](ba); - } -} else { - PyErr_Format(PyExc_TypeError, +if (PySlice_Check(_key) == 0) + return PyErr_Format(PyExc_TypeError, "list indices must be integers or slices, not %.200s", Py_TYPE(_key)->tp_name); + +Py_ssize_t start, stop, step, slicelength; +if (PySlice_GetIndicesEx(_key, %CPPSELF.size(), &start, &stop, &step, &slicelength) < 0) return nullptr; + +QByteArray ba; +if (slicelength <= 0) + return %CONVERTTOPYTHON[QByteArray](ba); + +if (step == 1) { + Py_ssize_t max = %CPPSELF.size(); + start = qBound(Py_ssize_t(0), start, max); + stop = qBound(Py_ssize_t(0), stop, max); + if (start < stop) + ba = %CPPSELF.mid(start, stop - start); + return %CONVERTTOPYTHON[QByteArray](ba); } + +for (Py_ssize_t cur = start; slicelength > 0; cur += step, --slicelength) + ba.append(%CPPSELF.at(cur)); + +return %CONVERTTOPYTHON[QByteArray](ba); // @snippet qbytearray-mgetitem // @snippet qbytearray-msetitem +// PYSIDE-2404: Usage of the `get()` function not necessary, the type exists. if (PyIndex_Check(_key)) { Py_ssize_t _i = PyNumber_AsSsize_t(_key, PyExc_IndexError); if (_i == -1 && PyErr_Occurred()) return -1; if (_i < 0) - _i += %CPPSELF.count(); + _i += %CPPSELF.size(); if (_i < 0 || _i >= %CPPSELF.size()) { PyErr_SetString(PyExc_IndexError, "QByteArray index out of range"); @@ -1008,7 +690,8 @@ if (PyIndex_Check(_key)) { PyErr_SetString(PyExc_ValueError, "bytearray must be of size 1"); return -1; } - } else if (reinterpret_cast<PyTypeObject *>(Py_TYPE(_value)) == reinterpret_cast<PyTypeObject *>(SbkPySide6_QtCoreTypes[SBK_QBYTEARRAY_IDX])) { + } else if (Py_TYPE(_value) == reinterpret_cast<PyTypeObject *>( + SbkPySide6_QtCoreTypeStructs[SBK_QByteArray_IDX].type)) { if (PyObject_Length(_value) != 1) { PyErr_SetString(PyExc_ValueError, "QByteArray must be of size 1"); return -1; @@ -1024,63 +707,64 @@ if (PyIndex_Check(_key)) { PyObject *result = Sbk_QByteArrayFunc_insert(self, args); Py_DECREF(args); Py_XDECREF(result); - return !result ? -1 : 0; -} else if (PySlice_Check(_key)) { - Py_ssize_t start, stop, step, slicelength, value_length; - if (PySlice_GetIndicesEx(_key, %CPPSELF.count(), &start, &stop, &step, &slicelength) < 0) { - return -1; - } - // The parameter candidates are: bytes/str, bytearray, QByteArray itself. - // Not support iterable which contains ints between 0~255 - - // case 1: value is nullpre, means delete the items within the range - // case 2: step is 1, means shrink or expanse - // case 3: step is not 1, then the number of slots have to equal the number of items in _value - QByteArray ba; - if (_value == nullptr || _value == Py_None) { - ba = QByteArray(); - value_length = 0; - } else if (!(PyBytes_Check(_value) || PyByteArray_Check(_value) || reinterpret_cast<PyTypeObject *>(Py_TYPE(_value)) == reinterpret_cast<PyTypeObject *>(SbkPySide6_QtCoreTypes[SBK_QBYTEARRAY_IDX]))) { - PyErr_Format(PyExc_TypeError, "bytes, bytearray or QByteArray is required, not %.200s", Py_TYPE(_value)->tp_name); - return -1; - } else { - value_length = PyObject_Length(_value); - } + return result != nullptr ? 0: -1; +} - if (step != 1 && value_length != slicelength) { - PyErr_Format(PyExc_ValueError, "attempt to assign %s of size %d to extended slice of size %d", - Py_TYPE(_value)->tp_name, int(value_length), int(slicelength)); - return -1; +if (PySlice_Check(_key) == 0) { + PyErr_Format(PyExc_TypeError, "QBytearray indices must be integers or slices, not %.200s", + Py_TYPE(_key)->tp_name); + return -1; +} + +Py_ssize_t start, stop, step, slicelength; +if (PySlice_GetIndicesEx(_key, %CPPSELF.size(), &start, &stop, &step, &slicelength) < 0) + return -1; + +// The parameter candidates are: bytes/str, bytearray, QByteArray itself. +// Not supported are iterables containing ints between 0~255 +// case 1: value is nullpre, means delete the items within the range +// case 2: step is 1, means shrink or expand +// case 3: step is not 1, then the number of slots have to equal the number of items in _value +Py_ssize_t value_length = 0; +if (_value != nullptr && _value != Py_None) { + if (!(PyBytes_Check(_value) || PyByteArray_Check(_value) + || Py_TYPE(_value) == SbkPySide6_QtCoreTypeStructs[SBK_QByteArray_IDX].type)) { + PyErr_Format(PyExc_TypeError, "bytes, bytearray or QByteArray is required, not %.200s", + Py_TYPE(_value)->tp_name); + return -1; } + value_length = PyObject_Length(_value); +} + +if (step != 1 && value_length != slicelength) { + PyErr_Format(PyExc_ValueError, "attempt to assign %s of size %d to extended slice of size %d", + Py_TYPE(_value)->tp_name, int(value_length), int(slicelength)); + return -1; +} - if (step != 1) { - int i = start; - for (int j = 0; j < slicelength; j++) { - PyObject *item = PyObject_GetItem(_value, PyLong_FromLong(j)); - QByteArray temp; - if (PyLong_Check(item)) { - int overflow; - long ival = PyLong_AsLongAndOverflow(item, &overflow); - // Not suppose to bigger than 255 because only bytes, bytearray, QByteArray were accept - temp = QByteArray(reinterpret_cast<const char *>(&ival)); - } else { - temp = %CONVERTTOCPP[QByteArray](item); - } - - %CPPSELF.replace(i, 1, temp); - i += step; +if (step != 1) { + Py_ssize_t i = start; + for (Py_ssize_t j = 0; j < slicelength; ++j) { + PyObject *item = PyObject_GetItem(_value, PyLong_FromSsize_t(j)); + QByteArray temp; + if (PyLong_Check(item)) { + int overflow; + const long ival = PyLong_AsLongAndOverflow(item, &overflow); + // Not supposed to be bigger than 255 because only bytes, + // bytearray, QByteArray were accepted + temp.append(char(ival)); + } else { + temp = %CONVERTTOCPP[QByteArray](item); } - return 0; - } else { - ba = %CONVERTTOCPP[QByteArray](_value); - %CPPSELF.replace(start, slicelength, ba); - return 0; + %CPPSELF.replace(i, 1, temp); + i += step; } -} else { - PyErr_Format(PyExc_TypeError, "QBytearray indices must be integers or slices, not %.200s", - Py_TYPE(_key)->tp_name); - return -1; + return 0; } + +QByteArray ba = %CONVERTTOCPP[QByteArray](_value); +%CPPSELF.replace(start, slicelength, ba); +return 0; // @snippet qbytearray-msetitem // @snippet qbytearray-bufferprotocol @@ -1095,16 +779,16 @@ static int SbkQByteArray_getbufferproc(PyObject *obj, Py_buffer *view, int flags QByteArray * cppSelf = %CONVERTTOCPP[QByteArray *](obj); //XXX /|\ omitting this space crashes shiboken! - #ifdef Py_LIMITED_API +#ifdef Py_LIMITED_API view->obj = obj; view->buf = reinterpret_cast<void *>(cppSelf->data()); view->len = cppSelf->size(); view->readonly = 0; view->itemsize = 1; - view->format = const_cast<char *>("c"); + view->format = (flags & PyBUF_FORMAT) == PyBUF_FORMAT ? const_cast<char *>("B") : nullptr; view->ndim = 1; view->shape = (flags & PyBUF_ND) == PyBUF_ND ? &(view->len) : nullptr; - view->strides = &view->itemsize; + view->strides = (flags & PyBUF_STRIDES) == PyBUF_STRIDES ? &(view->itemsize) : nullptr; view->suboffsets = nullptr; view->internal = nullptr; @@ -1236,7 +920,7 @@ Py_DECREF(aux); // @snippet qbytearray-str // @snippet qbytearray-len -return %CPPSELF.count(); +return %CPPSELF.size(); // @snippet qbytearray-len // @snippet qbytearray-getitem @@ -1270,6 +954,13 @@ uchar *ptr = reinterpret_cast<uchar *>(Shiboken::Buffer::getPointer(%PYARG_1)); %PYARG_0 = Shiboken::Buffer::newObject(%CPPSELF.%FUNCTION_NAME(%1, %2, %3), %2, Shiboken::Buffer::ReadWrite); // @snippet qfiledevice-map +// @snippet qiodevice-bufferedread +Py_ssize_t bufferLen; +auto *data = reinterpret_cast<char*>(Shiboken::Buffer::getPointer(%PYARG_1, &bufferLen)); +%RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(data, PyLong_AsLongLong(%PYARG_2)); +return PyLong_FromLong(%0); +// @snippet qiodevice-bufferedread + // @snippet qiodevice-readdata QByteArray ba(1 + qsizetype(%2), char(0)); %CPPSELF.%FUNCTION_NAME(ba.data(), qint64(%2)); @@ -1280,6 +971,11 @@ QByteArray ba(1 + qsizetype(%2), char(0)); %CPPSELF.%FUNCTION_NAME(Shiboken::String::toCString(%PYARG_1), Shiboken::String::len(%PYARG_1)); // @snippet qcryptographichash-adddata +// @snippet qmetaobject-repr +const QByteArray repr = PySide::MetaObjectBuilder::formatMetaObject(%CPPSELF).toUtf8(); +%PYARG_0 = PyUnicode_FromString(repr.constData()); +// @snippet qmetaobject-repr + // @snippet qsocketdescriptor #ifdef WIN32 using DescriptorType = Qt::HANDLE; @@ -1312,63 +1008,126 @@ auto *ptr = reinterpret_cast<uchar *>(Shiboken::Buffer::getPointer(%PYARG_1, &si %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); // @snippet qtranslator-load -// @snippet qtimer-singleshot-1 -// %FUNCTION_NAME() - disable generation of c++ function call -(void) %2; // remove warning about unused variable -Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); -auto *timerType = Shiboken::SbkType<QTimer>(); -auto *pyTimer = timerType->tp_new(Shiboken::SbkType<QTimer>(), emptyTuple, nullptr); -timerType->tp_init(pyTimer, emptyTuple, nullptr); - -auto timer = %CONVERTTOCPP[QTimer *](pyTimer); -//XXX /|\ omitting this space crashes shiboken! -Shiboken::AutoDecRef result( - PyObject_CallMethod(pyTimer, "connect", "OsOs", - pyTimer, - SIGNAL(timeout()), - %PYARG_2, - %3) -); -Shiboken::Object::releaseOwnership(reinterpret_cast<SbkObject *>(pyTimer)); -Py_XDECREF(pyTimer); -timer->setSingleShot(true); -timer->connect(timer, &QTimer::timeout, timer, &QObject::deleteLater); -timer->start(%1); -// @snippet qtimer-singleshot-1 - -// @snippet qtimer-singleshot-2 -// %FUNCTION_NAME() - disable generation of c++ function call +// @snippet qtimer-singleshot-functorclass +struct QSingleShotTimerFunctor : public Shiboken::PyObjectHolder +{ +public: + using Shiboken::PyObjectHolder::PyObjectHolder; + + void operator()(); +}; + +void QSingleShotTimerFunctor::operator()() +{ + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(0)); + Shiboken::AutoDecRef ret(PyObject_CallObject(object(), arglist)); + if (Shiboken::Errors::occurred()) + Shiboken::Errors::storeErrorOrPrint(); + release(); // single shot +} +// @snippet qtimer-singleshot-functorclass + +// @snippet qtimer-singleshot-direct-mapping Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); -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); - -if (PyObject_TypeCheck(%2, PySideSignalInstanceTypeF())) { - PySideSignalInstance *signalInstance = reinterpret_cast<PySideSignalInstance *>(%2); - Shiboken::AutoDecRef signalSignature(Shiboken::String::fromFormat("2%s", PySide::Signal::getSignature(signalInstance))); - Shiboken::AutoDecRef result( - PyObject_CallMethod(pyTimer, "connect", "OsOO", - pyTimer, - SIGNAL(timeout()), - PySide::Signal::getObject(signalInstance), - signalSignature.object()) - ); +%CPPSELF.%FUNCTION_NAME(%1, %2, %3); +// @snippet qtimer-singleshot-direct-mapping + +// @snippet qtimer-singleshot-functor +auto msec = %1; +if (msec == 0) { + if (PyObject_TypeCheck(%2, PySideSignalInstance_TypeF())) { + auto *signal = %PYARG_2; + auto cppCallback = [signal]() + { + Shiboken::GilState state; + Shiboken::AutoDecRef ret(PyObject_CallMethod(signal, "emit", "()")); + Py_DECREF(signal); + }; + + Py_INCREF(signal); + %CPPSELF.%FUNCTION_NAME(msec, cppCallback); + } else { + %CPPSELF.%FUNCTION_NAME(msec, QSingleShotTimerFunctor(%PYARG_2)); + } } else { + // %FUNCTION_NAME() - disable generation of c++ function call + Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); + auto *timerType = Shiboken::SbkType<QTimer>(); + auto newFunc = reinterpret_cast<newfunc>(PepType_GetSlot(timerType, Py_tp_new)); + auto initFunc = reinterpret_cast<initproc>(PepType_GetSlot(timerType, Py_tp_init)); + auto *pyTimer = newFunc(Shiboken::SbkType<QTimer>(), emptyTuple, nullptr); + initFunc(pyTimer, emptyTuple, nullptr); + + QTimer * timer = %CONVERTTOCPP[QTimer *](pyTimer); + timer->setSingleShot(true); + + if (PyObject_TypeCheck(%2, PySideSignalInstance_TypeF())) { + PySideSignalInstance *signalInstance = reinterpret_cast<PySideSignalInstance *>(%2); + Shiboken::AutoDecRef signalSignature(Shiboken::String::fromFormat("2%s", PySide::Signal::getSignature(signalInstance))); + Shiboken::AutoDecRef result( + PyObject_CallMethod(pyTimer, "connect", "OsOO", + pyTimer, + SIGNAL(timeout()), + PySide::Signal::getObject(signalInstance), + signalSignature.object()) + ); + } else { + Shiboken::AutoDecRef result( + PyObject_CallMethod(pyTimer, "connect", "OsO", + pyTimer, + SIGNAL(timeout()), + %PYARG_2) + ); + } + + 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 + +// @snippet qtimer-singleshot-functor-context +auto msec = %1; +if (msec == 0) { + Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); + 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(msec, %2, cppCallback); +} else { + Shiboken::AutoDecRef emptyTuple(PyTuple_New(0)); + auto *timerType = Shiboken::SbkType<QTimer>(); + auto newFunc = reinterpret_cast<newfunc>(PepType_GetSlot(timerType, Py_tp_new)); + auto initFunc = reinterpret_cast<initproc>(PepType_GetSlot(timerType, Py_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", "OsO", + PyObject_CallMethod(pyTimer, "connect", "OsOO", pyTimer, SIGNAL(timeout()), - %PYARG_2) + %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(%1); -// @snippet qtimer-singleshot-2 + 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 // @snippet qprocess-startdetached qint64 pid; @@ -1434,6 +1193,16 @@ if (result == -1) { } // @snippet qdatastream-readrawdata +// @snippet qdatastream-writerawdata-pybuffer +int r = 0; +Py_ssize_t bufferLen; +auto *data = reinterpret_cast<const char*>(Shiboken::Buffer::getPointer(%PYARG_1, &bufferLen)); +Py_BEGIN_ALLOW_THREADS +r = %CPPSELF.%FUNCTION_NAME(data, bufferLen); +Py_END_ALLOW_THREADS +%PYARG_0 = %CONVERTTOPYTHON[int](r); +// @snippet qdatastream-writerawdata-pybuffer + // @snippet qdatastream-writerawdata int r = 0; Py_BEGIN_ALLOW_THREADS @@ -1572,7 +1341,7 @@ Py_END_ALLOW_THREADS if (atexit.isNull()) { qWarning("Module atexit not found for registering __moduleShutdown"); PyErr_Clear(); - }else{ + } else { regFunc.reset(PyObject_GetAttrString(atexit, "register")); if (regFunc.isNull()) { qWarning("Function atexit.register not found for registering __moduleShutdown"); @@ -1588,7 +1357,16 @@ Py_END_ALLOW_THREADS } } // @snippet qt-module-shutdown -// + +// @snippet qthread_init_pypy +#ifdef PYPY_VERSION +// PYSIDE-535: PyPy 7.3.8 needs this call, which is actually a no-op in Python 3.9 +// This function should be replaced by a `Py_Initialize` call, but +// that is still undefined. So we don't rely yet on any PyPy version. +PyEval_InitThreads(); +#endif +// @snippet qthread_init_pypy + // @snippet qthread_exec_ if (PyErr_WarnEx(PyExc_DeprecationWarning, "'exec_' will be removed in the future. " @@ -1669,10 +1447,6 @@ if (PyErr_WarnEx(PyExc_DeprecationWarning, %out = %OUTTYPE(%in == Py_True); // @snippet conversion-pybool -// @snippet conversion-pylong -%out = %OUTTYPE(PyLong_AsLong(%in)); -// @snippet conversion-pylong - // @snippet conversion-pylong-quintptr #if QT_POINTER_SIZE == 8 %out = %OUTTYPE(PyLong_AsUnsignedLongLong(%in)); @@ -1682,22 +1456,11 @@ if (PyErr_WarnEx(PyExc_DeprecationWarning, // @snippet conversion-pylong-quintptr // @snippet conversion-pyunicode -void *data = _PepUnicode_DATA(%in); -Py_ssize_t len = PyUnicode_GetLength(%in); -switch (_PepUnicode_KIND(%in)) { - case PepUnicode_1BYTE_KIND: - %out = QString::fromLatin1(reinterpret_cast<const char *>(data)); - break; - case PepUnicode_2BYTE_KIND: - %out = QString::fromUtf16(reinterpret_cast<const char16_t *>(data), len); - break; - case PepUnicode_4BYTE_KIND: - %out = QString::fromUcs4(reinterpret_cast<const char32_t *>(data), len); - break; -} +%out = PySide::pyUnicodeToQString(%in); // @snippet conversion-pyunicode // @snippet conversion-pynone +SBK_UNUSED(%in) %out = %OUTTYPE(); // @snippet conversion-pynone @@ -1716,7 +1479,7 @@ auto res = (*%CPPSELF) + cppArg0; // @snippet conversion-pystring-char char c = %CONVERTTOCPP[char](%in); -%out = %OUTTYPE(c); +%out = %OUTTYPE(static_cast<unsigned short>(c)); // @snippet conversion-pystring-char // @snippet conversion-pyint @@ -1750,15 +1513,23 @@ double in = %CONVERTTOCPP[double](%in); // @snippet conversion-sbkobject // a class supported by QVariant? const QMetaType metaType = QVariant_resolveMetaType(Py_TYPE(%in)); +bool ok = false; if (metaType.isValid()) { QVariant var(metaType); - Shiboken::Conversions::SpecificConverter converter(metaType.name()); - converter.toCpp(pyIn, var.data()); - %out = var; -} else { - // If the type was not encountered, return a default PyObjectWrapper - %out = QVariant::fromValue(PySide::PyObjectWrapper(%in)); + auto converterO = converterForQtType(metaType.name()); + ok = converterO.has_value(); + if (ok) { + converterO.value().toCpp(pyIn, var.data()); + %out = var; + } else { + qWarning("%s: Cannot find a converter for \"%s\".", + __FUNCTION__, metaType.name()); + } } + +// If the type was not encountered, return a default PyObjectWrapper +if (!ok) + %out = QVariant::fromValue(PySide::PyObjectWrapper(%in)); // @snippet conversion-sbkobject // @snippet conversion-pydict @@ -1782,11 +1553,6 @@ QJsonValue val = QJsonValue::fromVariant(dict); %out = val.toObject(); // @snippet conversion-qjsonobject-pydict -// @snippet conversion-qpair-pysequence -%out.first = %CONVERTTOCPP[%OUTTYPE_0](PySequence_Fast_GET_ITEM(%in, 0)); -%out.second = %CONVERTTOCPP[%OUTTYPE_1](PySequence_Fast_GET_ITEM(%in, 1)); -// @snippet conversion-qpair-pysequence - // @snippet conversion-qdate-pydate int day = PyDateTime_GET_DAY(%in); int month = PyDateTime_GET_MONTH(%in); @@ -1849,14 +1615,42 @@ return PyLong_FromUnsignedLong(%in); #endif // @snippet return-pylong-quintptr +// @snippet return-qfunctionpointer-pylong +return PyLong_FromVoidPtr(reinterpret_cast<void *>(%in)); +// @snippet return-qfunctionpointer-pylong + +// @snippet conversion-pylong-qfunctionpointer +%out = reinterpret_cast<QFunctionPointer>(PyLong_AsVoidPtr(%in)); +// @snippet conversion-pylong-qfunctionpointer + // @snippet return-pyunicode -QByteArray ba = %in.toUtf8(); -return PyUnicode_FromStringAndSize(ba.constData(), ba.size()); +return PySide::qStringToPyUnicode(%in); // @snippet return-pyunicode +// @snippet return-pyunicode-from-qlatin1string +#ifdef Py_LIMITED_API +return PySide::qStringToPyUnicode(QString::fromLatin1(%in)); +#else +return PyUnicode_FromKindAndData(PyUnicode_1BYTE_KIND, %in.constData(), %in.size()); +#endif +// @snippet return-pyunicode-from-qlatin1string + +// @snippet qlatin1string-check +static bool qLatin1StringCheck(PyObject *o) +{ + return PyUnicode_CheckExact(o) != 0 + && _PepUnicode_KIND(o) == PepUnicode_1BYTE_KIND; +} +// @snippet qlatin1string-check + +// @snippet conversion-pystring-qlatin1string +const char *data = reinterpret_cast<const char *>(_PepUnicode_DATA(%in)); +const Py_ssize_t len = PyUnicode_GetLength(%in); +%out = QLatin1String(data, len); +// @snippet conversion-pystring-qlatin1string + // @snippet return-pyunicode-from-qanystringview -QByteArray ba = %in.toString().toUtf8(); -return PyUnicode_FromStringAndSize(ba.constData(), ba.size()); +return PySide::qStringToPyUnicode(%in.toString()); // @snippet return-pyunicode-from-qanystringview // @snippet return-pyunicode-qchar @@ -1893,11 +1687,10 @@ default: break; } -Shiboken::Conversions::SpecificConverter converter(cppInRef.typeName()); -if (converter) { - void *ptr = cppInRef.data(); - return converter.toPython(ptr); -} +auto converterO = converterForQtType(cppInRef.typeName()); +if (converterO.has_value()) + return converterO.value().toPython(cppInRef.data()); + PyErr_Format(PyExc_RuntimeError, "Can't find converter for '%s'.", %in.typeName()); return 0; // @snippet return-qvariant @@ -1912,16 +1705,8 @@ QVariant ret = val.toVariant(); return %CONVERTTOPYTHON[QVariant](ret); // @snippet return-qjsonobject -// @snippet return-qpair -PyObject *%out = PyTuple_New(2); -PyTuple_SET_ITEM(%out, 0, %CONVERTTOPYTHON[%INTYPE_0](%in.first)); -PyTuple_SET_ITEM(%out, 1, %CONVERTTOPYTHON[%INTYPE_1](%in.second)); -return %out; -// @snippet return-qpair - // @snippet qthread_pthread_cleanup #ifdef Q_OS_UNIX -# include <stdio.h> # include <pthread.h> static void qthread_pthread_cleanup(void *arg) { @@ -1948,13 +1733,17 @@ pthread_cleanup_pop(0); // @snippet qthread_pthread_cleanup_uninstall // @snippet qlibraryinfo_build -#if defined(Py_LIMITED_API) -auto suffix = PyUnicode_FromString(" [limited API]"); auto oldResult = pyResult; -pyResult = PyUnicode_Concat(pyResult, suffix); -Py_DECREF(oldResult); -Py_DECREF(suffix); +const auto version = _PepRuntimeVersion(); +pyResult = PyUnicode_FromFormat( +#ifdef Py_LIMITED_API + "%U [Python limited API %d.%d.%d]", +#else + "%U [Python %d.%d.%d]", #endif + oldResult, (version >> 16) & 0xFF, + (version >> 8) & 0xFF, version & 0xFF); +Py_DECREF(oldResult); // @snippet qlibraryinfo_build // @snippet qsharedmemory_data_readonly @@ -1988,3 +1777,374 @@ Py_INCREF(callable); %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(cppCallback); %PYARG_0 = %CONVERTTOPYTHON[int](cppResult); // @snippet qthreadpool-trystart + +// @snippet repr-qevent +QString result; +QDebug(&result).nospace() << "<PySide6.QtCore.QEvent(" << %CPPSELF->type() << ")>"; +%PYARG_0 = Shiboken::String::fromCString(qPrintable(result)); +// @snippet repr-qevent + +// @snippet qmetaproperty_write_enum +if (Shiboken::Enum::check(%PYARG_2)) + cppArg1 = QVariant(int(Shiboken::Enum::getValue(%PYARG_2))); +// @snippet qmetaproperty_write_enum + +// @snippet qdatastream-read-bytes +QByteArray data; +data.resize(%2); +auto dataChar = data.data(); +cppSelf->readBytes(dataChar, %2); +const char *constDataChar = dataChar; +if (dataChar == nullptr) { + Py_INCREF(Py_None); + %PYARG_0 = Py_None; +} else { + %PYARG_0 = PyBytes_FromStringAndSize(constDataChar, %2); +} +// @snippet qdatastream-read-bytes + +// @snippet qloggingcategory_to_cpp +// PYSIDE-2404: Usage of the `get()` function not necessary, the type exists. + QLoggingCategory *category{nullptr}; + Shiboken::Conversions::pythonToCppPointer(SbkPySide6_QtCoreTypeStructs[SBK_QLoggingCategory_IDX].type, + pyArgs[0], &(category)); +// @snippet qloggingcategory_to_cpp + +// Q_ARG()-equivalent +// @snippet q_arg +const QArgData qArgData = qArgDataFromPyType(%1); +if (!qArgData) + return nullptr; + +switch (qArgData.metaType.id()) { + case QMetaType::Bool: + *reinterpret_cast<bool *>(qArgData.data) = %2 == Py_True; + break; + case QMetaType::Int: + *reinterpret_cast<int *>(qArgData.data) = int(PyLong_AsLong(%2)); + break; + case QMetaType::Double: + *reinterpret_cast<double *>(qArgData.data) = PyFloat_AsDouble(%2); + break; + case QMetaType::QString: + *reinterpret_cast<QString *>(qArgData.data) = PySide::pyUnicodeToQString(%2); + break; + default: { + Shiboken::Conversions::SpecificConverter converter(qArgData.metaType.name()); + const auto type = converter.conversionType(); + // Copy for values, Pointer for objects + if (type == Shiboken::Conversions::SpecificConverter::InvalidConversion) { + PyErr_Format(PyExc_RuntimeError, "%s: Unable to find converter for \"%s\".", + __FUNCTION__, qArgData.metaType.name()); + return nullptr; + } + converter.toCpp(%2, qArgData.data); + } +} + +QtCoreHelper::QGenericArgumentHolder result(qArgData.metaType, qArgData.data); +%PYARG_0 = %CONVERTTOPYTHON[QtCoreHelper::QGenericArgumentHolder](result); +// @snippet q_arg + +// Q_RETURN_ARG()-equivalent +// @snippet q_return_arg +const QArgData qArgData = qArgDataFromPyType(%1); +if (!qArgData) + return nullptr; + +QtCoreHelper::QGenericReturnArgumentHolder result(qArgData.metaType, qArgData.data); +%PYARG_0 = %CONVERTTOPYTHON[QtCoreHelper::QGenericReturnArgumentHolder](result); +// @snippet q_return_arg + +// @snippet qmetamethod-invoke-helpers +static InvokeMetaMethodFunc + createInvokeMetaMethodFunc(const QMetaMethod &method, QObject *object, + Qt::ConnectionType type = Qt::AutoConnection) +{ + return [&method, object, type](QGenericArgument a0, QGenericArgument a1, + QGenericArgument a2, QGenericArgument a3, + QGenericArgument a4, QGenericArgument a5, + QGenericArgument a6, QGenericArgument a7, + QGenericArgument a8, QGenericArgument a9) -> bool + { + return method.invoke(object, type, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + }; +} + +static InvokeMetaMethodFuncWithReturn + createInvokeMetaMethodFuncWithReturn(const QMetaMethod &method, QObject *object, + Qt::ConnectionType type = Qt::AutoConnection) +{ + return [&method, object, type](QGenericReturnArgument r, + QGenericArgument a0, QGenericArgument a1, + QGenericArgument a2, QGenericArgument a3, + QGenericArgument a4, QGenericArgument a5, + QGenericArgument a6, QGenericArgument a7, + QGenericArgument a8, QGenericArgument a9) -> bool + { + return method.invoke(object, type, r, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + }; +} +// @snippet qmetamethod-invoke-helpers + +// @snippet qmetamethod-invoke-conn-type-return-arg +%PYARG_0 = invokeMetaMethodWithReturn(createInvokeMetaMethodFuncWithReturn(*%CPPSELF, %1, %2), + %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13); +// @snippet qmetamethod-invoke-conn-type-return-arg + +// @snippet qmetamethod-invoke-return-arg +%PYARG_0 = invokeMetaMethodWithReturn(createInvokeMetaMethodFuncWithReturn(*%CPPSELF, %1), + %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12); +// @snippet qmetamethod-invoke-return-arg + +// @snippet qmetamethod-invoke-conn-type +%PYARG_0 = invokeMetaMethod(createInvokeMetaMethodFunc(*%CPPSELF, %1, %2), + %3, %4, %5, %6, %7, %8, %9, %10, %11, %12); +// @snippet qmetamethod-invoke-conn-type + +// @snippet qmetamethod-invoke +%PYARG_0 = invokeMetaMethod(createInvokeMetaMethodFunc(*%CPPSELF, %1), + %2, %3, %4, %5, %6, %7, %8, %9, %10, %11); +// @snippet qmetamethod-invoke + +// @snippet qmetaobject-invokemethod-helpers +static InvokeMetaMethodFunc + createInvokeMetaMethodFunc(QObject *object, const char *methodName, + Qt::ConnectionType type = Qt::AutoConnection) +{ + return [object, methodName, type](QGenericArgument a0, QGenericArgument a1, + QGenericArgument a2, QGenericArgument a3, + QGenericArgument a4, QGenericArgument a5, + QGenericArgument a6, QGenericArgument a7, + QGenericArgument a8, QGenericArgument a9) -> bool + { + return QMetaObject::invokeMethod(object, methodName, type, + a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + }; +} + +static InvokeMetaMethodFuncWithReturn + createInvokeMetaMethodFuncWithReturn(QObject *object, const char *methodName, + Qt::ConnectionType type = Qt::AutoConnection) +{ + return [object, methodName, type](QGenericReturnArgument r, + QGenericArgument a0, QGenericArgument a1, + QGenericArgument a2, QGenericArgument a3, + QGenericArgument a4, QGenericArgument a5, + QGenericArgument a6, QGenericArgument a7, + QGenericArgument a8, QGenericArgument a9) -> bool + { + return QMetaObject::invokeMethod(object, methodName, type, + r, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); + }; +} +// @snippet qmetaobject-invokemethod-helpers + +// invokeMethod(QObject *,const char *, QGenericArgument a0, a1, a2 ) +// @snippet qmetaobject-invokemethod-arg +%PYARG_0 = invokeMetaMethod(createInvokeMetaMethodFunc(%1, %2), + %3, %4, %5, %6, %7, %8, %9, %10, %11, %12); +// @snippet qmetaobject-invokemethod-arg + +// invokeMethod(QObject *,const char *,Qt::ConnectionType, QGenericArgument a0, a1, a2 ) +// @snippet qmetaobject-invokemethod-conn-type-arg +%PYARG_0 = invokeMetaMethod(createInvokeMetaMethodFunc(%1, %2, %3), + %4, %5, %6, %7, %8, %9, %10, %11, %12, %13); +// @snippet qmetaobject-invokemethod-conn-type-arg + +// invokeMethod(QObject *,const char *, Qt::ConnectionType, QGenericReturnArgument,QGenericArgument a0, a1, a2 ) +// @snippet qmetaobject-invokemethod-conn-type-return-arg +%PYARG_0 = invokeMetaMethodWithReturn(createInvokeMetaMethodFuncWithReturn(%1, %2, %3), + %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14); +// @snippet qmetaobject-invokemethod-conn-type-return-arg + +// invokeMethod(QObject *,const char *, QGenericReturnArgument,QGenericArgument a0, a1, a2 ) +// @snippet qmetaobject-invokemethod-return-arg +%PYARG_0 = invokeMetaMethodWithReturn(createInvokeMetaMethodFuncWithReturn(%1, %2), + %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13); +// @snippet qmetaobject-invokemethod-return-arg + +// @snippet keycombination-from-keycombination +cptr = new ::%TYPE(%1); +// @snippet keycombination-from-keycombination + +// @snippet keycombination-from-modifier +cptr = new ::%TYPE(%1, %2); +// @snippet keycombination-from-modifier + +// @snippet qmetamethod-from-signal +auto *signalInst = reinterpret_cast<PySideSignalInstance *>(%PYARG_1); +const auto data = PySide::Signal::getEmitterData(signalInst); +const auto result = data.methodIndex != -1 + ? data.emitter->metaObject()->method(data.methodIndex) + : QMetaMethod{}; +%PYARG_0 = %CONVERTTOPYTHON[QMetaMethod](result); +// @snippet qmetamethod-from-signal + +// @snippet qrunnable_create +auto callable = %PYARG_1; +auto callback = [callable]() -> void +{ + if (!PyCallable_Check(callable)) { + qWarning("Argument 1 of %FUNCTION_NAME must be a callable."); + return; + } + Shiboken::GilState state; + Shiboken::AutoDecRef ret(PyObject_CallObject(callable, nullptr)); + Py_DECREF(callable); +}; +Py_INCREF(callable); +%RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(callback); +%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); +// @snippet qrunnable_create + +// @snippet qlocale_system +// For darwin systems, QLocale::system() involves looking at the Info.plist of the application +// bundle to detect the system localization. In the case of Qt for Python, the application bundle +// is the used Python framework. To enable retreival of localized string, the property list key +// CFBunldeAllowMixedLocalizations should be set to True inside the Info.plist file. Otherwise, +// CFBundleDevelopmentRegion will be used to find the language preference of the user, which in the +// case of Python is always english. +// This is a hack until CFBunldeAllowMixedLocalizations will be set in the Python framework +// installation in darwin systems. +// Upstream issue in CPython: https://github.com/python/cpython/issues/108269 +#ifdef Q_OS_DARWIN + Shiboken::AutoDecRef locale(PyImport_ImportModule("locale")); + Shiboken::AutoDecRef getLocale(PyObject_GetAttrString(locale, "getlocale")); + Shiboken::AutoDecRef systemLocale(PyObject_CallObject(getLocale, nullptr)); + PyObject* localeCode = PyTuple_GetItem(systemLocale, 0); + %RETURN_TYPE %0; + if (localeCode != Py_None) { + QString localeCodeStr = PySide::pyStringToQString(localeCode); + %0 = QLocale(localeCodeStr); + } else { + // The default locale is 'C' locale as mentioned in + // https://docs.python.org/3/library/locale.html + %0 = ::QLocale::c(); + } +#else + %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(); +#endif +%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); +// @snippet qlocale_system + +// @snippet qcoreapplication-requestpermission +auto permission = %1; +auto callable = %PYARG_3; + +// check if callable +if (!PyCallable_Check(callable)) { + qWarning("Functor of %FUNCTION_NAME is not a callable"); + return {}; +} + +// find the number of arguments of callable. It should either be empy or accept a QPermission +// object +int count = 0; +PyObject* fc = nullptr; +bool classMethod = false; +Shiboken::AutoDecRef func_ob(PyObject_GetAttr(callable, Shiboken::PyMagicName::func())); + +if (func_ob.isNull() && PyObject_HasAttr(callable, Shiboken::PyMagicName::code())) { + // variable `callable` is a function + fc = PyObject_GetAttr(callable, Shiboken::PyMagicName::code()); +} else { + // variable `callable` is a class method + fc = PyObject_GetAttr(func_ob, Shiboken::PyMagicName::code()); + classMethod = true; +} + +if (fc) { + PyObject* ac = PyObject_GetAttrString(fc, "co_argcount"); + if (ac) { + count = PyLong_AsLong(ac); + Py_DECREF(ac); + } + Py_DECREF(fc); +} + +if ((classMethod && (count > 2)) || (!classMethod && (count > 1))) { + qWarning("Functor of %FUNCTION_NAME must either have QPermission object as argument or none." + "The QPermission object store the result of requestPermission()"); + return {}; +} + +bool arg_qpermission = (classMethod && (count == 2)) || (!classMethod && (count == 1)); + +auto callback = [callable, count, arg_qpermission](const QPermission &permission) -> void +{ + Shiboken::GilState state; + if (arg_qpermission) { + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + PyTuple_SET_ITEM(arglist.object(), 0, %CONVERTTOPYTHON[QPermission](permission)); + Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); + } else { + Shiboken::AutoDecRef ret(PyObject_CallObject(callable, nullptr)); + } + Py_DECREF(callable); +}; +Py_INCREF(callable); + +Py_BEGIN_ALLOW_THREADS +%CPPSELF.%FUNCTION_NAME(permission, %2, callback); +Py_END_ALLOW_THREADS +// @snippet qcoreapplication-requestpermission + +// @snippet qlockfile-getlockinfo +qint64 pid{}; +QString hostname, appname; +%CPPSELF.%FUNCTION_NAME(&pid, &hostname, &appname); +%PYARG_0 = PyTuple_New(3); +PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[qint64](pid)); +PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[QString](hostname)); +PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[QString](appname)); +// @snippet qlockfile-getlockinfo + +// @snippet darwin_permission_plugin +#ifdef Q_OS_DARWIN +#include<QtCore/qplugin.h> +// register the static plugin and setup its metadata +Q_IMPORT_PLUGIN(QDarwinCameraPermissionPlugin) +Q_IMPORT_PLUGIN(QDarwinMicrophonePermissionPlugin) +Q_IMPORT_PLUGIN(QDarwinBluetoothPermissionPlugin) +Q_IMPORT_PLUGIN(QDarwinContactsPermissionPlugin) +Q_IMPORT_PLUGIN(QDarwinCalendarPermissionPlugin) +#endif +// @snippet darwin_permission_plugin + +// @snippet qt-modifier +PyObject *_inputDict = PyDict_New(); +// Note: The builtins line is no longer needed since Python 3.10. Undocumented! +PyDict_SetItemString(_inputDict, "__builtins__", PyEval_GetBuiltins()); +PyDict_SetItemString(_inputDict, "QtCore", module); +PyDict_SetItemString(_inputDict, "Qt", reinterpret_cast<PyObject *>(pyType)); +// Explicitly not dereferencing the result. +PyRun_String(R"PY(if True: + from enum import Flag + from textwrap import dedent + from warnings import warn + # QtCore and Qt come as globals. + + def func_or(self, other): + if isinstance(self, Flag) and isinstance(other, Flag): + # this is normal or-ing flags together + return Qt.KeyboardModifier(self.value | other.value) + return QtCore.QKeyCombination(self, other) + + def func_add(self, other): + warn(dedent(f""" + The "+" operator is deprecated in Qt For Python 6.0 . + Please use "|" instead."""), stacklevel=2) + return func_or(self, other) + + Qt.KeyboardModifier.__or__ = func_or + Qt.KeyboardModifier.__ror__ = func_or + Qt.Modifier.__or__ = func_or + Qt.Modifier.__ror__ = func_or + Qt.KeyboardModifier.__add__ = func_add + Qt.KeyboardModifier.__radd__ = func_add + Qt.Modifier.__add__ = func_add + Qt.Modifier.__radd__ = func_add + +)PY", Py_file_input, _inputDict, _inputDict); +// @snippet qt-modifier diff --git a/sources/pyside6/PySide6/glue/qtdatavisualization.cpp b/sources/pyside6/PySide6/glue/qtdatavisualization.cpp index 21c8eb23f..3a179cb17 100644 --- a/sources/pyside6/PySide6/glue/qtdatavisualization.cpp +++ b/sources/pyside6/PySide6/glue/qtdatavisualization.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 // @snippet releaseownership Shiboken::Object::releaseOwnership(%PYARG_1); @@ -77,8 +41,50 @@ using ListType = decltype(%2); using ListType = decltype(%2); %CPPSELF.setRow(%1, new ListType(%2), %3); // @snippet dataproxy-setrow-string -// + // @snippet dataproxy-resetarray using ListType = decltype(%1); %CPPSELF.resetArray(new ListType(%1)); // @snippet dataproxy-resetarray + +// @snippet dataproxy-resetarray2 +using ListType = decltype(%1); +%CPPSELF.resetArray(new ListType(%1), %2, %3); +// @snippet dataproxy-resetarray2 + +// @snippet scatterdataproxy-resetarray +%CPPSELF.resetArray(new QScatterDataArray(*%1)); +// @snippet scatterdataproxy-resetarray + +// @snippet qsurfacedataproxy-resetarraynp +auto *data = QtDataVisualizationHelper::surfaceDataFromNp(%1, %2, %3, %4, %5); +// %CPPSELF.%FUNCTION_NAME +%CPPSELF.resetArray(data); +// @snippet qsurfacedataproxy-resetarraynp + +// @snippet qvalue3daxisformatter-friend +class QFriendlyValue3DAxisFormatter : public QValue3DAxisFormatter +{ +public: +using QValue3DAxisFormatter::gridPositions; +using QValue3DAxisFormatter::labelPositions; +using QValue3DAxisFormatter::labelStrings; +}; + +static inline QFriendlyValue3DAxisFormatter *friendlyFormatter(QValue3DAxisFormatter *f) +{ + return static_cast<QFriendlyValue3DAxisFormatter *>(f); +} +// @snippet qvalue3daxisformatter-friend + +// @snippet qvalue3daxisformatter-setgridpositions +friendlyFormatter(%CPPSELF)->gridPositions() = %1; +// @snippet qvalue3daxisformatter-setgridpositions + +// @snippet qvalue3daxisformatter-setlabelpositions +friendlyFormatter(%CPPSELF)->labelPositions() = %1; +// @snippet qvalue3daxisformatter-setlabelpositions + +// @snippet qvalue3daxisformatter-setlabelstrings +friendlyFormatter(%CPPSELF)->labelStrings() = %1; +// @snippet qvalue3daxisformatter-setlabelstrings diff --git a/sources/pyside6/PySide6/glue/qtdesigner.cpp b/sources/pyside6/PySide6/glue/qtdesigner.cpp index d18b6f532..d26d9f857 100644 --- a/sources/pyside6/PySide6/glue/qtdesigner.cpp +++ b/sources/pyside6/PySide6/glue/qtdesigner.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// 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 // @snippet qtdesigner-registercustomwidget if (!QPyDesignerCustomWidgetCollection::_registerCustomWidgetHelper(%PYARG_1, kwds)) diff --git a/sources/pyside6/PySide6/glue/qtgraphs.cpp b/sources/pyside6/PySide6/glue/qtgraphs.cpp new file mode 100644 index 000000000..b5a5db799 --- /dev/null +++ b/sources/pyside6/PySide6/glue/qtgraphs.cpp @@ -0,0 +1,8 @@ +// Copyright (C) 2023 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 + +// @snippet graphs-qsurfacedataproxy-resetarraynp +auto data = QtGraphsHelper::surfaceDataFromNp(%1, %2, %3, %4, %5); +// %CPPSELF.%FUNCTION_NAME +%CPPSELF.resetArray(data); +// @snippet graphs-qsurfacedataproxy-resetarraynp diff --git a/sources/pyside6/PySide6/glue/qtgui.cpp b/sources/pyside6/PySide6/glue/qtgui.cpp index 81181dac4..5c860a2bf 100644 --- a/sources/pyside6/PySide6/glue/qtgui.cpp +++ b/sources/pyside6/PySide6/glue/qtgui.cpp @@ -1,46 +1,16 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 /********************************************************************* * INJECT CODE ********************************************************************/ +// @snippet gui-declarations +QT_BEGIN_NAMESPACE +void qt_set_sequence_auto_mnemonic(bool); +QT_END_NAMESPACE +// @snippet gui-declarations + // @snippet qaccessible-pysidefactory // Helper for QAccessible::installFactory() that forwards the calls to // Python callables. @@ -136,6 +106,140 @@ QAccessibleInterface *PySideAccessibleFactory::callFactories(const QString &key, PySideAccessibleFactory::ensureInstance()->installFactory(%1); // @snippet qaccessible-installfactory +// @snippet qaction-menu +// %CPPSELF->menu(); // pretend it was called. +QObject *object = %CPPSELF->menu<QObject *>(); +%PYARG_0 = %CONVERTTOPYTHON[QObject*](object); +// @snippet qaction-menu + +// @snippet qopenglfunctions-glgetv-return-size +// Return the number of return values of the glGetBoolean/Double/Integerv functions +// cf https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGet.xhtml +static int glGetVReturnSize(GLenum pname) +{ + switch (pname) { + case GL_ALIASED_LINE_WIDTH_RANGE: + case GL_DEPTH_RANGE: + case GL_MAX_VIEWPORT_DIMS: +#if !QT_CONFIG(opengles2) + case GL_POINT_SIZE_RANGE: + case GL_SMOOTH_LINE_WIDTH_RANGE: + case GL_VIEWPORT_BOUNDS_RANGE: +#endif + return 2; + case GL_BLEND_COLOR: + case GL_COLOR_CLEAR_VALUE: + case GL_COLOR_WRITEMASK: + case GL_SCISSOR_BOX: + case GL_VIEWPORT: + return 4; + case GL_COMPRESSED_TEXTURE_FORMATS: + return GL_NUM_COMPRESSED_TEXTURE_FORMATS; + default: + break; + } + return 1; +} +// @snippet qopenglfunctions-glgetv-return-size + +// @snippet qopenglextrafunctions-glgeti-v-return-size +// Return the number of return values of the indexed +// glGetBoolean/Double/Integeri_v functions +// cf https://registry.khronos.org/OpenGL-Refpages/gl4/html/glGet.xhtml +static int glGetI_VReturnSize(GLenum pname) +{ + return pname == GL_VIEWPORT ? 4 : 1; +} +// @snippet qopenglextrafunctions-glgeti-v-return-size + +// @snippet qopenglfunctions-glgetbooleanv +const int size = glGetVReturnSize(%1); +QVarLengthArray<GLboolean> result(size, GL_FALSE); +%CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, result.data()); +if (size == 1) { + %PYARG_0 = %CONVERTTOPYTHON[bool](result[0]); +} else { + %PYARG_0 = Shiboken::Numpy::createByteArray1(size, result.constData()); +} +// @snippet qopenglfunctions-glgetbooleanv + +// @snippet qopenglfunctions-glgetdoublev +const int size = glGetVReturnSize(%1); +QVarLengthArray<GLdouble> result(size, 0); +%CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, result.data()); +if (size == 1) { + %PYARG_0 = %CONVERTTOPYTHON[double](result[0]); +} else { + %PYARG_0 = Shiboken::Numpy::createDoubleArray1(size, result.constData()); +} +// @snippet qopenglfunctions-glgetdoublev + +// @snippet qopenglfunctions-glgetfloatv +const int size = glGetVReturnSize(%1); +QVarLengthArray<GLfloat> result(size, 0); +%CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, result.data()); +if (size == 1) { + %PYARG_0 = %CONVERTTOPYTHON[float](result[0]); +} else { + %PYARG_0 = Shiboken::Numpy::createFloatArray1(size, result.constData()); +} +// @snippet qopenglfunctions-glgetfloatv + +// @snippet qopenglfunctions-glgetintegerv +const int size = glGetVReturnSize(%1); +QVarLengthArray<GLint> result(size, 0); +%CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, result.data()); +if (size == 1) { + %PYARG_0 = %CONVERTTOPYTHON[int](result[0]); +} else { + %PYARG_0 = Shiboken::Numpy::createIntArray1(size, result.constData()); +} +// @snippet qopenglfunctions-glgetintegerv + +// @snippet qopenglextrafunctions-glgetbooleani-v +const int size = glGetI_VReturnSize(%1); +QVarLengthArray<GLboolean> result(size, GL_FALSE); +%CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, result.data()); +if (size == 1) { + %PYARG_0 = %CONVERTTOPYTHON[bool](result[0]); +} else { + %PYARG_0 = Shiboken::Numpy::createByteArray1(size, result.constData()); +} +// @snippet qopenglextrafunctions-glgetbooleani-v + +// @snippet qopenglextrafunctions-glgetdoublei-v +const int size = glGetI_VReturnSize(%1); +QVarLengthArray<GLdouble> result(size, 0); +%CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, result.data()); +if (size == 1) { + %PYARG_0 = %CONVERTTOPYTHON[double](result[0]); +} else { + %PYARG_0 = Shiboken::Numpy::createDoubleArray1(size, result.constData()); +} +// @snippet qopenglextrafunctions-glgetdoublei-v + +// @snippet qopenglextrafunctions-glgetfloati-v +const int size = glGetI_VReturnSize(%1); +QVarLengthArray<GLfloat> result(size, 0); +%CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, result.data()); +if (size == 1) { + %PYARG_0 = %CONVERTTOPYTHON[float](result[0]); +} else { + %PYARG_0 = Shiboken::Numpy::createFloatArray1(size, result.constData()); +} +// @snippet qopenglextrafunctions-glgetfloati-v + +// @snippet qopenglextrafunctions-glgetintegeri-v +const int size = glGetI_VReturnSize(%1); +QVarLengthArray<GLint> result(size, 0); +%CPPSELF.%FUNCTION_NAME(%ARGUMENT_NAMES, result.data()); +if (size == 1) { + %PYARG_0 = %CONVERTTOPYTHON[int](result[0]); +} else { + %PYARG_0 = Shiboken::Numpy::createIntArray1(size, result.constData()); +} +// @snippet qopenglextrafunctions-glgetintegeri-v + // @snippet glgetshadersource GLsizei bufSize = 4096; GLsizei length = bufSize - 1; @@ -210,10 +314,19 @@ if (_i < 0 || _i >= %CPPSELF.count()) { PyErr_SetString(PyExc_IndexError, "index out of bounds"); return 0; } -int item = (*%CPPSELF)[_i]; -return %CONVERTTOPYTHON[int](item); +QKeyCombination item = (*%CPPSELF)[_i]; +return %CONVERTTOPYTHON[QKeyCombination](item); // @snippet qkeysequence-getitem +// @snippet qkeysequence-repr +auto ObTuple_Type = reinterpret_cast<PyObject *>(&PyTuple_Type); +auto ObSelf_Type = reinterpret_cast<PyObject *>(Py_TYPE(%PYSELF)); +Shiboken::AutoDecRef surrogate(PyObject_CallFunctionObjArgs(ObTuple_Type, %PYSELF, nullptr)); +Shiboken::AutoDecRef argstr(PyObject_Repr(surrogate)); +Shiboken::AutoDecRef name(PyObject_GetAttrString(ObSelf_Type, "__name__")); +return PyUnicode_Concat(name, argstr); +// @snippet qkeysequence-repr + // @snippet qpicture-data %PYARG_0 = Shiboken::Buffer::newObject(%CPPSELF.data(), %CPPSELF.size()); // @snippet qpicture-data @@ -235,7 +348,7 @@ if (doc) { // @snippet qtextblock-userdata // @snippet qpolygon-reduce -const Py_ssize_t count = %CPPSELF.count(); +const Py_ssize_t count = %CPPSELF.size(); PyObject *points = PyList_New(count); for (Py_ssize_t i = 0; i < count; ++i){ int x, y; @@ -255,6 +368,21 @@ for (Py_ssize_t i = 0; i < count; ++i){ %0 = new %TYPE(QPixmap::fromImage(%1)); // @snippet qpixmap +// @snippet qicon-addpixmap +const auto path = PySide::pyPathToQString(%PYARG_1); +%CPPSELF->addPixmap(path); +// @snippet qicon-addpixmap + +// @snippet qclipboard-setpixmap +const auto path = PySide::pyPathToQString(%PYARG_1); +%CPPSELF->setPixmap(QPixmap(path)); +// @snippet qclipboard-setpixmap + +// @snippet qclipboard-setimage +const auto path = PySide::pyPathToQString(%PYARG_1); +%CPPSELF->setImage(QImage(path)); +// @snippet qclipboard-setimage + // @snippet qimage-decref-image-data static void imageDecrefDataHandler(void *data) { @@ -572,6 +700,15 @@ const auto points = PySide::Numpy::xyDataToQPointFList(%PYARG_1, %PYARG_2); %CPPSELF.%FUNCTION_NAME(%1.constData(), %1.size(), %2); // @snippet qpainter-drawpolygon +// @snippet qpainter-enter +Py_INCREF(%PYSELF); +pyResult = %PYSELF; +// @snippet qpainter-enter + +// @snippet qpainter-exit +%CPPSELF.end(); +// @snippet qpainter-exit + // @snippet qmatrix4x4 // PYSIDE-795: All PySequences can be made iterable with PySequence_Fast. Shiboken::AutoDecRef seq(PySequence_Fast(%PYARG_1, "Can't turn into sequence")); @@ -640,12 +777,51 @@ if (!PyTuple_SetItem(empty, 0, PyList_New(0))) { } // @snippet qguiapplication-2 +// @snippet qguiapplication-setoverridecursor +auto *cppResult = new QtGuiHelper::QOverrideCursorGuard(); +%PYARG_0 = %CONVERTTOPYTHON[QtGuiHelper::QOverrideCursorGuard*](cppResult); +Shiboken::Object::getOwnership(%PYARG_0); // Ensure the guard is removed +// @snippet qguiapplication-setoverridecursor + +// @snippet qguiapplication-nativeInterface +bool hasNativeApp = false; +#if QT_CONFIG(xcb) +if (auto *x11App = %CPPSELF.nativeInterface<QNativeInterface::QX11Application>()) { + hasNativeApp = true; + %PYARG_0 = %CONVERTTOPYTHON[QNativeInterface::QX11Application*](x11App); +} +#endif +if (!hasNativeApp) { + Py_INCREF(Py_None); + %PYARG_0 = Py_None; +} +// @snippet qguiapplication-nativeInterface + // @snippet qscreen-grabWindow WId id = %1; %RETURN_TYPE retval = %CPPSELF.%FUNCTION_NAME(id, %2, %3, %4, %5); %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](retval); // @snippet qscreen-grabWindow +// @snippet qscreen-nativeInterface +bool hasNativeScreen = false; +#ifdef Q_OS_WIN +if (auto *winScreen = %CPPSELF.nativeInterface<QNativeInterface::QWindowsScreen>()) { + hasNativeScreen = true; + %PYARG_0 = %CONVERTTOPYTHON[QNativeInterface::QWindowsScreen*](winScreen); +} +#endif +if (!hasNativeScreen) { + Py_INCREF(Py_None); + %PYARG_0 = Py_None; +} +// @snippet qscreen-nativeInterface + +// @snippet qx11application-resource-ptr + auto *resource = %CPPSELF.%FUNCTION_NAME(); +%PYARG_0 = PyLong_FromVoidPtr(resource); +// @snippet qx11application-resource-ptr + // @snippet qwindow-fromWinId WId id = %1; %RETURN_TYPE retval = %CPPSELF.%FUNCTION_NAME(id); @@ -713,6 +889,47 @@ else %PYARG_0 = %CONVERTTOPYTHON[int](cppResult); // @snippet qdrag-exec-arg2 +// @snippet qquaternion-getaxisandangle-vector3d-float +QVector3D outVec{}; +float angle{}; +%CPPSELF.%FUNCTION_NAME(&outVec, &angle); +%PYARG_0 = PyTuple_New(2); +PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[QVector3D](outVec)); +PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[float](angle)); +// @snippet qquaternion-getaxisandangle-vector3d-float + +// @snippet qquaternion-geteulerangles +float pitch{}, yaw{}, roll{}; +%CPPSELF.%FUNCTION_NAME(&pitch, &yaw, &roll); +%PYARG_0 = PyTuple_New(3); +PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[float](pitch)); +PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[float](yaw)); +PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[float](roll)); +// @snippet qquaternion-geteulerangles + +// @snippet qregion-len +return %CPPSELF.rectCount(); +// @snippet qregion-len + +// @snippet qregion-getitem +if (_i < 0 || _i >= %CPPSELF.rectCount()) + return PyErr_Format(PyExc_IndexError, "index out of bounds"); + +const QRect cppResult = *(%CPPSELF.cbegin() + _i); +return %CONVERTTOPYTHON[QRect](cppResult); +// @snippet qregion-getitem + +// Some RHI functions take a std::initializer_list<>. Add functions +// to convert from list. + +// @snippet qrhi-initializer-list +%CPPSELF.%FUNCTION_NAME(%1.cbegin(), %1.cend()); +// @snippet qrhi-initializer-list + +// @snippet qrhi-commandbuffer-setvertexinput +%CPPSELF.%FUNCTION_NAME(%1, %2.size(), %2.constData(), %3, %4, %5); +// @snippet qrhi-commandbuffer-setvertexinput + /********************************************************************* * CONVERSIONS ********************************************************************/ diff --git a/sources/pyside6/PySide6/glue/qtmultimedia.cpp b/sources/pyside6/PySide6/glue/qtmultimedia.cpp index 36f831f07..ac8434b97 100644 --- a/sources/pyside6/PySide6/glue/qtmultimedia.cpp +++ b/sources/pyside6/PySide6/glue/qtmultimedia.cpp @@ -1,46 +1,28 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 // @snippet qvideoframe-bits +#include "object.h" %BEGIN_ALLOW_THREADS %RETURN_TYPE %0 = %CPPSELF.%FUNCTION_NAME(%1); %END_ALLOW_THREADS const auto size = %CPPSELF.mappedBytes(%1); %PYARG_0 = Shiboken::Buffer::newObject(%0, size, Shiboken::Buffer::ReadWrite); // @snippet qvideoframe-bits + +// @snippet qaudiobuffer-data +unsigned char *data = %CPPSELF.%FUNCTION_NAME<unsigned char>(); +const auto size = %CPPSELF.byteCount(); +%PYARG_0 = Shiboken::Buffer::newObject(data, size, Shiboken::Buffer::ReadWrite); +// @snippet qaudiobuffer-data + +// @snippet qaudiobuffer-const-data +const unsigned char *data = %CPPSELF.%FUNCTION_NAME<unsigned char>(); +const auto size = %CPPSELF.byteCount(); +%PYARG_0 = Shiboken::Buffer::newObject(data, size); +// @snippet qaudiobuffer-const-data + +// @snippet qtaudio-namespace-compatibility-alias +Py_INCREF(pyType); +PyModule_AddObject(module, "QtAudio", reinterpret_cast<PyObject *>(pyType)); +// @snippet qtaudio-namespace-compatibility-alias diff --git a/sources/pyside6/PySide6/glue/qtnetwork.cpp b/sources/pyside6/PySide6/glue/qtnetwork.cpp index 277dd6d7c..f635f4671 100644 --- a/sources/pyside6/PySide6/glue/qtnetwork.cpp +++ b/sources/pyside6/PySide6/glue/qtnetwork.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 // @snippet qudpsocket-readdatagram Shiboken::AutoArrayPointer<char> data(%ARGUMENT_NAMES); @@ -51,20 +15,28 @@ PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[QHostAddress](ha)); PyTuple_SET_ITEM(%PYARG_0, 2, %CONVERTTOPYTHON[quint16](port)); // @snippet qudpsocket-readdatagram -// @snippet qhostinfo-lookuphost-callable -auto *callable = %PYARG_2; -auto cppCallback = [callable](const QHostInfo &hostInfo) +// @snippet qhostinfo-lookuphost-functor +struct QHostInfoFunctor : public Shiboken::PyObjectHolder +{ +public: + using Shiboken::PyObjectHolder::PyObjectHolder; + + void operator()(const QHostInfo &hostInfo); +}; + +void QHostInfoFunctor::operator()(const QHostInfo &hostInfo) { Shiboken::GilState state; Shiboken::AutoDecRef arglist(PyTuple_New(1)); auto *pyHostInfo = %CONVERTTOPYTHON[QHostInfo](hostInfo); PyTuple_SET_ITEM(arglist.object(), 0, pyHostInfo); - Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); - Py_DECREF(callable); -}; + Shiboken::AutoDecRef ret(PyObject_CallObject(object(), arglist)); + release(); // single shot +} +// @snippet qhostinfo-lookuphost-functor -Py_INCREF(callable); -%CPPSELF.%FUNCTION_NAME(%1, cppCallback); +// @snippet qhostinfo-lookuphost-callable +%CPPSELF.%FUNCTION_NAME(%1, QHostInfoFunctor(%PYARG_2)); // @snippet qhostinfo-lookuphost-callable // @snippet qipv6address-len @@ -94,3 +66,65 @@ quint8 item = %CONVERTTOCPP[quint8](_value); %CPPSELF.c[_i] = item; return 0; // @snippet qipv6address-setitem + +// @snippet qrestaccessmanager-functor +class QRestFunctor +{ +public: + explicit QRestFunctor(PyObject *callable) noexcept : m_callable(callable) + { + Py_INCREF(callable); + } + + void operator()(QRestReply &restReply); + +private: + PyObject *m_callable; +}; + +void QRestFunctor::operator()(QRestReply &restReply) +{ + Q_ASSERT(m_callable); + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + auto *restReplyPtr = &restReply; + auto *pyRestReply = %CONVERTTOPYTHON[QRestReply*](restReplyPtr); + PyTuple_SET_ITEM(arglist.object(), 0, pyRestReply); + Shiboken::AutoDecRef ret(PyObject_CallObject(m_callable, arglist)); + Py_DECREF(m_callable); + m_callable = nullptr; +} +// @snippet qrestaccessmanager-functor + +// @snippet qrestaccessmanager-callback +auto *networkReply = %CPPSELF.%FUNCTION_NAME(%1, %2, QRestFunctor(%PYARG_3)); +%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](networkReply); +// @snippet qrestaccessmanager-callback + +// @snippet qrestaccessmanager-data-callback +auto *networkReply = %CPPSELF.%FUNCTION_NAME(%1, %2, %3, QRestFunctor(%PYARG_4)); +%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](networkReply); +// @snippet qrestaccessmanager-data-callback + +// @snippet qrestaccessmanager-method-data-callback +auto *networkReply = %CPPSELF.%FUNCTION_NAME(%1, %2, %3, %4, QRestFunctor(%PYARG_5)); +%PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](networkReply); +// @snippet qrestaccessmanager-method-data-callback + +// @snippet qrestreply-readjson +QJsonParseError jsonParseError; +std::optional<QJsonDocument> documentOptional = %CPPSELF.%FUNCTION_NAME(&jsonParseError); + +PyObject *pyDocument{}; +if (documentOptional.has_value()) { + const auto &document = documentOptional.value(); + pyDocument = %CONVERTTOPYTHON[QJsonDocument](document); +} else { + pyDocument = Py_None; + Py_INCREF(Py_None); +} + +%PYARG_0 = PyTuple_New(2); +PyTuple_SetItem(%PYARG_0, 0, pyDocument); +PyTuple_SetItem(%PYARG_0, 1, %CONVERTTOPYTHON[QJsonParseError](jsonParseError)); +// @snippet qrestreply-readjson diff --git a/sources/pyside6/PySide6/glue/qtnetworkauth.cpp b/sources/pyside6/PySide6/glue/qtnetworkauth.cpp new file mode 100644 index 000000000..7877a8dd5 --- /dev/null +++ b/sources/pyside6/PySide6/glue/qtnetworkauth.cpp @@ -0,0 +1,44 @@ +// Copyright (C) 2022 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 + +// @snippet qabstractoauth-lookuphost-functor +struct QAbstractOAuthModifyFunctor : public Shiboken::PyObjectHolder +{ +public: + using Shiboken::PyObjectHolder::PyObjectHolder; + + void operator()(QAbstractOAuth::Stage stage, QMultiMap<QString, QVariant>* dictPointer); +}; + +void QAbstractOAuthModifyFunctor::operator()(QAbstractOAuth::Stage stage, + QMultiMap<QString, QVariant>* dictPointer) +{ + auto *callable = object(); + if (!PyCallable_Check(callable)) { + qWarning("Argument 1 of setModifyParametersFunction() must be a callable."); + return; + } + Shiboken::GilState state; + QMultiMap<QString, QVariant> dict = *dictPointer; + Shiboken::AutoDecRef arglist(PyTuple_New(2)); + PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[QAbstractOAuth::Stage](stage)); + PyTuple_SET_ITEM(arglist, 1, %CONVERTTOPYTHON[QMultiMap<QString, QVariant>](dict)); + Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); + + if (!ret.isNull() && PyDict_Check(ret.object()) != 0) { + PyObject *key{}; + PyObject *value{}; + Py_ssize_t pos = 0; + while (PyDict_Next(ret.object(), &pos, &key, &value)) { + QString cppKey = %CONVERTTOCPP[QString](key); + QVariant cppValue = %CONVERTTOCPP[QVariant](value); + dictPointer->replace(cppKey, cppValue); + } + } +} +// @snippet qabstractoauth-lookuphost-functor + +// @snippet qabstractoauth-setmodifyparametersfunction +%CPPSELF.%FUNCTION_NAME(QAbstractOAuthModifyFunctor(%PYARG_1)); +// @snippet qabstractoauth-setmodifyparametersfunction + diff --git a/sources/pyside6/PySide6/glue/qtopengl.cpp b/sources/pyside6/PySide6/glue/qtopengl.cpp index 9638ec77d..cdfaafb3b 100644 --- a/sources/pyside6/PySide6/glue/qtopengl.cpp +++ b/sources/pyside6/PySide6/glue/qtopengl.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// 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 /********************************************************************* * INJECT CODE @@ -107,3 +71,19 @@ if (auto *f = dynamic_cast<QOpenGLFunctions_4_5_Core *>(af)) { } // @snippet qopenglversionfunctionsfactory-get +// @snippet glgetvreturnsize_declaration +int glGetVReturnSize(GLenum pname); +// @snippet glgetvreturnsize_declaration + +// @snippet glgeti-vreturnsize_declaration +int glGetI_VReturnSize(GLenum pname); +// @snippet glgeti-vreturnsize_declaration + +// @snippet vao-binder-enter +Py_INCREF(%PYSELF); +pyResult = %PYSELF; +// @snippet vao-binder-enter + +// @snippet vao-binder-exit +%CPPSELF.release(); +// @snippet vao-binder-exit diff --git a/sources/pyside6/PySide6/glue/qtpositioning.cpp b/sources/pyside6/PySide6/glue/qtpositioning.cpp new file mode 100644 index 000000000..91c331c74 --- /dev/null +++ b/sources/pyside6/PySide6/glue/qtpositioning.cpp @@ -0,0 +1,14 @@ +// 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 + +/********************************************************************* + * INJECT CODE + ********************************************************************/ + +// @snippet darwin_location_permission_plugin +#ifdef Q_OS_DARWIN +#include<QtCore/qplugin.h> +// register the static plugin and setup its metadata +Q_IMPORT_PLUGIN(QDarwinLocationPermissionPlugin) +#endif +// @snippet darwin_location_permission_plugin diff --git a/sources/pyside6/PySide6/glue/qtprintsupport.cpp b/sources/pyside6/PySide6/glue/qtprintsupport.cpp index acd8eb4e2..39672c62a 100644 --- a/sources/pyside6/PySide6/glue/qtprintsupport.cpp +++ b/sources/pyside6/PySide6/glue/qtprintsupport.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 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 // @snippet setpagesize bool out = %CPPSELF.setPageSize(%1); diff --git a/sources/pyside6/PySide6/glue/qtqml.cpp b/sources/pyside6/PySide6/glue/qtqml.cpp index 99a1c441a..a56db8de6 100644 --- a/sources/pyside6/PySide6/glue/qtqml.cpp +++ b/sources/pyside6/PySide6/glue/qtqml.cpp @@ -1,74 +1,49 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 + +// @snippet qmlerrror-repr +const QByteArray message = %CPPSELF.toString().toUtf8(); +%PYARG_0 = Shiboken::String::fromCString(message.constData()); +// @snippet qmlerrror-repr + +// @snippet qmlattachedpropertiesobject +auto *%0 = PySide::Qml::qmlAttachedPropertiesObject(%ARGUMENT_NAMES); +%PYARG_0 = %CONVERTTOPYTHON[QObject*](%0); +// @snippet qmlattachedpropertiesobject // @snippet qmlregistertype -int %0 = PySide::qmlRegisterType(%ARGUMENT_NAMES); +int %0 = PySide::Qml::qmlRegisterType(%ARGUMENT_NAMES); %PYARG_0 = %CONVERTTOPYTHON[int](%0); // @snippet qmlregistertype // @snippet qmlregistersingletontype_qobject_callback -int %0 = PySide::qmlRegisterSingletonType(%ARGUMENT_NAMES, true, true); +int %0 = PySide::Qml::qmlRegisterSingletonType(%ARGUMENT_NAMES, true, true); %PYARG_0 = %CONVERTTOPYTHON[int](%0); // @snippet qmlregistersingletontype_qobject_callback // @snippet qmlregistersingletontype_qobject_nocallback -int %0 = PySide::qmlRegisterSingletonType(%ARGUMENT_NAMES, nullptr, true, false); +int %0 = PySide::Qml::qmlRegisterSingletonType(%ARGUMENT_NAMES, nullptr, true, false); %PYARG_0 = %CONVERTTOPYTHON[int](%0); // @snippet qmlregistersingletontype_qobject_nocallback // @snippet qmlregistersingletontype_qjsvalue -int %0 = PySide::qmlRegisterSingletonType(nullptr, %ARGUMENT_NAMES, false, true); +int %0 = PySide::Qml::qmlRegisterSingletonType(nullptr, %ARGUMENT_NAMES, false, true); %PYARG_0 = %CONVERTTOPYTHON[int](%0); // @snippet qmlregistersingletontype_qjsvalue // @snippet qmlregistersingletoninstance -int %0 = PySide::qmlRegisterSingletonInstance(%ARGUMENT_NAMES); +int %0 = PySide::Qml::qmlRegisterSingletonInstance(%ARGUMENT_NAMES); %PYARG_0 = %CONVERTTOPYTHON[int](%0); // @snippet qmlregistersingletoninstance // @snippet qmlregisteruncreatabletype -int %0 = PySide::qmlRegisterType(%ARGUMENT_NAMES, false); +int %0 = PySide::Qml::qmlRegisterType(%ARGUMENT_NAMES, false); %PYARG_0 = %CONVERTTOPYTHON[int](%0); // @snippet qmlregisteruncreatabletype // @snippet init -PySide::initQmlSupport(module); +PySide::Qml::init(module); +initQtQmlVolatileBool(module); // @snippet init // @snippet qjsengine-toscriptvalue @@ -77,5 +52,39 @@ return %CONVERTTOPYTHON[%RETURN_TYPE](retval); // @snippet qjsengine-toscriptvalue // @snippet qmlelement -%PYARG_0 = PySide::qmlElementMacro(%ARGUMENT_NAMES); +%PYARG_0 = PySide::Qml::qmlElementMacro(%ARGUMENT_NAMES); // @snippet qmlelement + +// @snippet qmlanonymous +%PYARG_0 = PySide::Qml::qmlAnonymousMacro(%ARGUMENT_NAMES); +// @snippet qmlanonymous + +// @snippet qmlsingleton +%PYARG_0 = PySide::Qml::qmlSingletonMacro(%ARGUMENT_NAMES); +// @snippet qmlsingleton + +// @snippet qqmlengine-singletoninstance-qmltypeid +QJSValue instance = %CPPSELF.singletonInstance<QJSValue>(%1); +if (instance.isNull()) { + Py_INCREF(Py_None); + %PYARG_0 = Py_None; +} else if (instance.isQObject()) { + QObject *result = instance.toQObject(); + %PYARG_0 = %CONVERTTOPYTHON[QObject *](result); +} else { + %PYARG_0 = %CONVERTTOPYTHON[QJSValue](instance); +} +// @snippet qqmlengine-singletoninstance-qmltypeid + +// @snippet qqmlengine-singletoninstance-typename +QJSValue instance = %CPPSELF.singletonInstance<QJSValue>(%1, %2); +if (instance.isNull()) { + Py_INCREF(Py_None); + %PYARG_0 = Py_None; +} else if (instance.isQObject()) { + QObject *result = instance.toQObject(); + %PYARG_0 = %CONVERTTOPYTHON[QObject *](result); +} else { + %PYARG_0 = %CONVERTTOPYTHON[QJSValue](instance); +} +// @snippet qqmlengine-singletoninstance-typename diff --git a/sources/pyside6/PySide6/glue/qtquick.cpp b/sources/pyside6/PySide6/glue/qtquick.cpp index b7c31aff3..060418faf 100644 --- a/sources/pyside6/PySide6/glue/qtquick.cpp +++ b/sources/pyside6/PySide6/glue/qtquick.cpp @@ -1,42 +1,27 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 // @snippet qtquick PySide::initQuickSupport(module); // @snippet qtquick + +// @snippet qsgeometry-vertexdataaspoint2d +auto *points = %CPPSELF->vertexDataAsPoint2D(); +const Py_ssize_t vertexCount = %CPPSELF->vertexCount(); +%PYARG_0 = PyList_New(vertexCount); +for (Py_ssize_t i = 0; i < vertexCount; ++i) { + QSGGeometry::Point2D p = points[i]; + PyList_SET_ITEM(%PYARG_0, i, %CONVERTTOPYTHON[QSGGeometry::Point2D](p)); +} +// @snippet qsgeometry-vertexdataaspoint2d + +// @snippet qsgeometry-setvertexdataaspoint2d +const qsizetype vertexCount = %CPPSELF->vertexCount(); +if (vertexCount != %1.size()) { + PyErr_SetString(PyExc_RuntimeError, "size mismatch"); + return {}; +} + +QSGGeometry::Point2D *points = %CPPSELF->vertexDataAsPoint2D(); +std::copy(%1.cbegin(), %1.cend(), points); +// @snippet qsgeometry-setvertexdataaspoint2d diff --git a/sources/pyside6/PySide6/glue/qtquicktest.cpp b/sources/pyside6/PySide6/glue/qtquicktest.cpp new file mode 100644 index 000000000..f41735ddf --- /dev/null +++ b/sources/pyside6/PySide6/glue/qtquicktest.cpp @@ -0,0 +1,50 @@ +// Copyright (C) 2023 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 + +/********************************************************************* + * INJECT CODE + ********************************************************************/ + +// @snippet call-quick-test-main +static int callQuickTestMain(const QString &name, QObject *setup, + QStringList argv, QString dir) +{ + if (dir.isEmpty()) + dir = QDir::currentPath(); + if (argv.isEmpty()) + argv.append(name); + + std::vector<QByteArray> argvB; + std::vector<char *> argvC; + const auto argc = argv.size(); + argvB.reserve(argc); + argvC.reserve(argc); + for (const auto &arg : argv) { + argvB.emplace_back(arg.toUtf8()); + argvC.push_back(argvB.back().data()); + } + + return quick_test_main_with_setup(int(argc), argvC.data(), + name.toUtf8().constData(), + dir.toUtf8().constData(), setup); +} +// @snippet call-quick-test-main + +// @snippet quick-test-main +const int exitCode = callQuickTestMain(%1, nullptr, %2, %3); +%PYARG_0 = %CONVERTTOPYTHON[int](exitCode); +// @snippet quick-test-main + +// @snippet quick-test-main_with_setup +Shiboken::AutoDecRef pySetupObject(PyObject_CallObject(reinterpret_cast<PyObject *>(%2), nullptr)); +if (pySetupObject.isNull() || PyErr_Occurred() != nullptr) + return nullptr; + +/// Convenience to convert a PyObject to QObject +QObject *setupObject = PySide::convertToQObject(pySetupObject.object(), true /* raiseError */); +if (setupObject == nullptr) + return nullptr; + +const int exitCode = callQuickTestMain(%1, setupObject, %3, %4); +%PYARG_0 = %CONVERTTOPYTHON[int](exitCode); +// @snippet quick-test-main_with_setup diff --git a/sources/pyside6/PySide6/glue/qtserialbus.cpp b/sources/pyside6/PySide6/glue/qtserialbus.cpp new file mode 100644 index 000000000..b5b491f49 --- /dev/null +++ b/sources/pyside6/PySide6/glue/qtserialbus.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2022 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 + +/********************************************************************* + * INJECT CODE + ********************************************************************/ + +// @snippet qcanbus-available-devices +QString errorMessage; +const QList<QCanBusDeviceInfo> result = %CPPSELF.%FUNCTION_NAME(%1, &errorMessage); +%PYARG_0 = PyTuple_New(2); +PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[QList<QCanBusDeviceInfo>](result)); +PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[QString](errorMessage)); +// @snippet qcanbus-available-devices + +// @snippet qcanbus-createdevice +PyObject *pyDevice{}; +QString errorMessage; +if (auto *device = %CPPSELF.%FUNCTION_NAME(%1, %2, &errorMessage)) { + pyDevice = %CONVERTTOPYTHON[%RETURN_TYPE](device); + // Ownership transferences (target) + Shiboken::Object::getOwnership(pyDevice); +} else { + pyDevice = Py_None; + Py_INCREF(pyDevice); +} +%PYARG_0 = PyTuple_New(2); +PyTuple_SET_ITEM(%PYARG_0, 0, pyDevice); +PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[QString](errorMessage)); +// @snippet qcanbus-createdevice diff --git a/sources/pyside6/PySide6/glue/qtsql.cpp b/sources/pyside6/PySide6/glue/qtsql.cpp index 34860ab9b..ff0d7a7a4 100644 --- a/sources/pyside6/PySide6/glue/qtsql.cpp +++ b/sources/pyside6/PySide6/glue/qtsql.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// 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 // @snippet simple-exec diff --git a/sources/pyside6/PySide6/glue/qtstatemachine.cpp b/sources/pyside6/PySide6/glue/qtstatemachine.cpp index 16b096b5d..098200b14 100644 --- a/sources/pyside6/PySide6/glue/qtstatemachine.cpp +++ b/sources/pyside6/PySide6/glue/qtstatemachine.cpp @@ -1,48 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// 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 /********************************************************************* * INJECT CODE ********************************************************************/ // @snippet qsignaltransition -if (PyObject_TypeCheck(%1, PySideSignalInstanceTypeF())) { +if (PyObject_TypeCheck(%1, PySideSignalInstance_TypeF())) { auto *signalInstance = reinterpret_cast<PySideSignalInstance *>(%PYARG_1); PyObject *dataSource = PySide::Signal::getObject(signalInstance); Shiboken::AutoDecRef obType(PyObject_Type(dataSource)); @@ -75,8 +39,9 @@ if (PySide::SignalManager::registerMetaMethod(%1, signalName.constData(), // since it refers to a name very tied to the generator implementation. // Check bug #362 for more information on this // http://bugs.openbossa.org/show_bug.cgi?id=362 -if (!PyObject_TypeCheck(%1, PySideSignalInstanceTypeF())) - goto Sbk_%TYPEFunc_%FUNCTION_NAME_TypeError; +// PYSIDE-2256: The label was removed +if (!PyObject_TypeCheck(%1, PySideSignalInstance_TypeF())) + return Shiboken::returnWrongArguments(args, fullName, errInfo); PySideSignalInstance *signalInstance = reinterpret_cast<PySideSignalInstance *>(%1); auto sender = %CONVERTTOCPP[QObject *](PySide::Signal::getObject(signalInstance)); QSignalTransition *%0 = %CPPSELF->%FUNCTION_NAME(sender, PySide::Signal::getSignature(signalInstance),%2); diff --git a/sources/pyside6/PySide6/glue/qttest.cpp b/sources/pyside6/PySide6/glue/qttest.cpp index 4fea0a98c..626cc1608 100644 --- a/sources/pyside6/PySide6/glue/qttest.cpp +++ b/sources/pyside6/PySide6/glue/qttest.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// 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 /********************************************************************* * INJECT CODE diff --git a/sources/pyside6/PySide6/glue/qtuitools.cpp b/sources/pyside6/PySide6/glue/qtuitools.cpp index 08cb89c46..1835ed096 100644 --- a/sources/pyside6/PySide6/glue/qtuitools.cpp +++ b/sources/pyside6/PySide6/glue/qtuitools.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 // @snippet uitools-loadui /* * Based on code provided by: @@ -81,7 +45,7 @@ static PyObject *QUiLoadedLoadUiFromDevice(QUiLoader *self, QIODevice *dev, QWid } if (!PyErr_Occurred()) - PyErr_SetString(PyExc_RuntimeError, "Unable to open/read ui device"); + PyErr_Format(PyExc_RuntimeError, "Unable to open/read ui device"); return nullptr; } @@ -98,7 +62,7 @@ Q_IMPORT_PLUGIN(PyCustomWidgets); // @snippet quiloader-registercustomwidget registerCustomWidget(%PYARG_1); -%CPPSELF.addPluginPath(""); // force reload widgets +%CPPSELF.addPluginPath(QString{}); // force reload widgets // @snippet quiloader-registercustomwidget // @snippet quiloader-load-1 @@ -123,38 +87,46 @@ char *arg1 = PyBytes_AsString(strObj); QByteArray uiFileName(arg1); Py_DECREF(strObj); -QFile uiFile(uiFileName); - -if (!uiFile.exists()) { - qCritical().noquote() << "File" << uiFileName << "does not exists"; +if (uiFileName.isEmpty()) { + qCritical() << "Error converting the UI filename to QByteArray"; Py_RETURN_NONE; } -if (uiFileName.isEmpty()) { - qCritical() << "Error converting the UI filename to QByteArray"; +QFile uiFile(QString::fromUtf8(uiFileName)); + +if (!uiFile.exists()) { + qCritical().noquote() << "File" << uiFileName << "does not exist"; Py_RETURN_NONE; } // Use the 'pyside6-uic' wrapper instead of 'uic' // This approach is better than rely on 'uic' since installing // the wheels cover this case. -QString uicBin("pyside6-uic"); +QString uicBin(QStringLiteral("pyside6-uic")); QStringList uicArgs = {QString::fromUtf8(uiFileName)}; QProcess uicProcess; uicProcess.start(uicBin, uicArgs); -if (!uicProcess.waitForFinished()) { - qCritical() << "Cannot run 'pyside6-uic': " << uicProcess.errorString() << " - " - << "Exit status " << uicProcess.exitStatus() - << " (" << uicProcess.exitCode() << ")\n" - << "Check if 'pyside6-uic' is in PATH"; +if (!uicProcess.waitForStarted()) { + qCritical().noquote() << "Cannot run '" << uicBin << "': " + << uicProcess.errorString() << " - Check if 'pyside6-uic' is in PATH"; + Py_RETURN_NONE; +} + +if (!uicProcess.waitForFinished() + || uicProcess.exitStatus() != QProcess::NormalExit + || uicProcess.exitCode() != 0) { + qCritical().noquote() << '\'' << uicBin << "' failed: " + << uicProcess.errorString() << " - Exit status " << uicProcess.exitStatus() + << " (" << uicProcess.exitCode() << ")\n"; Py_RETURN_NONE; } + QByteArray uiFileContent = uicProcess.readAllStandardOutput(); QByteArray errorOutput = uicProcess.readAllStandardError(); if (!errorOutput.isEmpty()) { - qCritical().noquote() << errorOutput; + qCritical().noquote() << '\'' << uicBin << "' failed: " << errorOutput; Py_RETURN_NONE; } @@ -178,8 +150,8 @@ QXmlStreamReader reader(&uiFile); while (!reader.atEnd() && baseClassName.isEmpty() && className.isEmpty()) { auto token = reader.readNext(); if (token == QXmlStreamReader::StartElement && reader.name() == u"widget") { - baseClassName = reader.attributes().value(QLatin1String("class")).toUtf8(); - className = reader.attributes().value(QLatin1String("name")).toUtf8(); + baseClassName = reader.attributes().value(QLatin1StringView("class")).toUtf8(); + className = reader.attributes().value(QLatin1StringView("name")).toUtf8(); } } diff --git a/sources/pyside6/PySide6/glue/qtwebenginecore.cpp b/sources/pyside6/PySide6/glue/qtwebenginecore.cpp new file mode 100644 index 000000000..76a7c6d73 --- /dev/null +++ b/sources/pyside6/PySide6/glue/qtwebenginecore.cpp @@ -0,0 +1,64 @@ +// Copyright (C) 2022 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 + +// @snippet qwebenginecookiestore-functor +struct QWebEngineCookieFilterFunctor : public Shiboken::PyObjectHolder +{ + using Shiboken::PyObjectHolder::PyObjectHolder; + + bool operator()(const QWebEngineCookieStore::FilterRequest& filterRequest) const; +}; + +bool QWebEngineCookieFilterFunctor::operator()(const QWebEngineCookieStore::FilterRequest & + filterRequest) const +{ + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + PyTuple_SET_ITEM(arglist, 0, + %CONVERTTOPYTHON[QWebEngineCookieStore::FilterRequest](filterRequest)); + Shiboken::AutoDecRef ret(PyObject_CallObject(object(), arglist)); + return ret.object() == Py_True; +} +// @snippet qwebenginecookiestore-functor + +// @snippet qwebenginecookiestore-setcookiefilter +%CPPSELF.%FUNCTION_NAME(QWebEngineCookieFilterFunctor(%PYARG_1)); +// @snippet qwebenginecookiestore-setcookiefilter + +// @snippet qwebengineprofile-functor +struct QWebEngineNotificationFunctor : public Shiboken::PyObjectHolder +{ + using Shiboken::PyObjectHolder::PyObjectHolder; + + void operator()(std::unique_ptr<QWebEngineNotification> webEngineNotification); +}; + +void QWebEngineNotificationFunctor::operator() + (std::unique_ptr<QWebEngineNotification> webEngineNotification) +{ + Shiboken::GilState state; + Shiboken::AutoDecRef arglist(PyTuple_New(1)); + auto *notification = webEngineNotification.release(); + PyTuple_SET_ITEM(arglist.object(), 0, + %CONVERTTOPYTHON[QWebEngineNotification*](notification)); + Shiboken::AutoDecRef ret(PyObject_CallObject(object(), arglist)); +}; +// @snippet qwebengineprofile-functor + +// @snippet qwebengineprofile-setnotificationpresenter +%CPPSELF.%FUNCTION_NAME(QWebEngineNotificationFunctor(%PYARG_1)); +// @snippet qwebengineprofile-setnotificationpresenter + +// @snippet qwebenginepage-javascriptprompt-virtual-redirect +std::pair<bool, QString> resultPair = javaScriptPromptPyOverride(gil, pyOverride.object(), securityOrigin, msg, defaultValue); +result->assign(resultPair.second); +return resultPair.first; +// @snippet qwebenginepage-javascriptprompt-virtual-redirect + +// @snippet qwebenginepage-javascriptprompt-return +QString str; +%RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(%1, %2, %3, &str); +%PYARG_0 = PyTuple_New(2); +PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](retval_)); +PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[QString](str)); +// @snippet qwebenginepage-javascriptprompt-return diff --git a/sources/pyside6/PySide6/glue/qtwebenginewidgets.cpp b/sources/pyside6/PySide6/glue/qtwebenginewidgets.cpp index 967bcbbbe..af15130a4 100644 --- a/sources/pyside6/PySide6/glue/qtwebenginewidgets.cpp +++ b/sources/pyside6/PySide6/glue/qtwebenginewidgets.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 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 // @snippet qwebenginepage-findtext auto callable = %PYARG_3; @@ -91,8 +55,8 @@ auto callback = [callable](const QString &text) PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[QString](text)); Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); Py_DECREF(callable); - }; + Py_INCREF(callable); %CPPSELF.%FUNCTION_NAME(callback); // @snippet qwebenginepage-convertto @@ -131,8 +95,8 @@ auto callback = [callable](const QVariant &result) // PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[bool](found)); Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); Py_DECREF(callable); - }; + Py_INCREF(callable); %CPPSELF.%FUNCTION_NAME(%1, %2, callback); // @snippet qwebenginepage-runjavascript @@ -150,8 +114,8 @@ auto callback = [callable](const QByteArray &pdf) PyTuple_SET_ITEM(arglist, 0, %CONVERTTOPYTHON[QByteArray](pdf)); Shiboken::AutoDecRef ret(PyObject_CallObject(callable, arglist)); Py_DECREF(callable); - }; + Py_INCREF(callable); %CPPSELF.%FUNCTION_NAME(callback, %2); // @snippet qwebenginepage-printtopdf diff --git a/sources/pyside6/PySide6/glue/qtwidgets.cpp b/sources/pyside6/PySide6/glue/qtwidgets.cpp index 802a3c172..f886106cf 100644 --- a/sources/pyside6/PySide6/glue/qtwidgets.cpp +++ b/sources/pyside6/PySide6/glue/qtwidgets.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 /********************************************************************* * INJECT CODE @@ -56,7 +20,8 @@ Shiboken::Object::releaseOwnership(%PYARG_0); // @snippet qgraphicsitem PyObject *userTypeConstant = PyLong_FromLong(QGraphicsItem::UserType); -PyDict_SetItemString(Sbk_QGraphicsItem_TypeF()->tp_dict, "UserType", userTypeConstant); +tpDict.reset(PepType_GetDict(Sbk_QGraphicsItem_TypeF())); +PyDict_SetItemString(tpDict.object(), "UserType", userTypeConstant); // @snippet qgraphicsitem // @snippet qgraphicsitem-scene-return-parenting @@ -96,18 +61,74 @@ QFormLayout::ItemRole _role; %CPPSELF->%FUNCTION_NAME(%ARGUMENT_NAMES, &_row, &_role); %PYARG_0 = PyTuple_New(2); PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[int](_row)); +// On the C++ side, *rolePtr is not set if row == -1, in which case on +// the Python side this gets converted to a random value outside the +// enum range. Fix this by setting _role to a default value here. +if (_row == -1) + _role = QFormLayout::LabelRole; PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[QFormLayout::ItemRole](_role)); // @snippet qformlayout-fix-args // @snippet qfiledialog-return +%BEGIN_ALLOW_THREADS %RETURN_TYPE retval_ = %CPPSELF.%FUNCTION_NAME(%1, %2, %3, %4, &%5, %6); +%END_ALLOW_THREADS %PYARG_0 = PyTuple_New(2); PyTuple_SET_ITEM(%PYARG_0, 0, %CONVERTTOPYTHON[%RETURN_TYPE](retval_)); -PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[%ARG5_TYPE](%5)); +PyTuple_SET_ITEM(%PYARG_0, 1, %CONVERTTOPYTHON[QString](%5)); // @snippet qfiledialog-return +// @snippet qwidget-addaction-glue +static PyObject *connectAction(QAction *action, PyObject *callback) +{ + PyObject *pyAct = %CONVERTTOPYTHON[QAction *](action); + Shiboken::AutoDecRef result(PyObject_CallMethod(pyAct, "connect", "OsO", + pyAct, + SIGNAL(triggered()), callback)); + if (result.isNull()) { + Py_DECREF(pyAct); + return nullptr; + } + return pyAct; +} + +static inline PyObject *addActionWithPyObject(QWidget *self, const QString &text, + PyObject *callback) +{ + QAction *act = self->addAction(text); + return connectAction(act, callback); +} + +static inline PyObject *addActionWithPyObject(QWidget *self, const QIcon &icon, const QString &text, + PyObject *callback) +{ + auto *act = self->addAction(icon, text); + return connectAction(act, callback); +} + +static inline PyObject *addActionWithPyObject(QWidget *self, const QString &text, + const QKeySequence &shortcut, + PyObject *callback) +{ + QAction *act = self->addAction(text, shortcut); + return connectAction(act, callback); +} + +static inline PyObject *addActionWithPyObject(QWidget *self, const QIcon &icon, + const QString &text, + const QKeySequence &shortcut, + PyObject *callback) +{ + QAction *act = self->addAction(icon, text, shortcut); + return connectAction(act, callback); +} +// @snippet qwidget-addaction-glue + +// FIXME PYSIDE7: Remove in favor of widgets methods // @snippet qmenu-glue -inline PyObject *addActionWithPyObject(QMenu *self, const QIcon &icon, const QString &text, PyObject *callback, const QKeySequence &shortcut) +inline PyObject *addMenuActionWithPyObject(QMenu *self, const QIcon &icon, + const QString &text, PyObject *callback, + const QKeySequence &shortcut) { QAction *act = self->addAction(text); @@ -132,18 +153,35 @@ inline PyObject *addActionWithPyObject(QMenu *self, const QIcon &icon, const QSt } // @snippet qmenu-glue +// addAction(QString,PyObject*,QKeySequence) FIXME PYSIDE7 deprecated // @snippet qmenu-addaction-1 -%PYARG_0 = addActionWithPyObject(%CPPSELF, QIcon(), %1, %2, %3); +%PYARG_0 = addMenuActionWithPyObject(%CPPSELF, QIcon(), %1, %2, %3); // @snippet qmenu-addaction-1 +// addAction(QIcon,QString,PyObject*,QKeySequence) FIXME PYSIDE7 deprecated // @snippet qmenu-addaction-2 -%PYARG_0 = addActionWithPyObject(%CPPSELF, %1, %2, %3, %4); +%PYARG_0 = addMenuActionWithPyObject(%CPPSELF, %1, %2, %3, %4); // @snippet qmenu-addaction-2 // @snippet qmenu-addaction-3 %CPPSELF.addAction(%1); // @snippet qmenu-addaction-3 +// addAction(QString,PyObject*) +// @snippet qwidget-addaction-2 +%PYARG_0 = addActionWithPyObject(%CPPSELF, %1, %2); +// @snippet qwidget-addaction-2 + +// addAction(QString,QKeySequence,PyObject*) or addAction(QIcon,QString,PyObject*) +// @snippet qwidget-addaction-3 +%PYARG_0 = addActionWithPyObject(%CPPSELF, %1, %2, %3); +// @snippet qwidget-addaction-3 + +// addAction(QIcon,QString,QKeySequence,PyObject*) +// @snippet qwidget-addaction-4 +%PYARG_0 = addActionWithPyObject(%CPPSELF, %1, %2, %3, %4); +// @snippet qwidget-addaction-4 + // @snippet qmenu-clear Shiboken::BindingManager &bm = Shiboken::BindingManager::instance(); const auto &actions = %CPPSELF.actions(); @@ -158,30 +196,6 @@ for (auto *act : actions) { } // @snippet qmenu-clear -// @snippet qmenubar-glue -inline PyObject * -addActionWithPyObject(QMenuBar *self, const QString &text, PyObject *callback) -{ - QAction *act = self->addAction(text); - - self->addAction(act); - - PyObject *pyAct = %CONVERTTOPYTHON[QAction *](act); - PyObject *result = PyObject_CallMethod(pyAct, "connect", "OsO", - pyAct, - SIGNAL(triggered(bool)), callback); - - if (result == nullptr || result == Py_False) { - if (result) - Py_DECREF(result); - Py_DECREF(pyAct); - return nullptr; - } - - return pyAct; -} -// @snippet qmenubar-glue - // @snippet qmenubar-clear const auto &actions = %CPPSELF.actions(); for (auto *act : actions) { @@ -191,14 +205,6 @@ for (auto *act : actions) { } // @snippet qmenubar-clear -// @snippet qmenubar-addaction-1 -%PYARG_0 = addActionWithPyObject(%CPPSELF, %1, %2); -// @snippet qmenubar-addaction-1 - -// @snippet qmenubar-addaction-2 -%CPPSELF.addAction(%1); -// @snippet qmenubar-addaction-2 - // @snippet qtoolbox-removeitem QWidget *_widget = %CPPSELF.widget(%1); if (_widget) { @@ -208,11 +214,24 @@ if (_widget) { // @snippet qtoolbox-removeitem // @snippet qlayout-help-functions +#ifndef _QLAYOUT_HELP_FUNCTIONS_ +#define _QLAYOUT_HELP_FUNCTIONS_ // Guard for jumbo builds + +static const char msgInvalidParameterAdd[] = + "Invalid parameter None passed to addLayoutOwnership()."; +static const char msgInvalidParameterRemoval[] = + "Invalid parameter None passed to removeLayoutOwnership()."; + void addLayoutOwnership(QLayout *layout, QLayoutItem *item); void removeLayoutOwnership(QLayout *layout, QWidget *widget); inline void addLayoutOwnership(QLayout *layout, QWidget *widget) { + if (layout == nullptr || widget == nullptr) { + PyErr_SetString(PyExc_RuntimeError, msgInvalidParameterAdd); + return; + } + //transfer ownership to parent widget QWidget *lw = layout->parentWidget(); QWidget *pw = widget->parentWidget(); @@ -239,6 +258,11 @@ inline void addLayoutOwnership(QLayout *layout, QWidget *widget) inline void addLayoutOwnership(QLayout *layout, QLayout *other) { + if (layout == nullptr || other == nullptr) { + PyErr_SetString(PyExc_RuntimeError, msgInvalidParameterAdd); + return; + } + //transfer all children widgets from other to layout parent widget QWidget *parent = layout->parentWidget(); if (!parent) { @@ -265,8 +289,11 @@ inline void addLayoutOwnership(QLayout *layout, QLayout *other) inline void addLayoutOwnership(QLayout *layout, QLayoutItem *item) { - if (!item) + + if (layout == nullptr || item == nullptr) { + PyErr_SetString(PyExc_RuntimeError, msgInvalidParameterAdd); return; + } if (QWidget *w = item->widget()) { addLayoutOwnership(layout, w); @@ -282,6 +309,11 @@ inline void addLayoutOwnership(QLayout *layout, QLayoutItem *item) static void removeWidgetFromLayout(QLayout *layout, QWidget *widget) { + if (layout == nullptr || widget == nullptr) { + PyErr_SetString(PyExc_RuntimeError, msgInvalidParameterRemoval); + return; + } + if (QWidget *parent = widget->parentWidget()) { //give the ownership to parent Shiboken::AutoDecRef pyParent(%CONVERTTOPYTHON[QWidget *](parent)); @@ -299,6 +331,11 @@ static void removeWidgetFromLayout(QLayout *layout, QWidget *widget) inline void removeLayoutOwnership(QLayout *layout, QLayoutItem *item) { + if (layout == nullptr || item == nullptr) { + PyErr_SetString(PyExc_RuntimeError, msgInvalidParameterRemoval); + return; + } + if (QWidget *w = item->widget()) { removeWidgetFromLayout(layout, w); } else { @@ -314,8 +351,10 @@ inline void removeLayoutOwnership(QLayout *layout, QLayoutItem *item) inline void removeLayoutOwnership(QLayout *layout, QWidget *widget) { - if (!widget) + if (layout == nullptr || widget == nullptr) { + PyErr_SetString(PyExc_RuntimeError, msgInvalidParameterRemoval); return; + } for (int i = 0, i_max = layout->count(); i < i_max; ++i) { QLayoutItem *item = layout->itemAt(i); @@ -325,15 +364,17 @@ inline void removeLayoutOwnership(QLayout *layout, QWidget *widget) removeLayoutOwnership(layout, item); } } +#endif // _QLAYOUT_HELP_FUNCTIONS_ // @snippet qlayout-help-functions // @snippet qlayout-setalignment %CPPSELF.setAlignment(%1); // @snippet qlayout-setalignment -// @snippet addownership-0 -addLayoutOwnership(%CPPSELF, %0); -// @snippet addownership-0 +// @snippet addownership-item-at +if (%0 != nullptr) + addLayoutOwnership(%CPPSELF, %0); +// @snippet addownership-item-at // @snippet addownership-1 addLayoutOwnership(%CPPSELF, %1); @@ -380,7 +421,7 @@ Shiboken::BindingManager &bm = Shiboken::BindingManager::instance(); for (auto *item : items) { SbkObject *obj = bm.retrieveWrapper(item); if (obj) { - if (reinterpret_cast<PyObject *>(obj)->ob_refcnt > 1) // If the refcnt is 1 the object will vannish anyway. + if (Py_REFCNT(reinterpret_cast<PyObject *>(obj)) > 1) // If the refcnt is 1 the object will vannish anyway. Shiboken::Object::invalidate(obj); Shiboken::Object::removeParent(obj); } @@ -429,11 +470,14 @@ for (int i = 0, count = %CPPSELF.count(); i < count; ++i) { // @snippet qlistwidget-clear // @snippet qwidget-retrieveobjectname +#ifndef _RETRIEVEOBJECTNAME_ +#define _RETRIEVEOBJECTNAME_ // Guard for jumbo builds static QByteArray retrieveObjectName(PyObject *obj) { Shiboken::AutoDecRef objName(PyObject_Str(obj)); return Shiboken::String::toCString(objName); } +#endif // @snippet qwidget-retrieveobjectname // @snippet qwidget-glue @@ -503,15 +547,20 @@ Shiboken::Object::keepReference(reinterpret_cast<SbkObject *>(%PYSELF), "__style // @snippet qwidget-style QStyle *myStyle = %CPPSELF->style(); if (myStyle && qApp) { -%PYARG_0 = %CONVERTTOPYTHON[QStyle *](myStyle); + bool keepReference = true; + %PYARG_0 = %CONVERTTOPYTHON[QStyle *](myStyle); QStyle *appStyle = qApp->style(); if (appStyle == myStyle) { Shiboken::AutoDecRef pyApp(%CONVERTTOPYTHON[QApplication *](qApp)); - Shiboken::Object::setParent(pyApp, %PYARG_0); - Shiboken::Object::releaseOwnership(%PYARG_0); - } else { - Shiboken::Object::keepReference(reinterpret_cast<SbkObject *>(%PYSELF), "__style__", %PYARG_0); + // Do not set parentship when qApp is embedded + if (Shiboken::Object::wasCreatedByPython(reinterpret_cast<SbkObject *>(pyApp.object()))) { + Shiboken::Object::setParent(pyApp, %PYARG_0); + Shiboken::Object::releaseOwnership(%PYARG_0); + keepReference = false; + } } + if (keepReference) + Shiboken::Object::keepReference(reinterpret_cast<SbkObject *>(%PYSELF), "__style__", %PYARG_0); } // @snippet qwidget-style @@ -566,27 +615,25 @@ for (int i = 0, count = %CPPSELF.count(); i < count; ++i) { %CPPSELF.addAction(%1); // @snippet qlineedit-addaction -// @snippet qtoolbar-addaction-1 +// addAction(QIcon,QString,const QObject*,const char*,Qt::ConnectionType) +// @snippet qwidget-addaction-1 QAction *action = %CPPSELF.addAction(%1, %2); %PYARG_0 = %CONVERTTOPYTHON[QAction *](action); Shiboken::AutoDecRef result(PyObject_CallMethod(%PYARG_0, "connect", "OsO", %PYARG_0, SIGNAL(triggered()), %PYARG_3) ); -// @snippet qtoolbar-addaction-1 +// @snippet qwidget-addaction-1 -// @snippet qtoolbar-addaction-2 +// addAction(QString,const QObject*,const char*,Qt::ConnectionType) +// @snippet qwidget-addaction-2 QAction *action = %CPPSELF.addAction(%1); %PYARG_0 = %CONVERTTOPYTHON[QAction *](action); Shiboken::AutoDecRef result(PyObject_CallMethod(%PYARG_0, "connect", "OsO", %PYARG_0, SIGNAL(triggered()), %PYARG_2) ); -// @snippet qtoolbar-addaction-2 - -// @snippet qtoolbar-addaction-3 -%CPPSELF.addAction(%1); -// @snippet qtoolbar-addaction-3 +// @snippet qwidget-addaction-2 // @snippet qtoolbar-clear QList<PyObject *> lst; @@ -609,7 +656,7 @@ for (auto *act : actions) { } %CPPSELF.clear(); -for (auto *obj : qAsConst(lst)) { +for (auto *obj : std::as_const(lst)) { Shiboken::Object::invalidate(reinterpret_cast<SbkObject *>(obj)); Py_XDECREF(obj); } @@ -685,6 +732,83 @@ QAction *cppResult = %CPPSELF.exec(%1, %2, %3, %4); %PYARG_0 = %CONVERTTOPYTHON[QAction*](cppResult); // @snippet qmenu-exec-3 +// @snippet qstyleoption-typename +const char *styleOptionType(const QStyleOption *o) +{ + switch (o->type) { + case QStyleOption::SO_Default: + break; + case QStyleOption::SO_FocusRect: + return "QStyleOptionFocusRect"; + case QStyleOption::SO_Button: + return "QStyleOptionButton"; + case QStyleOption::SO_Tab: + return "QStyleOptionTab"; + case QStyleOption::SO_MenuItem: + return "QStyleOptionMenuItem"; + case QStyleOption::SO_Frame: + return "QStyleOptionFrame"; + case QStyleOption::SO_ProgressBar: + return "QStyleOptionProgressBar"; + case QStyleOption::SO_ToolBox: + return "QStyleOptionToolBox"; + case QStyleOption::SO_Header: + return "QStyleOptionHeader"; + case QStyleOption::SO_DockWidget: + return "QStyleOptionDockWidget"; + case QStyleOption::SO_ViewItem: + return "QStyleOptionViewItem"; + case QStyleOption::SO_TabWidgetFrame: + return "QStyleOptionTabWidgetFrame"; + case QStyleOption::SO_TabBarBase: + return "QStyleOptionTabBarBase"; + case QStyleOption::SO_RubberBand: + return "QStyleOptionRubberBand"; + case QStyleOption::SO_ToolBar: + return "QStyleOptionToolBar"; + case QStyleOption::SO_GraphicsItem: + return "QStyleOptionGraphicsItem"; + case QStyleOption::SO_Slider: + return "QStyleOptionSlider"; + case QStyleOption::SO_SpinBox: + return "QStyleOptionSpinBox"; + case QStyleOption::SO_ToolButton: + return "QStyleOptionToolButton"; + case QStyleOption::SO_ComboBox: + return "QStyleOptionComboBox"; + case QStyleOption::SO_TitleBar: + return "QStyleOptionTitleBar"; + case QStyleOption::SO_GroupBox: + return "QStyleOptionGroupBox"; + case QStyleOption::SO_SizeGrip: + return "QStyleOptionSizeGrip"; + default: + break; + } + return "QStyleOption"; +} +// @snippet qstyleoption-typename + +// @snippet qwizardpage-registerfield +auto *signalInst = reinterpret_cast<PySideSignalInstance *>(%PYARG_4); +const auto data = PySide::Signal::getEmitterData(signalInst); +if (data.methodIndex == -1) + return PyErr_Format(PyExc_RuntimeError, "QWizardPage::registerField(): Unable to retrieve signal emitter."); +const auto method = data.emitter->metaObject()->method(data.methodIndex); +const QByteArray signature = QByteArrayLiteral("2") + method.methodSignature(); +%BEGIN_ALLOW_THREADS +%CPPSELF.%FUNCTION_NAME(%1, %2, %3, signature.constData()); +%END_ALLOW_THREADS +// @snippet qwizardpage-registerfield + +// The constructor heuristics generate setting a parent-child relationship +// when creating a QDialog with parent. This causes the dialog to leak +// when it synchronous exec() is used instead of asynchronous show(). +// In that case, remove the parent-child relationship. +// @snippet qdialog-exec-remove-parent-relation +Shiboken::Object::removeParent(reinterpret_cast<SbkObject *>(%PYSELF)); +// @snippet qdialog-exec-remove-parent-relation + /********************************************************************* * CONVERSIONS ********************************************************************/ diff --git a/sources/pyside6/PySide6/glue/qtxml.cpp b/sources/pyside6/PySide6/glue/qtxml.cpp index 264bf4074..120579927 100644 --- a/sources/pyside6/PySide6/glue/qtxml.cpp +++ b/sources/pyside6/PySide6/glue/qtxml.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt for Python. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2018 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 // @snippet qdomdocument-setcontent QString _errorMsg_; |