aboutsummaryrefslogtreecommitdiffstats
path: root/sources/pyside6/libpyside/pysideclassinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'sources/pyside6/libpyside/pysideclassinfo.cpp')
-rw-r--r--sources/pyside6/libpyside/pysideclassinfo.cpp207
1 files changed, 207 insertions, 0 deletions
diff --git a/sources/pyside6/libpyside/pysideclassinfo.cpp b/sources/pyside6/libpyside/pysideclassinfo.cpp
new file mode 100644
index 000000000..67334f2f4
--- /dev/null
+++ b/sources/pyside6/libpyside/pysideclassinfo.cpp
@@ -0,0 +1,207 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt for Python.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <sbkpython.h>
+
+#include "pysideclassinfo.h"
+#include "pyside_p.h"
+#include "pysideclassinfo_p.h"
+#include "dynamicqmetaobject.h"
+
+#include <shiboken.h>
+#include <signature.h>
+
+extern "C"
+{
+
+static PyObject *classInfoTpNew(PyTypeObject *subtype, PyObject *args, PyObject *kwds);
+static int classInfoTpInit(PyObject *, PyObject *, PyObject *);
+static void classInfoFree(void *);
+static PyObject *classCall(PyObject *, PyObject *, PyObject *);
+
+static PyType_Slot PySideClassInfoType_slots[] = {
+ {Py_tp_call, (void *)classCall},
+ {Py_tp_init, (void *)classInfoTpInit},
+ {Py_tp_new, (void *)classInfoTpNew},
+ {Py_tp_free, (void *)classInfoFree},
+ {Py_tp_dealloc, (void *)Sbk_object_dealloc},
+ {0, 0}
+};
+static PyType_Spec PySideClassInfoType_spec = {
+ "2:PySide6.QtCore.ClassInfo",
+ sizeof(PySideClassInfo),
+ 0,
+ Py_TPFLAGS_DEFAULT,
+ PySideClassInfoType_slots,
+};
+
+
+PyTypeObject *PySideClassInfoTypeF(void)
+{
+ static PyTypeObject *type =
+ reinterpret_cast<PyTypeObject *>(SbkType_FromSpec(&PySideClassInfoType_spec));
+ return type;
+}
+
+PyObject *classCall(PyObject *self, PyObject *args, PyObject * /* kw */)
+{
+ if (!PyTuple_Check(args) || PyTuple_Size(args) != 1) {
+ PyErr_Format(PyExc_TypeError,
+ "The ClassInfo decorator takes exactly 1 positional argument (%zd given)",
+ PyTuple_Size(args));
+ return 0;
+ }
+
+ PySideClassInfo *data = reinterpret_cast<PySideClassInfo *>(self);
+ PySideClassInfoPrivate *pData = data->d;
+
+ if (pData->m_alreadyWrapped) {
+ PyErr_SetString(PyExc_TypeError, "This instance of ClassInfo() was already used to wrap an object");
+ return 0;
+ }
+
+ PyObject *klass = PyTuple_GetItem(args, 0);
+ bool validClass = false;
+
+ // This will sometimes segfault if you mistakenly use it on a function declaration
+ if (!PyType_Check(klass)) {
+ PyErr_SetString(PyExc_TypeError, "This decorator can only be used on class declarations");
+ return 0;
+ }
+
+ PyTypeObject *klassType = reinterpret_cast<PyTypeObject *>(klass);
+ if (Shiboken::ObjectType::checkType(klassType)) {
+ if (auto userData = PySide::retrieveTypeUserData(klassType)) {
+ PySide::MetaObjectBuilder &mo = userData->mo;
+ mo.addInfo(PySide::ClassInfo::getMap(data));
+ pData->m_alreadyWrapped = true;
+ validClass = true;
+ }
+ }
+
+ if (!validClass) {
+ PyErr_SetString(PyExc_TypeError, "This decorator can only be used on classes that are subclasses of QObject");
+ return 0;
+ }
+
+ Py_INCREF(klass);
+ return klass;
+}
+
+static PyObject *classInfoTpNew(PyTypeObject *subtype, PyObject * /* args */, PyObject * /* kwds */)
+{
+ PySideClassInfo *me = reinterpret_cast<PySideClassInfo *>(subtype->tp_alloc(subtype, 0));
+ me->d = new PySideClassInfoPrivate;
+
+ me->d->m_alreadyWrapped = false;
+
+ return reinterpret_cast<PyObject *>(me);
+}
+
+int classInfoTpInit(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ if (PyTuple_Check(args) && PyTuple_Size(args) > 0) {
+ PyErr_Format(PyExc_TypeError, "ClassInfo() takes exactly 0 positional arguments (%zd given)", PyTuple_Size(args));
+ return -1;
+ }
+
+ PySideClassInfo *data = reinterpret_cast<PySideClassInfo *>(self);
+ PySideClassInfoPrivate *pData = data->d;
+
+ PyObject *key;
+ PyObject *value;
+ Py_ssize_t pos = 0;
+
+ // PyDict_Next causes a segfault if kwds is empty
+ if (kwds && PyDict_Check(kwds) && PyDict_Size(kwds) > 0) {
+ while (PyDict_Next(kwds, &pos, &key, &value)) {
+ if (Shiboken::String::check(key) && Shiboken::String::check(value)) {
+ pData->m_data[Shiboken::String::toCString(key)] = Shiboken::String::toCString(value);
+ } else {
+ PyErr_SetString(PyExc_TypeError, "All keys and values provided to ClassInfo() must be strings");
+ return -1;
+ }
+ }
+ }
+
+ return PyErr_Occurred() ? -1 : 0;
+}
+
+void classInfoFree(void *self)
+{
+ auto pySelf = reinterpret_cast<PyObject *>(self);
+ auto data = reinterpret_cast<PySideClassInfo *>(self);
+
+ delete data->d;
+ Py_TYPE(pySelf)->tp_base->tp_free(self);
+}
+
+
+} // extern "C"
+
+
+namespace PySide { namespace ClassInfo {
+
+static const char *ClassInfo_SignatureStrings[] = {
+ "PySide6.QtCore.ClassInfo(**info:typing.Dict[str,str])",
+ nullptr}; // Sentinel
+
+void init(PyObject *module)
+{
+ if (InitSignatureStrings(PySideClassInfoTypeF(), ClassInfo_SignatureStrings) < 0)
+ return;
+
+ Py_INCREF(PySideClassInfoTypeF());
+ PyModule_AddObject(module, "ClassInfo", reinterpret_cast<PyObject *>(PySideClassInfoTypeF()));
+}
+
+bool checkType(PyObject *pyObj)
+{
+ if (pyObj)
+ return PyType_IsSubtype(Py_TYPE(pyObj), PySideClassInfoTypeF());
+ return false;
+}
+
+QMap<QByteArray, QByteArray> getMap(PySideClassInfo *obj)
+{
+ return obj->d->m_data;
+}
+
+} //namespace Property
+} //namespace PySide