diff options
author | Maximilian Goldstein <max.goldstein@qt.io> | 2020-08-27 15:45:56 +0200 |
---|---|---|
committer | Maximilian Goldstein <max.goldstein@qt.io> | 2020-10-22 11:53:25 +0000 |
commit | 7c448f5c27a51a60e27a54b79e298b53312ef2a8 (patch) | |
tree | 8b3175f6bb84c9a2868d50905ffd25ac7f85f0ab /sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp | |
parent | 9614cb5e47e863f036f19ac3f818253dd69bb828 (diff) |
QtQml: Implement QmlElement
Equivalent to QML_ELEMENT in C++, this enables users to register classes
for use in QML by using the QmlElement decorator.
Change-Id: I697e486ef58b18cce4c310e4b556e28735a16d45
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
Diffstat (limited to 'sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp')
-rw-r--r-- | sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp index fd470cd71..3a3c0d27e 100644 --- a/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp +++ b/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp @@ -39,6 +39,8 @@ #include "pysideqmlregistertype.h" +#include <limits> + // shiboken #include <shiboken.h> #include <signature.h> @@ -649,3 +651,82 @@ void PySide::initQmlSupport(PyObject *module) PyModule_AddObject(module, PepType_GetNameStr(QtQml_VolatileBoolTypeF()), reinterpret_cast<PyObject *>(QtQml_VolatileBoolTypeF())); } + +static std::string getGlobalString(const char *name) +{ + using Shiboken::AutoDecRef; + + PyObject *globals = PyEval_GetGlobals(); + + AutoDecRef pyName(Py_BuildValue("s", name)); + + PyObject *globalVar = PyDict_GetItem(globals, pyName); + + if (globalVar == nullptr || !PyUnicode_Check(globalVar)) + return ""; + + const char *stringValue = PyUnicode_AsUTF8(globalVar); + return stringValue != nullptr ? stringValue : ""; +} + +static int getGlobalInt(const char *name) +{ + using Shiboken::AutoDecRef; + + PyObject *globals = PyEval_GetGlobals(); + + AutoDecRef pyName(Py_BuildValue("s", name)); + + PyObject *globalVar = PyDict_GetItem(globals, pyName); + + if (globalVar == nullptr || !PyLong_Check(globalVar)) + return -1; + + long value = PyLong_AsLong(globalVar); + + if (value > std::numeric_limits<int>::max() || value < std::numeric_limits<int>::min()) + return -1; + + return value; +} + +PyObject *PySide::qmlElementMacro(PyObject *pyObj) +{ + if (!PyType_Check(pyObj)) { + PyErr_Format(PyExc_TypeError, "This decorator can only be used on classes."); + return nullptr; + } + + static PyTypeObject *qobjectType = Shiboken::Conversions::getPythonTypeObject("QObject*"); + assert(qobjectType); + + PyTypeObject *pyObjType = reinterpret_cast<PyTypeObject *>(pyObj); + if (!PySequence_Contains(pyObjType->tp_mro, reinterpret_cast<PyObject *>(qobjectType))) { + PyErr_Format(PyExc_TypeError, "This decorator can only be used with classes inherited from QObject, got %s.", pyObjType->tp_name); + return nullptr; + } + + std::string importName = getGlobalString("QML_IMPORT_NAME"); + int majorVersion = getGlobalInt("QML_IMPORT_MAJOR_VERSION"); + int minorVersion = getGlobalInt("QML_IMPORT_MINOR_VERSION"); + + if (importName.empty()) { + PyErr_Format(PyExc_TypeError, "You need specify QML_IMPORT_NAME in order to use QmlElement."); + return nullptr; + } + + if (majorVersion == -1) { + PyErr_Format(PyExc_TypeError, "You need specify QML_IMPORT_MAJOR_VERSION in order to use QmlElement."); + return nullptr; + } + + // Specifying a minor version is optional + if (minorVersion == -1) + minorVersion = 0; + + if (qmlRegisterType(pyObj, importName.c_str(), majorVersion, minorVersion, pyObjType->tp_name) == -1) { + PyErr_Format(PyExc_TypeError, "Failed to register type %s.", pyObjType->tp_name); + } + + return pyObj; +} |