aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2/libpyside
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside2/libpyside')
-rw-r--r--sources/pyside2/libpyside/CMakeLists.txt165
-rw-r--r--sources/pyside2/libpyside/PySide2Config-spec.cmake.in18
-rw-r--r--sources/pyside2/libpyside/PySide2Config.cmake.in5
-rw-r--r--sources/pyside2/libpyside/PySide2ConfigVersion.cmake.in10
-rw-r--r--sources/pyside2/libpyside/destroylistener.cpp106
-rw-r--r--sources/pyside2/libpyside/destroylistener.h72
-rw-r--r--sources/pyside2/libpyside/dynamicqmetaobject.cpp901
-rw-r--r--sources/pyside2/libpyside/dynamicqmetaobject.h82
-rw-r--r--sources/pyside2/libpyside/dynamicqmetaobject_p.h108
-rw-r--r--sources/pyside2/libpyside/globalreceiver.cpp330
-rw-r--r--sources/pyside2/libpyside/globalreceiver.h80
-rw-r--r--sources/pyside2/libpyside/globalreceiverv2.cpp358
-rw-r--r--sources/pyside2/libpyside/globalreceiverv2.h149
-rw-r--r--sources/pyside2/libpyside/pyside.cpp387
-rw-r--r--sources/pyside2/libpyside/pyside.h157
-rw-r--r--sources/pyside2/libpyside/pyside2.pc.in14
-rw-r--r--sources/pyside2/libpyside/pysideclassinfo.cpp229
-rw-r--r--sources/pyside2/libpyside/pysideclassinfo.h68
-rw-r--r--sources/pyside2/libpyside/pysideclassinfo_p.h72
-rw-r--r--sources/pyside2/libpyside/pysideconversions.h275
-rw-r--r--sources/pyside2/libpyside/pysidemacros.h64
-rw-r--r--sources/pyside2/libpyside/pysidemetafunction.cpp253
-rw-r--r--sources/pyside2/libpyside/pysidemetafunction.h76
-rw-r--r--sources/pyside2/libpyside/pysidemetafunction_p.h62
-rw-r--r--sources/pyside2/libpyside/pysideproperty.cpp519
-rw-r--r--sources/pyside2/libpyside/pysideproperty.h117
-rw-r--r--sources/pyside2/libpyside/pysideproperty_p.h184
-rw-r--r--sources/pyside2/libpyside/pysideqflags.cpp167
-rw-r--r--sources/pyside2/libpyside/pysideqflags.h79
-rw-r--r--sources/pyside2/libpyside/pysidesignal.cpp1070
-rw-r--r--sources/pyside2/libpyside/pysidesignal.h173
-rw-r--r--sources/pyside2/libpyside/pysidesignal_p.h82
-rw-r--r--sources/pyside2/libpyside/pysideslot.cpp220
-rw-r--r--sources/pyside2/libpyside/pysideslot_p.h49
-rw-r--r--sources/pyside2/libpyside/pysideweakref.cpp141
-rw-r--r--sources/pyside2/libpyside/pysideweakref.h56
-rw-r--r--sources/pyside2/libpyside/signalmanager.cpp.in726
-rw-r--r--sources/pyside2/libpyside/signalmanager.h123
38 files changed, 7747 insertions, 0 deletions
diff --git a/sources/pyside2/libpyside/CMakeLists.txt b/sources/pyside2/libpyside/CMakeLists.txt
new file mode 100644
index 000000000..b740e4039
--- /dev/null
+++ b/sources/pyside2/libpyside/CMakeLists.txt
@@ -0,0 +1,165 @@
+project(libpyside)
+
+if(${Qt5Qml_FOUND})
+ if(NOT "${Qt5Qml_PRIVATE_INCLUDE_DIRS}" MATCHES "/QtQml/")
+ string(REPLACE "/QtCore" "/QtQml" replaceme "${Qt5Core_PRIVATE_INCLUDE_DIRS}")
+ list(APPEND Qt5Qml_PRIVATE_INCLUDE_DIRS ${replaceme})
+ list(REMOVE_DUPLICATES Qt5Qml_PRIVATE_INCLUDE_DIRS)
+ endif()
+endif()
+
+if(${Qt5Quick_FOUND})
+ if(NOT "${Qt5Quick_PRIVATE_INCLUDE_DIRS}" MATCHES "/QtQuick/")
+ string(REPLACE "/QtCore" "/QtQuick" replaceme "${Qt5Core_PRIVATE_INCLUDE_DIRS}")
+ list(APPEND Qt5Quick_PRIVATE_INCLUDE_DIRS ${Qt5Qml_PRIVATE_INCLUDE_DIRS})
+ list(APPEND Qt5Quick_PRIVATE_INCLUDE_DIRS ${replaceme})
+ list(REMOVE_DUPLICATES Qt5Quick_PRIVATE_INCLUDE_DIRS)
+ endif()
+endif()
+
+if(Qt5Qml_FOUND)
+ # Used for registering custom QQuickItem classes defined in Python code.
+ set(QML_SUPPORT 1)
+ set(QML_INCLUDES ${Qt5Qml_INCLUDE_DIRS})
+ set(QML_LIBRARIES ${Qt5Qml_LIBRARIES})
+
+ if(Qt5Qml_PRIVATE_INCLUDE_DIRS)
+ # Used for transforming QML exceptions into Python exceptions.
+ set(QML_PRIVATE_API_SUPPORT 1)
+ set(QML_INCLUDES ${QML_INCLUDES} ${Qt5Qml_PRIVATE_INCLUDE_DIRS})
+ else()
+ set(QML_PRIVATE_API_SUPPORT 0)
+ 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_INCLUDES "")
+ set(QML_LIBRARIES "")
+endif()
+
+qt5_wrap_cpp(DESTROYLISTENER_MOC "destroylistener.h")
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/signalmanager.cpp.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/signalmanager.cpp" @ONLY)
+
+set(libpyside_SRC
+ dynamicqmetaobject.cpp
+ destroylistener.cpp
+ ${CMAKE_CURRENT_BINARY_DIR}/signalmanager.cpp
+ globalreceiver.cpp
+ globalreceiverv2.cpp
+ pysideclassinfo.cpp
+ pysidemetafunction.cpp
+ pysidesignal.cpp
+ pysideslot.cpp
+ pysideproperty.cpp
+ pysideqflags.cpp
+ pysideweakref.cpp
+ pyside.cpp
+ ${DESTROYLISTENER_MOC}
+)
+
+# 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")
+
+# Example files.
+file(GLOB_RECURSE example_folder_py_files "../../pyside2-examples/*.py")
+
+# Mostly for setup.py.
+file(GLOB setup_folder_py_files "../../../*.py")
+
+set(other_files ${pyside_folder_py_files} ${example_folder_py_files} ${setup_folder_py_files})
+add_other_files(${other_files})
+
+include_directories(${CMAKE_CURRENT_SOURCE_DIR}
+ ${SHIBOKEN_INCLUDE_DIR}
+ ${SHIBOKEN_PYTHON_INCLUDE_DIR}
+ ${QML_INCLUDES}
+ ${Qt5Core_INCLUDE_DIRS})
+add_library(pyside2 SHARED ${libpyside_SRC} ${other_files})
+target_link_libraries(pyside2
+ ${SHIBOKEN_PYTHON_LIBRARIES}
+ ${SHIBOKEN_LIBRARY}
+ ${QML_LIBRARIES}
+ ${Qt5Core_LIBRARIES})
+
+set_target_properties(pyside2 PROPERTIES
+ VERSION ${BINDING_API_VERSION}
+ SOVERSION "${BINDING_API_MAJOR_VERSION}.${BINDING_API_MINOR_VERSION}"
+ OUTPUT_NAME "pyside2${pyside2_SUFFIX}${SHIBOKEN_PYTHON_EXTENSION_SUFFIX}"
+ DEFINE_SYMBOL PYSIDE_EXPORTS)
+
+if(Qt5Core_VERSION VERSION_GREATER "5.7.1")
+ set_property(TARGET pyside2 PROPERTY CXX_STANDARD 11)
+endif()
+
+if(QML_SUPPORT)
+ target_compile_definitions(pyside2 PUBLIC PYSIDE_QML_SUPPORT=1)
+endif()
+
+#
+# install stuff
+#
+
+set(libpyside_HEADERS
+ destroylistener.h
+ dynamicqmetaobject.h
+ globalreceiver.h
+ pysideclassinfo.h
+ pysideconversions.h
+ pysidemacros.h
+ signalmanager.h
+ pyside.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)
+# create cmake-config files
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PySide2Config.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/PySide2Config.cmake" @ONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PySide2Config-spec.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/PySide2Config${SHIBOKEN_PYTHON_EXTENSION_SUFFIX}.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 pyside2
+ LIBRARY DESTINATION "${LIB_INSTALL_DIR}"
+ ARCHIVE DESTINATION "${LIB_INSTALL_DIR}"
+ RUNTIME DESTINATION bin)
+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}/PySide2Config${SHIBOKEN_PYTHON_EXTENSION_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
new file mode 100644
index 000000000..205b6f10e
--- /dev/null
+++ b/sources/pyside2/libpyside/PySide2Config-spec.cmake.in
@@ -0,0 +1,18 @@
+# PYSIDE_INCLUDE_DIR - Directories to include to use PySide2
+# PYSIDE_LIBRARY - Files to link against to use PySide2
+# 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
+
+SET(PYSIDE_INCLUDE_DIR "@CMAKE_INSTALL_PREFIX@/include/PySide2@pyside2_SUFFIX@")
+# Platform specific library names
+if(MSVC)
+ SET(PYSIDE_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@pyside2@pyside2_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@SHIBOKEN_PYTHON_EXTENSION_SUFFIX@.lib")
+elseif(CYGWIN)
+ SET(PYSIDE_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@pyside2@pyside2_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@SHIBOKEN_PYTHON_EXTENSION_SUFFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@")
+elseif(WIN32)
+ SET(PYSIDE_LIBRARY "@CMAKE_INSTALL_PREFIX@/bin/@CMAKE_SHARED_LIBRARY_PREFIX@pyside2@pyside2_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@SHIBOKEN_PYTHON_EXTENSION_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@")
+else()
+ SET(PYSIDE_LIBRARY "@LIB_INSTALL_DIR@/@CMAKE_SHARED_LIBRARY_PREFIX@pyside2@pyside2_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@@SHIBOKEN_PYTHON_EXTENSION_SUFFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@")
+endif()
+SET(PYSIDE_PYTHONPATH "@SITE_PACKAGE@")
+SET(PYSIDE_TYPESYSTEMS "@CMAKE_INSTALL_PREFIX@/share/PySide2@pyside2_SUFFIX@/typesystems")
diff --git a/sources/pyside2/libpyside/PySide2Config.cmake.in b/sources/pyside2/libpyside/PySide2Config.cmake.in
new file mode 100644
index 000000000..cf3e6d1a6
--- /dev/null
+++ b/sources/pyside2/libpyside/PySide2Config.cmake.in
@@ -0,0 +1,5 @@
+if (NOT PYTHON_BASENAME)
+ message(STATUS "PySide2Config: Using default python: @SHIBOKEN_PYTHON_EXTENSION_SUFFIX@")
+ SET(PYTHON_BASENAME @SHIBOKEN_PYTHON_EXTENSION_SUFFIX@)
+endif()
+include(@LIB_INSTALL_DIR@/cmake/PySide2-@BINDING_API_VERSION@/PySide2Config${PYTHON_BASENAME}.cmake)
diff --git a/sources/pyside2/libpyside/PySide2ConfigVersion.cmake.in b/sources/pyside2/libpyside/PySide2ConfigVersion.cmake.in
new file mode 100644
index 000000000..f5073ce08
--- /dev/null
+++ b/sources/pyside2/libpyside/PySide2ConfigVersion.cmake.in
@@ -0,0 +1,10 @@
+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/destroylistener.cpp b/sources/pyside2/libpyside/destroylistener.cpp
new file mode 100644
index 000000000..c1d3afb89
--- /dev/null
+++ b/sources/pyside2/libpyside/destroylistener.cpp
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "destroylistener.h"
+
+#include <QObject>
+#include <shiboken.h>
+#include <QDebug>
+#include <QMutex>
+
+PySide::DestroyListener* PySide::DestroyListener::m_instance = 0;
+
+namespace PySide
+{
+
+struct DestroyListenerPrivate
+{
+ static bool m_destroyed;
+};
+
+
+DestroyListener* DestroyListener::instance()
+{
+ if (!m_instance)
+ m_instance = new DestroyListener(0);
+ return m_instance;
+}
+
+void DestroyListener::destroy()
+{
+ if (m_instance) {
+ m_instance->disconnect();
+ delete m_instance;
+ m_instance = 0;
+ }
+}
+
+void DestroyListener::listen(QObject *obj)
+{
+ SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(obj);
+ if (!wrapper) // avoid problem with multiple inheritance
+ return;
+
+ if (Py_IsInitialized() == 0)
+ onObjectDestroyed(obj);
+ else
+ QObject::connect(obj, SIGNAL(destroyed(QObject*)), this, SLOT(onObjectDestroyed(QObject*)), Qt::DirectConnection);
+}
+
+void DestroyListener::onObjectDestroyed(QObject* obj)
+{
+ SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(obj);
+ if (wrapper) //make sure the object exists before destroy
+ Shiboken::Object::destroy(wrapper, obj);
+}
+
+DestroyListener::DestroyListener(QObject *parent)
+ : QObject(parent)
+{
+ m_d = new DestroyListenerPrivate();
+}
+
+DestroyListener::~DestroyListener()
+{
+ delete m_d;
+}
+
+}//namespace
+
diff --git a/sources/pyside2/libpyside/destroylistener.h b/sources/pyside2/libpyside/destroylistener.h
new file mode 100644
index 000000000..c4aa55494
--- /dev/null
+++ b/sources/pyside2/libpyside/destroylistener.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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_DESTROY_LISTENER
+#define PYSIDE_DESTROY_LISTENER
+
+
+#include <QObject>
+#include "pysidemacros.h"
+
+namespace PySide
+{
+struct DestroyListenerPrivate;
+/// \deprecated This class is deprecated and isn't used by libpyside anymore.
+class PYSIDE_API DestroyListener : public QObject
+{
+ Q_OBJECT
+ public:
+ PYSIDE_DEPRECATED(static DestroyListener* instance());
+ static void destroy();
+ void listen(QObject* obj);
+
+ public slots:
+ void onObjectDestroyed(QObject* obj);
+
+ private:
+ static DestroyListener* m_instance;
+ DestroyListenerPrivate* m_d;
+ DestroyListener(QObject *parent);
+ ~DestroyListener();
+};
+
+}//namespace
+
+#endif
+
diff --git a/sources/pyside2/libpyside/dynamicqmetaobject.cpp b/sources/pyside2/libpyside/dynamicqmetaobject.cpp
new file mode 100644
index 000000000..651ed70c1
--- /dev/null
+++ b/sources/pyside2/libpyside/dynamicqmetaobject.cpp
@@ -0,0 +1,901 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QByteArray>
+#include <QString>
+#include <QStringList>
+#include <QList>
+#include <QLinkedList>
+#include <QObject>
+#include <cstring>
+#include <QDebug>
+#include <QMetaMethod>
+#include <shiboken.h>
+
+
+#define EMPTY_META_METHOD "0()"
+
+using namespace PySide;
+
+enum PropertyFlags {
+ Invalid = 0x00000000,
+ Readable = 0x00000001,
+ Writable = 0x00000002,
+ Resettable = 0x00000004,
+ EnumOrFlag = 0x00000008,
+ StdCppSet = 0x00000100,
+// Override = 0x00000200,
+ Constant = 0x00000400,
+ Final = 0x00000800,
+ Designable = 0x00001000,
+ ResolveDesignable = 0x00002000,
+ Scriptable = 0x00004000,
+ ResolveScriptable = 0x00008000,
+ Stored = 0x00010000,
+ ResolveStored = 0x00020000,
+ Editable = 0x00040000,
+ ResolveEditable = 0x00080000,
+ User = 0x00100000,
+ ResolveUser = 0x00200000,
+ Notify = 0x00400000
+};
+
+// these values are from moc source code, generator.cpp:66
+enum MethodFlags {
+ AccessPrivate = 0x00,
+ AccessProtected = 0x01,
+ AccessPublic = 0x02,
+ MethodMethod = 0x00,
+ MethodSignal = 0x04,
+ MethodSlot = 0x08,
+ MethodConstructor = 0x0c,
+ MethodCompatibility = 0x10,
+ MethodCloned = 0x20,
+ MethodScriptable = 0x40
+};
+
+enum MetaDataFlags {
+ IsUnresolvedType = 0x80000000,
+ TypeNameIndexMask = 0x7FFFFFFF
+};
+
+class DynamicQMetaObject::DynamicQMetaObjectPrivate
+{
+public:
+ QList<MethodData> m_methods;
+ QList<PropertyData> m_properties;
+
+ QMap<QByteArray, QByteArray> m_info;
+ QByteArray m_className;
+ bool m_updated; // when the meta data is not update
+ int m_methodOffset;
+ int m_propertyOffset;
+ int m_dataSize;
+ int m_emptyMethod;
+ int m_nullIndex;
+
+ DynamicQMetaObjectPrivate()
+ : m_updated(false), m_methodOffset(0), m_propertyOffset(0),
+ m_dataSize(0), m_emptyMethod(-1), m_nullIndex(0) {}
+
+ int createMetaData(QMetaObject* metaObj, QLinkedList<QByteArray> &strings);
+ void updateMetaObject(QMetaObject* metaObj);
+ void writeMethodsData(const QList<MethodData>& methods, unsigned int** data, QLinkedList<QByteArray>& strings, int* prtIndex, int nullIndex, int flags);
+ void writeStringData(char *, QLinkedList<QByteArray> &strings);
+ int getPropertyNotifyId(PySideProperty *property) const;
+};
+
+bool sortMethodSignalSlot(const MethodData &m1, const MethodData &m2)
+{
+ if (m1.methodType() == QMetaMethod::Signal)
+ return m2.methodType() == QMetaMethod::Slot;
+ return false;
+}
+
+static int registerString(const QByteArray& s, QLinkedList<QByteArray>& strings)
+{
+ int idx = 0;
+ QLinkedList<QByteArray>::const_iterator it = strings.begin();
+ QLinkedList<QByteArray>::const_iterator itEnd = strings.end();
+ while (it != itEnd) {
+ if (strcmp(*it, s) == 0)
+ return idx;
+ ++idx;
+ ++it;
+ }
+ strings.append(s);
+ return idx;
+}
+
+static int blobSize(QLinkedList<QByteArray> &strings)
+{
+ int size = strings.size() * sizeof(QByteArrayData);
+
+ QByteArray str;
+ QByteArray debug_str;
+ foreach (const QByteArray &field, strings) {
+ str.append(field);
+ str.append(char(0));
+
+ debug_str.append(field);
+ debug_str.append('|');
+ }
+ //qDebug()<<debug_str;
+ size += str.size();
+ return size;
+}
+
+static int aggregateParameterCount(const QList<MethodData> &methods)
+{
+ int sum = 0;
+ for (int i = 0; i < methods.size(); ++i)
+ sum += methods.at(i).parameterCount() * 2 + 1; // nb_param*2 (type and names) +1 for return type
+ return sum;
+}
+
+static void writeString(char *out, int i, const QByteArray &str,
+ const int offsetOfStringdataMember, int &stringdataOffset)
+{
+ int size = str.size();
+ qptrdiff offset = offsetOfStringdataMember + stringdataOffset
+ - i * sizeof(QByteArrayData);
+ const QByteArrayData data =
+ Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset);
+
+ memcpy(out + i * sizeof(QByteArrayData), &data, sizeof(QByteArrayData));
+
+ memcpy(out + offsetOfStringdataMember + stringdataOffset, str.constData(), size);
+ out[offsetOfStringdataMember + stringdataOffset + size] = '\0';
+
+ stringdataOffset += size + 1;
+}
+
+static int qvariant_nameToType(const char* name)
+{
+ if (!name)
+ return 0;
+
+ if (strcmp(name, "QVariant") == 0)
+ return 0xffffffff;
+ if (strcmp(name, "QCString") == 0)
+ return QMetaType::QByteArray;
+ if (strcmp(name, "Q_LLONG") == 0)
+ return QMetaType::LongLong;
+ if (strcmp(name, "Q_ULLONG") == 0)
+ return QMetaType::ULongLong;
+ if (strcmp(name, "QIconSet") == 0)
+ return QMetaType::QIcon;
+
+ uint tp = QMetaType::type(name);
+ return tp < QMetaType::User ? tp : 0;
+}
+
+/*
+ Returns true if the type is a QVariant types.
+*/
+static bool isVariantType(const char* type)
+{
+ return qvariant_nameToType(type) != 0;
+}
+
+/*!
+ Returns true if the type is qreal.
+*/
+static bool isQRealType(const char *type)
+{
+ return strcmp(type, "qreal") == 0;
+}
+
+uint PropertyData::flags() const
+{
+ const QByteArray btype(type());
+ const char* typeName = btype.data();
+ uint flags = Invalid;
+ if (!isVariantType(typeName))
+ flags |= EnumOrFlag;
+ else if (!isQRealType(typeName))
+ flags |= qvariant_nameToType(typeName) << 24;
+
+ if (PySide::Property::isReadable(m_data))
+ flags |= Readable;
+
+ if (PySide::Property::isWritable(m_data))
+ flags |= Writable;
+
+ if (PySide::Property::hasReset(m_data))
+ flags |= Resettable;
+
+ if (PySide::Property::isDesignable(m_data))
+ flags |= Designable;
+ else
+ flags |= ResolveDesignable;
+
+ if (PySide::Property::isScriptable(m_data))
+ flags |= Scriptable;
+ else
+ flags |= ResolveScriptable;
+
+ if (PySide::Property::isStored(m_data))
+ flags |= Stored;
+ else
+ flags |= ResolveStored;
+
+ //EDITABLE
+ flags |= ResolveEditable;
+
+ if (PySide::Property::isUser(m_data))
+ flags |= User;
+ else
+ flags |= ResolveUser;
+
+ if (m_cachedNotifyId != -1)
+ flags |= Notify;
+
+ if (PySide::Property::isConstant(m_data))
+ flags |= Constant;
+
+ if (PySide::Property::isFinal(m_data))
+ flags |= Final;
+
+ return flags;
+}
+
+// const QByteArray with EMPTY_META_METHOD, used to save some memory
+const QByteArray MethodData::m_emptySig(EMPTY_META_METHOD);
+
+MethodData::MethodData()
+ : m_signature(m_emptySig)
+{
+}
+
+MethodData::MethodData(QMetaMethod::MethodType mtype, const QByteArray& signature, const QByteArray& rtype)
+ : m_signature(QMetaObject::normalizedSignature(signature.constData()))
+ , m_rtype(QMetaObject::normalizedSignature(rtype.constData()))
+ , m_mtype(mtype)
+{
+}
+
+void MethodData::clear()
+{
+ m_signature = m_emptySig;
+ m_rtype.clear();
+}
+
+bool MethodData::isValid() const
+{
+ return m_signature != m_emptySig;
+}
+
+QList<QByteArray> MethodData::parameterTypes() const
+{
+ const char *signature = m_signature.constData();
+ QList<QByteArray> list;
+ while (*signature && *signature != '(')
+ ++signature;
+ while (*signature && *signature != ')' && *++signature != ')') {
+ const char *begin = signature;
+ int level = 0;
+ while (*signature && (level > 0 || *signature != ',') && *signature != ')') {
+ if (*signature == '<')
+ ++level;
+ else if (*signature == '>')
+ --level;
+ ++signature;
+ }
+ list += QByteArray(begin, signature - begin);
+ }
+ return list;
+}
+
+int MethodData::parameterCount() const
+{
+ return parameterTypes().size();
+}
+
+QByteArray MethodData::name() const
+{
+ return m_signature.left(qMax(m_signature.indexOf('('), 0));
+}
+
+PropertyData::PropertyData()
+ : m_cachedNotifyId(0), m_data(0)
+{
+}
+
+PropertyData::PropertyData(const char* name, int notifyId, PySideProperty* data)
+ : m_name(name), m_cachedNotifyId(notifyId), m_data(data)
+{
+}
+
+QByteArray PropertyData::type() const
+{
+ return QByteArray(PySide::Property::getTypeName(m_data));
+}
+
+
+bool PropertyData::isValid() const
+{
+ return !m_name.isEmpty();
+}
+
+int PropertyData::cachedNotifyId() const
+{
+ return m_cachedNotifyId;
+}
+
+bool PropertyData::operator==(const PropertyData& other) const
+{
+ return m_data == other.m_data;
+}
+
+bool PropertyData::operator==(const char* name) const
+{
+ return m_name == name;
+}
+
+
+DynamicQMetaObject::DynamicQMetaObject(PyTypeObject* type, const QMetaObject* base)
+ : m_d(new DynamicQMetaObjectPrivate)
+{
+ d.superdata = base;
+ d.stringdata = NULL;
+ d.data = NULL;
+ d.extradata = NULL;
+ d.relatedMetaObjects = NULL;
+ d.static_metacall = NULL;
+
+ m_d->m_className = QByteArray(type->tp_name).split('.').last();
+ m_d->m_methodOffset = base->methodCount() - 1;
+ m_d->m_propertyOffset = base->propertyCount() - 1;
+ parsePythonType(type);
+}
+
+DynamicQMetaObject::DynamicQMetaObject(const char* className, const QMetaObject* metaObject)
+ : m_d(new DynamicQMetaObjectPrivate)
+{
+ d.superdata = metaObject;
+ d.stringdata = 0;
+ d.data = 0;
+ d.extradata = 0;
+ d.relatedMetaObjects = NULL;
+ d.static_metacall = NULL;
+
+ m_d->m_className = className;
+ m_d->m_methodOffset = metaObject->methodCount() - 1;
+ m_d->m_propertyOffset = metaObject->propertyCount() - 1;
+}
+
+DynamicQMetaObject::~DynamicQMetaObject()
+{
+ free(reinterpret_cast<char *>(const_cast<QByteArrayData *>(d.stringdata)));
+ free(const_cast<uint*>(d.data));
+ delete m_d;
+}
+
+int DynamicQMetaObject::addMethod(QMetaMethod::MethodType mtype, const char* signature, const char* type)
+{
+ int index = -1;
+ int counter = 0;
+
+ QList<MethodData>::iterator it = m_d->m_methods.begin();
+ for (; it != m_d->m_methods.end(); ++it) {
+ if ((it->signature() == signature) && (it->methodType() == mtype))
+ return m_d->m_methodOffset + counter;
+ else if (!it->isValid()) {
+ index = counter;
+ }
+ counter++;
+ }
+
+ // Common mistake not to add parentheses to the signature.
+ if ((strchr(signature, ')') == 0) || ((strchr(signature, '(') == 0))) {
+ const QString message =
+ QLatin1String("DynamicQMetaObject::addMethod: Invalid method signature "
+ "provided for ") + QLatin1String(signature);
+ const QByteArray messageLatin = message.toLatin1();
+ PyErr_WarnEx(PyExc_RuntimeWarning, messageLatin.constData(), 0);
+ return -1;
+ }
+
+ //has blank method
+ if (index != -1) {
+ m_d->m_methods[index] = MethodData(mtype, signature, type);
+ index++;
+ } else {
+ m_d->m_methods << MethodData(mtype, signature, type);
+ index = m_d->m_methods.size();
+ }
+
+ m_d->m_updated = false;
+ return m_d->m_methodOffset + index;
+}
+
+void DynamicQMetaObject::removeMethod(QMetaMethod::MethodType mtype, uint index)
+{
+ const char* methodSig = method(index).methodSignature();
+ QList<MethodData>::iterator it = m_d->m_methods.begin();
+ for (; it != m_d->m_methods.end(); ++it) {
+ if ((it->signature() == methodSig) && (it->methodType() == mtype)){
+ it->clear();
+ m_d->m_updated = false;
+ break;
+ }
+ }
+}
+
+int DynamicQMetaObject::addSignal(const char* signal, const char* type)
+{
+ return addMethod(QMetaMethod::Signal, signal, type);
+}
+
+int DynamicQMetaObject::addSlot(const char* slot, const char* type)
+{
+ return addMethod(QMetaMethod::Slot, slot, type);
+}
+
+void DynamicQMetaObject::removeSlot(uint index)
+{
+ removeMethod(QMetaMethod::Slot, index);
+}
+
+void DynamicQMetaObject::removeSignal(uint index)
+{
+ removeMethod(QMetaMethod::Signal, index);
+}
+
+int DynamicQMetaObject::addProperty(const char* propertyName, PyObject* data)
+{
+ int index = m_d->m_properties.indexOf(propertyName);
+ if (index != -1)
+ return m_d->m_propertyOffset + index;
+
+ // retrieve notifyId
+ PySideProperty *property = reinterpret_cast<PySideProperty *>(data);
+ const int notifyId = m_d->getPropertyNotifyId(property);
+
+ //search for a empty space
+ PropertyData blank;
+ index = m_d->m_properties.indexOf(blank);
+ if (index != -1) {
+ m_d->m_properties[index] = PropertyData(propertyName, notifyId, property);
+ } else {
+ m_d->m_properties << PropertyData(propertyName, notifyId, property);
+ index = m_d->m_properties.size();
+ }
+ m_d->m_updated = false;
+ return m_d->m_propertyOffset + index;
+}
+
+int DynamicQMetaObject::DynamicQMetaObjectPrivate::getPropertyNotifyId(PySideProperty *property) const
+{
+ int notifyId = -1;
+ if (property->d->notify) {
+ const char *signalNotify = PySide::Property::getNotifyName(property);
+ if (signalNotify) {
+ const MethodData signalObject(QMetaMethod::Signal, signalNotify, "");
+ notifyId = m_methods.indexOf(signalObject);
+ }
+ }
+ return notifyId;
+}
+
+void DynamicQMetaObject::addInfo(const char* key, const char* value)
+{
+ m_d->m_info[key] = value;
+}
+
+void DynamicQMetaObject::addInfo(QMap<QByteArray, QByteArray> info)
+{
+ QMap<QByteArray, QByteArray>::const_iterator i = info.constBegin();
+ while (i != info.constEnd()) {
+ m_d->m_info[i.key()] = i.value();
+ ++i;
+ }
+ m_d->m_updated = false;
+}
+
+const QMetaObject* DynamicQMetaObject::update() const
+{
+ if (!m_d->m_updated) {
+ m_d->updateMetaObject(const_cast<DynamicQMetaObject*>(this));
+ m_d->m_updated = true;
+ }
+ return this;
+}
+
+void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeMethodsData(const QList<MethodData>& methods,
+ unsigned int** data,
+ QLinkedList<QByteArray>& strings,
+ int* prtIndex,
+ int nullIndex,
+ int flags)
+{
+ int index = *prtIndex;
+ int paramsIndex = index + methods.count() * 5;
+
+ QList<MethodData>::const_iterator it = methods.begin();
+
+ if (m_emptyMethod == -1)
+ m_emptyMethod = registerString(EMPTY_META_METHOD, strings);
+
+ for (; it != methods.end(); ++it) {
+ int name_idx = 0;
+ int argc = it->parameterCount();
+ if (it->signature() != EMPTY_META_METHOD)
+ name_idx = registerString(it->name(), strings);
+ else
+ name_idx = m_emptyMethod; // func name
+
+ (*data)[index++] = name_idx;
+ (*data)[index++] = argc; // argc (previously: arg name)
+ (*data)[index++] = paramsIndex; //parameter index
+ (*data)[index++] = nullIndex; // tags
+ (*data)[index++] = flags | (it->methodType() == QMetaMethod::Signal ? MethodSignal : MethodSlot);
+
+ if (it->methodType() == QMetaMethod::Signal)
+ (*data)[13] += 1; //signal count
+
+ paramsIndex += 1 + argc * 2;
+ }
+ *prtIndex = index;
+}
+
+void DynamicQMetaObject::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 = Shiboken::Conversions::getPythonTypeObject("QObject*");
+ QVector<PyTypeObject *> basesToCheck;
+ for (Py_ssize_t i = 0; i < basesCount; ++i) {
+ PyTypeObject *baseType = reinterpret_cast<PyTypeObject *>(PyTuple_GET_ITEM(mro, i));
+ if (PyType_IsSubtype(baseType, qObjectType)
+ || baseType == reinterpret_cast<PyTypeObject *>(&SbkObject_Type)
+ || baseType == reinterpret_cast<PyTypeObject *>(&PyBaseObject_Type)) {
+ continue;
+ } else {
+ basesToCheck.append(baseType);
+ }
+ }
+
+ // Prepend the actual type that we are parsing.
+ basesToCheck.prepend(type);
+ // PYSIDE-315: Handle all signals first, in all involved types.
+ for (int baseIndex = 0, baseEnd = basesToCheck.size(); baseIndex < baseEnd; ++baseIndex) {
+ PyTypeObject *baseType = basesToCheck[baseIndex];
+ PyObject *attrs = baseType->tp_dict;
+ PyObject *key = 0;
+ PyObject *value = 0;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next(attrs, &pos, &key, &value)) {
+ if (Signal::checkType(value)) {
+ // Register signals.
+ PySideSignal *data = reinterpret_cast<PySideSignal *>(value);
+ const char *signalName = Shiboken::String::toCString(key);
+ data->signalName = strdup(signalName);
+ QByteArray sig;
+ sig.reserve(128);
+ for (int i = 0; i < data->signaturesSize; ++i) {
+ sig = signalName;
+ sig += '(';
+ if (data->signatures[i])
+ sig += data->signatures[i];
+ sig += ')';
+ if (d.superdata->indexOfSignal(sig) == -1)
+ addSignal(sig, "void");
+ }
+ }
+ }
+ }
+
+ Shiboken::AutoDecRef slotAttrName(Shiboken::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 (int baseIndex = 0, baseEnd = basesToCheck.size(); baseIndex < baseEnd; ++baseIndex) {
+ PyTypeObject *baseType = basesToCheck[baseIndex];
+ PyObject *attrs = baseType->tp_dict;
+ PyObject *key = 0;
+ PyObject *value = 0;
+ Py_ssize_t pos = 0;
+
+ typedef std::pair<const char *, PyObject *> PropPair;
+ QVector<PropPair> properties;
+
+ while (PyDict_Next(attrs, &pos, &key, &value)) {
+ if (Property::checkType(value)) {
+ // Leave the properties to be registered after signals because they may depend on
+ // notify signals.
+ int index = d.superdata->indexOfProperty(Shiboken::String::toCString(key));
+ if (index == -1)
+ properties << PropPair(Shiboken::String::toCString(key), value);
+ } else if (PyFunction_Check(value)) {
+ // 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 *signature = PyList_GET_ITEM(signatureList, i);
+ QByteArray sig(Shiboken::String::toCString(signature));
+ // Split the slot type and its signature.
+ QList<QByteArray> slotInfo = sig.split(' ');
+ int index = d.superdata->indexOfSlot(slotInfo[1]);
+ if (index == -1)
+ addSlot(slotInfo[1], slotInfo[0]);
+ }
+ }
+ }
+ }
+
+ // Register properties
+ foreach (const PropPair &propPair, properties)
+ addProperty(propPair.first, propPair.second);
+ }
+}
+
+/*!
+ Allocate the meta data table.
+ Returns the index in the table corresponding to the header fields count.
+*/
+int DynamicQMetaObject::DynamicQMetaObjectPrivate::createMetaData(QMetaObject* metaObj, QLinkedList<QByteArray> &strings)
+{
+ const int n_methods = m_methods.size();
+ const int n_properties = m_properties.size();
+ const int n_info = m_info.size();
+
+ int header[] = {7, // revision (Used by moc, qmetaobjectbuilder and qdbus)
+ 0, // class name index in m_metadata
+ n_info, 0, // classinfo and classinfo index
+ n_methods, 0, // method count and method list index
+ n_properties, 0, // prop count and prop indexes
+ 0, 0, // enum count and enum index
+ 0, 0, // constructors (since revision 2)
+ 0, // flags (since revision 3)
+ 0}; // signal count (since revision 4)
+
+ const int HEADER_LENGHT = sizeof(header)/sizeof(int);
+
+ m_dataSize = HEADER_LENGHT;
+ m_dataSize += n_info*2; //class info: name, value
+ m_dataSize += n_methods*5; //method: name, argc, parameters, tag, flags
+ m_dataSize += n_properties*4; //property: name, type, flags
+ m_dataSize += 1; //eod
+
+ m_dataSize += aggregateParameterCount(m_methods); // types and parameter names
+
+ uint* data = reinterpret_cast<uint*>(realloc(const_cast<uint*>(metaObj->d.data), m_dataSize * sizeof(uint)));
+
+ Q_ASSERT(data);
+ std::memcpy(data, header, sizeof(header));
+
+ metaObj->d.data = data;
+
+ return HEADER_LENGHT;
+}
+
+// Writes strings to string data struct.
+// The struct consists of an array of QByteArrayData, followed by a char array
+// containing the actual strings. This format must match the one produced by
+// moc (see generator.cpp).
+void DynamicQMetaObject::DynamicQMetaObjectPrivate::writeStringData(char *out, QLinkedList<QByteArray> &strings)
+{
+ Q_ASSERT(!(reinterpret_cast<quintptr>(out) & (Q_ALIGNOF(QByteArrayData)-1)));
+
+ int offsetOfStringdataMember = strings.size() * sizeof(QByteArrayData);
+ int stringdataOffset = 0;
+ int i = 0;
+ foreach(const QByteArray& str, strings) {
+ writeString(out, i, str, offsetOfStringdataMember, stringdataOffset);
+ i++;
+ }
+}
+
+QList<MethodData>::iterator is_sorted_until(QList<MethodData>::iterator first,
+ QList<MethodData>::iterator last,
+ bool comp(const MethodData &m1, const MethodData &m2))
+{
+ if (first != last) {
+ QList<MethodData>::iterator next = first;
+ while (++next != last) {
+ if (comp(*next, *first))
+ return next;
+ ++first;
+ }
+ }
+ return last;
+}
+
+bool is_sorted(QList<MethodData>::iterator first, QList<MethodData>::iterator last,
+ bool comp(const MethodData &m1, const MethodData &m2))
+{
+ return is_sorted_until(first, last, comp) == last;
+}
+
+void DynamicQMetaObject::DynamicQMetaObjectPrivate::updateMetaObject(QMetaObject* metaObj)
+{
+ Q_ASSERT(!m_updated);
+ uint *data = const_cast<uint*>(metaObj->d.data);
+ int index = 0;
+ QLinkedList<QByteArray> strings;
+ m_dataSize = 0;
+
+ // Recompute the size and reallocate memory
+ // index is set after the last header field.
+ index = createMetaData(metaObj, strings);
+ data = const_cast<uint*>(metaObj->d.data);
+
+ registerString(m_className, strings); // register class string
+ m_nullIndex = registerString("", strings); // register a null string
+
+ // Write class info.
+ if (m_info.size()) {
+ if (data[3] == 0)
+ data[3] = index;
+
+ QMap<QByteArray, QByteArray>::const_iterator i = m_info.constBegin(); //TODO: info is a hash this can fail
+ while (i != m_info.constEnd()) {
+ int valueIndex = registerString(i.value(), strings);
+ int keyIndex = registerString(i.key(), strings);
+ data[index++] = keyIndex;
+ data[index++] = valueIndex;
+ i++;
+ }
+ }
+
+ // Write methods first, then properties, to be consistent with moc.
+ // Write signals/slots (signals must be written first, see indexOfMethodRelative in
+ // qmetaobject.cpp).
+
+ QList<MethodData>::iterator it;
+ // PYSIDE-315: Instead of sorting the items and maybe breaking indices,
+ // we ensure that the signals and slots are sorted by the improved parsePythonType().
+ // The order can only become distorted if the class is modified after creation.
+ // In that case, we give a warning.
+ if (!is_sorted(m_methods.begin(), m_methods.end(), sortMethodSignalSlot)) {
+ const char *metaObjectName = this->m_className.data();
+ PyObject *txt = PyBytes_FromFormat("\n\n*** Sort Warning ***\n"
+ "Signals and slots in QMetaObject '%s' are not ordered correctly, "
+ "this may lead to issues.\n", metaObjectName);
+ it = m_methods.begin();
+ QList<MethodData>::iterator end = m_methods.end();
+ QList<MethodData>::iterator until = is_sorted_until(m_methods.begin(), m_methods.end(),
+ sortMethodSignalSlot);
+ for (; it != end; ++it) {
+ PyObject *atxt = PyBytes_FromFormat("%d%s %s %s\n", it - m_methods.begin() + 1,
+ until >= it + 1 ? " " : "!",
+ it->methodType() == QMetaMethod::Signal ? "Signal" : "Slot ",
+ it->signature().data() );
+ PyBytes_ConcatAndDel(&txt, atxt);
+ }
+ PyErr_WarnEx(PyExc_RuntimeWarning, PyBytes_AsString(txt), 0);
+ Py_DECREF(txt);
+ // Prevent a warning from being turned into an error. We cannot easily unwind.
+ PyErr_Clear();
+ }
+
+ if (m_methods.size()) {
+ if (data[5] == 0)
+ data[5] = index;
+
+ writeMethodsData(m_methods, &data, strings, &index, m_nullIndex, AccessPublic);
+ }
+
+ // Write signal/slots parameters.
+ if (m_methods.size()) {
+ for (it = m_methods.begin(); it != m_methods.end(); ++it) {
+ QList<QByteArray> paramTypeNames = it->parameterTypes();
+ int paramCount = paramTypeNames.size();
+ for (int i = -1; i < paramCount; ++i) {
+ const QByteArray &typeName = (i < 0) ? it->returnType() : paramTypeNames.at(i);
+ int typeInfo;
+ if (QtPrivate::isBuiltinType(typeName))
+ typeInfo = QMetaType::type(typeName);
+ else
+ typeInfo = IsUnresolvedType | registerString(typeName, strings);
+ data[index++] = typeInfo;
+ }
+
+ // Parameter names (use a null string)
+ for (int i = 0; i < paramCount; ++i) {
+ data[index++] = m_nullIndex;
+ }
+ }
+ }
+
+ // Write properties.
+ if (m_properties.size()) {
+ if (data[7] == 0)
+ data[7] = index;
+
+ QList<PropertyData>::const_iterator i = m_properties.constBegin();
+ while (i != m_properties.constEnd()) {
+ if (i->isValid()) {
+ data[index++] = registerString(i->name(), strings); // name
+ } else
+ data[index++] = m_nullIndex;
+
+ // Find out the property type index.
+ int typeInfo = m_nullIndex;
+ if (i->isValid()) {
+ const QByteArray &typeName = i->type();
+ if (QtPrivate::isBuiltinType(typeName))
+ typeInfo = QMetaType::type(typeName);
+ else
+ typeInfo = IsUnresolvedType | registerString(typeName, strings);
+ }
+ data[index++] = typeInfo; // normalized type
+
+ data[index++] = i->flags();
+ i++;
+ }
+
+ // Write properties notify.
+ i = m_properties.constBegin();
+ while (i != m_properties.constEnd()) {
+ // Recompute notifyId, because sorting the methods might have changed the relative
+ // index.
+ const int notifyId = getPropertyNotifyId(i->data());
+ data[index++] = notifyId >= 0 ? static_cast<uint>(notifyId) : 0; //signal notify index
+ i++;
+ }
+ }
+
+ data[index++] = 0; // the end
+
+ // Create the m_metadata string.
+ int size = blobSize(strings);
+ char *blob =
+ reinterpret_cast<char *>(realloc(reinterpret_cast<char *>(const_cast<QByteArrayData *>(metaObj->d.stringdata)), size));
+ writeStringData(blob, strings);
+
+ metaObj->d.stringdata = reinterpret_cast<const QByteArrayData *>(blob);
+ metaObj->d.data = data;
+}
diff --git a/sources/pyside2/libpyside/dynamicqmetaobject.h b/sources/pyside2/libpyside/dynamicqmetaobject.h
new file mode 100644
index 000000000..ac8f4644d
--- /dev/null
+++ b/sources/pyside2/libpyside/dynamicqmetaobject.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "pysidemacros.h"
+#include <sbkpython.h>
+#include <QMetaObject>
+#include <QMetaMethod>
+
+namespace PySide
+{
+
+class DynamicQMetaObject : public QMetaObject
+{
+public:
+ DynamicQMetaObject(const char* className, const QMetaObject* metaObject);
+ DynamicQMetaObject(PyTypeObject* type, const QMetaObject* metaobject);
+ ~DynamicQMetaObject();
+
+
+ int addMethod(QMetaMethod::MethodType mtype, const char* signature, const char* type);
+ void removeMethod(QMetaMethod::MethodType mtype, uint index);
+ int addSignal(const char* signal, const char* type = 0);
+ int addSlot(const char* slot, const char* type = 0);
+ int addProperty(const char* property, PyObject* data);
+ void addInfo(const char* key, const char* value);
+ void addInfo(QMap<QByteArray, QByteArray> info);
+
+ void removeSignal(uint idex);
+ void removeSlot(uint index);
+ void removeProperty(uint index);
+
+ const QMetaObject* update() const;
+
+private:
+ class DynamicQMetaObjectPrivate;
+ DynamicQMetaObjectPrivate* m_d;
+
+ void parsePythonType(PyTypeObject *type);
+};
+
+
+}
+#endif
diff --git a/sources/pyside2/libpyside/dynamicqmetaobject_p.h b/sources/pyside2/libpyside/dynamicqmetaobject_p.h
new file mode 100644
index 000000000..202e87b08
--- /dev/null
+++ b/sources/pyside2/libpyside/dynamicqmetaobject_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QByteArray>
+#include <QMetaMethod>
+
+#define GLOBAL_RECEIVER_CLASS_NAME "__GlobalReceiver__"
+
+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/globalreceiver.cpp b/sources/pyside2/libpyside/globalreceiver.cpp
new file mode 100644
index 000000000..e183e09ba
--- /dev/null
+++ b/sources/pyside2/libpyside/globalreceiver.cpp
@@ -0,0 +1,330 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "globalreceiver.h"
+#include "dynamicqmetaobject_p.h"
+#include "pysideweakref.h"
+
+#include <QMetaMethod>
+#include <QDebug>
+#include <QEvent>
+#include <QLinkedList>
+#include <autodecref.h>
+#include <sbkconverter.h>
+#include <gilstate.h>
+
+#include "typeresolver.h"
+#include "signalmanager.h"
+
+#define RECEIVER_DESTROYED_SLOT_NAME "__receiverDestroyed__(QObject*)"
+
+namespace PySide
+{
+class DynamicSlotData
+{
+ public:
+ DynamicSlotData(int id, PyObject* callback, GlobalReceiver* parent);
+ void addRef(const QObject* o);
+ void decRef(const QObject* o);
+ void clear();
+ int hasRefTo(const QObject* o) const;
+ int refCount() const;
+ int id() const;
+ PyObject* call(PyObject* args);
+ ~DynamicSlotData();
+ static void onCallbackDestroyed(void* data);
+
+ private:
+ int m_id;
+ bool m_isMethod;
+ PyObject* m_callback;
+ PyObject* m_pythonSelf;
+ PyObject* m_pyClass;
+ PyObject* m_weakRef;
+ GlobalReceiver* m_parent;
+ QLinkedList<const QObject*> m_refs;
+};
+
+}
+
+using namespace PySide;
+
+DynamicSlotData::DynamicSlotData(int id, PyObject* callback, GlobalReceiver* parent)
+ : m_id(id), 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);
+#ifdef IS_PY3K
+ m_pyClass = 0;
+#else
+ m_pyClass = PyMethod_GET_CLASS(callback);
+#endif
+
+ m_pythonSelf = PyMethod_GET_SELF(callback);
+
+ //monitor class from method lifetime
+ m_weakRef = WeakRef::create(m_pythonSelf, DynamicSlotData::onCallbackDestroyed, this);
+ } else {
+ m_callback = callback;
+ Py_INCREF(m_callback);
+ }
+}
+
+PyObject* DynamicSlotData::call(PyObject* args)
+{
+ PyObject* callback = m_callback;
+
+ //create a callback based on method data
+ Shiboken::GilState gil;
+ if (m_isMethod)
+#ifdef IS_PY3K
+ callback = PyMethod_New(callback, m_pythonSelf);
+#else
+ callback = PyMethod_New(callback, m_pythonSelf, m_pyClass);
+#endif
+
+ PyObject* result = PyObject_CallObject(callback, args);
+
+ if (m_isMethod)
+ Py_DECREF(callback);
+
+ return result;
+}
+
+void DynamicSlotData::addRef(const QObject *o)
+{
+ m_refs.append(o);
+}
+
+void DynamicSlotData::decRef(const QObject *o)
+{
+ m_refs.removeOne(o);
+}
+
+int DynamicSlotData::refCount() const
+{
+ return m_refs.size();
+}
+
+int DynamicSlotData::id() const
+{
+ return m_id;
+}
+
+int DynamicSlotData::hasRefTo(const QObject *o) const
+{
+ return m_refs.count(o);
+}
+
+void DynamicSlotData::clear()
+{
+ Shiboken::GilState gil;
+ Py_XDECREF(m_weakRef);
+ m_weakRef = 0;
+ m_refs.clear();
+}
+
+DynamicSlotData::~DynamicSlotData()
+{
+ Shiboken::GilState gil;
+ clear();
+ if (!m_isMethod)
+ Py_DECREF(m_callback);
+}
+
+void DynamicSlotData::onCallbackDestroyed(void *data)
+{
+ Shiboken::GilState gil;
+ DynamicSlotData* self = reinterpret_cast<DynamicSlotData*>(data);
+
+ //Disconnect all sources
+ QMetaMethod m = self->m_parent->metaObject()->method(self->m_id);
+ QByteArray methodName = QByteArray::number(m.methodType()).append(m.methodSignature());
+ QLinkedList<const QObject*> sources = self->m_refs;
+ foreach(const QObject* src, sources)
+ const_cast<QObject*>(src)->disconnect(self->m_parent, methodName);
+ self->m_weakRef = 0;
+}
+
+GlobalReceiver::GlobalReceiver()
+ : m_metaObject(GLOBAL_RECEIVER_CLASS_NAME, &QObject::staticMetaObject)
+{
+ //slot used to be notifyed of object destrouction
+ m_metaObject.addSlot(RECEIVER_DESTROYED_SLOT_NAME);
+ m_metaObject.update();
+ setObjectName(QLatin1String("GLOBAL RECEIVER"));
+}
+
+GlobalReceiver::~GlobalReceiver()
+{
+ while(!m_slotReceivers.empty()) {
+ DynamicSlotData* data = m_slotReceivers.take(m_slotReceivers.begin().key());
+ data->clear();
+ delete data;
+ }
+}
+
+void GlobalReceiver::connectNotify(QObject* source, int slotId)
+{
+ if (m_slotReceivers.contains(slotId)) {
+ DynamicSlotData* data = m_slotReceivers[slotId];
+ if (!data->hasRefTo(source))
+ QObject::connect(source, SIGNAL(destroyed(QObject*)), this, "1" RECEIVER_DESTROYED_SLOT_NAME);
+ data->addRef(source);
+ }
+}
+
+void GlobalReceiver::disconnectNotify(QObject* source, int slotId)
+{
+ if (m_slotReceivers.contains(slotId)) {
+ DynamicSlotData *data = m_slotReceivers[slotId];
+ data->decRef(source);
+ if (data->refCount() == 0)
+ removeSlot(slotId);
+
+ if (!hasConnectionWith(source))
+ QObject::disconnect(source, SIGNAL(destroyed(QObject*)), this, "1" RECEIVER_DESTROYED_SLOT_NAME);
+ }
+}
+
+const QMetaObject* GlobalReceiver::metaObject() const
+{
+ return m_metaObject.update();
+}
+
+int GlobalReceiver::addSlot(const char* slot, PyObject* callback)
+{
+ int slotId = m_metaObject.addSlot(slot);
+ if (!m_slotReceivers.contains(slotId))
+ m_slotReceivers[slotId] = new DynamicSlotData(slotId, callback, this);
+
+ bool isShortCircuit = true;
+ for (int i = 0; slot[i]; ++i) {
+ if (slot[i] == '(') {
+ isShortCircuit = false;
+ break;
+ }
+ }
+
+ if (isShortCircuit)
+ m_shortCircuitSlots << slotId;
+
+ Q_ASSERT(slotId >= QObject::staticMetaObject.methodCount());
+ return slotId;
+}
+
+void GlobalReceiver::removeSlot(int slotId)
+{
+ if (m_slotReceivers.contains(slotId)) {
+ delete m_slotReceivers.take(slotId);
+ m_metaObject.removeSlot(slotId);
+ m_shortCircuitSlots.remove(slotId);
+ }
+}
+
+bool GlobalReceiver::hasConnectionWith(const QObject *object)
+{
+ QHash<int, DynamicSlotData*>::iterator i = m_slotReceivers.begin();
+ while(i != m_slotReceivers.end()) {
+ if (i.value()->hasRefTo(object)) {
+ return true;
+ }
+ i++;
+ }
+ return false;
+}
+
+int GlobalReceiver::qt_metacall(QMetaObject::Call call, int id, void** args)
+{
+ Q_ASSERT(call == QMetaObject::InvokeMetaMethod);
+ Q_ASSERT(id >= QObject::staticMetaObject.methodCount());
+ QMetaMethod slot = metaObject()->method(id);
+ Q_ASSERT(slot.methodType() == QMetaMethod::Slot);
+
+ if (strcmp(slot.methodSignature(), RECEIVER_DESTROYED_SLOT_NAME) == 0) {
+ QObject *arg = *(QObject**)args[1];
+
+ //avoid hash changes during the destruction
+ QHash<int, DynamicSlotData*> copy = m_slotReceivers;
+ QHash<int, DynamicSlotData*>::iterator i = copy.begin();
+ while(i != copy.end()) {
+ //Remove all refs
+ int refs = i.value()->hasRefTo(arg);
+ while(refs) {
+ disconnectNotify(arg, i.key());
+ refs--;
+ }
+ i++;
+ }
+ return -1;
+ }
+
+ DynamicSlotData* data = m_slotReceivers.value(id);
+ if (!data) {
+ qWarning() << "Unknown global slot, id:" << id;
+ return -1;
+ }
+
+ Shiboken::GilState gil;
+ PyObject* retval = 0;
+ if (m_shortCircuitSlots.contains(id)) {
+ retval = data->call(reinterpret_cast<PyObject*>(args[1]));
+ } else {
+ QList<QByteArray> paramTypes = slot.parameterTypes();
+ Shiboken::AutoDecRef preparedArgs(PyTuple_New(paramTypes.count()));
+ for (int i = 0, max = paramTypes.count(); i < max; ++i) {
+ const QByteArray& paramType = paramTypes[i];
+ Shiboken::Conversions::SpecificConverter converter(paramType.constData());
+ PyTuple_SET_ITEM(preparedArgs.object(), i, converter.toPython(args[i+1]));
+ }
+ retval = data->call(preparedArgs);
+ }
+
+ if (!retval)
+ PyErr_Print();
+ else
+ Py_DECREF(retval);
+
+ return -1;
+}
diff --git a/sources/pyside2/libpyside/globalreceiver.h b/sources/pyside2/libpyside/globalreceiver.h
new file mode 100644
index 000000000..d1114465a
--- /dev/null
+++ b/sources/pyside2/libpyside/globalreceiver.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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_H
+#define GLOBALRECEIVER_H
+
+#include <sbkpython.h>
+#include <QObject>
+#include <QHash>
+#include <QSet>
+#include "dynamicqmetaobject.h"
+
+namespace PySide
+{
+
+class DynamicSlotData;
+
+class GlobalReceiver : public QObject
+{
+public:
+ GlobalReceiver();
+ ~GlobalReceiver();
+ int qt_metacall(QMetaObject::Call call, int id, void** args);
+ const QMetaObject* metaObject() const;
+ int addSlot(const char* slot, PyObject* callback);
+ void removeSlot(int slotId);
+ void connectNotify(QObject* sender, int slotId);
+ void disconnectNotify(QObject* sender, int slotId);
+ bool hasConnectionWith(const QObject* object);
+
+protected:
+ using QObject::connectNotify;
+ using QObject::disconnectNotify;
+
+private:
+ DynamicQMetaObject m_metaObject;
+ QSet<int> m_shortCircuitSlots;
+ QHash<int, DynamicSlotData* > m_slotReceivers;
+};
+
+}
+
+#endif
+
diff --git a/sources/pyside2/libpyside/globalreceiverv2.cpp b/sources/pyside2/libpyside/globalreceiverv2.cpp
new file mode 100644
index 000000000..a79d43c20
--- /dev/null
+++ b/sources/pyside2/libpyside/globalreceiverv2.cpp
@@ -0,0 +1,358 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QMetaMethod>
+#include <QDebug>
+#include <QEvent>
+#include <QLinkedList>
+#include <autodecref.h>
+#include <gilstate.h>
+
+#include "typeresolver.h"
+#include "signalmanager.h"
+
+#define RECEIVER_DESTROYED_SLOT_NAME "__receiverDestroyed__(QObject*)"
+
+namespace
+{
+ static int DESTROY_SIGNAL_ID = 0;
+ static int DESTROY_SLOT_ID = 0;
+}
+
+namespace PySide
+{
+class 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);
+#ifndef IS_PY3K
+ m_pyClass = PyMethod_GET_CLASS(callback);
+#endif
+ 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)));
+ else
+ return QByteArray::number((qlonglong)PyObject_Hash(callback));
+}
+
+PyObject* DynamicSlotDataV2::callback()
+{
+ PyObject* callback = m_callback;
+
+ //create a callback based on method data
+ if (m_isMethod)
+#ifdef IS_PY3K
+ callback = PyMethod_New(m_callback, m_pythonSelf);
+#else
+ callback = PyMethod_New(m_callback, m_pythonSelf, m_pyClass);
+#endif
+ else
+ Py_INCREF(callback);
+
+ return callback;
+}
+
+int DynamicSlotDataV2::id(const char* signature) const
+{
+ if (m_signatures.contains(signature))
+ return m_signatures[signature];
+ return -1;
+}
+
+int DynamicSlotDataV2::addSlot(const char* signature)
+{
+ int index = id(signature);
+ if (index == -1) {
+ DynamicQMetaObject *dmo = const_cast<DynamicQMetaObject*>(reinterpret_cast<const DynamicQMetaObject*>(m_parent->metaObject()));
+ index = m_signatures[signature] = dmo->addSlot(signature);
+ }
+ return index;
+}
+
+void DynamicSlotDataV2::onCallbackDestroyed(void *data)
+{
+ DynamicSlotDataV2* 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(0), m_metaObject(GLOBAL_RECEIVER_CLASS_NAME, &QObject::staticMetaObject), m_sharedMap(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.indexOfSlot(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.size() <= 0)
+ 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.size() == 0)
+ 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()
+{
+ QSet<const QObject*> objs = QSet<const QObject*>::fromList(m_refs);
+ Py_BEGIN_ALLOW_THREADS
+ foreach(const QObject* o, objs) {
+ 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 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.size() == 0)
+ return -1;
+ QObject *obj = *(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
new file mode 100644
index 000000000..3ad9ba6b7
--- /dev/null
+++ b/sources/pyside2/libpyside/globalreceiverv2.h
@@ -0,0 +1,149 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QObject>
+#include <QHash>
+#include <QSet>
+#include <QSharedPointer>
+#include <QLinkedList>
+#include <QByteArray>
+
+#include "dynamicqmetaobject.h"
+
+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();
+
+ /**
+ * Reimplemented function from QObject
+ **/
+ int qt_metacall(QMetaObject::Call call, int id, void** args);
+ const QMetaObject* metaObject() const;
+
+ /**
+ * 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 = 0);
+
+ /**
+ * 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 = 0);
+
+ /*
+ * 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 retrive the unique hash of this GlobalReceiver object
+ *
+ * @return a string with a unique id based on GlobalReceiver contents
+ **/
+ QByteArray hash() const;
+
+ /**
+ * Use to retrive 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);
+
+private:
+ DynamicQMetaObject m_metaObject;
+ DynamicSlotDataV2 *m_data;
+ QList<const QObject*> m_refs;
+ int m_ref;
+ SharedMap m_sharedMap;
+};
+
+}
+
+#endif
diff --git a/sources/pyside2/libpyside/pyside.cpp b/sources/pyside2/libpyside/pyside.cpp
new file mode 100644
index 000000000..7d05f45a5
--- /dev/null
+++ b/sources/pyside2/libpyside/pyside.cpp
@@ -0,0 +1,387 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "signalmanager.h"
+#include "pysideclassinfo_p.h"
+#include "pysideproperty_p.h"
+#include "pysideproperty.h"
+#include "pysidesignal.h"
+#include "pysidesignal_p.h"
+#include "pysideslot_p.h"
+#include "pysidemetafunction_p.h"
+#include "pysidemetafunction.h"
+#include "dynamicqmetaobject.h"
+#include "destroylistener.h"
+
+#include <basewrapper.h>
+#include <conversions.h>
+#include <sbkconverter.h>
+#include <gilstate.h>
+#include <typeresolver.h>
+#include <bindingmanager.h>
+#include <algorithm>
+#include <cstring>
+#include <cctype>
+#include <QStack>
+#include <QCoreApplication>
+#include <QDebug>
+#include <QSharedPointer>
+
+static QStack<PySide::CleanupFunction> cleanupFunctionList;
+static void* qobjectNextAddr;
+
+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();
+}
+
+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));
+ if (metaObj->indexOfProperty(propName) != -1) {
+ propName[0] = std::toupper(propName[0]);
+ propName.prepend("set");
+
+ Shiboken::AutoDecRef propSetter(PyObject_GetAttrString(qObj, propName.constData()));
+ if (!propSetter.isNull()) {
+ Shiboken::AutoDecRef args(PyTuple_Pack(1, value));
+ Shiboken::AutoDecRef retval(PyObject_CallObject(propSetter, args));
+ } else {
+ PyObject* attr = PyObject_GenericGetAttr(qObj, key);
+ if (PySide::Property::checkType(attr))
+ PySide::Property::setValue(reinterpret_cast<PySideProperty*>(attr), qObj, value);
+ }
+ } else {
+ propName.append("()");
+ if (metaObj->indexOfSignal(propName) != -1) {
+ propName.prepend('2');
+ PySide::Signal::connect(qObj, propName, value);
+ } else {
+ 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()
+{
+ //PySide::DestroyListener::instance()->destroy();
+ while (!cleanupFunctionList.isEmpty()) {
+ CleanupFunction f = cleanupFunctionList.pop();
+ f();
+ }
+ PySide::DestroyListener::destroy();
+}
+
+static void destructionVisitor(SbkObject* pyObj, void* data)
+{
+ void** realData = reinterpret_cast<void**>(data);
+ SbkObject* pyQApp = reinterpret_cast<SbkObject*>(realData[0]);
+ PyTypeObject* 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()
+{
+ SignalManager::instance().clear();
+ QCoreApplication* app = QCoreApplication::instance();
+ if (!app)
+ return;
+
+ 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
+}
+
+struct TypeUserData {
+ TypeUserData(PyTypeObject* type, const QMetaObject* metaobject) : mo(type, metaobject) {}
+ DynamicQMetaObject mo;
+ std::size_t cppObjSize;
+};
+
+std::size_t getSizeOfQObject(SbkObjectType* type)
+{
+ using namespace Shiboken::ObjectType;
+ TypeUserData* userData = reinterpret_cast<TypeUserData*>(getTypeUserData(reinterpret_cast<SbkObjectType*>(type)));
+ return userData->cppObjSize;
+}
+
+void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base, const std::size_t& cppObjSize)
+{
+ //create DynamicMetaObject based on python type
+ TypeUserData* userData = new TypeUserData(reinterpret_cast<PyTypeObject*>(type), base);
+ userData->cppObjSize = cppObjSize;
+ userData->mo.update();
+ Shiboken::ObjectType::setTypeUserData(type, userData, Shiboken::callCppDestructor<TypeUserData>);
+
+ //initialize staticQMetaObject property
+ void* metaObjectPtr = &userData->mo;
+ static SbkConverter* converter = Shiboken::Conversions::getConverter("QMetaObject");
+ if (!converter)
+ return;
+ Shiboken::AutoDecRef pyMetaObject(Shiboken::Conversions::pointerToPython(converter, metaObjectPtr));
+ PyObject_SetAttrString(reinterpret_cast<PyObject*>(type), "staticMetaObject", pyMetaObject);
+}
+
+void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base)
+{
+ initDynamicMetaObject(type, base, 0);
+}
+
+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);
+ QMetaObject* baseMo = 0;
+ SbkObjectType* qobjBase = 0;
+
+ for (int i = 0; i < numBases; ++i) {
+ PyTypeObject* base = reinterpret_cast<PyTypeObject*>(PyTuple_GET_ITEM(bases, i));
+ if (PyType_IsSubtype(base, qObjType)) {
+ baseMo = reinterpret_cast<QMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(base)));
+ qobjBase = reinterpret_cast<SbkObjectType*>(base);
+ reinterpret_cast<DynamicQMetaObject*>(baseMo)->update();
+ break;
+ }
+ }
+ if (!baseMo) {
+ qWarning("Sub class of QObject not inheriting QObject!? Crash will happen when using %s.", className.constData());
+ return;
+ }
+
+ TypeUserData* userData = reinterpret_cast<TypeUserData*>(Shiboken::ObjectType::getTypeUserData(qobjBase));
+ initDynamicMetaObject(type, baseMo, userData->cppObjSize);
+}
+
+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;
+ Py_INCREF(value);
+ attr = value;
+ }
+
+ //mutate native signals to signal instance type
+ if (attr && PyObject_TypeCheck(attr, &PySideSignalType)) {
+ 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.size() > 0) {
+ 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";
+
+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((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;
+ }
+ }
+
+ const char* typeName = typeid(*cppSelf).name();
+ pyOut = Shiboken::Object::newObject(sbk_type, cppSelf, false, false, typeName);
+
+ return pyOut;
+}
+
+#ifdef PYSIDE_QML_SUPPORT
+static QuickRegisterItemFunction quickRegisterItem;
+
+QuickRegisterItemFunction getQuickRegisterItemFunction()
+{
+ return quickRegisterItem;
+}
+
+void setQuickRegisterItemFunction(QuickRegisterItemFunction function)
+{
+ quickRegisterItem = function;
+}
+#endif // PYSIDE_QML_SUPPORT
+
+} //namespace PySide
+
diff --git a/sources/pyside2/libpyside/pyside.h b/sources/pyside2/libpyside/pyside.h
new file mode 100644
index 000000000..3619e2875
--- /dev/null
+++ b/sources/pyside2/libpyside/pyside.h
@@ -0,0 +1,157 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <qqml.h>
+#endif
+
+#include <QMetaType>
+#include <QHash>
+#include <QList>
+
+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 uint 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_DEPRECATED(PYSIDE_API void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base));
+PYSIDE_API void initDynamicMetaObject(SbkObjectType* type, const QMetaObject* base, const std::size_t& cppObjSize);
+PYSIDE_API void initQObjectSubType(SbkObjectType* type, PyObject* args, PyObject* kwds);
+
+/// 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.
+typedef bool (*QuickRegisterItemFunction)(PyObject *pyObj, const char *uri, int versionMajor,
+ int versionMinor, const char *qmlName,
+ QQmlPrivate::RegisterType *);
+PYSIDE_API QuickRegisterItemFunction getQuickRegisterItemFunction();
+PYSIDE_API void setQuickRegisterItemFunction(QuickRegisterItemFunction function);
+#endif // PYSIDE_QML_SUPPORT
+
+} //namespace PySide
+
+
+#endif // PYSIDE_H
+
diff --git a/sources/pyside2/libpyside/pyside2.pc.in b/sources/pyside2/libpyside/pyside2.pc.in
new file mode 100644
index 000000000..4f396ac72
--- /dev/null
+++ b/sources/pyside2/libpyside/pyside2.pc.in
@@ -0,0 +1,14 @@
+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
+pythonpath=@SITE_PACKAGE@
+
+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_EXTENSION_SUFFIX@@LIBRARY_OUTPUT_SUFFIX@
+Cflags: -I${includedir}
+Requires: shiboken2
+
diff --git a/sources/pyside2/libpyside/pysideclassinfo.cpp b/sources/pyside2/libpyside/pysideclassinfo.cpp
new file mode 100644
index 000000000..a80ed9c54
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideclassinfo.cpp
@@ -0,0 +1,229 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "pysideclassinfo_p.h"
+#include "dynamicqmetaobject.h"
+
+#include <shiboken.h>
+#include <QDebug>
+
+#define CLASSINFO_CLASS_NAME "ClassInfo"
+
+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*);
+
+PyTypeObject PySideClassInfoType = {
+ PyVarObject_HEAD_INIT(0, 0)
+ "PySide2.QtCore." CLASSINFO_CLASS_NAME, /*tp_name*/
+ sizeof(PySideClassInfo), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ classCall, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ 0, /*tp_doc */
+ 0, /*tp_traverse */
+ 0, /*tp_clear */
+ 0, /*tp_richcompare */
+ 0, /*tp_weaklistoffset */
+ 0, /*tp_iter */
+ 0, /*tp_iternext */
+ 0, /*tp_methods */
+ 0, /*tp_members */
+ 0, /*tp_getset */
+ 0, /*tp_base */
+ 0, /*tp_dict */
+ 0, /*tp_descr_get */
+ 0, /*tp_descr_set */
+ 0, /*tp_dictoffset */
+ classInfoTpInit, /*tp_init */
+ 0, /*tp_alloc */
+ classInfoTpNew, /*tp_new */
+ classInfoFree, /*tp_free */
+ 0, /*tp_is_gc */
+ 0, /*tp_bases */
+ 0, /*tp_mro */
+ 0, /*tp_cache */
+ 0, /*tp_subclasses */
+ 0, /*tp_weaklist */
+ 0, /*tp_del */
+ 0, /*tp_version_tag */
+};
+
+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;
+ 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;
+ }
+
+ if (Shiboken::ObjectType::checkType(reinterpret_cast<PyTypeObject*>(klass))) {
+ PySide::DynamicQMetaObject* mo = reinterpret_cast<PySide::DynamicQMetaObject*>(Shiboken::ObjectType::getTypeUserData(reinterpret_cast<SbkObjectType*>(klass)));
+ if (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 : 1;
+}
+
+void classInfoFree(void *self)
+{
+ PyObject* pySelf = reinterpret_cast<PyObject*>(self);
+ PySideClassInfo* data = reinterpret_cast<PySideClassInfo*>(self);
+
+ delete data->d;
+ pySelf->ob_type->tp_base->tp_free(self);
+}
+
+
+} // extern "C"
+
+
+namespace PySide { namespace ClassInfo {
+
+void init(PyObject* module)
+{
+ if (PyType_Ready(&PySideClassInfoType) < 0)
+ return;
+
+ Py_INCREF(&PySideClassInfoType);
+ PyModule_AddObject(module, CLASSINFO_CLASS_NAME, reinterpret_cast<PyObject *>(&PySideClassInfoType));
+}
+
+bool checkType(PyObject* pyObj)
+{
+ if (pyObj)
+ return PyType_IsSubtype(pyObj->ob_type, &PySideClassInfoType);
+ 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
new file mode 100644
index 000000000..9c92b3fcf
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideclassinfo.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QMap>
+#include <QByteArray>
+
+extern "C"
+{
+ extern PYSIDE_API PyTypeObject PySideClassInfoType;
+
+ 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
new file mode 100644
index 000000000..3dbc0cd9a
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideclassinfo_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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"
+
+#define __INFO_ATTR_NAME__ "__classInfo__"
+
+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/pysideconversions.h b/sources/pyside2/libpyside/pysideconversions.h
new file mode 100644
index 000000000..ed8002fae
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideconversions.h
@@ -0,0 +1,275 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 PYSIDECONVERSIONS_H
+#define PYSIDECONVERSIONS_H
+
+#include <sbkpython.h>
+#include <QFlag>
+#include <conversions.h>
+#include <pysideqflags.h>
+
+template <typename QtDict>
+struct QtDictConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return isConvertible(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, Shiboken::SbkType<QtDict>()))
+ return true;
+
+ if ((Shiboken::SbkType<QtDict>() && Shiboken::Object::checkType(pyObj)) || !PyDict_Check(pyObj))
+ return false;
+
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next(pyObj, &pos, &key, &value)) {
+ if (!Shiboken::Converter<typename QtDict::key_type>::isConvertible(key)
+ && !Shiboken::Converter<typename QtDict::mapped_type>::isConvertible(value)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<QtDict*>(cppObj)); }
+ static inline PyObject* toPython(const QtDict& cppobj)
+ {
+ PyObject* result = PyDict_New();
+ typename QtDict::const_iterator it = cppobj.begin();
+
+ for (; it != cppobj.end(); ++it) {
+ Shiboken::AutoDecRef keyObj(Shiboken::Converter<typename QtDict::key_type>::toPython(it.key()));
+ Shiboken::AutoDecRef valueObj(Shiboken::Converter<typename QtDict::mapped_type>::toPython(it.value()));
+ PyDict_SetItem(result, keyObj, valueObj);
+ }
+
+ return result;
+ }
+ static inline QtDict toCpp(PyObject* pyobj)
+ {
+ if (PyObject_TypeCheck(pyobj, Shiboken::SbkType<QtDict>()))
+ return *reinterpret_cast<QtDict *>(Shiboken::Object::cppPointer(reinterpret_cast<SbkObject *>(pyobj), Shiboken::SbkType<QtDict>()));
+
+ QtDict result;
+
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next(pyobj, &pos, &key, &value))
+ result[Shiboken::Converter<typename QtDict::key_type>::toCpp(key)] = Shiboken::Converter<typename QtDict::mapped_type>::toCpp(value);
+ return result;
+ }
+};
+
+template <typename MultiMap>
+struct QtMultiMapConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return isConvertible(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, Shiboken::SbkType<MultiMap>()))
+ return true;
+
+ if ((Shiboken::SbkType<MultiMap>() && Shiboken::Object::checkType(pyObj)) || !PyDict_Check(pyObj))
+ return false;
+
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next(pyObj, &pos, &key, &value)) {
+ if (!Shiboken::Converter<typename MultiMap::key_type>::isConvertible(key)) {
+ if (PySequence_Check(value)) {
+ for (int i = 0, max = PySequence_Length(value); i < max; ++i) {
+ Shiboken::AutoDecRef item(PySequence_GetItem(value, i));
+ if (!Shiboken::Converter<typename MultiMap::mapped_type>::isConvertible(value))
+ return false;
+ }
+ } else if (!Shiboken::Converter<typename MultiMap::mapped_type>::isConvertible(value)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<MultiMap*>(cppObj)); }
+ static inline PyObject* toPython(const MultiMap& cppObj)
+ {
+ PyObject* result = PyDict_New();
+ typename MultiMap::const_iterator it = cppObj.begin();
+
+ for (; it != cppObj.end(); ++it) {
+ Shiboken::AutoDecRef key(Shiboken::Converter<typename MultiMap::key_type>::toPython(it.key()));
+ Shiboken::AutoDecRef value(Shiboken::Converter<typename MultiMap::mapped_type>::toPython(it.value()));
+
+ PyObject* values = PyDict_GetItem(result, key);
+ bool decRefValues = !values;
+ if (!values)
+ values = PyList_New(0);
+ PyList_Append(values, value);
+ PyDict_SetItem(result, key, values);
+ if (decRefValues) {
+ Py_DECREF(values);
+ }
+ }
+
+ return result;
+ }
+
+ static inline MultiMap toCpp(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, Shiboken::SbkType<MultiMap>()))
+ return *reinterpret_cast<MultiMap *>(Shiboken::Object::cppPointer(reinterpret_cast<SbkObject *>(pyObj), Shiboken::SbkType<MultiMap>()));
+
+ MultiMap result;
+
+ PyObject* key;
+ PyObject* value;
+ Py_ssize_t pos = 0;
+
+ while (PyDict_Next(pyObj, &pos, &key, &value))
+ result[Shiboken::Converter<typename MultiMap::key_type>::toCpp(key)] = Shiboken::Converter<typename MultiMap::mapped_type>::toCpp(value);
+ return result;
+ }
+};
+
+template <typename T>
+struct QSequenceConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return isConvertible(pyObj);
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ if (PyObject_TypeCheck(pyObj, Shiboken::SbkType<T>()))
+ return true;
+ if ((Shiboken::SbkType<T>() && Shiboken::Object::checkType(pyObj)) || !PySequence_Check(pyObj))
+ return false;
+ for (int i = 0, max = PySequence_Length(pyObj); i < max; ++i) {
+ Shiboken::AutoDecRef item(PySequence_GetItem(pyObj, i));
+ if (!Shiboken::Converter<typename T::value_type>::isConvertible(item))
+ return false;
+ }
+ return true;
+ }
+ static inline PyObject* toPython(void* cppObj) { return toPython(*reinterpret_cast<T*>(cppObj)); }
+ static PyObject* toPython(const T& cppobj)
+ {
+ PyObject* result = PyList_New((int) cppobj.size());
+ typename T::const_iterator it = cppobj.begin();
+ for (int idx = 0; it != cppobj.end(); ++it, ++idx) {
+ typename T::value_type vh(*it);
+ PyList_SET_ITEM(result, idx, Shiboken::Converter<typename T::value_type>::toPython(vh));
+ }
+ return result;
+ }
+ static T toCpp(PyObject* pyobj)
+ {
+ if (PyObject_TypeCheck(pyobj, Shiboken::SbkType<T>()))
+ return *reinterpret_cast<T *>(Shiboken::Object::cppPointer(reinterpret_cast<SbkObject *>(pyobj), Shiboken::SbkType<T>()));
+
+ Shiboken::AutoDecRef fastSequence(PySequence_Fast(pyobj, "Invalid sequence object"));
+ T result;
+ for (int i = 0; i < PySequence_Size(pyobj); i++) {
+ PyObject* pyItem = PySequence_Fast_GET_ITEM(fastSequence.object(), i);
+ result << Shiboken::Converter<typename T::value_type>::toCpp(pyItem);
+ }
+ return result;
+ }
+};
+
+
+template <typename T>
+struct QFlagsConverter
+{
+ static inline bool checkType(PyObject* pyObj)
+ {
+ return PyObject_TypeCheck(pyObj, Shiboken::SbkType<T>());
+ }
+
+ static inline bool isConvertible(PyObject* pyObj)
+ {
+ return PyObject_TypeCheck(pyObj, Shiboken::SbkType<T>())
+ || PyObject_TypeCheck(pyObj, Shiboken::SbkType<typename T::enum_type>());
+ }
+
+ static inline PyObject* toPython(void* cppObj)
+ {
+ return toPython(*reinterpret_cast<T*>(cppObj));
+ }
+
+ static inline PyObject* toPython(const T& cppObj)
+ {
+ return reinterpret_cast<PyObject*>(PySide::QFlags::newObject(cppObj, Shiboken::SbkType<T>()));
+ }
+
+ static inline T toCpp(PyObject* pyObj)
+ {
+ /* this was long. Needed int in Qt5 */
+ int val = 0;
+ if (Shiboken::Enum::check(pyObj)) {
+ val = Shiboken::Enum::getValue(pyObj);
+ } else if (PyObject_TypeCheck(pyObj, Shiboken::SbkType<T>())) {
+ val = PySide::QFlags::getValue(reinterpret_cast<PySideQFlagsObject*>(pyObj));
+ } else if (PyNumber_Check(pyObj)) {
+ Shiboken::AutoDecRef pyLong(PyNumber_Long(pyObj));
+ val = PyLong_AsLong(pyLong.object());
+ } else {
+ PyErr_BadArgument();
+ }
+ return T(QFlag(val));
+ }
+};
+
+#endif
diff --git a/sources/pyside2/libpyside/pysidemacros.h b/sources/pyside2/libpyside/pysidemacros.h
new file mode 100644
index 000000000..df1ed6e8c
--- /dev/null
+++ b/sources/pyside2/libpyside/pysidemacros.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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
+
+#if defined _WIN32
+ #if PYSIDE_EXPORTS
+ #define PYSIDE_API __declspec(dllexport)
+ #else
+ #if defined __MINGW32__
+ #define PYSIDE_API
+ #else
+ #define PYSIDE_API __declspec(dllimport)
+ #endif
+ #endif
+ #define PYSIDE_DEPRECATED(func) __declspec(deprecated) func
+#else
+ #if __GNUC__ >= 4
+ #define PYSIDE_API __attribute__ ((visibility("default")))
+ #define PYSIDE_DEPRECATED(func) func __attribute__ ((deprecated))
+ #else
+ #define PYSIDE_API
+ #define PYSIDE_DEPRECATED(func) func
+ #endif
+#endif
+
+#endif
diff --git a/sources/pyside2/libpyside/pysidemetafunction.cpp b/sources/pyside2/libpyside/pysidemetafunction.cpp
new file mode 100644
index 000000000..039db513b
--- /dev/null
+++ b/sources/pyside2/libpyside/pysidemetafunction.cpp
@@ -0,0 +1,253 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "pysidemetafunction.h"
+#include "pysidemetafunction_p.h"
+
+#include <shiboken.h>
+#include <QObject>
+#include <QMetaMethod>
+#include <QDebug>
+
+extern "C"
+{
+
+struct PySideMetaFunctionPrivate
+{
+ QObject* qobject;
+ int methodIndex;
+};
+
+//methods
+static void functionFree(void*);
+static PyObject* functionCall(PyObject*, PyObject*, PyObject*);
+
+PyTypeObject PySideMetaFunctionType = {
+ PyVarObject_HEAD_INIT(0, 0)
+ /*tp_name*/ "PySide.MetaFunction",
+ /*tp_basicsize*/ sizeof(PySideMetaFunction),
+ /*tp_itemsize*/ 0,
+ /*tp_dealloc*/ 0,
+ /*tp_print*/ 0,
+ /*tp_getattr*/ 0,
+ /*tp_setattr*/ 0,
+ /*tp_compare*/ 0,
+ /*tp_repr*/ 0,
+ /*tp_as_number*/ 0,
+ /*tp_as_sequence*/ 0,
+ /*tp_as_mapping*/ 0,
+ /*tp_hash*/ 0,
+ /*tp_call*/ functionCall,
+ /*tp_str*/ 0,
+ /*tp_getattro*/ 0,
+ /*tp_setattro*/ 0,
+ /*tp_as_buffer*/ 0,
+ /*tp_flags*/ Py_TPFLAGS_DEFAULT,
+ /*tp_doc*/ "MetaFunction",
+ /*tp_traverse*/ 0,
+ /*tp_clear*/ 0,
+ /*tp_richcompare*/ 0,
+ /*tp_weaklistoffset*/ 0,
+ /*tp_iter*/ 0,
+ /*tp_iternext*/ 0,
+ /*tp_methods*/ 0,
+ /*tp_members*/ 0,
+ /*tp_getset*/ 0,
+ /*tp_base*/ 0,
+ /*tp_dict*/ 0,
+ /*tp_descr_get*/ 0,
+ /*tp_descr_set*/ 0,
+ /*tp_dictoffset*/ 0,
+ /*tp_init*/ 0,
+ /*tp_alloc*/ 0,
+ /*tp_new*/ PyType_GenericNew,
+ /*tp_free*/ functionFree,
+ /*tp_is_gc*/ 0,
+ /*tp_bases*/ 0,
+ /*tp_mro*/ 0,
+ /*tp_cache*/ 0,
+ /*tp_subclasses*/ 0,
+ /*tp_weaklist*/ 0,
+ /*tp_del*/ 0,
+ /*tp_version_tag*/ 0
+};
+
+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 {
+
+void init(PyObject* module)
+{
+ if (PyType_Ready(&PySideMetaFunctionType) < 0)
+ return;
+
+ PyModule_AddObject(module, "MetaFunction", reinterpret_cast<PyObject *>(&PySideMetaFunctionType));
+}
+
+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, &PySideMetaFunctionType);
+ 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[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) {
+ int typeId = QMetaType::type(typeName);
+ if (!Shiboken::Conversions::pythonTypeIsObjectType(converter)) {
+ if (!typeId) {
+ 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(typeId, static_cast<const void *>(0));
+ }
+ methArgs[i] = methValues[i].data();
+ if (i == 0) // Don't do this for return type
+ continue;
+ if (typeId == QVariant::String) {
+ 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
new file mode 100644
index 000000000..2be369407
--- /dev/null
+++ b/sources/pyside2/libpyside/pysidemetafunction.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QObject>
+#include <QString>
+#include <QStringList>
+
+#include <pysidemacros.h>
+#include <sbkpython.h>
+
+extern "C"
+{
+ extern PYSIDE_API PyTypeObject PySideMetaFunctionType;
+
+ 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
new file mode 100644
index 000000000..979bbb120
--- /dev/null
+++ b/sources/pyside2/libpyside/pysidemetafunction_p.h
@@ -0,0 +1,62 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QList>
+#include <QByteArray>
+
+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 = 0);
+
+} //namespace MetaFunction
+} //namespace PySide
+
+#endif
diff --git a/sources/pyside2/libpyside/pysideproperty.cpp b/sources/pyside2/libpyside/pysideproperty.cpp
new file mode 100644
index 000000000..07b9dfae5
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideproperty.cpp
@@ -0,0 +1,519 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QDebug>
+
+
+#define QPROPERTY_CLASS_NAME "Property"
+
+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* qPropertyCall(PyObject*, PyObject*, PyObject*);
+static PyObject* qPropertySetter(PyObject*, PyObject*);
+static PyObject* qPropertyGetter(PyObject*, PyObject*);
+static int qpropertyTraverse(PyObject* self, visitproc visit, void* arg);
+static int qpropertyClear(PyObject* self);
+
+static PyMethodDef PySidePropertyMethods[] = {
+ {"setter", (PyCFunction)qPropertySetter, METH_O, 0},
+ {"write", (PyCFunction)qPropertySetter, METH_O, 0},
+ {"getter", (PyCFunction)qPropertyGetter, METH_O, 0},
+ {"read", (PyCFunction)qPropertyGetter, METH_O, 0},
+ {0, 0, 0, 0}
+};
+
+PyTypeObject PySidePropertyType = {
+ PyVarObject_HEAD_INIT(0, 0)
+ QPROPERTY_CLASS_NAME, /*tp_name*/
+ sizeof(PySideProperty), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ qpropertyDeAlloc, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ qPropertyCall, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /*tp_flags*/
+ 0, /*tp_doc */
+ qpropertyTraverse, /*tp_traverse */
+ qpropertyClear, /*tp_clear */
+ 0, /*tp_richcompare */
+ 0, /*tp_weaklistoffset */
+ 0, /*tp_iter */
+ 0, /*tp_iternext */
+ PySidePropertyMethods, /*tp_methods */
+ 0, /*tp_members */
+ 0, /*tp_getset */
+ 0, /*tp_base */
+ 0, /*tp_dict */
+ 0, /*tp_descr_get */
+ 0, /*tp_descr_set */
+ 0, /*tp_dictoffset */
+ qpropertyTpInit, /*tp_init */
+ 0, /*tp_alloc */
+ qpropertyTpNew, /*tp_new */
+ 0, /*tp_free */
+ 0, /*tp_is_gc */
+ 0, /*tp_bases */
+ 0, /*tp_mro */
+ 0, /*tp_cache */
+ 0, /*tp_subclasses */
+ 0, /*tp_weaklist */
+ 0, /*tp_del */
+ 0 /*tp_version_tag */
+};
+
+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;
+ }
+
+ case QMetaObject::QueryPropertyDesignable:
+ case QMetaObject::QueryPropertyScriptable:
+ case QMetaObject::QueryPropertyStored:
+ case QMetaObject::QueryPropertyEditable:
+ case QMetaObject::QueryPropertyUser:
+ // just to avoid gcc warnings
+ 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;
+ memset(me->d, 0, sizeof(PySidePropertyPrivate));
+ PySidePropertyPrivate* pData = me->d;
+ pData->designable = true;
+ pData->scriptable = true;
+ pData->stored = true;
+ return reinterpret_cast<PyObject *>(me);
+}
+
+int qpropertyTpInit(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ PyObject* type = 0;
+ PySideProperty* 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};
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ "O|OOOOsObbbbbb:QtCore.QProperty", (char**) kwlist,
+ /*OO*/ &type, &(pData->fget),
+ /*OOO*/ &(pData->fset), &(pData->freset), &(pData->fdel),
+ /*s*/ &(pData->doc),
+ /*O*/ &(pData->notify),
+ /*bbbbbb*/ &(pData->designable), &(pData->scriptable), &(pData->stored), &(pData->user), &(pData->constant), &(pData->final))) {
+ return 0;
+ }
+
+
+ pData->typeName = PySide::Signal::getTypeName(type);
+
+ if (!pData->typeName)
+ 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 1;
+ } else {
+ pData->fget = 0;
+ pData->fset = 0;
+ pData->freset = 0;
+ pData->fdel = 0;
+ pData->notify = 0;
+ return -1;
+ }
+}
+
+void qpropertyDeAlloc(PyObject* self)
+{
+ qpropertyClear(self);
+ Py_TYPE(self)->tp_free(self);
+}
+
+PyObject *qPropertyCall(PyObject *self, PyObject *args, PyObject * /* kw */)
+{
+ PyObject *callback = PyTuple_GetItem(args, 0);
+ if (PyFunction_Check(callback)) {
+ PySideProperty *prop = reinterpret_cast<PySideProperty*>(self);
+ PySidePropertyPrivate* pData = prop->d;
+
+ Py_INCREF(callback);
+ pData->fget = callback;
+
+ Py_INCREF(self);
+ return self;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Invalid property usage.");
+ return 0;
+ }
+}
+
+PyObject* qPropertySetter(PyObject* self, PyObject* callback)
+{
+ if (PyFunction_Check(callback)) {
+ PySideProperty *prop = reinterpret_cast<PySideProperty*>(self);
+ PySidePropertyPrivate* pData = prop->d;
+
+ Py_INCREF(callback);
+ pData->fset = callback;
+
+ Py_INCREF(callback);
+ return callback;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Invalid property setter agument.");
+ return 0;
+ }
+}
+
+PyObject* qPropertyGetter(PyObject* self, PyObject* callback)
+{
+ if (PyFunction_Check(callback)) {
+ PySideProperty *prop = reinterpret_cast<PySideProperty*>(self);
+ PySidePropertyPrivate* pData = prop->d;
+
+ Py_INCREF(callback);
+ pData->fget = callback;
+
+ Py_INCREF(callback);
+ return callback;
+ } else {
+ PyErr_SetString(PyExc_TypeError, "Invalid property getter agument.");
+ return 0;
+ }
+}
+
+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);
+
+
+ free(data->typeName);
+ free(data->doc);
+ free(data->notifySignature);
+ delete data;
+ reinterpret_cast<PySideProperty*>(self)->d = 0;
+ return 0;
+}
+
+} // extern "C"
+
+namespace {
+
+static PyObject* getFromType(PyTypeObject* type, PyObject* name)
+{
+ PyObject* attr = 0;
+ 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 {
+
+void init(PyObject* module)
+{
+ if (PyType_Ready(&PySidePropertyType) < 0)
+ return;
+
+ Py_INCREF(&PySidePropertyType);
+ PyModule_AddObject(module, QPROPERTY_CLASS_NAME, reinterpret_cast<PyObject *>(&PySidePropertyType));
+}
+
+bool checkType(PyObject* pyObj)
+{
+ if (pyObj) {
+ return PyType_IsSubtype(pyObj->ob_type, &PySidePropertyType);
+ }
+ return false;
+}
+
+bool isPropertyType(PyObject* pyObj)
+{
+ return checkType(pyObj);
+}
+
+int setValue(PySideProperty* self, PyObject* source, PyObject* value)
+{
+ PyObject* fset = self->d->fset;
+ if (fset) {
+ 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);
+ } else {
+ 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 = 0;
+
+ if (Shiboken::Object::isUserType(source)) {
+ PyObject* dict = reinterpret_cast<SbkObject*>(source)->ob_dict;
+ if (dict)
+ attr = PyDict_GetItem(dict, name);
+ }
+
+ attr = getFromType(source->ob_type, 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) {
+ PyObject* str = PyObject_Str(self->d->notify);
+ self->d->notifySignature = strdup(Shiboken::String::toCString(str));
+ Py_DECREF(str);
+ }
+
+ return self->d->notifySignature;
+}
+
+void setMetaCallHandler(PySideProperty* self, MetaCallHandler handler)
+{
+ self->d->metaCallHandler = handler;
+}
+
+void setTypeName(PySideProperty* self, const char* typeName)
+{
+ self->d->typeName = strdup(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
new file mode 100644
index 000000000..9ac61dc23
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideproperty.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QObject>
+
+extern "C"
+{
+ extern PYSIDE_API PyTypeObject PySidePropertyType;
+
+ 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);
+
+/// @deprecated Use checkType
+PYSIDE_DEPRECATED(PYSIDE_API bool isPropertyType(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
new file mode 100644
index 000000000..95ed2a0f8
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideproperty_p.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QMetaObject>
+#include "pysideproperty.h"
+
+struct PySideProperty;
+
+extern "C"
+{
+
+struct PySidePropertyPrivate {
+ char* typeName;
+ PySide::Property::MetaCallHandler metaCallHandler;
+ PyObject* fget;
+ PyObject* fset;
+ PyObject* freset;
+ PyObject* fdel;
+ PyObject* notify;
+ char* notifySignature;
+ char* doc;
+ bool designable;
+ bool scriptable;
+ bool stored;
+ bool user;
+ bool constant;
+ bool final;
+ void* userData;
+};
+
+} // extern "C"
+
+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/pysideqflags.cpp b/sources/pyside2/libpyside/pysideqflags.cpp
new file mode 100644
index 000000000..380c67f61
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideqflags.cpp
@@ -0,0 +1,167 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <sbkenum.h>
+#include <autodecref.h>
+
+extern "C" {
+ struct SbkConverter;
+
+ /**
+ * Type of all QFlags
+ */
+ struct PySideQFlagsType
+ {
+ PyHeapTypeObject super;
+ SbkConverter** converterPtr;
+ SbkConverter* converter;
+ };
+
+ #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);
+ }
+
+ 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
+{
+ PyTypeObject* create(const char* name, PyNumberMethods* numberMethods)
+ {
+ PyTypeObject* type = reinterpret_cast<PyTypeObject*>(new PySideQFlagsType);
+ ::memset(type, 0, sizeof(PySideQFlagsType));
+ Py_TYPE(type) = &PyType_Type;
+ type->tp_basicsize = sizeof(PySideQFlagsObject);
+ type->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES;
+ type->tp_name = name;
+ type->tp_new = &PySideQFlagsNew;
+ type->tp_as_number = numberMethods;
+ type->tp_richcompare = &PySideQFlagsRichCompare;
+
+ PySideQFlagsType* flagsType = reinterpret_cast<PySideQFlagsType*>(type);
+ flagsType->converterPtr = &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
new file mode 100644
index 000000000..500727eaf
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideqflags.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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, PyNumberMethods* 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
new file mode 100644
index 000000000..e213ff069
--- /dev/null
+++ b/sources/pyside2/libpyside/pysidesignal.cpp
@@ -0,0 +1,1070 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "signalmanager.h"
+
+#include <shiboken.h>
+#include <QDebug>
+
+#define SIGNAL_CLASS_NAME "Signal"
+#define SIGNAL_INSTANCE_NAME "SignalInstance"
+#define QT_SIGNAL_SENTINEL '2'
+
+namespace PySide {
+namespace Signal {
+ //aux
+ class SignalSignature {
+ public:
+ SignalSignature() : m_attributes(QMetaMethod::Compatibility) {}
+ SignalSignature(QByteArray parameterTypes) : m_parameterTypes(parameterTypes),
+ m_attributes(QMetaMethod::Compatibility) {}
+ SignalSignature(QByteArray parameterTypes, QMetaMethod::Attributes attributes) :
+ m_parameterTypes(parameterTypes),
+ m_attributes(attributes) {}
+ QByteArray m_parameterTypes;
+ QMetaMethod::Attributes m_attributes;
+ };
+
+ static char* buildSignature(const char*, const char*);
+ static void appendSignature(PySideSignal*, const SignalSignature &);
+ static void instanceInitialize(PySideSignalInstance*, PyObject*, PySideSignal*, PyObject*, int);
+ static char* parseSignature(PyObject*);
+ static PyObject* buildQtCompatible(const char*);
+}
+}
+
+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);
+
+// 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 PyMappingMethods Signal_as_mapping = {
+ 0,
+ signalGetItem,
+ 0
+};
+
+static PyMethodDef Signal_methods[] = {
+ {"__instancecheck__", (PyCFunction)metaSignalCheck, METH_O, NULL},
+ {0, 0, 0, 0}
+};
+
+PyTypeObject PySideSignalMetaType = {
+ PyVarObject_HEAD_INIT(0, 0)
+ /*tp_name*/ "PySide2.QtCore.MetaSignal",
+ /*tp_basicsize*/ sizeof(PyTypeObject),
+ /*tp_itemsize*/ 0,
+ /*tp_dealloc*/ 0,
+ /*tp_print*/ 0,
+ /*tp_getattr*/ 0,
+ /*tp_setattr*/ 0,
+ /*tp_compare*/ 0,
+ /*tp_repr*/ 0,
+ /*tp_as_number*/ 0,
+ /*tp_as_sequence*/ 0,
+ /*tp_as_mapping*/ 0,
+ /*tp_hash*/ 0,
+ /*tp_call*/ 0,
+ /*tp_str*/ 0,
+ /*tp_getattro*/ 0,
+ /*tp_setattro*/ 0,
+ /*tp_as_buffer*/ 0,
+ /*tp_flags*/ Py_TPFLAGS_DEFAULT,
+ /*tp_doc*/ 0,
+ /*tp_traverse*/ 0,
+ /*tp_clear*/ 0,
+ /*tp_richcompare*/ 0,
+ /*tp_weaklistoffset*/ 0,
+ /*tp_iter*/ 0,
+ /*tp_iternext*/ 0,
+ /*tp_methods*/ Signal_methods,
+ /*tp_members*/ 0,
+ /*tp_getset*/ 0,
+ /*tp_base*/ &PyType_Type,
+ /*tp_dict*/ 0,
+ /*tp_descr_get*/ 0,
+ /*tp_descr_set*/ 0,
+ /*tp_dictoffset*/ 0,
+ /*tp_init*/ 0,
+ /*tp_alloc*/ 0,
+ /*tp_new*/ 0,
+ /*tp_free*/ 0,
+ /*tp_is_gc*/ 0,
+ /*tp_bases*/ 0,
+ /*tp_mro*/ 0,
+ /*tp_cache*/ 0,
+ /*tp_subclasses*/ 0,
+ /*tp_weaklist*/ 0,
+ /*tp_del*/ 0,
+ /*tp_version_tag*/ 0
+};
+
+PyTypeObject PySideSignalType = {
+ PyVarObject_HEAD_INIT(&PySideSignalMetaType, 0)
+ /*tp_name*/ "PySide2.QtCore." SIGNAL_CLASS_NAME,
+ /*tp_basicsize*/ sizeof(PySideSignal),
+ /*tp_itemsize*/ 0,
+ /*tp_dealloc*/ 0,
+ /*tp_print*/ 0,
+ /*tp_getattr*/ 0,
+ /*tp_setattr*/ 0,
+ /*tp_compare*/ 0,
+ /*tp_repr*/ 0,
+ /*tp_as_number*/ 0,
+ /*tp_as_sequence*/ 0,
+ /*tp_as_mapping*/ &Signal_as_mapping,
+ /*tp_hash*/ 0,
+ /*tp_call*/ signalCall,
+ /*tp_str*/ signalToString,
+ /*tp_getattro*/ 0,
+ /*tp_setattro*/ 0,
+ /*tp_as_buffer*/ 0,
+ /*tp_flags*/ Py_TPFLAGS_DEFAULT,
+ /*tp_doc*/ SIGNAL_CLASS_NAME,
+ /*tp_traverse*/ 0,
+ /*tp_clear*/ 0,
+ /*tp_richcompare*/ 0,
+ /*tp_weaklistoffset*/ 0,
+ /*tp_iter*/ 0,
+ /*tp_iternext*/ 0,
+ /*tp_methods*/ 0,
+ /*tp_members*/ 0,
+ /*tp_getset*/ 0,
+ /*tp_base*/ 0,
+ /*tp_dict*/ 0,
+ /*tp_descr_get*/ 0,
+ /*tp_descr_set*/ 0,
+ /*tp_dictoffset*/ 0,
+ /*tp_init*/ signalTpInit,
+ /*tp_alloc*/ 0,
+ /*tp_new*/ PyType_GenericNew,
+ /*tp_free*/ signalFree,
+ /*tp_is_gc*/ 0,
+ /*tp_bases*/ 0,
+ /*tp_mro*/ 0,
+ /*tp_cache*/ 0,
+ /*tp_subclasses*/ 0,
+ /*tp_weaklist*/ 0,
+ /*tp_del*/ 0,
+ /*tp_version_tag*/ 0
+};
+
+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 PyMappingMethods SignalInstance_as_mapping = {
+ 0,
+ signalInstanceGetItem,
+ 0
+};
+
+PyTypeObject PySideSignalInstanceType = {
+ PyVarObject_HEAD_INIT(0, 0)
+ /*tp_name*/ "PySide2.QtCore." SIGNAL_INSTANCE_NAME,
+ /*tp_basicsize*/ sizeof(PySideSignalInstance),
+ /*tp_itemsize*/ 0,
+ /*tp_dealloc*/ 0,
+ /*tp_print*/ 0,
+ /*tp_getattr*/ 0,
+ /*tp_setattr*/ 0,
+ /*tp_compare*/ 0,
+ /*tp_repr*/ 0,
+ /*tp_as_number*/ 0,
+ /*tp_as_sequence*/ 0,
+ /*tp_as_mapping*/ &SignalInstance_as_mapping,
+ /*tp_hash*/ 0,
+ /*tp_call*/ signalInstanceCall,
+ /*tp_str*/ 0,
+ /*tp_getattro*/ 0,
+ /*tp_setattro*/ 0,
+ /*tp_as_buffer*/ 0,
+ /*tp_flags*/ Py_TPFLAGS_DEFAULT,
+ /*tp_doc*/ SIGNAL_INSTANCE_NAME,
+ /*tp_traverse*/ 0,
+ /*tp_clear*/ 0,
+ /*tp_richcompare*/ 0,
+ /*tp_weaklistoffset*/ 0,
+ /*tp_iter*/ 0,
+ /*tp_iternext*/ 0,
+ /*tp_methods*/ SignalInstance_methods,
+ /*tp_members*/ 0,
+ /*tp_getset*/ 0,
+ /*tp_base*/ 0,
+ /*tp_dict*/ 0,
+ /*tp_descr_get*/ 0,
+ /*tp_descr_set*/ 0,
+ /*tp_dictoffset*/ 0,
+ /*tp_init*/ 0,
+ /*tp_alloc*/ 0,
+ /*tp_new*/ PyType_GenericNew,
+ /*tp_free*/ signalInstanceFree,
+ /*tp_is_gc*/ 0,
+ /*tp_bases*/ 0,
+ /*tp_mro*/ 0,
+ /*tp_cache*/ 0,
+ /*tp_subclasses*/ 0,
+ /*tp_weaklist*/ 0,
+ /*tp_del*/ 0,
+ /*tp_version_tag*/ 0
+};
+
+int signalTpInit(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ static PyObject* emptyTuple = 0;
+ static const char* kwlist[] = {"name", 0};
+ char* argName = 0;
+
+ if (emptyTuple == 0)
+ emptyTuple = PyTuple_New(0);
+
+ if (!PyArg_ParseTupleAndKeywords(emptyTuple, kwds,
+ "|s:QtCore." SIGNAL_CLASS_NAME, const_cast<char**>(kwlist), &argName))
+ return 0;
+
+ bool tupledArgs = false;
+ PySideSignal* data = reinterpret_cast<PySideSignal*>(self);
+ if (argName) {
+ data->signalName = strdup(argName);
+ }
+
+ 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)) {
+ tupledArgs = true;
+ char *sig = PySide::Signal::parseSignature(arg);
+ PySide::Signal::appendSignature(
+ data,
+ PySide::Signal::SignalSignature(sig));
+ free(sig);
+ }
+ }
+
+ if (!tupledArgs) {
+ char *sig = PySide::Signal::parseSignature(args);
+ PySide::Signal::appendSignature(
+ data,
+ PySide::Signal::SignalSignature(sig));
+ free(sig);
+ }
+
+ return 1;
+}
+
+void signalFree(void* self)
+{
+ PyObject* pySelf = reinterpret_cast<PyObject*>(self);
+ PySideSignal* data = reinterpret_cast<PySideSignal*>(self);
+
+ for (int i = 0, i_max = data->signaturesSize; i < i_max; i++) {
+ if (data->signatures[i])
+ free(data->signatures[i]);
+ }
+
+ free(data->signatures);
+ free(data->signatureAttributes);
+ free(data->signalName);
+ data->initialized = 0;
+ data->signaturesSize = 0;
+ Py_XDECREF(data->homonymousMethod);
+ data->homonymousMethod = 0;
+
+ pySelf->ob_type->tp_base->tp_free(self);
+}
+
+PyObject* signalGetItem(PyObject* self, PyObject* key)
+{
+ PySideSignal* data = reinterpret_cast<PySideSignal*>(self);
+ char* sigKey;
+ if (key) {
+ sigKey = PySide::Signal::parseSignature(key);
+ } else {
+ if (data->signatures[0])
+ sigKey = strdup(data->signatures[0]);
+ else
+ sigKey = strdup("void");
+ }
+ char* sig = PySide::Signal::buildSignature(data->signalName, sigKey);
+ free(sigKey);
+ PyObject* pySignature = Shiboken::String::fromCString(sig);
+ free(sig);
+ return pySignature;
+}
+
+
+PyObject* signalToString(PyObject* self)
+{
+ return signalGetItem(self, 0);
+}
+
+void signalInstanceFree(void* self)
+{
+ PyObject* pySelf = reinterpret_cast<PyObject*>(self);
+ PySideSignalInstance* data = reinterpret_cast<PySideSignalInstance*>(self);
+
+ PySideSignalInstancePrivate* dataPvt = data->d;
+ free(dataPvt->signalName);
+ free(dataPvt->signature);
+
+ Py_XDECREF(dataPvt->homonymousMethod);
+
+ if (dataPvt->next) {
+ Py_DECREF(dataPvt->next);
+ dataPvt->next = 0;
+ }
+ delete dataPvt;
+ data->d = 0;
+ pySelf->ob_type->tp_base->tp_free(self);
+}
+
+PyObject* signalInstanceConnect(PyObject* self, PyObject* args, PyObject* kwds)
+{
+ PyObject* slot = 0;
+ PyObject* type = 0;
+ static const char* kwlist[] = {"slot", "type", 0};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ "O|O:" SIGNAL_INSTANCE_NAME, const_cast<char**>(kwlist), &slot, &type))
+ return 0;
+
+ PySideSignalInstance* source = reinterpret_cast<PySideSignalInstance*>(self);
+ Shiboken::AutoDecRef pyArgs(PyList_New(0));
+
+ bool match = false;
+ if (slot->ob_type == &PySideSignalInstanceType) {
+ 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 {
+ //try the first signature
+ PyList_Append(pyArgs, source->d->source);
+ 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_GetAttrString(source->d->source, "connect"));
+ 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)
+ return result;
+ else
+ 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);
+ return 0;
+}
+
+int argCountInSignature(const char *signature)
+{
+ return QByteArray(signature).count(",") + 1;
+}
+
+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_GetAttrString(source->d->source, "emit"));
+
+ Shiboken::AutoDecRef tupleArgs(PyList_AsTuple(pyArgs));
+ return PyObject_CallObject(pyMethod, tupleArgs);
+}
+
+PyObject* signalInstanceGetItem(PyObject* self, PyObject* key)
+{
+ PySideSignalInstance* data = reinterpret_cast<PySideSignalInstance*>(self);
+ char* sigKey = PySide::Signal::parseSignature(key);
+ char* sig = PySide::Signal::buildSignature(data->d->signalName, sigKey);
+ free(sigKey);
+ const char* sigName = data->d->signalName;
+
+ while (data) {
+ if (strcmp(data->d->signature, sig) == 0) {
+ free(sig);
+ PyObject* result = reinterpret_cast<PyObject*>(data);
+ Py_INCREF(result);
+ return result;
+ }
+ data = reinterpret_cast<PySideSignalInstance*>(data->d->next);
+ }
+
+ PyErr_Format(PyExc_IndexError, "Signature %s not found for signal: %s", sig, sigName);
+ free(sig);
+ return 0;
+}
+
+PyObject* signalInstanceDisconnect(PyObject* self, PyObject* args)
+{
+ PySideSignalInstance* 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 (slot->ob_type == &PySideSignalInstanceType) {
+ 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_GetAttrString(source->d->source, "disconnect"));
+ 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);
+ return 0;
+}
+
+PyObject* signalCall(PyObject* self, PyObject* args, PyObject* kw)
+{
+ PySideSignal* signal = reinterpret_cast<PySideSignal*>(self);
+
+ if (!signal->homonymousMethod) {
+ PyErr_SetString(PyExc_TypeError, "native Qt signal is not callable");
+ return 0;
+ }
+
+ descrgetfunc getDescriptor = signal->homonymousMethod->ob_type->tp_descr_get;
+ Shiboken::AutoDecRef homonymousMethod(getDescriptor(signal->homonymousMethod, 0, 0));
+
+ if (PyCFunction_GET_FLAGS(homonymousMethod.object()) & METH_STATIC)
+ return PyCFunction_Call(homonymousMethod, args, kw);
+
+ ternaryfunc callFunc = signal->homonymousMethod->ob_type->tp_call;
+ return callFunc(homonymousMethod, args, kw);
+}
+
+PyObject* signalInstanceCall(PyObject* self, PyObject* args, PyObject* kw)
+{
+ PySideSignalInstance* PySideSignal = reinterpret_cast<PySideSignalInstance*>(self);
+ if (!PySideSignal->d->homonymousMethod) {
+ PyErr_SetString(PyExc_TypeError, "native Qt signal is not callable");
+ return 0;
+ }
+
+ descrgetfunc getDescriptor = PySideSignal->d->homonymousMethod->ob_type->tp_descr_get;
+ Shiboken::AutoDecRef homonymousMethod(getDescriptor(PySideSignal->d->homonymousMethod, PySideSignal->d->source, 0));
+ return PyCFunction_Call(homonymousMethod, args, kw);
+}
+
+static PyObject *metaSignalCheck(PyObject * /* klass */, PyObject* args)
+{
+ if (PyType_IsSubtype(args->ob_type, &PySideSignalInstanceType))
+ Py_RETURN_TRUE;
+ else
+ Py_RETURN_FALSE;
+}
+
+} // extern "C"
+
+namespace PySide {
+namespace Signal {
+
+void init(PyObject* module)
+{
+ if (PyType_Ready(&PySideSignalMetaType) < 0)
+ return;
+
+ if (PyType_Ready(&PySideSignalType) < 0)
+ return;
+
+ Py_INCREF(&PySideSignalType);
+ PyModule_AddObject(module, SIGNAL_CLASS_NAME, reinterpret_cast<PyObject *>(&PySideSignalType));
+
+ if (PyType_Ready(&PySideSignalInstanceType) < 0)
+ return;
+
+ Py_INCREF(&PySideSignalInstanceType);
+}
+
+bool checkType(PyObject* pyObj)
+{
+ if (pyObj)
+ return PyType_IsSubtype(pyObj->ob_type, &PySideSignalType);
+ 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, &PySideSignalType)) {
+ Shiboken::AutoDecRef signalInstance(reinterpret_cast<PyObject *>(PyObject_New(PySideSignalInstance, &PySideSignalInstanceType)));
+ instanceInitialize(signalInstance.cast<PySideSignalInstance*>(), key, reinterpret_cast<PySideSignal*>(value), source, 0);
+ PyObject_SetAttr(source, key, signalInstance);
+ }
+ }
+
+ Py_XDECREF(objType);
+}
+
+char* getTypeName(PyObject* type)
+{
+ if (PyType_Check(type)) {
+ char* typeName = NULL;
+ if (PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(type), reinterpret_cast<PyTypeObject*>(&SbkObject_Type))) {
+ SbkObjectType* objType = reinterpret_cast<SbkObjectType*>(type);
+ typeName = strdup(Shiboken::ObjectType::getOriginalName(objType));
+ } else {
+ // Translate python types to Qt names
+ PyTypeObject* objType = reinterpret_cast<PyTypeObject*>(type);
+ if (Shiboken::String::checkType(objType))
+ typeName = strdup("QString");
+ else if (objType == &PyInt_Type)
+ typeName = strdup("int");
+ else if (objType == &PyLong_Type)
+ typeName = strdup("long");
+ else if (objType == &PyFloat_Type)
+ typeName = strdup("double");
+ else if (objType == &PyBool_Type)
+ typeName = strdup("bool");
+ else if (Py_TYPE(objType) == &SbkEnumType_Type)
+ typeName = strdup(Shiboken::Enum::getCppName(objType));
+ else
+ typeName = strdup("PyObject");
+ }
+ return typeName;
+ } else if (type == Py_None) { // Must be checked before as Shiboken::String::check accepts Py_None
+ return strdup("void");
+ } else if (Shiboken::String::check(type)) {
+ const char *result = Shiboken::String::toCString(type);
+ if (!strcmp(result, "qreal"))
+ result = sizeof(qreal) == sizeof(double) ? "double" : "float";
+ return strdup(result);
+ }
+ return 0;
+}
+
+char* buildSignature(const char* name, const char* signature)
+{
+ QByteArray signal(name);
+ signal += '(';
+ signal += signature;
+ signal += ')';
+ return strdup(QMetaObject::normalizedSignature(signal));
+}
+
+char* parseSignature(PyObject* args)
+{
+ char* signature = 0;
+ if (args && (Shiboken::String::check(args) || !PySequence_Check(args)))
+ return getTypeName(args);
+
+ for (Py_ssize_t i = 0, i_max = PySequence_Size(args); i < i_max; i++) {
+ Shiboken::AutoDecRef arg(PySequence_ITEM(args, i));
+ char* typeName = getTypeName(arg);
+ if (typeName) {
+ if (signature) {
+ signature = reinterpret_cast<char*>(realloc(signature, (strlen(signature) + 1 + strlen(typeName)) * sizeof(char*)));
+ signature = strcat(signature, ",");
+ signature = strcat(signature, typeName);
+ free(typeName);
+ } else {
+ signature = typeName;
+ }
+ }
+ }
+ return signature;
+}
+
+void appendSignature(PySideSignal* self, const SignalSignature &signature)
+{
+ self->signaturesSize++;
+
+ if (self->signaturesSize > 1) {
+ self->signatures = reinterpret_cast<char **>(realloc(self->signatures, sizeof(char *) * self->signaturesSize));
+ self->signatureAttributes = reinterpret_cast<int *>(realloc(self->signatureAttributes, sizeof(int) * self->signaturesSize));
+ } else {
+ self->signatures = reinterpret_cast<char **>(malloc(sizeof(char *)));
+ self->signatureAttributes = reinterpret_cast<int *>(malloc(sizeof(int)));
+ }
+ self->signatures[self->signaturesSize - 1] = strdup(signature.m_parameterTypes);
+ self->signatureAttributes[self->signaturesSize - 1] = signature.m_attributes;
+}
+
+PySideSignalInstance* initialize(PySideSignal* self, PyObject* name, PyObject* object)
+{
+ PySideSignalInstance* instance = PyObject_New(PySideSignalInstance, &PySideSignalInstanceType);
+ SbkObject* sbkObj = reinterpret_cast<SbkObject*>(object);
+ if (!Shiboken::Object::wasCreatedByPython(sbkObj))
+ Py_INCREF(object); // PYSIDE-79: this flag was crucial for a wrapper call.
+ instanceInitialize(instance, name, self, object, 0);
+ return instance;
+}
+
+void instanceInitialize(PySideSignalInstance* self, PyObject* name, PySideSignal* data, PyObject* source, int index)
+{
+ self->d = new PySideSignalInstancePrivate;
+ PySideSignalInstancePrivate* selfPvt = self->d;
+ selfPvt->next = 0;
+ if (data->signalName)
+ selfPvt->signalName = strdup(data->signalName);
+ else {
+ selfPvt->signalName = strdup(Shiboken::String::toCString(name));
+ data->signalName = strdup(selfPvt->signalName);
+ }
+
+ selfPvt->source = source;
+ selfPvt->signature = buildSignature(self->d->signalName, data->signatures[index]);
+ selfPvt->attributes = data->signatureAttributes[index];
+ selfPvt->homonymousMethod = 0;
+ if (data->homonymousMethod) {
+ selfPvt->homonymousMethod = data->homonymousMethod;
+ Py_INCREF(selfPvt->homonymousMethod);
+ }
+ index++;
+
+ if (index < data->signaturesSize) {
+ selfPvt->next = PyObject_New(PySideSignalInstance, &PySideSignalInstanceType);
+ instanceInitialize(selfPvt->next, name, data, source, index);
+ }
+}
+
+bool connect(PyObject* source, const char* signal, PyObject* callback)
+{
+ Shiboken::AutoDecRef pyMethod(PyObject_GetAttrString(source, "connect"));
+ 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 = 0;
+ PySideSignalInstance* previous = 0;
+ foreach (const QMetaMethod &m, methodList) {
+ PySideSignalInstance* item = PyObject_New(PySideSignalInstance, &PySideSignalInstanceType);
+ 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 = strdup(cppName.data());
+ selfPvt->signature = strdup(m.methodSignature());
+ selfPvt->attributes = m.attributes();
+ selfPvt->homonymousMethod = 0;
+ selfPvt->next = 0;
+ }
+ return root;
+}
+
+PySideSignal* newObject(const char* name, ...)
+{
+ va_list listSignatures;
+ char* sig = 0;
+ PySideSignal* self = PyObject_New(PySideSignal, &PySideSignalType);
+ self->signalName = strdup(name);
+ self->signaturesSize = 0;
+ self->signatures = 0;
+ self->signatureAttributes = 0;
+ self->initialized = 0;
+ self->homonymousMethod = 0;
+
+ va_start(listSignatures, name);
+ sig = va_arg(listSignatures, char*);
+
+ while (sig != NULL) {
+ if (strcmp(sig, "void") == 0)
+ appendSignature(self, SignalSignature(""));
+ else
+ appendSignature(self, SignalSignature(sig));
+
+ sig = va_arg(listSignatures, char*);
+ }
+
+ va_end(listSignatures);
+
+ return self;
+}
+
+template<typename T>
+static typename T::value_type join(T t, const char* sep)
+{
+ typename T::value_type res;
+ if (!t.size())
+ 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)
+{
+ PyObject* typeDict = wrapperType->super.ht_type.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();
+}
+
+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, &PySideSignalType);
+ self->signalName = strdup(it.key().constData());
+ self->signaturesSize = 0;
+ self->signatures = 0;
+ self->signatureAttributes = 0;
+ self->initialized = 0;
+ self->homonymousMethod = 0;
+
+ // Empty signatures comes first! So they will be the default signal signature
+ qStableSort(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* buildQtCompatible(const char* signature)
+{
+ QByteArray ba;
+ ba.append(QT_SIGNAL_SENTINEL);
+ ba.append(signature);
+ return Shiboken::String::fromStringAndSize(ba, ba.size());
+}
+
+void addSignalToWrapper(SbkObjectType* wrapperType, const char* signalName, PySideSignal* signal)
+{
+ _addSignalToWrapper(wrapperType, signalName, signal);
+}
+
+PyObject* getObject(PySideSignalInstance* signal)
+{
+ return signal->d->source;
+}
+
+const char* getSignature(PySideSignalInstance* signal)
+{
+ return signal->d->signature;
+}
+
+const char** getSignatures(PyObject* signal, int* size)
+{
+ PySideSignal* self = reinterpret_cast<PySideSignal*>(signal);
+ *size = self->signaturesSize;
+ return const_cast<const char**>(self->signatures);
+}
+
+QStringList getArgsFromSignature(const char* signature, bool* isShortCircuit)
+{
+ const QString qsignature = QLatin1String(signature);
+ QStringList result;
+ QRegExp splitRegex(QLatin1String("\\s*,\\s*"));
+
+ if (isShortCircuit)
+ *isShortCircuit = !qsignature.contains(QLatin1Char('('));
+ if (qsignature.contains(QLatin1String("()")) || qsignature.contains(QLatin1String("(void)"))) {
+ return result;
+ } else if (qsignature.contains(QLatin1Char('('))) {
+ static QRegExp regex(QLatin1String(".+\\((.*)\\)"));
+ //get args types
+ QString types = qsignature;
+ types.replace(regex, QLatin1String("\\1"));
+ result = types.split(splitRegex);
+ }
+ 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;
+ PyCodeObject* objCode = reinterpret_cast<PyCodeObject*>(PyFunction_GET_CODE(function));
+ functionName = Shiboken::String::toCString(reinterpret_cast<PyFunctionObject*>(function)->func_name);
+ useSelf = isMethod;
+ numArgs = objCode->co_flags & CO_VARARGS ? -1 : objCode->co_argcount;
+ } else if (PyCFunction_Check(callback)) {
+ const PyCFunctionObject *funcObj = reinterpret_cast<const PyCFunctionObject *>(callback);
+ functionName = funcObj->m_ml->ml_name;
+ useSelf = funcObj->m_self;
+ const int flags = funcObj->m_ml->ml_flags;
+
+ 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);
+ } else {
+ return funcName + QString::number(quint64(callback), 16);
+ }
+}
+
+} //namespace Signal
+} //namespace PySide
+
diff --git a/sources/pyside2/libpyside/pysidesignal.h b/sources/pyside2/libpyside/pysidesignal.h
new file mode 100644
index 000000000..ead62198c
--- /dev/null
+++ b/sources/pyside2/libpyside/pysidesignal.h
@@ -0,0 +1,173 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QObject>
+#include <QString>
+#include <QStringList>
+
+#include <pysidemacros.h>
+#include <sbkpython.h>
+#include <basewrapper.h>
+
+extern "C"
+{
+ extern PYSIDE_API PyTypeObject PySideSignalType;
+ extern PYSIDE_API PyTypeObject PySideSignalInstanceType;
+
+ // 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);
+
+/**
+ * This function creates a Signal object which stays attached to QObject class
+ *
+ * @param name of the Signal to be registered on meta object
+ * @param signatures a list of signatures supported by this signal, ended with a NULL pointer
+ * @return Return a new reference to PyObject* of type PySideSignal
+ * @deprecated Use registerSignals
+ **/
+PYSIDE_DEPRECATED(PYSIDE_API PySideSignal* newObject(const char* name, ...));
+
+/**
+ * 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);
+
+/**
+ * @deprecated Use registerSignals
+ **/
+PYSIDE_DEPRECATED(PYSIDE_API void addSignalToWrapper(SbkObjectType* wrapperType, const char* signalName, PySideSignal* signal));
+
+/**
+ * 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
new file mode 100644
index 000000000..b692b96ad
--- /dev/null
+++ b/sources/pyside2/libpyside/pysidesignal_p.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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>
+
+extern "C"
+{
+ extern PyTypeObject PySideSignalType;
+
+ struct PySideSignal {
+ PyObject_HEAD
+ bool initialized;
+ char* signalName;
+ char** signatures;
+ int* signatureAttributes;
+ int signaturesSize;
+ PyObject* homonymousMethod;
+ };
+
+ struct PySideSignalInstance;
+ struct PySideSignalInstancePrivate {
+ char* signalName;
+ char* signature;
+ int attributes;
+ PyObject* source;
+ PyObject* homonymousMethod;
+ PySideSignalInstance* next;
+ };
+
+
+}; //extern "C"
+
+namespace PySide { namespace Signal {
+
+ void init(PyObject* module);
+ bool connect(PyObject* source, const char* signal, PyObject* callback);
+ char* getTypeName(PyObject*);
+ const char** getSignatures(PyObject* self, int *size);
+ QString codeCallbackName(PyObject* callback, const QString& funcName);
+
+}} //namespace PySide
+
+#endif
diff --git a/sources/pyside2/libpyside/pysideslot.cpp b/sources/pyside2/libpyside/pysideslot.cpp
new file mode 100644
index 000000000..c562e41e2
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideslot.cpp
@@ -0,0 +1,220 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <QString>
+#include <QMetaObject>
+
+#define SLOT_DEC_NAME "Slot"
+
+typedef struct
+{
+ PyObject_HEAD
+ char* slotName;
+ char* args;
+ char* resultType;
+} PySideSlot;
+
+extern "C"
+{
+
+static int slotTpInit(PyObject*, PyObject*, PyObject*);
+static PyObject* slotCall(PyObject*, PyObject*, PyObject*);
+
+// Class Definition -----------------------------------------------
+static PyTypeObject PySideSlotType = {
+ PyVarObject_HEAD_INIT(0, 0)
+ "PySide2.QtCore." SLOT_DEC_NAME, /*tp_name*/
+ sizeof(PySideSlot), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ slotCall, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ SLOT_DEC_NAME, /*tp_doc */
+ 0, /*tp_traverse */
+ 0, /*tp_clear */
+ 0, /*tp_richcompare */
+ 0, /*tp_weaklistoffset */
+ 0, /*tp_iter */
+ 0, /*tp_iternext */
+ 0, /*tp_methods */
+ 0, /*tp_members */
+ 0, /*tp_getset */
+ 0, /*tp_base */
+ 0, /*tp_dict */
+ 0, /*tp_descr_get */
+ 0, /*tp_descr_set */
+ 0, /*tp_dictoffset */
+ slotTpInit, /*tp_init */
+ 0, /*tp_alloc */
+ PyType_GenericNew, /*tp_new */
+ 0, /*tp_free */
+ 0, /*tp_is_gc */
+ 0, /*tp_bases */
+ 0, /*tp_mro */
+ 0, /*tp_cache */
+ 0, /*tp_subclasses */
+ 0, /*tp_weaklist */
+ 0, /*tp_del */
+ 0 /*tp_version_tag*/
+};
+
+int slotTpInit(PyObject *self, PyObject *args, PyObject *kw)
+{
+ static PyObject *emptyTuple = 0;
+ static const char *kwlist[] = {"name", "result", 0};
+ char* argName = 0;
+ PyObject* argResult = 0;
+
+ if (emptyTuple == 0)
+ emptyTuple = PyTuple_New(0);
+
+ if (!PyArg_ParseTupleAndKeywords(emptyTuple, kw, "|sO:QtCore." SLOT_DEC_NAME, (char**) kwlist, &argName, &argResult))
+ return 0;
+
+ PySideSlot *data = reinterpret_cast<PySideSlot*>(self);
+ for(Py_ssize_t i = 0, i_max = PyTuple_Size(args); i < i_max; i++) {
+ PyObject *argType = PyTuple_GET_ITEM(args, i);
+ char *typeName = PySide::Signal::getTypeName(argType);
+ if (typeName) {
+ if (data->args) {
+ data->args = reinterpret_cast<char*>(realloc(data->args, (strlen(data->args) + 1 + strlen(typeName)) * sizeof(char*)));
+ data->args = strcat(data->args, ",");
+ data->args = strcat(data->args, typeName);
+ free(typeName);
+ } else {
+ data->args = typeName;
+ }
+ } else {
+ PyErr_Format(PyExc_TypeError, "Unknown signal argument type: %s", argType->ob_type->tp_name);
+ return -1;
+ }
+ }
+
+ if (argName)
+ data->slotName = strdup(argName);
+
+ if (argResult)
+ data->resultType = PySide::Signal::getTypeName(argResult);
+ else
+ data->resultType = strdup("void");
+
+ return 1;
+}
+
+PyObject *slotCall(PyObject *self, PyObject *args, PyObject * /* kw */)
+{
+ static PyObject* pySlotName = 0;
+ PyObject* callback;
+ callback = PyTuple_GetItem(args, 0);
+ Py_INCREF(callback);
+
+ if (PyFunction_Check(callback)) {
+ PySideSlot *data = reinterpret_cast<PySideSlot*>(self);
+
+ if (!data->slotName) {
+ PyObject *funcName = reinterpret_cast<PyFunctionObject*>(callback)->func_name;
+ data->slotName = strdup(Shiboken::String::toCString(funcName));
+ }
+
+
+ QByteArray returnType = QMetaObject::normalizedType(data->resultType);
+ QByteArray signature = QString().sprintf("%s(%s)", data->slotName, data->args).toUtf8();
+ signature = returnType + " " + signature;
+
+ if (!pySlotName)
+ pySlotName = Shiboken::String::fromCString(PYSIDE_SLOT_LIST_ATTR);
+
+ PyObject *pySignature = Shiboken::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
+ free(data->slotName);
+ data->slotName = 0;
+ free(data->resultType);
+ data->resultType = 0;
+ free(data->args);
+ data->args = 0;
+ return callback;
+ }
+ return callback;
+}
+
+} // extern "C"
+
+namespace PySide { namespace Slot {
+
+void init(PyObject* module)
+{
+ if (PyType_Ready(&PySideSlotType) < 0)
+ return;
+
+ Py_INCREF(&PySideSlotType);
+ PyModule_AddObject(module, SLOT_DEC_NAME, reinterpret_cast<PyObject *>(&PySideSlotType));
+}
+
+} // namespace Slot
+} // namespace PySide
diff --git a/sources/pyside2/libpyside/pysideslot_p.h b/sources/pyside2/libpyside/pysideslot_p.h
new file mode 100644
index 000000000..33e881c18
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideslot_p.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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/pysideweakref.cpp b/sources/pyside2/libpyside/pysideweakref.cpp
new file mode 100644
index 000000000..dfbf9e90c
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideweakref.cpp
@@ -0,0 +1,141 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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>
+
+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 PyTypeObject PySideCallableObjectType = {
+ PyVarObject_HEAD_INIT(0, 0)
+ const_cast<char*>("PySide.Callable"),
+ sizeof(PySideCallableObject), /*tp_basicsize*/
+ 0, /*tp_itemsize*/
+ 0, /*tp_dealloc*/
+ 0, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ 0, /*tp_compare*/
+ 0, /*tp_repr*/
+ 0, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+ 0, /*tp_hash */
+ CallableObject_call, /*tp_call*/
+ 0, /*tp_str*/
+ 0, /*tp_getattro*/
+ 0, /*tp_setattro*/
+ 0, /*tp_as_buffer*/
+ Py_TPFLAGS_DEFAULT, /*tp_flags*/
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ 0, /* tp_iter */
+ 0, /* tp_iternext */
+ 0, /* tp_methods */
+ 0, /* tp_members */
+ 0, /* tp_getset */
+ 0, /* tp_base */
+ 0, /* tp_dict */
+ 0, /* tp_descr_get */
+ 0, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ 0, /* tp_init */
+ 0, /* tp_alloc */
+ 0, /* tp_new */
+ 0, /* tp_free */
+ 0, /* tp_is_gc */
+ 0, /* tp_bases */
+ 0, /* tp_mro */
+ 0, /* tp_cache */
+ 0, /* tp_subclasses */
+ 0, /* tp_weaklist */
+ 0, /* tp_del */
+ 0 /* tp_version_tag */
+};
+
+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(&PySideCallableObjectType) == 0)
+ {
+ Py_TYPE(&PySideCallableObjectType) = &PyType_Type;
+ PyType_Ready(&PySideCallableObjectType);
+ }
+
+ PySideCallableObject* callable = PyObject_New(PySideCallableObject, &PySideCallableObjectType);
+ 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
new file mode 100644
index 000000000..7a7082345
--- /dev/null
+++ b/sources/pyside2/libpyside/pysideweakref.h
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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.in b/sources/pyside2/libpyside/signalmanager.cpp.in
new file mode 100644
index 000000000..473057cbc
--- /dev/null
+++ b/sources/pyside2/libpyside/signalmanager.cpp.in
@@ -0,0 +1,726 @@
+// -*- mode: cpp;-*-
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 "dynamicqmetaobject.h"
+#include "pysidemetafunction_p.h"
+
+#include <QtCore>
+#include <QHash>
+#include <QStringList>
+#include <QMetaMethod>
+#include <autodecref.h>
+#include <gilstate.h>
+#include <QDebug>
+#include <limits>
+#include <algorithm>
+#include <typeresolver.h>
+#include <basewrapper.h>
+#include <sbkconverter.h>
+#include <conversions.h>
+
+// These private headers are needed to throw JavaScript exceptions
+#if @QML_PRIVATE_API_SUPPORT@
+ #include <private/qv4engine_p.h>
+ #include <private/qv4context_p.h>
+ #include <private/qqmldata_p.h>
+#if QT_VERSION < 0x050700
+ #include <private/qqmlcontextwrapper_p.h>
+#endif
+#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"
+#include "globalreceiver.h"
+
+#define PYTHON_TYPE "PyObject"
+
+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);
+
+#ifdef IS_PY3K
+ static void destroyMetaObject(PyObject* obj)
+ {
+ void* ptr = PyCapsule_GetPointer(obj, 0);
+ PySide::DynamicQMetaObject* meta = reinterpret_cast<PySide::DynamicQMetaObject*>(ptr);
+ SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(meta);
+ if (wrapper)
+ Shiboken::BindingManager::instance().releaseWrapper(wrapper);
+ delete meta;
+ }
+
+#else
+ static void destroyMetaObject(void* obj)
+ {
+ PySide::DynamicQMetaObject* meta = reinterpret_cast<PySide::DynamicQMetaObject*>(obj);
+ SbkObject* wrapper = Shiboken::BindingManager::instance().retrieveWrapper(meta);
+ if (wrapper)
+ Shiboken::BindingManager::instance().releaseWrapper(wrapper);
+ delete meta;
+ }
+#endif
+}
+
+namespace PySide {
+
+
+PyObjectWrapper::PyObjectWrapper()
+ :m_me(Py_None)
+{
+ Py_INCREF(m_me);
+}
+
+PyObjectWrapper::PyObjectWrapper(PyObject* me)
+ : m_me(me)
+{
+ Py_INCREF(m_me);
+}
+
+PyObjectWrapper::PyObjectWrapper(const PyObjectWrapper &other)
+ : m_me(other.m_me)
+{
+ Py_INCREF(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_DECREF(m_me);
+}
+
+PyObjectWrapper& PyObjectWrapper::operator=(const PySide::PyObjectWrapper& other)
+{
+ Py_INCREF(other.m_me);
+ Py_DECREF(m_me);
+ m_me = 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_GetAttrString(pickleModule, "dumps");
+ }
+ Shiboken::AutoDecRef repr(PyObject_CallFunctionObjArgs(reduce_func, (PyObject*)myObj, NULL));
+ if (repr.object()) {
+ const char* buff = 0;
+ 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_GetAttrString(pickleModule, "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 = Py_None;
+ }
+ myObj = PyObjectWrapper(value);
+ return in;
+}
+
+};
+
+namespace Shiboken {
+
+template<>
+struct Converter<PySide::PyObjectWrapper>
+{
+ static PySide::PyObjectWrapper toCpp(PyObject* obj)
+ {
+ return PySide::PyObjectWrapper(obj);
+ }
+
+ static PyObject* toPython(void* obj)
+ {
+ return toPython(*reinterpret_cast<PySide::PyObjectWrapper*>(obj));
+ }
+
+ static PyObject* toPython(const PySide::PyObjectWrapper& obj)
+ {
+ Py_INCREF((PyObject*)obj);
+ return obj;
+ }
+};
+
+};
+
+using namespace PySide;
+
+struct SignalManager::SignalManagerPrivate
+{
+ SharedMap m_globalReceivers;
+
+ //Deprecated
+ GlobalReceiver m_globalReceiver;
+
+ 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)
+{
+ *((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)
+{
+ PyObject* pyOut = (PyObject*)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>(PYTHON_TYPE);
+ qRegisterMetaTypeStreamOperators<PyObjectWrapper>(PYTHON_TYPE);
+ qRegisterMetaTypeStreamOperators<PyObjectWrapper>("PyObjectWrapper");
+ qRegisterMetaTypeStreamOperators<PyObjectWrapper>("PySide::PyObjectWrapper");
+
+ SbkConverter* converter = Shiboken::Conversions::createConverter(&PyBaseObject_Type, 0);
+ 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, PYTHON_TYPE);
+ 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()
+{
+ return &m_d->m_globalReceiver;
+}
+
+void SignalManager::globalReceiverConnectNotify(QObject* source, int slotIndex)
+{
+ m_d->m_globalReceiver.connectNotify(source, slotIndex);
+}
+
+void SignalManager::globalReceiverDisconnectNotify(QObject* source, int slotIndex)
+{
+ m_d->m_globalReceiver.disconnectNotify(source, slotIndex);
+}
+
+void SignalManager::addGlobalSlot(const char* slot, PyObject* callback)
+{
+ addGlobalSlotGetIndex(slot, callback);
+}
+
+int SignalManager::addGlobalSlotGetIndex(const char* slot, PyObject* callback)
+{
+ return m_d->m_globalReceiver.addSlot(slot, callback);
+}
+
+QObject* SignalManager::globalReceiver(QObject *sender, PyObject *callback)
+{
+ SharedMap globalReceivers = m_d->m_globalReceivers;
+ QByteArray hash = GlobalReceiverV2::hash(callback);
+ GlobalReceiverV2* gr = 0;
+ if (!globalReceivers->contains(hash)) {
+ gr = (*globalReceivers)[hash] = new GlobalReceiverV2(callback, globalReceivers);
+ if (sender) {
+ gr->incRef(sender); // create a link reference
+ gr->decRef(); // remove extra reference
+ }
+ } else {
+ gr = (*globalReceivers)[hash];
+ 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)
+{
+ GlobalReceiverV2* 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 = 0;
+ PyObject* pp_name = 0;
+ QMetaProperty mp;
+ PyObject* pySelf = 0;
+ 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 = (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:
+ case QMetaObject::QueryPropertyDesignable:
+ case QMetaObject::QueryPropertyScriptable:
+ case QMetaObject::QueryPropertyStored:
+ case QMetaObject::QueryPropertyEditable:
+ case QMetaObject::QueryPropertyUser:
+ 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 @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 QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
+ QV4::Heap::ExecutionContext *ctx = engine->current;
+#elif QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
+ QV4::Heap::ExecutionContext *ctx = engine->currentContext();
+#else
+ QV4::ExecutionContext *ctx = engine->currentContext();
+#endif
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
+ if (ctx->type == QV4::Heap::ExecutionContext::Type_CallContext ||
+ ctx->type == QV4::Heap::ExecutionContext::Type_SimpleCallContext) {
+#elif QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
+ if (ctx->d()->type == QV4::ExecutionContext::Type_CallContext ||
+ ctx->d()->type == QV4::ExecutionContext::Type_SimpleCallContext) {
+#else
+ if (ctx->type == QV4::ExecutionContext::Type_CallContext ||
+ ctx->type == QV4::ExecutionContext::Type_SimpleCallContext) {
+#endif
+ 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 QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)
+ if (isSyntaxError) {
+ return engine->throwSyntaxError(errString);
+ } else if (isTypeError) {
+ return engine->throwTypeError(errString);
+ } else {
+ return engine->throwError(errString);
+ }
+#else
+ if (isSyntaxError) {
+ return ctx->throwSyntaxError(errString);
+ } else if (isTypeError) {
+ return ctx->throwTypeError(errString);
+ } else {
+ return ctx->throwError(errString);
+ }
+#endif
+ }
+ }
+#endif
+
+ 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 = 0;
+
+ if (isShortCuit){
+ pyArguments = reinterpret_cast<PyObject*>(args[1]);
+ } else {
+ pyArguments = parseArguments(method.parameterTypes(), args);
+ }
+
+ if (pyArguments) {
+ Shiboken::Conversions::SpecificConverter* retConverter = NULL;
+ 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);
+}
+
+int SignalManager::registerMetaMethodGetIndex(QObject* source, const char* signature, QMetaMethod::MethodType type)
+{
+ Q_ASSERT(source);
+ 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 {
+ DynamicQMetaObject *dmo = 0;
+ PyObject *pySelf = reinterpret_cast<PyObject*>(self);
+ PyObject* dict = self->ob_dict;
+
+ // Create a instance meta object
+ if (!dict || !PyDict_Contains(dict, metaObjectAttr)) {
+ dmo = new DynamicQMetaObject(pySelf->ob_type, metaObject);
+#ifdef IS_PY3K
+ PyObject* pyDmo = PyCapsule_New(dmo, 0, destroyMetaObject);
+#else
+ PyObject* pyDmo = PyCObject_FromVoidPtr(dmo, destroyMetaObject);
+#endif
+
+ PyObject_SetAttr(pySelf, metaObjectAttr, pyDmo);
+ Py_DECREF(pyDmo);
+ } else {
+ dmo = reinterpret_cast<DynamicQMetaObject*>(const_cast<QMetaObject*>(metaObject));
+ }
+
+ if (type == QMetaMethod::Signal)
+ return dmo->addSignal(signature);
+ else
+ return dmo->addSlot(signature);
+ }
+ }
+ return methodIndex;
+}
+
+bool SignalManager::hasConnectionWith(const QObject *object)
+{
+ return m_d->m_globalReceiver.hasConnectionWith(object);
+}
+
+const QMetaObject* SignalManager::retriveMetaObject(PyObject *self)
+{
+ Shiboken::GilState gil;
+ DynamicQMetaObject *mo = 0;
+ Q_ASSERT(self);
+
+ PyObject* dict = reinterpret_cast<SbkObject*>(self)->ob_dict;
+ if (dict && PyDict_Contains(dict, metaObjectAttr)) {
+ PyObject *pyMo = PyDict_GetItem(dict, metaObjectAttr);
+
+#ifdef IS_PY3K
+ mo = reinterpret_cast<DynamicQMetaObject*>(PyCapsule_GetPointer(pyMo, 0));
+#else
+ mo = reinterpret_cast<DynamicQMetaObject*>(PyCObject_AsVoidPtr(pyMo));
+#endif
+ } else {
+ mo = reinterpret_cast<DynamicQMetaObject*>(Shiboken::Object::getTypeUserData(reinterpret_cast<SbkObject*>(self)));
+ }
+
+ mo->update();
+ return mo;
+}
+
+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;
+ PyObject* self = (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] = {0, 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
new file mode 100644
index 000000000..6f2201ed0
--- /dev/null
+++ b/sources/pyside2/libpyside/signalmanager.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of PySide2.
+**
+** $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 <Qt>
+#include <QStringList>
+#include <QMetaMethod>
+
+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(PyObject* me);
+ PyObjectWrapper(const PyObjectWrapper &other);
+ ~PyObjectWrapper();
+ operator PyObject*() const;
+ PyObjectWrapper& operator=(const PyObjectWrapper &other);
+private:
+ PyObject* m_me;
+ void* m_data; //future
+};
+
+PYSIDE_API QDataStream &operator<<(QDataStream& out, const PyObjectWrapper& myObj);
+PYSIDE_API QDataStream &operator>>(QDataStream& in, PyObjectWrapper& myObj);
+
+class PYSIDE_API 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* retriveMetaObject(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);
+
+ PYSIDE_DEPRECATED(QObject* globalReceiver());
+ PYSIDE_DEPRECATED(void addGlobalSlot(const char* slot, PyObject* callback));
+ PYSIDE_DEPRECATED(int addGlobalSlotGetIndex(const char* slot, PyObject* callback));
+
+ PYSIDE_DEPRECATED(void globalReceiverConnectNotify(QObject *sender, int slotIndex));
+ PYSIDE_DEPRECATED(void globalReceiverDisconnectNotify(QObject *sender, int slotIndex));
+ PYSIDE_DEPRECATED(bool hasConnectionWith(const QObject *object));
+
+private:
+ struct SignalManagerPrivate;
+ SignalManagerPrivate* m_d;
+
+ SignalManager();
+ ~SignalManager();
+
+ // disable copy
+ SignalManager(const SignalManager&);
+ SignalManager operator=(const SignalManager&);
+};
+
+}
+
+Q_DECLARE_METATYPE(PySide::PyObjectWrapper)
+
+#endif