From 7e8d529d1542b3c581cff27641ba7b37b40ca161 Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Wed, 16 Dec 2009 17:34:38 +1000 Subject: Allow a ListView.section.delegate to avoid creating sections in delegate. --- examples/declarative/listview/sections.qml | 25 +++---- .../graphicsitems/qmlgraphicslistview.cpp | 84 ++++++++++++++++++---- .../graphicsitems/qmlgraphicslistview_p.h | 8 ++- 3 files changed, 88 insertions(+), 29 deletions(-) diff --git a/examples/declarative/listview/sections.qml b/examples/declarative/listview/sections.qml index b51cf58..6e72ce7 100644 --- a/examples/declarative/listview/sections.qml +++ b/examples/declarative/listview/sections.qml @@ -17,25 +17,11 @@ Rectangle { id: wrapper width: 200 // My height is the combined height of the description and the section separator - height: separator.height + desc.height - Rectangle { - id: separator - color: "lightsteelblue" - width: parent.width - // Only show the section separator when we are the beginning of a new section - // Note that for this to work nicely, the list must be ordered by section. - height: wrapper.ListView.prevSection != wrapper.ListView.section ? 20 : 0 - opacity: wrapper.ListView.prevSection != wrapper.ListView.section ? 1 : 0 - Text { - text: wrapper.ListView.section; font.bold: true - x: 2; height: parent.height; verticalAlignment: 'AlignVCenter' - } - } + height: desc.height Item { id: desc x: 5 height: layout.height + 4 - anchors.top: separator.bottom Column { id: layout y: 2 @@ -66,6 +52,15 @@ Rectangle { // We use this to determine which section we are in above. section.property: "size" section.criteria: ViewSection.FullString + section.delegate: Rectangle { + color: "lightsteelblue" + width: 200 + height: 20 + Text { + text: section; font.bold: true + x: 2; height: parent.height; verticalAlignment: 'AlignVCenter' + } + } focus: true } } diff --git a/src/declarative/graphicsitems/qmlgraphicslistview.cpp b/src/declarative/graphicsitems/qmlgraphicslistview.cpp index bf734b8..77761ac 100644 --- a/src/declarative/graphicsitems/qmlgraphicslistview.cpp +++ b/src/declarative/graphicsitems/qmlgraphicslistview.cpp @@ -68,6 +68,14 @@ void QmlGraphicsViewSection::setCriteria(QmlGraphicsViewSection::SectionCriteria } } +void QmlGraphicsViewSection::setDelegate(QmlComponent *delegate) +{ + if (delegate != m_delegate) { + m_delegate = delegate; + emit delegateChanged(); + } +} + QString QmlGraphicsViewSection::sectionString(const QString &value) { if (m_criteria == FirstCharacter) @@ -162,14 +170,23 @@ QHash QmlGraphicsListViewAttached::attac class FxListItem { public: - FxListItem(QmlGraphicsItem *i, QmlGraphicsListView *v) : item(i), view(v) { + FxListItem(QmlGraphicsItem *i, QmlGraphicsListView *v) : item(i), section(0), view(v) { attached = QmlGraphicsListViewAttached::properties(item); attached->m_view = view; } ~FxListItem() {} - - qreal position() const { return (view->orientation() == QmlGraphicsListView::Vertical ? item->y() : item->x()); } - int size() const { return (view->orientation() == QmlGraphicsListView::Vertical ? item->height() : item->width()); } + qreal position() const { + if (section) + return (view->orientation() == QmlGraphicsListView::Vertical ? section->y() : section->x()); + else + return (view->orientation() == QmlGraphicsListView::Vertical ? item->y() : item->x()); + } + int size() const { + if (section) + return (view->orientation() == QmlGraphicsListView::Vertical ? item->height()+section->height() : item->width()+section->height()); + else + return (view->orientation() == QmlGraphicsListView::Vertical ? item->height() : item->width()); + } qreal endPosition() const { return (view->orientation() == QmlGraphicsListView::Vertical ? item->y() + (item->height() > 0 ? item->height() : 1) @@ -177,13 +194,22 @@ public: } void setPosition(qreal pos) { if (view->orientation() == QmlGraphicsListView::Vertical) { + if (section) { + section->setY(pos); + pos += section->height(); + } item->setY(pos); } else { + if (section) { + section->setX(pos); + pos += section->width(); + } item->setX(pos); } } QmlGraphicsItem *item; + QmlGraphicsItem *section; QmlGraphicsListView *view; QmlGraphicsListViewAttached *attached; int index; @@ -467,6 +493,7 @@ public: void updateTrackedItem(); void createHighlight(); void updateHighlight(); + void createSection(FxListItem *); void updateSections(); void updateCurrentSection(); void updateCurrent(int); @@ -573,6 +600,11 @@ FxListItem *QmlGraphicsListViewPrivate::createItem(int modelIndex) listItem->item->setParent(q->viewport()); QmlGraphicsItemPrivate *itemPrivate = static_cast(QGraphicsItemPrivate::get(item)); itemPrivate->addGeometryListener(this); + if (sectionCriteria && sectionCriteria->delegate()) { + qDebug() << "have delegate"; + if (listItem->attached->m_prevSection != listItem->attached->m_section) + createSection(listItem); + } } requestedIndex = -1; @@ -597,6 +629,8 @@ void QmlGraphicsListViewPrivate::releaseItem(FxListItem *item) // item was not destroyed, and we no longer reference it. unrequestedItems.insert(item->item, model->indexOf(item->item, q)); } + if (item->section) + delete item->section; delete item; } @@ -693,6 +727,7 @@ void QmlGraphicsListViewPrivate::refill(qreal from, qreal to, bool doBuffer) void QmlGraphicsListViewPrivate::layout() { Q_Q(QmlGraphicsListView); + updateSections(); if (!visibleItems.isEmpty()) { int oldEnd = visibleItems.last()->endPosition(); int pos = visibleItems.first()->endPosition() + spacing + 1; @@ -842,6 +877,36 @@ void QmlGraphicsListViewPrivate::updateHighlight() updateTrackedItem(); } +void QmlGraphicsListViewPrivate::createSection(FxListItem *listItem) +{ + Q_Q(QmlGraphicsListView); + if (!sectionCriteria || !sectionCriteria->delegate()) + return; + if (listItem->attached->m_prevSection != listItem->attached->m_section) { + if (!listItem->section) { + qDebug() << "create Section"; + QmlContext *context = new QmlContext(qmlContext(q)); + QObject *nobj = sectionCriteria->delegate()->create(context); + if (nobj) { + context->setParent(nobj); + listItem->section = qobject_cast(nobj); + if (!listItem->section) { + delete nobj; + } else { + context->setContextProperty(QLatin1String("section"), listItem->attached->m_section); + listItem->section->setZValue(1); + listItem->section->setParent(q->viewport()); + } + } else { + delete context; + } + } + } else { + delete listItem->section; + listItem->section = 0; + } +} + void QmlGraphicsListViewPrivate::updateSections() { if (sectionCriteria) { @@ -852,6 +917,7 @@ void QmlGraphicsListViewPrivate::updateSections() if (visibleItems.at(i)->index != -1) { QmlGraphicsListViewAttached *attached = visibleItems.at(i)->attached; attached->setPrevSection(prevSection); + createSection(visibleItems.at(i)); prevSection = attached->section(); } } @@ -2240,7 +2306,6 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) d->updateUnrequestedIndexes(); if (!d->visibleItems.count() || d->model->count() <= 1) { d->layout(); - d->updateSections(); d->updateCurrent(qMax(0, qMin(d->currentIndex, d->model->count()-1))); emit countChanged(); return; @@ -2351,11 +2416,7 @@ void QmlGraphicsListView::itemsInserted(int modelIndex, int count) // everything is in order now - emit add() signal for (int j = 0; j < added.count(); ++j) added.at(j)->attached->emitAdd(); - d->updateUnrequestedPositions(); - d->updateViewport(); - d->updateSections(); - d->updateHeader(); - d->updateFooter(); + d->layout(); emit countChanged(); } @@ -2386,7 +2447,6 @@ void QmlGraphicsListView::itemsRemoved(int modelIndex, int count) d->updateCurrent(qMin(modelIndex, d->model->count()-1)); } d->layout(); - d->updateSections(); emit countChanged(); return; } @@ -2459,7 +2519,6 @@ void QmlGraphicsListView::itemsRemoved(int modelIndex, int count) } else { // Correct the positioning of the items d->layout(); - d->updateSections(); } emit countChanged(); @@ -2557,7 +2616,6 @@ void QmlGraphicsListView::itemsMoved(int from, int to, int count) d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + moveBy); d->layout(); - d->updateSections(); } void QmlGraphicsListView::createdItem(int index, QmlGraphicsItem *item) diff --git a/src/declarative/graphicsitems/qmlgraphicslistview_p.h b/src/declarative/graphicsitems/qmlgraphicslistview_p.h index 18b2ab5..2a2ef8a 100644 --- a/src/declarative/graphicsitems/qmlgraphicslistview_p.h +++ b/src/declarative/graphicsitems/qmlgraphicslistview_p.h @@ -55,9 +55,10 @@ class Q_DECLARATIVE_EXPORT QmlGraphicsViewSection : public QObject Q_OBJECT Q_PROPERTY(QString property READ property WRITE setProperty NOTIFY changed) Q_PROPERTY(SectionCriteria criteria READ criteria WRITE setCriteria NOTIFY changed) + Q_PROPERTY(QmlComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged) Q_ENUMS(SectionCriteria) public: - QmlGraphicsViewSection(QObject *parent=0) : QObject(parent), m_criteria(FullString) {} + QmlGraphicsViewSection(QObject *parent=0) : QObject(parent), m_criteria(FullString), m_delegate(0) {} QString property() const { return m_property; } void setProperty(const QString &); @@ -66,14 +67,19 @@ public: SectionCriteria criteria() const { return m_criteria; } void setCriteria(SectionCriteria); + QmlComponent *delegate() const { return m_delegate; } + void setDelegate(QmlComponent *delegate); + QString sectionString(const QString &value); Q_SIGNALS: void changed(); + void delegateChanged(); private: QString m_property; SectionCriteria m_criteria; + QmlComponent *m_delegate; }; -- cgit v0.12