return retVal;
enum {
- DefaultStreamVersion = QDataStream::Qt_4_6
+ DefaultStreamVersion = QDataStream::Qt_5_0
};
// ### 5.0: when streaming invalid QVariants, just the type should
Qt_4_7 = Qt_4_6,
Qt_4_8 = Qt_4_7,
Qt_4_9 = Qt_4_8,
- Qt_5_0 = Qt_4_8
+ Qt_5_0 = 13
#if QT_VERSION >= 0x050100
#error Add the datastream version for this Qt version
#endif
\value User Base value for user types
- \omitvalue FirstCoreExtType
\omitvalue FirstGuiType
\omitvalue FirstWidgetsType
- \omitvalue LastCoreExtType
\omitvalue LastCoreType
\omitvalue LastGuiType
\omitvalue LastWidgetsType
\omitvalue QReal
+ \omitvalue HighestInternalId
Additional types can be registered using Q_DECLARE_METATYPE().
// In theory it can be filled during compilation time, but for some reason template code
// that is able to do it causes GCC 4.6 to generate additional 3K of executable code. Probably
// it is not worth of it.
- static const char *namesCache[QMetaType::LastCoreExtType + 1];
+ static const char *namesCache[QMetaType::HighestInternalId + 1];
const char *result;
- if (type <= QMetaType::LastCoreExtType && ((result = namesCache[type])))
+ if (type <= QMetaType::HighestInternalId && ((result = namesCache[type])))
return result;
#define QT_METATYPE_TYPEID_TYPENAME_CONVERTER(MetaTypeName, TypeId, RealName) \
}
#undef QT_METATYPE_TYPEID_TYPENAME_CONVERTER
- Q_ASSERT(type <= QMetaType::LastCoreExtType);
+ Q_ASSERT(type <= QMetaType::HighestInternalId);
namesCache[type] = result;
return result;
}
F(LongLong, 4, qlonglong) \
F(ULongLong, 5, qulonglong) \
F(Double, 6, double) \
- F(Long, 129, long) \
- F(Short, 130, short) \
- F(Char, 131, char) \
- F(ULong, 132, ulong) \
- F(UShort, 133, ushort) \
- F(UChar, 134, uchar) \
- F(Float, 135, float) \
+ F(Long, 32, long) \
+ F(Short, 33, short) \
+ F(Char, 34, char) \
+ F(ULong, 35, ulong) \
+ F(UShort, 36, ushort) \
+ F(UChar, 37, uchar) \
+ F(Float, 38, float) \
#define QT_FOR_EACH_STATIC_PRIMITIVE_POINTER(F)\
- F(VoidStar, 128, void*) \
+ F(VoidStar, 31, void*) \
#define QT_FOR_EACH_STATIC_CORE_CLASS(F)\
F(QChar, 7, QChar) \
F(QRegExp, 27, QRegExp) \
F(QEasingCurve, 29, QEasingCurve) \
F(QUuid, 30, QUuid) \
- F(QModelIndex, 31, QModelIndex) \
- F(QVariant, 138, QVariant) \
+ F(QVariant, 41, QVariant) \
+ F(QModelIndex, 42, QModelIndex) \
#define QT_FOR_EACH_STATIC_CORE_POINTER(F)\
- F(QObjectStar, 136, QObject*) \
- F(QWidgetStar, 137, QWidget*) \
+ F(QObjectStar, 39, QObject*) \
+ F(QWidgetStar, 40, QWidget*) \
#define QT_FOR_EACH_STATIC_CORE_TEMPLATE(F)\
F(QVariantMap, 8, QVariantMap) \
LastGuiType = QPolygonF,
FirstWidgetsType = QIcon,
LastWidgetsType = QSizePolicy,
- FirstCoreExtType = VoidStar,
- LastCoreExtType = QVariant,
+ HighestInternalId = LastWidgetsType,
// This logic must match the one in qglobal.h
#if defined(QT_COORD_TYPE)
return Gui;
if (typeId <= QMetaType::LastWidgetsType)
return Widgets;
- if (typeId <= QMetaType::LastCoreExtType)
- return Core;
return Unknown;
}
}
#ifndef QT_NO_DATASTREAM
enum { MapFromThreeCount = 36 };
-static const ushort map_from_three[MapFromThreeCount] =
+static const ushort mapIdFromQt3ToCurrent[MapFromThreeCount] =
{
QVariant::Invalid,
QVariant::Map,
{
clear();
- quint32 u;
- s >> u;
+ quint32 typeId;
+ s >> typeId;
if (s.version() < QDataStream::Qt_4_0) {
- if (u >= MapFromThreeCount)
+ if (typeId >= MapFromThreeCount)
return;
- u = map_from_three[u];
+ typeId = mapIdFromQt3ToCurrent[typeId];
+ } else if (s.version() < QDataStream::Qt_5_0) {
+ if (typeId >= 128 && typeId != QVariant::UserType) {
+ // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
+ // by moving all ids down by 97.
+ typeId -= 97;
+ } else if (typeId == 69 /* QIcon */) {
+ // In Qt5 after modularization project this types where moved to a separate module (and ids were downgraded)
+ typeId = QMetaType::QIcon;
+ } else if (typeId == 75 /* QSizePolicy */) {
+ typeId = QMetaType::QSizePolicy;
+ } else if (typeId >= 70) {
+ // and as a result this types recieved lower ids too
+ if (typeId <= 74) { // QImage QPolygon QRegion QBitmap QCursor
+ typeId -=1;
+ } else if (typeId <= 86) { // QKeySequence QPen QTextLength QTextFormat QMatrix QTransform QMatrix4x4 QVector2D QVector3D QVector4D QQuaternion
+ typeId -=2;
+ }
+ }
}
+
qint8 is_null = false;
if (s.version() >= QDataStream::Qt_4_2)
s >> is_null;
- if (u == QVariant::UserType) {
+ if (typeId == QVariant::UserType) {
QByteArray name;
s >> name;
- u = QMetaType::type(name);
- if (!u) {
+ typeId = QMetaType::type(name);
+ if (!typeId) {
s.setStatus(QDataStream::ReadCorruptData);
return;
}
}
- create(static_cast<int>(u), 0);
+ create(static_cast<int>(typeId), 0);
d.is_null = is_null;
if (!isValid()) {
*/
void QVariant::save(QDataStream &s) const
{
- quint32 tp = type();
+ quint32 typeId = type();
if (s.version() < QDataStream::Qt_4_0) {
int i;
for (i = MapFromThreeCount - 1; i >= 0; i--) {
- if (map_from_three[i] == tp) {
- tp = i;
+ if (mapIdFromQt3ToCurrent[i] == typeId) {
+ typeId = i;
break;
}
}
s << QVariant();
return;
}
+ } else if (s.version() < QDataStream::Qt_5_0) {
+ if (typeId >= 128 - 97 && typeId <= LastCoreType) {
+ // In Qt4 id == 128 was FirstExtCoreType. In Qt5 ExtCoreTypes set was merged to CoreTypes
+ // by moving all ids down by 97.
+ typeId += 97;
+ } else if (typeId == QMetaType::QIcon) {
+ // In Qt5 after modularization project this types where moved to a separate module (and ids were downgraded)
+ typeId = 69;
+ } else if (typeId == QMetaType::QSizePolicy) {
+ typeId = 75;
+ } else if (typeId >= QMetaType::QImage) {
+ // and as a result this types recieved lower ids too
+ if (typeId <= QMetaType::QCursor) {
+ typeId +=1;
+ } else if (typeId <= QMetaType::QQuaternion) {
+ typeId +=2;
+ }
+ }
}
- s << tp;
+ s << typeId;
if (s.version() >= QDataStream::Qt_4_2)
s << qint8(d.is_null);
- if (tp == QVariant::UserType) {
+ if (typeId == QVariant::UserType) {
s << QMetaType::typeName(userType());
}
*/
bool QVariant::canConvert(Type t) const
{
- //we can treat floats as double
- //the reason for not doing it the "proper" way is that QMetaType::Float's value is 135,
- //which can't be handled by qCanConvertMatrix
- //In addition QVariant::Type doesn't have a Float value, so we're using QMetaType::Float
+ // TODO Reimplement this function, currently it works but it is a historical mess.
const uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
if (uint(t) == uint(QMetaType::Float)) t = QVariant::Double;
if (currentType == uint(t))
return true;
- if (currentType > QVariant::LastCoreType || t > QVariant::LastCoreType) {
+ // FIXME It should be LastCoreType intead of Uuid
+ if (currentType > QVariant::Uuid || t > QVariant::Uuid) {
switch (uint(t)) {
case QVariant::Int:
return currentType == QVariant::KeySequence
QPalette::ToolTipText + 1, // Qt_4_4
QPalette::ToolTipText + 1, // Qt_4_5
QPalette::ToolTipText + 1, // Qt_4_6
- 0 // add the correct value for Qt_4_7 here later
+ QPalette::ToolTipText + 1, // Qt_5_0
+ 0 // add the correct value for Qt_5_1 here later
};
// Testing get/set functions
TARGET = tst_qvariant
QT += widgets network testlib
SOURCES = tst_qvariant.cpp
+RESOURCES += qvariant.qrc
mac: CONFIG += insignificant_test # QTBUG-QTBUG-22747
--- /dev/null
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>stream/qt4.9/</file>
+ <file>stream/qt5.0/</file>
+</qresource>
+</RCC>
void forwardDeclare();
void debugStream_data();
void debugStream();
+
+ void loadQt4Stream_data();
+ void loadQt4Stream();
+ void saveQt4Stream_data();
+ void saveQt4Stream();
+ void loadQt5Stream_data();
+ void loadQt5Stream();
+ void saveQt5Stream_data();
+ void saveQt5Stream();
+private:
+ void dataStream_data(QDataStream::Version version);
+ void loadQVariantFromDataStream(QDataStream::Version version);
+ void saveQVariantFromDataStream(QDataStream::Version version);
};
Q_DECLARE_METATYPE(QDate)
void tst_QVariant::userType()
{
{
- QVariant userVariant(QVariant::UserType);
-
- QVERIFY(userVariant.isValid());
- QVERIFY(userVariant.isNull());
- }
-
- {
MyType data(1, "eins");
MyType data2(2, "zwei");
QCOMPARE(qvariant_cast<Forward*>(v), f);
}
+void tst_QVariant::loadQt5Stream_data()
+{
+ dataStream_data(QDataStream::Qt_5_0);
+}
+
+void tst_QVariant::loadQt5Stream()
+{
+ loadQVariantFromDataStream(QDataStream::Qt_5_0);
+}
+
+void tst_QVariant::saveQt5Stream_data()
+{
+ dataStream_data(QDataStream::Qt_5_0);
+}
+
+void tst_QVariant::saveQt5Stream()
+{
+ saveQVariantFromDataStream(QDataStream::Qt_5_0);
+}
+
+void tst_QVariant::loadQt4Stream_data()
+{
+ dataStream_data(QDataStream::Qt_4_9);
+}
+
+void tst_QVariant::loadQt4Stream()
+{
+ loadQVariantFromDataStream(QDataStream::Qt_4_9);
+}
+
+void tst_QVariant::saveQt4Stream_data()
+{
+ dataStream_data(QDataStream::Qt_4_9);
+}
+
+void tst_QVariant::saveQt4Stream()
+{
+ saveQVariantFromDataStream(QDataStream::Qt_4_9);
+}
+
+void tst_QVariant::dataStream_data(QDataStream::Version version)
+{
+ QTest::addColumn<QString>("fileName");
+
+ QString path;
+ switch (version) {
+ case QDataStream::Qt_4_9:
+ path = QString::fromLatin1("qt4.9");
+ break;
+ case QDataStream::Qt_5_0:
+ path = QString::fromLatin1("qt5.0");
+ break;
+ default:
+ Q_UNIMPLEMENTED();
+ }
+
+ path = path.prepend(":/stream/").append("/");
+ QDir dir(path);
+ uint i = 0;
+ foreach (const QFileInfo &fileInfo, dir.entryInfoList(QStringList() << "*.bin")) {
+ QTest::newRow((path + fileInfo.fileName()).toLatin1()) << fileInfo.filePath();
+ i += 1;
+ }
+ QVERIFY(i > 10);
+}
+
+void tst_QVariant::loadQVariantFromDataStream(QDataStream::Version version)
+{
+ QFETCH(QString, fileName);
+
+ QFile file(fileName);
+ QVERIFY(file.open(QIODevice::ReadOnly));
+
+ QDataStream stream(&file);
+ stream.setVersion(version);
+
+ QString typeName;
+ QVariant loadedVariant;
+ stream >> typeName >> loadedVariant;
+
+ const int id = QMetaType::type(typeName.toLatin1());
+ QVariant constructedVariant(static_cast<QVariant::Type>(id));
+ QCOMPARE(constructedVariant.userType(), id);
+ QCOMPARE(QMetaType::typeName(loadedVariant.userType()), typeName.toLatin1().constData());
+ QCOMPARE(loadedVariant.userType(), constructedVariant.userType());
+}
+
+void tst_QVariant::saveQVariantFromDataStream(QDataStream::Version version)
+{
+ QFETCH(QString, fileName);
+
+ QFile file(fileName);
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QDataStream dataFileStream(&file);
+
+ QString typeName;
+ dataFileStream >> typeName;
+ QByteArray data = file.readAll();
+ const int id = QMetaType::type(typeName.toLatin1());
+
+ QBuffer buffer;
+ buffer.open(QIODevice::ReadWrite);
+ QDataStream stream(&buffer);
+ stream.setVersion(version);
+
+ QVariant constructedVariant(static_cast<QVariant::Type>(id));
+ QCOMPARE(constructedVariant.userType(), id);
+ stream << constructedVariant;
+
+ // We are testing QVariant there is no point in testing full array.
+ QCOMPARE(buffer.data().left(5), data.left(5));
+
+ buffer.seek(0);
+ QVariant recunstructedVariant;
+ stream >> recunstructedVariant;
+ QCOMPARE(recunstructedVariant.userType(), constructedVariant.userType());
+}
class MessageHandler {
public:
QVERIFY(msgHandler.testPassed());
}
-
QTEST_MAIN(tst_QVariant)
#include "tst_qvariant.moc"
QTest::addColumn<int>("typeId");
for (int i = 0; i <= QMetaType::LastCoreType; ++i)
QTest::newRow(QMetaType::typeName(i)) << i;
- for (int i = QMetaType::FirstCoreExtType; i <= QMetaType::LastCoreExtType; ++i)
- QTest::newRow(QMetaType::typeName(i)) << i;
// GUI types are tested in tst_QGuiMetaType.
}
QTest::addColumn<int>("typeId");
for (int i = 0; i <= QMetaType::LastCoreType; ++i)
QTest::newRow(QMetaType::typeName(i)) << i;
- for (int i = QMetaType::FirstCoreExtType; i <= QMetaType::LastCoreExtType; ++i)
- QTest::newRow(QMetaType::typeName(i)) << i;
}
// Tests how fast a Qt core type can be default-constructed by a