@@ -121,6 +121,7 @@ void ListViewWithPageHeader::ListItem::setCulled(bool culled)
121121
122122ListViewWithPageHeader::ListViewWithPageHeader()
123123 : m_delegateModel(nullptr)
124+ , m_asyncRequestedIndex(-1)
124125 , m_delegateValidated(false)
125126 , m_firstVisibleIndex(-1)
126127 , m_minYExtent(0)
@@ -503,7 +504,7 @@ void ListViewWithPageHeader::updateWatchedRoles()
503504 }
504505}
505506
506−QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex)
507+QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyInserted)
507508{
508509 if (!m_sectionDelegate)
509510 return nullptr;
@@ -514,6 +515,19 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex)
514515 if (section == prevSection)
515516 return nullptr;
516517 }
518+ if (modelIndex + 1 < model()->rowCount() && !alreadyInserted) {
519+ // Already inserted items can't steal next section header
520+ const QString nextSection = m_delegateModel->stringValue(modelIndex + 1, m_sectionProperty);
521+ if (section == nextSection) {
522+ // Steal the section header
523+ ListItem *nextItem = itemAtIndex(modelIndex); // Not +1 since not yet inserted into m_visibleItems
524+ if (nextItem) {
525+ QQuickItem *sectionItem = nextItem->m_sectionItem;
526+ nextItem->m_sectionItem = nullptr;
527+ return sectionItem;
528+ }
529+ }
530+ }
517531
518532 return getSectionItem(section);
519533}
@@ -580,21 +594,24 @@ bool ListViewWithPageHeader::removeNonVisibleItems(qreal bufferFrom, qreal buffe
580594ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIndex, bool asynchronous)
581595{
582596// qDebug() << "CREATE ITEM" << modelIndex;
583− if (asynchronous && m_asyncRequestedIndexes.contains(modelIndex))
597+ if (asynchronous && m_asyncRequestedIndex != -1)
584598 return nullptr;
585599
586− m_asyncRequestedIndexes.remove(modelIndex);
600+ m_asyncRequestedIndex = -1;
587601 QQuickItem *item = m_delegateModel->item(modelIndex, asynchronous);
588602 if (!item) {
589− m_asyncRequestedIndexes << modelIndex;
603+ m_asyncRequestedIndex = modelIndex;
590604 return 0;
591605 } else {
592606// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
593607 ListItem *listItem = new ListItem;
594608 listItem->m_item = item;
595− listItem->m_sectionItem = getSectionItem(modelIndex);
609+ listItem->m_sectionItem = getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/);
596610 QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
597611 ListItem *prevItem = itemAtIndex(modelIndex - 1);
612+ bool lostItem = false; // Is an item that we requested async but because of model changes
613+ // it is no longer attached to any of the existing items (has no prev nor next item)
614+ // nor is the first item
598615 if (prevItem) {
599616 listItem->setY(prevItem->y() + prevItem->height());
600617 } else {
@@ -603,18 +620,25 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
603620 listItem->setY(nextItem->y() - listItem ->height());
604621 } else if (modelIndex == 0 && m_headerItem) {
605622 listItem->setY(m_headerItem->height());
623+ } else if (!m_visibleItems.isEmpty()) {
624+ lostItem = true;
606625 }
607626 }
608− listItem->setCulled(listItem->y() + listItem->height() + m_clipItem->y() < contentY() || listItem->y() + m_clipItem->y() >= contentY() + height());
609− if (m_visibleItems.isEmpty()) {
610− m_visibleItems << listItem;
627+ if (lostItem) {
628+ releaseItem(listItem);
629+ listItem = nullptr;
611630 } else {
612− m_visibleItems.insert(modelIndex - m_firstVisibleIndex, listItem);
613− }
614− if (m_firstVisibleIndex < 0 || modelIndex < m_firstVisibleIndex) {
615− m_firstVisibleIndex = modelIndex;
616− adjustMinYExtent();
617− qDebug() << "ListViewWithPageHeader::createItem" << m_minYExtent;
631+ listItem->setCulled(listItem->y() + listItem->height() + m_clipItem->y() < contentY() || listItem->y() + m_clipItem->y() >= contentY() + height());
632+ if (m_visibleItems.isEmpty()) {
633+ m_visibleItems << listItem;
634+ } else {
635+ m_visibleItems.insert(modelIndex - m_firstVisibleIndex, listItem);
636+ }
637+ if (m_firstVisibleIndex < 0 || modelIndex < m_firstVisibleIndex) {
638+ m_firstVisibleIndex = modelIndex;
639+ adjustMinYExtent();
640+ qDebug() << "ListViewWithPageHeader::createItem" << m_minYExtent;
641+ }
618642 }
619643 return listItem;
620644 }
@@ -627,7 +651,7 @@ void ListViewWithPageHeader::itemCreated(int modelIndex, QQuickItem *item)
627651 item->setParentItem(m_clipItem);
628652 QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
629653 context->setContextProperty(QLatin1String("ListViewWithPageHeader"), this);
630− if (m_asyncRequestedIndexes.remove(modelIndex)) {
654+ if (modelIndex == m_asyncRequestedIndex) {
631655 createItem(modelIndex, false);
632656 }
633657}
@@ -677,6 +701,14 @@ void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bo
677701 const int visibleIndex = remove.index + i - m_firstVisibleIndex;
678702 if (visibleIndex >= 0 && visibleIndex < m_visibleItems.count()) {
679703 ListItem *item = m_visibleItems[visibleIndex];
704+ // Pass the section item down if needed
705+ if (item->m_sectionItem && visibleIndex + 1 < m_visibleItems.count()) {
706+ ListItem *nextItem = m_visibleItems[visibleIndex + 1];
707+ if (!nextItem->m_sectionItem) {
708+ nextItem->m_sectionItem = item->m_sectionItem;
709+ item->m_sectionItem = nullptr;
710+ }
711+ }
680712 releaseItem(item);
681713 m_visibleItems.removeAt(visibleIndex);
682714 }
@@ -692,6 +724,14 @@ void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bo
692724 } else if (remove.index + remove.count <= m_firstVisibleIndex) {
693725 m_firstVisibleIndex -= remove.count;
694726 }
727+ for (int i = remove.count - 1; i >= 0; --i) {
728+ const int modelIndex = remove.index + i;
729+ if (modelIndex == m_asyncRequestedIndex) {
730+ m_asyncRequestedIndex = -1;
731+ } else if (modelIndex < m_asyncRequestedIndex) {
732+ m_asyncRequestedIndex--;
733+ }
734+ }
695735 }
696736
697737 foreach(const QQuickChangeSet::Insert &insert, changeSet.inserts()) {
@@ -724,6 +764,19 @@ void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bo
724764 adjustMinYExtent();
725765 qDebug() << "ListViewWithPageHeader::onModelUpdated growed up" << m_minYExtent;
726766 }
767+ // Adding an item may break a "same section" chain, so check
768+ // if we need adding a new section item
769+ if (m_sectionDelegate) {
770+ ListItem *nextItem = itemAtIndex(modelIndex + 1);
771+ if (nextItem && !nextItem->m_sectionItem) {
772+ nextItem->m_sectionItem = getSectionItem(modelIndex + 1, true /* alredy inserted into m_visibleItems*/);
773+ if (growUp) {
774+ ListItem *firstItem = m_visibleItems.first();
775+ firstItem->setY(firstItem->y() - nextItem->m_sectionItem->height());
776+ adjustMinYExtent();
777+ }
778+ }
779+ }
727780 }
728781 if (firstItemWithViewOnTop) {
729782 ListItem *firstItem = m_visibleItems.first();
@@ -732,6 +785,13 @@ void ListViewWithPageHeader::onModelUpdated(const QQuickChangeSet &changeSet, bo
732785 } else if (insert.index <= m_firstVisibleIndex) {
733786 m_firstVisibleIndex += insert.count;
734787 }
788+
789+ for (int i = insert.count - 1; i >= 0; --i) {
790+ const int modelIndex = insert.index + i;
791+ if (modelIndex <= m_asyncRequestedIndex) {
792+ m_asyncRequestedIndex++;
793+ }
794+ }
735795 }
736796
737797 polish();
@@ -860,13 +920,15 @@ void ListViewWithPageHeader::updatePolish()
860920 // Second step of section sticky item positioning
861921 // Look at the next section header, check if it's pushing up the sticky one
862922 if (m_topSectionItem) {
863− for (int i = firstReallyVisibleItem - m_firstVisibleIndex + 1; i < m_visibleItems.count(); ++i) {
864− ListItem *item = m_visibleItems[i];
865− if (item->m_sectionItem) {
866− if (m_topSectionItem->y() + m_topSectionItem->height() > item->y()) {
867− m_topSectionItem->setY(item->y() - m_topSectionItem->height());
923+ if (firstReallyVisibleItem >= 0) {
924+ for (int i = firstReallyVisibleItem - m_firstVisibleIndex + 1; i < m_visibleItems.count(); ++i) {
925+ ListItem *item = m_visibleItems[i];
926+ if (item->m_sectionItem) {
927+ if (m_topSectionItem->y() + m_topSectionItem->height() > item->y()) {
928+ m_topSectionItem->setY(item->y() - m_topSectionItem->height());
929+ }
930+ break;
868931 }
869− break;
870932 }
871933 }
872934 }