Navigation Menu

Skip to content

Commit

Permalink
Ensure items in ListView and GridViews viewport are visible.
Browse files Browse the repository at this point in the history
Unrequested items and items in the cache buffer are hidden by the views.
Make these items visible again if they enter the viewport due to a
relayout.

Change-Id: I574d1513e88c31c3c01a4a20ac77c21111279d3e
Reviewed-by: Bea Lam <bea.lam@nokia.com>
  • Loading branch information
Andrew den Exter authored and Qt by Nokia committed Dec 20, 2011
1 parent f3c7d8c commit ac50bb1
Show file tree
Hide file tree
Showing 7 changed files with 488 additions and 8 deletions.
5 changes: 5 additions & 0 deletions src/quick/items/qquickgridview.cpp
Expand Up @@ -542,13 +542,17 @@ void QQuickGridViewPrivate::updateViewport()
void QQuickGridViewPrivate::layoutVisibleItems()
{
if (visibleItems.count()) {
const qreal from = isContentFlowReversed() ? -position() - size() : position();
const qreal to = isContentFlowReversed() ? -position() : position() + size();

FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
qreal rowPos = firstItem->rowPos();
qreal colPos = firstItem->colPos();
int col = visibleIndex % columns;
if (colPos != col * colSize()) {
colPos = col * colSize();
firstItem->setPosition(colPos, rowPos);
firstItem->item->setVisible(rowPos + rowSize() >= from && rowPos <= to);
}
for (int i = 1; i < visibleItems.count(); ++i) {
FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
Expand All @@ -558,6 +562,7 @@ void QQuickGridViewPrivate::layoutVisibleItems()
}
colPos = col * colSize();
item->setPosition(colPos, rowPos);
item->item->setVisible(rowPos + rowSize() >= from && rowPos <= to);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions src/quick/items/qquickitemview.cpp
Expand Up @@ -1651,6 +1651,7 @@ void QQuickItemViewPrivate::releaseItem(FxViewItem *item)
itemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
if (model->release(item->item) == 0) {
// item was not destroyed, and we no longer reference it.
item->item->setVisible(false);
unrequestedItems.insert(item->item, model->indexOf(item->item, q));
}
delete item;
Expand Down
13 changes: 9 additions & 4 deletions src/quick/items/qquicklistview.cpp
Expand Up @@ -692,12 +692,18 @@ void QQuickListViewPrivate::visibleItemsChanged()
void QQuickListViewPrivate::layoutVisibleItems()
{
if (!visibleItems.isEmpty()) {
bool fixedCurrent = currentItem && (*visibleItems.constBegin())->item == currentItem->item;
qreal sum = (*visibleItems.constBegin())->size();
qreal pos = (*visibleItems.constBegin())->position() + (*visibleItems.constBegin())->size() + spacing;
const qreal from = isContentFlowReversed() ? -position() - size() : position();
const qreal to = isContentFlowReversed() ? -position() : position() + size();

FxViewItem *firstItem = *visibleItems.constBegin();
bool fixedCurrent = currentItem && firstItem->item == currentItem->item;
qreal sum = firstItem->size();
qreal pos = firstItem->position() + firstItem->size() + spacing;
firstItem->item->setVisible(firstItem->endPosition() >= from && firstItem->position() <= to);
for (int i=1; i < visibleItems.count(); ++i) {
FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.at(i));
item->setPosition(pos);
item->item->setVisible(item->endPosition() >= from && item->position() <= to);
pos += item->size() + spacing;
sum += item->size();
fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
Expand Down Expand Up @@ -2373,7 +2379,6 @@ bool QQuickListViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::In
int modelIndex = change.index;
int count = change.count;


qreal tempPos = isRightToLeft() ? -position()-size() : position();
int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;

Expand Down
67 changes: 67 additions & 0 deletions tests/auto/qtquick2/qquickgridview/data/unrequestedItems.qml
@@ -0,0 +1,67 @@
import QtQuick 2.0

Item {
width: 240
height: 320

Component {
id: myDelegate

Package {
Rectangle {
id: leftWrapper
objectName: "wrapper"
Package.name: "left"
height: 80
width: 60
Text {
text: index
}
color: ListView.isCurrentItem ? "lightsteelblue" : "white"
}
Rectangle {
id: rightWrapper
objectName: "wrapper"
Package.name: "right"
height: 80
width: 60
Text {
text: index
}
color: ListView.isCurrentItem ? "lightsteelblue" : "white"
}
}

}

VisualDataModel {
id: visualModel

delegate: myDelegate
model: testModel
}

GridView {
id: leftList
objectName: "leftGrid"
anchors {
left: parent.left; top: parent.top;
right: parent.horizontalCenter; bottom: parent.bottom
}
model: visualModel.parts.left
cellWidth: 60
cellHeight: 80
}

GridView {
id: rightList
objectName: "rightGrid"
anchors {
left: parent.horizontalCenter; top: parent.top;
right: parent.right; bottom: parent.bottom
}
model: visualModel.parts.right
cellWidth: 60
cellHeight: 80
}
}
169 changes: 169 additions & 0 deletions tests/auto/qtquick2/qquickgridview/tst_qquickgridview.cpp
Expand Up @@ -120,6 +120,7 @@ private slots:
void unaligned();
void cacheBuffer();
void asynchronous();
void unrequestedVisibility();

private:
QQuickView *createView();
Expand Down Expand Up @@ -3747,6 +3748,174 @@ void tst_QQuickGridView::asynchronous()
delete canvas;
}

void tst_QQuickGridView::unrequestedVisibility()
{
TestModel model;
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), QString::number(i));

QQuickView *canvas = new QQuickView(0);
canvas->setGeometry(0,0,240,320);

QDeclarativeContext *ctxt = canvas->rootContext();
ctxt->setContextProperty("testModel", &model);
ctxt->setContextProperty("testWrap", QVariant(false));

QString filename(TESTDATA("unrequestedItems.qml"));
canvas->setSource(QUrl::fromLocalFile(filename));

canvas->show();

qApp->processEvents();

QQuickGridView *leftview = findItem<QQuickGridView>(canvas->rootObject(), "leftGrid");
QTRY_VERIFY(leftview != 0);

QQuickGridView *rightview = findItem<QQuickGridView>(canvas->rootObject(), "rightGrid");
QTRY_VERIFY(rightview != 0);

QQuickItem *leftContent = leftview->contentItem();
QTRY_VERIFY(leftContent != 0);

QQuickItem *rightContent = rightview->contentItem();
QTRY_VERIFY(rightContent != 0);

rightview->setCurrentIndex(12);

QTRY_COMPARE(leftview->contentY(), 0.0);
QTRY_COMPARE(rightview->contentY(), 240.0);

QQuickItem *item;

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
QCOMPARE(item->isVisible(), false);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
QCOMPARE(item->isVisible(), true);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 9));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 10));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 3));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 4));
QCOMPARE(item->isVisible(), true);

rightview->setCurrentIndex(0);

QTRY_COMPARE(leftview->contentY(), 0.0);
QTRY_COMPARE(rightview->contentY(), 0.0);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
QTRY_COMPARE(item->isVisible(), true);

QVERIFY(!findItem<QQuickItem>(leftContent, "wrapper", 11));
QVERIFY(!findItem<QQuickItem>(rightContent, "wrapper", 11));

leftview->setCurrentIndex(12);

QTRY_COMPARE(leftview->contentY(), 240.0);
QTRY_COMPARE(rightview->contentY(), 0.0);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
QTRY_COMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
QCOMPARE(item->isVisible(), true);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
QCOMPARE(item->isVisible(), false);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
QCOMPARE(item->isVisible(), false);

model.moveItems(19, 1, 1);
QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);

QTRY_VERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 1));
QCOMPARE(item->isVisible(), true);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 11));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 11));
QCOMPARE(item->isVisible(), false);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 3));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 4));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
QCOMPARE(item->isVisible(), false);

model.moveItems(3, 4, 1);
QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
QCOMPARE(item->isVisible(), false);

model.moveItems(4, 5, 1);
QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
QCOMPARE(item->isVisible(), false);

model.moveItems(9, 10, 1);
QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
QCOMPARE(item->isVisible(), false);

model.moveItems(10, 9, 1);
QTRY_COMPARE(QQuickItemPrivate::get(leftview)->polishScheduled, false);

QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 1));
QCOMPARE(item->isVisible(), false);
QVERIFY(item = findItem<QQuickItem>(leftContent, "wrapper", 2));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 9));
QCOMPARE(item->isVisible(), true);
QVERIFY(item = findItem<QQuickItem>(rightContent, "wrapper", 10));
QCOMPARE(item->isVisible(), false);

delete canvas;
}

/*
Find an item with the specified objectName. If index is supplied then the
item must also evaluate the {index} expression equal to index
Expand Down
63 changes: 63 additions & 0 deletions tests/auto/qtquick2/qquicklistview/data/unrequestedItems.qml
@@ -0,0 +1,63 @@
import QtQuick 2.0

Item {
width: 240
height: 320

Component {
id: myDelegate

Package {
Rectangle {
id: leftWrapper
objectName: "wrapper"
Package.name: "left"
height: 20
width: 120
Text {
text: index
}
color: ListView.isCurrentItem ? "lightsteelblue" : "white"
}
Rectangle {
id: rightWrapper
objectName: "wrapper"
Package.name: "right"
height: 20
width: 120
Text {
text: index
}
color: ListView.isCurrentItem ? "lightsteelblue" : "white"
}
}

}

VisualDataModel {
id: visualModel

delegate: myDelegate
model: testModel
}

ListView {
id: leftList
objectName: "leftList"
anchors {
left: parent.left; top: parent.top;
right: parent.horizontalCenter; bottom: parent.bottom
}
model: visualModel.parts.left
}

ListView {
id: rightList
objectName: "rightList"
anchors {
left: parent.horizontalCenter; top: parent.top;
right: parent.right; bottom: parent.bottom
}
model: visualModel.parts.right
}
}

0 comments on commit ac50bb1

Please sign in to comment.