From 5322ad410a78e43a86bb00b9765698c59f9449cb Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Fri, 23 Sep 2016 23:10:02 +0200 Subject: Fix a crash in StackView::pop() If an item is still activating (from a previous pop) when it gets already popped out, we must not set the deactivating status before calling prepareTransition(). This method cancels and finishes the ongoing activation transition, and if the status says that the item was deactivating, the item gets destroyed in the middle of preparing for the deactivation transition. Let prepareTransition() cancel any ongoing transition first, and then set the status after the preparation. The cleanest way is to pass the target status to startTransition() and completeTransition(). Task-number: QTBUG-56158 Change-Id: Id52752200b650ea9f84659bbf43431f8a8b22f1e Reviewed-by: Mitch Curtis --- src/quicktemplates2/qquickstackview_p.cpp | 58 +++++++++++++------------------ 1 file changed, 24 insertions(+), 34 deletions(-) (limited to 'src/quicktemplates2/qquickstackview_p.cpp') diff --git a/src/quicktemplates2/qquickstackview_p.cpp b/src/quicktemplates2/qquickstackview_p.cpp index c1b68652..3709b988 100644 --- a/src/quicktemplates2/qquickstackview_p.cpp +++ b/src/quicktemplates2/qquickstackview_p.cpp @@ -251,8 +251,9 @@ bool QQuickStackElement::prepareTransition(QQuickItemViewTransitioner *transitio return false; } -void QQuickStackElement::startTransition(QQuickItemViewTransitioner *transitioner) +void QQuickStackElement::startTransition(QQuickItemViewTransitioner *transitioner, QQuickStackView::Status status) { + setStatus(status); if (transitioner) QQuickItemViewTransitionableItem::startTransition(transitioner, index); } @@ -415,27 +416,23 @@ void QQuickStackViewPrivate::popTransition(QQuickStackElement *enter, QQuickStac { ensureTransitioner(); - if (exit) { - exit->removal = true; - exit->setStatus(QQuickStackView::Deactivating); + if (exit) exit->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, true); - } - if (enter) { - enter->setStatus(QQuickStackView::Activating); + if (enter) enter->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, false); - } if (exit) { + exit->removal = true; if (immediate || !exit->item || !exit->prepareTransition(transitioner, viewBounds)) - completeTransition(exit, transitioner->removeTransition); + completeTransition(exit, transitioner->removeTransition, QQuickStackView::Deactivating); else - exit->startTransition(transitioner); + exit->startTransition(transitioner, QQuickStackView::Deactivating); } if (enter) { if (immediate || !enter->item || !enter->prepareTransition(transitioner, QRectF())) - completeTransition(enter, transitioner->removeDisplacedTransition); + completeTransition(enter, transitioner->removeDisplacedTransition, QQuickStackView::Activating); else - enter->startTransition(transitioner); + enter->startTransition(transitioner, QQuickStackView::Activating); } if (transitioner) { @@ -448,26 +445,22 @@ void QQuickStackViewPrivate::pushTransition(QQuickStackElement *enter, QQuickSta { ensureTransitioner(); - if (enter) { - enter->setStatus(QQuickStackView::Activating); + if (enter) enter->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true); - } - if (exit) { - exit->setStatus(QQuickStackView::Deactivating); + if (exit) exit->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, false); - } if (enter) { if (immediate || !enter->item || !enter->prepareTransition(transitioner, viewBounds)) - completeTransition(enter, transitioner->addTransition); + completeTransition(enter, transitioner->addTransition, QQuickStackView::Activating); else - enter->startTransition(transitioner); + enter->startTransition(transitioner, QQuickStackView::Activating); } if (exit) { if (immediate || !exit->item || !exit->prepareTransition(transitioner, QRectF())) - completeTransition(exit, transitioner->addDisplacedTransition); + completeTransition(exit, transitioner->addDisplacedTransition, QQuickStackView::Deactivating); else - exit->startTransition(transitioner); + exit->startTransition(transitioner, QQuickStackView::Deactivating); } if (transitioner) { @@ -480,27 +473,23 @@ void QQuickStackViewPrivate::replaceTransition(QQuickStackElement *enter, QQuick { ensureTransitioner(); - if (exit) { - exit->removal = true; - exit->setStatus(QQuickStackView::Deactivating); + if (exit) exit->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, false); - } - if (enter) { - enter->setStatus(QQuickStackView::Activating); + if (enter) enter->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, true); - } if (exit) { + exit->removal = true; if (immediate || !exit->item || !exit->prepareTransition(transitioner, QRectF())) - completeTransition(exit, transitioner->moveDisplacedTransition); + completeTransition(exit, transitioner->moveDisplacedTransition, QQuickStackView::Deactivating); else - exit->startTransition(transitioner); + exit->startTransition(transitioner, QQuickStackView::Deactivating); } if (enter) { if (immediate || !enter->item || !enter->prepareTransition(transitioner, viewBounds)) - completeTransition(enter, transitioner->moveTransition); + completeTransition(enter, transitioner->moveTransition, QQuickStackView::Activating); else - enter->startTransition(transitioner); + enter->startTransition(transitioner, QQuickStackView::Activating); } if (transitioner) { @@ -509,8 +498,9 @@ void QQuickStackViewPrivate::replaceTransition(QQuickStackElement *enter, QQuick } } -void QQuickStackViewPrivate::completeTransition(QQuickStackElement *element, QQuickTransition *transition) +void QQuickStackViewPrivate::completeTransition(QQuickStackElement *element, QQuickTransition *transition, QQuickStackView::Status status) { + element->setStatus(status); if (transition) { // TODO: add a proper way to complete a transition QQmlListProperty animations = transition->animations(); -- cgit v1.2.3