Introduce more generic fast property handling
authorAaron Kennedy <aaron.kennedy@nokia.com>
Mon, 28 Nov 2011 16:04:33 +0000 (16:04 +0000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 5 Dec 2011 14:33:30 +0000 (15:33 +0100)
Also reduce the number of direct calls to qt_metacall().

Change-Id: I04cd6e516a3e61058548309a19fe0b830f15c93f
Reviewed-by: Roberto Raggi <roberto.raggi@nokia.com>
29 files changed:
src/declarative/qml/qdeclarativeaccessors.cpp [new file with mode: 0644]
src/declarative/qml/qdeclarativeaccessors_p.h [new file with mode: 0644]
src/declarative/qml/qdeclarativebinding.cpp
src/declarative/qml/qdeclarativebinding_p.h
src/declarative/qml/qdeclarativefastproperties.cpp [deleted file]
src/declarative/qml/qdeclarativefastproperties_p.h [deleted file]
src/declarative/qml/qdeclarativeproperty.cpp
src/declarative/qml/qdeclarativeproperty_p.h
src/declarative/qml/qdeclarativepropertycache.cpp
src/declarative/qml/qdeclarativepropertycache_p.h
src/declarative/qml/qdeclarativevaluetype.cpp
src/declarative/qml/qdeclarativevaluetype_p.h
src/declarative/qml/qdeclarativevme.cpp
src/declarative/qml/qml.pri
src/declarative/qml/v4/qv4bindings.cpp
src/declarative/qml/v4/qv4compiler.cpp
src/declarative/qml/v4/qv4instruction.cpp
src/declarative/qml/v4/qv4instruction_p.h
src/declarative/qml/v8/qv8bindings.cpp
src/declarative/qml/v8/qv8qobjectwrapper.cpp
src/declarative/qml/v8/qv8sequencewrapper_p_p.h
src/declarative/qml/v8/qv8valuetypewrapper.cpp
src/qtquick1/graphicsitems/qdeclarativeitem.cpp
src/qtquick1/graphicsitems/qdeclarativeitem_p.h
src/qtquick1/qtquick1.cpp
src/quick/items/qquickitem.cpp
src/quick/items/qquickitem.h
src/quick/items/qquickitem_p.h
src/quick/items/qquickitemsmodule.cpp

diff --git a/src/declarative/qml/qdeclarativeaccessors.cpp b/src/declarative/qml/qdeclarativeaccessors.cpp
new file mode 100644 (file)
index 0000000..9652103
--- /dev/null
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativeaccessors_p.h"
+
+#include "qdeclarativedata_p.h"
+#include "qdeclarativenotifier_p.h"
+
+QT_BEGIN_NAMESPACE
+
+struct AccessorProperties {
+    AccessorProperties();
+
+    QReadWriteLock lock;
+    QHash<const QMetaObject *, QDeclarativeAccessorProperties::Properties> properties;
+};
+
+Q_GLOBAL_STATIC(AccessorProperties, accessorProperties)
+
+QML_PRIVATE_ACCESSOR(QObject, QString, objectName, objectName)
+
+static void QObject_objectNameNotifier(QObject *object, intptr_t, QDeclarativeNotifier **notifier)
+{
+    *notifier = QDeclarativeData::get(object, true)->objectNameNotifier();
+}
+
+static QDeclarativeAccessors QObject_objectName = { QObject_objectNameRead,
+                                                    QObject_objectNameNotifier };
+
+QML_DECLARE_PROPERTIES(QObject) {
+    { QML_PROPERTY_NAME(objectName), 0, &QObject_objectName }
+};
+
+static void buildNameMask(QDeclarativeAccessorProperties::Properties &properties)
+{
+    quint32 mask = 0;
+
+    for (int ii = 0; ii < properties.count; ++ii) {
+        Q_ASSERT(strlen(properties.properties[ii].name) == properties.properties[ii].nameLength);
+        Q_ASSERT(properties.properties[ii].nameLength > 0);
+
+        mask |= (1 << qMin(31U, properties.properties[ii].nameLength - 1));
+    }
+
+    properties.nameMask = mask;
+}
+
+AccessorProperties::AccessorProperties()
+{
+    // Pre-seed QObject::objectName accessor
+    typedef QDeclarativeAccessorProperties::Properties P;
+    properties.insert(&QObject::staticMetaObject,
+                      P(qdeclarative_accessor_properties_QObject,
+                        sizeof(qdeclarative_accessor_properties_QObject) /
+                        sizeof(QDeclarativeAccessorProperties::Property)));
+}
+
+QDeclarativeAccessorProperties::Properties::Properties(Property *properties, int count)
+: count(count), properties(properties)
+{
+    buildNameMask(*this);
+}
+
+QDeclarativeAccessorProperties::Properties
+QDeclarativeAccessorProperties::properties(const QMetaObject *mo)
+{
+    AccessorProperties *This = accessorProperties();
+
+    QReadLocker lock(&This->lock);
+    return This->properties.value(mo);
+}
+
+void QDeclarativeAccessorProperties::registerProperties(const QMetaObject *mo, int count,
+                                                        Property *props)
+{
+    Q_ASSERT(count > 0);
+
+    Properties properties(props, count);
+
+    AccessorProperties *This = accessorProperties();
+
+    QWriteLocker lock(&This->lock);
+
+    Q_ASSERT(!This->properties.contains(mo) || This->properties.value(mo) == properties);
+
+    This->properties.insert(mo, properties);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeaccessors_p.h b/src/declarative/qml/qdeclarativeaccessors_p.h
new file mode 100644 (file)
index 0000000..bf0b111
--- /dev/null
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEACCESSORS_P_H
+#define QDECLARATIVEACCESSORS_P_H
+
+#include <QtCore/qvector.h>
+#include <QtCore/qhash.h>
+#include <QtCore/QReadWriteLock>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QDeclarativeNotifier;
+
+// QML "accessor properties" allow V4 and V8 to bypass Qt's meta system to read and, more
+// importantly, subscribe to properties directly.  Any property that is primarily read
+// from bindings is a candidate for inclusion as an accessor property.
+//
+// To define accessor properties, use the QML_DECLARE_PROPERTIES() and QML_DEFINE_PROPERTIES()
+// macros.  The QML_DECLARE_PROPERTIES() macro is used to specify the properties, and the
+// QML_DEFINE_PROPERTIES() macro to register the properties with the
+// QDeclarativeAccessorProperties singleton.
+//
+// A class with accessor properties must also add the Q_CLASSINFO("qt_HasQmlAccessors", "true")
+// tag to its declaration.  This is essential for QML to maintain internal consistency,
+// and forgetting to do so will probably cause your application to qFatal() with a
+// helpful reminder of this requirement.
+//
+// It is important that QML_DEFINE_PROPERTIES() has been called before QML ever sees
+// the type with the accessor properties.  As QML_DEFINE_PROPERTIES() is idempotent, it is
+// recommended to call it in the type's constructor as well as when the type is registered
+// as a QML element (if it ever is).  QML_DEFINE_PROPERTIES() is a very cheap operation
+// if registration has already occurred.
+
+#define QML_DECLARE_PROPERTIES(type) \
+    static volatile bool qdeclarative_accessor_properties_isregistered_ ## type = false; \
+    static QDeclarativeAccessorProperties::Property qdeclarative_accessor_properties_ ## type[] =
+
+#define QML_DEFINE_PROPERTIES(type) \
+    do { \
+        if (!qdeclarative_accessor_properties_isregistered_ ## type) { \
+            int count = sizeof(qdeclarative_accessor_properties_ ## type) / \
+                        sizeof(QDeclarativeAccessorProperties::Property); \
+            QDeclarativeAccessorProperties::registerProperties(&type::staticMetaObject, count, \
+                    qdeclarative_accessor_properties_ ## type);\
+            qdeclarative_accessor_properties_isregistered_ ## type = true; \
+        } \
+    } while (false);
+
+#define QML_PRIVATE_ACCESSOR(clazz, cpptype, name, variable) \
+    static void clazz ## _ ## name ## Read(QObject *o, intptr_t, void *rv) \
+    { \
+        clazz ## Private *d = clazz ## Private::get(static_cast<clazz *>(o)); \
+        *static_cast<cpptype *>(rv) = d->variable; \
+    }
+
+#define QML_PROPERTY_NAME(name) #name, sizeof #name - 1
+
+struct QDeclarativeAccessors
+{
+    void (*read)(QObject *object, intptr_t property, void *output);
+    void (*notifier)(QObject *object, intptr_t property, QDeclarativeNotifier **notifier);
+};
+
+namespace QDeclarativeAccessorProperties {
+    struct Property {
+        const char *name;
+        unsigned int nameLength;
+        intptr_t data;
+        QDeclarativeAccessors *accessors;
+    };
+
+    struct Properties {
+        inline Properties();
+        Properties(Property *, int);
+
+        bool operator==(const Properties &o) const {
+            return count == o.count && properties == o.properties;
+        }
+
+        inline Property *property(const char *name);
+
+        int count;
+        Property *properties;
+        quint32 nameMask;
+    };
+
+    Properties properties(const QMetaObject *);
+    void Q_DECLARATIVE_EXPORT registerProperties(const QMetaObject *, int, Property *);
+};
+
+QDeclarativeAccessorProperties::Property *
+QDeclarativeAccessorProperties::Properties::property(const char *name)
+{
+    if (count == 0)
+        return 0;
+
+    unsigned int length = strlen(name);
+
+    Q_ASSERT(length);
+
+    if (nameMask & (1 << qMin(31U, length - 1))) {
+
+        for (int ii = 0; ii < count; ++ii) {
+            if (properties[ii].nameLength == length && 0 == qstrcmp(name, properties[ii].name))
+                return &properties[ii];
+        }
+
+    }
+
+    return 0;
+}
+
+QDeclarativeAccessorProperties::Properties::Properties()
+: count(0), properties(0), nameMask(0)
+{
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEACCESSORS_P_H
index 9a3a7e0..fbfba6d 100644 (file)
@@ -300,6 +300,16 @@ void QDeclarativeBinding::setTarget(const QDeclarativeProperty &prop)
     update();
 }
 
+void QDeclarativeBinding::setTarget(QObject *object,
+                                    const QDeclarativePropertyData &core,
+                                    QDeclarativeContextData *ctxt)
+{
+    Q_D(QDeclarativeBinding);
+    d->property = QDeclarativePropertyPrivate::restore(object, core, ctxt);
+
+    update();
+}
+
 QDeclarativeProperty QDeclarativeBinding::property() const 
 {
    Q_D(const QDeclarativeBinding);
index 6f545fc..8f4c736 100644 (file)
@@ -157,6 +157,7 @@ public:
     QDeclarativeBinding(void *, QObject *, QDeclarativeContextData *, QObject *parent=0);
 
     void setTarget(const QDeclarativeProperty &);
+    void setTarget(QObject *, const QDeclarativePropertyData &, QDeclarativeContextData *);
     QDeclarativeProperty property() const;
 
     void setEvaluateFlags(EvaluateFlags flags);
diff --git a/src/declarative/qml/qdeclarativefastproperties.cpp b/src/declarative/qml/qdeclarativefastproperties.cpp
deleted file mode 100644 (file)
index 5816b3f..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qdeclarativefastproperties_p.h"
-
-#include "qdeclarativedata_p.h"
-#include "qdeclarativenotifier_p.h"
-
-QT_BEGIN_NAMESPACE
-
-// Adding entries to the QDeclarativeFastProperties class allows the QML 
-// binding optimizer to bypass Qt's meta system and read and, more 
-// importantly, subscribe to properties directly.  Any property that is
-// primarily read from bindings is a candidate for inclusion as a fast 
-// property.
-
-Q_GLOBAL_STATIC(QDeclarativeFastProperties, fastProperties)
-
-QDeclarativeFastProperties *QDeclarativeFastProperties::instance()
-{
-    return fastProperties();
-}
-
-static void QObject_objectName(QObject *object, void *output, QDeclarativeNotifierEndpoint *endpoint)
-{
-    if (endpoint) 
-        endpoint->connect(QDeclarativeData::get(object, true)->objectNameNotifier());
-    *((QString *)output) = object->objectName();
-}
-
-QDeclarativeFastProperties::QDeclarativeFastProperties()
-{
-    add(&QObject::staticMetaObject, QObject::staticMetaObject.indexOfProperty("objectName"),
-        QObject_objectName);    
-}
-
-int QDeclarativeFastProperties::accessorIndexForProperty(const QMetaObject *metaObject, int propertyIndex)
-{
-    Q_ASSERT(metaObject);
-    Q_ASSERT(propertyIndex >= 0);
-
-    // Find the "real" metaObject
-    while (metaObject->propertyOffset() > propertyIndex) 
-        metaObject = metaObject->superClass();
-
-    QReadLocker lock(&m_lock);
-    QHash<QPair<const QMetaObject *, int>, int>::Iterator iter = 
-        m_index.find(qMakePair(metaObject, propertyIndex));
-    if (iter != m_index.end())
-        return *iter;
-    else
-        return -1;
-}
-
-void QDeclarativeFastProperties::add(const QMetaObject *metaObject, int propertyIndex, Accessor accessor)
-{
-    Q_ASSERT(metaObject);
-    Q_ASSERT(propertyIndex >= 0);
-
-    // Find the "real" metaObject
-    while (metaObject->propertyOffset() > propertyIndex) 
-        metaObject = metaObject->superClass();
-
-    QPair<const QMetaObject *, int> data = qMakePair(metaObject, propertyIndex);
-    QWriteLocker lock(&m_lock);
-    int accessorIndex = m_accessors.count();
-    m_accessors.append(accessor);
-    m_index.insert(data, accessorIndex);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativefastproperties_p.h b/src/declarative/qml/qdeclarativefastproperties_p.h
deleted file mode 100644 (file)
index 1e09131..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QDECLARATIVEFASTPROPERTIES_P_H
-#define QDECLARATIVEFASTPROPERTIES_P_H
-
-#include <QtCore/qvector.h>
-#include <QtCore/qhash.h>
-#include <QtCore/QReadWriteLock>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-class QObject;
-class QDeclarativeNotifierEndpoint;
-class Q_DECLARATIVE_EXPORT QDeclarativeFastProperties
-{
-public:
-    typedef void (*Accessor)(QObject *object, void *output, QDeclarativeNotifierEndpoint *endpoint);
-    QDeclarativeFastProperties();
-
-    Accessor accessor(int index) const { QReadLocker lock(&m_lock); return m_accessors.at(index); }
-    int accessorIndexForProperty(const QMetaObject *, int);
-
-    void add(const QMetaObject *, int, Accessor);
-
-    static QDeclarativeFastProperties *instance();
-
-private:
-    QHash<QPair<const QMetaObject *, int>, int> m_index;
-    QVector<Accessor> m_accessors;
-    mutable QReadWriteLock m_lock;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QDECLARATIVEFASTPROPERTIES_P_H
index 795283c..1e0b14e 100644 (file)
@@ -219,6 +219,11 @@ QDeclarativeProperty::QDeclarativeProperty(QObject *obj, const QString &name, QD
 
 Q_GLOBAL_STATIC(QDeclarativeValueTypeFactory, qmlValueTypes);
 
+QDeclarativePropertyPrivate::QDeclarativePropertyPrivate()
+: context(0), engine(0), object(0), isNameCached(false)
+{
+}
+
 QDeclarativeContextData *QDeclarativePropertyPrivate::effectiveContext() const 
 {
     if (context) return context;
@@ -1695,8 +1700,8 @@ QDeclarativePropertyPrivate::saveValueType(const QMetaObject *metaObject, int in
 }
 
 QDeclarativeProperty
-QDeclarativePropertyPrivate::restore(const QDeclarativePropertyData &data,
-                                     QObject *object, QDeclarativeContextData *ctxt)
+QDeclarativePropertyPrivate::restore(QObject *object, const QDeclarativePropertyData &data,
+                                     QDeclarativeContextData *ctxt)
 {
     QDeclarativeProperty prop;
 
index f2e86dd..ce66ef8 100644 (file)
@@ -69,21 +69,26 @@ class QDeclarativeJavaScriptExpression;
 class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePropertyPrivate : public QDeclarativeRefCount
 {
 public:
-    enum WriteFlag { BypassInterceptor = 0x01, DontRemoveBinding = 0x02, RemoveBindingOnAliasWrite = 0x04 };
+    enum WriteFlag {
+        BypassInterceptor = 0x01,
+        DontRemoveBinding = 0x02,
+        RemoveBindingOnAliasWrite = 0x04
+    };
     Q_DECLARE_FLAGS(WriteFlags, WriteFlag)
 
-    QDeclarativePropertyPrivate()
-        : context(0), engine(0), object(0), isNameCached(false) {}
-
-    inline QDeclarativeContextData *effectiveContext() const;
     QDeclarativeContextData *context;
     QDeclarativeEngine *engine;
     QDeclarativeGuard<QObject> object;
 
-    bool isNameCached:1;
     QDeclarativePropertyData core;
+
+    bool isNameCached:1;
     QString nameCache;
 
+    QDeclarativePropertyPrivate();
+
+    inline QDeclarativeContextData *effectiveContext() const;
+
     void initProperty(QObject *obj, const QString &name);
     void initDefault(QObject *obj);
 
@@ -105,18 +110,21 @@ public:
     static bool write(QObject *, const QDeclarativePropertyData &, const QVariant &,
                       QDeclarativeContextData *, WriteFlags flags = 0);
     static void findAliasTarget(QObject *, int, QObject **, int *);
-    static QDeclarativeAbstractBinding *setBinding(QObject *, int coreIndex, int valueTypeIndex /* -1 */,
+    static QDeclarativeAbstractBinding *setBinding(QObject *, int coreIndex,
+                                                   int valueTypeIndex /* -1 */,
                                                    QDeclarativeAbstractBinding *,
                                                    WriteFlags flags = DontRemoveBinding);
-    static QDeclarativeAbstractBinding *setBindingNoEnable(QObject *, int coreIndex, int valueTypeIndex /* -1 */,
+    static QDeclarativeAbstractBinding *setBindingNoEnable(QObject *, int coreIndex,
+                                                           int valueTypeIndex /* -1 */,
                                                            QDeclarativeAbstractBinding *);
-    static QDeclarativeAbstractBinding *binding(QObject *, int coreIndex, int valueTypeIndex /* -1 */);
+    static QDeclarativeAbstractBinding *binding(QObject *, int coreIndex,
+                                                int valueTypeIndex /* -1 */);
 
     static QDeclarativePropertyData saveValueType(const QMetaObject *, int,
                                                   const QMetaObject *, int,
                                                   QDeclarativeEngine *);
-    static QDeclarativeProperty restore(const QDeclarativePropertyData &,
-                                        QObject *,
+    static QDeclarativeProperty restore(QObject *,
+                                        const QDeclarativePropertyData &,
                                         QDeclarativeContextData *);
 
     static bool equal(const QMetaObject *, const QMetaObject *);
index d997319..239b794 100644 (file)
@@ -46,6 +46,7 @@
 #include <private/qv8engine_p.h>
 
 #include <private/qmetaobject_p.h>
+#include <private/qdeclarativeaccessors_p.h>
 
 #include <QtCore/qdebug.h>
 
@@ -54,6 +55,8 @@ Q_DECLARE_METATYPE(QDeclarativeV8Handle);
 
 QT_BEGIN_NAMESPACE
 
+#define Q_INT16_MAX 32767
+
 class QDeclarativePropertyCacheMethodArguments 
 {
 public:
@@ -85,9 +88,15 @@ static QDeclarativePropertyData::Flags fastFlagsForProperty(const QMetaProperty
 // load
 static QDeclarativePropertyData::Flags flagsForPropertyType(int propType, QDeclarativeEngine *engine)
 {
+    Q_ASSERT(propType != -1);
+
     QDeclarativePropertyData::Flags flags;
 
-    if (propType < QMetaType::User && propType != QMetaType::QObjectStar && propType != QMetaType::QWidgetStar) {
+    if (propType == QMetaType::QObjectStar || propType == QMetaType::QWidgetStar) {
+        flags |= QDeclarativePropertyData::IsQObjectDerived;
+    } else if (propType == QMetaType::QVariant) {
+        flags |= QDeclarativePropertyData::IsQVariant;
+    } else if (propType < (int)QVariant::UserType) {
     } else if (propType == qMetaTypeId<QDeclarativeBinding *>()) {
         flags |= QDeclarativePropertyData::IsQmlBinding;
     } else if (propType == qMetaTypeId<QJSValue>()) {
@@ -120,6 +129,7 @@ void QDeclarativePropertyData::lazyLoad(const QMetaProperty &p, QDeclarativeEngi
 
     coreIndex = p.propertyIndex();
     notifyIndex = p.notifySignalIndex();
+    Q_ASSERT(p.revision() <= Q_INT16_MAX);
     revision = p.revision();
 
     flags = fastFlagsForProperty(p);
@@ -140,10 +150,11 @@ void QDeclarativePropertyData::load(const QMetaProperty &p, QDeclarativeEngine *
 {
     propType = p.userType();
     if (QVariant::Type(propType) == QVariant::LastType)
-        propType = qMetaTypeId<QVariant>();
+        propType = QMetaType::QVariant;
     coreIndex = p.propertyIndex();
     notifyIndex = p.notifySignalIndex();
     flags = fastFlagsForProperty(p) | flagsForPropertyType(propType, engine);
+    Q_ASSERT(p.revision() <= Q_INT16_MAX);
     revision = p.revision();
 }
 
@@ -171,6 +182,7 @@ void QDeclarativePropertyData::load(const QMetaMethod &m)
         }
     }
 
+    Q_ASSERT(m.revision() <= Q_INT16_MAX);
     revision = m.revision();
 }
 
@@ -200,6 +212,7 @@ void QDeclarativePropertyData::lazyLoad(const QMetaMethod &m)
         }
     }
 
+    Q_ASSERT(m.revision() <= Q_INT16_MAX);
     revision = m.revision();
 }
 
@@ -259,52 +272,6 @@ void QDeclarativePropertyCache::clear()
     engine = 0;
 }
 
-QDeclarativePropertyData QDeclarativePropertyCache::create(const QMetaObject *metaObject,
-                                                           const QString &property)
-{
-    Q_ASSERT(metaObject);
-
-    QDeclarativePropertyData rv;
-    {
-        const QMetaObject *cmo = metaObject;
-        const QByteArray propertyName = property.toUtf8();
-        while (cmo) {
-            int idx = cmo->indexOfProperty(propertyName);
-            if (idx != -1) {
-                QMetaProperty p = cmo->property(idx);
-                if (p.isScriptable()) {
-                    rv.load(p);
-                    return rv;
-                } else {
-                    while (cmo && cmo->propertyOffset() >= idx)
-                        cmo = cmo->superClass();
-                }
-            } else {
-                cmo = 0;
-            }
-        }
-    }
-
-    int methodCount = metaObject->methodCount();
-    for (int ii = methodCount - 1; ii >= 3; --ii) { // >=3 to block the destroyed signal and deleteLater() slot
-        QMetaMethod m = metaObject->method(ii);
-        if (m.access() == QMetaMethod::Private)
-            continue;
-        QString methodName = QString::fromUtf8(m.signature());
-
-        int parenIdx = methodName.indexOf(QLatin1Char('('));
-        Q_ASSERT(parenIdx != -1);
-        QStringRef methodNameRef = methodName.leftRef(parenIdx);
-
-        if (methodNameRef == property) {
-            rv.load(m);
-            return rv;
-        }
-    }
-
-    return rv;
-}
-
 QDeclarativePropertyCache *QDeclarativePropertyCache::copy(int reserve) 
 {
     QDeclarativePropertyCache *cache = new QDeclarativePropertyCache(engine);
@@ -347,6 +314,40 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
     int methodCount = metaObject->methodCount();
     Q_ASSERT(QMetaObjectPrivate::get(metaObject)->revision >= 4);
     int signalCount = QMetaObjectPrivate::get(metaObject)->signalCount;
+    int classInfoCount = QMetaObjectPrivate::get(metaObject)->classInfoCount;
+
+    QDeclarativeAccessorProperties::Properties accessorProperties;
+
+    // Special case QObject as we don't want to add a qt_HasQmlAccessors classinfo to it
+    if (metaObject == &QObject::staticMetaObject) {
+        accessorProperties = QDeclarativeAccessorProperties::properties(metaObject);
+    } else if (classInfoCount) {
+        int classInfoOffset = metaObject->classInfoOffset();
+        bool hasFastProperty = false;
+        for (int ii = 0; ii < classInfoCount; ++ii) {
+            int idx = ii + classInfoOffset;
+
+            if (0 == qstrcmp(metaObject->classInfo(idx).name(), "qt_HasQmlAccessors")) {
+                hasFastProperty = true;
+                break;
+            }
+        }
+
+        if (hasFastProperty) {
+            accessorProperties = QDeclarativeAccessorProperties::properties(metaObject);
+            if (accessorProperties.count == 0)
+                qFatal("QDeclarativePropertyCache: %s has FastProperty class info, but has not "
+                       "installed property accessors", metaObject->className());
+        } else {
+#ifndef QT_NO_DEBUG
+            accessorProperties = QDeclarativeAccessorProperties::properties(metaObject);
+            if (accessorProperties.count != 0)
+                qFatal("QDeclarativePropertyCache: %s has fast property accessors, but is missing "
+                       "FastProperty class info", metaObject->className());
+#endif
+        }
+    }
+
     // 3 to block the destroyed signal and the deleteLater() slot
     int methodOffset = qMax(3, metaObject->methodOffset()); 
 
@@ -381,6 +382,7 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
         if (!dynamicMetaObject)
             data->flags |= QDeclarativePropertyData::IsDirect;
 
+        Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
         data->metaObjectOffset = allowedRevisionCache.count() - 1;
 
         if (data->isSignal()) {
@@ -459,6 +461,7 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
         if (!dynamicMetaObject) 
             data->flags |= QDeclarativePropertyData::IsDirect;
 
+        Q_ASSERT((allowedRevisionCache.count() - 1) < Q_INT16_MAX);
         data->metaObjectOffset = allowedRevisionCache.count() - 1;
 
         QDeclarativePropertyData *old = 0;
@@ -475,7 +478,16 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
             stringCache.insert(propName, data);
         }
 
-        if (old) {
+        QDeclarativeAccessorProperties::Property *accessorProperty = accessorProperties.property(str);
+
+        // Fast properties may not be overrides
+        Q_ASSERT(accessorProperty == 0 || old == 0);
+
+        if (accessorProperty) {
+            data->flags |= QDeclarativePropertyData::HasAccessors;
+            data->accessors = accessorProperty->accessors;
+            data->accessorData = accessorProperty->data;
+        } else if (old) {
             data->overrideIndexIsProperty = !old->isFunction();
             data->overrideIndex = old->coreIndex;
         }
@@ -488,8 +500,7 @@ void QDeclarativePropertyCache::resolve(QDeclarativePropertyData *data) const
 
     data->propType = QMetaType::type(data->propTypeName);
     if (QVariant::Type(data->propType) == QVariant::LastType)
-        data->propType = qMetaTypeId<QVariant>();
-
+        data->propType = QMetaType::QVariant;
 
     if (!data->isFunction())
         data->flags |= flagsForPropertyType(data->propType, engine);
@@ -699,21 +710,83 @@ int *QDeclarativePropertyCache::methodParameterTypes(QObject *object, int index,
     }
 }
 
+QDeclarativePropertyData qDeclarativePropertyCacheCreate(const QMetaObject *metaObject,
+                                                         const QString &property)
+{
+    Q_ASSERT(metaObject);
+
+    QDeclarativePropertyData rv;
+    {
+        const QMetaObject *cmo = metaObject;
+        const QByteArray propertyName = property.toUtf8();
+        while (cmo) {
+            int idx = cmo->indexOfProperty(propertyName);
+            if (idx != -1) {
+                QMetaProperty p = cmo->property(idx);
+                if (p.isScriptable()) {
+                    rv.load(p);
+                    return rv;
+                } else {
+                    while (cmo && cmo->propertyOffset() >= idx)
+                        cmo = cmo->superClass();
+                }
+            } else {
+                cmo = 0;
+            }
+        }
+    }
+
+    int methodCount = metaObject->methodCount();
+    for (int ii = methodCount - 1; ii >= 3; --ii) {
+        // >=3 to block the destroyed signal and deleteLater() slot
+        QMetaMethod m = metaObject->method(ii);
+        if (m.access() == QMetaMethod::Private)
+            continue;
+        QString methodName = QString::fromUtf8(m.signature());
+
+        int parenIdx = methodName.indexOf(QLatin1Char('('));
+        Q_ASSERT(parenIdx != -1);
+        QStringRef methodNameRef = methodName.leftRef(parenIdx);
+
+        if (methodNameRef == property) {
+            rv.load(m);
+            return rv;
+        }
+    }
+
+    return rv;
+}
+
+inline const QString &qDeclarativePropertyCacheToString(const QString &string)
+{
+    return string;
+}
+
+inline QString qDeclarativePropertyCacheToString(const QHashedV8String &string)
+{
+    return QV8Engine::toStringStatic(string.string());
+}
+
+template<typename T>
 QDeclarativePropertyData *
-QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj, 
-                                    const QHashedV8String &name, QDeclarativePropertyData &local)
+qDeclarativePropertyCacheProperty(QDeclarativeEngine *engine, QObject *obj,
+                                  const T &name, QDeclarativePropertyData &local)
 {
-    // XXX Optimize for worker script case where engine isn't available
     QDeclarativePropertyCache *cache = 0;
-    if (engine) {
-        QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
 
+    if (engine) {
         QDeclarativeData *ddata = QDeclarativeData::get(obj);
-        if (ddata && ddata->propertyCache)
+
+        if (ddata && ddata->propertyCache) {
             cache = ddata->propertyCache;
-        if (!cache) {
+        } else if (engine) {
+            QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
             cache = ep->cache(obj);
-            if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
+            if (cache) {
+                ddata = QDeclarativeData::get(obj, true);
+                cache->addref();
+                ddata->propertyCache = cache;
+            }
         }
     }
 
@@ -722,9 +795,8 @@ QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
     if (cache) {
         rv = cache->property(name);
     } else {
-        QString strname = QV8Engine::toStringStatic(name.string());
-        // QString strname = ep->v8engine()->toString(name);
-        local = QDeclarativePropertyCache::create(obj->metaObject(), strname);
+        local = qDeclarativePropertyCacheCreate(obj->metaObject(),
+                                                qDeclarativePropertyCacheToString(name));
         if (local.isValid())
             rv = &local;
     }
@@ -734,36 +806,16 @@ QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
 
 QDeclarativePropertyData *
 QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj, 
-                                    const QString &name, QDeclarativePropertyData &local)
+                                    const QHashedV8String &name, QDeclarativePropertyData &local)
 {
-    QDeclarativePropertyData *rv = 0;
-
-    if (!engine) {
-        local = QDeclarativePropertyCache::create(obj->metaObject(), name);
-        if (local.isValid())
-            rv = &local;
-    } else {
-        QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
-
-        QDeclarativePropertyCache *cache = 0;
-        QDeclarativeData *ddata = QDeclarativeData::get(obj);
-        if (ddata && ddata->propertyCache)
-            cache = ddata->propertyCache;
-        if (!cache) {
-            cache = enginePrivate->cache(obj);
-            if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
-        }
-
-        if (cache) {
-            rv = cache->property(name);
-        } else {
-            local = QDeclarativePropertyCache::create(obj->metaObject(), name);
-            if (local.isValid())
-                rv = &local;
-        }
-    }
+    return qDeclarativePropertyCacheProperty<QHashedV8String>(engine, obj, name, local);
+}
 
-    return rv;
+QDeclarativePropertyData *
+QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
+                                    const QString &name, QDeclarativePropertyData &local)
+{
+    return qDeclarativePropertyCacheProperty<QString>(engine, obj, name, local);
 }
 
 static inline const QMetaObjectPrivate *priv(const uint* data)
index fc4a24c..3deafdf 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
-class QDeclarativeEngine;
-class QMetaProperty;
 class QV8Engine;
+class QMetaProperty;
 class QV8QObjectWrapper;
-class QDeclarativePropertyCacheMethodArguments;
+class QDeclarativeEngine;
 class QDeclarativePropertyData;
+class QDeclarativeAccessors;
+class QDeclarativePropertyCacheMethodArguments;
 
-// We have this somewhat aweful split between RawData and Data so that RawData can be
+// We have this somewhat awful split between RawData and Data so that RawData can be
 // used in unions.  In normal code, you should always use Data which initializes RawData
 // to an invalid state on construction.
 class QDeclarativePropertyRawData
@@ -87,29 +88,31 @@ public:
         IsAlias            = 0x00000008, // Is a QML alias to another property
         IsFinal            = 0x00000010, // Has FINAL flag
         IsDirect           = 0x00000020, // Exists on a C++ QMetaObject
+        HasAccessors       = 0x00000040, // Has property accessors
 
         // These are mutualy exclusive
-        IsFunction         = 0x00000040, // Is an invokable
-        IsQObjectDerived   = 0x00000080, // Property type is a QObject* derived type
-        IsEnumType         = 0x00000100, // Property type is an enum
-        IsQList            = 0x00000200, // Property type is a QML list
-        IsQmlBinding       = 0x00000400, // Property type is a QDeclarativeBinding*
-        IsQJSValue         = 0x00000800, // Property type is a QScriptValue
-        IsV8Handle         = 0x00001000, // Property type is a QDeclarativeV8Handle
-        IsVMEProperty      = 0x00002000, // Property type is a "var" property of VMEMO
-        IsValueTypeVirtual = 0x00004000, // Property is a value type "virtual" property
+        IsFunction         = 0x00000080, // Is an invokable
+        IsQObjectDerived   = 0x00000100, // Property type is a QObject* derived type
+        IsEnumType         = 0x00000200, // Property type is an enum
+        IsQList            = 0x00000400, // Property type is a QML list
+        IsQmlBinding       = 0x00000800, // Property type is a QDeclarativeBinding*
+        IsQJSValue         = 0x00001000, // Property type is a QScriptValue
+        IsV8Handle         = 0x00002000, // Property type is a QDeclarativeV8Handle
+        IsVMEProperty      = 0x00004000, // Property type is a "var" property of VMEMO
+        IsValueTypeVirtual = 0x00008000, // Property is a value type "virtual" property
+        IsQVariant         = 0x00010000, // Property is a QVariant
 
         // Apply only to IsFunctions
-        IsVMEFunction      = 0x00008000, // Function was added by QML
-        HasArguments       = 0x00010000, // Function takes arguments
-        IsSignal           = 0x00020000, // Function is a signal
-        IsVMESignal        = 0x00040000, // Signal was added by QML
-        IsV8Function       = 0x00080000, // Function takes QDeclarativeV8Function* args
-        IsSignalHandler    = 0x00100000, // Function is a signal handler
-        IsOverload         = 0x00200000, // Function is an overload of another function
+        IsVMEFunction      = 0x00020000, // Function was added by QML
+        HasArguments       = 0x00040000, // Function takes arguments
+        IsSignal           = 0x00080000, // Function is a signal
+        IsVMESignal        = 0x00100000, // Signal was added by QML
+        IsV8Function       = 0x00200000, // Function takes QDeclarativeV8Function* args
+        IsSignalHandler    = 0x00400000, // Function is a signal handler
+        IsOverload         = 0x00800000, // Function is an overload of another function
 
         // Internal QDeclarativePropertyCache flags
-        NotFullyResolved   = 0x00400000  // True if the type data is to be lazily resolved
+        NotFullyResolved   = 0x01000000  // True if the type data is to be lazily resolved
     };
     Q_DECLARE_FLAGS(Flags, Flag)
 
@@ -124,6 +127,7 @@ public:
     bool isAlias() const { return flags & IsAlias; }
     bool isFinal() const { return flags & IsFinal; }
     bool isDirect() const { return flags & IsDirect; }
+    bool hasAccessors() const { return flags & HasAccessors; }
     bool isFunction() const { return flags & IsFunction; }
     bool isQObject() const { return flags & IsQObjectDerived; }
     bool isEnum() const { return flags & IsEnumType; }
@@ -133,6 +137,7 @@ public:
     bool isV8Handle() const { return flags & IsV8Handle; }
     bool isVMEProperty() const { return flags & IsVMEProperty; }
     bool isValueTypeVirtual() const { return flags & IsValueTypeVirtual; }
+    bool isQVariant() const { return flags & IsQVariant; }
     bool isVMEFunction() const { return flags & IsVMEFunction; }
     bool hasArguments() const { return flags & HasArguments; }
     bool isSignal() const { return flags & IsSignal; }
@@ -141,6 +146,11 @@ public:
     bool isSignalHandler() const { return flags & IsSignalHandler; }
     bool isOverload() const { return flags & IsOverload; }
 
+    bool hasOverride() const { return !(flags & IsValueTypeVirtual) && overrideIndex >= 0; }
+
+    // Returns -1 if not a value type virtual property
+    inline int getValueTypeCoreIndex() const;
+
     union {
         int propType;             // When !NotFullyResolved
         const char *propTypeName; // When NotFullyResolved
@@ -163,8 +173,14 @@ public:
                                        //proxy object
         };
     };
-    int revision;
-    int metaObjectOffset;
+
+    qint16 revision;
+    qint16 metaObjectOffset;
+
+    struct { // When HasAccessors
+        QDeclarativeAccessors *accessors;
+        intptr_t accessorData;
+    };
 
 private:
     friend class QDeclarativePropertyData;
@@ -187,9 +203,6 @@ public:
     QString name(QObject *);
     QString name(const QMetaObject *);
 
-    // Returns -1 if not a value type virtual property
-    inline int getValueTypeCoreIndex() const;
-
 private:
     friend class QDeclarativePropertyCache;
     void lazyLoad(const QMetaProperty &, QDeclarativeEngine *engine = 0);
@@ -216,8 +229,6 @@ public:
                 QDeclarativePropertyData::Flag methodFlags = QDeclarativePropertyData::NoFlags,
                 QDeclarativePropertyData::Flag signalFlags = QDeclarativePropertyData::NoFlags);
 
-    static QDeclarativePropertyData create(const QMetaObject *, const QString &);
-
     inline QDeclarativePropertyData *property(const QHashedV8String &) const;
     QDeclarativePropertyData *property(const QHashedStringRef &) const;
     QDeclarativePropertyData *property(const QHashedCStringRef &) const;
@@ -282,6 +293,8 @@ QDeclarativePropertyData::QDeclarativePropertyData()
     overrideIndex = -1;
     revision = 0;
     metaObjectOffset = -1; 
+    accessors = 0;
+    accessorData = 0;
     flags = 0;
 }
 
@@ -302,7 +315,7 @@ bool QDeclarativePropertyData::operator==(const QDeclarativePropertyRawData &oth
              valueTypePropType == other.valueTypePropType));
 }
 
-int QDeclarativePropertyData::getValueTypeCoreIndex() const
+int QDeclarativePropertyRawData::getValueTypeCoreIndex() const
 {
     return isValueTypeVirtual()?valueTypeCoreIndex:-1;
 }
@@ -310,7 +323,7 @@ int QDeclarativePropertyData::getValueTypeCoreIndex() const
 QDeclarativePropertyData *
 QDeclarativePropertyCache::overrideData(QDeclarativePropertyData *data) const
 {
-    if (data->overrideIndex < 0)
+    if (!data->hasOverride())
         return 0;
 
     if (data->overrideIndexIsProperty)
index ffd0041..434059f 100644 (file)
@@ -168,44 +168,58 @@ QDeclarativeValueType::QDeclarativeValueType(QObject *parent)
 {
 }
 
-QDeclarativePointFValueType::QDeclarativePointFValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativePointFValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &point, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativePointFValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &point, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant QDeclarativePointFValueType::value()
-{
-    return QVariant(point);
-}
+#define QML_VALUETYPE_READWRITE(name, cpptype, var) \
+    QDeclarative ## name ## ValueType::QDeclarative ## name ## ValueType(QObject *parent) \
+    : QDeclarativeValueType(parent) \
+    { \
+    } \
+    void QDeclarative ## name ## ValueType::read(QObject *obj, int idx) \
+    { \
+        void *a[] = { &var, 0 }; \
+        QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a); \
+        onLoad(); \
+    } \
+    void QDeclarative ## name ## ValueType::write(QObject *obj, int idx, \
+                                                  QDeclarativePropertyPrivate::WriteFlags flags) \
+    { \
+        int status = -1; \
+        void *a[] = { &var, 0, &status, &flags }; \
+        QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a); \
+    } \
+    bool QDeclarative ## name ## ValueType::isEqual(const QVariant &value) const \
+    { \
+        return QVariant(var) == value; \
+    } \
+    QVariant QDeclarative ## name ## ValueType::value() \
+    { \
+        return QVariant(var); \
+    } \
+    void QDeclarative ## name ## ValueType::setValue(const QVariant &value) \
+    { \
+        var = qvariant_cast<cpptype>(value); \
+        onLoad(); \
+    }
 
-void QDeclarativePointFValueType::setValue(QVariant value)
-{
-    point = qvariant_cast<QPointF>(value);
-}
+QML_VALUETYPE_READWRITE(PointF, QPointF, point);
+QML_VALUETYPE_READWRITE(Point, QPoint, point);
+QML_VALUETYPE_READWRITE(SizeF, QSizeF, size);
+QML_VALUETYPE_READWRITE(Size, QSize, size);
+QML_VALUETYPE_READWRITE(RectF, QRectF, rect);
+QML_VALUETYPE_READWRITE(Rect, QRect, rect);
+QML_VALUETYPE_READWRITE(Vector2D, QVector2D, vector);
+QML_VALUETYPE_READWRITE(Vector3D, QVector3D, vector);
+QML_VALUETYPE_READWRITE(Vector4D, QVector4D, vector);
+QML_VALUETYPE_READWRITE(Quaternion, QQuaternion, quaternion);
+QML_VALUETYPE_READWRITE(Matrix4x4, QMatrix4x4, matrix);
+QML_VALUETYPE_READWRITE(Easing, QEasingCurve, easing);
+QML_VALUETYPE_READWRITE(Font, QFont, font);
+QML_VALUETYPE_READWRITE(Color, QColor, color);
 
 QString QDeclarativePointFValueType::toString() const
 {
     return QString(QLatin1String("QPointF(%1, %2)")).arg(point.x()).arg(point.y());
 }
 
-bool QDeclarativePointFValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(point) == value);
-}
-
 qreal QDeclarativePointFValueType::x() const
 {
     return point.x();
@@ -226,44 +240,11 @@ void QDeclarativePointFValueType::setY(qreal y)
     point.setY(y);
 }
 
-QDeclarativePointValueType::QDeclarativePointValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativePointValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &point, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativePointValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &point, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant QDeclarativePointValueType::value()
-{
-    return QVariant(point);
-}
-
-void QDeclarativePointValueType::setValue(QVariant value)
-{
-    point = qvariant_cast<QPoint>(value);
-}
-
 QString QDeclarativePointValueType::toString() const
 {
     return QString(QLatin1String("QPoint(%1, %2)")).arg(point.x()).arg(point.y());
 }
 
-bool QDeclarativePointValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(point) == value);
-}
-
 int QDeclarativePointValueType::x() const
 {
     return point.x();
@@ -284,44 +265,11 @@ void QDeclarativePointValueType::setY(int y)
     point.setY(y);
 }
 
-QDeclarativeSizeFValueType::QDeclarativeSizeFValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeSizeFValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &size, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeSizeFValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &size, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant QDeclarativeSizeFValueType::value()
-{
-    return QVariant(size);
-}
-
-void QDeclarativeSizeFValueType::setValue(QVariant value)
-{
-    size = qvariant_cast<QSizeF>(value);
-}
-
 QString QDeclarativeSizeFValueType::toString() const
 {
     return QString(QLatin1String("QSizeF(%1, %2)")).arg(size.width()).arg(size.height());
 }
 
-bool QDeclarativeSizeFValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(size) == value);
-}
-
 qreal QDeclarativeSizeFValueType::width() const
 {
     return size.width();
@@ -342,44 +290,11 @@ void QDeclarativeSizeFValueType::setHeight(qreal h)
     size.setHeight(h);
 }
 
-QDeclarativeSizeValueType::QDeclarativeSizeValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeSizeValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &size, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeSizeValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &size, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant QDeclarativeSizeValueType::value()
-{
-    return QVariant(size);
-}
-
-void QDeclarativeSizeValueType::setValue(QVariant value)
-{
-    size = qvariant_cast<QSize>(value);
-}
-
 QString QDeclarativeSizeValueType::toString() const
 {
     return QString(QLatin1String("QSize(%1, %2)")).arg(size.width()).arg(size.height());
 }
 
-bool QDeclarativeSizeValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(size) == value);
-}
-
 int QDeclarativeSizeValueType::width() const
 {
     return size.width();
@@ -400,44 +315,11 @@ void QDeclarativeSizeValueType::setHeight(int h)
     size.setHeight(h);
 }
 
-QDeclarativeRectFValueType::QDeclarativeRectFValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeRectFValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &rect, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeRectFValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &rect, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant QDeclarativeRectFValueType::value()
-{
-    return QVariant(rect);
-}
-
-void QDeclarativeRectFValueType::setValue(QVariant value)
-{
-    rect = qvariant_cast<QRectF>(value);
-}
-
 QString QDeclarativeRectFValueType::toString() const
 {
     return QString(QLatin1String("QRectF(%1, %2, %3, %4)")).arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height());
 }
 
-bool QDeclarativeRectFValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(rect) == value);
-}
-
 qreal QDeclarativeRectFValueType::x() const
 {
     return rect.x();
@@ -478,44 +360,11 @@ void QDeclarativeRectFValueType::setHeight(qreal h)
     rect.setHeight(h);
 }
 
-QDeclarativeRectValueType::QDeclarativeRectValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeRectValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &rect, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeRectValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &rect, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant QDeclarativeRectValueType::value()
-{
-    return QVariant(rect);
-}
-
-void QDeclarativeRectValueType::setValue(QVariant value)
-{
-    rect = qvariant_cast<QRect>(value);
-}
-
 QString QDeclarativeRectValueType::toString() const
 {
     return QString(QLatin1String("QRect(%1, %2, %3, %4)")).arg(rect.x()).arg(rect.y()).arg(rect.width()).arg(rect.height());
 }
 
-bool QDeclarativeRectValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(rect) == value);
-}
-
 int QDeclarativeRectValueType::x() const
 {
     return rect.x();
@@ -556,44 +405,11 @@ void QDeclarativeRectValueType::setHeight(int h)
     rect.setHeight(h);
 }
 
-QDeclarativeVector2DValueType::QDeclarativeVector2DValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeVector2DValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &vector, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeVector2DValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &vector, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant  QDeclarativeVector2DValueType::value()
-{
-    return QVariant(vector);
-}
-
-void QDeclarativeVector2DValueType::setValue(QVariant value)
-{
-    vector = qvariant_cast<QVector2D>(value);
-}
-
 QString QDeclarativeVector2DValueType::toString() const
 {
     return QString(QLatin1String("QVector2D(%1, %2)")).arg(vector.x()).arg(vector.y());
 }
 
-bool QDeclarativeVector2DValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(vector) == value);
-}
-
 qreal QDeclarativeVector2DValueType::x() const
 {
     return vector.x();
@@ -614,44 +430,11 @@ void QDeclarativeVector2DValueType::setY(qreal y)
     vector.setY(y);
 }
 
-QDeclarativeVector3DValueType::QDeclarativeVector3DValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeVector3DValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &vector, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeVector3DValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &vector, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant  QDeclarativeVector3DValueType::value()
-{
-    return QVariant(vector);
-}
-
-void QDeclarativeVector3DValueType::setValue(QVariant value)
-{
-    vector = qvariant_cast<QVector3D>(value);
-}
-
 QString QDeclarativeVector3DValueType::toString() const
 {
     return QString(QLatin1String("QVector3D(%1, %2, %3)")).arg(vector.x()).arg(vector.y()).arg(vector.z());
 }
 
-bool QDeclarativeVector3DValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(vector) == value);
-}
-
 qreal QDeclarativeVector3DValueType::x() const
 {
     return vector.x();
@@ -682,44 +465,11 @@ void QDeclarativeVector3DValueType::setZ(qreal z)
     vector.setZ(z);
 }
 
-QDeclarativeVector4DValueType::QDeclarativeVector4DValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeVector4DValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &vector, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeVector4DValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &vector, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant  QDeclarativeVector4DValueType::value()
-{
-    return QVariant(vector);
-}
-
-void QDeclarativeVector4DValueType::setValue(QVariant value)
-{
-    vector = qvariant_cast<QVector4D>(value);
-}
-
 QString QDeclarativeVector4DValueType::toString() const
 {
     return QString(QLatin1String("QVector4D(%1, %2, %3, %4)")).arg(vector.x()).arg(vector.y()).arg(vector.z()).arg(vector.w());
 }
 
-bool QDeclarativeVector4DValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(vector) == value);
-}
-
 qreal QDeclarativeVector4DValueType::x() const
 {
     return vector.x();
@@ -760,44 +510,11 @@ void QDeclarativeVector4DValueType::setW(qreal w)
     vector.setW(w);
 }
 
-QDeclarativeQuaternionValueType::QDeclarativeQuaternionValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeQuaternionValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &quaternion, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeQuaternionValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &quaternion, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant  QDeclarativeQuaternionValueType::value()
-{
-    return QVariant(quaternion);
-}
-
-void QDeclarativeQuaternionValueType::setValue(QVariant value)
-{
-    quaternion = qvariant_cast<QQuaternion>(value);
-}
-
 QString QDeclarativeQuaternionValueType::toString() const
 {
     return QString(QLatin1String("QQuaternion(%1, %2, %3, %4)")).arg(quaternion.scalar()).arg(quaternion.x()).arg(quaternion.y()).arg(quaternion.z());
 }
 
-bool QDeclarativeQuaternionValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(quaternion) == value);
-}
-
 qreal QDeclarativeQuaternionValueType::scalar() const
 {
     return quaternion.scalar();
@@ -838,34 +555,6 @@ void QDeclarativeQuaternionValueType::setZ(qreal z)
     quaternion.setZ(z);
 }
 
-QDeclarativeMatrix4x4ValueType::QDeclarativeMatrix4x4ValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeMatrix4x4ValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &matrix, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeMatrix4x4ValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &matrix, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant  QDeclarativeMatrix4x4ValueType::value()
-{
-    return QVariant(matrix);
-}
-
-void QDeclarativeMatrix4x4ValueType::setValue(QVariant value)
-{
-    matrix = qvariant_cast<QMatrix4x4>(value);
-}
-
 QString QDeclarativeMatrix4x4ValueType::toString() const
 {
     return QString(QLatin1String("QMatrix4x4(%1, %2, %3, %4, %5, %6, %7, %8, %9, %10, %11, %12, %13, %14, %15, %16)"))
@@ -875,49 +564,11 @@ QString QDeclarativeMatrix4x4ValueType::toString() const
             .arg(matrix(3, 0)).arg(matrix(3, 1)).arg(matrix(3, 2)).arg(matrix(3, 3));
 }
 
-bool QDeclarativeMatrix4x4ValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(matrix) == value);
-}
-
-QDeclarativeEasingValueType::QDeclarativeEasingValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeEasingValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &easing, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeEasingValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &easing, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant QDeclarativeEasingValueType::value()
-{
-    return QVariant(easing);
-}
-
-void QDeclarativeEasingValueType::setValue(QVariant value)
-{
-    easing = qvariant_cast<QEasingCurve>(value);
-}
-
 QString QDeclarativeEasingValueType::toString() const
 {
     return QString(QLatin1String("QEasingCurve(%1, %2, %3, %4)")).arg(easing.type()).arg(easing.amplitude()).arg(easing.overshoot()).arg(easing.period());
 }
 
-bool QDeclarativeEasingValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(easing) == value);
-}
-
 QDeclarativeEasingValueType::Type QDeclarativeEasingValueType::type() const
 {
     return (QDeclarativeEasingValueType::Type)easing.type();
@@ -1004,47 +655,17 @@ QVariantList QDeclarativeEasingValueType::bezierCurve() const
     return rv;
 }
 
-QDeclarativeFontValueType::QDeclarativeFontValueType(QObject *parent)
-: QDeclarativeValueType(parent), pixelSizeSet(false), pointSizeSet(false)
-{
-}
-
-void QDeclarativeFontValueType::read(QObject *obj, int idx)
+void QDeclarativeFontValueType::onLoad()
 {
-    void *a[] = { &font, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
     pixelSizeSet = false;
     pointSizeSet = false;
 }
 
-void QDeclarativeFontValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &font, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant  QDeclarativeFontValueType::value()
-{
-    return QVariant(font);
-}
-
-void QDeclarativeFontValueType::setValue(QVariant value)
-{
-    font = qvariant_cast<QFont>(value);
-}
-
 QString QDeclarativeFontValueType::toString() const
 {
     return QString(QLatin1String("QFont(%1)")).arg(font.toString());
 }
 
-bool QDeclarativeFontValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(font) == value);
-}
-
-
 QString QDeclarativeFontValueType::family() const
 {
     return font.family();
@@ -1192,45 +813,12 @@ void QDeclarativeFontValueType::setWordSpacing(qreal size)
     font.setWordSpacing(size);
 }
 
-QDeclarativeColorValueType::QDeclarativeColorValueType(QObject *parent)
-: QDeclarativeValueType(parent)
-{
-}
-
-void QDeclarativeColorValueType::read(QObject *obj, int idx)
-{
-    void *a[] = { &color, 0 };
-    QMetaObject::metacall(obj, QMetaObject::ReadProperty, idx, a);
-}
-
-void QDeclarativeColorValueType::write(QObject *obj, int idx, QDeclarativePropertyPrivate::WriteFlags flags)
-{
-    int status = -1;
-    void *a[] = { &color, 0, &status, &flags };
-    QMetaObject::metacall(obj, QMetaObject::WriteProperty, idx, a);
-}
-
-QVariant QDeclarativeColorValueType::value()
-{
-    return QVariant(color);
-}
-
-void QDeclarativeColorValueType::setValue(QVariant value)
-{
-    color = qvariant_cast<QColor>(value);
-}
-
 QString QDeclarativeColorValueType::toString() const
 {
     // special case - to maintain behaviour with QtQuick 1.0, we just output normal toString() value.
     return QVariant(color).toString();
 }
 
-bool QDeclarativeColorValueType::isEqual(const QVariant &value) const
-{
-    return (QVariant(color) == value);
-}
-
 qreal QDeclarativeColorValueType::r() const
 {
     return color.redF();
index 9f00d97..b4c8d7f 100644 (file)
@@ -79,10 +79,12 @@ public:
     virtual void read(QObject *, int) = 0;
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags flags) = 0;
     virtual QVariant value() = 0;
-    virtual void setValue(QVariant) = 0;
+    virtual void setValue(const QVariant &) = 0;
 
     virtual QString toString() const = 0;
     virtual bool isEqual(const QVariant &value) const = 0;
+
+    inline void onLoad();
 };
 
 class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeValueTypeFactory
@@ -117,7 +119,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -142,7 +144,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -167,7 +169,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -192,7 +194,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -219,7 +221,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -251,7 +253,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -280,7 +282,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -305,7 +307,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -333,7 +335,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -363,7 +365,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -405,7 +407,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -490,7 +492,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -546,7 +548,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -586,6 +588,7 @@ public:
     qreal wordSpacing() const;
     void setWordSpacing(qreal spacing);
 
+    void onLoad();
 private:
     QFont font;
     bool pixelSizeSet;
@@ -606,7 +609,7 @@ public:
     virtual void read(QObject *, int);
     virtual void write(QObject *, int, QDeclarativePropertyPrivate::WriteFlags);
     virtual QVariant value();
-    virtual void setValue(QVariant value);
+    virtual void setValue(const QVariant &value);
     virtual QString toString() const;
     virtual bool isEqual(const QVariant &value) const;
 
@@ -623,6 +626,10 @@ private:
     QColor color;
 };
 
+void QDeclarativeValueType::onLoad()
+{
+}
+
 QT_END_NAMESPACE
 
 #endif  // QDECLARATIVEVALUETYPE_P_H
index 327a0ae..556e2a2 100644 (file)
@@ -199,6 +199,11 @@ static void removeBindingOnProperty(QObject *o, int index)
     if (binding) binding->destroy();
 }
 
+static QVariant variantFromString(const QString &string)
+{
+    return QDeclarativeStringConverters::variantFromString(string);
+}
+
 // XXX we probably need some form of "work count" here to prevent us checking this 
 // for every instruction.
 #define QML_BEGIN_INSTR_COMMON(I) { \
@@ -237,7 +242,46 @@ static void removeBindingOnProperty(QObject *o, int index)
     } break;
 #endif
 
-#define CLEAN_PROPERTY(o, index) if (fastHasBinding(o, index)) removeBindingOnProperty(o, index)
+#define QML_STORE_VALUE(name, cpptype, value) \
+    QML_BEGIN_INSTR(name) \
+        cpptype v = value; \
+        void *a[] = { (void *)&v, 0, &status, &flags }; \
+        QObject *target = objects.top(); \
+        CLEAN_PROPERTY(target, instr.propertyIndex); \
+        QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
+    QML_END_INSTR(name)
+
+#define QML_STORE_LIST(name, cpptype, value) \
+    QML_BEGIN_INSTR(name) \
+        cpptype v; \
+        v.append(value); \
+        void *a[] = { (void *)&v, 0, &status, &flags }; \
+        QObject *target = objects.top(); \
+        CLEAN_PROPERTY(target, instr.propertyIndex); \
+        QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
+    QML_END_INSTR(name)
+
+#define QML_STORE_VAR(name, value) \
+    QML_BEGIN_INSTR(name) \
+        v8::Handle<v8::Value> v8value = value; \
+        QObject *target = objects.top(); \
+        CLEAN_PROPERTY(target, instr.propertyIndex); \
+        QMetaObject *mo = const_cast<QMetaObject *>(target->metaObject()); \
+        QDeclarativeVMEMetaObject *vmemo = static_cast<QDeclarativeVMEMetaObject *>(mo); \
+        vmemo->setVMEProperty(instr.propertyIndex, v8value); \
+    QML_END_INSTR(name)
+
+#define QML_STORE_POINTER(name, value) \
+    QML_BEGIN_INSTR(name) \
+        void *a[] = { (void *)value, 0, &status, &flags }; \
+        QObject *target = objects.top(); \
+        CLEAN_PROPERTY(target, instr.propertyIndex); \
+        QMetaObject::metacall(target, QMetaObject::WriteProperty, instr.propertyIndex, a); \
+    QML_END_INSTR(name)
+
+#define CLEAN_PROPERTY(o, index) \
+    if (fastHasBinding(o, index)) \
+        removeBindingOnProperty(o, index)
 
 QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
                               const Interrupt &interrupt
@@ -294,6 +338,55 @@ QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
 
         switch (genericInstr->common.instructionType) {
 #endif
+
+        // Store a created object in a property.  These all pop from the objects stack.
+        QML_STORE_VALUE(StoreObject, QObject *, objects.pop());
+        QML_STORE_VALUE(StoreVariantObject, QVariant, QVariant::fromValue(objects.pop()));
+        QML_STORE_VAR(StoreVarObject, ep->v8engine()->newQObject(objects.pop()));
+
+        // Store a literal value in a corresponding property
+        QML_STORE_VALUE(StoreFloat, float, instr.value);
+        QML_STORE_VALUE(StoreDouble, double, instr.value);
+        QML_STORE_VALUE(StoreBool, bool, instr.value);
+        QML_STORE_VALUE(StoreInteger, int, instr.value);
+        QML_STORE_VALUE(StoreColor, QColor, QColor::fromRgba(instr.value));
+        QML_STORE_VALUE(StoreDate, QDate, QDate::fromJulianDay(instr.value));
+        QML_STORE_VALUE(StoreDateTime, QDateTime,
+                        QDateTime(QDate::fromJulianDay(instr.date), *(QTime *)&instr.time));
+        QML_STORE_POINTER(StoreTime, (QTime *)&instr.time);
+        QML_STORE_POINTER(StorePoint, (QPoint *)&instr.point);
+        QML_STORE_POINTER(StorePointF, (QPointF *)&instr.point);
+        QML_STORE_POINTER(StoreSize, (QSize *)&instr.size);
+        QML_STORE_POINTER(StoreSizeF, (QSizeF *)&instr.size);
+        QML_STORE_POINTER(StoreRect, (QRect *)&instr.rect);
+        QML_STORE_POINTER(StoreRectF, (QRectF *)&instr.rect);
+        QML_STORE_POINTER(StoreVector3D, (QVector3D *)&instr.vector);
+        QML_STORE_POINTER(StoreVector4D, (QVector4D *)&instr.vector);
+        QML_STORE_POINTER(StoreString, &PRIMITIVES.at(instr.value));
+        QML_STORE_POINTER(StoreByteArray, &DATAS.at(instr.value));
+        QML_STORE_POINTER(StoreUrl, &URLS.at(instr.value));
+
+        // Store a literal value in a QList
+        QML_STORE_LIST(StoreStringList, QStringList, PRIMITIVES.at(instr.value));
+        QML_STORE_LIST(StoreStringQList, QList<QString>, PRIMITIVES.at(instr.value));
+        QML_STORE_LIST(StoreUrlQList, QList<QUrl>, URLS.at(instr.value));
+        QML_STORE_LIST(StoreDoubleQList, QList<double>, instr.value);
+        QML_STORE_LIST(StoreBoolQList, QList<bool>, instr.value);
+        QML_STORE_LIST(StoreIntegerQList, QList<int>, instr.value);
+
+        // Store a literal value in a QVariant property
+        QML_STORE_VALUE(StoreVariant, QVariant, variantFromString(PRIMITIVES.at(instr.value)));
+        QML_STORE_VALUE(StoreVariantInteger, QVariant, QVariant(instr.value));
+        QML_STORE_VALUE(StoreVariantDouble, QVariant, QVariant(instr.value));
+        QML_STORE_VALUE(StoreVariantBool, QVariant, QVariant(instr.value));
+
+        // Store a literal value in a var property.
+        // We deliberately do not use string converters here
+        QML_STORE_VAR(StoreVar, ep->v8engine()->fromVariant(PRIMITIVES.at(instr.value)));
+        QML_STORE_VAR(StoreVarInteger, v8::Integer::New(instr.value));
+        QML_STORE_VAR(StoreVarDouble, v8::Number::New(instr.value));
+        QML_STORE_VAR(StoreVarBool, v8::Boolean::New(instr.value));
+
         QML_BEGIN_INSTR(Init)
             // Ensure that the compiled data has been initialized
             if (!COMP->isInitialized()) COMP->initialize(engine);
@@ -540,341 +633,6 @@ QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
             }
         QML_END_INSTR(StoreMetaObject)
 
-        QML_BEGIN_INSTR(StoreVariant)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            // XXX - can be more efficient
-            QVariant v = QDeclarativeStringConverters::variantFromString(PRIMITIVES.at(instr.value));
-            void *a[] = { &v, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreVariant)
-
-        QML_BEGIN_INSTR(StoreVariantInteger)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QVariant v(instr.value);
-            void *a[] = { &v, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreVariantInteger)
-
-        QML_BEGIN_INSTR(StoreVariantDouble)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QVariant v(instr.value);
-            void *a[] = { &v, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreVariantDouble)
-
-        QML_BEGIN_INSTR(StoreVariantBool)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QVariant v(instr.value);
-            void *a[] = { &v, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreVariantBool)
-
-        QML_BEGIN_INSTR(StoreVar)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            // Note that we don't use QDeclarativeStringConverters::variantFromString() here, which
-            // means that automatic generation of value types from strings doesn't occur.
-            // This is a deliberate behaviour difference to variant properties.
-            v8::Handle<v8::Value> v8Value = ep->v8engine()->fromVariant(PRIMITIVES.at(instr.value));
-            static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
-        QML_END_INSTR(StoreVar)
-
-        QML_BEGIN_INSTR(StoreVarInteger)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            v8::Handle<v8::Value> v8Value = v8::Integer::New(instr.value);
-            static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
-        QML_END_INSTR(StoreVarInteger)
-
-        QML_BEGIN_INSTR(StoreVarDouble)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            v8::Handle<v8::Value> v8Value = v8::Number::New(instr.value);
-            static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
-        QML_END_INSTR(StoreVarDouble)
-
-        QML_BEGIN_INSTR(StoreVarBool)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            v8::Handle<v8::Value> v8Value = v8::Boolean::New(instr.value);
-            static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
-        QML_END_INSTR(StoreVarBool)
-
-        QML_BEGIN_INSTR(StoreString)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            void *a[] = { (void *)&PRIMITIVES.at(instr.value), 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreString)
-
-        QML_BEGIN_INSTR(StoreStringList)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QStringList stringlist(PRIMITIVES.at(instr.value));
-            void *a[] = { (void *)&stringlist, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreStringList)
-
-        QML_BEGIN_INSTR(StoreStringQList)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QList<QString> stringqlist;
-            stringqlist.append(PRIMITIVES.at(instr.value));
-            void *a[] = { (void *)&stringqlist, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreStringQList)
-
-        QML_BEGIN_INSTR(StoreByteArray)
-            QObject *target = objects.top();
-            void *a[] = { (void *)&DATAS.at(instr.value), 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreByteArray)
-
-        QML_BEGIN_INSTR(StoreUrl)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            void *a[] = { (void *)&URLS.at(instr.value), 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreUrl)
-
-        QML_BEGIN_INSTR(StoreUrlQList)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QList<QUrl> urlqlist;
-            urlqlist.append(URLS.at(instr.value));
-            void *a[] = { (void *)&urlqlist, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreUrlQList)
-
-        QML_BEGIN_INSTR(StoreFloat)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            float f = instr.value;
-            void *a[] = { &f, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreFloat)
-
-        QML_BEGIN_INSTR(StoreDouble)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            double d = instr.value;
-            void *a[] = { &d, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreDouble)
-
-        QML_BEGIN_INSTR(StoreDoubleQList)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QList<double> doubleqlist;
-            doubleqlist.append(instr.value);
-            void *a[] = { (void *)&doubleqlist, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreDoubleQList)
-
-        QML_BEGIN_INSTR(StoreBool)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            void *a[] = { (void *)&instr.value, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreBool)
-
-        QML_BEGIN_INSTR(StoreBoolQList)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QList<bool> boolqlist;
-            boolqlist.append(instr.value);
-            void *a[] = { (void *)&boolqlist, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreBoolQList)
-
-        QML_BEGIN_INSTR(StoreInteger)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            void *a[] = { (void *)&instr.value, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreInteger)
-
-        QML_BEGIN_INSTR(StoreIntegerQList)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QList<int> intqlist;
-            intqlist.append(instr.value);
-            void *a[] = { (void *)&intqlist, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreIntegerQList)
-
-        QML_BEGIN_INSTR(StoreColor)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QColor c = QColor::fromRgba(instr.value);
-            void *a[] = { &c, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreColor)
-
-        QML_BEGIN_INSTR(StoreDate)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QDate d = QDate::fromJulianDay(instr.value);
-            void *a[] = { &d, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreDate)
-
-        QML_BEGIN_INSTR(StoreTime)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QTime *t = (QTime *)&instr.time;
-            void *a[] = { t, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreTime)
-
-        QML_BEGIN_INSTR(StoreDateTime)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QTime *t = (QTime *)&instr.time;
-            QDateTime dt(QDate::fromJulianDay(instr.date), *t);
-            void *a[] = { &dt, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreDateTime)
-
-        QML_BEGIN_INSTR(StorePoint)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QPoint *p = (QPoint *)&instr.point;
-            void *a[] = { p, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StorePoint)
-
-        QML_BEGIN_INSTR(StorePointF)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QPointF *p = (QPointF *)&instr.point;
-            void *a[] = { p, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StorePointF)
-
-        QML_BEGIN_INSTR(StoreSize)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QSize *s = (QSize *)&instr.size;
-            void *a[] = { s, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreSize)
-
-        QML_BEGIN_INSTR(StoreSizeF)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QSizeF *s = (QSizeF *)&instr.size;
-            void *a[] = { s, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreSizeF)
-
-        QML_BEGIN_INSTR(StoreRect)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QRect *r = (QRect *)&instr.rect;
-            void *a[] = { r, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreRect)
-
-        QML_BEGIN_INSTR(StoreRectF)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QRectF *r = (QRectF *)&instr.rect;
-            void *a[] = { r, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreRectF)
-
-        QML_BEGIN_INSTR(StoreVector3D)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QVector3D *v = (QVector3D *)&instr.vector;
-            void *a[] = { v, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreVector3D)
-
-        QML_BEGIN_INSTR(StoreVector4D)
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QVector4D *v = (QVector4D *)&instr.vector;
-            void *a[] = { v, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty,
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreVector4D)
-
-        QML_BEGIN_INSTR(StoreObject)
-            QObject *assignObj = objects.pop();
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            void *a[] = { (void *)&assignObj, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreObject)
-
         QML_BEGIN_INSTR(AssignCustomType)
             QObject *target = objects.top();
             CLEAN_PROPERTY(target, instr.propertyIndex);
@@ -972,21 +730,16 @@ QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
             QObject *context = 
                 objects.at(objects.count() - 1 - instr.context);
 
-            QDeclarativeProperty mp = 
-                QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
-
-            int coreIndex = mp.index();
-
-            if (instr.isRoot && BINDINGSKIPLIST.testBit(coreIndex)) 
+            if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
                 QML_NEXT_INSTR(StoreBinding);
 
             QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true, 
                                                                 context, CTXT, COMP->name, instr.line);
             bindValues.push(bind);
             bind->m_mePtr = &bindValues.top();
-            bind->setTarget(mp);
+            bind->setTarget(target, instr.property, CTXT);
 
-            bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(mp));
+            bind->addToObject(target, QDeclarativePropertyPrivate::bindingIndex(instr.property));
         QML_END_INSTR(StoreBinding)
 
         QML_BEGIN_INSTR(StoreBindingOnAlias)
@@ -995,21 +748,19 @@ QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
             QObject *context = 
                 objects.at(objects.count() - 1 - instr.context);
 
-            QDeclarativeProperty mp = 
-                QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
-
-            int coreIndex = mp.index();
-
-            if (instr.isRoot && BINDINGSKIPLIST.testBit(coreIndex)) 
+            if (instr.isRoot && BINDINGSKIPLIST.testBit(instr.property.coreIndex))
                 QML_NEXT_INSTR(StoreBindingOnAlias);
 
             QDeclarativeBinding *bind = new QDeclarativeBinding(PRIMITIVES.at(instr.value), true,
                                                                 context, CTXT, COMP->name, instr.line);
             bindValues.push(bind);
             bind->m_mePtr = &bindValues.top();
-            bind->setTarget(mp);
+            bind->setTarget(target, instr.property, CTXT);
 
-            QDeclarativeAbstractBinding *old = QDeclarativePropertyPrivate::setBindingNoEnable(target, coreIndex, QDeclarativePropertyPrivate::valueTypeCoreIndex(mp), bind);
+            QDeclarativeAbstractBinding *old =
+                QDeclarativePropertyPrivate::setBindingNoEnable(target, instr.property.coreIndex,
+                                                                instr.property.getValueTypeCoreIndex(),
+                                                                bind);
             if (old) { old->destroy(); }
         QML_END_INSTR(StoreBindingOnAlias)
 
@@ -1052,10 +803,8 @@ QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
             QDeclarativePropertyValueSource *vs = reinterpret_cast<QDeclarativePropertyValueSource *>(reinterpret_cast<char *>(obj) + instr.castValue);
             QObject *target = objects.at(objects.count() - 1 - instr.owner);
 
-            QDeclarativeProperty prop = 
-                QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
             obj->setParent(target);
-            vs->setTarget(prop);
+            vs->setTarget(QDeclarativePropertyPrivate::restore(target, instr.property, CTXT));
         QML_END_INSTR(StoreValueSource)
 
         QML_BEGIN_INSTR(StoreValueInterceptor)
@@ -1063,7 +812,7 @@ QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
             QDeclarativePropertyValueInterceptor *vi = reinterpret_cast<QDeclarativePropertyValueInterceptor *>(reinterpret_cast<char *>(obj) + instr.castValue);
             QObject *target = objects.at(objects.count() - 1 - instr.owner);
             QDeclarativeProperty prop = 
-                QDeclarativePropertyPrivate::restore(instr.property, target, CTXT);
+                QDeclarativePropertyPrivate::restore(target, instr.property, CTXT);
             obj->setParent(target);
             vi->setTarget(prop);
             QDeclarativeVMEMetaObject *mo = static_cast<QDeclarativeVMEMetaObject *>((QMetaObject*)target->metaObject());
@@ -1096,26 +845,6 @@ QObject *QDeclarativeVME::run(QList<QDeclarativeError> *errors,
             list.qListProperty.append((QDeclarativeListProperty<void>*)&list.qListProperty, ptr);
         QML_END_INSTR(AssignObjectList)
 
-        QML_BEGIN_INSTR(StoreVariantObject)
-            QObject *assign = objects.pop();
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            QVariant v = QVariant::fromValue(assign);
-            void *a[] = { &v, 0, &status, &flags };
-            QMetaObject::metacall(target, QMetaObject::WriteProperty, 
-                                  instr.propertyIndex, a);
-        QML_END_INSTR(StoreVariantObject)
-
-        QML_BEGIN_INSTR(StoreVarObject)
-            QObject *assign = objects.pop();
-            QObject *target = objects.top();
-            CLEAN_PROPERTY(target, instr.propertyIndex);
-
-            v8::Handle<v8::Value> v8Value = ep->v8engine()->newQObject(assign);
-            static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject *>(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value);
-        QML_END_INSTR(StoreVarObject)
-
         QML_BEGIN_INSTR(StoreInterface)
             QObject *assign = objects.pop();
             QObject *target = objects.top();
index 8508e24..890eadf 100644 (file)
@@ -29,7 +29,7 @@ SOURCES += \
     $$PWD/qdeclarativescript.cpp \
     $$PWD/qdeclarativerewrite.cpp \
     $$PWD/qdeclarativevaluetype.cpp \
-    $$PWD/qdeclarativefastproperties.cpp \
+    $$PWD/qdeclarativeaccessors.cpp \
     $$PWD/qdeclarativexmlhttprequest.cpp \
     $$PWD/qdeclarativesqldatabase.cpp \
     $$PWD/qdeclarativewatcher.cpp \
@@ -95,7 +95,7 @@ HEADERS += \
     $$PWD/qdeclarativescript_p.h \
     $$PWD/qdeclarativerewrite_p.h \
     $$PWD/qdeclarativevaluetype_p.h \
-    $$PWD/qdeclarativefastproperties_p.h \
+    $$PWD/qdeclarativeaccessors_p.h \
     $$PWD/qdeclarativexmlhttprequest_p.h \
     $$PWD/qdeclarativesqldatabase_p.h \
     $$PWD/qdeclarativewatcher_p.h \
index 835b7e7..2dc812f 100644 (file)
@@ -46,7 +46,7 @@
 #include "qv4compiler_p.h"
 #include "qv4compiler_p_p.h"
 
-#include <private/qdeclarativefastproperties_p.h>
+#include <private/qdeclarativeaccessors_p.h>
 #include <private/qdeclarativedebugtrace_p.h>
 #include <private/qdeclarativemetatype_p.h>
 
@@ -760,7 +760,17 @@ void QV4Bindings::run(int instrIndex, quint32 &executedBlocks,
             reg.init((Register::Type)instr->fetchAndSubscribe.valueType);
             if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
                 MARK_REGISTER(instr->fetchAndSubscribe.reg);
-            QDeclarativeFastProperties::instance()->accessor(instr->fetchAndSubscribe.function)(object, reg.typeDataPtr(), sub);
+            QDeclarativeAccessors *accessors = instr->fetchAndSubscribe.property.accessors;
+            accessors->read(object, instr->fetchAndSubscribe.property.accessorData,
+                            reg.typeDataPtr());
+
+            if (accessors->notifier) {
+                QDeclarativeNotifier *notifier = 0;
+                accessors->notifier(object, instr->fetchAndSubscribe.property.accessorData, &notifier);
+                if (notifier) sub->connect(notifier);
+            } else if (instr->fetchAndSubscribe.property.notifyIndex != -1) {
+                sub->connect(object, instr->fetchAndSubscribe.property.notifyIndex);
+            }
         }
     }
     QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe)
index 1d6cd30..e091ce2 100644 (file)
@@ -46,7 +46,7 @@
 #include "qv4irbuilder_p.h"
 
 #include <private/qdeclarativejsast_p.h>
-#include <private/qdeclarativefastproperties_p.h>
+#include <private/qdeclarativeaccessors_p.h>
 #include <private/qdeclarativejsengine_p.h>
 
 QT_BEGIN_NAMESPACE
@@ -323,7 +323,6 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
             QMetaProperty prop;
             e->property->load(prop, QDeclarativeEnginePrivate::get(engine));
         }
-        int fastFetchIndex = QDeclarativeFastProperties::instance()->accessorIndexForProperty(e->meta, e->property->coreIndex);
 
         const int propTy = e->property->propType;
         QDeclarativeRegisterType regType;
@@ -359,13 +358,13 @@ void QV4CompilerPrivate::visitName(IR::Name *e)
             break;
         } // switch
 
-        if (fastFetchIndex != -1) {
+        if (e->property->hasAccessors()) {
             Instr::FetchAndSubscribe fetch;
             fetch.reg = currentReg;
-            fetch.function = fastFetchIndex;
             fetch.subscription = subscriptionIndex(_subscribeName);
             fetch.exceptionId = exceptionId(e->line, e->column);
             fetch.valueType = regType;
+            fetch.property = *e->property;
             gen(fetch);
         } else {
             if (blockNeedsSubscription(_subscribeName) && e->property->notifyIndex != -1) {
index 411e96b..ccf91d5 100644 (file)
@@ -103,7 +103,7 @@ void Bytecode::dump(const V4Instr *i, int address) const
         INSTR_DUMP << "\t" << "SubscribeId" << "\t\t" << "Id_Offset(" << i->subscribeop.index << ") -> Subscribe_Slot(" << i->subscribeop.offset << ")";
         break;
     case V4Instr::FetchAndSubscribe:
-        INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << i->fetchAndSubscribe.reg << ") Fast_Accessor(" << i->fetchAndSubscribe.function << ") -> Output_Reg(" << i->fetchAndSubscribe.reg << ") Subscription_Slot(" <<  i->fetchAndSubscribe.subscription << ")";
+        INSTR_DUMP << "\t" << "FetchAndSubscribe" << "\t" << "Object_Reg(" << i->fetchAndSubscribe.reg << ") Fast_Accessor(" << i->fetchAndSubscribe.property.accessors << ") -> Output_Reg(" << i->fetchAndSubscribe.reg << ") Subscription_Slot(" <<  i->fetchAndSubscribe.subscription << ")";
         break;
     case V4Instr::LoadId:
         INSTR_DUMP << "\t" << "LoadId" << "\t\t\t" << "Id_Offset(" << i->load.index << ") -> Output_Reg(" << i->load.reg << ")";
index 343df80..6f90117 100644 (file)
@@ -58,6 +58,8 @@
 #include <QtCore/qvector.h>
 #include <QtCore/qvarlengtharray.h>
 
+#include <private/qdeclarativepropertycache_p.h>
+
 QT_BEGIN_HEADER
 
 QT_BEGIN_NAMESPACE
@@ -166,6 +168,9 @@ QT_BEGIN_NAMESPACE
 #  define QML_V4_INSTR_HEADER quint8 type;
 #endif
 
+class QObject;
+class QDeclarativeNotifier;
+
 namespace QDeclarativeJS {
 
 union V4Instr {
@@ -232,7 +237,7 @@ union V4Instr {
         quint8 exceptionId;
         quint8 valueType;
         quint16 subscription;
-        quint16 function;
+        QDeclarativePropertyRawData property;
     };
 
     struct instr_fetch{
index 271267d..3386c5d 100644 (file)
@@ -122,7 +122,7 @@ void QV8Bindings::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
         ep->dereferenceScarceResources(); 
 
     } else {
-        QDeclarativeProperty p = QDeclarativePropertyPrivate::restore(property, object, context);
+        QDeclarativeProperty p = QDeclarativePropertyPrivate::restore(object, property, context);
         QDeclarativeBindingPrivate::printBindingLoopError(p);
     }
 }
index 6a9f583..40ad93a 100644 (file)
@@ -50,6 +50,7 @@
 #include <private/qdeclarativebinding_p.h>
 #include <private/qjsvalue_p.h>
 #include <private/qscript_impl_p.h>
+#include <private/qdeclarativeaccessors_p.h>
 
 #include <QtDeclarative/qjsvalue.h>
 #include <QtCore/qvarlengtharray.h>
@@ -131,9 +132,9 @@ public:
     static const size_t Size = SMax<A, SMax<B, SMax<C, SMax<D, E> > > >::Size;
 };
 
-struct MetaCallArgument {
-    inline MetaCallArgument();
-    inline ~MetaCallArgument();
+struct CallArgument {
+    inline CallArgument();
+    inline ~CallArgument();
     inline void *dataPtr();
 
     inline void initAsType(int type);
@@ -141,7 +142,7 @@ struct MetaCallArgument {
     inline v8::Handle<v8::Value> toValue(QV8Engine *);
 
 private:
-    MetaCallArgument(const MetaCallArgument &);
+    CallArgument(const CallArgument &);
 
     inline void cleanup();
 
@@ -213,65 +214,90 @@ void QV8QObjectWrapper::destroy()
     qPersistentDispose(m_constructor);
 }
 
-#define FAST_VALUE_GETTER(name, cpptype, defaultvalue, constructor) \
-static v8::Handle<v8::Value> name ## ValueGetter(v8::Local<v8::String>, const v8::AccessorInfo &info) \
-{ \
-    v8::Handle<v8::Object> This = info.This(); \
-    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This); \
- \
-    if (resource->object.isNull()) return v8::Undefined(); \
- \
-    QObject *object = resource->object; \
- \
-    uint32_t data = info.Data()->Uint32Value(); \
-    int index = data & 0x7FFF; \
-    int notify = (data & 0x0FFF0000) >> 16; \
-    if (notify == 0x0FFF) notify = -1; \
- \
-    QDeclarativeEnginePrivate *ep = resource->engine->engine()?QDeclarativeEnginePrivate::get(resource->engine->engine()):0; \
-    if (ep && notify /* 0 means constant */ ) \
-        ep->captureProperty(object, index, notify); \
- \
-    cpptype value = defaultvalue; \
-    void *args[] = { &value, 0 }; \
-    QMetaObject::metacall(object, QMetaObject::ReadProperty, index, args); \
- \
-    return constructor(value); \
-} \
-static v8::Handle<v8::Value> name ## ValueGetterDirect(v8::Local<v8::String>, const v8::AccessorInfo &info) \
-{ \
-    v8::Handle<v8::Object> This = info.This(); \
-    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This); \
- \
-    if (resource->object.isNull()) return v8::Undefined(); \
- \
-    QObject *object = resource->object; \
- \
-    uint32_t data = info.Data()->Uint32Value(); \
-    int index = data & 0x7FFF; \
-    int notify = (data & 0x0FFF0000) >> 16; \
-    if (notify == 0x0FFF) notify = -1; \
- \
-    QDeclarativeEnginePrivate *ep = resource->engine->engine()?QDeclarativeEnginePrivate::get(resource->engine->engine()):0; \
-    if (ep && notify /* 0 means constant */ ) \
-        ep->captureProperty(object, index, notify); \
- \
-    cpptype value = defaultvalue; \
-    void *args[] = { &value, 0 }; \
-    object->qt_metacall(QMetaObject::ReadProperty, index, args); \
- \
-    return constructor(value); \
-} 
-
-#define CREATE_FUNCTION \
-    "(function(method) { "\
-        "return (function(object, data, qmlglobal) { "\
-            "return (function() { "\
-                "return method(object, data, qmlglobal, arguments.length, arguments); "\
-            "});"\
-        "});"\
-    "})"
+struct ReadAccessor {
+    static inline void Indirect(QObject *object, const QDeclarativePropertyData &property,
+                                void *output, QDeclarativeNotifier **n)
+    {
+        Q_ASSERT(n == 0);
+        Q_UNUSED(n);
+
+        void *args[] = { output, 0 };
+        QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
+    }
 
+    static inline void Direct(QObject *object, const QDeclarativePropertyData &property,
+                              void *output, QDeclarativeNotifier **n)
+    {
+        Q_ASSERT(n == 0);
+        Q_UNUSED(n);
+
+        void *args[] = { output, 0 };
+        object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args);
+    }
+
+    static inline void Accessor(QObject *object, const QDeclarativePropertyData &property,
+                                void *output, QDeclarativeNotifier **n)
+    {
+        Q_ASSERT(property.accessors);
+
+        property.accessors->read(object, property.accessorData, output);
+        if (n) property.accessors->notifier(object, property.accessorData, n);
+    }
+};
+
+static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, int v)
+{ return v8::Integer::New(v); }
+static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, uint v)
+{ return v8::Integer::NewFromUnsigned(v); }
+static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, bool v)
+{ return v8::Boolean::New(v); }
+static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *e, const QString &v)
+{ return e->toString(v); }
+static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, float v)
+{ return v8::Number::New(v); }
+static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *, double v)
+{ return v8::Number::New(v); }
+static inline v8::Handle<v8::Value> valueToHandle(QV8Engine *e, QObject *v)
+{ return e->newQObject(v); }
+
+template<typename T, void (*ReadFunction)(QObject *, const QDeclarativePropertyData &,
+                                          void *, QDeclarativeNotifier **)>
+static v8::Handle<v8::Value> GenericValueGetter(v8::Local<v8::String>, const v8::AccessorInfo &info)
+{
+    v8::Handle<v8::Object> This = info.This();
+    QV8QObjectResource *resource = v8_resource_check<QV8QObjectResource>(This);
+
+    QObject *object = resource->object;
+    if (!object) return v8::Undefined();
+
+    QDeclarativePropertyData *property =
+        (QDeclarativePropertyData *)v8::External::Unwrap(info.Data());
+
+    QDeclarativeEngine *engine = resource->engine->engine();
+    QDeclarativeEnginePrivate *ep = engine?QDeclarativeEnginePrivate::get(engine):0;
+
+    T value = T();
+
+    if (ep && ep->propertyCapture) {
+        if (ReadFunction == ReadAccessor::Accessor && property->accessors->notifier) {
+            QDeclarativeNotifier *notifier = 0;
+            ReadFunction(object, *property, &value, &notifier);
+            if (notifier) ep->captureProperty(notifier);
+        } else if (!property->isConstant()) {
+            ep->captureProperty(object, property->coreIndex, property->notifyIndex);
+            ReadFunction(object, *property, &value, 0);
+        } else {
+            ReadFunction(object, *property, &value, 0);
+        }
+    } else {
+        ReadFunction(object, *property, &value, 0);
+    }
+
+    return valueToHandle(resource->engine, value);
+}
+
+#define FAST_GETTER_FUNCTION(property, cpptype) \
+    (property->hasAccessors()?((v8::AccessorGetter)GenericValueGetter<cpptype, &ReadAccessor::Accessor>):(property->isDirect()?((v8::AccessorGetter)GenericValueGetter<cpptype, &ReadAccessor::Direct>):((v8::AccessorGetter)GenericValueGetter<cpptype, &ReadAccessor::Indirect>)))
 
 static quint32 toStringHash = -1;
 static quint32 destroyHash = -1;
@@ -298,8 +324,17 @@ void QV8QObjectWrapper::init(QV8Engine *engine)
     }
     {
     v8::ScriptOrigin origin(m_hiddenObject); // Hack to allow us to identify these functions
-    v8::Local<v8::Script> script = v8::Script::New(v8::String::New(CREATE_FUNCTION), &origin, 0,
+#define CREATE_FUNCTION_SOURCE \
+    "(function(method) { "\
+        "return (function(object, data, qmlglobal) { "\
+            "return (function() { "\
+                "return method(object, data, qmlglobal, arguments.length, arguments); "\
+            "});"\
+        "});"\
+    "})"
+    v8::Local<v8::Script> script = v8::Script::New(v8::String::New(CREATE_FUNCTION_SOURCE), &origin, 0,
                                                    v8::Handle<v8::String>(), v8::Script::NativeMode);
+#undef CREATE_FUNCTION_SOURCE
     v8::Local<v8::Function> fn = v8::Local<v8::Function>::Cast(script->Run());
     v8::Handle<v8::Value> invokeFn = v8::FunctionTemplate::New(Invoke)->GetFunction();
     v8::Handle<v8::Value> args[] = { invokeFn };
@@ -344,107 +379,85 @@ QObject *QV8QObjectWrapper::toQObject(QV8ObjectResource *r)
 }
 
 // Load value properties
-static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object, 
-                                          const QDeclarativePropertyData &property)
+template<void (*ReadFunction)(QObject *, const QDeclarativePropertyData &,
+                              void *, QDeclarativeNotifier **)>
+static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
+                                          const QDeclarativePropertyData &property,
+                                          QDeclarativeNotifier **notifier)
 {
     Q_ASSERT(!property.isFunction());
 
-#define PROPERTY_LOAD(metatype, cpptype, constructor) \
-    if (property.propType == QMetaType:: metatype) { \
-        cpptype type = cpptype(); \
-        void *args[] = { &type, 0 }; \
-        QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args); \
-        return constructor(type); \
-    }
-
     if (property.isQObject()) {
         QObject *rv = 0;
-        void *args[] = { &rv, 0 };
-        QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
+        ReadFunction(object, property, &rv, notifier);
         return engine->newQObject(rv);
     } else if (property.isQList()) {
         return engine->listWrapper()->newList(object, property.coreIndex, property.propType);
-    } else PROPERTY_LOAD(QReal, qreal, v8::Number::New)
-    else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Integer::New)
-    else PROPERTY_LOAD(Bool, bool, v8::Boolean::New)
-    else PROPERTY_LOAD(QString, QString, engine->toString)
-    else PROPERTY_LOAD(UInt, uint, v8::Integer::NewFromUnsigned)
-    else PROPERTY_LOAD(Float, float, v8::Number::New)
-    else PROPERTY_LOAD(Double, double, v8::Number::New)
-    else if(property.isV8Handle()) {
+    } else if (property.propType == QMetaType::QReal) {
+        qreal v = 0;
+        ReadFunction(object, property, &v, notifier);
+        return valueToHandle(engine, v);
+    } else if (property.propType == QMetaType::Int || property.isEnum()) {
+        int v = 0;
+        ReadFunction(object, property, &v, notifier);
+        return valueToHandle(engine, v);
+    } else if (property.propType == QMetaType::Bool) {
+        bool v = false;
+        ReadFunction(object, property, &v, notifier);
+        return valueToHandle(engine, v);
+    } else if (property.propType == QMetaType::QString) {
+        QString v;
+        ReadFunction(object, property, &v, notifier);
+        return valueToHandle(engine, v);
+    } else if (property.propType == QMetaType::UInt) {
+        uint v = 0;
+        ReadFunction(object, property, &v, notifier);
+        return valueToHandle(engine, v);
+    } else if (property.propType == QMetaType::Float) {
+        float v = 0;
+        ReadFunction(object, property, &v, notifier);
+        return valueToHandle(engine, v);
+    } else if (property.propType == QMetaType::Double) {
+        double v = 0;
+        ReadFunction(object, property, &v, notifier);
+        return valueToHandle(engine, v);
+    } else if (property.isV8Handle()) {
         QDeclarativeV8Handle handle;
-        void *args[] = { &handle, 0 };
-        QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args); 
+        ReadFunction(object, property, &handle, notifier);
         return handle.toHandle();
+    } else if (property.isQVariant()) {
+        QVariant v;
+        ReadFunction(object, property, &v, notifier);
+        return engine->fromVariant(v);
     } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)
                && engine->engine()) {
+        Q_ASSERT(notifier == 0);
+
         QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
         QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
         if (valueType)
             return engine->newValueType(object, property.coreIndex, valueType);
     } else {
+        Q_ASSERT(notifier == 0);
+
         // see if it's a sequence type
         bool succeeded = false;
-        v8::Handle<v8::Value> retn = engine->newSequence(property.propType, object, property.coreIndex, &succeeded);
+        v8::Handle<v8::Value> retn = engine->newSequence(property.propType, object, property.coreIndex,
+                                                         &succeeded);
         if (succeeded)
             return retn;
     }
 
-    QVariant var = object->metaObject()->property(property.coreIndex).read(object);
-    return engine->fromVariant(var);
-
-#undef PROPERTY_LOAD
-}
-
-static v8::Handle<v8::Value> LoadPropertyDirect(QV8Engine *engine, QObject *object, 
-                                                const QDeclarativePropertyData &property)
-{
-    Q_ASSERT(!property.isFunction());
-
-#define PROPERTY_LOAD(metatype, cpptype, constructor) \
-    if (property.propType == QMetaType:: metatype) { \
-        cpptype type = cpptype(); \
-        void *args[] = { &type, 0 }; \
-        object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args); \
-        return constructor(type); \
-    }
-
-    if (property.isQObject()) {
-        QObject *rv = 0;
-        void *args[] = { &rv, 0 };
-        QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
-        return engine->newQObject(rv);
-    } else if (property.isQList()) {
-        return engine->listWrapper()->newList(object, property.coreIndex, property.propType);
-    } else PROPERTY_LOAD(QReal, qreal, v8::Number::New)
-    else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Integer::New)
-    else PROPERTY_LOAD(Bool, bool, v8::Boolean::New)
-    else PROPERTY_LOAD(QString, QString, engine->toString)
-    else PROPERTY_LOAD(UInt, uint, v8::Integer::NewFromUnsigned)
-    else PROPERTY_LOAD(Float, float, v8::Number::New)
-    else PROPERTY_LOAD(Double, double, v8::Number::New)
-    else if(property.isV8Handle()) {
-        QDeclarativeV8Handle handle;
-        void *args[] = { &handle, 0 };
-        object->qt_metacall(QMetaObject::ReadProperty, property.coreIndex, args); 
-        return handle.toHandle();
-    } else if (engine->engine() && QDeclarativeValueTypeFactory::isValueType((uint)property.propType)) {
-        QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
-        QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
-        if (valueType)
-            return engine->newValueType(object, property.coreIndex, valueType);
+    if (property.propType == QVariant::Invalid) {
+        QMetaProperty p = object->metaObject()->property(property.coreIndex);
+        qWarning("QMetaProperty::read: Unable to handle unregistered datatype '%s' for property "
+                 "'%s::%s'", p.typeName(), object->metaObject()->className(), p.name());
+        return v8::Undefined();
     } else {
-        // see if it's a sequence type
-        bool success = false;
-        v8::Handle<v8::Value> retn = engine->newSequence(property.propType, object, property.coreIndex, &success);
-        if (success)
-            return retn;
+        QVariant v(property.propType, (void *)0);
+        ReadFunction(object, property, v.data(), notifier);
+        return engine->fromVariant(v);
     }
-
-    QVariant var = object->metaObject()->property(property.coreIndex).read(object);
-    return engine->fromVariant(var);
-
-#undef PROPERTY_LOAD
 }
 
 v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object, 
@@ -520,21 +533,43 @@ v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject
         }
     }
 
-    QDeclarativeEnginePrivate *ep = engine->engine()?QDeclarativeEnginePrivate::get(engine->engine()):0;
+    QDeclarativeEnginePrivate *ep =
+        engine->engine()?QDeclarativeEnginePrivate::get(engine->engine()):0;
+
+    if (result->hasAccessors()) {
+        QDeclarativeNotifier *n = 0;
+        QDeclarativeNotifier **nptr = 0;
+
+        if (ep && ep->propertyCapture && result->accessors->notifier)
+            nptr = &n;
+
+        v8::Handle<v8::Value> rv = LoadProperty<ReadAccessor::Accessor>(engine, object, *result, nptr);
+
+        if (result->accessors->notifier) {
+            if (n) ep->captureProperty(n);
+        } else {
+            ep->captureProperty(object, result->coreIndex, result->notifyIndex);
+        }
+
+        return rv;
+    }
+
     if (ep && !result->isConstant()) {
+
         if (result->coreIndex == 0)
             ep->captureProperty(QDeclarativeData::get(object, true)->objectNameNotifier());
         else
             ep->captureProperty(object, result->coreIndex, result->notifyIndex);
     }
 
-    if (result->isVMEProperty())
-        return static_cast<QDeclarativeVMEMetaObject *>(const_cast<QMetaObject*>(object->metaObject()))->vmeProperty(result->coreIndex);
-
-    if (result->isDirect())  {
-        return LoadPropertyDirect(engine, object, *result);
+    if (result->isVMEProperty()) {
+        typedef QDeclarativeVMEMetaObject VMEMO;
+        VMEMO *vmemo = const_cast<VMEMO *>(static_cast<const VMEMO *>(object->metaObject()));
+        return vmemo->vmeProperty(result->coreIndex);
+    } else if (result->isDirect())  {
+        return LoadProperty<ReadAccessor::Direct>(engine, object, *result, 0);
     } else {
-        return LoadProperty(engine, object, *result);
+        return LoadProperty<ReadAccessor::Indirect>(engine, object, *result, 0);
     }
 }
 
@@ -557,8 +592,9 @@ static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativ
 
         newBinding = new QDeclarativeBinding(&function, object, context);
         newBinding->setSourceLocation(url, lineNumber);
-        newBinding->setTarget(QDeclarativePropertyPrivate::restore(*property, object, context));
-        newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
+        newBinding->setTarget(object, *property, context);
+        newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
+                                     QDeclarativeBinding::RequiresThisObject);
     }
 
     QDeclarativeAbstractBinding *oldBinding = 
@@ -791,14 +827,6 @@ v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info
     return rv;
 }
 
-FAST_VALUE_GETTER(QObject, QObject*, 0, resource->engine->newQObject);
-FAST_VALUE_GETTER(Int, int, 0, v8::Integer::New);
-FAST_VALUE_GETTER(Bool, bool, false, v8::Boolean::New);
-FAST_VALUE_GETTER(QString, QString, QString(), resource->engine->toString);
-FAST_VALUE_GETTER(UInt, uint, 0, v8::Integer::NewFromUnsigned);
-FAST_VALUE_GETTER(Float, float, 0, v8::Number::New);
-FAST_VALUE_GETTER(Double, double, 0, v8::Number::New);
-
 static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
                             const v8::AccessorInfo& info)
 {
@@ -809,8 +837,10 @@ static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
 
     QObject *object = resource->object;
 
-    uint32_t data = info.Data()->Uint32Value(); 
-    int index = data & 0x7FFF;  // So that we can use the same data for Setter and Getter
+    QDeclarativePropertyData *property =
+        (QDeclarativePropertyData *)v8::External::Unwrap(info.Data());
+
+    int index = property->coreIndex;
 
     QDeclarativeData *ddata = QDeclarativeData::get(object, false);
     Q_ASSERT(ddata);
@@ -887,9 +917,9 @@ v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8
         // its not guarenteed that this is a win overall.  We need to try and measure the cost.
         for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) {
             QDeclarativePropertyData *property = *iter;
-            if (property->isFunction() || 
-                property->coreIndex >= 0x7FFF || property->notifyIndex >= 0x0FFF || 
-                property->coreIndex == 0)
+            if (property->notFullyResolved()) resolve(property);
+
+            if (property->isFunction())
                 continue;
 
             v8::AccessorGetter fastgetter = 0;
@@ -898,26 +928,21 @@ v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8
                 fastsetter = FastValueSetterReadOnly;
 
             if (property->isQObject()) 
-                fastgetter = property->isDirect()?QObjectValueGetterDirect:QObjectValueGetter;
+                fastgetter = FAST_GETTER_FUNCTION(property, QObject*);
             else if (property->propType == QMetaType::Int || property->isEnum()) 
-                fastgetter = property->isDirect()?IntValueGetterDirect:IntValueGetter;
+                fastgetter = FAST_GETTER_FUNCTION(property, int);
             else if (property->propType == QMetaType::Bool)
-                fastgetter = property->isDirect()?BoolValueGetterDirect:BoolValueGetter;
+                fastgetter = FAST_GETTER_FUNCTION(property, bool);
             else if (property->propType == QMetaType::QString)
-                fastgetter = property->isDirect()?QStringValueGetterDirect:QStringValueGetter;
+                fastgetter = FAST_GETTER_FUNCTION(property, QString);
             else if (property->propType == QMetaType::UInt)
-                fastgetter = property->isDirect()?UIntValueGetterDirect:UIntValueGetter;
+                fastgetter = FAST_GETTER_FUNCTION(property, uint);
             else if (property->propType == QMetaType::Float) 
-                fastgetter = property->isDirect()?FloatValueGetterDirect:FloatValueGetter;
+                fastgetter = FAST_GETTER_FUNCTION(property, float);
             else if (property->propType == QMetaType::Double) 
-                fastgetter = property->isDirect()?DoubleValueGetterDirect:DoubleValueGetter;
+                fastgetter = FAST_GETTER_FUNCTION(property, double);
 
             if (fastgetter) {
-                int notifyIndex = property->notifyIndex;
-                if (property->isConstant()) notifyIndex = 0;
-                else if (notifyIndex == -1) notifyIndex = 0x0FFF;
-                uint32_t data = (notifyIndex & 0x0FFF) << 16 | property->coreIndex;
-
                 QString name = iter.key();
                 if (name == toString || name == destroy)
                     continue;
@@ -932,8 +957,12 @@ v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8
                     ft->InstanceTemplate()->SetHasExternalResource(true);
                 }
 
+                // We wrap the raw QDeclarativePropertyData pointer here.  This is safe as the
+                // pointer will remain valid at least as long as the lifetime of any QObject's of
+                // this type and the property accessor checks if the object is 0 (deleted) before
+                // dereferencing the pointer.
                 ft->InstanceTemplate()->SetAccessor(engine->toString(name), fastgetter, fastsetter,
-                                                    v8::Integer::NewFromUnsigned(data));
+                                                    v8::External::Wrap(property));
             }
         }
 
@@ -1422,7 +1451,7 @@ static v8::Handle<v8::Value> CallMethod(QObject *object, int index, int returnTy
 {
     if (argCount > 0) {
 
-        QVarLengthArray<MetaCallArgument, 9> args(argCount + 1);
+        QVarLengthArray<CallArgument, 9> args(argCount + 1);
         args[0].initAsType(returnType);
 
         for (int ii = 0; ii < argCount; ++ii)
@@ -1438,7 +1467,7 @@ static v8::Handle<v8::Value> CallMethod(QObject *object, int index, int returnTy
 
     } else if (returnType != 0) {
         
-        MetaCallArgument arg;
+        CallArgument arg;
         arg.initAsType(returnType);
 
         void *args[] = { arg.dataPtr() };
@@ -1871,17 +1900,17 @@ v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args)
     }
 }
 
-MetaCallArgument::MetaCallArgument()
+CallArgument::CallArgument()
 : type(QVariant::Invalid)
 {
 }
 
-MetaCallArgument::~MetaCallArgument()
+CallArgument::~CallArgument()
 {
     cleanup();
 }
 
-void MetaCallArgument::cleanup()
+void CallArgument::cleanup()
 {
     if (type == QMetaType::QString) {
         qstringPtr->~QString();
@@ -1894,7 +1923,7 @@ void MetaCallArgument::cleanup()
     } 
 }
 
-void *MetaCallArgument::dataPtr()
+void *CallArgument::dataPtr()
 {
     if (type == -1)
         return qvariantPtr->data();
@@ -1902,7 +1931,7 @@ void *MetaCallArgument::dataPtr()
         return (void *)&allocData;
 }
 
-void MetaCallArgument::initAsType(int callType)
+void CallArgument::initAsType(int callType)
 {
     if (type != 0) { cleanup(); type = 0; }
     if (callType == 0) return;
@@ -1937,7 +1966,7 @@ void MetaCallArgument::initAsType(int callType)
     }
 }
 
-void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Value> value)
+void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Value> value)
 {
     if (type != 0) { cleanup(); type = 0; }
 
@@ -2013,7 +2042,7 @@ void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8:
     }
 }
 
-v8::Handle<v8::Value> MetaCallArgument::toValue(QV8Engine *engine)
+v8::Handle<v8::Value> CallArgument::toValue(QV8Engine *engine)
 {
     if (type == qMetaTypeId<QJSValue>()) {
         return QJSValuePrivate::get(*qjsValuePtr)->asV8Value(engine);
index a947d52..1861ea6 100644 (file)
@@ -254,8 +254,7 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
                 if (objectType == QV8SequenceResource::Reference) { \
                     if (!object) \
                         return QVariant(); \
-                    void *a[] = { &c, 0 }; \
-                    QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \
+                    loadReference(); \
                 } \
                 return QVariant::fromValue<SequenceType>(c); \
             } \
@@ -283,8 +282,7 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
                 if (objectType == QV8SequenceResource::Reference) { \
                     if (!object) \
                         return 0; \
-                    void *a[] = { &c, 0 }; \
-                    QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \
+                    loadReference(); \
                 } \
                 return c.count(); \
             } \
@@ -335,8 +333,7 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
                 if (objectType == QV8SequenceResource::Reference) { \
                     if (!object) \
                         return v8::Undefined(); \
-                    void *a[] = { &c, 0 }; \
-                    QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \
+                    loadReference(); \
                 } \
                 /* modify the sequence */ \
                 SequenceElementType elementValue = ConversionFromV8fn(engine, value); \
@@ -353,13 +350,9 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
                     } \
                     c.append(elementValue); \
                 } \
-                if (objectType == QV8SequenceResource::Reference) { \
-                    /* write back.  already checked that object is non-null, so skip that check here. */ \
-                    int status = -1; \
-                    QDeclarativePropertyPrivate::WriteFlags flags = QDeclarativePropertyPrivate::DontRemoveBinding; \
-                    void *a[] = { &c, 0, &status, &flags }; \
-                    QMetaObject::metacall(object, QMetaObject::WriteProperty, propertyIndex, a); \
-                } \
+                /* write back.  already checked that object is non-null, so skip that check here. */ \
+                if (objectType == QV8SequenceResource::Reference) \
+                    storeReference(); \
                 return value; \
             } \
             v8::Handle<v8::Value> indexedGetter(quint32 index) \
@@ -367,8 +360,7 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
                 if (objectType == QV8SequenceResource::Reference) { \
                     if (!object) \
                         return v8::Undefined(); \
-                    void *a[] = { &c, 0 }; \
-                    QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \
+                    loadReference(); \
                 } \
                 quint32 count = c.count(); \
                 if (index < count) \
@@ -403,8 +395,7 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
                 if (objectType == QV8SequenceResource::Reference) { \
                     if (!object) \
                         return v8::Handle<v8::Array>(); \
-                    void *a[] = { &c, 0 }; \
-                    QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \
+                    loadReference(); \
                 } \
                 quint32 count = c.count(); \
                 v8::Local<v8::Array> retn = v8::Array::New(count); \
@@ -418,8 +409,7 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
                 if (objectType == QV8SequenceResource::Reference) { \
                     if (!object) \
                         return v8::Undefined(); \
-                    void *a[] = { &c, 0 }; \
-                    QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \
+                    loadReference(); \
                 } \
                 QString str; \
                 quint32 count = c.count(); \
@@ -429,6 +419,23 @@ static QString convertUrlToString(QV8Engine *, const QUrl &v)
                 str.chop(1); \
                 return engine->toString(str); \
             } \
+            void loadReference() \
+            { \
+                Q_ASSERT(object); \
+                Q_ASSERT(objectType == QV8SequenceResource::Reference); \
+                void *a[] = { &c, 0 }; \
+                QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \
+            } \
+            void storeReference() \
+            { \
+                Q_ASSERT(object); \
+                Q_ASSERT(objectType == QV8SequenceResource::Reference); \
+                int status = -1; \
+                QDeclarativePropertyPrivate::WriteFlags flags = \
+                    QDeclarativePropertyPrivate::DontRemoveBinding; \
+                void *a[] = { &c, 0, &status, &flags }; \
+                QMetaObject::metacall(object, QMetaObject::WriteProperty, propertyIndex, a); \
+            } \
         private: \
             QDeclarativeGuard<QObject> object; \
             int propertyIndex; \
index aca0c85..53d500c 100644 (file)
@@ -346,9 +346,9 @@ v8::Handle<v8::Value> QV8ValueTypeWrapper::Setter(v8::Local<v8::String> property
 
             newBinding = new QDeclarativeBinding(&function, reference->object, context);
             newBinding->setSourceLocation(url, lineNumber);
-            newBinding->setTarget(QDeclarativePropertyPrivate::restore(cacheData, reference->object, 
-                                                                       context));
-            newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
+            newBinding->setTarget(reference->object, cacheData, context);
+            newBinding->setEvaluateFlags(newBinding->evaluateFlags() |
+                                         QDeclarativeBinding::RequiresThisObject);
         }
 
         QDeclarativeAbstractBinding *oldBinding = 
index bd795cb..1f57d53 100644 (file)
@@ -1986,14 +1986,6 @@ void QDeclarativeItemPrivate::transform_clear(QDeclarativeListProperty<QGraphics
     }
 }
 
-void QDeclarativeItemPrivate::parentProperty(QObject *o, void *rv, QDeclarativeNotifierEndpoint *e)
-{
-    QDeclarativeItem *item = static_cast<QDeclarativeItem*>(o);
-    if (e)
-        e->connect(&item->d_func()->parentNotifier);
-    *((QDeclarativeItem **)rv) = item->parentItem();
-}
-
 /*!
     \qmlproperty list<Object> QtQuick1::Item::data
     \default
@@ -3101,7 +3093,6 @@ QVariant QDeclarativeItem::itemChange(GraphicsItemChange change,
     case ItemParentHasChanged:
         d->resolveLayoutMirror();
         emit parentChanged(parentItem());
-        d->parentNotifier.notify();
         break;
     case ItemVisibleHasChanged: {
             for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
index 8dccd1a..1dcafe5 100644 (file)
@@ -216,10 +216,6 @@ public:
         return item->d_func();
     }
 
-    // Accelerated property accessors
-    QDeclarativeNotifier parentNotifier;
-    static void parentProperty(QObject *o, void *rv, QDeclarativeNotifierEndpoint *e);
-
     QDeclarative1Anchors *anchors() {
         if (!_anchors) {
             Q_Q(QDeclarativeItem);
index b8c0e10..bb6c536 100644 (file)
@@ -40,7 +40,6 @@
 ****************************************************************************/
 
 #include <QtDeclarative/qdeclarative.h>
-#include <QtDeclarative/private/qdeclarativefastproperties_p.h>
 #include <QtQuick1/qdeclarativeitem.h>
 #include <QtQuick1/private/qdeclarativeitem_p.h>
 #include <QtQuick1/private/qdeclarativeutilmodule_p.h>
@@ -51,9 +50,6 @@ QT_BEGIN_NAMESPACE
 
 void QDeclarativeQtQuick1Module::defineModule(QDeclarativeQtQuick1Module::Module module)
 {
-    QDeclarativeFastProperties::instance()->add(&QDeclarativeItem::staticMetaObject,
-                                QDeclarativeItem::staticMetaObject.indexOfProperty("parent"),
-                                QDeclarativeItemPrivate::parentProperty);
     if (module == QtQuick1)
         qmlRegisterBaseTypes("QtQuick", 1, 0);
     else if (module == Qt47)
index a9409ec..5ec0787 100644 (file)
 #include <QtQuick/private/qdeclarativestate_p.h>
 #include <private/qlistmodelinterface_p.h>
 #include <private/qquickitem_p.h>
+#include <private/qdeclarativeaccessors_p.h>
 
 #include <float.h>
 
-// XXX todo Readd parentNotifier for faster parent bindings
 // XXX todo Check that elements that create items handle memory correctly after visual ownership change
 
 QT_BEGIN_NAMESPACE
 
+static void QQuickItem_parentNotifier(QObject *o, intptr_t, QDeclarativeNotifier **n)
+{
+    QQuickItemPrivate *d = QQuickItemPrivate::get(static_cast<QQuickItem *>(o));
+    *n = &d->parentNotifier;
+}
+
+QML_PRIVATE_ACCESSOR(QQuickItem, QQuickItem *, parent, parentItem)
+QML_PRIVATE_ACCESSOR(QQuickItem, qreal, x, x)
+QML_PRIVATE_ACCESSOR(QQuickItem, qreal, y, y)
+QML_PRIVATE_ACCESSOR(QQuickItem, qreal, width, width)
+QML_PRIVATE_ACCESSOR(QQuickItem, qreal, height, height)
+
+static QDeclarativeAccessors QQuickItem_parent = { QQuickItem_parentRead, QQuickItem_parentNotifier };
+static QDeclarativeAccessors QQuickItem_x = { QQuickItem_xRead, 0 };
+static QDeclarativeAccessors QQuickItem_y = { QQuickItem_yRead, 0 };
+static QDeclarativeAccessors QQuickItem_width = { QQuickItem_widthRead, 0 };
+static QDeclarativeAccessors QQuickItem_height = { QQuickItem_heightRead, 0 };
+
+QML_DECLARE_PROPERTIES(QQuickItem) {
+    { QML_PROPERTY_NAME(parent), 0, &QQuickItem_parent },
+    { QML_PROPERTY_NAME(x), 0, &QQuickItem_x },
+    { QML_PROPERTY_NAME(y), 0, &QQuickItem_y },
+    { QML_PROPERTY_NAME(width), 0, &QQuickItem_width },
+    { QML_PROPERTY_NAME(height), 0, &QQuickItem_height }
+};
+
+void QQuickItemPrivate::registerAccessorProperties()
+{
+    QML_DEFINE_PROPERTIES(QQuickItem);
+}
+
 /*!
     \qmlclass Transform QQuickTransform
     \inqmlmodule QtQuick 2
@@ -1880,6 +1911,7 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
 
     d->itemChange(ItemParentHasChanged, d->parentItem);
 
+    d->parentNotifier.notify();
     emit parentChanged(d->parentItem);
 }
 
index 6e7a909..ffc1017 100644 (file)
@@ -146,6 +146,7 @@ class Q_QUICK_EXPORT QQuickItem : public QObject, public QDeclarativeParserStatu
 
     Q_ENUMS(TransformOrigin)
     Q_CLASSINFO("DefaultProperty", "data")
+    Q_CLASSINFO("qt_HasQmlAccessors", "true")
 
 public:
     enum Flag {
index a522a19..79d98d7 100644 (file)
@@ -141,6 +141,8 @@ public:
     static QQuickItemPrivate* get(QQuickItem *item) { return item->d_func(); }
     static const QQuickItemPrivate* get(const QQuickItem *item) { return item->d_func(); }
 
+    static void registerAccessorProperties();
+
     QQuickItemPrivate();
     ~QQuickItemPrivate();
     void init(QQuickItem *parent);
@@ -281,6 +283,8 @@ public:
     QSGContext *sceneGraphContext() const { Q_ASSERT(canvas); return static_cast<QQuickCanvasPrivate *>(QObjectPrivate::get(canvas))->context; }
 
     QQuickItem *parentItem;
+    QDeclarativeNotifier parentNotifier;
+
     QList<QQuickItem *> childItems;
     mutable QList<QQuickItem *> *sortedChildItems;
     QList<QQuickItem *> paintOrderChildItems() const;
index a9d8a19..69b9caf 100644 (file)
@@ -108,6 +108,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor)
 {
     QDeclarativePrivate::RegisterAutoParent autoparent = { 0, &qquickitem_autoParent };
     QDeclarativePrivate::qmlregister(QDeclarativePrivate::AutoParentRegistration, &autoparent);
+    QQuickItemPrivate::registerAccessorProperties();
 
 #ifdef QT_NO_MOVIE
     qmlRegisterTypeNotAvailable(uri,major,minor,"AnimatedImage", qApp->translate("QQuickAnimatedImage","Qt was built without support for QMovie"));