aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/libpysideqml
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/libpysideqml')
-rw-r--r--sources/pyside6/libpysideqml/CMakeLists.txt85
-rw-r--r--sources/pyside6/libpysideqml/PySide6QmlConfig-spec.cmake.in7
-rw-r--r--sources/pyside6/libpysideqml/PySide6QmlConfig.cmake.in5
-rw-r--r--sources/pyside6/libpysideqml/PySide6QmlConfigVersion.cmake.in10
-rw-r--r--sources/pyside6/libpysideqml/pysideqml.cpp58
-rw-r--r--sources/pyside6/libpysideqml/pysideqml.h54
-rw-r--r--sources/pyside6/libpysideqml/pysideqmllistproperty.cpp319
-rw-r--r--sources/pyside6/libpysideqml/pysideqmllistproperty_p.h47
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlmacros.h54
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlmetacallerror.cpp97
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlmetacallerror_p.h57
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlregistertype.cpp455
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlregistertype.h112
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlregistertype_p.h47
-rw-r--r--sources/pyside6/libpysideqml/pysideqmluncreatable.cpp196
-rw-r--r--sources/pyside6/libpysideqml/pysideqmluncreatable.h69
16 files changed, 1672 insertions, 0 deletions
diff --git a/sources/pyside6/libpysideqml/CMakeLists.txt b/sources/pyside6/libpysideqml/CMakeLists.txt
new file mode 100644
index 000000000..8142f7040
--- /dev/null
+++ b/sources/pyside6/libpysideqml/CMakeLists.txt
@@ -0,0 +1,85 @@
+set(libpysideqml_libraries Qt::Core Qt::CorePrivate Qt::Qml Qt::QmlPrivate)
+
+set(libpysideqml_SRC
+ pysideqml.cpp
+ pysideqmlregistertype.cpp
+ pysideqmlmetacallerror.cpp
+ pysideqmllistproperty.cpp
+ pysideqmluncreatable.cpp
+)
+
+add_library(pyside6qml SHARED ${libpysideqml_SRC} ${other_files})
+add_library(PySide6::pyside6qml ALIAS pyside6qml)
+
+target_include_directories(pyside6qml PUBLIC
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
+ $<INSTALL_INTERFACE:include/PySide6Qml>
+)
+
+target_link_libraries(pyside6qml
+ PRIVATE PySide6::pyside6 Shiboken6::libshiboken ${libpysideqml_libraries})
+
+set_target_properties(pyside6qml PROPERTIES
+ VERSION ${BINDING_API_VERSION}
+ SOVERSION "${PYSIDE_SO_VERSION}"
+ OUTPUT_NAME "pyside6qml${pyside6_SUFFIX}${SHIBOKEN_PYTHON_SHARED_LIBRARY_SUFFIX}"
+ DEFINE_SYMBOL BUILD_LIBPYSIDEQML)
+
+set_property(TARGET pyside6 PROPERTY CXX_STANDARD 17)
+
+if(PYSIDE_QT_CONF_PREFIX)
+ set_property(SOURCE pysideqml.cpp
+ APPEND
+ PROPERTY COMPILE_DEFINITIONS
+ PYSIDE_QT_CONF_PREFIX=${PYSIDE_QT_CONF_PREFIX})
+endif()
+
+#
+# install stuff
+#
+
+set(libpysideqml_HEADERS
+ pysideqmlmacros.h
+ pysideqml.h
+ pysideqmlregistertype.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")
+
+# Install-tree / relocatable package config file.
+configure_package_config_file(
+ "${CMAKE_CURRENT_SOURCE_DIR}/PySide6QmlConfig-spec.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/install/PySide6QmlConfig${SHIBOKEN_PYTHON_CONFIG_SUFFIX}.cmake"
+ INSTALL_DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide6Qml-${BINDING_API_VERSION}"
+)
+
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PySide6QmlConfig.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/PySide6QmlConfig.cmake" @ONLY)
+configure_file("${CMAKE_CURRENT_SOURCE_DIR}/PySide6QmlConfigVersion.cmake.in"
+ "${CMAKE_CURRENT_BINARY_DIR}/PySide6QmlConfigVersion.cmake" @ONLY)
+
+install(FILES ${libpysideqml_HEADERS}
+ DESTINATION include/${BINDING_NAME}${pyside6qml_SUFFIX})
+
+install(TARGETS pyside6qml EXPORT PySide6QmlTargets
+ LIBRARY DESTINATION "${LIB_INSTALL_DIR}"
+ ARCHIVE DESTINATION "${LIB_INSTALL_DIR}"
+ RUNTIME DESTINATION bin)
+install(EXPORT PySide6QmlTargets NAMESPACE PySide6Qml::
+ DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide6Qml-${BINDING_API_VERSION}")
+
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/PySide6QmlConfig.cmake"
+ DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide6Qml-${BINDING_API_VERSION}")
+
+install(FILES
+ "${CMAKE_CURRENT_BINARY_DIR}/install/PySide6QmlConfig${SHIBOKEN_PYTHON_CONFIG_SUFFIX}.cmake"
+ DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide6Qml-${BINDING_API_VERSION}")
+
+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/PySide6QmlConfigVersion.cmake"
+ DESTINATION "${LIB_INSTALL_DIR}/cmake/PySide6Qml-${BINDING_API_VERSION}")
diff --git a/sources/pyside6/libpysideqml/PySide6QmlConfig-spec.cmake.in b/sources/pyside6/libpysideqml/PySide6QmlConfig-spec.cmake.in
new file mode 100644
index 000000000..36eb4123a
--- /dev/null
+++ b/sources/pyside6/libpysideqml/PySide6QmlConfig-spec.cmake.in
@@ -0,0 +1,7 @@
+@PACKAGE_INIT@
+
+# Import targets only when using an installed PySide6 config file (so not during a regular
+# PySide6 build, or during a super project build).
+if (NOT TARGET PySide6::pyside6qml)
+ include("${CMAKE_CURRENT_LIST_DIR}/PySide6QmlTargets.cmake")
+endif()
diff --git a/sources/pyside6/libpysideqml/PySide6QmlConfig.cmake.in b/sources/pyside6/libpysideqml/PySide6QmlConfig.cmake.in
new file mode 100644
index 000000000..dab0a6b13
--- /dev/null
+++ b/sources/pyside6/libpysideqml/PySide6QmlConfig.cmake.in
@@ -0,0 +1,5 @@
+if (NOT PYTHON_CONFIG_SUFFIX)
+ message(STATUS "PySide6QmlConfig: Using default python: @SHIBOKEN_PYTHON_CONFIG_SUFFIX@")
+ SET(PYTHON_CONFIG_SUFFIX @SHIBOKEN_PYTHON_CONFIG_SUFFIX@)
+endif()
+include(${CMAKE_CURRENT_LIST_DIR}/PySide6QmlConfig${PYTHON_CONFIG_SUFFIX}.cmake)
diff --git a/sources/pyside6/libpysideqml/PySide6QmlConfigVersion.cmake.in b/sources/pyside6/libpysideqml/PySide6QmlConfigVersion.cmake.in
new file mode 100644
index 000000000..f5073ce08
--- /dev/null
+++ b/sources/pyside6/libpysideqml/PySide6QmlConfigVersion.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/pyside6/libpysideqml/pysideqml.cpp b/sources/pyside6/libpysideqml/pysideqml.cpp
new file mode 100644
index 000000000..6bdc277f6
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqml.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pysideqml.h"
+#include "pysideqmllistproperty_p.h"
+#include "pysideqmluncreatable.h"
+#include "pysideqmluncreatable.h"
+#include "pysideqmlmetacallerror_p.h"
+
+#include <signalmanager.h>
+
+namespace PySide::Qml
+{
+
+void init(PyObject *module)
+{
+ initQtQmlListProperty(module);
+ initQmlUncreatable(module);
+ PySide::SignalManager::setQmlMetaCallErrorHandler(PySide::qmlMetaCallErrorHandler);
+}
+
+} //namespace PySide::Qml
diff --git a/sources/pyside6/libpysideqml/pysideqml.h b/sources/pyside6/libpysideqml/pysideqml.h
new file mode 100644
index 000000000..a227a4cee
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqml.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYSIDEQML_H
+#define PYSIDEQML_H
+
+#include "pysideqmlmacros.h"
+
+#include <sbkpython.h>
+
+namespace PySide::Qml
+{
+
+PYSIDEQML_API void init(PyObject *module);
+
+} //namespace PySide::Qml
+
+#endif // PYSIDEQML_H
diff --git a/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp b/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp
new file mode 100644
index 000000000..7cca21326
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp
@@ -0,0 +1,319 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pysideqmllistproperty_p.h"
+#include "pysideqmlregistertype_p.h"
+
+#include <shiboken.h>
+#include <signature.h>
+
+#include <pysideproperty.h>
+
+#include <QtCore/QObject>
+#include <QtQml/QQmlListProperty>
+
+// Forward declarations.
+static void propListMetaCall(PySideProperty *pp, PyObject *self, QMetaObject::Call call,
+ void **args);
+
+extern "C"
+{
+
+// This is the user data we store in the property.
+struct QmlListProperty
+{
+ PyTypeObject *type;
+ PyObject *append;
+ PyObject *count;
+ PyObject *at;
+ PyObject *clear;
+ PyObject *replace;
+ PyObject *removeLast;
+};
+
+static int propListTpInit(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"type", "append", "count", "at", "clear", "replace", "removeLast", 0};
+ PySideProperty *pySelf = reinterpret_cast<PySideProperty *>(self);
+ QmlListProperty *data = new QmlListProperty;
+ memset(data, 0, sizeof(QmlListProperty));
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ "O|OOOOOO:QtQml.ListProperty", (char **) kwlist,
+ &data->type,
+ &data->append,
+ &data->count,
+ &data->at,
+ &data->clear,
+ &data->replace,
+ &data->removeLast)) {
+ delete data;
+ return -1;
+ }
+
+ PyTypeObject *qobjectType = qObjectType();
+
+ if (!PySequence_Contains(data->type->tp_mro, reinterpret_cast<PyObject *>(qobjectType))) {
+ PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.",
+ qobjectType->tp_name, data->type->tp_name);
+ delete data;
+ return -1;
+ }
+
+ if ((data->append && data->append != Py_None && !PyCallable_Check(data->append)) ||
+ (data->count && data->count != Py_None && !PyCallable_Check(data->count)) ||
+ (data->at && data->at != Py_None && !PyCallable_Check(data->at)) ||
+ (data->clear && data->clear != Py_None && !PyCallable_Check(data->clear)) ||
+ (data->replace && data->replace != Py_None && !PyCallable_Check(data->replace)) ||
+ (data->removeLast && data->removeLast != Py_None && !PyCallable_Check(data->removeLast))) {
+ PyErr_Format(PyExc_TypeError, "Non-callable parameter given");
+ delete data;
+ return -1;
+ }
+
+ PySide::Property::setMetaCallHandler(pySelf, &propListMetaCall);
+ PySide::Property::setTypeName(pySelf, "QQmlListProperty<QObject>");
+ PySide::Property::setUserData(pySelf, data);
+
+ return 0;
+}
+
+void propListTpFree(void *self)
+{
+ auto pySelf = reinterpret_cast<PySideProperty *>(self);
+ delete reinterpret_cast<QmlListProperty *>(PySide::Property::userData(pySelf));
+ // calls base type constructor
+ Py_TYPE(pySelf)->tp_base->tp_free(self);
+}
+
+static PyType_Slot PropertyListType_slots[] = {
+ {Py_tp_init, reinterpret_cast<void *>(propListTpInit)},
+ {Py_tp_free, reinterpret_cast<void *>(propListTpFree)},
+ {Py_tp_dealloc, reinterpret_cast<void *>(Sbk_object_dealloc)},
+ {0, nullptr}
+};
+static PyType_Spec PropertyListType_spec = {
+ "2:PySide6.QtQml.ListProperty",
+ sizeof(PySideProperty),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PropertyListType_slots,
+};
+
+
+PyTypeObject *PropertyListTypeF(void)
+{
+ static Shiboken::AutoDecRef bases(Py_BuildValue("(O)", PySidePropertyTypeF()));
+ static auto *type = SbkType_FromSpecWithBases(&PropertyListType_spec, bases);
+ return type;
+}
+
+} // extern "C"
+
+// Implementation of QQmlListProperty<T>::AppendFunction callback
+void propListAppender(QQmlListProperty<QObject> *propList, QObject *item)
+{
+ Shiboken::GilState state;
+
+ Shiboken::AutoDecRef args(PyTuple_New(2));
+ PyTypeObject *qobjectType = qObjectType();
+ PyTuple_SET_ITEM(args, 0,
+ Shiboken::Conversions::pointerToPython(qobjectType, propList->object));
+ PyTuple_SET_ITEM(args, 1,
+ Shiboken::Conversions::pointerToPython(qobjectType, item));
+
+ auto data = reinterpret_cast<QmlListProperty *>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->append, args));
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+}
+
+// Implementation of QQmlListProperty<T>::CountFunction callback
+qsizetype propListCount(QQmlListProperty<QObject> *propList)
+{
+ Shiboken::GilState state;
+
+ Shiboken::AutoDecRef args(PyTuple_New(1));
+ PyTuple_SET_ITEM(args, 0,
+ Shiboken::Conversions::pointerToPython(qObjectType(), propList->object));
+
+ auto data = reinterpret_cast<QmlListProperty *>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->count, args));
+
+ // Check return type
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ return 0;
+ }
+
+ int cppResult = 0;
+ auto *converter = Shiboken::Conversions::PrimitiveTypeConverter<qsizetype>();
+ if (auto *pythonToCpp = Shiboken::Conversions::isPythonToCppConvertible(converter, retVal))
+ pythonToCpp(retVal, &cppResult);
+ return cppResult;
+}
+
+// Implementation of QQmlListProperty<T>::AtFunction callback
+QObject *propListAt(QQmlListProperty<QObject> *propList, qsizetype index)
+{
+ Shiboken::GilState state;
+
+ Shiboken::AutoDecRef args(PyTuple_New(2));
+ PyTypeObject *qobjectType = qObjectType();
+ PyTuple_SET_ITEM(args, 0,
+ Shiboken::Conversions::pointerToPython(qobjectType, propList->object));
+ auto *converter = Shiboken::Conversions::PrimitiveTypeConverter<qsizetype>();
+ PyTuple_SET_ITEM(args, 1,
+ Shiboken::Conversions::copyToPython(converter, &index));
+
+ auto data = reinterpret_cast<QmlListProperty *>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->at, args));
+
+ QObject *result = 0;
+ if (PyErr_Occurred())
+ PyErr_Print();
+ else if (PyType_IsSubtype(Py_TYPE(retVal), data->type))
+ Shiboken::Conversions::pythonToCppPointer(qobjectType, retVal, &result);
+ return result;
+}
+
+// Implementation of QQmlListProperty<T>::ClearFunction callback
+void propListClear(QQmlListProperty<QObject> * propList)
+{
+ Shiboken::GilState state;
+
+ Shiboken::AutoDecRef args(PyTuple_New(1));
+ PyTypeObject *qobjectType = qObjectType();
+ PyTuple_SET_ITEM(args, 0,
+ Shiboken::Conversions::pointerToPython(qobjectType, propList->object));
+
+ auto data = reinterpret_cast<QmlListProperty *>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->clear, args));
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+}
+
+// Implementation of QQmlListProperty<T>::ReplaceFunction callback
+void propListReplace(QQmlListProperty<QObject> *propList, qsizetype index, QObject *value)
+{
+ Shiboken::GilState state;
+
+ Shiboken::AutoDecRef args(PyTuple_New(3));
+ PyTypeObject *qobjectType = qObjectType();
+ PyTuple_SET_ITEM(args, 0,
+ Shiboken::Conversions::pointerToPython(qobjectType, propList->object));
+ auto *converter = Shiboken::Conversions::PrimitiveTypeConverter<qsizetype>();
+ PyTuple_SET_ITEM(args, 1,
+ Shiboken::Conversions::copyToPython(converter, &index));
+ PyTuple_SET_ITEM(args, 2,
+ Shiboken::Conversions::pointerToPython(qobjectType, value));
+
+ auto data = reinterpret_cast<QmlListProperty *>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->replace, args));
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+}
+
+// Implementation of QQmlListProperty<T>::RemoveLastFunction callback
+void propListRemoveLast(QQmlListProperty<QObject> *propList)
+{
+ Shiboken::GilState state;
+
+ Shiboken::AutoDecRef args(PyTuple_New(1));
+ PyTypeObject *qobjectType = qObjectType();
+ PyTuple_SET_ITEM(args, 0,
+ Shiboken::Conversions::pointerToPython(qobjectType, propList->object));
+
+ auto data = reinterpret_cast<QmlListProperty *>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->removeLast, args));
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+}
+
+// qt_metacall specialization for ListProperties
+static void propListMetaCall(PySideProperty *pp, PyObject *self,
+ QMetaObject::Call call, void **args)
+{
+ if (call != QMetaObject::ReadProperty)
+ return;
+
+ auto data = reinterpret_cast<QmlListProperty *>(PySide::Property::userData(pp));
+ QObject *qobj;
+ PyTypeObject *qobjectType = qObjectType();
+ Shiboken::Conversions::pythonToCppPointer(qobjectType, self, &qobj);
+ QQmlListProperty<QObject> declProp(
+ qobj, data,
+ data->append && data->append != Py_None ? &propListAppender : nullptr,
+ data->count && data->count != Py_None ? &propListCount : nullptr,
+ data->at && data->at != Py_None ? &propListAt : nullptr,
+ data->clear && data->clear != Py_None ? &propListClear : nullptr,
+ data->replace && data->replace != Py_None ? &propListReplace : nullptr,
+ data->removeLast && data->removeLast != Py_None ? &propListRemoveLast : nullptr);
+
+ // Copy the data to the memory location requested by the meta call
+ void *v = args[0];
+ *reinterpret_cast<QQmlListProperty<QObject> *>(v) = declProp;
+}
+
+static const char *PropertyList_SignatureStrings[] = {
+ "PySide6.QtQml.ListProperty(self,type:type,append:typing.Callable,"
+ "at:typing.Callable=None,clear:typing.Callable=None,count:typing.Callable=None)",
+ nullptr // Sentinel
+};
+
+void initQtQmlListProperty(PyObject *module)
+{
+ // Export QmlListProperty type
+ if (InitSignatureStrings(PropertyListTypeF(), PropertyList_SignatureStrings) < 0) {
+ PyErr_Print();
+ qWarning() << "Error initializing PropertyList type.";
+ return;
+ }
+
+ // Register QQmlListProperty metatype for use in QML
+ qRegisterMetaType<QQmlListProperty<QObject>>();
+
+ Py_INCREF(reinterpret_cast<PyObject *>(PropertyListTypeF()));
+ PyModule_AddObject(module, PepType_GetNameStr(PropertyListTypeF()),
+ reinterpret_cast<PyObject *>(PropertyListTypeF()));
+}
diff --git a/sources/pyside6/libpysideqml/pysideqmllistproperty_p.h b/sources/pyside6/libpysideqml/pysideqmllistproperty_p.h
new file mode 100644
index 000000000..bfae04bfc
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmllistproperty_p.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYSIDEQMLLISTPROPERTY_H
+#define PYSIDEQMLLISTPROPERTY_H
+
+#include <sbkpython.h>
+
+void initQtQmlListProperty(PyObject *module);
+
+#endif // PYSIDEQMLLISTPROPERTY_H
diff --git a/sources/pyside6/libpysideqml/pysideqmlmacros.h b/sources/pyside6/libpysideqml/pysideqmlmacros.h
new file mode 100644
index 000000000..208a92f04
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmlmacros.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYSIDEQMLMACROS_H
+#define PYSIDEQMLMACROS_H
+
+#include <shibokenmacros.h>
+
+#define PYSIDEQML_EXPORT LIBSHIBOKEN_EXPORT
+#define PYSIDEQML_IMPORT LIBSHIBOKEN_IMPORT
+
+#ifdef BUILD_LIBPYSIDEQML
+# define PYSIDEQML_API PYSIDEQML_EXPORT
+#else
+# define PYSIDEQML_API PYSIDEQML_IMPORT
+#endif
+
+#endif // PYSIDEQMLMACROS_H
diff --git a/sources/pyside6/libpysideqml/pysideqmlmetacallerror.cpp b/sources/pyside6/libpysideqml/pysideqmlmetacallerror.cpp
new file mode 100644
index 000000000..4887e3f51
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmlmetacallerror.cpp
@@ -0,0 +1,97 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pysideqmlmetacallerror_p.h"
+
+#include <sbkpython.h>
+#include <sbkstring.h>
+#include <autodecref.h>
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+#include <QtQml/QQmlEngine>
+#include <QtQml/QQmlListProperty>
+
+#if __has_include (<private/qv4engine_p.h>)
+# define QML_PRIVATE_API_SUPPORT
+# include <private/qv4engine_p.h>
+# include <private/qv4context_p.h>
+# include <private/qqmldata_p.h>
+#endif
+
+namespace PySide {
+
+std::optional<int> qmlMetaCallErrorHandler(QObject *object)
+{
+#ifdef 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())
+ return {};
+
+ QV4::ExecutionEngine *engine = data->jsWrapper.engine();
+ if (engine->currentStackFrame == nullptr)
+ return {};
+
+ PyObject *errType, *errValue, *errTraceback;
+ PyErr_Fetch(&errType, &errValue, &errTraceback);
+ // PYSIDE-464: The error is only valid before PyErr_Restore,
+ // PYSIDE-464: therefore we take local copies.
+ Shiboken::AutoDecRef objStr(PyObject_Str(errValue));
+ const QString errString = QLatin1String(Shiboken::String::toCString(objStr));
+ const bool isSyntaxError = errType == PyExc_SyntaxError;
+ const bool isTypeError = errType == PyExc_TypeError;
+ PyErr_Restore(errType, errValue, errTraceback);
+
+ PyErr_Print(); // Note: PyErr_Print clears the error.
+
+ if (isSyntaxError)
+ return engine->throwSyntaxError(errString);
+ if (isTypeError)
+ return engine->throwTypeError(errString);
+ return engine->throwError(errString);
+#else
+ Q_UNUSED(object);
+ qWarning("libpyside6qml was built without QML private API support, error handling will not work.");
+ return {};
+#endif // QML_PRIVATE_API_SUPPORT
+}
+
+} // namespace PySide
diff --git a/sources/pyside6/libpysideqml/pysideqmlmetacallerror_p.h b/sources/pyside6/libpysideqml/pysideqmlmetacallerror_p.h
new file mode 100644
index 000000000..9ecb0f6eb
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmlmetacallerror_p.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYSIDEQMLMETACALLERROR_P_H
+#define PYSIDEQMLMETACALLERROR_P_H
+
+#include <optional>
+
+#include <QtCore/QtGlobal>
+
+QT_FORWARD_DECLARE_CLASS(QObject)
+
+namespace PySide {
+
+// Helper for SignalManager::qt_metacall():
+// Bubbles Python exceptions up to the Javascript engine, if called from one
+std::optional<int> qmlMetaCallErrorHandler(QObject *object);
+
+} // namespace PySide
+
+#endif // PYSIDEQMLMETACALLERROR_P_H
diff --git a/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp b/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp
new file mode 100644
index 000000000..84fec16b6
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp
@@ -0,0 +1,455 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pysideqmlregistertype.h"
+#include "pysideqmlregistertype_p.h"
+#include "pysideqmluncreatable.h"
+
+#include <limits>
+
+// shiboken
+#include <shiboken.h>
+#include <sbkstring.h>
+
+// pyside
+#include <pyside.h>
+#include <pysideqobject.h>
+#include <pyside_p.h>
+
+#include <QtCore/QMutex>
+#include <QtCore/QTypeRevision>
+
+#include <QtQml/qqml.h>
+#include <QtQml/QJSValue>
+#include <QtQml/QQmlListProperty>
+
+// Mutex used to avoid race condition on PySide::nextQObjectMemoryAddr.
+static QMutex nextQmlElementMutex;
+
+static void createInto(void *memory, void *type)
+{
+ QMutexLocker locker(&nextQmlElementMutex);
+ PySide::setNextQObjectMemoryAddr(memory);
+ Shiboken::GilState state;
+ PyObject *obj = PyObject_CallObject(reinterpret_cast<PyObject *>(type), 0);
+ if (!obj || PyErr_Occurred())
+ PyErr_Print();
+ PySide::setNextQObjectMemoryAddr(0);
+}
+
+PyTypeObject *qObjectType()
+{
+ static PyTypeObject *const result =
+ Shiboken::Conversions::getPythonTypeObject("QObject*");
+ assert(result);
+ return result;
+}
+
+static PyTypeObject *qQmlEngineType()
+{
+ static PyTypeObject *const result =
+ Shiboken::Conversions::getPythonTypeObject("QQmlEngine*");
+ assert(result);
+ return result;
+}
+
+static PyTypeObject *qQJSValueType()
+{
+ static PyTypeObject *const result =
+ Shiboken::Conversions::getPythonTypeObject("QJSValue*");
+ assert(result);
+ return result;
+}
+
+int PySide::qmlRegisterType(PyObject *pyObj, const char *uri, int versionMajor,
+ int versionMinor, const char *qmlName, const char *noCreationReason,
+ bool creatable)
+{
+ using namespace Shiboken;
+
+ PyTypeObject *qobjectType = qObjectType();
+
+ PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj);
+ if (!PySequence_Contains(pyObjType->tp_mro, reinterpret_cast<PyObject *>(qobjectType))) {
+ PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.",
+ qobjectType->tp_name, pyObjType->tp_name);
+ return -1;
+ }
+
+ const QMetaObject *metaObject = PySide::retrieveMetaObject(pyObjType);
+ Q_ASSERT(metaObject);
+
+ QQmlPrivate::RegisterType type;
+
+ // Allow registering Qt Quick items.
+ bool registered = false;
+ QuickRegisterItemFunction quickRegisterItemFunction = getQuickRegisterItemFunction();
+ if (quickRegisterItemFunction) {
+ registered =
+ quickRegisterItemFunction(pyObj, uri, versionMajor, versionMinor,
+ qmlName, creatable, noCreationReason, &type);
+ }
+
+ // Register as simple QObject rather than Qt Quick item.
+ if (!registered) {
+ // Incref the type object, don't worry about decref'ing it because
+ // there's no way to unregister a QML type.
+ Py_INCREF(pyObj);
+
+ type.structVersion = 0;
+
+ // FIXME: Fix this to assign new type ids each time.
+ type.typeId = QMetaType(QMetaType::QObjectStar);
+ type.listId = QMetaType::fromType<QQmlListProperty<QObject> >();
+ type.attachedPropertiesFunction = QQmlPrivate::attachedPropertiesFunc<QObject>();
+ type.attachedPropertiesMetaObject = QQmlPrivate::attachedPropertiesMetaObject<QObject>();
+
+ type.parserStatusCast =
+ QQmlPrivate::StaticCastSelector<QObject, QQmlParserStatus>::cast();
+ type.valueSourceCast =
+ QQmlPrivate::StaticCastSelector<QObject, QQmlPropertyValueSource>::cast();
+ type.valueInterceptorCast =
+ QQmlPrivate::StaticCastSelector<QObject, QQmlPropertyValueInterceptor>::cast();
+
+ int objectSize = static_cast<int>(PySide::getSizeOfQObject(
+ reinterpret_cast<PyTypeObject *>(pyObj)));
+ type.objectSize = objectSize;
+ type.create = creatable ? createInto : nullptr;
+ type.noCreationReason = QString::fromUtf8(noCreationReason);
+ type.userdata = pyObj;
+ type.uri = uri;
+ type.version = QTypeRevision::fromVersion(versionMajor, versionMinor);
+ type.elementName = qmlName;
+
+ type.extensionObjectCreate = 0;
+ type.extensionMetaObject = 0;
+ type.customParser = 0;
+ }
+ type.metaObject = metaObject; // Snapshot may have changed.
+
+ int qmlTypeId = QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
+ if (qmlTypeId == -1) {
+ PyErr_Format(PyExc_TypeError, "QML meta type registration of \"%s\" failed.",
+ qmlName);
+ }
+ return qmlTypeId;
+}
+
+int PySide::qmlRegisterSingletonType(PyObject *pyObj, const char *uri, int versionMajor,
+ int versionMinor, const char *qmlName, PyObject *callback,
+ bool isQObject, bool hasCallback)
+{
+ using namespace Shiboken;
+
+ if (hasCallback) {
+ if (!PyCallable_Check(callback)) {
+ PyErr_Format(PyExc_TypeError, "Invalid callback specified.");
+ return -1;
+ }
+
+ AutoDecRef funcCode(PyObject_GetAttrString(callback, "__code__"));
+ AutoDecRef argCount(PyObject_GetAttrString(funcCode, "co_argcount"));
+
+ int count = PyLong_AsLong(argCount);
+
+ if (count != 1) {
+ PyErr_Format(PyExc_TypeError, "Callback has a bad parameter count.");
+ return -1;
+ }
+
+ // Make sure the callback never gets deallocated
+ Py_INCREF(callback);
+ }
+
+ const QMetaObject *metaObject = nullptr;
+
+ if (isQObject) {
+ PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj);
+
+ if (!isQObjectDerived(pyObjType, true))
+ return -1;
+
+ // If we don't have a callback we'll need the pyObj to stay allocated indefinitely
+ if (!hasCallback)
+ Py_INCREF(pyObj);
+
+ metaObject = PySide::retrieveMetaObject(pyObjType);
+ Q_ASSERT(metaObject);
+ }
+
+ QQmlPrivate::RegisterSingletonType type;
+ type.structVersion = 0;
+
+ type.uri = uri;
+ type.version = QTypeRevision::fromVersion(versionMajor, versionMinor);
+ type.typeName = qmlName;
+ type.instanceMetaObject = metaObject;
+
+ if (isQObject) {
+ // FIXME: Fix this to assign new type ids each time.
+ type.typeId = QMetaType(QMetaType::QObjectStar);
+
+ type.qObjectApi =
+ [callback, pyObj, hasCallback](QQmlEngine *engine, QJSEngine *) -> QObject * {
+ Shiboken::GilState gil;
+ AutoDecRef args(PyTuple_New(hasCallback ? 1 : 0));
+
+ if (hasCallback) {
+ PyTuple_SET_ITEM(args, 0, Conversions::pointerToPython(
+ qQmlEngineType(), engine));
+ }
+
+ AutoDecRef retVal(PyObject_CallObject(hasCallback ? callback : pyObj, args));
+
+ // Make sure the callback returns something we can convert, else the entire application will crash.
+ if (retVal.isNull() ||
+ Conversions::isPythonToCppPointerConvertible(qObjectType(), retVal) == nullptr) {
+ PyErr_Format(PyExc_TypeError, "Callback returns invalid value.");
+ return nullptr;
+ }
+
+ QObject *obj = nullptr;
+ Conversions::pythonToCppPointer(qObjectType(), retVal, &obj);
+
+ if (obj != nullptr)
+ Py_INCREF(retVal);
+
+ return obj;
+ };
+ } else {
+ type.scriptApi =
+ [callback](QQmlEngine *engine, QJSEngine *) -> QJSValue {
+ Shiboken::GilState gil;
+ AutoDecRef args(PyTuple_New(1));
+
+ PyTuple_SET_ITEM(args, 0, Conversions::pointerToPython(
+ qQmlEngineType(), engine));
+
+ AutoDecRef retVal(PyObject_CallObject(callback, args));
+
+ PyTypeObject *qjsvalueType = qQJSValueType();
+
+ // Make sure the callback returns something we can convert, else the entire application will crash.
+ if (retVal.isNull() ||
+ Conversions::isPythonToCppPointerConvertible(qjsvalueType, retVal) == nullptr) {
+ PyErr_Format(PyExc_TypeError, "Callback returns invalid value.");
+ return QJSValue(QJSValue::UndefinedValue);
+ }
+
+ QJSValue *val = nullptr;
+ Conversions::pythonToCppPointer(qjsvalueType, retVal, &val);
+
+ Py_INCREF(retVal);
+
+ return *val;
+ };
+ }
+
+ return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &type);
+}
+
+int PySide::qmlRegisterSingletonInstance(PyObject *pyObj, const char *uri, int versionMajor,
+ int versionMinor, const char *qmlName,
+ PyObject *instanceObject)
+{
+ using namespace Shiboken;
+
+ // Check if the Python Type inherit from QObject
+ PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj);
+
+ if (!isQObjectDerived(pyObjType, true))
+ return -1;
+
+ // Convert the instanceObject (PyObject) into a QObject
+ QObject *instanceQObject = PySide::convertToQObject(instanceObject, true);
+ if (instanceQObject == nullptr)
+ return -1;
+
+ // Create Singleton Functor to pass the QObject to the Type registration step
+ // similarly to the case when we have a callback
+ QQmlPrivate::SingletonFunctor registrationFunctor;
+ registrationFunctor.m_object = instanceQObject;
+
+ const QMetaObject *metaObject = PySide::retrieveMetaObject(pyObjType);
+ Q_ASSERT(metaObject);
+
+ QQmlPrivate::RegisterSingletonType type;
+ type.structVersion = 0;
+
+ type.uri = uri;
+ type.version = QTypeRevision::fromVersion(versionMajor, versionMinor);
+ type.typeName = qmlName;
+ type.instanceMetaObject = metaObject;
+
+ // FIXME: Fix this to assign new type ids each time.
+ type.typeId = QMetaType(QMetaType::QObjectStar);
+ type.qObjectApi = registrationFunctor;
+
+
+ return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &type);
+}
+
+static std::string getGlobalString(const char *name)
+{
+ using Shiboken::AutoDecRef;
+
+ PyObject *globals = PyEval_GetGlobals();
+
+ AutoDecRef pyName(Py_BuildValue("s", name));
+
+ PyObject *globalVar = PyDict_GetItem(globals, pyName);
+
+ if (globalVar == nullptr || !PyUnicode_Check(globalVar))
+ return "";
+
+ const char *stringValue = _PepUnicode_AsString(globalVar);
+ return stringValue != nullptr ? stringValue : "";
+}
+
+static int getGlobalInt(const char *name)
+{
+ using Shiboken::AutoDecRef;
+
+ PyObject *globals = PyEval_GetGlobals();
+
+ AutoDecRef pyName(Py_BuildValue("s", name));
+
+ PyObject *globalVar = PyDict_GetItem(globals, pyName);
+
+ if (globalVar == nullptr || !PyLong_Check(globalVar))
+ return -1;
+
+ long value = PyLong_AsLong(globalVar);
+
+ if (value > std::numeric_limits<int>::max() || value < std::numeric_limits<int>::min())
+ return -1;
+
+ return value;
+}
+
+enum class RegisterMode {
+ Normal,
+ Anonymous,
+ Uncreatable,
+ Singleton
+};
+
+static PyObject *qmlElementMacroHelper(PyObject *pyObj,
+ const char *decoratorName,
+ RegisterMode mode = RegisterMode::Normal,
+ const char *noCreationReason = nullptr)
+{
+ if (!PyType_Check(pyObj)) {
+ PyErr_Format(PyExc_TypeError, "This decorator can only be used on classes.");
+ return nullptr;
+ }
+
+ PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj);
+ const char *typeName = pyObjType->tp_name;
+ if (!PySequence_Contains(pyObjType->tp_mro, reinterpret_cast<PyObject *>(qObjectType()))) {
+ PyErr_Format(PyExc_TypeError, "This decorator can only be used with classes inherited from QObject, got %s.",
+ typeName);
+ return nullptr;
+ }
+
+ std::string importName = getGlobalString("QML_IMPORT_NAME");
+ int majorVersion = getGlobalInt("QML_IMPORT_MAJOR_VERSION");
+ int minorVersion = getGlobalInt("QML_IMPORT_MINOR_VERSION");
+
+ if (importName.empty()) {
+ PyErr_Format(PyExc_TypeError, "You need specify QML_IMPORT_NAME in order to use %s.",
+ decoratorName);
+ return nullptr;
+ }
+
+ if (majorVersion == -1) {
+ PyErr_Format(PyExc_TypeError, "You need specify QML_IMPORT_MAJOR_VERSION in order to use %s.",
+ decoratorName);
+ return nullptr;
+ }
+
+ // Specifying a minor version is optional
+ if (minorVersion == -1)
+ minorVersion = 0;
+
+ const char *uri = importName.c_str();
+ const int result = mode == RegisterMode::Singleton
+ ? PySide::qmlRegisterSingletonType(pyObj, uri, majorVersion, minorVersion,
+ typeName, nullptr,
+ PySide::isQObjectDerived(pyObjType, false),
+ false)
+ : PySide::qmlRegisterType(pyObj, uri, majorVersion, minorVersion,
+ mode != RegisterMode::Anonymous ? typeName : nullptr,
+ noCreationReason,
+ mode == RegisterMode::Normal);
+
+ if (result == -1) {
+ PyErr_Format(PyExc_TypeError, "%s: Failed to register type %s.",
+ decoratorName, typeName);
+ }
+
+ return pyObj;
+}
+
+// FIXME: Store this in PySide::TypeUserData once it is moved to libpyside?
+static QList<PyObject *> decoratedSingletons;
+
+PyObject *PySide::qmlElementMacro(PyObject *pyObj)
+{
+ const char *noCreationReason = nullptr;
+ RegisterMode mode = RegisterMode::Normal;
+ if (decoratedSingletons.contains(pyObj))
+ mode = RegisterMode::Singleton;
+ else if ((noCreationReason = PySide::qmlNoCreationReason(pyObj)))
+ mode = RegisterMode::Uncreatable;
+ return qmlElementMacroHelper(pyObj, "QmlElement", mode, noCreationReason);
+}
+
+PyObject *PySide::qmlAnonymousMacro(PyObject *pyObj)
+{
+ return qmlElementMacroHelper(pyObj, "QmlAnonymous",
+ RegisterMode::Anonymous);
+}
+
+PyObject *PySide::qmlSingletonMacro(PyObject *pyObj)
+{
+ decoratedSingletons.append(pyObj);
+ Py_INCREF(pyObj);
+ return pyObj;
+}
diff --git a/sources/pyside6/libpysideqml/pysideqmlregistertype.h b/sources/pyside6/libpysideqml/pysideqmlregistertype.h
new file mode 100644
index 000000000..b1c4f9dcc
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmlregistertype.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYSIDEQMLREGISTERTYPE_H
+#define PYSIDEQMLREGISTERTYPE_H
+
+#include "pysideqmlmacros.h"
+
+#include <sbkpython.h>
+
+namespace PySide
+{
+
+/**
+ * PySide implementation of qmlRegisterType<T> function.
+ *
+ * \param pyObj Python type to be registered.
+ * \param uri QML element uri.
+ * \param versionMajor QML component major version.
+ * \param versionMinor QML component minor version.
+ * \param qmlName QML element name
+ * \return the metatype id of the registered type.
+ */
+PYSIDEQML_API int qmlRegisterType(PyObject *pyObj, const char *uri,
+ int versionMajor, int versionMinor,
+ const char *qmlName, const char *noCreationReason = nullptr,
+ bool creatable = true);
+
+/**
+ * PySide implementation of qmlRegisterSingletonType<T> function.
+ *
+ * \param pyObj Python type to be registered.
+ * \param uri QML element uri.
+ * \param versionMajor QML component major version.
+ * \param versionMinor QML component minor version.
+ * \param qmlName QML element name
+ * \param callback Registration callback
+ * \return the metatype id of the registered type.
+ */
+PYSIDEQML_API int qmlRegisterSingletonType(PyObject *pyObj,const char *uri,
+ int versionMajor, int versionMinor, const char *qmlName,
+ PyObject *callback, bool isQObject, bool hasCallback);
+
+/**
+ * PySide implementation of qmlRegisterSingletonInstance<T> function.
+ *
+ * \param pyObj Python type to be registered.
+ * \param uri QML element uri.
+ * \param versionMajor QML component major version.
+ * \param versionMinor QML component minor version.
+ * \param qmlName QML element name
+ * \param instanceObject singleton object to be registered.
+ * \return the metatype id of the registered type.
+ */
+PYSIDEQML_API int qmlRegisterSingletonInstance(PyObject *pyObj, const char *uri,
+ int versionMajor, int versionMinor,
+ const char *qmlName, PyObject *instanceObject);
+
+/**
+ * PySide implementation of the QML_ELEMENT macro
+ *
+ * \param pyObj Python type to be registered
+ */
+PYSIDEQML_API PyObject *qmlElementMacro(PyObject *pyObj);
+
+/// PySide implementation of the QML_ANONYMOUS macro
+/// \param pyObj Python type to be registered
+PYSIDEQML_API PyObject *qmlAnonymousMacro(PyObject *pyObj);
+
+/// PySide implementation of the QML_SINGLETON macro
+/// \param pyObj Python type to be registered
+PYSIDEQML_API PyObject *qmlSingletonMacro(PyObject *pyObj);
+
+} // namespace PySide
+
+#endif // PYSIDEQMLREGISTERTYPE_H
diff --git a/sources/pyside6/libpysideqml/pysideqmlregistertype_p.h b/sources/pyside6/libpysideqml/pysideqmlregistertype_p.h
new file mode 100644
index 000000000..d357a0392
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmlregistertype_p.h
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYSIDEQMLREGISTERTYPE_P_H
+#define PYSIDEQMLREGISTERTYPE_P_H
+
+#include <sbkpython.h>
+
+PyTypeObject *qObjectType();
+
+#endif // PYSIDEQMLREGISTERTYPE_P_H
diff --git a/sources/pyside6/libpysideqml/pysideqmluncreatable.cpp b/sources/pyside6/libpysideqml/pysideqmluncreatable.cpp
new file mode 100644
index 000000000..e59476146
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmluncreatable.cpp
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "pysideqmluncreatable.h"
+
+#include <shiboken.h>
+#include <signature.h>
+#include <sbkcppstring.h>
+
+#include <string>
+#include <unordered_map>
+
+#include <QtCore/QtGlobal>
+
+struct PySideQmlUncreatablePrivate
+{
+ std::string reason;
+};
+
+using UncreatableReasonMap = std::unordered_map<PyObject *, std::string>;
+
+// Types and their nocreationReason. FIXME: Store this in PySide::TypeUserData
+// once it is moved to libpyside?
+UncreatableReasonMap &uncreatableReasonMap()
+{
+ static UncreatableReasonMap result;
+ return result;
+}
+
+extern "C"
+{
+
+// The call operator is passed the class type and registers the reason
+// in the uncreatableReasonMap()
+static PyObject *classCall(PyObject *self, PyObject *args, PyObject * /* kw */)
+{
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ PyErr_Format(PyExc_TypeError,
+ "The QmlUncreatable decorator takes exactly 1 positional argument (%zd given)",
+ PyTuple_Size(args));
+ return nullptr;
+ }
+
+ PyObject *klass = PyTuple_GetItem(args, 0);
+ // 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 nullptr;
+ }
+
+ PyTypeObject *klassType = reinterpret_cast<PyTypeObject *>(klass);
+ if (!Shiboken::ObjectType::checkType(klassType)) {
+ PyErr_SetString(PyExc_TypeError,
+ "This decorator can only be used on classes that are subclasses of QObject");
+ return nullptr;
+ }
+
+ auto data = reinterpret_cast<PySideQmlUncreatable *>(self);
+ uncreatableReasonMap().insert({klass, data->d->reason});
+
+ Py_INCREF(klass);
+ return klass;
+}
+
+static PyObject *qmlUncreatableTpNew(PyTypeObject *subtype, PyObject * /* args */,
+ PyObject * /* kwds */)
+{
+ auto *me = reinterpret_cast<PySideQmlUncreatable *>(subtype->tp_alloc(subtype, 0));
+ me->d = new PySideQmlUncreatablePrivate;
+ return reinterpret_cast<PyObject *>(me);
+}
+
+static int qmlUncreatableTpInit(PyObject *self, PyObject *args, PyObject * /* kwds */)
+{
+ PySideQmlUncreatable *data = reinterpret_cast<PySideQmlUncreatable *>(self);
+ PySideQmlUncreatablePrivate *pData = data->d;
+
+ bool ok = false;
+ const auto argsCount = PyTuple_Size(args);
+ if (argsCount == 0) {
+ ok = true; // QML-generated reason
+ } else if (argsCount == 1) {
+ PyObject *arg = PyTuple_GET_ITEM(args, 0);
+ if (arg == Py_None) {
+ ok = true; // QML-generated reason
+ } else if (PyUnicode_Check(arg)) {
+ ok = true;
+ Shiboken::String::toCppString(arg, &(pData->reason));
+ }
+ }
+
+ if (!ok) {
+ PyErr_Format(PyExc_TypeError,
+ "QmlUncreatable() takes a single string argument or no argument");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void qmlUncreatableFree(void *self)
+{
+ auto pySelf = reinterpret_cast<PyObject *>(self);
+ auto data = reinterpret_cast<PySideQmlUncreatable *>(self);
+
+ delete data->d;
+ Py_TYPE(pySelf)->tp_base->tp_free(self);
+}
+
+static PyType_Slot PySideQmlUncreatableType_slots[] = {
+ {Py_tp_call, reinterpret_cast<void *>(classCall)},
+ {Py_tp_init, reinterpret_cast<void *>(qmlUncreatableTpInit)},
+ {Py_tp_new, reinterpret_cast<void *>(qmlUncreatableTpNew)},
+ {Py_tp_free, reinterpret_cast<void *>(qmlUncreatableFree)},
+ {Py_tp_dealloc, reinterpret_cast<void *>(Sbk_object_dealloc)},
+ {0, nullptr}
+};
+
+static PyType_Spec PySideQmlUncreatableType_spec = {
+ "2:PySide6.QtCore.qmlUncreatable",
+ sizeof(PySideQmlUncreatable),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PySideQmlUncreatableType_slots,
+};
+
+PyTypeObject *PySideQmlUncreatableTypeF(void)
+{
+ static auto *type = SbkType_FromSpec(&PySideQmlUncreatableType_spec);
+ return type;
+}
+
+} // extern "C"
+
+static const char *qmlUncreatable_SignatureStrings[] = {
+ "PySide6.QtQml.QmlUncreatable(self,reason:str)",
+ nullptr // Sentinel
+};
+
+void initQmlUncreatable(PyObject *module)
+{
+ if (InitSignatureStrings(PySideQmlUncreatableTypeF(), qmlUncreatable_SignatureStrings) < 0)
+ return;
+
+ Py_INCREF(PySideQmlUncreatableTypeF());
+ PyModule_AddObject(module, "QmlUncreatable",
+ reinterpret_cast<PyObject *>(PySideQmlUncreatableTypeF()));
+}
+
+namespace PySide
+{
+const char *qmlNoCreationReason(PyObject *type)
+{
+ const auto &map = uncreatableReasonMap();
+ auto it = map.find(type);
+ return it != map.cend() ? it->second.c_str() : nullptr;
+}
+
+} // PySide
diff --git a/sources/pyside6/libpysideqml/pysideqmluncreatable.h b/sources/pyside6/libpysideqml/pysideqmluncreatable.h
new file mode 100644
index 000000000..89a5f1223
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmluncreatable.h
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PYSIDEQMLUNCREATABLE_H
+#define PYSIDEQMLUNCREATABLE_H
+
+#include <sbkpython.h>
+
+// The QmlUncreatable decorator modifies QmlElement to register an uncreatable
+// type. Due to the (reverse) execution order of decorators, it needs to follow
+// QmlElement.
+extern "C"
+{
+ extern PyTypeObject *PySideQmlUncreatableTypeF(void);
+
+ struct PySideQmlUncreatablePrivate;
+ struct PySideQmlUncreatable
+ {
+ PyObject_HEAD
+ PySideQmlUncreatablePrivate* d;
+ };
+
+} // extern "C"
+
+void initQmlUncreatable(PyObject *module);
+
+namespace PySide
+{
+ // Return the reason if a type is not creatable.
+ const char *qmlNoCreationReason(PyObject *type);
+} // PySide
+
+#endif // PYSIDEQMLUNCREATABLE_H