Add a currentItem property to PathView.
authorAndrew den Exter <andrew.den-exter@nokia.com>
Mon, 1 Aug 2011 03:09:10 +0000 (13:09 +1000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 2 Aug 2011 08:46:54 +0000 (10:46 +0200)
Task-number: QTBUG-16347
Change-Id: I6df4b2d7c5f325e84d54ed5befd66e20b64cc7e0
Reviewed-on: http://codereview.qt.nokia.com/2421
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Martin Jones <martin.jones@nokia.com>
doc/src/declarative/whatsnew.qdoc
src/declarative/items/qsgpathview.cpp
src/declarative/items/qsgpathview_p.h
src/declarative/items/qsgpathview_p_p.h
tests/auto/declarative/qsgpathview/data/pathview0.qml
tests/auto/declarative/qsgpathview/tst_qsgpathview.cpp

index 1eb64f9..d3db134 100644 (file)
@@ -65,6 +65,13 @@ QDeclarativeView and QDeclarativeItem headers are now in the QtQuick 1 module, i
 the library (lib/libQtQuick1*) and plugin (imports/QtQuick/) must be installed.
 
 
+\section2 PathView
+
+Added the following properties:
+\list
+\o \l {PathView::}{currentItem}
+\endlist
+
 \section1 Qt 4.7.4 includes QtQuick 1.1
 
 QtQuick 1.1 is a minor feature update.  \e {import QtQuick 1.1} to use the new
index 9fae40f..4a0496c 100644 (file)
@@ -111,7 +111,7 @@ void QSGPathViewPrivate::init()
                          q, movementEndingIdx, Qt::DirectConnection);
 }
 
-QSGItem *QSGPathViewPrivate::getItem(int modelIndex)
+QSGItem *QSGPathViewPrivate::getItem(int modelIndex, bool onPath)
 {
     Q_Q(QSGPathView);
     requestedIndex = modelIndex;
@@ -128,7 +128,7 @@ QSGItem *QSGPathViewPrivate::getItem(int modelIndex)
         qPathViewAttachedType = 0;
         if (att) {
             att->m_view = q;
-            att->setOnPath(true);
+            att->setOnPath(onPath);
         }
         item->setParentItem(q);
         QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
@@ -158,6 +158,10 @@ QSGPathViewAttached *QSGPathViewPrivate::attached(QSGItem *item)
 
 void QSGPathViewPrivate::clear()
 {
+    if (currentItem) {
+        releaseItem(currentItem);
+        currentItem = 0;
+    }
     for (int i=0; i<items.count(); i++){
         QSGItem *p = items[i];
         releaseItem(p);
@@ -470,28 +474,31 @@ void QSGPathView::setCurrentIndex(int idx)
     if (d->model && d->modelCount)
         idx = qAbs(idx % d->modelCount);
     if (d->model && idx != d->currentIndex) {
-        if (d->modelCount) {
-            int itemIndex = (d->currentIndex - d->firstIndex + d->modelCount) % d->modelCount;
-            if (itemIndex < d->items.count()) {
-                if (QSGItem *item = d->items.at(itemIndex)) {
-                    if (QSGPathViewAttached *att = d->attached(item))
-                        att->setIsCurrentItem(false);
-                }
-            }
+        if (d->currentItem) {
+            if (QSGPathViewAttached *att = d->attached(d->currentItem))
+                att->setIsCurrentItem(false);
+            d->releaseItem(d->currentItem);
         }
         d->currentItem = 0;
         d->moveReason = QSGPathViewPrivate::SetIndex;
         d->currentIndex = idx;
         if (d->modelCount) {
-            if (d->haveHighlightRange && d->highlightRangeMode == QSGPathView::StrictlyEnforceRange)
-                d->snapToCurrent();
             int itemIndex = (idx - d->firstIndex + d->modelCount) % d->modelCount;
             if (itemIndex < d->items.count()) {
-                d->currentItem = d->items.at(itemIndex);
+                d->currentItem = d->model->item(d->currentIndex, true);
                 d->currentItem->setFocus(true);
                 if (QSGPathViewAttached *att = d->attached(d->currentItem))
                     att->setIsCurrentItem(true);
+            } else {
+                d->currentItem = d->getItem(d->currentIndex, false);
+                d->updateItem(d->currentItem, d->currentIndex < d->firstIndex ? 0.0 : 1.0);
+                if (QSGPathViewAttached *att = d->attached(d->currentItem))
+                    att->setIsCurrentItem(true);
+                if (d->model->completePending())
+                    d->model->completeItem();
             }
+            if (d->haveHighlightRange && d->highlightRangeMode == QSGPathView::StrictlyEnforceRange)
+                d->snapToCurrent();
             d->currentItemOffset = d->positionOfIndex(d->currentIndex);
             d->updateHighlight();
         }
@@ -499,6 +506,12 @@ void QSGPathView::setCurrentIndex(int idx)
     }
 }
 
+QSGItem *QSGPathView::currentItem() const
+{
+    Q_D(const QSGPathView);
+    return d->currentItem;
+}
+
 void QSGPathView::incrementCurrentIndex()
 {
     Q_D(QSGPathView);
@@ -1092,12 +1105,8 @@ void QSGPathView::refill()
                 if (d->model->completePending())
                     item->setZ(idx+1);
                 if (d->currentIndex == idx) {
-                    item->setFocus(true);
-                    if (QSGPathViewAttached *att = d->attached(item))
-                        att->setIsCurrentItem(true);
                     currentVisible = true;
                     d->currentItemOffset = pos;
-                    d->currentItem = item;
                 }
                 if (d->items.count() == 0)
                     d->firstIndex = idx;
@@ -1121,12 +1130,8 @@ void QSGPathView::refill()
                 if (d->model->completePending())
                     item->setZ(idx+1);
                 if (d->currentIndex == idx) {
-                    item->setFocus(true);
-                    if (QSGPathViewAttached *att = d->attached(item))
-                        att->setIsCurrentItem(true);
                     currentVisible = true;
                     d->currentItemOffset = pos;
-                    d->currentItem = item;
                 }
                 d->items.prepend(item);
                 d->updateItem(item, pos);
@@ -1141,8 +1146,25 @@ void QSGPathView::refill()
         }
     }
 
-    if (!currentVisible)
+    if (!currentVisible) {
         d->currentItemOffset = 1.0;
+        if (d->currentItem) {
+            if (QSGPathViewAttached *att = d->attached(d->currentItem))
+                att->setOnPath(false);
+        } else if (d->currentIndex >= 0 && d->currentIndex < d->modelCount) {
+            d->currentItem = d->getItem(d->currentIndex, false);
+            d->updateItem(d->currentItem, d->currentIndex < d->firstIndex ? 0.0 : 1.0);
+            if (QSGPathViewAttached *att = d->attached(d->currentItem))
+                att->setIsCurrentItem(true);
+            if (d->model->completePending())
+                d->model->completeItem();
+        }
+    } else if (!d->currentItem) {
+        d->currentItem = d->model->item(d->currentIndex, true);
+        d->currentItem->setFocus(true);
+        if (QSGPathViewAttached *att = d->attached(d->currentItem))
+            att->setIsCurrentItem(true);
+    }
 
     if (d->highlightItem && d->haveHighlightRange && d->highlightRangeMode == QSGPathView::StrictlyEnforceRange) {
         d->updateItem(d->highlightItem, d->highlightRangeStart);
@@ -1206,6 +1228,8 @@ void QSGPathView::itemsRemoved(int modelIndex, int count)
         if (d->currentItem) {
             if (QSGPathViewAttached *att = d->attached(d->currentItem))
                 att->setIsCurrentItem(true);
+            d->releaseItem(d->currentItem);
+            d->currentItem = 0;
         }
         currentChanged = true;
     }
@@ -1345,21 +1369,26 @@ void QSGPathViewPrivate::updateCurrent()
 
     int idx = calcCurrentIndex();
     if (model && idx != currentIndex) {
-        int itemIndex = (currentIndex - firstIndex + modelCount) % modelCount;
-        if (itemIndex < items.count()) {
-            if (QSGItem *item = items.at(itemIndex)) {
-                if (QSGPathViewAttached *att = attached(item))
-                    att->setIsCurrentItem(false);
-            }
+        if (currentItem) {
+            if (QSGPathViewAttached *att = attached(currentItem))
+                att->setIsCurrentItem(false);
+            releaseItem(currentItem);
         }
         currentIndex = idx;
         currentItem = 0;
-        itemIndex = (idx - firstIndex + modelCount) % modelCount;
+        int itemIndex = (idx - firstIndex + modelCount) % modelCount;
         if (itemIndex < items.count()) {
-            currentItem = items.at(itemIndex);
+            currentItem = model->item(currentIndex, true);
             currentItem->setFocus(true);
             if (QSGPathViewAttached *att = attached(currentItem))
                 att->setIsCurrentItem(true);
+        } else if (currentIndex >= 0 && currentIndex < modelCount) {
+            currentItem = getItem(currentIndex, false);
+            updateItem(currentItem, currentIndex < firstIndex ? 0.0 : 1.0);
+            if (QSGPathViewAttached *att = attached(currentItem))
+                att->setIsCurrentItem(true);
+            if (model->completePending())
+                model->completeItem();
         }
         emit q->currentIndexChanged();
     }
index c91c4b6..a271e32 100644 (file)
@@ -62,6 +62,7 @@ class Q_AUTOTEST_EXPORT QSGPathView : public QSGItem
     Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
     Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
     Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+    Q_PROPERTY(QSGItem *currentItem READ currentItem NOTIFY currentIndexChanged)
     Q_PROPERTY(qreal offset READ offset WRITE setOffset NOTIFY offsetChanged)
 
     Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
@@ -98,6 +99,8 @@ public:
     int currentIndex() const;
     void setCurrentIndex(int idx);
 
+    QSGItem *currentItem() const;
+
     qreal offset() const;
     void setOffset(qreal offset);
 
index a133e80..1575c6c 100644 (file)
@@ -111,7 +111,7 @@ public:
         }
     }
 
-    QSGItem *getItem(int modelIndex);
+    QSGItem *getItem(int modelIndex, bool onPath = true);
     void releaseItem(QSGItem *item);
     QSGPathViewAttached *attached(QSGItem *item);
     void clear();
index 72b71a3..8b93781 100644 (file)
@@ -17,6 +17,7 @@ Rectangle {
             Rectangle {
                 id: wrapper
                 objectName: "wrapper"
+                property bool onPath: PathView.onPath
                 height: root.delegateHeight
                 width: root.delegateWidth
                 scale: root.delegateScale
index 91f6491..00202f7 100644 (file)
@@ -423,6 +423,7 @@ void tst_QSGPathView::dataModel()
     QTRY_COMPARE(findItems<QSGItem>(pathview, "wrapper").count(), 14);
 
     QVERIFY(pathview->currentIndex() == 0);
+    QCOMPARE(pathview->currentItem(), findItem<QSGItem>(pathview, "wrapper", 0));
 
     QSGText *text = findItem<QSGText>(pathview, "myText", 4);
     QVERIFY(text);
@@ -433,6 +434,7 @@ void tst_QSGPathView::dataModel()
     text = findItem<QSGText>(pathview, "myText", 2);
     QVERIFY(text);
     QCOMPARE(text->text(), model.name(2));
+    QCOMPARE(pathview->currentItem(), findItem<QSGItem>(pathview, "wrapper", 0));
 
     testObject->setPathItemCount(5);
     QMetaObject::invokeMethod(canvas->rootObject(), "checkProperties");
@@ -446,12 +448,15 @@ void tst_QSGPathView::dataModel()
     QVERIFY(testItem == 0);
 
     pathview->setCurrentIndex(1);
+    QCOMPARE(pathview->currentItem(), findItem<QSGItem>(pathview, "wrapper", 1));
+    QTest::qWait(100);
 
     model.insertItem(2, "pink", "2");
     QTest::qWait(100);
 
     QTRY_COMPARE(findItems<QSGItem>(pathview, "wrapper").count(), 5);
     QVERIFY(pathview->currentIndex() == 1);
+    QCOMPARE(pathview->currentItem(), findItem<QSGItem>(pathview, "wrapper", 1));
 
     text = findItem<QSGText>(pathview, "myText", 2);
     QVERIFY(text);
@@ -462,6 +467,7 @@ void tst_QSGPathView::dataModel()
     text = findItem<QSGText>(pathview, "myText", 3);
     QVERIFY(text);
     QCOMPARE(text->text(), model.name(3));
+    QCOMPARE(pathview->currentItem(), findItem<QSGItem>(pathview, "wrapper", 1));
 
     model.moveItem(3, 5);
     QTRY_COMPARE(findItems<QSGItem>(pathview, "wrapper").count(), 5);
@@ -469,6 +475,7 @@ void tst_QSGPathView::dataModel()
     foreach (QSGItem *item, items) {
         QVERIFY(item->property("onPath").toBool());
     }
+    QCOMPARE(pathview->currentItem(), findItem<QSGItem>(pathview, "wrapper", 1));
 
     // QTBUG-14199
     pathview->setOffset(7);
@@ -578,30 +585,81 @@ void tst_QSGPathView::setCurrentIndex()
     QTRY_COMPARE(firstItem->pos() + offset, start);
     QCOMPARE(canvas->rootObject()->property("currentA").toInt(), 2);
     QCOMPARE(canvas->rootObject()->property("currentB").toInt(), 2);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(true));
 
     pathview->decrementCurrentIndex();
     QTRY_COMPARE(pathview->currentIndex(), 1);
     firstItem = findItem<QSGRectangle>(pathview, "wrapper", 1);
     QVERIFY(firstItem);
     QTRY_COMPARE(firstItem->pos() + offset, start);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(true));
 
     pathview->decrementCurrentIndex();
     QTRY_COMPARE(pathview->currentIndex(), 0);
     firstItem = findItem<QSGRectangle>(pathview, "wrapper", 0);
     QVERIFY(firstItem);
     QTRY_COMPARE(firstItem->pos() + offset, start);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(true));
 
     pathview->decrementCurrentIndex();
     QTRY_COMPARE(pathview->currentIndex(), 3);
     firstItem = findItem<QSGRectangle>(pathview, "wrapper", 3);
     QVERIFY(firstItem);
     QTRY_COMPARE(firstItem->pos() + offset, start);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(true));
 
     pathview->incrementCurrentIndex();
     QTRY_COMPARE(pathview->currentIndex(), 0);
     firstItem = findItem<QSGRectangle>(pathview, "wrapper", 0);
     QVERIFY(firstItem);
     QTRY_COMPARE(firstItem->pos() + offset, start);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+    // Check the current item is still created when outside the bounds of pathItemCount.
+    pathview->setPathItemCount(2);
+    pathview->setHighlightRangeMode(QSGPathView::NoHighlightRange);
+    QVERIFY(findItem<QSGRectangle>(pathview, "wrapper", 0));
+    QVERIFY(findItem<QSGRectangle>(pathview, "wrapper", 1));
+    QVERIFY(!findItem<QSGRectangle>(pathview, "wrapper", 2));
+    QVERIFY(!findItem<QSGRectangle>(pathview, "wrapper", 3));
+
+    pathview->setCurrentIndex(2);
+    firstItem = findItem<QSGRectangle>(pathview, "wrapper", 2);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(false));
+
+    pathview->decrementCurrentIndex();
+    QTRY_COMPARE(pathview->currentIndex(), 1);
+    firstItem = findItem<QSGRectangle>(pathview, "wrapper", 1);
+    QVERIFY(firstItem);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+    pathview->decrementCurrentIndex();
+    QTRY_COMPARE(pathview->currentIndex(), 0);
+    firstItem = findItem<QSGRectangle>(pathview, "wrapper", 0);
+    QVERIFY(firstItem);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(true));
+
+    pathview->decrementCurrentIndex();
+    QTRY_COMPARE(pathview->currentIndex(), 3);
+    firstItem = findItem<QSGRectangle>(pathview, "wrapper", 3);
+    QVERIFY(firstItem);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(false));
+
+    pathview->incrementCurrentIndex();
+    QTRY_COMPARE(pathview->currentIndex(), 0);
+    firstItem = findItem<QSGRectangle>(pathview, "wrapper", 0);
+    QVERIFY(firstItem);
+    QCOMPARE(pathview->currentItem(), firstItem);
+    QCOMPARE(firstItem->property("onPath"), QVariant(true));
 
     delete canvas;
 }