virtual Qt::Orientation layoutOrientation() const;
virtual bool isContentFlowReversed() const;
bool isRightToLeft() const;
+ bool isBottomToTop() const;
virtual qreal positionAt(int index) const;
virtual qreal endPositionAt(int index) const;
virtual void init();
virtual void clear();
- virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer);
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer);
virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
virtual void visibleItemsChanged();
virtual bool applyInsertionChange(const QQuickChangeSet::Insert &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView);
virtual void translateAndTransitionItemsAfter(int afterIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult);
+ virtual void updateSectionCriteria();
virtual void updateSections();
QQuickItem *getSectionItem(const QString §ion);
void releaseSectionItem(QQuickItem *item);
+ void releaseSectionItems();
void updateInlineSection(FxListItemSG *);
void updateCurrentSection();
void updateStickySections();
void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
virtual void fixupPosition();
virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
- virtual void flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ virtual bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
QQuickTimeLineCallback::Callback fixupCallback, qreal velocity);
QQuickListView::Orientation orient;
QSmoothedAnimation *highlightPosAnimator;
QSmoothedAnimation *highlightSizeAnimator;
- qreal highlightMoveSpeed;
- qreal highlightResizeSpeed;
+ qreal highlightMoveVelocity;
+ qreal highlightResizeVelocity;
int highlightResizeDuration;
QQuickViewSection *sectionCriteria;
, averageSize(100.0), spacing(0.0)
, snapMode(QQuickListView::NoSnap)
, highlightPosAnimator(0), highlightSizeAnimator(0)
- , highlightMoveSpeed(400), highlightResizeSpeed(400), highlightResizeDuration(-1)
+ , highlightMoveVelocity(400), highlightResizeVelocity(400), highlightResizeDuration(-1)
, sectionCriteria(0), currentSectionItem(0), nextSectionItem(0)
, overshootDist(0.0), correctFlick(false), inFlickCorrection(false)
{}
if (property != m_property) {
m_property = property;
emit propertyChanged();
- m_view->updateSections();
+ // notify view that the contents of the sections must be recalculated
+ m_view->updateSectionCriteria();
}
}
if (criteria != m_criteria) {
m_criteria = criteria;
emit criteriaChanged();
- m_view->updateSections();
+ // notify view that the contents of the sections must be recalculated
+ m_view->updateSectionCriteria();
}
}
void QQuickViewSection::setDelegate(QQmlComponent *delegate)
{
if (delegate != m_delegate) {
+ if (m_delegate)
+ m_view->releaseSectionItems();
m_delegate = delegate;
emit delegateChanged();
- m_view->updateSections();
+ m_view->forceLayoutPolish();
}
}
if (m_labelPositioning != l) {
m_labelPositioning = l;
emit labelPositioningChanged();
- m_view->updateSections();
+ m_view->forceLayoutPolish();
}
}
class FxListItemSG : public FxViewItem
{
public:
- FxListItemSG(QQuickItem *i, QQuickListView *v, bool own) : FxViewItem(i, own), view(v) {
+ FxListItemSG(QQuickItem *i, QQuickListView *v, bool own, bool trackGeometry) : FxViewItem(i, own, trackGeometry), view(v) {
attached = static_cast<QQuickListViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(item));
- if (attached)
- static_cast<QQuickListViewAttached*>(attached)->setView(view);
+ if (trackGeometry) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ }
}
- ~FxListItemSG() {}
+ ~FxListItemSG() {
+ if (trackGeom) {
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
+ }
+ }
inline QQuickItem *section() const {
return attached ? static_cast<QQuickListViewAttached*>(attached)->m_sectionItem : 0;
qreal position() const {
if (section()) {
if (view->orientation() == QQuickListView::Vertical)
- return section()->y();
+ return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -section()->height()-section()->y() : section()->y());
else
return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -section()->width()-section()->x() : section()->x());
} else {
}
qreal itemPosition() const {
if (view->orientation() == QQuickListView::Vertical)
- return itemY();
+ return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -item->height()-itemY() : itemY());
else
return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -item->width()-itemX() : itemX());
}
}
qreal endPosition() const {
if (view->orientation() == QQuickListView::Vertical) {
- return itemY() + item->height();
+ return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop
+ ? -itemY()
+ : itemY() + item->height());
} else {
return (view->effectiveLayoutDirection() == Qt::RightToLeft
? -itemX()
: itemX() + item->width());
}
}
- void setPosition(qreal pos) {
+ void setPosition(qreal pos, bool immediate = false) {
// position the section immediately even if there is a transition
if (section()) {
if (view->orientation() == QQuickListView::Vertical) {
- section()->setY(pos);
+ if (view->verticalLayoutDirection() == QQuickItemView::BottomToTop)
+ section()->setY(-section()->height()-pos);
+ else
+ section()->setY(pos);
} else {
if (view->effectiveLayoutDirection() == Qt::RightToLeft)
section()->setX(-section()->width()-pos);
section()->setX(pos);
}
}
- moveTo(pointForPosition(pos));
+ moveTo(pointForPosition(pos), immediate);
}
void setSize(qreal size) {
if (view->orientation() == QQuickListView::Vertical)
private:
QPointF pointForPosition(qreal pos) const {
if (view->orientation() == QQuickListView::Vertical) {
- if (section())
- pos += section()->height();
- return QPointF(itemX(), pos);
+ if (view->verticalLayoutDirection() == QQuickItemView::BottomToTop) {
+ if (section())
+ pos += section()->height();
+ return QPointF(itemX(), -item->height() - pos);
+ } else {
+ if (section())
+ pos += section()->height();
+ return QPointF(itemX(), pos);
+ }
} else {
if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
if (section())
bool QQuickListViewPrivate::isContentFlowReversed() const
{
- return isRightToLeft();
+ return isRightToLeft() || isBottomToTop();
}
Qt::Orientation QQuickListViewPrivate::layoutOrientation() const
return orient == QQuickListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft;
}
+bool QQuickListViewPrivate::isBottomToTop() const
+{
+ return orient == QQuickListView::Vertical && verticalLayoutDirection == QQuickItemView::BottomToTop;
+}
+
// Returns the item before modelIndex, if created.
// May return an item marked for removal.
FxViewItem *QQuickListViewPrivate::itemBefore(int modelIndex) const
{
Q_Q(QQuickListView);
if (orient == QQuickListView::Vertical) {
- q->QQuickFlickable::setContentY(pos);
+ if (isBottomToTop())
+ q->QQuickFlickable::setContentY(-pos-size());
+ else
+ q->QQuickFlickable::setContentY(pos);
} else {
if (isRightToLeft())
q->QQuickFlickable::setContentX(-pos-size());
sectionCache[i] = 0;
}
visiblePos = 0;
+ releaseSectionItem(currentSectionItem);
currentSectionItem = 0;
+ releaseSectionItem(nextSectionItem);
nextSectionItem = 0;
lastVisibleSection = QString();
QQuickItemViewPrivate::clear();
{
Q_Q(QQuickListView);
- FxListItemSG *listItem = new FxListItemSG(item, q, false);
+ FxListItemSG *listItem = new FxListItemSG(item, q, false, false);
listItem->index = modelIndex;
// initialise attached properties
if (sectionCriteria) {
QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
- listItem->attached->m_section = sectionCriteria->sectionString(propValue);
+ listItem->attached->setSection(sectionCriteria->sectionString(propValue));
if (modelIndex > 0) {
if (FxViewItem *item = itemBefore(modelIndex))
- listItem->attached->m_prevSection = item->attached->section();
+ listItem->attached->setPrevSection(item->attached->section());
else
- listItem->attached->m_prevSection = sectionAt(modelIndex-1);
+ listItem->attached->setPrevSection(sectionAt(modelIndex-1));
}
if (modelIndex < model->count()-1) {
if (FxViewItem *item = visibleItem(modelIndex+1))
- listItem->attached->m_nextSection = static_cast<QQuickListViewAttached*>(item->attached)->section();
+ listItem->attached->setNextSection(static_cast<QQuickListViewAttached*>(item->attached)->section());
else
- listItem->attached->m_nextSection = sectionAt(modelIndex+1);
+ listItem->attached->setNextSection(sectionAt(modelIndex+1));
}
}
itemPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry);
if (sectionCriteria && sectionCriteria->delegate()) {
- if (item->attached->m_prevSection != item->attached->m_section)
+ if (QString::compare(item->attached->m_prevSection, item->attached->m_section, Qt::CaseInsensitive))
updateInlineSection(static_cast<FxListItemSG*>(item));
}
}
return released;
}
-bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer)
+bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer)
{
qreal itemEnd = visiblePos;
if (visibleItems.count()) {
bool haveValidItems = modelIndex >= 0;
modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
- if (haveValidItems && (fillFrom > itemEnd+averageSize+spacing
- || fillTo < visiblePos - averageSize - spacing)) {
+ if (haveValidItems && (bufferFrom > itemEnd+averageSize+spacing
+ || bufferTo < visiblePos - averageSize - spacing)) {
// We've jumped more than a page. Estimate which items are now
// visible and fill from there.
int count = (fillFrom - itemEnd) / (averageSize + spacing);
- for (int i = 0; i < visibleItems.count(); ++i)
- releaseItem(visibleItems.at(i));
- visibleItems.clear();
- modelIndex += count;
- if (modelIndex >= model->count()) {
- count -= modelIndex - model->count() + 1;
- modelIndex = model->count() - 1;
- } else if (modelIndex < 0) {
- count -= modelIndex;
- modelIndex = 0;
- }
- visibleIndex = modelIndex;
- visiblePos = itemEnd + count * (averageSize + spacing);
- itemEnd = visiblePos;
+ int newModelIdx = qBound(0, modelIndex + count, model->count());
+ count = newModelIdx - modelIndex;
+ if (count) {
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ modelIndex = newModelIdx;
+ visibleIndex = modelIndex;
+ visiblePos = itemEnd + count * (averageSize + spacing);
+ itemEnd = visiblePos;
+ }
}
bool changed = false;
qreal pos = itemEnd;
while (modelIndex < model->count() && pos <= fillTo) {
#ifdef DEBUG_DELEGATE_LIFECYCLE
- qDebug() << "refill: append item" << modelIndex << "pos" << pos;
+ qDebug() << "refill: append item" << modelIndex << "pos" << pos << "buffer" << doBuffer;
#endif
if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex, doBuffer))))
break;
if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
- item->setPosition(pos);
- item->item->setVisible(!doBuffer);
+ item->setPosition(pos, true);
+ QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
pos += item->size() + spacing;
visibleItems.append(item);
++modelIndex;
while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos > fillFrom) {
#ifdef DEBUG_DELEGATE_LIFECYCLE
- qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
+ qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos << "buffer" << doBuffer;
#endif
if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1, doBuffer))))
break;
--visibleIndex;
visiblePos -= item->size() + spacing;
if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
- item->setPosition(visiblePos);
- item->item->setVisible(!doBuffer);
+ item->setPosition(visiblePos, true);
+ QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
visibleItems.prepend(item);
changed = true;
}
bool fixedCurrent = currentItem && firstItem->item == currentItem->item;
qreal sum = firstItem->size();
qreal pos = firstItem->position() + firstItem->size() + spacing;
- firstItem->item->setVisible(firstItem->endPosition() >= from && firstItem->position() <= to);
+ firstItem->setVisible(firstItem->endPosition() >= from && firstItem->position() <= to);
for (int i=1; i < visibleItems.count(); ++i) {
FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.at(i));
// move current item if it is not a visible item.
if (currentIndex >= 0 && currentItem && !fixedCurrent)
static_cast<FxListItemSG*>(currentItem)->setPosition(positionAt(currentIndex));
+
+ updateCurrentSection();
+ updateStickySections();
}
}
Q_Q(QQuickListView);
qreal pos = position();
if (orient == QQuickListView::Vertical) {
- if (item->y() + item->height() > pos && item->y() < pos + q->height())
- item->setY(positionAt(index));
+ if (item->y() + item->height() > pos && item->y() < pos + q->height()) {
+ if (isBottomToTop())
+ item->setY(-positionAt(index)-item->height());
+ else
+ item->setY(positionAt(index));
+ }
} else {
if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
if (isRightToLeft())
if (currentItem) {
QQuickItem *item = createHighlightItem();
if (item) {
- FxListItemSG *newHighlight = new FxListItemSG(item, q, true);
+ FxListItemSG *newHighlight = new FxListItemSG(item, q, true, true);
if (autoHighlight) {
newHighlight->setSize(static_cast<FxListItemSG*>(currentItem)->itemSize());
const QLatin1String posProp(orient == QQuickListView::Vertical ? "y" : "x");
highlightPosAnimator = new QSmoothedAnimation;
highlightPosAnimator->target = QQmlProperty(item, posProp);
- highlightPosAnimator->velocity = highlightMoveSpeed;
+ highlightPosAnimator->velocity = highlightMoveVelocity;
highlightPosAnimator->userDuration = highlightMoveDuration;
const QLatin1String sizeProp(orient == QQuickListView::Vertical ? "height" : "width");
highlightSizeAnimator = new QSmoothedAnimation;
- highlightSizeAnimator->velocity = highlightResizeSpeed;
+ highlightSizeAnimator->velocity = highlightResizeVelocity;
highlightSizeAnimator->userDuration = highlightResizeDuration;
highlightSizeAnimator->target = QQmlProperty(item, sizeProp);
if (currentItem && autoHighlight && highlight && (!strictHighlight || !pressed)) {
// auto-update highlight
FxListItemSG *listItem = static_cast<FxListItemSG*>(currentItem);
- highlightPosAnimator->to = isRightToLeft()
+ highlightPosAnimator->to = isContentFlowReversed()
? -listItem->itemPosition()-listItem->itemSize()
: listItem->itemPosition();
highlightSizeAnimator->to = listItem->itemSize();
void QQuickListViewPrivate::releaseSectionItem(QQuickItem *item)
{
+ if (!item)
+ return;
int i = 0;
do {
if (!sectionCache[i]) {
delete item;
}
+
+void QQuickListViewPrivate::releaseSectionItems()
+{
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxListItemSG *listItem = static_cast<FxListItemSG *>(visibleItems.at(i));
+ if (listItem->section()) {
+ qreal pos = listItem->position();
+ releaseSectionItem(listItem->section());
+ listItem->setSection(0);
+ listItem->setPosition(pos);
+ }
+ }
+ for (int i = 0; i < sectionCacheSize; ++i) {
+ delete sectionCache[i];
+ sectionCache[i] = 0;
+ }
+}
+
void QQuickListViewPrivate::updateInlineSection(FxListItemSG *listItem)
{
if (!sectionCriteria || !sectionCriteria->delegate())
return;
- if (listItem->attached->m_prevSection != listItem->attached->m_section
+ if (QString::compare(listItem->attached->m_prevSection, listItem->attached->m_section, Qt::CaseInsensitive)
&& (sectionCriteria->labelPositioning() & QQuickViewSection::InlineLabels
|| (listItem->index == 0 && sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart))) {
if (!listItem->section()) {
void QQuickListViewPrivate::updateStickySections()
{
- if (!sectionCriteria || visibleItems.isEmpty()
+ if (!sectionCriteria
|| (!sectionCriteria->labelPositioning() && !currentSectionItem && !nextSectionItem))
return;
- bool isRtl = isRightToLeft();
- qreal viewPos = isRightToLeft() ? -position()-size() : position();
+ bool isFlowReversed = isContentFlowReversed();
+ qreal viewPos = isFlowReversed ? -position()-size() : position();
QQuickItem *sectionItem = 0;
QQuickItem *lastSectionItem = 0;
int index = 0;
qreal sectionSize = orient == QQuickListView::Vertical ? section->height() : section->width();
bool visTop = true;
if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart)
- visTop = isRtl ? -sectionPos-sectionSize >= viewPos : sectionPos >= viewPos;
+ visTop = isFlowReversed ? -sectionPos-sectionSize >= viewPos : sectionPos >= viewPos;
bool visBot = true;
if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd)
- visBot = isRtl ? -sectionPos <= viewPos + size() : sectionPos + sectionSize < viewPos + size();
+ visBot = isFlowReversed ? -sectionPos <= viewPos + size() : sectionPos + sectionSize < viewPos + size();
section->setVisible(visBot && visTop);
if (visTop && !sectionItem)
sectionItem = section;
- if (isRtl) {
+ if (isFlowReversed) {
if (-sectionPos <= viewPos + size())
lastSectionItem = section;
} else {
}
// Current section header
- if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart) {
+ if (sectionCriteria->labelPositioning() & QQuickViewSection::CurrentLabelAtStart && isValid() && visibleItems.count()) {
if (!currentSectionItem) {
currentSectionItem = getSectionItem(currentSection);
- } else if (currentStickySection != currentSection) {
+ } else if (QString::compare(currentStickySection, currentSection, Qt::CaseInsensitive)) {
QQmlContext *context = QQmlEngine::contextForObject(currentSectionItem)->parentContext();
context->setContextProperty(QLatin1String("section"), currentSection);
}
return;
qreal sectionSize = orient == QQuickListView::Vertical ? currentSectionItem->height() : currentSectionItem->width();
- bool atBeginning = orient == QQuickListView::Vertical ? vData.atBeginning : (isRightToLeft() ? hData.atEnd : hData.atBeginning);
+ bool atBeginning = orient == QQuickListView::Vertical ? (isBottomToTop() ? vData.atEnd : vData.atBeginning) : (isRightToLeft() ? hData.atEnd : hData.atBeginning);
+
currentSectionItem->setVisible(!atBeginning && (!header || header->endPosition() < viewPos));
- qreal pos = isRtl ? position() + size() - sectionSize : viewPos;
+ qreal pos = isFlowReversed ? position() + size() - sectionSize : viewPos;
if (sectionItem) {
qreal sectionPos = orient == QQuickListView::Vertical ? sectionItem->y() : sectionItem->x();
- pos = isRtl ? qMax(pos, sectionPos + sectionSize) : qMin(pos, sectionPos - sectionSize);
+ pos = isFlowReversed ? qMax(pos, sectionPos + sectionSize) : qMin(pos, sectionPos - sectionSize);
}
if (header)
- pos = isRtl ? qMin(header->endPosition(), pos) : qMax(header->endPosition(), pos);
+ pos = isFlowReversed ? qMin(header->endPosition(), pos) : qMax(header->endPosition(), pos);
if (footer)
- pos = isRtl ? qMax(-footer->position(), pos) : qMin(footer->position() - sectionSize, pos);
+ pos = isFlowReversed ? qMax(-footer->position(), pos) : qMin(footer->position() - sectionSize, pos);
if (orient == QQuickListView::Vertical)
currentSectionItem->setY(pos);
else
}
// Next section footer
- if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd) {
+ if (sectionCriteria->labelPositioning() & QQuickViewSection::NextLabelAtEnd && isValid() && visibleItems.count()) {
if (!nextSectionItem) {
nextSectionItem = getSectionItem(nextSection);
- } else if (nextStickySection != nextSection) {
+ } else if (QString::compare(nextStickySection, nextSection, Qt::CaseInsensitive)) {
QQmlContext *context = QQmlEngine::contextForObject(nextSectionItem)->parentContext();
context->setContextProperty(QLatin1String("section"), nextSection);
}
qreal sectionSize = orient == QQuickListView::Vertical ? nextSectionItem->height() : nextSectionItem->width();
nextSectionItem->setVisible(!nextSection.isEmpty());
- qreal pos = isRtl ? position() : viewPos + size() - sectionSize;
+ qreal pos = isFlowReversed ? position() : viewPos + size() - sectionSize;
if (lastSectionItem) {
qreal sectionPos = orient == QQuickListView::Vertical ? lastSectionItem->y() : lastSectionItem->x();
- pos = isRtl ? qMin(pos, sectionPos - sectionSize) : qMax(pos, sectionPos + sectionSize);
+ pos = isFlowReversed ? qMin(pos, sectionPos - sectionSize) : qMax(pos, sectionPos + sectionSize);
}
if (header)
- pos = isRtl ? qMin(header->endPosition() - sectionSize, pos) : qMax(header->endPosition(), pos);
+ pos = isFlowReversed ? qMin(header->endPosition() - sectionSize, pos) : qMax(header->endPosition(), pos);
if (orient == QQuickListView::Vertical)
nextSectionItem->setY(pos);
else
QQuickItemViewPrivate::updateSections();
- if (sectionCriteria && !visibleItems.isEmpty()) {
+ if (sectionCriteria && !visibleItems.isEmpty() && isValid()) {
QString prevSection;
if (visibleIndex > 0)
prevSection = sectionAt(visibleIndex-1);
}
lastVisibleSection = QString();
- updateCurrentSection();
- updateStickySections();
}
void QQuickListViewPrivate::updateCurrentSection()
// section when that changes. Clearing lastVisibleSection will also
// force searching.
QString lastSection = currentSection;
- qreal endPos = isRightToLeft() ? -position() : position() + size();
+ qreal endPos = isContentFlowReversed() ? -position() : position() + size();
if (nextSectionItem && !inlineSections)
endPos -= orient == QQuickListView::Vertical ? nextSectionItem->height() : nextSectionItem->width();
while (index < visibleItems.count() && static_cast<FxListItemSG*>(visibleItems.at(index))->itemPosition() < endPos) {
Q_Q(QQuickListView);
bool created = false;
if (!footer) {
- QQuickItem *item = createComponentItem(footerComponent, true);
+ QQuickItem *item = createComponentItem(footerComponent, 1.0);
if (!item)
return;
- item->setZ(1);
- footer = new FxListItemSG(item, q, true);
+ footer = new FxListItemSG(item, q, true, true);
created = true;
}
Q_Q(QQuickListView);
bool created = false;
if (!header) {
- QQuickItem *item = createComponentItem(headerComponent, true);
+ QQuickItem *item = createComponentItem(headerComponent, 1.0);
if (!item)
return;
- item->setZ(1);
- header = new FxListItemSG(item, q, true);
+ header = new FxListItemSG(item, q, true, true);
created = true;
}
QQuickItemViewPrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
if (!q->isComponentComplete())
return;
+
if (item != contentItem && (!highlight || item != highlight->item)) {
if ((orient == QQuickListView::Vertical && newGeometry.height() != oldGeometry.height())
|| (orient == QQuickListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
- forceLayout = true;
- q->polish();
+
+ // if visibleItems.first() has resized, adjust its pos since it is used to
+ // position all subsequent items
+ if (visibleItems.count() && item == visibleItems.first()->item) {
+ FxListItemSG *listItem = static_cast<FxListItemSG*>(visibleItems.first());
+ if (orient == QQuickListView::Vertical) {
+ qreal diff = newGeometry.height() - oldGeometry.height();
+ if (verticalLayoutDirection == QQuickListView::TopToBottom && listItem->endPosition() < q->contentY())
+ listItem->setPosition(listItem->position() - diff, true);
+ else if (verticalLayoutDirection == QQuickListView::BottomToTop && listItem->endPosition() > q->contentY())
+ listItem->setPosition(listItem->position() + diff, true);
+ } else {
+ qreal diff = newGeometry.width() - oldGeometry.width();
+ if (q->effectiveLayoutDirection() == Qt::LeftToRight && listItem->endPosition() < q->contentX())
+ listItem->setPosition(listItem->position() - diff, true);
+ else if (q->effectiveLayoutDirection() == Qt::RightToLeft && listItem->endPosition() > q->contentX())
+ listItem->setPosition(listItem->position() + diff, true);
+ }
+ }
+ forceLayoutPolish();
}
}
}
fixupMode = moveReason == Mouse ? fixupMode : Immediate;
bool strictHighlightRange = haveHighlightRange && highlightRange == QQuickListView::StrictlyEnforceRange;
- qreal viewPos = isRightToLeft() ? -position()-size() : position();
+ qreal viewPos = isContentFlowReversed() ? -position()-size() : position();
if (snapMode != QQuickListView::NoSnap && moveReason != QQuickListViewPrivate::SetIndex) {
- qreal tempPosition = isRightToLeft() ? -position()-size() : position();
+ qreal tempPosition = isContentFlowReversed() ? -position()-size() : position();
if (snapMode == QQuickListView::SnapOneItem && moveReason == Mouse) {
// if we've been dragged < averageSize/2 then bias towards the next item
qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
bias = averageSize/2;
else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -averageSize/2)
bias = -averageSize/2;
- if (isRightToLeft())
+ if (isContentFlowReversed())
bias = -bias;
tempPosition -= bias;
}
bool isInBounds = -position() > maxExtent && -position() <= minExtent;
if (topItem && (isInBounds || strictHighlightRange)) {
if (topItem->index == 0 && header && tempPosition+highlightRangeStart < header->position()+header->size()/2 && !strictHighlightRange) {
- pos = isRightToLeft() ? - header->position() + highlightRangeStart - size() : header->position() - highlightRangeStart;
+ pos = isContentFlowReversed() ? - header->position() + highlightRangeStart - size() : header->position() - highlightRangeStart;
} else {
- if (isRightToLeft())
+ if (isContentFlowReversed())
pos = qMax(qMin(-topItem->position() + highlightRangeStart - size(), -maxExtent), -minExtent);
else
pos = qMax(qMin(topItem->position() - highlightRangeStart, -maxExtent), -minExtent);
}
} else if (bottomItem && isInBounds) {
- if (isRightToLeft())
+ if (isContentFlowReversed())
pos = qMax(qMin(-bottomItem->position() + highlightRangeEnd - size(), -maxExtent), -minExtent);
else
pos = qMax(qMin(bottomItem->position() - highlightRangeEnd, -maxExtent), -minExtent);
viewPos = pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightRangeEnd;
if (viewPos > pos - highlightRangeStart)
viewPos = pos - highlightRangeStart;
- if (isRightToLeft())
+ if (isContentFlowReversed())
viewPos = -viewPos-size();
timeline.reset(data.move);
fixupMode = Normal;
}
-void QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+bool QQuickListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
QQuickTimeLineCallback::Callback fixupCallback, qreal velocity)
{
- Q_Q(QQuickListView);
-
data.fixingUp = false;
moveReason = Mouse;
if ((!haveHighlightRange || highlightRange != QQuickListView::StrictlyEnforceRange) && snapMode == QQuickListView::NoSnap) {
correctFlick = true;
- QQuickItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
- return;
+ return QQuickItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
}
qreal maxDistance = 0;
- qreal dataValue = isRightToLeft() ? -data.move.value()+size() : data.move.value();
+ qreal dataValue = isContentFlowReversed() ? -data.move.value()+size() : data.move.value();
// -ve velocity means list is moving up/left
if (velocity > 0) {
// if we've been dragged < averageSize/2 then bias towards the next item
qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
qreal bias = dist < averageSize/2 ? averageSize/2 : 0;
- if (isRightToLeft())
+ if (isContentFlowReversed())
bias = -bias;
data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) - bias) + highlightRangeStart;
maxDistance = qAbs(data.flickTarget - data.move.value());
// if we've been dragged < averageSize/2 then bias towards the next item
qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
qreal bias = -dist < averageSize/2 ? averageSize/2 : 0;
- if (isRightToLeft())
+ if (isContentFlowReversed())
bias = -bias;
data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) + bias) + highlightRangeStart;
maxDistance = qAbs(data.flickTarget - data.move.value());
dist = -dist;
if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QQuickListView::SnapOneItem) {
if (snapMode != QQuickListView::SnapOneItem) {
- qreal distTemp = isRightToLeft() ? -dist : dist;
+ qreal distTemp = isContentFlowReversed() ? -dist : dist;
data.flickTarget = -snapPosAt(-(dataValue - highlightRangeStart) + distTemp) + highlightRangeStart;
}
- data.flickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
+ data.flickTarget = isContentFlowReversed() ? -data.flickTarget+size() : data.flickTarget;
if (overShoot) {
if (data.flickTarget >= minExtent) {
overshootDist = overShootDistance(vSize);
timeline.reset(data.move);
timeline.accel(data.move, v, accel, maxDistance + overshootDist);
timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback, this));
- if (!hData.flicking && q->xflick()) {
- hData.flicking = true;
- emit q->flickingChanged();
- emit q->flickingHorizontallyChanged();
- emit q->flickStarted();
- }
- if (!vData.flicking && q->yflick()) {
- vData.flicking = true;
- emit q->flickingChanged();
- emit q->flickingVerticallyChanged();
- emit q->flickStarted();
- }
correctFlick = true;
+ return true;
} else {
// reevaluate the target boundary.
qreal newtarget = data.flickTarget;
if (snapMode != QQuickListView::NoSnap || highlightRange == QQuickListView::StrictlyEnforceRange) {
- qreal tempFlickTarget = isRightToLeft() ? -data.flickTarget+size() : data.flickTarget;
+ qreal tempFlickTarget = isContentFlowReversed() ? -data.flickTarget+size() : data.flickTarget;
newtarget = -snapPosAt(-(tempFlickTarget - highlightRangeStart)) + highlightRangeStart;
- newtarget = isRightToLeft() ? -newtarget+size() : newtarget;
+ newtarget = isContentFlowReversed() ? -newtarget+size() : newtarget;
}
if (velocity < 0 && newtarget <= maxExtent)
newtarget = maxExtent - overshootDist;
if (newtarget == data.flickTarget) { // boundary unchanged - nothing to do
if (qAbs(velocity) < MinimumFlickVelocity)
correctFlick = false;
- return;
+ return false;
}
data.flickTarget = newtarget;
qreal dist = -newtarget + data.move.value();
correctFlick = false;
timeline.reset(data.move);
fixup(data, minExtent, maxExtent);
- return;
+ return false;
}
timeline.reset(data.move);
timeline.accelDistance(data.move, v, -dist);
timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback, this));
+ return false;
}
} else {
correctFlick = false;
timeline.reset(data.move);
fixup(data, minExtent, maxExtent);
+ return false;
}
}
/*!
\qmlclass ListView QQuickListView
\inqmlmodule QtQuick 2
- \ingroup qml-view-elements
+ \ingroup qtquick-views
\inherits Flickable
- \brief The ListView item provides a list view of items provided by a model.
+ \brief Provides a list view of items provided by a model
A ListView displays data from models created from built-in QML elements like ListModel
and XmlListModel, or custom model classes defined in C++ that inherit from
The following example shows the definition of a simple list model defined
in a file called \c ContactModel.qml:
- \snippet doc/src/snippets/qml/listview/ContactModel.qml 0
+ \snippet qml/listview/ContactModel.qml 0
Another component can display this model data in a ListView, like this:
- \snippet doc/src/snippets/qml/listview/listview.qml import
+ \snippet qml/listview/listview.qml import
\codeline
- \snippet doc/src/snippets/qml/listview/listview.qml classdocs simple
+ \snippet qml/listview/listview.qml classdocs simple
\image listview-simple.png
An improved list view is shown below. The delegate is visually improved and is moved
into a separate \c contactDelegate component.
- \snippet doc/src/snippets/qml/listview/listview.qml classdocs advanced
+ \snippet qml/listview/listview.qml classdocs advanced
\image listview-highlight.png
The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
this attached property directly as \c ListView.isCurrentItem, while the child
\c contactInfo object must refer to this property as \c wrapper.ListView.isCurrentItem.
- \snippet doc/src/snippets/qml/listview/listview.qml isCurrentItem
+ \snippet qml/listview/listview.qml isCurrentItem
\note Views do not enable \e clip automatically. If the view
is not clipped by another item or the screen, it will be necessary
to set \e {clip: true} in order to have the out of view items clipped
nicely.
- \sa {QML Data Models}, GridView, {declarative/modelviews/listview}{ListView examples}
+
+ \section1 ListView layouts
+
+ The layout of the items in a ListView can be controlled by these properties:
+
+ \list
+ \li \l orientation - controls whether items flow horizontally or vertically.
+ This value can be either Qt.Horizontal or Qt.Vertical.
+ \li \l layoutDirection - controls the horizontal layout direction for a
+ horizontally-oriented view: that is, whether items are laid out from the left side of
+ the view to the right, or vice-versa. This value can be either Qt.LeftToRight or Qt.RightToLeft.
+ \li \l verticalLayoutDirection - controls the vertical layout direction for a vertically-oriented
+ view: that is, whether items are laid out from the top of the view down towards the bottom of
+ the view, or vice-versa. This value can be either ListView.TopToBottom or ListView.BottomToTop.
+ \endlist
+
+ By default, a ListView has a vertical orientation, and items are laid out from top to bottom. The
+ table below shows the different layouts that a ListView can have, depending on the values of
+ the properties listed above.
+
+ \table
+ \header
+ \li {2, 1}
+ \bold ListViews with Qt.Vertical orientation
+ \row
+ \li Top to bottom
+ \image listview-layout-toptobottom.png
+ \li Bottom to top
+ \image listview-layout-bottomtotop.png
+ \header
+ \li {2, 1}
+ \bold ListViews with Qt.Horizontal orientation
+ \row
+ \li Left to right
+ \image listview-layout-lefttoright.png
+ \li Right to left
+ \image listview-layout-righttoleft.png
+ \endtable
+
+ \sa {QML Data Models}, GridView, {quick/modelviews/listview}{ListView examples}
*/
QQuickListView::QQuickListView(QQuickItem *parent)
: QQuickItemView(*(new QQuickListViewPrivate), parent)
This property may be used to adjust the appearance of the current item, for example:
- \snippet doc/src/snippets/qml/listview/listview.qml isCurrentItem
+ \snippet qml/listview/listview.qml isCurrentItem
*/
/*!
until an animation completes. The example delegate below ensures that the
animation completes before the item is removed from the list.
- \snippet doc/src/snippets/qml/listview/listview.qml delayRemove
+ \snippet qml/listview/listview.qml delayRemove
If a \l remove transition has been specified, it will not be applied until
delayRemove is returned to \c false.
so as to stay with the current item, unless the highlightFollowsCurrentItem
property is false.
- \sa highlightItem, highlightFollowsCurrentItem, {declarative/modelviews/listview}{ListView examples}
+ \sa highlightItem, highlightFollowsCurrentItem, {quick/modelviews/listview}{ListView examples}
*/
/*!
Here is a highlight with its motion defined by a \l {SpringAnimation} item:
- \snippet doc/src/snippets/qml/listview/listview.qml highlightFollowsCurrentItem
+ \snippet qml/listview/listview.qml highlightFollowsCurrentItem
Note that the highlight animation also affects the way that the view
is scrolled. This is because the view moves to maintain the
highlight within the preferred highlight range (or visible viewport).
- \sa highlight, highlightMoveSpeed
+ \sa highlight, highlightMoveVelocity
*/
//###Possibly rename these properties, since they are very useful even without a highlight?
/*!
Valid values for \c highlightRangeMode are:
\list
- \o ListView.ApplyRange - the view attempts to maintain the highlight within the range.
+ \li ListView.ApplyRange - the view attempts to maintain the highlight within the range.
However, the highlight can move outside of the range at the ends of the list or due
to mouse interaction.
- \o ListView.StrictlyEnforceRange - the highlight never moves outside of the range.
+ \li ListView.StrictlyEnforceRange - the highlight never moves outside of the range.
The current item changes if a keyboard or mouse action would cause the highlight to move
outside of the range.
- \o ListView.NoHighlightRange - this is the default value.
+ \li ListView.NoHighlightRange - this is the default value.
\endlist
*/
void QQuickListView::setHighlightFollowsCurrentItem(bool autoHighlight)
Q_D(QQuickListView);
if (spacing != d->spacing) {
d->spacing = spacing;
- d->forceLayout = true;
- polish();
+ d->forceLayoutPolish();
emit spacingChanged();
}
}
Possible values:
\list
- \o ListView.Horizontal - Items are laid out horizontally
- \o ListView.Vertical (default) - Items are laid out vertically
+ \li ListView.Horizontal - Items are laid out horizontally
+ \li ListView.Vertical (default) - Items are laid out vertically
\endlist
\table
\row
- \o Horizontal orientation:
+ \li Horizontal orientation:
\image ListViewHorizontal.png
\row
- \o Vertical orientation:
+ \li Vertical orientation:
\image listview-highlight.png
\endtable
*/
/*!
\qmlproperty enumeration QtQuick2::ListView::layoutDirection
- This property holds the layout direction of the horizontal list.
+ This property holds the layout direction of a horizontally-oriented list.
Possible values:
\list
- \o Qt.LeftToRight (default) - Items will be laid out from left to right.
- \o Qt.RightToLeft - Items will be laid out from right to let.
+ \li Qt.LeftToRight (default) - Items will be laid out from left to right.
+ \li Qt.RightToLeft - Items will be laid out from right to let.
\endlist
- \sa ListView::effectiveLayoutDirection
+ Setting this property has no effect if the \l orientation is Qt.Vertical.
+
+ \sa ListView::effectiveLayoutDirection, ListView::verticalLayoutDirection
*/
/*!
\qmlproperty enumeration QtQuick2::ListView::effectiveLayoutDirection
- This property holds the effective layout direction of the horizontal list.
+ This property holds the effective layout direction of a horizontally-oriented list.
When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
the visual layout direction of the horizontal list will be mirrored. However, the
\sa ListView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
*/
+
+/*!
+ \qmlproperty enumeration QtQuick2::ListView::verticalLayoutDirection
+ This property holds the layout direction of a vertically-oriented list.
+
+ Possible values:
+
+ \list
+ \li ListView.TopToBottom (default) - Items are laid out from the top of the view down to the bottom of the view.
+ \li ListView.BottomToTop - Items are laid out from the bottom of the view up to the top of the view.
+ \endlist
+
+ Setting this property has no effect if the \l orientation is Qt.Horizontal.
+
+ \sa ListView::layoutDirection
+*/
+
+
/*!
\qmlproperty bool QtQuick2::ListView::keyNavigationWraps
This property holds whether the list wraps key navigation.
area may be created/retained. The buffered delegates are created asynchronously,
allowing creation to occur across multiple frames and reducing the
likelihood of skipping frames. In order to improve painting performance
- delegates outside the visible area have their \l visible property set to
- false until they are moved into the visible area.
+ delegates outside the visible area are not painted.
+
+ The default value of this property is platform dependent, but will usually
+ be a non-zero value.
Note that cacheBuffer is not a pixel buffer - it only maintains additional
instantiated delegates.
\c section.property. This value can be one of:
\list
- \o ViewSection.FullString (default) - sections are created based on the
+ \li ViewSection.FullString (default) - sections are created based on the
\c section.property value.
- \o ViewSection.FirstCharacter - sections are created based on the first
+ \li ViewSection.FirstCharacter - sections are created based on the first
character of the \c section.property value (for example, 'A', 'B', 'C'
sections, etc. for an address book)
\endlist
+ A case insensitive comparison is used when determining section
+ boundaries.
+
\c section.delegate holds the delegate component for each section.
\c section.labelPositioning determines whether the current and/or
the labels are shown inline. This value can be a combination of:
\list
- \o ViewSection.InlineLabels - section labels are shown inline between
+ \li ViewSection.InlineLabels - section labels are shown inline between
the item delegates separating sections (default).
- \o ViewSection.CurrentLabelAtStart - the current section label sticks to the
+ \li ViewSection.CurrentLabelAtStart - the current section label sticks to the
start of the view as it is moved.
- \o ViewSection.NextLabelAtEnd - the next section label (beyond all visible
+ \li ViewSection.NextLabelAtEnd - the next section label (beyond all visible
sections) sticks to the end of the view as it is moved. \note Enabling
\c ViewSection.NextLabelAtEnd requires the view to scan ahead for the next
section, which has performance implications, especially for slower models.
each section.
- \snippet examples/declarative/modelviews/listview/sections.qml 0
+ \snippet examples/quick/modelviews/listview/sections.qml 0
\image qml-listview-sections-example.png
differing sections will result in a section header being created
even if that section exists elsewhere.
- \sa {declarative/modelviews/listview}{ListView examples}
+ \sa {quick/modelviews/listview}{ListView examples}
*/
QQuickViewSection *QQuickListView::sectionCriteria()
{
Q_D(QQuickListView);
- if (!d->sectionCriteria) {
+ if (!d->sectionCriteria)
d->sectionCriteria = new QQuickViewSection(this);
- connect(d->sectionCriteria, SIGNAL(propertyChanged()), this, SLOT(updateSections()));
- }
return d->sectionCriteria;
}
}
/*!
- \qmlproperty real QtQuick2::ListView::highlightMoveSpeed
+ \qmlproperty real QtQuick2::ListView::highlightMoveVelocity
\qmlproperty int QtQuick2::ListView::highlightMoveDuration
- \qmlproperty real QtQuick2::ListView::highlightResizeSpeed
+ \qmlproperty real QtQuick2::ListView::highlightResizeVelocity
\qmlproperty int QtQuick2::ListView::highlightResizeDuration
- These properties hold the move and resize animation speed of the highlight delegate.
+ These properties control the speed of the move and resize animations for the
+ highlight delegate.
\l highlightFollowsCurrentItem must be true for these properties
to have effect.
- The default value for the speed properties is 400 pixels/second.
+ The default value for the velocity properties is 400 pixels/second.
The default value for the duration properties is -1, i.e. the
highlight will take as much time as necessary to move at the set speed.
\sa highlightFollowsCurrentItem
*/
-qreal QQuickListView::highlightMoveSpeed() const
+qreal QQuickListView::highlightMoveVelocity() const
{
Q_D(const QQuickListView);
- return d->highlightMoveSpeed;
+ return d->highlightMoveVelocity;
}
-void QQuickListView::setHighlightMoveSpeed(qreal speed)
+void QQuickListView::setHighlightMoveVelocity(qreal speed)
{
Q_D(QQuickListView);
- if (d->highlightMoveSpeed != speed) {
- d->highlightMoveSpeed = speed;
+ if (d->highlightMoveVelocity != speed) {
+ d->highlightMoveVelocity = speed;
if (d->highlightPosAnimator)
- d->highlightPosAnimator->velocity = d->highlightMoveSpeed;
- emit highlightMoveSpeedChanged();
+ d->highlightPosAnimator->velocity = d->highlightMoveVelocity;
+ emit highlightMoveVelocityChanged();
}
}
}
}
-qreal QQuickListView::highlightResizeSpeed() const
+qreal QQuickListView::highlightResizeVelocity() const
{
Q_D(const QQuickListView);
- return d->highlightResizeSpeed;
+ return d->highlightResizeVelocity;
}
-void QQuickListView::setHighlightResizeSpeed(qreal speed)
+void QQuickListView::setHighlightResizeVelocity(qreal speed)
{
Q_D(QQuickListView);
- if (d->highlightResizeSpeed != speed) {
- d->highlightResizeSpeed = speed;
+ if (d->highlightResizeVelocity != speed) {
+ d->highlightResizeVelocity = speed;
if (d->highlightSizeAnimator)
- d->highlightSizeAnimator->velocity = d->highlightResizeSpeed;
- emit highlightResizeSpeedChanged();
+ d->highlightSizeAnimator->velocity = d->highlightResizeVelocity;
+ emit highlightResizeVelocityChanged();
}
}
The possible values are:
\list
- \o ListView.NoSnap (default) - the view stops anywhere within the visible area.
- \o ListView.SnapToItem - the view settles with an item aligned with the start of
+ \li ListView.NoSnap (default) - the view stops anywhere within the visible area.
+ \li ListView.SnapToItem - the view settles with an item aligned with the start of
the view.
- \o ListView.SnapOneItem - the view settles no more than one item away from the first
+ \li ListView.SnapOneItem - the view settles no more than one item away from the first
visible item at the time the mouse button is released. This mode is particularly
useful for moving one page at a time.
\endlist
It is applied to all items that are created when:
\list
- \o The view is first created
- \o The view's \l model changes
- \o The view's \l model is \l {QAbstractItemModel::reset}{reset}, if the model is a QAbstractItemModel subclass
+ \li The view is first created
+ \li The view's \l model changes
+ \li The view's \l model is \l {QAbstractItemModel::reset}{reset}, if the model is a QAbstractItemModel subclass
\endlist
For example, here is a view that specifies such a transition:
\sa addDisplaced, moveDisplaced, removeDisplaced, ViewTransition
*/
-void QQuickListView::viewportMoved()
+void QQuickListView::viewportMoved(Qt::Orientations orient)
{
Q_D(QQuickListView);
- QQuickItemView::viewportMoved();
+ QQuickItemView::viewportMoved(orient);
if (!d->itemCount)
return;
// Recursion can occur due to refill changing the content size.
return;
d->inViewportMoved = true;
- if (yflick())
- d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
- else if (d->isRightToLeft())
- d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferAfter : QQuickListViewPrivate::BufferBefore;
- else
- d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
+ if (yflick()) {
+ if (d->isBottomToTop())
+ d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferAfter : QQuickListViewPrivate::BufferBefore;
+ else
+ d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
+ } else {
+ if (d->isRightToLeft())
+ d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferAfter : QQuickListViewPrivate::BufferBefore;
+ else
+ d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickListViewPrivate::BufferBefore : QQuickListViewPrivate::BufferAfter;
+ }
- d->refill();
+ 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();
for (int i = 0; i < d->visibleItems.count(); ++i) {
FxViewItem *item = static_cast<FxListItemSG*>(d->visibleItems.at(i));
- item->item->setVisible(item->endPosition() >= from && item->position() <= to);
+ QQuickItemPrivate::get(item->item)->setCulled(item->endPosition() < from || item->position() > to);
}
+ if (d->currentItem)
+ QQuickItemPrivate::get(d->currentItem->item)->setCulled(d->currentItem->endPosition() < from || d->currentItem->position() > to);
if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
d->moveReason = QQuickListViewPrivate::Mouse;
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
// reposition highlight
qreal pos = d->highlight->position();
- qreal viewPos = d->isRightToLeft() ? -d->position()-d->size() : d->position();
+ qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
pos = viewPos + d->highlightRangeEnd - d->highlight->size();
if (pos < viewPos + d->highlightRangeStart)
if (d->model && d->model->count() && d->interactive) {
if ((d->orient == QQuickListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Left)
|| (d->orient == QQuickListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Right)
- || (d->orient == QQuickListView::Vertical && event->key() == Qt::Key_Up)) {
+ || (d->orient == QQuickListView::Vertical && !d->isBottomToTop() && event->key() == Qt::Key_Up)
+ || (d->orient == QQuickListView::Vertical && d->isBottomToTop() && event->key() == Qt::Key_Down)) {
if (currentIndex() > 0 || (d->wrap && !event->isAutoRepeat())) {
decrementCurrentIndex();
event->accept();
}
} else if ((d->orient == QQuickListView::Horizontal && !d->isRightToLeft() && event->key() == Qt::Key_Right)
|| (d->orient == QQuickListView::Horizontal && d->isRightToLeft() && event->key() == Qt::Key_Left)
- || (d->orient == QQuickListView::Vertical && event->key() == Qt::Key_Down)) {
+ || (d->orient == QQuickListView::Vertical && !d->isBottomToTop() && event->key() == Qt::Key_Down)
+ || (d->orient == QQuickListView::Vertical && d->isBottomToTop() && event->key() == Qt::Key_Up)) {
if (currentIndex() < d->model->count() - 1 || (d->wrap && !event->isAutoRepeat())) {
incrementCurrentIndex();
event->accept();
void QQuickListView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QQuickListView);
- if (d->isRightToLeft() && d->orient == QQuickListView::Horizontal) {
+ if (d->isRightToLeft()) {
// maintain position relative to the right edge
int dx = newGeometry.width() - oldGeometry.width();
setContentX(contentX() - dx);
+ } else if (d->isBottomToTop()) {
+ // maintain position relative to the bottom edge
+ int dy = newGeometry.height() - oldGeometry.height();
+ setContentY(contentY() - dy);
}
QQuickItemView::geometryChanged(newGeometry, oldGeometry);
}
+void QQuickListView::initItem(int index, QQuickItem *item)
+{
+ QQuickItemView::initItem(index, item);
+ QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>(
+ qmlAttachedPropertiesObject<QQuickListView>(item));
+ if (attached)
+ attached->setView(this);
+}
+
/*!
\qmlmethod QtQuick2::ListView::incrementCurrentIndex()
if keyNavigationWraps is true and it is currently at the end.
This method has no effect if the \l count is zero.
- \bold Note: methods should only be called after the Component has completed.
+ \b Note: methods should only be called after the Component has completed.
*/
void QQuickListView::incrementCurrentIndex()
{
if keyNavigationWraps is true and it is currently at the beginning.
This method has no effect if the \l count is zero.
- \bold Note: methods should only be called after the Component has completed.
+ \b Note: methods should only be called after the Component has completed.
*/
void QQuickListView::decrementCurrentIndex()
{
}
}
-void QQuickListView::updateSections()
+void QQuickListViewPrivate::updateSectionCriteria()
{
- Q_D(QQuickListView);
- if (isComponentComplete() && d->model) {
+ Q_Q(QQuickListView);
+ if (q->isComponentComplete() && model) {
QList<QByteArray> roles;
- if (d->sectionCriteria && !d->sectionCriteria->property().isEmpty())
- roles << d->sectionCriteria->property().toUtf8();
- d->model->setWatchedRoles(roles);
- d->updateSections();
- if (d->itemCount) {
- d->forceLayout = true;
- polish();
- }
+ if (sectionCriteria && !sectionCriteria->property().isEmpty())
+ roles << sectionCriteria->property().toUtf8();
+ model->setWatchedRoles(roles);
+ updateSections();
+ if (itemCount)
+ forceLayoutPolish();
}
}
int modelIndex = change.index;
int count = change.count;
- qreal tempPos = isRightToLeft() ? -position()-size() : position();
+ qreal tempPos = isContentFlowReversed() ? -position()-size() : position();
int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;
if (index < 0) {
insertResult->changedFirstItem = true;
if (!change.isMove()) {
addedItems->append(item);
- if (transitioner)
- transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::AddTransition, true);
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
}
insertResult->sizeChangesBeforeVisiblePos += item->size() + spacing;
pos -= item->size() + spacing;
movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
} else {
addedItems->append(item);
- if (transitioner)
- transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::AddTransition, true);
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
}
insertResult->sizeChangesAfterVisiblePos += item->size() + spacing;
pos += item->size() + spacing;
for (; index < visibleItems.count(); ++index) {
FxViewItem *item = visibleItems.at(index);
- if (item->index != -1)
+ if (item->index != -1) {
item->index += count;
- if (transitioner) {
if (change.isMove())
- transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::MoveTransition, false);
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, false);
else
- transitioner->transitionNextReposition(item, QQuickItemViewTransitioner::AddTransition, false);
+ item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, false);
}
}
if (!listItem->transitionScheduledOrRunning()) {
qreal pos = listItem->position();
listItem->setPosition(pos - sizeRemoved);
- transitioner->transitionNextReposition(listItem, QQuickItemViewTransitioner::RemoveTransition, false);
+ listItem->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, false);
listItem->setPosition(pos);
}
}
\a mode:
\list
- \o ListView.Beginning - position item at the top (or left for horizontal orientation) of the view.
- \o ListView.Center - position item in the center of the view.
- \o ListView.End - position item at bottom (or right for horizontal orientation) of the view.
- \o ListView.Visible - if any part of the item is visible then take no action, otherwise
+ \li ListView.Beginning - position item at the top (or left for horizontal orientation) of the view.
+ \li ListView.Center - position item in the center of the view.
+ \li ListView.End - position item at bottom (or right for horizontal orientation) of the view.
+ \li ListView.Visible - if any part of the item is visible then take no action, otherwise
bring the item into view.
- \o ListView.Contain - ensure the entire item is visible. If the item is larger than
+ \li ListView.Contain - ensure the entire item is visible. If the item is larger than
the view the item is positioned at the top (or left for horizontal orientation) of the view.
\endlist
the actual start of the view can vary based on the size of the delegates.
The correct way to bring an item into view is with \c positionViewAtIndex.
- \bold Note: methods should only be called after the Component has completed. To position
+ \b Note: methods should only be called after the Component has completed. To position
the view at startup, this method should be called by Component.onCompleted. For
example, to position the view at the end:
of the list does not cause all other items to be repositioned, and because
the actual start of the view can vary based on the size of the delegates.
- \bold Note: methods should only be called after the Component has completed. To position
+ \b Note: methods should only be called after the Component has completed. To position
the view at startup, this method should be called by Component.onCompleted. For
example, to position the view at the end on startup:
If the item is outside the visible area, -1 is returned, regardless of
whether an item will exist at that point when scrolled into view.
- \bold Note: methods should only be called after the Component has completed.
+ \b Note: methods should only be called after the Component has completed.
*/
/*!
If the item is outside the visible area, null is returned, regardless of
whether an item will exist at that point when scrolled into view.
- \bold Note: methods should only be called after the Component has completed.
+ \b Note: methods should only be called after the Component has completed.
*/
QQuickListViewAttached *QQuickListView::qmlAttachedProperties(QObject *obj)