From 237c3972fd8869698cea69ff57f751c982bec487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 19 Dec 2018 20:13:02 +0100 Subject: [PATCH] Allow more fine grained control over QFlags debug output Useful in contexts such as other QDebug operators, where the class is already known, and the full scope of the flags is not needed. Change-Id: I546381b1722c9c846e2412e56763563b8f625212 Reviewed-by: Thiago Macieira --- src/corelib/io/qdebug.cpp | 58 +++++++++++++++-- .../kernel/qmetaobject/tst_qmetaobject.cpp | 65 ++++++++++++++----- 2 files changed, 102 insertions(+), 21 deletions(-) diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp index cc77db28de..15c5e0ce96 100644 --- a/src/corelib/io/qdebug.cpp +++ b/src/corelib/io/qdebug.cpp @@ -976,17 +976,67 @@ QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, int value, const QMetaObject *met return dbg; } +/*! + \fn QDebug qt_QMetaEnum_flagDebugOperator(QDebug &, quint64 value, const QMetaObject *, const char *name) + \internal + + Formats the given flag \a value for debug output. + + The supported verbosity are: + + 0: Just the key(s): + + MyFlag1 + MyFlag2|MyFlag3 + MyScopedFlag(MyFlag2) + MyScopedFlag(MyFlag2|MyFlag3) + + 1: Same as 0, but treating all flags as scoped: + + MyFlag(MyFlag1) + MyFlag(MyFlag2|MyFlag3) + MyScopedFlag(MyFlag2) + MyScopedFlag(MyFlag2|MyFlag3) + + 2: The QDebug default. Same as 1, and includes class/namespace scope: + + QFlags(MyFlag1) + QFlags(MyFlag2|MyFlag3) + QFlags(MyFlag2) + QFlags(MyFlag2|MyFlag3) + */ QDebug qt_QMetaEnum_flagDebugOperator(QDebug &debug, quint64 value, const QMetaObject *meta, const char *name) { + const int verbosity = debug.verbosity(); + QDebugStateSaver saver(debug); debug.resetFormat(); debug.noquote(); debug.nospace(); - debug << "QFlags<"; + const QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name)); - if (const char *scope = me.scope()) - debug << scope << "::"; - debug << me.enumName() << ">(" << me.valueToKeys(value) << ')'; + + const bool classScope = verbosity >= QDebug::DefaultVerbosity; + if (classScope) { + debug << "QFlags<"; + + if (const char *scope = me.scope()) + debug << scope << "::"; + } + + const bool enumScope = me.isScoped() || verbosity > QDebug::MinimumVerbosity; + if (enumScope) { + debug << me.enumName(); + if (classScope) + debug << ">"; + debug << "("; + } + + debug << me.valueToKeys(value); + + if (enumScope) + debug << ')'; + return debug; } #endif // !QT_NO_QOBJECT diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index 68e9040ce2..467d299526 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -1748,35 +1748,68 @@ void tst_QMetaObject::enumDebugStream_data() QTest::addColumn("normalEnumMsg"); QTest::addColumn("scopedEnumMsg"); QTest::addColumn("globalEnumMsg"); + QTest::addColumn("normalFlagMsg"); + QTest::addColumn("normalFlagsMsg"); + QTest::addColumn("scopedFlagMsg"); + QTest::addColumn("scopedFlagsMsg"); + QTest::addColumn("flagAsEnumMsg"); QTest::newRow("verbosity=0") << 0 - << "WindowTitleHint Window Desktop WindowSystemMenuHint"; << "hello MyEnum2 world" << "hello MyScopedEnum::Enum3 scoped world" + << "WindowTitleHint Window Desktop WindowSystemMenuHint" + << "hello MyFlag1 world" + << "MyFlag1 MyFlag2|MyFlag3" + << "MyScopedFlag(MyFlag2)" + << "MyScopedFlag(MyFlag2|MyFlag3)" + << "MyFlag1"; QTest::newRow("verbosity=1") << 1 - << "WindowType::WindowTitleHint WindowType::Window WindowType::Desktop WindowType::WindowSystemMenuHint"; << "hello MyEnum::MyEnum2 world" << "hello MyScopedEnum::Enum3 scoped world" + << "WindowType::WindowTitleHint WindowType::Window WindowType::Desktop WindowType::WindowSystemMenuHint" + << "hello MyFlag(MyFlag1) world" + << "MyFlag(MyFlag1) MyFlag(MyFlag2|MyFlag3)" + << "MyScopedFlag(MyFlag2)" + << "MyScopedFlag(MyFlag2|MyFlag3)" + << "MyFlag::MyFlag1"; QTest::newRow("verbosity=2") << 2 - << "Qt::WindowTitleHint Qt::Window Qt::Desktop Qt::WindowSystemMenuHint"; << "hello MyNamespace::MyClass::MyEnum2 world" << "hello MyNamespace::MyClass::MyScopedEnum::Enum3 scoped world" + << "Qt::WindowTitleHint Qt::Window Qt::Desktop Qt::WindowSystemMenuHint" + << "hello QFlags(MyFlag1) world" + << "QFlags(MyFlag1) QFlags(MyFlag2|MyFlag3)" + << "QFlags(MyFlag2)" + << "QFlags(MyFlag2|MyFlag3)" + << "MyNamespace::MyClass::MyFlag1"; QTest::newRow("verbosity=3") << 3 - << "Qt::WindowType::WindowTitleHint Qt::WindowType::Window Qt::WindowType::Desktop Qt::WindowType::WindowSystemMenuHint"; << "hello MyNamespace::MyClass::MyEnum::MyEnum2 world" << "hello MyNamespace::MyClass::MyScopedEnum::Enum3 scoped world" + << "Qt::WindowType::WindowTitleHint Qt::WindowType::Window Qt::WindowType::Desktop Qt::WindowType::WindowSystemMenuHint" + << "hello QFlags(MyFlag1) world" + << "QFlags(MyFlag1) QFlags(MyFlag2|MyFlag3)" + << "QFlags(MyFlag2)" + << "QFlags(MyFlag2|MyFlag3)" + << "MyNamespace::MyClass::MyFlag::MyFlag1"; } void tst_QMetaObject::enumDebugStream() { QFETCH(int, verbosity); + QFETCH(QString, normalEnumMsg); QFETCH(QString, scopedEnumMsg); QFETCH(QString, globalEnumMsg); + QFETCH(QString, normalFlagMsg); + QFETCH(QString, normalFlagsMsg); + QFETCH(QString, scopedFlagMsg); + QFETCH(QString, scopedFlagsMsg); + QFETCH(QString, flagAsEnumMsg); + + // Enums QTest::ignoreMessage(QtDebugMsg, qPrintable(normalEnumMsg)); qDebug().verbosity(verbosity) << "hello" << MyNamespace::MyClass::MyEnum2 << "world"; @@ -1786,29 +1819,27 @@ void tst_QMetaObject::enumDebugStream() QTest::ignoreMessage(QtDebugMsg, qPrintable(globalEnumMsg)); qDebug().verbosity(verbosity) << Qt::WindowTitleHint << Qt::Window << Qt::Desktop << Qt::WindowSystemMenuHint; - if (verbosity != 2) - return; - - QTest::ignoreMessage(QtDebugMsg, "hello QFlags(MyFlag1) world"); + // Flags + QTest::ignoreMessage(QtDebugMsg, qPrintable(normalFlagMsg)); MyNamespace::MyClass::MyFlags f1 = MyNamespace::MyClass::MyFlag1; - qDebug() << "hello" << f1 << "world"; + qDebug().verbosity(verbosity) << "hello" << f1 << "world"; MyNamespace::MyClass::MyFlags f2 = MyNamespace::MyClass::MyFlag2 | MyNamespace::MyClass::MyFlag3; - QTest::ignoreMessage(QtDebugMsg, "QFlags(MyFlag1) QFlags(MyFlag2|MyFlag3)"); - qDebug() << f1 << f2; + QTest::ignoreMessage(QtDebugMsg, qPrintable(normalFlagsMsg)); + qDebug().verbosity(verbosity) << f1 << f2; - QTest::ignoreMessage(QtDebugMsg, "QFlags(MyFlag2)"); + QTest::ignoreMessage(QtDebugMsg, qPrintable(scopedFlagMsg)); MyNamespace::MyClass::MyScopedFlags f3 = MyNamespace::MyClass::MyScopedFlag::MyFlag2; - qDebug() << f3; + qDebug().verbosity(verbosity) << f3; - QTest::ignoreMessage(QtDebugMsg, "QFlags(MyFlag2|MyFlag3)"); + QTest::ignoreMessage(QtDebugMsg, qPrintable(scopedFlagsMsg)); f3 |= MyNamespace::MyClass::MyScopedFlag::MyFlag3; - qDebug() << f3; + qDebug().verbosity(verbosity) << f3; // Single flag recognized as enum: - QTest::ignoreMessage(QtDebugMsg, "MyNamespace::MyClass::MyFlag1"); + QTest::ignoreMessage(QtDebugMsg, qPrintable(flagAsEnumMsg)); MyNamespace::MyClass::MyFlag f4 = MyNamespace::MyClass::MyFlag1; - qDebug() << f4; + qDebug().verbosity(verbosity) << f4; } void tst_QMetaObject::inherits_data()