1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "private/qdeclarativegridview_p.h"
44 #include "private/qdeclarativevisualitemmodel_p.h"
45 #include "private/qdeclarativeflickable_p_p.h"
47 #include "private/qdeclarativesmoothedanimation_p_p.h"
48 #include <qdeclarativeguard_p.h>
50 #include <qlistmodelinterface_p.h>
59 //----------------------------------------------------------------------------
64 FxGridItem(QDeclarativeItem *i, QDeclarativeGridView *v) : item(i), view(v) {
65 attached = static_cast<QDeclarativeGridViewAttached*>(qmlAttachedPropertiesObject<QDeclarativeGridView>(item));
67 attached->setView(view);
71 qreal rowPos() const {
73 if (view->flow() == QDeclarativeGridView::LeftToRight) {
76 if (view->effectiveLayoutDirection() == Qt::RightToLeft)
77 rowPos = -view->cellWidth()-item->x();
83 qreal colPos() const {
85 if (view->flow() == QDeclarativeGridView::LeftToRight) {
86 if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
87 int colSize = view->cellWidth();
88 int columns = view->width()/colSize;
89 colPos = colSize * (columns-1) - item->x();
100 qreal endRowPos() const {
101 if (view->flow() == QDeclarativeGridView::LeftToRight) {
102 return item->y() + view->cellHeight() - 1;
104 if (view->effectiveLayoutDirection() == Qt::RightToLeft)
105 return -item->x() - 1;
107 return item->x() + view->cellWidth() - 1;
110 void setPosition(qreal col, qreal row) {
111 if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
112 if (view->flow() == QDeclarativeGridView::LeftToRight) {
113 int columns = view->width()/view->cellWidth();
114 item->setPos(QPointF((view->cellWidth() * (columns-1) - col), row));
116 item->setPos(QPointF(-view->cellWidth()-row, col));
119 if (view->flow() == QDeclarativeGridView::LeftToRight)
120 item->setPos(QPointF(col, row));
122 item->setPos(QPointF(row, col));
126 bool contains(qreal x, qreal y) const {
127 return (x >= item->x() && x < item->x() + view->cellWidth() &&
128 y >= item->y() && y < item->y() + view->cellHeight());
131 QDeclarativeItem *item;
132 QDeclarativeGridView *view;
133 QDeclarativeGridViewAttached *attached;
137 //----------------------------------------------------------------------------
139 class QDeclarativeGridViewPrivate : public QDeclarativeFlickablePrivate
141 Q_DECLARE_PUBLIC(QDeclarativeGridView)
144 QDeclarativeGridViewPrivate()
145 : currentItem(0), layoutDirection(Qt::LeftToRight), flow(QDeclarativeGridView::LeftToRight)
146 , visibleIndex(0) , currentIndex(-1)
147 , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0)
148 , highlightRangeStart(0), highlightRangeEnd(0)
149 , highlightRangeStartValid(false), highlightRangeEndValid(false)
150 , highlightRange(QDeclarativeGridView::NoHighlightRange)
151 , highlightComponent(0), highlight(0), trackedItem(0)
152 , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
153 , highlightMoveDuration(150)
154 , footerComponent(0), footer(0), headerComponent(0), header(0)
155 , bufferMode(BufferBefore | BufferAfter), snapMode(QDeclarativeGridView::NoSnap)
156 , ownModel(false), wrap(false), autoHighlight(true)
157 , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
158 , deferredRelease(false), haveHighlightRange(false), currentIndexCleared(false) {}
162 FxGridItem *createItem(int modelIndex);
163 void releaseItem(FxGridItem *item);
164 void refill(qreal from, qreal to, bool doBuffer=false);
167 void scheduleLayout();
169 void updateUnrequestedIndexes();
170 void updateUnrequestedPositions();
171 void updateTrackedItem();
172 void createHighlight();
173 void updateHighlight();
174 void updateCurrent(int modelIndex);
177 void fixupPosition();
179 FxGridItem *visibleItem(int modelIndex) const {
180 if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
181 for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
182 FxGridItem *item = visibleItems.at(i);
183 if (item->index == modelIndex)
190 bool isRightToLeftTopToBottom() const {
191 Q_Q(const QDeclarativeGridView);
192 return flow == QDeclarativeGridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
196 Q_Q(QDeclarativeGridView);
197 if (q->isComponentComplete()) {
202 updateCurrent(currentIndex);
206 void mirrorChange() {
207 Q_Q(QDeclarativeGridView);
209 emit q->effectiveLayoutDirectionChanged();
212 qreal position() const {
213 Q_Q(const QDeclarativeGridView);
214 return flow == QDeclarativeGridView::LeftToRight ? q->contentY() : q->contentX();
216 void setPosition(qreal pos) {
217 Q_Q(QDeclarativeGridView);
218 if (flow == QDeclarativeGridView::LeftToRight) {
219 q->QDeclarativeFlickable::setContentY(pos);
220 q->QDeclarativeFlickable::setContentX(0);
222 if (q->effectiveLayoutDirection() == Qt::LeftToRight)
223 q->QDeclarativeFlickable::setContentX(pos);
225 q->QDeclarativeFlickable::setContentX(-pos-size());
226 q->QDeclarativeFlickable::setContentY(0);
230 Q_Q(const QDeclarativeGridView);
231 return flow == QDeclarativeGridView::LeftToRight ? q->height() : q->width();
233 qreal originPosition() const {
235 if (!visibleItems.isEmpty())
236 pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
240 qreal lastPosition() const {
242 if (model && model->count())
243 pos = rowPosAt(model->count() - 1) + rowSize();
247 qreal startPosition() const {
248 return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
251 qreal endPosition() const {
252 return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
256 bool isValid() const {
257 return model && model->count() && model->isValid();
260 int rowSize() const {
261 return flow == QDeclarativeGridView::LeftToRight ? cellHeight : cellWidth;
263 int colSize() const {
264 return flow == QDeclarativeGridView::LeftToRight ? cellWidth : cellHeight;
267 qreal colPosAt(int modelIndex) const {
268 if (FxGridItem *item = visibleItem(modelIndex))
269 return item->colPos();
270 if (!visibleItems.isEmpty()) {
271 if (modelIndex < visibleIndex) {
272 int count = (visibleIndex - modelIndex) % columns;
273 int col = visibleItems.first()->colPos() / colSize();
274 col = (columns - count + col) % columns;
275 return col * colSize();
277 int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
278 return visibleItems.last()->colPos() - count * colSize();
281 return (modelIndex % columns) * colSize();
285 qreal rowPosAt(int modelIndex) const {
286 if (FxGridItem *item = visibleItem(modelIndex))
287 return item->rowPos();
288 if (!visibleItems.isEmpty()) {
289 if (modelIndex < visibleIndex) {
290 int firstCol = visibleItems.first()->colPos() / colSize();
291 int col = visibleIndex - modelIndex + (columns - firstCol - 1);
292 int rows = col / columns;
293 return visibleItems.first()->rowPos() - rows * rowSize();
295 int count = modelIndex - visibleItems.last()->index;
296 int col = visibleItems.last()->colPos() + count * colSize();
297 int rows = col / (columns * colSize());
298 return visibleItems.last()->rowPos() + rows * rowSize();
301 qreal pos = (modelIndex / columns) * rowSize();
309 FxGridItem *firstVisibleItem() const {
310 const qreal pos = isRightToLeftTopToBottom() ? -position()-size() : position();
311 for (int i = 0; i < visibleItems.count(); ++i) {
312 FxGridItem *item = visibleItems.at(i);
313 if (item->index != -1 && item->endRowPos() > pos)
316 return visibleItems.count() ? visibleItems.first() : 0;
319 int lastVisibleIndex() const {
320 for (int i = 0; i < visibleItems.count(); ++i) {
321 FxGridItem *item = visibleItems.at(i);
322 if (item->index != -1)
328 // Map a model index to visibleItems list index.
329 // These may differ if removed items are still present in the visible list,
330 // e.g. doing a removal animation
331 int mapFromModel(int modelIndex) const {
332 if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
334 for (int i = 0; i < visibleItems.count(); ++i) {
335 FxGridItem *listItem = visibleItems.at(i);
336 if (listItem->index == modelIndex)
337 return i + visibleIndex;
338 if (listItem->index > modelIndex)
341 return -1; // Not in visibleList
344 qreal snapPosAt(qreal pos) const {
345 Q_Q(const QDeclarativeGridView);
347 if (!visibleItems.isEmpty()) {
349 snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
350 snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
353 if (isRightToLeftTopToBottom()) {
354 maxExtent = q->minXExtent();
355 minExtent = q->maxXExtent();
357 maxExtent = flow == QDeclarativeGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
358 minExtent = flow == QDeclarativeGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
360 if (snapPos > maxExtent)
362 if (snapPos < minExtent)
368 FxGridItem *snapItemAt(qreal pos) {
369 for (int i = 0; i < visibleItems.count(); ++i) {
370 FxGridItem *item = visibleItems[i];
371 if (item->index == -1)
373 qreal itemTop = item->rowPos();
374 if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
381 int index = currentIndex;
382 for (int i = 0; i < visibleItems.count(); ++i) {
383 FxGridItem *item = visibleItems[i];
384 if (item->index == -1)
386 qreal itemTop = item->rowPos();
387 if (itemTop >= highlight->rowPos()-rowSize()/2 && itemTop < highlight->rowPos()+rowSize()/2) {
389 if (item->colPos() >= highlight->colPos()-colSize()/2 && item->colPos() < highlight->colPos()+colSize()/2)
396 qreal headerSize() const {
400 return flow == QDeclarativeGridView::LeftToRight
401 ? header->item->height()
402 : header->item->width();
406 virtual void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
407 Q_Q(const QDeclarativeGridView);
408 QDeclarativeFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
410 if (newGeometry.height() != oldGeometry.height()
411 || newGeometry.width() != oldGeometry.width()) {
412 if (q->isComponentComplete()) {
417 } else if ((header && header->item == item) || (footer && footer->item == item)) {
425 void positionViewAtIndex(int index, int mode);
426 virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
427 virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
428 QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
430 // for debugging only
431 void checkVisible() const {
433 for (int i = 0; i < visibleItems.count(); ++i) {
434 FxGridItem *listItem = visibleItems.at(i);
435 if (listItem->index == -1) {
437 } else if (listItem->index != visibleIndex + i - skip) {
438 for (int j = 0; j < visibleItems.count(); j++)
439 qDebug() << " index" << j << "item index" << visibleItems.at(j)->index;
440 qFatal("index %d %d %d", visibleIndex, i, listItem->index);
445 QDeclarativeGuard<QDeclarativeVisualModel> model;
446 QVariant modelVariant;
447 QList<FxGridItem*> visibleItems;
448 QHash<QDeclarativeItem*,int> unrequestedItems;
449 FxGridItem *currentItem;
450 Qt::LayoutDirection layoutDirection;
451 QDeclarativeGridView::Flow flow;
459 qreal highlightRangeStart;
460 qreal highlightRangeEnd;
461 bool highlightRangeStartValid;
462 bool highlightRangeEndValid;
463 QDeclarativeGridView::HighlightRangeMode highlightRange;
464 QDeclarativeComponent *highlightComponent;
465 FxGridItem *highlight;
466 FxGridItem *trackedItem;
467 enum MovementReason { Other, SetIndex, Mouse };
468 MovementReason moveReason;
470 QSmoothedAnimation *highlightXAnimator;
471 QSmoothedAnimation *highlightYAnimator;
472 int highlightMoveDuration;
473 QDeclarativeComponent *footerComponent;
475 QDeclarativeComponent *headerComponent;
477 enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
479 QDeclarativeGridView::SnapMode snapMode;
483 bool autoHighlight : 1;
484 bool fixCurrentVisibility : 1;
485 bool lazyRelease : 1;
486 bool layoutScheduled : 1;
487 bool deferredRelease : 1;
488 bool haveHighlightRange : 1;
489 bool currentIndexCleared : 1;
492 void QDeclarativeGridViewPrivate::init()
494 Q_Q(QDeclarativeGridView);
495 QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
496 q->setFlag(QGraphicsItem::ItemIsFocusScope);
497 q->setFlickableDirection(QDeclarativeFlickable::VerticalFlick);
498 addItemChangeListener(this, Geometry);
501 void QDeclarativeGridViewPrivate::clear()
503 for (int i = 0; i < visibleItems.count(); ++i)
504 releaseItem(visibleItems.at(i));
505 visibleItems.clear();
507 releaseItem(currentItem);
514 FxGridItem *QDeclarativeGridViewPrivate::createItem(int modelIndex)
516 Q_Q(QDeclarativeGridView);
518 requestedIndex = modelIndex;
519 FxGridItem *listItem = 0;
520 if (QDeclarativeItem *item = model->item(modelIndex, false)) {
521 listItem = new FxGridItem(item, q);
522 listItem->index = modelIndex;
523 if (model->completePending()) {
525 listItem->item->setZValue(1);
526 listItem->item->setParentItem(q->contentItem());
527 model->completeItem();
529 listItem->item->setParentItem(q->contentItem());
531 unrequestedItems.remove(listItem->item);
538 void QDeclarativeGridViewPrivate::releaseItem(FxGridItem *item)
540 Q_Q(QDeclarativeGridView);
543 if (trackedItem == item) {
544 QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
545 QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
548 if (model->release(item->item) == 0) {
549 // item was not destroyed, and we no longer reference it.
550 unrequestedItems.insert(item->item, model->indexOf(item->item, q));
555 void QDeclarativeGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
557 Q_Q(QDeclarativeGridView);
558 if (!isValid() || !q->isComponentComplete())
560 itemCount = model->count();
561 qreal bufferFrom = from - buffer;
562 qreal bufferTo = to + buffer;
563 qreal fillFrom = from;
565 if (doBuffer && (bufferMode & BufferAfter))
567 if (doBuffer && (bufferMode & BufferBefore))
568 fillFrom = bufferFrom;
570 bool changed = false;
572 int colPos = colPosAt(visibleIndex);
573 int rowPos = rowPosAt(visibleIndex);
574 int modelIndex = visibleIndex;
575 if (visibleItems.count()) {
576 rowPos = visibleItems.last()->rowPos();
577 colPos = visibleItems.last()->colPos() + colSize();
578 if (colPos > colSize() * (columns-1)) {
582 int i = visibleItems.count() - 1;
583 while (i > 0 && visibleItems.at(i)->index == -1)
585 modelIndex = visibleItems.at(i)->index + 1;
588 if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
589 || fillTo < rowPosAt(visibleIndex) - rowSize())) {
590 // We've jumped more than a page. Estimate which items are now
591 // visible and fill from there.
592 int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
593 for (int i = 0; i < visibleItems.count(); ++i)
594 releaseItem(visibleItems.at(i));
595 visibleItems.clear();
597 if (modelIndex >= model->count())
598 modelIndex = model->count() - 1;
599 else if (modelIndex < 0)
601 modelIndex = modelIndex / columns * columns;
602 visibleIndex = modelIndex;
603 colPos = colPosAt(visibleIndex);
604 rowPos = rowPosAt(visibleIndex);
607 int colNum = colPos / colSize();
609 FxGridItem *item = 0;
611 // Item creation and release is staggered in order to avoid
612 // creating/releasing multiple items in one frame
613 // while flicking (as much as possible).
614 while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
615 // qDebug() << "refill: append item" << modelIndex;
616 if (!(item = createItem(modelIndex)))
618 item->setPosition(colPos, rowPos);
619 visibleItems.append(item);
622 if (colPos > colSize() * (columns-1)) {
629 if (doBuffer) // never buffer more than one item per frame
633 if (visibleItems.count()) {
634 rowPos = visibleItems.first()->rowPos();
635 colPos = visibleItems.first()->colPos() - colSize();
637 colPos = colSize() * (columns - 1);
641 colNum = colPos / colSize();
642 while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
643 // qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
644 if (!(item = createItem(visibleIndex-1)))
647 item->setPosition(colPos, rowPos);
648 visibleItems.prepend(item);
652 colPos = colSize() * (columns - 1);
657 if (doBuffer) // never buffer more than one item per frame
661 if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
662 while (visibleItems.count() > 1
663 && (item = visibleItems.first())
664 && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
665 if (item->attached->delayRemove())
667 // qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
668 if (item->index != -1)
670 visibleItems.removeFirst();
674 while (visibleItems.count() > 1
675 && (item = visibleItems.last())
676 && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
677 if (item->attached->delayRemove())
679 // qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
680 visibleItems.removeLast();
684 deferredRelease = false;
686 deferredRelease = true;
693 if (flow == QDeclarativeGridView::LeftToRight)
694 q->setContentHeight(endPosition() - startPosition());
696 q->setContentWidth(endPosition() - startPosition());
697 } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
698 refill(from, to, true);
703 void QDeclarativeGridViewPrivate::updateGrid()
705 Q_Q(QDeclarativeGridView);
707 columns = (int)qMax((flow == QDeclarativeGridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
709 if (flow == QDeclarativeGridView::LeftToRight)
710 q->setContentHeight(endPosition() - startPosition());
712 q->setContentWidth(lastPosition() - originPosition());
716 void QDeclarativeGridViewPrivate::scheduleLayout()
718 Q_Q(QDeclarativeGridView);
719 if (!layoutScheduled) {
720 layoutScheduled = true;
721 QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority);
725 void QDeclarativeGridViewPrivate::layout()
727 Q_Q(QDeclarativeGridView);
728 layoutScheduled = false;
729 if (!isValid() && !visibleItems.count()) {
733 if (visibleItems.count()) {
734 qreal rowPos = visibleItems.first()->rowPos();
735 qreal colPos = visibleItems.first()->colPos();
736 int col = visibleIndex % columns;
737 if (colPos != col * colSize()) {
738 colPos = col * colSize();
739 visibleItems.first()->setPosition(colPos, rowPos);
741 for (int i = 1; i < visibleItems.count(); ++i) {
742 FxGridItem *item = visibleItems.at(i);
744 if (colPos > colSize() * (columns-1)) {
748 item->setPosition(colPos, rowPos);
758 if (flow == QDeclarativeGridView::LeftToRight) {
759 q->setContentHeight(endPosition() - startPosition());
762 q->setContentWidth(endPosition() - startPosition());
765 updateUnrequestedPositions();
768 void QDeclarativeGridViewPrivate::updateUnrequestedIndexes()
770 Q_Q(QDeclarativeGridView);
771 QHash<QDeclarativeItem*,int>::iterator it;
772 for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
773 *it = model->indexOf(it.key(), q);
776 void QDeclarativeGridViewPrivate::updateUnrequestedPositions()
778 QHash<QDeclarativeItem*,int>::const_iterator it;
779 for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
780 QDeclarativeItem *item = it.key();
781 if (flow == QDeclarativeGridView::LeftToRight) {
782 item->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
784 if (isRightToLeftTopToBottom())
785 item->setPos(QPointF(-rowPosAt(*it)-item->width(), colPosAt(*it)));
787 item->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
792 void QDeclarativeGridViewPrivate::updateTrackedItem()
794 Q_Q(QDeclarativeGridView);
795 FxGridItem *item = currentItem;
799 if (trackedItem && item != trackedItem) {
800 QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
801 QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
805 if (!trackedItem && item) {
807 QObject::connect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
808 QObject::connect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
811 q->trackedPositionChanged();
814 void QDeclarativeGridViewPrivate::createHighlight()
816 Q_Q(QDeclarativeGridView);
817 bool changed = false;
819 if (trackedItem == highlight)
821 delete highlight->item;
824 delete highlightXAnimator;
825 delete highlightYAnimator;
826 highlightXAnimator = 0;
827 highlightYAnimator = 0;
832 QDeclarativeItem *item = 0;
833 if (highlightComponent) {
834 QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
835 QObject *nobj = highlightComponent->create(highlightContext);
837 QDeclarative_setParent_noEvent(highlightContext, nobj);
838 item = qobject_cast<QDeclarativeItem *>(nobj);
842 delete highlightContext;
845 item = new QDeclarativeItem;
846 QDeclarative_setParent_noEvent(item, q->contentItem());
847 item->setParentItem(q->contentItem());
850 QDeclarative_setParent_noEvent(item, q->contentItem());
851 item->setParentItem(q->contentItem());
852 highlight = new FxGridItem(item, q);
853 if (currentItem && autoHighlight)
854 highlight->setPosition(currentItem->colPos(), currentItem->rowPos());
855 highlightXAnimator = new QSmoothedAnimation(q);
856 highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
857 highlightXAnimator->userDuration = highlightMoveDuration;
858 highlightYAnimator = new QSmoothedAnimation(q);
859 highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y"));
860 highlightYAnimator->userDuration = highlightMoveDuration;
862 highlightXAnimator->restart();
863 highlightYAnimator->restart();
869 emit q->highlightItemChanged();
872 void QDeclarativeGridViewPrivate::updateHighlight()
874 if ((!currentItem && highlight) || (currentItem && !highlight))
876 if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
877 // auto-update highlight
878 highlightXAnimator->to = currentItem->item->x();
879 highlightYAnimator->to = currentItem->item->y();
880 highlight->item->setWidth(currentItem->item->width());
881 highlight->item->setHeight(currentItem->item->height());
882 highlightXAnimator->restart();
883 highlightYAnimator->restart();
888 void QDeclarativeGridViewPrivate::updateCurrent(int modelIndex)
890 Q_Q(QDeclarativeGridView);
891 if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
893 currentItem->attached->setIsCurrentItem(false);
894 releaseItem(currentItem);
896 currentIndex = modelIndex;
897 emit q->currentIndexChanged();
899 } else if (currentIndex != modelIndex) {
900 currentIndex = modelIndex;
901 emit q->currentIndexChanged();
906 if (currentItem && currentIndex == modelIndex) {
911 FxGridItem *oldCurrentItem = currentItem;
912 currentIndex = modelIndex;
913 currentItem = createItem(modelIndex);
914 fixCurrentVisibility = true;
915 if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
916 oldCurrentItem->attached->setIsCurrentItem(false);
918 currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
919 currentItem->item->setFocus(true);
920 currentItem->attached->setIsCurrentItem(true);
923 emit q->currentIndexChanged();
924 releaseItem(oldCurrentItem);
927 void QDeclarativeGridViewPrivate::updateFooter()
929 Q_Q(QDeclarativeGridView);
930 if (!footer && footerComponent) {
931 QDeclarativeItem *item = 0;
932 QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
933 QObject *nobj = footerComponent->create(context);
935 QDeclarative_setParent_noEvent(context, nobj);
936 item = qobject_cast<QDeclarativeItem *>(nobj);
943 QDeclarative_setParent_noEvent(item, q->contentItem());
944 item->setParentItem(q->contentItem());
946 QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
947 itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
948 footer = new FxGridItem(item, q);
954 if (isRightToLeftTopToBottom()) {
955 rowOffset = footer->item->width()-cellWidth;
958 if (q->effectiveLayoutDirection() == Qt::RightToLeft)
959 colOffset = footer->item->width()-cellWidth;
961 if (visibleItems.count()) {
962 qreal endPos = lastPosition();
963 if (lastVisibleIndex() == model->count()-1) {
964 footer->setPosition(colOffset, endPos + rowOffset);
966 qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
967 if (endPos <= visiblePos || footer->endRowPos() < endPos + rowOffset)
968 footer->setPosition(colOffset, endPos + rowOffset);
973 endPos += flow == QDeclarativeGridView::LeftToRight ? header->item->height() : header->item->width();
975 footer->setPosition(colOffset, endPos);
980 void QDeclarativeGridViewPrivate::updateHeader()
982 Q_Q(QDeclarativeGridView);
983 if (!header && headerComponent) {
984 QDeclarativeItem *item = 0;
985 QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
986 QObject *nobj = headerComponent->create(context);
988 QDeclarative_setParent_noEvent(context, nobj);
989 item = qobject_cast<QDeclarativeItem *>(nobj);
996 QDeclarative_setParent_noEvent(item, q->contentItem());
997 item->setParentItem(q->contentItem());
999 QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
1000 itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
1001 header = new FxGridItem(item, q);
1005 qreal colOffset = 0;
1007 if (isRightToLeftTopToBottom()) {
1008 rowOffset = -cellWidth;
1010 rowOffset = -headerSize();
1011 if (q->effectiveLayoutDirection() == Qt::RightToLeft)
1012 colOffset = header->item->width()-cellWidth;
1014 if (visibleItems.count()) {
1015 qreal startPos = originPosition();
1016 if (visibleIndex == 0) {
1017 header->setPosition(colOffset, startPos + rowOffset);
1019 qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position();
1020 qreal headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
1021 if (tempPos <= startPos || headerPos > startPos + rowOffset)
1022 header->setPosition(colOffset, startPos + rowOffset);
1025 header->setPosition(colOffset, 0);
1030 void QDeclarativeGridViewPrivate::fixupPosition()
1033 if (flow == QDeclarativeGridView::LeftToRight)
1039 void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
1041 if ((flow == QDeclarativeGridView::TopToBottom && &data == &vData)
1042 || (flow == QDeclarativeGridView::LeftToRight && &data == &hData))
1045 fixupMode = moveReason == Mouse ? fixupMode : Immediate;
1047 qreal highlightStart;
1050 if (isRightToLeftTopToBottom()) {
1051 // Handle Right-To-Left exceptions
1052 viewPos = -position()-size();
1053 highlightStart = highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
1054 highlightEnd = highlightRangeEndValid ? size()-highlightRangeStart : highlightRangeEnd;
1056 viewPos = position();
1057 highlightStart = highlightRangeStart;
1058 highlightEnd = highlightRangeEnd;
1061 if (snapMode != QDeclarativeGridView::NoSnap) {
1062 qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position();
1063 FxGridItem *topItem = snapItemAt(tempPosition+highlightStart);
1064 FxGridItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
1066 if (topItem && bottomItem && haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) {
1067 qreal topPos = qMin(topItem->rowPos() - highlightStart, -maxExtent);
1068 qreal bottomPos = qMax(bottomItem->rowPos() - highlightEnd, -minExtent);
1069 pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
1070 } else if (topItem) {
1071 qreal headerPos = 0;
1073 headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
1074 if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2) {
1075 pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart;
1077 if (isRightToLeftTopToBottom())
1078 pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
1080 pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
1082 } else if (bottomItem) {
1083 if (isRightToLeftTopToBottom())
1084 pos = qMax(qMin(-bottomItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
1086 pos = qMax(qMin(bottomItem->rowPos() - highlightStart, -maxExtent), -minExtent);
1088 QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent);
1091 if (currentItem && haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) {
1093 qreal currPos = currentItem->rowPos();
1094 if (isRightToLeftTopToBottom())
1095 pos = -pos-size(); // Transform Pos if required
1096 if (pos < currPos + rowSize() - highlightEnd)
1097 pos = currPos + rowSize() - highlightEnd;
1098 if (pos > currPos - highlightStart)
1099 pos = currPos - highlightStart;
1100 if (isRightToLeftTopToBottom())
1101 pos = -pos-size(); // Untransform
1103 qreal dist = qAbs(data.move + pos);
1105 timeline.reset(data.move);
1106 if (fixupMode != Immediate) {
1107 timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
1108 data.fixingUp = true;
1110 timeline.set(data.move, -pos);
1112 vTime = timeline.time();
1114 } else if (haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) {
1117 qreal pos = currentItem->rowPos();
1118 if (viewPos < pos + rowSize() - highlightEnd)
1119 viewPos = pos + rowSize() - highlightEnd;
1120 if (viewPos > pos - highlightStart)
1121 viewPos = pos - highlightStart;
1122 if (isRightToLeftTopToBottom())
1123 viewPos = -viewPos-size();
1124 timeline.reset(data.move);
1125 if (viewPos != position()) {
1126 if (fixupMode != Immediate) {
1127 timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
1128 data.fixingUp = true;
1130 timeline.set(data.move, -viewPos);
1133 vTime = timeline.time();
1136 QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent);
1138 data.inOvershoot = false;
1142 void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
1143 QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity)
1145 Q_Q(QDeclarativeGridView);
1146 data.fixingUp = false;
1148 if ((!haveHighlightRange || highlightRange != QDeclarativeGridView::StrictlyEnforceRange)
1149 && snapMode == QDeclarativeGridView::NoSnap) {
1150 QDeclarativeFlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
1153 qreal maxDistance = 0;
1154 qreal dataValue = isRightToLeftTopToBottom() ? -data.move.value()+size() : data.move.value();
1155 // -ve velocity means list is moving up/left
1157 if (data.move.value() < minExtent) {
1158 if (snapMode == QDeclarativeGridView::SnapOneRow) {
1159 if (FxGridItem *item = firstVisibleItem()) {
1160 maxDistance = qAbs(item->rowPos() + dataValue);
1163 maxDistance = qAbs(minExtent - data.move.value());
1166 if (snapMode == QDeclarativeGridView::NoSnap && highlightRange != QDeclarativeGridView::StrictlyEnforceRange)
1167 data.flickTarget = minExtent;
1169 if (data.move.value() > maxExtent) {
1170 if (snapMode == QDeclarativeGridView::SnapOneRow) {
1171 qreal pos = snapPosAt(-dataValue) + (isRightToLeftTopToBottom() ? 0 : rowSize());
1172 maxDistance = qAbs(pos + dataValue);
1174 maxDistance = qAbs(maxExtent - data.move.value());
1177 if (snapMode == QDeclarativeGridView::NoSnap && highlightRange != QDeclarativeGridView::StrictlyEnforceRange)
1178 data.flickTarget = maxExtent;
1181 bool overShoot = boundsBehavior == QDeclarativeFlickable::DragAndOvershootBounds;
1182 qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
1184 if (maxDistance > 0 || overShoot) {
1185 // This mode requires the grid to stop exactly on a row boundary.
1187 if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
1193 qreal accel = deceleration;
1195 qreal overshootDist = 0.0;
1196 if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarativeGridView::SnapOneRow) {
1197 // + rowSize()/4 to encourage moving at least one item in the flick direction
1198 qreal dist = v2 / (accel * 2.0) + rowSize()/4;
1199 dist = qMin(dist, maxDistance);
1202 qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist;
1203 data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart;
1204 data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget;
1205 qreal adjDist = -data.flickTarget + data.move.value();
1206 if (qAbs(adjDist) > qAbs(dist)) {
1207 // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
1208 qreal adjv2 = accel * 2.0f * qAbs(adjDist);
1217 accel = v2 / (2.0f * qAbs(dist));
1219 data.flickTarget = velocity > 0 ? minExtent : maxExtent;
1220 overshootDist = overShoot ? overShootDistance(vSize) : 0;
1222 timeline.reset(data.move);
1223 timeline.accel(data.move, v, accel, maxDistance + overshootDist);
1224 timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this));
1225 if (!flickingHorizontally && q->xflick()) {
1226 flickingHorizontally = true;
1227 emit q->flickingChanged();
1228 emit q->flickingHorizontallyChanged();
1229 emit q->flickStarted();
1231 if (!flickingVertically && q->yflick()) {
1232 flickingVertically = true;
1233 emit q->flickingChanged();
1234 emit q->flickingVerticallyChanged();
1235 emit q->flickStarted();
1238 timeline.reset(data.move);
1239 fixup(data, minExtent, maxExtent);
1244 //----------------------------------------------------------------------------
1247 \qmlclass GridView QDeclarativeGridView
1249 \ingroup qml-view-elements
1252 \brief The GridView item provides a grid view of items provided by a model.
1254 A GridView displays data from models created from built-in QML elements like ListModel
1255 and XmlListModel, or custom model classes defined in C++ that inherit from
1258 A GridView has a \l model, which defines the data to be displayed, and
1259 a \l delegate, which defines how the data should be displayed. Items in a
1260 GridView are laid out horizontally or vertically. Grid views are inherently flickable
1261 as GridView inherits from \l Flickable.
1263 \section1 Example Usage
1265 The following example shows the definition of a simple list model defined
1266 in a file called \c ContactModel.qml:
1268 \snippet doc/src/snippets/declarative/gridview/ContactModel.qml 0
1270 \div {class="float-right"}
1271 \inlineimage gridview-simple.png
1274 This model can be referenced as \c ContactModel in other QML files. See \l{QML Modules}
1275 for more information about creating reusable components like this.
1277 Another component can display this model data in a GridView, as in the following
1278 example, which creates a \c ContactModel component for its model, and a \l Column element
1279 (containing \l Image and \l Text elements) for its delegate.
1282 \snippet doc/src/snippets/declarative/gridview/gridview.qml import
1284 \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs simple
1286 \div {class="float-right"}
1287 \inlineimage gridview-highlight.png
1290 The view will create a new delegate for each item in the model. Note that the delegate
1291 is able to access the model's \c name and \c portrait data directly.
1293 An improved grid view is shown below. The delegate is visually improved and is moved
1294 into a separate \c contactDelegate component.
1297 \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs advanced
1299 The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
1300 and \c focus is set to \c true to enable keyboard navigation for the grid view.
1301 The grid view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
1303 Delegates are instantiated as needed and may be destroyed at any time.
1304 State should \e never be stored in a delegate.
1306 GridView attaches a number of properties to the root item of the delegate, for example
1307 \c {GridView.isCurrentItem}. In the following example, the root delegate item can access
1308 this attached property directly as \c GridView.isCurrentItem, while the child
1309 \c contactInfo object must refer to this property as \c wrapper.GridView.isCurrentItem.
1311 \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
1313 \note Views do not set the \l{Item::}{clip} property automatically.
1314 If the view is not clipped by another item or the screen, it will be necessary
1315 to set this property to true in order to clip the items that are partially or
1316 fully outside the view.
1318 \sa {declarative/modelviews/gridview}{GridView example}
1320 QDeclarativeGridView::QDeclarativeGridView(QDeclarativeItem *parent)
1321 : QDeclarativeFlickable(*(new QDeclarativeGridViewPrivate), parent)
1323 Q_D(QDeclarativeGridView);
1327 QDeclarativeGridView::~QDeclarativeGridView()
1329 Q_D(QDeclarativeGridView);
1338 \qmlattachedproperty bool GridView::isCurrentItem
1339 This attached property is true if this delegate is the current item; otherwise false.
1341 It is attached to each instance of the delegate.
1345 \qmlattachedproperty GridView GridView::view
1346 This attached property holds the view that manages this delegate instance.
1348 It is attached to each instance of the delegate.
1350 \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
1354 \qmlattachedproperty bool GridView::delayRemove
1355 This attached property holds whether the delegate may be destroyed.
1357 It is attached to each instance of the delegate.
1359 It is sometimes necessary to delay the destruction of an item
1360 until an animation completes.
1362 The example below ensures that the animation completes before
1363 the item is removed from the grid.
1365 \snippet doc/src/snippets/declarative/gridview/gridview.qml delayRemove
1369 \qmlattachedsignal GridView::onAdd()
1370 This attached handler is called immediately after an item is added to the view.
1374 \qmlattachedsignal GridView::onRemove()
1375 This attached handler is called immediately before an item is removed from the view.
1380 \qmlproperty model GridView::model
1381 This property holds the model providing data for the grid.
1383 The model provides the set of data that is used to create the items
1384 in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
1385 or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
1386 used, it must be a subclass of \l QAbstractItemModel or a simple list.
1388 \sa {qmlmodels}{Data Models}
1390 QVariant QDeclarativeGridView::model() const
1392 Q_D(const QDeclarativeGridView);
1393 return d->modelVariant;
1397 int QDeclarativeGridView::modelCount() const
1399 Q_D(const QDeclarativeGridView);
1400 return d->model->count();
1403 void QDeclarativeGridView::setModel(const QVariant &model)
1405 Q_D(QDeclarativeGridView);
1406 if (d->modelVariant == model)
1409 disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
1410 disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
1411 disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
1412 disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
1413 disconnect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
1414 disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
1417 d->modelVariant = model;
1418 QObject *object = qvariant_cast<QObject*>(model);
1419 QDeclarativeVisualModel *vim = 0;
1420 if (object && (vim = qobject_cast<QDeclarativeVisualModel *>(object))) {
1423 d->ownModel = false;
1428 d->model = new QDeclarativeVisualDataModel(qmlContext(this), this);
1431 if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model))
1432 dataModel->setModel(model);
1435 d->bufferMode = QDeclarativeGridViewPrivate::BufferBefore | QDeclarativeGridViewPrivate::BufferAfter;
1436 if (isComponentComplete()) {
1438 if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
1441 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
1442 d->updateCurrent(d->currentIndex);
1443 if (d->highlight && d->currentItem) {
1444 if (d->autoHighlight)
1445 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
1446 d->updateTrackedItem();
1448 d->moveReason = QDeclarativeGridViewPrivate::Other;
1451 connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
1452 connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
1453 connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
1454 connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
1455 connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
1456 connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
1457 emit countChanged();
1459 emit modelChanged();
1463 \qmlproperty Component GridView::delegate
1465 The delegate provides a template defining each item instantiated by the view.
1466 The index is exposed as an accessible \c index property. Properties of the
1467 model are also available depending upon the type of \l {qmlmodels}{Data Model}.
1469 The number of elements in the delegate has a direct effect on the
1470 flicking performance of the view. If at all possible, place functionality
1471 that is not needed for the normal display of the delegate in a \l Loader which
1472 can load additional elements when needed.
1474 The GridView will layout the items based on the size of the root item
1477 \note Delegates are instantiated as needed and may be destroyed at any time.
1478 State should \e never be stored in a delegate.
1480 QDeclarativeComponent *QDeclarativeGridView::delegate() const
1482 Q_D(const QDeclarativeGridView);
1484 if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model))
1485 return dataModel->delegate();
1491 void QDeclarativeGridView::setDelegate(QDeclarativeComponent *delegate)
1493 Q_D(QDeclarativeGridView);
1494 if (delegate == this->delegate())
1498 d->model = new QDeclarativeVisualDataModel(qmlContext(this));
1501 if (QDeclarativeVisualDataModel *dataModel = qobject_cast<QDeclarativeVisualDataModel*>(d->model)) {
1502 dataModel->setDelegate(delegate);
1503 if (isComponentComplete()) {
1504 for (int i = 0; i < d->visibleItems.count(); ++i)
1505 d->releaseItem(d->visibleItems.at(i));
1506 d->visibleItems.clear();
1507 d->releaseItem(d->currentItem);
1510 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
1511 d->updateCurrent(d->currentIndex);
1512 if (d->highlight && d->currentItem) {
1513 if (d->autoHighlight)
1514 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
1515 d->updateTrackedItem();
1517 d->moveReason = QDeclarativeGridViewPrivate::Other;
1519 emit delegateChanged();
1524 \qmlproperty int GridView::currentIndex
1525 \qmlproperty Item GridView::currentItem
1527 The \c currentIndex property holds the index of the current item, and
1528 \c currentItem holds the current item. Setting the currentIndex to -1
1529 will clear the highlight and set currentItem to null.
1531 If highlightFollowsCurrentItem is \c true, setting either of these
1532 properties will smoothly scroll the GridView so that the current
1533 item becomes visible.
1535 Note that the position of the current item
1536 may only be approximate until it becomes visible in the view.
1538 int QDeclarativeGridView::currentIndex() const
1540 Q_D(const QDeclarativeGridView);
1541 return d->currentIndex;
1544 void QDeclarativeGridView::setCurrentIndex(int index)
1546 Q_D(QDeclarativeGridView);
1547 if (d->requestedIndex >= 0) // currently creating item
1549 d->currentIndexCleared = (index == -1);
1550 if (index == d->currentIndex)
1552 if (isComponentComplete() && d->isValid()) {
1553 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
1554 d->updateCurrent(index);
1556 d->currentIndex = index;
1557 emit currentIndexChanged();
1561 QDeclarativeItem *QDeclarativeGridView::currentItem()
1563 Q_D(QDeclarativeGridView);
1564 if (!d->currentItem)
1566 return d->currentItem->item;
1570 \qmlproperty Item GridView::highlightItem
1572 This holds the highlight item created from the \l highlight component.
1574 The highlightItem is managed by the view unless
1575 \l highlightFollowsCurrentItem is set to false.
1577 \sa highlight, highlightFollowsCurrentItem
1579 QDeclarativeItem *QDeclarativeGridView::highlightItem()
1581 Q_D(QDeclarativeGridView);
1584 return d->highlight->item;
1588 \qmlproperty int GridView::count
1589 This property holds the number of items in the view.
1591 int QDeclarativeGridView::count() const
1593 Q_D(const QDeclarativeGridView);
1595 return d->model->count();
1600 \qmlproperty Component GridView::highlight
1601 This property holds the component to use as the highlight.
1603 An instance of the highlight component is created for each view.
1604 The geometry of the resulting component instance will be managed by the view
1605 so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
1607 \sa highlightItem, highlightFollowsCurrentItem
1609 QDeclarativeComponent *QDeclarativeGridView::highlight() const
1611 Q_D(const QDeclarativeGridView);
1612 return d->highlightComponent;
1615 void QDeclarativeGridView::setHighlight(QDeclarativeComponent *highlight)
1617 Q_D(QDeclarativeGridView);
1618 if (highlight != d->highlightComponent) {
1619 d->highlightComponent = highlight;
1620 d->updateCurrent(d->currentIndex);
1621 emit highlightChanged();
1626 \qmlproperty bool GridView::highlightFollowsCurrentItem
1627 This property sets whether the highlight is managed by the view.
1629 If this property is true (the default value), the highlight is moved smoothly
1630 to follow the current item. Otherwise, the
1631 highlight is not moved by the view, and any movement must be implemented
1634 Here is a highlight with its motion defined by a \l {SpringAnimation} item:
1636 \snippet doc/src/snippets/declarative/gridview/gridview.qml highlightFollowsCurrentItem
1638 bool QDeclarativeGridView::highlightFollowsCurrentItem() const
1640 Q_D(const QDeclarativeGridView);
1641 return d->autoHighlight;
1644 void QDeclarativeGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
1646 Q_D(QDeclarativeGridView);
1647 if (d->autoHighlight != autoHighlight) {
1648 d->autoHighlight = autoHighlight;
1649 if (autoHighlight) {
1650 d->updateHighlight();
1651 } else if (d->highlightXAnimator) {
1652 d->highlightXAnimator->stop();
1653 d->highlightYAnimator->stop();
1659 \qmlproperty int GridView::highlightMoveDuration
1660 This property holds the move animation duration of the highlight delegate.
1662 highlightFollowsCurrentItem must be true for this property
1665 The default value for the duration is 150ms.
1667 \sa highlightFollowsCurrentItem
1669 int QDeclarativeGridView::highlightMoveDuration() const
1671 Q_D(const QDeclarativeGridView);
1672 return d->highlightMoveDuration;
1675 void QDeclarativeGridView::setHighlightMoveDuration(int duration)
1677 Q_D(QDeclarativeGridView);
1678 if (d->highlightMoveDuration != duration) {
1679 d->highlightMoveDuration = duration;
1680 if (d->highlightYAnimator) {
1681 d->highlightXAnimator->userDuration = d->highlightMoveDuration;
1682 d->highlightYAnimator->userDuration = d->highlightMoveDuration;
1684 emit highlightMoveDurationChanged();
1690 \qmlproperty real GridView::preferredHighlightBegin
1691 \qmlproperty real GridView::preferredHighlightEnd
1692 \qmlproperty enumeration GridView::highlightRangeMode
1694 These properties define the preferred range of the highlight (for the current item)
1695 within the view. The \c preferredHighlightBegin value must be less than the
1696 \c preferredHighlightEnd value.
1698 These properties affect the position of the current item when the view is scrolled.
1699 For example, if the currently selected item should stay in the middle of the
1700 view when it is scrolled, set the \c preferredHighlightBegin and
1701 \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
1702 item would be. If the \c currentItem is changed programmatically, the view will
1703 automatically scroll so that the current item is in the middle of the view.
1704 Furthermore, the behavior of the current item index will occur whether or not a
1707 Valid values for \c highlightRangeMode are:
1710 \o GridView.ApplyRange - the view attempts to maintain the highlight within the range.
1711 However, the highlight can move outside of the range at the ends of the view or due
1712 to mouse interaction.
1713 \o GridView.StrictlyEnforceRange - the highlight never moves outside of the range.
1714 The current item changes if a keyboard or mouse action would cause the highlight to move
1715 outside of the range.
1716 \o GridView.NoHighlightRange - this is the default value.
1719 qreal QDeclarativeGridView::preferredHighlightBegin() const
1721 Q_D(const QDeclarativeGridView);
1722 return d->highlightRangeStart;
1725 void QDeclarativeGridView::setPreferredHighlightBegin(qreal start)
1727 Q_D(QDeclarativeGridView);
1728 d->highlightRangeStartValid = true;
1729 if (d->highlightRangeStart == start)
1731 d->highlightRangeStart = start;
1732 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1733 emit preferredHighlightBeginChanged();
1736 void QDeclarativeGridView::resetPreferredHighlightBegin()
1738 Q_D(QDeclarativeGridView);
1739 d->highlightRangeStartValid = false;
1740 if (d->highlightRangeStart == 0)
1742 d->highlightRangeStart = 0;
1743 emit preferredHighlightBeginChanged();
1746 qreal QDeclarativeGridView::preferredHighlightEnd() const
1748 Q_D(const QDeclarativeGridView);
1749 return d->highlightRangeEnd;
1752 void QDeclarativeGridView::setPreferredHighlightEnd(qreal end)
1754 Q_D(QDeclarativeGridView);
1755 d->highlightRangeEndValid = true;
1756 if (d->highlightRangeEnd == end)
1758 d->highlightRangeEnd = end;
1759 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1760 emit preferredHighlightEndChanged();
1763 void QDeclarativeGridView::resetPreferredHighlightEnd()
1765 Q_D(QDeclarativeGridView);
1766 d->highlightRangeEndValid = false;
1767 if (d->highlightRangeEnd == 0)
1769 d->highlightRangeEnd = 0;
1770 emit preferredHighlightEndChanged();
1773 QDeclarativeGridView::HighlightRangeMode QDeclarativeGridView::highlightRangeMode() const
1775 Q_D(const QDeclarativeGridView);
1776 return d->highlightRange;
1779 void QDeclarativeGridView::setHighlightRangeMode(HighlightRangeMode mode)
1781 Q_D(QDeclarativeGridView);
1782 if (d->highlightRange == mode)
1784 d->highlightRange = mode;
1785 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1786 emit highlightRangeModeChanged();
1790 \qmlproperty enumeration GridView::layoutDirection
1791 This property holds the layout direction of the grid.
1796 \o Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is
1797 dependent on the \l GridView::flow property.
1798 \o Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent
1799 on the \l GridView:flow property.
1802 \bold Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if
1803 GridView::layoutDirection is set to Qt.RightToLeft. The GridView.LeftToRight flow value simply
1804 indicates that the flow is horizontal.
1807 Qt::LayoutDirection QDeclarativeGridView::layoutDirection() const
1809 Q_D(const QDeclarativeGridView);
1810 return d->layoutDirection;
1813 void QDeclarativeGridView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
1815 Q_D(QDeclarativeGridView);
1816 if (d->layoutDirection != layoutDirection) {
1817 d->layoutDirection = layoutDirection;
1819 emit layoutDirectionChanged();
1820 emit effectiveLayoutDirectionChanged();
1825 \qmlproperty enumeration GridView::effectiveLayoutDirection
1826 This property holds the effective layout direction of the grid.
1828 When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
1829 the visual layout direction of the grid will be mirrored. However, the
1830 property \l {GridView::layoutDirection}{layoutDirection} will remain unchanged.
1832 \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
1835 Qt::LayoutDirection QDeclarativeGridView::effectiveLayoutDirection() const
1837 Q_D(const QDeclarativeGridView);
1838 if (d->effectiveLayoutMirror)
1839 return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
1841 return d->layoutDirection;
1845 \qmlproperty enumeration GridView::flow
1846 This property holds the flow of the grid.
1851 \o GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically
1852 \o GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally
1855 QDeclarativeGridView::Flow QDeclarativeGridView::flow() const
1857 Q_D(const QDeclarativeGridView);
1861 void QDeclarativeGridView::setFlow(Flow flow)
1863 Q_D(QDeclarativeGridView);
1864 if (d->flow != flow) {
1866 if (d->flow == LeftToRight) {
1867 setContentWidth(-1);
1868 setFlickableDirection(QDeclarativeFlickable::VerticalFlick);
1870 setContentHeight(-1);
1871 setFlickableDirection(QDeclarativeFlickable::HorizontalFlick);
1881 \qmlproperty bool GridView::keyNavigationWraps
1882 This property holds whether the grid wraps key navigation
1884 If this is true, key navigation that would move the current item selection
1885 past one end of the view instead wraps around and moves the selection to
1886 the other end of the view.
1888 By default, key navigation is not wrapped.
1890 bool QDeclarativeGridView::isWrapEnabled() const
1892 Q_D(const QDeclarativeGridView);
1896 void QDeclarativeGridView::setWrapEnabled(bool wrap)
1898 Q_D(QDeclarativeGridView);
1899 if (d->wrap == wrap)
1902 emit keyNavigationWrapsChanged();
1906 \qmlproperty int GridView::cacheBuffer
1907 This property determines whether delegates are retained outside the
1908 visible area of the view.
1910 If non-zero the view will keep as many delegates
1911 instantiated as will fit within the buffer specified. For example,
1912 if in a vertical view the delegate is 20 pixels high and \c cacheBuffer is
1913 set to 40, then up to 2 delegates above and 2 delegates below the visible
1914 area may be retained.
1916 Note that cacheBuffer is not a pixel buffer - it only maintains additional
1917 instantiated delegates.
1919 Setting this value can make scrolling the list smoother at the expense
1920 of additional memory usage. It is not a substitute for creating efficient
1921 delegates; the fewer elements in a delegate, the faster a view may be
1924 int QDeclarativeGridView::cacheBuffer() const
1926 Q_D(const QDeclarativeGridView);
1930 void QDeclarativeGridView::setCacheBuffer(int buffer)
1932 Q_D(QDeclarativeGridView);
1933 if (d->buffer != buffer) {
1935 if (isComponentComplete())
1937 emit cacheBufferChanged();
1942 \qmlproperty int GridView::cellWidth
1943 \qmlproperty int GridView::cellHeight
1945 These properties holds the width and height of each cell in the grid.
1947 The default cell size is 100x100.
1949 int QDeclarativeGridView::cellWidth() const
1951 Q_D(const QDeclarativeGridView);
1952 return d->cellWidth;
1955 void QDeclarativeGridView::setCellWidth(int cellWidth)
1957 Q_D(QDeclarativeGridView);
1958 if (cellWidth != d->cellWidth && cellWidth > 0) {
1959 d->cellWidth = qMax(1, cellWidth);
1961 emit cellWidthChanged();
1966 int QDeclarativeGridView::cellHeight() const
1968 Q_D(const QDeclarativeGridView);
1969 return d->cellHeight;
1972 void QDeclarativeGridView::setCellHeight(int cellHeight)
1974 Q_D(QDeclarativeGridView);
1975 if (cellHeight != d->cellHeight && cellHeight > 0) {
1976 d->cellHeight = qMax(1, cellHeight);
1978 emit cellHeightChanged();
1983 \qmlproperty enumeration GridView::snapMode
1985 This property determines how the view scrolling will settle following a drag or flick.
1986 The possible values are:
1989 \o GridView.NoSnap (default) - the view stops anywhere within the visible area.
1990 \o GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow)
1991 aligned with the start of the view.
1992 \o GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow)
1993 away from the first visible row at the time the mouse button is released.
1994 This mode is particularly useful for moving one page at a time.
1998 QDeclarativeGridView::SnapMode QDeclarativeGridView::snapMode() const
2000 Q_D(const QDeclarativeGridView);
2004 void QDeclarativeGridView::setSnapMode(SnapMode mode)
2006 Q_D(QDeclarativeGridView);
2007 if (d->snapMode != mode) {
2009 emit snapModeChanged();
2014 \qmlproperty Component GridView::footer
2015 This property holds the component to use as the footer.
2017 An instance of the footer component is created for each view. The
2018 footer is positioned at the end of the view, after any items.
2022 QDeclarativeComponent *QDeclarativeGridView::footer() const
2024 Q_D(const QDeclarativeGridView);
2025 return d->footerComponent;
2028 void QDeclarativeGridView::setFooter(QDeclarativeComponent *footer)
2030 Q_D(QDeclarativeGridView);
2031 if (d->footerComponent != footer) {
2034 scene()->removeItem(d->footer->item);
2035 d->footer->item->deleteLater();
2039 d->footerComponent = footer;
2040 if (isComponentComplete()) {
2045 emit footerChanged();
2050 \qmlproperty Component GridView::header
2051 This property holds the component to use as the header.
2053 An instance of the header component is created for each view. The
2054 header is positioned at the beginning of the view, before any items.
2058 QDeclarativeComponent *QDeclarativeGridView::header() const
2060 Q_D(const QDeclarativeGridView);
2061 return d->headerComponent;
2064 void QDeclarativeGridView::setHeader(QDeclarativeComponent *header)
2066 Q_D(QDeclarativeGridView);
2067 if (d->headerComponent != header) {
2070 scene()->removeItem(d->header->item);
2071 d->header->item->deleteLater();
2075 d->headerComponent = header;
2076 if (isComponentComplete()) {
2082 emit headerChanged();
2086 void QDeclarativeGridView::setContentX(qreal pos)
2088 Q_D(QDeclarativeGridView);
2089 // Positioning the view manually should override any current movement state
2090 d->moveReason = QDeclarativeGridViewPrivate::Other;
2091 QDeclarativeFlickable::setContentX(pos);
2094 void QDeclarativeGridView::setContentY(qreal pos)
2096 Q_D(QDeclarativeGridView);
2097 // Positioning the view manually should override any current movement state
2098 d->moveReason = QDeclarativeGridViewPrivate::Other;
2099 QDeclarativeFlickable::setContentY(pos);
2102 bool QDeclarativeGridView::event(QEvent *event)
2104 Q_D(QDeclarativeGridView);
2105 if (event->type() == QEvent::User) {
2110 return QDeclarativeFlickable::event(event);
2113 void QDeclarativeGridView::viewportMoved()
2115 Q_D(QDeclarativeGridView);
2116 QDeclarativeFlickable::viewportMoved();
2119 d->lazyRelease = true;
2120 if (d->flickingHorizontally || d->flickingVertically) {
2122 if (d->vData.velocity > 0)
2123 d->bufferMode = QDeclarativeGridViewPrivate::BufferBefore;
2124 else if (d->vData.velocity < 0)
2125 d->bufferMode = QDeclarativeGridViewPrivate::BufferAfter;
2129 if (d->hData.velocity > 0)
2130 d->bufferMode = QDeclarativeGridViewPrivate::BufferBefore;
2131 else if (d->hData.velocity < 0)
2132 d->bufferMode = QDeclarativeGridViewPrivate::BufferAfter;
2136 if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
2137 d->moveReason = QDeclarativeGridViewPrivate::Mouse;
2138 if (d->moveReason != QDeclarativeGridViewPrivate::SetIndex) {
2139 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
2140 // reposition highlight
2141 qreal pos = d->highlight->rowPos();
2143 qreal highlightStart;
2145 if (d->isRightToLeftTopToBottom()) {
2146 highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
2147 highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
2148 viewPos = -d->position()-d->size();
2150 highlightStart = d->highlightRangeStart;
2151 highlightEnd = d->highlightRangeEnd;
2152 viewPos = d->position();
2154 if (pos > viewPos + highlightEnd - d->rowSize())
2155 pos = viewPos + highlightEnd - d->rowSize();
2156 if (pos < viewPos + highlightStart)
2157 pos = viewPos + highlightStart;
2159 d->highlight->setPosition(d->highlight->colPos(), qRound(pos));
2161 // update current index
2162 int idx = d->snapIndex();
2163 if (idx >= 0 && idx != d->currentIndex) {
2164 d->updateCurrent(idx);
2165 if (d->currentItem && d->currentItem->colPos() != d->highlight->colPos() && d->autoHighlight) {
2166 if (d->flow == LeftToRight)
2167 d->highlightXAnimator->to = d->currentItem->item->x();
2169 d->highlightYAnimator->to = d->currentItem->item->y();
2176 qreal QDeclarativeGridView::minYExtent() const
2178 Q_D(const QDeclarativeGridView);
2179 if (d->flow == QDeclarativeGridView::TopToBottom)
2180 return QDeclarativeFlickable::minYExtent();
2181 qreal extent = -d->startPosition();
2182 if (d->header && d->visibleItems.count())
2183 extent += d->header->item->height();
2184 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2185 extent += d->highlightRangeStart;
2186 extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
2191 qreal QDeclarativeGridView::maxYExtent() const
2193 Q_D(const QDeclarativeGridView);
2194 if (d->flow == QDeclarativeGridView::TopToBottom)
2195 return QDeclarativeFlickable::maxYExtent();
2197 if (!d->model || !d->model->count()) {
2199 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2200 extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
2201 if (d->highlightRangeEnd != d->highlightRangeStart)
2202 extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
2204 extent = -(d->endPosition() - height());
2207 extent -= d->footer->item->height();
2208 const qreal minY = minYExtent();
2214 qreal QDeclarativeGridView::minXExtent() const
2216 Q_D(const QDeclarativeGridView);
2217 if (d->flow == QDeclarativeGridView::LeftToRight)
2218 return QDeclarativeFlickable::minXExtent();
2219 qreal extent = -d->startPosition();
2220 qreal highlightStart;
2222 qreal endPositionFirstItem;
2223 if (d->isRightToLeftTopToBottom()) {
2224 endPositionFirstItem = d->rowPosAt(d->model->count()-1);
2225 highlightStart = d->highlightRangeStartValid
2226 ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
2227 : d->size() - (d->lastPosition()-endPositionFirstItem);
2228 highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
2229 if (d->footer && d->visibleItems.count())
2230 extent += d->footer->item->width();
2232 endPositionFirstItem = d->rowPosAt(0)+d->rowSize();
2233 highlightStart = d->highlightRangeStart;
2234 highlightEnd = d->highlightRangeEnd;
2235 if (d->header && d->visibleItems.count())
2236 extent += d->header->item->width();
2238 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2239 extent += highlightStart;
2240 extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
2245 qreal QDeclarativeGridView::maxXExtent() const
2247 Q_D(const QDeclarativeGridView);
2248 if (d->flow == QDeclarativeGridView::LeftToRight)
2249 return QDeclarativeFlickable::maxXExtent();
2251 qreal highlightStart;
2253 qreal lastItemPosition = 0;
2254 if (d->isRightToLeftTopToBottom()){
2255 highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
2256 highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
2257 lastItemPosition = d->endPosition();
2259 highlightStart = d->highlightRangeStart;
2260 highlightEnd = d->highlightRangeEnd;
2261 lastItemPosition = 0;
2262 if (d->model && d->model->count())
2263 lastItemPosition = d->rowPosAt(d->model->count()-1);
2265 if (!d->model || !d->model->count()) {
2267 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2268 extent = -(lastItemPosition - highlightStart);
2269 if (highlightEnd != highlightStart)
2270 extent = d->isRightToLeftTopToBottom()
2271 ? qMax(extent, -(d->endPosition() - highlightEnd + 1))
2272 : qMin(extent, -(d->endPosition() - highlightEnd + 1));
2274 extent = -(d->endPosition() - width());
2276 if (d->isRightToLeftTopToBottom()) {
2278 extent -= d->header->item->width();
2281 extent -= d->footer->item->width();
2284 const qreal minX = minXExtent();
2290 void QDeclarativeGridView::keyPressEvent(QKeyEvent *event)
2292 Q_D(QDeclarativeGridView);
2293 keyPressPreHandler(event);
2294 if (event->isAccepted())
2296 if (d->model && d->model->count() && d->interactive) {
2297 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
2298 int oldCurrent = currentIndex();
2299 switch (event->key()) {
2301 moveCurrentIndexUp();
2304 moveCurrentIndexDown();
2307 moveCurrentIndexLeft();
2310 moveCurrentIndexRight();
2315 if (oldCurrent != currentIndex()) {
2320 d->moveReason = QDeclarativeGridViewPrivate::Other;
2322 QDeclarativeFlickable::keyPressEvent(event);
2326 \qmlmethod GridView::moveCurrentIndexUp()
2328 Move the currentIndex up one item in the view.
2329 The current index will wrap if keyNavigationWraps is true and it
2330 is currently at the end. This method has no effect if the \l count is zero.
2332 \bold Note: methods should only be called after the Component has completed.
2334 void QDeclarativeGridView::moveCurrentIndexUp()
2336 Q_D(QDeclarativeGridView);
2337 const int count = d->model ? d->model->count() : 0;
2340 if (d->flow == QDeclarativeGridView::LeftToRight) {
2341 if (currentIndex() >= d->columns || d->wrap) {
2342 int index = currentIndex() - d->columns;
2343 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2346 if (currentIndex() > 0 || d->wrap) {
2347 int index = currentIndex() - 1;
2348 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2354 \qmlmethod GridView::moveCurrentIndexDown()
2356 Move the currentIndex down one item in the view.
2357 The current index will wrap if keyNavigationWraps is true and it
2358 is currently at the end. This method has no effect if the \l count is zero.
2360 \bold Note: methods should only be called after the Component has completed.
2362 void QDeclarativeGridView::moveCurrentIndexDown()
2364 Q_D(QDeclarativeGridView);
2365 const int count = d->model ? d->model->count() : 0;
2368 if (d->flow == QDeclarativeGridView::LeftToRight) {
2369 if (currentIndex() < count - d->columns || d->wrap) {
2370 int index = currentIndex()+d->columns;
2371 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2374 if (currentIndex() < count - 1 || d->wrap) {
2375 int index = currentIndex() + 1;
2376 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2382 \qmlmethod GridView::moveCurrentIndexLeft()
2384 Move the currentIndex left one item in the view.
2385 The current index will wrap if keyNavigationWraps is true and it
2386 is currently at the end. This method has no effect if the \l count is zero.
2388 \bold Note: methods should only be called after the Component has completed.
2390 void QDeclarativeGridView::moveCurrentIndexLeft()
2392 Q_D(QDeclarativeGridView);
2393 const int count = d->model ? d->model->count() : 0;
2397 if (effectiveLayoutDirection() == Qt::LeftToRight) {
2398 if (d->flow == QDeclarativeGridView::LeftToRight) {
2399 if (currentIndex() > 0 || d->wrap) {
2400 int index = currentIndex() - 1;
2401 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2404 if (currentIndex() >= d->columns || d->wrap) {
2405 int index = currentIndex() - d->columns;
2406 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2410 if (d->flow == QDeclarativeGridView::LeftToRight) {
2411 if (currentIndex() < count - 1 || d->wrap) {
2412 int index = currentIndex() + 1;
2413 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2416 if (currentIndex() < count - d->columns || d->wrap) {
2417 int index = currentIndex() + d->columns;
2418 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2425 \qmlmethod GridView::moveCurrentIndexRight()
2427 Move the currentIndex right one item in the view.
2428 The current index will wrap if keyNavigationWraps is true and it
2429 is currently at the end. This method has no effect if the \l count is zero.
2431 \bold Note: methods should only be called after the Component has completed.
2433 void QDeclarativeGridView::moveCurrentIndexRight()
2435 Q_D(QDeclarativeGridView);
2436 const int count = d->model ? d->model->count() : 0;
2440 if (effectiveLayoutDirection() == Qt::LeftToRight) {
2441 if (d->flow == QDeclarativeGridView::LeftToRight) {
2442 if (currentIndex() < count - 1 || d->wrap) {
2443 int index = currentIndex() + 1;
2444 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2447 if (currentIndex() < count - d->columns || d->wrap) {
2448 int index = currentIndex()+d->columns;
2449 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2453 if (d->flow == QDeclarativeGridView::LeftToRight) {
2454 if (currentIndex() > 0 || d->wrap) {
2455 int index = currentIndex() - 1;
2456 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2459 if (currentIndex() >= d->columns || d->wrap) {
2460 int index = currentIndex() - d->columns;
2461 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2467 void QDeclarativeGridViewPrivate::positionViewAtIndex(int index, int mode)
2469 Q_Q(QDeclarativeGridView);
2472 if (mode < QDeclarativeGridView::Beginning || mode > QDeclarativeGridView::Contain)
2475 int idx = qMax(qMin(index, model->count()-1), 0);
2477 if (layoutScheduled)
2479 qreal pos = isRightToLeftTopToBottom() ? -position() - size() : position();
2480 FxGridItem *item = visibleItem(idx);
2482 if (flow == QDeclarativeGridView::LeftToRight)
2483 maxExtent = -q->maxYExtent();
2485 maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
2488 int itemPos = rowPosAt(idx);
2489 // save the currently visible items in case any of them end up visible again
2490 QList<FxGridItem*> oldVisible = visibleItems;
2491 visibleItems.clear();
2492 visibleIndex = idx - idx % columns;
2493 if (flow == QDeclarativeGridView::LeftToRight)
2494 maxExtent = -q->maxYExtent();
2496 maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
2497 setPosition(qMin(qreal(itemPos), maxExtent));
2498 // now release the reference to all the old visible items.
2499 for (int i = 0; i < oldVisible.count(); ++i)
2500 releaseItem(oldVisible.at(i));
2501 item = visibleItem(idx);
2504 qreal itemPos = item->rowPos();
2506 case QDeclarativeGridView::Beginning:
2508 if (index < 0 && header) {
2509 pos -= flow == QDeclarativeGridView::LeftToRight
2510 ? header->item->height()
2511 : header->item->width();
2514 case QDeclarativeGridView::Center:
2515 pos = itemPos - (size() - rowSize())/2;
2517 case QDeclarativeGridView::End:
2518 pos = itemPos - size() + rowSize();
2519 if (index >= model->count() && footer) {
2520 pos += flow == QDeclarativeGridView::LeftToRight
2521 ? footer->item->height()
2522 : footer->item->width();
2525 case QDeclarativeGridView::Visible:
2526 if (itemPos > pos + size())
2527 pos = itemPos - size() + rowSize();
2528 else if (item->endRowPos() < pos)
2531 case QDeclarativeGridView::Contain:
2532 if (item->endRowPos() > pos + size())
2533 pos = itemPos - size() + rowSize();
2538 pos = qMin(pos, maxExtent);
2540 if (flow == QDeclarativeGridView::LeftToRight)
2541 minExtent = -q->minYExtent();
2543 minExtent = isRightToLeftTopToBottom() ? q->maxXExtent()-size() : -q->minXExtent();
2544 pos = qMax(pos, minExtent);
2545 moveReason = QDeclarativeGridViewPrivate::Other;
2553 \qmlmethod GridView::positionViewAtIndex(int index, PositionMode mode)
2555 Positions the view such that the \a index is at the position specified by
2559 \o GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view.
2560 \o GridView.Center - position item in the center of the view.
2561 \o GridView.End - position item at bottom (or right for horizontal orientation) of the view.
2562 \o GridView.Visible - if any part of the item is visible then take no action, otherwise
2563 bring the item into view.
2564 \o GridView.Contain - ensure the entire item is visible. If the item is larger than
2565 the view the item is positioned at the top (or left for \c GridView.TopToBottom flow) of the view.
2568 If positioning the view at the index would cause empty space to be displayed at
2569 the beginning or end of the view, the view will be positioned at the boundary.
2571 It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
2572 at a particular index. This is unreliable since removing items from the start
2573 of the view does not cause all other items to be repositioned.
2574 The correct way to bring an item into view is with \c positionViewAtIndex.
2576 \bold Note: methods should only be called after the Component has completed. To position
2577 the view at startup, this method should be called by Component.onCompleted. For
2578 example, to position the view at the end:
2581 Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
2584 void QDeclarativeGridView::positionViewAtIndex(int index, int mode)
2586 Q_D(QDeclarativeGridView);
2587 if (!d->isValid() || index < 0 || index >= d->model->count())
2589 d->positionViewAtIndex(index, mode);
2593 \qmlmethod GridView::positionViewAtBeginning()
2594 \qmlmethod GridView::positionViewAtEnd()
2597 Positions the view at the beginning or end, taking into account any header or footer.
2599 It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
2600 at a particular index. This is unreliable since removing items from the start
2601 of the list does not cause all other items to be repositioned, and because
2602 the actual start of the view can vary based on the size of the delegates.
2604 \bold Note: methods should only be called after the Component has completed. To position
2605 the view at startup, this method should be called by Component.onCompleted. For
2606 example, to position the view at the end on startup:
2609 Component.onCompleted: positionViewAtEnd()
2612 void QDeclarativeGridView::positionViewAtBeginning()
2614 Q_D(QDeclarativeGridView);
2617 d->positionViewAtIndex(-1, Beginning);
2620 void QDeclarativeGridView::positionViewAtEnd()
2622 Q_D(QDeclarativeGridView);
2625 d->positionViewAtIndex(d->model->count(), End);
2629 \qmlmethod int GridView::indexAt(int x, int y)
2631 Returns the index of the visible item containing the point \a x, \a y in content
2632 coordinates. If there is no item at the point specified, or the item is
2633 not visible -1 is returned.
2635 If the item is outside the visible area, -1 is returned, regardless of
2636 whether an item will exist at that point when scrolled into view.
2638 \bold Note: methods should only be called after the Component has completed.
2640 int QDeclarativeGridView::indexAt(qreal x, qreal y) const
2642 Q_D(const QDeclarativeGridView);
2643 for (int i = 0; i < d->visibleItems.count(); ++i) {
2644 const FxGridItem *listItem = d->visibleItems.at(i);
2645 if(listItem->contains(x, y))
2646 return listItem->index;
2652 void QDeclarativeGridView::componentComplete()
2654 Q_D(QDeclarativeGridView);
2655 QDeclarativeFlickable::componentComplete();
2661 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
2662 if (d->currentIndex < 0 && !d->currentIndexCleared)
2663 d->updateCurrent(0);
2665 d->updateCurrent(d->currentIndex);
2666 if (d->highlight && d->currentItem) {
2667 if (d->autoHighlight)
2668 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
2669 d->updateTrackedItem();
2671 d->moveReason = QDeclarativeGridViewPrivate::Other;
2676 void QDeclarativeGridView::trackedPositionChanged()
2678 Q_D(QDeclarativeGridView);
2679 if (!d->trackedItem || !d->currentItem)
2681 if (d->moveReason == QDeclarativeGridViewPrivate::SetIndex) {
2682 const qreal trackedPos = d->trackedItem->rowPos();
2684 qreal highlightStart;
2686 if (d->isRightToLeftTopToBottom()) {
2687 viewPos = -d->position()-d->size();
2688 highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
2689 highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
2691 viewPos = d->position();
2692 highlightStart = d->highlightRangeStart;
2693 highlightEnd = d->highlightRangeEnd;
2695 qreal pos = viewPos;
2696 if (d->haveHighlightRange) {
2697 if (d->highlightRange == StrictlyEnforceRange) {
2698 if (trackedPos > pos + highlightEnd - d->rowSize())
2699 pos = trackedPos - highlightEnd + d->rowSize();
2700 if (trackedPos < pos + highlightStart)
2701 pos = trackedPos - highlightStart;
2703 if (trackedPos < d->startPosition() + highlightStart) {
2704 pos = d->startPosition();
2705 } else if (d->trackedItem->endRowPos() > d->endPosition() - d->size() + highlightEnd) {
2706 pos = d->endPosition() - d->size() + 1;
2707 if (pos < d->startPosition())
2708 pos = d->startPosition();
2710 if (trackedPos < viewPos + highlightStart) {
2711 pos = trackedPos - highlightStart;
2712 } else if (trackedPos > viewPos + highlightEnd - d->rowSize()) {
2713 pos = trackedPos - highlightEnd + d->rowSize();
2718 if (trackedPos < viewPos && d->currentItem->rowPos() < viewPos) {
2719 pos = qMax(trackedPos, d->currentItem->rowPos());
2720 } else if (d->trackedItem->endRowPos() >= viewPos + d->size()
2721 && d->currentItem->endRowPos() >= viewPos + d->size()) {
2722 if (d->trackedItem->endRowPos() <= d->currentItem->endRowPos()) {
2723 pos = d->trackedItem->endRowPos() - d->size() + 1;
2724 if (d->rowSize() > d->size())
2727 pos = d->currentItem->endRowPos() - d->size() + 1;
2728 if (d->rowSize() > d->size())
2729 pos = d->currentItem->rowPos();
2733 if (viewPos != pos) {
2735 d->calcVelocity = true;
2736 d->setPosition(pos);
2737 d->calcVelocity = false;
2742 void QDeclarativeGridView::itemsInserted(int modelIndex, int count)
2744 Q_D(QDeclarativeGridView);
2745 if (!isComponentComplete())
2748 int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
2750 int i = d->visibleItems.count() - 1;
2751 while (i > 0 && d->visibleItems.at(i)->index == -1)
2753 if (d->visibleItems.at(i)->index + 1 == modelIndex) {
2754 // Special case of appending an item to the model.
2755 index = d->visibleIndex + d->visibleItems.count();
2757 if (modelIndex <= d->visibleIndex) {
2758 // Insert before visible items
2759 d->visibleIndex += count;
2760 for (int i = 0; i < d->visibleItems.count(); ++i) {
2761 FxGridItem *listItem = d->visibleItems.at(i);
2762 if (listItem->index != -1 && listItem->index >= modelIndex)
2763 listItem->index += count;
2766 if (d->currentIndex >= modelIndex) {
2767 // adjust current item index
2768 d->currentIndex += count;
2770 d->currentItem->index = d->currentIndex;
2771 emit currentIndexChanged();
2773 d->scheduleLayout();
2774 d->itemCount += count;
2775 emit countChanged();
2780 int insertCount = count;
2781 if (index < d->visibleIndex && d->visibleItems.count()) {
2782 insertCount -= d->visibleIndex - index;
2783 index = d->visibleIndex;
2784 modelIndex = d->visibleIndex;
2787 qreal tempPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size()+d->width()+1 : d->position();
2788 int to = d->buffer+tempPos+d->size()-1;
2791 if (d->visibleItems.count()) {
2792 index -= d->visibleIndex;
2793 if (index < d->visibleItems.count()) {
2794 colPos = d->visibleItems.at(index)->colPos();
2795 rowPos = d->visibleItems.at(index)->rowPos();
2797 // appending items to visible list
2798 colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
2799 rowPos = d->visibleItems.at(index-1)->rowPos();
2800 if (colPos > d->colSize() * (d->columns-1)) {
2802 rowPos += d->rowSize();
2805 } else if (d->itemCount == 0 && d->header) {
2806 rowPos = d->headerSize();
2809 // Update the indexes of the following visible items.
2810 for (int i = 0; i < d->visibleItems.count(); ++i) {
2811 FxGridItem *listItem = d->visibleItems.at(i);
2812 if (listItem->index != -1 && listItem->index >= modelIndex)
2813 listItem->index += count;
2816 bool addedVisible = false;
2817 QList<FxGridItem*> added;
2819 while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) {
2820 if (!addedVisible) {
2821 d->scheduleLayout();
2822 addedVisible = true;
2824 FxGridItem *item = d->createItem(modelIndex + i);
2825 d->visibleItems.insert(index, item);
2826 item->setPosition(colPos, rowPos);
2828 colPos += d->colSize();
2829 if (colPos > d->colSize() * (d->columns-1)) {
2831 rowPos += d->rowSize();
2836 if (i < insertCount) {
2837 // We didn't insert all our new items, which means anything
2838 // beyond the current index is not visible - remove it.
2839 while (d->visibleItems.count() > index) {
2840 d->releaseItem(d->visibleItems.takeLast());
2844 // update visibleIndex
2845 d->visibleIndex = 0;
2846 for (QList<FxGridItem*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
2847 if ((*it)->index != -1) {
2848 d->visibleIndex = (*it)->index;
2853 if (d->itemCount && d->currentIndex >= modelIndex) {
2854 // adjust current item index
2855 d->currentIndex += count;
2856 if (d->currentItem) {
2857 d->currentItem->index = d->currentIndex;
2858 d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
2860 emit currentIndexChanged();
2861 } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
2865 // everything is in order now - emit add() signal
2866 for (int j = 0; j < added.count(); ++j)
2867 added.at(j)->attached->emitAdd();
2869 d->itemCount += count;
2870 emit countChanged();
2873 void QDeclarativeGridView::itemsRemoved(int modelIndex, int count)
2875 Q_D(QDeclarativeGridView);
2876 if (!isComponentComplete())
2879 d->itemCount -= count;
2880 bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
2881 bool removedVisible = false;
2883 // Remove the items from the visible list, skipping anything already marked for removal
2884 QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
2885 while (it != d->visibleItems.end()) {
2886 FxGridItem *item = *it;
2887 if (item->index == -1 || item->index < modelIndex) {
2888 // already removed, or before removed items
2889 if (item->index < modelIndex && !removedVisible) {
2890 d->scheduleLayout();
2891 removedVisible = true;
2894 } else if (item->index >= modelIndex + count) {
2895 // after removed items
2896 item->index -= count;
2900 if (!removedVisible) {
2901 d->scheduleLayout();
2902 removedVisible = true;
2904 item->attached->emitRemove();
2905 if (item->attached->delayRemove()) {
2907 connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
2910 it = d->visibleItems.erase(it);
2911 d->releaseItem(item);
2917 if (d->currentIndex >= modelIndex + count) {
2918 d->currentIndex -= count;
2920 d->currentItem->index -= count;
2921 emit currentIndexChanged();
2922 } else if (currentRemoved) {
2923 // current item has been removed.
2924 d->releaseItem(d->currentItem);
2926 d->currentIndex = -1;
2928 d->updateCurrent(qMin(modelIndex, d->itemCount-1));
2930 emit currentIndexChanged();
2933 // update visibleIndex
2934 d->visibleIndex = 0;
2935 for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
2936 if ((*it)->index != -1) {
2937 d->visibleIndex = (*it)->index;
2942 if (removedVisible && d->visibleItems.isEmpty()) {
2943 d->timeline.clear();
2944 if (d->itemCount == 0) {
2952 emit countChanged();
2955 void QDeclarativeGridView::destroyRemoved()
2957 Q_D(QDeclarativeGridView);
2958 for (QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
2959 it != d->visibleItems.end();) {
2960 FxGridItem *listItem = *it;
2961 if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
2962 d->releaseItem(listItem);
2963 it = d->visibleItems.erase(it);
2969 // Correct the positioning of the items
2973 void QDeclarativeGridView::itemsMoved(int from, int to, int count)
2975 Q_D(QDeclarativeGridView);
2976 if (!isComponentComplete())
2978 QHash<int,FxGridItem*> moved;
2980 FxGridItem *firstItem = d->firstVisibleItem();
2982 QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
2983 while (it != d->visibleItems.end()) {
2984 FxGridItem *item = *it;
2985 if (item->index >= from && item->index < from + count) {
2986 // take the items that are moving
2987 item->index += (to-from);
2988 moved.insert(item->index, item);
2989 it = d->visibleItems.erase(it);
2991 if (item->index > from && item->index != -1) {
2992 // move everything after the moved items.
2993 item->index -= count;
2994 if (item->index < d->visibleIndex)
2995 d->visibleIndex = item->index;
3001 int remaining = count;
3002 int endIndex = d->visibleIndex;
3003 it = d->visibleItems.begin();
3004 while (it != d->visibleItems.end()) {
3005 FxGridItem *item = *it;
3006 if (remaining && item->index >= to && item->index < to + count) {
3007 // place items in the target position, reusing any existing items
3008 FxGridItem *movedItem = moved.take(item->index);
3010 movedItem = d->createItem(item->index);
3011 it = d->visibleItems.insert(it, movedItem);
3012 if (it == d->visibleItems.begin() && firstItem)
3013 movedItem->setPosition(firstItem->colPos(), firstItem->rowPos());
3017 if (item->index != -1) {
3018 if (item->index >= to) {
3019 // update everything after the moved items.
3020 item->index += count;
3022 endIndex = item->index;
3028 // If we have moved items to the end of the visible items
3029 // then add any existing moved items that we have
3030 while (FxGridItem *item = moved.take(endIndex+1)) {
3031 d->visibleItems.append(item);
3035 // update visibleIndex
3036 for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
3037 if ((*it)->index != -1) {
3038 d->visibleIndex = (*it)->index;
3043 // Fix current index
3044 if (d->currentIndex >= 0 && d->currentItem) {
3045 int oldCurrent = d->currentIndex;
3046 d->currentIndex = d->model->indexOf(d->currentItem->item, this);
3047 if (oldCurrent != d->currentIndex) {
3048 d->currentItem->index = d->currentIndex;
3049 emit currentIndexChanged();
3053 // Whatever moved items remain are no longer visible items.
3054 while (moved.count()) {
3055 int idx = moved.begin().key();
3056 FxGridItem *item = moved.take(idx);
3057 if (d->currentItem && item->item == d->currentItem->item)
3058 item->setPosition(d->colPosAt(idx), d->rowPosAt(idx));
3059 d->releaseItem(item);
3065 void QDeclarativeGridView::modelReset()
3067 Q_D(QDeclarativeGridView);
3070 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
3071 d->updateCurrent(d->currentIndex);
3072 if (d->highlight && d->currentItem) {
3073 if (d->autoHighlight)
3074 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
3075 d->updateTrackedItem();
3077 d->moveReason = QDeclarativeGridViewPrivate::Other;
3079 emit countChanged();
3082 void QDeclarativeGridView::createdItem(int index, QDeclarativeItem *item)
3084 Q_D(QDeclarativeGridView);
3085 if (d->requestedIndex != index) {
3086 item->setParentItem(this);
3087 d->unrequestedItems.insert(item, index);
3088 if (d->flow == QDeclarativeGridView::LeftToRight) {
3089 item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
3091 item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
3096 void QDeclarativeGridView::destroyingItem(QDeclarativeItem *item)
3098 Q_D(QDeclarativeGridView);
3099 d->unrequestedItems.remove(item);
3102 void QDeclarativeGridView::animStopped()
3104 Q_D(QDeclarativeGridView);
3105 d->bufferMode = QDeclarativeGridViewPrivate::NoBuffer;
3106 if (d->haveHighlightRange && d->highlightRange == QDeclarativeGridView::StrictlyEnforceRange)
3107 d->updateHighlight();
3110 void QDeclarativeGridView::refill()
3112 Q_D(QDeclarativeGridView);
3113 if (d->isRightToLeftTopToBottom())
3114 d->refill(-d->position()-d->size()+1, -d->position());
3116 d->refill(d->position(), d->position()+d->size()-1);
3120 QDeclarativeGridViewAttached *QDeclarativeGridView::qmlAttachedProperties(QObject *obj)
3122 return new QDeclarativeGridViewAttached(obj);