Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2023-10-09 08:24:21 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2023-10-23 12:26:07 +0200
commit91bf9aa10faad14de557136664f58005c935d11c (patch)
treed5ff6278aca875c89ffad46cc36d68ba74a366c9 /sources/pyside6/libpysideqml
parent624e52a0114a966bd852aeb66b8a1b928d80343b (diff)
QML registration code: Modernize
Use QQmlPrivate::RegisterTypeAndRevisions and information set as QMetaClassInfo as recommended by QML team. The only remaining old code path is for qmlRegisterSingletonType() for the hypothetical case of a value type. [ChangeLog][PySide6] QML type registration has been ported to use RegisterTypeAndRevisions. Fixes: PYSIDE-2484 Change-Id: I7134cbfe1fad1fb543a560cc13b68327b9bd9c2b Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/pyside6/libpysideqml')
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlregistertype.cpp332
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlregistertype.h8
-rw-r--r--sources/pyside6/libpysideqml/pysideqmltypeinfo.cpp2
-rw-r--r--sources/pyside6/libpysideqml/pysideqmltypeinfo_p.h4
-rw-r--r--sources/pyside6/libpysideqml/pysideqmluncreatable.cpp17
-rw-r--r--sources/pyside6/libpysideqml/pysideqmluncreatable.h4
6 files changed, 235 insertions, 132 deletions
diff --git a/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp b/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp
index 940847632..24b313d32 100644
--- a/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp
+++ b/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp
@@ -6,6 +6,7 @@
#include "pysideqmltypeinfo_p.h"
#include "pysideqmlattached_p.h"
#include "pysideqmlextended_p.h"
+#include "pysideqmluncreatable.h"
#include <limits>
#include <optional>
@@ -17,6 +18,7 @@
// pyside
#include <pyside.h>
#include <pysideqobject.h>
+#include <pysideclassinfo.h>
#include <pyside_p.h>
#include <QtCore/QMutex>
@@ -27,8 +29,12 @@
#include <QtQml/QQmlListProperty>
#include <private/qqmlmetatype_p.h>
+using namespace Qt::StringLiterals;
+
static PySide::Qml::QuickRegisterItemFunction quickRegisterItemFunction = nullptr;
+static const auto qmlElementKey = "QML.Element"_ba;
+
static void createInto(void *memory, void *type)
{
QMutexLocker locker(&PySide::nextQObjectMemoryAddrMutex());
@@ -150,11 +156,41 @@ std::optional<ImportData> getGlobalImportData(const char *decoratorName)
return result;
}
+static PyTypeObject *checkTypeObject(PyObject *pyObj, const char *what)
+{
+ if (PyType_Check(pyObj) == 0) {
+ PyErr_Format(PyExc_TypeError, "%s can only be used for classes.", what);
+ return nullptr;
+ }
+ return reinterpret_cast<PyTypeObject *>(pyObj);
+}
+
+static bool setClassInfo(PyTypeObject *type, const QByteArray &key, const QByteArray &value)
+{
+ if (!PySide::ClassInfo::setClassInfo(type, key, value)) {
+ PyErr_Format(PyExc_TypeError, "Setting class info \"%s\" to \"%s\" on \"%s\" failed.",
+ key.constData(), value.constData(), type->tp_name);
+ return false;
+ }
+ return true;
+}
+
+static inline bool setSingletonClassInfo(PyTypeObject *type)
+{
+ return setClassInfo(type, "QML.Singleton"_ba, "true"_ba);
+}
+
+static QQmlCustomParser *defaultCustomParserFactory()
+{
+ return nullptr;
+}
+
namespace PySide::Qml {
-static int qmlRegisterType(PyObject *pyObj, const ImportData &importData,
- const char *qmlName, const char *noCreationReason,
- bool creatable)
+// Modern (6.7) type registration using RegisterTypeAndRevisions
+// and information set to QMetaClassInfo.
+static int qmlRegisterType(PyObject *pyObj, PyObject *pyClassInfoObj,
+ const ImportData &importData)
{
using namespace Shiboken;
@@ -164,6 +200,8 @@ static int qmlRegisterType(PyObject *pyObj, const ImportData &importData,
const QMetaObject *metaObject = PySide::retrieveMetaObject(pyObjType);
Q_ASSERT(metaObject);
+ const QMetaObject *classInfoMetaObject = pyObj == pyClassInfoObj
+ ? metaObject : PySide::retrieveMetaObject(pyClassInfoObj);
// Register as simple QObject rather than Qt Quick item.
// Incref the type object, don't worry about decref'ing it because
@@ -181,26 +219,27 @@ static int qmlRegisterType(PyObject *pyObj, const ImportData &importData,
const auto attachedInfo = qmlAttachedInfo(pyObjType, typeInfo);
const auto extendedInfo = qmlExtendedInfo(pyObj, typeInfo);
- QQmlPrivate::RegisterType type {
+ QList<int> ids;
+ QQmlPrivate::RegisterTypeAndRevisions type {
QQmlPrivate::RegisterType::StructVersion::Base, // structVersion
typeId, listId, objectSize,
- creatable ? createInto : nullptr, // create
+ createInto, // create
pyObj, // userdata
- QString::fromUtf8(noCreationReason),
nullptr, // createValueType (Remove in Qt 7)
importData.importName.constData(),
importData.toTypeRevision(), // version
- qmlName, // elementName
metaObject,
+ classInfoMetaObject,
attachedInfo.factory, // attachedPropertiesFunction
attachedInfo.metaObject, // attachedPropertiesMetaObject
0, 0, 0, // parserStatusCast, valueSourceCast, valueInterceptorCast
extendedInfo.factory, // extensionObjectCreate
extendedInfo.metaObject, // extensionMetaObject
- nullptr, // customParser
- {}, // revision
+ defaultCustomParserFactory, // customParser
+ &ids, // qmlTypeIds
0, // finalizerCast
- QQmlPrivate::ValueTypeCreationMethod::None // creationMethod
+ false, // forceAnonymous
+ {} // listMetaSequence
};
// Allow registering Qt Quick items.
@@ -220,47 +259,137 @@ static int qmlRegisterType(PyObject *pyObj, const ImportData &importData,
QQmlPrivate::StaticCastSelector<QObject, QQmlPropertyValueInterceptor>::cast();
}
- int qmlTypeId = QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
+ QQmlPrivate::qmlregister(QQmlPrivate::TypeAndRevisionsRegistration, &type);
+ const int qmlTypeId = ids.value(0, -1);
if (qmlTypeId == -1) {
PyErr_Format(PyExc_TypeError, "QML meta type registration of \"%s\" failed.",
- qmlName);
+ typeName.constData());
}
return qmlTypeId;
}
+// Legacy (pre 6.7) compatibility helper for the free register functions.
int qmlRegisterType(PyObject *pyObj, const char *uri, int versionMajor, int versionMinor,
const char *qmlName, const char *noCreationReason,
bool creatable)
{
- return qmlRegisterType(pyObj, {uri, versionMajor, versionMinor}, qmlName,
- noCreationReason, creatable);
+ auto *type = checkTypeObject(pyObj, "qmlRegisterType()");
+ if (type == nullptr || !setClassInfo(type, qmlElementKey, qmlName))
+ return -1;
+ if (!creatable)
+ setUncreatableClassInfo(type, noCreationReason);
+ return qmlRegisterType(pyObj, pyObj, {uri, versionMajor, versionMinor});
}
-static int qmlRegisterSingletonType(PyObject *pyObj, const ImportData &importData,
- const char *qmlName, PyObject *callback,
- bool isQObject, bool hasCallback)
+// Singleton helpers
+
+bool checkSingletonCallback(PyObject *callback)
+{
+ if (PyCallable_Check(callback) == 0) {
+ PyErr_Format(PyExc_TypeError, "Invalid callback specified.");
+ return false;
+ }
+ Shiboken::AutoDecRef funcCode(PyObject_GetAttrString(callback, "__code__"));
+ Shiboken::AutoDecRef argCount(PyObject_GetAttrString(funcCode, "co_argcount"));
+ if (PyLong_AsLong(argCount) != 1) {
+ PyErr_Format(PyExc_TypeError, "Callback has a bad parameter count.");
+ return false;
+ }
+ // Make sure the callback never gets deallocated
+ Py_INCREF(callback);
+
+ return true;
+}
+
+using SingletonQObjectCreation = std::function<QObject*(QQmlEngine *, QJSEngine *)>;
+
+static SingletonQObjectCreation
+ singletonQObjectCreation(PyObject *pyObj, PyObject *callback, bool hasCallback)
{
using namespace Shiboken;
- if (hasCallback) {
- if (!PyCallable_Check(callback)) {
- PyErr_Format(PyExc_TypeError, "Invalid callback specified.");
- return -1;
- }
+ return [callback, pyObj, hasCallback](QQmlEngine *engine, QJSEngine *) -> QObject * {
+ Shiboken::GilState gil;
+ AutoDecRef args(PyTuple_New(hasCallback ? 1 : 0));
- AutoDecRef funcCode(PyObject_GetAttrString(callback, "__code__"));
- AutoDecRef argCount(PyObject_GetAttrString(funcCode, "co_argcount"));
+ if (hasCallback) {
+ PyTuple_SET_ITEM(args, 0, Conversions::pointerToPython(
+ qQmlEngineType(), engine));
+ }
- int count = PyLong_AsLong(argCount);
+ AutoDecRef retVal(PyObject_CallObject(hasCallback ? callback : pyObj, args));
- if (count != 1) {
- PyErr_Format(PyExc_TypeError, "Callback has a bad parameter count.");
- return -1;
+ // 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;
}
- // Make sure the callback never gets deallocated
- Py_INCREF(callback);
+ QObject *obj = nullptr;
+ Conversions::pythonToCppPointer(qObjectType(), retVal, &obj);
+
+ if (obj != nullptr)
+ Py_INCREF(retVal);
+
+ return obj;
+ };
+}
+
+// Modern (6.7) singleton type registration using RegisterSingletonTypeAndRevisions
+// and information set to QMetaClassInfo (QObject only pending QTBUG-110467).
+static int qmlRegisterSingletonTypeV2(PyObject *pyObj, PyObject *pyClassInfoObj,
+ const ImportData &importData,
+ PyObject *callback, bool hasCallback)
+{
+ PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj);
+ if (!isQObjectDerived(pyObjType, true))
+ return -1;
+
+ if (hasCallback && !checkSingletonCallback(callback))
+ return -1;
+
+ const QMetaObject *metaObject = PySide::retrieveMetaObject(pyObjType);
+ Q_ASSERT(metaObject);
+ const QMetaObject *classInfoMetaObject = pyObj == pyClassInfoObj
+ ? metaObject : PySide::retrieveMetaObject(pyClassInfoObj);
+
+ // If we don't have a callback we'll need the pyObj to stay allocated indefinitely
+ if (!hasCallback)
+ Py_INCREF(pyObj);
+
+ QList<int> ids;
+ QQmlPrivate::RegisterSingletonTypeAndRevisions type {
+ QQmlPrivate::RegisterType::StructVersion::Base, // structVersion
+ importData.importName.constData(),
+ importData.toTypeRevision(), // version
+ singletonQObjectCreation(pyObj, callback, hasCallback), // qObjectApi,
+ metaObject,
+ classInfoMetaObject,
+ QMetaType(QMetaType::QObjectStar), // typeId
+ nullptr, // extensionMetaObject
+ nullptr, // extensionObjectCreate
+ &ids
+ };
+
+ QQmlPrivate::qmlregister(QQmlPrivate::SingletonAndRevisionsRegistration, &type);
+ const int qmlTypeId = ids.value(0, -1);
+ if (qmlTypeId == -1) {
+ PyErr_Format(PyExc_TypeError, "Singleton QML meta type registration of \"%s\" failed.",
+ pyObjType->tp_name);
}
+ return qmlTypeId;
+}
+
+// Legacy (pre 6.7) singleton type registration using RegisterSingletonType
+// for QObject and value types. Still used by qmlRegisterSingletonType()
+// for the hypothetical case of a value type.
+static int qmlRegisterSingletonType(PyObject *pyObj, const ImportData &importData,
+ const char *qmlName, PyObject *callback,
+ bool isQObject, bool hasCallback)
+{
+ if (hasCallback && !checkSingletonCallback(callback))
+ return -1;
const QMetaObject *metaObject = nullptr;
@@ -296,36 +425,12 @@ static int qmlRegisterSingletonType(PyObject *pyObj, const ImportData &importDat
// 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;
- };
+ type.qObjectApi = singletonQObjectCreation(pyObj, callback, hasCallback);
} else {
type.scriptApi =
[callback](QQmlEngine *engine, QJSEngine *) -> QJSValue {
+ using namespace Shiboken;
+
Shiboken::GilState gil;
AutoDecRef args(PyTuple_New(1));
@@ -355,6 +460,7 @@ static int qmlRegisterSingletonType(PyObject *pyObj, const ImportData &importDat
return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &type);
}
+// Legacy (pre 6.7) compatibility helper for the free register functions.
int qmlRegisterSingletonType(PyObject *pyObj,const char *uri,
int versionMajor, int versionMinor, const char *qmlName,
PyObject *callback, bool isQObject, bool hasCallback)
@@ -363,8 +469,10 @@ int qmlRegisterSingletonType(PyObject *pyObj,const char *uri,
callback, isQObject, hasCallback);
}
+// Modern (6.7) singleton instance registration using RegisterSingletonTypeAndRevisions
+// and information set to QMetaClassInfo (QObject only).
static int qmlRegisterSingletonInstance(PyObject *pyObj, const ImportData &importData,
- const char *qmlName, PyObject *instanceObject)
+ PyObject *instanceObject)
{
using namespace Shiboken;
@@ -387,123 +495,105 @@ static int qmlRegisterSingletonInstance(PyObject *pyObj, const ImportData &impor
const QMetaObject *metaObject = PySide::retrieveMetaObject(pyObjType);
Q_ASSERT(metaObject);
- // FIXME: Fix this to assign new type ids each time.
- const QMetaType typeId = QMetaType(QMetaType::QObjectStar);
-
- QQmlPrivate::RegisterSingletonType type {
+ QList<int> ids;
+ QQmlPrivate::RegisterSingletonTypeAndRevisions type {
QQmlPrivate::RegisterType::StructVersion::Base, // structVersion
importData.importName.constData(),
importData.toTypeRevision(), // version
- qmlName, // typeName
- {}, // scriptApi
- registrationFunctor, // qObjectApi
- metaObject, // instanceMetaObject
- typeId,
+ registrationFunctor, // qObjectApi,
+ metaObject,
+ metaObject, // classInfoMetaObject
+ QMetaType(QMetaType::QObjectStar), // typeId
nullptr, // extensionMetaObject
nullptr, // extensionObjectCreate
- {} // revision
+ &ids
};
- return QQmlPrivate::qmlregister(QQmlPrivate::SingletonRegistration, &type);
+ QQmlPrivate::qmlregister(QQmlPrivate::SingletonAndRevisionsRegistration, &type);
+ return ids.value(0, -1);
}
+// Legacy (pre 6.7) compatibility helper for the free register functions.
int qmlRegisterSingletonInstance(PyObject *pyObj, const char *uri, int versionMajor,
int versionMinor, const char *qmlName,
PyObject *instanceObject)
{
+ auto *type = checkTypeObject(pyObj, "qmlRegisterSingletonInstance()");
+ if (type == nullptr || !setClassInfo(type, qmlElementKey, qmlName)
+ || !setSingletonClassInfo(type)) {
+ return -1;
+ }
return qmlRegisterSingletonInstance(pyObj, {uri, versionMajor, versionMinor},
- qmlName, instanceObject);
+ instanceObject);
}
} // namespace PySide::Qml
enum class RegisterMode {
Normal,
- Anonymous,
- Uncreatable,
Singleton
};
-static PyObject *qmlElementMacroHelper(PyObject *pyObj,
- const char *decoratorName,
- const char *typeName = nullptr,
- RegisterMode mode = RegisterMode::Normal,
- const char *noCreationReason = nullptr)
+namespace PySide::Qml {
+
+PyObject *qmlElementMacro(PyObject *pyObj, const char *decoratorName,
+ const QByteArray &typeName)
{
- if (!PyType_Check(pyObj)) {
- PyErr_Format(PyExc_TypeError, "This decorator can only be used on classes.");
+ auto *pyObjType = checkTypeObject(pyObj, decoratorName);
+ if (pyObjType == nullptr || !setClassInfo(pyObjType, qmlElementKey, typeName))
return nullptr;
- }
- PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj);
- if (typeName == nullptr)
- typeName = pyObjType->tp_name;
if (!PySide::isQObjectDerived(pyObjType, false)) {
- PyErr_Format(PyExc_TypeError, "This decorator can only be used with classes inherited from QObject, got %s.",
- pyObjType->tp_name);
+ PyErr_Format(PyExc_TypeError,
+ "%s can only be used with classes inherited from QObject, got %s.",
+ decoratorName, pyObjType->tp_name);
return nullptr;
}
+ RegisterMode mode = RegisterMode::Normal;
+ const auto info = PySide::Qml::qmlTypeInfo(pyObj);
+ auto *registerObject = pyObj;
+ if (info) {
+ if (info->flags.testFlag(PySide::Qml::QmlTypeFlag::Singleton)) {
+ mode = RegisterMode::Singleton;
+ setSingletonClassInfo(pyObjType);
+ }
+ if (info->foreignType)
+ registerObject = reinterpret_cast<PyObject *>(info->foreignType);
+ }
+
const auto importDataO = getGlobalImportData(decoratorName);
if (!importDataO.has_value())
return nullptr;
const auto importData = importDataO.value();
const int result = mode == RegisterMode::Singleton
- ? PySide::Qml::qmlRegisterSingletonType(pyObj, importData,
- typeName, nullptr,
- true /* is QObject */,
- false)
- : PySide::Qml::qmlRegisterType(pyObj, importData,
- mode != RegisterMode::Anonymous ? typeName : nullptr,
- noCreationReason,
- mode == RegisterMode::Normal);
+ ? PySide::Qml::qmlRegisterSingletonTypeV2(registerObject, pyObj, importData,
+ nullptr, false)
+ : PySide::Qml::qmlRegisterType(registerObject, pyObj, importData);
if (result == -1) {
PyErr_Format(PyExc_TypeError, "%s: Failed to register type %s.",
- decoratorName, typeName);
+ decoratorName, pyObjType->tp_name);
+ return nullptr;
}
return pyObj;
}
-namespace PySide::Qml {
-
-PyObject *qmlElementMacro(PyObject *pyObj, const char *decoratorName,
- const char *typeName = nullptr)
-{
- RegisterMode mode = RegisterMode::Normal;
- const char *noCreationReason = nullptr;
- const auto info = PySide::Qml::qmlTypeInfo(pyObj);
- auto *registerObject = pyObj;
- if (info) {
- if (info->flags.testFlag(PySide::Qml::QmlTypeFlag::Singleton))
- mode = RegisterMode::Singleton;
- else if (info->flags.testFlag(PySide::Qml::QmlTypeFlag::Uncreatable))
- mode = RegisterMode::Uncreatable;
- noCreationReason = info->noCreationReason.constData();
- if (info->foreignType)
- registerObject = reinterpret_cast<PyObject *>(info->foreignType);
- }
- if (!qmlElementMacroHelper(registerObject, decoratorName, typeName, mode, noCreationReason))
- return nullptr;
- return pyObj;
-}
-
PyObject *qmlElementMacro(PyObject *pyObj)
{
- return qmlElementMacro(pyObj, "QmlElement");
+ return qmlElementMacro(pyObj, "QmlElement", "auto"_ba);
}
PyObject *qmlNamedElementMacro(PyObject *pyObj, const QByteArray &typeName)
{
- return qmlElementMacro(pyObj, "QmlNamedElement", qstrdup(typeName.constData()));
+ return qmlElementMacro(pyObj, "QmlNamedElement", typeName);
}
PyObject *qmlAnonymousMacro(PyObject *pyObj)
{
- return qmlElementMacroHelper(pyObj, "QmlAnonymous", nullptr,
- RegisterMode::Anonymous);
+ return qmlElementMacro(pyObj, "QmlAnonymous", "anonymous"_ba);
}
PyObject *qmlSingletonMacro(PyObject *pyObj)
diff --git a/sources/pyside6/libpysideqml/pysideqmlregistertype.h b/sources/pyside6/libpysideqml/pysideqmlregistertype.h
index 1e6c7d28d..3524adaf4 100644
--- a/sources/pyside6/libpysideqml/pysideqmlregistertype.h
+++ b/sources/pyside6/libpysideqml/pysideqmlregistertype.h
@@ -19,6 +19,9 @@ namespace PySide::Qml
/**
* PySide implementation of qmlRegisterType<T> function.
*
+ * This is a helper for the legacy free qmlRegisterType*() type functions.
+ * Decorators should be used instead.
+ *
* \param pyObj Python type to be registered.
* \param uri QML element uri.
* \param versionMajor QML component major version.
@@ -34,6 +37,9 @@ PYSIDEQML_API int qmlRegisterType(PyObject *pyObj, const char *uri,
/**
* PySide implementation of qmlRegisterSingletonType<T> function.
*
+ * This is a helper for the legacy free qmlRegisterSingletonType<T> type function.
+ * Decorators should be used instead.
+ *
* \param pyObj Python type to be registered.
* \param uri QML element uri.
* \param versionMajor QML component major version.
@@ -80,7 +86,7 @@ PYSIDEQML_API PyObject *qmlSingletonMacro(PyObject *pyObj);
// Used by QtQuick module to fill the QQmlPrivate::RegisterType::parserStatusCast,
// valueSourceCast and valueInterceptorCast fields with the correct values.
using QuickRegisterItemFunction =
- bool (*)(PyObject *pyObj, QQmlPrivate::RegisterType *);
+ bool (*)(PyObject *pyObj, QQmlPrivate::RegisterTypeAndRevisions *);
PYSIDEQML_API QuickRegisterItemFunction getQuickRegisterItemFunction();
PYSIDEQML_API void setQuickRegisterItemFunction(QuickRegisterItemFunction function);
diff --git a/sources/pyside6/libpysideqml/pysideqmltypeinfo.cpp b/sources/pyside6/libpysideqml/pysideqmltypeinfo.cpp
index 0dc5d64c8..f369f7400 100644
--- a/sources/pyside6/libpysideqml/pysideqmltypeinfo.cpp
+++ b/sources/pyside6/libpysideqml/pysideqmltypeinfo.cpp
@@ -42,8 +42,6 @@ QDebug operator<<(QDebug d, const QmlTypeInfo &i)
d.noquote();
d.nospace();
d << "QmlTypeInfo(" << i.flags;
- if (!i.noCreationReason.isEmpty())
- d << ", noCreationReason=\"" << i.noCreationReason << '"';
if (i.foreignType)
d << ", foreignType=" << i.foreignType->tp_name;
if (i.attachedType)
diff --git a/sources/pyside6/libpysideqml/pysideqmltypeinfo_p.h b/sources/pyside6/libpysideqml/pysideqmltypeinfo_p.h
index cf06bb304..112e127a7 100644
--- a/sources/pyside6/libpysideqml/pysideqmltypeinfo_p.h
+++ b/sources/pyside6/libpysideqml/pysideqmltypeinfo_p.h
@@ -19,8 +19,7 @@ namespace PySide::Qml {
enum class QmlTypeFlag
{
- Singleton = 0x1,
- Uncreatable = 0x2
+ Singleton = 0x1
};
Q_DECLARE_FLAGS(QmlTypeFlags, QmlTypeFlag)
@@ -30,7 +29,6 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QmlTypeFlags)
struct QmlTypeInfo
{
QmlTypeFlags flags;
- QByteArray noCreationReason;
PyTypeObject *foreignType = nullptr;
PyTypeObject *attachedType = nullptr;
PyTypeObject *extensionType = nullptr;
diff --git a/sources/pyside6/libpysideqml/pysideqmluncreatable.cpp b/sources/pyside6/libpysideqml/pysideqmluncreatable.cpp
index 43c795cb0..dad13cf5f 100644
--- a/sources/pyside6/libpysideqml/pysideqmluncreatable.cpp
+++ b/sources/pyside6/libpysideqml/pysideqmluncreatable.cpp
@@ -2,8 +2,8 @@
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "pysideqmluncreatable.h"
-#include "pysideqmltypeinfo_p.h"
#include <pysideclassdecorator_p.h>
+#include <pysideclassinfo.h>
#include <shiboken.h>
#include <signature.h>
@@ -14,6 +14,8 @@
#include <QtCore/QtGlobal>
+using namespace Qt::StringLiterals;
+
class PySideQmlUncreatablePrivate : public PySide::ClassDecorator::StringDecoratorPrivate
{
public:
@@ -35,11 +37,9 @@ PyObject *PySideQmlUncreatablePrivate::tp_call(PyObject *self, PyObject *args, P
if (klass== nullptr)
return nullptr;
+ auto *type = reinterpret_cast<PyTypeObject *>(klass);
auto *data = DecoratorPrivate::get<PySideQmlUncreatablePrivate>(self);
-
- const auto info = PySide::Qml::ensureQmlTypeInfo(klass);
- info->flags.setFlag(PySide::Qml::QmlTypeFlag::Uncreatable);
- info->noCreationReason = data->string();
+ setUncreatableClassInfo(type, data->string());
Py_INCREF(klass);
return klass;
@@ -105,3 +105,10 @@ void initQmlUncreatable(PyObject *module)
PyModule_AddObject(module, "QmlUncreatable",
reinterpret_cast<PyObject *>(PySideQmlUncreatable_TypeF()));
}
+
+void setUncreatableClassInfo(PyTypeObject *type, const QByteArray &reason)
+{
+ PySide::ClassInfo::setClassInfo(type, {
+ {"QML.Creatable"_ba, "false"_ba},
+ {"QML.UncreatableReason"_ba, reason} });
+}
diff --git a/sources/pyside6/libpysideqml/pysideqmluncreatable.h b/sources/pyside6/libpysideqml/pysideqmluncreatable.h
index 7961634ca..772ad4ccb 100644
--- a/sources/pyside6/libpysideqml/pysideqmluncreatable.h
+++ b/sources/pyside6/libpysideqml/pysideqmluncreatable.h
@@ -6,6 +6,8 @@
#include <sbkpython.h>
+#include <QtCore/QByteArray>
+
// The QmlUncreatable decorator modifies QmlElement to register an uncreatable
// type. Due to the (reverse) execution order of decorators, it needs to follow
// QmlElement.
@@ -16,4 +18,6 @@ extern "C"
void initQmlUncreatable(PyObject *module);
+void setUncreatableClassInfo(PyTypeObject *type, const QByteArray &reason);
+
#endif // PYSIDEQMLUNCREATABLE_H