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 <thiago.macieira@intel.com>
This commit is contained in:
Tor Arne Vestbø 2018-12-19 20:13:02 +01:00
parent 25fc90e48b
commit 237c3972fd
2 changed files with 102 additions and 21 deletions

View File

@ -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<MyNamespace::MyClass::MyFlag>(MyFlag1)
QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)
QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)
QFlags<MyNamespace::MyClass::MyScopedFlag>(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

View File

@ -1748,35 +1748,68 @@ void tst_QMetaObject::enumDebugStream_data()
QTest::addColumn<QString>("normalEnumMsg");
QTest::addColumn<QString>("scopedEnumMsg");
QTest::addColumn<QString>("globalEnumMsg");
QTest::addColumn<QString>("normalFlagMsg");
QTest::addColumn<QString>("normalFlagsMsg");
QTest::addColumn<QString>("scopedFlagMsg");
QTest::addColumn<QString>("scopedFlagsMsg");
QTest::addColumn<QString>("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<MyNamespace::MyClass::MyFlag>(MyFlag1) world"
<< "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)"
<< "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)"
<< "QFlags<MyNamespace::MyClass::MyScopedFlag>(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<MyNamespace::MyClass::MyFlag>(MyFlag1) world"
<< "QFlags<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)"
<< "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)"
<< "QFlags<MyNamespace::MyClass::MyScopedFlag>(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<MyNamespace::MyClass::MyFlag>(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<MyNamespace::MyClass::MyFlag>(MyFlag1) QFlags<MyNamespace::MyClass::MyFlag>(MyFlag2|MyFlag3)");
qDebug() << f1 << f2;
QTest::ignoreMessage(QtDebugMsg, qPrintable(normalFlagsMsg));
qDebug().verbosity(verbosity) << f1 << f2;
QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(MyFlag2)");
QTest::ignoreMessage(QtDebugMsg, qPrintable(scopedFlagMsg));
MyNamespace::MyClass::MyScopedFlags f3 = MyNamespace::MyClass::MyScopedFlag::MyFlag2;
qDebug() << f3;
qDebug().verbosity(verbosity) << f3;
QTest::ignoreMessage(QtDebugMsg, "QFlags<MyNamespace::MyClass::MyScopedFlag>(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()