summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qvariant.cpp105
-rw-r--r--src/corelib/kernel/qvariant.h1
-rw-r--r--src/corelib/kernel/qvariant_p.h51
-rw-r--r--src/gui/kernel/qguivariant.cpp87
-rw-r--r--src/widgets/kernel/qwidgetsvariant.cpp19
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp62
6 files changed, 140 insertions, 185 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 9cf131312b..89d1290022 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -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");
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 12a512f0dd..738e516b82 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -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>
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index b79d4623c1..015ca5b464 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -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
diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp
index 8618c04a32..532a5353e2 100644
--- a/src/gui/kernel/qguivariant.cpp
+++ b/src/gui/kernel/qguivariant.cpp
@@ -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
diff --git a/src/widgets/kernel/qwidgetsvariant.cpp b/src/widgets/kernel/qwidgetsvariant.cpp
index e33d0da0a1..e9fa99a80e 100644
--- a/src/widgets/kernel/qwidgetsvariant.cpp
+++ b/src/widgets/kernel/qwidgetsvariant.cpp
@@ -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
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index 8f75f13958..c2d4f0a240 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -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"