PathView element's current item changes on insertion.
authorMartin Jones <martin.jones@nokia.com>
Wed, 9 Nov 2011 05:34:01 +0000 (15:34 +1000)
committerQt by Nokia <qt-info@nokia.com>
Thu, 10 Nov 2011 03:30:30 +0000 (04:30 +0100)
When inserting an item before the current item update the offset
to ensure the current item doesn't change.

Task-number: QTBUG-21320
Change-Id: I2375bc5098e7f83c33e7a0b123ed1b82f607055f
Reviewed-by: Bea Lam <bea.lam@nokia.com>
src/declarative/items/qquickpathview.cpp
tests/auto/declarative/qquickpathview/data/pathline.qml [new file with mode: 0644]
tests/auto/declarative/qquickpathview/tst_qquickpathview.cpp

index dc73bf2..c4da6f5 100644 (file)
@@ -494,7 +494,7 @@ void QQuickPathView::setModel(const QVariant &model)
         disconnect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
         for (int i=0; i<d->items.count(); i++){
             QQuickItem *p = d->items[i];
-            d->model->release(p);
+            d->releaseItem(p);
         }
         d->items.clear();
     }
@@ -1537,9 +1537,12 @@ void QQuickPathView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool r
         if (d->modelCount) {
             if (moveId == -1 && i.index <= d->currentIndex) {
                 d->currentIndex += i.count;
+                currentChanged = true;
             } else if (d->offset != 0) {
-                if (moveId != -1 && moveId == i.moveId)
+                if (moveId != -1 && moveId == i.moveId) {
                     d->currentIndex = i.index + moveOffset;
+                    currentChanged = true;
+                }
                 d->offset += i.count;
                 d->offsetAdj += i.count;
             }
@@ -1558,13 +1561,20 @@ void QQuickPathView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool r
         d->tl.reset(d->moveOffset);
     } else if (removed) {
         d->regenerate();
-        d->updateCurrent();
-        if (!d->flicking && !d->moving && d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange)
-            d->snapToCurrent();
+        if (!d->flicking && !d->moving && d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
+            qreal targetOffset = qmlMod(d->modelCount - d->currentIndex, d->modelCount);
+            if (targetOffset != d->offset)
+                d->tl.set(d->moveOffset, targetOffset);
+        }
     } else if (inserted) {
         d->firstIndex = -1;
         d->updateMappedRange();
         d->scheduleLayout();
+        if (!d->flicking && !d->moving && d->haveHighlightRange && d->highlightRangeMode == QQuickPathView::StrictlyEnforceRange) {
+            qreal targetOffset = qmlMod(d->modelCount - d->currentIndex, d->modelCount);
+            if (targetOffset != d->offset)
+                d->tl.set(d->moveOffset, targetOffset);
+        }
     }
     if (changedOffset)
         emit offsetChanged();
@@ -1698,6 +1708,9 @@ void QQuickPathViewPrivate::snapToCurrent()
 
     qreal targetOffset = qmlMod(modelCount - currentIndex, modelCount);
 
+    if (offset == targetOffset)
+        return;
+
     moveReason = Other;
     offsetAdj = 0.0;
     tl.reset(moveOffset);
diff --git a/tests/auto/declarative/qquickpathview/data/pathline.qml b/tests/auto/declarative/qquickpathview/data/pathline.qml
new file mode 100644 (file)
index 0000000..4c1c785
--- /dev/null
@@ -0,0 +1,48 @@
+import QtQuick 2.0
+
+Rectangle {
+    id: app
+    width: 360
+    height: 360
+
+    PathView {
+        id: pathView
+        objectName: "view"
+        x: (app.width-pathView.width)/2
+        y: 100
+        width: 240
+        height: 100
+
+        model: testModel
+
+        Rectangle {
+            anchors.fill: parent
+            color: "white"
+            border.color: "black"
+        }
+        preferredHighlightBegin: 0.5
+        preferredHighlightEnd: 0.5
+
+        delegate: Rectangle {
+            objectName: "wrapper"
+            width: 100
+            height: 100
+            color: PathView.isCurrentItem ? "red" : "yellow"
+            Text {
+                text: index
+                anchors.centerIn: parent
+            }
+            z: (PathView.isCurrentItem?1:0)
+        }
+        path: Path {
+            id: path
+            startX: -100+pathView.width/2
+            startY: pathView.height/2
+            PathLine {
+                id: line
+                x: 100+pathView.width/2
+                y: pathView.height/2
+            }
+        }
+    }
+}
index dc85f59..5e434b0 100644 (file)
@@ -111,6 +111,7 @@ private slots:
     void changePreferredHighlight();
     void missingPercent();
     void creationContext();
+    void currentOffsetOnInsertion();
 
 private:
     QQuickView *createView();
@@ -240,6 +241,8 @@ void tst_QQuickPathView::initValues()
     QCOMPARE(obj->dragMargin(), 0.);
     QCOMPARE(obj->count(), 0);
     QCOMPARE(obj->pathItemCount(), -1);
+
+    delete obj;
 }
 
 void tst_QQuickPathView::items()
@@ -303,6 +306,8 @@ void tst_QQuickPathView::pathview2()
     QCOMPARE(obj->dragMargin(), 0.);
     QCOMPARE(obj->count(), 8);
     QCOMPARE(obj->pathItemCount(), 10);
+
+    delete obj;
 }
 
 void tst_QQuickPathView::pathview3()
@@ -321,6 +326,8 @@ void tst_QQuickPathView::pathview3()
     QCOMPARE(obj->dragMargin(), 24.);
     QCOMPARE(obj->count(), 8);
     QCOMPARE(obj->pathItemCount(), 4);
+
+    delete obj;
 }
 
 void tst_QQuickPathView::path()
@@ -366,6 +373,8 @@ void tst_QQuickPathView::path()
     QCOMPARE(cubic->control1Y(), 90.);
     QCOMPARE(cubic->control2X(), 210.);
     QCOMPARE(cubic->control2Y(), 90.);
+
+    delete obj;
 }
 
 void tst_QQuickPathView::dataModel()
@@ -1081,6 +1090,86 @@ void tst_QQuickPathView::creationContext()
     QCOMPARE(item->property("text").toString(), QString("Hello!"));
 }
 
+// QTBUG-21320
+void tst_QQuickPathView::currentOffsetOnInsertion()
+{
+    QQuickView *canvas = createView();
+    canvas->show();
+
+    TestModel model;
+
+    QDeclarativeContext *ctxt = canvas->rootContext();
+    ctxt->setContextProperty("testModel", &model);
+
+    canvas->setSource(QUrl::fromLocalFile(TESTDATA("pathline.qml")));
+    qApp->processEvents();
+
+    QQuickPathView *pathview = findItem<QQuickPathView>(canvas->rootObject(), "view");
+    QVERIFY(pathview != 0);
+
+    pathview->setPreferredHighlightBegin(0.5);
+    pathview->setPreferredHighlightEnd(0.5);
+
+    QCOMPARE(pathview->count(), model.count());
+
+    model.addItem("item0", "0");
+
+    QCOMPARE(pathview->count(), model.count());
+
+    QQuickRectangle *item = 0;
+    QTRY_VERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 0));
+
+    QDeclarativePath *path = qobject_cast<QDeclarativePath*>(pathview->path());
+    QVERIFY(path);
+
+    QPointF start = path->pointAt(0.5);
+    start = QPointF(qRound(start.x()), qRound(start.y()));
+    QPointF offset;//Center of item is at point, but pos is from corner
+    offset.setX(item->width()/2);
+    offset.setY(item->height()/2);
+    QCOMPARE(item->pos() + offset, start);
+
+    QSignalSpy currentIndexSpy(pathview, SIGNAL(currentIndexChanged()));
+
+    // insert an item at the beginning
+    model.insertItem(0, "item1", "1");
+    qApp->processEvents();
+
+    QCOMPARE(currentIndexSpy.count(), 1);
+
+    // currentIndex is now 1
+    QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 1));
+
+    // verify that current item (item 1) is still at offset 0.5
+    QCOMPARE(item->pos() + offset, start);
+
+    // insert another item at the beginning
+    model.insertItem(0, "item2", "2");
+    qApp->processEvents();
+
+    QCOMPARE(currentIndexSpy.count(), 2);
+
+    // currentIndex is now 2
+    QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 2));
+
+    // verify that current item (item 2) is still at offset 0.5
+    QCOMPARE(item->pos() + offset, start);
+
+    // verify that remove before current maintains current item
+    model.removeItem(0);
+    qApp->processEvents();
+
+    QCOMPARE(currentIndexSpy.count(), 3);
+
+    // currentIndex is now 1
+    QVERIFY(item = findItem<QQuickRectangle>(pathview, "wrapper", 1));
+
+    // verify that current item (item 1) is still at offset 0.5
+    QCOMPARE(item->pos() + offset, start);
+
+    delete canvas;
+}
+
 QQuickView *tst_QQuickPathView::createView()
 {
     QQuickView *canvas = new QQuickView(0);