aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp
diff options
context:
space:
mode:
authorMaximilian Goldstein <max.goldstein@qt.io>2020-08-27 15:45:56 +0200
committerMaximilian Goldstein <max.goldstein@qt.io>2020-10-22 11:53:25 +0000
commit7c448f5c27a51a60e27a54b79e298b53312ef2a8 (patch)
tree8b3175f6bb84c9a2868d50905ffd25ac7f85f0ab /sources/pyside2/PySide2/QtQml/pysideqmlregistertype.cpp
parent9614cb5e47e863f036f19ac3f818253dd69bb828 (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.cpp81
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;
+}