From a46312b3b5f97802b8a74e53a86ce4a57df320ef Mon Sep 17 00:00:00 2001 From: Martin Jones Date: Thu, 29 Aug 2013 07:48:29 +0000 Subject: Add displayMarginBeginning/End to ListView and GridView. This allows displaying content outside the visible area of the view. [ChangeLog][QtQuick] Add displayMarginBeginning/End to ListView and GridView. Change-Id: Idf9b5a0cd34a781c9603a9ad98ea189754972ba1 Reviewed-by: Alan Alpert (Personal) <416365416c@gmail.com> --- src/quick/items/qquickgridview.cpp | 40 +++++++++++++++++++++++++++++------ src/quick/items/qquickitemsmodule.cpp | 1 + src/quick/items/qquickitemview.cpp | 40 +++++++++++++++++++++++++++++++++-- src/quick/items/qquickitemview_p.h | 10 +++++++++ src/quick/items/qquickitemview_p_p.h | 2 ++ src/quick/items/qquicklistview.cpp | 39 ++++++++++++++++++++++++++++------ 6 files changed, 117 insertions(+), 15 deletions(-) (limited to 'src/quick') diff --git a/src/quick/items/qquickgridview.cpp b/src/quick/items/qquickgridview.cpp index c9e6d4d7e2..43eb9ff6be 100644 --- a/src/quick/items/qquickgridview.cpp +++ b/src/quick/items/qquickgridview.cpp @@ -630,8 +630,8 @@ void QQuickGridViewPrivate::updateViewport() void QQuickGridViewPrivate::layoutVisibleItems(int fromModelIndex) { if (visibleItems.count()) { - const qreal from = isContentFlowReversed() ? -position() - size() : position(); - const qreal to = isContentFlowReversed() ? -position() : position() + size(); + const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning; + const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd; FxGridItemSG *firstItem = static_cast(visibleItems.first()); qreal rowPos = firstItem->rowPos(); @@ -1534,7 +1534,35 @@ void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight) of additional memory usage. It is not a substitute for creating efficient delegates; the fewer objects and bindings in a delegate, the faster a view may be scrolled. + + The cacheBuffer operates outside of any display margins specified by + displayMarginBeginning or displayMarginEnd. +*/ + +/*! + \qmlproperty int QtQuick::GridView::displayMarginBeginning + \qmlproperty int QtQuick::GridView::displayMarginEnd + \since QtQuick 2.3 + + This property allows delegates to be displayed outside of the view geometry. + + If this value is non-zero, the view will create extra delegates before the + start of the view, or after the end. The view will create as many delegates + as it can fit into the pixel size specified. + + For example, if in a vertical view the delegate is 20 pixels high, + there are 3 columns, and + \c displayMarginBeginning and \c displayMarginEnd are both set to 40, + then 6 delegates above and 6 delegates below will be created and shown. + + The default value is 0. + + This property is meant for allowing certain UI configurations, + and not as a performance optimization. If you wish to create delegates + outside of the view geometry for performance reasons, you probably + want to use the cacheBuffer property instead. */ + void QQuickGridView::setHighlightMoveDuration(int duration) { Q_D(QQuickGridView); @@ -2000,8 +2028,8 @@ void QQuickGridView::viewportMoved(Qt::Orientations orient) d->refillOrLayout(); // Set visibility of items to eliminate cost of items outside the visible area. - qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position(); - qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size(); + qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning; + qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd; for (int i = 0; i < d->visibleItems.count(); ++i) { FxGridItemSG *item = static_cast(d->visibleItems.at(i)); QQuickItemPrivate::get(item->item)->setCulled(item->rowPos() + d->rowSize() < from || item->rowPos() > to); @@ -2350,7 +2378,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch // Insert items before the visible item. int insertionIdx = index; int i = count - 1; - int from = tempPos - buffer; + int from = tempPos - buffer - displayMarginBeginning; while (i >= 0) { if (rowPos > from && insertionIdx < visibleIndex) { @@ -2387,7 +2415,7 @@ bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch } } else { int i = 0; - int to = buffer+tempPos+size()-1; + int to = buffer+displayMarginEnd+tempPos+size()-1; while (i < count && rowPos <= to + rowSize()*(columns - colNum)/qreal(columns+1)) { FxViewItem *item = 0; if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) diff --git a/src/quick/items/qquickitemsmodule.cpp b/src/quick/items/qquickitemsmodule.cpp index a5b78b28e1..8b2b5d4fc8 100644 --- a/src/quick/items/qquickitemsmodule.cpp +++ b/src/quick/items/qquickitemsmodule.cpp @@ -261,6 +261,7 @@ static void qt_quickitems_defineModule(const char *uri, int major, int minor) qmlRegisterType(uri, 2, 1,"Item"); qmlRegisterType(uri, 2, 1, "Grid"); qmlRegisterUncreatableType(uri, 2, 1, "ItemView", QQuickItemView::tr("ItemView is an abstract base class")); + qmlRegisterUncreatableType(uri, 2, 3, "ItemView", QQuickItemView::tr("ItemView is an abstract base class")); qmlRegisterType(uri, 2, 1, "ListView"); qmlRegisterType(uri, 2, 1, "GridView"); qmlRegisterType(uri, 2, 1, "TextEdit"); diff --git a/src/quick/items/qquickitemview.cpp b/src/quick/items/qquickitemview.cpp index d9ff024d9f..6d4c2e7877 100644 --- a/src/quick/items/qquickitemview.cpp +++ b/src/quick/items/qquickitemview.cpp @@ -459,6 +459,41 @@ void QQuickItemView::setCacheBuffer(int b) } } +int QQuickItemView::displayMarginBeginning() const +{ + Q_D(const QQuickItemView); + return d->displayMarginBeginning; +} + +void QQuickItemView::setDisplayMarginBeginning(int margin) +{ + Q_D(QQuickItemView); + if (d->displayMarginBeginning != margin) { + d->displayMarginBeginning = margin; + if (isComponentComplete()) { + d->refillOrLayout(); + } + emit displayMarginBeginningChanged(); + } +} + +int QQuickItemView::displayMarginEnd() const +{ + Q_D(const QQuickItemView); + return d->displayMarginEnd; +} + +void QQuickItemView::setDisplayMarginEnd(int margin) +{ + Q_D(QQuickItemView); + if (d->displayMarginEnd != margin) { + d->displayMarginEnd = margin; + if (isComponentComplete()) { + d->refillOrLayout(); + } + emit displayMarginEndChanged(); + } +} Qt::LayoutDirection QQuickItemView::layoutDirection() const { @@ -1443,6 +1478,7 @@ void QQuickItemView::componentComplete() QQuickItemViewPrivate::QQuickItemViewPrivate() : itemCount(0) , buffer(QML_VIEW_DEFAULTCACHEBUFFER), bufferMode(BufferBefore | BufferAfter) + , displayMarginBeginning(0), displayMarginEnd(0) , layoutDirection(Qt::LeftToRight), verticalLayoutDirection(QQuickItemView::TopToBottom) , moveReason(Other) , visibleIndex(0) @@ -1682,9 +1718,9 @@ void QQuickItemViewPrivate::refill() { qreal s = qMax(size(), qreal(0.)); if (isContentFlowReversed()) - refill(-position()-s, -position()); + refill(-position()-displayMarginBeginning-s, -position()+displayMarginEnd); else - refill(position(), position()+s); + refill(position()-displayMarginBeginning, position()+displayMarginEnd+s); } void QQuickItemViewPrivate::refill(qreal from, qreal to) diff --git a/src/quick/items/qquickitemview_p.h b/src/quick/items/qquickitemview_p.h index 318f5361b5..5931d6c09e 100644 --- a/src/quick/items/qquickitemview_p.h +++ b/src/quick/items/qquickitemview_p.h @@ -63,6 +63,8 @@ class Q_AUTOTEST_EXPORT QQuickItemView : public QQuickFlickable Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged) Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged) + Q_PROPERTY(int displayMarginBeginning READ displayMarginBeginning WRITE setDisplayMarginBeginning NOTIFY displayMarginBeginningChanged REVISION 2) + Q_PROPERTY(int displayMarginEnd READ displayMarginEnd WRITE setDisplayMarginEnd NOTIFY displayMarginEndChanged REVISION 2) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged) @@ -133,6 +135,12 @@ public: int cacheBuffer() const; void setCacheBuffer(int); + int displayMarginBeginning() const; + void setDisplayMarginBeginning(int); + + int displayMarginEnd() const; + void setDisplayMarginEnd(int); + Qt::LayoutDirection layoutDirection() const; void setLayoutDirection(Qt::LayoutDirection); Qt::LayoutDirection effectiveLayoutDirection() const; @@ -218,6 +226,8 @@ Q_SIGNALS: void keyNavigationWrapsChanged(); void cacheBufferChanged(); + void displayMarginBeginningChanged(); + void displayMarginEndChanged(); void layoutDirectionChanged(); void effectiveLayoutDirectionChanged(); diff --git a/src/quick/items/qquickitemview_p_p.h b/src/quick/items/qquickitemview_p_p.h index c528fa3b2c..bb1b7927c2 100644 --- a/src/quick/items/qquickitemview_p_p.h +++ b/src/quick/items/qquickitemview_p_p.h @@ -256,6 +256,8 @@ public: int itemCount; int buffer; int bufferMode; + int displayMarginBeginning; + int displayMarginEnd; Qt::LayoutDirection layoutDirection; QQuickItemView::VerticalLayoutDirection verticalLayoutDirection; diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp index c55f9ef696..7f6c7fdbb9 100644 --- a/src/quick/items/qquicklistview.cpp +++ b/src/quick/items/qquicklistview.cpp @@ -774,8 +774,8 @@ void QQuickListViewPrivate::visibleItemsChanged() void QQuickListViewPrivate::layoutVisibleItems(int fromModelIndex) { if (!visibleItems.isEmpty()) { - const qreal from = isContentFlowReversed() ? -position() - size() : position(); - const qreal to = isContentFlowReversed() ? -position() : position() + size(); + const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning; + const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd; FxViewItem *firstItem = *visibleItems.constBegin(); bool fixedCurrent = currentItem && firstItem->item == currentItem->item; @@ -2126,8 +2126,33 @@ void QQuickListView::setOrientation(QQuickListView::Orientation orientation) of additional memory usage. It is not a substitute for creating efficient delegates; the fewer objects and bindings in a delegate, the faster a view can be scrolled. + + The cacheBuffer operates outside of any display margins specified by + displayMarginBeginning or displayMarginEnd. */ +/*! + \qmlproperty int QtQuick::ListView::displayMarginBeginning + \qmlproperty int QtQuick::ListView::displayMarginEnd + \since QtQuick 2.3 + + This property allows delegates to be displayed outside of the view geometry. + + If this value is non-zero, the view will create extra delegates before the + start of the view, or after the end. The view will create as many delegates + as it can fit into the pixel size specified. + + For example, if in a vertical view the delegate is 20 pixels high and + \c displayMarginBeginning and \c displayMarginEnd are both set to 40, + then 2 delegates above and 2 delegates below will be created and shown. + + The default value is 0. + + This property is meant for allowing certain UI configurations, + and not as a performance optimization. If you wish to create delegates + outside of the view geometry for performance reasons, you probably + want to use the cacheBuffer property instead. +*/ /*! \qmlproperty string QtQuick::ListView::section.property @@ -2679,8 +2704,8 @@ void QQuickListView::viewportMoved(Qt::Orientations orient) d->refillOrLayout(); // Set visibility of items to eliminate cost of items outside the visible area. - qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position(); - qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size(); + qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning; + qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd; for (int i = 0; i < d->visibleItems.count(); ++i) { FxViewItem *item = static_cast(d->visibleItems.at(i)); QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to); @@ -2886,7 +2911,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch // there are no visible items except items marked for removal index = visibleItems.count(); } else if (visibleItems.at(i)->index + 1 == modelIndex - && visibleItems.at(i)->endPosition() <= buffer+tempPos+size()) { + && visibleItems.at(i)->endPosition() <= buffer+displayMarginEnd+tempPos+size()) { // Special case of appending an item to the model. index = visibleItems.count(); } else { @@ -2915,7 +2940,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch // Insert items before the visible item. int insertionIdx = index; int i = 0; - int from = tempPos - buffer; + int from = tempPos - displayMarginBeginning - buffer; for (i = count-1; i >= 0; --i) { if (pos > from && insertionIdx < visibleIndex) { @@ -2946,7 +2971,7 @@ bool QQuickListViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &ch } } else { int i = 0; - int to = buffer+tempPos+size(); + int to = buffer+displayMarginEnd+tempPos+size(); for (i = 0; i < count && pos <= to; ++i) { FxViewItem *item = 0; if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) -- cgit v1.2.3