From 5ac2990688c7da6ce872bccc5c08129267887d68 Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Mon, 28 Nov 2011 16:04:33 +0000 Subject: [PATCH] Introduce more generic fast property handling Also reduce the number of direct calls to qt_metacall(). Change-Id: I04cd6e516a3e61058548309a19fe0b830f15c93f Reviewed-by: Roberto Raggi --- src/declarative/qml/qdeclarativeaccessors.cpp | 127 +++++ src/declarative/qml/qdeclarativeaccessors_p.h | 164 ++++++ src/declarative/qml/qdeclarativebinding.cpp | 10 + src/declarative/qml/qdeclarativebinding_p.h | 1 + .../qml/qdeclarativefastproperties.cpp | 109 ---- .../qml/qdeclarativefastproperties_p.h | 78 --- src/declarative/qml/qdeclarativeproperty.cpp | 9 +- src/declarative/qml/qdeclarativeproperty_p.h | 30 +- .../qml/qdeclarativepropertycache.cpp | 232 ++++---- .../qml/qdeclarativepropertycache_p.h | 73 +-- src/declarative/qml/qdeclarativevaluetype.cpp | 504 ++---------------- src/declarative/qml/qdeclarativevaluetype_p.h | 37 +- src/declarative/qml/qdeclarativevme.cpp | 481 ++++------------- src/declarative/qml/qml.pri | 4 +- src/declarative/qml/v4/qv4bindings.cpp | 14 +- src/declarative/qml/v4/qv4compiler.cpp | 7 +- src/declarative/qml/v4/qv4instruction.cpp | 2 +- src/declarative/qml/v4/qv4instruction_p.h | 7 +- src/declarative/qml/v8/qv8bindings.cpp | 2 +- src/declarative/qml/v8/qv8qobjectwrapper.cpp | 395 +++++++------- .../qml/v8/qv8sequencewrapper_p_p.h | 45 +- .../qml/v8/qv8valuetypewrapper.cpp | 6 +- .../graphicsitems/qdeclarativeitem.cpp | 9 - .../graphicsitems/qdeclarativeitem_p.h | 4 - src/qtquick1/qtquick1.cpp | 4 - src/quick/items/qquickitem.cpp | 34 +- src/quick/items/qquickitem.h | 1 + src/quick/items/qquickitem_p.h | 4 + src/quick/items/qquickitemsmodule.cpp | 1 + 29 files changed, 991 insertions(+), 1403 deletions(-) create mode 100644 src/declarative/qml/qdeclarativeaccessors.cpp create mode 100644 src/declarative/qml/qdeclarativeaccessors_p.h delete mode 100644 src/declarative/qml/qdeclarativefastproperties.cpp delete mode 100644 src/declarative/qml/qdeclarativefastproperties_p.h diff --git a/src/declarative/qml/qdeclarativeaccessors.cpp b/src/declarative/qml/qdeclarativeaccessors.cpp new file mode 100644 index 0000000000..96521033b2 --- /dev/null +++ b/src/declarative/qml/qdeclarativeaccessors.cpp @@ -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 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 index 0000000000..bf0b11189a --- /dev/null +++ b/src/declarative/qml/qdeclarativeaccessors_p.h @@ -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 +#include +#include + +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(o)); \ + *static_cast(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 diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp index 9a3a7e005c..fbfba6d8d3 100644 --- a/src/declarative/qml/qdeclarativebinding.cpp +++ b/src/declarative/qml/qdeclarativebinding.cpp @@ -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); diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h index 6f545fc2c6..8f4c736d6a 100644 --- a/src/declarative/qml/qdeclarativebinding_p.h +++ b/src/declarative/qml/qdeclarativebinding_p.h @@ -157,6 +157,7 @@ Q_OBJECT 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 index 5816b3f8cb..0000000000 --- a/src/declarative/qml/qdeclarativefastproperties.cpp +++ /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, 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 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 index 1e09131222..0000000000 --- a/src/declarative/qml/qdeclarativefastproperties_p.h +++ /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 -#include -#include - -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, int> m_index; - QVector m_accessors; - mutable QReadWriteLock m_lock; -}; - -QT_END_NAMESPACE - -QT_END_HEADER - -#endif // QDECLARATIVEFASTPROPERTIES_P_H diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp index 795283c41d..1e0b14ee02 100644 --- a/src/declarative/qml/qdeclarativeproperty.cpp +++ b/src/declarative/qml/qdeclarativeproperty.cpp @@ -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; diff --git a/src/declarative/qml/qdeclarativeproperty_p.h b/src/declarative/qml/qdeclarativeproperty_p.h index f2e86dda19..ce66ef8c2c 100644 --- a/src/declarative/qml/qdeclarativeproperty_p.h +++ b/src/declarative/qml/qdeclarativeproperty_p.h @@ -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 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePropertyPrivate : public QDeclara 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 *); diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp index d99731955b..239b7942da 100644 --- a/src/declarative/qml/qdeclarativepropertycache.cpp +++ b/src/declarative/qml/qdeclarativepropertycache.cpp @@ -46,6 +46,7 @@ #include #include +#include #include @@ -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()) { flags |= QDeclarativePropertyData::IsQmlBinding; } else if (propType == qMetaTypeId()) { @@ -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(); + 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(); - + 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 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(engine, obj, name, local); +} - return rv; +QDeclarativePropertyData * +QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj, + const QString &name, QDeclarativePropertyData &local) +{ + return qDeclarativePropertyCacheProperty(engine, obj, name, local); } static inline const QMetaObjectPrivate *priv(const uint* data) diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h index fc4a24ca9c..3deafdf9c5 100644 --- a/src/declarative/qml/qdeclarativepropertycache_p.h +++ b/src/declarative/qml/qdeclarativepropertycache_p.h @@ -63,14 +63,15 @@ 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 @@ class QDeclarativePropertyRawData 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 @@ class QDeclarativePropertyRawData 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 @@ class QDeclarativePropertyRawData 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 @@ class QDeclarativePropertyRawData 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 @@ class QDeclarativePropertyRawData //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 @@ class QDeclarativePropertyData : public QDeclarativePropertyRawData 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 @@ class Q_DECLARATIVE_EXPORT QDeclarativePropertyCache : public QDeclarativeRefCou 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) diff --git a/src/declarative/qml/qdeclarativevaluetype.cpp b/src/declarative/qml/qdeclarativevaluetype.cpp index ffd0041f7e..434059ff76 100644 --- a/src/declarative/qml/qdeclarativevaluetype.cpp +++ b/src/declarative/qml/qdeclarativevaluetype.cpp @@ -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(value); \ + onLoad(); \ + } -void QDeclarativePointFValueType::setValue(QVariant value) -{ - point = qvariant_cast(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(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(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(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(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(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(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(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(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(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(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(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(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(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(); diff --git a/src/declarative/qml/qdeclarativevaluetype_p.h b/src/declarative/qml/qdeclarativevaluetype_p.h index 9f00d97800..b4c8d7f0a5 100644 --- a/src/declarative/qml/qdeclarativevaluetype_p.h +++ b/src/declarative/qml/qdeclarativevaluetype_p.h @@ -79,10 +79,12 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeValueType : public QObject 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePointFValueType : public QDeclara 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativePointValueType : public QDeclarat 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeSizeFValueType : public QDeclarat 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeSizeValueType : public QDeclarati 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeRectFValueType : public QDeclarat 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeRectValueType : public QDeclarati 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeVector2DValueType : public QDecla 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeVector3DValueType : public QDecla 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeVector4DValueType : public QDecla 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeQuaternionValueType : public QDec 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeMatrix4x4ValueType : public QDecl 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeEasingValueType : public QDeclara 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeFontValueType : public QDeclarati 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeFontValueType : public QDeclarati qreal wordSpacing() const; void setWordSpacing(qreal spacing); + void onLoad(); private: QFont font; bool pixelSizeSet; @@ -606,7 +609,7 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeColorValueType : public QDeclarat 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 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeColorValueType : public QDeclarat QColor color; }; +void QDeclarativeValueType::onLoad() +{ +} + QT_END_NAMESPACE #endif // QDECLARATIVEVALUETYPE_P_H diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp index 327a0ae6c0..556e2a2b69 100644 --- a/src/declarative/qml/qdeclarativevme.cpp +++ b/src/declarative/qml/qdeclarativevme.cpp @@ -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 v8value = value; \ + QObject *target = objects.top(); \ + CLEAN_PROPERTY(target, instr.propertyIndex); \ + QMetaObject *mo = const_cast(target->metaObject()); \ + QDeclarativeVMEMetaObject *vmemo = static_cast(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 *errors, const Interrupt &interrupt @@ -294,6 +338,55 @@ QObject *QDeclarativeVME::run(QList *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, PRIMITIVES.at(instr.value)); + QML_STORE_LIST(StoreUrlQList, QList, URLS.at(instr.value)); + QML_STORE_LIST(StoreDoubleQList, QList, instr.value); + QML_STORE_LIST(StoreBoolQList, QList, instr.value); + QML_STORE_LIST(StoreIntegerQList, QList, 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 *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 v8Value = ep->v8engine()->fromVariant(PRIMITIVES.at(instr.value)); - static_cast(const_cast(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 v8Value = v8::Integer::New(instr.value); - static_cast(const_cast(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 v8Value = v8::Number::New(instr.value); - static_cast(const_cast(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 v8Value = v8::Boolean::New(instr.value); - static_cast(const_cast(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 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 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 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 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 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 *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 *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 *errors, QDeclarativePropertyValueSource *vs = reinterpret_cast(reinterpret_cast(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 *errors, QDeclarativePropertyValueInterceptor *vi = reinterpret_cast(reinterpret_cast(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((QMetaObject*)target->metaObject()); @@ -1096,26 +845,6 @@ QObject *QDeclarativeVME::run(QList *errors, list.qListProperty.append((QDeclarativeListProperty*)&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 v8Value = ep->v8engine()->newQObject(assign); - static_cast(const_cast(target->metaObject()))->setVMEProperty(instr.propertyIndex, v8Value); - QML_END_INSTR(StoreVarObject) - QML_BEGIN_INSTR(StoreInterface) QObject *assign = objects.pop(); QObject *target = objects.top(); diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri index 8508e24e10..890eadf2e1 100644 --- a/src/declarative/qml/qml.pri +++ b/src/declarative/qml/qml.pri @@ -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 \ diff --git a/src/declarative/qml/v4/qv4bindings.cpp b/src/declarative/qml/v4/qv4bindings.cpp index 835b7e7752..2dc812f47b 100644 --- a/src/declarative/qml/v4/qv4bindings.cpp +++ b/src/declarative/qml/v4/qv4bindings.cpp @@ -46,7 +46,7 @@ #include "qv4compiler_p.h" #include "qv4compiler_p_p.h" -#include +#include #include #include @@ -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, ¬ifier); + 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) diff --git a/src/declarative/qml/v4/qv4compiler.cpp b/src/declarative/qml/v4/qv4compiler.cpp index 1d6cd30a99..e091ce2731 100644 --- a/src/declarative/qml/v4/qv4compiler.cpp +++ b/src/declarative/qml/v4/qv4compiler.cpp @@ -46,7 +46,7 @@ #include "qv4irbuilder_p.h" #include -#include +#include #include 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) { diff --git a/src/declarative/qml/v4/qv4instruction.cpp b/src/declarative/qml/v4/qv4instruction.cpp index 411e96b137..ccf91d567b 100644 --- a/src/declarative/qml/v4/qv4instruction.cpp +++ b/src/declarative/qml/v4/qv4instruction.cpp @@ -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 << ")"; diff --git a/src/declarative/qml/v4/qv4instruction_p.h b/src/declarative/qml/v4/qv4instruction_p.h index 343df809b4..6f90117c7c 100644 --- a/src/declarative/qml/v4/qv4instruction_p.h +++ b/src/declarative/qml/v4/qv4instruction_p.h @@ -58,6 +58,8 @@ #include #include +#include + 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{ diff --git a/src/declarative/qml/v8/qv8bindings.cpp b/src/declarative/qml/v8/qv8bindings.cpp index 271267d851..3386c5ddc8 100644 --- a/src/declarative/qml/v8/qv8bindings.cpp +++ b/src/declarative/qml/v8/qv8bindings.cpp @@ -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); } } diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp index 6a9f583b0f..40ad93a544 100644 --- a/src/declarative/qml/v8/qv8qobjectwrapper.cpp +++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include @@ -131,9 +132,9 @@ class MaxSizeOf5 { static const size_t Size = SMax > > >::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 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 name ## ValueGetter(v8::Local, const v8::AccessorInfo &info) \ -{ \ - v8::Handle This = info.This(); \ - QV8QObjectResource *resource = v8_resource_check(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 name ## ValueGetterDirect(v8::Local, const v8::AccessorInfo &info) \ -{ \ - v8::Handle This = info.This(); \ - QV8QObjectResource *resource = v8_resource_check(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 valueToHandle(QV8Engine *, int v) +{ return v8::Integer::New(v); } +static inline v8::Handle valueToHandle(QV8Engine *, uint v) +{ return v8::Integer::NewFromUnsigned(v); } +static inline v8::Handle valueToHandle(QV8Engine *, bool v) +{ return v8::Boolean::New(v); } +static inline v8::Handle valueToHandle(QV8Engine *e, const QString &v) +{ return e->toString(v); } +static inline v8::Handle valueToHandle(QV8Engine *, float v) +{ return v8::Number::New(v); } +static inline v8::Handle valueToHandle(QV8Engine *, double v) +{ return v8::Number::New(v); } +static inline v8::Handle valueToHandle(QV8Engine *e, QObject *v) +{ return e->newQObject(v); } + +template +static v8::Handle GenericValueGetter(v8::Local, const v8::AccessorInfo &info) +{ + v8::Handle This = info.This(); + QV8QObjectResource *resource = v8_resource_check(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, ¬ifier); + 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):(property->isDirect()?((v8::AccessorGetter)GenericValueGetter):((v8::AccessorGetter)GenericValueGetter))) 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 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 script = v8::Script::New(v8::String::New(CREATE_FUNCTION_SOURCE), &origin, 0, v8::Handle(), v8::Script::NativeMode); +#undef CREATE_FUNCTION_SOURCE v8::Local fn = v8::Local::Cast(script->Run()); v8::Handle invokeFn = v8::FunctionTemplate::New(Invoke)->GetFunction(); v8::Handle args[] = { invokeFn }; @@ -344,107 +379,85 @@ QObject *QV8QObjectWrapper::toQObject(QV8ObjectResource *r) } // Load value properties -static v8::Handle LoadProperty(QV8Engine *engine, QObject *object, - const QDeclarativePropertyData &property) +template +static v8::Handle 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 retn = engine->newSequence(property.propType, object, property.coreIndex, &succeeded); + v8::Handle 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 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 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 QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object, @@ -520,21 +533,43 @@ v8::Handle 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 rv = LoadProperty(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(const_cast(object->metaObject()))->vmeProperty(result->coreIndex); - - if (result->isDirect()) { - return LoadPropertyDirect(engine, object, *result); + if (result->isVMEProperty()) { + typedef QDeclarativeVMEMetaObject VMEMO; + VMEMO *vmemo = const_cast(static_cast(object->metaObject())); + return vmemo->vmeProperty(result->coreIndex); + } else if (result->isDirect()) { + return LoadProperty(engine, object, *result, 0); } else { - return LoadProperty(engine, object, *result); + return LoadProperty(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 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::Local value, const v8::AccessorInfo& info) { @@ -809,8 +837,10 @@ static void FastValueSetter(v8::Local, v8::Local 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 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 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 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 CallMethod(QObject *object, int index, int returnTy { if (argCount > 0) { - QVarLengthArray args(argCount + 1); + QVarLengthArray args(argCount + 1); args[0].initAsType(returnType); for (int ii = 0; ii < argCount; ++ii) @@ -1438,7 +1467,7 @@ static v8::Handle 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 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 value) +void CallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle value) { if (type != 0) { cleanup(); type = 0; } @@ -2013,7 +2042,7 @@ void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle MetaCallArgument::toValue(QV8Engine *engine) +v8::Handle CallArgument::toValue(QV8Engine *engine) { if (type == qMetaTypeId()) { return QJSValuePrivate::get(*qjsValuePtr)->asV8Value(engine); diff --git a/src/declarative/qml/v8/qv8sequencewrapper_p_p.h b/src/declarative/qml/v8/qv8sequencewrapper_p_p.h index a947d52013..1861ea69e6 100644 --- a/src/declarative/qml/v8/qv8sequencewrapper_p_p.h +++ b/src/declarative/qml/v8/qv8sequencewrapper_p_p.h @@ -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(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 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(); \ - void *a[] = { &c, 0 }; \ - QMetaObject::metacall(object, QMetaObject::ReadProperty, propertyIndex, a); \ + loadReference(); \ } \ quint32 count = c.count(); \ v8::Local 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 object; \ int propertyIndex; \ diff --git a/src/declarative/qml/v8/qv8valuetypewrapper.cpp b/src/declarative/qml/v8/qv8valuetypewrapper.cpp index aca0c85ace..53d500c454 100644 --- a/src/declarative/qml/v8/qv8valuetypewrapper.cpp +++ b/src/declarative/qml/v8/qv8valuetypewrapper.cpp @@ -346,9 +346,9 @@ v8::Handle QV8ValueTypeWrapper::Setter(v8::Local 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 = diff --git a/src/qtquick1/graphicsitems/qdeclarativeitem.cpp b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp index bd795cb4b5..1f57d53b7e 100644 --- a/src/qtquick1/graphicsitems/qdeclarativeitem.cpp +++ b/src/qtquick1/graphicsitems/qdeclarativeitem.cpp @@ -1986,14 +1986,6 @@ void QDeclarativeItemPrivate::transform_clear(QDeclarativeListProperty(o); - if (e) - e->connect(&item->d_func()->parentNotifier); - *((QDeclarativeItem **)rv) = item->parentItem(); -} - /*! \qmlproperty list 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) { diff --git a/src/qtquick1/graphicsitems/qdeclarativeitem_p.h b/src/qtquick1/graphicsitems/qdeclarativeitem_p.h index 8dccd1ac37..1dcafe55f4 100644 --- a/src/qtquick1/graphicsitems/qdeclarativeitem_p.h +++ b/src/qtquick1/graphicsitems/qdeclarativeitem_p.h @@ -216,10 +216,6 @@ class Q_QTQUICK1_EXPORT QDeclarativeItemPrivate : public QGraphicsItemPrivate 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); diff --git a/src/qtquick1/qtquick1.cpp b/src/qtquick1/qtquick1.cpp index b8c0e109ba..bb6c536413 100644 --- a/src/qtquick1/qtquick1.cpp +++ b/src/qtquick1/qtquick1.cpp @@ -40,7 +40,6 @@ ****************************************************************************/ #include -#include #include #include #include @@ -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) diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index a9409ecdf4..5ec0787d9e 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -64,14 +64,45 @@ #include #include #include +#include #include -// 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(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); } diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 6e7a909696..ffc1017105 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -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 { diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index a522a19a70..79d98d7fe4 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -141,6 +141,8 @@ class Q_QUICK_EXPORT QQuickItemPrivate : public QObjectPrivate 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 @@ class Q_QUICK_EXPORT QQuickItemPrivate : public QObjectPrivate QSGContext *sceneGraphContext() const { Q_ASSERT(canvas); return static_cast(QObjectPrivate::get(canvas))->context; } QQuickItem *parentItem; + QDeclarativeNotifier parentNotifier; + QList childItems; mutable QList *sortedChildItems; QList paintOrderChildItems() const; diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index a9d8a193f0..69b9caf940 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -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"));