Navigation Menu

Skip to content

Commit

Permalink
[qtquick] Correctly initialize ListView section attached properties. …
Browse files Browse the repository at this point in the history
…Fixes JB#29647

During item insertion, indexes of items in the visibleItems list were
not adjusted before new items were created. Section initialization was
broken during insertion because section calculation relies on the
indexes of the items in the visibleItems list. The incorrect section
properties caused spurious section header creation, and layout issues.

Apply the index offset before creating the new items. This mirrors what
GridView already does.
  • Loading branch information
martinjones committed Jun 24, 2015
1 parent 10c6012 commit 974bc6c
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 13 deletions.
30 changes: 17 additions & 13 deletions src/quick/items/qquicklistview.cpp
Expand Up @@ -1163,9 +1163,11 @@ void QQuickListViewPrivate::updateSections()
if (visibleIndex > 0)
prevSection = sectionAt(visibleIndex-1);
QQuickListViewAttached *prevAtt = 0;
int prevIdx = -1;
int idx = -1;
for (int i = 0; i < visibleItems.count(); ++i) {
QQuickListViewAttached *attached = static_cast<QQuickListViewAttached*>(visibleItems.at(i)->attached);
FxViewItem *item = visibleItems.at(i);
QQuickListViewAttached *attached = static_cast<QQuickListViewAttached*>(item->attached);
attached->setPrevSection(prevSection);
if (visibleItems.at(i)->index != -1) {
QString propValue = model->stringValue(visibleItems.at(i)->index, sectionCriteria->property());
Expand All @@ -1174,9 +1176,10 @@ void QQuickListViewPrivate::updateSections()
}
updateInlineSection(static_cast<FxListItemSG*>(visibleItems.at(i)));
if (prevAtt)
prevAtt->setNextSection(attached->section());
prevAtt->setNextSection(sectionAt(prevIdx+1));
prevSection = attached->section();
prevAtt = attached;
prevIdx = item->index;
}
if (prevAtt) {
if (idx > 0 && idx < model->count()-1)
Expand Down Expand Up @@ -2969,6 +2972,18 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch
: visibleItems.last()->endPosition()+spacing;
}

// Update the indexes of the following visible items.
for (int i = 0; i < visibleItems.count(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index != -1 && item->index >= modelIndex) {
item->index += count;
if (change.isMove())
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, false);
else
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, false);
}
}

int prevVisibleCount = visibleItems.count();
if (insertResult->visiblePos.isValid() && pos < insertResult->visiblePos) {
// Insert items before the visible item.
Expand Down Expand Up @@ -3034,17 +3049,6 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch
}
}

for (; index < visibleItems.count(); ++index) {
FxViewItem *item = visibleItems.at(index);
if (item->index != -1) {
item->index += count;
if (change.isMove())
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, false);
else
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, false);
}
}

updateVisibleIndex();

return visibleItems.count() > prevVisibleCount;
Expand Down
Expand Up @@ -12,6 +12,9 @@ Rectangle {
Item {
id: wrapper
objectName: "wrapper"
property string section: ListView.section
property string nextSection: ListView.nextSection
property string prevSection: ListView.previousSection
height: 20;
width: 240
Rectangle {
Expand Down
62 changes: 62 additions & 0 deletions tests/auto/quick/qquicklistview/tst_qquicklistview.cpp
Expand Up @@ -142,6 +142,7 @@ private slots:
void sectionsDelegate_headerVisibility();
void sectionPropertyChange();
void sectionDelegateChange();
void sectionsItemInsertion();
void cacheBuffer();
void positionViewAtBeginningEnd();
void positionViewAtIndex();
Expand Down Expand Up @@ -2533,6 +2534,67 @@ void tst_QQuickListView::sectionDelegateChange()
delete window;
}

// QTBUG-43873
void tst_QQuickListView::sectionsItemInsertion()
{
QQuickView *window = createView();

QaimModel model;
for (int i = 0; i < 30; i++)
model.addItem("Item" + QString::number(i), QString::number(i/5));

QQmlContext *ctxt = window->rootContext();
ctxt->setContextProperty("testModel", &model);

window->setSource(testFileUrl("listview-sections_delegate.qml"));
window->show();
QVERIFY(QTest::qWaitForWindowExposed(window));

QQuickListView *listview = findItem<QQuickListView>(window->rootObject(), "list");
QTRY_VERIFY(listview != 0);
QQuickItem *contentItem = listview->contentItem();
QTRY_VERIFY(contentItem != 0);
QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);

for (int i = 0; i < 3; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "sect_" + QString::number(i));
QVERIFY(item);
QTRY_COMPARE(item->y(), qreal(i*20*6));
}

QQuickItem *topItem = findVisibleChild(contentItem, "sect_0"); // section header
QVERIFY(topItem);
QCOMPARE(topItem->y(), 0.);

// Insert a full screen of items at the beginning.
for (int i = 0; i < 10; i++)
model.insertItem(i, "Item" + QString::number(i), QLatin1String("A"));

QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);

int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
QVERIFY(itemCount > 10);

// Verify that the new items are postioned correctly, and have the correct attached section properties
for (int i = 0; i < 10 && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
QVERIFY(item);
QTRY_COMPARE(item->y(), 20+i*20.0);
QCOMPARE(item->property("section").toString(), QLatin1String("A"));
QCOMPARE(item->property("nextSection").toString(), i < 9 ? QLatin1String("A") : QLatin1String("0"));
QCOMPARE(item->property("prevSection").toString(), i > 0 ? QLatin1String("A") : QLatin1String(""));
}
// Verify that the exiting items are postioned correctly, and have the correct attached section properties
for (int i = 10; i < 15 && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
QVERIFY(item);
QTRY_COMPARE(item->y(), 40+i*20.0);
QCOMPARE(item->property("section").toString(), QLatin1String("0"));
QCOMPARE(item->property("nextSection").toString(), i < 14 ? QLatin1String("0") : QLatin1String("1"));
QCOMPARE(item->property("prevSection").toString(), i > 10 ? QLatin1String("0") : QLatin1String("A"));
}
}

void tst_QQuickListView::currentIndex_delayedItemCreation()
{
QFETCH(bool, setCurrentToZero);
Expand Down

0 comments on commit 974bc6c

Please sign in to comment.