From a19afebf6acee64aa4a5c804a87846c91650a474 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 6 Aug 2009 13:01:12 +1000 Subject: Fix expression linked list. --- src/declarative/qml/qmlexpression.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 3206734..a9175ea 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -66,6 +66,7 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, const QString &expr, if (ctxt) { QmlContextPrivate *cp = ctxt->d_func(); nextExpression = cp->expressions; + if (nextExpression) nextExpression->prevExpression = &nextExpression; prevExpression = &cp->expressions; cp->expressions = this; } @@ -91,6 +92,7 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, if (ctxt) { QmlContextPrivate *cp = ctxt->d_func(); nextExpression = cp->expressions; + if (nextExpression) nextExpression->prevExpression = &nextExpression; prevExpression = &cp->expressions; cp->expressions = this; } -- cgit v0.12 From d4ebb04b8f0db7821f5059fc31020362f85c7c30 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 6 Aug 2009 13:11:21 +1000 Subject: Don't leak bindings. Make sure we clean up bindings for a cancelled state change. --- src/declarative/util/qmlsetproperties.cpp | 1 + src/declarative/util/qmlstate.cpp | 11 ++++------- src/declarative/util/qmlstate.h | 1 + src/declarative/util/qmltransitionmanager.cpp | 16 ++++++++++++++-- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/declarative/util/qmlsetproperties.cpp b/src/declarative/util/qmlsetproperties.cpp index bbbc6a9..1cd4a79 100644 --- a/src/declarative/util/qmlsetproperties.cpp +++ b/src/declarative/util/qmlsetproperties.cpp @@ -335,6 +335,7 @@ QmlSetProperties::ActionList QmlSetProperties::actions() a.toValue = d->expressions.at(ii).second->value(); } else { a.toBinding = new QmlBinding(d->expressions.at(ii).second->expression(), object(), qmlContext(this)); + a.deletableToBinding = true; a.toBinding->setTarget(prop); } diff --git a/src/declarative/util/qmlstate.cpp b/src/declarative/util/qmlstate.cpp index b5ba909..9967486 100644 --- a/src/declarative/util/qmlstate.cpp +++ b/src/declarative/util/qmlstate.cpp @@ -54,14 +54,14 @@ QT_BEGIN_NAMESPACE DEFINE_BOOL_CONFIG_OPTION(stateChangeDebug, STATECHANGE_DEBUG); Action::Action() -: restore(true), actionDone(false), reverseEvent(false), fromBinding(0), toBinding(0), event(0), +: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), fromBinding(0), toBinding(0), event(0), specifiedObject(0) { } Action::Action(QObject *target, const QString &propertyName, const QVariant &value) -: restore(true), actionDone(false), reverseEvent(false), toValue(value), fromBinding(0), +: restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), toValue(value), fromBinding(0), toBinding(0), event(0), specifiedObject(target), specifiedProperty(propertyName) { @@ -413,11 +413,8 @@ void QmlState::apply(QmlStateGroup *group, QmlTransition *trans, QmlState *rever SimpleAction r(action); additionalReverts << r; } - } else { - - if (!found || d->revertList.at(jj).binding != action.fromBinding) { - action.deleteFromBinding(); - } + } else if (d->revertList.at(jj).binding != action.fromBinding) { + action.deleteFromBinding(); } } diff --git a/src/declarative/util/qmlstate.h b/src/declarative/util/qmlstate.h index 7c62768..9eb7aee 100644 --- a/src/declarative/util/qmlstate.h +++ b/src/declarative/util/qmlstate.h @@ -64,6 +64,7 @@ public: bool restore:1; bool actionDone:1; bool reverseEvent:1; + bool deletableToBinding:1; QmlMetaProperty property; QVariant fromValue; diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp index b2d9414..be082f8 100644 --- a/src/declarative/util/qmltransitionmanager.cpp +++ b/src/declarative/util/qmltransitionmanager.cpp @@ -239,10 +239,10 @@ void QmlTransitionManager::transition(const QList &list, } } if (!transition) - d->applyBindings(); //### merge into above foreach? + d->applyBindings(); } - +#include void QmlTransitionManager::cancel() { if (d->transition) { @@ -251,6 +251,18 @@ void QmlTransitionManager::cancel() d->transition = 0; } + for(int i = 0; i < d->bindingsList.count(); ++i) { + Action action = d->bindingsList[i]; + if (action.toBinding && action.deletableToBinding) { + action.property.setBinding(0); + delete action.toBinding; + action.toBinding = 0; + action.deletableToBinding = false; + } else if (action.event) { + //### what do we do here? + } + + } d->bindingsList.clear(); d->completeList.clear(); -- cgit v0.12 From f132fde07d0d852f2aa61dbc80d5d5f89ae5dcfa Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 6 Aug 2009 13:26:13 +1000 Subject: Don't init Number/Color animations twice. --- src/declarative/util/qmlanimation.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index 27caf20..3240360 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -723,7 +723,6 @@ QmlColorAnimation::QmlColorAnimation(QObject *parent) : QmlPropertyAnimation(parent) { Q_D(QmlPropertyAnimation); - d->init(); d->interpolatorType = QMetaType::QColor; d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); d->defaultToInterpolatorType = true; @@ -1199,7 +1198,6 @@ QmlNumberAnimation::QmlNumberAnimation(QObject *parent) : QmlPropertyAnimation(parent) { Q_D(QmlPropertyAnimation); - d->init(); d->interpolatorType = QMetaType::QReal; d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType); } -- cgit v0.12 From 28a8c6b02e52bce8b2ac14961997b9c2cc0e01fd Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 6 Aug 2009 14:10:50 +1000 Subject: Use meta property cache for property restores --- src/declarative/qml/qmlengine_p.h | 4 ++ src/declarative/qml/qmlmetaproperty.cpp | 103 +++++++++++++++++++++----------- src/declarative/qml/qmlmetaproperty_p.h | 13 +++- 3 files changed, 84 insertions(+), 36 deletions(-) diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h index dffae6c..602321d 100644 --- a/src/declarative/qml/qmlengine_p.h +++ b/src/declarative/qml/qmlengine_p.h @@ -179,6 +179,10 @@ public: QmlValueTypeFactory valueTypes; QHash propertyCache; + static QmlMetaObjectCache *cache(QmlEnginePrivate *priv, QObject *obj) { + if (!priv || !obj || QObjectPrivate::get(obj)->metaObject) return 0; + return &priv->propertyCache[obj->metaObject()]; + } struct Imports { Imports(); diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index 350d84b..c445599 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -56,25 +56,53 @@ Q_DECLARE_METATYPE(QList); QT_BEGIN_NAMESPACE -QmlMetaObjectCache::Data -QmlMetaObjectCache::property(const QString &name, const QMetaObject *metaObject) +QmlMetaObjectCache::QmlMetaObjectCache() +: propertyCache(0) { - QHash::ConstIterator iter = properties.find(name); - if (iter != properties.end()) { - return *iter; - } else { - Data cacheData = { -1, -1 }; +} + +void QmlMetaObjectCache::init(const QMetaObject *metaObject) +{ + if (propertyCache || !metaObject) + return; + + int propCount = metaObject->propertyCount(); + + propertyCache = new Data[propCount]; + for (int ii = 0; ii < propCount; ++ii) { + QMetaProperty p = metaObject->property(ii); + propertyCache[ii].propType = p.userType(); + propertyCache[ii].coreIndex = ii; + propertyCache[ii].name = QLatin1String(p.name()); + + propertyNameCache.insert(propertyCache[ii].name, ii); + } +} + +QmlMetaObjectCache::~QmlMetaObjectCache() +{ + delete [] propertyCache; +} + +QmlMetaObjectCache::Data * +QmlMetaObjectCache::property(int index, const QMetaObject *metaObject) +{ + init(metaObject); - int idx = metaObject->indexOfProperty(name.toUtf8().constData()); - if (idx == -1) - return cacheData; + return propertyCache + index; +} + +QmlMetaObjectCache::Data * +QmlMetaObjectCache::property(const QString &name, const QMetaObject *metaObject) +{ + init(metaObject); - QMetaProperty property = metaObject->property(idx); - cacheData.propType = property.userType(); - cacheData.coreIndex = idx; - properties.insert(name, cacheData); + QHash::ConstIterator iter = propertyNameCache.find(name); - return cacheData; + if (iter != propertyNameCache.end()) { + return propertyCache + *iter; + } else { + return 0; } } @@ -99,14 +127,6 @@ QmlMetaProperty::~QmlMetaProperty() delete d; d = 0; } -struct CachedPropertyData { - CachedPropertyData(const QString &n, int pt, int ci) - : name(n), propType(pt), coreIdx(ci) {} - QString name; - int propType; - int coreIdx; -}; - /*! Creates a QmlMetaProperty for the default property of \a obj. If there is no default property, an invalid QmlMetaProperty will be created. @@ -218,15 +238,14 @@ void QmlMetaPropertyPrivate::initProperty(QObject *obj, const QString &name) } // Property - if (!QObjectPrivate::get(obj)->metaObject && enginePrivate) { - // Can cache - QmlMetaObjectCache &cache = - enginePrivate->propertyCache[obj->metaObject()]; - QmlMetaObjectCache::Data data = cache.property(name, obj->metaObject()); - if (data.coreIndex != -1) { + QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj); + if (cache) { + QmlMetaObjectCache::Data *data = + cache->property(name, obj->metaObject()); + if (data) { type = QmlMetaProperty::Property; - propType = data.propType; - coreIdx = data.coreIndex; + propType = data->propType; + coreIdx = data->coreIndex; } } else { // Can't cache @@ -1015,6 +1034,10 @@ quint32 QmlMetaPropertyPrivate::saveProperty(int core) */ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) { + QmlEnginePrivate *enginePrivate = 0; + if (ctxt && ctxt->engine()) + enginePrivate = QmlEnginePrivate::get(ctxt->engine()); + d->object = obj; d->context = ctxt; @@ -1042,10 +1065,22 @@ void QmlMetaProperty::restore(quint32 id, QObject *obj, QmlContext *ctxt) d->valueTypeId = p.type(); } else if (d->type & Property) { - QMetaProperty p(obj->metaObject()->property(id)); - d->name = QLatin1String(p.name()); - d->propType = p.userType(); + + QmlMetaObjectCache *cache = QmlEnginePrivate::cache(enginePrivate, obj); + d->coreIdx = id; + + if (cache) { + QmlMetaObjectCache::Data *data = + cache->property(id, obj->metaObject()); + d->propType = data->propType; + d->name = data->name; + } else { + QMetaProperty p(obj->metaObject()->property(id)); + d->name = QLatin1String(p.name()); + d->propType = p.userType(); + } + } else if (d->type & SignalProperty) { d->signal = obj->metaObject()->method(id); d->coreIdx = id; diff --git a/src/declarative/qml/qmlmetaproperty_p.h b/src/declarative/qml/qmlmetaproperty_p.h index 0410dd6..8e8966e 100644 --- a/src/declarative/qml/qmlmetaproperty_p.h +++ b/src/declarative/qml/qmlmetaproperty_p.h @@ -61,14 +61,23 @@ QT_BEGIN_NAMESPACE class QmlMetaObjectCache { public: + QmlMetaObjectCache(); + ~QmlMetaObjectCache(); + struct Data { int propType; int coreIndex; + QString name; }; - QHash properties; + Data *property(const QString &, const QMetaObject *); + Data *property(int, const QMetaObject *); + +private: + void init(const QMetaObject *); - Data property(const QString &, const QMetaObject *); + Data *propertyCache; + QHash propertyNameCache; }; class QmlContext; -- cgit v0.12 From 9fcf4d49ca04b6dab94b19530899a452521e91de Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 6 Aug 2009 14:56:08 +1000 Subject: Remove debug. --- src/declarative/util/qmltransitionmanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/declarative/util/qmltransitionmanager.cpp b/src/declarative/util/qmltransitionmanager.cpp index be082f8..f04a821 100644 --- a/src/declarative/util/qmltransitionmanager.cpp +++ b/src/declarative/util/qmltransitionmanager.cpp @@ -242,7 +242,7 @@ void QmlTransitionManager::transition(const QList &list, d->applyBindings(); } -#include + void QmlTransitionManager::cancel() { if (d->transition) { -- cgit v0.12 From 3270c41c1e1f78b403a4d587d726203520eb707b Mon Sep 17 00:00:00 2001 From: Aaron Kennedy Date: Thu, 6 Aug 2009 15:50:49 +1000 Subject: Add a QmlMetaType::typeCategory() method QmlMetaProperty was calling isObject(), isList() and isQmlList() to determine its property category, resulting in acquiring and releasing three locks (one for each call). This call allows QmlMetaProperty to do the same with only one lock. --- src/declarative/qml/qmlmetaproperty.cpp | 25 +++++++++++++++++-------- src/declarative/qml/qmlmetatype.cpp | 16 ++++++++++++++++ src/declarative/qml/qmlmetatype.h | 3 +++ 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/src/declarative/qml/qmlmetaproperty.cpp b/src/declarative/qml/qmlmetaproperty.cpp index c445599..09ca872 100644 --- a/src/declarative/qml/qmlmetaproperty.cpp +++ b/src/declarative/qml/qmlmetaproperty.cpp @@ -310,14 +310,23 @@ QmlMetaPropertyPrivate::propertyCategory() const category = QmlMetaProperty::Normal; else if (type == qMetaTypeId()) category = QmlMetaProperty::Bindable; - else if (QmlMetaType::isList(type)) - category = QmlMetaProperty::List; - else if (QmlMetaType::isQmlList(type)) - category = QmlMetaProperty::QmlList; - else if (QmlMetaType::isObject(type)) - category = QmlMetaProperty::Object; - else - category = QmlMetaProperty::Normal; + else { + QmlMetaType::TypeCategory tc = QmlMetaType::typeCategory(type); + switch(tc) { + case QmlMetaType::Object: + category = QmlMetaProperty::Object; + break; + case QmlMetaType::QmlList: + category = QmlMetaProperty::QmlList; + break; + case QmlMetaType::List: + category = QmlMetaProperty::List; + break; + case QmlMetaType::Unknown: + category = QmlMetaProperty::Normal; + break; + } + } } return category; } diff --git a/src/declarative/qml/qmlmetatype.cpp b/src/declarative/qml/qmlmetatype.cpp index 29fe026..50bc676 100644 --- a/src/declarative/qml/qmlmetatype.cpp +++ b/src/declarative/qml/qmlmetatype.cpp @@ -794,6 +794,22 @@ QMetaProperty QmlMetaType::property(QObject *obj, const char *name) return metaObject->property(idx); } +QmlMetaType::TypeCategory QmlMetaType::typeCategory(int userType) +{ + if (userType < 0) + return Unknown; + QReadLocker lock(metaTypeDataLock()); + QmlMetaTypeData *data = metaTypeData(); + if (userType < data->objects.size() && data->objects.testBit(userType)) + return Object; + else if (userType < data->qmllists.size() && data->qmllists.testBit(userType)) + return QmlList; + else if (userType < data->lists.size() && data->lists.testBit(userType)) + return List; + else + return Unknown; +} + bool QmlMetaType::isObject(int userType) { QReadLocker lock(metaTypeDataLock()); diff --git a/src/declarative/qml/qmlmetatype.h b/src/declarative/qml/qmlmetatype.h index e023e83..9cbf7f3 100644 --- a/src/declarative/qml/qmlmetatype.h +++ b/src/declarative/qml/qmlmetatype.h @@ -94,6 +94,9 @@ public: static QmlAttachedPropertiesFunc attachedPropertiesFuncById(int); static QmlAttachedPropertiesFunc attachedPropertiesFunc(const QByteArray &); + enum TypeCategory { Unknown, Object, List, QmlList }; + static TypeCategory typeCategory(int); + static bool isInterface(int); static const char *interfaceIId(int); static bool isObject(int); -- cgit v0.12 From 5eec63013bafc3b737c1375158128b3288ce7d70 Mon Sep 17 00:00:00 2001 From: Michael Brasser Date: Thu, 6 Aug 2009 16:44:58 +1000 Subject: Mico-optimization for animations. --- src/declarative/util/qmlanimation.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/declarative/util/qmlanimation.cpp b/src/declarative/util/qmlanimation.cpp index 3240360..f3691ea 100644 --- a/src/declarative/util/qmlanimation.cpp +++ b/src/declarative/util/qmlanimation.cpp @@ -1494,7 +1494,9 @@ QmlPropertyAnimation::~QmlPropertyAnimation() void QmlPropertyAnimationPrivate::init() { Q_Q(QmlPropertyAnimation); - va = new QmlTimeLineValueAnimator(q); + va = new QmlTimeLineValueAnimator; + QFx_setParent_noEvent(va, q); + va->setStartValue(QVariant(0.0f)); va->setEndValue(QVariant(1.0f)); } -- cgit v0.12