1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qquickitemview_p_p.h"
47 FxViewItem::FxViewItem(QQuickItem *i, bool own)
48 : item(i), ownItem(own), index(-1)
52 FxViewItem::~FxViewItem()
54 if (ownItem && item) {
55 item->setParentItem(0);
62 QQuickItemViewChangeSet::QQuickItemViewChangeSet()
68 bool QQuickItemViewChangeSet::hasPendingChanges() const
70 return !pendingChanges.isEmpty();
73 void QQuickItemViewChangeSet::applyChanges(const QDeclarativeChangeSet &changeSet)
75 pendingChanges.apply(changeSet);
80 foreach (const QDeclarativeChangeSet::Remove &r, changeSet.removes()) {
82 if (moveId == -1 && newCurrentIndex >= r.index + r.count) {
83 newCurrentIndex -= r.count;
84 currentChanged = true;
85 } else if (moveId == -1 && newCurrentIndex >= r.index && newCurrentIndex < r.index + r.count) {
86 // current item has been removed.
89 moveOffset = newCurrentIndex - r.index;
91 currentRemoved = true;
94 newCurrentIndex = qMin(r.index, itemCount - 1);
96 currentChanged = true;
99 foreach (const QDeclarativeChangeSet::Insert &i, changeSet.inserts()) {
101 if (itemCount && newCurrentIndex >= i.index) {
102 newCurrentIndex += i.count;
103 currentChanged = true;
104 } else if (newCurrentIndex < 0) {
106 currentChanged = true;
107 } else if (newCurrentIndex == 0 && !itemCount) {
108 // this is the first item, set the initial current index
109 currentChanged = true;
111 } else if (moveId == i.moveId) {
112 newCurrentIndex = i.index + moveOffset;
114 itemCount += i.count;
118 void QQuickItemViewChangeSet::prepare(int currentIndex, int count)
125 newCurrentIndex = currentIndex;
128 void QQuickItemViewChangeSet::reset()
131 newCurrentIndex = -1;
132 pendingChanges.clear();
133 removedItems.clear();
135 currentChanged = false;
136 currentRemoved = false;
140 QQuickItemView::QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent)
141 : QQuickFlickable(dd, parent)
147 QQuickItemView::~QQuickItemView()
158 QQuickItem *QQuickItemView::currentItem() const
160 Q_D(const QQuickItemView);
163 const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
164 return d->currentItem->item;
167 QVariant QQuickItemView::model() const
169 Q_D(const QQuickItemView);
170 return d->modelVariant;
173 void QQuickItemView::setModel(const QVariant &model)
176 if (d->modelVariant == model)
179 disconnect(d->model, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)),
180 this, SLOT(modelUpdated(QDeclarativeChangeSet,bool)));
181 disconnect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
182 disconnect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
183 disconnect(d->model, SIGNAL(destroyingItem(QQuickItem*)), this, SLOT(destroyingItem(QQuickItem*)));
186 QQuickVisualModel *oldModel = d->model;
189 d->setPosition(d->contentStartPosition());
191 d->modelVariant = model;
193 QObject *object = qvariant_cast<QObject*>(model);
194 QQuickVisualModel *vim = 0;
195 if (object && (vim = qobject_cast<QQuickVisualModel *>(object))) {
203 d->model = new QQuickVisualDataModel(qmlContext(this), this);
205 if (isComponentComplete())
206 static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
210 if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
211 dataModel->setModel(model);
215 d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
216 connect(d->model, SIGNAL(createdItem(int,QQuickItem*)), this, SLOT(createdItem(int,QQuickItem*)));
217 connect(d->model, SIGNAL(initItem(int,QQuickItem*)), this, SLOT(initItem(int,QQuickItem*)));
218 connect(d->model, SIGNAL(destroyingItem(QQuickItem*)), this, SLOT(destroyingItem(QQuickItem*)));
219 if (isComponentComplete()) {
222 if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
225 d->moveReason = QQuickItemViewPrivate::SetIndex;
226 d->updateCurrent(d->currentIndex);
227 if (d->highlight && d->currentItem) {
228 if (d->autoHighlight)
229 d->resetHighlightPosition();
230 d->updateTrackedItem();
232 d->moveReason = QQuickItemViewPrivate::Other;
236 connect(d->model, SIGNAL(modelUpdated(QDeclarativeChangeSet,bool)),
237 this, SLOT(modelUpdated(QDeclarativeChangeSet,bool)));
243 QDeclarativeComponent *QQuickItemView::delegate() const
245 Q_D(const QQuickItemView);
247 if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model))
248 return dataModel->delegate();
254 void QQuickItemView::setDelegate(QDeclarativeComponent *delegate)
257 if (delegate == this->delegate())
260 d->model = new QQuickVisualDataModel(qmlContext(this));
263 if (QQuickVisualDataModel *dataModel = qobject_cast<QQuickVisualDataModel*>(d->model)) {
264 int oldCount = dataModel->count();
265 dataModel->setDelegate(delegate);
266 if (isComponentComplete()) {
267 for (int i = 0; i < d->visibleItems.count(); ++i)
268 d->releaseItem(d->visibleItems.at(i));
269 d->visibleItems.clear();
270 d->releaseItem(d->currentItem);
274 d->moveReason = QQuickItemViewPrivate::SetIndex;
275 d->updateCurrent(d->currentIndex);
276 if (d->highlight && d->currentItem) {
277 if (d->autoHighlight)
278 d->resetHighlightPosition();
279 d->updateTrackedItem();
281 d->moveReason = QQuickItemViewPrivate::Other;
284 if (oldCount != dataModel->count())
287 emit delegateChanged();
291 int QQuickItemView::count() const
293 Q_D(const QQuickItemView);
296 const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
297 return d->model->count();
300 int QQuickItemView::currentIndex() const
302 Q_D(const QQuickItemView);
303 const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
304 return d->currentIndex;
307 void QQuickItemView::setCurrentIndex(int index)
310 if (d->requestedIndex >= 0 && !d->requestedAsync) // currently creating item
312 d->currentIndexCleared = (index == -1);
314 d->applyPendingChanges();
315 if (index == d->currentIndex)
317 if (isComponentComplete() && d->isValid()) {
318 d->moveReason = QQuickItemViewPrivate::SetIndex;
319 d->updateCurrent(index);
320 } else if (d->currentIndex != index) {
321 d->currentIndex = index;
322 emit currentIndexChanged();
327 bool QQuickItemView::isWrapEnabled() const
329 Q_D(const QQuickItemView);
333 void QQuickItemView::setWrapEnabled(bool wrap)
339 emit keyNavigationWrapsChanged();
342 int QQuickItemView::cacheBuffer() const
344 Q_D(const QQuickItemView);
348 void QQuickItemView::setCacheBuffer(int b)
351 if (d->buffer != b) {
353 if (isComponentComplete()) {
354 d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
357 emit cacheBufferChanged();
362 Qt::LayoutDirection QQuickItemView::layoutDirection() const
364 Q_D(const QQuickItemView);
365 return d->layoutDirection;
368 void QQuickItemView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
371 if (d->layoutDirection != layoutDirection) {
372 d->layoutDirection = layoutDirection;
374 emit layoutDirectionChanged();
375 emit effectiveLayoutDirectionChanged();
379 Qt::LayoutDirection QQuickItemView::effectiveLayoutDirection() const
381 Q_D(const QQuickItemView);
382 if (d->effectiveLayoutMirror)
383 return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
385 return d->layoutDirection;
389 QDeclarativeComponent *QQuickItemView::header() const
391 Q_D(const QQuickItemView);
392 return d->headerComponent;
395 QQuickItem *QQuickItemView::headerItem() const
397 Q_D(const QQuickItemView);
398 const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
399 return d->header ? d->header->item : 0;
402 void QQuickItemView::setHeader(QDeclarativeComponent *headerComponent)
405 if (d->headerComponent != headerComponent) {
406 d->applyPendingChanges();
409 d->headerComponent = headerComponent;
411 d->markExtentsDirty();
413 if (isComponentComplete()) {
419 emit headerItemChanged();
421 emit headerChanged();
425 QDeclarativeComponent *QQuickItemView::footer() const
427 Q_D(const QQuickItemView);
428 return d->footerComponent;
431 QQuickItem *QQuickItemView::footerItem() const
433 Q_D(const QQuickItemView);
434 const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
435 return d->footer ? d->footer->item : 0;
438 void QQuickItemView::setFooter(QDeclarativeComponent *footerComponent)
441 if (d->footerComponent != footerComponent) {
442 d->applyPendingChanges();
445 d->footerComponent = footerComponent;
447 if (isComponentComplete()) {
452 emit footerItemChanged();
454 emit footerChanged();
458 QDeclarativeComponent *QQuickItemView::highlight() const
460 Q_D(const QQuickItemView);
461 const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
462 return d->highlightComponent;
465 void QQuickItemView::setHighlight(QDeclarativeComponent *highlightComponent)
468 if (highlightComponent != d->highlightComponent) {
469 d->applyPendingChanges();
470 d->highlightComponent = highlightComponent;
471 d->createHighlight();
473 d->updateHighlight();
474 emit highlightChanged();
478 QQuickItem *QQuickItemView::highlightItem() const
480 Q_D(const QQuickItemView);
481 const_cast<QQuickItemViewPrivate*>(d)->applyPendingChanges();
482 return d->highlight ? d->highlight->item : 0;
485 bool QQuickItemView::highlightFollowsCurrentItem() const
487 Q_D(const QQuickItemView);
488 return d->autoHighlight;
491 void QQuickItemView::setHighlightFollowsCurrentItem(bool autoHighlight)
494 if (d->autoHighlight != autoHighlight) {
495 d->autoHighlight = autoHighlight;
497 d->updateHighlight();
498 emit highlightFollowsCurrentItemChanged();
502 QQuickItemView::HighlightRangeMode QQuickItemView::highlightRangeMode() const
504 Q_D(const QQuickItemView);
505 return static_cast<QQuickItemView::HighlightRangeMode>(d->highlightRange);
508 void QQuickItemView::setHighlightRangeMode(HighlightRangeMode mode)
511 if (d->highlightRange == mode)
513 d->highlightRange = mode;
514 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
515 emit highlightRangeModeChanged();
518 //###Possibly rename these properties, since they are very useful even without a highlight?
519 qreal QQuickItemView::preferredHighlightBegin() const
521 Q_D(const QQuickItemView);
522 return d->highlightRangeStart;
525 void QQuickItemView::setPreferredHighlightBegin(qreal start)
528 d->highlightRangeStartValid = true;
529 if (d->highlightRangeStart == start)
531 d->highlightRangeStart = start;
532 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
533 emit preferredHighlightBeginChanged();
536 void QQuickItemView::resetPreferredHighlightBegin()
539 d->highlightRangeStartValid = false;
540 if (d->highlightRangeStart == 0)
542 d->highlightRangeStart = 0;
543 emit preferredHighlightBeginChanged();
546 qreal QQuickItemView::preferredHighlightEnd() const
548 Q_D(const QQuickItemView);
549 return d->highlightRangeEnd;
552 void QQuickItemView::setPreferredHighlightEnd(qreal end)
555 d->highlightRangeEndValid = true;
556 if (d->highlightRangeEnd == end)
558 d->highlightRangeEnd = end;
559 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
560 emit preferredHighlightEndChanged();
563 void QQuickItemView::resetPreferredHighlightEnd()
566 d->highlightRangeEndValid = false;
567 if (d->highlightRangeEnd == 0)
569 d->highlightRangeEnd = 0;
570 emit preferredHighlightEndChanged();
573 int QQuickItemView::highlightMoveDuration() const
575 Q_D(const QQuickItemView);
576 return d->highlightMoveDuration;
579 void QQuickItemView::setHighlightMoveDuration(int duration)
582 if (d->highlightMoveDuration != duration) {
583 d->highlightMoveDuration = duration;
584 emit highlightMoveDurationChanged();
588 void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
593 if (mode < QQuickItemView::Beginning || mode > QQuickItemView::Contain)
596 applyPendingChanges();
597 int idx = qMax(qMin(index, model->count()-1), 0);
599 qreal pos = isContentFlowReversed() ? -position() - size() : position();
600 FxViewItem *item = visibleItem(idx);
602 if (layoutOrientation() == Qt::Vertical)
603 maxExtent = -q->maxYExtent();
605 maxExtent = isContentFlowReversed() ? q->minXExtent()-size(): -q->maxXExtent();
607 int itemPos = positionAt(idx);
608 changedVisibleIndex(idx);
609 // save the currently visible items in case any of them end up visible again
610 QList<FxViewItem *> oldVisible = visibleItems;
611 visibleItems.clear();
612 setPosition(qMin(qreal(itemPos), maxExtent));
613 // now release the reference to all the old visible items.
614 for (int i = 0; i < oldVisible.count(); ++i)
615 releaseItem(oldVisible.at(i));
616 item = visibleItem(idx);
619 const qreal itemPos = item->position();
621 case QQuickItemView::Beginning:
623 if (index < 0 && header)
626 case QQuickItemView::Center:
627 pos = itemPos - (size() - item->size())/2;
629 case QQuickItemView::End:
630 pos = itemPos - size() + item->size();
631 if (index >= model->count() && footer)
634 case QQuickItemView::Visible:
635 if (itemPos > pos + size())
636 pos = itemPos - size() + item->size();
637 else if (item->endPosition() <= pos)
640 case QQuickItemView::Contain:
641 if (item->endPosition() >= pos + size())
642 pos = itemPos - size() + item->size();
646 pos = qMin(pos, maxExtent);
648 if (layoutOrientation() == Qt::Vertical)
649 minExtent = -q->minYExtent();
651 minExtent = isContentFlowReversed() ? q->maxXExtent()-size(): -q->minXExtent();
652 pos = qMax(pos, minExtent);
653 moveReason = QQuickItemViewPrivate::Other;
659 resetHighlightPosition();
666 void QQuickItemView::positionViewAtIndex(int index, int mode)
669 if (!d->isValid() || index < 0 || index >= d->model->count())
671 d->positionViewAtIndex(index, mode);
675 void QQuickItemView::positionViewAtBeginning()
680 d->positionViewAtIndex(-1, Beginning);
683 void QQuickItemView::positionViewAtEnd()
688 d->positionViewAtIndex(d->model->count(), End);
691 int QQuickItemView::indexAt(qreal x, qreal y) const
693 Q_D(const QQuickItemView);
694 for (int i = 0; i < d->visibleItems.count(); ++i) {
695 const FxViewItem *item = d->visibleItems.at(i);
696 if (item->contains(x, y))
703 QQuickItem *QQuickItemView::itemAt(qreal x, qreal y) const
705 Q_D(const QQuickItemView);
706 for (int i = 0; i < d->visibleItems.count(); ++i) {
707 const FxViewItem *item = d->visibleItems.at(i);
708 if (item->contains(x, y))
715 void QQuickItemViewPrivate::applyPendingChanges()
718 if (q->isComponentComplete() && currentChanges.hasPendingChanges())
722 // for debugging only
723 void QQuickItemViewPrivate::checkVisible() const
726 for (int i = 0; i < visibleItems.count(); ++i) {
727 FxViewItem *item = visibleItems.at(i);
728 if (item->index == -1) {
730 } else if (item->index != visibleIndex + i - skip) {
731 qFatal("index %d %d %d", visibleIndex, i, item->index);
736 void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
739 QQuickFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
740 if (!q->isComponentComplete())
743 if (header && header->item == item) {
746 if (!q->isMoving() && !q->isFlicking())
748 } else if (footer && footer->item == item) {
751 if (!q->isMoving() && !q->isFlicking())
755 if (currentItem && currentItem->item == item)
757 if (trackedItem && trackedItem->item == item)
758 q->trackedPositionChanged();
761 void QQuickItemView::destroyRemoved()
764 for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
765 it != d->visibleItems.end();) {
766 FxViewItem *item = *it;
767 if (item->index == -1 && item->attached->delayRemove() == false) {
768 d->releaseItem(item);
769 it = d->visibleItems.erase(it);
775 // Correct the positioning of the items
777 d->forceLayout = true;
781 void QQuickItemView::modelUpdated(const QDeclarativeChangeSet &changeSet, bool reset)
785 d->moveReason = QQuickItemViewPrivate::SetIndex;
787 if (d->highlight && d->currentItem) {
788 if (d->autoHighlight)
789 d->resetHighlightPosition();
790 d->updateTrackedItem();
792 d->moveReason = QQuickItemViewPrivate::Other;
796 d->currentChanges.prepare(d->currentIndex, d->itemCount);
797 d->currentChanges.applyChanges(changeSet);
802 void QQuickItemView::animStopped()
805 d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
807 if (d->haveHighlightRange && d->highlightRange == QQuickItemView::StrictlyEnforceRange)
808 d->updateHighlight();
812 void QQuickItemView::trackedPositionChanged()
815 if (!d->trackedItem || !d->currentItem)
817 if (d->moveReason == QQuickItemViewPrivate::SetIndex) {
818 qreal trackedPos = d->trackedItem->position();
819 qreal trackedSize = d->trackedItem->size();
820 if (d->trackedItem != d->currentItem) {
821 trackedSize += d->currentItem->sectionSize();
823 qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
825 if (d->haveHighlightRange) {
826 if (trackedPos > pos + d->highlightRangeEnd - trackedSize)
827 pos = trackedPos - d->highlightRangeEnd + trackedSize;
828 if (trackedPos < pos + d->highlightRangeStart)
829 pos = trackedPos - d->highlightRangeStart;
830 if (d->highlightRange != StrictlyEnforceRange) {
831 if (pos > d->endPosition() - d->size())
832 pos = d->endPosition() - d->size();
833 if (pos < d->startPosition())
834 pos = d->startPosition();
837 qreal trackedEndPos = d->trackedItem->endPosition();
838 qreal toItemPos = d->currentItem->position();
839 qreal toItemEndPos = d->currentItem->endPosition();
841 if (d->header && d->showHeaderForIndex(d->currentIndex)) {
842 trackedPos -= d->headerSize();
843 trackedEndPos -= d->headerSize();
844 toItemPos -= d->headerSize();
845 toItemEndPos -= d->headerSize();
846 } else if (d->footer && d->showFooterForIndex(d->currentIndex)) {
847 trackedPos += d->footerSize();
848 trackedEndPos += d->footerSize();
849 toItemPos += d->footerSize();
850 toItemEndPos += d->footerSize();
853 if (trackedPos < viewPos && toItemPos < viewPos) {
854 pos = qMax(trackedPos, toItemPos);
855 } else if (trackedEndPos >= viewPos + d->size()
856 && toItemEndPos >= viewPos + d->size()) {
857 if (trackedEndPos <= toItemEndPos) {
858 pos = trackedEndPos - d->size();
859 if (trackedSize > d->size())
862 pos = toItemEndPos - d->size();
863 if (d->currentItem->size() > d->size())
864 pos = d->currentItem->position();
868 if (viewPos != pos) {
870 d->calcVelocity = true;
872 d->calcVelocity = false;
877 void QQuickItemView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
880 d->markExtentsDirty();
881 if (isComponentComplete() && d->isValid()) {
882 d->forceLayout = true;
885 QQuickFlickable::geometryChanged(newGeometry, oldGeometry);
889 qreal QQuickItemView::minYExtent() const
891 Q_D(const QQuickItemView);
892 if (d->layoutOrientation() == Qt::Horizontal)
893 return QQuickFlickable::minYExtent();
895 if (d->vData.minExtentDirty) {
896 d->minExtent = d->vData.startMargin-d->startPosition();
898 d->minExtent += d->headerSize();
899 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
900 d->minExtent += d->highlightRangeStart;
901 if (d->visibleItem(0))
902 d->minExtent -= d->visibleItem(0)->sectionSize();
903 d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd));
905 d->vData.minExtentDirty = false;
911 qreal QQuickItemView::maxYExtent() const
913 Q_D(const QQuickItemView);
914 if (d->layoutOrientation() == Qt::Horizontal)
917 if (d->vData.maxExtentDirty) {
918 if (!d->model || !d->model->count()) {
919 d->maxExtent = d->header ? -d->headerSize() : 0;
920 d->maxExtent += height();
921 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
922 d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
923 if (d->highlightRangeEnd != d->highlightRangeStart)
924 d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd));
926 d->maxExtent = -(d->endPosition() - height());
930 d->maxExtent -= d->footerSize();
931 d->maxExtent -= d->vData.endMargin;
932 qreal minY = minYExtent();
933 if (d->maxExtent > minY)
935 d->vData.maxExtentDirty = false;
940 qreal QQuickItemView::minXExtent() const
942 Q_D(const QQuickItemView);
943 if (d->layoutOrientation() == Qt::Vertical)
944 return QQuickFlickable::minXExtent();
946 if (d->hData.minExtentDirty) {
947 d->minExtent = -d->startPosition();
948 qreal highlightStart;
950 qreal endPositionFirstItem = 0;
951 if (d->isContentFlowReversed()) {
952 d->minExtent += d->hData.endMargin;
953 if (d->model && d->model->count())
954 endPositionFirstItem = d->positionAt(d->model->count()-1);
956 d->minExtent += d->headerSize();
957 highlightStart = d->highlightRangeEndValid ? d->size() - d->highlightRangeEnd : d->size();
958 highlightEnd = d->highlightRangeStartValid ? d->size() - d->highlightRangeStart : d->size();
960 d->minExtent += d->footerSize();
961 qreal maxX = maxXExtent();
962 if (d->minExtent < maxX)
965 d->minExtent += d->hData.startMargin;
966 endPositionFirstItem = d->endPositionAt(0);
967 highlightStart = d->highlightRangeStart;
968 highlightEnd = d->highlightRangeEnd;
970 d->minExtent += d->headerSize();
972 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
973 d->minExtent += highlightStart;
974 d->minExtent = d->isContentFlowReversed()
975 ? qMin(d->minExtent, endPositionFirstItem + highlightEnd)
976 : qMax(d->minExtent, -(endPositionFirstItem - highlightEnd));
978 d->hData.minExtentDirty = false;
984 qreal QQuickItemView::maxXExtent() const
986 Q_D(const QQuickItemView);
987 if (d->layoutOrientation() == Qt::Vertical)
990 if (d->hData.maxExtentDirty) {
991 qreal highlightStart;
993 qreal lastItemPosition = 0;
995 if (d->isContentFlowReversed()) {
996 highlightStart = d->highlightRangeEndValid ? d->size() - d->highlightRangeEnd : d->size();
997 highlightEnd = d->highlightRangeStartValid ? d->size() - d->highlightRangeStart : d->size();
998 lastItemPosition = d->endPosition();
1000 highlightStart = d->highlightRangeStart;
1001 highlightEnd = d->highlightRangeEnd;
1002 if (d->model && d->model->count())
1003 lastItemPosition = d->positionAt(d->model->count()-1);
1005 if (!d->model || !d->model->count()) {
1006 if (!d->isContentFlowReversed())
1007 d->maxExtent = d->header ? -d->headerSize() : 0;
1008 d->maxExtent += width();
1009 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
1010 d->maxExtent = -(lastItemPosition - highlightStart);
1011 if (highlightEnd != highlightStart) {
1012 d->maxExtent = d->isContentFlowReversed()
1013 ? qMax(d->maxExtent, -(d->endPosition() - highlightEnd))
1014 : qMin(d->maxExtent, -(d->endPosition() - highlightEnd));
1017 d->maxExtent = -(d->endPosition() - width());
1019 if (d->isContentFlowReversed()) {
1021 d->maxExtent -= d->headerSize();
1022 d->maxExtent -= d->hData.startMargin;
1025 d->maxExtent -= d->footerSize();
1026 d->maxExtent -= d->hData.endMargin;
1027 qreal minX = minXExtent();
1028 if (d->maxExtent > minX)
1029 d->maxExtent = minX;
1031 d->hData.maxExtentDirty = false;
1034 return d->maxExtent;
1037 void QQuickItemView::setContentX(qreal pos)
1039 Q_D(QQuickItemView);
1040 // Positioning the view manually should override any current movement state
1041 d->moveReason = QQuickItemViewPrivate::Other;
1042 QQuickFlickable::setContentX(pos);
1045 void QQuickItemView::setContentY(qreal pos)
1047 Q_D(QQuickItemView);
1048 // Positioning the view manually should override any current movement state
1049 d->moveReason = QQuickItemViewPrivate::Other;
1050 QQuickFlickable::setContentY(pos);
1053 qreal QQuickItemView::xOrigin() const
1055 Q_D(const QQuickItemView);
1056 if (d->isContentFlowReversed())
1057 return -maxXExtent() + d->size() - d->hData.startMargin;
1059 return -minXExtent() + d->hData.startMargin;
1062 void QQuickItemView::updatePolish()
1064 Q_D(QQuickItemView);
1065 QQuickFlickable::updatePolish();
1069 void QQuickItemView::componentComplete()
1071 Q_D(QQuickItemView);
1072 if (d->model && d->ownModel)
1073 static_cast<QQuickVisualDataModel *>(d->model.data())->componentComplete();
1075 QQuickFlickable::componentComplete();
1080 d->updateViewport();
1081 d->setPosition(d->contentStartPosition());
1084 d->moveReason = QQuickItemViewPrivate::SetIndex;
1085 if (d->currentIndex < 0 && !d->currentIndexCleared)
1086 d->updateCurrent(0);
1088 d->updateCurrent(d->currentIndex);
1089 if (d->highlight && d->currentItem) {
1090 if (d->autoHighlight)
1091 d->resetHighlightPosition();
1092 d->updateTrackedItem();
1094 d->moveReason = QQuickItemViewPrivate::Other;
1097 if (d->model && d->model->count())
1098 emit countChanged();
1103 QQuickItemViewPrivate::QQuickItemViewPrivate()
1105 , buffer(0), bufferMode(BufferBefore | BufferAfter)
1106 , layoutDirection(Qt::LeftToRight)
1109 , currentIndex(-1), currentItem(0)
1110 , trackedItem(0), requestedIndex(-1), requestedItem(0)
1111 , highlightComponent(0), highlight(0)
1112 , highlightRange(QQuickItemView::NoHighlightRange)
1113 , highlightRangeStart(0), highlightRangeEnd(0)
1114 , highlightMoveDuration(150)
1115 , headerComponent(0), header(0), footerComponent(0), footer(0)
1116 , minExtent(0), maxExtent(0)
1117 , ownModel(false), wrap(false)
1118 , inApplyModelChanges(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false)
1119 , haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
1120 , fillCacheBuffer(false), inRequest(false), requestedAsync(false)
1124 bool QQuickItemViewPrivate::isValid() const
1126 return model && model->count() && model->isValid();
1129 qreal QQuickItemViewPrivate::position() const
1131 Q_Q(const QQuickItemView);
1132 return layoutOrientation() == Qt::Vertical ? q->contentY() : q->contentX();
1135 qreal QQuickItemViewPrivate::size() const
1137 Q_Q(const QQuickItemView);
1138 return layoutOrientation() == Qt::Vertical ? q->height() : q->width();
1141 qreal QQuickItemViewPrivate::startPosition() const
1143 return isContentFlowReversed() ? -lastPosition() : originPosition();
1146 qreal QQuickItemViewPrivate::endPosition() const
1148 return isContentFlowReversed() ? -originPosition() : lastPosition();
1151 qreal QQuickItemViewPrivate::contentStartPosition() const
1153 qreal pos = -headerSize();
1154 if (layoutOrientation() == Qt::Vertical)
1155 pos -= vData.startMargin;
1156 else if (isContentFlowReversed())
1157 pos -= hData.endMargin;
1159 pos -= hData.startMargin;
1164 int QQuickItemViewPrivate::findLastVisibleIndex(int defaultValue) const
1166 if (visibleItems.count()) {
1167 int i = visibleItems.count() - 1;
1168 while (i > 0 && visibleItems.at(i)->index == -1)
1170 if (visibleItems.at(i)->index != -1)
1171 return visibleItems.at(i)->index;
1173 return defaultValue;
1176 FxViewItem *QQuickItemViewPrivate::visibleItem(int modelIndex) const {
1177 if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
1178 for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
1179 FxViewItem *item = visibleItems.at(i);
1180 if (item->index == modelIndex)
1187 FxViewItem *QQuickItemViewPrivate::firstVisibleItem() const {
1188 const qreal pos = isContentFlowReversed() ? -position()-size() : position();
1189 for (int i = 0; i < visibleItems.count(); ++i) {
1190 FxViewItem *item = visibleItems.at(i);
1191 if (item->index != -1 && item->endPosition() > pos)
1194 return visibleItems.count() ? visibleItems.first() : 0;
1197 // Map a model index to visibleItems list index.
1198 // These may differ if removed items are still present in the visible list,
1199 // e.g. doing a removal animation
1200 int QQuickItemViewPrivate::mapFromModel(int modelIndex) const
1202 if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
1204 for (int i = 0; i < visibleItems.count(); ++i) {
1205 FxViewItem *item = visibleItems.at(i);
1206 if (item->index == modelIndex)
1208 if (item->index > modelIndex)
1211 return -1; // Not in visibleList
1214 void QQuickItemViewPrivate::init()
1216 Q_Q(QQuickItemView);
1217 QQuickItemPrivate::get(contentItem)->childrenDoNotOverlap = true;
1218 q->setFlag(QQuickItem::ItemIsFocusScope);
1219 QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
1220 q->setFlickableDirection(QQuickFlickable::VerticalFlick);
1223 void QQuickItemViewPrivate::updateCurrent(int modelIndex)
1225 Q_Q(QQuickItemView);
1226 applyPendingChanges();
1227 if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
1229 currentItem->attached->setIsCurrentItem(false);
1230 releaseItem(currentItem);
1232 currentIndex = modelIndex;
1233 emit q->currentIndexChanged();
1234 emit q->currentItemChanged();
1236 } else if (currentIndex != modelIndex) {
1237 currentIndex = modelIndex;
1238 emit q->currentIndexChanged();
1243 if (currentItem && currentIndex == modelIndex) {
1248 FxViewItem *oldCurrentItem = currentItem;
1249 int oldCurrentIndex = currentIndex;
1250 currentIndex = modelIndex;
1251 currentItem = createItem(modelIndex, false);
1252 if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
1253 oldCurrentItem->attached->setIsCurrentItem(false);
1255 currentItem->item->setFocus(true);
1256 currentItem->attached->setIsCurrentItem(true);
1257 initializeCurrentItem();
1261 if (oldCurrentIndex != currentIndex)
1262 emit q->currentIndexChanged();
1263 if (oldCurrentItem != currentItem)
1264 emit q->currentItemChanged();
1265 releaseItem(oldCurrentItem);
1268 void QQuickItemViewPrivate::clear()
1270 currentChanges.reset();
1273 for (int i = 0; i < visibleItems.count(); ++i)
1274 releaseItem(visibleItems.at(i));
1275 visibleItems.clear();
1278 releaseItem(currentItem);
1288 void QQuickItemViewPrivate::mirrorChange()
1290 Q_Q(QQuickItemView);
1292 emit q->effectiveLayoutDirectionChanged();
1295 void QQuickItemViewPrivate::refill()
1297 qreal s = qMax(size(), qreal(0.));
1298 if (isContentFlowReversed())
1299 refill(-position()-s, -position());
1301 refill(position(), position()+s);
1304 void QQuickItemViewPrivate::refill(qreal from, qreal to)
1306 Q_Q(QQuickItemView);
1307 if (!isValid() || !q->isComponentComplete())
1310 currentChanges.reset();
1312 int prevCount = itemCount;
1313 itemCount = model->count();
1314 qreal bufferFrom = from - buffer;
1315 qreal bufferTo = to + buffer;
1316 qreal fillFrom = from;
1319 bool added = addVisibleItems(fillFrom, fillTo, false);
1320 bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
1322 if (buffer && bufferMode != NoBuffer) {
1323 if (bufferMode & BufferAfter)
1325 if (bufferMode & BufferBefore)
1326 fillFrom = bufferFrom;
1327 added |= addVisibleItems(fillFrom, fillTo, true);
1330 if (added || removed) {
1332 updateBeginningEnd();
1333 visibleItemsChanged();
1336 if (prevCount != itemCount)
1337 emit q->countChanged();
1340 void QQuickItemViewPrivate::regenerate()
1342 Q_Q(QQuickItemView);
1343 if (q->isComponentComplete()) {
1344 currentChanges.reset();
1353 setPosition(contentStartPosition());
1355 updateCurrent(currentIndex);
1359 void QQuickItemViewPrivate::updateViewport()
1361 Q_Q(QQuickItemView);
1363 if (layoutOrientation() == Qt::Vertical)
1364 q->setContentHeight(endPosition() - startPosition());
1366 q->setContentWidth(endPosition() - startPosition());
1370 void QQuickItemViewPrivate::layout()
1372 Q_Q(QQuickItemView);
1373 if (inApplyModelChanges)
1376 if (!isValid() && !visibleItems.count()) {
1378 setPosition(contentStartPosition());
1382 if (!applyModelChanges() && !forceLayout) {
1383 if (fillCacheBuffer) {
1384 fillCacheBuffer = false;
1389 forceLayout = false;
1391 layoutVisibleItems();
1398 if (!q->isMoving() && !q->isFlicking()) {
1406 updateUnrequestedPositions();
1409 bool QQuickItemViewPrivate::applyModelChanges()
1411 Q_Q(QQuickItemView);
1412 if (!q->isComponentComplete() || !currentChanges.hasPendingChanges() || inApplyModelChanges)
1415 inApplyModelChanges = true;
1417 updateUnrequestedIndexes();
1418 moveReason = QQuickItemViewPrivate::Other;
1420 FxViewItem *prevVisibleItemsFirst = visibleItems.count() ? visibleItems.first() : 0;
1421 int prevItemCount = itemCount;
1422 int prevVisibleItemsCount = visibleItems.count();
1423 bool visibleAffected = false;
1424 bool viewportChanged = !currentChanges.pendingChanges.removes().isEmpty()
1425 || !currentChanges.pendingChanges.inserts().isEmpty();
1427 FxViewItem *prevFirstVisible = firstVisibleItem();
1428 QDeclarativeNullableValue<qreal> prevViewPos;
1429 if (prevFirstVisible)
1430 prevViewPos = prevFirstVisible->position();
1431 qreal prevVisibleItemsFirstPos = visibleItems.count() ? visibleItems.first()->position() : 0.0;
1433 const QVector<QDeclarativeChangeSet::Remove> &removals = currentChanges.pendingChanges.removes();
1434 const QVector<QDeclarativeChangeSet::Insert> &insertions = currentChanges.pendingChanges.inserts();
1435 ChangeResult removalResult(prevViewPos);
1436 ChangeResult insertionResult(prevViewPos);
1438 int removedCount = 0;
1439 for (int i=0; i<removals.count(); i++) {
1440 itemCount -= removals[i].count;
1441 if (applyRemovalChange(removals[i], &removalResult, &removedCount))
1442 visibleAffected = true;
1443 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(removals[i].index))
1444 visibleAffected = true;
1446 if (!removals.isEmpty()) {
1447 updateVisibleIndex();
1449 // set positions correctly for the next insertion
1450 if (!insertions.isEmpty()) {
1451 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
1452 layoutVisibleItems(removals.first().index);
1456 QList<FxViewItem *> newItems;
1457 for (int i=0; i<insertions.count(); i++) {
1458 bool wasEmpty = visibleItems.isEmpty();
1459 if (applyInsertionChange(insertions[i], &insertionResult, &newItems))
1460 visibleAffected = true;
1461 if (!visibleAffected && needsRefillForAddedOrRemovedIndex(insertions[i].index))
1462 visibleAffected = true;
1463 if (wasEmpty && !visibleItems.isEmpty())
1464 resetFirstItemPosition();
1466 // set positions correctly for the next insertion
1467 if (i < insertions.count() - 1) {
1468 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
1469 layoutVisibleItems(insertions[i].index);
1472 itemCount += insertions[i].count;
1474 for (int i=0; i<newItems.count(); i++)
1475 newItems.at(i)->attached->emitAdd();
1477 // reposition visibleItems.first() correctly so that the content y doesn't jump
1478 if (removedCount != prevVisibleItemsCount)
1479 repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
1481 // Whatever removed/moved items remain are no longer visible items.
1482 for (QHash<QDeclarativeChangeSet::MoveKey, FxViewItem *>::Iterator it = currentChanges.removedItems.begin();
1483 it != currentChanges.removedItems.end(); ++it) {
1484 releaseItem(it.value());
1486 currentChanges.removedItems.clear();
1488 if (currentChanges.currentChanged) {
1489 if (currentChanges.currentRemoved && currentItem) {
1490 currentItem->attached->setIsCurrentItem(false);
1491 releaseItem(currentItem);
1494 if (!currentIndexCleared)
1495 updateCurrent(currentChanges.newCurrentIndex);
1497 currentChanges.reset();
1500 if (prevItemCount != itemCount)
1501 emit q->countChanged();
1503 if (!visibleAffected)
1504 visibleAffected = !currentChanges.pendingChanges.changes().isEmpty();
1505 if (!visibleAffected && viewportChanged)
1508 inApplyModelChanges = false;
1509 return visibleAffected;
1512 bool QQuickItemViewPrivate::applyRemovalChange(const QDeclarativeChangeSet::Remove &removal, ChangeResult *removeResult, int *removedCount)
1514 Q_Q(QQuickItemView);
1515 bool visibleAffected = false;
1517 QList<FxViewItem*>::Iterator it = visibleItems.begin();
1518 while (it != visibleItems.end()) {
1519 FxViewItem *item = *it;
1520 if (item->index == -1 || item->index < removal.index) {
1521 // already removed, or before removed items
1522 if (!visibleAffected && item->index < removal.index)
1523 visibleAffected = true;
1525 } else if (item->index >= removal.index + removal.count) {
1526 // after removed items
1527 item->index -= removal.count;
1531 visibleAffected = true;
1532 if (!removal.isMove())
1533 item->attached->emitRemove();
1535 if (item->attached->delayRemove() && !removal.isMove()) {
1537 QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
1540 if (removeResult->visiblePos.isValid()) {
1541 if (item->position() < removeResult->visiblePos)
1542 removeResult->sizeChangesBeforeVisiblePos += item->size();
1544 removeResult->sizeChangesAfterVisiblePos += item->size();
1546 if (removal.isMove()) {
1547 currentChanges.removedItems.insert(removal.moveKey(item->index), item);
1549 // track item so it is released later
1550 currentChanges.removedItems.insertMulti(QDeclarativeChangeSet::MoveKey(), item);
1553 if (!removeResult->changedFirstItem && item == visibleItems.first())
1554 removeResult->changedFirstItem = true;
1555 it = visibleItems.erase(it);
1560 if (removal.index + removal.count < visibleIndex)
1561 removeResult->changeBeforeVisible -= removal.count;
1563 return visibleAffected;
1566 void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirst,
1567 qreal prevVisibleItemsFirstPos,
1568 FxViewItem *prevFirstVisible,
1569 ChangeResult *insertionResult,
1570 ChangeResult *removalResult)
1572 const QDeclarativeNullableValue<qreal> prevViewPos = insertionResult->visiblePos;
1574 // reposition visibleItems.first() correctly so that the content y doesn't jump
1575 if (visibleItems.count()) {
1576 if (prevVisibleItemsFirst && insertionResult->changedFirstItem)
1577 resetFirstItemPosition(prevVisibleItemsFirstPos);
1579 if (prevFirstVisible && prevVisibleItemsFirst == prevFirstVisible
1580 && prevFirstVisible != *visibleItems.constBegin()) {
1581 // the previous visibleItems.first() was also the first visible item, and it has been
1582 // moved/removed, so move the new visibleItems.first() to the pos of the previous one
1583 if (!insertionResult->changedFirstItem)
1584 resetFirstItemPosition(prevVisibleItemsFirstPos);
1586 } else if (prevViewPos.isValid()) {
1587 qreal moveForwardsBy = 0;
1588 qreal moveBackwardsBy = 0;
1590 // shift visibleItems.first() relative to the number of added/removed items
1591 if (visibleItems.first()->position() > prevViewPos) {
1592 moveForwardsBy = insertionResult->sizeChangesAfterVisiblePos;
1593 moveBackwardsBy = removalResult->sizeChangesAfterVisiblePos;
1594 } else if (visibleItems.first()->position() < prevViewPos) {
1595 moveForwardsBy = removalResult->sizeChangesBeforeVisiblePos;
1596 moveBackwardsBy = insertionResult->sizeChangesBeforeVisiblePos;
1598 adjustFirstItem(moveForwardsBy, moveBackwardsBy, insertionResult->changeBeforeVisible + removalResult->changeBeforeVisible);
1600 insertionResult->reset();
1601 removalResult->reset();
1606 This may return 0 if the item is being created asynchronously.
1607 When the item becomes available, refill() will be called and the item
1608 will be returned on the next call to createItem().
1610 FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous)
1612 Q_Q(QQuickItemView);
1613 if (requestedIndex == modelIndex && (asynchronous || requestedAsync == asynchronous))
1616 if (requestedIndex != -1 && requestedIndex != modelIndex) {
1617 if (requestedItem && requestedItem->item)
1618 requestedItem->item->setParentItem(0);
1619 delete requestedItem;
1623 requestedIndex = modelIndex;
1624 requestedAsync = asynchronous;
1627 if (QQuickItem *item = model->item(modelIndex, asynchronous)) {
1628 item->setParentItem(q->contentItem());
1629 QDeclarative_setParent_noEvent(item, q->contentItem());
1630 requestedIndex = -1;
1631 FxViewItem *viewItem = requestedItem;
1633 viewItem = newViewItem(modelIndex, item); // already in cache, so viewItem not initialized in initItem()
1635 viewItem->index = modelIndex;
1636 // do other set up for the new item that should not happen
1637 // until after bindings are evaluated
1638 initializeViewItem(viewItem);
1639 unrequestedItems.remove(item);
1650 void QQuickItemView::createdItem(int index, QQuickItem *item)
1652 Q_D(QQuickItemView);
1653 if (d->requestedIndex != index) {
1654 item->setParentItem(contentItem());
1655 d->unrequestedItems.insert(item, index);
1656 item->setVisible(false);
1657 d->repositionPackageItemAt(item, index);
1659 d->requestedIndex = -1;
1660 if (!d->inRequest) {
1661 if (index == d->currentIndex)
1662 d->updateCurrent(index);
1668 void QQuickItemView::initItem(int index, QQuickItem *item)
1670 Q_D(QQuickItemView);
1672 if (d->requestedIndex == index) {
1673 item->setParentItem(contentItem());
1674 QDeclarative_setParent_noEvent(item, contentItem());
1675 d->requestedItem = d->newViewItem(index, item);
1679 void QQuickItemView::destroyingItem(QQuickItem *item)
1681 Q_D(QQuickItemView);
1682 d->unrequestedItems.remove(item);
1685 void QQuickItemViewPrivate::releaseItem(FxViewItem *item)
1687 Q_Q(QQuickItemView);
1688 if (!item || !model)
1690 if (trackedItem == item)
1692 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item->item);
1693 itemPrivate->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
1694 if (model->release(item->item) == 0) {
1695 // item was not destroyed, and we no longer reference it.
1696 item->item->setVisible(false);
1697 unrequestedItems.insert(item->item, model->indexOf(item->item, q));
1702 QQuickItem *QQuickItemViewPrivate::createHighlightItem()
1704 return createComponentItem(highlightComponent, true, true);
1707 QQuickItem *QQuickItemViewPrivate::createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault)
1709 Q_Q(QQuickItemView);
1711 QQuickItem *item = 0;
1713 QDeclarativeContext *creationContext = component->creationContext();
1714 QDeclarativeContext *context = new QDeclarativeContext(
1715 creationContext ? creationContext : qmlContext(q));
1716 QObject *nobj = component->create(context);
1718 QDeclarative_setParent_noEvent(context, nobj);
1719 item = qobject_cast<QQuickItem *>(nobj);
1725 } else if (createDefault) {
1726 item = new QQuickItem;
1729 QDeclarative_setParent_noEvent(item, q->contentItem());
1730 item->setParentItem(q->contentItem());
1731 if (receiveItemGeometryChanges) {
1732 QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
1733 itemPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry);
1739 void QQuickItemViewPrivate::updateTrackedItem()
1741 Q_Q(QQuickItemView);
1742 FxViewItem *item = currentItem;
1748 q->trackedPositionChanged();
1751 void QQuickItemViewPrivate::updateUnrequestedIndexes()
1753 Q_Q(QQuickItemView);
1754 for (QHash<QQuickItem*,int>::iterator it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
1755 *it = model->indexOf(it.key(), q);
1758 void QQuickItemViewPrivate::updateUnrequestedPositions()
1760 for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
1761 repositionPackageItemAt(it.key(), it.value());
1764 void QQuickItemViewPrivate::updateVisibleIndex()
1767 for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end(); ++it) {
1768 if ((*it)->index != -1) {
1769 visibleIndex = (*it)->index;