Adapt the ValueTypeProvider interface and port its types
authorFrank Meerkoetter <frank.meerkoetter@basyskom.com>
Sat, 25 Jul 2015 17:43:43 +0000 (19:43 +0200)
committerSimon Hausmann <simon.hausmann@theqtcompany.com>
Tue, 18 Aug 2015 20:26:00 +0000 (20:26 +0000)
The ValueTypeProvider system allows non-QML modules to add new basic
QML types. It needs to be changed when porting away from QQmlVmeVariant
as underlying type of properties.

Change-Id: I2b52d7e6f578647a39832896c28553404b9a679f
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
src/qml/qml/qqmlglobal.cpp
src/qml/qml/qqmlglobal_p.h
src/qml/qml/qqmlvmemetaobject.cpp
src/quick/util/qquickglobal.cpp

index 2e772eaaf0f3b3673e241de2c49666678f3fcda2..17de696af346845b9128b1344562ef7082659609 100644 (file)
@@ -62,13 +62,11 @@ const QMetaObject *QQmlValueTypeProvider::metaObjectForMetaType(int type)
     return 0;
 }
 
-bool QQmlValueTypeProvider::initValueType(int type, void *data, size_t n)
+bool QQmlValueTypeProvider::initValueType(int type, QVariant& dst)
 {
-    Q_ASSERT(data);
-
     QQmlValueTypeProvider *p = this;
     do {
-        if (p->init(type, data, n))
+        if (p->init(type, dst))
             return true;
     } while ((p = p->next));
 
@@ -174,14 +172,13 @@ QVariant QQmlValueTypeProvider::createVariantFromJsObject(int type, QQmlV4Handle
     return QVariant();
 }
 
-bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const void *rhs, size_t rhsSize)
+bool QQmlValueTypeProvider::equalValueType(int type, const void *lhs, const QVariant& rhs)
 {
     Q_ASSERT(lhs);
-    Q_ASSERT(rhs);
 
     QQmlValueTypeProvider *p = this;
     do {
-        if (p->equal(type, lhs, rhs, rhsSize))
+        if (p->equal(type, lhs, rhs))
             return true;
     } while ((p = p->next));
 
@@ -202,28 +199,26 @@ bool QQmlValueTypeProvider::storeValueType(int type, const void *src, void *dst,
     return false;
 }
 
-bool QQmlValueTypeProvider::readValueType(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+bool QQmlValueTypeProvider::readValueType(const QVariant& src, void *dst, int dstType)
 {
-    Q_ASSERT(src);
     Q_ASSERT(dst);
 
     QQmlValueTypeProvider *p = this;
     do {
-        if (p->read(srcType, src, srcSize, dstType, dst))
+        if (p->read(src, dst, dstType))
             return true;
     } while ((p = p->next));
 
     return false;
 }
 
-bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst, size_t n)
+bool QQmlValueTypeProvider::writeValueType(int type, const void *src, QVariant& dst)
 {
     Q_ASSERT(src);
-    Q_ASSERT(dst);
 
     QQmlValueTypeProvider *p = this;
     do {
-        if (p->write(type, src, dst, n))
+        if (p->write(type, src, dst))
             return true;
     } while ((p = p->next));
 
@@ -231,7 +226,7 @@ bool QQmlValueTypeProvider::writeValueType(int type, const void *src, void *dst,
 }
 
 const QMetaObject *QQmlValueTypeProvider::getMetaObjectForMetaType(int) { return 0; }
-bool QQmlValueTypeProvider::init(int, void *, size_t) { return false; }
+bool QQmlValueTypeProvider::init(int, QVariant&) { return false; }
 bool QQmlValueTypeProvider::destroy(int, void *, size_t) { return false; }
 bool QQmlValueTypeProvider::create(int, int, const void *[], QVariant *) { return false; }
 bool QQmlValueTypeProvider::createFromString(int, const QString &, void *, size_t) { return false; }
@@ -239,10 +234,10 @@ bool QQmlValueTypeProvider::createStringFrom(int, const void *, QString *) { ret
 bool QQmlValueTypeProvider::variantFromString(const QString &, QVariant *) { return false; }
 bool QQmlValueTypeProvider::variantFromString(int, const QString &, QVariant *) { return false; }
 bool QQmlValueTypeProvider::variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *) { return false; }
-bool QQmlValueTypeProvider::equal(int, const void *, const void *, size_t) { return false; }
+bool QQmlValueTypeProvider::equal(int, const void *, const QVariant&) { return false; }
 bool QQmlValueTypeProvider::store(int, const void *, void *, size_t) { return false; }
-bool QQmlValueTypeProvider::read(int, const void *, size_t, int, void *) { return false; }
-bool QQmlValueTypeProvider::write(int, const void *, void *, size_t) { return false; }
+bool QQmlValueTypeProvider::read(const QVariant&, void *, int) { return false; }
+bool QQmlValueTypeProvider::write(int, const void *, QVariant&) { return false; }
 
 Q_GLOBAL_STATIC(QQmlValueTypeProvider, nullValueTypeProvider)
 static QQmlValueTypeProvider *valueTypeProvider = 0;
index 8ed044d2c9a9497b8e27c7b9e712830abb6ebce5..c19f7dab646504d53510d0ef32226e7c036cc8f8 100644 (file)
@@ -224,7 +224,7 @@ public:
 
     const QMetaObject *metaObjectForMetaType(int);
 
-    bool initValueType(int, void *, size_t);
+    bool initValueType(int, QVariant&);
     bool destroyValueType(int, void *, size_t);
 
     QVariant createValueType(int, int, const void *[]);
@@ -235,14 +235,14 @@ public:
     QVariant createVariantFromString(int, const QString &, bool *);
     QVariant createVariantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, bool*);
 
-    bool equalValueType(int, const void *, const void *, size_t);
+    bool equalValueType(int, const void *, const QVariant&);
     bool storeValueType(int, const void *, void *, size_t);
-    bool readValueType(int, const void *, size_t, int, void *);
-    bool writeValueType(int, const void *, void *, size_t);
+    bool readValueType(const QVariant&, void *, int);
+    bool writeValueType(int, const void *, QVariant&);
 
 private:
     virtual const QMetaObject *getMetaObjectForMetaType(int);
-    virtual bool init(int, void *, size_t);
+    virtual bool init(int, QVariant&);
     virtual bool destroy(int, void *, size_t);
 
     virtual bool create(int, int, const void *[], QVariant *);
@@ -253,10 +253,10 @@ private:
     virtual bool variantFromString(int, const QString &, QVariant *);
     virtual bool variantFromJsObject(int, QQmlV4Handle, QV4::ExecutionEngine *, QVariant *);
 
-    virtual bool equal(int, const void *, const void *, size_t);
+    virtual bool equal(int, const void *, const QVariant&);
     virtual bool store(int, const void *, void *, size_t);
-    virtual bool read(int, const void *, size_t, int, void *);
-    virtual bool write(int, const void *, void *, size_t);
+    virtual bool read(const QVariant&, void *, int);
+    virtual bool write(int, const void *, QVariant&);
 
     friend Q_QML_PRIVATE_EXPORT void QQml_addValueTypeProvider(QQmlValueTypeProvider *);
     friend Q_QML_PRIVATE_EXPORT void QQml_removeValueTypeProvider(QQmlValueTypeProvider *);
index 0d10550fab74f265a640f83b12767525d2fd68db..a96079762693410b9760ad78efc20b6b3e4c21a9 100644 (file)
@@ -1026,9 +1026,20 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
                             *reinterpret_cast<QVariant *>(a[0]) = readPropertyAsVariant(id);
                             break;
                         default:
-                            QQml_valueTypeProvider()->readValueType(data[id].dataType(), data[id].dataPtr(), data->dataSize(), t, a[0]);
+                        {
+                            if (ensurePropertiesAllocated()) {
+                                QV4::ExecutionEngine *v4 = properties.engine();
+                                QV4::Scope scope(v4);
+                                QV4::ScopedObject o(scope, properties.value());
+                                QV4::ScopedValue sv(scope, o->getIndexed(id));
+                                const QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+                                if (v) {
+                                    QQml_valueTypeProvider()->readValueType(v->d()->data, a[0], t);
+                                }
+                            }
                             break;
                         }
+                        }
                         if (t == qMetaTypeId<QQmlListProperty<QObject> >()) {
                             const int listIndex = readPropertyAsInt(id);
                             const List *list = &listProperties.at(listIndex);
@@ -1088,12 +1099,26 @@ int QQmlVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
                         case QMetaType::QVariant:
                             writeProperty(id, *reinterpret_cast<QVariant *>(a[0]));
                             break;
-                        default:
-                            data[id].ensureValueType(t);
-                            needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
-                            QQml_valueTypeProvider()->writeValueType(t, a[0], data[id].dataPtr(), data[id].dataSize());
+                        default: {
+                            if (ensurePropertiesAllocated()) {
+                                QV4::ExecutionEngine *v4 = properties.engine();
+                                QV4::Scope scope(v4);
+                                QV4::ScopedObject o(scope, properties.value());
+                                QV4::ScopedValue sv(scope, o->getIndexed(id));
+                                QV4::VariantObject *v = sv->as<QV4::VariantObject>();
+                                if (!v) {
+                                    QV4::ScopedValue svo(scope, properties.engine()->newVariantObject(QVariant()));
+                                    o->putIndexed(id, svo);
+                                    svo = o->getIndexed(id);
+                                    v = svo->as<QV4::VariantObject>();
+                                }
+                                QQmlValueTypeProvider().initValueType(t, v->d()->data);
+                                needActivate = !QQml_valueTypeProvider()->equalValueType(t, a[0], v->d()->data);
+                                QQml_valueTypeProvider()->writeValueType(t, a[0], v->d()->data);
+                            }
                             break;
                         }
+                        }
                     }
 
                 }
index fd172006e017b192a02d9baaa3b8f91ae7a5a5d6..adf3a68e922eaf52a8e7f533bba9e0ec50154caf 100644 (file)
@@ -397,41 +397,30 @@ public:
         return 0;
     }
 
-    template<typename T>
-    bool typedInit(void *data, size_t dataSize)
-    {
-        ASSERT_VALID_SIZE(dataSize, sizeof(T));
-        T *t = reinterpret_cast<T *>(data);
-        new (t) T();
-        return true;
-    }
-
-    bool init(int type, void *data, size_t dataSize)
+    bool init(int type, QVariant& dst)
     {
         switch (type) {
         case QMetaType::QColor:
-            return typedInit<QColor>(data, dataSize);
+            dst.setValue<QColor>(QColor());
+            return true;
         case QMetaType::QFont:
-            return typedInit<QFont>(data, dataSize);
+            dst.setValue<QFont>(QFont());
+            return true;
         case QMetaType::QVector2D:
-            return typedInit<QVector2D>(data, dataSize);
+            dst.setValue<QVector2D>(QVector2D());
+            return true;
         case QMetaType::QVector3D:
-            return typedInit<QVector3D>(data, dataSize);
+            dst.setValue<QVector3D>(QVector3D());
+            return true;
         case QMetaType::QVector4D:
-            return typedInit<QVector4D>(data, dataSize);
+            dst.setValue<QVector4D>(QVector4D());
+            return true;
         case QMetaType::QQuaternion:
-            return typedInit<QQuaternion>(data, dataSize);
+            dst.setValue<QQuaternion>(QQuaternion());
+            return true;
         case QMetaType::QMatrix4x4:
-            {
-            if (dataSize >= sizeof(QMatrix4x4))
-                return typedInit<QMatrix4x4>(data, dataSize);
-
-            // special case: init matrix-containing qvariant.
-            Q_ASSERT(dataSize >= sizeof(QVariant));
-            QVariant *matvar = reinterpret_cast<QVariant *>(data);
-            new (matvar) QVariant(QMatrix4x4());
+            dst.setValue<QMatrix4x4>(QMatrix4x4());
             return true;
-            }
         default: break;
         }
 
@@ -691,12 +680,12 @@ public:
     }
 
     template<typename T>
-    bool typedEqual(const void *lhs, const void *rhs)
+    bool typedEqual(const void *lhs, const QVariant& rhs)
     {
-        return (*(reinterpret_cast<const T *>(lhs)) == *(reinterpret_cast<const T *>(rhs)));
+        return (*(reinterpret_cast<const T *>(lhs)) == rhs.value<T>());
     }
 
-    bool equal(int type, const void *lhs, const void *rhs, size_t rhsSize)
+    bool equal(int type, const void *lhs, const QVariant &rhs)
     {
         switch (type) {
         case QMetaType::QColor:
@@ -712,14 +701,7 @@ public:
         case QMetaType::QQuaternion:
             return typedEqual<QQuaternion>(lhs, rhs);
         case QMetaType::QMatrix4x4:
-            {
-            if (rhsSize >= sizeof(QMatrix4x4))
-                return typedEqual<QMatrix4x4>(lhs, rhs);
-
-            Q_ASSERT(rhsSize >= sizeof(QVariant));
-            QMatrix4x4 rhsmat = reinterpret_cast<const QVariant *>(rhs)->value<QMatrix4x4>();
-            return typedEqual<QMatrix4x4>(lhs, &rhsmat);
-            }
+            return typedEqual<QMatrix4x4>(lhs, rhs);
         default: break;
         }
 
@@ -778,50 +760,34 @@ public:
     }
 
     template<typename T>
-    bool typedRead(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+    bool typedRead(const QVariant& src, int dstType, void *dst)
     {
         T *dstT = reinterpret_cast<T *>(dst);
-        if (srcType == dstType) {
-            ASSERT_VALID_SIZE(srcSize, sizeof(T));
-            const T *srcT = reinterpret_cast<const T *>(src);
-            *dstT = *srcT;
+        if (src.type() == static_cast<uint>(dstType)) {
+            *dstT = src.value<T>();
         } else {
             *dstT = T();
         }
         return true;
     }
 
-    bool read(int srcType, const void *src, size_t srcSize, int dstType, void *dst)
+    bool read(const QVariant &src, void *dst, int dstType)
     {
         switch (dstType) {
         case QMetaType::QColor:
-            return typedRead<QColor>(srcType, src, srcSize, dstType, dst);
+            return typedRead<QColor>(src, dstType, dst);
         case QMetaType::QFont:
-            return typedRead<QFont>(srcType, src, srcSize, dstType, dst);
+            return typedRead<QFont>(src, dstType, dst);
         case QMetaType::QVector2D:
-            return typedRead<QVector2D>(srcType, src, srcSize, dstType, dst);
+            return typedRead<QVector2D>(src, dstType, dst);
         case QMetaType::QVector3D:
-            return typedRead<QVector3D>(srcType, src, srcSize, dstType, dst);
+            return typedRead<QVector3D>(src, dstType, dst);
         case QMetaType::QVector4D:
-            return typedRead<QVector4D>(srcType, src, srcSize, dstType, dst);
+            return typedRead<QVector4D>(src, dstType, dst);
         case QMetaType::QQuaternion:
-            return typedRead<QQuaternion>(srcType, src, srcSize, dstType, dst);
+            return typedRead<QQuaternion>(src, dstType, dst);
         case QMetaType::QMatrix4x4:
-            {
-            if (srcSize >= sizeof(QMatrix4x4))
-                return typedRead<QMatrix4x4>(srcType, src, srcSize, dstType, dst);
-
-            // the source data may be stored in a QVariant.
-            QMatrix4x4 *dstMat = reinterpret_cast<QMatrix4x4 *>(dst);
-            if (srcType == dstType) {
-                Q_ASSERT(srcSize >= sizeof(QVariant));
-                const QVariant *srcMatVar = reinterpret_cast<const QVariant *>(src);
-                *dstMat = srcMatVar->value<QMatrix4x4>();
-            } else {
-                *dstMat = QMatrix4x4();
-            }
-            return true;
-            }
+            return typedRead<QMatrix4x4>(src, dstType, dst);
         default: break;
         }
 
@@ -829,51 +795,33 @@ public:
     }
 
     template<typename T>
-    bool typedWrite(const void *src, void *dst, size_t dstSize)
+    bool typedWrite(const void *src, QVariant& dst)
     {
-        ASSERT_VALID_SIZE(dstSize, sizeof(T));
         const T *srcT = reinterpret_cast<const T *>(src);
-        T *dstT = reinterpret_cast<T *>(dst);
-        if (*dstT != *srcT) {
-            *dstT = *srcT;
+        if (dst.value<T>() != *srcT) {
+            dst = *srcT;
             return true;
         }
         return false;
     }
 
-    bool write(int type, const void *src, void *dst, size_t dstSize)
+    bool write(int type, const void *src, QVariant& dst)
     {
         switch (type) {
         case QMetaType::QColor:
-            return typedWrite<QColor>(src, dst, dstSize);
+            return typedWrite<QColor>(src, dst);
         case QMetaType::QFont:
-            return typedWrite<QFont>(src, dst, dstSize);
+            return typedWrite<QFont>(src, dst);
         case QMetaType::QVector2D:
-            return typedWrite<QVector2D>(src, dst, dstSize);
+            return typedWrite<QVector2D>(src, dst);
         case QMetaType::QVector3D:
-            return typedWrite<QVector3D>(src, dst, dstSize);
+            return typedWrite<QVector3D>(src, dst);
         case QMetaType::QVector4D:
-            return typedWrite<QVector4D>(src, dst, dstSize);
+            return typedWrite<QVector4D>(src, dst);
         case QMetaType::QQuaternion:
-            return typedWrite<QQuaternion>(src, dst, dstSize);
+            return typedWrite<QQuaternion>(src, dst);
         case QMetaType::QMatrix4x4:
-            {
-            if (dstSize >= sizeof(QMatrix4x4))
-                return typedWrite<QMatrix4x4>(src, dst, dstSize);
-
-            // special case: storing matrix into variant
-            // eg, QVMEMO QVMEVariant data cell is big enough to store
-            // QVariant, but not large enough to store QMatrix4x4.
-            Q_ASSERT(dstSize >= sizeof(QVariant));
-            const QMatrix4x4 *srcMat = reinterpret_cast<const QMatrix4x4 *>(src);
-            QVariant *dstMatVar = reinterpret_cast<QVariant *>(dst);
-            QMatrix4x4 dstMatVal = dstMatVar->value<QMatrix4x4>();
-            if (dstMatVal != *srcMat) {
-                *dstMatVar = QVariant(*srcMat);
-                return true;
-            }
-            return false;
-            }
+            return typedWrite<QMatrix4x4>(src, dst);
         default: break;
         }