@@ -138,6 +138,13 @@ void ListViewWithPageHeader::ListItem::setCulled(bool culled)
138138 QQuickItemPrivate::get(m_sectionItem)->setCulled(culled);
139139}
140140
141+void ListViewWithPageHeader::ListItem::setSectionItem(QQuickItem *sectionItem)
142+{
143+ m_sectionItem = sectionItem;
144+ QQmlContext *context = QQmlEngine::contextForObject(m_item)->parentContext();
145+ context->setContextProperty(QLatin1String("hasSectionHeader"), QVariant::fromValue<bool>(sectionItem != nullptr));
146+}
147+
141148ListViewWithPageHeader::ListViewWithPageHeader()
142149 : m_delegateModel(nullptr)
143150 , m_asyncRequestedIndex(-1)
@@ -251,6 +258,8 @@ void ListViewWithPageHeader::setHeader(QQuickItem *headerItem)
251258 if (m_headerItem) {
252259 m_headerItem->setParentItem(contentItem());
253260 m_headerItem->setZ(1);
261+ m_previousHeaderImplicitHeight = m_headerItem->implicitHeight();
262+ QQuickItemPrivate::get(m_headerItem)->addItemChangeListener(this, QQuickItemPrivate::ImplicitHeight);
254263 }
255264 qreal newHeaderHeight = m_headerItem ? m_headerItem->height() : 0;
256265 if (!m_visibleItems.isEmpty() && newHeaderHeight != oldHeaderHeight) {
@@ -422,7 +431,7 @@ bool ListViewWithPageHeader::maximizeVisibleArea(int modelIndex, int itemHeight)
422431
423432 ListItem *listItem = itemAtIndex(modelIndex);
424433 if (listItem) {
425− return maximizeVisibleArea(listItem, itemHeight + (listItem->m_sectionItem ? listItem->m_sectionItem->height() : 0));
434+ return maximizeVisibleArea(listItem, itemHeight + (listItem->sectionItem() ? listItem->sectionItem()->height() : 0));
426435 }
427436
428437 return false;
@@ -440,7 +449,7 @@ bool ListViewWithPageHeader::maximizeVisibleArea(ListItem *listItem, int listIte
440449 contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
441450 m_contentYAnimation->start();
442451 } else if ((listItemY < contentY() && listItemY + listItemHeight < contentY() + height()) ||
443− (m_topSectionItem && !listItem->m_sectionItem && listItemY - m_topSectionItem->height() < contentY() && listItemY + listItemHeight < contentY() + height()))
452+ (m_topSectionItem && !listItem->sectionItem() && listItemY - m_topSectionItem->height() < contentY() && listItemY + listItemHeight < contentY() + height()))
444453 {
445454 // we can scroll the list down to show more stuff
446455 auto realVisibleListItemY = listItemY;
@@ -449,7 +458,7 @@ bool ListViewWithPageHeader::maximizeVisibleArea(ListItem *listItem, int listIte
449458 // item we have to make sure to scroll it a bit more so that it is not underlapping
450459 // the top section sticky item
451460 bool topSectionShown = !QQuickItemPrivate::get(m_topSectionItem)->culled;
452− if (topSectionShown && !listItem->m_sectionItem) {
461+ if (topSectionShown && !listItem->sectionItem()) {
453462 realVisibleListItemY -= m_topSectionItem->height();
454463 }
455464 }
@@ -489,7 +498,15 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
489498
490499 QQuickFlickable::viewportMoved(orient);
491500// qDebug() << "ListViewWithPageHeader::viewportMoved" << contentY();
492− qreal diff = m_previousContentY - contentY();
501+ const qreal diff = m_previousContentY - contentY();
502+ adjustHeader(diff);
503+ m_previousContentY = contentY();
504+ layout();
505+ polish();
506+}
507+
508+void ListViewWithPageHeader::adjustHeader(qreal diff)
509+{
493510 const bool showHeaderAnimationRunning = m_contentYAnimation->isRunning() && contentYAnimationType == ContentYAnimationShowHeader;
494511 if (m_headerItem) {
495512 const auto oldHeaderItemShownHeight = m_headerItemShownHeight;
@@ -551,10 +568,6 @@ void ListViewWithPageHeader::viewportMoved(Qt::Orientations orient)
551568 adjustMinYExtent();
552569 }
553570 }
554−
555− m_previousContentY = contentY();
556− layout();
557− polish();
558571}
559572
560573void ListViewWithPageHeader::createDelegateModel()
@@ -645,7 +658,7 @@ void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
645658 if (flags & QQmlDelegateModel::Destroyed) {
646659 item->setParentItem(nullptr);
647660 }
648− delete listItem->m_sectionItem;
661+ delete listItem->sectionItem();
649662 delete listItem;
650663}
651664
@@ -672,6 +685,9 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyI
672685 return nullptr;
673686
674687 const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
688+ if (section.isEmpty())
689+ return nullptr;
690+
675691 if (modelIndex > 0) {
676692 const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
677693 if (section == prevSection)
@@ -684,8 +700,8 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyI
684700 // Steal the section header
685701 ListItem *nextItem = itemAtIndex(modelIndex); // Not +1 since not yet inserted into m_visibleItems
686702 if (nextItem) {
687− QQuickItem *sectionItem = nextItem->m_sectionItem;
688− nextItem->m_sectionItem = nullptr;
703+ QQuickItem *sectionItem = nextItem->sectionItem();
704+ nextItem->setSectionItem(nullptr);
689705 return sectionItem;
690706 }
691707 }
@@ -793,7 +809,7 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
793809// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
794810 ListItem *listItem = new ListItem;
795811 listItem->m_item = item;
796− listItem->m_sectionItem = getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/);
812+ listItem->setSectionItem(getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/));
797813 QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
798814 ListItem *prevItem = itemAtIndex(modelIndex - 1);
799815 bool lostItem = false; // Is an item that we requested async but because of model changes
@@ -832,8 +848,8 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
832848 m_firstVisibleIndex = modelIndex;
833849 polish();
834850 }
835− if (listItem->m_sectionItem) {
836− QQmlContext *context = QQmlEngine::contextForObject(listItem->m_sectionItem)->parentContext();
851+ if (listItem->sectionItem()) {
852+ QQmlContext *context = QQmlEngine::contextForObject(listItem->sectionItem())->parentContext();
837853 context->setContextProperty(QLatin1String("delegateIndex"), modelIndex);
838854 }
839855 adjustMinYExtent();
@@ -861,6 +877,7 @@ void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
861877 QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
862878 context->setContextProperty(QLatin1String("ListViewWithPageHeader"), this);
863879 context->setContextProperty(QLatin1String("heightToClip"), QVariant::fromValue<int>(0));
880+ context->setContextProperty(QLatin1String("hasSectionHeader"), QVariant::fromValue<bool>(false));
864881 if (modelIndex == m_asyncRequestedIndex) {
865882 createItem(modelIndex, false);
866883 refill();
@@ -915,11 +932,11 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
915932 if (visibleIndex >= 0 && visibleIndex < m_visibleItems.count()) {
916933 ListItem *item = m_visibleItems[visibleIndex];
917934 // Pass the section item down if needed
918− if (item->m_sectionItem && visibleIndex + 1 < m_visibleItems.count()) {
935+ if (item->sectionItem() && visibleIndex + 1 < m_visibleItems.count()) {
919936 ListItem *nextItem = m_visibleItems[visibleIndex + 1];
920− if (!nextItem->m_sectionItem) {
921− nextItem->m_sectionItem = item->m_sectionItem;
922− item->m_sectionItem = nullptr;
937+ if (!nextItem->sectionItem()) {
938+ nextItem->setSectionItem(item->sectionItem());
939+ item->setSectionItem(nullptr);
923940 }
924941 }
925942 releaseItem(item);
@@ -982,11 +999,11 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
982999 // if we need adding a new section item
9831000 if (m_sectionDelegate) {
9841001 ListItem *nextItem = itemAtIndex(modelIndex + 1);
985− if (nextItem && !nextItem->m_sectionItem) {
986− nextItem->m_sectionItem = getSectionItem(modelIndex + 1, true /* alredy inserted into m_visibleItems*/);
987− if (growUp && nextItem->m_sectionItem) {
1002+ if (nextItem && !nextItem->sectionItem()) {
1003+ nextItem->setSectionItem(getSectionItem(modelIndex + 1, true /* alredy inserted into m_visibleItems*/));
1004+ if (growUp && nextItem->sectionItem()) {
9881005 ListItem *firstItem = m_visibleItems.first();
989− firstItem->setY(firstItem->y() - nextItem->m_sectionItem->height());
1006+ firstItem->setY(firstItem->y() - nextItem->sectionItem()->height());
9901007 }
9911008 }
9921009 }
@@ -1012,8 +1029,8 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
10121029// qDebug() << "ListViewWithPageHeader::onModelUpdated Change" << change.index << change.count;
10131030 for (int i = change.index; i < change.count; ++i) {
10141031 ListItem *item = itemAtIndex(i);
1015− if (item && item->m_sectionItem) {
1016− QQmlContext *context = QQmlEngine::contextForObject(item->m_sectionItem)->parentContext();
1032+ if (item && item->sectionItem()) {
1033+ QQmlContext *context = QQmlEngine::contextForObject(item->sectionItem())->parentContext();
10171034 const QString sectionText = m_delegateModel->stringValue(i, m_sectionProperty);
10181035 context->setContextProperty(QLatin1String("section"), sectionText);
10191036 }
@@ -1026,8 +1043,8 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
10261043
10271044 for (int i = 0; i < m_visibleItems.count(); ++i) {
10281045 ListItem *item = m_visibleItems[i];
1029− if (item->m_sectionItem) {
1030− QQmlContext *context = QQmlEngine::contextForObject(item->m_sectionItem)->parentContext();
1046+ if (item->sectionItem()) {
1047+ QQmlContext *context = QQmlEngine::contextForObject(item->sectionItem())->parentContext();
10311048 context->setContextProperty(QLatin1String("delegateIndex"), m_firstVisibleIndex + i);
10321049 }
10331050 }
@@ -1060,6 +1077,20 @@ void ListViewWithPageHeader::itemGeometryChanged(QQuickItem * /*item*/, const QR
10601077 }
10611078}
10621079
1080+void ListViewWithPageHeader::itemImplicitHeightChanged(QQuickItem *item)
1081+{
1082+ if (item == m_headerItem) {
1083+ const qreal diff = m_headerItem->implicitHeight() - m_previousHeaderImplicitHeight;
1084+ if (diff != 0) {
1085+ adjustHeader(diff);
1086+ m_previousHeaderImplicitHeight = m_headerItem->implicitHeight();
1087+ layout();
1088+ polish();
1089+ m_contentHeightDirty = true;
1090+ }
1091+ }
1092+}
1093+
10631094void ListViewWithPageHeader::headerHeightChanged(qreal newHeaderHeight, qreal oldHeaderHeight, qreal oldHeaderY)
10641095{
10651096 const qreal heightDiff = newHeaderHeight - oldHeaderHeight;
@@ -1156,18 +1187,18 @@ void ListViewWithPageHeader::layout()
11561187 if (topSectionStickPos > pos) {
11571188 showStickySectionItem = true;
11581189 } else if (topSectionStickPos == pos) {
1159− showStickySectionItem = !item->m_sectionItem;
1190+ showStickySectionItem = !item->sectionItem();
11601191 } else {
11611192 showStickySectionItem = false;
11621193 }
11631194 if (!showStickySectionItem) {
11641195 QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
1165− if (item->m_sectionItem) {
1196+ if (item->sectionItem()) {
11661197 // This seems it should happen since why would we cull the top section
11671198 // if the first visible item has no section header? This only happens briefly
11681199 // when increasing the height of a list that is at the bottom, the m_topSectionItem
11691200 // gets shown shortly in the next polish call
1170− QQuickItemPrivate::get(item->m_sectionItem)->setCulled(false);
1201+ QQuickItemPrivate::get(item->sectionItem())->setCulled(false);
11711202 }
11721203 } else {
11731204 // Update the top sticky section header
@@ -1186,14 +1217,14 @@ void ListViewWithPageHeader::layout()
11861217 delegateIndex--;
11871218 }
11881219 context->setContextProperty(QLatin1String("delegateIndex"), delegateIndex);
1189− if (item->m_sectionItem) {
1190− QQuickItemPrivate::get(item->m_sectionItem)->setCulled(true);
1220+ if (item->sectionItem()) {
1221+ QQuickItemPrivate::get(item->sectionItem())->setCulled(true);
11911222 }
11921223 }
11931224 }
11941225 }
11951226 QQmlContext *context = QQmlEngine::contextForObject(item->m_item)->parentContext();
1196− const qreal clipFrom = visibleFrom + (!item->m_sectionItem && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
1227+ const qreal clipFrom = visibleFrom + (!item->sectionItem() && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
11971228 if (!cull && pos < clipFrom) {
11981229 context->setContextProperty(QLatin1String("heightToClip"), clipFrom - pos);
11991230 } else {
@@ -1210,7 +1241,7 @@ void ListViewWithPageHeader::layout()
12101241 if (firstReallyVisibleItem >= 0) {
12111242 for (int i = firstReallyVisibleItem - m_firstVisibleIndex + 1; i < m_visibleItems.count(); ++i) {
12121243 ListItem *item = m_visibleItems[i];
1213− if (item->m_sectionItem) {
1244+ if (item->sectionItem()) {
12141245 if (m_topSectionItem->y() + m_topSectionItem->height() > item->y()) {
12151246 m_topSectionItem->setY(item->y() - m_topSectionItem->height());
12161247 }