Delay conversion of v8 exceptions to QQmlErrors.
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlproperty.cpp
index 00cb65d..2a8aa32 100644 (file)
 #include "qqmlcompiler_p.h"
 #include "qqmlvmemetaobject_p.h"
 #include "qqmlexpression_p.h"
+#include "qqmlvaluetypeproxybinding_p.h"
 
 #include <QStringList>
 #include <QtCore/qdebug.h>
 
 #include <math.h>
 
+Q_DECLARE_METATYPE(QJSValue)
 Q_DECLARE_METATYPE(QList<int>)
 Q_DECLARE_METATYPE(QList<qreal>)
 Q_DECLARE_METATYPE(QList<bool>)
@@ -71,7 +73,8 @@ QT_BEGIN_NAMESPACE
 
 /*!
 \class QQmlProperty
-\since 4.7
+\since 5.0
+\inmodule QtQml
 \brief The QQmlProperty class abstracts accessing properties on objects created from  QML.
 
 As QML uses Qt's meta-type system all of the existing QMetaObject classes can be used to introspect
@@ -107,6 +110,8 @@ qWarning() << "Current pixel size:" << property.read().toInt();
 property.write(24);
 qWarning() << "Pixel size should now be 24:" << property.read().toInt();
 \endcode
+
+The QtQuick 1 version of this class was named QDeclarativeProperty.
 */
 
 /*!
@@ -332,11 +337,44 @@ void QQmlPropertyPrivate::initProperty(QObject *obj, const QString &name)
         QString signalName = terminal.mid(2);
         signalName[0] = signalName.at(0).toLower();
 
-        QMetaMethod method = findSignalByName(currentObject->metaObject(), signalName.toLatin1().constData());
-        if (method.signature()) {
-            object = currentObject;
-            core.load(method);
-            return;
+        // XXX - this code treats methods as signals
+
+        QQmlData *ddata = QQmlData::get(currentObject, false);
+        if (ddata && ddata->propertyCache) {
+
+            // Try method
+            QQmlPropertyData *d = ddata->propertyCache->property(signalName);
+            while (d && !d->isFunction())
+                d = ddata->propertyCache->overrideData(d);
+
+            if (d) {
+                object = currentObject;
+                core = *d;
+                return;
+            }
+
+            // Try property
+            if (signalName.endsWith(QLatin1String("Changed"))) {
+                QString propName = signalName.mid(0, signalName.length() - 7);
+                QQmlPropertyData *d = ddata->propertyCache->property(propName);
+                while (d && d->isFunction())
+                    d = ddata->propertyCache->overrideData(d);
+
+                if (d && d->notifyIndex != -1) {
+                    object = currentObject;
+                    core = *ddata->propertyCache->method(d->notifyIndex);
+                    return;
+                }
+            }
+
+        } else {
+            QMetaMethod method = findSignalByName(currentObject->metaObject(),
+                                                  signalName.toLatin1().constData());
+            if (method.isValid()) {
+                object = currentObject;
+                core.load(method);
+                return;
+            }
         }
     }
 
@@ -730,8 +768,7 @@ QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
     QQmlPropertyData *propertyData =
         data->propertyCache?data->propertyCache->property(coreIndex):0;
     if (propertyData && propertyData->isAlias()) {
-        const QQmlVMEMetaObject *vme = 
-            static_cast<const QQmlVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
+        QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
 
         QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
         if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex) || aCoreIndex == -1)
@@ -748,7 +785,7 @@ QQmlPropertyPrivate::binding(QObject *object, int coreIndex, int valueTypeIndex)
 
     QQmlAbstractBinding *binding = data->bindings;
     while (binding && binding->propertyIndex() != coreIndex)
-        binding = binding->m_nextBinding;
+        binding = binding->nextBinding();
 
     if (binding && valueTypeIndex != -1) {
         if (binding->bindingType() == QQmlAbstractBinding::ValueTypeProxy) {
@@ -772,8 +809,8 @@ void QQmlPropertyPrivate::findAliasTarget(QObject *object, int bindingIndex,
         QQmlPropertyData *propertyData =
             data->propertyCache?data->propertyCache->property(coreIndex):0;
         if (propertyData && propertyData->isAlias()) {
-            const QQmlVMEMetaObject *vme = 
-                static_cast<const QQmlVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
+            QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
+
             QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
             if (vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
                 // This will either be a value type sub-reference or an alias to a value-type sub-reference not both
@@ -806,8 +843,7 @@ QQmlPropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeInd
         QQmlPropertyData *propertyData =
             data->propertyCache?data->propertyCache->property(coreIndex):0;
         if (propertyData && propertyData->isAlias()) {
-            const QQmlVMEMetaObject *vme = 
-                static_cast<const QQmlVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
+            QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
 
             QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
             if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
@@ -826,7 +862,7 @@ QQmlPropertyPrivate::setBinding(QObject *object, int coreIndex, int valueTypeInd
         binding = data->bindings;
 
         while (binding && binding->propertyIndex() != coreIndex) 
-            binding = binding->m_nextBinding;
+            binding = binding->nextBinding();
     }
 
     int index = coreIndex;
@@ -866,8 +902,7 @@ QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valu
         QQmlPropertyData *propertyData =
             data->propertyCache?data->propertyCache->property(coreIndex):0;
         if (propertyData && propertyData->isAlias()) {
-            const QQmlVMEMetaObject *vme = 
-                static_cast<const QQmlVMEMetaObject *>(metaObjectForProperty(object->metaObject(), coreIndex));
+            QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForProperty(object, coreIndex);
 
             QObject *aObject = 0; int aCoreIndex = -1; int aValueTypeIndex = -1;
             if (!vme->aliasTarget(coreIndex, &aObject, &aCoreIndex, &aValueTypeIndex)) {
@@ -886,7 +921,7 @@ QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valu
         binding = data->bindings;
 
         while (binding && binding->propertyIndex() != coreIndex) 
-            binding = binding->m_nextBinding;
+            binding = binding->nextBinding();
     }
 
     int index = coreIndex;
@@ -916,57 +951,78 @@ QQmlPropertyPrivate::setBindingNoEnable(QObject *object, int coreIndex, int valu
     Returns the expression associated with this signal property, or 0 if no 
     signal expression exists.
 */
-QQmlExpression *
+QQmlBoundSignalExpression *
 QQmlPropertyPrivate::signalExpression(const QQmlProperty &that)
 {
     if (!(that.type() & QQmlProperty::SignalProperty))
         return 0;
 
-    const QObjectList &children = that.d->object->children();
-    
-    for (int ii = 0; ii < children.count(); ++ii) {
-        QObject *child = children.at(ii);
+    QQmlData *data = QQmlData::get(that.d->object);
+    if (!data)
+        return 0;
 
-        QQmlBoundSignal *signal = QQmlBoundSignal::cast(child);
-        if (signal && signal->index() == that.index()) 
-            return signal->expression();
-    }
+    QQmlAbstractBoundSignal *signalHandler = data->signalHandlers;
+
+    while (signalHandler && signalHandler->index() != that.index())
+        signalHandler = signalHandler->m_nextSignal;
+
+    if (signalHandler)
+        return signalHandler->expression();
 
     return 0;
 }
 
 /*!
     Set the signal expression associated with this signal property to \a expr.
-    Returns the existing signal expression (if any), otherwise 0.
+    Returns the existing signal expression (if any), otherwise null.
 
-    Ownership of \a expr transfers to QML.  Ownership of the return value is
-    assumed by the caller.
+    A reference to \a expr will be added by QML.  Ownership of the return value
+    reference is assumed by the caller.
 */
-QQmlExpression *
+QQmlBoundSignalExpressionPointer
 QQmlPropertyPrivate::setSignalExpression(const QQmlProperty &that,
-                                                     QQmlExpression *expr) 
+                                         QQmlBoundSignalExpression *expr)
+{
+    if (expr)
+        expr->addref();
+    return QQmlPropertyPrivate::takeSignalExpression(that, expr);
+}
+
+/*!
+    Set the signal expression associated with this signal property to \a expr.
+    Returns the existing signal expression (if any), otherwise null.
+
+    Ownership of \a expr transfers to QML.  Ownership of the return value
+    reference is assumed by the caller.
+*/
+QQmlBoundSignalExpressionPointer
+QQmlPropertyPrivate::takeSignalExpression(const QQmlProperty &that,
+                                         QQmlBoundSignalExpression *expr)
 {
     if (!(that.type() & QQmlProperty::SignalProperty)) {
-        delete expr;
+        if (expr)
+            expr->release();
         return 0;
     }
 
-    const QObjectList &children = that.d->object->children();
-    
-    for (int ii = 0; ii < children.count(); ++ii) {
-        QObject *child = children.at(ii);
+    QQmlData *data = QQmlData::get(that.d->object, 0 != expr);
+    if (!data)
+        return 0;
 
-        QQmlBoundSignal *signal = QQmlBoundSignal::cast(child);
-        if (signal && signal->index() == that.index()) 
-            return signal->setExpression(expr);
-    }
+    QQmlAbstractBoundSignal *signalHandler = data->signalHandlers;
+
+    while (signalHandler && signalHandler->index() != that.index())
+        signalHandler = signalHandler->m_nextSignal;
+
+    if (signalHandler)
+        return signalHandler->takeExpression(expr);
 
     if (expr) {
-        QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, that.method(), that.d->object);
-        return signal->setExpression(expr);
-    } else {
-        return 0;
+        QQmlBoundSignal *signal = new QQmlBoundSignal(that.d->object, that.index(), that.d->object,
+                                                      expr->context()->engine);
+        signal->takeExpression(expr);
     }
+    return 0;
 }
 
 /*!
@@ -1070,25 +1126,24 @@ QVariant QQmlPropertyPrivate::readValueProperty()
 
     } else {
 
-        return object->metaObject()->property(core.coreIndex).read(object.data());
+        if (!core.propType) // Unregistered type
+            return object->metaObject()->property(core.coreIndex).read(object);
 
-    }
-}
+        QVariant value;
+        int status = -1;
+        void *args[] = { 0, &value, &status };
+        if (core.propType == QMetaType::QVariant) {
+            args[0] = &value;
+        } else {
+            value = QVariant(core.propType, (void*)0);
+            args[0] = value.data();
+        }
+        QMetaObject::metacall(object, QMetaObject::ReadProperty, core.coreIndex, args);
+        if (core.propType != QMetaType::QVariant && args[0] != value.data())
+            return QVariant((QVariant::Type)core.propType, args[0]);
 
-static QUrl urlFromUserString(const QByteArray &data)
-{
-    QUrl u;
-    if (!data.isEmpty())
-    {
-        // Preserve any valid percent-encoded octets supplied by the source
-        u.setEncodedUrl(data, QUrl::TolerantMode);
+        return value;
     }
-    return u;
-}
-
-static QUrl urlFromUserString(const QString &data)
-{
-    return urlFromUserString(data.toUtf8());
 }
 
 // helper function to allow assignment / binding to QList<QUrl> properties.
@@ -1098,19 +1153,19 @@ static QVariant resolvedUrlSequence(const QVariant &value, QQmlContextData *cont
     if (value.userType() == qMetaTypeId<QUrl>()) {
         urls.append(value.toUrl());
     } else if (value.userType() == qMetaTypeId<QString>()) {
-        urls.append(urlFromUserString(value.toString()));
+        urls.append(QUrl(value.toString()));
     } else if (value.userType() == qMetaTypeId<QByteArray>()) {
-        urls.append(urlFromUserString(value.toByteArray()));
+        urls.append(QUrl(QString::fromUtf8(value.toByteArray())));
     } else if (value.userType() == qMetaTypeId<QList<QUrl> >()) {
         urls = value.value<QList<QUrl> >();
     } else if (value.userType() == qMetaTypeId<QStringList>()) {
         QStringList urlStrings = value.value<QStringList>();
         for (int i = 0; i < urlStrings.size(); ++i)
-            urls.append(urlFromUserString(urlStrings.at(i)));
+            urls.append(QUrl(urlStrings.at(i)));
     } else if (value.userType() == qMetaTypeId<QList<QString> >()) {
         QList<QString> urlStrings = value.value<QList<QString> >();
         for (int i = 0; i < urlStrings.size(); ++i)
-            urls.append(urlFromUserString(urlStrings.at(i)));
+            urls.append(QUrl(urlStrings.at(i)));
     } // note: QList<QByteArray> is not currently supported.
 
     QList<QUrl> resolvedUrls;
@@ -1147,7 +1202,7 @@ bool QQmlPropertyPrivate::writeEnumProperty(const QMetaProperty &prop, int idx,
                 return false;
         } else if (v.userType() != QVariant::Int && v.userType() != QVariant::UInt) {
             int enumMetaTypeId = QMetaType::type(QByteArray(menum.scope() + QByteArray("::") + menum.name()));
-            if ((enumMetaTypeId == 0) || (v.userType() != enumMetaTypeId) || !v.constData())
+            if ((enumMetaTypeId == QMetaType::UnknownType) || (v.userType() != enumMetaTypeId) || !v.constData())
                 return false;
             v = QVariant(*reinterpret_cast<const int *>(v.constData()));
         }
@@ -1250,10 +1305,10 @@ bool QQmlPropertyPrivate::write(QObject *object,
             u = value.toUrl();
             found = true;
         } else if (variantType == QVariant::ByteArray) {
-            u = urlFromUserString(value.toByteArray());
+            u = QUrl(QString::fromUtf8(value.toByteArray()));
             found = true;
         } else if (variantType == QVariant::String) {
-            u = urlFromUserString(value.toString());
+            u = QUrl(value.toString());
             found = true;
         }
 
@@ -1283,34 +1338,33 @@ bool QQmlPropertyPrivate::write(QObject *object,
 
     } else if (property.isQObject()) {
 
-        const QMetaObject *valMo = rawMetaObjectForType(enginePriv, value.userType());
+        QQmlMetaObject valMo = rawMetaObjectForType(enginePriv, value.userType());
         
-        if (!valMo)
+        if (valMo.isNull())
             return false;
 
         QObject *o = *(QObject **)value.constData();
-        const QMetaObject *propMo = rawMetaObjectForType(enginePriv, propertyType);
+        QQmlMetaObject propMo = rawMetaObjectForType(enginePriv, propertyType);
 
-        if (o) valMo = o->metaObject();
+        if (o) valMo = o;
 
-        if (canConvert(valMo, propMo)) {
+        if (QQmlMetaObject::canConvert(valMo, propMo)) {
             void *args[] = { &o, 0, &status, &flags };
-            QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, 
-                                  args);
-        } else if (!o && canConvert(propMo, valMo)) {
+            QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args);
+        } else if (!o && QQmlMetaObject::canConvert(propMo, valMo)) {
             // In the case of a null QObject, we assign the null if there is 
             // any change that the null variant type could be up or down cast to 
             // the property type.
             void *args[] = { &o, 0, &status, &flags };
-            QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, 
-                                  args);
+            QMetaObject::metacall(object, QMetaObject::WriteProperty, coreIdx, args);
         } else {
             return false;
         }
 
     } else if (property.isQList()) {
 
-        const QMetaObject *listType = 0;
+        QQmlMetaObject listType;
+
         if (enginePriv) {
             listType = enginePriv->rawMetaObjectForType(enginePriv->listType(property.propType));
         } else {
@@ -1318,7 +1372,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
             if (!type) return false;
             listType = type->baseMetaObject();
         }
-        if (!listType) return false;
+        if (listType.isNull()) return false;
 
         QQmlListProperty<void> prop;
         void *args[] = { &prop, 0 };
@@ -1333,7 +1387,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
 
             for (int ii = 0; ii < qdlr.count(); ++ii) {
                 QObject *o = qdlr.at(ii);
-                if (o && !canConvert(o->metaObject(), listType))
+                if (o && !QQmlMetaObject::canConvert(o, listType))
                     o = 0;
                 prop.append(&prop, (void *)o);
             }
@@ -1342,13 +1396,13 @@ bool QQmlPropertyPrivate::write(QObject *object,
 
             for (int ii = 0; ii < list.count(); ++ii) {
                 QObject *o = list.at(ii);
-                if (o && !canConvert(o->metaObject(), listType))
+                if (o && !QQmlMetaObject::canConvert(o, listType))
                     o = 0;
                 prop.append(&prop, (void *)o);
             }
         } else {
             QObject *o = enginePriv?enginePriv->toQObject(value):QQmlMetaType::toQObject(value);
-            if (o && !canConvert(o->metaObject(), listType))
+            if (o && !QQmlMetaObject::canConvert(o, listType))
                 o = 0;
             prop.append(&prop, (void *)o);
         }
@@ -1362,7 +1416,7 @@ bool QQmlPropertyPrivate::write(QObject *object,
             v = QQmlStringConverters::variantFromString(value.toString(), propertyType, &ok);
         if (!ok) {
             v = value;
-            if (v.convert((QVariant::Type)propertyType)) {
+            if (v.convert(propertyType)) {
                 ok = true;
             } else if ((uint)propertyType >= QVariant::UserType && variantType == QVariant::String) {
                 QQmlMetaType::StringConverter con = QQmlMetaType::customStringConverter(propertyType);
@@ -1471,7 +1525,7 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
     QQmlJavaScriptExpression::DeleteWatcher watcher(expression);
 
     QVariant value;
-    bool isVmeProperty = core.isVMEProperty();
+    bool isVarProperty = core.isVarProperty();
 
     if (isUndefined) {
     } else if (core.isQList()) {
@@ -1480,36 +1534,50 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
         value = QVariant::fromValue((QObject *)0);
     } else if (core.propType == qMetaTypeId<QList<QUrl> >()) {
         value = resolvedUrlSequence(v8engine->toVariant(result, qMetaTypeId<QList<QUrl> >()), context);
-    } else if (!isVmeProperty) {
+    } else if (!isVarProperty && type != qMetaTypeId<QJSValue>()) {
         value = v8engine->toVariant(result, type);
     }
 
     if (expression->hasError()) {
         return false;
-    } else if (isVmeProperty) {
-        typedef QQmlVMEMetaObject VMEMO;
+    } else if (isVarProperty) {
         if (!result.IsEmpty() && result->IsFunction()
                 && !result->ToObject()->GetHiddenValue(v8engine->bindingFlagKey()).IsEmpty()) {
             // we explicitly disallow this case to avoid confusion.  Users can still store one
             // in an array in a var property if they need to, but the common case is user error.
-            expression->delayedError()->error.setDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+            expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
             return false;
         }
-        VMEMO *vmemo = static_cast<VMEMO *>(const_cast<QMetaObject *>(object->metaObject()));
+
+        typedef QQmlVMEMetaObject VMEMO;
+        QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
+        Q_ASSERT(vmemo);
         vmemo->setVMEProperty(core.coreIndex, result);
     } else if (isUndefined && core.isResettable()) {
         void *args[] = { 0 };
         QMetaObject::metacall(object, QMetaObject::ResetProperty, core.coreIndex, args);
     } else if (isUndefined && type == qMetaTypeId<QVariant>()) {
         writeValueProperty(object, engine, core, QVariant(), context, flags);
+    } else if (type == qMetaTypeId<QJSValue>()) {
+        if (!result.IsEmpty() && result->IsFunction()
+                && !result->ToObject()->GetHiddenValue(v8engine->bindingFlagKey()).IsEmpty()) {
+            expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+            return false;
+        }
+        writeValueProperty(object, engine, core, QVariant::fromValue(v8engine->scriptValueFromInternal(result)), context, flags);
     } else if (isUndefined) {
-        expression->delayedError()->error.setDescription(QLatin1String("Unable to assign [undefined] to ") + QLatin1String(QMetaType::typeName(type)));
+        QString errorStr = QLatin1String("Unable to assign [undefined] to ");
+        if (!QMetaType::typeName(type))
+            errorStr += QLatin1String("[unknown property type]");
+        else
+            errorStr += QLatin1String(QMetaType::typeName(type));
+        expression->delayedError()->setErrorDescription(errorStr);
         return false;
     } else if (result->IsFunction()) {
         if (!result->ToObject()->GetHiddenValue(v8engine->bindingFlagKey()).IsEmpty())
-            expression->delayedError()->error.setDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
+            expression->delayedError()->setErrorDescription(QLatin1String("Invalid use of Qt.binding() in a binding declaration."));
         else
-            expression->delayedError()->error.setDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
+            expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign a function to a property of any type other than var."));
         return false;
     } else if (!writeValueProperty(object, engine, core, value, context, flags)) {
 
@@ -1517,44 +1585,44 @@ bool QQmlPropertyPrivate::writeBinding(QObject *object,
             return true;
 
         const char *valueType = 0;
-        if (value.userType() == QVariant::Invalid) valueType = "null";
-        else valueType = QMetaType::typeName(value.userType());
+        const char *propertyType = 0;
+
+        if (value.userType() == QMetaType::QObjectStar) {
+            if (QObject *o = *(QObject **)value.constData()) {
+                valueType = o->metaObject()->className();
 
-        expression->delayedError()->error.setDescription(QLatin1String("Unable to assign ") +
-                                                         QLatin1String(valueType) +
-                                                         QLatin1String(" to ") +
-                                                         QLatin1String(QMetaType::typeName(type)));
+                QQmlMetaObject propertyMetaObject = rawMetaObjectForType(QQmlEnginePrivate::get(engine), type);
+                if (!propertyMetaObject.isNull())
+                    propertyType = propertyMetaObject.className();
+            }
+        } else if (value.userType() != QVariant::Invalid) {
+            valueType = QMetaType::typeName(value.userType());
+        }
+
+        if (!valueType)
+            valueType = "null";
+        if (!propertyType)
+            propertyType = QMetaType::typeName(type);
+        if (!propertyType)
+            propertyType = "[unknown property type]";
+
+        expression->delayedError()->setErrorDescription(QLatin1String("Unable to assign ") +
+                                                        QLatin1String(valueType) +
+                                                        QLatin1String(" to ") +
+                                                        QLatin1String(propertyType));
         return false;
     }
 
     return true;
 }
 
-bool QQmlPropertyPrivate::writeBinding(const QQmlProperty &that, 
-                                               QQmlContextData *context,
-                                               QQmlJavaScriptExpression *expression, 
-                                               v8::Handle<v8::Value> result, bool isUndefined,
-                                               WriteFlags flags)
-{
-    QQmlPropertyPrivate *pp = that.d;
-
-    if (!pp)
-        return true;
-
-    QObject *object = that.object();
-    if (!object)
-        return true;
-
-    return writeBinding(object, pp->core, context, expression, result, isUndefined, flags);
-}
-
-const QMetaObject *QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType)
+QQmlMetaObject QQmlPropertyPrivate::rawMetaObjectForType(QQmlEnginePrivate *engine, int userType)
 {
     if (engine) {
         return engine->rawMetaObjectForType(userType);
     } else {
         QQmlType *type = QQmlMetaType::qmlType(userType);
-        return type?type->baseMetaObject():0;
+        return QQmlMetaObject(type?type->baseMetaObject():0);
     }
 }
 
@@ -1707,7 +1775,7 @@ bool QQmlProperty::connectNotifySignal(QObject *dest, const char *slot) const
 
     QMetaProperty prop = d->object->metaObject()->property(d->core.coreIndex);
     if (prop.hasNotifySignal()) {
-        QByteArray signal(QByteArray("2") + prop.notifySignal().signature());
+        QByteArray signal('2' + prop.notifySignal().methodSignature());
         return QObject::connect(d->object, signal.constData(), dest, slot);
     } else  {
         return false;
@@ -1747,14 +1815,13 @@ int QQmlPropertyPrivate::bindingIndex(const QQmlPropertyData &that)
 }
 
 QQmlPropertyData
-QQmlPropertyPrivate::saveValueType(const QMetaObject *metaObject, int index, 
-                                           const QMetaObject *subObject, int subIndex,
-                                           QQmlEngine *)
+QQmlPropertyPrivate::saveValueType(const QQmlPropertyData &base,
+                                   const QMetaObject *subObject, int subIndex,
+                                   QQmlEngine *)
 {
     QMetaProperty subProp = subObject->property(subIndex);
 
-    QQmlPropertyData core;
-    core.load(metaObject->property(index));
+    QQmlPropertyData core = base;
     core.setFlags(core.getFlags() | QQmlPropertyData::IsValueTypeVirtual);
     core.valueTypeFlags = QQmlPropertyData::flagsForProperty(subProp);
     core.valueTypeCoreIndex = subIndex;
@@ -1780,31 +1847,6 @@ QQmlPropertyPrivate::restore(QObject *object, const QQmlPropertyData &data,
 }
 
 /*!
-    Returns true if lhs and rhs refer to the same metaobject data
-*/
-bool QQmlPropertyPrivate::equal(const QMetaObject *lhs, const QMetaObject *rhs)
-{
-    return lhs == rhs || (1 && lhs && rhs && lhs->d.stringdata == rhs->d.stringdata);
-}
-
-/*!
-    Returns true if from inherits to.
-*/
-bool QQmlPropertyPrivate::canConvert(const QMetaObject *from, const QMetaObject *to)
-{
-    if (from && to == &QObject::staticMetaObject)
-        return true;
-
-    while (from) {
-        if (equal(from, to))
-            return true;
-        from = from->superClass();
-    }
-    
-    return false;
-}
-
-/*!
     Return the signal corresponding to \a name
 */
 QMetaMethod QQmlPropertyPrivate::findSignalByName(const QMetaObject *mo, const QByteArray &name)
@@ -1813,11 +1855,8 @@ QMetaMethod QQmlPropertyPrivate::findSignalByName(const QMetaObject *mo, const Q
     int methods = mo->methodCount();
     for (int ii = methods - 1; ii >= 2; --ii) { // >= 2 to block the destroyed signal
         QMetaMethod method = mo->method(ii);
-        QByteArray methodName = method.signature();
-        int idx = methodName.indexOf('(');
-        methodName = methodName.left(idx);
 
-        if (methodName == name)
+        if (method.name() == name)
             return method;
     }
 
@@ -1836,34 +1875,6 @@ QMetaMethod QQmlPropertyPrivate::findSignalByName(const QMetaObject *mo, const Q
     return QMetaMethod();
 }
 
-static inline int QMetaObject_methods(const QMetaObject *metaObject)
-{
-    struct Private
-    {
-        int revision;
-        int className;
-        int classInfoCount, classInfoData;
-        int methodCount, methodData;
-        int propertyCount, propertyData;
-    };
-
-    return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
-}
-
-static inline int QMetaObject_properties(const QMetaObject *metaObject)
-{
-    struct Private
-    {
-        int revision;
-        int className;
-        int classInfoCount, classInfoData;
-        int methodCount, methodData;
-        int propertyCount, propertyData;
-    };
-
-    return reinterpret_cast<const Private *>(metaObject->d.data)->propertyCount;
-}
-
 static inline void flush_vme_signal(const QObject *object, int index)
 {
     QQmlData *data = static_cast<QQmlData *>(QObjectPrivate::get(const_cast<QObject *>(object))->declarativeData);
@@ -1871,17 +1882,8 @@ static inline void flush_vme_signal(const QObject *object, int index)
         QQmlPropertyData *property = data->propertyCache->method(index);
 
         if (property && property->isVMESignal()) {
-            const QMetaObject *metaObject = object->metaObject();
-            int methodOffset = metaObject->methodOffset();
-
-            while (methodOffset > index) {
-                metaObject = metaObject->d.superdata;
-                methodOffset -= QMetaObject_methods(metaObject);
-            }
-
-            QQmlVMEMetaObject *vme = 
-                static_cast<QQmlVMEMetaObject *>(const_cast<QMetaObject *>(metaObject));
-
+            QQmlVMEMetaObject *vme = QQmlVMEMetaObject::getForMethod(const_cast<QObject *>(object),
+                                                                     index);
             vme->connectAliasSignal(index);
         }
     }
@@ -1909,19 +1911,4 @@ void QQmlPropertyPrivate::flushSignal(const QObject *sender, int signal_index)
     flush_vme_signal(sender, signal_index);
 }
 
-/*!
-Return \a metaObject's [super] meta object that provides data for \a property.
-*/
-const QMetaObject *QQmlPropertyPrivate::metaObjectForProperty(const QMetaObject *metaObject, int property)
-{
-    int propertyOffset = metaObject->propertyOffset();
-
-    while (propertyOffset > property) {
-        metaObject = metaObject->d.superdata;
-        propertyOffset -= QMetaObject_properties(metaObject);
-    }
-
-    return metaObject;
-}
-
 QT_END_NAMESPACE