diff options
-rw-r--r-- | src/controls/qquickstackview.cpp | 1 | ||||
-rw-r--r-- | src/controls/qquickstackview_p.cpp | 8 | ||||
-rw-r--r-- | src/controls/qquickstackview_p_p.h | 1 | ||||
-rw-r--r-- | tests/auto/controls/data/TestItem.qml | 49 | ||||
-rw-r--r-- | tests/auto/controls/data/tst_stackview.qml | 48 |
5 files changed, 105 insertions, 2 deletions
diff --git a/src/controls/qquickstackview.cpp b/src/controls/qquickstackview.cpp index 39cca26c..1c09b6e8 100644 --- a/src/controls/qquickstackview.cpp +++ b/src/controls/qquickstackview.cpp @@ -269,6 +269,7 @@ QQuickStackView::~QQuickStackView() d->transitioner->setChangeListener(Q_NULLPTR); delete d->transitioner; } + qDeleteAll(d->removals); qDeleteAll(d->elements); } diff --git a/src/controls/qquickstackview_p.cpp b/src/controls/qquickstackview_p.cpp index 67cdde59..19ab6a39 100644 --- a/src/controls/qquickstackview_p.cpp +++ b/src/controls/qquickstackview_p.cpp @@ -389,6 +389,7 @@ void QQuickStackViewPrivate::ensureTransitioner() void QQuickStackViewPrivate::popTransition(QQuickStackElement *enter, QQuickStackElement *exit, const QRectF &viewBounds, bool immediate) { if (exit) { + exit->removal = true; exit->setStatus(QQuickStackView::Deactivating); exit->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, true); } @@ -504,11 +505,14 @@ void QQuickStackViewPrivate::viewItemTransitionFinished(QQuickItemViewTransition if (element->item) element->item->setVisible(false); if (element->removal || element->isPendingRemoval()) - delete element; + removals += element; } - if (transitioner->runningJobs.isEmpty()) + if (transitioner->runningJobs.isEmpty()) { + qDeleteAll(removals); + removals.clear(); setBusy(false); + } } void QQuickStackViewPrivate::setBusy(bool busy) diff --git a/src/controls/qquickstackview_p_p.h b/src/controls/qquickstackview_p_p.h index 84ed9f35..7a185b7c 100644 --- a/src/controls/qquickstackview_p_p.h +++ b/src/controls/qquickstackview_p_p.h @@ -135,6 +135,7 @@ public: QVariant initialItem; QQuickItem *currentItem; + QList<QQuickStackElement*> removals; QStack<QQuickStackElement *> elements; QQuickItemViewTransitioner *transitioner; }; diff --git a/tests/auto/controls/data/TestItem.qml b/tests/auto/controls/data/TestItem.qml new file mode 100644 index 00000000..e018670f --- /dev/null +++ b/tests/auto/controls/data/TestItem.qml @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.5 + +Item { + id: item + property var createdCallback + property var destroyedCallback + Component.onCompleted: if (createdCallback) createdCallback(item) + Component.onDestruction: if (destroyedCallback) destroyedCallback(item) +} diff --git a/tests/auto/controls/data/tst_stackview.qml b/tests/auto/controls/data/tst_stackview.qml index 3a26b423..c4690ccb 100644 --- a/tests/auto/controls/data/tst_stackview.qml +++ b/tests/auto/controls/data/tst_stackview.qml @@ -475,4 +475,52 @@ TestCase { control.destroy() } + + TestItem { + id: indestructibleItem + } + + Component { + id: destructibleComponent + TestItem { } + } + + function test_ownership_data() { + return [ + {tag:"item, transition", arg: indestructibleItem, operation: AbstractStackView.Transition, destroyed: false}, + {tag:"item, immediate", arg: indestructibleItem, operation: AbstractStackView.Immediate, destroyed: false}, + {tag:"component, transition", arg: destructibleComponent, operation: AbstractStackView.Transition, destroyed: true}, + {tag:"component, immediate", arg: destructibleComponent, operation: AbstractStackView.Immediate, destroyed: true}, + {tag:"url, transition", arg: Qt.resolvedUrl("TestItem.qml"), operation: AbstractStackView.Transition, destroyed: true}, + {tag:"url, immediate", arg: Qt.resolvedUrl("TestItem.qml"), operation: AbstractStackView.Immediate, destroyed: true} + ] + } + + function test_ownership(data) { + var control = transitionView.createObject(testCase, {initialItem: component}) + + // push-pop + control.push(data.arg, AbstractStackView.Immediate) + verify(control.currentItem) + verify(control.currentItem.hasOwnProperty("destroyedCallback")) + var destroyed = false + control.currentItem.destroyedCallback = function() { destroyed = true } + control.pop(data.operation) + tryCompare(control, "busy", false) + wait(0) // deferred delete + compare(destroyed, data.destroyed) + + // push-replace + control.push(data.arg, AbstractStackView.Immediate) + verify(control.currentItem) + verify(control.currentItem.hasOwnProperty("destroyedCallback")) + destroyed = false + control.currentItem.destroyedCallback = function() { destroyed = true } + control.replace(component, data.operation) + tryCompare(control, "busy", false) + wait(0) // deferred delete + compare(destroyed, data.destroyed) + + control.destroy() + } } |