Reimplement QVariant to QDebug streaming.

New implementation fixes some commented code marked as FIXME.

Change-Id: If8f5bebedd65bcf8f839d804c2022ca79ef82ddf
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Jędrzej Nowacki 2011-12-05 12:43:10 +01:00 committed by Qt by Nokia
parent 7024ddba4b
commit f85b9f8242
6 changed files with 140 additions and 185 deletions

View File

@ -731,104 +731,9 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
static void streamDebug(QDebug dbg, const QVariant &v)
{
switch (v.userType()) {
case QVariant::Int:
dbg.nospace() << v.toInt();
break;
case QVariant::UInt:
dbg.nospace() << v.toUInt();
break;
case QVariant::LongLong:
dbg.nospace() << v.toLongLong();
break;
case QVariant::ULongLong:
dbg.nospace() << v.toULongLong();
break;
case QMetaType::Float:
dbg.nospace() << v.toFloat();
break;
case QMetaType::QObjectStar:
dbg.nospace() << qvariant_cast<QObject *>(v);
break;
case QVariant::Double:
dbg.nospace() << v.toDouble();
break;
case QVariant::Bool:
dbg.nospace() << v.toBool();
break;
case QVariant::String:
dbg.nospace() << v.toString();
break;
case QVariant::Char:
dbg.nospace() << v.toChar();
break;
case QVariant::StringList:
dbg.nospace() << v.toStringList();
break;
case QVariant::Map:
dbg.nospace() << v.toMap();
break;
case QVariant::Hash:
dbg.nospace() << v.toHash();
break;
case QVariant::List:
dbg.nospace() << v.toList();
break;
case QVariant::Date:
dbg.nospace() << v.toDate();
break;
case QVariant::Time:
dbg.nospace() << v.toTime();
break;
case QVariant::DateTime:
dbg.nospace() << v.toDateTime();
break;
#ifndef QT_BOOTSTRAPPED
case QVariant::EasingCurve:
dbg.nospace() << v.toEasingCurve();
break;
#endif
case QVariant::ByteArray:
dbg.nospace() << v.toByteArray();
break;
case QVariant::Url:
dbg.nospace() << v.toUrl();
break;
#ifndef QT_NO_GEOM_VARIANT
case QVariant::Point:
dbg.nospace() << v.toPoint();
break;
case QVariant::PointF:
dbg.nospace() << v.toPointF();
break;
case QVariant::Rect:
dbg.nospace() << v.toRect();
break;
case QVariant::Size:
dbg.nospace() << v.toSize();
break;
case QVariant::SizeF:
dbg.nospace() << v.toSizeF();
break;
case QVariant::Line:
dbg.nospace() << v.toLine();
break;
case QVariant::LineF:
dbg.nospace() << v.toLineF();
break;
case QVariant::RectF:
dbg.nospace() << v.toRectF();
break;
#endif
case QVariant::Uuid:
dbg.nospace() << v.value<QUuid>().toString();
break;
case QVariant::BitArray:
//dbg.nospace() << v.toBitArray();
break;
default:
break;
}
QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
QVariantDebugStream<CoreTypesFilter> stream(dbg, d);
QMetaTypeSwitcher::switcher<void>(stream, d->type, 0);
}
#endif
@ -2707,7 +2612,7 @@ bool QVariant::isNull() const
QDebug operator<<(QDebug dbg, const QVariant &v)
{
#ifndef Q_BROKEN_DEBUG_STREAM
dbg.nospace() << "QVariant(" << v.typeName() << ", ";
dbg.nospace() << "QVariant(" << QMetaType::typeName(v.userType()) << ", ";
handlerManager[v.d.type]->debugStream(dbg, v);
dbg.nospace() << ')';
return dbg.space();
@ -2721,7 +2626,7 @@ QDebug operator<<(QDebug dbg, const QVariant &v)
QDebug operator<<(QDebug dbg, const QVariant::Type p)
{
#ifndef Q_BROKEN_DEBUG_STREAM
dbg.nospace() << "QVariant::" << QVariant::typeToName(p);
dbg.nospace() << "QVariant::" << QMetaType::typeName(p);
return dbg.space();
#else
qWarning("This compiler doesn't support streaming QVariant::Type to QDebug");

View File

@ -397,6 +397,7 @@ private:
public:
typedef Private DataPtr;
inline DataPtr &data_ptr() { return d; }
inline const DataPtr &data_ptr() const { return d; }
};
template <typename T>

View File

@ -58,6 +58,9 @@
#include <QtCore/qglobal.h>
#include <QtCore/qvariant.h>
#include <QtCore/private/qmetatype_p.h>
#include <QtCore/qdebug.h>
#include "qmetatypeswitcher_p.h"
QT_BEGIN_NAMESPACE
@ -418,6 +421,54 @@ Q_CORE_EXPORT void registerHandler(const int /* Modules::Names */ name, const QV
Q_CORE_EXPORT void unregisterHandler(const int /* Modules::Names */ name);
}
#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
template<class Filter>
class QVariantDebugStream
{
template<typename T, bool IsAcceptedType = Filter::template Acceptor<T>::IsAccepted>
struct Filtered {
Filtered(QDebug dbg, QVariant::Private *d)
{
dbg.nospace() << *v_cast<T>(d);
}
};
template<typename T>
struct Filtered<T, /* IsAcceptedType = */ false> {
Filtered(QDebug dbg, QVariant::Private *d)
{
dbg.nospace() << "QVariant::Type(" << d->type << ")";
}
};
public:
QVariantDebugStream(QDebug dbg, QVariant::Private *d)
: m_debugStream(dbg)
, m_d(d)
{}
template<typename T>
void delegate(const T*)
{
Filtered<T> streamIt(m_debugStream, m_d);
}
void delegate(const QMetaTypeSwitcher::UnknownType*)
{
if (m_d->type == QVariant::UserType)
m_debugStream.nospace() << "QVariant::UserType";
else
qWarning("Trying to stream an instance of an invalid type, type id: %i", m_d->type);
}
void delegate(const void*)
{
m_debugStream.nospace() << "QVariant::Invalid";
}
private:
QDebug m_debugStream;
QVariant::Private *m_d;
};
#endif
QT_END_NAMESPACE
#endif // QVARIANT_P_H

View File

@ -345,90 +345,9 @@ static bool convert(const QVariant::Private *d, QVariant::Type t,
#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
static void streamDebug(QDebug dbg, const QVariant &v)
{
switch(v.type()) {
case QVariant::Cursor:
#ifndef QT_NO_CURSOR
// dbg.nospace() << qvariant_cast<QCursor>(v); //FIXME
#endif
break;
case QVariant::Bitmap:
// dbg.nospace() << qvariant_cast<QBitmap>(v); //FIXME
break;
case QVariant::Polygon:
dbg.nospace() << qvariant_cast<QPolygon>(v);
break;
case QVariant::Region:
dbg.nospace() << qvariant_cast<QRegion>(v);
break;
case QVariant::Font:
// dbg.nospace() << qvariant_cast<QFont>(v); //FIXME
break;
case QVariant::Matrix:
dbg.nospace() << qvariant_cast<QMatrix>(v);
break;
case QVariant::Transform:
dbg.nospace() << qvariant_cast<QTransform>(v);
break;
case QVariant::Pixmap:
// dbg.nospace() << qvariant_cast<QPixmap>(v); //FIXME
break;
case QVariant::Image:
// dbg.nospace() << qvariant_cast<QImage>(v); //FIXME
break;
case QVariant::Brush:
dbg.nospace() << qvariant_cast<QBrush>(v);
break;
case QVariant::Color:
dbg.nospace() << qvariant_cast<QColor>(v);
break;
case QVariant::Palette:
// dbg.nospace() << qvariant_cast<QPalette>(v); //FIXME
break;
#ifndef QT_NO_ICON
case QVariant::Icon:
// dbg.nospace() << qvariant_cast<QIcon>(v); // FIXME
break;
#endif
case QVariant::SizePolicy:
// dbg.nospace() << qvariant_cast<QSizePolicy>(v); //FIXME
break;
#ifndef QT_NO_SHORTCUT
case QVariant::KeySequence:
dbg.nospace() << qvariant_cast<QKeySequence>(v);
break;
#endif
case QVariant::Pen:
dbg.nospace() << qvariant_cast<QPen>(v);
break;
#ifndef QT_NO_MATRIX4X4
case QVariant::Matrix4x4:
dbg.nospace() << qvariant_cast<QMatrix4x4>(v);
break;
#endif
#ifndef QT_NO_VECTOR2D
case QVariant::Vector2D:
dbg.nospace() << qvariant_cast<QVector2D>(v);
break;
#endif
#ifndef QT_NO_VECTOR3D
case QVariant::Vector3D:
dbg.nospace() << qvariant_cast<QVector3D>(v);
break;
#endif
#ifndef QT_NO_VECTOR4D
case QVariant::Vector4D:
dbg.nospace() << qvariant_cast<QVector4D>(v);
break;
#endif
#ifndef QT_NO_QUATERNION
case QVariant::Quaternion:
dbg.nospace() << qvariant_cast<QQuaternion>(v);
break;
#endif
default:
qcoreVariantHandler()->debugStream(dbg, v);
break;
}
QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
QVariantDebugStream<GuiTypesFilter> stream(dbg, d);
QMetaTypeSwitcher::switcher<void>(stream, d->type, 0);
}
#endif

View File

@ -127,6 +127,23 @@ static bool convert(const QVariant::Private *d, QVariant::Type type, void *resul
return false;
}
static void streamDebug(QDebug dbg, const QVariant &v)
{
QVariant::Private *d = const_cast<QVariant::Private *>(&v.data_ptr());
switch (d->type) {
#ifndef QT_NO_ICON
case QVariant::Icon:
dbg.nospace() << *v_cast<QIcon>(d);
break;
#endif
case QVariant::SizePolicy:
dbg.nospace() << *v_cast<QSizePolicy>(d);
break;
default:
dbg.nospace() << "QVariant::Type(" << d->type << ")";
}
}
static const QVariant::Handler widgets_handler = {
construct,
clear,
@ -139,7 +156,7 @@ static const QVariant::Handler widgets_handler = {
convert,
0,
#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
0
streamDebug
#else
0
#endif

View File

@ -63,6 +63,7 @@
#include <qvector3d.h>
#include <qvector4d.h>
#include <qquaternion.h>
#include <qdebug.h>
#include <limits.h>
@ -259,6 +260,8 @@ private slots:
void colorInteger();
void forwardDeclare();
void debugStream_data();
void debugStream();
};
Q_DECLARE_METATYPE(QDate)
@ -3331,5 +3334,64 @@ void tst_QVariant::forwardDeclare()
}
class MessageHandler {
public:
MessageHandler(const int typeId)
: oldMsgHandler(qInstallMsgHandler(handler))
{
currentId = typeId;
}
~MessageHandler()
{
qInstallMsgHandler(oldMsgHandler);
}
bool testPassed() const
{
return ok;
}
private:
static void handler(QtMsgType, const char *txt)
{
QString msg = QString::fromLatin1(txt);
// Format itself is not important, but basic data as a type name should be included in the output
ok = msg.startsWith("QVariant(") + QMetaType::typeName(currentId);
QVERIFY2(ok, (QString::fromLatin1("Message is not valid: '") + msg + '\'').toLatin1().constData());
}
QtMsgHandler oldMsgHandler;
static int currentId;
static bool ok;
};
bool MessageHandler::ok;
int MessageHandler::currentId;
void tst_QVariant::debugStream_data()
{
QTest::addColumn<QVariant>("variant");
QTest::addColumn<int>("typeId");
for (int id = QMetaType::Void; id < QMetaType::User; ++id) {
const char *tagName = QMetaType::typeName(id);
if (!tagName)
continue;
QTest::newRow(tagName) << QVariant(static_cast<QVariant::Type>(id)) << id;
}
QTest::newRow("QBitArray(111)") << QVariant(QBitArray(3, true)) << qMetaTypeId<QBitArray>();
QTest::newRow("CustomStreamableClass") << QVariant(qMetaTypeId<CustomStreamableClass>(), 0) << qMetaTypeId<CustomStreamableClass>();
QTest::newRow("MyClass") << QVariant(qMetaTypeId<MyClass>(), 0) << qMetaTypeId<MyClass>();
}
void tst_QVariant::debugStream()
{
QFETCH(QVariant, variant);
QFETCH(int, typeId);
MessageHandler msgHandler(typeId);
qDebug() << variant;
QVERIFY(msgHandler.testPassed());
}
QTEST_MAIN(tst_QVariant)
#include "tst_qvariant.moc"