Fix QDebug cumulating operator<< with many Q_ENUM

The problem is that the operator<< was taking a non-const reference to the QDebug
object. This causes a problem as all other operator<< return a temporary.
Since every other roperator<< takes the QDebug by value, we should also take it by value
in this case.

Move the operator<< in qdebug.h because i don't want to #include qdebug.h from qobject.h
And move the qt_QMetaEnum_debugOperator to be in the corresponding .cpp

Task-number: QTBUG-44462
Change-Id: Ia01629224c58930c2997e767efc43de90d6309e2
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@theqtcompany.com>
This commit is contained in:
Olivier Goffart 2015-02-16 15:25:46 +01:00 committed by Friedemann Kleint
parent 51b7bd1e4f
commit 50e2bc2aa0
5 changed files with 36 additions and 24 deletions

View File

@ -40,6 +40,7 @@
#endif
#include "qdebug.h"
#include "qmetaobject.h"
#include <private/qtextstream_p.h>
#include <private/qtools_p.h>
@ -643,4 +644,23 @@ QDebugStateSaver::~QDebugStateSaver()
d->restoreState();
}
#ifndef QT_NO_QOBJECT
/*!
\internal
*/
QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, int value, const QMetaObject *meta, const char *name)
{
QDebugStateSaver saver(dbg);
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
const char *key = me.valueToKey(value);
dbg.nospace() << meta->className() << "::" << name << '(';
if (key)
dbg << key;
else
dbg << value;
dbg << ')';
return dbg;
}
#endif
QT_END_NAMESPACE

View File

@ -261,6 +261,19 @@ inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
return debug.maybeSpace();
}
#ifndef QT_NO_QOBJECT
Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, int value, const QMetaObject *meta, const char *name);
template<typename T>
typename QtPrivate::QEnableIf<QtPrivate::IsQEnumHelper<T>::Value, QDebug>::Type
operator<<(QDebug dbg, T value)
{
const QMetaObject *obj = qt_getEnumMetaObject(value);
const char *name = qt_getEnumName(value);
return qt_QMetaEnum_debugOperator(dbg, typename QFlags<T>::Int(value), obj, name);
}
#endif
template <class T>
inline QDebug operator<<(QDebug debug, const QFlags<T> &flags)
{

View File

@ -4106,20 +4106,6 @@ QDebug operator<<(QDebug dbg, const QObject *o)
dbg << ')';
return dbg;
}
QDebug qt_QMetaEnum_debugOperator(QDebug &dbg, int value, const QMetaObject *meta, const char *name)
{
QDebugStateSaver saver(dbg);
QMetaEnum me = meta->enumerator(meta->indexOfEnumerator(name));
const char *key = me.valueToKey(value);
dbg.nospace() << meta->className() << "::" << name << '(';
if (key)
dbg << key;
else
dbg << value;
dbg << ')';
return dbg;
}
#endif
/*!

View File

@ -547,16 +547,6 @@ template <class T> inline const char * qobject_interface_iid()
#ifndef QT_NO_DEBUG_STREAM
Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
Q_CORE_EXPORT QDebug qt_QMetaEnum_debugOperator(QDebug&, int value, const QMetaObject *meta, const char *name);
template<typename T>
typename QtPrivate::QEnableIf<QtPrivate::IsQEnumHelper<T>::Value , QDebug>::Type
operator<<(QDebug &dbg, T value)
{
const QMetaObject *obj = qt_getEnumMetaObject(value);
const char *name = qt_getEnumName(value);
return qt_QMetaEnum_debugOperator(dbg, typename QFlags<T>::Int(value), obj, name);
}
#endif
class QSignalBlocker

View File

@ -1417,6 +1417,9 @@ void tst_QMetaObject::enumDebugStream()
QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyEnum(MyEnum2) world ");
MyNamespace::MyClass::MyEnum e = MyNamespace::MyClass::MyEnum2;
qDebug() << "hello" << e << "world";
QTest::ignoreMessage(QtDebugMsg, "Qt::WindowType(WindowTitleHint) Qt::WindowType(Window) Qt::WindowType(Desktop) Qt::WindowType(WindowSystemMenuHint)");
qDebug() << Qt::WindowTitleHint << Qt::Window <<Qt::Desktop << Qt::WindowSystemMenuHint;
}
QTEST_MAIN(tst_QMetaObject)