Qt - QVariant
QVariant相当于一个包含大多数Qt数据类型的联合体
将数据存储为一个Private结构体类型的成员变量d:
<qvariant.cpp>
1 QVariant::QVariant(Type type) 2 { create(type, 0); }
1 void QVariant::create(int type, const void *copy) 2 { 3 d.type = type; 4 handler->construct(&d, copy); 5 }
static void construct(QVariant::Private *x, const void *copy) { x->is_shared = false; switch (x->type) { case QVariant::String: v_construct<QString>(x, copy); break; ...... default: void *ptr = QMetaType::construct(x->type, copy); if (!ptr) { x->type = QVariant::Invalid; } else { x->is_shared = true; x->data.shared = new QVariant::PrivateShared(ptr); } break; } x->is_null = !copy; }
1 QVariant::QVariant(int val) 2 { d.is_null = false; d.type = Int; d.data.i = val; }
<qvariant.h>
class Q_CORE_EXPORT QVariant { ...... struct Private { inline Private(): type(Invalid), is_shared(false), is_null(true) { data.ptr = 0; } inline Private(const Private &other) : data(other.data), type(other.type), is_shared(other.is_shared), is_null(other.is_null) {} union Data { char c; int i; uint u; bool b; double d; float f; qreal real; qlonglong ll; qulonglong ull; QObject *o; void *ptr; PrivateShared *shared; } data; uint type : 30; uint is_shared : 1; uint is_null : 1; }; ...... Private d; ...... }
QVariant支持的数据类型:
1 enum Type { 2 Invalid = 0, 3 4 Bool = 1, 5 Int = 2, 6 UInt = 3, 7 LongLong = 4, 8 ULongLong = 5, 9 Double = 6, 10 Char = 7, 11 Map = 8, 12 List = 9, 13 String = 10, 14 StringList = 11, 15 ByteArray = 12, 16 BitArray = 13, 17 Date = 14, 18 Time = 15, 19 DateTime = 16, 20 Url = 17, 21 Locale = 18, 22 Rect = 19, 23 RectF = 20, 24 Size = 21, 25 SizeF = 22, 26 Line = 23, 27 LineF = 24, 28 Point = 25, 29 PointF = 26, 30 RegExp = 27, 31 Hash = 28, 32 EasingCurve = 29, 33 LastCoreType = EasingCurve, 34 35 // value 62 is internally reserved 36 #ifdef QT3_SUPPORT 37 ColorGroup = 63, 38 #endif 39 Font = 64, 40 Pixmap = 65, 41 Brush = 66, 42 Color = 67, 43 Palette = 68, 44 Icon = 69, 45 Image = 70, 46 Polygon = 71, 47 Region = 72, 48 Bitmap = 73, 49 Cursor = 74, 50 SizePolicy = 75, 51 KeySequence = 76, 52 Pen = 77, 53 TextLength = 78, 54 TextFormat = 79, 55 Matrix = 80, 56 Transform = 81, 57 Matrix4x4 = 82, 58 Vector2D = 83, 59 Vector3D = 84, 60 Vector4D = 85, 61 Quaternion = 86, 62 LastGuiType = Quaternion, 63 64 UserType = 127, 65 #ifdef QT3_SUPPORT 66 IconSet = Icon, 67 CString = ByteArray, 68 PointArray = Polygon, 69 #endif 70 LastType = 0xffffffff // need this so that gcc >= 3.4 allocates 32 bits for Type 71 };
数据类型转换:
以下数据类型可以自动转换
可通过成员函数bool QVariant::canConvert ( Type t ) const确定是否可执行指定数据类型的转换
自定义QVariant可存储的数据类型:
class Q_CORE_EXPORT QVariant { ...... template<typename T> bool canConvert() const { return canConvert(Type(qMetaTypeId<T>())); } ...... }
1 static inline QVariant fromValue(const T &value) 2 { return qVariantFromValue(value); }
template <typename T> inline QVariant qVariantFromValue(const T &t) { return QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t, QTypeInfo<T>::isPointer); }
从类的声明中可以看出,要成为QVariant可存储的数据类型,必须将该自定义数据类型通过宏Q_DECLARE_METATYPE (Type)注册到MetaType系统中
<qmetatype.h>
1 #define Q_DECLARE_METATYPE(TYPE) \ 2 QT_BEGIN_NAMESPACE \ 3 template <> \ 4 struct QMetaTypeId< TYPE > \ 5 { \ 6 enum { Defined = 1 }; \ 7 static int qt_metatype_id() \ 8 { \ 9 static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \ 10 if (!metatype_id) \ 11 metatype_id = qRegisterMetaType< TYPE >(#TYPE, \ 12 reinterpret_cast< TYPE *>(quintptr(-1))); \ 13 return metatype_id; \ 14 } \ 15 }; \ 16 QT_END_NAMESPACE
示例:
namespace MyNamespace { struct MyStruct { int i; ... }; } Q_DECLARE_METATYPE(MyNamespace::MyStruct)
1 MyStruct s; 2 QVariant var; 3 var.setValue(s); 4 5 ...... 6 7 QVariant var2 = QVariant::fromValue(s); 8 if (var2.canConvert<MyStruct>()) 9 { 10 MyStruct s2 = var2.value<MyStruct>(); 11 }