diff options
| author | Brett Stottlemyer <bstottle@ford.com> | 2024-12-18 10:33:56 -0500 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2025-03-13 16:28:42 +0100 |
| commit | 19abd816e73bebdd489408d0a3b7676822bff39c (patch) | |
| tree | 8459ae9401f5e190995b3e24b6ae6968cf457baf /sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h | |
| parent | 3c66c456aeab597b7cb046f81c7f015433bb57a4 (diff) | |
Make Remote Objects usable beyond Models
While present, the Qt Remote Objects bindings to Python have not been
very useful. The only usable components were those based on
QAbstractItemModel, due to the lack of a way to interpret .rep files
from Python. This addresses that limitation.
Fixes: PYSIDE-862
Change-Id: Ice57c0c64f11c3c7e74d50ce3c48617bd9b422a3
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Reviewed-by: Brett Stottlemyer <brett.stottlemyer@gmail.com>
Diffstat (limited to 'sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h')
| -rw-r--r-- | sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h b/sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h new file mode 100644 index 000000000..1e9f8d55a --- /dev/null +++ b/sources/pyside6/libpysideremoteobjects/pysidedynamiccommon_p.h @@ -0,0 +1,89 @@ +// Copyright (C) 2025 Ford Motor Company +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef PYSIDE_DYNAMIC_COMMON_P_H +#define PYSIDE_DYNAMIC_COMMON_P_H + +#include <sbkconverter.h> + +#include <QtCore/qlist.h> +#include <QtCore/qvariant.h> +#include <QtCore/qmetatype.h> + +PyObject *toPython(const QVariant &variant); +int create_managed_py_enums(PyObject *self, QMetaObject *meta); +PyObject *DynamicType_get_enum(PyObject *self, PyObject *name); + +// Data for dynamically created property handlers +struct PropertyCapsule +{ + QByteArray name; + int propertyIndex; // meta->indexOfProperty() - including offset + int indexInObject; // Index minus offset for indexing into QVariantList +}; + +// Data for dynamically created method handlers +struct MethodCapsule +{ + QByteArray name; + int methodIndex; + QList<QMetaType> argumentTypes; + QMetaType returnType; // meta->indexOfMethod() - including offset +}; + +// These functions are used to create a PyCapsule holding a pointer to a C++ +// object, which is set as an attribute on a Python type. When the Python +// type is garbage collected, the type's attributes are as well, resulting in +// the capsule's cleanup running to delete the pointer. This won't be as +// efficient as a custom tp_free on the type, but it's easier to manage. +// And it only runs when as all references to the type (and all instances) are +// released, so it won't be used frequently. + +static int capsule_count = 0; + +static PyObject *get_capsule_count() +{ + return PyLong_FromLong(capsule_count); +} + +template <typename T> +void Capsule_destructor(PyObject *capsule) +{ + capsule_count--; + T pointer = static_cast<T>(PyCapsule_GetPointer(capsule, nullptr)); + delete pointer; + pointer = nullptr; +} + +template <> +inline void Capsule_destructor<SbkConverter *>(PyObject *capsule) +{ + capsule_count--; + SbkConverter *pointer = static_cast<SbkConverter *>(PyCapsule_GetPointer(capsule, nullptr)); + Shiboken::Conversions::deleteConverter(pointer); + pointer = nullptr; +} + +template <typename T> +int set_cleanup_capsule_attr_for_pointer(PyTypeObject *type, const char *name, T pointer) +{ + static_assert(std::is_pointer<T>::value, "T must be a pointer type"); + + if (!pointer) { + PyErr_SetString(PyExc_RuntimeError, "Pointer is null"); + return -1; + } + auto capsule = PyCapsule_New(pointer, nullptr, Capsule_destructor<T>); + if (!capsule) + return -1; // Propagate the error + + if (PyObject_SetAttrString(reinterpret_cast<PyObject *>(type), name, capsule) < 0) + return -1; // Propagate the error + + Py_DECREF(capsule); + capsule_count++; + + return 0; +} + +#endif // PYSIDE_DYNAMIC_COMMON_P_H |
