diff options
Diffstat (limited to 'sources/pyside2/libpyside')
42 files changed, 0 insertions, 8342 deletions
diff --git a/sources/pyside2/libpyside/CMakeLists.txt b/sources/pyside2/libpyside/CMakeLists.txt deleted file mode 100644 index 579159c6a..000000000 --- a/sources/pyside2/libpyside/CMakeLists.txt +++ /dev/null @@ -1,210 +0,0 @@ -project(libpyside) - -if(${Qt${QT_MAJOR_VERSION}Qml_FOUND}) - if(NOT "${Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS}" MATCHES "/QtQml/") - string(REPLACE "/QtCore" "/QtQml" replaceme "${Qt${QT_MAJOR_VERSION}Core_PRIVATE_INCLUDE_DIRS}") - list(APPEND Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS ${replaceme}) - list(REMOVE_DUPLICATES Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS) - endif() -endif() - -if(${Qt${QT_MAJOR_VERSION}Quick_FOUND}) - if(NOT "${Qt${QT_MAJOR_VERSION}Quick_PRIVATE_INCLUDE_DIRS}" MATCHES "/QtQuick/") - string(REPLACE "/QtCore" "/QtQuick" replaceme "${Qt${QT_MAJOR_VERSION}Core_PRIVATE_INCLUDE_DIRS}") - list(APPEND Qt${QT_MAJOR_VERSION}Quick_PRIVATE_INCLUDE_DIRS ${Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS}) - list(APPEND Qt${QT_MAJOR_VERSION}Quick_PRIVATE_INCLUDE_DIRS ${replaceme}) - list(REMOVE_DUPLICATES Qt${QT_MAJOR_VERSION}Quick_PRIVATE_INCLUDE_DIRS) - endif() -endif() - -set(QML_PRIVATE_API_SUPPORT 0) -if(Qt${QT_MAJOR_VERSION}Qml_FOUND) - # Used for registering custom QQuickItem classes defined in Python code. - set(QML_SUPPORT 1) - set(QML_INCLUDES ${Qt${QT_MAJOR_VERSION}Qml_INCLUDE_DIRS}) - set(QML_LIBRARIES ${Qt${QT_MAJOR_VERSION}Qml_LIBRARIES}) - - if(Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS) - # Used for transforming QML exceptions into Python exceptions. - set(QML_PRIVATE_API_SUPPORT 1) - set(QML_INCLUDES ${QML_INCLUDES} ${Qt${QT_MAJOR_VERSION}Qml_PRIVATE_INCLUDE_DIRS}) - else() - message(WARNING "QML private API include files could not be found, support for catching QML exceptions inside Python code will not work.") - endif() -else() - set(QML_SUPPORT 0) - set(QML_PRIVATE_API_SUPPORT 0) - set(QML_INCLUDES "") - set(QML_LIBRARIES "") -endif() - -set(libpyside_SRC - class_property.cpp - dynamicqmetaobject.cpp - feature_select.cpp - signalmanager.cpp - globalreceiverv2.cpp - pysideclassinfo.cpp - pysideqenum.cpp - pysidemetafunction.cpp - pysidesignal.cpp - pysideslot.cpp - pysideproperty.cpp - pysideqflags.cpp - pysideweakref.cpp - pyside.cpp - pysidestaticstrings.cpp -) - -# Add python files to project explorer in Qt Creator, when opening the CMakeLists.txt as a project, -# so you can look up python files with the Locator. -macro(add_other_files) - foreach(_it ${ARGN}) - if(NOT IS_DIRECTORY ${_it}) - get_filename_component(name ${_it} NAME) - if(NOT ${_it} MATCHES "^/\\\\..*$;~$") - set_source_files_properties(${_it} PROPERTIES HEADER_FILE_ONLY TRUE) - endif() - endif() - endforeach() -endmacro() - -# Test files. -file(GLOB_RECURSE pyside_folder_py_files "../*.py") - -# Mostly for setup.py. -file(GLOB setup_folder_py_files "../../../*.py") - -set(other_files ${pyside_folder_py_files} ${setup_folder_py_files}) -add_other_files(${other_files}) - -add_library(pyside2 SHARED ${libpyside_SRC} ${other_files}) -add_library(PySide2::pyside2 ALIAS pyside2) - -target_include_directories(pyside2 PRIVATE - ${QML_INCLUDES} - ${Qt${QT_MAJOR_VERSION}Core_PRIVATE_INCLUDE_DIRS} - ${Qt${QT_MAJOR_VERSION}Core_INCLUDE_DIRS} -) - -target_include_directories(pyside2 PUBLIC - $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> - $<INSTALL_INTERFACE:include/PySide2> -) - -target_link_libraries(pyside2 - PRIVATE Shiboken6::libshiboken - PRIVATE ${QML_LIBRARIES} - PRIVATE ${Qt${QT_MAJOR_VERSION}Core_LIBRARIES}) - -set_target_properties(pyside2 PROPERTIES - VERSION ${BINDING_API_VERSION} - SOVERSION "${PYSIDE_SO_VERSION}" - OUTPUT_NAME "pyside2${pyside2_SUFFIX}${SHIBOKEN_PYTHON_SHARED_LIBRARY_SUFFIX}" - DEFINE_SYMBOL BUILD_LIBPYSIDE) - -if(${QT_MAJOR_VERSION} GREATER_EQUAL 6) - set_property(TARGET pyside2 PROPERTY CXX_STANDARD 17) -else() - set_property(TARGET pyside2 PROPERTY CXX_STANDARD 11) -endif() - -if(QML_SUPPORT) - target_compile_definitions(pyside2 PUBLIC PYSIDE_QML_SUPPORT=1) -endif() -target_compile_definitions(pyside2 PRIVATE PYSIDE_QML_PRIVATE_API_SUPPORT=${QML_PRIVATE_API_SUPPORT}) - -if(PYSIDE_QT_CONF_PREFIX) - set_property(SOURCE pyside.cpp - APPEND - PROPERTY COMPILE_DEFINITIONS - PYSIDE_QT_CONF_PREFIX=${PYSIDE_QT_CONF_PREFIX}) -endif() - -# -# install stuff -# - -set(libpyside_HEADERS - class_property.h - dynamicqmetaobject.h - feature_select.h - pysideclassinfo.h - pysideqenum.h - pysidemacros.h - signalmanager.h - pyside.h - pysidestaticstrings.h - pysidemetafunction.h - pysidesignal.h - pysideproperty.h - pysideqflags.h - pysideweakref.h -) - -if (CMAKE_BUILD_TYPE STREQUAL "Debug") - set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_DEBUG_POSTFIX}) -else() - set(LIBRARY_OUTPUT_SUFFIX ${CMAKE_RELEASE_POSTFIX}) -endif() - -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D QT_NO_CAST_FROM_ASCII -D QT_NO_CAST_TO_ASCII") - -# create pkg-config file -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/pyside2.pc.in" - "${CMAKE_CURRENT_BINARY_DIR}/pyside2${pyside2_SUFFIX}.pc" @ONLY) - -# for creating cmake-config files -include(CMakePackageConfigHelpers) - -# Build-tree / super project package config file. -set(PYSIDE_PYTHONPATH "${pysidebindings_BINARY_DIR}/PySide2") -set(PYSIDE_TYPESYSTEMS "${pysidebindings_SOURCE_DIR}/PySide2/templates/") -set(PYSIDE_GLUE "${pysidebindings_SOURCE_DIR}/PySide2/glue") - -configure_package_config_file( - "${CMAKE_CURRENT_SOURCE_DIR}/PySide2Config-spec.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/PySide2Config${SHIBOKEN_PYTHON_CONFIG_SUFFIX}.cmake" - INSTALL_DESTINATION "${CMAKE_CURRENT_BINARY_DIR}" - PATH_VARS PYSIDE_PYTHONPATH PYSIDE_TYPESYSTEMS PYSIDE_GLUE - INSTALL_PREFIX "${CMAKE_CURRENT_BINARY_DIR}" -) - -set(PYSIDE_PYTHONPATH "${PYTHON_SITE_PACKAGES}/PySide2") -set(PYSIDE_TYPESYSTEMS "${CMAKE_INSTALL_PREFIX}/share/PySide2${pyside2_SUFFIX}/typesystems") -set(PYSIDE_GLUE "${CMAKE_INSTALL_PREFIX}/share/PySide2${pyside2_SUFFIX}/glue") - -# Install-tree / relocatable package config file. -configure_package_config_file( - "${CMAKE_CURRENT_SOURCE_DIR}/PySide2Config-spec.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/install/PySide2Config${SHIBOKEN_PYTHON_CONFIG_SUFFIX}.cmake" - INSTALL_DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide2-${BINDING_API_VERSION}" - PATH_VARS PYSIDE_PYTHONPATH PYSIDE_TYPESYSTEMS PYSIDE_GLUE -) - -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PySide2Config.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/PySide2Config.cmake" @ONLY) -configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PySide2ConfigVersion.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/PySide2ConfigVersion.cmake" @ONLY) - -install(FILES ${libpyside_HEADERS} - DESTINATION include/${BINDING_NAME}${pyside2_SUFFIX}) - -install(TARGETS pyside2 EXPORT PySide2Targets - LIBRARY DESTINATION "${LIB_INSTALL_DIR}" - ARCHIVE DESTINATION "${LIB_INSTALL_DIR}" - RUNTIME DESTINATION bin) -install(EXPORT PySide2Targets NAMESPACE PySide2:: - DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide2-${BINDING_API_VERSION}") - -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/pyside2${pyside2_SUFFIX}.pc" - DESTINATION "${LIB_INSTALL_DIR}/pkgconfig") - -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/PySide2Config.cmake" - DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide2-${BINDING_API_VERSION}") - -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/install/PySide2Config${SHIBOKEN_PYTHON_CONFIG_SUFFIX}.cmake" - DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide2-${BINDING_API_VERSION}") - -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/PySide2ConfigVersion.cmake" - DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide2-${BINDING_API_VERSION}") diff --git a/sources/pyside2/libpyside/PySide2Config-spec.cmake.in b/sources/pyside2/libpyside/PySide2Config-spec.cmake.in deleted file mode 100644 index 9f0ae236a..000000000 --- a/sources/pyside2/libpyside/PySide2Config-spec.cmake.in +++ /dev/null @@ -1,16 +0,0 @@ -# PYSIDE_PYTHONPATH - Path to where the PySide2 Python module files could be found -# PYSIDE_TYPESYSTEMS - Type system files that should be used by other bindings extending PySide2 -# PYSIDE_GLUE - Path to module glue files. - -@PACKAGE_INIT@ - -# Import targets only when using an installed PySide2 config file (so not during a regular -# PySide2 build, or during a super project build). -if (NOT TARGET PySide2::pyside2) - include("${CMAKE_CURRENT_LIST_DIR}/PySide2Targets.cmake") -endif() - -# Set relocatable variables. -set_and_check(PYSIDE_PYTHONPATH "@PACKAGE_PYSIDE_PYTHONPATH@") -set_and_check(PYSIDE_TYPESYSTEMS "@PACKAGE_PYSIDE_TYPESYSTEMS@") -set_and_check(PYSIDE_GLUE "@PACKAGE_PYSIDE_GLUE@") diff --git a/sources/pyside2/libpyside/PySide2Config.cmake.in b/sources/pyside2/libpyside/PySide2Config.cmake.in deleted file mode 100644 index c5c1f44b4..000000000 --- a/sources/pyside2/libpyside/PySide2Config.cmake.in +++ /dev/null @@ -1,5 +0,0 @@ -if (NOT PYTHON_CONFIG_SUFFIX) - message(STATUS "PySide2Config: Using default python: @SHIBOKEN_PYTHON_CONFIG_SUFFIX@") - SET(PYTHON_CONFIG_SUFFIX @SHIBOKEN_PYTHON_CONFIG_SUFFIX@) -endif() -include(${CMAKE_CURRENT_LIST_DIR}/PySide2Config${PYTHON_CONFIG_SUFFIX}.cmake) diff --git a/sources/pyside2/libpyside/PySide2ConfigVersion.cmake.in b/sources/pyside2/libpyside/PySide2ConfigVersion.cmake.in deleted file mode 100644 index f5073ce08..000000000 --- a/sources/pyside2/libpyside/PySide2ConfigVersion.cmake.in +++ /dev/null @@ -1,10 +0,0 @@ -set(PACKAGE_VERSION @BINDING_API_VERSION@) - -if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) - set(PACKAGE_VERSION_COMPATIBLE FALSE) -else("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) - set(PACKAGE_VERSION_COMPATIBLE TRUE) - if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") - set(PACKAGE_VERSION_EXACT TRUE) - endif( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") -endif("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) diff --git a/sources/pyside2/libpyside/class_property.cpp b/sources/pyside2/libpyside/class_property.cpp deleted file mode 100644 index 90ce0d2f3..000000000 --- a/sources/pyside2/libpyside/class_property.cpp +++ /dev/null @@ -1,158 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "pyside.h" -#include "pysidestaticstrings.h" -#include "feature_select.h" -#include "class_property.h" - -#include <shiboken.h> -#include <sbkstaticstrings.h> - -extern "C" { - -/* - * A `classproperty` is the same as a `property` but the `__get__()` and `__set__()` - * methods are modified to always use the object class instead of a concrete instance. - * - * Note: A "static property" as it is often called does not exist per se. - * Static methods do not receive anything when created. Static methods which - * should participate in a property must be turned into class methods, before. - * See function `createProperty` in `feature_select.cpp`. - */ - -// `class_property.__get__()`: Always pass the class instead of the instance. -static PyObject *PyClassProperty_get(PyObject *self, PyObject * /*ob*/, PyObject *cls) -{ - return PyProperty_Type.tp_descr_get(self, cls, cls); -} - -// `class_property.__set__()`: Just like the above `__get__()`. -static int PyClassProperty_set(PyObject *self, PyObject *obj, PyObject *value) -{ - PyObject *cls = PyType_Check(obj) ? obj : reinterpret_cast<PyObject *>(Py_TYPE(obj)); - return PyProperty_Type.tp_descr_set(self, cls, value); -} - -// The property `__doc__` default does not work for class properties -// because PyProperty_Type.tp_init thinks this is a subclass which needs PyObject_SetAttr. -// We call `__init__` while pretending to be a PyProperty_Type instance. -static int PyClassProperty_init(PyObject *self, PyObject *args, PyObject *kwargs) -{ - auto hold = Py_TYPE(self); - Py_TYPE(self) = &PyProperty_Type; - auto ret = PyProperty_Type.tp_init(self, args, kwargs); - Py_TYPE(self) = hold; - return ret; -} - -static PyType_Slot PyClassProperty_slots[] = { - {Py_tp_getset, nullptr}, // will be set below - {Py_tp_base, reinterpret_cast<void *>(&PyProperty_Type)}, - {Py_tp_descr_get, reinterpret_cast<void *>(PyClassProperty_get)}, - {Py_tp_descr_set, reinterpret_cast<void *>(PyClassProperty_set)}, - {Py_tp_init, reinterpret_cast<void *>(PyClassProperty_init)}, - {0, 0} -}; - -static PyType_Spec PyClassProperty_spec = { - "PySide2.PyClassProperty", - sizeof(propertyobject), - 0, - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, - PyClassProperty_slots, -}; - -PyTypeObject *PyClassPropertyTypeF() -{ - static PyTypeObject *type = nullptr; - if (type == nullptr) { - // Provide the same `tp_getset`, which is not inherited. - PyClassProperty_slots[0].pfunc = PyProperty_Type.tp_getset; - type = reinterpret_cast<PyTypeObject *>( - PyType_FromSpec(&PyClassProperty_spec)); - } - return type; -} - -/* - * Types with class properties need to handle `Type.class_prop = x` in a specific way. - * By default, Python replaces the `class_property` itself, but for wrapped C++ types - * we need to call `class_property.__set__()` in order to propagate the new value to - * the underlying C++ data structure. - */ -static int SbkObjectType_meta_setattro(PyObject *obj, PyObject *name, PyObject *value) -{ - // Use `_PepType_Lookup()` instead of `PyObject_GetAttr()` in order to get the raw - // descriptor (`property`) instead of calling `tp_descr_get` (`property.__get__()`). - auto type = reinterpret_cast<PyTypeObject *>(obj); - PyObject *descr = _PepType_Lookup(type, name); - - // The following assignment combinations are possible: - // 1. `Type.class_prop = value` --> descr_set: `Type.class_prop.__set__(value)` - // 2. `Type.class_prop = other_class_prop` --> setattro: replace existing `class_prop` - // 3. `Type.regular_attribute = value` --> setattro: regular attribute assignment - const auto class_prop = reinterpret_cast<PyObject *>(PyClassPropertyTypeF()); - const auto call_descr_set = descr && PyObject_IsInstance(descr, class_prop) - && !PyObject_IsInstance(value, class_prop); - if (call_descr_set) { - // Call `class_property.__set__()` instead of replacing the `class_property`. - return Py_TYPE(descr)->tp_descr_set(descr, obj, value); - } else { - // Replace existing attribute. - return PyType_Type.tp_setattro(obj, name, value); - } -} - -} // extern "C" - -/* - * These functions are added to the SbkObjectType_TypeF() dynamically. - */ -namespace PySide { namespace ClassProperty { - -void init() -{ - PyTypeObject *type = SbkObjectType_TypeF(); - type->tp_setattro = SbkObjectType_meta_setattro; - Py_TYPE(PyClassPropertyTypeF()) = type; -} - -} // namespace ClassProperty -} // namespace PySide diff --git a/sources/pyside2/libpyside/class_property.h b/sources/pyside2/libpyside/class_property.h deleted file mode 100644 index f94fdde31..000000000 --- a/sources/pyside2/libpyside/class_property.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef CLASS_PROPERTY_H -#define CLASS_PROPERTY_H - -#include "pysidemacros.h" -#include <sbkpython.h> - -extern "C" { - -typedef struct { - PyObject_HEAD - PyObject *prop_get; - PyObject *prop_set; - PyObject *prop_del; - PyObject *prop_doc; - int getter_doc; -} propertyobject; - -PYSIDE_API PyTypeObject *PyClassPropertyTypeF(); - -} // extern "C" - -namespace PySide { -namespace ClassProperty { - -PYSIDE_API void init(); - -} // namespace ClassProperty -} // namespace PySide - -#endif // CLASS_PROPERTY_H diff --git a/sources/pyside2/libpyside/dynamicqmetaobject.cpp b/sources/pyside2/libpyside/dynamicqmetaobject.cpp deleted file mode 100644 index f67e97e01..000000000 --- a/sources/pyside2/libpyside/dynamicqmetaobject.cpp +++ /dev/null @@ -1,588 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 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$ -** -****************************************************************************/ - -#include "dynamicqmetaobject.h" -#include "dynamicqmetaobject_p.h" -#include "pysidesignal.h" -#include "pysidesignal_p.h" -#include "pysideproperty.h" -#include "pysideproperty_p.h" -#include "pysideslot_p.h" -#include "pysideqenum.h" - -#include <shiboken.h> - -#include <QtCore/QByteArray> -#include <QtCore/QObject> -#include <QtCore/QStringList> -#include <QtCore/QTextStream> -#include <QtCore/QVector> -#include <private/qmetaobjectbuilder_p.h> - -#include <cstring> -#include <vector> - -using namespace PySide; - -// MetaObjectBuilder: Provides the QMetaObject's returned by -// QObject::metaObject() for PySide2 objects. There are several -// scenarios to consider: -// 1) A plain Qt class (say QTimer) is instantiated. In that case, -// return the base meta object until a modification is made by -// adding methods, properties or class info (cf qmetaobject_test.py). -// In that case, instantiate a QMetaObjectBuilder inheriting the -// base meta meta object, add the method and return the result -// of QMetaObjectBuilder::toMetaObject() (with dirty handling should -// further modifications be made). -// 2) A Python class inheriting a Qt class is instantiated. For this, -// instantiate a QMetaObjectBuilder and add the methods/properties -// found by inspecting the Python class. - -class MetaObjectBuilderPrivate -{ -public: - using MetaObjects = std::vector<const QMetaObject *>; - - QMetaObjectBuilder *ensureBuilder(); - void parsePythonType(PyTypeObject *type); - int indexOfMethod(QMetaMethod::MethodType mtype, - const QByteArray &signature) const; - int indexOfProperty(const QByteArray &name) const; - int addSlot(const QByteArray &signature); - int addSlot(const QByteArray &signature, const QByteArray &type); - int addSignal(const QByteArray &signature); - void removeMethod(QMetaMethod::MethodType mtype, int index); - int getPropertyNotifyId(PySideProperty *property) const; - int addProperty(const QByteArray &property, PyObject *data); - void addInfo(const QByteArray &key, const QByteArray &value); - void addInfo(const QMap<QByteArray, QByteArray> &info); - void addEnumerator(const char *name, - bool flag, - bool scoped, - const QVector<QPair<QByteArray, int> > &entries); - void removeProperty(int index); - const QMetaObject *update(); - - QMetaObjectBuilder *m_builder = nullptr; - - const QMetaObject *m_baseObject = nullptr; - MetaObjects m_cachedMetaObjects; - bool m_dirty = true; -}; - -QMetaObjectBuilder *MetaObjectBuilderPrivate::ensureBuilder() -{ - if (!m_builder) { - m_builder = new QMetaObjectBuilder(); - m_builder->setClassName(m_baseObject->className()); - m_builder->setSuperClass(m_baseObject); - } - return m_builder; -} - -MetaObjectBuilder::MetaObjectBuilder(const char *className, const QMetaObject *metaObject) : - m_d(new MetaObjectBuilderPrivate) -{ - m_d->m_baseObject = metaObject; - m_d->m_builder = new QMetaObjectBuilder(); - m_d->m_builder->setClassName(className); - m_d->m_builder->setSuperClass(metaObject); - m_d->m_builder->setClassName(className); -} - -MetaObjectBuilder::MetaObjectBuilder(PyTypeObject *type, const QMetaObject *metaObject) - : m_d(new MetaObjectBuilderPrivate) -{ - m_d->m_baseObject = metaObject; - const char *className = type->tp_name; - if (const char *lastDot = strrchr(type->tp_name, '.')) - className = lastDot + 1; - // Different names indicate a Python class inheriting a Qt class. - // Parse the type. - if (strcmp(className, metaObject->className()) != 0) { - m_d->m_builder = new QMetaObjectBuilder(); - m_d->m_builder->setClassName(className); - m_d->m_builder->setSuperClass(metaObject); - m_d->parsePythonType(type); - } -} - -MetaObjectBuilder::~MetaObjectBuilder() -{ - for (auto *metaObject : m_d->m_cachedMetaObjects) - free(const_cast<QMetaObject*>(metaObject)); - delete m_d->m_builder; - delete m_d; -} - -int MetaObjectBuilderPrivate::indexOfMethod(QMetaMethod::MethodType mtype, - const QByteArray &signature) const -{ - int result = -1; - if (m_builder) { - switch (mtype) { - case QMetaMethod::Signal: - result = m_builder->indexOfSignal(signature); - break; - case QMetaMethod::Slot: - result = m_builder->indexOfSlot(signature); - break; - case QMetaMethod::Constructor: - result = m_builder->indexOfConstructor(signature); - break; - case QMetaMethod::Method: - result = m_builder->indexOfMethod(signature); - break; - } - if (result >= 0) - return result + m_baseObject->methodCount(); - } - switch (mtype) { - case QMetaMethod::Signal: - result = m_baseObject->indexOfSignal(signature); - break; - case QMetaMethod::Slot: - result = m_baseObject->indexOfSlot(signature); - break; - case QMetaMethod::Constructor: - result = m_baseObject->indexOfConstructor(signature); - break; - case QMetaMethod::Method: - result = m_baseObject->indexOfMethod(signature); - break; - } - return result; -} - -int MetaObjectBuilder::indexOfMethod(QMetaMethod::MethodType mtype, - const QByteArray &signature) const -{ - return m_d->indexOfMethod(mtype, signature); -} - -int MetaObjectBuilderPrivate::indexOfProperty(const QByteArray &name) const -{ - if (m_builder) { - const int result = m_builder->indexOfProperty(name); - if (result >= 0) - return m_baseObject->propertyCount() + result; - } - return m_baseObject->indexOfProperty(name); -} - -int MetaObjectBuilder::indexOfProperty(const QByteArray &name) const -{ - return m_d->indexOfProperty(name); -} - -static bool checkMethodSignature(const QByteArray &signature) -{ - // Common mistake not to add parentheses to the signature. - const int openParen = signature.indexOf('('); - const int closingParen = signature.lastIndexOf(')'); - const bool ok = openParen != -1 && closingParen != -1 && openParen < closingParen; - if (!ok) { - const QByteArray message = - "MetaObjectBuilder::addMethod: Invalid method signature provided for \"" - + signature + '"'; - PyErr_WarnEx(PyExc_RuntimeWarning, message.constData(), 0); - } - return ok; -} - -int MetaObjectBuilderPrivate::addSlot(const QByteArray &signature) -{ - if (!checkMethodSignature(signature)) - return -1; - m_dirty = true; - return m_baseObject->methodCount() - + ensureBuilder()->addSlot(signature).index(); -} - -int MetaObjectBuilder::addSlot(const char *signature) -{ - return m_d->addSlot(signature); -} - -int MetaObjectBuilderPrivate::addSlot(const QByteArray &signature, - const QByteArray &type) -{ - if (!checkMethodSignature(signature)) - return -1; - m_dirty = true; - QMetaMethodBuilder methodBuilder = ensureBuilder()->addSlot(signature); - methodBuilder.setReturnType(type); - return m_baseObject->methodCount() + methodBuilder.index(); -} - -int MetaObjectBuilder::addSlot(const char *signature, const char *type) -{ - return m_d->addSlot(signature, type); -} - -int MetaObjectBuilderPrivate::addSignal(const QByteArray &signature) -{ - if (!checkMethodSignature(signature)) - return -1; - m_dirty = true; - return m_baseObject->methodCount() - + ensureBuilder()->addSignal(signature).index(); -} - -int MetaObjectBuilder::addSignal(const char *signature) -{ - return m_d->addSignal(signature); -} - -void MetaObjectBuilderPrivate::removeMethod(QMetaMethod::MethodType mtype, - int index) -{ - index -= m_baseObject->methodCount(); - auto builder = ensureBuilder(); - Q_ASSERT(index >= 0 && index < builder->methodCount()); - switch (mtype) { - case QMetaMethod::Constructor: - builder->removeConstructor(index); - break; - default: - builder->removeMethod(index); - break; - } - m_dirty = true; -} - -void MetaObjectBuilder::removeMethod(QMetaMethod::MethodType mtype, int index) -{ - m_d->removeMethod(mtype, index); -} - -int MetaObjectBuilderPrivate::getPropertyNotifyId(PySideProperty *property) const -{ - int notifyId = -1; - if (property->d->notify) { - if (const char *signalNotify = PySide::Property::getNotifyName(property)) - notifyId = indexOfMethod(QMetaMethod::Signal, signalNotify); - } - return notifyId; -} - -int MetaObjectBuilderPrivate::addProperty(const QByteArray &propertyName, - PyObject *data) -{ - int index = indexOfProperty(propertyName); - if (index != -1) - return index; - - PySideProperty *property = reinterpret_cast<PySideProperty *>(data); - int propertyNotifyId = getPropertyNotifyId(property); - if (propertyNotifyId >= 0) - propertyNotifyId -= m_baseObject->methodCount(); - auto newProperty = - ensureBuilder()->addProperty(propertyName, property->d->typeName, - propertyNotifyId); - // Adding property attributes - newProperty.setReadable(PySide::Property::isReadable(property)); - newProperty.setWritable(PySide::Property::isWritable(property)); - newProperty.setResettable(PySide::Property::hasReset(property)); - newProperty.setDesignable(PySide::Property::isDesignable(property)); - newProperty.setScriptable(PySide::Property::isScriptable(property)); - newProperty.setStored(PySide::Property::isStored(property)); - newProperty.setUser(PySide::Property::isUser(property)); - newProperty.setConstant(PySide::Property::isConstant(property)); - newProperty.setFinal(PySide::Property::isFinal(property)); - - index = newProperty.index() + m_baseObject->propertyCount(); - m_dirty = true; - return index; -} - -int MetaObjectBuilder::addProperty(const char *property, PyObject *data) -{ - return m_d->addProperty(property, data); -} - -void MetaObjectBuilderPrivate::addInfo(const QByteArray &key, - const QByteArray &value) -{ - ensureBuilder()->addClassInfo(key, value); - m_dirty = true; -} - -void MetaObjectBuilder::addInfo(const char *key, const char *value) -{ - m_d->addInfo(key, value); -} - -void MetaObjectBuilderPrivate::addInfo(const QMap<QByteArray, QByteArray> &info) -{ - auto builder = ensureBuilder(); - for (auto i = info.constBegin(), end = info.constEnd(); i != end; ++i) - builder->addClassInfo(i.key(), i.value()); - m_dirty = true; -} - -void MetaObjectBuilder::addInfo(const QMap<QByteArray, QByteArray> &info) -{ - m_d->addInfo(info); -} - -void MetaObjectBuilder::addEnumerator(const char *name, bool flag, bool scoped, - const QVector<QPair<QByteArray, int> > &entries) -{ - m_d->addEnumerator(name, flag, scoped, entries); -} - -void MetaObjectBuilderPrivate::addEnumerator(const char *name, bool flag, bool scoped, - const QVector<QPair<QByteArray, int> > &entries) -{ - auto builder = ensureBuilder(); - int have_already = builder->indexOfEnumerator(name); - if (have_already >= 0) - builder->removeEnumerator(have_already); - auto enumbuilder = builder->addEnumerator(name); - enumbuilder.setIsFlag(flag); - enumbuilder.setIsScoped(scoped); - - for (auto item : entries) - enumbuilder.addKey(item.first, item.second); - m_dirty = true; -} - -void MetaObjectBuilderPrivate::removeProperty(int index) -{ - index -= m_baseObject->propertyCount(); - auto builder = ensureBuilder(); - Q_ASSERT(index >= 0 && index < builder->propertyCount()); - builder->removeProperty(index); - m_dirty = true; -} - -void MetaObjectBuilder::removeProperty(int index) -{ - m_d->removeProperty(index); -} - -// PYSIDE-315: Instead of sorting the items and maybe breaking indices, we -// ensure that the signals and slots are sorted by the improved -// parsePythonType() (signals must go before slots). The order can only -// become distorted if the class is modified after creation. In that -// case, we give a warning. - -static QString msgMethodSortOrder(const QMetaObject *mo, int offendingIndex) -{ - QString result; - QTextStream str(&result); - str << "\n\n*** Sort Warning ***\nSignals and slots in QMetaObject '" - << mo->className() - << "' are not ordered correctly, this may lead to issues.\n"; - const int methodOffset = mo->methodOffset(); - for (int m = methodOffset, methodCount = mo->methodCount(); m < methodCount; ++m) { - const auto method = mo->method(m); - str << (m - methodOffset + 1) << (m > offendingIndex ? '!' : ' ') - << (method.methodType() == QMetaMethod::Signal ? " Signal " : " Slot ") - << method.methodSignature() << '\n'; - } - return result; -} - -static void checkMethodOrder(const QMetaObject *metaObject) -{ - const int lastMethod = metaObject->methodCount() - 1; - for (int m = metaObject->methodOffset(); m < lastMethod; ++m) { - if (metaObject->method(m).methodType() == QMetaMethod::Slot - && metaObject->method(m + 1).methodType() == QMetaMethod::Signal) { - const auto message = msgMethodSortOrder(metaObject, m); - PyErr_WarnEx(PyExc_RuntimeWarning, qPrintable(message), 0); - // Prevent a warning from being turned into an error. We cannot easily unwind. - PyErr_Clear(); - break; - } - } -} - -const QMetaObject *MetaObjectBuilderPrivate::update() -{ - if (!m_builder) - return m_baseObject; - if (m_cachedMetaObjects.empty() || m_dirty) { - // PYSIDE-803: The dirty branch needs to be protected by the GIL. - // This was moved from SignalManager::retrieveMetaObject to here, - // which is only the update in "return builder->update()". - Shiboken::GilState gil; - m_cachedMetaObjects.push_back(m_builder->toMetaObject()); - checkMethodOrder(m_cachedMetaObjects.back()); - m_dirty = false; - } - return m_cachedMetaObjects.back(); -} - -const QMetaObject *MetaObjectBuilder::update() -{ - return m_d->update(); -} - -using namespace Shiboken; - -void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type) -{ - // Get all non-QObject-derived base types in method resolution order, filtering out the types - // that can't have signals, slots or properties. - // This enforces registering of all signals and slots at type parsing time, and not later at - // signal connection time, thus making sure no method indices change which would break - // existing connections. - const PyObject *mro = type->tp_mro; - const Py_ssize_t basesCount = PyTuple_GET_SIZE(mro); - PyTypeObject *qObjectType = Conversions::getPythonTypeObject("QObject*"); - - std::vector<PyTypeObject *> basesToCheck; - // Prepend the actual type that we are parsing. - basesToCheck.reserve(1u + basesCount); - basesToCheck.push_back(type); - - auto sbkObjTypeF = reinterpret_cast<PyTypeObject *>(SbkObject_TypeF()); - auto baseObjType = reinterpret_cast<PyTypeObject *>(&PyBaseObject_Type); - for (Py_ssize_t i = 0; i < basesCount; ++i) { - auto baseType = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, i)); - if (baseType != sbkObjTypeF && baseType != baseObjType - && PyType_IsSubtype(baseType, qObjectType) == 0) { - basesToCheck.push_back(baseType); - } - } - - // PYSIDE-315: Handle all signals first, in all involved types. - // Leave the properties to be registered after signals because they may depend on - // notify signals. - for (PyTypeObject *baseType : basesToCheck) { - PyObject *attrs = baseType->tp_dict; - PyObject *key = nullptr; - PyObject *value = nullptr; - Py_ssize_t pos = 0; - - while (PyDict_Next(attrs, &pos, &key, &value)) { - if (Signal::checkType(value)) { - // Register signals. - auto data = reinterpret_cast<PySideSignal *>(value); - if (data->data->signalName.isEmpty()) - data->data->signalName = String::toCString(key); - for (const auto &s : data->data->signatures) { - const auto sig = data->data->signalName + '(' + s.signature + ')'; - if (m_baseObject->indexOfSignal(sig) == -1) { - // Registering the parameterNames to the QMetaObject (PYSIDE-634) - // from: - // Signal(..., arguments=['...', ...] - // the arguments are now on data-data->signalArguments - if (!data->data->signalArguments->isEmpty()) { - m_builder->addSignal(sig).setParameterNames(*data->data->signalArguments); - } else { - m_builder->addSignal(sig); - } - } - } - } - } - } - - AutoDecRef slotAttrName(String::fromCString(PYSIDE_SLOT_LIST_ATTR)); - // PYSIDE-315: Now take care of the rest. - // Signals and slots should be separated, unless the types are modified, later. - // We check for this using "is_sorted()". Sorting no longer happens at all. - for (PyTypeObject *baseType : basesToCheck) { - PyObject *attrs = baseType->tp_dict; - PyObject *key = nullptr; - PyObject *value = nullptr; - Py_ssize_t pos = 0; - - while (PyDict_Next(attrs, &pos, &key, &value)) { - if (Property::checkType(value)) { - const int index = m_baseObject->indexOfProperty(String::toCString(key)); - if (index == -1) - addProperty(String::toCString(key), value); - } else if (Py_TYPE(value)->tp_call != nullptr) { - // PYSIDE-198: PyFunction_Check does not work with Nuitka. - // Register slots. - if (PyObject_HasAttr(value, slotAttrName)) { - PyObject *signatureList = PyObject_GetAttr(value, slotAttrName); - for (Py_ssize_t i = 0, i_max = PyList_Size(signatureList); i < i_max; ++i) { - PyObject *pySignature = PyList_GET_ITEM(signatureList, i); - QByteArray signature(String::toCString(pySignature)); - // Split the slot type and its signature. - QByteArray type; - const int spacePos = signature.indexOf(' '); - if (spacePos != -1) { - type = signature.left(spacePos); - signature.remove(0, spacePos + 1); - } - const int index = m_baseObject->indexOfSlot(signature); - if (index == -1) { - if (type.isEmpty() || type == "void") - addSlot(signature); - else - addSlot(signature, type); - } - } - } - } - } - } - // PYSIDE-957: Collect the delayed QEnums - auto collectedEnums = PySide::QEnum::resolveDelayedQEnums(type); - for (PyObject *obEnumType : collectedEnums) { - bool isFlag = PySide::QEnum::isFlag(obEnumType); - AutoDecRef obName(PyObject_GetAttr(obEnumType, PyMagicName::name())); - // Everything has been checked already in resolveDelayedQEnums. - // Therefore, we don't need to error-check here again. - auto name = String::toCString(obName); - AutoDecRef members(PyObject_GetAttr(obEnumType, PyMagicName::members())); - AutoDecRef items(PyMapping_Items(members)); - Py_ssize_t nr_items = PySequence_Length(items); - - QVector<QPair<QByteArray, int> > entries; - for (Py_ssize_t idx = 0; idx < nr_items; ++idx) { - AutoDecRef item(PySequence_GetItem(items, idx)); - AutoDecRef key(PySequence_GetItem(item, 0)); - AutoDecRef member(PySequence_GetItem(item, 1)); - AutoDecRef value(PyObject_GetAttr(member, Shiboken::PyName::value())); - auto ckey = String::toCString(key); - auto ivalue = PyInt_AsSsize_t(value); // int/long cheating - auto thing = QPair<QByteArray, int>(ckey, int(ivalue)); - entries.push_back(thing); - } - addEnumerator(name, isFlag, true, entries); - } -} diff --git a/sources/pyside2/libpyside/dynamicqmetaobject.h b/sources/pyside2/libpyside/dynamicqmetaobject.h deleted file mode 100644 index 7279d5c26..000000000 --- a/sources/pyside2/libpyside/dynamicqmetaobject.h +++ /dev/null @@ -1,84 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef DYNAMICQMETAOBJECT_H -#define DYNAMICQMETAOBJECT_H - -#include <sbkpython.h> - -#include <QtCore/QMetaObject> -#include <QtCore/QMetaMethod> - -class MetaObjectBuilderPrivate; - -namespace PySide -{ - -class MetaObjectBuilder -{ - Q_DISABLE_COPY(MetaObjectBuilder) -public: - MetaObjectBuilder(const char *className, const QMetaObject *metaObject); - - MetaObjectBuilder(PyTypeObject *type, const QMetaObject *metaObject); - ~MetaObjectBuilder(); - - int indexOfMethod(QMetaMethod::MethodType mtype, const QByteArray &signature) const; - int indexOfProperty(const QByteArray &name) const; - int addSlot(const char *signature); - int addSlot(const char *signature, const char *type); - int addSignal(const char *signature); - void removeMethod(QMetaMethod::MethodType mtype, int index); - int addProperty(const char *property, PyObject *data); - void addInfo(const char *key, const char *value); - void addInfo(const QMap<QByteArray, QByteArray> &info); - void addEnumerator(const char *name, - bool flag, - bool scoped, - const QVector<QPair<QByteArray, int> > &entries); - void removeProperty(int index); - - const QMetaObject *update(); - -private: - MetaObjectBuilderPrivate *m_d; -}; - -} -#endif diff --git a/sources/pyside2/libpyside/dynamicqmetaobject_p.h b/sources/pyside2/libpyside/dynamicqmetaobject_p.h deleted file mode 100644 index 9199630b7..000000000 --- a/sources/pyside2/libpyside/dynamicqmetaobject_p.h +++ /dev/null @@ -1,107 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef DYNAMICMETAPROPERTY_P_H -#define DYNAMICMETAPROPERTY_P_H - -#include <sbkpython.h> - -#include <QtCore/QByteArray> -#include <QtCore/QMetaMethod> - -struct PySideProperty; -namespace PySide -{ - class MethodData - { - public: - MethodData(); - /** - * \param signature method signature - * \param type method return type - */ - MethodData(QMetaMethod::MethodType mtype, - const QByteArray &signature, - const QByteArray &rtype = QByteArray("void")); - void clear(); - bool isValid() const; - const QByteArray &signature() const { return m_signature; } - const QByteArray &returnType() const { return m_rtype; } - QMetaMethod::MethodType methodType() const { return m_mtype; } - //Qt5 moc: now we have to store method parameter names, count, type - QList<QByteArray> parameterTypes() const; - int parameterCount() const; - QByteArray name() const; - bool operator==(const MethodData &other) const; - - private: - QByteArray m_signature; - QByteArray m_rtype; - QMetaMethod::MethodType m_mtype; - static const QByteArray m_emptySig; - }; - - class PropertyData - { - public: - PropertyData(); - PropertyData(const char *name, int cachedNotifyId = 0, PySideProperty *data = 0); - const QByteArray &name() const { return m_name; } - PySideProperty *data() const { return m_data; } - QByteArray type() const; - uint flags() const; - bool isValid() const; - int cachedNotifyId() const; - bool operator==(const PropertyData &other) const; - bool operator==(const char *name) const; - - private: - QByteArray m_name; - int m_cachedNotifyId; - PySideProperty *m_data; - }; - -inline bool MethodData::operator==(const MethodData &other) const -{ - return m_mtype == other.methodType() && m_signature == other.signature(); -} - -} - -#endif diff --git a/sources/pyside2/libpyside/feature_select.cpp b/sources/pyside2/libpyside/feature_select.cpp deleted file mode 100644 index 660547d99..000000000 --- a/sources/pyside2/libpyside/feature_select.cpp +++ /dev/null @@ -1,766 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "feature_select.h" -#include "pyside.h" -#include "pysidestaticstrings.h" -#include "class_property.h" - -#include <shiboken.h> -#include <sbkstaticstrings.h> - -////////////////////////////////////////////////////////////////////////////// -// -// PYSIDE-1019: Support switchable extensions -// -// This functionality is no longer implemented in the signature module, since -// the PyCFunction getsets do not have to be modified any longer. -// Instead, we simply exchange the complete class dicts. This is done in the -// basewrapper.cpp file and in every generated `tp_(get|set)attro`. -// -// This is the general framework of the switchable extensions. -// A maximum of eight features is planned so far. This seems to be enough. -// More features are possible, but then we must somehow register the -// extra `select_id`s above 255. -// - -/***************************************************************************** - - How Does This Feature Selection Work? - ------------------------------------- - -The basic idea is to replace the `tp_dict` of a QObject derived type. -This way, we can replace the methods of the class in no time. - -The crucial point to understand is how the `tp_dict` is actually accessed: -When you type "QObject.__dict__", the descriptor of `SbkObjectType_Type` -is called. This descriptor is per default unassigned, so the base class -PyType_Type provides the tp_getset method `type_dict`: - - static PyObject * - type_dict(PyTypeObject *type, void *context) - { - if (type->tp_dict == NULL) { - Py_RETURN_NONE; - } - return PyDictProxy_New(type->tp_dict); - } - -In order to change that, we need to insert our own version into SbkObjectType: - - static PyObject *Sbk_TypeGet___dict__(PyTypeObject *type, void *context) - { - auto dict = type->tp_dict; - if (dict == NULL) - Py_RETURN_NONE; - if (SelectFeatureSet != nullptr) - dict = SelectFeatureSet(type); - return PyDictProxy_New(dict); - } - -This way, the Python function `type_ready()` does not fill in the default, -but uses our modified version. It a similar way, we overwrite type_getattro -with our own version, again in SbkObjectType, replacing the default of -PyType_Type. - -Now we can exchange the dict with a customized version. -We have our own derived type `ChameleonDict` with additional attributes. -These allow us to create a ring of dicts which can be rotated to the actual -needed dict version: - -Every dict has a field `select_id` which is selected by the `from __feature__` -import. The dicts are cyclic connected by the `dict_ring` field. - -When a class dict is required, now always `SelectFeatureSet` is called, which -looks into the `__name__` attribute of the active module and decides which -version of `tp_dict` is needed. Then the right dict is searched in the ring -and created if not already there. - -Furthermore, we need to overwrite every `tp_(get|set)attro` with a version -that switches dicts right before looking up methods. -The dict changing must walk the whole `tp_mro` in order to change all names. - -This is everything that the following code does. - -*****************************************************************************/ - - -namespace PySide { namespace Feature { - -using namespace Shiboken; - -typedef bool(*FeatureProc)(PyTypeObject *type, PyObject *prev_dict, int id); - -static FeatureProc *featurePointer = nullptr; - -static PyObject *cached_globals = nullptr; -static PyObject *last_select_id = nullptr; - -static PyObject *_fast_id_array[1 + 256] = {}; -// this will point to element 1 to allow indexing from -1 -static PyObject **fast_id_array; - -static inline PyObject *getFeatureSelectId() -{ - static PyObject *undef = fast_id_array[-1]; - static PyObject *feature_dict = GetFeatureDict(); - // these things are all borrowed - PyObject *globals = PyEval_GetGlobals(); - if ( globals == nullptr - || globals == cached_globals) - return last_select_id; - - PyObject *modname = PyDict_GetItem(globals, PyMagicName::name()); - if (modname == nullptr) - return last_select_id; - - PyObject *select_id = PyDict_GetItem(feature_dict, modname); - if ( select_id == nullptr - || !PyInt_Check(select_id) // int/long cheating - || select_id == undef) - return last_select_id; - - cached_globals = globals; - last_select_id = select_id; - assert(PyInt_AsSsize_t(select_id) >= 0); - return select_id; -} - -// Create a derived dict class -static PyTypeObject * -createDerivedDictType() -{ - // It is not easy to create a compatible dict object with the - // limited API. Easier is to use Python to create a derived - // type and to modify that a bit from the C code. - PyObject *ChameleonDict = PepRun_GetResult(R"CPP(if True: - - class ChameleonDict(dict): - __slots__ = ("dict_ring", "select_id") - - result = ChameleonDict - - )CPP"); - return reinterpret_cast<PyTypeObject *>(ChameleonDict); -} - -static PyTypeObject *new_dict_type = nullptr; - -static void ensureNewDictType() -{ - if (new_dict_type == nullptr) { - new_dict_type = createDerivedDictType(); - if (new_dict_type == nullptr) - Py_FatalError("PySide2: Problem creating ChameleonDict"); - } -} - -static inline PyObject *nextInCircle(PyObject *dict) -{ - // returns a borrowed ref - AutoDecRef next_dict(PyObject_GetAttr(dict, PyName::dict_ring())); - return next_dict; -} - -static inline void setNextDict(PyObject *dict, PyObject *next_dict) -{ - PyObject_SetAttr(dict, PyName::dict_ring(), next_dict); -} - -static inline void setSelectId(PyObject *dict, PyObject *select_id) -{ - PyObject_SetAttr(dict, PyName::select_id(), select_id); -} - -static inline PyObject *getSelectId(PyObject *dict) -{ - auto select_id = PyObject_GetAttr(dict, PyName::select_id()); - return select_id; -} - -static inline void setCurrentSelectId(PyTypeObject *type, PyObject *select_id) -{ - SbkObjectType_SetReserved(type, PyInt_AsSsize_t(select_id)); // int/long cheating -} - -static inline void setCurrentSelectId(PyTypeObject *type, int id) -{ - SbkObjectType_SetReserved(type, id); -} - -static inline PyObject *getCurrentSelectId(PyTypeObject *type) -{ - int id = SbkObjectType_GetReserved(type); - // This can be too early. - if (id < 0) - id = 0; - return fast_id_array[id]; -} - -static bool replaceClassDict(PyTypeObject *type) -{ - /* - * Replace the type dict by the derived ChameleonDict. - * This is mandatory for all type dicts when they are touched. - */ - ensureNewDictType(); - PyObject *dict = type->tp_dict; - auto ob_ndt = reinterpret_cast<PyObject *>(new_dict_type); - PyObject *new_dict = PyObject_CallObject(ob_ndt, nullptr); - if (new_dict == nullptr || PyDict_Update(new_dict, dict) < 0) - return false; - // Insert the default id. Cannot fail for small numbers. - AutoDecRef select_id(PyInt_FromLong(0)); - setSelectId(new_dict, select_id); - // insert the dict into itself as ring - setNextDict(new_dict, new_dict); - // We have now an exact copy of the dict with a new type. - // Replace `__dict__` which usually has refcount 1 (but see cyclic_test.py) - Py_DECREF(type->tp_dict); - type->tp_dict = new_dict; - return true; -} - -static bool addNewDict(PyTypeObject *type, PyObject *select_id) -{ - /* - * Add a new dict to the ring and set it as `type->tp_dict`. - * A 'false' return is fatal. - */ - auto dict = type->tp_dict; - auto ob_ndt = reinterpret_cast<PyObject *>(new_dict_type); - auto new_dict = PyObject_CallObject(ob_ndt, nullptr); - if (new_dict == nullptr) - return false; - setSelectId(new_dict, select_id); - // insert the dict into the ring - auto next_dict = nextInCircle(dict); - setNextDict(dict, new_dict); - setNextDict(new_dict, next_dict); - type->tp_dict = new_dict; - return true; -} - -static bool moveToFeatureSet(PyTypeObject *type, PyObject *select_id) -{ - /* - * Rotate the ring to the given `select_id` and return `true`. - * If not found, stay at the current position and return `false`. - */ - auto initial_dict = type->tp_dict; - auto dict = initial_dict; - do { - dict = nextInCircle(dict); - AutoDecRef current_id(getSelectId(dict)); - // This works because small numbers are singleton objects. - if (current_id == select_id) { - type->tp_dict = dict; - setCurrentSelectId(type, select_id); - return true; - } - } while (dict != initial_dict); - type->tp_dict = initial_dict; - return false; -} - -static bool createNewFeatureSet(PyTypeObject *type, PyObject *select_id) -{ - /* - * Create a new feature set. - * A `false` return value is a fatal error. - * - * A FeatureProc sees an empty `type->tp_dict` and the previous dict - * content in `prev_dict`. It is responsible of filling `type->tp_dict` - * with modified content. - */ - static auto small_1 = PyInt_FromLong(255); - Q_UNUSED(small_1); - static auto small_2 = PyInt_FromLong(255); - Q_UNUSED(small_2); - // make sure that small integers are cached - assert(small_1 != nullptr && small_1 == small_2); - - static auto zero = fast_id_array[0]; - bool ok = moveToFeatureSet(type, zero); - Q_UNUSED(ok); - assert(ok); - - AutoDecRef prev_dict(type->tp_dict); - Py_INCREF(prev_dict); // keep the first ref unchanged - if (!addNewDict(type, select_id)) - return false; - auto id = PyInt_AsSsize_t(select_id); // int/long cheating - if (id == -1) - return false; - setCurrentSelectId(type, id); - FeatureProc *proc = featurePointer; - for (int idx = id; *proc != nullptr; ++proc, idx >>= 1) { - if (idx & 1) { - // clear the tp_dict that will get new content - PyDict_Clear(type->tp_dict); - // let the proc re-fill the tp_dict - if (!(*proc)(type, prev_dict, id)) - return false; - // if there is still a step, prepare `prev_dict` - if (idx >> 1) { - prev_dict.reset(PyDict_Copy(type->tp_dict)); - if (prev_dict.isNull()) - return false; - } - } - } - return true; -} - -static bool SelectFeatureSetSubtype(PyTypeObject *type, PyObject *select_id) -{ - /* - * This is the selector for one sublass. We need to call this for - * every subclass until no more subclasses or reaching the wanted id. - */ - if (Py_TYPE(type->tp_dict) == Py_TYPE(PyType_Type.tp_dict)) { - // On first touch, we initialize the dynamic naming. - // The dict type will be replaced after the first call. - if (!replaceClassDict(type)) { - Py_FatalError("failed to replace class dict!"); - return false; - } - } - if (!moveToFeatureSet(type, select_id)) { - if (!createNewFeatureSet(type, select_id)) { - Py_FatalError("failed to create a new feature set!"); - return false; - } - } - return true; -} - -static inline PyObject *SelectFeatureSet(PyTypeObject *type) -{ - /* - * This is the main function of the module. - * The purpose of this function is to switch the dict of a class right - * before a (get|set)attro call is performed. - * - * Generated functions call this directly. - * Shiboken will assign it via a public hook of `basewrapper.cpp`. - */ - if (Py_TYPE(type->tp_dict) == Py_TYPE(PyType_Type.tp_dict)) { - // We initialize the dynamic features by using our own dict type. - if (!replaceClassDict(type)) - return nullptr; - } - PyObject *select_id = getFeatureSelectId(); // borrowed - PyObject *current_id = getCurrentSelectId(type); // borrowed - static PyObject *undef = fast_id_array[-1]; - - // PYSIDE-1019: During import PepType_SOTP is still zero. - if (current_id == undef) - current_id = select_id = fast_id_array[0]; - - if (select_id != current_id) { - PyObject *mro = type->tp_mro; - Py_ssize_t idx, n = PyTuple_GET_SIZE(mro); - // We leave 'Shiboken.Object' and 'object' alone, therefore "n - 2". - for (idx = 0; idx < n - 2; idx++) { - auto *sub_type = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, idx)); - // When any subtype is already resolved (false), we can stop. - if (!SelectFeatureSetSubtype(sub_type, select_id)) - break; - } - } - return type->tp_dict; -} - -// For cppgenerator: -void Select(PyObject *obj) -{ - if (featurePointer == nullptr) - return; - auto type = Py_TYPE(obj); - type->tp_dict = SelectFeatureSet(type); -} - -PyObject *Select(PyTypeObject *type) -{ - if (featurePointer != nullptr) - type->tp_dict = SelectFeatureSet(type); - return type->tp_dict; -} - -static bool feature_01_addLowerNames(PyTypeObject *type, PyObject *prev_dict, int id); -static bool feature_02_true_property(PyTypeObject *type, PyObject *prev_dict, int id); -static bool feature_04_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int id); -static bool feature_08_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int id); -static bool feature_10_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int id); -static bool feature_20_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int id); -static bool feature_40_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int id); -static bool feature_80_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int id); - -static FeatureProc featureProcArray[] = { - feature_01_addLowerNames, - feature_02_true_property, - feature_04_addDummyNames, - feature_08_addDummyNames, - feature_10_addDummyNames, - feature_20_addDummyNames, - feature_40_addDummyNames, - feature_80_addDummyNames, - nullptr -}; - -void finalize() -{ - for (int idx = -1; idx < 256; ++idx) - Py_DECREF(fast_id_array[idx]); -} - -static bool patch_property_impl(); - -void init() -{ - // This function can be called multiple times. - static bool is_initialized = false; - if (!is_initialized) { - fast_id_array = &_fast_id_array[1]; - for (int idx = -1; idx < 256; ++idx) - fast_id_array[idx] = PyInt_FromLong(idx); - last_select_id = fast_id_array[0]; - featurePointer = featureProcArray; - initSelectableFeature(SelectFeatureSet); - registerCleanupFunction(finalize); - patch_property_impl(); - PySide::ClassProperty::init(); - is_initialized = true; - } - // Reset the cache. This is called at any "from __feature__ import". - cached_globals = nullptr; -} - -////////////////////////////////////////////////////////////////////////////// -// -// PYSIDE-1019: Support switchable extensions -// -// Feature 0x01: Allow snake_case instead of camelCase -// -// This functionality is no longer implemented in the signature module, since -// the PyCFunction getsets do not have to be modified any longer. -// Instead, we simply exchange the complete class dicts. This is done in the -// basewrapper.cpp file. -// - -static PyObject *methodWithNewName(PyTypeObject *type, - PyMethodDef *meth, - const char *new_name) -{ - /* - * Create a method with a lower case name. - */ - auto obtype = reinterpret_cast<PyObject *>(type); - int len = strlen(new_name); - auto name = new char[len + 1]; - strcpy(name, new_name); - auto new_meth = new PyMethodDef; - new_meth->ml_name = name; - new_meth->ml_meth = meth->ml_meth; - new_meth->ml_flags = meth->ml_flags; - new_meth->ml_doc = meth->ml_doc; - PyObject *descr = nullptr; - if (new_meth->ml_flags & METH_STATIC) { - AutoDecRef cfunc(PyCFunction_NewEx(new_meth, obtype, nullptr)); - if (cfunc.isNull()) - return nullptr; - descr = PyStaticMethod_New(cfunc); - } - else { - descr = PyDescr_NewMethod(type, new_meth); - } - return descr; -} - -static bool feature_01_addLowerNames(PyTypeObject *type, PyObject *prev_dict, int id) -{ - /* - * Add objects with lower names to `type->tp_dict` from 'prev_dict`. - */ - PyObject *lower_dict = type->tp_dict; - PyObject *key, *value; - Py_ssize_t pos = 0; - - // We first copy the things over which will not be changed: - while (PyDict_Next(prev_dict, &pos, &key, &value)) { - if ( Py_TYPE(value) != PepMethodDescr_TypePtr - && Py_TYPE(value) != PepStaticMethod_TypePtr) { - if (PyDict_SetItem(lower_dict, key, value)) - return false; - continue; - } - } - // Then we walk over the tp_methods to get all methods and insert - // them with changed names. - PyMethodDef *meth = type->tp_methods; - if (!meth) - return true; - - for (; meth != nullptr && meth->ml_name != nullptr; ++meth) { - const char *name = String::toCString(String::getSnakeCaseName(meth->ml_name, true)); - AutoDecRef new_method(methodWithNewName(type, meth, name)); - if (new_method.isNull()) - return false; - if (PyDict_SetItemString(lower_dict, name, new_method) < 0) - return false; - } - return true; -} - -////////////////////////////////////////////////////////////////////////////// -// -// PYSIDE-1019: Support switchable extensions -// -// Feature 0x02: Use true properties instead of getters and setters -// - -// This is the Python 2 version for inspection of m_ml, only. -// The actual Python 3 version is larget. - -typedef struct { - PyObject_HEAD - PyMethodDef *m_ml; /* Description of the C function to call */ - PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */ - PyObject *m_module; /* The __module__ attribute, can be anything */ -} PyCFunctionObject; - -static PyObject *modifyStaticToClassMethod(PyTypeObject *type, PyObject *sm) -{ - AutoDecRef func_ob(PyObject_GetAttr(sm, PyMagicName::func())); - if (func_ob.isNull()) - return nullptr; - auto func = reinterpret_cast<PyCFunctionObject *>(func_ob.object()); - auto new_func = new PyMethodDef; - new_func->ml_name = func->m_ml->ml_name; - new_func->ml_meth = func->m_ml->ml_meth; - new_func->ml_flags = (func->m_ml->ml_flags & ~METH_STATIC) | METH_CLASS; - new_func->ml_doc = func->m_ml->ml_doc; - auto cfunc = PyCFunction_NewEx(new_func, nullptr, nullptr); - cfunc = PyDescr_NewClassMethod(type, new_func); - return cfunc; -} - -static PyObject *createProperty(PyTypeObject *type, PyObject *getter, PyObject *setter) -{ - bool chassprop = false; - assert(getter != nullptr); - if (setter == nullptr) - setter = Py_None; - auto ptype = &PyProperty_Type; - if (Py_TYPE(getter) == PepStaticMethod_TypePtr) { - ptype = PyClassPropertyTypeF(); - chassprop = true; - getter = modifyStaticToClassMethod(type, getter); - if (setter != Py_None) - setter = modifyStaticToClassMethod(type, setter); - } - auto obtype = reinterpret_cast<PyObject *>(ptype); - PyObject *prop = PyObject_CallFunctionObjArgs(obtype, getter, setter, nullptr); - return prop; -} - -static QStringList parseFields(const char *propstr) -{ - /* - * Break the string into subfields at ':' and add defaults. - */ - QString s = QString(QLatin1String(propstr)); - auto list = s.split(QLatin1Char(':')); - assert(list.size() == 2 || list.size() == 3); - auto name = list[0]; - auto read = list[1]; - if (read.size() == 0) - list[1] = name; - if (list.size() == 2) - return list; - auto write = list[2]; - if (write.size() == 0) { - list[2] = QLatin1String("set") + name; - list[2][3] = list[2][3].toUpper(); - } - return list; -} - -static PyObject *make_snake_case(QString s, bool lower) -{ - if (s.isNull()) - return nullptr; - return String::getSnakeCaseName(s.toLatin1().data(), lower); -} - -static bool feature_02_true_property(PyTypeObject *type, PyObject *prev_dict, int id) -{ - /* - * Use the property info to create true Python property objects. - */ - - // The empty `tp_dict` gets populated by the previous dict. - PyObject *prop_dict = type->tp_dict; - if (PyDict_Update(prop_dict, prev_dict) < 0) - return false; - - // We then replace methods by properties. - bool lower = (id & 0x01) != 0; - auto props = SbkObjectType_GetPropertyStrings(type); - if (props == nullptr || *props == nullptr) - return true; - for (; *props != nullptr; ++props) { - auto propstr = *props; - auto fields = parseFields(propstr); - bool haveWrite = fields.size() == 3; - PyObject *name = make_snake_case(fields[0], lower); - PyObject *read = make_snake_case(fields[1], lower); - PyObject *write = haveWrite ? make_snake_case(fields[2], lower) : nullptr; - PyObject *getter = PyDict_GetItem(prev_dict, read); - if (getter == nullptr || !(Py_TYPE(getter) == PepMethodDescr_TypePtr || - Py_TYPE(getter) == PepStaticMethod_TypePtr)) - continue; - PyObject *setter = haveWrite ? PyDict_GetItem(prev_dict, write) : nullptr; - - AutoDecRef PyProperty(createProperty(type, getter, setter)); - if (PyProperty.isNull()) - return false; - if (PyDict_SetItem(prop_dict, name, PyProperty) < 0) - return false; - if (fields[0] != fields[1] && PyDict_GetItem(prop_dict, read)) - if (PyDict_DelItem(prop_dict, read) < 0) - return false; - // Theoretically, we need to check for multiple signatures to be exact. - // But we don't do so intentionally because it would be confusing. - if (haveWrite && PyDict_GetItem(prop_dict, write)) - if (PyDict_DelItem(prop_dict, write) < 0) - return false; - } - return true; -} - -////////////////////////////////////////////////////////////////////////////// -// -// These are a number of patches to make Python's property object better -// suitable for us. -// We turn `__doc__` into a lazy attribute saving signature initialization. -// -// There is now also a class property implementation which inherits -// from this one. -// - -static PyObject *property_doc_get(PyObject *self, void *) -{ - auto po = reinterpret_cast<propertyobject *>(self); - - if (po->prop_doc != nullptr && po->prop_doc != Py_None) { - Py_INCREF(po->prop_doc); - return po->prop_doc; - } - if (po->prop_get) { - // PYSIDE-1019: Fetch the default `__doc__` from fget. We do it late. - auto txt = PyObject_GetAttr(po->prop_get, PyMagicName::doc()); - if (txt != nullptr) { - Py_INCREF(txt); - po->prop_doc = txt; - Py_INCREF(txt); - return txt; - } - PyErr_Clear(); - } - Py_RETURN_NONE; -} - -static int property_doc_set(PyObject *self, PyObject *value, void *) -{ - auto po = reinterpret_cast<propertyobject *>(self); - - Py_INCREF(value); - po->prop_doc = value; - return 0; -} - -static PyGetSetDef property_getset[] = { - // This gets added to the existing getsets - {const_cast<char *>("__doc__"), property_doc_get, property_doc_set, nullptr, nullptr}, - {nullptr, nullptr, nullptr, nullptr, nullptr} -}; - -static bool patch_property_impl() -{ - // Turn `__doc__` into a computed attribute without changing writability. - auto gsp = property_getset; - auto type = &PyProperty_Type; - auto dict = type->tp_dict; - AutoDecRef descr(PyDescr_NewGetSet(type, gsp)); - if (descr.isNull()) - return false; - if (PyDict_SetItemString(dict, gsp->name, descr) < 0) - return false; - return true; -} - -////////////////////////////////////////////////////////////////////////////// -// -// PYSIDE-1019: Support switchable extensions -// -// Feature 0x04..0x40: A fake switchable option for testing -// - -#define SIMILAR_FEATURE(xx) \ -static bool feature_##xx##_addDummyNames(PyTypeObject *type, PyObject *prev_dict, int id) \ -{ \ - PyObject *dict = type->tp_dict; \ - if (PyDict_Update(dict, prev_dict) < 0) \ - return false; \ - if (PyDict_SetItemString(dict, "fake_feature_" #xx, Py_None) < 0) \ - return false; \ - return true; \ -} - -SIMILAR_FEATURE(04) -SIMILAR_FEATURE(08) -SIMILAR_FEATURE(10) -SIMILAR_FEATURE(20) -SIMILAR_FEATURE(40) -SIMILAR_FEATURE(80) - -} // namespace PySide -} // namespace Feature diff --git a/sources/pyside2/libpyside/feature_select.h b/sources/pyside2/libpyside/feature_select.h deleted file mode 100644 index 845828a4c..000000000 --- a/sources/pyside2/libpyside/feature_select.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef FEATURE_SELECT_H -#define FEATURE_SELECT_H - -#include "pysidemacros.h" -#include <sbkpython.h> - -namespace PySide { -namespace Feature { - -PYSIDE_API void init(); -PYSIDE_API void Select(PyObject *obj); -PYSIDE_API PyObject *Select(PyTypeObject *type); - -} // namespace Feature -} // namespace PySide - -#endif // FEATURE_SELECT_H diff --git a/sources/pyside2/libpyside/globalreceiverv2.cpp b/sources/pyside2/libpyside/globalreceiverv2.cpp deleted file mode 100644 index bfaa9ff44..000000000 --- a/sources/pyside2/libpyside/globalreceiverv2.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "globalreceiverv2.h" -#include "dynamicqmetaobject_p.h" -#include "pysideweakref.h" -#include "signalmanager.h" - -#include <autodecref.h> -#include <gilstate.h> - -#include <QtCore/QMetaMethod> -#include <QtCore/QSet> - -#define RECEIVER_DESTROYED_SLOT_NAME "__receiverDestroyed__(QObject*)" - -namespace -{ - static int DESTROY_SIGNAL_ID = 0; - static int DESTROY_SLOT_ID = 0; -} - -namespace PySide -{ -class DynamicSlotDataV2 -{ - Q_DISABLE_COPY(DynamicSlotDataV2) - public: - DynamicSlotDataV2(PyObject *callback, GlobalReceiverV2 *parent); - ~DynamicSlotDataV2(); - - int addSlot(const char *signature); - int id(const char *signature) const; - PyObject *callback(); - QByteArray hash() const; - void notify(); - - static void onCallbackDestroyed(void *data); - static QByteArray hash(PyObject *callback); - - - private: - bool m_isMethod; - PyObject *m_callback; - PyObject *m_pythonSelf; - PyObject *m_pyClass; - PyObject *m_weakRef; - QMap<QByteArray, int> m_signatures; - GlobalReceiverV2 *m_parent; - QByteArray m_hash; -}; - -} - -using namespace PySide; - -DynamicSlotDataV2::DynamicSlotDataV2(PyObject *callback, GlobalReceiverV2 *parent) - : m_pythonSelf(0), m_pyClass(0), m_weakRef(0), m_parent(parent) -{ - Shiboken::GilState gil; - - m_isMethod = PyMethod_Check(callback); - if (m_isMethod) { - //Can not store calback pointe because this will be destroyed at the end of the scope - //To avoid increment intance reference keep the callback information - m_callback = PyMethod_GET_FUNCTION(callback); - m_pythonSelf = PyMethod_GET_SELF(callback); - - //monitor class from method lifetime - m_weakRef = WeakRef::create(m_pythonSelf, DynamicSlotDataV2::onCallbackDestroyed, this); - - m_hash = QByteArray::number((qlonglong)PyObject_Hash(m_callback)) - + QByteArray::number((qlonglong)PyObject_Hash(m_pythonSelf)); - - } else { - m_callback = callback; - Py_INCREF(m_callback); - - m_hash = QByteArray::number((qlonglong)PyObject_Hash(m_callback)); - } -} - -QByteArray DynamicSlotDataV2::hash() const -{ - return m_hash; -} - -QByteArray DynamicSlotDataV2::hash(PyObject *callback) -{ - Shiboken::GilState gil; - if (PyMethod_Check(callback)) { - return QByteArray::number((qlonglong)PyObject_Hash(PyMethod_GET_FUNCTION(callback))) - + QByteArray::number((qlonglong)PyObject_Hash(PyMethod_GET_SELF(callback))); - } - return QByteArray::number(qlonglong(PyObject_Hash(callback))); -} - -PyObject *DynamicSlotDataV2::callback() -{ - PyObject *callback = m_callback; - - //create a callback based on method data - if (m_isMethod) - callback = PyMethod_New(m_callback, m_pythonSelf); - else - Py_INCREF(callback); - - return callback; -} - -int DynamicSlotDataV2::id(const char *signature) const -{ - const auto it = m_signatures.constFind(signature); - return it != m_signatures.cend() ? it.value() : -1; -} - -int DynamicSlotDataV2::addSlot(const char *signature) -{ - int index = id(signature); - if (index == -1) - index = m_signatures[signature] = m_parent->metaObjectBuilder().addSlot(signature); - return index; -} - -void DynamicSlotDataV2::onCallbackDestroyed(void *data) -{ - auto self = reinterpret_cast<DynamicSlotDataV2 *>(data); - self->m_weakRef = 0; - Py_BEGIN_ALLOW_THREADS - delete self->m_parent; - Py_END_ALLOW_THREADS -} - -DynamicSlotDataV2::~DynamicSlotDataV2() -{ - Shiboken::GilState gil; - - Py_XDECREF(m_weakRef); - m_weakRef = 0; - - if (!m_isMethod) - Py_DECREF(m_callback); -} - -GlobalReceiverV2::GlobalReceiverV2(PyObject *callback, SharedMap map) : - QObject(nullptr), - m_metaObject("__GlobalReceiver__", &QObject::staticMetaObject), - m_sharedMap(std::move(map)) -{ - m_data = new DynamicSlotDataV2(callback, this); - m_metaObject.addSlot(RECEIVER_DESTROYED_SLOT_NAME); - m_metaObject.update(); - m_refs.append(NULL); - - - if (DESTROY_SIGNAL_ID == 0) - DESTROY_SIGNAL_ID = QObject::staticMetaObject.indexOfSignal("destroyed(QObject*)"); - - if (DESTROY_SLOT_ID == 0) - DESTROY_SLOT_ID = m_metaObject.indexOfMethod(QMetaMethod::Slot, RECEIVER_DESTROYED_SLOT_NAME); - - -} - -GlobalReceiverV2::~GlobalReceiverV2() -{ - m_refs.clear(); - // Remove itself from map. - m_sharedMap->remove(m_data->hash()); - // Suppress handling of destroyed() for objects whose last reference is contained inside - // the callback object that will now be deleted. The reference could be a default argument, - // a callback local variable, etc. - // The signal has to be suppressed because it would lead to the following situation: - // Callback is deleted, hence the last reference is decremented, - // leading to the object being deleted, which emits destroyed(), which would try to invoke - // the already deleted callback, and also try to delete the object again. - DynamicSlotDataV2 *data = m_data; - m_data = Q_NULLPTR; - delete data; -} - -int GlobalReceiverV2::addSlot(const char *signature) -{ - return m_data->addSlot(signature); -} - -void GlobalReceiverV2::incRef(const QObject *link) -{ - if (link) { - if (!m_refs.contains(link)) { - bool connected; - Py_BEGIN_ALLOW_THREADS - connected = QMetaObject::connect(link, DESTROY_SIGNAL_ID, this, DESTROY_SLOT_ID); - Py_END_ALLOW_THREADS - if (connected) - m_refs.append(link); - else - Q_ASSERT(false); - } else { - m_refs.append(link); - } - } else { - m_refs.append(NULL); - } -} - -void GlobalReceiverV2::decRef(const QObject *link) -{ - if (m_refs.empty()) - return; - - - m_refs.removeOne(link); - if (link) { - if (!m_refs.contains(link)) { - bool result; - Py_BEGIN_ALLOW_THREADS - result = QMetaObject::disconnect(link, DESTROY_SIGNAL_ID, this, DESTROY_SLOT_ID); - Py_END_ALLOW_THREADS - Q_ASSERT(result); - if (!result) - return; - } - } - - if (m_refs.empty()) - Py_BEGIN_ALLOW_THREADS - delete this; - Py_END_ALLOW_THREADS - -} - -int GlobalReceiverV2::refCount(const QObject *link) const -{ - if (link) - return m_refs.count(link); - - return m_refs.size(); -} - -void GlobalReceiverV2::notify() -{ - const QSet<const QObject *> objSet(m_refs.cbegin(), m_refs.cend()); - Py_BEGIN_ALLOW_THREADS - for (const QObject *o : objSet) { - QMetaObject::disconnect(o, DESTROY_SIGNAL_ID, this, DESTROY_SLOT_ID); - QMetaObject::connect(o, DESTROY_SIGNAL_ID, this, DESTROY_SLOT_ID); - } - Py_END_ALLOW_THREADS -} - -QByteArray GlobalReceiverV2::hash() const -{ - return m_data->hash(); -} - -QByteArray GlobalReceiverV2::hash(PyObject *callback) -{ - return DynamicSlotDataV2::hash(callback); -} - -const QMetaObject *GlobalReceiverV2::metaObject() const -{ - return const_cast<GlobalReceiverV2 *>(this)->m_metaObject.update(); -} - -int GlobalReceiverV2::qt_metacall(QMetaObject::Call call, int id, void **args) -{ - Shiboken::GilState gil; - Q_ASSERT(call == QMetaObject::InvokeMetaMethod); - Q_ASSERT(id >= QObject::staticMetaObject.methodCount()); - - QMetaMethod slot = metaObject()->method(id); - Q_ASSERT(slot.methodType() == QMetaMethod::Slot); - - if (!m_data) { - if (id != DESTROY_SLOT_ID) { - const QByteArray message = "PySide2 Warning: Skipping callback call " - + slot.methodSignature() + " because the callback object is being destructed."; - PyErr_WarnEx(PyExc_RuntimeWarning, message.constData(), 0); - } - return -1; - } - - if (id == DESTROY_SLOT_ID) { - if (m_refs.empty()) - return -1; - auto obj = *reinterpret_cast<QObject **>(args[1]); - incRef(); //keep the object live (safe ref) - m_refs.removeAll(obj); // remove all refs to this object - decRef(); //remove the safe ref - } else { - bool isShortCuit = (strstr(slot.methodSignature(), "(") == 0); - Shiboken::AutoDecRef callback(m_data->callback()); - SignalManager::callPythonMetaMethod(slot, args, callback, isShortCuit); - } - - // SignalManager::callPythonMetaMethod might have failed, in that case we have to print the - // error so it considered "handled". - if (PyErr_Occurred()) { - int reclimit = Py_GetRecursionLimit(); - // Inspired by Python's errors.c: PyErr_GivenExceptionMatches() function. - // Temporarily bump the recursion limit, so that PyErr_Print will not raise a recursion - // error again. Don't do it when the limit is already insanely high, to avoid overflow. - if (reclimit < (1 << 30)) - Py_SetRecursionLimit(reclimit + 5); - PyErr_Print(); - Py_SetRecursionLimit(reclimit); - } - - return -1; -} diff --git a/sources/pyside2/libpyside/globalreceiverv2.h b/sources/pyside2/libpyside/globalreceiverv2.h deleted file mode 100644 index 433f587a9..000000000 --- a/sources/pyside2/libpyside/globalreceiverv2.h +++ /dev/null @@ -1,150 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef GLOBALRECEIVER_V2_H -#define GLOBALRECEIVER_V2_H - -#include <sbkpython.h> - -#include "dynamicqmetaobject.h" - -#include <QtCore/QByteArray> -#include <QtCore/QObject> -#include <QtCore/QMap> -#include <QtCore/QSharedPointer> - -namespace PySide -{ - -class DynamicSlotDataV2; -class GlobalReceiverV2; - -typedef QMap<QByteArray, GlobalReceiverV2 *> GlobalReceiverV2Map; -typedef QSharedPointer<GlobalReceiverV2Map> SharedMap; - -/** - * A class used to make the link between the C++ Signal/Slot and Python callback - * This class is used internally by SignalManager - **/ - -class GlobalReceiverV2 : public QObject -{ -public: - /** - * Create a GlobalReceiver object that will call 'callback' argumentent - * - * @param callback A Python callable object (can be a method or not) - * @param ma A SharedPointer used on Signal manager that contains all instaces of GlobalReceiver - **/ - GlobalReceiverV2(PyObject *callback, SharedMap map); - - /** - * Destructor - **/ - ~GlobalReceiverV2() override; - - /** - * Reimplemented function from QObject - **/ - int qt_metacall(QMetaObject::Call call, int id, void **args) override; - const QMetaObject *metaObject() const override; - - /** - * Add a extra slot to this object - * - * @param signature The signature of the slot to be added - * @return The index of this slot on metaobject - **/ - int addSlot(const char *signature); - - /** - * Notify to GlobalReceiver about when a new connection was made - **/ - void notify(); - - /** - * Used to increment the reference of the GlobalReceiver object - * - * @param link This is a optional paramenter used to link the ref to some QObject life - **/ - void incRef(const QObject *link = nullptr); - - /** - * Used to decrement the reference of the GlobalReceiver object - * - * @param link This is a optional paramenter used to dismiss the link ref to some QObject - **/ - void decRef(const QObject *link = nullptr); - - /* - * Return the count of refs which the GlobalReceiver has - * - * @param link If any QObject was passed, the function return the number of references relative to this 'link' object - * @return The number of references - **/ - int refCount(const QObject *link) const; - - /** - * Use to retrieve the unique hash of this GlobalReceiver object - * - * @return a string with a unique id based on GlobalReceiver contents - **/ - QByteArray hash() const; - - /** - * Use to retrieve the unique hash of the PyObject based on GlobalReceiver rules - * - * @param callback The Python callable object used to calculate the id - * @return a string with a unique id based on GlobalReceiver contents - **/ - static QByteArray hash(PyObject *callback); - - const MetaObjectBuilder &metaObjectBuilder() const { return m_metaObject; } - MetaObjectBuilder &metaObjectBuilder() { return m_metaObject; } - -private: - MetaObjectBuilder m_metaObject; - DynamicSlotDataV2 *m_data; - QList<const QObject *> m_refs; - SharedMap m_sharedMap; -}; - -} - -#endif diff --git a/sources/pyside2/libpyside/pyside.cpp b/sources/pyside2/libpyside/pyside.cpp deleted file mode 100644 index 4995f35dd..000000000 --- a/sources/pyside2/libpyside/pyside.cpp +++ /dev/null @@ -1,616 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "pyside.h" -#include "pyside_p.h" -#include "signalmanager.h" -#include "pysideclassinfo_p.h" -#include "pysideproperty_p.h" -#include "pysideproperty.h" -#include "pysidesignal.h" -#include "pysidesignal_p.h" -#include "pysidestaticstrings.h" -#include "pysideslot_p.h" -#include "pysidemetafunction_p.h" -#include "pysidemetafunction.h" -#include "dynamicqmetaobject.h" - -#include <autodecref.h> -#include <basewrapper.h> -#include <bindingmanager.h> -#include <gilstate.h> -#include <sbkconverter.h> -#include <sbkstring.h> -#include <sbkstaticstrings.h> -#include <qapp_macro.h> - -#include <QtCore/QByteArray> -#include <QtCore/QCoreApplication> -#include <QtCore/QDir> -#include <QtCore/QFileInfo> -#include <QtCore/QSharedPointer> -#include <QtCore/QStack> - -#include <algorithm> -#include <cstring> -#include <cctype> -#include <typeinfo> - -static QStack<PySide::CleanupFunction> cleanupFunctionList; -static void *qobjectNextAddr; - -QT_BEGIN_NAMESPACE -extern bool qRegisterResourceData(int, const unsigned char *, const unsigned char *, - const unsigned char *); -QT_END_NAMESPACE - -namespace PySide -{ - -void init(PyObject *module) -{ - qobjectNextAddr = 0; - ClassInfo::init(module); - Signal::init(module); - Slot::init(module); - Property::init(module); - MetaFunction::init(module); - // Init signal manager, so it will register some meta types used by QVariant. - SignalManager::instance(); - initQApp(); -} - -static bool _setProperty(PyObject *qObj, PyObject *name, PyObject *value, bool *accept) -{ - QByteArray propName(Shiboken::String::toCString(name)); - propName[0] = std::toupper(propName[0]); - propName.prepend("set"); - - Shiboken::AutoDecRef propSetter(PyObject_GetAttrString(qObj, propName.constData())); - if (!propSetter.isNull()) { - *accept = true; - Shiboken::AutoDecRef args(PyTuple_Pack(1, value)); - Shiboken::AutoDecRef retval(PyObject_CallObject(propSetter, args)); - if (retval.isNull()) - return false; - } else { - PyErr_Clear(); - Shiboken::AutoDecRef attr(PyObject_GenericGetAttr(qObj, name)); - if (PySide::Property::checkType(attr)) { - *accept = true; - if (PySide::Property::setValue(reinterpret_cast<PySideProperty *>(attr.object()), qObj, value) < 0) - return false; - } - } - return true; -} - -bool fillQtProperties(PyObject *qObj, const QMetaObject *metaObj, PyObject *kwds, const char **blackList, unsigned int blackListSize) -{ - - PyObject *key, *value; - Py_ssize_t pos = 0; - - while (PyDict_Next(kwds, &pos, &key, &value)) { - if (!blackListSize || !std::binary_search(blackList, blackList + blackListSize, std::string(Shiboken::String::toCString(key)))) { - QByteArray propName(Shiboken::String::toCString(key)); - bool accept = false; - if (metaObj->indexOfProperty(propName) != -1) { - if (!_setProperty(qObj, key, value, &accept)) - return false; - } else { - propName.append("()"); - if (metaObj->indexOfSignal(propName) != -1) { - accept = true; - propName.prepend('2'); - if (!PySide::Signal::connect(qObj, propName, value)) - return false; - } - } - if (!accept) { - // PYSIDE-1019: Allow any existing attribute in the constructor. - if (!_setProperty(qObj, key, value, &accept)) - return false; - } - if (!accept) { - PyErr_Format(PyExc_AttributeError, "'%s' is not a Qt property or a signal", - propName.constData()); - return false; - } - } - } - return true; -} - -void registerCleanupFunction(CleanupFunction func) -{ - cleanupFunctionList.push(func); -} - -void runCleanupFunctions() -{ - while (!cleanupFunctionList.isEmpty()) { - CleanupFunction f = cleanupFunctionList.pop(); - f(); - } -} - -static void destructionVisitor(SbkObject *pyObj, void *data) -{ - auto realData = reinterpret_cast<void **>(data); - auto pyQApp = reinterpret_cast<SbkObject *>(realData[0]); - auto pyQObjectType = reinterpret_cast<PyTypeObject *>(realData[1]); - - if (pyObj != pyQApp && PyObject_TypeCheck(pyObj, pyQObjectType)) { - if (Shiboken::Object::hasOwnership(pyObj) && Shiboken::Object::isValid(pyObj, false)) { - Shiboken::Object::setValidCpp(pyObj, false); - - Py_BEGIN_ALLOW_THREADS - Shiboken::callCppDestructor<QObject>(Shiboken::Object::cppPointer(pyObj, pyQObjectType)); - Py_END_ALLOW_THREADS - } - } - -}; - -void destroyQCoreApplication() -{ - QCoreApplication *app = QCoreApplication::instance(); - if (!app) - return; - SignalManager::instance().clear(); - - Shiboken::BindingManager &bm = Shiboken::BindingManager::instance(); - SbkObject *pyQApp = bm.retrieveWrapper(app); - PyTypeObject *pyQObjectType = Shiboken::Conversions::getPythonTypeObject("QObject*"); - assert(pyQObjectType); - - void *data[2] = {pyQApp, pyQObjectType}; - bm.visitAllPyObjects(&destructionVisitor, &data); - - // in the end destroy app - // Allow threads because the destructor calls - // QThreadPool::globalInstance().waitForDone() which may deadlock on the GIL - // if there is a worker working with python objects. - Py_BEGIN_ALLOW_THREADS - delete app; - Py_END_ALLOW_THREADS - // PYSIDE-571: make sure to create a singleton deleted qApp. - Py_DECREF(MakeQAppWrapper(nullptr)); -} - -std::size_t getSizeOfQObject(SbkObjectType *type) -{ - return retrieveTypeUserData(type)->cppObjSize; -} - -void initDynamicMetaObject(SbkObjectType *type, const QMetaObject *base, std::size_t cppObjSize) -{ - //create DynamicMetaObject based on python type - auto userData = new TypeUserData(reinterpret_cast<PyTypeObject *>(type), base, cppObjSize); - userData->mo.update(); - Shiboken::ObjectType::setTypeUserData(type, userData, Shiboken::callCppDestructor<TypeUserData>); - - //initialize staticQMetaObject property - void *metaObjectPtr = const_cast<QMetaObject *>(userData->mo.update()); - static SbkConverter *converter = Shiboken::Conversions::getConverter("QMetaObject"); - if (!converter) - return; - Shiboken::AutoDecRef pyMetaObject(Shiboken::Conversions::pointerToPython(converter, metaObjectPtr)); - PyObject_SetAttr(reinterpret_cast<PyObject *>(type), - PySide::PyName::qtStaticMetaObject(), pyMetaObject); -} - -TypeUserData *retrieveTypeUserData(SbkObjectType *sbkTypeObj) -{ - return reinterpret_cast<TypeUserData *>(Shiboken::ObjectType::getTypeUserData(sbkTypeObj)); -} - -TypeUserData *retrieveTypeUserData(PyTypeObject *pyTypeObj) -{ - return retrieveTypeUserData(reinterpret_cast<SbkObjectType *>(pyTypeObj)); -} - -TypeUserData *retrieveTypeUserData(PyObject *pyObj) -{ - auto pyTypeObj = PyType_Check(pyObj) - ? reinterpret_cast<PyTypeObject *>(pyObj) : Py_TYPE(pyObj); - return retrieveTypeUserData(pyTypeObj); -} - -const QMetaObject *retrieveMetaObject(PyTypeObject *pyTypeObj) -{ - TypeUserData *userData = retrieveTypeUserData(pyTypeObj); - return userData ? userData->mo.update() : nullptr; -} - -const QMetaObject *retrieveMetaObject(PyObject *pyObj) -{ - auto pyTypeObj = PyType_Check(pyObj) - ? reinterpret_cast<PyTypeObject *>(pyObj) : Py_TYPE(pyObj); - return retrieveMetaObject(pyTypeObj); -} - -void initQObjectSubType(SbkObjectType *type, PyObject *args, PyObject * /* kwds */) -{ - PyTypeObject *qObjType = Shiboken::Conversions::getPythonTypeObject("QObject*"); - QByteArray className(Shiboken::String::toCString(PyTuple_GET_ITEM(args, 0))); - - PyObject *bases = PyTuple_GET_ITEM(args, 1); - int numBases = PyTuple_GET_SIZE(bases); - - TypeUserData *userData = nullptr; - - for (int i = 0; i < numBases; ++i) { - auto base = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(bases, i)); - if (PyType_IsSubtype(base, qObjType)) { - userData = retrieveTypeUserData(base); - break; - } - } - if (!userData) { - qWarning("Sub class of QObject not inheriting QObject!? Crash will happen when using %s.", className.constData()); - return; - } - initDynamicMetaObject(type, userData->mo.update(), userData->cppObjSize); -} - -void initQApp() -{ - /* - * qApp will not be initialized when embedding is active. - * That means that qApp exists already when PySide is initialized. - * We could solve that by creating a qApp variable, but in embedded - * mode, we also have the effect that the first assignment to qApp - * is persistent! Therefore, we can never be sure to have created - * qApp late enough to get the right type for the instance. - * - * I would appreciate very much if someone could explain or even fix - * this issue. It exists only when a pre-existing application exists. - */ - if (!qApp) - Py_DECREF(MakeQAppWrapper(nullptr)); -} - -PyObject *getMetaDataFromQObject(QObject *cppSelf, PyObject *self, PyObject *name) -{ - PyObject *attr = PyObject_GenericGetAttr(self, name); - if (!Shiboken::Object::isValid(reinterpret_cast<SbkObject *>(self), false)) - return attr; - - if (attr && Property::checkType(attr)) { - PyObject *value = Property::getValue(reinterpret_cast<PySideProperty *>(attr), self); - Py_DECREF(attr); - if (!value) - return 0; - attr = value; - } - - //mutate native signals to signal instance type - if (attr && PyObject_TypeCheck(attr, PySideSignalTypeF())) { - PyObject *signal = reinterpret_cast<PyObject *>(Signal::initialize(reinterpret_cast<PySideSignal *>(attr), name, self)); - PyObject_SetAttr(self, name, reinterpret_cast<PyObject *>(signal)); - return signal; - } - - //search on metaobject (avoid internal attributes started with '__') - if (!attr) { - const char *cname = Shiboken::String::toCString(name); - uint cnameLen = qstrlen(cname); - if (std::strncmp("__", cname, 2)) { - const QMetaObject *metaObject = cppSelf->metaObject(); - //signal - QList<QMetaMethod> signalList; - for(int i=0, i_max = metaObject->methodCount(); i < i_max; i++) { - QMetaMethod method = metaObject->method(i); - const QByteArray methSig_ = method.methodSignature(); - const char *methSig = methSig_.constData(); - bool methMacth = !std::strncmp(cname, methSig, cnameLen) && methSig[cnameLen] == '('; - if (methMacth) { - if (method.methodType() == QMetaMethod::Signal) { - signalList.append(method); - } else { - PySideMetaFunction *func = MetaFunction::newObject(cppSelf, i); - if (func) { - PyObject *result = reinterpret_cast<PyObject *>(func); - PyObject_SetAttr(self, name, result); - return result; - } - } - } - } - if (!signalList.empty()) { - PyObject *pySignal = reinterpret_cast<PyObject *>(Signal::newObjectFromMethod(self, signalList)); - PyObject_SetAttr(self, name, pySignal); - return pySignal; - } - } - } - return attr; -} - -bool inherits(PyTypeObject *objType, const char *class_name) -{ - if (strcmp(objType->tp_name, class_name) == 0) - return true; - - PyTypeObject *base = objType->tp_base; - if (base == 0) - return false; - - return inherits(base, class_name); -} - -void *nextQObjectMemoryAddr() -{ - return qobjectNextAddr; -} - -void setNextQObjectMemoryAddr(void *addr) -{ - qobjectNextAddr = addr; -} - -} // namespace PySide - -// A QSharedPointer is used with a deletion function to invalidate a pointer -// when the property value is cleared. This should be a QSharedPointer with -// a void *pointer, but that isn't allowed -typedef char any_t; -Q_DECLARE_METATYPE(QSharedPointer<any_t>); - -namespace PySide -{ - -static void invalidatePtr(any_t *object) -{ - Shiboken::GilState state; - - SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(object); - if (wrapper != NULL) - Shiboken::BindingManager::instance().releaseWrapper(wrapper); -} - -static const char invalidatePropertyName[] = "_PySideInvalidatePtr"; - -// PYSIDE-1214, when creating new wrappers for classes inheriting QObject but -// not exposed to Python, try to find the best-matching (most-derived) Qt -// class by walking up the meta objects. -static const char *typeName(QObject *cppSelf) -{ - const char *typeName = typeid(*cppSelf).name(); - if (!Shiboken::Conversions::getConverter(typeName)) { - for (auto metaObject = cppSelf->metaObject(); metaObject; metaObject = metaObject->superClass()) { - const char *name = metaObject->className(); - if (Shiboken::Conversions::getConverter(name)) { - typeName = name; - break; - } - } - } - return typeName; -} - -PyObject *getWrapperForQObject(QObject *cppSelf, SbkObjectType *sbk_type) -{ - PyObject *pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppSelf)); - if (pyOut) { - Py_INCREF(pyOut); - return pyOut; - } - - // Setting the property will trigger an QEvent notification, which may call into - // code that creates the wrapper so only set the property if it isn't already - // set and check if it's created after the set call - QVariant existing = cppSelf->property(invalidatePropertyName); - if (!existing.isValid()) { - QSharedPointer<any_t> shared_with_del(reinterpret_cast<any_t *>(cppSelf), invalidatePtr); - cppSelf->setProperty(invalidatePropertyName, QVariant::fromValue(shared_with_del)); - pyOut = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(cppSelf)); - if (pyOut) { - Py_INCREF(pyOut); - return pyOut; - } - } - - pyOut = Shiboken::Object::newObject(sbk_type, cppSelf, false, false, typeName(cppSelf)); - - return pyOut; -} - -#ifdef PYSIDE_QML_SUPPORT -static QuickRegisterItemFunction quickRegisterItem; - -QuickRegisterItemFunction getQuickRegisterItemFunction() -{ - return quickRegisterItem; -} - -void setQuickRegisterItemFunction(QuickRegisterItemFunction function) -{ - quickRegisterItem = function; -} -#endif // PYSIDE_QML_SUPPORT - -// Inspired by Shiboken::String::toCString; -QString pyStringToQString(PyObject *str) { - if (str == Py_None) - return QString(); - - if (PyUnicode_Check(str)) { - const char *unicodeBuffer = _PepUnicode_AsString(str); - if (unicodeBuffer) - return QString::fromUtf8(unicodeBuffer); - } - if (PyBytes_Check(str)) { - const char *asciiBuffer = PyBytes_AS_STRING(str); - if (asciiBuffer) - return QString::fromLatin1(asciiBuffer); - } - return QString(); -} - -static const unsigned char qt_resource_name[] = { - // qt - 0x0,0x2, - 0x0,0x0,0x7,0x84, - 0x0,0x71, - 0x0,0x74, - // etc - 0x0,0x3, - 0x0,0x0,0x6c,0xa3, - 0x0,0x65, - 0x0,0x74,0x0,0x63, - // qt.conf - 0x0,0x7, - 0x8,0x74,0xa6,0xa6, - 0x0,0x71, - 0x0,0x74,0x0,0x2e,0x0,0x63,0x0,0x6f,0x0,0x6e,0x0,0x66 -}; - -static const unsigned char qt_resource_struct[] = { - // : - 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x1, - // :/qt - 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x2, - // :/qt/etc - 0x0,0x0,0x0,0xa,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x3, - // :/qt/etc/qt.conf - 0x0,0x0,0x0,0x16,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0 -}; - -bool registerInternalQtConf() -{ - // Guard to ensure single registration. -#ifdef PYSIDE_QT_CONF_PREFIX - static bool registrationAttempted = false; -#else - static bool registrationAttempted = true; -#endif - static bool isRegistered = false; - if (registrationAttempted) - return isRegistered; - registrationAttempted = true; - - // Support PyInstaller case when a qt.conf file might be provided next to the generated - // PyInstaller executable. - // This will disable the internal qt.conf which points to the PySide2 subdirectory (due to the - // subdirectory not existing anymore). - QString executablePath = - QString::fromWCharArray(Py_GetProgramFullPath()); - QString appDirPath = QFileInfo(executablePath).absolutePath(); - QString maybeQtConfPath = QDir(appDirPath).filePath(QStringLiteral("qt.conf")); - bool executableQtConfAvailable = QFileInfo::exists(maybeQtConfPath); - maybeQtConfPath = QDir::toNativeSeparators(maybeQtConfPath); - - // Allow disabling the usage of the internal qt.conf. This is necessary for tests to work, - // because tests are executed before the package is installed, and thus the Prefix specified - // in qt.conf would point to a not yet existing location. - bool disableInternalQtConf = - qEnvironmentVariableIntValue("PYSIDE_DISABLE_INTERNAL_QT_CONF") > 0 ? true : false; - if (disableInternalQtConf || executableQtConfAvailable) { - registrationAttempted = true; - return false; - } - - PyObject *pysideModule = PyImport_ImportModule("PySide2"); - if (!pysideModule) - return false; - - // Querying __file__ should be done only for modules that have finished their initialization. - // Thus querying for the top-level PySide2 package works for us whenever any Qt-wrapped module - // is loaded. - PyObject *pysideInitFilePath = PyObject_GetAttr(pysideModule, Shiboken::PyMagicName::file()); - Py_DECREF(pysideModule); - if (!pysideInitFilePath) - return false; - - QString initPath = pyStringToQString(pysideInitFilePath); - Py_DECREF(pysideInitFilePath); - if (initPath.isEmpty()) - return false; - - // pysideDir - absolute path to the directory containing the init file, which also contains - // the rest of the PySide2 modules. - // prefixPath - absolute path to the directory containing the installed Qt (prefix). - QDir pysideDir = QFileInfo(QDir::fromNativeSeparators(initPath)).absoluteDir(); - QString setupPrefix; -#ifdef PYSIDE_QT_CONF_PREFIX - setupPrefix = QStringLiteral(PYSIDE_QT_CONF_PREFIX); -#endif - const QString prefixPathStr = pysideDir.absoluteFilePath(setupPrefix); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - const QByteArray prefixPath = prefixPathStr.toLocal8Bit(); -#else - // PYSIDE-972, QSettings used by QtCore uses Latin1 - const QByteArray prefixPath = prefixPathStr.toLatin1(); -#endif - - // rccData needs to be static, otherwise when it goes out of scope, the Qt resource system - // will point to invalid memory. - static QByteArray rccData = QByteArrayLiteral("[Paths]\nPrefix = ") + prefixPath -#ifdef Q_OS_WIN - // LibraryExecutables needs to point to Prefix instead of ./bin because we don't - // currently conform to the Qt default directory layout on Windows. This is necessary - // for QtWebEngineCore to find the location of QtWebEngineProcess.exe. - + QByteArray("\nLibraryExecutables = ") + prefixPath -#endif - ; - rccData.append('\n'); - - // The RCC data structure expects a 4-byte size value representing the actual data. - int size = rccData.size(); - - for (int i = 0; i < 4; ++i) { - rccData.prepend((size & 0xff)); - size >>= 8; - } - - const int version = 0x01; - isRegistered = qRegisterResourceData(version, qt_resource_struct, qt_resource_name, - reinterpret_cast<const unsigned char *>( - rccData.constData())); - - return isRegistered; -} - - - -} //namespace PySide - diff --git a/sources/pyside2/libpyside/pyside.h b/sources/pyside2/libpyside/pyside.h deleted file mode 100644 index e241ac74d..000000000 --- a/sources/pyside2/libpyside/pyside.h +++ /dev/null @@ -1,173 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_H -#define PYSIDE_H - -#include <sbkpython.h> - -#include <pysidemacros.h> - -#ifdef PYSIDE_QML_SUPPORT -# include <QtQml/qqml.h> -#endif - -#include <QtCore/QMetaType> -#include <QtCore/QHash> - -struct SbkObjectType; - -namespace PySide -{ - -PYSIDE_API void init(PyObject *module); - -/** - * Hash function used to enable hash on objects not supported on native Qt library which has toString function. - */ -template<class T> -inline Py_ssize_t hash(const T& value) -{ - return qHash(value.toString()); -} - -/** - * Fill QObject properties and do signal connections using the values found in \p kwds dictonary. - * \param qObj PyObject fot the QObject. - * \param metaObj QMetaObject of \p qObj. - * \param blackList keys to be ignored in kwds dictionary, this string list MUST be sorted. - * \param blackListSize numbe rof elements in blackList. - * \param kwds key->value dictonary. - * \return True if everything goes well, false with a Python error setted otherwise. - */ -PYSIDE_API bool fillQtProperties(PyObject *qObj, const QMetaObject *metaObj, PyObject *kwds, const char **blackList, unsigned int blackListSize); - -/** -* If the type \p T was registered on Qt meta type system with Q_DECLARE_METATYPE macro, this class will initialize -* the meta type. -* -* Initialize a meta type means register it on Qt meta type system, Qt itself only do this on the first call of -* qMetaTypeId, and this is exactly what we do to init it. If we don't do that, calls to QMetaType::type("QMatrix2x2") -* could return zero, causing QVariant to not recognize some C++ types, like QMatrix2x2. -*/ -template<typename T, bool OK = QMetaTypeId<T>::Defined > -struct initQtMetaType { - initQtMetaType() - { - qMetaTypeId<T>(); - } -}; - -// Template specialization to do nothing when the type wasn't registered on Qt meta type system. -template<typename T> -struct initQtMetaType<T, false> { -}; - -PYSIDE_API void initDynamicMetaObject(SbkObjectType *type, const QMetaObject *base, - std::size_t cppObjSize); -PYSIDE_API void initQObjectSubType(SbkObjectType *type, PyObject *args, PyObject *kwds); -PYSIDE_API void initQApp(); - -/// Return the size in bytes of a type that inherits QObject. -PYSIDE_API std::size_t getSizeOfQObject(SbkObjectType *type); - -typedef void (*CleanupFunction)(void); - -/** - * Register a function to be called before python die - */ -PYSIDE_API void registerCleanupFunction(CleanupFunction func); -PYSIDE_API void runCleanupFunctions(); - -/** - * Destroy a QCoreApplication taking care of destroy all instances of QObject first. - */ -PYSIDE_API void destroyQCoreApplication(); - -/** - * Check for properties and signals registered on MetaObject and return these - * \param cppSelf Is the QObject which contains the metaobject - * \param self Python object of cppSelf - * \param name Name of the argument which the function will try retrieve from MetaData - * \return The Python object which contains the Data obtained in metaObject or the Python attribute related with name - */ -PYSIDE_API PyObject *getMetaDataFromQObject(QObject *cppSelf, PyObject *self, PyObject *name); - -/** - * Check if self inherits from class_name - * \param self Python object - * \param class_name strict with the class name - * \return Returns true if self object inherits from class_name, otherwise returns false - */ -PYSIDE_API bool inherits(PyTypeObject *self, const char *class_name); - -PYSIDE_API void *nextQObjectMemoryAddr(); -PYSIDE_API void setNextQObjectMemoryAddr(void *addr); - -PYSIDE_API PyObject *getWrapperForQObject(QObject *cppSelf, SbkObjectType *sbk_type); - -#ifdef PYSIDE_QML_SUPPORT -// Used by QtQuick module to notify QtQml that custom QtQuick items can be registered. -using QuickRegisterItemFunction = - bool (*)(PyObject *pyObj, const char *uri, int versionMajor, - int versionMinor, const char *qmlName, - bool creatable, const char *noCreationReason, - QQmlPrivate::RegisterType *); -PYSIDE_API QuickRegisterItemFunction getQuickRegisterItemFunction(); -PYSIDE_API void setQuickRegisterItemFunction(QuickRegisterItemFunction function); -#endif // PYSIDE_QML_SUPPORT - -/** - * Given A PyObject repesenting ASCII or Unicode data, returns an equivalent QString. - */ -PYSIDE_API QString pyStringToQString(PyObject *str); - -/** - * Registers a dynamic "qt.conf" file with the Qt resource system. - * - * This is used in a standalone build, to inform QLibraryInfo of the Qt prefix (where Qt libraries - * are installed) so that plugins can be successfully loaded. - */ -PYSIDE_API bool registerInternalQtConf(); - - -} //namespace PySide - - -#endif // PYSIDE_H diff --git a/sources/pyside2/libpyside/pyside2.pc.in b/sources/pyside2/libpyside/pyside2.pc.in deleted file mode 100644 index 0653006f3..000000000 --- a/sources/pyside2/libpyside/pyside2.pc.in +++ /dev/null @@ -1,15 +0,0 @@ -prefix=@CMAKE_INSTALL_PREFIX@ -exec_prefix=@CMAKE_INSTALL_PREFIX@ -libdir=@LIB_INSTALL_DIR@ -includedir=@CMAKE_INSTALL_PREFIX@/include/PySide2@pyside2_SUFFIX@ -typesystemdir=@CMAKE_INSTALL_PREFIX@/share/PySide2@pyside2_SUFFIX@/typesystems -gluedir=@CMAKE_INSTALL_PREFIX@/share/PySide2@pyside2_SUFFIX@/glue -pythonpath=@PYTHON_SITE_PACKAGES@ - -Name: PySide2@pyside2_SUFFIX@ -Description: Support library for Python bindings of Qt5-based libraries. -Version: @BINDING_API_VERSION_FULL@ -Libs: -L${libdir} -lpyside2@pyside2_SUFFIX@@SHIBOKEN_PYTHON_CONFIG_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@ -Cflags: -I${includedir} -Requires: shiboken6 - diff --git a/sources/pyside2/libpyside/pyside_p.h b/sources/pyside2/libpyside/pyside_p.h deleted file mode 100644 index 1084a40a1..000000000 --- a/sources/pyside2/libpyside/pyside_p.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_P_H -#define PYSIDE_P_H - -#include <pysidemacros.h> - -#include <dynamicqmetaobject.h> - -struct SbkObjectType; - -namespace PySide -{ - -// Struct associated with QObject's via Shiboken::Object::getTypeUserData() -struct TypeUserData -{ - explicit TypeUserData(PyTypeObject* type, const QMetaObject* metaobject, std::size_t size) : - mo(type, metaobject), cppObjSize(size) {} - - MetaObjectBuilder mo; - std::size_t cppObjSize; -}; - -TypeUserData *retrieveTypeUserData(SbkObjectType *sbkTypeObj); -TypeUserData *retrieveTypeUserData(PyTypeObject *pyTypeObj); -TypeUserData *retrieveTypeUserData(PyObject *pyObj); -// For QML -PYSIDE_API const QMetaObject *retrieveMetaObject(PyTypeObject *pyTypeObj); -PYSIDE_API const QMetaObject *retrieveMetaObject(PyObject *pyObj); - -} //namespace PySide - -#endif // PYSIDE_P_H diff --git a/sources/pyside2/libpyside/pysideclassinfo.cpp b/sources/pyside2/libpyside/pysideclassinfo.cpp deleted file mode 100644 index aa47f97c1..000000000 --- a/sources/pyside2/libpyside/pysideclassinfo.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include <sbkpython.h> - -#include "pysideclassinfo.h" -#include "pyside_p.h" -#include "pysideclassinfo_p.h" -#include "dynamicqmetaobject.h" - -#include <shiboken.h> -#include <signature.h> - -extern "C" -{ - -static PyObject *classInfoTpNew(PyTypeObject *subtype, PyObject *args, PyObject *kwds); -static int classInfoTpInit(PyObject *, PyObject *, PyObject *); -static void classInfoFree(void *); -static PyObject *classCall(PyObject *, PyObject *, PyObject *); - -static PyType_Slot PySideClassInfoType_slots[] = { - {Py_tp_call, (void *)classCall}, - {Py_tp_init, (void *)classInfoTpInit}, - {Py_tp_new, (void *)classInfoTpNew}, - {Py_tp_free, (void *)classInfoFree}, - {Py_tp_dealloc, (void *)Sbk_object_dealloc}, - {0, 0} -}; -static PyType_Spec PySideClassInfoType_spec = { - "2:PySide2.QtCore.ClassInfo", - sizeof(PySideClassInfo), - 0, - Py_TPFLAGS_DEFAULT, - PySideClassInfoType_slots, -}; - - -PyTypeObject *PySideClassInfoTypeF(void) -{ - static PyTypeObject *type = - reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideClassInfoType_spec)); - return type; -} - -PyObject *classCall(PyObject *self, PyObject *args, PyObject * /* kw */) -{ - if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) { - PyErr_Format(PyExc_TypeError, - "The ClassInfo decorator takes exactly 1 positional argument (%zd given)", - PyTuple_Size(args)); - return 0; - } - - PySideClassInfo *data = reinterpret_cast<PySideClassInfo *>(self); - PySideClassInfoPrivate *pData = data->d; - - if (pData->m_alreadyWrapped) { - PyErr_SetString(PyExc_TypeError, "This instance of ClassInfo() was already used to wrap an object"); - return 0; - } - - PyObject *klass = PyTuple_GetItem(args, 0); - bool validClass = false; - - // This will sometimes segfault if you mistakenly use it on a function declaration - if (!PyType_Check(klass)) { - PyErr_SetString(PyExc_TypeError, "This decorator can only be used on class declarations"); - return 0; - } - - PyTypeObject *klassType = reinterpret_cast<PyTypeObject *>(klass); - if (Shiboken::ObjectType::checkType(klassType)) { - if (auto userData = PySide::retrieveTypeUserData(klassType)) { - PySide::MetaObjectBuilder &mo = userData->mo; - mo.addInfo(PySide::ClassInfo::getMap(data)); - pData->m_alreadyWrapped = true; - validClass = true; - } - } - - if (!validClass) { - PyErr_SetString(PyExc_TypeError, "This decorator can only be used on classes that are subclasses of QObject"); - return 0; - } - - Py_INCREF(klass); - return klass; -} - -static PyObject *classInfoTpNew(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */) -{ - PySideClassInfo *me = reinterpret_cast<PySideClassInfo *>(subtype->tp_alloc(subtype, 0)); - me->d = new PySideClassInfoPrivate; - - me->d->m_alreadyWrapped = false; - - return reinterpret_cast<PyObject *>(me); -} - -int classInfoTpInit(PyObject *self, PyObject *args, PyObject *kwds) -{ - if (PyTuple_Check(args) && PyTuple_Size(args) > 0) { - PyErr_Format(PyExc_TypeError, "ClassInfo() takes exactly 0 positional arguments (%zd given)", PyTuple_Size(args)); - return -1; - } - - PySideClassInfo *data = reinterpret_cast<PySideClassInfo *>(self); - PySideClassInfoPrivate *pData = data->d; - - PyObject *key; - PyObject *value; - Py_ssize_t pos = 0; - - // PyDict_Next causes a segfault if kwds is empty - if (kwds && PyDict_Check(kwds) && PyDict_Size(kwds) > 0) { - while (PyDict_Next(kwds, &pos, &key, &value)) { - if (Shiboken::String::check(key) && Shiboken::String::check(value)) { - pData->m_data[Shiboken::String::toCString(key)] = Shiboken::String::toCString(value); - } else { - PyErr_SetString(PyExc_TypeError, "All keys and values provided to ClassInfo() must be strings"); - return -1; - } - } - } - - return PyErr_Occurred() ? -1 : 0; -} - -void classInfoFree(void *self) -{ - auto pySelf = reinterpret_cast<PyObject *>(self); - auto data = reinterpret_cast<PySideClassInfo *>(self); - - delete data->d; - Py_TYPE(pySelf)->tp_base->tp_free(self); -} - - -} // extern "C" - - -namespace PySide { namespace ClassInfo { - -static const char *ClassInfo_SignatureStrings[] = { - "PySide2.QtCore.ClassInfo(**info:typing.Dict[str,str])", - nullptr}; // Sentinel - -void init(PyObject *module) -{ - if (InitSignatureStrings(PySideClassInfoTypeF(), ClassInfo_SignatureStrings) < 0) - return; - - Py_INCREF(PySideClassInfoTypeF()); - PyModule_AddObject(module, "ClassInfo", reinterpret_cast<PyObject *>(PySideClassInfoTypeF())); -} - -bool checkType(PyObject *pyObj) -{ - if (pyObj) - return PyType_IsSubtype(Py_TYPE(pyObj), PySideClassInfoTypeF()); - return false; -} - -QMap<QByteArray, QByteArray> getMap(PySideClassInfo *obj) -{ - return obj->d->m_data; -} - -} //namespace Property -} //namespace PySide diff --git a/sources/pyside2/libpyside/pysideclassinfo.h b/sources/pyside2/libpyside/pysideclassinfo.h deleted file mode 100644 index ff60b91c3..000000000 --- a/sources/pyside2/libpyside/pysideclassinfo.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_CLASSINFO_H -#define PYSIDE_CLASSINFO_H - -#include <pysidemacros.h> - -#include <sbkpython.h> - -#include <QtCore/QMap> -#include <QtCore/QByteArray> - -extern "C" -{ - extern PYSIDE_API PyTypeObject *PySideClassInfoTypeF(void); - - struct PySideClassInfoPrivate; - struct PYSIDE_API PySideClassInfo - { - PyObject_HEAD - PySideClassInfoPrivate* d; - }; -}; - -namespace PySide { namespace ClassInfo { - -PYSIDE_API bool checkType(PyObject* pyObj); -PYSIDE_API QMap<QByteArray, QByteArray> getMap(PySideClassInfo* obj); - -} //namespace ClassInfo -} //namespace PySide - -#endif diff --git a/sources/pyside2/libpyside/pysideclassinfo_p.h b/sources/pyside2/libpyside/pysideclassinfo_p.h deleted file mode 100644 index 021aa58e9..000000000 --- a/sources/pyside2/libpyside/pysideclassinfo_p.h +++ /dev/null @@ -1,70 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_CLASSINFO_P_H -#define PYSIDE_CLASSINFO_P_H - -#include <sbkpython.h> -#include <QMetaObject> -#include "pysideclassinfo.h" - -struct PySideClassInfo; - -extern "C" -{ - -struct PySideClassInfoPrivate { - QMap<QByteArray, QByteArray> m_data; - bool m_alreadyWrapped; -}; - -} // extern "C" - -namespace PySide { namespace ClassInfo { - -/** - * Init PySide QProperty support system - */ -void init(PyObject* module); - - -} // namespace ClassInfo -} // namespace PySide - -#endif diff --git a/sources/pyside2/libpyside/pysidemacros.h b/sources/pyside2/libpyside/pysidemacros.h deleted file mode 100644 index fcdfe3c6e..000000000 --- a/sources/pyside2/libpyside/pysidemacros.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef PYSIDEMACROS_H -#define PYSIDEMACROS_H - -#include <shibokenmacros.h> - -#define PYSIDE_EXPORT LIBSHIBOKEN_EXPORT -#define PYSIDE_IMPORT LIBSHIBOKEN_IMPORT -#define PYSIDE_DEPRECATED(func) SBK_DEPRECATED(func) - -#ifdef BUILD_LIBPYSIDE -# define PYSIDE_API PYSIDE_EXPORT -#else -# define PYSIDE_API PYSIDE_IMPORT -#endif - -#endif // PYSIDEMACROS_H diff --git a/sources/pyside2/libpyside/pysidemetafunction.cpp b/sources/pyside2/libpyside/pysidemetafunction.cpp deleted file mode 100644 index 96ed953b6..000000000 --- a/sources/pyside2/libpyside/pysidemetafunction.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "pysidemetafunction.h" -#include "pysidemetafunction_p.h" - -#include <shiboken.h> -#include <signature.h> - -#include <QtCore/QMetaMethod> - -extern "C" -{ - -struct PySideMetaFunctionPrivate -{ - QObject *qobject; - int methodIndex; -}; - -//methods -static void functionFree(void *); -static PyObject *functionCall(PyObject *, PyObject *, PyObject *); - -static PyType_Slot PySideMetaFunctionType_slots[] = { - {Py_tp_call, (void *)functionCall}, - {Py_tp_new, (void *)PyType_GenericNew}, - {Py_tp_free, (void *)functionFree}, - {Py_tp_dealloc, (void *)Sbk_object_dealloc}, - {0, 0} -}; -static PyType_Spec PySideMetaFunctionType_spec = { - "2:PySide2.QtCore.MetaFunction", - sizeof(PySideMetaFunction), - 0, - Py_TPFLAGS_DEFAULT, - PySideMetaFunctionType_slots, -}; - - -PyTypeObject *PySideMetaFunctionTypeF(void) -{ - static PyTypeObject *type = reinterpret_cast<PyTypeObject *>( - SbkType_FromSpec(&PySideMetaFunctionType_spec)); - return type; -} - -void functionFree(void *self) -{ - PySideMetaFunction *function = reinterpret_cast<PySideMetaFunction *>(self); - delete function->d; -} - -PyObject *functionCall(PyObject *self, PyObject *args, PyObject * /* kw */) -{ - PySideMetaFunction *function = reinterpret_cast<PySideMetaFunction *>(self); - - PyObject *retVal; - if (!PySide::MetaFunction::call(function->d->qobject, function->d->methodIndex, args, &retVal)) - return 0; - return retVal; -} - -} // extern "C" - -namespace PySide { namespace MetaFunction { - -static const char *MetaFunction_SignatureStrings[] = { - "PySide2.QtCore.MetaFunction.__call__(*args:typing.Any)->typing.Any", - nullptr}; // Sentinel - -void init(PyObject *module) -{ - if (InitSignatureStrings(PySideMetaFunctionTypeF(), MetaFunction_SignatureStrings) < 0) - return; - - Py_INCREF(PySideMetaFunctionTypeF()); - PyModule_AddObject(module, "MetaFunction", reinterpret_cast<PyObject *>(PySideMetaFunctionTypeF())); -} - -PySideMetaFunction *newObject(QObject *source, int methodIndex) -{ - if (methodIndex >= source->metaObject()->methodCount()) - return 0; - - QMetaMethod method = source->metaObject()->method(methodIndex); - if ((method.methodType() == QMetaMethod::Slot) || - (method.methodType() == QMetaMethod::Method)) { - PySideMetaFunction *function = PyObject_New(PySideMetaFunction, PySideMetaFunctionTypeF()); - function->d = new PySideMetaFunctionPrivate(); - function->d->qobject = source; - function->d->methodIndex = methodIndex; - return function; - } - return 0; -} - -bool call(QObject *self, int methodIndex, PyObject *args, PyObject **retVal) -{ - - QMetaMethod method = self->metaObject()->method(methodIndex); - QList<QByteArray> argTypes = method.parameterTypes(); - - // args given plus return type - Shiboken::AutoDecRef sequence(PySequence_Fast(args, 0)); - int numArgs = PySequence_Fast_GET_SIZE(sequence.object()) + 1; - - if (numArgs - 1 > argTypes.count()) { - PyErr_Format(PyExc_TypeError, "%s only accepts %d argument(s), %d given!", - method.methodSignature().constData(), - argTypes.count(), numArgs - 1); - return false; - } - - if (numArgs - 1 < argTypes.count()) { - PyErr_Format(PyExc_TypeError, "%s needs %d argument(s), %d given!", - method.methodSignature().constData(), - argTypes.count(), numArgs - 1); - return false; - } - - QVariant *methValues = new QVariant[numArgs]; - void **methArgs = new void *[numArgs]; - - // Prepare room for return type - const char *returnType = method.typeName(); - if (returnType && std::strcmp("void", returnType)) - argTypes.prepend(returnType); - else - argTypes.prepend(QByteArray()); - - int i; - for (i = 0; i < numArgs; ++i) { - const QByteArray &typeName = argTypes.at(i); - // This must happen only when the method hasn't return type. - if (typeName.isEmpty()) { - methArgs[i] = 0; - continue; - } - - Shiboken::Conversions::SpecificConverter converter(typeName); - if (converter) { - QMetaType metaType = QMetaType::fromName(typeName); - if (!Shiboken::Conversions::pythonTypeIsObjectType(converter)) { - if (!metaType.isValid()) { - PyErr_Format(PyExc_TypeError, "Value types used on meta functions (including signals) need to be " - "registered on meta type: %s", typeName.data()); - break; - } - methValues[i] = QVariant(metaType); - } - methArgs[i] = methValues[i].data(); - if (i == 0) // Don't do this for return type - continue; - if (metaType.id() == QMetaType::QString) { - QString tmp; - converter.toCpp(PySequence_Fast_GET_ITEM(sequence.object(), i - 1), &tmp); - methValues[i] = tmp; - } else { - converter.toCpp(PySequence_Fast_GET_ITEM(sequence.object(), i - 1), methArgs[i]); - } - } else { - PyErr_Format(PyExc_TypeError, "Unknown type used to call meta function (that may be a signal): %s", argTypes[i].constData()); - break; - } - } - - bool ok = i == numArgs; - if (ok) { - Py_BEGIN_ALLOW_THREADS - QMetaObject::metacall(self, QMetaObject::InvokeMetaMethod, method.methodIndex(), methArgs); - Py_END_ALLOW_THREADS - - if (retVal) { - if (methArgs[0]) { - static SbkConverter *qVariantTypeConverter = Shiboken::Conversions::getConverter("QVariant"); - Q_ASSERT(qVariantTypeConverter); - *retVal = Shiboken::Conversions::copyToPython(qVariantTypeConverter, &methValues[0]); - } else { - *retVal = Py_None; - Py_INCREF(*retVal); - } - } - } - - delete[] methArgs; - delete[] methValues; - - return ok; -} - - -} //namespace MetaFunction -} //namespace PySide - diff --git a/sources/pyside2/libpyside/pysidemetafunction.h b/sources/pyside2/libpyside/pysidemetafunction.h deleted file mode 100644 index f7cc5307b..000000000 --- a/sources/pyside2/libpyside/pysidemetafunction.h +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_METAFUNCTION_H -#define PYSIDE_METAFUNCTION_H - -#include <pysidemacros.h> - -#include <sbkpython.h> - -#include <QtCore/QObject> - -extern "C" -{ - extern PYSIDE_API PyTypeObject *PySideMetaFunctionTypeF(void); - - struct PySideMetaFunctionPrivate; - struct PYSIDE_API PySideMetaFunction - { - PyObject_HEAD - PySideMetaFunctionPrivate *d; - }; -}; //extern "C" - -namespace PySide { namespace MetaFunction { - -/** - * This function creates a MetaFunction object - * - * @param obj the QObject witch this fuction is part of - * @param methodIndex The index of this function on MetaObject - * @return Return a new reference of PySideMetaFunction - **/ -PYSIDE_API PySideMetaFunction *newObject(QObject *obj, int methodIndex); - -} //namespace MetaFunction -} //namespace PySide - -#endif diff --git a/sources/pyside2/libpyside/pysidemetafunction_p.h b/sources/pyside2/libpyside/pysidemetafunction_p.h deleted file mode 100644 index c67233857..000000000 --- a/sources/pyside2/libpyside/pysidemetafunction_p.h +++ /dev/null @@ -1,62 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_METAFUNCTION_P_H -#define PYSIDE_METAFUNCTION_P_H - -#include <sbkpython.h> - -#include <QtCore/QtGlobal> - -QT_BEGIN_NAMESPACE -class QObject; -QT_END_NAMESPACE - -namespace PySide { namespace MetaFunction { - - void init(PyObject *module); - /** - * Does a Qt metacall on a QObject - */ - bool call(QObject *self, int methodIndex, PyObject *args, PyObject **retVal = nullptr); - -} //namespace MetaFunction -} //namespace PySide - -#endif diff --git a/sources/pyside2/libpyside/pysideproperty.cpp b/sources/pyside2/libpyside/pysideproperty.cpp deleted file mode 100644 index 30cfabf86..000000000 --- a/sources/pyside2/libpyside/pysideproperty.cpp +++ /dev/null @@ -1,634 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include <sbkpython.h> -#include "pysideproperty.h" -#include "pysideproperty_p.h" -#include "dynamicqmetaobject_p.h" -#include "pysidesignal.h" -#include "pysidesignal_p.h" - -#include <shiboken.h> -#include <signature.h> - -using namespace Shiboken; - -extern "C" -{ - -static PyObject *qpropertyTpNew(PyTypeObject *subtype, PyObject *args, PyObject *kwds); -static int qpropertyTpInit(PyObject *, PyObject *, PyObject *); -static void qpropertyDeAlloc(PyObject *self); - -//methods -static PyObject *qPropertyGetter(PyObject *, PyObject *); -static PyObject *qPropertySetter(PyObject *, PyObject *); -static PyObject *qPropertyResetter(PyObject *, PyObject *); -static PyObject *qPropertyDeleter(PyObject *, PyObject *); -static PyObject *qPropertyCall(PyObject *, PyObject *, PyObject *); -static int qpropertyTraverse(PyObject *self, visitproc visit, void *arg); -static int qpropertyClear(PyObject *self); - -// Attributes -static PyObject *qPropertyDocGet(PyObject *, void *); -static int qPropertyDocSet(PyObject *, PyObject *, void *); -static PyObject *qProperty_fget(PyObject *, void *); -static PyObject *qProperty_fset(PyObject *, void *); -static PyObject *qProperty_freset(PyObject *, void *); -static PyObject *qProperty_fdel(PyObject *, void *); - -static PyMethodDef PySidePropertyMethods[] = { - {"getter", (PyCFunction)qPropertyGetter, METH_O, 0}, - {"setter", (PyCFunction)qPropertySetter, METH_O, 0}, - {"resetter", (PyCFunction)qPropertyResetter, METH_O, 0}, - {"deleter", (PyCFunction)qPropertyDeleter, METH_O, 0}, - // Synonyms from Qt - {"read", (PyCFunction)qPropertyGetter, METH_O, 0}, - {"write", (PyCFunction)qPropertySetter, METH_O, 0}, - {0, 0, 0, 0} -}; - -static PyGetSetDef PySidePropertyType_getset[] = { - // Note: we could not use `PyMemberDef` like Python's properties, - // because of the indirection of PySidePropertyPrivate. - {const_cast<char *>("fget"), qProperty_fget, nullptr, nullptr, nullptr}, - {const_cast<char *>("fset"), qProperty_fset, nullptr, nullptr, nullptr}, - {const_cast<char *>("freset"), qProperty_freset, nullptr, nullptr, nullptr}, - {const_cast<char *>("fdel"), qProperty_fdel, nullptr, nullptr, nullptr}, - {const_cast<char *>("__doc__"), qPropertyDocGet, qPropertyDocSet, nullptr, nullptr}, - {nullptr, nullptr, nullptr, nullptr, nullptr} -}; - -static PyType_Slot PySidePropertyType_slots[] = { - {Py_tp_dealloc, (void *)qpropertyDeAlloc}, - {Py_tp_call, (void *)qPropertyCall}, - {Py_tp_traverse, (void *)qpropertyTraverse}, - {Py_tp_clear, (void *)qpropertyClear}, - {Py_tp_methods, (void *)PySidePropertyMethods}, - {Py_tp_init, (void *)qpropertyTpInit}, - {Py_tp_new, (void *)qpropertyTpNew}, - {Py_tp_getset, PySidePropertyType_getset}, - {0, 0} -}; -// Dotted modulename is crucial for SbkType_FromSpec to work. Is this name right? -static PyType_Spec PySidePropertyType_spec = { - "2:PySide2.QtCore.Property", - sizeof(PySideProperty), - 0, - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_HAVE_GC|Py_TPFLAGS_BASETYPE, - PySidePropertyType_slots, -}; - - -PyTypeObject *PySidePropertyTypeF(void) -{ - static PyTypeObject *type = reinterpret_cast<PyTypeObject *>( - SbkType_FromSpec(&PySidePropertyType_spec)); - return type; -} - -static void qpropertyMetaCall(PySideProperty *pp, PyObject *self, QMetaObject::Call call, void **args) -{ - Shiboken::Conversions::SpecificConverter converter(pp->d->typeName); - Q_ASSERT(converter); - - QByteArray type(pp->d->typeName); - - switch(call) { - case QMetaObject::ReadProperty: - { - Shiboken::GilState gil; - PyObject *value = PySide::Property::getValue(pp, self); - if (value) { - converter.toCpp(value, args[0]); - Py_DECREF(value); - } - break; - } - - case QMetaObject::WriteProperty: - { - Shiboken::GilState gil; - Shiboken::AutoDecRef value(converter.toPython(args[0])); - PySide::Property::setValue(pp, self, value); - break; - } - - case QMetaObject::ResetProperty: - { - Shiboken::GilState gil; - PySide::Property::reset(pp, self); - break; - } - - // just to avoid gcc warnings - case QMetaObject::BindableProperty: - case QMetaObject::InvokeMetaMethod: - case QMetaObject::CreateInstance: - case QMetaObject::IndexOfMethod: - case QMetaObject::RegisterPropertyMetaType: - case QMetaObject::RegisterMethodArgumentMetaType: - break; - } -} - - -static PyObject *qpropertyTpNew(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */) -{ - PySideProperty *me = reinterpret_cast<PySideProperty *>(subtype->tp_alloc(subtype, 0)); - me->d = new PySidePropertyPrivate; - return reinterpret_cast<PyObject *>(me); -} - -static int qpropertyTpInit(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *type = nullptr; - auto data = reinterpret_cast<PySideProperty *>(self); - PySidePropertyPrivate *pData = data->d; - pData->metaCallHandler = &qpropertyMetaCall; - - static const char *kwlist[] = {"type", "fget", "fset", "freset", "fdel", "doc", "notify", - "designable", "scriptable", "stored", - "user", "constant", "final", 0}; - char *doc{}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|OOOOsObbbbbb:QtCore.Property", - const_cast<char **>(kwlist), - /*OO*/ &type, &(pData->fget), - /*OOO*/ &(pData->fset), &(pData->freset), &(pData->fdel), - /*s*/ &doc, - /*O*/ &(pData->notify), - /*bbb*/ &(pData->designable), &(pData->scriptable), &(pData->stored), - /*bbb*/ &(pData->user), &(pData->constant), &(pData->final))) { - return -1; - } - - // PYSIDE-1019: Fetching the default `__doc__` from fget would fail for inherited functions - // because we don't initialize the mro with signatures (and we will not!). - // But it is efficient and in-time to do that on demand in qPropertyDocGet. - pData->getter_doc = false; - if (doc) - pData->doc = doc; - else - pData->doc.clear(); - - pData->typeName = PySide::Signal::getTypeName(type); - - if (pData->typeName.isEmpty()) - PyErr_SetString(PyExc_TypeError, "Invalid property type or type name."); - else if (pData->constant && (pData->fset || pData->notify)) - PyErr_SetString(PyExc_TypeError, "A constant property cannot have a WRITE method or a NOTIFY signal."); - - if (!PyErr_Occurred()) { - Py_XINCREF(pData->fget); - Py_XINCREF(pData->fset); - Py_XINCREF(pData->freset); - Py_XINCREF(pData->fdel); - Py_XINCREF(pData->notify); - return 0; - } - pData->fget = nullptr; - pData->fset = nullptr; - pData->freset = nullptr; - pData->fdel = nullptr; - pData->notify = nullptr; - return -1; -} - -static void qpropertyDeAlloc(PyObject *self) -{ - qpropertyClear(self); - if (PepRuntime_38_flag) { - // PYSIDE-939: Handling references correctly. - // This was not needed before Python 3.8 (Python issue 35810) - Py_DECREF(Py_TYPE(self)); - } - Py_TYPE(self)->tp_free(self); -} - -static PyObject * -_property_copy(PyObject *old, PyObject *get, PyObject *set, PyObject *reset, PyObject *del) -{ - PySideProperty *pold = reinterpret_cast<PySideProperty *>(old); - PySidePropertyPrivate *pData = pold->d; - - AutoDecRef type(PyObject_Type(old)); - QByteArray doc{}; - if (type.isNull()) - return nullptr; - - if (get == nullptr || get == Py_None) { - Py_XDECREF(get); - get = pData->fget ? pData->fget : Py_None; - } - if (set == nullptr || set == Py_None) { - Py_XDECREF(set); - set = pData->fset ? pData->fset : Py_None; - } - if (reset == nullptr || reset == Py_None) { - Py_XDECREF(reset); - reset = pData->freset ? pData->freset : Py_None; - } - if (del == nullptr || del == Py_None) { - Py_XDECREF(del); - del = pData->fdel ? pData->fdel : Py_None; - } - if (pData->getter_doc && get != Py_None) { - /* make _init use __doc__ from getter */ - doc = ""; - } - else { - doc = !pData->doc.isEmpty() ? pData->doc : ""; - } - auto notify = pData->notify ? pData->notify : Py_None; - - PyObject *typeName = String::fromCString(pData->typeName); - PyObject *obNew = PyObject_CallFunction(type, const_cast<char *>("OOOOOsO" "bbb" "bbb"), - typeName, get, set, reset, del, doc.data(), notify, - pData->designable, pData->scriptable, pData->stored, - pData->user, pData->constant, pData->final); - - return obNew; -} - -static PyObject *qPropertyGetter(PyObject *self, PyObject *getter) -{ - return _property_copy(self, getter, nullptr, nullptr, nullptr); -} - -static PyObject *qPropertySetter(PyObject *self, PyObject *setter) -{ - return _property_copy(self, nullptr, setter, nullptr, nullptr); -} - -static PyObject *qPropertyResetter(PyObject *self, PyObject *resetter) -{ - return _property_copy(self, nullptr, nullptr, resetter, nullptr); -} - -static PyObject *qPropertyDeleter(PyObject *self, PyObject *deleter) -{ - return _property_copy(self, nullptr, nullptr, nullptr, deleter); -} - -static PyObject *qPropertyCall(PyObject *self, PyObject *args, PyObject * /* kw */) -{ - PyObject *getter = PyTuple_GetItem(args, 0); - return _property_copy(self, getter, nullptr, nullptr, nullptr); -} - -// PYSIDE-1019: Provide the same getters as Pythons `PyProperty`. - -static PyObject *qProperty_fget(PyObject *self, void *) -{ - auto func = reinterpret_cast<PySideProperty *>(self)->d->fget; - auto ret = func != nullptr ? func : Py_None; - Py_INCREF(ret); - return ret; -} - -static PyObject *qProperty_fset(PyObject *self, void *) -{ - auto func = reinterpret_cast<PySideProperty *>(self)->d->fset; - auto ret = func != nullptr ? func : Py_None; - Py_INCREF(ret); - return ret; -} - -static PyObject *qProperty_freset(PyObject *self, void *) -{ - auto func = reinterpret_cast<PySideProperty *>(self)->d->freset; - auto ret = func != nullptr ? func : Py_None; - Py_INCREF(ret); - return ret; -} - -static PyObject *qProperty_fdel(PyObject *self, void *) -{ - auto func = reinterpret_cast<PySideProperty *>(self)->d->fdel; - auto ret = func != nullptr ? func : Py_None; - Py_INCREF(ret); - return ret; -} - -static PyObject *qPropertyDocGet(PyObject *self, void *) -{ - auto data = reinterpret_cast<PySideProperty *>(self); - PySidePropertyPrivate *pData = data->d; - - QByteArray doc(pData->doc); - if (!doc.isEmpty()) - return PyUnicode_FromString(doc); - if (pData->fget != nullptr) { - // PYSIDE-1019: Fetch the default `__doc__` from fget. We do it late. - AutoDecRef get_doc(PyObject_GetAttr(pData->fget, PyMagicName::doc())); - if (!get_doc.isNull()) { - pData->doc = String::toCString(get_doc); - pData->getter_doc = true; - if (Py_TYPE(self) == PySidePropertyTypeF()) - return qPropertyDocGet(self, nullptr); - /* - * If this is a property subclass, put __doc__ in dict of the - * subclass instance instead, otherwise it gets shadowed by - * __doc__ in the class's dict. - */ - auto get_doc_obj = get_doc.object(); - int err = PyObject_SetAttr(self, PyMagicName::doc(), get_doc); - return err < 0 ? nullptr : (Py_INCREF(get_doc_obj), get_doc_obj); - } - PyErr_Clear(); - } - Py_RETURN_NONE; -} - -static int qPropertyDocSet(PyObject *self, PyObject *value, void *) -{ - auto data = reinterpret_cast<PySideProperty *>(self); - PySidePropertyPrivate *pData = data->d; - - if (String::check(value)) { - pData->doc = String::toCString(value); - return 0; - } - PyErr_SetString(PyExc_TypeError, "String argument expected."); - return -1; -} - -static int qpropertyTraverse(PyObject *self, visitproc visit, void *arg) -{ - PySidePropertyPrivate *data = reinterpret_cast<PySideProperty *>(self)->d; - if (!data) - return 0; - - Py_VISIT(data->fget); - Py_VISIT(data->fset); - Py_VISIT(data->freset); - Py_VISIT(data->fdel); - Py_VISIT(data->notify); - return 0; -} - -static int qpropertyClear(PyObject *self) -{ - PySidePropertyPrivate *data = reinterpret_cast<PySideProperty *>(self)->d; - if (!data) - return 0; - - Py_CLEAR(data->fget); - Py_CLEAR(data->fset); - Py_CLEAR(data->freset); - Py_CLEAR(data->fdel); - Py_CLEAR(data->notify); - - - delete data; - reinterpret_cast<PySideProperty *>(self)->d = nullptr; - return 0; -} - -} // extern "C" - -namespace { - -static PyObject *getFromType(PyTypeObject *type, PyObject *name) -{ - PyObject *attr = nullptr; - attr = PyDict_GetItem(type->tp_dict, name); - if (!attr) { - PyObject *bases = type->tp_bases; - int size = PyTuple_GET_SIZE(bases); - for(int i=0; i < size; i++) { - PyObject *base = PyTuple_GET_ITEM(bases, i); - attr = getFromType(reinterpret_cast<PyTypeObject *>(base), name); - if (attr) - return attr; - } - } - return attr; -} - -} //namespace - - -namespace PySide { namespace Property { - -static const char *Property_SignatureStrings[] = { - "PySide2.QtCore.Property(self,type:type,fget:typing.Callable=None,fset:typing.Callable=None," - "freset:typing.Callable=None,fdel:typing.Callable=None,doc:str=None," - "notify:typing.Callable=None,designable:bool=True,scriptable:bool=True," - "stored:bool=True,user:bool=False,constant:bool=False,final:bool=False)" - "->PySide2.QtCore.Property", - "PySide2.QtCore.Property.deleter(self,func:typing.Callable)", - "PySide2.QtCore.Property.fdel(self)->typing.Callable", - "PySide2.QtCore.Property.fget(self)->typing.Callable", - "PySide2.QtCore.Property.freset(self)->typing.Callable", - "PySide2.QtCore.Property.fset(self)->typing.Callable", - "PySide2.QtCore.Property.getter(self,func:typing.Callable)", - "PySide2.QtCore.Property.read(self,func:typing.Callable)", - "PySide2.QtCore.Property.setter(self,func:typing.Callable)", - "PySide2.QtCore.Property.write(self,func:typing.Callable)", - nullptr}; // Sentinel - -void init(PyObject *module) -{ - if (InitSignatureStrings(PySidePropertyTypeF(), Property_SignatureStrings) < 0) - return; - - Py_INCREF(PySidePropertyTypeF()); - PyModule_AddObject(module, "Property", reinterpret_cast<PyObject *>(PySidePropertyTypeF())); -} - -bool checkType(PyObject *pyObj) -{ - if (pyObj) { - return PyType_IsSubtype(Py_TYPE(pyObj), PySidePropertyTypeF()); - } - return false; -} - -int setValue(PySideProperty *self, PyObject *source, PyObject *value) -{ - PyObject *fset = self->d->fset; - if (fset && value) { - Shiboken::AutoDecRef args(PyTuple_New(2)); - PyTuple_SET_ITEM(args, 0, source); - PyTuple_SET_ITEM(args, 1, value); - Py_INCREF(source); - Py_INCREF(value); - Shiboken::AutoDecRef result(PyObject_CallObject(fset, args)); - return (result.isNull() ? -1 : 0); - } - PyObject *fdel = self->d->fdel; - if (fdel) { - Shiboken::AutoDecRef args(PyTuple_New(1)); - PyTuple_SET_ITEM(args, 0, source); - Py_INCREF(source); - Shiboken::AutoDecRef result(PyObject_CallObject(fdel, args)); - return (result.isNull() ? -1 : 0); - } - PyErr_SetString(PyExc_AttributeError, "Attibute read only"); - return -1; -} - -PyObject *getValue(PySideProperty *self, PyObject *source) -{ - PyObject *fget = self->d->fget; - if (fget) { - Shiboken::AutoDecRef args(PyTuple_New(1)); - Py_INCREF(source); - PyTuple_SET_ITEM(args, 0, source); - return PyObject_CallObject(fget, args); - } - return 0; -} - -int reset(PySideProperty *self, PyObject *source) -{ - PyObject *freset = self->d->freset; - if (freset) { - Shiboken::AutoDecRef args(PyTuple_New(1)); - Py_INCREF(source); - PyTuple_SET_ITEM(args, 0, source); - Shiboken::AutoDecRef result(PyObject_CallObject(freset, args)); - return (result.isNull() ? -1 : 0); - } - return -1; -} - -const char *getTypeName(const PySideProperty *self) -{ - return self->d->typeName; -} - -PySideProperty *getObject(PyObject *source, PyObject *name) -{ - PyObject *attr = nullptr; - - attr = getFromType(Py_TYPE(source), name); - if (attr && checkType(attr)) { - Py_INCREF(attr); - return reinterpret_cast<PySideProperty *>(attr); - } - - if (!attr) - PyErr_Clear(); //Clear possible error caused by PyObject_GenericGetAttr - - return 0; -} - -bool isReadable(const PySideProperty * /* self */) -{ - return true; -} - -bool isWritable(const PySideProperty *self) -{ - return (self->d->fset != 0); -} - -bool hasReset(const PySideProperty *self) -{ - return (self->d->freset != 0); -} - -bool isDesignable(const PySideProperty *self) -{ - return self->d->designable; -} - -bool isScriptable(const PySideProperty *self) -{ - return self->d->scriptable; -} - -bool isStored(const PySideProperty *self) -{ - return self->d->stored; -} - -bool isUser(const PySideProperty *self) -{ - return self->d->user; -} - -bool isConstant(const PySideProperty *self) -{ - return self->d->constant; -} - -bool isFinal(const PySideProperty *self) -{ - return self->d->final; -} - -const char *getNotifyName(PySideProperty *self) -{ - if (self->d->notifySignature.isEmpty()) { - PyObject *str = PyObject_Str(self->d->notify); - self->d->notifySignature = Shiboken::String::toCString(str); - Py_DECREF(str); - } - - return self->d->notifySignature.isEmpty() - ? nullptr : self->d->notifySignature.constData(); -} - -void setMetaCallHandler(PySideProperty *self, MetaCallHandler handler) -{ - self->d->metaCallHandler = handler; -} - -void setTypeName(PySideProperty *self, const char *typeName) -{ - self->d->typeName = typeName; -} - -void setUserData(PySideProperty *self, void *data) -{ - self->d->userData = data; -} - -void *userData(PySideProperty *self) -{ - return self->d->userData; -} - -} //namespace Property -} //namespace PySide diff --git a/sources/pyside2/libpyside/pysideproperty.h b/sources/pyside2/libpyside/pysideproperty.h deleted file mode 100644 index 4a467b186..000000000 --- a/sources/pyside2/libpyside/pysideproperty.h +++ /dev/null @@ -1,116 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_PROPERTY_H -#define PYSIDE_PROPERTY_H - -#include <pysidemacros.h> - -#include <sbkpython.h> - -#include <QtCore/QMetaObject> - -extern "C" -{ - extern PYSIDE_API PyTypeObject *PySidePropertyTypeF(void); - - struct PySidePropertyPrivate; - struct PYSIDE_API PySideProperty - { - PyObject_HEAD - PySidePropertyPrivate* d; - }; -}; - -namespace PySide { namespace Property { - -typedef void (*MetaCallHandler)(PySideProperty*,PyObject*,QMetaObject::Call, void**); - -PYSIDE_API bool checkType(PyObject *pyObj); - -/** - * This function call set property function and pass value as arg - * This function does not check the property object type - * - * @param self The property object - * @param source The QObject witch has the property - * @param value The value to set in property - * @return Return 0 if ok or -1 if this function fail - **/ -PYSIDE_API int setValue(PySideProperty *self, PyObject *source, PyObject *value); - -/** - * This function call get property function - * This function does not check the property object type - * - * @param self The property object - * @param source The QObject witch has the property - * @return Return the result of property get function or 0 if this fail - **/ -PYSIDE_API PyObject *getValue(PySideProperty *self, PyObject *source); - -/** - * This function return the notify name used on this property - * - * @param self The property object - * @return Return a const char with the notify name used - **/ -PYSIDE_API const char *getNotifyName(PySideProperty *self); - - -/** - * This function search in the source object for desired property - * - * @param source The QObject object - * @param name The property name - * @return Return a new reference to property object - **/ -PYSIDE_API PySideProperty *getObject(PyObject *source, PyObject *name); - -PYSIDE_API void setMetaCallHandler(PySideProperty *self, MetaCallHandler handler); - -PYSIDE_API void setTypeName(PySideProperty *self, const char *typeName); - -PYSIDE_API void setUserData(PySideProperty *self, void *data); -PYSIDE_API void* userData(PySideProperty *self); - -} //namespace Property -} //namespace PySide - -#endif diff --git a/sources/pyside2/libpyside/pysideproperty_p.h b/sources/pyside2/libpyside/pysideproperty_p.h deleted file mode 100644 index e7b6e4d77..000000000 --- a/sources/pyside2/libpyside/pysideproperty_p.h +++ /dev/null @@ -1,182 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_QPROPERTY_P_H -#define PYSIDE_QPROPERTY_P_H - -#include <sbkpython.h> -#include <QtCore/QByteArray> -#include <QMetaObject> -#include "pysideproperty.h" - -struct PySideProperty; - -struct PySidePropertyPrivate -{ - QByteArray typeName; - PySide::Property::MetaCallHandler metaCallHandler = nullptr; - PyObject *fget = nullptr; - PyObject *fset = nullptr; - PyObject *freset = nullptr; - PyObject *fdel = nullptr; - PyObject *notify = nullptr; - bool getter_doc = false; - QByteArray notifySignature; - QByteArray doc; - bool designable = true; - bool scriptable = true; - bool stored = true; - bool user = false; - bool constant = false; - bool final = false; - void *userData = nullptr; -}; - -namespace PySide { namespace Property { - -/** - * Init PySide QProperty support system - */ -void init(PyObject* module); - -/** - * This function call reset property function - * This function does not check the property object type - * - * @param self The property object - * @param source The QObject witch has the property - * @return Return 0 if ok or -1 if this function fail - **/ -int reset(PySideProperty* self, PyObject* source); - - -/** - * This function return the property type - * This function does not check the property object type - * - * @param self The property object - * @return Return the property type name - **/ -const char* getTypeName(const PySideProperty* self); - -/** - * This function check if property has read function - * This function does not check the property object type - * - * @param self The property object - * @return Return a boolean value - **/ -bool isReadable(const PySideProperty* self); - -/** - * This function check if property has write function - * This function does not check the property object type - * - * @param self The property object - * @return Return a boolean value - **/ -bool isWritable(const PySideProperty* self); - -/** - * This function check if property has reset function - * This function does not check the property object type - * - * @param self The property object - * @return Return a boolean value - **/ -bool hasReset(const PySideProperty* self); - -/** - * This function check if property has the flag DESIGNABLE setted - * This function does not check the property object type - * - * @param self The property object - * @return Return a boolean value - **/ -bool isDesignable(const PySideProperty* self); - -/** - * This function check if property has the flag SCRIPTABLE setted - * This function does not check the property object type - * - * @param self The property object - * @return Return a boolean value - **/ -bool isScriptable(const PySideProperty* self); - -/** - * This function check if property has the flag STORED setted - * This function does not check the property object type - * - * @param self The property object - * @return Return a boolean value - **/ -bool isStored(const PySideProperty* self); - -/** - * This function check if property has the flag USER setted - * This function does not check the property object type - * - * @param self The property object - * @return Return a boolean value - **/ -bool isUser(const PySideProperty* self); - -/** - * This function check if property has the flag CONSTANT setted - * This function does not check the property object type - * - * @param self The property object - * @return Return a boolean value - **/ -bool isConstant(const PySideProperty* self); - -/** - * This function check if property has the flag FINAL setted - * This function does not check the property object type - * - * @param self The property object - * @return Return a boolean value - **/ -bool isFinal(const PySideProperty* self); - -} // namespace Property -} // namespace PySide - -#endif diff --git a/sources/pyside2/libpyside/pysideqenum.cpp b/sources/pyside2/libpyside/pysideqenum.cpp deleted file mode 100644 index 07a548cb6..000000000 --- a/sources/pyside2/libpyside/pysideqenum.cpp +++ /dev/null @@ -1,258 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include <shiboken.h> - -#include "pysideqenum.h" -#include "dynamicqmetaobject.h" -#include "pyside_p.h" - - -/////////////////////////////////////////////////////////////// -// -// PYSIDE-957: Create QEnum dynamically from Python Enum -// -// -extern "C" { - -using namespace Shiboken; - -static PyObject *analyzePyEnum(PyObject *pyenum, PyObject *container = nullptr) -{ - /* - * This is the straight-forward implementation of QEnum/QFlag. It does no - * longer create an equivalent Qt enum but takes the Python enum as-is. - * - * It parses an Enum/Flag derived Python enum completely so that - * registering can be done without error checks. This would be impossible - * in MetaObjectBuilderPrivate::parsePythonType. - */ - AutoDecRef members(PyObject_GetAttr(pyenum, Shiboken::PyMagicName::members())); - if (members.isNull()) - return nullptr; - AutoDecRef items(PyMapping_Items(members)); - if (items.isNull()) - return nullptr; - int iflag = PySide::QEnum::isFlag(pyenum); - if (iflag < 0) - return nullptr; - Py_ssize_t nr_items = PySequence_Length(items); - if (nr_items < 0) - return nullptr; - - for (Py_ssize_t idx = 0; idx < nr_items; ++idx) { - AutoDecRef item(PySequence_GetItem(items, idx)); - if (item.isNull()) - return nullptr; - - // The item should be a 2-element sequence of the key name and an - // object containing the value. - AutoDecRef key(PySequence_GetItem(item, 0)); - AutoDecRef member(PySequence_GetItem(item, 1)); - if (key.isNull() || member.isNull()) - return nullptr; - if (!Shiboken::String::check(key)) { - // '%.200s' is the safety stringbuffer size of most CPython functions. - PyErr_Format(PyExc_TypeError, - "QEnum expected a string mapping as __members__, got '%.200s'", - Py_TYPE(key)->tp_name); - return nullptr; - } - - // Get the value. - AutoDecRef value(PyObject_GetAttr(member, Shiboken::PyName::value())); - if (value.isNull()) - return nullptr; - if (!PyInt_Check(value)) { // int/long cheating - PyErr_Format(PyExc_TypeError, - "QEnum expected an int value as '%.200s', got '%.200s'", - Shiboken::String::toCString(key), Py_TYPE(value)->tp_name); - return nullptr; - } - } - Py_RETURN_NONE; -} - -static Py_ssize_t get_lineno() -{ - PyObject *frame = reinterpret_cast<PyObject *>(PyEval_GetFrame()); // borrowed ref - AutoDecRef ob_lineno(PyObject_GetAttr(frame, Shiboken::PyName::f_lineno())); - if (ob_lineno.isNull() || !PyInt_Check(ob_lineno)) // int/long cheating - return -1; - return PyInt_AsSsize_t(ob_lineno); // int/long cheating -} - -static bool is_module_code() -{ - PyObject *frame = reinterpret_cast<PyObject *>(PyEval_GetFrame()); // borrowed ref - AutoDecRef ob_code(PyObject_GetAttr(frame, Shiboken::PyName::f_code())); - if (ob_code.isNull()) - return false; - AutoDecRef ob_name(PyObject_GetAttr(ob_code, Shiboken::PyName::co_name())); - if (ob_name.isNull()) - return false; - const char *codename = Shiboken::String::toCString(ob_name); - return strcmp(codename, "<module>") == 0; -} - -} // extern "C" - -namespace PySide { namespace QEnum { - -static std::map<int, PyObject *> enumCollector; - -int isFlag(PyObject *obType) -{ - /* - * Find out if this is an Enum or a Flag derived class. - * It checks also if things come from the enum module and if it is - * an Enum or Flag class at all. - * - * The function is called in MetaObjectBuilderPrivate::parsePythonType - * again to obtain the flag value. - */ - if (!PyType_Check(obType)) { - PyErr_Format(PyExc_TypeError, "a class argument was expected, not a '%.200s' instance", - Py_TYPE(obType)->tp_name); - return -1; - }; - auto *type = reinterpret_cast<PyTypeObject *>(obType); - PyObject *mro = type->tp_mro; - Py_ssize_t i, n = PyTuple_GET_SIZE(mro); - bool right_module = false; - bool have_enum = false; - bool have_flag = false; - bool have_members = PyObject_HasAttr(obType, PyMagicName::members()); - for (i = 0; i < n; i++) { - obType = PyTuple_GET_ITEM(mro, i); - type = reinterpret_cast<PyTypeObject *>(obType); - AutoDecRef mod(PyObject_GetAttr(obType, PyMagicName::module())); - QByteArray cmod = String::toCString(mod); - QByteArray cname = type->tp_name; - if (cmod == "enum") { - right_module = true; - if (cname == "Enum") - have_enum = true; - else if (cname == "Flag") - have_flag = true; - } - } - if (!right_module || !(have_enum || have_flag) || !have_members) { - PyErr_Format(PyExc_TypeError, "type %.200s does not inherit from 'Enum' or 'Flag'", - type->tp_name); - return -1; - } - return bool(have_flag); -} - -PyObject *QEnumMacro(PyObject *pyenum, bool flag) -{ - /* - * This is the official interface of 'QEnum'. It first calls 'analyzePyEnum'. - * When called as toplevel enum, it simply returns after some checks. - * Otherwise, 'pyenum' is stored for later use by the meta class registation. - */ - int computedFlag = isFlag(pyenum); - if (computedFlag < 0) - return nullptr; - if (bool(computedFlag) != flag) { - AutoDecRef name(PyObject_GetAttr(pyenum, PyMagicName::qualname())); - auto cname = String::toCString(name); - const char *e = "Enum"; - const char *f = "Flag"; - PyErr_Format(PyExc_TypeError, "expected '%s' but got '%s' (%.200s)", - flag ? f : e, flag ? e : f, cname); - return nullptr; - } - auto ok = analyzePyEnum(pyenum); - if (ok == nullptr) - return nullptr; - if (is_module_code()) { - // This is a toplevel enum which we resolve immediately. - Py_INCREF(pyenum); - return pyenum; - } - - Py_ssize_t lineno = get_lineno(); - if (lineno < 0) - return nullptr; - // Handle the rest via line number and the meta class. - Py_INCREF(pyenum); - Py_XDECREF(enumCollector[lineno]); - enumCollector[lineno] = pyenum; - Py_RETURN_NONE; -} - -std::vector<PyObject *> resolveDelayedQEnums(PyTypeObject *containerType) -{ - /* - * This is the internal interface of 'QEnum'. - * It is called at the end of the meta class call 'SbkObjectTypeTpNew' via - * MetaObjectBuilderPrivate::parsePythonType and resolves the collected - * Python Enum arguments. The result is then registered. - */ - if (enumCollector.empty()) - return {}; - PyObject *obContainerType = reinterpret_cast<PyObject *>(containerType); - Py_ssize_t lineno = get_lineno(); - - std::vector<PyObject *> result; - - auto it = enumCollector.begin(); - while (it != enumCollector.end()) { - int nr = it->first; - PyObject *pyenum = it->second; - if (nr >= lineno) { - AutoDecRef name(PyObject_GetAttr(pyenum, PyMagicName::name())); - if (name.isNull() || PyObject_SetAttr(obContainerType, name, pyenum) < 0) - return {}; - result.push_back(pyenum); - it = enumCollector.erase(it); - } else { - ++it; - } - } - return result; -} - -} // namespace Enum -} // namespace Shiboken - -// -/////////////////////////////////////////////////////////////// diff --git a/sources/pyside2/libpyside/pysideqenum.h b/sources/pyside2/libpyside/pysideqenum.h deleted file mode 100644 index fc4e55982..000000000 --- a/sources/pyside2/libpyside/pysideqenum.h +++ /dev/null @@ -1,57 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_QENUM_H -#define PYSIDE_QENUM_H - -#include <pysidemacros.h> -#include <vector> - -namespace PySide { namespace QEnum { - -// PYSIDE-957: Support the QEnum macro -PYSIDE_API PyObject *QEnumMacro(PyObject *, bool); -PYSIDE_API int isFlag(PyObject *); -PYSIDE_API std::vector<PyObject *> resolveDelayedQEnums(PyTypeObject *); -PYSIDE_API void init(); - -} // namespace QEnum -} // namespace PySide - -#endif diff --git a/sources/pyside2/libpyside/pysideqflags.cpp b/sources/pyside2/libpyside/pysideqflags.cpp deleted file mode 100644 index b07a73332..000000000 --- a/sources/pyside2/libpyside/pysideqflags.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "pysideqflags.h" - -#include <autodecref.h> -#include <sbkenum.h> - -extern "C" { - struct SbkConverter; - - struct PySideQFlagsTypePrivate - { - SbkConverter **converterPtr; - SbkConverter *converter; - }; - /** - * Type of all QFlags - */ - struct PySideQFlagsType - { - PyTypeObject type; - }; - - #define PYSIDE_QFLAGS(X) reinterpret_cast<PySideQFlagsObject *>(X) - - PyObject *PySideQFlagsNew(PyTypeObject *type, PyObject *args, PyObject * /* kwds */) - { - long val = 0; - if (PyTuple_GET_SIZE(args)) { - PyObject *arg = PyTuple_GET_ITEM(args, 0); - if (Shiboken::isShibokenEnum(arg)) {// faster call - val = Shiboken::Enum::getValue(arg); - } else if (PyNumber_Check(arg)) { - Shiboken::AutoDecRef number(PyNumber_Long(arg)); - val = PyLong_AsLong(number); - } else { - PyErr_SetString(PyExc_TypeError,"QFlags must be created using enums or numbers."); - return 0; - } - } - PySideQFlagsObject *self = PyObject_New(PySideQFlagsObject, type); - self->ob_value = val; - return reinterpret_cast<PyObject *>(self); - } - - static long getNumberValue(PyObject *v) - { - Shiboken::AutoDecRef number(PyNumber_Long(v)); - return PyLong_AsLong(number); - } - - static PyObject *qflag_int(PyObject *self) - { - return PyLong_FromLong(reinterpret_cast<PySideQFlagsObject*>(self)->ob_value); - } - - PyObject *PySideQFlagsRichCompare(PyObject *self, PyObject *other, int op) - { - int result = 0; - if (!PyNumber_Check(other)) { - PyErr_BadArgument(); - return NULL; - } - - long valA = PYSIDE_QFLAGS(self)->ob_value; - long valB = getNumberValue(other); - - if (self == other) { - result = 1; - } else { - switch (op) { - case Py_EQ: - result = (valA == valB); - break; - case Py_NE: - result = (valA != valB); - break; - case Py_LE: - result = (valA <= valB); - break; - case Py_GE: - result = (valA >= valB); - break; - case Py_LT: - result = (valA < valB); - break; - case Py_GT: - result = (valA > valB); - break; - default: - PyErr_BadArgument(); - return NULL; - } - } - if (result) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; - } -} - -namespace PySide -{ -namespace QFlags -{ - static PyType_Slot SbkNewQFlagsType_slots[] = { - {Py_nb_bool, 0}, - {Py_nb_invert, 0}, - {Py_nb_and, 0}, - {Py_nb_xor, 0}, - {Py_nb_or, 0}, - {Py_nb_int, reinterpret_cast<void*>(qflag_int)}, - {Py_nb_index, reinterpret_cast<void*>(qflag_int)}, - {Py_tp_new, (void *)PySideQFlagsNew}, - {Py_tp_richcompare, (void *)PySideQFlagsRichCompare}, - {Py_tp_dealloc, (void *)Sbk_object_dealloc}, - {0, 0} - }; - static PyType_Spec SbkNewQFlagsType_spec = { - "missing QFlags name", // to be inserted later - sizeof(PySideQFlagsObject), - 0, - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_CHECKTYPES, - SbkNewQFlagsType_slots, - }; - - PyTypeObject *create(const char *name, PyType_Slot numberMethods[]) - { - char qualname[200]; - // PYSIDE-747: Here we insert now the full class name. - strcpy(qualname, name); - // Careful: SbkType_FromSpec does not allocate the string. - PyType_Spec newspec; - newspec.name = strdup(qualname); - newspec.basicsize = SbkNewQFlagsType_spec.basicsize; - newspec.itemsize = SbkNewQFlagsType_spec.itemsize; - newspec.flags = SbkNewQFlagsType_spec.flags; - int idx = -1; - while (numberMethods[++idx].slot) { - assert(SbkNewQFlagsType_slots[idx].slot == numberMethods[idx].slot); - SbkNewQFlagsType_slots[idx].pfunc = numberMethods[idx].pfunc; - } - newspec.slots = SbkNewQFlagsType_spec.slots; - PyTypeObject *type = (PyTypeObject *)SbkType_FromSpec(&newspec); - Py_TYPE(type) = &PyType_Type; - - PySideQFlagsType *flagsType = reinterpret_cast<PySideQFlagsType *>(type); - PepType_PFTP(flagsType)->converterPtr = &PepType_PFTP(flagsType)->converter; - - if (PyType_Ready(type) < 0) - return 0; - - return type; - } - - PySideQFlagsObject *newObject(long value, PyTypeObject *type) - { - PySideQFlagsObject *qflags = PyObject_New(PySideQFlagsObject, type); - qflags->ob_value = value; - return qflags; - } - - long getValue(PySideQFlagsObject *self) - { - return self->ob_value; - } -} -} diff --git a/sources/pyside2/libpyside/pysideqflags.h b/sources/pyside2/libpyside/pysideqflags.h deleted file mode 100644 index 71f30808d..000000000 --- a/sources/pyside2/libpyside/pysideqflags.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_QFLAGS_H -#define PYSIDE_QFLAGS_H - -#include <sbkpython.h> -#include "pysidemacros.h" - - -extern "C" -{ - struct PYSIDE_API PySideQFlagsObject { - PyObject_HEAD - long ob_value; - }; - - PYSIDE_API PyObject* PySideQFlagsNew(PyTypeObject *type, PyObject *args, PyObject *kwds); - PYSIDE_API PyObject* PySideQFlagsRichCompare(PyObject *self, PyObject *other, int op); -} - - -namespace PySide -{ -namespace QFlags -{ - /** - * Creates a new QFlags type. - */ - PYSIDE_API PyTypeObject *create(const char* name, PyType_Slot *numberMethods); - /** - * Creates a new QFlags instance of type \p type and value \p value. - */ - PYSIDE_API PySideQFlagsObject* newObject(long value, PyTypeObject* type); - /** - * Returns the value held by a QFlag. - */ - PYSIDE_API long getValue(PySideQFlagsObject* self); -} -} - -#endif - diff --git a/sources/pyside2/libpyside/pysidesignal.cpp b/sources/pyside2/libpyside/pysidesignal.cpp deleted file mode 100644 index f3fb4e06d..000000000 --- a/sources/pyside2/libpyside/pysidesignal.cpp +++ /dev/null @@ -1,1040 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include <sbkpython.h> -#include "pysidesignal.h" -#include "pysidesignal_p.h" -#include "pysidestaticstrings.h" -#include "signalmanager.h" - -#include <shiboken.h> - -#include <QtCore/QObject> -#include <QtCore/QMetaMethod> -#include <QtCore/QMetaObject> -#include <signature.h> - -#include <algorithm> -#include <utility> - -#define QT_SIGNAL_SENTINEL '2' - -namespace PySide { -namespace Signal { - //aux - class SignalSignature { - public: - SignalSignature() = default; - explicit SignalSignature(QByteArray parameterTypes) : - m_parameterTypes(std::move(parameterTypes)) {} - explicit SignalSignature(QByteArray parameterTypes, QMetaMethod::Attributes attributes) : - m_parameterTypes(std::move(parameterTypes)), - m_attributes(attributes) {} - - QByteArray m_parameterTypes; - QMetaMethod::Attributes m_attributes = QMetaMethod::Compatibility; - }; - - static QByteArray buildSignature(const QByteArray &, const QByteArray &); - static void appendSignature(PySideSignal *, const SignalSignature &); - static void instanceInitialize(PySideSignalInstance *, PyObject *, PySideSignal *, PyObject *, int); - static QByteArray parseSignature(PyObject *); - static PyObject *buildQtCompatible(const QByteArray &); -} -} - -extern "C" -{ - -// Signal methods -static int signalTpInit(PyObject *, PyObject *, PyObject *); -static void signalFree(void *); -static void signalInstanceFree(void *); -static PyObject *signalGetItem(PyObject *self, PyObject *key); -static PyObject *signalToString(PyObject *self); -static PyObject *signalDescrGet(PyObject *self, PyObject *obj, PyObject *type); - -// Signal Instance methods -static PyObject *signalInstanceConnect(PyObject *, PyObject *, PyObject *); -static PyObject *signalInstanceDisconnect(PyObject *, PyObject *); -static PyObject *signalInstanceEmit(PyObject *, PyObject *); -static PyObject *signalInstanceGetItem(PyObject *, PyObject *); - -static PyObject *signalInstanceCall(PyObject *self, PyObject *args, PyObject *kw); -static PyObject *signalCall(PyObject *, PyObject *, PyObject *); - -static PyObject *metaSignalCheck(PyObject *, PyObject *); - - -static PyMethodDef MetaSignal_methods[] = { - {"__instancecheck__", (PyCFunction)metaSignalCheck, METH_O|METH_STATIC, NULL}, - {0, 0, 0, 0} -}; - -static PyType_Slot PySideMetaSignalType_slots[] = { - {Py_tp_methods, reinterpret_cast<void *>(MetaSignal_methods)}, - {Py_tp_base, reinterpret_cast<void *>(&PyType_Type)}, - {Py_tp_free, reinterpret_cast<void *>(PyObject_GC_Del)}, - {Py_tp_dealloc, reinterpret_cast<void *>(Sbk_object_dealloc)}, - {0, 0} -}; -static PyType_Spec PySideMetaSignalType_spec = { - "2:PySide2.QtCore.MetaSignal", - 0, - // sizeof(PyHeapTypeObject) is filled in by SbkType_FromSpecWithBases - // which calls PyType_Ready which calls inherit_special. - 0, - Py_TPFLAGS_DEFAULT, - PySideMetaSignalType_slots, -}; - - -static PyTypeObject *PySideMetaSignalTypeF(void) -{ - static PyTypeObject *type = nullptr; - if (!type) { - PyObject *bases = Py_BuildValue("(O)", &PyType_Type); - type = (PyTypeObject *)SbkType_FromSpecWithBases(&PySideMetaSignalType_spec, bases); - Py_XDECREF(bases); - } - return type; -} - -static PyType_Slot PySideSignalType_slots[] = { - {Py_mp_subscript, reinterpret_cast<void *>(signalGetItem)}, - {Py_tp_descr_get, reinterpret_cast<void *>(signalDescrGet)}, - {Py_tp_call, reinterpret_cast<void *>(signalCall)}, - {Py_tp_str, reinterpret_cast<void *>(signalToString)}, - {Py_tp_init, reinterpret_cast<void *>(signalTpInit)}, - {Py_tp_new, reinterpret_cast<void *>(PyType_GenericNew)}, - {Py_tp_free, reinterpret_cast<void *>(signalFree)}, - {Py_tp_dealloc, reinterpret_cast<void *>(Sbk_object_dealloc)}, - {0, 0} -}; -static PyType_Spec PySideSignalType_spec = { - "2:PySide2.QtCore.Signal", - sizeof(PySideSignal), - 0, - Py_TPFLAGS_DEFAULT, - PySideSignalType_slots, -}; - - -PyTypeObject *PySideSignalTypeF(void) -{ - static PyTypeObject *type = nullptr; - if (!type) { - type = reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideSignalType_spec)); - PyTypeObject *hold = Py_TYPE(type); - Py_TYPE(type) = PySideMetaSignalTypeF(); - Py_INCREF(Py_TYPE(type)); - Py_DECREF(hold); - } - return type; -} - -static PyMethodDef SignalInstance_methods[] = { - {"connect", (PyCFunction)signalInstanceConnect, METH_VARARGS|METH_KEYWORDS, 0}, - {"disconnect", signalInstanceDisconnect, METH_VARARGS, 0}, - {"emit", signalInstanceEmit, METH_VARARGS, 0}, - {0, 0, 0, 0} /* Sentinel */ -}; - -static PyType_Slot PySideSignalInstanceType_slots[] = { - {Py_mp_subscript, reinterpret_cast<void *>(signalInstanceGetItem)}, - {Py_tp_call, reinterpret_cast<void *>(signalInstanceCall)}, - {Py_tp_methods, reinterpret_cast<void *>(SignalInstance_methods)}, - {Py_tp_new, reinterpret_cast<void *>(PyType_GenericNew)}, - {Py_tp_free, reinterpret_cast<void *>(signalInstanceFree)}, - {Py_tp_dealloc, reinterpret_cast<void *>(Sbk_object_dealloc)}, - {0, 0} -}; -static PyType_Spec PySideSignalInstanceType_spec = { - "2:PySide2.QtCore.SignalInstance", - sizeof(PySideSignalInstance), - 0, - Py_TPFLAGS_DEFAULT, - PySideSignalInstanceType_slots, -}; - - -PyTypeObject *PySideSignalInstanceTypeF(void) -{ - static PyTypeObject *type = - reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideSignalInstanceType_spec)); - return type; -} - -static int signalTpInit(PyObject *self, PyObject *args, PyObject *kwds) -{ - static PyObject *emptyTuple = nullptr; - static const char *kwlist[] = {"name", "arguments", nullptr}; - char *argName = nullptr; - PyObject *argArguments = nullptr; - - if (emptyTuple == 0) - emptyTuple = PyTuple_New(0); - - if (!PyArg_ParseTupleAndKeywords(emptyTuple, kwds, - "|sO:QtCore.Signal", const_cast<char **>(kwlist), &argName, &argArguments)) - return -1; - - bool tupledArgs = false; - PySideSignal *data = reinterpret_cast<PySideSignal *>(self); - if (!data->data) - data->data = new PySideSignalData; - if (argName) - data->data->signalName = argName; - - data->data->signalArguments = new QByteArrayList(); - if (argArguments && PySequence_Check(argArguments)) { - Py_ssize_t argument_size = PySequence_Size(argArguments); - for (Py_ssize_t i = 0; i < argument_size; ++i) { - PyObject *item = PySequence_GetItem(argArguments, i); - PyObject *strObj = PyUnicode_AsUTF8String(item); - char *s = PyBytes_AsString(strObj); - Py_DECREF(strObj); - Py_DECREF(item); - if (s != nullptr) - data->data->signalArguments->append(QByteArray(s)); - } - } - - for (Py_ssize_t i = 0, i_max = PyTuple_Size(args); i < i_max; i++) { - PyObject *arg = PyTuple_GET_ITEM(args, i); - if (PySequence_Check(arg) && !Shiboken::String::check(arg) && !PyEnumMeta_Check(arg)) { - tupledArgs = true; - const auto sig = PySide::Signal::parseSignature(arg); - PySide::Signal::appendSignature( - data, - PySide::Signal::SignalSignature(sig)); - } - } - - if (!tupledArgs) { - const auto sig = PySide::Signal::parseSignature(args); - PySide::Signal::appendSignature( - data, - PySide::Signal::SignalSignature(sig)); - } - - return 0; -} - -static void signalFree(void *self) -{ - auto pySelf = reinterpret_cast<PyObject *>(self); - auto data = reinterpret_cast<PySideSignal *>(self); - delete data->data; - data->data = nullptr; - Py_XDECREF(data->homonymousMethod); - data->homonymousMethod = 0; - - Py_TYPE(pySelf)->tp_base->tp_free(self); -} - -static PyObject *signalGetItem(PyObject *self, PyObject *key) -{ - auto data = reinterpret_cast<PySideSignal *>(self); - QByteArray sigKey; - if (key) { - sigKey = PySide::Signal::parseSignature(key); - } else { - sigKey = data->data == nullptr || data->data->signatures.isEmpty() - ? PySide::Signal::voidType() : data->data->signatures.constFirst().signature; - } - auto sig = PySide::Signal::buildSignature(data->data->signalName, sigKey); - return Shiboken::String::fromCString(sig.constData()); -} - - -static PyObject *signalToString(PyObject *self) -{ - return signalGetItem(self, 0); -} - -static void signalInstanceFree(void *self) -{ - auto pySelf = reinterpret_cast<PyObject *>(self); - auto data = reinterpret_cast<PySideSignalInstance *>(self); - - PySideSignalInstancePrivate *dataPvt = data->d; - - Py_XDECREF(dataPvt->homonymousMethod); - - if (dataPvt->next) { - Py_DECREF(dataPvt->next); - dataPvt->next = 0; - } - delete dataPvt; - data->d = 0; - Py_TYPE(pySelf)->tp_base->tp_free(self); -} - -static PyObject *signalInstanceConnect(PyObject *self, PyObject *args, PyObject *kwds) -{ - PyObject *slot = nullptr; - PyObject *type = nullptr; - static const char *kwlist[] = {"slot", "type", nullptr}; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|O:SignalInstance", const_cast<char **>(kwlist), &slot, &type)) - return 0; - - PySideSignalInstance *source = reinterpret_cast<PySideSignalInstance *>(self); - Shiboken::AutoDecRef pyArgs(PyList_New(0)); - - bool match = false; - if (Py_TYPE(slot) == PySideSignalInstanceTypeF()) { - PySideSignalInstance *sourceWalk = source; - PySideSignalInstance *targetWalk; - - //find best match - while (sourceWalk && !match) { - targetWalk = reinterpret_cast<PySideSignalInstance *>(slot); - while (targetWalk && !match) { - if (QMetaObject::checkConnectArgs(sourceWalk->d->signature, targetWalk->d->signature)) { - PyList_Append(pyArgs, sourceWalk->d->source); - Shiboken::AutoDecRef sourceSignature(PySide::Signal::buildQtCompatible(sourceWalk->d->signature)); - PyList_Append(pyArgs, sourceSignature); - - PyList_Append(pyArgs, targetWalk->d->source); - Shiboken::AutoDecRef targetSignature(PySide::Signal::buildQtCompatible(targetWalk->d->signature)); - PyList_Append(pyArgs, targetSignature); - - match = true; - } - targetWalk = reinterpret_cast<PySideSignalInstance *>(targetWalk->d->next); - } - sourceWalk = reinterpret_cast<PySideSignalInstance *>(sourceWalk->d->next); - } - } else { - // Check signature of the slot (method or function) to match signal - int slotArgs = -1; - bool useSelf = false; - bool isMethod = PyMethod_Check(slot); - bool isFunction = PyFunction_Check(slot); - bool matchedSlot = false; - - QByteArray functionName; - PySideSignalInstance *it = source; - - if (isMethod || isFunction) { - PyObject *function = isMethod ? PyMethod_GET_FUNCTION(slot) : slot; - auto *objCode = reinterpret_cast<PepCodeObject *>(PyFunction_GET_CODE(function)); - useSelf = isMethod; - slotArgs = PepCode_GET_FLAGS(objCode) & CO_VARARGS ? -1 : PepCode_GET_ARGCOUNT(objCode); - if (useSelf) - slotArgs -= 1; - - // Get signature args - bool isShortCircuit = false; - int signatureArgs = 0; - QStringList argsSignature; - - argsSignature = PySide::Signal::getArgsFromSignature(it->d->signature, - &isShortCircuit); - signatureArgs = argsSignature.length(); - - // Iterate the possible types of connection for this signal and compare - // it with slot arguments - if (signatureArgs != slotArgs) { - while (it->d->next != nullptr) { - it = it->d->next; - argsSignature = PySide::Signal::getArgsFromSignature(it->d->signature, - &isShortCircuit); - signatureArgs = argsSignature.length(); - if (signatureArgs == slotArgs) { - matchedSlot = true; - break; - } - } - } - } - - // Adding references to pyArgs - PyList_Append(pyArgs, source->d->source); - - if (matchedSlot) { - // If a slot matching the same number of arguments was found, - // include signature to the pyArgs - Shiboken::AutoDecRef signature(PySide::Signal::buildQtCompatible(it->d->signature)); - PyList_Append(pyArgs, signature); - } else { - // Try the first by default if the slot was not found - Shiboken::AutoDecRef signature(PySide::Signal::buildQtCompatible(source->d->signature)); - PyList_Append(pyArgs, signature); - } - PyList_Append(pyArgs, slot); - match = true; - } - - if (type) - PyList_Append(pyArgs, type); - - if (match) { - Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs)); - Shiboken::AutoDecRef pyMethod(PyObject_GetAttr(source->d->source, - PySide::PyName::qtConnect())); - if (pyMethod.isNull()) { // PYSIDE-79: check if pyMethod exists. - PyErr_SetString(PyExc_RuntimeError, "method 'connect' vanished!"); - return 0; - } - PyObject *result = PyObject_CallObject(pyMethod, tupleArgs); - if (result == Py_True || result == Py_False) - return result; - Py_XDECREF(result); - } - if (!PyErr_Occurred()) // PYSIDE-79: inverse the logic. A Null return needs an error. - PyErr_Format(PyExc_RuntimeError, "Failed to connect signal %s.", - source->d->signature.constData()); - return 0; -} - -static int argCountInSignature(const char *signature) -{ - return QByteArray(signature).count(",") + 1; -} - -static PyObject *signalInstanceEmit(PyObject *self, PyObject *args) -{ - PySideSignalInstance *source = reinterpret_cast<PySideSignalInstance *>(self); - - Shiboken::AutoDecRef pyArgs(PyList_New(0)); - int numArgsGiven = PySequence_Fast_GET_SIZE(args); - int numArgsInSignature = argCountInSignature(source->d->signature); - - // If number of arguments given to emit is smaller than the first source signature expects, - // it is possible it's a case of emitting a signal with default parameters. - // Search through all the overloaded signals with the same name, and try to find a signature - // with the same number of arguments as given to emit, and is also marked as a cloned method - // (which in metaobject parlance means a signal with default parameters). - // @TODO: This should be improved to take into account argument types as well. The current - // assumption is there are no signals which are both overloaded on argument types and happen to - // have signatures with default parameters. - if (numArgsGiven < numArgsInSignature) { - PySideSignalInstance *possibleDefaultInstance = source; - while ((possibleDefaultInstance = possibleDefaultInstance->d->next)) { - if (possibleDefaultInstance->d->attributes & QMetaMethod::Cloned - && argCountInSignature(possibleDefaultInstance->d->signature) == numArgsGiven) { - source = possibleDefaultInstance; - break; - } - } - } - Shiboken::AutoDecRef sourceSignature(PySide::Signal::buildQtCompatible(source->d->signature)); - - PyList_Append(pyArgs, sourceSignature); - for (Py_ssize_t i = 0, max = PyTuple_Size(args); i < max; i++) - PyList_Append(pyArgs, PyTuple_GetItem(args, i)); - - Shiboken::AutoDecRef pyMethod(PyObject_GetAttr(source->d->source, - PySide::PyName::qtEmit())); - - Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs)); - return PyObject_CallObject(pyMethod, tupleArgs); -} - -static PyObject *signalInstanceGetItem(PyObject *self, PyObject *key) -{ - auto data = reinterpret_cast<PySideSignalInstance *>(self); - const auto sigName = data->d->signalName; - const auto sigKey = PySide::Signal::parseSignature(key); - const auto sig = PySide::Signal::buildSignature(sigName, sigKey); - while (data) { - if (data->d->signature == sig) { - PyObject *result = reinterpret_cast<PyObject *>(data); - Py_INCREF(result); - return result; - } - data = data->d->next; - } - - PyErr_Format(PyExc_IndexError, "Signature %s not found for signal: %s", - sig.constData(), sigName.constData()); - return 0; -} - -static PyObject *signalInstanceDisconnect(PyObject *self, PyObject *args) -{ - auto source = reinterpret_cast<PySideSignalInstance *>(self); - Shiboken::AutoDecRef pyArgs(PyList_New(0)); - - PyObject *slot; - if (PyTuple_Check(args) && PyTuple_GET_SIZE(args)) - slot = PyTuple_GET_ITEM(args, 0); - else - slot = Py_None; - - bool match = false; - if (Py_TYPE(slot) == PySideSignalInstanceTypeF()) { - PySideSignalInstance *target = reinterpret_cast<PySideSignalInstance *>(slot); - if (QMetaObject::checkConnectArgs(source->d->signature, target->d->signature)) { - PyList_Append(pyArgs, source->d->source); - Shiboken::AutoDecRef source_signature(PySide::Signal::buildQtCompatible(source->d->signature)); - PyList_Append(pyArgs, source_signature); - - PyList_Append(pyArgs, target->d->source); - Shiboken::AutoDecRef target_signature(PySide::Signal::buildQtCompatible(target->d->signature)); - PyList_Append(pyArgs, target_signature); - match = true; - } - } else { - //try the first signature - PyList_Append(pyArgs, source->d->source); - Shiboken::AutoDecRef signature(PySide::Signal::buildQtCompatible(source->d->signature)); - PyList_Append(pyArgs, signature); - - // disconnect all, so we need to use the c++ signature disconnect(qobj, signal, 0, 0) - if (slot == Py_None) - PyList_Append(pyArgs, slot); - PyList_Append(pyArgs, slot); - match = true; - } - - if (match) { - Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs)); - Shiboken::AutoDecRef pyMethod(PyObject_GetAttr(source->d->source, - PySide::PyName::qtDisconnect())); - PyObject *result = PyObject_CallObject(pyMethod, tupleArgs); - if (!result || result == Py_True) - return result; - else - Py_DECREF(result); - } - - PyErr_Format(PyExc_RuntimeError, "Failed to disconnect signal %s.", - source->d->signature.constData()); - return 0; -} - -// PYSIDE-68: Supply the missing __get__ function -static PyObject *signalDescrGet(PyObject *self, PyObject *obj, PyObject * /*type*/) -{ - auto signal = reinterpret_cast<PySideSignal *>(self); - // Return the unbound signal if there is nothing to bind it to. - if (obj == nullptr || obj == Py_None) { - Py_INCREF(self); - return self; - } - Shiboken::AutoDecRef name(Py_BuildValue("s", signal->data->signalName.data())); - return reinterpret_cast<PyObject *>(PySide::Signal::initialize(signal, name, obj)); -} - -static PyObject *signalCall(PyObject *self, PyObject *args, PyObject *kw) -{ - auto signal = reinterpret_cast<PySideSignal *>(self); - - // Native C++ signals can't be called like functions, thus we throw an exception. - // The only way calling a signal can succeed (the Python equivalent of C++'s operator() ) - // is when a method with the same name as the signal is attached to an object. - // An example is QProcess::error() (don't check the docs, but the source code of qprocess.h). - if (!signal->homonymousMethod) { - PyErr_SetString(PyExc_TypeError, "native Qt signal is not callable"); - return 0; - } - - descrgetfunc getDescriptor = Py_TYPE(signal->homonymousMethod)->tp_descr_get; - - // Check if there exists a method with the same name as the signal, which is also a static - // method in C++ land. - Shiboken::AutoDecRef homonymousMethod(getDescriptor(signal->homonymousMethod, 0, 0)); - if (PyCFunction_Check(homonymousMethod) - && (PyCFunction_GET_FLAGS(homonymousMethod.object()) & METH_STATIC)) { -#if PY_VERSION_HEX >= 0x03090000 - return PyObject_Call(homonymousMethod, args, kw); -#else - return PyCFunction_Call(homonymousMethod, args, kw); -#endif - } - - // Assumes homonymousMethod is not a static method. - ternaryfunc callFunc = Py_TYPE(signal->homonymousMethod)->tp_call; - return callFunc(homonymousMethod, args, kw); -} - -static PyObject *signalInstanceCall(PyObject *self, PyObject *args, PyObject *kw) -{ - auto PySideSignal = reinterpret_cast<PySideSignalInstance *>(self); - if (!PySideSignal->d->homonymousMethod) { - PyErr_SetString(PyExc_TypeError, "native Qt signal is not callable"); - return 0; - } - - descrgetfunc getDescriptor = Py_TYPE(PySideSignal->d->homonymousMethod)->tp_descr_get; - Shiboken::AutoDecRef homonymousMethod(getDescriptor(PySideSignal->d->homonymousMethod, PySideSignal->d->source, 0)); -#if PY_VERSION_HEX >= 0x03090000 - return PyObject_Call(homonymousMethod, args, kw); -#else - return PyCFunction_Call(homonymousMethod, args, kw); -#endif -} - -static PyObject *metaSignalCheck(PyObject * /* klass */, PyObject *arg) -{ - if (PyType_IsSubtype(Py_TYPE(arg), PySideSignalInstanceTypeF())) - Py_RETURN_TRUE; - else - Py_RETURN_FALSE; -} - -} // extern "C" - -namespace PySide { -namespace Signal { - -static const char *MetaSignal_SignatureStrings[] = { - "PySide2.QtCore.MetaSignal.__instancecheck__(object:object)->bool", - nullptr}; // Sentinel - -static const char *Signal_SignatureStrings[] = { - "PySide2.QtCore.Signal(*types:type,name:str=nullptr,arguments:str=nullptr)", - nullptr}; // Sentinel - -static const char *SignalInstance_SignatureStrings[] = { - "PySide2.QtCore.SignalInstance.connect(slot:object,type:type=nullptr)", - "PySide2.QtCore.SignalInstance.disconnect(slot:object=nullptr)", - "PySide2.QtCore.SignalInstance.emit(*args:typing.Any)", - nullptr}; // Sentinel - -void init(PyObject *module) -{ - if (InitSignatureStrings(PySideMetaSignalTypeF(), MetaSignal_SignatureStrings) < 0) - return; - Py_INCREF(PySideMetaSignalTypeF()); - PyModule_AddObject(module, "MetaSignal", reinterpret_cast<PyObject *>(PySideMetaSignalTypeF())); - - if (InitSignatureStrings(PySideSignalTypeF(), Signal_SignatureStrings) < 0) - return; - Py_INCREF(PySideSignalTypeF()); - PyModule_AddObject(module, "Signal", reinterpret_cast<PyObject *>(PySideSignalTypeF())); - - if (InitSignatureStrings(PySideSignalInstanceTypeF(), SignalInstance_SignatureStrings) < 0) - return; - Py_INCREF(PySideSignalInstanceTypeF()); - PyModule_AddObject(module, "SignalInstance", reinterpret_cast<PyObject *>(PySideSignalInstanceTypeF())); -} - -bool checkType(PyObject *pyObj) -{ - if (pyObj) - return PyType_IsSubtype(Py_TYPE(pyObj), PySideSignalTypeF()); - return false; -} - -void updateSourceObject(PyObject *source) -{ - PyTypeObject *objType = reinterpret_cast<PyTypeObject *>(PyObject_Type(source)); - - Py_ssize_t pos = 0; - PyObject *value; - PyObject *key; - - while (PyDict_Next(objType->tp_dict, &pos, &key, &value)) { - if (PyObject_TypeCheck(value, PySideSignalTypeF())) { - Shiboken::AutoDecRef signalInstance(reinterpret_cast<PyObject *>(PyObject_New(PySideSignalInstance, PySideSignalInstanceTypeF()))); - instanceInitialize(signalInstance.cast<PySideSignalInstance *>(), key, reinterpret_cast<PySideSignal *>(value), source, 0); - PyObject_SetAttr(source, key, signalInstance); - } - } - - Py_XDECREF(objType); -} - -QByteArray getTypeName(PyObject *type) -{ - if (PyType_Check(type)) { - if (PyType_IsSubtype(reinterpret_cast<PyTypeObject *>(type), - reinterpret_cast<PyTypeObject *>(SbkObject_TypeF()))) { - auto objType = reinterpret_cast<SbkObjectType *>(type); - return Shiboken::ObjectType::getOriginalName(objType); - } - // Translate python types to Qt names - auto objType = reinterpret_cast<PyTypeObject *>(type); - if (Shiboken::String::checkType(objType)) - return QByteArrayLiteral("QString"); - if (objType == &PyInt_Type) - return QByteArrayLiteral("int"); - if (objType == &PyLong_Type) - return QByteArrayLiteral("long"); - if (objType == &PyFloat_Type) - return QByteArrayLiteral("double"); - if (objType == &PyBool_Type) - return QByteArrayLiteral("bool"); - if (objType == &PyList_Type) - return QByteArrayLiteral("QVariantList"); - if (Py_TYPE(objType) == SbkEnumType_TypeF()) - return Shiboken::Enum::getCppName(objType); - return QByteArrayLiteral("PyObject"); - } - if (type == Py_None) // Must be checked before as Shiboken::String::check accepts Py_None - return voidType(); - if (Shiboken::String::check(type)) { - QByteArray result = Shiboken::String::toCString(type); - if (result == "qreal") - result = sizeof(qreal) == sizeof(double) ? "double" : "float"; - return result; - } - return QByteArray(); -} - -static QByteArray buildSignature(const QByteArray &name, const QByteArray &signature) -{ - return QMetaObject::normalizedSignature(name + '(' + signature + ')'); -} - -static QByteArray parseSignature(PyObject *args) -{ - if (args && (Shiboken::String::check(args) || !PySequence_Check(args))) - return getTypeName(args); - - QByteArray signature; - for (Py_ssize_t i = 0, i_max = PySequence_Size(args); i < i_max; i++) { - Shiboken::AutoDecRef arg(PySequence_GetItem(args, i)); - const auto typeName = getTypeName(arg); - if (!typeName.isEmpty()) { - if (!signature.isEmpty()) - signature += ','; - signature += typeName; - } - } - return signature; -} - -static void appendSignature(PySideSignal *self, const SignalSignature &signature) -{ - self->data->signatures.append({signature.m_parameterTypes, signature.m_attributes}); -} - -static void instanceInitialize(PySideSignalInstance *self, PyObject *name, PySideSignal *data, PyObject *source, int index) -{ - self->d = new PySideSignalInstancePrivate; - PySideSignalInstancePrivate *selfPvt = self->d; - selfPvt->next = nullptr; - if (data->data->signalName.isEmpty()) - data->data->signalName = Shiboken::String::toCString(name); - selfPvt->signalName = data->data->signalName; - - selfPvt->source = source; - const auto &signature = data->data->signatures.at(index); - selfPvt->signature = buildSignature(self->d->signalName, signature.signature); - selfPvt->attributes = signature.attributes; - selfPvt->homonymousMethod = 0; - if (data->homonymousMethod) { - selfPvt->homonymousMethod = data->homonymousMethod; - Py_INCREF(selfPvt->homonymousMethod); - } - index++; - - if (index < data->data->signatures.size()) { - selfPvt->next = PyObject_New(PySideSignalInstance, PySideSignalInstanceTypeF()); - instanceInitialize(selfPvt->next, name, data, source, index); - } -} - -PySideSignalInstance *initialize(PySideSignal *self, PyObject *name, PyObject *object) -{ - PySideSignalInstance *instance = PyObject_New(PySideSignalInstance, - PySideSignalInstanceTypeF()); - instanceInitialize(instance, name, self, object, 0); - auto sbkObj = reinterpret_cast<SbkObject *>(object); - if (!Shiboken::Object::wasCreatedByPython(sbkObj)) - Py_INCREF(object); // PYSIDE-79: this flag was crucial for a wrapper call. - return instance; -} - -bool connect(PyObject *source, const char *signal, PyObject *callback) -{ - Shiboken::AutoDecRef pyMethod(PyObject_GetAttr(source, - PySide::PyName::qtConnect())); - if (pyMethod.isNull()) - return false; - - Shiboken::AutoDecRef pySignature(Shiboken::String::fromCString(signal)); - Shiboken::AutoDecRef pyArgs(PyTuple_Pack(3, source, pySignature.object(), callback)); - PyObject *result = PyObject_CallObject(pyMethod, pyArgs); - if (result == Py_False) { - PyErr_Format(PyExc_RuntimeError, "Failed to connect signal %s, to python callable object.", signal); - Py_DECREF(result); - result = 0; - } - return result; -} - -PySideSignalInstance *newObjectFromMethod(PyObject *source, const QList<QMetaMethod>& methodList) -{ - PySideSignalInstance *root = nullptr; - PySideSignalInstance *previous = nullptr; - for (const QMetaMethod &m : methodList) { - PySideSignalInstance *item = PyObject_New(PySideSignalInstance, PySideSignalInstanceTypeF()); - if (!root) - root = item; - - if (previous) - previous->d->next = item; - - item->d = new PySideSignalInstancePrivate; - PySideSignalInstancePrivate *selfPvt = item->d; - selfPvt->source = source; - Py_INCREF(selfPvt->source); // PYSIDE-79: an INCREF is missing. - QByteArray cppName(m.methodSignature()); - cppName.truncate(cppName.indexOf('(')); - // separe SignalName - selfPvt->signalName = cppName; - selfPvt->signature = m.methodSignature(); - selfPvt->attributes = m.attributes(); - selfPvt->homonymousMethod = 0; - selfPvt->next = 0; - } - return root; -} - -template<typename T> -static typename T::value_type join(T t, const char *sep) -{ - typename T::value_type res; - if (t.isEmpty()) - return res; - - typename T::const_iterator it = t.begin(); - typename T::const_iterator end = t.end(); - res += *it; - ++it; - - while (it != end) { - res += sep; - res += *it; - ++it; - } - return res; -} - -static void _addSignalToWrapper(SbkObjectType *wrapperType, const char *signalName, PySideSignal *signal) -{ - auto typeDict = reinterpret_cast<PyTypeObject *>(wrapperType)->tp_dict; - PyObject *homonymousMethod; - if ((homonymousMethod = PyDict_GetItemString(typeDict, signalName))) { - Py_INCREF(homonymousMethod); - signal->homonymousMethod = homonymousMethod; - } - PyDict_SetItemString(typeDict, signalName, reinterpret_cast<PyObject *>(signal)); -} - -// This function is used by qStableSort to promote empty signatures -static bool compareSignals(const SignalSignature &sig1, const SignalSignature &) -{ - return sig1.m_parameterTypes.isEmpty(); -} - -static PyObject *buildQtCompatible(const QByteArray &signature) -{ - const auto ba = QT_SIGNAL_SENTINEL + signature; - return Shiboken::String::fromStringAndSize(ba, ba.size()); -} - -void registerSignals(SbkObjectType *pyObj, const QMetaObject *metaObject) -{ - typedef QHash<QByteArray, QList<SignalSignature> > SignalSigMap; - SignalSigMap signalsFound; - for (int i = metaObject->methodOffset(), max = metaObject->methodCount(); i < max; ++i) { - QMetaMethod method = metaObject->method(i); - - if (method.methodType() == QMetaMethod::Signal) { - QByteArray methodName(method.methodSignature()); - methodName.chop(methodName.size() - methodName.indexOf('(')); - SignalSignature signature; - signature.m_parameterTypes = join(method.parameterTypes(), ","); - if (method.attributes() & QMetaMethod::Cloned) - signature.m_attributes = QMetaMethod::Cloned; - signalsFound[methodName] << signature; - } - } - - SignalSigMap::Iterator it = signalsFound.begin(); - SignalSigMap::Iterator end = signalsFound.end(); - for (; it != end; ++it) { - PySideSignal *self = PyObject_New(PySideSignal, PySideSignalTypeF()); - self->data = new PySideSignalData; - self->data->signalName = it.key(); - self->homonymousMethod = 0; - - // Empty signatures comes first! So they will be the default signal signature - std::stable_sort(it.value().begin(), it.value().end(), &compareSignals); - SignalSigMap::mapped_type::const_iterator j = it.value().begin(); - SignalSigMap::mapped_type::const_iterator endJ = it.value().end(); - for (; j != endJ; ++j) { - const SignalSignature &sig = *j; - appendSignature(self, sig); - } - - _addSignalToWrapper(pyObj, it.key(), self); - Py_DECREF(reinterpret_cast<PyObject *>(self)); - } -} - -PyObject *getObject(PySideSignalInstance *signal) -{ - return signal->d->source; -} - -const char *getSignature(PySideSignalInstance *signal) -{ - return signal->d->signature; -} - -QStringList getArgsFromSignature(const char *signature, bool *isShortCircuit) -{ - QString qsignature = QString::fromLatin1(signature).trimmed(); - QStringList result; - - if (isShortCircuit) - *isShortCircuit = !qsignature.contains(QLatin1Char('(')); - if (qsignature.contains(QLatin1String("()")) || qsignature.contains(QLatin1String("(void)"))) - return result; - if (qsignature.endsWith(QLatin1Char(')'))) { - const int paren = qsignature.indexOf(QLatin1Char('(')); - if (paren >= 0) { - qsignature.chop(1); - qsignature.remove(0, paren + 1); - result = qsignature.split(QLatin1Char(',')); - for (QString &type : result) - type = type.trimmed(); - } - } - return result; -} - -QString getCallbackSignature(const char *signal, QObject *receiver, PyObject *callback, bool encodeName) -{ - QByteArray functionName; - int numArgs = -1; - bool useSelf = false; - bool isMethod = PyMethod_Check(callback); - bool isFunction = PyFunction_Check(callback); - - if (isMethod || isFunction) { - PyObject *function = isMethod ? PyMethod_GET_FUNCTION(callback) : callback; - auto objCode = reinterpret_cast<PepCodeObject *>(PyFunction_GET_CODE(function)); - functionName = Shiboken::String::toCString(PepFunction_GetName(function)); - useSelf = isMethod; - numArgs = PepCode_GET_FLAGS(objCode) & CO_VARARGS ? -1 : PepCode_GET_ARGCOUNT(objCode); - } else if (PyCFunction_Check(callback)) { - const PyCFunctionObject *funcObj = reinterpret_cast<const PyCFunctionObject *>(callback); - functionName = PepCFunction_GET_NAMESTR(funcObj); - useSelf = PyCFunction_GET_SELF(funcObj); - const int flags = PyCFunction_GET_FLAGS(funcObj); - - if (receiver) { - //Search for signature on metaobject - const QMetaObject *mo = receiver->metaObject(); - QByteArray prefix(functionName); - prefix += '('; - for (int i = 0; i < mo->methodCount(); i++) { - QMetaMethod me = mo->method(i); - if ((strncmp(me.methodSignature(), prefix, prefix.size()) == 0) && - QMetaObject::checkConnectArgs(signal, me.methodSignature())) { - numArgs = me.parameterTypes().size() + useSelf; - break; - } - } - } - - if (numArgs == -1) { - if (flags & METH_VARARGS) - numArgs = -1; - else if (flags & METH_NOARGS) - numArgs = 0; - } - } else if (PyCallable_Check(callback)) { - functionName = "__callback" + QByteArray::number((qlonglong)callback); - } - - Q_ASSERT(!functionName.isEmpty()); - - bool isShortCircuit = false; - - const QString functionNameS = QLatin1String(functionName); - QString signature = encodeName ? codeCallbackName(callback, functionNameS) : functionNameS; - QStringList args = getArgsFromSignature(signal, &isShortCircuit); - - if (!isShortCircuit) { - signature.append(QLatin1Char('(')); - if (numArgs == -1) - numArgs = std::numeric_limits<int>::max(); - while (args.count() && (args.count() > (numArgs - useSelf))) { - args.removeLast(); - } - signature.append(args.join(QLatin1Char(','))); - signature.append(QLatin1Char(')')); - } - return signature; -} - -bool isQtSignal(const char *signal) -{ - return (signal && signal[0] == QT_SIGNAL_SENTINEL); -} - -bool checkQtSignal(const char *signal) -{ - if (!isQtSignal(signal)) { - PyErr_SetString(PyExc_TypeError, "Use the function PySide2.QtCore.SIGNAL on signals"); - return false; - } - return true; -} - -QString codeCallbackName(PyObject *callback, const QString &funcName) -{ - if (PyMethod_Check(callback)) { - PyObject *self = PyMethod_GET_SELF(callback); - PyObject *func = PyMethod_GET_FUNCTION(callback); - return funcName + QString::number(quint64(self), 16) + QString::number(quint64(func), 16); - } - return funcName + QString::number(quint64(callback), 16); -} - -QByteArray voidType() -{ - return QByteArrayLiteral("void"); -} - -} //namespace Signal -} //namespace PySide - diff --git a/sources/pyside2/libpyside/pysidesignal.h b/sources/pyside2/libpyside/pysidesignal.h deleted file mode 100644 index 973644b0a..000000000 --- a/sources/pyside2/libpyside/pysidesignal.h +++ /dev/null @@ -1,163 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_SIGNAL_H -#define PYSIDE_SIGNAL_H - -#include <pysidemacros.h> - -#include <sbkpython.h> -#include <basewrapper.h> - -#include <QtCore/QList> -#include <QtCore/QMetaMethod> - -QT_BEGIN_NAMESPACE -struct QMetaObject; -class QObject; -QT_END_NAMESPACE - -extern "C" -{ - extern PYSIDE_API PyTypeObject *PySideSignalTypeF(void); - extern PYSIDE_API PyTypeObject *PySideSignalInstanceTypeF(void); - - // Internal object - struct PYSIDE_API PySideSignal; - - struct PySideSignalInstancePrivate; - struct PYSIDE_API PySideSignalInstance - { - PyObject_HEAD - PySideSignalInstancePrivate *d; - }; -}; // extern "C" - -namespace PySide { -namespace Signal { - -PYSIDE_API bool checkType(PyObject *type); - -/** - * Register all C++ signals of a QObject on Python type. - */ -PYSIDE_API void registerSignals(SbkObjectType *pyObj, const QMetaObject *metaObject); - -/** - * This function creates a Signal object which stays attached to QObject class based on a list of QMetaMethods - * - * @param source of the Signal to be registered on meta object - * @param methods a list of QMetaMethod wich contains the supported signature - * @return Return a new reference to PyObject* of type PySideSignal - **/ -PYSIDE_API PySideSignalInstance *newObjectFromMethod(PyObject *source, const QList<QMetaMethod> &methods); - -/** - * This function initializes the Signal object by creating a PySideSignalInstance - * - * @param self a Signal object used as base to PySideSignalInstance - * @param name the name to be used on PySideSignalInstance - * @param object the PyObject where the signal will be attached - * @return Return a new reference to PySideSignalInstance - **/ -PYSIDE_API PySideSignalInstance *initialize(PySideSignal *signal, PyObject *name, PyObject *object); - -/** - * This function is used to retrieve the object in which the signal is attached - * - * @param self The Signal object - * @return Return the internal reference to the parent object of the signal - **/ -PYSIDE_API PyObject *getObject(PySideSignalInstance *signal); - -/** - * This function is used to retrieve the signal signature - * - * @param self The Signal object - * @return Return the signal signature - **/ -PYSIDE_API const char *getSignature(PySideSignalInstance *signal); - -/** - * This function is used to retrieve the signal signature - * - * @param self The Signal object - * @return Return the signal signature - **/ -PYSIDE_API void updateSourceObject(PyObject *source); - -/** - * This function verifies if the signature is a QtSignal base on SIGNAL flag - * @param signature The signal signature - * @return Return true if this is a Qt Signal, otherwise return false - **/ -PYSIDE_API bool isQtSignal(const char *signature); - -/** - * This function is similar to isQtSignal, however if it fails, it'll raise a Python error instead. - * - * @param signature The signal signature - * @return Return true if this is a Qt Signal, otherwise return false - **/ -PYSIDE_API bool checkQtSignal(const char *signature); - -/** - * This function is used to retrieve the signature base on Signal and receiver callback - * @param signature The signal signature - * @param receiver The QObject which will receive the signal - * @param callback Callback function which will connect to the signal - * @param encodeName Used to specify if the returned signature will be encoded with Qt signal/slot style - * @return Return the callback signature - **/ -PYSIDE_API QString getCallbackSignature(const char *signal, QObject *receiver, PyObject *callback, bool encodeName); - -/** - * This function parses the signature and then returns a list of argument types. - * - * @param signature The signal signature - * @param isShortCircuit If this is a shortCircuit(python<->python) signal - * @return Return true if this is a Qt Signal, otherwise return false - * @todo replace return type by QList<QByteArray> - **/ -QStringList getArgsFromSignature(const char *signature, bool *isShortCircuit = 0); - -} // namespace Signal -} // namespace PySide - -#endif diff --git a/sources/pyside2/libpyside/pysidesignal_p.h b/sources/pyside2/libpyside/pysidesignal_p.h deleted file mode 100644 index 337feaa8a..000000000 --- a/sources/pyside2/libpyside/pysidesignal_p.h +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef PYSIDE_QSIGNAL_P_H -#define PYSIDE_QSIGNAL_P_H - -#include <sbkpython.h> - -#include <QtCore/QByteArray> -#include <QtCore/QVector> - -struct PySideSignalData -{ - struct Signature - { - QByteArray signature; - int attributes; - }; - - QByteArray signalName; - QVector<Signature> signatures; - QByteArrayList *signalArguments; -}; - -extern "C" -{ - extern PyTypeObject *PySideSignalTypeF(void); - - struct PySideSignal { - PyObject_HEAD - PySideSignalData *data; - PyObject *homonymousMethod; - }; - - struct PySideSignalInstance; -}; //extern "C" - -struct PySideSignalInstancePrivate -{ - QByteArray signalName; - QByteArray signature; - int attributes = 0; - PyObject *source = nullptr; - PyObject *homonymousMethod = nullptr; - PySideSignalInstance *next = nullptr; -}; - -namespace PySide { namespace Signal { - - void init(PyObject *module); - bool connect(PyObject *source, const char *signal, PyObject *callback); - QByteArray getTypeName(PyObject *); - QString codeCallbackName(PyObject *callback, const QString &funcName); - QByteArray voidType(); - -}} //namespace PySide - -#endif diff --git a/sources/pyside2/libpyside/pysideslot.cpp b/sources/pyside2/libpyside/pysideslot.cpp deleted file mode 100644 index 1ec24ab21..000000000 --- a/sources/pyside2/libpyside/pysideslot.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "dynamicqmetaobject_p.h" -#include "pysidesignal_p.h" -#include "pysideslot_p.h" - -#include <shiboken.h> - -#include <QtCore/QMetaObject> -#include <QtCore/QString> -#include <signature.h> - -using namespace Shiboken; - -struct SlotData -{ - QByteArray name; - QByteArray args; - QByteArray resultType; -}; - -typedef struct -{ - PyObject_HEAD - SlotData *slotData; -} PySideSlot; - -extern "C" -{ - -static int slotTpInit(PyObject *, PyObject *, PyObject *); -static PyObject *slotCall(PyObject *, PyObject *, PyObject *); - -// Class Definition ----------------------------------------------- -static PyType_Slot PySideSlotType_slots[] = { - {Py_tp_call, (void *)slotCall}, - {Py_tp_init, (void *)slotTpInit}, - {Py_tp_new, (void *)PyType_GenericNew}, - {Py_tp_dealloc, (void *)Sbk_object_dealloc}, - {0, 0} -}; -static PyType_Spec PySideSlotType_spec = { - "2:PySide2.QtCore.Slot", - sizeof(PySideSlot), - 0, - Py_TPFLAGS_DEFAULT, - PySideSlotType_slots, -}; - - -static PyTypeObject *PySideSlotTypeF(void) -{ - static PyTypeObject *type = reinterpret_cast<PyTypeObject *>( - SbkType_FromSpec(&PySideSlotType_spec)); - return type; -} - -int slotTpInit(PyObject *self, PyObject *args, PyObject *kw) -{ - static PyObject *emptyTuple = nullptr; - static const char *kwlist[] = {"name", "result", nullptr}; - char *argName = nullptr; - PyObject *argResult = nullptr; - - if (emptyTuple == 0) - emptyTuple = PyTuple_New(0); - - if (!PyArg_ParseTupleAndKeywords(emptyTuple, kw, "|sO:QtCore.Slot", - const_cast<char **>(kwlist), &argName, &argResult)) { - return -1; - } - - PySideSlot *data = reinterpret_cast<PySideSlot *>(self); - if (!data->slotData) - data->slotData = new SlotData; - for(Py_ssize_t i = 0, i_max = PyTuple_Size(args); i < i_max; i++) { - PyObject *argType = PyTuple_GET_ITEM(args, i); - const auto typeName = PySide::Signal::getTypeName(argType); - if (typeName.isEmpty()) { - PyErr_Format(PyExc_TypeError, "Unknown signal argument type: %s", Py_TYPE(argType)->tp_name); - return -1; - } - if (!data->slotData->args.isEmpty()) - data->slotData->args += ','; - data->slotData->args += typeName; - } - - if (argName) - data->slotData->name = argName; - - data->slotData->resultType = argResult - ? PySide::Signal::getTypeName(argResult) : PySide::Signal::voidType(); - - return 0; -} - -PyObject *slotCall(PyObject *self, PyObject *args, PyObject * /* kw */) -{ - static PyObject *pySlotName = nullptr; - PyObject *callback; - callback = PyTuple_GetItem(args, 0); - Py_INCREF(callback); - - if (Py_TYPE(callback)->tp_call != nullptr) { - PySideSlot *data = reinterpret_cast<PySideSlot *>(self); - - if (!data->slotData) - data->slotData = new SlotData; - - if (data->slotData->name.isEmpty()) { - // PYSIDE-198: Use PyObject_GetAttr instead of PepFunction_GetName to support Nuitka. - AutoDecRef funcName(PyObject_GetAttr(callback, PyMagicName::name())); - data->slotData->name = String::toCString(funcName); - } - const QByteArray returnType = QMetaObject::normalizedType(data->slotData->resultType); - const QByteArray signature = - returnType + ' ' + data->slotData->name + '(' + data->slotData->args + ')'; - - if (!pySlotName) - pySlotName = String::fromCString(PYSIDE_SLOT_LIST_ATTR); - - PyObject *pySignature = String::fromCString(signature); - PyObject *signatureList = 0; - if (PyObject_HasAttr(callback, pySlotName)) { - signatureList = PyObject_GetAttr(callback, pySlotName); - } else { - signatureList = PyList_New(0); - PyObject_SetAttr(callback, pySlotName, signatureList); - Py_DECREF(signatureList); - } - - PyList_Append(signatureList, pySignature); - Py_DECREF(pySignature); - - //clear data - delete data->slotData; - data->slotData = nullptr; - return callback; - } - return callback; -} - -} // extern "C" - -namespace PySide { -namespace Slot { - -static const char *Slot_SignatureStrings[] = { - "PySide2.QtCore.Slot(*types:type,name:str=nullptr,result:str=nullptr)->typing.Callable[...,typing.Optional[str]]", - nullptr}; // Sentinel - -void init(PyObject *module) -{ - if (InitSignatureStrings(PySideSlotTypeF(), Slot_SignatureStrings) < 0) - return; - - Py_INCREF(PySideSlotTypeF()); - PyModule_AddObject(module, "Slot", reinterpret_cast<PyObject *>(PySideSlotTypeF())); -} - -} // namespace Slot -} // namespace PySide diff --git a/sources/pyside2/libpyside/pysideslot_p.h b/sources/pyside2/libpyside/pysideslot_p.h deleted file mode 100644 index 3d98e15c4..000000000 --- a/sources/pyside2/libpyside/pysideslot_p.h +++ /dev/null @@ -1,49 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ -#ifndef PYSIDE_SLOT_P_H -#define PYSIDE_SLOT_P_H - -#include <sbkpython.h> -#define PYSIDE_SLOT_LIST_ATTR "_slots" - -namespace PySide { namespace Slot { - void init(PyObject* module); -}} - -#endif diff --git a/sources/pyside2/libpyside/pysidestaticstrings.cpp b/sources/pyside2/libpyside/pysidestaticstrings.cpp deleted file mode 100644 index 760d77632..000000000 --- a/sources/pyside2/libpyside/pysidestaticstrings.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#include "pysidestaticstrings.h" -#include <sbkstring.h> - -#define STATIC_STRING_IMPL(funcName, value) \ -PyObject *funcName() \ -{ \ - static PyObject *const s = Shiboken::String::createStaticString(value); \ - return s; \ -} - -namespace PySide -{ -namespace PyName -{ -STATIC_STRING_IMPL(qtStaticMetaObject, "staticMetaObject") -STATIC_STRING_IMPL(qtConnect, "connect") -STATIC_STRING_IMPL(qtDisconnect, "disconnect") -STATIC_STRING_IMPL(qtEmit, "emit") -STATIC_STRING_IMPL(dict_ring, "dict_ring") -STATIC_STRING_IMPL(name, "name") -STATIC_STRING_IMPL(property, "property") -STATIC_STRING_IMPL(select_id, "select_id") -} // namespace PyName -} // namespace PySide diff --git a/sources/pyside2/libpyside/pysidestaticstrings.h b/sources/pyside2/libpyside/pysidestaticstrings.h deleted file mode 100644 index 1222d8f47..000000000 --- a/sources/pyside2/libpyside/pysidestaticstrings.h +++ /dev/null @@ -1,60 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef PYSIDESTRINGS_H -#define PYSIDESTRINGS_H - -#include <sbkpython.h> - -namespace PySide -{ -namespace PyName -{ -PyObject *qtStaticMetaObject(); -PyObject *qtConnect(); -PyObject *qtDisconnect(); -PyObject *qtEmit(); -PyObject *dict_ring(); -PyObject *name(); -PyObject *property(); -PyObject *select_id(); -} // namespace PyName -} // namespace PySide - -#endif // PYSIDESTRINGS_H diff --git a/sources/pyside2/libpyside/pysideweakref.cpp b/sources/pyside2/libpyside/pysideweakref.cpp deleted file mode 100644 index cd90634bd..000000000 --- a/sources/pyside2/libpyside/pysideweakref.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "pysideweakref.h" - -#include <sbkpython.h> -#include <shiboken.h> - -typedef struct { - PyObject_HEAD - /* Type-specific fields go here. */ - PySideWeakRefFunction weakref_func; - void *user_data; -} PySideCallableObject; - -static PyObject *CallableObject_call(PyObject *callable_object, PyObject *args, PyObject *kw); - -static PyType_Slot PySideCallableObjectType_slots[] = { - {Py_tp_call, (void *)CallableObject_call}, - {Py_tp_dealloc, (void *)Sbk_object_dealloc}, - {0, 0} -}; -static PyType_Spec PySideCallableObjectType_spec = { - "1:PySide.Callable", - sizeof(PySideCallableObject), - 0, - Py_TPFLAGS_DEFAULT, - PySideCallableObjectType_slots, -}; - - -static PyTypeObject *PySideCallableObjectTypeF() -{ - static PyTypeObject *type = - reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideCallableObjectType_spec)); - return type; -} - -static PyObject *CallableObject_call(PyObject *callable_object, PyObject *args, PyObject * /* kw */) -{ - PySideCallableObject *obj = reinterpret_cast<PySideCallableObject *>(callable_object); - obj->weakref_func(obj->user_data); - - Py_XDECREF(PyTuple_GET_ITEM(args, 0)); //kill weak ref object - Py_RETURN_NONE; -} - -namespace PySide { namespace WeakRef { - -PyObject *create(PyObject *obj, PySideWeakRefFunction func, void *userData) -{ - if (obj == Py_None) - return 0; - - if (Py_TYPE(PySideCallableObjectTypeF()) == 0) - { - Py_TYPE(PySideCallableObjectTypeF()) = &PyType_Type; - PyType_Ready(PySideCallableObjectTypeF()); - } - - PyTypeObject *type = PySideCallableObjectTypeF(); - PySideCallableObject *callable = PyObject_New(PySideCallableObject, type); - if (!callable || PyErr_Occurred()) - return 0; - - PyObject *weak = PyWeakref_NewRef(obj, reinterpret_cast<PyObject *>(callable)); - if (!weak || PyErr_Occurred()) - return 0; - - callable->weakref_func = func; - callable->user_data = userData; - Py_DECREF(callable); // PYSIDE-79: after decref the callable is undefined (theoretically) - - return reinterpret_cast<PyObject *>(weak); -} - -} } //namespace - diff --git a/sources/pyside2/libpyside/pysideweakref.h b/sources/pyside2/libpyside/pysideweakref.h deleted file mode 100644 index 628c1eda4..000000000 --- a/sources/pyside2/libpyside/pysideweakref.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef __PYSIDEWEAKREF__ -#define __PYSIDEWEAKREF__ - -#include <pysidemacros.h> -#include <sbkpython.h> - -typedef void (*PySideWeakRefFunction)(void* userData); - -namespace PySide { namespace WeakRef { - -PYSIDE_API PyObject* create(PyObject* ob, PySideWeakRefFunction func, void* userData); - -} //PySide -} //WeakRef - - -#endif diff --git a/sources/pyside2/libpyside/signalmanager.cpp b/sources/pyside2/libpyside/signalmanager.cpp deleted file mode 100644 index 0992cfcfd..000000000 --- a/sources/pyside2/libpyside/signalmanager.cpp +++ /dev/null @@ -1,640 +0,0 @@ -// -*- mode: cpp;-*- -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#include "signalmanager.h" -#include "pysidesignal.h" -#include "pysideproperty.h" -#include "pysideproperty_p.h" -#include "pyside.h" -#include "pyside_p.h" -#include "dynamicqmetaobject.h" -#include "pysidemetafunction_p.h" - -#include <autodecref.h> -#include <basewrapper.h> -#include <bindingmanager.h> -#include <gilstate.h> -#include <sbkconverter.h> -#include <sbkstring.h> -#include <sbkstaticstrings.h> - -#include <QtCore/QDebug> -#include <QtCore/QHash> - -#include <algorithm> -#include <limits> - -// These private headers are needed to throw JavaScript exceptions -#if PYSIDE_QML_PRIVATE_API_SUPPORT - #include <private/qv4engine_p.h> - #include <private/qv4context_p.h> - #include <private/qqmldata_p.h> -#endif - -#if QSLOT_CODE != 1 || QSIGNAL_CODE != 2 -#error QSLOT_CODE and/or QSIGNAL_CODE changed! change the hardcoded stuff to the correct value! -#endif -#define PYSIDE_SLOT '1' -#define PYSIDE_SIGNAL '2' -#include "globalreceiverv2.h" - -namespace { - static PyObject *metaObjectAttr = 0; - - static int callMethod(QObject *object, int id, void **args); - static PyObject *parseArguments(const QList< QByteArray >& paramTypes, void **args); - static bool emitShortCircuitSignal(QObject *source, int signalIndex, PyObject *args); - - static void destroyMetaObject(PyObject *obj) - { - void *ptr = PyCapsule_GetPointer(obj, 0); - auto meta = reinterpret_cast<PySide::MetaObjectBuilder *>(ptr); - SbkObject *wrapper = Shiboken::BindingManager::instance().retrieveWrapper(meta); - if (wrapper) - Shiboken::BindingManager::instance().releaseWrapper(wrapper); - delete meta; - } -} - -namespace PySide { - - -PyObjectWrapper::PyObjectWrapper() - :m_me(Py_None) -{ - // PYSIDE-813: When PYSIDE-164 was solved by adding some thread allowance, - // this code was no longer protected. It was hard to find this connection. - // See the website https://bugreports.qt.io/browse/PYSIDE-813 for details. - Shiboken::GilState gil; - Py_XINCREF(m_me); -} - -PyObjectWrapper::PyObjectWrapper(PyObject *me) - : m_me(me) -{ - Shiboken::GilState gil; - Py_XINCREF(m_me); -} - -PyObjectWrapper::PyObjectWrapper(const PyObjectWrapper &other) - : m_me(other.m_me) -{ - Shiboken::GilState gil; - Py_XINCREF(m_me); -} - -PyObjectWrapper::~PyObjectWrapper() -{ - // Check that Python is still initialized as sometimes this is called by a static destructor - // after Python interpeter is shutdown. - if (!Py_IsInitialized()) - return; - - Shiboken::GilState gil; - Py_XDECREF(m_me); -} - -void PyObjectWrapper::reset(PyObject *o) -{ - Shiboken::GilState gil; - Py_XINCREF(o); - Py_XDECREF(m_me); - m_me = o; -} - -PyObjectWrapper &PyObjectWrapper::operator=(const PySide::PyObjectWrapper &other) -{ - reset(other.m_me); - return *this; -} - -PyObjectWrapper::operator PyObject *() const -{ - return m_me; -} - -QDataStream &operator<<(QDataStream &out, const PyObjectWrapper &myObj) -{ - if (Py_IsInitialized() == 0) { - qWarning() << "Stream operator for PyObject called without python interpreter."; - return out; - } - - static PyObject *reduce_func = 0; - - Shiboken::GilState gil; - if (!reduce_func) { - Shiboken::AutoDecRef pickleModule(PyImport_ImportModule("pickle")); - reduce_func = PyObject_GetAttr(pickleModule, Shiboken::PyName::dumps()); - } - Shiboken::AutoDecRef repr(PyObject_CallFunctionObjArgs(reduce_func, (PyObject *)myObj, NULL)); - if (repr.object()) { - const char *buff = nullptr; - Py_ssize_t size = 0; - if (PyBytes_Check(repr.object())) { - buff = PyBytes_AS_STRING(repr.object()); - size = PyBytes_GET_SIZE(repr.object()); - } else if (Shiboken::String::check(repr.object())) { - buff = Shiboken::String::toCString(repr.object()); - size = Shiboken::String::len(repr.object()); - } - QByteArray data(buff, size); - out << data; - } - return out; -} - -QDataStream &operator>>(QDataStream &in, PyObjectWrapper &myObj) -{ - if (Py_IsInitialized() == 0) { - qWarning() << "Stream operator for PyObject called without python interpreter."; - return in; - } - - static PyObject *eval_func = 0; - - Shiboken::GilState gil; - if (!eval_func) { - Shiboken::AutoDecRef pickleModule(PyImport_ImportModule("pickle")); - eval_func = PyObject_GetAttr(pickleModule, Shiboken::PyName::loads()); - } - - QByteArray repr; - in >> repr; - Shiboken::AutoDecRef pyCode(PyBytes_FromStringAndSize(repr.data(), repr.size())); - Shiboken::AutoDecRef value(PyObject_CallFunctionObjArgs(eval_func, pyCode.object(), 0)); - if (!value.object()) - value.reset(Py_None); - myObj.reset(value); - return in; -} - -}; - -using namespace PySide; - -struct SignalManager::SignalManagerPrivate -{ - SharedMap m_globalReceivers; - - SignalManagerPrivate() - { - m_globalReceivers = SharedMap( new QMap<QByteArray, GlobalReceiverV2 *>() ); - } - - ~SignalManagerPrivate() - { - if (!m_globalReceivers.isNull()) { - // Delete receivers by always retrieving the current first element, because deleting a - // receiver can indirectly delete another one, and if we use qDeleteAll, that could - // cause either a double delete, or iterator invalidation, and thus undefined behavior. - while (!m_globalReceivers->isEmpty()) - delete *m_globalReceivers->cbegin(); - Q_ASSERT(m_globalReceivers->isEmpty()); - } - } -}; - -static void clearSignalManager() -{ - PySide::SignalManager::instance().clear(); -} - -static void PyObject_PythonToCpp_PyObject_PTR(PyObject *pyIn, void *cppOut) -{ - *reinterpret_cast<PyObject **>(cppOut) = pyIn; -} -static PythonToCppFunc is_PyObject_PythonToCpp_PyObject_PTR_Convertible(PyObject *pyIn) -{ - return PyObject_PythonToCpp_PyObject_PTR; -} -static PyObject *PyObject_PTR_CppToPython_PyObject(const void *cppIn) -{ - auto pyOut = reinterpret_cast<PyObject *>(const_cast<void *>(cppIn)); - if (pyOut) - Py_INCREF(pyOut); - return pyOut; -} - -SignalManager::SignalManager() : m_d(new SignalManagerPrivate) -{ - // Register Qt primitive typedefs used on signals. - using namespace Shiboken; - - // Register PyObject type to use in queued signal and slot connections - qRegisterMetaType<PyObjectWrapper>("PyObject"); - - SbkConverter *converter = Shiboken::Conversions::createConverter(&PyBaseObject_Type, nullptr); - Shiboken::Conversions::setCppPointerToPythonFunction(converter, PyObject_PTR_CppToPython_PyObject); - Shiboken::Conversions::setPythonToCppPointerFunctions(converter, PyObject_PythonToCpp_PyObject_PTR, is_PyObject_PythonToCpp_PyObject_PTR_Convertible); - Shiboken::Conversions::registerConverterName(converter, "PyObject"); - Shiboken::Conversions::registerConverterName(converter, "object"); - Shiboken::Conversions::registerConverterName(converter, "PyObjectWrapper"); - Shiboken::Conversions::registerConverterName(converter, "PySide::PyObjectWrapper"); - - PySide::registerCleanupFunction(clearSignalManager); - - if (!metaObjectAttr) - metaObjectAttr = Shiboken::String::fromCString("__METAOBJECT__"); -} - -void SignalManager::clear() -{ - delete m_d; - m_d = new SignalManagerPrivate(); -} - -SignalManager::~SignalManager() -{ - delete m_d; -} - -SignalManager &SignalManager::instance() -{ - static SignalManager me; - return me; -} - -QObject *SignalManager::globalReceiver(QObject *sender, PyObject *callback) -{ - SharedMap globalReceivers = m_d->m_globalReceivers; - QByteArray hash = GlobalReceiverV2::hash(callback); - GlobalReceiverV2 *gr = nullptr; - auto it = globalReceivers->find(hash); - if (it == globalReceivers->end()) { - gr = new GlobalReceiverV2(callback, globalReceivers); - globalReceivers->insert(hash, gr); - if (sender) { - gr->incRef(sender); // create a link reference - gr->decRef(); // remove extra reference - } - } else { - gr = it.value(); - if (sender) - gr->incRef(sender); - } - - return reinterpret_cast<QObject *>(gr); -} - -int SignalManager::countConnectionsWith(const QObject *object) -{ - int count = 0; - for (GlobalReceiverV2Map::const_iterator it = m_d->m_globalReceivers->cbegin(), end = m_d->m_globalReceivers->cend(); it != end; ++it) { - if (it.value()->refCount(object)) - count++; - } - return count; -} - -void SignalManager::notifyGlobalReceiver(QObject *receiver) -{ - reinterpret_cast<GlobalReceiverV2 *>(receiver)->notify(); -} - -void SignalManager::releaseGlobalReceiver(const QObject *source, QObject *receiver) -{ - auto gr = reinterpret_cast<GlobalReceiverV2 *>(receiver); - gr->decRef(source); -} - -int SignalManager::globalReceiverSlotIndex(QObject *receiver, const char *signature) const -{ - return reinterpret_cast<GlobalReceiverV2 *>(receiver)->addSlot(signature); -} - -bool SignalManager::emitSignal(QObject *source, const char *signal, PyObject *args) -{ - if (!Signal::checkQtSignal(signal)) - return false; - signal++; - - int signalIndex = source->metaObject()->indexOfSignal(signal); - if (signalIndex != -1) { - // cryptic but works! - // if the signature doesn't have a '(' it's a shor circuited signal, i.e. std::find - // returned the string null terminator. - bool isShortCircuit = !*std::find(signal, signal + std::strlen(signal), '('); - if (isShortCircuit) - return emitShortCircuitSignal(source, signalIndex, args); - else - return MetaFunction::call(source, signalIndex, args); - } - return false; -} - -int SignalManager::qt_metacall(QObject *object, QMetaObject::Call call, int id, void **args) -{ - const QMetaObject *metaObject = object->metaObject(); - PySideProperty *pp = nullptr; - PyObject *pp_name = nullptr; - QMetaProperty mp; - PyObject *pySelf = nullptr; - int methodCount = metaObject->methodCount(); - int propertyCount = metaObject->propertyCount(); - - if (call != QMetaObject::InvokeMetaMethod) { - mp = metaObject->property(id); - if (!mp.isValid()) { - return id - methodCount; - } - - Shiboken::GilState gil; - pySelf = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(object)); - Q_ASSERT(pySelf); - pp_name = Shiboken::String::fromCString(mp.name()); - pp = Property::getObject(pySelf, pp_name); - if (!pp) { - qWarning("Invalid property: %s.", mp.name()); - Py_XDECREF(pp_name); - return id - methodCount; - } - } - - switch(call) { -#ifndef QT_NO_PROPERTIES - case QMetaObject::ReadProperty: - case QMetaObject::WriteProperty: - case QMetaObject::ResetProperty: - pp->d->metaCallHandler(pp, pySelf, call, args); - break; -#endif - case QMetaObject::InvokeMetaMethod: - id = callMethod(object, id, args); - break; - - default: - qWarning("Unsupported meta invocation type."); - } - - // WARNING Isn't safe to call any metaObject and/or object methods beyond this point - // because the object can be deleted inside the called slot. - - if (call == QMetaObject::InvokeMetaMethod) { - id = id - methodCount; - } else { - id = id - propertyCount; - } - - if (pp || pp_name) { - Shiboken::GilState gil; - Py_XDECREF(pp); - Py_XDECREF(pp_name); - } - - // Bubbles Python exceptions up to the Javascript engine, if called from one - { - Shiboken::GilState gil; - - if (PyErr_Occurred()) { - -#if PYSIDE_QML_PRIVATE_API_SUPPORT - // This JS engine grabber based off of Qt 5.5's `qjsEngine` function - QQmlData *data = QQmlData::get(object, false); - - if (data && !data->jsWrapper.isNullOrUndefined()) { - QV4::ExecutionEngine *engine = data->jsWrapper.engine(); - if (engine->currentStackFrame != nullptr) { - PyObject *errType, *errValue, *errTraceback; - PyErr_Fetch(&errType, &errValue, &errTraceback); - // PYSIDE-464: The error is only valid before PyErr_Restore, - // PYSIDE-464: therefore we take local copies. - Shiboken::AutoDecRef objStr(PyObject_Str(errValue)); - const QString errString = QLatin1String(Shiboken::String::toCString(objStr)); - const bool isSyntaxError = errType == PyExc_SyntaxError; - const bool isTypeError = errType == PyExc_TypeError; - PyErr_Restore(errType, errValue, errTraceback); - - PyErr_Print(); // Note: PyErr_Print clears the error. - - if (isSyntaxError) { - return engine->throwSyntaxError(errString); - } else if (isTypeError) { - return engine->throwTypeError(errString); - } else { - return engine->throwError(errString); - } - } - } -#endif // PYSIDE_QML_PRIVATE_API_SUPPORT - - int reclimit = Py_GetRecursionLimit(); - // Inspired by Python's errors.c: PyErr_GivenExceptionMatches() function. - // Temporarily bump the recursion limit, so that PyErr_Print will not raise a recursion - // error again. Don't do it when the limit is already insanely high, to avoid overflow. - if (reclimit < (1 << 30)) - Py_SetRecursionLimit(reclimit + 5); - PyErr_Print(); - Py_SetRecursionLimit(reclimit); - } - } - - return id; -} - -int SignalManager::callPythonMetaMethod(const QMetaMethod &method, void **args, PyObject *pyMethod, bool isShortCuit) -{ - Q_ASSERT(pyMethod); - - Shiboken::GilState gil; - PyObject *pyArguments = nullptr; - - if (isShortCuit){ - pyArguments = reinterpret_cast<PyObject *>(args[1]); - } else { - pyArguments = parseArguments(method.parameterTypes(), args); - } - - if (pyArguments) { - Shiboken::Conversions::SpecificConverter *retConverter = nullptr; - const char *returnType = method.typeName(); - if (returnType && std::strcmp("", returnType) && std::strcmp("void", returnType)) { - retConverter = new Shiboken::Conversions::SpecificConverter(returnType); - if (!retConverter || !*retConverter) { - PyErr_Format(PyExc_RuntimeError, "Can't find converter for '%s' to call Python meta method.", returnType); - return -1; - } - } - - Shiboken::AutoDecRef retval(PyObject_CallObject(pyMethod, pyArguments)); - - if (!isShortCuit && pyArguments){ - Py_DECREF(pyArguments); - } - - if (!retval.isNull() && retval != Py_None && !PyErr_Occurred() && retConverter) { - retConverter->toCpp(retval, args[0]); - } - delete retConverter; - } - - return -1; -} - -bool SignalManager::registerMetaMethod(QObject *source, const char *signature, QMetaMethod::MethodType type) -{ - int ret = registerMetaMethodGetIndex(source, signature, type); - return (ret != -1); -} - -static MetaObjectBuilder *metaBuilderFromDict(PyObject *dict) -{ - // PYSIDE-803: The dict in this function is the ob_dict of an SbkObject. - // The "metaObjectAttr" entry is only handled in this file. There is no - // way in this function to involve the interpreter. Therefore, we need - // no GIL. - // Note that "SignalManager::registerMetaMethodGetIndex" has write actions - // that might involve the interpreter, but in that context the GIL is held. - if (!dict || !PyDict_Contains(dict, metaObjectAttr)) - return nullptr; - - // PYSIDE-813: The above assumption is not true in debug mode: - // PyDict_GetItem would touch PyThreadState_GET and the global error state. - // PyDict_GetItemWithError instead can work without GIL. - PyObject *pyBuilder = PyDict_GetItemWithError(dict, metaObjectAttr); - return reinterpret_cast<MetaObjectBuilder *>(PyCapsule_GetPointer(pyBuilder, nullptr)); -} - -int SignalManager::registerMetaMethodGetIndex(QObject *source, const char *signature, QMetaMethod::MethodType type) -{ - if (!source) { - qWarning("SignalManager::registerMetaMethodGetIndex(\"%s\") called with source=nullptr.", - signature); - return -1; - } - const QMetaObject *metaObject = source->metaObject(); - int methodIndex = metaObject->indexOfMethod(signature); - // Create the dynamic signal is needed - if (methodIndex == -1) { - SbkObject *self = Shiboken::BindingManager::instance().retrieveWrapper(source); - if (!Shiboken::Object::hasCppWrapper(self)) { - qWarning() << "Invalid Signal signature:" << signature; - return -1; - } else { - auto pySelf = reinterpret_cast<PyObject *>(self); - PyObject *dict = self->ob_dict; - MetaObjectBuilder *dmo = metaBuilderFromDict(dict); - - // Create a instance meta object - if (!dmo) { - dmo = new MetaObjectBuilder(Py_TYPE(pySelf), metaObject); - PyObject *pyDmo = PyCapsule_New(dmo, 0, destroyMetaObject); - PyObject_SetAttr(pySelf, metaObjectAttr, pyDmo); - Py_DECREF(pyDmo); - } - - if (type == QMetaMethod::Signal) - return dmo->addSignal(signature); - else - return dmo->addSlot(signature); - } - } - return methodIndex; -} - -const QMetaObject *SignalManager::retrieveMetaObject(PyObject *self) -{ - // PYSIDE-803: Avoid the GIL in SignalManager::retrieveMetaObject - // This function had the GIL. We do not use the GIL unless we have to. - // metaBuilderFromDict accesses a Python dict, but in that context there - // is no way to reach the interpreter, see "metaBuilderFromDict". - // - // The update function is MetaObjectBuilderPrivate::update in - // dynamicmetaobject.c . That function now uses the GIL when the - // m_dirty flag is set. - Q_ASSERT(self); - - MetaObjectBuilder *builder = metaBuilderFromDict(reinterpret_cast<SbkObject *>(self)->ob_dict); - if (!builder) - builder = &(retrieveTypeUserData(self)->mo); - - return builder->update(); -} - -namespace { - -static int callMethod(QObject *object, int id, void **args) -{ - const QMetaObject *metaObject = object->metaObject(); - QMetaMethod method = metaObject->method(id); - - if (method.methodType() == QMetaMethod::Signal) { - // emit python signal - QMetaObject::activate(object, id, args); - } else { - Shiboken::GilState gil; - auto self = reinterpret_cast<PyObject *>(Shiboken::BindingManager::instance().retrieveWrapper(object)); - QByteArray methodName = method.methodSignature(); - methodName.truncate(methodName.indexOf('(')); - Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(self, methodName)); - return SignalManager::callPythonMetaMethod(method, args, pyMethod, false); - } - return -1; -} - - -static PyObject *parseArguments(const QList<QByteArray>& paramTypes, void **args) -{ - int argsSize = paramTypes.count(); - PyObject *preparedArgs = PyTuple_New(argsSize); - - for (int i = 0, max = argsSize; i < max; ++i) { - void *data = args[i+1]; - const char *dataType = paramTypes[i].constData(); - Shiboken::Conversions::SpecificConverter converter(dataType); - if (converter) { - PyTuple_SET_ITEM(preparedArgs, i, converter.toPython(data)); - } else { - PyErr_Format(PyExc_TypeError, "Can't call meta function because I have no idea how to handle %s", dataType); - Py_DECREF(preparedArgs); - return 0; - } - } - return preparedArgs; -} - -static bool emitShortCircuitSignal(QObject *source, int signalIndex, PyObject *args) -{ - void *signalArgs[2] = {nullptr, args}; - source->qt_metacall(QMetaObject::InvokeMetaMethod, signalIndex, signalArgs); - return true; -} - -} //namespace diff --git a/sources/pyside2/libpyside/signalmanager.h b/sources/pyside2/libpyside/signalmanager.h deleted file mode 100644 index fe077bd1a..000000000 --- a/sources/pyside2/libpyside/signalmanager.h +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 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$ -** -****************************************************************************/ - -#ifndef SIGNALMANAGER_H -#define SIGNALMANAGER_H - -#include "pysidemacros.h" - -#include <sbkpython.h> -#include <shibokenmacros.h> - -#include <QtCore/QMetaMethod> - -QT_FORWARD_DECLARE_CLASS(QDataStream) - -namespace PySide -{ - -/// Thin wrapper for PyObject which increases the reference count at the constructor but *NOT* at destructor. -class PYSIDE_API PyObjectWrapper -{ -public: - PyObjectWrapper(PyObjectWrapper&&) = delete; - PyObjectWrapper& operator=(PyObjectWrapper &&) = delete; - - PyObjectWrapper(); - explicit PyObjectWrapper(PyObject* me); - PyObjectWrapper(const PyObjectWrapper &other); - PyObjectWrapper& operator=(const PyObjectWrapper &other); - - void reset(PyObject *o); - - ~PyObjectWrapper(); - operator PyObject*() const; - -private: - PyObject* m_me; -}; - -PYSIDE_API QDataStream &operator<<(QDataStream& out, const PyObjectWrapper& myObj); -PYSIDE_API QDataStream &operator>>(QDataStream& in, PyObjectWrapper& myObj); - -class PYSIDE_API SignalManager -{ - Q_DISABLE_COPY(SignalManager) -public: - static SignalManager& instance(); - - QObject* globalReceiver(QObject* sender, PyObject* callback); - void releaseGlobalReceiver(const QObject* sender, QObject* receiver); - int globalReceiverSlotIndex(QObject* sender, const char* slotSignature) const; - void notifyGlobalReceiver(QObject* receiver); - - bool emitSignal(QObject* source, const char* signal, PyObject* args); - static int qt_metacall(QObject* object, QMetaObject::Call call, int id, void** args); - - // Used to register a new signal/slot on QMetaobject of source. - static bool registerMetaMethod(QObject* source, const char* signature, QMetaMethod::MethodType type); - static int registerMetaMethodGetIndex(QObject* source, const char* signature, QMetaMethod::MethodType type); - - // used to discovery metaobject - static const QMetaObject* retrieveMetaObject(PyObject* self); - - // Used to discovery if SignalManager was connected with object "destroyed()" signal. - int countConnectionsWith(const QObject *object); - - // Disconnect all signals managed by Globalreceiver - void clear(); - - // Utility function to call a python method usign args received in qt_metacall - static int callPythonMetaMethod(const QMetaMethod& method, void** args, PyObject* obj, bool isShortCuit); - -private: - struct SignalManagerPrivate; - SignalManagerPrivate* m_d; - - SignalManager(); - ~SignalManager(); -}; - -} - -Q_DECLARE_METATYPE(PySide::PyObjectWrapper) - -#endif |