aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/controls/qquickstackview.cpp1
-rw-r--r--src/controls/qquickstackview_p.cpp8
-rw-r--r--src/controls/qquickstackview_p_p.h1
-rw-r--r--tests/auto/controls/data/TestItem.qml49
-rw-r--r--tests/auto/controls/data/tst_stackview.qml48
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()
+ }
}