aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2022-08-16 13:15:30 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2022-08-26 12:09:26 +0200
commitbd6a2f1f880effb95ea3e42f52d06f0730103a03 (patch)
tree3317a73a350c328e5e2a0ed8fb0524eb0370359e
parent9ab2d9ccdea6dbb60234d203ed921db89144d2e1 (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.cpp3
-rw-r--r--sources/pyside6/libpyside/pysidelogging_p.h11
-rw-r--r--sources/pyside6/libpyside/signalmanager.cpp88
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);
}