aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/libpysideqml/pysideqmllistproperty.cpp')
-rw-r--r--sources/pyside6/libpysideqml/pysideqmllistproperty.cpp307
1 files changed, 307 insertions, 0 deletions
diff --git a/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp b/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp
new file mode 100644
index 000000000..75bb5af96
--- /dev/null
+++ b/sources/pyside6/libpysideqml/pysideqmllistproperty.cpp
@@ -0,0 +1,307 @@
+// Copyright (C) 2021 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "pysideqmllistproperty_p.h"
+#include "pysideqmlregistertype_p.h"
+
+#include <shiboken.h>
+#include <pep384ext.h>
+#include <signature.h>
+
+#include <pysideproperty.h>
+#include <pysideproperty_p.h>
+
+#include <QtCore/QObject>
+#include <QtQml/QQmlListProperty>
+
+// This is the user data we store in the property.
+class QmlListPropertyPrivate : public PySidePropertyPrivate
+{
+public:
+ void metaCall(PyObject *source, QMetaObject::Call call, void **args) override;
+
+ PyTypeObject *type = nullptr;
+ PyObject *append = nullptr;
+ PyObject *count = nullptr;
+ PyObject *at = nullptr;
+ PyObject *clear = nullptr;
+ PyObject *replace = nullptr;
+ PyObject *removeLast = nullptr;
+};
+
+extern "C"
+{
+
+static PyObject *propList_tp_new(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */)
+{
+ auto *me = PepExt_TypeCallAlloc<PySideProperty>(subtype, 0);
+ me->d = new QmlListPropertyPrivate;
+ return reinterpret_cast<PyObject *>(me);
+}
+
+static int propListTpInit(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ static const char *kwlist[] = {"type", "append", "count", "at", "clear",
+ "replace", "removeLast",
+ "doc", "notify", // PySideProperty
+ "designable", "scriptable", "stored",
+ "user", "constant", "final",
+ nullptr};
+ PySideProperty *pySelf = reinterpret_cast<PySideProperty *>(self);
+
+ auto *data = static_cast<QmlListPropertyPrivate *>(pySelf->d);
+
+ char *doc{};
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds,
+ "O|OOOOOOsObbbbbb:QtQml.ListProperty",
+ const_cast<char **>(kwlist),
+ &data->type,
+ &data->append,
+ &data->count,
+ &data->at,
+ &data->clear,
+ &data->replace,
+ &data->removeLast,
+ /*s*/ &doc,
+ /*O*/ &(data->notify), // PySideProperty
+ /*bbb*/ &(data->designable),
+ &(data->scriptable),
+ &(data->stored),
+ /*bbb*/ &(data->user),
+ &(data->constant),
+ &(data->final))) {
+ return -1;
+ }
+
+ if (doc)
+ data->doc = doc;
+ else
+ data->doc.clear();
+
+ 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);
+ 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");
+ return -1;
+ }
+
+ data->typeName = QByteArrayLiteral("QQmlListProperty<QObject>");
+
+ return 0;
+}
+
+static PyTypeObject *createPropertyListType()
+{
+ PyType_Slot PropertyListType_slots[] = {
+ {Py_tp_new, reinterpret_cast<void *>(propList_tp_new)},
+ {Py_tp_init, reinterpret_cast<void *>(propListTpInit)},
+ {0, nullptr}
+ };
+
+ PyType_Spec PropertyListType_spec = {
+ "2:PySide6.QtQml.ListProperty",
+ sizeof(PySideProperty),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PropertyListType_slots,
+ };
+
+ Shiboken::AutoDecRef bases(Py_BuildValue("(O)", PySideProperty_TypeF()));
+ return SbkType_FromSpecWithBases(&PropertyListType_spec, bases.object());
+}
+
+PyTypeObject *PropertyList_TypeF(void)
+{
+ // PYSIDE-2230: This was a wrong replacement by static AutoDecref.
+ // Never do that, deletes things way too late.
+ static PyTypeObject *type = createPropertyListType();
+ 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<QmlListPropertyPrivate *>(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<QmlListPropertyPrivate *>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->count, args));
+
+ // Check return type
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ return 0;
+ }
+
+ qsizetype 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<QmlListPropertyPrivate *>(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<QmlListPropertyPrivate *>(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<QmlListPropertyPrivate *>(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<QmlListPropertyPrivate *>(propList->data);
+ Shiboken::AutoDecRef retVal(PyObject_CallObject(data->removeLast, args));
+
+ if (PyErr_Occurred())
+ PyErr_Print();
+}
+
+// qt_metacall specialization for ListProperties
+void QmlListPropertyPrivate::metaCall(PyObject *source, QMetaObject::Call call, void **args)
+{
+ if (call != QMetaObject::ReadProperty)
+ return;
+
+ QObject *qobj;
+ PyTypeObject *qobjectType = qObjectType();
+ Shiboken::Conversions::pythonToCppPointer(qobjectType, source, &qobj);
+ QQmlListProperty<QObject> declProp(
+ qobj, this,
+ append && append != Py_None ? &propListAppender : nullptr,
+ count && count != Py_None ? &propListCount : nullptr,
+ at && at != Py_None ? &propListAt : nullptr,
+ clear && clear != Py_None ? &propListClear : nullptr,
+ replace && replace != Py_None ? &propListReplace : nullptr,
+ removeLast && 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
+};
+
+namespace PySide::Qml {
+
+void initQtQmlListProperty(PyObject *module)
+{
+ // Export QmlListProperty type
+ if (InitSignatureStrings(PropertyList_TypeF(), 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 *>(PropertyList_TypeF()));
+ PyModule_AddObject(module, PepType_GetNameStr(PropertyList_TypeF()),
+ reinterpret_cast<PyObject *>(PropertyList_TypeF()));
+}
+
+} // namespace PySide::Qml