diff options
Diffstat (limited to 'sources/pyside6/libpysideqml/pysideqmllistproperty.cpp')
| -rw-r--r-- | sources/pyside6/libpysideqml/pysideqmllistproperty.cpp | 134 |
1 files changed, 114 insertions, 20 deletions
diff --git a/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp b/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp index de3e6b501..fd2014a35 100644 --- a/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp +++ b/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp @@ -15,16 +15,27 @@ #include <sbktypefactory.h> #include <pysideproperty.h> -#include <pysideproperty_p.h> +#include <pysidepropertybase_p.h> #include <pysideqobject.h> #include <QtCore/qobject.h> #include <QtQml/qqmllist.h> +#include <utility> + +using namespace Qt::StringLiterals; + // This is the user data we store in the property. -class QmlListPropertyPrivate : public PySidePropertyPrivate, public QmlListPropertyMixin +class QmlListPropertyPrivate : public PySidePropertyBase, public QmlListPropertyMixin { public: + QmlListPropertyPrivate(const QmlListPropertyPrivate &) = delete; + QmlListPropertyPrivate& operator=(const QmlListPropertyPrivate &) = delete; + QmlListPropertyPrivate(QmlListPropertyPrivate &&) = delete; + QmlListPropertyPrivate& operator=(QmlListPropertyPrivate &&) = delete; + + QmlListPropertyPrivate() : PySidePropertyBase(Type::ListProperty) {} + void metaCall(PyObject *source, QMetaObject::Call call, void **args) override { handleMetaCall(source, call, args); } @@ -36,7 +47,11 @@ public: void replace(QQmlListProperty<QObject> *propList, qsizetype index, QObject *value) override; void removeLast(QQmlListProperty<QObject> *propList) override; - PyTypeObject *elementType = nullptr; + void tp_clear(); + int tp_traverse(visitproc visit, void *arg); + void incref(); + + PyObject *obElementType = nullptr; PyObject *obAppend = nullptr; PyObject *obCount = nullptr; PyObject *obAt = nullptr; @@ -45,6 +60,50 @@ public: PyObject *obRemoveLast = nullptr; }; +void QmlListPropertyPrivate::tp_clear() +{ + PySidePropertyBase::tp_clearBase(); + Py_CLEAR(obElementType); + Py_CLEAR(obAppend); + Py_CLEAR(obCount); + Py_CLEAR(obAt); + Py_CLEAR(obClear); + Py_CLEAR(obReplace); + Py_CLEAR(obRemoveLast); +} + +int QmlListPropertyPrivate::tp_traverse(visitproc visit, void *arg) +{ + Py_VISIT(obElementType); + Py_VISIT(obAppend); + Py_VISIT(obCount); + Py_VISIT(obAt); + Py_VISIT(obClear); + Py_VISIT(obReplace); + Py_VISIT(obRemoveLast); + return PySidePropertyBase::tp_traverseBase(visit, arg); +} + +void QmlListPropertyPrivate::incref() +{ + PySidePropertyBase::increfBase(); + Py_XINCREF(obElementType); + Py_XINCREF(obAppend); + Py_XINCREF(obCount); + Py_XINCREF(obAt); + Py_XINCREF(obClear); + Py_XINCREF(obReplace); + Py_XINCREF(obRemoveLast); +} + +static inline QmlListPropertyPrivate *qmlListProperty(PyObject *self) +{ + auto *data = reinterpret_cast<PySideProperty *>(self); + Q_ASSERT(data->d != nullptr); + Q_ASSERT(data->d->type() == PySidePropertyBase::Type::ListProperty); + return static_cast<QmlListPropertyPrivate *>(data->d); +} + extern "C" { @@ -75,7 +134,7 @@ static int propListTpInit(PyObject *self, PyObject *args, PyObject *kwds) if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOOOOOsObbbbbb:QtQml.ListProperty", const_cast<char **>(kwlist), - &data->elementType, + &data->obElementType, &append, &count, &at, &clear, &replace, &removeLast, /*s*/ &doc, /*O*/ ¬ify, // PySideProperty @@ -84,12 +143,12 @@ static int propListTpInit(PyObject *self, PyObject *args, PyObject *kwds) return -1; } - if (!PySidePropertyPrivate::assignCheckCallable(append, "append", &data->obAppend) - || !PySidePropertyPrivate::assignCheckCallable(count, "count", &data->obCount) - || !PySidePropertyPrivate::assignCheckCallable(at, "at", &data->obAt) - || !PySidePropertyPrivate::assignCheckCallable(clear, "clear", &data->obClear) - || !PySidePropertyPrivate::assignCheckCallable(replace, "replace", &data->obReplace) - || !PySidePropertyPrivate::assignCheckCallable(removeLast, "removeLast", &data->obRemoveLast)) { + if (!PySidePropertyBase::assignCheckCallable(append, "append", &data->obAppend) + || !PySidePropertyBase::assignCheckCallable(count, "count", &data->obCount) + || !PySidePropertyBase::assignCheckCallable(at, "at", &data->obAt) + || !PySidePropertyBase::assignCheckCallable(clear, "clear", &data->obClear) + || !PySidePropertyBase::assignCheckCallable(replace, "replace", &data->obReplace) + || !PySidePropertyBase::assignCheckCallable(removeLast, "removeLast", &data->obRemoveLast)) { return -1; } @@ -101,24 +160,22 @@ static int propListTpInit(PyObject *self, PyObject *args, PyObject *kwds) data->setMethodFlag(QmlListPropertyMixin::MethodFlag::RemoveLast, data->obRemoveLast != nullptr); if (notify != nullptr && notify != Py_None) - data->notify = notify; + data->setNotify(notify); - if (doc) - data->doc = doc; - else - data->doc.clear(); + data->setDoc(doc != nullptr ? QByteArray(doc) : QByteArray{}); PyTypeObject *qobjectType = PySide::qObjectType(); - if (!PySequence_Contains(data->elementType->tp_mro, reinterpret_cast<PyObject *>(qobjectType))) { + auto *elementType = reinterpret_cast<PyTypeObject *>(data->obElementType); + if (!PySequence_Contains(elementType->tp_mro, reinterpret_cast<PyObject *>(qobjectType))) { PyErr_Format(PyExc_TypeError, "A type inherited from %s expected, got %s.", - qobjectType->tp_name, data->elementType->tp_name); + qobjectType->tp_name, elementType->tp_name); return -1; } - data->typeName = QByteArrayLiteral("QQmlListProperty<QObject>"); + data->setTypeName("QQmlListProperty<QObject>"_ba); - auto &flags = data->flags; + PySide::Property::PropertyFlags flags; flags.setFlag(PySide::Property::PropertyFlag::Readable, true); flags.setFlag(PySide::Property::PropertyFlag::Designable, designable); flags.setFlag(PySide::Property::PropertyFlag::Scriptable, scriptable); @@ -126,15 +183,51 @@ static int propListTpInit(PyObject *self, PyObject *args, PyObject *kwds) flags.setFlag(PySide::Property::PropertyFlag::User, user); flags.setFlag(PySide::Property::PropertyFlag::Constant, constant); flags.setFlag(PySide::Property::PropertyFlag::Final, finalProp); + data->setFlags(flags); + + data->incref(); return 0; } +static int tp_propListTraverse(PyObject *self, visitproc visit, void *arg) +{ + auto *pData = qmlListProperty(self); + return pData != nullptr ? pData->tp_traverse(visit, arg) : 0; +} + +static int tp_propListClear(PyObject *self) +{ + auto *data = reinterpret_cast<PySideProperty *>(self); + if (data->d == nullptr) + return 0; + + auto *baseData = std::exchange(data->d, nullptr); + Q_ASSERT(baseData->type() == PySidePropertyBase::Type::ListProperty); + static_cast<QmlListPropertyPrivate *>(baseData)->tp_clear(); + delete baseData; + return 0; +} + +static void tp_propListDeAlloc(PyObject *self) +{ + tp_propListClear(self); + // PYSIDE-939: Handling references correctly. + // This was not needed before Python 3.8 (Python issue 35810) + Py_DECREF(Py_TYPE(self)); + PyObject_GC_UnTrack(self); + PepExt_TypeCallFree(self); +} + static PyTypeObject *createPropertyListType() { PyType_Slot PropertyListType_slots[] = { {Py_tp_new, reinterpret_cast<void *>(propList_tp_new)}, {Py_tp_init, reinterpret_cast<void *>(propListTpInit)}, + {Py_tp_dealloc, reinterpret_cast<void *>(tp_propListDeAlloc)}, + {Py_tp_traverse, reinterpret_cast<void *>(tp_propListTraverse)}, + {Py_tp_clear, reinterpret_cast<void *>(tp_propListClear)}, + {Py_tp_del, reinterpret_cast<void *>(PyObject_GC_Del)}, {0, nullptr} }; @@ -142,7 +235,7 @@ static PyTypeObject *createPropertyListType() "2:PySide6.QtQml.ListProperty", sizeof(PySideProperty), 0, - Py_TPFLAGS_DEFAULT, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, PropertyListType_slots, }; @@ -219,6 +312,7 @@ QObject *QmlListPropertyPrivate::at(QQmlListProperty<QObject> *propList, qsizety Shiboken::AutoDecRef retVal(PyObject_CallObject(obAt, args)); QObject *result = nullptr; + auto *elementType = reinterpret_cast<PyTypeObject *>(obElementType); if (PyErr_Occurred()) PyErr_Print(); else if (PyType_IsSubtype(Py_TYPE(retVal), elementType)) |
