diff options
-rw-r--r-- | src/quick/util/qquickanimatorcontroller.cpp | 8 | ||||
-rw-r--r-- | src/quick/util/qquickanimatorjob.cpp | 14 | ||||
-rw-r--r-- | src/quick/util/qquickanimatorjob_p.h | 3 | ||||
-rw-r--r-- | tests/auto/qmltest/animators/tst_targetdestroyed.qml | 77 |
4 files changed, 95 insertions, 7 deletions
diff --git a/src/quick/util/qquickanimatorcontroller.cpp b/src/quick/util/qquickanimatorcontroller.cpp index 42b8840bf4..e009de205c 100644 --- a/src/quick/util/qquickanimatorcontroller.cpp +++ b/src/quick/util/qquickanimatorcontroller.cpp @@ -184,8 +184,6 @@ void QQuickAnimatorController::beforeNodeSync() m_nodesAreInvalid = false; } - - foreach (QQuickAnimatorJob *job, m_activeLeafAnimations) { if (!job->target()) continue; @@ -197,9 +195,9 @@ void QQuickAnimatorController::beforeNodeSync() } } foreach (QQuickItem *wiped, m_deletedSinceLastFrame) { - QQuickTransformAnimatorJob::Helper *helper = m_transforms.value(wiped); - if (helper) - helper->item = 0; + QQuickTransformAnimatorJob::Helper *helper = m_transforms.take(wiped); + // Helper will now already have been reset in all animators referencing it. + delete helper; } m_deletedSinceLastFrame.clear(); diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp index 3725e22397..fdbffd4709 100644 --- a/src/quick/util/qquickanimatorjob.cpp +++ b/src/quick/util/qquickanimatorjob.cpp @@ -256,6 +256,10 @@ QQuickTransformAnimatorJob::QQuickTransformAnimatorJob() QQuickTransformAnimatorJob::~QQuickTransformAnimatorJob() { if (m_helper && --m_helper->ref == 0) { + // The only condition for not having a controller is when target was + // destroyed, in which case we have neither m_helper nor m_contorller. + Q_ASSERT(m_controller); + Q_ASSERT(m_helper->item); m_controller->m_transforms.remove(m_helper->item); delete m_helper; } @@ -266,6 +270,7 @@ void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller QQuickAnimatorJob::initialize(controller); if (m_controller) { + bool newHelper = m_helper == 0; m_helper = m_controller->m_transforms.value(m_target); if (!m_helper) { m_helper = new Helper(); @@ -273,7 +278,8 @@ void QQuickTransformAnimatorJob::initialize(QQuickAnimatorController *controller m_controller->m_transforms.insert(m_target, m_helper); QObject::connect(m_target, SIGNAL(destroyed(QObject*)), m_controller, SLOT(itemDestroyed(QObject*)), Qt::DirectConnection); } else { - ++m_helper->ref; + if (newHelper) // only add reference the first time around.. + ++m_helper->ref; // Make sure leftovers from previous runs are being used... m_helper->wasSynced = false; } @@ -287,6 +293,12 @@ void QQuickTransformAnimatorJob::nodeWasDestroyed() m_helper->node = 0; } +void QQuickTransformAnimatorJob::targetWasDeleted() +{ + m_helper = 0; + QQuickAnimatorJob::targetWasDeleted(); +} + void QQuickTransformAnimatorJob::Helper::sync() { const quint32 mask = QQuickItemPrivate::Position diff --git a/src/quick/util/qquickanimatorjob_p.h b/src/quick/util/qquickanimatorjob_p.h index f91410950c..4bdcd6917d 100644 --- a/src/quick/util/qquickanimatorjob_p.h +++ b/src/quick/util/qquickanimatorjob_p.h @@ -122,7 +122,7 @@ public: QEasingCurve easingCurve() const { return m_easing; } void setEasingCurve(const QEasingCurve &curve) { m_easing = curve; } - void targetWasDeleted(); + virtual void targetWasDeleted(); virtual void initialize(QQuickAnimatorController *controller); virtual void writeBack() = 0; virtual void nodeWasDestroyed() = 0; @@ -204,6 +204,7 @@ protected: QQuickTransformAnimatorJob(); void initialize(QQuickAnimatorController *controller); void nodeWasDestroyed(); + void targetWasDeleted() Q_DECL_OVERRIDE; Helper *m_helper; }; diff --git a/tests/auto/qmltest/animators/tst_targetdestroyed.qml b/tests/auto/qmltest/animators/tst_targetdestroyed.qml new file mode 100644 index 0000000000..92b14d0594 --- /dev/null +++ b/tests/auto/qmltest/animators/tst_targetdestroyed.qml @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Gunnar Sletta <gunnar@sletta.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtTest 1.0 + +Item { + id: root; + width: 200 + height: 200 + + TestCase { + id: testcase + name: "animators-targetdestroyed" + when: false + function test_endresult() { + verify(true, "Got here :)"); + } + } + + Rectangle { + id: box + width: 10 + height: 10 + color: "steelblue" + } + + YAnimator { + id: anim + target: box + from: 0; + to: 100 + duration: 100 + loops: Animation.Infinite + running: true + } + + SequentialAnimation { + running: true + PauseAnimation { duration: 150 } + ScriptAction { script: box.destroy(); } + PauseAnimation { duration: 50 } + ScriptAction { script: anim.destroy(); } + PauseAnimation { duration: 50 } + ScriptAction { script: testcase.when = true } + } +} |