diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-08-16 13:15:30 +0200 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-08-26 12:09:26 +0200 |
| commit | bd6a2f1f880effb95ea3e42f52d06f0730103a03 (patch) | |
| tree | 3317a73a350c328e5e2a0ed8fb0524eb0370359e | |
| parent | 9ab2d9ccdea6dbb60234d203ed921db89144d2e1 (diff) | |
Add a logging category to libpyside
It provides:
- Debug output for Qt meta calls (useful for debugging QML
applications).
- Warnings, for example about dynamic slot registration caused
by missing decorators.
It can be enabled for example by
export QT_LOGGING_RULES="qt.pyside.libpyside.warning=true".
[ChangeLog][PySide6] A logging category "qt.pyside.libpyside"
with warnings has been added to libpyside.
Task-number: PYSIDE-2033
Change-Id: Ie972b85b8e92d2f3e2cf00efbc1047a178d95241
Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
| -rw-r--r-- | sources/pyside6/libpyside/pyside.cpp | 3 | ||||
| -rw-r--r-- | sources/pyside6/libpyside/pysidelogging_p.h | 11 | ||||
| -rw-r--r-- | sources/pyside6/libpyside/signalmanager.cpp | 88 |
3 files changed, 102 insertions, 0 deletions
diff --git a/sources/pyside6/libpyside/pyside.cpp b/sources/pyside6/libpyside/pyside.cpp index b2f03b210..4336f4970 100644 --- a/sources/pyside6/libpyside/pyside.cpp +++ b/sources/pyside6/libpyside/pyside.cpp @@ -22,6 +22,7 @@ #include "pysidemetafunction.h" #include "dynamicqmetaobject.h" #include "feature_select.h" +#include "pysidelogging_p.h" #include <autodecref.h> #include <basewrapper.h> @@ -53,6 +54,8 @@ extern bool qRegisterResourceData(int, const unsigned char *, const unsigned cha const unsigned char *); QT_END_NAMESPACE +Q_LOGGING_CATEGORY(lcPySide, "qt.pyside.libpyside", QtCriticalMsg) + namespace PySide { diff --git a/sources/pyside6/libpyside/pysidelogging_p.h b/sources/pyside6/libpyside/pysidelogging_p.h new file mode 100644 index 000000000..bf167264d --- /dev/null +++ b/sources/pyside6/libpyside/pysidelogging_p.h @@ -0,0 +1,11 @@ +// Copyright (C) 2022 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef PYSIDE_LOGGING_P_H +#define PYSIDE_LOGGING_P_H + +#include <QtCore/QLoggingCategory> + +Q_DECLARE_LOGGING_CATEGORY(lcPySide) + +#endif // PYSIDE_LOGGING_P_H diff --git a/sources/pyside6/libpyside/signalmanager.cpp b/sources/pyside6/libpyside/signalmanager.cpp index 3d7b1f896..68f31948b 100644 --- a/sources/pyside6/libpyside/signalmanager.cpp +++ b/sources/pyside6/libpyside/signalmanager.cpp @@ -3,6 +3,7 @@ #include "signalmanager.h" #include "pysidesignal.h" +#include "pysidelogging_p.h" #include "pysideproperty.h" #include "pysideproperty_p.h" #include "pysidecleanup.h" @@ -19,6 +20,7 @@ #include <sbkstring.h> #include <sbkstaticstrings.h> +#include <QtCore/QByteArrayView> #include <QtCore/QDebug> #include <QtCore/QHash> @@ -50,6 +52,24 @@ namespace { } } +static const char *metaCallName(QMetaObject::Call call) +{ + static const QHash<QMetaObject::Call, const char *> mapping = { + {QMetaObject::InvokeMetaMethod, "InvokeMetaMethod"}, + {QMetaObject::ReadProperty, "ReadProperty"}, + {QMetaObject::WriteProperty, "WriteProperty"}, + {QMetaObject::ResetProperty, "ResetProperty"}, + {QMetaObject::CreateInstance, "CreateInstance"}, + {QMetaObject::IndexOfMethod, "IndexOfMethod"}, + {QMetaObject::RegisterPropertyMetaType, "RegisterPropertyMetaType"}, + {QMetaObject::RegisterMethodArgumentMetaType, "RegisterMethodArgumentMetaType"}, + {QMetaObject::BindableProperty, "BindableProperty"}, + {QMetaObject::CustomCall, "CustomCall"} + }; + auto it = mapping.constFind(call); + return it != mapping.constEnd() ? it.value() : "<Unknown>"; +} + namespace PySide { PyObjectWrapper::PyObjectWrapper() @@ -359,6 +379,11 @@ int SignalManager::SignalManagerPrivate::qtPropertyMetacall(QObject *object, int result = id - metaObject->propertyCount(); const QMetaProperty mp = metaObject->property(id); + + qCDebug(lcPySide).noquote().nospace() << __FUNCTION__ + << ' ' << metaCallName(call) << " #" << id << ' ' << mp.typeName() + << "/\"" << mp.name() << "\" " << object; + if (!mp.isValid()) return result; @@ -395,6 +420,9 @@ int SignalManager::SignalManagerPrivate::qtMethodMetacall(QObject *object, std::unique_ptr<Shiboken::GilState> gil; + qCDebug(lcPySide).noquote().nospace() << __FUNCTION__ << " #" << id + << " \"" << method.methodSignature() << '"'; + if (method.methodType() == QMetaMethod::Signal) { // emit python signal QMetaObject::activate(object, id, args); @@ -444,6 +472,8 @@ int SignalManager::qt_metacall(QObject *object, QMetaObject::Call call, int id, case QMetaObject::IndexOfMethod: case QMetaObject::RegisterMethodArgumentMetaType: case QMetaObject::CustomCall: + qCDebug(lcPySide).noquote().nospace() << __FUNCTION__ << ' ' + << metaCallName(call) << " #" << id << ' ' << object; id -= object->metaObject()->methodCount(); break; } @@ -513,6 +543,57 @@ static MetaObjectBuilder *metaBuilderFromDict(PyObject *dict) return reinterpret_cast<MetaObjectBuilder *>(PyCapsule_GetPointer(pyBuilder, nullptr)); } +// Helper to format a method signature "foo(QString)" into +// Slot decorator "@Slot(str)" + +struct slotSignature +{ + explicit slotSignature(const char *signature) : m_signature(signature) {} + + const char *m_signature; +}; + +QDebug operator<<(QDebug debug, const slotSignature &sig) +{ + QDebugStateSaver saver(debug); + debug.noquote(); + debug.nospace(); + debug << "@Slot("; + QByteArrayView signature(sig.m_signature); + const auto len = signature.size(); + auto pos = signature.indexOf('('); + if (pos != -1 && pos < len - 2) { + ++pos; + while (true) { + auto nextPos = signature.indexOf(',', pos); + if (nextPos == -1) + nextPos = len - 1; + const QByteArrayView parameter = signature.sliced(pos, nextPos - pos); + if (parameter == "QString") { + debug << "str"; + } else if (parameter == "double") { + debug << "float"; + } else { + const bool hasDelimiter = parameter.contains("::"); + if (hasDelimiter) + debug << '"'; + if (!hasDelimiter && parameter.endsWith('*')) + debug << parameter.first(parameter.size() - 1); + else + debug << parameter; + if (hasDelimiter) + debug << '"'; + } + pos = nextPos + 1; + if (pos >= len) + break; + debug << ','; + } + } + debug << ')'; + return debug; +} + int SignalManager::registerMetaMethodGetIndex(QObject *source, const char *signature, QMetaMethod::MethodType type) { if (!source) { @@ -541,6 +622,13 @@ int SignalManager::registerMetaMethodGetIndex(QObject *source, const char *signa Py_DECREF(pyDmo); } + if (type == QMetaMethod::Slot) { + qCWarning(lcPySide).noquote().nospace() + << "Warning: Registering dynamic slot \"" + << signature << "\" on " << source->metaObject()->className() + << ". Consider annotating with " << slotSignature(signature); + } + return type == QMetaMethod::Signal ? dmo->addSignal(signature) : dmo->addSlot(signature); } |
