aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2022-03-02 21:14:49 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2022-03-03 16:17:42 +0100
commitbd67be48143a26e4073fce933c479b9f6649cae7 (patch)
tree78c9323c0d498f549cc2b769fe7c0c859ab295a9
parentcf40e624e603dc468ec585ecddc9fbf1ee0ccddd (diff)
Simplify special code handling Qt Quick type registration
The code used templates to ensure the QMetaTypes registered in QML matched the Qt Quick types (QQuickPaintedItem, QQuickFramebufferObject, QQuickItem). After fixing the metatypes, all that is left is to determine the correct values for QQmlPrivate::RegisterType::parserStatusCast, valueSourceCast and valueInterceptorCast by the template code. This will make the QmlAttached/QmlExtended work with Qt Quick, too. Task-number: PYSIDE-1836 Change-Id: Ic31587c9fd2dca46f6957757079b6abc56cc7416 Reviewed-by: Christian Tismer <tismer@stackless.com> Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r--sources/pyside6/PySide6/QtQuick/pysidequickregistertype.cpp132
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlregistertype.cpp77
-rw-r--r--sources/pyside6/libpysideqml/pysideqmlregistertype.h8
3 files changed, 60 insertions, 157 deletions
diff --git a/sources/pyside6/PySide6/QtQuick/pysidequickregistertype.cpp b/sources/pyside6/PySide6/QtQuick/pysidequickregistertype.cpp
index edca30620..2f2e5a6a2 100644
--- a/sources/pyside6/PySide6/QtQuick/pysidequickregistertype.cpp
+++ b/sources/pyside6/PySide6/QtQuick/pysidequickregistertype.cpp
@@ -47,83 +47,31 @@
#include <QtQuick/QQuickPaintedItem>
#include <QtQuick/QQuickFramebufferObject>
-#include <QtQml/private/qqmlmetatype_p.h>
-
-#include <QtCore/QMutex>
-
-static void createQuickItem(void *memory, void *type)
-{
- QMutexLocker locker(&PySide::nextQObjectMemoryAddrMutex());
- PySide::setNextQObjectMemoryAddr(memory);
- Shiboken::GilState state;
- PyObject *obj = PyObject_CallObject(reinterpret_cast<PyObject *>(type), 0);
- if (!obj || PyErr_Occurred())
- PyErr_Print();
- PySide::setNextQObjectMemoryAddr(nullptr);
-}
-
-bool pyTypeObjectInheritsFromClass(PyTypeObject *pyObjType, QByteArray className)
+bool pyTypeObjectInheritsFromClass(PyTypeObject *pyObjType, const char *classPtrName)
{
- className.append('*');
- PyTypeObject *classPyType = Shiboken::Conversions::getPythonTypeObject(className.constData());
+ PyTypeObject *classPyType = Shiboken::Conversions::getPythonTypeObject(classPtrName);
bool isDerived = PySequence_Contains(pyObjType->tp_mro,
reinterpret_cast<PyObject *>(classPyType));
return isDerived;
}
-template <typename T>
-struct QPysideQmlMetaTypeInterface : public QQmlMetaTypeInterface
-{
- const QMetaObject *metaObject;
-
- static const QMetaObject *metaObjectFun(const QMetaTypeInterface *mti)
- {
- return static_cast<const QPysideQmlMetaTypeInterface *>(mti)->metaObject;
- }
-
- QPysideQmlMetaTypeInterface(const QByteArray &name, const QMetaObject *metaObjectIn = nullptr)
- : QQmlMetaTypeInterface(name, static_cast<T*>(nullptr)), metaObject(metaObjectIn) {
- metaObjectFn = metaObjectFun;
- }
-};
-
template <class WrappedClass>
-void registerTypeIfInheritsFromClass(
- const QByteArray &className,
- PyTypeObject *typeToRegister,
- const QByteArray &typePointerName,
- const QByteArray &typeListName,
- const QMetaObject *typeMetaObject,
- QQmlPrivate::RegisterType *type,
- bool &registered)
+bool registerTypeIfInheritsFromClass(const char *classPtrName,
+ PyTypeObject *typeToRegister,
+ QQmlPrivate::RegisterType *type)
{
- bool shouldRegister = !registered && pyTypeObjectInheritsFromClass(typeToRegister, className);
- if (shouldRegister) {
-
- QMetaType ptrType(new QPysideQmlMetaTypeInterface<WrappedClass *>(typePointerName, typeMetaObject));
-
- QMetaType lstType(new QQmlListMetaTypeInterface(typeListName, static_cast<QQmlListProperty<WrappedClass>*>(nullptr), ptrType.iface()));
-
- type->typeId = std::move(ptrType);
- type->listId = std::move(lstType);
- type->attachedPropertiesFunction = QQmlPrivate::attachedPropertiesFunc<WrappedClass>();
- type->attachedPropertiesMetaObject =
- QQmlPrivate::attachedPropertiesMetaObject<WrappedClass>();
- type->parserStatusCast =
- QQmlPrivate::StaticCastSelector<WrappedClass, QQmlParserStatus>::cast();
- type->valueSourceCast =
- QQmlPrivate::StaticCastSelector<WrappedClass, QQmlPropertyValueSource>::cast();
- type->valueInterceptorCast =
- QQmlPrivate::StaticCastSelector<WrappedClass, QQmlPropertyValueInterceptor>::cast();
- // Pass the size of the generated wrapper class (larger than the plain
- // Qt class due to virtual method cache) since that is what is instantiated.
- type->objectSize = int(PySide::getSizeOfQObject(typeToRegister));
- registered = true;
- }
+ if (!pyTypeObjectInheritsFromClass(typeToRegister, classPtrName))
+ return false;
+ type->parserStatusCast =
+ QQmlPrivate::StaticCastSelector<WrappedClass, QQmlParserStatus>::cast();
+ type->valueSourceCast =
+ QQmlPrivate::StaticCastSelector<WrappedClass, QQmlPropertyValueSource>::cast();
+ type->valueInterceptorCast =
+ QQmlPrivate::StaticCastSelector<WrappedClass, QQmlPropertyValueInterceptor>::cast();
+ return true;
}
-bool quickRegisterType(PyObject *pyObj, const char *uri, int versionMajor, int versionMinor,
- const char *qmlName, bool creatable, const char *noCreationReason, QQmlPrivate::RegisterType *type)
+bool quickRegisterType(PyObject *pyObj, QQmlPrivate::RegisterType *type)
{
using namespace Shiboken;
@@ -137,50 +85,12 @@ bool quickRegisterType(PyObject *pyObj, const char *uri, int versionMajor, int v
if (!isQuickItem)
return false;
- // Used inside macros to register the type.
- const QMetaObject *metaObject = PySide::retrieveMetaObject(pyObj);
- Q_ASSERT(metaObject);
-
-
- // Incref the type object, don't worry about decref'ing it because
- // there's no way to unregister a QML type.
- Py_INCREF(pyObj);
-
- // Used in macro registration.
- QByteArray pointerName(qmlName);
- pointerName.append('*');
- QByteArray listName(qmlName);
- listName.prepend("QQmlListProperty<");
- listName.append('>');
-
- bool registered = false;
- // Pass the size of the generated wrapper class since that is what is instantiated.
- registerTypeIfInheritsFromClass<QQuickPaintedItem>(
- "QQuickPaintedItem", pyObjType, pointerName, listName,
- metaObject, type, registered);
- registerTypeIfInheritsFromClass<QQuickFramebufferObject>(
- "QQuickFramebufferObject", pyObjType, pointerName, listName,
- metaObject, type, registered);
- registerTypeIfInheritsFromClass<QQuickItem>(
- "QQuickItem", pyObjType, pointerName, listName,
- metaObject, type, registered);
- if (!registered)
- return false;
-
- type->structVersion = 0;
- type->create = creatable ? createQuickItem : nullptr;
- type->noCreationReason = noCreationReason;
- type->userdata = pyObj;
- type->uri = uri;
- type->version = QTypeRevision::fromVersion(versionMajor, versionMinor);
- type->elementName = qmlName;
- type->metaObject = metaObject;
-
- type->extensionObjectCreate = 0;
- type->extensionMetaObject = 0;
- type->customParser = 0;
-
- return true;
+ return registerTypeIfInheritsFromClass<QQuickPaintedItem>("QQuickPaintedItem*",
+ pyObjType, type)
+ || registerTypeIfInheritsFromClass<QQuickFramebufferObject>("QQuickFramebufferObject*",
+ pyObjType, type)
+ || registerTypeIfInheritsFromClass<QQuickItem>("QQuickItem*",
+ pyObjType, type);
}
void PySide::initQuickSupport(PyObject *module)
diff --git a/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp b/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp
index 05a7bbffb..94b4897e1 100644
--- a/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp
+++ b/sources/pyside6/libpysideqml/pysideqmlregistertype.cpp
@@ -132,35 +132,30 @@ int qmlRegisterType(PyObject *pyObj, const char *uri, int versionMajor,
QQmlPrivate::RegisterType type;
// Allow registering Qt Quick items.
- bool registered = false;
- if (quickRegisterItemFunction) {
- registered =
- quickRegisterItemFunction(pyObj, uri, versionMajor, versionMinor,
- qmlName, creatable, noCreationReason, &type);
- }
+ const bool isQuickType = quickRegisterItemFunction && quickRegisterItemFunction(pyObj, &type);
// Register as simple QObject rather than Qt Quick item.
- if (!registered) {
- using QObjectQmlList = QQmlListProperty<QObject>;
- // 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;
-
- const QByteArray typeName(pyObjType->tp_name);
- QByteArray ptrType = typeName + '*';
- QByteArray listType = QByteArrayLiteral("QQmlListProperty<") + typeName + '>';
-
- type.typeId = QMetaType(new QQmlMetaTypeInterface(ptrType, static_cast<QObject **>(nullptr)));
- type.listId = QMetaType(new QQmlListMetaTypeInterface(listType,
- static_cast<QObjectQmlList*>(nullptr),
- type.typeId.iface()));
- const auto typeInfo = qmlTypeInfo(pyObj);
- auto info = qmlAttachedInfo(pyObjType, typeInfo);
- type.attachedPropertiesFunction = info.factory;
- type.attachedPropertiesMetaObject = info.metaObject;
+ using QObjectQmlList = QQmlListProperty<QObject>;
+ // 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;
+
+ const QByteArray typeName(pyObjType->tp_name);
+ QByteArray ptrType = typeName + '*';
+ QByteArray listType = QByteArrayLiteral("QQmlListProperty<") + typeName + '>';
+
+ type.typeId = QMetaType(new QQmlMetaTypeInterface(ptrType, static_cast<QObject **>(nullptr)));
+ type.listId = QMetaType(new QQmlListMetaTypeInterface(listType,
+ static_cast<QObjectQmlList*>(nullptr),
+ type.typeId.iface()));
+ const auto typeInfo = qmlTypeInfo(pyObj);
+ auto info = qmlAttachedInfo(pyObjType, typeInfo);
+ type.attachedPropertiesFunction = info.factory;
+ type.attachedPropertiesMetaObject = info.metaObject;
+ if (!isQuickType) { // values filled by the Quick registration
type.parserStatusCast =
QQmlPrivate::StaticCastSelector<QObject, QQmlParserStatus>::cast();
// QPyQmlPropertyValueSource inherits QObject, QmlPropertyValueSource, so,
@@ -172,22 +167,22 @@ int qmlRegisterType(PyObject *pyObj, const char *uri, int versionMajor,
: 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;
-
- info = qmlExtendedInfo(pyObj, typeInfo);
- type.extensionObjectCreate = info.factory;
- type.extensionMetaObject = info.metaObject;
- type.customParser = 0;
}
+
+ 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;
+
+ info = qmlExtendedInfo(pyObj, typeInfo);
+ type.extensionObjectCreate = info.factory;
+ type.extensionMetaObject = info.metaObject;
+ type.customParser = 0;
type.metaObject = metaObject; // Snapshot may have changed.
int qmlTypeId = QQmlPrivate::qmlregister(QQmlPrivate::TypeRegistration, &type);
diff --git a/sources/pyside6/libpysideqml/pysideqmlregistertype.h b/sources/pyside6/libpysideqml/pysideqmlregistertype.h
index d77a67bdb..e3da4ac31 100644
--- a/sources/pyside6/libpysideqml/pysideqmlregistertype.h
+++ b/sources/pyside6/libpysideqml/pysideqmlregistertype.h
@@ -113,12 +113,10 @@ PYSIDEQML_API PyObject *qmlAnonymousMacro(PyObject *pyObj);
PYSIDEQML_API PyObject *qmlSingletonMacro(PyObject *pyObj);
-// Used by QtQuick module to notify QtQml that custom QtQuick items can be registered.
+// Used by QtQuick module to fill the QQmlPrivate::RegisterType::parserStatusCast,
+// valueSourceCast and valueInterceptorCast fields with the correct values.
using QuickRegisterItemFunction =
- bool (*)(PyObject *pyObj, const char *uri, int versionMajor,
- int versionMinor, const char *qmlName,
- bool creatable, const char *noCreationReason,
- QQmlPrivate::RegisterType *);
+ bool (*)(PyObject *pyObj, QQmlPrivate::RegisterType *);
PYSIDEQML_API QuickRegisterItemFunction getQuickRegisterItemFunction();
PYSIDEQML_API void setQuickRegisterItemFunction(QuickRegisterItemFunction function);