-
Jani Heikkinen authored
- Renamed LICENSE.LGPL to LICENSE.LGPLv21 - Added LICENSE.LGPLv3 & LICENSE.GPLv2 - Removed LICENSE.GPL Change-Id: I84a565e2e0caa3b76bf291a7d188a57a4b00e1b0 Reviewed-by:
Jani Heikkinen <jani.heikkinen@digia.com>
e7ceacda
/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtQuick module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qquickitemview_p_p.h"
#include <QtQuick/private/qquicktransition_p.h>
#include <QtQml/QQmlInfo>
#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcItemViewDelegateLifecycle, "qt.quick.itemview.lifecycle")
// Default cacheBuffer for all views.
#ifndef QML_VIEW_DEFAULTCACHEBUFFER
#define QML_VIEW_DEFAULTCACHEBUFFER 320
#endif
FxViewItem::FxViewItem(QQuickItem *i, QQuickItemView *v, bool own, QQuickItemViewAttached *attached)
: item(i)
, view(v)
, transitionableItem(0)
, attached(attached)
, ownItem(own)
, releaseAfterTransition(false)
, trackGeom(false)
{
if (attached) // can be null for default components (see createComponentItem)
attached->setView(view);
}
FxViewItem::~FxViewItem()
{
delete transitionableItem;
if (ownItem && item) {
trackGeometry(false);
item->setParentItem(0);
item->deleteLater();
item = 0;
}
}
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
qreal FxViewItem::itemX() const
{
return transitionableItem ? transitionableItem->itemX() : item->x();
}
qreal FxViewItem::itemY() const
{
return transitionableItem ? transitionableItem->itemY() : item->y();
}
void FxViewItem::moveTo(const QPointF &pos, bool immediate)
{
if (transitionableItem)
transitionableItem->moveTo(pos, immediate);
else
item->setPosition(pos);
}
void FxViewItem::setVisible(bool visible)
{
if (!visible && transitionableItem && transitionableItem->transitionScheduledOrRunning())
return;
QQuickItemPrivate::get(item)->setCulled(!visible);
}
void FxViewItem::trackGeometry(bool track)
{
if (track) {
if (!trackGeom) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
trackGeom = true;
}
} else {
if (trackGeom) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->removeItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
trackGeom = false;
}
}
}
QQuickItemViewTransitioner::TransitionType FxViewItem::scheduledTransitionType() const
{
return transitionableItem ? transitionableItem->nextTransitionType : QQuickItemViewTransitioner::NoTransition;
}
bool FxViewItem::transitionScheduledOrRunning() const
{
return transitionableItem ? transitionableItem->transitionScheduledOrRunning() : false;
}
bool FxViewItem::transitionRunning() const
{
return transitionableItem ? transitionableItem->transitionRunning() : false;
}
bool FxViewItem::isPendingRemoval() const
{
return transitionableItem ? transitionableItem->isPendingRemoval() : false;
}
void FxViewItem::transitionNextReposition(QQuickItemViewTransitioner *transitioner, QQuickItemViewTransitioner::TransitionType type, bool asTarget)
{
if (!transitioner)
return;
if (!transitionableItem)
transitionableItem = new QQuickItemViewTransitionableItem(item);
transitioner->transitionNextReposition(transitionableItem, type, asTarget);
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
}
bool FxViewItem::prepareTransition(QQuickItemViewTransitioner *transitioner, const QRectF &viewBounds)
{
return transitionableItem ? transitionableItem->prepareTransition(transitioner, index, viewBounds) : false;
}
void FxViewItem::startTransition(QQuickItemViewTransitioner *transitioner)
{
if (transitionableItem)
transitionableItem->startTransition(transitioner, index);
}
QQuickItemViewChangeSet::QQuickItemViewChangeSet()
: active(false)
{
reset();
}
bool QQuickItemViewChangeSet::hasPendingChanges() const
{
return !pendingChanges.isEmpty();
}
void QQuickItemViewChangeSet::applyChanges(const QQmlChangeSet &changeSet)
{
pendingChanges.apply(changeSet);
int moveId = -1;
int moveOffset = 0;
foreach (const QQmlChangeSet::Change &r, changeSet.removes()) {
itemCount -= r.count;
if (moveId == -1 && newCurrentIndex >= r.index + r.count) {
newCurrentIndex -= r.count;
currentChanged = true;
} else if (moveId == -1 && newCurrentIndex >= r.index && newCurrentIndex < r.index + r.count) {
// current item has been removed.
if (r.isMove()) {
moveId = r.moveId;
moveOffset = newCurrentIndex - r.index;
} else {
currentRemoved = true;
newCurrentIndex = -1;
if (itemCount)
newCurrentIndex = qMin(r.index, itemCount - 1);
}
currentChanged = true;
}
}
foreach (const QQmlChangeSet::Change &i, changeSet.inserts()) {
if (moveId == -1) {
if (itemCount && newCurrentIndex >= i.index) {
newCurrentIndex += i.count;
currentChanged = true;
} else if (newCurrentIndex < 0) {
newCurrentIndex = 0;
currentChanged = true;
} else if (newCurrentIndex == 0 && !itemCount) {
// this is the first item, set the initial current index
currentChanged = true;
}
} else if (moveId == i.moveId) {
newCurrentIndex = i.index + moveOffset;
}
itemCount += i.count;
}
}
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
void QQuickItemViewChangeSet::applyBufferedChanges(const QQuickItemViewChangeSet &other)
{
if (!other.hasPendingChanges())
return;
pendingChanges.apply(other.pendingChanges);
itemCount = other.itemCount;
newCurrentIndex = other.newCurrentIndex;
currentChanged = other.currentChanged;
currentRemoved = other.currentRemoved;
}
void QQuickItemViewChangeSet::prepare(int currentIndex, int count)
{
if (active)
return;
reset();
active = true;
itemCount = count;
newCurrentIndex = currentIndex;
}
void QQuickItemViewChangeSet::reset()
{
itemCount = 0;
newCurrentIndex = -1;
pendingChanges.clear();
removedItems.clear();
active = false;
currentChanged = false;
currentRemoved = false;
}
//-----------------------------------
QQuickItemView::QQuickItemView(QQuickFlickablePrivate &dd, QQuickItem *parent)
: QQuickFlickable(dd, parent)
{
Q_D(QQuickItemView);
d->init();
}
QQuickItemView::~QQuickItemView()
{
Q_D(QQuickItemView);
d->clear();
if (d->ownModel)
delete d->model;
delete d->header;
delete d->footer;
}
QQuickItem *QQuickItemView::currentItem() const
{
Q_D(const QQuickItemView);
return d->currentItem ? d->currentItem->item : 0;
}
QVariant QQuickItemView::model() const
{
Q_D(const QQuickItemView);
return d->modelVariant;
}
void QQuickItemView::setModel(const QVariant &model)
{
Q_D(QQuickItemView);
if (d->modelVariant == model)
return;
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
if (d->model) {
disconnect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
this, SLOT(modelUpdated(QQmlChangeSet,bool)));
disconnect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
disconnect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
disconnect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
}
QQmlInstanceModel *oldModel = d->model;
d->clear();
d->model = 0;
d->setPosition(d->contentStartOffset());
d->modelVariant = model;
QObject *object = qvariant_cast<QObject*>(model);
QQmlInstanceModel *vim = 0;
if (object && (vim = qobject_cast<QQmlInstanceModel *>(object))) {
if (d->ownModel) {
delete oldModel;
d->ownModel = false;
}
d->model = vim;
} else {
if (!d->ownModel) {
d->model = new QQmlDelegateModel(qmlContext(this), this);
d->ownModel = true;
if (isComponentComplete())
static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
} else {
d->model = oldModel;
}
if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
dataModel->setModel(model);
}
if (d->model) {
d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
connect(d->model, SIGNAL(createdItem(int,QObject*)), this, SLOT(createdItem(int,QObject*)));
connect(d->model, SIGNAL(initItem(int,QObject*)), this, SLOT(initItem(int,QObject*)));
connect(d->model, SIGNAL(destroyingItem(QObject*)), this, SLOT(destroyingItem(QObject*)));
if (isComponentComplete()) {
d->updateSectionCriteria();
d->refill();
d->currentIndex = -1;
setCurrentIndex(d->model->count() > 0 ? 0 : -1);
d->updateViewport();
if (d->transitioner && d->transitioner->populateTransition) {
d->transitioner->setPopulateTransitionEnabled(true);
d->forceLayoutPolish();
}
}
connect(d->model, SIGNAL(modelUpdated(QQmlChangeSet,bool)),
this, SLOT(modelUpdated(QQmlChangeSet,bool)));
emit countChanged();
}
emit modelChanged();
}
QQmlComponent *QQuickItemView::delegate() const
{
Q_D(const QQuickItemView);
if (d->model) {
if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model))
return dataModel->delegate();
}
return 0;
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
}
void QQuickItemView::setDelegate(QQmlComponent *delegate)
{
Q_D(QQuickItemView);
if (delegate == this->delegate())
return;
if (!d->ownModel) {
d->model = new QQmlDelegateModel(qmlContext(this));
d->ownModel = true;
if (isComponentComplete())
static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
}
if (QQmlDelegateModel *dataModel = qobject_cast<QQmlDelegateModel*>(d->model)) {
int oldCount = dataModel->count();
dataModel->setDelegate(delegate);
if (isComponentComplete()) {
for (int i = 0; i < d->visibleItems.count(); ++i)
d->releaseItem(d->visibleItems.at(i));
d->visibleItems.clear();
d->releaseItem(d->currentItem);
d->currentItem = 0;
d->updateSectionCriteria();
d->refill();
d->moveReason = QQuickItemViewPrivate::SetIndex;
d->updateCurrent(d->currentIndex);
if (d->highlight && d->currentItem) {
if (d->autoHighlight)
d->resetHighlightPosition();
d->updateTrackedItem();
}
d->moveReason = QQuickItemViewPrivate::Other;
d->updateViewport();
}
if (oldCount != dataModel->count())
emit countChanged();
}
emit delegateChanged();
d->delegateValidated = false;
}
int QQuickItemView::count() const
{
Q_D(const QQuickItemView);
if (!d->model)
return 0;
return d->model->count();
}
int QQuickItemView::currentIndex() const
{
Q_D(const QQuickItemView);
return d->currentIndex;
}
void QQuickItemView::setCurrentIndex(int index)
{
Q_D(QQuickItemView);
if (d->inRequest) // currently creating item
return;
d->currentIndexCleared = (index == -1);
d->applyPendingChanges();
if (index == d->currentIndex)
return;
if (isComponentComplete() && d->isValid()) {
d->moveReason = QQuickItemViewPrivate::SetIndex;
d->updateCurrent(index);
} else if (d->currentIndex != index) {
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
d->currentIndex = index;
emit currentIndexChanged();
}
}
bool QQuickItemView::isWrapEnabled() const
{
Q_D(const QQuickItemView);
return d->wrap;
}
void QQuickItemView::setWrapEnabled(bool wrap)
{
Q_D(QQuickItemView);
if (d->wrap == wrap)
return;
d->wrap = wrap;
emit keyNavigationWrapsChanged();
}
int QQuickItemView::cacheBuffer() const
{
Q_D(const QQuickItemView);
return d->buffer;
}
void QQuickItemView::setCacheBuffer(int b)
{
Q_D(QQuickItemView);
if (b < 0) {
qmlInfo(this) << "Cannot set a negative cache buffer";
return;
}
if (d->buffer != b) {
d->buffer = b;
if (isComponentComplete()) {
d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
d->refillOrLayout();
}
emit cacheBufferChanged();
}
}
int QQuickItemView::displayMarginBeginning() const
{
Q_D(const QQuickItemView);
return d->displayMarginBeginning;
}
void QQuickItemView::setDisplayMarginBeginning(int margin)
{
Q_D(QQuickItemView);
if (d->displayMarginBeginning != margin) {
d->displayMarginBeginning = margin;
if (isComponentComplete()) {
d->forceLayoutPolish();
}
emit displayMarginBeginningChanged();
}
}
int QQuickItemView::displayMarginEnd() const
{
Q_D(const QQuickItemView);
return d->displayMarginEnd;
}
void QQuickItemView::setDisplayMarginEnd(int margin)
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
{
Q_D(QQuickItemView);
if (d->displayMarginEnd != margin) {
d->displayMarginEnd = margin;
if (isComponentComplete()) {
d->forceLayoutPolish();
}
emit displayMarginEndChanged();
}
}
Qt::LayoutDirection QQuickItemView::layoutDirection() const
{
Q_D(const QQuickItemView);
return d->layoutDirection;
}
void QQuickItemView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
{
Q_D(QQuickItemView);
if (d->layoutDirection != layoutDirection) {
d->layoutDirection = layoutDirection;
d->regenerate();
emit layoutDirectionChanged();
emit effectiveLayoutDirectionChanged();
}
}
Qt::LayoutDirection QQuickItemView::effectiveLayoutDirection() const
{
Q_D(const QQuickItemView);
if (d->effectiveLayoutMirror)
return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
else
return d->layoutDirection;
}
QQuickItemView::VerticalLayoutDirection QQuickItemView::verticalLayoutDirection() const
{
Q_D(const QQuickItemView);
return d->verticalLayoutDirection;
}
void QQuickItemView::setVerticalLayoutDirection(VerticalLayoutDirection layoutDirection)
{
Q_D(QQuickItemView);
if (d->verticalLayoutDirection != layoutDirection) {
d->verticalLayoutDirection = layoutDirection;
d->regenerate();
emit verticalLayoutDirectionChanged();
}
}
QQmlComponent *QQuickItemView::header() const
{
Q_D(const QQuickItemView);
return d->headerComponent;
}
QQuickItem *QQuickItemView::headerItem() const
{
Q_D(const QQuickItemView);
return d->header ? d->header->item : 0;
}
void QQuickItemView::setHeader(QQmlComponent *headerComponent)
{
Q_D(QQuickItemView);
if (d->headerComponent != headerComponent) {
d->applyPendingChanges();
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
delete d->header;
d->header = 0;
d->headerComponent = headerComponent;
d->markExtentsDirty();
if (isComponentComplete()) {
d->updateHeader();
d->updateFooter();
d->updateViewport();
d->fixupPosition();
} else {
emit headerItemChanged();
}
emit headerChanged();
}
}
QQmlComponent *QQuickItemView::footer() const
{
Q_D(const QQuickItemView);
return d->footerComponent;
}
QQuickItem *QQuickItemView::footerItem() const
{
Q_D(const QQuickItemView);
return d->footer ? d->footer->item : 0;
}
void QQuickItemView::setFooter(QQmlComponent *footerComponent)
{
Q_D(QQuickItemView);
if (d->footerComponent != footerComponent) {
d->applyPendingChanges();
delete d->footer;
d->footer = 0;
d->footerComponent = footerComponent;
if (isComponentComplete()) {
d->updateFooter();
d->updateViewport();
d->fixupPosition();
} else {
emit footerItemChanged();
}
emit footerChanged();
}
}
QQmlComponent *QQuickItemView::highlight() const
{
Q_D(const QQuickItemView);
return d->highlightComponent;
}
void QQuickItemView::setHighlight(QQmlComponent *highlightComponent)
{
Q_D(QQuickItemView);
if (highlightComponent != d->highlightComponent) {
d->applyPendingChanges();
d->highlightComponent = highlightComponent;
d->createHighlight();
if (d->currentItem)
d->updateHighlight();
emit highlightChanged();
}
}
QQuickItem *QQuickItemView::highlightItem() const
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
{
Q_D(const QQuickItemView);
return d->highlight ? d->highlight->item : 0;
}
bool QQuickItemView::highlightFollowsCurrentItem() const
{
Q_D(const QQuickItemView);
return d->autoHighlight;
}
void QQuickItemView::setHighlightFollowsCurrentItem(bool autoHighlight)
{
Q_D(QQuickItemView);
if (d->autoHighlight != autoHighlight) {
d->autoHighlight = autoHighlight;
if (autoHighlight)
d->updateHighlight();
emit highlightFollowsCurrentItemChanged();
}
}
QQuickItemView::HighlightRangeMode QQuickItemView::highlightRangeMode() const
{
Q_D(const QQuickItemView);
return static_cast<QQuickItemView::HighlightRangeMode>(d->highlightRange);
}
void QQuickItemView::setHighlightRangeMode(HighlightRangeMode mode)
{
Q_D(QQuickItemView);
if (d->highlightRange == mode)
return;
d->highlightRange = mode;
d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
if (isComponentComplete()) {
d->updateViewport();
d->fixupPosition();
}
emit highlightRangeModeChanged();
}
//###Possibly rename these properties, since they are very useful even without a highlight?
qreal QQuickItemView::preferredHighlightBegin() const
{
Q_D(const QQuickItemView);
return d->highlightRangeStart;
}
void QQuickItemView::setPreferredHighlightBegin(qreal start)
{
Q_D(QQuickItemView);
d->highlightRangeStartValid = true;
if (d->highlightRangeStart == start)
return;
d->highlightRangeStart = start;
d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
if (isComponentComplete()) {
d->updateViewport();
if (!isMoving() && !isFlicking())
d->fixupPosition();
}
emit preferredHighlightBeginChanged();
}
void QQuickItemView::resetPreferredHighlightBegin()
{
Q_D(QQuickItemView);
d->highlightRangeStartValid = false;
if (d->highlightRangeStart == 0)
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
return;
d->highlightRangeStart = 0;
if (isComponentComplete()) {
d->updateViewport();
if (!isMoving() && !isFlicking())
d->fixupPosition();
}
emit preferredHighlightBeginChanged();
}
qreal QQuickItemView::preferredHighlightEnd() const
{
Q_D(const QQuickItemView);
return d->highlightRangeEnd;
}
void QQuickItemView::setPreferredHighlightEnd(qreal end)
{
Q_D(QQuickItemView);
d->highlightRangeEndValid = true;
if (d->highlightRangeEnd == end)
return;
d->highlightRangeEnd = end;
d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
if (isComponentComplete()) {
d->updateViewport();
if (!isMoving() && !isFlicking())
d->fixupPosition();
}
emit preferredHighlightEndChanged();
}
void QQuickItemView::resetPreferredHighlightEnd()
{
Q_D(QQuickItemView);
d->highlightRangeEndValid = false;
if (d->highlightRangeEnd == 0)
return;
d->highlightRangeEnd = 0;
if (isComponentComplete()) {
d->updateViewport();
if (!isMoving() && !isFlicking())
d->fixupPosition();
}
emit preferredHighlightEndChanged();
}
int QQuickItemView::highlightMoveDuration() const
{
Q_D(const QQuickItemView);
return d->highlightMoveDuration;
}
void QQuickItemView::setHighlightMoveDuration(int duration)
{
Q_D(QQuickItemView);
if (d->highlightMoveDuration != duration) {
d->highlightMoveDuration = duration;
emit highlightMoveDurationChanged();
}
}
QQuickTransition *QQuickItemView::populateTransition() const
{
Q_D(const QQuickItemView);
return d->transitioner ? d->transitioner->populateTransition : 0;
}
void QQuickItemView::setPopulateTransition(QQuickTransition *transition)
{
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
Q_D(QQuickItemView);
d->createTransitioner();
if (d->transitioner->populateTransition != transition) {
d->transitioner->populateTransition = transition;
emit populateTransitionChanged();
}
}
QQuickTransition *QQuickItemView::addTransition() const
{
Q_D(const QQuickItemView);
return d->transitioner ? d->transitioner->addTransition : 0;
}
void QQuickItemView::setAddTransition(QQuickTransition *transition)
{
Q_D(QQuickItemView);
d->createTransitioner();
if (d->transitioner->addTransition != transition) {
d->transitioner->addTransition = transition;
emit addTransitionChanged();
}
}
QQuickTransition *QQuickItemView::addDisplacedTransition() const
{
Q_D(const QQuickItemView);
return d->transitioner ? d->transitioner->addDisplacedTransition : 0;
}
void QQuickItemView::setAddDisplacedTransition(QQuickTransition *transition)
{
Q_D(QQuickItemView);
d->createTransitioner();
if (d->transitioner->addDisplacedTransition != transition) {
d->transitioner->addDisplacedTransition = transition;
emit addDisplacedTransitionChanged();
}
}
QQuickTransition *QQuickItemView::moveTransition() const
{
Q_D(const QQuickItemView);
return d->transitioner ? d->transitioner->moveTransition : 0;
}
void QQuickItemView::setMoveTransition(QQuickTransition *transition)
{
Q_D(QQuickItemView);
d->createTransitioner();
if (d->transitioner->moveTransition != transition) {
d->transitioner->moveTransition = transition;
emit moveTransitionChanged();
}
}
QQuickTransition *QQuickItemView::moveDisplacedTransition() const
{
Q_D(const QQuickItemView);
return d->transitioner ? d->transitioner->moveDisplacedTransition : 0;
}
void QQuickItemView::setMoveDisplacedTransition(QQuickTransition *transition)
{
Q_D(QQuickItemView);
d->createTransitioner();
if (d->transitioner->moveDisplacedTransition != transition) {
d->transitioner->moveDisplacedTransition = transition;
emit moveDisplacedTransitionChanged();
}
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
}
QQuickTransition *QQuickItemView::removeTransition() const
{
Q_D(const QQuickItemView);
return d->transitioner ? d->transitioner->removeTransition : 0;
}
void QQuickItemView::setRemoveTransition(QQuickTransition *transition)
{
Q_D(QQuickItemView);
d->createTransitioner();
if (d->transitioner->removeTransition != transition) {
d->transitioner->removeTransition = transition;
emit removeTransitionChanged();
}
}
QQuickTransition *QQuickItemView::removeDisplacedTransition() const
{
Q_D(const QQuickItemView);
return d->transitioner ? d->transitioner->removeDisplacedTransition : 0;
}
void QQuickItemView::setRemoveDisplacedTransition(QQuickTransition *transition)
{
Q_D(QQuickItemView);
d->createTransitioner();
if (d->transitioner->removeDisplacedTransition != transition) {
d->transitioner->removeDisplacedTransition = transition;
emit removeDisplacedTransitionChanged();
}
}
QQuickTransition *QQuickItemView::displacedTransition() const
{
Q_D(const QQuickItemView);
return d->transitioner ? d->transitioner->displacedTransition : 0;
}
void QQuickItemView::setDisplacedTransition(QQuickTransition *transition)
{
Q_D(QQuickItemView);
d->createTransitioner();
if (d->transitioner->displacedTransition != transition) {
d->transitioner->displacedTransition = transition;
emit displacedTransitionChanged();
}
}
void QQuickItemViewPrivate::positionViewAtIndex(int index, int mode)
{
Q_Q(QQuickItemView);
if (!isValid())
return;
if (mode < QQuickItemView::Beginning || mode > QQuickItemView::SnapPosition)
return;
applyPendingChanges();
int idx = qMax(qMin(index, model->count()-1), 0);
qreal pos = isContentFlowReversed() ? -position() - size() : position();
FxViewItem *item = visibleItem(idx);
qreal maxExtent;
if (layoutOrientation() == Qt::Vertical)
maxExtent = isContentFlowReversed() ? q->minYExtent()-size(): -q->maxYExtent();
else
maxExtent = isContentFlowReversed() ? q->minXExtent()-size(): -q->maxXExtent();
if (!item) {
qreal itemPos = positionAt(idx);
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
changedVisibleIndex(idx);
// save the currently visible items in case any of them end up visible again
QList<FxViewItem *> oldVisible = visibleItems;
visibleItems.clear();
setPosition(qMin(itemPos, maxExtent));
// now release the reference to all the old visible items.
for (int i = 0; i < oldVisible.count(); ++i)
releaseItem(oldVisible.at(i));
item = visibleItem(idx);
}
if (item) {
const qreal itemPos = item->position();
switch (mode) {
case QQuickItemView::Beginning:
pos = itemPos;
if (index < 0 && header)
pos -= headerSize();
break;
case QQuickItemView::Center:
pos = itemPos - (size() - item->size())/2;
break;
case QQuickItemView::End:
pos = itemPos - size() + item->size();
if (index >= model->count() && footer)
pos += footerSize();
break;
case QQuickItemView::Visible:
if (itemPos > pos + size())
pos = itemPos - size() + item->size();
else if (item->endPosition() <= pos)
pos = itemPos;
break;
case QQuickItemView::Contain:
if (item->endPosition() >= pos + size())
pos = itemPos - size() + item->size();
if (itemPos < pos)
pos = itemPos;
break;
case QQuickItemView::SnapPosition:
pos = itemPos - highlightRangeStart;
break;
}
pos = qMin(pos, maxExtent);
qreal minExtent;
if (layoutOrientation() == Qt::Vertical)
minExtent = isContentFlowReversed() ? q->maxYExtent()-size(): -q->minYExtent();
else
minExtent = isContentFlowReversed() ? q->maxXExtent()-size(): -q->minXExtent();
pos = qMax(pos, minExtent);
moveReason = QQuickItemViewPrivate::Other;
q->cancelFlick();
setPosition(pos);
if (highlight) {
if (autoHighlight)
resetHighlightPosition();
updateHighlight();
}
}
fixupPosition();
}
void QQuickItemView::positionViewAtIndex(int index, int mode)
{
Q_D(QQuickItemView);
if (!d->isValid() || index < 0 || index >= d->model->count())
return;
d->positionViewAtIndex(index, mode);
}
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
void QQuickItemView::positionViewAtBeginning()
{
Q_D(QQuickItemView);
if (!d->isValid())
return;
d->positionViewAtIndex(-1, Beginning);
}
void QQuickItemView::positionViewAtEnd()
{
Q_D(QQuickItemView);
if (!d->isValid())
return;
d->positionViewAtIndex(d->model->count(), End);
}
int QQuickItemView::indexAt(qreal x, qreal y) const
{
Q_D(const QQuickItemView);
for (int i = 0; i < d->visibleItems.count(); ++i) {
const FxViewItem *item = d->visibleItems.at(i);
if (item->contains(x, y))
return item->index;
}
return -1;
}
QQuickItem *QQuickItemView::itemAt(qreal x, qreal y) const
{
Q_D(const QQuickItemView);
for (int i = 0; i < d->visibleItems.count(); ++i) {
const FxViewItem *item = d->visibleItems.at(i);
if (item->contains(x, y))
return item->item;
}
return 0;
}
void QQuickItemView::forceLayout()
{
Q_D(QQuickItemView);
d->applyPendingChanges();
}
void QQuickItemViewPrivate::applyPendingChanges()
{
Q_Q(QQuickItemView);
if (q->isComponentComplete() && currentChanges.hasPendingChanges())
layout();
}
int QQuickItemViewPrivate::findMoveKeyIndex(QQmlChangeSet::MoveKey key, const QVector<QQmlChangeSet::Change> &changes) const
{
for (int i=0; i<changes.count(); i++) {
for (int j=changes[i].index; j<changes[i].index + changes[i].count; j++) {
if (changes[i].moveKey(j) == key)
return j;
}
}
return -1;
}
qreal QQuickItemViewPrivate::minExtentForAxis(const AxisData &axisData, bool forXAxis) const
{
Q_Q(const QQuickItemView);
qreal highlightStart;
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
qreal highlightEnd;
qreal endPositionFirstItem = 0;
qreal extent = -startPosition() + axisData.startMargin;
if (isContentFlowReversed()) {
if (model && model->count())
endPositionFirstItem = positionAt(model->count()-1);
else
extent += headerSize();
highlightStart = highlightRangeEndValid ? size() - highlightRangeEnd : size();
highlightEnd = highlightRangeStartValid ? size() - highlightRangeStart : size();
extent += footerSize();
qreal maxExtentAlongAxis = forXAxis ? q->maxXExtent() : q->maxYExtent();
if (extent < maxExtentAlongAxis)
extent = maxExtentAlongAxis;
} else {
endPositionFirstItem = endPositionAt(0);
highlightStart = highlightRangeStart;
highlightEnd = highlightRangeEnd;
extent += headerSize();
}
if (haveHighlightRange && highlightRange == QQuickItemView::StrictlyEnforceRange) {
extent += highlightStart;
FxViewItem *firstItem = visibleItem(0);
if (firstItem)
extent -= firstItem->sectionSize();
extent = isContentFlowReversed()
? qMin(extent, endPositionFirstItem + highlightEnd)
: qMax(extent, -(endPositionFirstItem - highlightEnd));
}
return extent;
}
qreal QQuickItemViewPrivate::maxExtentForAxis(const AxisData &axisData, bool forXAxis) const
{
Q_Q(const QQuickItemView);
qreal highlightStart;
qreal highlightEnd;
qreal lastItemPosition = 0;
qreal extent = 0;
if (isContentFlowReversed()) {
highlightStart = highlightRangeEndValid ? size() - highlightRangeEnd : size();
highlightEnd = highlightRangeStartValid ? size() - highlightRangeStart : size();
lastItemPosition = endPosition();
} else {
highlightStart = highlightRangeStart;
highlightEnd = highlightRangeEnd;
if (model && model->count())
lastItemPosition = positionAt(model->count()-1);
}
if (!model || !model->count()) {
if (!isContentFlowReversed())
maxExtent = header ? -headerSize() : 0;
extent += forXAxis ? q->width() : q->height();
} else if (haveHighlightRange && highlightRange == QQuickItemView::StrictlyEnforceRange) {
extent = -(lastItemPosition - highlightStart);
if (highlightEnd != highlightStart) {
extent = isContentFlowReversed()
? qMax(extent, -(endPosition() - highlightEnd))
: qMin(extent, -(endPosition() - highlightEnd));
}
} else {
extent = -(endPosition() - (forXAxis ? q->width() : q->height()));
}
if (isContentFlowReversed()) {
extent -= headerSize();
extent -= axisData.endMargin;
} else {
extent -= footerSize();
extent -= axisData.endMargin;
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
qreal minExtentAlongAxis = forXAxis ? q->minXExtent() : q->minYExtent();
if (extent > minExtentAlongAxis)
extent = minExtentAlongAxis;
}
return extent;
}
// for debugging only
void QQuickItemViewPrivate::checkVisible() const
{
int skip = 0;
for (int i = 0; i < visibleItems.count(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index == -1) {
++skip;
} else if (item->index != visibleIndex + i - skip) {
qFatal("index %d %d %d", visibleIndex, i, item->index);
}
}
}
// for debugging only
void QQuickItemViewPrivate::showVisibleItems() const
{
qDebug() << "Visible items:";
for (int i = 0; i < visibleItems.count(); ++i) {
qDebug() << "\t" << visibleItems[i]->index
<< visibleItems[i]->item->objectName()
<< visibleItems[i]->position();
}
}
void QQuickItemViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_Q(QQuickItemView);
QQuickFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
if (!q->isComponentComplete())
return;
if (header && header->item == item) {
updateHeader();
markExtentsDirty();
updateViewport();
if (!q->isMoving() && !q->isFlicking())
fixupPosition();
} else if (footer && footer->item == item) {
updateFooter();
markExtentsDirty();
updateViewport();
if (!q->isMoving() && !q->isFlicking())
fixupPosition();
}
if (currentItem && currentItem->item == item) {
// don't allow item movement transitions to trigger a re-layout and
// start new transitions
bool prevInLayout = inLayout;
if (!inLayout) {
FxViewItem *actualItem = transitioner ? visibleItem(currentIndex) : 0;
if (actualItem && actualItem->transitionRunning())
inLayout = true;
}
updateHighlight();
inLayout = prevInLayout;
}
if (trackedItem && trackedItem->item == item)
q->trackedPositionChanged();
}
1191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
void QQuickItemView::destroyRemoved()
{
Q_D(QQuickItemView);
for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
it != d->visibleItems.end();) {
FxViewItem *item = *it;
if (item->index == -1 && item->attached->delayRemove() == false) {
if (d->transitioner && d->transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)) {
// don't remove from visibleItems until next layout()
d->runDelayedRemoveTransition = true;
QObject::disconnect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()));
++it;
} else {
d->releaseItem(item);
it = d->visibleItems.erase(it);
}
} else {
++it;
}
}
// Correct the positioning of the items
d->forceLayoutPolish();
}
void QQuickItemView::modelUpdated(const QQmlChangeSet &changeSet, bool reset)
{
Q_D(QQuickItemView);
if (reset) {
if (d->transitioner)
d->transitioner->setPopulateTransitionEnabled(true);
d->moveReason = QQuickItemViewPrivate::SetIndex;
d->regenerate();
if (d->highlight && d->currentItem) {
if (d->autoHighlight)
d->resetHighlightPosition();
d->updateTrackedItem();
}
d->moveReason = QQuickItemViewPrivate::Other;
emit countChanged();
if (d->transitioner && d->transitioner->populateTransition)
d->forceLayoutPolish();
} else {
if (d->inLayout) {
d->bufferedChanges.prepare(d->currentIndex, d->itemCount);
d->bufferedChanges.applyChanges(changeSet);
} else {
if (d->bufferedChanges.hasPendingChanges()) {
d->currentChanges.applyBufferedChanges(d->bufferedChanges);
d->bufferedChanges.reset();
}
d->currentChanges.prepare(d->currentIndex, d->itemCount);
d->currentChanges.applyChanges(changeSet);
}
polish();
}
}
void QQuickItemView::animStopped()
{
Q_D(QQuickItemView);
d->bufferMode = QQuickItemViewPrivate::BufferBefore | QQuickItemViewPrivate::BufferAfter;
d->refillOrLayout();
if (d->haveHighlightRange && d->highlightRange == QQuickItemView::StrictlyEnforceRange)
d->updateHighlight();
}
void QQuickItemView::trackedPositionChanged()
1261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330
{
Q_D(QQuickItemView);
if (!d->trackedItem || !d->currentItem)
return;
if (d->moveReason == QQuickItemViewPrivate::SetIndex) {
qreal trackedPos = d->trackedItem->position();
qreal trackedSize = d->trackedItem->size();
qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
qreal pos = viewPos;
if (d->haveHighlightRange) {
if (trackedPos > pos + d->highlightRangeEnd - trackedSize)
pos = trackedPos - d->highlightRangeEnd + trackedSize;
if (trackedPos < pos + d->highlightRangeStart)
pos = trackedPos - d->highlightRangeStart;
if (d->highlightRange != StrictlyEnforceRange) {
if (pos > d->endPosition() - d->size())
pos = d->endPosition() - d->size();
if (pos < d->startPosition())
pos = d->startPosition();
}
} else {
if (d->trackedItem != d->currentItem) {
// also make section header visible
trackedPos -= d->currentItem->sectionSize();
trackedSize += d->currentItem->sectionSize();
}
qreal trackedEndPos = d->trackedItem->endPosition();
qreal toItemPos = d->currentItem->position();
qreal toItemEndPos = d->currentItem->endPosition();
if (d->showHeaderForIndex(d->currentIndex)) {
qreal startOffset = -d->contentStartOffset();
trackedPos -= startOffset;
trackedEndPos -= startOffset;
toItemPos -= startOffset;
toItemEndPos -= startOffset;
} else if (d->showFooterForIndex(d->currentIndex)) {
qreal endOffset = d->footerSize();
if (d->layoutOrientation() == Qt::Vertical) {
if (d->isContentFlowReversed())
endOffset += d->vData.startMargin;
else
endOffset += d->vData.endMargin;
} else {
if (d->isContentFlowReversed())
endOffset += d->hData.startMargin;
else
endOffset += d->hData.endMargin;
}
trackedPos += endOffset;
trackedEndPos += endOffset;
toItemPos += endOffset;
toItemEndPos += endOffset;
}
if (trackedEndPos >= viewPos + d->size()
&& toItemEndPos >= viewPos + d->size()) {
if (trackedEndPos <= toItemEndPos) {
pos = trackedEndPos - d->size();
if (trackedSize > d->size())
pos = trackedPos;
} else {
pos = toItemEndPos - d->size();
if (d->currentItem->size() > d->size())
pos = d->currentItem->position();
}
}
if (trackedPos < pos && toItemPos < pos)
pos = qMax(trackedPos, toItemPos);
}
if (viewPos != pos) {
1331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400
cancelFlick();
d->calcVelocity = true;
d->setPosition(pos);
d->calcVelocity = false;
}
}
}
void QQuickItemView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QQuickItemView);
d->markExtentsDirty();
if (isComponentComplete() && d->isValid())
d->forceLayoutPolish();
QQuickFlickable::geometryChanged(newGeometry, oldGeometry);
}
qreal QQuickItemView::minYExtent() const
{
Q_D(const QQuickItemView);
if (d->layoutOrientation() == Qt::Horizontal)
return QQuickFlickable::minYExtent();
if (d->vData.minExtentDirty) {
d->minExtent = d->minExtentForAxis(d->vData, false);
d->vData.minExtentDirty = false;
}
return d->minExtent;
}
qreal QQuickItemView::maxYExtent() const
{
Q_D(const QQuickItemView);
if (d->layoutOrientation() == Qt::Horizontal)
return height();
if (d->vData.maxExtentDirty) {
d->maxExtent = d->maxExtentForAxis(d->vData, false);
d->vData.maxExtentDirty = false;
}
return d->maxExtent;
}
qreal QQuickItemView::minXExtent() const
{
Q_D(const QQuickItemView);
if (d->layoutOrientation() == Qt::Vertical)
return QQuickFlickable::minXExtent();
if (d->hData.minExtentDirty) {
d->minExtent = d->minExtentForAxis(d->hData, true);
d->hData.minExtentDirty = false;
}
return d->minExtent;
}
qreal QQuickItemView::maxXExtent() const
{
Q_D(const QQuickItemView);
if (d->layoutOrientation() == Qt::Vertical)
return width();
if (d->hData.maxExtentDirty) {
d->maxExtent = d->maxExtentForAxis(d->hData, true);
d->hData.maxExtentDirty = false;
}
1401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470
return d->maxExtent;
}
void QQuickItemView::setContentX(qreal pos)
{
Q_D(QQuickItemView);
// Positioning the view manually should override any current movement state
d->moveReason = QQuickItemViewPrivate::Other;
QQuickFlickable::setContentX(pos);
}
void QQuickItemView::setContentY(qreal pos)
{
Q_D(QQuickItemView);
// Positioning the view manually should override any current movement state
d->moveReason = QQuickItemViewPrivate::Other;
QQuickFlickable::setContentY(pos);
}
qreal QQuickItemView::originX() const
{
Q_D(const QQuickItemView);
if (d->layoutOrientation() == Qt::Horizontal
&& effectiveLayoutDirection() == Qt::RightToLeft
&& contentWidth() < width()) {
return -d->lastPosition() - d->footerSize();
}
return QQuickFlickable::originX();
}
qreal QQuickItemView::originY() const
{
Q_D(const QQuickItemView);
if (d->layoutOrientation() == Qt::Vertical
&& d->verticalLayoutDirection == QQuickItemView::BottomToTop
&& contentHeight() < height()) {
return -d->lastPosition() - d->footerSize();
}
return QQuickFlickable::originY();
}
void QQuickItemView::updatePolish()
{
Q_D(QQuickItemView);
QQuickFlickable::updatePolish();
d->layout();
}
void QQuickItemView::componentComplete()
{
Q_D(QQuickItemView);
if (d->model && d->ownModel)
static_cast<QQmlDelegateModel *>(d->model.data())->componentComplete();
QQuickFlickable::componentComplete();
d->updateSectionCriteria();
d->updateHeader();
d->updateFooter();
d->updateViewport();
d->setPosition(d->contentStartOffset());
if (d->transitioner)
d->transitioner->setPopulateTransitionEnabled(true);
if (d->isValid()) {
d->refill();
d->moveReason = QQuickItemViewPrivate::SetIndex;
if (d->currentIndex < 0 && !d->currentIndexCleared)
d->updateCurrent(0);
else
1471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540
d->updateCurrent(d->currentIndex);
if (d->highlight && d->currentItem) {
if (d->autoHighlight)
d->resetHighlightPosition();
d->updateTrackedItem();
}
d->moveReason = QQuickItemViewPrivate::Other;
d->fixupPosition();
}
if (d->model && d->model->count())
emit countChanged();
}
QQuickItemViewPrivate::QQuickItemViewPrivate()
: itemCount(0)
, buffer(QML_VIEW_DEFAULTCACHEBUFFER), bufferMode(BufferBefore | BufferAfter)
, displayMarginBeginning(0), displayMarginEnd(0)
, layoutDirection(Qt::LeftToRight), verticalLayoutDirection(QQuickItemView::TopToBottom)
, moveReason(Other)
, visibleIndex(0)
, currentIndex(-1), currentItem(0)
, trackedItem(0), requestedIndex(-1)
, highlightComponent(0), highlight(0)
, highlightRange(QQuickItemView::NoHighlightRange)
, highlightRangeStart(0), highlightRangeEnd(0)
, highlightMoveDuration(150)
, headerComponent(0), header(0), footerComponent(0), footer(0)
, transitioner(0)
, minExtent(0), maxExtent(0)
, ownModel(false), wrap(false)
, inLayout(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false)
, haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
, fillCacheBuffer(false), inRequest(false)
, runDelayedRemoveTransition(false), delegateValidated(false)
{
bufferPause.addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
bufferPause.setLoopCount(1);
bufferPause.setDuration(16);
}
QQuickItemViewPrivate::~QQuickItemViewPrivate()
{
if (transitioner)
transitioner->setChangeListener(0);
delete transitioner;
}
bool QQuickItemViewPrivate::isValid() const
{
return model && model->count() && model->isValid();
}
qreal QQuickItemViewPrivate::position() const
{
Q_Q(const QQuickItemView);
return layoutOrientation() == Qt::Vertical ? q->contentY() : q->contentX();
}
qreal QQuickItemViewPrivate::size() const
{
Q_Q(const QQuickItemView);
return layoutOrientation() == Qt::Vertical ? q->height() : q->width();
}
qreal QQuickItemViewPrivate::startPosition() const
{
return isContentFlowReversed() ? -lastPosition() : originPosition();
}
1541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610
qreal QQuickItemViewPrivate::endPosition() const
{
return isContentFlowReversed() ? -originPosition() : lastPosition();
}
qreal QQuickItemViewPrivate::contentStartOffset() const
{
qreal pos = -headerSize();
if (layoutOrientation() == Qt::Vertical) {
if (isContentFlowReversed())
pos -= vData.endMargin;
else
pos -= vData.startMargin;
} else {
if (isContentFlowReversed())
pos -= hData.endMargin;
else
pos -= hData.startMargin;
}
return pos;
}
int QQuickItemViewPrivate::findLastVisibleIndex(int defaultValue) const
{
if (visibleItems.count()) {
int i = visibleItems.count() - 1;
while (i > 0 && visibleItems.at(i)->index == -1)
--i;
if (visibleItems.at(i)->index != -1)
return visibleItems.at(i)->index;
}
return defaultValue;
}
FxViewItem *QQuickItemViewPrivate::visibleItem(int modelIndex) const {
if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index == modelIndex)
return item;
}
}
return 0;
}
// should rename to firstItemInView() to avoid confusion with other "*visible*" methods
// that don't look at the view position and size
FxViewItem *QQuickItemViewPrivate::firstVisibleItem() const {
const qreal pos = isContentFlowReversed() ? -position()-size() : position();
for (int i = 0; i < visibleItems.count(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index != -1 && item->endPosition() > pos)
return item;
}
return visibleItems.count() ? visibleItems.first() : 0;
}
int QQuickItemViewPrivate::findLastIndexInView() const
{
const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size();
for (int i=visibleItems.count() - 1; i>=0; i--) {
if (visibleItems.at(i)->position() <= viewEndPos && visibleItems.at(i)->index != -1)
return visibleItems.at(i)->index;
}
return -1;
}
// Map a model index to visibleItems list index.
// These may differ if removed items are still present in the visible list,
1611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680
// e.g. doing a removal animation
int QQuickItemViewPrivate::mapFromModel(int modelIndex) const
{
if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
return -1;
for (int i = 0; i < visibleItems.count(); ++i) {
FxViewItem *item = visibleItems.at(i);
if (item->index == modelIndex)
return i;
if (item->index > modelIndex)
return -1;
}
return -1; // Not in visibleList
}
void QQuickItemViewPrivate::init()
{
Q_Q(QQuickItemView);
q->setFlag(QQuickItem::ItemIsFocusScope);
QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
q->setFlickableDirection(QQuickFlickable::VerticalFlick);
}
void QQuickItemViewPrivate::updateCurrent(int modelIndex)
{
Q_Q(QQuickItemView);
applyPendingChanges();
if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
if (currentItem) {
currentItem->attached->setIsCurrentItem(false);
releaseItem(currentItem);
currentItem = 0;
currentIndex = modelIndex;
emit q->currentIndexChanged();
emit q->currentItemChanged();
updateHighlight();
} else if (currentIndex != modelIndex) {
currentIndex = modelIndex;
emit q->currentIndexChanged();
}
return;
}
if (currentItem && currentIndex == modelIndex) {
updateHighlight();
return;
}
FxViewItem *oldCurrentItem = currentItem;
int oldCurrentIndex = currentIndex;
currentIndex = modelIndex;
currentItem = createItem(modelIndex, false);
if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
oldCurrentItem->attached->setIsCurrentItem(false);
if (currentItem) {
currentItem->item->setFocus(true);
currentItem->attached->setIsCurrentItem(true);
initializeCurrentItem();
}
updateHighlight();
if (oldCurrentIndex != currentIndex)
emit q->currentIndexChanged();
if (oldCurrentItem != currentItem)
emit q->currentItemChanged();
releaseItem(oldCurrentItem);
}
void QQuickItemViewPrivate::clear()
{
1681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750
currentChanges.reset();
timeline.clear();
for (int i = 0; i < visibleItems.count(); ++i)
releaseItem(visibleItems.at(i));
visibleItems.clear();
visibleIndex = 0;
for (int i = 0; i < releasePendingTransition.count(); ++i) {
releasePendingTransition.at(i)->releaseAfterTransition = false;
releaseItem(releasePendingTransition.at(i));
}
releasePendingTransition.clear();
releaseItem(currentItem);
currentItem = 0;
createHighlight();
trackedItem = 0;
if (requestedIndex >= 0) {
if (model)
model->cancel(requestedIndex);
requestedIndex = -1;
}
markExtentsDirty();
itemCount = 0;
}
void QQuickItemViewPrivate::mirrorChange()
{
Q_Q(QQuickItemView);
regenerate();
emit q->effectiveLayoutDirectionChanged();
}
void QQuickItemViewPrivate::animationFinished(QAbstractAnimationJob *)
{
Q_Q(QQuickItemView);
fillCacheBuffer = true;
q->polish();
}
void QQuickItemViewPrivate::refill()
{
qreal s = qMax(size(), qreal(0.));
if (isContentFlowReversed())
refill(-position()-displayMarginBeginning-s, -position()+displayMarginEnd);
else
refill(position()-displayMarginBeginning, position()+displayMarginEnd+s);
}
void QQuickItemViewPrivate::refill(qreal from, qreal to)
{
Q_Q(QQuickItemView);
if (!isValid() || !q->isComponentComplete())
return;
bufferPause.stop();
currentChanges.reset();
int prevCount = itemCount;
itemCount = model->count();
qreal bufferFrom = from - buffer;
qreal bufferTo = to + buffer;
qreal fillFrom = from;
qreal fillTo = to;
bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, false);
1751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820
bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) {
if (added) {
// We've already created a new delegate this frame.
// Just schedule a buffer refill.
bufferPause.start();
} else {
if (bufferMode & BufferAfter)
fillTo = bufferTo;
if (bufferMode & BufferBefore)
fillFrom = bufferFrom;
added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, true);
}
}
if (added || removed) {
markExtentsDirty();
updateBeginningEnd();
visibleItemsChanged();
updateHeader();
updateFooter();
updateViewport();
}
if (prevCount != itemCount)
emit q->countChanged();
}
void QQuickItemViewPrivate::regenerate(bool orientationChanged)
{
Q_Q(QQuickItemView);
if (q->isComponentComplete()) {
currentChanges.reset();
if (orientationChanged) {
delete header;
header = 0;
delete footer;
footer = 0;
}
clear();
updateHeader();
updateFooter();
updateViewport();
setPosition(contentStartOffset());
refill();
updateCurrent(currentIndex);
}
}
void QQuickItemViewPrivate::updateViewport()
{
Q_Q(QQuickItemView);
qreal extra = headerSize() + footerSize();
qreal contentSize = isValid() ? (endPosition() - startPosition()) : 0.0;
if (layoutOrientation() == Qt::Vertical)
q->setContentHeight(contentSize + extra);
else
q->setContentWidth(contentSize + extra);
}
void QQuickItemViewPrivate::layout()
{
Q_Q(QQuickItemView);
if (inLayout)
return;
inLayout = true;
if (!isValid() && !visibleItems.count()) {
1821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890
clear();
setPosition(contentStartOffset());
if (transitioner)
transitioner->setPopulateTransitionEnabled(false);
inLayout = false;
return;
}
if (runDelayedRemoveTransition && transitioner
&& transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false)) {
// assume that any items moving now are moving due to the remove - if they schedule
// a different transition, that will override this one anyway
for (int i=0; i<visibleItems.count(); i++)
visibleItems[i]->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, false);
}
ChangeResult insertionPosChanges;
ChangeResult removalPosChanges;
if (!applyModelChanges(&insertionPosChanges, &removalPosChanges) && !forceLayout) {
if (fillCacheBuffer) {
fillCacheBuffer = false;
refill();
}
inLayout = false;
return;
}
forceLayout = false;
if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) {
for (int i=0; i<visibleItems.count(); i++) {
if (!visibleItems.at(i)->transitionScheduledOrRunning())
visibleItems.at(i)->transitionNextReposition(transitioner, QQuickItemViewTransitioner::PopulateTransition, true);
}
}
updateSections();
layoutVisibleItems();
int lastIndexInView = findLastIndexInView();
refill();
markExtentsDirty();
updateHighlight();
if (!q->isMoving() && !q->isFlicking()) {
fixupPosition();
refill();
}
updateHeader();
updateFooter();
updateViewport();
updateUnrequestedPositions();
if (transitioner) {
// items added in the last refill() may need to be transitioned in - e.g. a remove
// causes items to slide up into view
if (transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, false)
|| transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false)) {
translateAndTransitionItemsAfter(lastIndexInView, insertionPosChanges, removalPosChanges);
}
prepareVisibleItemTransitions();
QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
for (QList<FxViewItem*>::Iterator it = releasePendingTransition.begin();
it != releasePendingTransition.end(); ) {
FxViewItem *item = *it;
if (prepareNonVisibleItemTransition(item, viewBounds)) {
++it;
} else {
1891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960
releaseItem(item);
it = releasePendingTransition.erase(it);
}
}
for (int i=0; i<visibleItems.count(); i++)
visibleItems[i]->startTransition(transitioner);
for (int i=0; i<releasePendingTransition.count(); i++)
releasePendingTransition[i]->startTransition(transitioner);
transitioner->setPopulateTransitionEnabled(false);
transitioner->resetTargetLists();
}
runDelayedRemoveTransition = false;
inLayout = false;
}
bool QQuickItemViewPrivate::applyModelChanges(ChangeResult *totalInsertionResult, ChangeResult *totalRemovalResult)
{
Q_Q(QQuickItemView);
if (!q->isComponentComplete() || !hasPendingChanges())
return false;
if (bufferedChanges.hasPendingChanges()) {
currentChanges.applyBufferedChanges(bufferedChanges);
bufferedChanges.reset();
}
updateUnrequestedIndexes();
moveReason = QQuickItemViewPrivate::Other;
FxViewItem *prevVisibleItemsFirst = visibleItems.count() ? *visibleItems.constBegin() : 0;
int prevItemCount = itemCount;
int prevVisibleItemsCount = visibleItems.count();
bool visibleAffected = false;
bool viewportChanged = !currentChanges.pendingChanges.removes().isEmpty()
|| !currentChanges.pendingChanges.inserts().isEmpty();
FxViewItem *prevFirstVisible = firstVisibleItem();
QQmlNullableValue<qreal> prevViewPos;
int prevFirstVisibleIndex = -1;
if (prevFirstVisible) {
prevViewPos = prevFirstVisible->position();
prevFirstVisibleIndex = prevFirstVisible->index;
}
qreal prevVisibleItemsFirstPos = visibleItems.count() ? visibleItems.first()->position() : 0.0;
totalInsertionResult->visiblePos = prevViewPos;
totalRemovalResult->visiblePos = prevViewPos;
const QVector<QQmlChangeSet::Change> &removals = currentChanges.pendingChanges.removes();
const QVector<QQmlChangeSet::Change> &insertions = currentChanges.pendingChanges.inserts();
ChangeResult insertionResult(prevViewPos);
ChangeResult removalResult(prevViewPos);
int removedCount = 0;
for (int i=0; i<removals.count(); i++) {
itemCount -= removals[i].count;
if (applyRemovalChange(removals[i], &removalResult, &removedCount))
visibleAffected = true;
if (!visibleAffected && needsRefillForAddedOrRemovedIndex(removals[i].index))
visibleAffected = true;
const int correctedFirstVisibleIndex = prevFirstVisibleIndex - removalResult.countChangeBeforeVisible;
if (correctedFirstVisibleIndex >= 0 && removals[i].index < correctedFirstVisibleIndex) {
if (removals[i].index + removals[i].count < correctedFirstVisibleIndex)
removalResult.countChangeBeforeVisible += removals[i].count;
else
removalResult.countChangeBeforeVisible += (correctedFirstVisibleIndex - removals[i].index);
}
1961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030
}
if (runDelayedRemoveTransition) {
QQmlChangeSet::Change removal;
for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end();) {
FxViewItem *item = *it;
if (item->index == -1 && !item->attached->delayRemove()) {
removeItem(item, removal, &removalResult);
removedCount++;
it = visibleItems.erase(it);
} else {
++it;
}
}
}
*totalRemovalResult += removalResult;
if (!removals.isEmpty()) {
updateVisibleIndex();
// set positions correctly for the next insertion
if (!insertions.isEmpty()) {
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
layoutVisibleItems(removals.first().index);
}
}
QList<FxViewItem *> newItems;
QList<MovedItem> movingIntoView;
for (int i=0; i<insertions.count(); i++) {
bool wasEmpty = visibleItems.isEmpty();
if (applyInsertionChange(insertions[i], &insertionResult, &newItems, &movingIntoView))
visibleAffected = true;
if (!visibleAffected && needsRefillForAddedOrRemovedIndex(insertions[i].index))
visibleAffected = true;
if (wasEmpty && !visibleItems.isEmpty())
resetFirstItemPosition();
*totalInsertionResult += insertionResult;
// set positions correctly for the next insertion
if (i < insertions.count() - 1) {
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
layoutVisibleItems(insertions[i].index);
}
itemCount += insertions[i].count;
}
for (int i=0; i<newItems.count(); i++)
newItems.at(i)->attached->emitAdd();
// for each item that was moved directly into the view as a result of a move(),
// find the index it was moved from in order to set its initial position, so that we
// can transition it from this "original" position to its new position in the view
if (transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true)) {
for (int i=0; i<movingIntoView.count(); i++) {
int fromIndex = findMoveKeyIndex(movingIntoView[i].moveKey, removals);
if (fromIndex >= 0) {
if (prevFirstVisibleIndex >= 0 && fromIndex < prevFirstVisibleIndex)
repositionItemAt(movingIntoView[i].item, fromIndex, -totalInsertionResult->sizeChangesAfterVisiblePos);
else
repositionItemAt(movingIntoView[i].item, fromIndex, totalInsertionResult->sizeChangesAfterVisiblePos);
movingIntoView[i].item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, true);
}
}
}
// reposition visibleItems.first() correctly so that the content y doesn't jump
if (removedCount != prevVisibleItemsCount)
repositionFirstItem(prevVisibleItemsFirst, prevVisibleItemsFirstPos, prevFirstVisible, &insertionResult, &removalResult);
// Whatever removed/moved items remain are no longer visible items.
prepareRemoveTransitions(¤tChanges.removedItems);
2031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100
for (QHash<QQmlChangeSet::MoveKey, FxViewItem *>::Iterator it = currentChanges.removedItems.begin();
it != currentChanges.removedItems.end(); ++it) {
releaseItem(it.value());
}
currentChanges.removedItems.clear();
if (currentChanges.currentChanged) {
if (currentChanges.currentRemoved && currentItem) {
currentItem->attached->setIsCurrentItem(false);
releaseItem(currentItem);
currentItem = 0;
}
if (!currentIndexCleared)
updateCurrent(currentChanges.newCurrentIndex);
}
if (!visibleAffected)
visibleAffected = !currentChanges.pendingChanges.changes().isEmpty();
currentChanges.reset();
updateSections();
if (prevItemCount != itemCount)
emit q->countChanged();
if (!visibleAffected && viewportChanged)
updateViewport();
return visibleAffected;
}
bool QQuickItemViewPrivate::applyRemovalChange(const QQmlChangeSet::Change &removal, ChangeResult *removeResult, int *removedCount)
{
Q_Q(QQuickItemView);
bool visibleAffected = false;
if (visibleItems.count() && removal.index + removal.count > visibleItems.last()->index) {
if (removal.index > visibleItems.last()->index)
removeResult->countChangeAfterVisibleItems += removal.count;
else
removeResult->countChangeAfterVisibleItems += ((removal.index + removal.count - 1) - visibleItems.last()->index);
}
QList<FxViewItem*>::Iterator it = visibleItems.begin();
while (it != visibleItems.end()) {
FxViewItem *item = *it;
if (item->index == -1 || item->index < removal.index) {
// already removed, or before removed items
if (!visibleAffected && item->index < removal.index)
visibleAffected = true;
++it;
} else if (item->index >= removal.index + removal.count) {
// after removed items
item->index -= removal.count;
if (removal.isMove())
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, false);
else
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, false);
++it;
} else {
// removed item
visibleAffected = true;
if (!removal.isMove())
item->attached->emitRemove();
if (item->attached->delayRemove() && !removal.isMove()) {
item->index = -1;
QObject::connect(item->attached, SIGNAL(delayRemoveChanged()), q, SLOT(destroyRemoved()), Qt::QueuedConnection);
++it;
} else {
removeItem(item, removal, removeResult);
if (!removal.isMove())
2101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170
(*removedCount)++;
it = visibleItems.erase(it);
}
}
}
return visibleAffected;
}
void QQuickItemViewPrivate::removeItem(FxViewItem *item, const QQmlChangeSet::Change &removal, ChangeResult *removeResult)
{
if (removeResult->visiblePos.isValid()) {
if (item->position() < removeResult->visiblePos)
updateSizeChangesBeforeVisiblePos(item, removeResult);
else
removeResult->sizeChangesAfterVisiblePos += item->size();
}
if (removal.isMove()) {
currentChanges.removedItems.insert(removal.moveKey(item->index), item);
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, true);
} else {
// track item so it is released later
currentChanges.removedItems.insertMulti(QQmlChangeSet::MoveKey(), item);
}
if (!removeResult->changedFirstItem && item == *visibleItems.constBegin())
removeResult->changedFirstItem = true;
}
void QQuickItemViewPrivate::updateSizeChangesBeforeVisiblePos(FxViewItem *item, ChangeResult *removeResult)
{
removeResult->sizeChangesBeforeVisiblePos += item->size();
}
void QQuickItemViewPrivate::repositionFirstItem(FxViewItem *prevVisibleItemsFirst,
qreal prevVisibleItemsFirstPos,
FxViewItem *prevFirstVisible,
ChangeResult *insertionResult,
ChangeResult *removalResult)
{
const QQmlNullableValue<qreal> prevViewPos = insertionResult->visiblePos;
// reposition visibleItems.first() correctly so that the content y doesn't jump
if (visibleItems.count()) {
if (prevVisibleItemsFirst && insertionResult->changedFirstItem)
resetFirstItemPosition(prevVisibleItemsFirstPos);
if (prevFirstVisible && prevVisibleItemsFirst == prevFirstVisible
&& prevFirstVisible != *visibleItems.constBegin()) {
// the previous visibleItems.first() was also the first visible item, and it has been
// moved/removed, so move the new visibleItems.first() to the pos of the previous one
if (!insertionResult->changedFirstItem)
resetFirstItemPosition(prevVisibleItemsFirstPos);
} else if (prevViewPos.isValid()) {
qreal moveForwardsBy = 0;
qreal moveBackwardsBy = 0;
// shift visibleItems.first() relative to the number of added/removed items
if (visibleItems.first()->position() > prevViewPos) {
moveForwardsBy = insertionResult->sizeChangesAfterVisiblePos;
moveBackwardsBy = removalResult->sizeChangesAfterVisiblePos;
} else if (visibleItems.first()->position() < prevViewPos) {
moveForwardsBy = removalResult->sizeChangesBeforeVisiblePos;
moveBackwardsBy = insertionResult->sizeChangesBeforeVisiblePos;
}
adjustFirstItem(moveForwardsBy, moveBackwardsBy, insertionResult->countChangeBeforeVisible - removalResult->countChangeBeforeVisible);
}
insertionResult->reset();
removalResult->reset();
}
2171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240
}
void QQuickItemViewPrivate::createTransitioner()
{
if (!transitioner) {
transitioner = new QQuickItemViewTransitioner;
transitioner->setChangeListener(this);
}
}
void QQuickItemViewPrivate::prepareVisibleItemTransitions()
{
Q_Q(QQuickItemView);
if (!transitioner)
return;
// must call for every visible item to init or discard transitions
QRectF viewBounds(q->contentX(), q->contentY(), q->width(), q->height());
for (int i=0; i<visibleItems.count(); i++)
visibleItems[i]->prepareTransition(transitioner, viewBounds);
}
void QQuickItemViewPrivate::prepareRemoveTransitions(QHash<QQmlChangeSet::MoveKey, FxViewItem *> *removedItems)
{
if (!transitioner)
return;
if (transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, true)
|| transitioner->canTransition(QQuickItemViewTransitioner::RemoveTransition, false)) {
for (QHash<QQmlChangeSet::MoveKey, FxViewItem *>::Iterator it = removedItems->begin();
it != removedItems->end(); ) {
bool isRemove = it.key().moveId < 0;
if (isRemove) {
FxViewItem *item = *it;
item->trackGeometry(false);
item->releaseAfterTransition = true;
releasePendingTransition.append(item);
item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, true);
it = removedItems->erase(it);
} else {
++it;
}
}
}
}
bool QQuickItemViewPrivate::prepareNonVisibleItemTransition(FxViewItem *item, const QRectF &viewBounds)
{
// Called for items that have been removed from visibleItems and may now be
// transitioned out of the view. This applies to items that are being directly
// removed, or moved to outside of the view, as well as those that are
// displaced to a position outside of the view due to an insert or move.
if (!transitioner)
return false;
if (item->scheduledTransitionType() == QQuickItemViewTransitioner::MoveTransition)
repositionItemAt(item, item->index, 0);
if (item->prepareTransition(transitioner, viewBounds)) {
item->releaseAfterTransition = true;
return true;
}
return false;
}
void QQuickItemViewPrivate::viewItemTransitionFinished(QQuickItemViewTransitionableItem *item)
{
for (int i=0; i<releasePendingTransition.count(); i++) {
if (releasePendingTransition[i]->transitionableItem == item) {
2241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310
releaseItem(releasePendingTransition.takeAt(i));
return;
}
}
}
/*
This may return 0 if the item is being created asynchronously.
When the item becomes available, refill() will be called and the item
will be returned on the next call to createItem().
*/
FxViewItem *QQuickItemViewPrivate::createItem(int modelIndex, bool asynchronous)
{
Q_Q(QQuickItemView);
if (requestedIndex == modelIndex && asynchronous)
return 0;
for (int i=0; i<releasePendingTransition.count(); i++) {
if (releasePendingTransition[i]->index == modelIndex
&& !releasePendingTransition[i]->isPendingRemoval()) {
releasePendingTransition[i]->releaseAfterTransition = false;
return releasePendingTransition.takeAt(i);
}
}
if (asynchronous)
requestedIndex = modelIndex;
inRequest = true;
QObject* object = model->object(modelIndex, asynchronous);
QQuickItem *item = qmlobject_cast<QQuickItem*>(object);
if (!item) {
if (object) {
model->release(object);
if (!delegateValidated) {
delegateValidated = true;
QObject* delegate = q->delegate();
qmlInfo(delegate ? delegate : q) << QQuickItemView::tr("Delegate must be of Item type");
}
}
inRequest = false;
return 0;
} else {
item->setParentItem(q->contentItem());
if (requestedIndex == modelIndex)
requestedIndex = -1;
FxViewItem *viewItem = newViewItem(modelIndex, item);
if (viewItem) {
viewItem->index = modelIndex;
// do other set up for the new item that should not happen
// until after bindings are evaluated
initializeViewItem(viewItem);
unrequestedItems.remove(item);
}
inRequest = false;
return viewItem;
}
}
void QQuickItemView::createdItem(int index, QObject* object)
{
Q_D(QQuickItemView);
QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
if (!d->inRequest) {
d->unrequestedItems.insert(item, index);
d->requestedIndex = -1;
if (d->hasPendingChanges())
d->layout();
2311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380
else
d->refill();
if (d->unrequestedItems.contains(item))
d->repositionPackageItemAt(item, index);
else if (index == d->currentIndex)
d->updateCurrent(index);
}
}
void QQuickItemView::initItem(int, QObject *object)
{
QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
if (item) {
if (qFuzzyIsNull(item->z()))
item->setZ(1);
item->setParentItem(contentItem());
QQuickItemPrivate::get(item)->setCulled(true);
}
}
void QQuickItemView::destroyingItem(QObject *object)
{
Q_D(QQuickItemView);
QQuickItem* item = qmlobject_cast<QQuickItem*>(object);
if (item) {
item->setParentItem(0);
d->unrequestedItems.remove(item);
}
}
bool QQuickItemViewPrivate::releaseItem(FxViewItem *item)
{
Q_Q(QQuickItemView);
if (!item || !model)
return true;
if (trackedItem == item)
trackedItem = 0;
item->trackGeometry(false);
QQmlInstanceModel::ReleaseFlags flags = model->release(item->item);
if (flags == 0) {
// item was not destroyed, and we no longer reference it.
QQuickItemPrivate::get(item->item)->setCulled(true);
unrequestedItems.insert(item->item, model->indexOf(item->item, q));
} else if (flags & QQmlInstanceModel::Destroyed) {
item->item->setParentItem(0);
}
delete item;
return flags != QQmlInstanceModel::Referenced;
}
QQuickItem *QQuickItemViewPrivate::createHighlightItem()
{
return createComponentItem(highlightComponent, 0.0, true);
}
QQuickItem *QQuickItemViewPrivate::createComponentItem(QQmlComponent *component, qreal zValue, bool createDefault)
{
Q_Q(QQuickItemView);
QQuickItem *item = 0;
if (component) {
QQmlContext *creationContext = component->creationContext();
QQmlContext *context = new QQmlContext(
creationContext ? creationContext : qmlContext(q));
QObject *nobj = component->beginCreate(context);
if (nobj) {
QQml_setParent_noEvent(context, nobj);
item = qobject_cast<QQuickItem *>(nobj);
if (!item)
23812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436
delete nobj;
} else {
delete context;
}
} else if (createDefault) {
item = new QQuickItem;
}
if (item) {
if (qFuzzyIsNull(item->z()))
item->setZ(zValue);
QQml_setParent_noEvent(item, q->contentItem());
item->setParentItem(q->contentItem());
}
if (component)
component->completeCreate();
return item;
}
void QQuickItemViewPrivate::updateTrackedItem()
{
Q_Q(QQuickItemView);
FxViewItem *item = currentItem;
if (highlight)
item = highlight;
trackedItem = item;
if (trackedItem)
q->trackedPositionChanged();
}
void QQuickItemViewPrivate::updateUnrequestedIndexes()
{
Q_Q(QQuickItemView);
for (QHash<QQuickItem*,int>::iterator it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
*it = model->indexOf(it.key(), q);
}
void QQuickItemViewPrivate::updateUnrequestedPositions()
{
for (QHash<QQuickItem*,int>::const_iterator it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
repositionPackageItemAt(it.key(), it.value());
}
void QQuickItemViewPrivate::updateVisibleIndex()
{
visibleIndex = 0;
for (QList<FxViewItem*>::Iterator it = visibleItems.begin(); it != visibleItems.end(); ++it) {
if ((*it)->index != -1) {
visibleIndex = (*it)->index;
break;
}
}
}
QT_END_NAMESPACE