aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2022-01-06 14:12:58 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2022-01-06 21:34:30 +0100
commitf823a41e7bf75957ea74b9545bc95c30317d84f1 (patch)
treed5611f52f75d115adb76d9692e089b574222906e
parent683314b3491dea17f0205baa2976e71595ccb05d (diff)
Add a __repr__ function for QMetaObject
This is helpful for QML debugging. Task-number: PYSIDE-1709 Change-Id: If9baeb5a52999c4718e951f0ea5736783a9fcbff Reviewed-by: Christian Tismer <tismer@stackless.com>
-rw-r--r--sources/pyside6/PySide6/QtCore/typesystem_core_common.xml4
-rw-r--r--sources/pyside6/PySide6/glue/qtcore.cpp5
-rw-r--r--sources/pyside6/libpyside/dynamicqmetaobject.cpp101
-rw-r--r--sources/pyside6/libpyside/dynamicqmetaobject.h3
4 files changed, 113 insertions, 0 deletions
diff --git a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
index 2e4308cf1..b3651288e 100644
--- a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
+++ b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml
@@ -2894,6 +2894,7 @@
<object-type name="QMetaObject">
<enum-type name="Call"/>
<include file-name="qobjectdefs.h" location="global"/>
+ <include file-name="dynamicqmetaobject.h" location="global"/>
<!-- This isn't part of Qt public API -->
<modify-function signature="connect(const QObject*,int,const QObject*,int,int,int*)" remove="all"/>
<value-type name="Connection" operator-bool="true">
@@ -2902,6 +2903,9 @@
<declare-function signature="operator bool() const" return-type="bool"/>
</value-type>
<modify-function signature="^invokeMethod\(" allow-thread="yes"/>
+ <add-function signature="__repr__" return-type="PyObject*">
+ <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qmetaobject-repr"/>
+ </add-function>
</object-type>
<value-type name="QMetaProperty" >
<!-- This isn't part of Qt public API -->
diff --git a/sources/pyside6/PySide6/glue/qtcore.cpp b/sources/pyside6/PySide6/glue/qtcore.cpp
index 4a25e435a..85d30053f 100644
--- a/sources/pyside6/PySide6/glue/qtcore.cpp
+++ b/sources/pyside6/PySide6/glue/qtcore.cpp
@@ -863,6 +863,11 @@ QByteArray ba(1 + qsizetype(%2), char(0));
%CPPSELF.%FUNCTION_NAME(Shiboken::String::toCString(%PYARG_1), Shiboken::String::len(%PYARG_1));
// @snippet qcryptographichash-adddata
+// @snippet qmetaobject-repr
+const QByteArray repr = PySide::MetaObjectBuilder::formatMetaObject(%CPPSELF).toUtf8();
+%PYARG_0 = PyUnicode_FromString(repr.constData());
+// @snippet qmetaobject-repr
+
// @snippet qsocketdescriptor
#ifdef WIN32
using DescriptorType = Qt::HANDLE;
diff --git a/sources/pyside6/libpyside/dynamicqmetaobject.cpp b/sources/pyside6/libpyside/dynamicqmetaobject.cpp
index 90090018f..f1d07fc15 100644
--- a/sources/pyside6/libpyside/dynamicqmetaobject.cpp
+++ b/sources/pyside6/libpyside/dynamicqmetaobject.cpp
@@ -456,6 +456,107 @@ const QMetaObject *MetaObjectBuilder::update()
return m_d->update();
}
+static void formatEnum(QTextStream &str, const QMetaEnum &e)
+{
+ str << '"' << e.name() << "\" {";
+ for (int k = 0, cnt = e.keyCount(); k < cnt; ++k) {
+ if (k)
+ str << ", ";
+ str << e.key(k);
+ }
+ str << "}";
+}
+
+static void formatProperty(QTextStream &str, const QMetaProperty &p)
+{
+ str << '"' << p.name() << "\", " << p.typeName();
+ if (p.isWritable())
+ str << " [writeable]";
+ if (p.isResettable())
+ str << " [resettable]";
+ if (p.isConstant())
+ str << " [constant]";
+ if (p.isFinal())
+ str << " [final]";
+ if (p.isDesignable())
+ str << " [designable]";
+ auto sig = p.notifySignal();
+ if (sig.isValid())
+ str << ", notify=" << sig.name();
+}
+
+static void formatMethod(QTextStream &str, const QMetaMethod &m)
+{
+ str << "type=";
+ switch (m.methodType()) {
+ case QMetaMethod::Method:
+ str << "Method";
+ break;
+ case QMetaMethod::Signal:
+ str << "Signal";
+ break;
+ case QMetaMethod::Slot:
+ str << "Slot";
+ break;
+ case QMetaMethod::Constructor:
+ str << "Constructor";
+ break;
+ }
+
+ str << ", signature="
+ << m.methodSignature();
+ const QByteArrayList parms = m.parameterTypes();
+ if (!parms.isEmpty())
+ str << ", parameters=" << parms.join(", ");
+}
+
+QString MetaObjectBuilder::formatMetaObject(const QMetaObject *metaObject)
+{
+ QString result;
+ QTextStream str(&result);
+ str << "PySide" << QT_VERSION_MAJOR << ".QtCore.QMetaObject(\""
+ << metaObject->className() << '"';
+ if (auto *s = metaObject->superClass())
+ str << " inherits \"" << s->className() << '"';
+ str << ":\n";
+
+ int offset = metaObject->enumeratorOffset();
+ int count = metaObject->enumeratorCount();
+ if (offset < count) {
+ str << "Enumerators:\n";
+ for (int e = offset; e < count; ++e) {
+ str << " #" << e << ' ';
+ formatEnum(str, metaObject->enumerator(e));
+ str << '\n';
+ }
+ }
+
+ offset = metaObject->propertyOffset();
+ count = metaObject->propertyCount();
+ if (offset < count) {
+ str << "Properties:\n";
+ for (int p = offset; p < count; ++p) {
+ str << " #" << p << ' ';
+ formatProperty(str, metaObject->property(p));
+ str << '\n';
+ }
+ }
+
+ offset = metaObject->methodOffset();
+ count = metaObject->methodCount();
+ if (offset < count) {
+ str << "Methods:\n";
+ for (int m = offset; m < count; ++m) {
+ str << " #" << m << ' ';
+ formatMethod(str, metaObject->method(m));
+ str << '\n';
+ }
+ }
+
+ str << ')';
+ return result;
+}
+
using namespace Shiboken;
void MetaObjectBuilderPrivate::parsePythonType(PyTypeObject *type)
diff --git a/sources/pyside6/libpyside/dynamicqmetaobject.h b/sources/pyside6/libpyside/dynamicqmetaobject.h
index 6e7a079a3..a5366c919 100644
--- a/sources/pyside6/libpyside/dynamicqmetaobject.h
+++ b/sources/pyside6/libpyside/dynamicqmetaobject.h
@@ -41,6 +41,7 @@
#define DYNAMICQMETAOBJECT_H
#include <sbkpython.h>
+#include <pysidemacros.h>
#include <QtCore/QMetaObject>
#include <QtCore/QMetaMethod>
@@ -77,6 +78,8 @@ public:
const QMetaObject *update();
+ PYSIDE_API static QString formatMetaObject(const QMetaObject *metaObject);
+
private:
MetaObjectBuilderPrivate *m_d;
};