diff options
Diffstat (limited to 'sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp')
-rw-r--r-- | sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp | 148 |
1 files changed, 53 insertions, 95 deletions
diff --git a/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp b/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp index a042ac2cc..acb733f73 100644 --- a/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp +++ b/sources/pyside2/PySide2/QtQuick/pysidequickregistertype.cpp @@ -51,56 +51,19 @@ #include "pyside2_qtquick_python.h" #include "pyside2_qtqml_python.h" -#ifndef PYSIDE_MAX_QUICK_TYPES -// Maximum number of different Qt Quick types the user can export to QML using -// qmlRegisterType. This limit exists because the QML engine instantiates objects -// by calling a function with one argument (a void* pointer where the object should -// be created), and thus does not allow us to choose which object to create. Thus -// we create a C++ factory function for each new registered type at compile time. -# define PYSIDE_MAX_QUICK_TYPES 50 -#endif // !PYSIDE_MAX_QUICK_TYPES - -// All registered python types and their creation functions. -static PyObject *pyTypes[PYSIDE_MAX_QUICK_TYPES]; -static void (*createFuncs[PYSIDE_MAX_QUICK_TYPES])(void *); - // Mutex used to avoid race condition on PySide::nextQObjectMemoryAddr. static QMutex nextQmlElementMutex; -// Python object factory functions. -template<int N> -struct ElementFactoryBase -{ - static void createQuickItem(void *memory) - { - QMutexLocker locker(&nextQmlElementMutex); - PySide::setNextQObjectMemoryAddr(memory); - Shiboken::GilState state; - PyObject *obj = PyObject_CallObject(pyTypes[N], 0); - if (!obj || PyErr_Occurred()) - PyErr_Print(); - PySide::setNextQObjectMemoryAddr(0); - } -}; - -template<int N> -struct ElementFactory : ElementFactoryBase<N> -{ - static void init() - { - createFuncs[N] = &ElementFactoryBase<N>::createQuickItem; - ElementFactory<N-1>::init(); - } -}; - -template<> -struct ElementFactory<0> : ElementFactoryBase<0> +static void createQuickItem(void *memory, void *type) { - static void init() - { - createFuncs[0] = &ElementFactoryBase<0>::createQuickItem; - } -}; + 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); +} #define PY_REGISTER_IF_INHERITS_FROM(className, typeToRegister,typePointerName, \ typeListName, typeMetaObject, type, registered) \ @@ -117,6 +80,40 @@ bool pyTypeObjectInheritsFromClass(PyTypeObject *pyObjType, QByteArray className return isDerived; } +template <typename T> +struct QPysideQmlMetaTypeInterface : QtPrivate::QMetaTypeInterface +{ + const QByteArray name; + + QPysideQmlMetaTypeInterface(const QByteArray &name, const QMetaObject *metaObject = nullptr) + : QMetaTypeInterface { + /*.revision=*/ 0, + /*.alignment=*/ alignof(T), + /*.size=*/ sizeof(T), + /*.flags=*/ QtPrivate::QMetaTypeTypeFlags<T>::Flags, + /*.typeId=*/ 0, + /*.metaObject=*/ metaObject, + /*.name=*/ name.constData(), + /*.defaultCtr=*/ [](const QMetaTypeInterface *, void *addr) { new (addr) T(); }, + /*.copyCtr=*/ [](const QMetaTypeInterface *, void *addr, const void *other) { + new (addr) T(*reinterpret_cast<const T *>(other)); + }, + /*.moveCtr=*/ [](const QMetaTypeInterface *, void *addr, void *other) { + new (addr) T(std::move(*reinterpret_cast<T *>(other))); + }, + /*.dtor=*/ [](const QMetaTypeInterface *, void *addr) { + reinterpret_cast<T *>(addr)->~T(); + }, + /*.equals=*/ nullptr, + /*.lessThan=*/ nullptr, + /*.debugStream=*/ nullptr, + /*.dataStreamOut=*/ nullptr, + /*.dataStreamIn=*/ nullptr, + /*.legacyRegisterOp=*/ nullptr + } + , name(name) {} +}; + template <class WrapperClass> void registerTypeIfInheritsFromClass( QByteArray className, @@ -129,40 +126,11 @@ void registerTypeIfInheritsFromClass( { bool shouldRegister = !registered && pyTypeObjectInheritsFromClass(typeToRegister, className); if (shouldRegister) { - int ptrType = - QMetaType::registerNormalizedType( - typePointerName.constData(), - QtMetaTypePrivate::QMetaTypeFunctionHelper<WrapperClass *>::Destruct, - QtMetaTypePrivate::QMetaTypeFunctionHelper<WrapperClass *>::Construct, - sizeof(WrapperClass *), - static_cast< ::QFlags<QMetaType::TypeFlag> >(QtPrivate::QMetaTypeTypeFlags< - WrapperClass *>::Flags), - typeMetaObject); - if (ptrType == -1) { - PyErr_Format(PyExc_TypeError, "Meta type registration of \"%s\" for QML usage failed.", - typePointerName.constData()); - return; - } + QMetaType ptrType(new QPysideQmlMetaTypeInterface<WrapperClass *>(typePointerName, typeMetaObject)); + QMetaType lstType(new QPysideQmlMetaTypeInterface<QQmlListProperty<WrapperClass>>(typeListName)); - int lstType = - QMetaType::registerNormalizedType( - typeListName.constData(), - QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<WrapperClass> > - ::Destruct, - QtMetaTypePrivate::QMetaTypeFunctionHelper<QQmlListProperty<WrapperClass> > - ::Construct, - sizeof(QQmlListProperty<WrapperClass>), - static_cast< ::QFlags<QMetaType::TypeFlag> >( - QtPrivate::QMetaTypeTypeFlags<QQmlListProperty<WrapperClass> >::Flags), - nullptr); - if (lstType == -1) { - PyErr_Format(PyExc_TypeError, "Meta type registration of \"%s\" for QML usage failed.", - typeListName.constData()); - return; - } - - type->typeId = ptrType; - type->listId = lstType; + type->typeId = std::move(ptrType); + type->listId = std::move(lstType); type->attachedPropertiesFunction = QQmlPrivate::attachedPropertiesFunc<WrapperClass>(); type->attachedPropertiesMetaObject = QQmlPrivate::attachedPropertiesMetaObject<WrapperClass>(); @@ -178,16 +146,9 @@ void registerTypeIfInheritsFromClass( } bool quickRegisterType(PyObject *pyObj, const char *uri, int versionMajor, int versionMinor, - const char *qmlName, QQmlPrivate::RegisterType *type) + const char *qmlName, bool creatable, const char *noCreationReason, QQmlPrivate::RegisterType *type) { using namespace Shiboken; - static int nextType = 0; - - if (nextType >= PYSIDE_MAX_QUICK_TYPES) { - PyErr_Format(PyExc_TypeError, - "You can only export %d Qt Quick types to QML.", PYSIDE_MAX_QUICK_TYPES); - return false; - } PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj); PyTypeObject *qQuickItemPyType = @@ -208,8 +169,6 @@ bool quickRegisterType(PyObject *pyObj, const char *uri, int versionMajor, int v // there's no way to unregister a QML type. Py_INCREF(pyObj); - pyTypes[nextType] = pyObj; - // Used in macro registration. QByteArray pointerName(qmlName); pointerName.append('*'); @@ -227,11 +186,12 @@ bool quickRegisterType(PyObject *pyObj, const char *uri, int versionMajor, int v if (!registered) return false; - type->create = createFuncs[nextType]; - type->version = 0; + type->structVersion = 0; + type->create = creatable ? createQuickItem : nullptr; + type->noCreationReason = noCreationReason; + type->userdata = pyObj; type->uri = uri; - type->versionMajor = versionMajor; - type->versionMinor = versionMinor; + type->version = QTypeRevision::fromVersion(versionMajor, versionMinor); type->elementName = qmlName; type->metaObject = metaObject; @@ -239,14 +199,12 @@ bool quickRegisterType(PyObject *pyObj, const char *uri, int versionMajor, int v type->extensionMetaObject = 0; type->customParser = 0; - ++nextType; return true; } void PySide::initQuickSupport(PyObject *module) { Q_UNUSED(module); - ElementFactory<PYSIDE_MAX_QUICK_TYPES - 1>::init(); #ifdef PYSIDE_QML_SUPPORT setQuickRegisterItemFunction(quickRegisterType); #endif |