From 53d3a0779663285baaaf13a05afc4a7d11f6ed29 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Thu, 2 Nov 2017 09:48:57 +0100 Subject: Make deletion of transitions safe Task-number: QTBUG-63844 Change-Id: I65029e9039ea3db85152fc3cdefaac3deee0db6c Reviewed-by: Simon Hausmann --- src/quick/util/qquicktransition.cpp | 29 +++++++++++++++++------------ src/quick/util/qquicktransition_p.h | 15 ++++++++++++--- 2 files changed, 29 insertions(+), 15 deletions(-) (limited to 'src/quick/util') diff --git a/src/quick/util/qquicktransition.cpp b/src/quick/util/qquicktransition.cpp index 29690a4857..6ae89c4ed4 100644 --- a/src/quick/util/qquicktransition.cpp +++ b/src/quick/util/qquicktransition.cpp @@ -109,7 +109,7 @@ protected: void updateState(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) override; }; -class QQuickTransitionPrivate : public QObjectPrivate, QAnimationJobChangeListener +class QQuickTransitionPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QQuickTransition) public: @@ -120,11 +120,8 @@ public: { } - void removeStateChangeListener(QAbstractAnimationJob *anim) - { - if (anim) - anim->removeAnimationChangeListener(this, QAbstractAnimationJob::StateChange); - } + static QQuickTransitionPrivate *get(QQuickTransition *q) { return q->d_func(); } + void animationStateChanged(QAbstractAnimationJob::State newState); QString fromState; QString toState; @@ -134,7 +131,6 @@ public: bool reversible; bool enabled; protected: - void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State) override; static void append_animation(QQmlListProperty *list, QQuickAbstractAnimation *a); static int animation_count(QQmlListProperty *list); @@ -171,7 +167,16 @@ void QQuickTransitionPrivate::clear_animations(QQmlListPropertyanimationStateChanged(newState); +} + +void QQuickTransitionPrivate::animationStateChanged(QAbstractAnimationJob::State newState) { Q_Q(QQuickTransition); @@ -197,15 +202,16 @@ void ParallelAnimationWrapper::updateState(QAbstractAnimationJob::State newState } } -QQuickTransitionInstance::QQuickTransitionInstance(QQuickTransitionPrivate *transition, QAbstractAnimationJob *anim) +QQuickTransitionInstance::QQuickTransitionInstance(QQuickTransition *transition, QAbstractAnimationJob *anim) : m_transition(transition) , m_anim(anim) { + anim->addAnimationChangeListener(this, QAbstractAnimationJob::StateChange); } QQuickTransitionInstance::~QQuickTransitionInstance() { - m_transition->removeStateChangeListener(m_anim); + removeStateChangeListener(); delete m_anim; } @@ -270,8 +276,7 @@ QQuickTransitionInstance *QQuickTransition::prepare(QQuickStateOperation::Action group->setDirection(d->reversed ? QAbstractAnimationJob::Backward : QAbstractAnimationJob::Forward); - group->addAnimationChangeListener(d, QAbstractAnimationJob::StateChange); - QQuickTransitionInstance *wrapper = new QQuickTransitionInstance(d, group); + QQuickTransitionInstance *wrapper = new QQuickTransitionInstance(this, group); return wrapper; } diff --git a/src/quick/util/qquicktransition_p.h b/src/quick/util/qquicktransition_p.h index d6f365f99e..6d2e41fc9d 100644 --- a/src/quick/util/qquicktransition_p.h +++ b/src/quick/util/qquicktransition_p.h @@ -53,6 +53,7 @@ #include "qquickstate_p.h" #include +#include #include #include @@ -64,10 +65,10 @@ class QQuickTransitionPrivate; class QQuickTransitionManager; class QQuickTransition; -class QQuickTransitionInstance +class QQuickTransitionInstance : QAnimationJobChangeListener { public: - QQuickTransitionInstance(QQuickTransitionPrivate *transition, QAbstractAnimationJob *anim); + QQuickTransitionInstance(QQuickTransition *transition, QAbstractAnimationJob *anim); ~QQuickTransitionInstance(); void start(); @@ -75,8 +76,16 @@ public: bool isRunning() const; +protected: + void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State, QAbstractAnimationJob::State) override; + + void removeStateChangeListener() + { + m_anim->removeAnimationChangeListener(this, QAbstractAnimationJob::StateChange); + } + private: - QQuickTransitionPrivate *m_transition; + QQmlGuard m_transition; QAbstractAnimationJob *m_anim; friend class QQuickTransition; }; -- cgit v1.2.3 From 3bbf303403550e4e6f48b8778982d248651449ee Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 11 Dec 2017 15:47:49 +0100 Subject: Check the context matcher for isDestroyed() before assigning it Some code "resets" a custom context matcher on destruction. As destruction order of global objects is not defined, that may be after the context matcher has already been destroyed. Change-Id: I1d3869cb393c490ddb70b71a2d93578a03e2af79 Reviewed-by: Simon Hausmann Reviewed-by: J-P Nurmi --- src/quick/util/qquickshortcut.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/quick/util') diff --git a/src/quick/util/qquickshortcut.cpp b/src/quick/util/qquickshortcut.cpp index 58f7fc8439..78dc855326 100644 --- a/src/quick/util/qquickshortcut.cpp +++ b/src/quick/util/qquickshortcut.cpp @@ -122,7 +122,8 @@ Q_QUICK_PRIVATE_EXPORT ContextMatcher qt_quick_shortcut_context_matcher() Q_QUICK_PRIVATE_EXPORT void qt_quick_set_shortcut_context_matcher(ContextMatcher matcher) { - *ctxMatcher() = matcher; + if (!ctxMatcher.isDestroyed()) + *ctxMatcher() = matcher; } QT_BEGIN_NAMESPACE -- cgit v1.2.3 From e4ffad84fecebb3c1fc554b3252fd5d059c0ff38 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 16 Jan 2018 09:29:59 +0100 Subject: Speed up PropertyChange state application Every time we decode a potential binding of a PropertyChanges{} object, we call qmlContext(this) and we go through a full QQmlProperty construction (which involves property name decoding by dots and property lookups), just to determine if we're doing a binding on a property or a signal. QQmlProperty::isSignalProperty() will only return true if the property is valid and if it's a "function" type. The QQmlProperty constructor on the other hand only constructs a valid regular property if it's _not_ a function type and a signal property _has_ to start with "on" followed by an upper case character. We can copy this shortcut out into decodeBinding() to avoid the QQmlProperty construction in the common case of plain property bindings. This is also legit in the scope of group properties, as signal bindings on group properties are not supported (we always use the state's target object for signal lookup, never the group object). In addition, avoid creating a public QQmlContext for the PropertyChange object by allowing for the construction of the QQmlProperty object via the QQmlContextData, as that's the only data structure we really need. These two changes used to be separate, but they need to go together to keep the tests passing, as the property validation and warning issuing is now moved from decodeBinding() into ::actions() itself. Shaves off 1.5% off delegates_item_states.qml Task-number: QTBUG-65708 Change-Id: I32a17d815bd3495a907a51068a971eb7cb69c6ef Reviewed-by: Lars Knoll --- src/quick/util/qquickpropertychanges.cpp | 33 +++++++++++++++++++------------- src/quick/util/qquickstate.cpp | 5 ++--- src/quick/util/qquickstate_p.h | 4 ++-- 3 files changed, 24 insertions(+), 18 deletions(-) (limited to 'src/quick/util') diff --git a/src/quick/util/qquickpropertychanges.cpp b/src/quick/util/qquickpropertychanges.cpp index 61380b3ea0..aecb7115ea 100644 --- a/src/quick/util/qquickpropertychanges.cpp +++ b/src/quick/util/qquickpropertychanges.cpp @@ -281,15 +281,19 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix, return; } - QQmlProperty prop = property(propertyName); //### better way to check for signal property? - - if (prop.type() & QQmlProperty::SignalProperty) { - QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler; - handler->property = prop; - handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(), - QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex))); - signalReplacements << handler; - return; + if (propertyName.count() >= 3 && + propertyName.at(0) == QLatin1Char('o') && + propertyName.at(1) == QLatin1Char('n') && + propertyName.at(2).isUpper()) { + QQmlProperty prop = property(propertyName); + if (prop.isSignalProperty()) { + QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler; + handler->property = prop; + handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(), + QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions.at(binding->value.compiledScriptIndex))); + signalReplacements << handler; + return; + } } if (binding->type == QV4::CompiledData::Binding::Type_Script) { @@ -395,7 +399,10 @@ QQmlProperty QQuickPropertyChangesPrivate::property(const QString &property) { Q_Q(QQuickPropertyChanges); - QQmlProperty prop(object, property, qmlContext(q)); + QQmlContextData *context = nullptr; + if (QQmlData *ddata = QQmlData::get(q)) + context = ddata->outerContext; + QQmlProperty prop = QQmlPropertyPrivate::create(object, property, context); if (!prop.isValid()) { qmlWarning(q) << QQuickPropertyChanges::tr("Cannot assign to non-existent property \"%1\"").arg(property); return QQmlProperty(); @@ -415,9 +422,10 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions() ActionList list; for (int ii = 0; ii < d->properties.count(); ++ii) { + QQmlProperty prop = d->property(d->properties.at(ii).first); - QQuickStateAction a(d->object, d->properties.at(ii).first, - qmlContext(this), d->properties.at(ii).second); + QQuickStateAction a(d->object, prop, d->properties.at(ii).first, + d->properties.at(ii).second); if (a.property.isValid()) { a.restore = restoreEntryValues(); @@ -426,7 +434,6 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions() } for (int ii = 0; ii < d->signalReplacements.count(); ++ii) { - QQuickReplaceSignalHandler *handler = d->signalReplacements.at(ii); if (handler->property.isValid()) { diff --git a/src/quick/util/qquickstate.cpp b/src/quick/util/qquickstate.cpp index 0a49d41491..ca8b7bbc2b 100644 --- a/src/quick/util/qquickstate.cpp +++ b/src/quick/util/qquickstate.cpp @@ -68,10 +68,9 @@ QQuickStateAction::QQuickStateAction(QObject *target, const QString &propertyNam fromValue = property.read(); } -QQuickStateAction::QQuickStateAction(QObject *target, const QString &propertyName, - QQmlContext *context, const QVariant &value) +QQuickStateAction::QQuickStateAction(QObject *target, const QQmlProperty &property, const QString &propertyName, const QVariant &value) : restore(true), actionDone(false), reverseEvent(false), deletableToBinding(false), - property(target, propertyName, context), toValue(value), + property(property), toValue(value), fromBinding(0), event(0), specifiedObject(target), specifiedProperty(propertyName) { diff --git a/src/quick/util/qquickstate_p.h b/src/quick/util/qquickstate_p.h index 7d22ca9f8c..3826daf283 100644 --- a/src/quick/util/qquickstate_p.h +++ b/src/quick/util/qquickstate_p.h @@ -69,8 +69,8 @@ class Q_QUICK_PRIVATE_EXPORT QQuickStateAction public: QQuickStateAction(); QQuickStateAction(QObject *, const QString &, const QVariant &); - QQuickStateAction(QObject *, const QString &, - QQmlContext *, const QVariant &); + QQuickStateAction(QObject *, const QQmlProperty &property, const QString &, + const QVariant &); bool restore:1; bool actionDone:1; -- cgit v1.2.3 From efeccb3f008c3463d333623cbefc8b77dd9db389 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Wed, 17 Jan 2018 13:42:21 +0100 Subject: Avoid repeated calls into thread local storage to get the animation timer Instead hold a direct pointer to the animation timer and make it's methods non static. Change-Id: I6382fd2a1c02464ddb573f0210a14c603fd932db Reviewed-by: Simon Hausmann Reviewed-by: J-P Nurmi Reviewed-by: Robin Burchell --- src/quick/util/qquickanimationcontroller.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/quick/util') diff --git a/src/quick/util/qquickanimationcontroller.cpp b/src/quick/util/qquickanimationcontroller.cpp index cebb0391ae..5e56460098 100644 --- a/src/quick/util/qquickanimationcontroller.cpp +++ b/src/quick/util/qquickanimationcontroller.cpp @@ -223,7 +223,7 @@ void QQuickAnimationController::updateProgress() d->animationInstance->setDisableUserControl(); d->animationInstance->start(); - QQmlAnimationTimer::unregisterAnimation(d->animationInstance); + QQmlAnimationTimer::instance()->unregisterAnimation(d->animationInstance); d->animationInstance->setCurrentTime(d->progress * d->animationInstance->duration()); } -- cgit v1.2.3