on xenial help sign in
Improvements for headerless categories

LVPWH: No section name -> no header LVPWH: New hasSectionHeader context property for delegates GSV: Add topMargin if no hasSectionHeader

commitf481e940ee79adb1f90d03550c0527779e9dd95e authorAlbert Astals <albert.astals@canonical.com> dateThu 5 Jun 2014, 10:38 (12 years ago) parent6efb4eb
5 files changed+58−36
plugins/Dash/listviewwithpageheader.cpp+39−28 plugins/Dash/listviewwithpageheader.h+4 qml/Dash/GenericScopeView.qml+1 tests/plugins/Dash/listviewwithpageheadersectionexternalmodeltest.cpp+3−3 tests/plugins/Dash/listviewwithpageheadersectiontest.cpp+11−5
plugins/Dash/listviewwithpageheader.cpp+39−28
@@ -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)
@@ -422,7 +429,7 @@ bool ListViewWithPageHeader::maximizeVisibleArea(int modelIndex, int itemHeight)
422429
423430 ListItem *listItem = itemAtIndex(modelIndex);
424431 if (listItem) {
425− return maximizeVisibleArea(listItem, itemHeight + (listItem->m_sectionItem ? listItem->m_sectionItem->height() : 0));
432+ return maximizeVisibleArea(listItem, itemHeight + (listItem->sectionItem() ? listItem->sectionItem()->height() : 0));
426433 }
427434
428435 return false;
@@ -440,7 +447,7 @@ bool ListViewWithPageHeader::maximizeVisibleArea(ListItem *listItem, int listIte
440447 contentYAnimationType = ContentYAnimationMaximizeVisibleArea;
441448 m_contentYAnimation->start();
442449 } else if ((listItemY < contentY() && listItemY + listItemHeight < contentY() + height()) ||
443− (m_topSectionItem && !listItem->m_sectionItem && listItemY - m_topSectionItem->height() < contentY() && listItemY + listItemHeight < contentY() + height()))
450+ (m_topSectionItem && !listItem->sectionItem() && listItemY - m_topSectionItem->height() < contentY() && listItemY + listItemHeight < contentY() + height()))
444451 {
445452 // we can scroll the list down to show more stuff
446453 auto realVisibleListItemY = listItemY;
@@ -449,7 +456,7 @@ bool ListViewWithPageHeader::maximizeVisibleArea(ListItem *listItem, int listIte
449456 // item we have to make sure to scroll it a bit more so that it is not underlapping
450457 // the top section sticky item
451458 bool topSectionShown = !QQuickItemPrivate::get(m_topSectionItem)->culled;
452− if (topSectionShown && !listItem->m_sectionItem) {
459+ if (topSectionShown && !listItem->sectionItem()) {
453460 realVisibleListItemY -= m_topSectionItem->height();
454461 }
455462 }
@@ -645,7 +652,7 @@ void ListViewWithPageHeader::reallyReleaseItem(ListItem *listItem)
645652 if (flags & QQmlDelegateModel::Destroyed) {
646653 item->setParentItem(nullptr);
647654 }
648− delete listItem->m_sectionItem;
655+ delete listItem->sectionItem();
649656 delete listItem;
650657}
651658
@@ -672,6 +679,9 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyI
672679 return nullptr;
673680
674681 const QString section = m_delegateModel->stringValue(modelIndex, m_sectionProperty);
682+ if (section.isEmpty())
683+ return nullptr;
684+
675685 if (modelIndex > 0) {
676686 const QString prevSection = m_delegateModel->stringValue(modelIndex - 1, m_sectionProperty);
677687 if (section == prevSection)
@@ -684,8 +694,8 @@ QQuickItem *ListViewWithPageHeader::getSectionItem(int modelIndex, bool alreadyI
684694 // Steal the section header
685695 ListItem *nextItem = itemAtIndex(modelIndex); // Not +1 since not yet inserted into m_visibleItems
686696 if (nextItem) {
687− QQuickItem *sectionItem = nextItem->m_sectionItem;
688− nextItem->m_sectionItem = nullptr;
697+ QQuickItem *sectionItem = nextItem->sectionItem();
698+ nextItem->setSectionItem(nullptr);
689699 return sectionItem;
690700 }
691701 }
@@ -793,7 +803,7 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
793803// qDebug() << "ListViewWithPageHeader::createItem::We have the item" << modelIndex << item;
794804 ListItem *listItem = new ListItem;
795805 listItem->m_item = item;
796− listItem->m_sectionItem = getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/);
806+ listItem->setSectionItem(getSectionItem(modelIndex, false /*Not yet inserted into m_visibleItems*/));
797807 QQuickItemPrivate::get(item)->addItemChangeListener(this, QQuickItemPrivate::Geometry);
798808 ListItem *prevItem = itemAtIndex(modelIndex - 1);
799809 bool lostItem = false; // Is an item that we requested async but because of model changes
@@ -832,8 +842,8 @@ ListViewWithPageHeader::ListItem *ListViewWithPageHeader::createItem(int modelIn
832842 m_firstVisibleIndex = modelIndex;
833843 polish();
834844 }
835− if (listItem->m_sectionItem) {
836− QQmlContext *context = QQmlEngine::contextForObject(listItem->m_sectionItem)->parentContext();
845+ if (listItem->sectionItem()) {
846+ QQmlContext *context = QQmlEngine::contextForObject(listItem->sectionItem())->parentContext();
837847 context->setContextProperty(QLatin1String("delegateIndex"), modelIndex);
838848 }
839849 adjustMinYExtent();
@@ -861,6 +871,7 @@ void ListViewWithPageHeader::itemCreated(int modelIndex, QObject *object)
861871 QQmlContext *context = QQmlEngine::contextForObject(item)->parentContext();
862872 context->setContextProperty(QLatin1String("ListViewWithPageHeader"), this);
863873 context->setContextProperty(QLatin1String("heightToClip"), QVariant::fromValue<int>(0));
874+ context->setContextProperty(QLatin1String("hasSectionHeader"), QVariant::fromValue<bool>(false));
864875 if (modelIndex == m_asyncRequestedIndex) {
865876 createItem(modelIndex, false);
866877 refill();
@@ -915,11 +926,11 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
915926 if (visibleIndex >= 0 && visibleIndex < m_visibleItems.count()) {
916927 ListItem *item = m_visibleItems[visibleIndex];
917928 // Pass the section item down if needed
918− if (item->m_sectionItem && visibleIndex + 1 < m_visibleItems.count()) {
929+ if (item->sectionItem() && visibleIndex + 1 < m_visibleItems.count()) {
919930 ListItem *nextItem = m_visibleItems[visibleIndex + 1];
920− if (!nextItem->m_sectionItem) {
921− nextItem->m_sectionItem = item->m_sectionItem;
922− item->m_sectionItem = nullptr;
931+ if (!nextItem->sectionItem()) {
932+ nextItem->setSectionItem(item->sectionItem());
933+ item->setSectionItem(nullptr);
923934 }
924935 }
925936 releaseItem(item);
@@ -982,11 +993,11 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
982993 // if we need adding a new section item
983994 if (m_sectionDelegate) {
984995 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) {
996+ if (nextItem && !nextItem->sectionItem()) {
997+ nextItem->setSectionItem(getSectionItem(modelIndex + 1, true /* alredy inserted into m_visibleItems*/));
998+ if (growUp && nextItem->sectionItem()) {
988999 ListItem *firstItem = m_visibleItems.first();
989− firstItem->setY(firstItem->y() - nextItem->m_sectionItem->height());
1000+ firstItem->setY(firstItem->y() - nextItem->sectionItem()->height());
9901001 }
9911002 }
9921003 }
@@ -1012,8 +1023,8 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
10121023// qDebug() << "ListViewWithPageHeader::onModelUpdated Change" << change.index << change.count;
10131024 for (int i = change.index; i < change.count; ++i) {
10141025 ListItem *item = itemAtIndex(i);
1015− if (item && item->m_sectionItem) {
1016− QQmlContext *context = QQmlEngine::contextForObject(item->m_sectionItem)->parentContext();
1026+ if (item && item->sectionItem()) {
1027+ QQmlContext *context = QQmlEngine::contextForObject(item->sectionItem())->parentContext();
10171028 const QString sectionText = m_delegateModel->stringValue(i, m_sectionProperty);
10181029 context->setContextProperty(QLatin1String("section"), sectionText);
10191030 }
@@ -1026,8 +1037,8 @@ void ListViewWithPageHeader::onModelUpdated(const QQmlChangeSet &changeSet, bool
10261037
10271038 for (int i = 0; i < m_visibleItems.count(); ++i) {
10281039 ListItem *item = m_visibleItems[i];
1029− if (item->m_sectionItem) {
1030− QQmlContext *context = QQmlEngine::contextForObject(item->m_sectionItem)->parentContext();
1040+ if (item->sectionItem()) {
1041+ QQmlContext *context = QQmlEngine::contextForObject(item->sectionItem())->parentContext();
10311042 context->setContextProperty(QLatin1String("delegateIndex"), m_firstVisibleIndex + i);
10321043 }
10331044 }
@@ -1156,18 +1167,18 @@ void ListViewWithPageHeader::layout()
11561167 if (topSectionStickPos > pos) {
11571168 showStickySectionItem = true;
11581169 } else if (topSectionStickPos == pos) {
1159− showStickySectionItem = !item->m_sectionItem;
1170+ showStickySectionItem = !item->sectionItem();
11601171 } else {
11611172 showStickySectionItem = false;
11621173 }
11631174 if (!showStickySectionItem) {
11641175 QQuickItemPrivate::get(m_topSectionItem)->setCulled(true);
1165− if (item->m_sectionItem) {
1176+ if (item->sectionItem()) {
11661177 // This seems it should happen since why would we cull the top section
11671178 // if the first visible item has no section header? This only happens briefly
11681179 // when increasing the height of a list that is at the bottom, the m_topSectionItem
11691180 // gets shown shortly in the next polish call
1170− QQuickItemPrivate::get(item->m_sectionItem)->setCulled(false);
1181+ QQuickItemPrivate::get(item->sectionItem())->setCulled(false);
11711182 }
11721183 } else {
11731184 // Update the top sticky section header
@@ -1186,14 +1197,14 @@ void ListViewWithPageHeader::layout()
11861197 delegateIndex--;
11871198 }
11881199 context->setContextProperty(QLatin1String("delegateIndex"), delegateIndex);
1189− if (item->m_sectionItem) {
1190− QQuickItemPrivate::get(item->m_sectionItem)->setCulled(true);
1200+ if (item->sectionItem()) {
1201+ QQuickItemPrivate::get(item->sectionItem())->setCulled(true);
11911202 }
11921203 }
11931204 }
11941205 }
11951206 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);
1207+ const qreal clipFrom = visibleFrom + (!item->sectionItem() && m_topSectionItem && !QQuickItemPrivate::get(m_topSectionItem)->culled ? m_topSectionItem->height() : 0);
11971208 if (!cull && pos < clipFrom) {
11981209 context->setContextProperty(QLatin1String("heightToClip"), clipFrom - pos);
11991210 } else {
@@ -1210,7 +1221,7 @@ void ListViewWithPageHeader::layout()
12101221 if (firstReallyVisibleItem >= 0) {
12111222 for (int i = firstReallyVisibleItem - m_firstVisibleIndex + 1; i < m_visibleItems.count(); ++i) {
12121223 ListItem *item = m_visibleItems[i];
1213− if (item->m_sectionItem) {
1224+ if (item->sectionItem()) {
12141225 if (m_topSectionItem->y() + m_topSectionItem->height() > item->y()) {
12151226 m_topSectionItem->setY(item->y() - m_topSectionItem->height());
12161227 }
plugins/Dash/listviewwithpageheader.h+4
@@ -128,7 +128,11 @@ private:
128128 bool culled() const;
129129 void setCulled(bool culled);
130130
131+ QQuickItem *sectionItem() const { return m_sectionItem; }
132+ void setSectionItem(QQuickItem *sectionItem);
133+
131134 QQuickItem *m_item;
135+ private:
132136 QQuickItem *m_sectionItem;
133137 };
134138
qml/Dash/GenericScopeView.qml+1
@@ -141,6 +141,7 @@ FocusScope {
141141 top: parent.top
142142 left: parent.left
143143 right: parent.right
144+ topMargin: hasSectionHeader ? 0 : units.gu(2)
144145 }
145146
146147 source: {
tests/plugins/Dash/listviewwithpageheadersectionexternalmodeltest.cpp+3−3
@@ -82,10 +82,10 @@ private:
8282 QTRY_COMPARE(lvwph->m_visibleItems[visibleIndex]->y(), pos);
8383 QTRY_COMPARE(lvwph->m_visibleItems[visibleIndex]->height(), height);
8484 QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->m_item)->culled, culled);
85− QCOMPARE(section(lvwph->m_visibleItems[visibleIndex]->m_sectionItem), sectionHeader);
85+ QCOMPARE(section(lvwph->m_visibleItems[visibleIndex]->sectionItem()), sectionHeader);
8686 if (!sectionHeader.isNull()) {
87− QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->m_sectionItem)->culled, sectionHeaderCulled);
88− QCOMPARE(sectionDelegateIndex(lvwph->m_visibleItems[visibleIndex]->m_sectionItem), lvwph->m_firstVisibleIndex + visibleIndex);
87+ QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->sectionItem())->culled, sectionHeaderCulled);
88+ QCOMPARE(sectionDelegateIndex(lvwph->m_visibleItems[visibleIndex]->sectionItem()), lvwph->m_firstVisibleIndex + visibleIndex);
8989 }
9090 }
9191
tests/plugins/Dash/listviewwithpageheadersectiontest.cpp+11−5
@@ -39,10 +39,11 @@ private:
3939 QTRY_COMPARE(lvwph->m_visibleItems[visibleIndex]->y(), pos);
4040 QTRY_COMPARE(lvwph->m_visibleItems[visibleIndex]->height(), height);
4141 QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->m_item)->culled, culled);
42− QCOMPARE(section(lvwph->m_visibleItems[visibleIndex]->m_sectionItem), sectionHeader);
42+ QCOMPARE(section(lvwph->m_visibleItems[visibleIndex]->sectionItem()), sectionHeader);
43+ QTRY_COMPARE(hasSectionHeaderProperty(lvwph->m_visibleItems[visibleIndex]->m_item), !sectionHeader.isNull());
4344 if (!sectionHeader.isNull()) {
44− QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->m_sectionItem)->culled, sectionHeaderCulled);
45− QCOMPARE(sectionDelegateIndex(lvwph->m_visibleItems[visibleIndex]->m_sectionItem), lvwph->m_firstVisibleIndex + visibleIndex);
45+ QCOMPARE(QQuickItemPrivate::get(lvwph->m_visibleItems[visibleIndex]->sectionItem())->culled, sectionHeaderCulled);
46+ QCOMPARE(sectionDelegateIndex(lvwph->m_visibleItems[visibleIndex]->sectionItem()), lvwph->m_firstVisibleIndex + visibleIndex);
4647 }
4748 }
4849
@@ -109,12 +110,17 @@ private:
109110 QVERIFY(QQuickItemPrivate::get(lvwph->m_topSectionItem)->culled);
110111 }
111112
112− QString section(QQuickItem *item)
113+ bool hasSectionHeaderProperty(QQuickItem *item) const
114+ {
115+ return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("hasSectionHeader")).toBool() : false;
116+ }
117+
118+ QString section(QQuickItem *item) const
113119 {
114120 return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("section")).toString() : QString();
115121 }
116122
117− int sectionDelegateIndex(QQuickItem *item)
123+ int sectionDelegateIndex(QQuickItem *item) const
118124 {
119125 return item ? QQmlEngine::contextForObject(item)->parentContext()->contextProperty(QLatin1String("delegateIndex")).toInt() : -1;
120126 }