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 int oldCount = dataModel->count();
1503 dataModel->setDelegate(delegate);
1504 if (isComponentComplete()) {
1505 for (int i = 0; i < d->visibleItems.count(); ++i)
1506 d->releaseItem(d->visibleItems.at(i));
1507 d->visibleItems.clear();
1508 d->releaseItem(d->currentItem);
1511 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
1512 d->updateCurrent(d->currentIndex);
1513 if (d->highlight && d->currentItem) {
1514 if (d->autoHighlight)
1515 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
1516 d->updateTrackedItem();
1518 d->moveReason = QDeclarativeGridViewPrivate::Other;
1520 if (oldCount != dataModel->count())
1521 emit countChanged();
1522 emit delegateChanged();
1527 \qmlproperty int GridView::currentIndex
1528 \qmlproperty Item GridView::currentItem
1530 The \c currentIndex property holds the index of the current item, and
1531 \c currentItem holds the current item. Setting the currentIndex to -1
1532 will clear the highlight and set currentItem to null.
1534 If highlightFollowsCurrentItem is \c true, setting either of these
1535 properties will smoothly scroll the GridView so that the current
1536 item becomes visible.
1538 Note that the position of the current item
1539 may only be approximate until it becomes visible in the view.
1541 int QDeclarativeGridView::currentIndex() const
1543 Q_D(const QDeclarativeGridView);
1544 return d->currentIndex;
1547 void QDeclarativeGridView::setCurrentIndex(int index)
1549 Q_D(QDeclarativeGridView);
1550 if (d->requestedIndex >= 0) // currently creating item
1552 d->currentIndexCleared = (index == -1);
1553 if (index == d->currentIndex)
1555 if (isComponentComplete() && d->isValid()) {
1556 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
1557 d->updateCurrent(index);
1559 d->currentIndex = index;
1560 emit currentIndexChanged();
1564 QDeclarativeItem *QDeclarativeGridView::currentItem()
1566 Q_D(QDeclarativeGridView);
1567 if (!d->currentItem)
1569 return d->currentItem->item;
1573 \qmlproperty Item GridView::highlightItem
1575 This holds the highlight item created from the \l highlight component.
1577 The highlightItem is managed by the view unless
1578 \l highlightFollowsCurrentItem is set to false.
1580 \sa highlight, highlightFollowsCurrentItem
1582 QDeclarativeItem *QDeclarativeGridView::highlightItem()
1584 Q_D(QDeclarativeGridView);
1587 return d->highlight->item;
1591 \qmlproperty int GridView::count
1592 This property holds the number of items in the view.
1594 int QDeclarativeGridView::count() const
1596 Q_D(const QDeclarativeGridView);
1598 return d->model->count();
1603 \qmlproperty Component GridView::highlight
1604 This property holds the component to use as the highlight.
1606 An instance of the highlight component is created for each view.
1607 The geometry of the resulting component instance will be managed by the view
1608 so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
1610 \sa highlightItem, highlightFollowsCurrentItem
1612 QDeclarativeComponent *QDeclarativeGridView::highlight() const
1614 Q_D(const QDeclarativeGridView);
1615 return d->highlightComponent;
1618 void QDeclarativeGridView::setHighlight(QDeclarativeComponent *highlight)
1620 Q_D(QDeclarativeGridView);
1621 if (highlight != d->highlightComponent) {
1622 d->highlightComponent = highlight;
1623 d->updateCurrent(d->currentIndex);
1624 emit highlightChanged();
1629 \qmlproperty bool GridView::highlightFollowsCurrentItem
1630 This property sets whether the highlight is managed by the view.
1632 If this property is true (the default value), the highlight is moved smoothly
1633 to follow the current item. Otherwise, the
1634 highlight is not moved by the view, and any movement must be implemented
1637 Here is a highlight with its motion defined by a \l {SpringAnimation} item:
1639 \snippet doc/src/snippets/declarative/gridview/gridview.qml highlightFollowsCurrentItem
1641 bool QDeclarativeGridView::highlightFollowsCurrentItem() const
1643 Q_D(const QDeclarativeGridView);
1644 return d->autoHighlight;
1647 void QDeclarativeGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
1649 Q_D(QDeclarativeGridView);
1650 if (d->autoHighlight != autoHighlight) {
1651 d->autoHighlight = autoHighlight;
1652 if (autoHighlight) {
1653 d->updateHighlight();
1654 } else if (d->highlightXAnimator) {
1655 d->highlightXAnimator->stop();
1656 d->highlightYAnimator->stop();
1662 \qmlproperty int GridView::highlightMoveDuration
1663 This property holds the move animation duration of the highlight delegate.
1665 highlightFollowsCurrentItem must be true for this property
1668 The default value for the duration is 150ms.
1670 \sa highlightFollowsCurrentItem
1672 int QDeclarativeGridView::highlightMoveDuration() const
1674 Q_D(const QDeclarativeGridView);
1675 return d->highlightMoveDuration;
1678 void QDeclarativeGridView::setHighlightMoveDuration(int duration)
1680 Q_D(QDeclarativeGridView);
1681 if (d->highlightMoveDuration != duration) {
1682 d->highlightMoveDuration = duration;
1683 if (d->highlightYAnimator) {
1684 d->highlightXAnimator->userDuration = d->highlightMoveDuration;
1685 d->highlightYAnimator->userDuration = d->highlightMoveDuration;
1687 emit highlightMoveDurationChanged();
1693 \qmlproperty real GridView::preferredHighlightBegin
1694 \qmlproperty real GridView::preferredHighlightEnd
1695 \qmlproperty enumeration GridView::highlightRangeMode
1697 These properties define the preferred range of the highlight (for the current item)
1698 within the view. The \c preferredHighlightBegin value must be less than the
1699 \c preferredHighlightEnd value.
1701 These properties affect the position of the current item when the view is scrolled.
1702 For example, if the currently selected item should stay in the middle of the
1703 view when it is scrolled, set the \c preferredHighlightBegin and
1704 \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
1705 item would be. If the \c currentItem is changed programmatically, the view will
1706 automatically scroll so that the current item is in the middle of the view.
1707 Furthermore, the behavior of the current item index will occur whether or not a
1710 Valid values for \c highlightRangeMode are:
1713 \o GridView.ApplyRange - the view attempts to maintain the highlight within the range.
1714 However, the highlight can move outside of the range at the ends of the view or due
1715 to mouse interaction.
1716 \o GridView.StrictlyEnforceRange - the highlight never moves outside of the range.
1717 The current item changes if a keyboard or mouse action would cause the highlight to move
1718 outside of the range.
1719 \o GridView.NoHighlightRange - this is the default value.
1722 qreal QDeclarativeGridView::preferredHighlightBegin() const
1724 Q_D(const QDeclarativeGridView);
1725 return d->highlightRangeStart;
1728 void QDeclarativeGridView::setPreferredHighlightBegin(qreal start)
1730 Q_D(QDeclarativeGridView);
1731 d->highlightRangeStartValid = true;
1732 if (d->highlightRangeStart == start)
1734 d->highlightRangeStart = start;
1735 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1736 emit preferredHighlightBeginChanged();
1739 void QDeclarativeGridView::resetPreferredHighlightBegin()
1741 Q_D(QDeclarativeGridView);
1742 d->highlightRangeStartValid = false;
1743 if (d->highlightRangeStart == 0)
1745 d->highlightRangeStart = 0;
1746 emit preferredHighlightBeginChanged();
1749 qreal QDeclarativeGridView::preferredHighlightEnd() const
1751 Q_D(const QDeclarativeGridView);
1752 return d->highlightRangeEnd;
1755 void QDeclarativeGridView::setPreferredHighlightEnd(qreal end)
1757 Q_D(QDeclarativeGridView);
1758 d->highlightRangeEndValid = true;
1759 if (d->highlightRangeEnd == end)
1761 d->highlightRangeEnd = end;
1762 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1763 emit preferredHighlightEndChanged();
1766 void QDeclarativeGridView::resetPreferredHighlightEnd()
1768 Q_D(QDeclarativeGridView);
1769 d->highlightRangeEndValid = false;
1770 if (d->highlightRangeEnd == 0)
1772 d->highlightRangeEnd = 0;
1773 emit preferredHighlightEndChanged();
1776 QDeclarativeGridView::HighlightRangeMode QDeclarativeGridView::highlightRangeMode() const
1778 Q_D(const QDeclarativeGridView);
1779 return d->highlightRange;
1782 void QDeclarativeGridView::setHighlightRangeMode(HighlightRangeMode mode)
1784 Q_D(QDeclarativeGridView);
1785 if (d->highlightRange == mode)
1787 d->highlightRange = mode;
1788 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1789 emit highlightRangeModeChanged();
1793 \qmlproperty enumeration GridView::layoutDirection
1794 This property holds the layout direction of the grid.
1799 \o Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is
1800 dependent on the \l GridView::flow property.
1801 \o Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent
1802 on the \l GridView:flow property.
1805 \bold Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if
1806 GridView::layoutDirection is set to Qt.RightToLeft. The GridView.LeftToRight flow value simply
1807 indicates that the flow is horizontal.
1810 Qt::LayoutDirection QDeclarativeGridView::layoutDirection() const
1812 Q_D(const QDeclarativeGridView);
1813 return d->layoutDirection;
1816 void QDeclarativeGridView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
1818 Q_D(QDeclarativeGridView);
1819 if (d->layoutDirection != layoutDirection) {
1820 d->layoutDirection = layoutDirection;
1822 emit layoutDirectionChanged();
1823 emit effectiveLayoutDirectionChanged();
1828 \qmlproperty enumeration GridView::effectiveLayoutDirection
1829 This property holds the effective layout direction of the grid.
1831 When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
1832 the visual layout direction of the grid will be mirrored. However, the
1833 property \l {GridView::layoutDirection}{layoutDirection} will remain unchanged.
1835 \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
1838 Qt::LayoutDirection QDeclarativeGridView::effectiveLayoutDirection() const
1840 Q_D(const QDeclarativeGridView);
1841 if (d->effectiveLayoutMirror)
1842 return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
1844 return d->layoutDirection;
1848 \qmlproperty enumeration GridView::flow
1849 This property holds the flow of the grid.
1854 \o GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically
1855 \o GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally
1858 QDeclarativeGridView::Flow QDeclarativeGridView::flow() const
1860 Q_D(const QDeclarativeGridView);
1864 void QDeclarativeGridView::setFlow(Flow flow)
1866 Q_D(QDeclarativeGridView);
1867 if (d->flow != flow) {
1869 if (d->flow == LeftToRight) {
1870 setContentWidth(-1);
1871 setFlickableDirection(QDeclarativeFlickable::VerticalFlick);
1873 setContentHeight(-1);
1874 setFlickableDirection(QDeclarativeFlickable::HorizontalFlick);
1884 \qmlproperty bool GridView::keyNavigationWraps
1885 This property holds whether the grid wraps key navigation
1887 If this is true, key navigation that would move the current item selection
1888 past one end of the view instead wraps around and moves the selection to
1889 the other end of the view.
1891 By default, key navigation is not wrapped.
1893 bool QDeclarativeGridView::isWrapEnabled() const
1895 Q_D(const QDeclarativeGridView);
1899 void QDeclarativeGridView::setWrapEnabled(bool wrap)
1901 Q_D(QDeclarativeGridView);
1902 if (d->wrap == wrap)
1905 emit keyNavigationWrapsChanged();
1909 \qmlproperty int GridView::cacheBuffer
1910 This property determines whether delegates are retained outside the
1911 visible area of the view.
1913 If non-zero the view will keep as many delegates
1914 instantiated as will fit within the buffer specified. For example,
1915 if in a vertical view the delegate is 20 pixels high and \c cacheBuffer is
1916 set to 40, then up to 2 delegates above and 2 delegates below the visible
1917 area may be retained.
1919 Note that cacheBuffer is not a pixel buffer - it only maintains additional
1920 instantiated delegates.
1922 Setting this value can make scrolling the list smoother at the expense
1923 of additional memory usage. It is not a substitute for creating efficient
1924 delegates; the fewer elements in a delegate, the faster a view may be
1927 int QDeclarativeGridView::cacheBuffer() const
1929 Q_D(const QDeclarativeGridView);
1933 void QDeclarativeGridView::setCacheBuffer(int buffer)
1935 Q_D(QDeclarativeGridView);
1936 if (d->buffer != buffer) {
1938 if (isComponentComplete())
1940 emit cacheBufferChanged();
1945 \qmlproperty int GridView::cellWidth
1946 \qmlproperty int GridView::cellHeight
1948 These properties holds the width and height of each cell in the grid.
1950 The default cell size is 100x100.
1952 int QDeclarativeGridView::cellWidth() const
1954 Q_D(const QDeclarativeGridView);
1955 return d->cellWidth;
1958 void QDeclarativeGridView::setCellWidth(int cellWidth)
1960 Q_D(QDeclarativeGridView);
1961 if (cellWidth != d->cellWidth && cellWidth > 0) {
1962 d->cellWidth = qMax(1, cellWidth);
1964 emit cellWidthChanged();
1969 int QDeclarativeGridView::cellHeight() const
1971 Q_D(const QDeclarativeGridView);
1972 return d->cellHeight;
1975 void QDeclarativeGridView::setCellHeight(int cellHeight)
1977 Q_D(QDeclarativeGridView);
1978 if (cellHeight != d->cellHeight && cellHeight > 0) {
1979 d->cellHeight = qMax(1, cellHeight);
1981 emit cellHeightChanged();
1986 \qmlproperty enumeration GridView::snapMode
1988 This property determines how the view scrolling will settle following a drag or flick.
1989 The possible values are:
1992 \o GridView.NoSnap (default) - the view stops anywhere within the visible area.
1993 \o GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow)
1994 aligned with the start of the view.
1995 \o GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow)
1996 away from the first visible row at the time the mouse button is released.
1997 This mode is particularly useful for moving one page at a time.
2001 QDeclarativeGridView::SnapMode QDeclarativeGridView::snapMode() const
2003 Q_D(const QDeclarativeGridView);
2007 void QDeclarativeGridView::setSnapMode(SnapMode mode)
2009 Q_D(QDeclarativeGridView);
2010 if (d->snapMode != mode) {
2012 emit snapModeChanged();
2017 \qmlproperty Component GridView::footer
2018 This property holds the component to use as the footer.
2020 An instance of the footer component is created for each view. The
2021 footer is positioned at the end of the view, after any items.
2025 QDeclarativeComponent *QDeclarativeGridView::footer() const
2027 Q_D(const QDeclarativeGridView);
2028 return d->footerComponent;
2031 void QDeclarativeGridView::setFooter(QDeclarativeComponent *footer)
2033 Q_D(QDeclarativeGridView);
2034 if (d->footerComponent != footer) {
2037 scene()->removeItem(d->footer->item);
2038 d->footer->item->deleteLater();
2042 d->footerComponent = footer;
2043 if (isComponentComplete()) {
2048 emit footerChanged();
2053 \qmlproperty Component GridView::header
2054 This property holds the component to use as the header.
2056 An instance of the header component is created for each view. The
2057 header is positioned at the beginning of the view, before any items.
2061 QDeclarativeComponent *QDeclarativeGridView::header() const
2063 Q_D(const QDeclarativeGridView);
2064 return d->headerComponent;
2067 void QDeclarativeGridView::setHeader(QDeclarativeComponent *header)
2069 Q_D(QDeclarativeGridView);
2070 if (d->headerComponent != header) {
2073 scene()->removeItem(d->header->item);
2074 d->header->item->deleteLater();
2078 d->headerComponent = header;
2079 if (isComponentComplete()) {
2085 emit headerChanged();
2089 void QDeclarativeGridView::setContentX(qreal pos)
2091 Q_D(QDeclarativeGridView);
2092 // Positioning the view manually should override any current movement state
2093 d->moveReason = QDeclarativeGridViewPrivate::Other;
2094 QDeclarativeFlickable::setContentX(pos);
2097 void QDeclarativeGridView::setContentY(qreal pos)
2099 Q_D(QDeclarativeGridView);
2100 // Positioning the view manually should override any current movement state
2101 d->moveReason = QDeclarativeGridViewPrivate::Other;
2102 QDeclarativeFlickable::setContentY(pos);
2105 bool QDeclarativeGridView::event(QEvent *event)
2107 Q_D(QDeclarativeGridView);
2108 if (event->type() == QEvent::User) {
2113 return QDeclarativeFlickable::event(event);
2116 void QDeclarativeGridView::viewportMoved()
2118 Q_D(QDeclarativeGridView);
2119 QDeclarativeFlickable::viewportMoved();
2122 d->lazyRelease = true;
2123 if (d->flickingHorizontally || d->flickingVertically) {
2125 if (d->vData.velocity > 0)
2126 d->bufferMode = QDeclarativeGridViewPrivate::BufferBefore;
2127 else if (d->vData.velocity < 0)
2128 d->bufferMode = QDeclarativeGridViewPrivate::BufferAfter;
2132 if (d->hData.velocity > 0)
2133 d->bufferMode = QDeclarativeGridViewPrivate::BufferBefore;
2134 else if (d->hData.velocity < 0)
2135 d->bufferMode = QDeclarativeGridViewPrivate::BufferAfter;
2139 if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
2140 d->moveReason = QDeclarativeGridViewPrivate::Mouse;
2141 if (d->moveReason != QDeclarativeGridViewPrivate::SetIndex) {
2142 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
2143 // reposition highlight
2144 qreal pos = d->highlight->rowPos();
2146 qreal highlightStart;
2148 if (d->isRightToLeftTopToBottom()) {
2149 highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
2150 highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
2151 viewPos = -d->position()-d->size();
2153 highlightStart = d->highlightRangeStart;
2154 highlightEnd = d->highlightRangeEnd;
2155 viewPos = d->position();
2157 if (pos > viewPos + highlightEnd - d->rowSize())
2158 pos = viewPos + highlightEnd - d->rowSize();
2159 if (pos < viewPos + highlightStart)
2160 pos = viewPos + highlightStart;
2162 d->highlight->setPosition(d->highlight->colPos(), qRound(pos));
2164 // update current index
2165 int idx = d->snapIndex();
2166 if (idx >= 0 && idx != d->currentIndex) {
2167 d->updateCurrent(idx);
2168 if (d->currentItem && d->currentItem->colPos() != d->highlight->colPos() && d->autoHighlight) {
2169 if (d->flow == LeftToRight)
2170 d->highlightXAnimator->to = d->currentItem->item->x();
2172 d->highlightYAnimator->to = d->currentItem->item->y();
2179 qreal QDeclarativeGridView::minYExtent() const
2181 Q_D(const QDeclarativeGridView);
2182 if (d->flow == QDeclarativeGridView::TopToBottom)
2183 return QDeclarativeFlickable::minYExtent();
2184 qreal extent = -d->startPosition();
2185 if (d->header && d->visibleItems.count())
2186 extent += d->header->item->height();
2187 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2188 extent += d->highlightRangeStart;
2189 extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
2194 qreal QDeclarativeGridView::maxYExtent() const
2196 Q_D(const QDeclarativeGridView);
2197 if (d->flow == QDeclarativeGridView::TopToBottom)
2198 return QDeclarativeFlickable::maxYExtent();
2200 if (!d->model || !d->model->count()) {
2202 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2203 extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
2204 if (d->highlightRangeEnd != d->highlightRangeStart)
2205 extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
2207 extent = -(d->endPosition() - height());
2210 extent -= d->footer->item->height();
2211 const qreal minY = minYExtent();
2217 qreal QDeclarativeGridView::minXExtent() const
2219 Q_D(const QDeclarativeGridView);
2220 if (d->flow == QDeclarativeGridView::LeftToRight)
2221 return QDeclarativeFlickable::minXExtent();
2222 qreal extent = -d->startPosition();
2223 qreal highlightStart;
2225 qreal endPositionFirstItem;
2226 if (d->isRightToLeftTopToBottom()) {
2227 endPositionFirstItem = d->rowPosAt(d->model->count()-1);
2228 highlightStart = d->highlightRangeStartValid
2229 ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
2230 : d->size() - (d->lastPosition()-endPositionFirstItem);
2231 highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
2232 if (d->footer && d->visibleItems.count())
2233 extent += d->footer->item->width();
2235 endPositionFirstItem = d->rowPosAt(0)+d->rowSize();
2236 highlightStart = d->highlightRangeStart;
2237 highlightEnd = d->highlightRangeEnd;
2238 if (d->header && d->visibleItems.count())
2239 extent += d->header->item->width();
2241 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2242 extent += highlightStart;
2243 extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
2248 qreal QDeclarativeGridView::maxXExtent() const
2250 Q_D(const QDeclarativeGridView);
2251 if (d->flow == QDeclarativeGridView::LeftToRight)
2252 return QDeclarativeFlickable::maxXExtent();
2254 qreal highlightStart;
2256 qreal lastItemPosition = 0;
2257 if (d->isRightToLeftTopToBottom()){
2258 highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
2259 highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
2260 lastItemPosition = d->endPosition();
2262 highlightStart = d->highlightRangeStart;
2263 highlightEnd = d->highlightRangeEnd;
2264 lastItemPosition = 0;
2265 if (d->model && d->model->count())
2266 lastItemPosition = d->rowPosAt(d->model->count()-1);
2268 if (!d->model || !d->model->count()) {
2270 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2271 extent = -(lastItemPosition - highlightStart);
2272 if (highlightEnd != highlightStart)
2273 extent = d->isRightToLeftTopToBottom()
2274 ? qMax(extent, -(d->endPosition() - highlightEnd + 1))
2275 : qMin(extent, -(d->endPosition() - highlightEnd + 1));
2277 extent = -(d->endPosition() - width());
2279 if (d->isRightToLeftTopToBottom()) {
2281 extent -= d->header->item->width();
2284 extent -= d->footer->item->width();
2287 const qreal minX = minXExtent();
2293 void QDeclarativeGridView::keyPressEvent(QKeyEvent *event)
2295 Q_D(QDeclarativeGridView);
2296 keyPressPreHandler(event);
2297 if (event->isAccepted())
2299 if (d->model && d->model->count() && d->interactive) {
2300 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
2301 int oldCurrent = currentIndex();
2302 switch (event->key()) {
2304 moveCurrentIndexUp();
2307 moveCurrentIndexDown();
2310 moveCurrentIndexLeft();
2313 moveCurrentIndexRight();
2318 if (oldCurrent != currentIndex()) {
2323 d->moveReason = QDeclarativeGridViewPrivate::Other;
2325 QDeclarativeFlickable::keyPressEvent(event);
2329 \qmlmethod GridView::moveCurrentIndexUp()
2331 Move the currentIndex up one item in the view.
2332 The current index will wrap if keyNavigationWraps is true and it
2333 is currently at the end. This method has no effect if the \l count is zero.
2335 \bold Note: methods should only be called after the Component has completed.
2337 void QDeclarativeGridView::moveCurrentIndexUp()
2339 Q_D(QDeclarativeGridView);
2340 const int count = d->model ? d->model->count() : 0;
2343 if (d->flow == QDeclarativeGridView::LeftToRight) {
2344 if (currentIndex() >= d->columns || d->wrap) {
2345 int index = currentIndex() - d->columns;
2346 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2349 if (currentIndex() > 0 || d->wrap) {
2350 int index = currentIndex() - 1;
2351 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2357 \qmlmethod GridView::moveCurrentIndexDown()
2359 Move the currentIndex down one item in the view.
2360 The current index will wrap if keyNavigationWraps is true and it
2361 is currently at the end. This method has no effect if the \l count is zero.
2363 \bold Note: methods should only be called after the Component has completed.
2365 void QDeclarativeGridView::moveCurrentIndexDown()
2367 Q_D(QDeclarativeGridView);
2368 const int count = d->model ? d->model->count() : 0;
2371 if (d->flow == QDeclarativeGridView::LeftToRight) {
2372 if (currentIndex() < count - d->columns || d->wrap) {
2373 int index = currentIndex()+d->columns;
2374 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2377 if (currentIndex() < count - 1 || d->wrap) {
2378 int index = currentIndex() + 1;
2379 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2385 \qmlmethod GridView::moveCurrentIndexLeft()
2387 Move the currentIndex left one item in the view.
2388 The current index will wrap if keyNavigationWraps is true and it
2389 is currently at the end. This method has no effect if the \l count is zero.
2391 \bold Note: methods should only be called after the Component has completed.
2393 void QDeclarativeGridView::moveCurrentIndexLeft()
2395 Q_D(QDeclarativeGridView);
2396 const int count = d->model ? d->model->count() : 0;
2400 if (effectiveLayoutDirection() == Qt::LeftToRight) {
2401 if (d->flow == QDeclarativeGridView::LeftToRight) {
2402 if (currentIndex() > 0 || d->wrap) {
2403 int index = currentIndex() - 1;
2404 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2407 if (currentIndex() >= d->columns || d->wrap) {
2408 int index = currentIndex() - d->columns;
2409 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2413 if (d->flow == QDeclarativeGridView::LeftToRight) {
2414 if (currentIndex() < count - 1 || d->wrap) {
2415 int index = currentIndex() + 1;
2416 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2419 if (currentIndex() < count - d->columns || d->wrap) {
2420 int index = currentIndex() + d->columns;
2421 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2428 \qmlmethod GridView::moveCurrentIndexRight()
2430 Move the currentIndex right one item in the view.
2431 The current index will wrap if keyNavigationWraps is true and it
2432 is currently at the end. This method has no effect if the \l count is zero.
2434 \bold Note: methods should only be called after the Component has completed.
2436 void QDeclarativeGridView::moveCurrentIndexRight()
2438 Q_D(QDeclarativeGridView);
2439 const int count = d->model ? d->model->count() : 0;
2443 if (effectiveLayoutDirection() == Qt::LeftToRight) {
2444 if (d->flow == QDeclarativeGridView::LeftToRight) {
2445 if (currentIndex() < count - 1 || d->wrap) {
2446 int index = currentIndex() + 1;
2447 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2450 if (currentIndex() < count - d->columns || d->wrap) {
2451 int index = currentIndex()+d->columns;
2452 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2456 if (d->flow == QDeclarativeGridView::LeftToRight) {
2457 if (currentIndex() > 0 || d->wrap) {
2458 int index = currentIndex() - 1;
2459 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2462 if (currentIndex() >= d->columns || d->wrap) {
2463 int index = currentIndex() - d->columns;
2464 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2470 void QDeclarativeGridViewPrivate::positionViewAtIndex(int index, int mode)
2472 Q_Q(QDeclarativeGridView);
2475 if (mode < QDeclarativeGridView::Beginning || mode > QDeclarativeGridView::Contain)
2478 int idx = qMax(qMin(index, model->count()-1), 0);
2480 if (layoutScheduled)
2482 qreal pos = isRightToLeftTopToBottom() ? -position() - size() : position();
2483 FxGridItem *item = visibleItem(idx);
2485 if (flow == QDeclarativeGridView::LeftToRight)
2486 maxExtent = -q->maxYExtent();
2488 maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
2491 int itemPos = rowPosAt(idx);
2492 // save the currently visible items in case any of them end up visible again
2493 QList<FxGridItem*> oldVisible = visibleItems;
2494 visibleItems.clear();
2495 visibleIndex = idx - idx % columns;
2496 if (flow == QDeclarativeGridView::LeftToRight)
2497 maxExtent = -q->maxYExtent();
2499 maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
2500 setPosition(qMin(qreal(itemPos), maxExtent));
2501 // now release the reference to all the old visible items.
2502 for (int i = 0; i < oldVisible.count(); ++i)
2503 releaseItem(oldVisible.at(i));
2504 item = visibleItem(idx);
2507 qreal itemPos = item->rowPos();
2509 case QDeclarativeGridView::Beginning:
2511 if (index < 0 && header) {
2512 pos -= flow == QDeclarativeGridView::LeftToRight
2513 ? header->item->height()
2514 : header->item->width();
2517 case QDeclarativeGridView::Center:
2518 pos = itemPos - (size() - rowSize())/2;
2520 case QDeclarativeGridView::End:
2521 pos = itemPos - size() + rowSize();
2522 if (index >= model->count() && footer) {
2523 pos += flow == QDeclarativeGridView::LeftToRight
2524 ? footer->item->height()
2525 : footer->item->width();
2528 case QDeclarativeGridView::Visible:
2529 if (itemPos > pos + size())
2530 pos = itemPos - size() + rowSize();
2531 else if (item->endRowPos() < pos)
2534 case QDeclarativeGridView::Contain:
2535 if (item->endRowPos() > pos + size())
2536 pos = itemPos - size() + rowSize();
2541 pos = qMin(pos, maxExtent);
2543 if (flow == QDeclarativeGridView::LeftToRight)
2544 minExtent = -q->minYExtent();
2546 minExtent = isRightToLeftTopToBottom() ? q->maxXExtent()-size() : -q->minXExtent();
2547 pos = qMax(pos, minExtent);
2548 moveReason = QDeclarativeGridViewPrivate::Other;
2556 \qmlmethod GridView::positionViewAtIndex(int index, PositionMode mode)
2558 Positions the view such that the \a index is at the position specified by
2562 \o GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view.
2563 \o GridView.Center - position item in the center of the view.
2564 \o GridView.End - position item at bottom (or right for horizontal orientation) of the view.
2565 \o GridView.Visible - if any part of the item is visible then take no action, otherwise
2566 bring the item into view.
2567 \o GridView.Contain - ensure the entire item is visible. If the item is larger than
2568 the view the item is positioned at the top (or left for \c GridView.TopToBottom flow) of the view.
2571 If positioning the view at the index would cause empty space to be displayed at
2572 the beginning or end of the view, the view will be positioned at the boundary.
2574 It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
2575 at a particular index. This is unreliable since removing items from the start
2576 of the view does not cause all other items to be repositioned.
2577 The correct way to bring an item into view is with \c positionViewAtIndex.
2579 \bold Note: methods should only be called after the Component has completed. To position
2580 the view at startup, this method should be called by Component.onCompleted. For
2581 example, to position the view at the end:
2584 Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
2587 void QDeclarativeGridView::positionViewAtIndex(int index, int mode)
2589 Q_D(QDeclarativeGridView);
2590 if (!d->isValid() || index < 0 || index >= d->model->count())
2592 d->positionViewAtIndex(index, mode);
2596 \qmlmethod GridView::positionViewAtBeginning()
2597 \qmlmethod GridView::positionViewAtEnd()
2600 Positions the view at the beginning or end, taking into account any header or footer.
2602 It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
2603 at a particular index. This is unreliable since removing items from the start
2604 of the list does not cause all other items to be repositioned, and because
2605 the actual start of the view can vary based on the size of the delegates.
2607 \bold Note: methods should only be called after the Component has completed. To position
2608 the view at startup, this method should be called by Component.onCompleted. For
2609 example, to position the view at the end on startup:
2612 Component.onCompleted: positionViewAtEnd()
2615 void QDeclarativeGridView::positionViewAtBeginning()
2617 Q_D(QDeclarativeGridView);
2620 d->positionViewAtIndex(-1, Beginning);
2623 void QDeclarativeGridView::positionViewAtEnd()
2625 Q_D(QDeclarativeGridView);
2628 d->positionViewAtIndex(d->model->count(), End);
2632 \qmlmethod int GridView::indexAt(int x, int y)
2634 Returns the index of the visible item containing the point \a x, \a y in content
2635 coordinates. If there is no item at the point specified, or the item is
2636 not visible -1 is returned.
2638 If the item is outside the visible area, -1 is returned, regardless of
2639 whether an item will exist at that point when scrolled into view.
2641 \bold Note: methods should only be called after the Component has completed.
2643 int QDeclarativeGridView::indexAt(qreal x, qreal y) const
2645 Q_D(const QDeclarativeGridView);
2646 for (int i = 0; i < d->visibleItems.count(); ++i) {
2647 const FxGridItem *listItem = d->visibleItems.at(i);
2648 if(listItem->contains(x, y))
2649 return listItem->index;
2655 void QDeclarativeGridView::componentComplete()
2657 Q_D(QDeclarativeGridView);
2658 QDeclarativeFlickable::componentComplete();
2664 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
2665 if (d->currentIndex < 0 && !d->currentIndexCleared)
2666 d->updateCurrent(0);
2668 d->updateCurrent(d->currentIndex);
2669 if (d->highlight && d->currentItem) {
2670 if (d->autoHighlight)
2671 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
2672 d->updateTrackedItem();
2674 d->moveReason = QDeclarativeGridViewPrivate::Other;
2679 void QDeclarativeGridView::trackedPositionChanged()
2681 Q_D(QDeclarativeGridView);
2682 if (!d->trackedItem || !d->currentItem)
2684 if (d->moveReason == QDeclarativeGridViewPrivate::SetIndex) {
2685 const qreal trackedPos = d->trackedItem->rowPos();
2687 qreal highlightStart;
2689 if (d->isRightToLeftTopToBottom()) {
2690 viewPos = -d->position()-d->size();
2691 highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
2692 highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
2694 viewPos = d->position();
2695 highlightStart = d->highlightRangeStart;
2696 highlightEnd = d->highlightRangeEnd;
2698 qreal pos = viewPos;
2699 if (d->haveHighlightRange) {
2700 if (d->highlightRange == StrictlyEnforceRange) {
2701 if (trackedPos > pos + highlightEnd - d->rowSize())
2702 pos = trackedPos - highlightEnd + d->rowSize();
2703 if (trackedPos < pos + highlightStart)
2704 pos = trackedPos - highlightStart;
2706 if (trackedPos < d->startPosition() + highlightStart) {
2707 pos = d->startPosition();
2708 } else if (d->trackedItem->endRowPos() > d->endPosition() - d->size() + highlightEnd) {
2709 pos = d->endPosition() - d->size() + 1;
2710 if (pos < d->startPosition())
2711 pos = d->startPosition();
2713 if (trackedPos < viewPos + highlightStart) {
2714 pos = trackedPos - highlightStart;
2715 } else if (trackedPos > viewPos + highlightEnd - d->rowSize()) {
2716 pos = trackedPos - highlightEnd + d->rowSize();
2721 if (trackedPos < viewPos && d->currentItem->rowPos() < viewPos) {
2722 pos = qMax(trackedPos, d->currentItem->rowPos());
2723 } else if (d->trackedItem->endRowPos() >= viewPos + d->size()
2724 && d->currentItem->endRowPos() >= viewPos + d->size()) {
2725 if (d->trackedItem->endRowPos() <= d->currentItem->endRowPos()) {
2726 pos = d->trackedItem->endRowPos() - d->size() + 1;
2727 if (d->rowSize() > d->size())
2730 pos = d->currentItem->endRowPos() - d->size() + 1;
2731 if (d->rowSize() > d->size())
2732 pos = d->currentItem->rowPos();
2736 if (viewPos != pos) {
2738 d->calcVelocity = true;
2739 d->setPosition(pos);
2740 d->calcVelocity = false;
2745 void QDeclarativeGridView::itemsInserted(int modelIndex, int count)
2747 Q_D(QDeclarativeGridView);
2748 if (!isComponentComplete())
2751 int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
2753 int i = d->visibleItems.count() - 1;
2754 while (i > 0 && d->visibleItems.at(i)->index == -1)
2756 if (d->visibleItems.at(i)->index + 1 == modelIndex) {
2757 // Special case of appending an item to the model.
2758 index = d->visibleIndex + d->visibleItems.count();
2760 if (modelIndex <= d->visibleIndex) {
2761 // Insert before visible items
2762 d->visibleIndex += count;
2763 for (int i = 0; i < d->visibleItems.count(); ++i) {
2764 FxGridItem *listItem = d->visibleItems.at(i);
2765 if (listItem->index != -1 && listItem->index >= modelIndex)
2766 listItem->index += count;
2769 if (d->currentIndex >= modelIndex) {
2770 // adjust current item index
2771 d->currentIndex += count;
2773 d->currentItem->index = d->currentIndex;
2774 emit currentIndexChanged();
2776 d->scheduleLayout();
2777 d->itemCount += count;
2778 emit countChanged();
2783 int insertCount = count;
2784 if (index < d->visibleIndex && d->visibleItems.count()) {
2785 insertCount -= d->visibleIndex - index;
2786 index = d->visibleIndex;
2787 modelIndex = d->visibleIndex;
2790 qreal tempPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size()+d->width()+1 : d->position();
2791 int to = d->buffer+tempPos+d->size()-1;
2794 if (d->visibleItems.count()) {
2795 index -= d->visibleIndex;
2796 if (index < d->visibleItems.count()) {
2797 colPos = d->visibleItems.at(index)->colPos();
2798 rowPos = d->visibleItems.at(index)->rowPos();
2800 // appending items to visible list
2801 colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
2802 rowPos = d->visibleItems.at(index-1)->rowPos();
2803 if (colPos > d->colSize() * (d->columns-1)) {
2805 rowPos += d->rowSize();
2808 } else if (d->itemCount == 0 && d->header) {
2809 rowPos = d->headerSize();
2812 // Update the indexes of the following visible items.
2813 for (int i = 0; i < d->visibleItems.count(); ++i) {
2814 FxGridItem *listItem = d->visibleItems.at(i);
2815 if (listItem->index != -1 && listItem->index >= modelIndex)
2816 listItem->index += count;
2819 bool addedVisible = false;
2820 QList<FxGridItem*> added;
2822 while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) {
2823 if (!addedVisible) {
2824 d->scheduleLayout();
2825 addedVisible = true;
2827 FxGridItem *item = d->createItem(modelIndex + i);
2828 d->visibleItems.insert(index, item);
2829 item->setPosition(colPos, rowPos);
2831 colPos += d->colSize();
2832 if (colPos > d->colSize() * (d->columns-1)) {
2834 rowPos += d->rowSize();
2839 if (i < insertCount) {
2840 // We didn't insert all our new items, which means anything
2841 // beyond the current index is not visible - remove it.
2842 while (d->visibleItems.count() > index) {
2843 d->releaseItem(d->visibleItems.takeLast());
2847 // update visibleIndex
2848 d->visibleIndex = 0;
2849 for (QList<FxGridItem*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
2850 if ((*it)->index != -1) {
2851 d->visibleIndex = (*it)->index;
2856 if (d->itemCount && d->currentIndex >= modelIndex) {
2857 // adjust current item index
2858 d->currentIndex += count;
2859 if (d->currentItem) {
2860 d->currentItem->index = d->currentIndex;
2861 d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
2863 emit currentIndexChanged();
2864 } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
2868 // everything is in order now - emit add() signal
2869 for (int j = 0; j < added.count(); ++j)
2870 added.at(j)->attached->emitAdd();
2872 d->itemCount += count;
2873 emit countChanged();
2876 void QDeclarativeGridView::itemsRemoved(int modelIndex, int count)
2878 Q_D(QDeclarativeGridView);
2879 if (!isComponentComplete())
2882 d->itemCount -= count;
2883 bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
2884 bool removedVisible = false;
2886 // Remove the items from the visible list, skipping anything already marked for removal
2887 QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
2888 while (it != d->visibleItems.end()) {
2889 FxGridItem *item = *it;
2890 if (item->index == -1 || item->index < modelIndex) {
2891 // already removed, or before removed items
2892 if (item->index < modelIndex && !removedVisible) {
2893 d->scheduleLayout();
2894 removedVisible = true;
2897 } else if (item->index >= modelIndex + count) {
2898 // after removed items
2899 item->index -= count;
2903 if (!removedVisible) {
2904 d->scheduleLayout();
2905 removedVisible = true;
2907 item->attached->emitRemove();
2908 if (item->attached->delayRemove()) {
2910 connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
2913 it = d->visibleItems.erase(it);
2914 d->releaseItem(item);
2920 if (d->currentIndex >= modelIndex + count) {
2921 d->currentIndex -= count;
2923 d->currentItem->index -= count;
2924 emit currentIndexChanged();
2925 } else if (currentRemoved) {
2926 // current item has been removed.
2927 d->releaseItem(d->currentItem);
2929 d->currentIndex = -1;
2931 d->updateCurrent(qMin(modelIndex, d->itemCount-1));
2933 emit currentIndexChanged();
2936 // update visibleIndex
2937 d->visibleIndex = 0;
2938 for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
2939 if ((*it)->index != -1) {
2940 d->visibleIndex = (*it)->index;
2945 if (removedVisible && d->visibleItems.isEmpty()) {
2946 d->timeline.clear();
2947 if (d->itemCount == 0) {
2955 emit countChanged();
2958 void QDeclarativeGridView::destroyRemoved()
2960 Q_D(QDeclarativeGridView);
2961 for (QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
2962 it != d->visibleItems.end();) {
2963 FxGridItem *listItem = *it;
2964 if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
2965 d->releaseItem(listItem);
2966 it = d->visibleItems.erase(it);
2972 // Correct the positioning of the items
2976 void QDeclarativeGridView::itemsMoved(int from, int to, int count)
2978 Q_D(QDeclarativeGridView);
2979 if (!isComponentComplete())
2981 QHash<int,FxGridItem*> moved;
2983 FxGridItem *firstItem = d->firstVisibleItem();
2985 QList<FxGridItem*>::Iterator it = d->visibleItems.begin();
2986 while (it != d->visibleItems.end()) {
2987 FxGridItem *item = *it;
2988 if (item->index >= from && item->index < from + count) {
2989 // take the items that are moving
2990 item->index += (to-from);
2991 moved.insert(item->index, item);
2992 it = d->visibleItems.erase(it);
2994 if (item->index > from && item->index != -1) {
2995 // move everything after the moved items.
2996 item->index -= count;
2997 if (item->index < d->visibleIndex)
2998 d->visibleIndex = item->index;
3004 int remaining = count;
3005 int endIndex = d->visibleIndex;
3006 it = d->visibleItems.begin();
3007 while (it != d->visibleItems.end()) {
3008 FxGridItem *item = *it;
3009 if (remaining && item->index >= to && item->index < to + count) {
3010 // place items in the target position, reusing any existing items
3011 FxGridItem *movedItem = moved.take(item->index);
3013 movedItem = d->createItem(item->index);
3014 it = d->visibleItems.insert(it, movedItem);
3015 if (it == d->visibleItems.begin() && firstItem)
3016 movedItem->setPosition(firstItem->colPos(), firstItem->rowPos());
3020 if (item->index != -1) {
3021 if (item->index >= to) {
3022 // update everything after the moved items.
3023 item->index += count;
3025 endIndex = item->index;
3031 // If we have moved items to the end of the visible items
3032 // then add any existing moved items that we have
3033 while (FxGridItem *item = moved.take(endIndex+1)) {
3034 d->visibleItems.append(item);
3038 // update visibleIndex
3039 for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
3040 if ((*it)->index != -1) {
3041 d->visibleIndex = (*it)->index;
3046 // Fix current index
3047 if (d->currentIndex >= 0 && d->currentItem) {
3048 int oldCurrent = d->currentIndex;
3049 d->currentIndex = d->model->indexOf(d->currentItem->item, this);
3050 if (oldCurrent != d->currentIndex) {
3051 d->currentItem->index = d->currentIndex;
3052 emit currentIndexChanged();
3056 // Whatever moved items remain are no longer visible items.
3057 while (moved.count()) {
3058 int idx = moved.begin().key();
3059 FxGridItem *item = moved.take(idx);
3060 if (d->currentItem && item->item == d->currentItem->item)
3061 item->setPosition(d->colPosAt(idx), d->rowPosAt(idx));
3062 d->releaseItem(item);
3068 void QDeclarativeGridView::modelReset()
3070 Q_D(QDeclarativeGridView);
3073 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
3074 d->updateCurrent(d->currentIndex);
3075 if (d->highlight && d->currentItem) {
3076 if (d->autoHighlight)
3077 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
3078 d->updateTrackedItem();
3080 d->moveReason = QDeclarativeGridViewPrivate::Other;
3082 emit countChanged();
3085 void QDeclarativeGridView::createdItem(int index, QDeclarativeItem *item)
3087 Q_D(QDeclarativeGridView);
3088 if (d->requestedIndex != index) {
3089 item->setParentItem(this);
3090 d->unrequestedItems.insert(item, index);
3091 if (d->flow == QDeclarativeGridView::LeftToRight) {
3092 item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
3094 item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
3099 void QDeclarativeGridView::destroyingItem(QDeclarativeItem *item)
3101 Q_D(QDeclarativeGridView);
3102 d->unrequestedItems.remove(item);
3105 void QDeclarativeGridView::animStopped()
3107 Q_D(QDeclarativeGridView);
3108 d->bufferMode = QDeclarativeGridViewPrivate::NoBuffer;
3109 if (d->haveHighlightRange && d->highlightRange == QDeclarativeGridView::StrictlyEnforceRange)
3110 d->updateHighlight();
3113 void QDeclarativeGridView::refill()
3115 Q_D(QDeclarativeGridView);
3116 if (d->isRightToLeftTopToBottom())
3117 d->refill(-d->position()-d->size()+1, -d->position());
3119 d->refill(d->position(), d->position()+d->size()-1);
3123 QDeclarativeGridViewAttached *QDeclarativeGridView::qmlAttachedProperties(QObject *obj)
3125 return new QDeclarativeGridViewAttached(obj);