if (nextTransitionType != QQuickItemViewTransitioner::NoTransition && !nextTransitionToSet)
moveTo(item->pos());
+ // For move transitions (both target and displaced) and displaced transitions of other
+ // types, only run the transition if the item is actually moving to another position.
+
switch (nextTransitionType) {
case QQuickItemViewTransitioner::NoTransition:
{
}
case QQuickItemViewTransitioner::AddTransition:
case QQuickItemViewTransitioner::RemoveTransition:
- // For Add targets, do transition if item is moving into visible area
- // For Remove targets, do transition if item is currently in visible area
if (viewBounds.isNull()) {
if (isTransitionTarget)
doTransition = true;
else
- doTransition = (nextTransitionTo != item->pos());
+ doTransition = transitionWillChangePosition();
} else if (isTransitionTarget) {
+ // For Add targets, do transition if item is moving into visible area
+ // For Remove targets, do transition if item is currently in visible area
doTransition = (nextTransitionType == QQuickItemViewTransitioner::AddTransition)
? viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))
: viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()));
} else {
if (viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()))
|| viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()))) {
- doTransition = (nextTransitionTo != item->pos());
+ doTransition = transitionWillChangePosition();
} else {
item->setPos(nextTransitionTo);
}
break;
case QQuickItemViewTransitioner::MoveTransition:
// do transition if moving from or into visible area
- if (nextTransitionTo != item->pos()) {
+ if (transitionWillChangePosition()) {
doTransition = viewBounds.isNull()
|| viewBounds.intersects(QRectF(item->x(), item->y(), item->width(), item->height()))
|| viewBounds.intersects(QRectF(nextTransitionTo.x(), nextTransitionTo.y(), item->width(), item->height()));
isTransitionTarget = isTargetItem;
}
+bool QQuickViewItem::transitionWillChangePosition() const
+{
+ if (transitionRunning() && transition->m_toPos != nextTransitionTo)
+ return true;
+ return nextTransitionTo != item->pos();
+}
+
void QQuickViewItem::finishedTransition()
{
nextTransitionToSet = false;
friend class QQuickItemViewTransitioner;
friend class QQuickItemViewTransitionJob;
void setNextTransition(QQuickItemViewTransitioner::TransitionType, bool isTargetItem);
+ bool transitionWillChangePosition() const;
void finishedTransition();
void resetTransitionData();
};
// interrupting transitions will still produce the correct result)
property int timeBetweenActions: duration / 2
- property int duration: 100
+ property int duration: 300
property int count: grid.count
property bool runningAddDisplaced: false
property bool runningMoveTargets: false
property bool runningMoveDisplaced: false
+ property bool runningRemoveTargets: false
+ property bool runningRemoveDisplaced: false
objectName: "grid"
width: 240
ScriptAction { script: grid.runningMoveDisplaced = false }
}
}
+
+ remove: Transition {
+ id: removeTargets
+ SequentialAnimation {
+ ScriptAction { script: grid.runningRemoveTargets = true }
+ ParallelAnimation {
+ NumberAnimation { properties: "x"; to: removeTargets_transitionTo.x; duration: root.duration }
+ NumberAnimation { properties: "y"; to: removeTargets_transitionTo.y; duration: root.duration }
+ }
+ ScriptAction { script: grid.runningRemoveTargets = false }
+ }
+ }
+
+ removeDisplaced: Transition {
+ id: removeDisplaced
+ SequentialAnimation {
+ ScriptAction { script: grid.runningRemoveDisplaced = true }
+ ParallelAnimation {
+ NumberAnimation { properties: "x"; from: removeDisplaced_transitionFrom.x; duration: root.duration }
+ NumberAnimation { properties: "y"; from: removeDisplaced_transitionFrom.y; duration: root.duration }
+ }
+ ScriptAction { script: grid.runningRemoveDisplaced = false }
+ }
+ }
}
Rectangle {
QFETCH(int, initialCount);
QFETCH(qreal, contentY);
QFETCH(QList<ListChange>, changes);
+ QFETCH(bool, rippleAddDisplaced);
// add transitions on the left, moves on the right
QPointF addTargets_transitionFrom(-50, -50);
QPointF addDisplaced_transitionFrom(-50, 50);
QPointF moveTargets_transitionFrom(50, -50);
QPointF moveDisplaced_transitionFrom(50, 50);
+ QPointF removeTargets_transitionTo(-100, 300);
+ QPointF removeDisplaced_transitionFrom(100, 300);
QmlListModel model;
for (int i = 0; i < initialCount; i++)
ctxt->setContextProperty("addDisplaced_transitionFrom", addDisplaced_transitionFrom);
ctxt->setContextProperty("moveTargets_transitionFrom", moveTargets_transitionFrom);
ctxt->setContextProperty("moveDisplaced_transitionFrom", moveDisplaced_transitionFrom);
+ ctxt->setContextProperty("removeTargets_transitionTo", removeTargets_transitionTo);
+ ctxt->setContextProperty("removeDisplaced_transitionFrom", removeDisplaced_transitionFrom);
+ ctxt->setContextProperty("rippleAddDisplaced", rippleAddDisplaced);
canvas->setSource(testFileUrl("multipleTransitions.qml"));
canvas->show();
+ QTest::qWaitForWindowShown(canvas);
QQuickGridView *gridview = findItem<QQuickGridView>(canvas->rootObject(), "grid");
QTRY_VERIFY(gridview != 0);
QVERIFY(contentItem != 0);
QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ if (contentY != 0) {
+ gridview->setContentY(contentY);
+ QTRY_COMPARE(QQuickItemPrivate::get(gridview)->polishScheduled, false);
+ }
+
int timeBetweenActions = canvas->rootObject()->property("timeBetweenActions").toInt();
QList<QPair<QString, QString> > targetItems;
QTest::addColumn<int>("initialCount");
QTest::addColumn<qreal>("contentY");
QTest::addColumn<QList<ListChange> >("changes");
+ QTest::addColumn<bool>("rippleAddDisplaced");
// the added item and displaced items should move to final dest correctly
QTest::newRow("add item, then move it immediately") << 10 << 0.0 << (QList<ListChange>()
- << ListChange::insert(0, 1)
- << ListChange::move(0, 3, 1)
- );
+ << ListChange::insert(0, 1)
+ << ListChange::move(0, 3, 1)
+ )
+ << false;
// items affected by the add should change from move to add transition
QTest::newRow("move, then insert item before the moved item") << 20 << 0.0 << (QList<ListChange>()
<< ListChange::move(1, 10, 3)
<< ListChange::insert(0, 1)
- );
+ )
+ << false;
// items should be placed correctly if you trigger a transition then refill for that index
QTest::newRow("add at 0, flick down, flick back to top and add at 0 again") << 20 << 0.0 << (QList<ListChange>()
<< ListChange::setContentY(160.0)
<< ListChange::setContentY(0.0)
<< ListChange::insert(0, 1)
- );
+ )
+ << false;
+
+ QTest::newRow("insert then remove same index, with ripple effect on add displaced") << 20 << 0.0 << (QList<ListChange>()
+ << ListChange::insert(1, 1)
+ << ListChange::remove(1, 1)
+ )
+ << true;
}
void tst_QQuickGridView::cacheBuffer()
property bool runningAddDisplaced: false
property bool runningMoveTargets: false
property bool runningMoveDisplaced: false
+ property bool runningRemoveTargets: false
+ property bool runningRemoveDisplaced: false
objectName: "list"
focus: true
id: addDisplaced
SequentialAnimation {
ScriptAction { script: list.runningAddDisplaced = true }
+ PauseAnimation { duration: rippleAddDisplaced ? addDisplaced.ViewTransition.index * root.duration/10 : 0 }
ParallelAnimation {
NumberAnimation { properties: "x"; from: addDisplaced_transitionFrom.x; duration: root.duration }
NumberAnimation { properties: "y"; from: addDisplaced_transitionFrom.y; duration: root.duration }
ScriptAction { script: list.runningMoveDisplaced = false }
}
}
+
+ remove: Transition {
+ id: removeTargets
+ SequentialAnimation {
+ ScriptAction { script: list.runningRemoveTargets = true }
+ ParallelAnimation {
+ NumberAnimation { properties: "x"; to: removeTargets_transitionTo.x; duration: root.duration }
+ NumberAnimation { properties: "y"; to: removeTargets_transitionTo.y; duration: root.duration }
+ }
+ ScriptAction { script: list.runningRemoveTargets = false }
+ }
+ }
+
+ removeDisplaced: Transition {
+ id: removeDisplaced
+ SequentialAnimation {
+ ScriptAction { script: list.runningRemoveDisplaced = true }
+ ParallelAnimation {
+ NumberAnimation { properties: "x"; from: removeDisplaced_transitionFrom.x; duration: root.duration }
+ NumberAnimation { properties: "y"; from: removeDisplaced_transitionFrom.y; duration: root.duration }
+ }
+ ScriptAction { script: list.runningRemoveDisplaced = false }
+ }
+ }
}
Rectangle {
QFETCH(int, initialCount);
QFETCH(qreal, contentY);
QFETCH(QList<ListChange>, changes);
+ QFETCH(bool, rippleAddDisplaced);
- // add transitions on the left, moves on the right
QPointF addTargets_transitionFrom(-50, -50);
QPointF addDisplaced_transitionFrom(-50, 50);
QPointF moveTargets_transitionFrom(50, -50);
QPointF moveDisplaced_transitionFrom(50, 50);
+ QPointF removeTargets_transitionTo(-100, 300);
+ QPointF removeDisplaced_transitionFrom(100, 300);
QmlListModel model;
for (int i = 0; i < initialCount; i++)
ctxt->setContextProperty("addDisplaced_transitionFrom", addDisplaced_transitionFrom);
ctxt->setContextProperty("moveTargets_transitionFrom", moveTargets_transitionFrom);
ctxt->setContextProperty("moveDisplaced_transitionFrom", moveDisplaced_transitionFrom);
+ ctxt->setContextProperty("removeTargets_transitionTo", removeTargets_transitionTo);
+ ctxt->setContextProperty("removeDisplaced_transitionFrom", removeDisplaced_transitionFrom);
+ ctxt->setContextProperty("rippleAddDisplaced", rippleAddDisplaced);
canvas->setSource(testFileUrl("multipleTransitions.qml"));
canvas->show();
QTest::qWaitForWindowShown(canvas);
QVERIFY(contentItem != 0);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ if (contentY != 0) {
+ listview->setContentY(contentY);
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+ }
+
int timeBetweenActions = canvas->rootObject()->property("timeBetweenActions").toInt();
QList<QPair<QString, QString> > targetItems;
QTest::addColumn<int>("initialCount");
QTest::addColumn<qreal>("contentY");
QTest::addColumn<QList<ListChange> >("changes");
+ QTest::addColumn<bool>("rippleAddDisplaced");
// the added item and displaced items should move to final dest correctly
QTest::newRow("add item, then move it immediately") << 10 << 0.0 << (QList<ListChange>()
<< ListChange::insert(0, 1)
<< ListChange::move(0, 3, 1)
- );
+ )
+ << false;
// items affected by the add should change from move to add transition
QTest::newRow("move, then insert item before the moved item") << 20 << 0.0 << (QList<ListChange>()
<< ListChange::move(1, 10, 3)
<< ListChange::insert(0, 1)
- );
+ )
+ << false;
// items should be placed correctly if you trigger a transition then refill for that index
QTest::newRow("add at 0, flick down, flick back to top and add at 0 again") << 20 << 0.0 << (QList<ListChange>()
<< ListChange::setContentY(80.0)
<< ListChange::setContentY(0.0)
<< ListChange::insert(0, 1)
- );
+ )
+ << false;
+
+ QTest::newRow("insert then remove same index, with ripple effect on add displaced") << 20 << 0.0 << (QList<ListChange>()
+ << ListChange::insert(1, 1)
+ << ListChange::remove(1, 1)
+ )
+ << true;
}
QList<int> tst_QQuickListView::toIntList(const QVariantList &list)