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:
parent
7024ddba4b
commit
f85b9f8242
@ -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");
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user