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 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "QtQuick1/private/qdeclarativegridview_p.h"
44 #include "QtQuick1/private/qdeclarativevisualitemmodel_p.h"
45 #include "QtQuick1/private/qdeclarativeflickable_p_p.h"
47 #include "QtQuick1/private/qdeclarativesmoothedanimation_p_p.h"
48 #include <QtDeclarative/private/qdeclarativeguard_p.h>
60 //----------------------------------------------------------------------------
65 FxGridItem1(QDeclarativeItem *i, QDeclarative1GridView *v) : item(i), view(v) {
66 attached = static_cast<QDeclarative1GridViewAttached*>(qmlAttachedPropertiesObject<QDeclarative1GridView>(item));
68 attached->setView(view);
72 qreal rowPos() const {
74 if (view->flow() == QDeclarative1GridView::LeftToRight) {
77 if (view->effectiveLayoutDirection() == Qt::RightToLeft)
78 rowPos = -view->cellWidth()-item->x();
84 qreal colPos() const {
86 if (view->flow() == QDeclarative1GridView::LeftToRight) {
87 if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
88 int colSize = view->cellWidth();
89 int columns = view->width()/colSize;
90 colPos = colSize * (columns-1) - item->x();
101 qreal endRowPos() const {
102 if (view->flow() == QDeclarative1GridView::LeftToRight) {
103 return item->y() + view->cellHeight() - 1;
105 if (view->effectiveLayoutDirection() == Qt::RightToLeft)
106 return -item->x() - 1;
108 return item->x() + view->cellWidth() - 1;
111 void setPosition(qreal col, qreal row) {
112 if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
113 if (view->flow() == QDeclarative1GridView::LeftToRight) {
114 int columns = view->width()/view->cellWidth();
115 item->setPos(QPointF((view->cellWidth() * (columns-1) - col), row));
117 item->setPos(QPointF(-view->cellWidth()-row, col));
120 if (view->flow() == QDeclarative1GridView::LeftToRight)
121 item->setPos(QPointF(col, row));
123 item->setPos(QPointF(row, col));
127 bool contains(qreal x, qreal y) const {
128 return (x >= item->x() && x < item->x() + view->cellWidth() &&
129 y >= item->y() && y < item->y() + view->cellHeight());
132 QDeclarativeItem *item;
133 QDeclarative1GridView *view;
134 QDeclarative1GridViewAttached *attached;
138 //----------------------------------------------------------------------------
140 class QDeclarative1GridViewPrivate : public QDeclarative1FlickablePrivate
142 Q_DECLARE_PUBLIC(QDeclarative1GridView)
145 QDeclarative1GridViewPrivate()
146 : currentItem(0), layoutDirection(Qt::LeftToRight), flow(QDeclarative1GridView::LeftToRight)
147 , visibleIndex(0) , currentIndex(-1)
148 , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0)
149 , highlightRangeStart(0), highlightRangeEnd(0)
150 , highlightRangeStartValid(false), highlightRangeEndValid(false)
151 , highlightRange(QDeclarative1GridView::NoHighlightRange)
152 , highlightComponent(0), highlight(0), trackedItem(0)
153 , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
154 , highlightMoveDuration(150)
155 , footerComponent(0), footer(0), headerComponent(0), header(0)
156 , bufferMode(BufferBefore | BufferAfter), snapMode(QDeclarative1GridView::NoSnap)
157 , ownModel(false), wrap(false), autoHighlight(true)
158 , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
159 , deferredRelease(false), haveHighlightRange(false), currentIndexCleared(false) {}
163 FxGridItem1 *createItem(int modelIndex);
164 void releaseItem(FxGridItem1 *item);
165 void refill(qreal from, qreal to, bool doBuffer=false);
168 void scheduleLayout();
170 void updateUnrequestedIndexes();
171 void updateUnrequestedPositions();
172 void updateTrackedItem();
173 void createHighlight();
174 void updateHighlight();
175 void updateCurrent(int modelIndex);
178 void fixupPosition();
180 FxGridItem1 *visibleItem(int modelIndex) const {
181 if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
182 for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
183 FxGridItem1 *item = visibleItems.at(i);
184 if (item->index == modelIndex)
191 bool isRightToLeftTopToBottom() const {
192 Q_Q(const QDeclarative1GridView);
193 return flow == QDeclarative1GridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
197 Q_Q(QDeclarative1GridView);
198 if (q->isComponentComplete()) {
203 updateCurrent(currentIndex);
207 void mirrorChange() {
208 Q_Q(QDeclarative1GridView);
210 emit q->effectiveLayoutDirectionChanged();
213 qreal position() const {
214 Q_Q(const QDeclarative1GridView);
215 return flow == QDeclarative1GridView::LeftToRight ? q->contentY() : q->contentX();
217 void setPosition(qreal pos) {
218 Q_Q(QDeclarative1GridView);
219 if (flow == QDeclarative1GridView::LeftToRight) {
220 q->QDeclarative1Flickable::setContentY(pos);
221 q->QDeclarative1Flickable::setContentX(0);
223 if (q->effectiveLayoutDirection() == Qt::LeftToRight)
224 q->QDeclarative1Flickable::setContentX(pos);
226 q->QDeclarative1Flickable::setContentX(-pos-size());
227 q->QDeclarative1Flickable::setContentY(0);
231 Q_Q(const QDeclarative1GridView);
232 return flow == QDeclarative1GridView::LeftToRight ? q->height() : q->width();
234 qreal originPosition() const {
236 if (!visibleItems.isEmpty())
237 pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
241 qreal lastPosition() const {
243 if (model && model->count())
244 pos = rowPosAt(model->count() - 1) + rowSize();
248 qreal startPosition() const {
249 return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
252 qreal endPosition() const {
253 return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
257 bool isValid() const {
258 return model && model->count() && model->isValid();
261 int rowSize() const {
262 return flow == QDeclarative1GridView::LeftToRight ? cellHeight : cellWidth;
264 int colSize() const {
265 return flow == QDeclarative1GridView::LeftToRight ? cellWidth : cellHeight;
268 qreal colPosAt(int modelIndex) const {
269 if (FxGridItem1 *item = visibleItem(modelIndex))
270 return item->colPos();
271 if (!visibleItems.isEmpty()) {
272 if (modelIndex < visibleIndex) {
273 int count = (visibleIndex - modelIndex) % columns;
274 int col = visibleItems.first()->colPos() / colSize();
275 col = (columns - count + col) % columns;
276 return col * colSize();
278 int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
279 return visibleItems.last()->colPos() - count * colSize();
282 return (modelIndex % columns) * colSize();
286 qreal rowPosAt(int modelIndex) const {
287 if (FxGridItem1 *item = visibleItem(modelIndex))
288 return item->rowPos();
289 if (!visibleItems.isEmpty()) {
290 if (modelIndex < visibleIndex) {
291 int firstCol = visibleItems.first()->colPos() / colSize();
292 int col = visibleIndex - modelIndex + (columns - firstCol - 1);
293 int rows = col / columns;
294 return visibleItems.first()->rowPos() - rows * rowSize();
296 int count = modelIndex - visibleItems.last()->index;
297 int col = visibleItems.last()->colPos() + count * colSize();
298 int rows = col / (columns * colSize());
299 return visibleItems.last()->rowPos() + rows * rowSize();
302 qreal pos = (modelIndex / columns) * rowSize();
310 FxGridItem1 *firstVisibleItem() const {
311 const qreal pos = isRightToLeftTopToBottom() ? -position()-size() : position();
312 for (int i = 0; i < visibleItems.count(); ++i) {
313 FxGridItem1 *item = visibleItems.at(i);
314 if (item->index != -1 && item->endRowPos() > pos)
317 return visibleItems.count() ? visibleItems.first() : 0;
320 int lastVisibleIndex() const {
321 for (int i = 0; i < visibleItems.count(); ++i) {
322 FxGridItem1 *item = visibleItems.at(i);
323 if (item->index != -1)
329 // Map a model index to visibleItems list index.
330 // These may differ if removed items are still present in the visible list,
331 // e.g. doing a removal animation
332 int mapFromModel(int modelIndex) const {
333 if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
335 for (int i = 0; i < visibleItems.count(); ++i) {
336 FxGridItem1 *listItem = visibleItems.at(i);
337 if (listItem->index == modelIndex)
338 return i + visibleIndex;
339 if (listItem->index > modelIndex)
342 return -1; // Not in visibleList
345 qreal snapPosAt(qreal pos) const {
346 Q_Q(const QDeclarative1GridView);
348 if (!visibleItems.isEmpty()) {
350 snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
351 snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
354 if (isRightToLeftTopToBottom()) {
355 maxExtent = q->minXExtent();
356 minExtent = q->maxXExtent();
358 maxExtent = flow == QDeclarative1GridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
359 minExtent = flow == QDeclarative1GridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
361 if (snapPos > maxExtent)
363 if (snapPos < minExtent)
369 FxGridItem1 *snapItemAt(qreal pos) {
370 for (int i = 0; i < visibleItems.count(); ++i) {
371 FxGridItem1 *item = visibleItems[i];
372 if (item->index == -1)
374 qreal itemTop = item->rowPos();
375 if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
382 int index = currentIndex;
383 for (int i = 0; i < visibleItems.count(); ++i) {
384 FxGridItem1 *item = visibleItems[i];
385 if (item->index == -1)
387 qreal itemTop = item->rowPos();
388 if (itemTop >= highlight->rowPos()-rowSize()/2 && itemTop < highlight->rowPos()+rowSize()/2) {
390 if (item->colPos() >= highlight->colPos()-colSize()/2 && item->colPos() < highlight->colPos()+colSize()/2)
397 qreal headerSize() const {
401 return flow == QDeclarative1GridView::LeftToRight
402 ? header->item->height()
403 : header->item->width();
407 virtual void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
408 Q_Q(const QDeclarative1GridView);
409 QDeclarative1FlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
411 if (newGeometry.height() != oldGeometry.height()
412 || newGeometry.width() != oldGeometry.width()) {
413 if (q->isComponentComplete()) {
418 } else if ((header && header->item == item) || (footer && footer->item == item)) {
426 void positionViewAtIndex(int index, int mode);
427 virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
428 virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
429 QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity);
431 // for debugging only
432 void checkVisible() const {
434 for (int i = 0; i < visibleItems.count(); ++i) {
435 FxGridItem1 *listItem = visibleItems.at(i);
436 if (listItem->index == -1) {
438 } else if (listItem->index != visibleIndex + i - skip) {
439 for (int j = 0; j < visibleItems.count(); j++)
440 qDebug() << " index" << j << "item index" << visibleItems.at(j)->index;
441 qFatal("index %d %d %d", visibleIndex, i, listItem->index);
446 QDeclarativeGuard<QDeclarative1VisualModel> model;
447 QVariant modelVariant;
448 QList<FxGridItem1*> visibleItems;
449 QHash<QDeclarativeItem*,int> unrequestedItems;
450 FxGridItem1 *currentItem;
451 Qt::LayoutDirection layoutDirection;
452 QDeclarative1GridView::Flow flow;
460 qreal highlightRangeStart;
461 qreal highlightRangeEnd;
462 bool highlightRangeStartValid;
463 bool highlightRangeEndValid;
464 QDeclarative1GridView::HighlightRangeMode highlightRange;
465 QDeclarativeComponent *highlightComponent;
466 FxGridItem1 *highlight;
467 FxGridItem1 *trackedItem;
468 enum MovementReason { Other, SetIndex, Mouse };
469 MovementReason moveReason;
471 QSmoothedAnimation_1 *highlightXAnimator;
472 QSmoothedAnimation_1 *highlightYAnimator;
473 int highlightMoveDuration;
474 QDeclarativeComponent *footerComponent;
476 QDeclarativeComponent *headerComponent;
478 enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
480 QDeclarative1GridView::SnapMode snapMode;
484 bool autoHighlight : 1;
485 bool fixCurrentVisibility : 1;
486 bool lazyRelease : 1;
487 bool layoutScheduled : 1;
488 bool deferredRelease : 1;
489 bool haveHighlightRange : 1;
490 bool currentIndexCleared : 1;
493 void QDeclarative1GridViewPrivate::init()
495 Q_Q(QDeclarative1GridView);
496 QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
497 q->setFlag(QGraphicsItem::ItemIsFocusScope);
498 q->setFlickableDirection(QDeclarative1Flickable::VerticalFlick);
499 addItemChangeListener(this, Geometry);
502 void QDeclarative1GridViewPrivate::clear()
504 for (int i = 0; i < visibleItems.count(); ++i)
505 releaseItem(visibleItems.at(i));
506 visibleItems.clear();
508 releaseItem(currentItem);
515 FxGridItem1 *QDeclarative1GridViewPrivate::createItem(int modelIndex)
517 Q_Q(QDeclarative1GridView);
519 requestedIndex = modelIndex;
520 FxGridItem1 *listItem = 0;
521 if (QDeclarativeItem *item = model->item(modelIndex, false)) {
522 listItem = new FxGridItem1(item, q);
523 listItem->index = modelIndex;
524 if (model->completePending()) {
526 listItem->item->setZValue(1);
527 listItem->item->setParentItem(q->contentItem());
528 model->completeItem();
530 listItem->item->setParentItem(q->contentItem());
532 unrequestedItems.remove(listItem->item);
539 void QDeclarative1GridViewPrivate::releaseItem(FxGridItem1 *item)
541 Q_Q(QDeclarative1GridView);
544 if (trackedItem == item) {
545 QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
546 QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
549 if (model->release(item->item) == 0) {
550 // item was not destroyed, and we no longer reference it.
551 unrequestedItems.insert(item->item, model->indexOf(item->item, q));
556 void QDeclarative1GridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
558 Q_Q(QDeclarative1GridView);
559 if (!isValid() || !q->isComponentComplete())
561 itemCount = model->count();
562 qreal bufferFrom = from - buffer;
563 qreal bufferTo = to + buffer;
564 qreal fillFrom = from;
566 if (doBuffer && (bufferMode & BufferAfter))
568 if (doBuffer && (bufferMode & BufferBefore))
569 fillFrom = bufferFrom;
571 bool changed = false;
573 int colPos = colPosAt(visibleIndex);
574 int rowPos = rowPosAt(visibleIndex);
575 int modelIndex = visibleIndex;
576 if (visibleItems.count()) {
577 rowPos = visibleItems.last()->rowPos();
578 colPos = visibleItems.last()->colPos() + colSize();
579 if (colPos > colSize() * (columns-1)) {
583 int i = visibleItems.count() - 1;
584 while (i > 0 && visibleItems.at(i)->index == -1)
586 modelIndex = visibleItems.at(i)->index + 1;
589 if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
590 || fillTo < rowPosAt(visibleIndex) - rowSize())) {
591 // We've jumped more than a page. Estimate which items are now
592 // visible and fill from there.
593 int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
594 for (int i = 0; i < visibleItems.count(); ++i)
595 releaseItem(visibleItems.at(i));
596 visibleItems.clear();
598 if (modelIndex >= model->count())
599 modelIndex = model->count() - 1;
600 else if (modelIndex < 0)
602 modelIndex = modelIndex / columns * columns;
603 visibleIndex = modelIndex;
604 colPos = colPosAt(visibleIndex);
605 rowPos = rowPosAt(visibleIndex);
608 int colNum = colPos / colSize();
610 FxGridItem1 *item = 0;
612 // Item creation and release is staggered in order to avoid
613 // creating/releasing multiple items in one frame
614 // while flicking (as much as possible).
615 while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
616 // qDebug() << "refill: append item" << modelIndex;
617 if (!(item = createItem(modelIndex)))
619 item->setPosition(colPos, rowPos);
620 visibleItems.append(item);
623 if (colPos > colSize() * (columns-1)) {
630 if (doBuffer) // never buffer more than one item per frame
634 if (visibleItems.count()) {
635 rowPos = visibleItems.first()->rowPos();
636 colPos = visibleItems.first()->colPos() - colSize();
638 colPos = colSize() * (columns - 1);
642 colNum = colPos / colSize();
643 while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
644 // qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
645 if (!(item = createItem(visibleIndex-1)))
648 item->setPosition(colPos, rowPos);
649 visibleItems.prepend(item);
653 colPos = colSize() * (columns - 1);
658 if (doBuffer) // never buffer more than one item per frame
662 if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
663 while (visibleItems.count() > 1
664 && (item = visibleItems.first())
665 && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
666 if (item->attached->delayRemove())
668 // qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
669 if (item->index != -1)
671 visibleItems.removeFirst();
675 while (visibleItems.count() > 1
676 && (item = visibleItems.last())
677 && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
678 if (item->attached->delayRemove())
680 // qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
681 visibleItems.removeLast();
685 deferredRelease = false;
687 deferredRelease = true;
694 if (flow == QDeclarative1GridView::LeftToRight)
695 q->setContentHeight(endPosition() - startPosition());
697 q->setContentWidth(endPosition() - startPosition());
698 } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
699 refill(from, to, true);
704 void QDeclarative1GridViewPrivate::updateGrid()
706 Q_Q(QDeclarative1GridView);
708 columns = (int)qMax((flow == QDeclarative1GridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
710 if (flow == QDeclarative1GridView::LeftToRight)
711 q->setContentHeight(endPosition() - startPosition());
713 q->setContentWidth(lastPosition() - originPosition());
717 void QDeclarative1GridViewPrivate::scheduleLayout()
719 Q_Q(QDeclarative1GridView);
720 if (!layoutScheduled) {
721 layoutScheduled = true;
722 QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority);
726 void QDeclarative1GridViewPrivate::layout()
728 Q_Q(QDeclarative1GridView);
729 layoutScheduled = false;
730 if (!isValid() && !visibleItems.count()) {
734 if (visibleItems.count()) {
735 qreal rowPos = visibleItems.first()->rowPos();
736 qreal colPos = visibleItems.first()->colPos();
737 int col = visibleIndex % columns;
738 if (colPos != col * colSize()) {
739 colPos = col * colSize();
740 visibleItems.first()->setPosition(colPos, rowPos);
742 for (int i = 1; i < visibleItems.count(); ++i) {
743 FxGridItem1 *item = visibleItems.at(i);
745 if (colPos > colSize() * (columns-1)) {
749 item->setPosition(colPos, rowPos);
759 if (flow == QDeclarative1GridView::LeftToRight) {
760 q->setContentHeight(endPosition() - startPosition());
763 q->setContentWidth(endPosition() - startPosition());
766 updateUnrequestedPositions();
769 void QDeclarative1GridViewPrivate::updateUnrequestedIndexes()
771 Q_Q(QDeclarative1GridView);
772 QHash<QDeclarativeItem*,int>::iterator it;
773 for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
774 *it = model->indexOf(it.key(), q);
777 void QDeclarative1GridViewPrivate::updateUnrequestedPositions()
779 QHash<QDeclarativeItem*,int>::const_iterator it;
780 for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
781 QDeclarativeItem *item = it.key();
782 if (flow == QDeclarative1GridView::LeftToRight) {
783 item->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
785 if (isRightToLeftTopToBottom())
786 item->setPos(QPointF(-rowPosAt(*it)-item->width(), colPosAt(*it)));
788 item->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
793 void QDeclarative1GridViewPrivate::updateTrackedItem()
795 Q_Q(QDeclarative1GridView);
796 FxGridItem1 *item = currentItem;
800 if (trackedItem && item != trackedItem) {
801 QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
802 QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
806 if (!trackedItem && item) {
808 QObject::connect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
809 QObject::connect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
812 q->trackedPositionChanged();
815 void QDeclarative1GridViewPrivate::createHighlight()
817 Q_Q(QDeclarative1GridView);
818 bool changed = false;
820 if (trackedItem == highlight)
822 if (highlight->item->scene())
823 highlight->item->scene()->removeItem(highlight->item);
824 highlight->item->deleteLater();
827 delete highlightXAnimator;
828 delete highlightYAnimator;
829 highlightXAnimator = 0;
830 highlightYAnimator = 0;
835 QDeclarativeItem *item = 0;
836 if (highlightComponent) {
837 QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
838 QObject *nobj = highlightComponent->create(highlightContext);
840 QDeclarative_setParent_noEvent(highlightContext, nobj);
841 item = qobject_cast<QDeclarativeItem *>(nobj);
845 delete highlightContext;
848 item = new QDeclarativeItem;
849 QDeclarative_setParent_noEvent(item, q->contentItem());
850 item->setParentItem(q->contentItem());
853 QDeclarative_setParent_noEvent(item, q->contentItem());
854 item->setParentItem(q->contentItem());
855 highlight = new FxGridItem1(item, q);
856 if (currentItem && autoHighlight)
857 highlight->setPosition(currentItem->colPos(), currentItem->rowPos());
858 highlightXAnimator = new QSmoothedAnimation_1(q);
859 highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
860 highlightXAnimator->userDuration = highlightMoveDuration;
861 highlightYAnimator = new QSmoothedAnimation_1(q);
862 highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y"));
863 highlightYAnimator->userDuration = highlightMoveDuration;
865 highlightXAnimator->restart();
866 highlightYAnimator->restart();
872 emit q->highlightItemChanged();
875 void QDeclarative1GridViewPrivate::updateHighlight()
877 if ((!currentItem && highlight) || (currentItem && !highlight))
879 if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
880 // auto-update highlight
881 highlightXAnimator->to = currentItem->item->x();
882 highlightYAnimator->to = currentItem->item->y();
883 highlight->item->setWidth(currentItem->item->width());
884 highlight->item->setHeight(currentItem->item->height());
885 highlightXAnimator->restart();
886 highlightYAnimator->restart();
891 void QDeclarative1GridViewPrivate::updateCurrent(int modelIndex)
893 Q_Q(QDeclarative1GridView);
894 if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
896 currentItem->attached->setIsCurrentItem(false);
897 releaseItem(currentItem);
899 currentIndex = modelIndex;
900 emit q->currentIndexChanged();
902 } else if (currentIndex != modelIndex) {
903 currentIndex = modelIndex;
904 emit q->currentIndexChanged();
909 if (currentItem && currentIndex == modelIndex) {
914 FxGridItem1 *oldCurrentItem = currentItem;
915 currentIndex = modelIndex;
916 currentItem = createItem(modelIndex);
917 fixCurrentVisibility = true;
918 if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
919 oldCurrentItem->attached->setIsCurrentItem(false);
921 currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
922 currentItem->item->setFocus(true);
923 currentItem->attached->setIsCurrentItem(true);
926 emit q->currentIndexChanged();
927 releaseItem(oldCurrentItem);
930 void QDeclarative1GridViewPrivate::updateFooter()
932 Q_Q(QDeclarative1GridView);
933 if (!footer && footerComponent) {
934 QDeclarativeItem *item = 0;
935 QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
936 QObject *nobj = footerComponent->create(context);
938 QDeclarative_setParent_noEvent(context, nobj);
939 item = qobject_cast<QDeclarativeItem *>(nobj);
946 QDeclarative_setParent_noEvent(item, q->contentItem());
947 item->setParentItem(q->contentItem());
949 QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
950 itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
951 footer = new FxGridItem1(item, q);
957 if (isRightToLeftTopToBottom()) {
958 rowOffset = footer->item->width()-cellWidth;
961 if (q->effectiveLayoutDirection() == Qt::RightToLeft)
962 colOffset = footer->item->width()-cellWidth;
964 if (visibleItems.count()) {
965 qreal endPos = lastPosition();
966 if (lastVisibleIndex() == model->count()-1) {
967 footer->setPosition(colOffset, endPos + rowOffset);
969 qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
970 if (endPos <= visiblePos || footer->endRowPos() < endPos + rowOffset)
971 footer->setPosition(colOffset, endPos + rowOffset);
976 endPos += flow == QDeclarative1GridView::LeftToRight ? header->item->height() : header->item->width();
978 footer->setPosition(colOffset, endPos);
983 void QDeclarative1GridViewPrivate::updateHeader()
985 Q_Q(QDeclarative1GridView);
986 if (!header && headerComponent) {
987 QDeclarativeItem *item = 0;
988 QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
989 QObject *nobj = headerComponent->create(context);
991 QDeclarative_setParent_noEvent(context, nobj);
992 item = qobject_cast<QDeclarativeItem *>(nobj);
999 QDeclarative_setParent_noEvent(item, q->contentItem());
1000 item->setParentItem(q->contentItem());
1002 QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
1003 itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
1004 header = new FxGridItem1(item, q);
1008 qreal colOffset = 0;
1010 if (isRightToLeftTopToBottom()) {
1011 rowOffset = -cellWidth;
1013 rowOffset = -headerSize();
1014 if (q->effectiveLayoutDirection() == Qt::RightToLeft)
1015 colOffset = header->item->width()-cellWidth;
1017 if (visibleItems.count()) {
1018 qreal startPos = originPosition();
1019 if (visibleIndex == 0) {
1020 header->setPosition(colOffset, startPos + rowOffset);
1022 qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position();
1023 qreal headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
1024 if (tempPos <= startPos || headerPos > startPos + rowOffset)
1025 header->setPosition(colOffset, startPos + rowOffset);
1028 header->setPosition(colOffset, 0);
1033 void QDeclarative1GridViewPrivate::fixupPosition()
1036 if (flow == QDeclarative1GridView::LeftToRight)
1042 void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
1044 if ((flow == QDeclarative1GridView::TopToBottom && &data == &vData)
1045 || (flow == QDeclarative1GridView::LeftToRight && &data == &hData))
1048 fixupMode = moveReason == Mouse ? fixupMode : Immediate;
1050 qreal highlightStart;
1053 if (isRightToLeftTopToBottom()) {
1054 // Handle Right-To-Left exceptions
1055 viewPos = -position()-size();
1056 highlightStart = highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
1057 highlightEnd = highlightRangeEndValid ? size()-highlightRangeStart : highlightRangeEnd;
1059 viewPos = position();
1060 highlightStart = highlightRangeStart;
1061 highlightEnd = highlightRangeEnd;
1064 if (snapMode != QDeclarative1GridView::NoSnap) {
1065 qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position();
1066 FxGridItem1 *topItem = snapItemAt(tempPosition+highlightStart);
1067 FxGridItem1 *bottomItem = snapItemAt(tempPosition+highlightEnd);
1069 if (topItem && bottomItem && haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) {
1070 qreal topPos = qMin(topItem->rowPos() - highlightStart, -maxExtent);
1071 qreal bottomPos = qMax(bottomItem->rowPos() - highlightEnd, -minExtent);
1072 pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
1073 } else if (topItem) {
1074 qreal headerPos = 0;
1076 headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
1077 if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2) {
1078 pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart;
1080 if (isRightToLeftTopToBottom())
1081 pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
1083 pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
1085 } else if (bottomItem) {
1086 if (isRightToLeftTopToBottom())
1087 pos = qMax(qMin(-bottomItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
1089 pos = qMax(qMin(bottomItem->rowPos() - highlightStart, -maxExtent), -minExtent);
1091 QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
1094 if (currentItem && haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) {
1096 qreal currPos = currentItem->rowPos();
1097 if (isRightToLeftTopToBottom())
1098 pos = -pos-size(); // Transform Pos if required
1099 if (pos < currPos + rowSize() - highlightEnd)
1100 pos = currPos + rowSize() - highlightEnd;
1101 if (pos > currPos - highlightStart)
1102 pos = currPos - highlightStart;
1103 if (isRightToLeftTopToBottom())
1104 pos = -pos-size(); // Untransform
1106 qreal dist = qAbs(data.move + pos);
1108 timeline.reset(data.move);
1109 if (fixupMode != Immediate) {
1110 timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
1111 data.fixingUp = true;
1113 timeline.set(data.move, -pos);
1115 vTime = timeline.time();
1117 } else if (haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) {
1120 qreal pos = currentItem->rowPos();
1121 if (viewPos < pos + rowSize() - highlightEnd)
1122 viewPos = pos + rowSize() - highlightEnd;
1123 if (viewPos > pos - highlightStart)
1124 viewPos = pos - highlightStart;
1125 if (isRightToLeftTopToBottom())
1126 viewPos = -viewPos-size();
1127 timeline.reset(data.move);
1128 if (viewPos != position()) {
1129 if (fixupMode != Immediate) {
1130 timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
1131 data.fixingUp = true;
1133 timeline.set(data.move, -viewPos);
1136 vTime = timeline.time();
1139 QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
1141 data.inOvershoot = false;
1145 void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
1146 QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity)
1148 Q_Q(QDeclarative1GridView);
1149 data.fixingUp = false;
1151 if ((!haveHighlightRange || highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
1152 && snapMode == QDeclarative1GridView::NoSnap) {
1153 QDeclarative1FlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
1156 qreal maxDistance = 0;
1157 qreal dataValue = isRightToLeftTopToBottom() ? -data.move.value()+size() : data.move.value();
1158 // -ve velocity means list is moving up/left
1160 if (data.move.value() < minExtent) {
1161 if (snapMode == QDeclarative1GridView::SnapOneRow) {
1162 if (FxGridItem1 *item = firstVisibleItem()) {
1163 maxDistance = qAbs(item->rowPos() + dataValue);
1166 maxDistance = qAbs(minExtent - data.move.value());
1169 if (snapMode == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
1170 data.flickTarget = minExtent;
1172 if (data.move.value() > maxExtent) {
1173 if (snapMode == QDeclarative1GridView::SnapOneRow) {
1174 qreal pos = snapPosAt(-dataValue) + (isRightToLeftTopToBottom() ? 0 : rowSize());
1175 maxDistance = qAbs(pos + dataValue);
1177 maxDistance = qAbs(maxExtent - data.move.value());
1180 if (snapMode == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
1181 data.flickTarget = maxExtent;
1184 bool overShoot = boundsBehavior == QDeclarative1Flickable::DragAndOvershootBounds;
1185 qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
1187 if (maxDistance > 0 || overShoot) {
1188 // This mode requires the grid to stop exactly on a row boundary.
1190 if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
1196 qreal accel = deceleration;
1198 qreal overshootDist = 0.0;
1199 if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarative1GridView::SnapOneRow) {
1200 // + rowSize()/4 to encourage moving at least one item in the flick direction
1201 qreal dist = v2 / (accel * 2.0) + rowSize()/4;
1202 dist = qMin(dist, maxDistance);
1205 qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist;
1206 data.flickTarget = -snapPosAt(-(dataValue - highlightStart) + distTemp) + highlightStart;
1207 data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget;
1208 qreal adjDist = -data.flickTarget + data.move.value();
1209 if (qAbs(adjDist) > qAbs(dist)) {
1210 // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
1211 qreal adjv2 = accel * 2.0f * qAbs(adjDist);
1220 accel = v2 / (2.0f * qAbs(dist));
1222 data.flickTarget = velocity > 0 ? minExtent : maxExtent;
1223 overshootDist = overShoot ? overShootDistance(vSize) : 0;
1225 timeline.reset(data.move);
1226 timeline.accel(data.move, v, accel, maxDistance + overshootDist);
1227 timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this));
1228 if (!flickingHorizontally && q->xflick()) {
1229 flickingHorizontally = true;
1230 emit q->flickingChanged();
1231 emit q->flickingHorizontallyChanged();
1232 emit q->flickStarted();
1234 if (!flickingVertically && q->yflick()) {
1235 flickingVertically = true;
1236 emit q->flickingChanged();
1237 emit q->flickingVerticallyChanged();
1238 emit q->flickStarted();
1241 timeline.reset(data.move);
1242 fixup(data, minExtent, maxExtent);
1247 //----------------------------------------------------------------------------
1250 \qmlclass GridView QDeclarative1GridView
1251 \inqmlmodule QtQuick 1
1253 \ingroup qml-view-elements
1256 \brief The GridView item provides a grid view of items provided by a model.
1258 A GridView displays data from models created from built-in QML elements like ListModel
1259 and XmlListModel, or custom model classes defined in C++ that inherit from
1262 A GridView has a \l model, which defines the data to be displayed, and
1263 a \l delegate, which defines how the data should be displayed. Items in a
1264 GridView are laid out horizontally or vertically. Grid views are inherently flickable
1265 as GridView inherits from \l Flickable.
1267 \section1 Example Usage
1269 The following example shows the definition of a simple list model defined
1270 in a file called \c ContactModel.qml:
1272 \snippet doc/src/snippets/declarative/gridview/ContactModel.qml 0
1274 \div {class="float-right"}
1275 \inlineimage gridview-simple.png
1278 This model can be referenced as \c ContactModel in other QML files. See \l{QML Modules}
1279 for more information about creating reusable components like this.
1281 Another component can display this model data in a GridView, as in the following
1282 example, which creates a \c ContactModel component for its model, and a \l Column element
1283 (containing \l Image and \l Text elements) for its delegate.
1286 \snippet doc/src/snippets/declarative/gridview/gridview.qml import
1288 \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs simple
1290 \div {class="float-right"}
1291 \inlineimage gridview-highlight.png
1294 The view will create a new delegate for each item in the model. Note that the delegate
1295 is able to access the model's \c name and \c portrait data directly.
1297 An improved grid view is shown below. The delegate is visually improved and is moved
1298 into a separate \c contactDelegate component.
1301 \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs advanced
1303 The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
1304 and \c focus is set to \c true to enable keyboard navigation for the grid view.
1305 The grid view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
1307 Delegates are instantiated as needed and may be destroyed at any time.
1308 State should \e never be stored in a delegate.
1310 GridView attaches a number of properties to the root item of the delegate, for example
1311 \c {GridView.isCurrentItem}. In the following example, the root delegate item can access
1312 this attached property directly as \c GridView.isCurrentItem, while the child
1313 \c contactInfo object must refer to this property as \c wrapper.GridView.isCurrentItem.
1315 \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
1317 \note Views do not set the \l{Item::}{clip} property automatically.
1318 If the view is not clipped by another item or the screen, it will be necessary
1319 to set this property to true in order to clip the items that are partially or
1320 fully outside the view.
1322 \sa {declarative/modelviews/gridview}{GridView example}
1324 QDeclarative1GridView::QDeclarative1GridView(QDeclarativeItem *parent)
1325 : QDeclarative1Flickable(*(new QDeclarative1GridViewPrivate), parent)
1327 Q_D(QDeclarative1GridView);
1331 QDeclarative1GridView::~QDeclarative1GridView()
1333 Q_D(QDeclarative1GridView);
1342 \qmlattachedproperty bool GridView::isCurrentItem
1343 This attached property is true if this delegate is the current item; otherwise false.
1345 It is attached to each instance of the delegate.
1349 \qmlattachedproperty GridView GridView::view
1350 This attached property holds the view that manages this delegate instance.
1352 It is attached to each instance of the delegate.
1354 \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
1358 \qmlattachedproperty bool GridView::delayRemove
1359 This attached property holds whether the delegate may be destroyed.
1361 It is attached to each instance of the delegate.
1363 It is sometimes necessary to delay the destruction of an item
1364 until an animation completes.
1366 The example below ensures that the animation completes before
1367 the item is removed from the grid.
1369 \snippet doc/src/snippets/declarative/gridview/gridview.qml delayRemove
1373 \qmlattachedsignal QtQuick1::GridView::onAdd()
1374 This attached handler is called immediately after an item is added to the view.
1378 \qmlattachedsignal QtQuick1::GridView::onRemove()
1379 This attached handler is called immediately before an item is removed from the view.
1384 \qmlproperty model QtQuick1::GridView::model
1385 This property holds the model providing data for the grid.
1387 The model provides the set of data that is used to create the items
1388 in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
1389 or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
1390 used, it must be a subclass of \l QAbstractItemModel or a simple list.
1392 \sa {qmlmodels}{Data Models}
1394 QVariant QDeclarative1GridView::model() const
1396 Q_D(const QDeclarative1GridView);
1397 return d->modelVariant;
1401 int QDeclarative1GridView::modelCount() const
1403 Q_D(const QDeclarative1GridView);
1404 return d->model->count();
1407 void QDeclarative1GridView::setModel(const QVariant &model)
1409 Q_D(QDeclarative1GridView);
1410 if (d->modelVariant == model)
1413 disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
1414 disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
1415 disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
1416 disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
1417 disconnect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
1418 disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
1421 d->modelVariant = model;
1422 QObject *object = qvariant_cast<QObject*>(model);
1423 QDeclarative1VisualModel *vim = 0;
1424 if (object && (vim = qobject_cast<QDeclarative1VisualModel *>(object))) {
1427 d->ownModel = false;
1432 d->model = new QDeclarative1VisualDataModel(qmlContext(this), this);
1435 if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
1436 dataModel->setModel(model);
1439 d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore | QDeclarative1GridViewPrivate::BufferAfter;
1440 if (isComponentComplete()) {
1442 if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
1445 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
1446 d->updateCurrent(d->currentIndex);
1447 if (d->highlight && d->currentItem) {
1448 if (d->autoHighlight)
1449 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
1450 d->updateTrackedItem();
1452 d->moveReason = QDeclarative1GridViewPrivate::Other;
1455 connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
1456 connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
1457 connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
1458 connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
1459 connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
1460 connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
1461 emit countChanged();
1463 emit modelChanged();
1467 \qmlproperty Component QtQuick1::GridView::delegate
1469 The delegate provides a template defining each item instantiated by the view.
1470 The index is exposed as an accessible \c index property. Properties of the
1471 model are also available depending upon the type of \l {qmlmodels}{Data Model}.
1473 The number of elements in the delegate has a direct effect on the
1474 flicking performance of the view. If at all possible, place functionality
1475 that is not needed for the normal display of the delegate in a \l Loader which
1476 can load additional elements when needed.
1478 The GridView will layout the items based on the size of the root item
1481 \note Delegates are instantiated as needed and may be destroyed at any time.
1482 State should \e never be stored in a delegate.
1484 QDeclarativeComponent *QDeclarative1GridView::delegate() const
1486 Q_D(const QDeclarative1GridView);
1488 if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
1489 return dataModel->delegate();
1495 void QDeclarative1GridView::setDelegate(QDeclarativeComponent *delegate)
1497 Q_D(QDeclarative1GridView);
1498 if (delegate == this->delegate())
1502 d->model = new QDeclarative1VisualDataModel(qmlContext(this));
1505 if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model)) {
1506 int oldCount = dataModel->count();
1507 dataModel->setDelegate(delegate);
1508 if (isComponentComplete()) {
1509 for (int i = 0; i < d->visibleItems.count(); ++i)
1510 d->releaseItem(d->visibleItems.at(i));
1511 d->visibleItems.clear();
1512 d->releaseItem(d->currentItem);
1515 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
1516 d->updateCurrent(d->currentIndex);
1517 if (d->highlight && d->currentItem) {
1518 if (d->autoHighlight)
1519 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
1520 d->updateTrackedItem();
1522 d->moveReason = QDeclarative1GridViewPrivate::Other;
1524 if (oldCount != dataModel->count())
1525 emit countChanged();
1526 emit delegateChanged();
1531 \qmlproperty int QtQuick1::GridView::currentIndex
1532 \qmlproperty Item QtQuick1::GridView::currentItem
1534 The \c currentIndex property holds the index of the current item, and
1535 \c currentItem holds the current item. Setting the currentIndex to -1
1536 will clear the highlight and set currentItem to null.
1538 If highlightFollowsCurrentItem is \c true, setting either of these
1539 properties will smoothly scroll the GridView so that the current
1540 item becomes visible.
1542 Note that the position of the current item
1543 may only be approximate until it becomes visible in the view.
1545 int QDeclarative1GridView::currentIndex() const
1547 Q_D(const QDeclarative1GridView);
1548 return d->currentIndex;
1551 void QDeclarative1GridView::setCurrentIndex(int index)
1553 Q_D(QDeclarative1GridView);
1554 if (d->requestedIndex >= 0) // currently creating item
1556 d->currentIndexCleared = (index == -1);
1557 if (index == d->currentIndex)
1559 if (isComponentComplete() && d->isValid()) {
1560 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
1561 d->updateCurrent(index);
1563 d->currentIndex = index;
1564 emit currentIndexChanged();
1568 QDeclarativeItem *QDeclarative1GridView::currentItem()
1570 Q_D(QDeclarative1GridView);
1571 if (!d->currentItem)
1573 return d->currentItem->item;
1577 \qmlproperty Item QtQuick1::GridView::highlightItem
1579 This holds the highlight item created from the \l highlight component.
1581 The highlightItem is managed by the view unless
1582 \l highlightFollowsCurrentItem is set to false.
1584 \sa highlight, highlightFollowsCurrentItem
1586 QDeclarativeItem *QDeclarative1GridView::highlightItem()
1588 Q_D(QDeclarative1GridView);
1591 return d->highlight->item;
1595 \qmlproperty int QtQuick1::GridView::count
1596 This property holds the number of items in the view.
1598 int QDeclarative1GridView::count() const
1600 Q_D(const QDeclarative1GridView);
1602 return d->model->count();
1607 \qmlproperty Component QtQuick1::GridView::highlight
1608 This property holds the component to use as the highlight.
1610 An instance of the highlight component is created for each view.
1611 The geometry of the resulting component instance will be managed by the view
1612 so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
1614 \sa highlightItem, highlightFollowsCurrentItem
1616 QDeclarativeComponent *QDeclarative1GridView::highlight() const
1618 Q_D(const QDeclarative1GridView);
1619 return d->highlightComponent;
1622 void QDeclarative1GridView::setHighlight(QDeclarativeComponent *highlight)
1624 Q_D(QDeclarative1GridView);
1625 if (highlight != d->highlightComponent) {
1626 d->highlightComponent = highlight;
1627 d->updateCurrent(d->currentIndex);
1628 emit highlightChanged();
1633 \qmlproperty bool QtQuick1::GridView::highlightFollowsCurrentItem
1634 This property sets whether the highlight is managed by the view.
1636 If this property is true (the default value), the highlight is moved smoothly
1637 to follow the current item. Otherwise, the
1638 highlight is not moved by the view, and any movement must be implemented
1641 Here is a highlight with its motion defined by a \l {SpringAnimation} item:
1643 \snippet doc/src/snippets/declarative/gridview/gridview.qml highlightFollowsCurrentItem
1645 bool QDeclarative1GridView::highlightFollowsCurrentItem() const
1647 Q_D(const QDeclarative1GridView);
1648 return d->autoHighlight;
1651 void QDeclarative1GridView::setHighlightFollowsCurrentItem(bool autoHighlight)
1653 Q_D(QDeclarative1GridView);
1654 if (d->autoHighlight != autoHighlight) {
1655 d->autoHighlight = autoHighlight;
1656 if (autoHighlight) {
1657 d->updateHighlight();
1658 } else if (d->highlightXAnimator) {
1659 d->highlightXAnimator->stop();
1660 d->highlightYAnimator->stop();
1666 \qmlproperty int QtQuick1::GridView::highlightMoveDuration
1667 This property holds the move animation duration of the highlight delegate.
1669 highlightFollowsCurrentItem must be true for this property
1672 The default value for the duration is 150ms.
1674 \sa highlightFollowsCurrentItem
1676 int QDeclarative1GridView::highlightMoveDuration() const
1678 Q_D(const QDeclarative1GridView);
1679 return d->highlightMoveDuration;
1682 void QDeclarative1GridView::setHighlightMoveDuration(int duration)
1684 Q_D(QDeclarative1GridView);
1685 if (d->highlightMoveDuration != duration) {
1686 d->highlightMoveDuration = duration;
1687 if (d->highlightYAnimator) {
1688 d->highlightXAnimator->userDuration = d->highlightMoveDuration;
1689 d->highlightYAnimator->userDuration = d->highlightMoveDuration;
1691 emit highlightMoveDurationChanged();
1697 \qmlproperty real QtQuick1::GridView::preferredHighlightBegin
1698 \qmlproperty real QtQuick1::GridView::preferredHighlightEnd
1699 \qmlproperty enumeration QtQuick1::GridView::highlightRangeMode
1701 These properties define the preferred range of the highlight (for the current item)
1702 within the view. The \c preferredHighlightBegin value must be less than the
1703 \c preferredHighlightEnd value.
1705 These properties affect the position of the current item when the view is scrolled.
1706 For example, if the currently selected item should stay in the middle of the
1707 view when it is scrolled, set the \c preferredHighlightBegin and
1708 \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
1709 item would be. If the \c currentItem is changed programmatically, the view will
1710 automatically scroll so that the current item is in the middle of the view.
1711 Furthermore, the behavior of the current item index will occur whether or not a
1714 Valid values for \c highlightRangeMode are:
1717 \o GridView.ApplyRange - the view attempts to maintain the highlight within the range.
1718 However, the highlight can move outside of the range at the ends of the view or due
1719 to mouse interaction.
1720 \o GridView.StrictlyEnforceRange - the highlight never moves outside of the range.
1721 The current item changes if a keyboard or mouse action would cause the highlight to move
1722 outside of the range.
1723 \o GridView.NoHighlightRange - this is the default value.
1726 qreal QDeclarative1GridView::preferredHighlightBegin() const
1728 Q_D(const QDeclarative1GridView);
1729 return d->highlightRangeStart;
1732 void QDeclarative1GridView::setPreferredHighlightBegin(qreal start)
1734 Q_D(QDeclarative1GridView);
1735 d->highlightRangeStartValid = true;
1736 if (d->highlightRangeStart == start)
1738 d->highlightRangeStart = start;
1739 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1740 emit preferredHighlightBeginChanged();
1743 void QDeclarative1GridView::resetPreferredHighlightBegin()
1745 Q_D(QDeclarative1GridView);
1746 d->highlightRangeStartValid = false;
1747 if (d->highlightRangeStart == 0)
1749 d->highlightRangeStart = 0;
1750 emit preferredHighlightBeginChanged();
1753 qreal QDeclarative1GridView::preferredHighlightEnd() const
1755 Q_D(const QDeclarative1GridView);
1756 return d->highlightRangeEnd;
1759 void QDeclarative1GridView::setPreferredHighlightEnd(qreal end)
1761 Q_D(QDeclarative1GridView);
1762 d->highlightRangeEndValid = true;
1763 if (d->highlightRangeEnd == end)
1765 d->highlightRangeEnd = end;
1766 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1767 emit preferredHighlightEndChanged();
1770 void QDeclarative1GridView::resetPreferredHighlightEnd()
1772 Q_D(QDeclarative1GridView);
1773 d->highlightRangeEndValid = false;
1774 if (d->highlightRangeEnd == 0)
1776 d->highlightRangeEnd = 0;
1777 emit preferredHighlightEndChanged();
1780 QDeclarative1GridView::HighlightRangeMode QDeclarative1GridView::highlightRangeMode() const
1782 Q_D(const QDeclarative1GridView);
1783 return d->highlightRange;
1786 void QDeclarative1GridView::setHighlightRangeMode(HighlightRangeMode mode)
1788 Q_D(QDeclarative1GridView);
1789 if (d->highlightRange == mode)
1791 d->highlightRange = mode;
1792 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1793 emit highlightRangeModeChanged();
1797 \qmlproperty enumeration QtQuick1::GridView::layoutDirection
1798 This property holds the layout direction of the grid.
1803 \o Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is
1804 dependent on the \l GridView::flow property.
1805 \o Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent
1806 on the \l GridView::flow property.
1809 \bold Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if
1810 GridView::layoutDirection is set to Qt.RightToLeft. The GridView.LeftToRight flow value simply
1811 indicates that the flow is horizontal.
1814 Qt::LayoutDirection QDeclarative1GridView::layoutDirection() const
1816 Q_D(const QDeclarative1GridView);
1817 return d->layoutDirection;
1820 void QDeclarative1GridView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
1822 Q_D(QDeclarative1GridView);
1823 if (d->layoutDirection != layoutDirection) {
1824 d->layoutDirection = layoutDirection;
1826 emit layoutDirectionChanged();
1827 emit effectiveLayoutDirectionChanged();
1832 \qmlproperty enumeration QtQuick1::GridView::effectiveLayoutDirection
1833 This property holds the effective layout direction of the grid.
1835 When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
1836 the visual layout direction of the grid will be mirrored. However, the
1837 property \l {GridView::layoutDirection}{layoutDirection} will remain unchanged.
1839 \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
1842 Qt::LayoutDirection QDeclarative1GridView::effectiveLayoutDirection() const
1844 Q_D(const QDeclarative1GridView);
1845 if (d->effectiveLayoutMirror)
1846 return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
1848 return d->layoutDirection;
1852 \qmlproperty enumeration QtQuick1::GridView::flow
1853 This property holds the flow of the grid.
1858 \o GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically
1859 \o GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally
1862 QDeclarative1GridView::Flow QDeclarative1GridView::flow() const
1864 Q_D(const QDeclarative1GridView);
1868 void QDeclarative1GridView::setFlow(Flow flow)
1870 Q_D(QDeclarative1GridView);
1871 if (d->flow != flow) {
1873 if (d->flow == LeftToRight) {
1874 setContentWidth(-1);
1875 setFlickableDirection(QDeclarative1Flickable::VerticalFlick);
1877 setContentHeight(-1);
1878 setFlickableDirection(QDeclarative1Flickable::HorizontalFlick);
1888 \qmlproperty bool QtQuick1::GridView::keyNavigationWraps
1889 This property holds whether the grid wraps key navigation
1891 If this is true, key navigation that would move the current item selection
1892 past one end of the view instead wraps around and moves the selection to
1893 the other end of the view.
1895 By default, key navigation is not wrapped.
1897 bool QDeclarative1GridView::isWrapEnabled() const
1899 Q_D(const QDeclarative1GridView);
1903 void QDeclarative1GridView::setWrapEnabled(bool wrap)
1905 Q_D(QDeclarative1GridView);
1906 if (d->wrap == wrap)
1909 emit keyNavigationWrapsChanged();
1913 \qmlproperty int QtQuick1::GridView::cacheBuffer
1914 This property determines whether delegates are retained outside the
1915 visible area of the view.
1917 If non-zero the view will keep as many delegates
1918 instantiated as will fit within the buffer specified. For example,
1919 if in a vertical view the delegate is 20 pixels high and \c cacheBuffer is
1920 set to 40, then up to 2 delegates above and 2 delegates below the visible
1921 area may be retained.
1923 Note that cacheBuffer is not a pixel buffer - it only maintains additional
1924 instantiated delegates.
1926 Setting this value can make scrolling the list smoother at the expense
1927 of additional memory usage. It is not a substitute for creating efficient
1928 delegates; the fewer elements in a delegate, the faster a view may be
1931 int QDeclarative1GridView::cacheBuffer() const
1933 Q_D(const QDeclarative1GridView);
1937 void QDeclarative1GridView::setCacheBuffer(int buffer)
1939 Q_D(QDeclarative1GridView);
1940 if (d->buffer != buffer) {
1942 if (isComponentComplete())
1944 emit cacheBufferChanged();
1949 \qmlproperty int QtQuick1::GridView::cellWidth
1950 \qmlproperty int QtQuick1::GridView::cellHeight
1952 These properties holds the width and height of each cell in the grid.
1954 The default cell size is 100x100.
1956 int QDeclarative1GridView::cellWidth() const
1958 Q_D(const QDeclarative1GridView);
1959 return d->cellWidth;
1962 void QDeclarative1GridView::setCellWidth(int cellWidth)
1964 Q_D(QDeclarative1GridView);
1965 if (cellWidth != d->cellWidth && cellWidth > 0) {
1966 d->cellWidth = qMax(1, cellWidth);
1968 emit cellWidthChanged();
1973 int QDeclarative1GridView::cellHeight() const
1975 Q_D(const QDeclarative1GridView);
1976 return d->cellHeight;
1979 void QDeclarative1GridView::setCellHeight(int cellHeight)
1981 Q_D(QDeclarative1GridView);
1982 if (cellHeight != d->cellHeight && cellHeight > 0) {
1983 d->cellHeight = qMax(1, cellHeight);
1985 emit cellHeightChanged();
1990 \qmlproperty enumeration QtQuick1::GridView::snapMode
1992 This property determines how the view scrolling will settle following a drag or flick.
1993 The possible values are:
1996 \o GridView.NoSnap (default) - the view stops anywhere within the visible area.
1997 \o GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow)
1998 aligned with the start of the view.
1999 \o GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow)
2000 away from the first visible row at the time the mouse button is released.
2001 This mode is particularly useful for moving one page at a time.
2005 QDeclarative1GridView::SnapMode QDeclarative1GridView::snapMode() const
2007 Q_D(const QDeclarative1GridView);
2011 void QDeclarative1GridView::setSnapMode(SnapMode mode)
2013 Q_D(QDeclarative1GridView);
2014 if (d->snapMode != mode) {
2016 emit snapModeChanged();
2021 \qmlproperty Component QtQuick1::GridView::footer
2022 This property holds the component to use as the footer.
2024 An instance of the footer component is created for each view. The
2025 footer is positioned at the end of the view, after any items.
2029 QDeclarativeComponent *QDeclarative1GridView::footer() const
2031 Q_D(const QDeclarative1GridView);
2032 return d->footerComponent;
2035 void QDeclarative1GridView::setFooter(QDeclarativeComponent *footer)
2037 Q_D(QDeclarative1GridView);
2038 if (d->footerComponent != footer) {
2041 scene()->removeItem(d->footer->item);
2042 d->footer->item->deleteLater();
2046 d->footerComponent = footer;
2047 if (isComponentComplete()) {
2052 emit footerChanged();
2057 \qmlproperty Component QtQuick1::GridView::header
2058 This property holds the component to use as the header.
2060 An instance of the header component is created for each view. The
2061 header is positioned at the beginning of the view, before any items.
2065 QDeclarativeComponent *QDeclarative1GridView::header() const
2067 Q_D(const QDeclarative1GridView);
2068 return d->headerComponent;
2071 void QDeclarative1GridView::setHeader(QDeclarativeComponent *header)
2073 Q_D(QDeclarative1GridView);
2074 if (d->headerComponent != header) {
2077 scene()->removeItem(d->header->item);
2078 d->header->item->deleteLater();
2082 d->headerComponent = header;
2083 if (isComponentComplete()) {
2089 emit headerChanged();
2093 void QDeclarative1GridView::setContentX(qreal pos)
2095 Q_D(QDeclarative1GridView);
2096 // Positioning the view manually should override any current movement state
2097 d->moveReason = QDeclarative1GridViewPrivate::Other;
2098 QDeclarative1Flickable::setContentX(pos);
2101 void QDeclarative1GridView::setContentY(qreal pos)
2103 Q_D(QDeclarative1GridView);
2104 // Positioning the view manually should override any current movement state
2105 d->moveReason = QDeclarative1GridViewPrivate::Other;
2106 QDeclarative1Flickable::setContentY(pos);
2109 bool QDeclarative1GridView::event(QEvent *event)
2111 Q_D(QDeclarative1GridView);
2112 if (event->type() == QEvent::User) {
2117 return QDeclarative1Flickable::event(event);
2120 void QDeclarative1GridView::viewportMoved()
2122 Q_D(QDeclarative1GridView);
2123 QDeclarative1Flickable::viewportMoved();
2126 d->lazyRelease = true;
2127 if (d->flickingHorizontally || d->flickingVertically) {
2129 if (d->vData.velocity > 0)
2130 d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore;
2131 else if (d->vData.velocity < 0)
2132 d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter;
2136 if (d->hData.velocity > 0)
2137 d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore;
2138 else if (d->hData.velocity < 0)
2139 d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter;
2143 if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
2144 d->moveReason = QDeclarative1GridViewPrivate::Mouse;
2145 if (d->moveReason != QDeclarative1GridViewPrivate::SetIndex) {
2146 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
2147 // reposition highlight
2148 qreal pos = d->highlight->rowPos();
2150 qreal highlightStart;
2152 if (d->isRightToLeftTopToBottom()) {
2153 highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
2154 highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
2155 viewPos = -d->position()-d->size();
2157 highlightStart = d->highlightRangeStart;
2158 highlightEnd = d->highlightRangeEnd;
2159 viewPos = d->position();
2161 if (pos > viewPos + highlightEnd - d->rowSize())
2162 pos = viewPos + highlightEnd - d->rowSize();
2163 if (pos < viewPos + highlightStart)
2164 pos = viewPos + highlightStart;
2166 d->highlight->setPosition(d->highlight->colPos(), qRound(pos));
2168 // update current index
2169 int idx = d->snapIndex();
2170 if (idx >= 0 && idx != d->currentIndex) {
2171 d->updateCurrent(idx);
2172 if (d->currentItem && d->currentItem->colPos() != d->highlight->colPos() && d->autoHighlight) {
2173 if (d->flow == LeftToRight)
2174 d->highlightXAnimator->to = d->currentItem->item->x();
2176 d->highlightYAnimator->to = d->currentItem->item->y();
2183 qreal QDeclarative1GridView::minYExtent() const
2185 Q_D(const QDeclarative1GridView);
2186 if (d->flow == QDeclarative1GridView::TopToBottom)
2187 return QDeclarative1Flickable::minYExtent();
2188 qreal extent = -d->startPosition();
2189 if (d->header && d->visibleItems.count())
2190 extent += d->header->item->height();
2191 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2192 extent += d->highlightRangeStart;
2193 extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
2198 qreal QDeclarative1GridView::maxYExtent() const
2200 Q_D(const QDeclarative1GridView);
2201 if (d->flow == QDeclarative1GridView::TopToBottom)
2202 return QDeclarative1Flickable::maxYExtent();
2204 if (!d->model || !d->model->count()) {
2206 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2207 extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
2208 if (d->highlightRangeEnd != d->highlightRangeStart)
2209 extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
2211 extent = -(d->endPosition() - height());
2214 extent -= d->footer->item->height();
2215 const qreal minY = minYExtent();
2221 qreal QDeclarative1GridView::minXExtent() const
2223 Q_D(const QDeclarative1GridView);
2224 if (d->flow == QDeclarative1GridView::LeftToRight)
2225 return QDeclarative1Flickable::minXExtent();
2226 qreal extent = -d->startPosition();
2227 qreal highlightStart;
2229 qreal endPositionFirstItem;
2230 if (d->isRightToLeftTopToBottom()) {
2231 endPositionFirstItem = d->rowPosAt(d->model->count()-1);
2232 highlightStart = d->highlightRangeStartValid
2233 ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
2234 : d->size() - (d->lastPosition()-endPositionFirstItem);
2235 highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
2236 if (d->footer && d->visibleItems.count())
2237 extent += d->footer->item->width();
2239 endPositionFirstItem = d->rowPosAt(0)+d->rowSize();
2240 highlightStart = d->highlightRangeStart;
2241 highlightEnd = d->highlightRangeEnd;
2242 if (d->header && d->visibleItems.count())
2243 extent += d->header->item->width();
2245 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2246 extent += highlightStart;
2247 extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
2252 qreal QDeclarative1GridView::maxXExtent() const
2254 Q_D(const QDeclarative1GridView);
2255 if (d->flow == QDeclarative1GridView::LeftToRight)
2256 return QDeclarative1Flickable::maxXExtent();
2258 qreal highlightStart;
2260 qreal lastItemPosition = 0;
2261 if (d->isRightToLeftTopToBottom()){
2262 highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
2263 highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
2264 lastItemPosition = d->endPosition();
2266 highlightStart = d->highlightRangeStart;
2267 highlightEnd = d->highlightRangeEnd;
2268 lastItemPosition = 0;
2269 if (d->model && d->model->count())
2270 lastItemPosition = d->rowPosAt(d->model->count()-1);
2272 if (!d->model || !d->model->count()) {
2274 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2275 extent = -(lastItemPosition - highlightStart);
2276 if (highlightEnd != highlightStart)
2277 extent = d->isRightToLeftTopToBottom()
2278 ? qMax(extent, -(d->endPosition() - highlightEnd + 1))
2279 : qMin(extent, -(d->endPosition() - highlightEnd + 1));
2281 extent = -(d->endPosition() - width());
2283 if (d->isRightToLeftTopToBottom()) {
2285 extent -= d->header->item->width();
2288 extent -= d->footer->item->width();
2291 const qreal minX = minXExtent();
2297 void QDeclarative1GridView::keyPressEvent(QKeyEvent *event)
2299 Q_D(QDeclarative1GridView);
2300 keyPressPreHandler(event);
2301 if (event->isAccepted())
2303 if (d->model && d->model->count() && d->interactive) {
2304 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
2305 int oldCurrent = currentIndex();
2306 switch (event->key()) {
2308 moveCurrentIndexUp();
2311 moveCurrentIndexDown();
2314 moveCurrentIndexLeft();
2317 moveCurrentIndexRight();
2322 if (oldCurrent != currentIndex()) {
2327 d->moveReason = QDeclarative1GridViewPrivate::Other;
2329 QDeclarative1Flickable::keyPressEvent(event);
2333 \qmlmethod QtQuick1::GridView::moveCurrentIndexUp()
2335 Move the currentIndex up one item in the view.
2336 The current index will wrap if keyNavigationWraps is true and it
2337 is currently at the end. This method has no effect if the \l count is zero.
2339 \bold Note: methods should only be called after the Component has completed.
2341 void QDeclarative1GridView::moveCurrentIndexUp()
2343 Q_D(QDeclarative1GridView);
2344 const int count = d->model ? d->model->count() : 0;
2347 if (d->flow == QDeclarative1GridView::LeftToRight) {
2348 if (currentIndex() >= d->columns || d->wrap) {
2349 int index = currentIndex() - d->columns;
2350 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2353 if (currentIndex() > 0 || d->wrap) {
2354 int index = currentIndex() - 1;
2355 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2361 \qmlmethod QtQuick1::GridView::moveCurrentIndexDown()
2363 Move the currentIndex down one item in the view.
2364 The current index will wrap if keyNavigationWraps is true and it
2365 is currently at the end. This method has no effect if the \l count is zero.
2367 \bold Note: methods should only be called after the Component has completed.
2369 void QDeclarative1GridView::moveCurrentIndexDown()
2371 Q_D(QDeclarative1GridView);
2372 const int count = d->model ? d->model->count() : 0;
2375 if (d->flow == QDeclarative1GridView::LeftToRight) {
2376 if (currentIndex() < count - d->columns || d->wrap) {
2377 int index = currentIndex()+d->columns;
2378 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2381 if (currentIndex() < count - 1 || d->wrap) {
2382 int index = currentIndex() + 1;
2383 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2389 \qmlmethod QtQuick1::GridView::moveCurrentIndexLeft()
2391 Move the currentIndex left one item in the view.
2392 The current index will wrap if keyNavigationWraps is true and it
2393 is currently at the end. This method has no effect if the \l count is zero.
2395 \bold Note: methods should only be called after the Component has completed.
2397 void QDeclarative1GridView::moveCurrentIndexLeft()
2399 Q_D(QDeclarative1GridView);
2400 const int count = d->model ? d->model->count() : 0;
2404 if (effectiveLayoutDirection() == Qt::LeftToRight) {
2405 if (d->flow == QDeclarative1GridView::LeftToRight) {
2406 if (currentIndex() > 0 || d->wrap) {
2407 int index = currentIndex() - 1;
2408 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2411 if (currentIndex() >= d->columns || d->wrap) {
2412 int index = currentIndex() - d->columns;
2413 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2417 if (d->flow == QDeclarative1GridView::LeftToRight) {
2418 if (currentIndex() < count - 1 || d->wrap) {
2419 int index = currentIndex() + 1;
2420 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2423 if (currentIndex() < count - d->columns || d->wrap) {
2424 int index = currentIndex() + d->columns;
2425 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2432 \qmlmethod QtQuick1::GridView::moveCurrentIndexRight()
2434 Move the currentIndex right one item in the view.
2435 The current index will wrap if keyNavigationWraps is true and it
2436 is currently at the end. This method has no effect if the \l count is zero.
2438 \bold Note: methods should only be called after the Component has completed.
2440 void QDeclarative1GridView::moveCurrentIndexRight()
2442 Q_D(QDeclarative1GridView);
2443 const int count = d->model ? d->model->count() : 0;
2447 if (effectiveLayoutDirection() == Qt::LeftToRight) {
2448 if (d->flow == QDeclarative1GridView::LeftToRight) {
2449 if (currentIndex() < count - 1 || d->wrap) {
2450 int index = currentIndex() + 1;
2451 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2454 if (currentIndex() < count - d->columns || d->wrap) {
2455 int index = currentIndex()+d->columns;
2456 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2460 if (d->flow == QDeclarative1GridView::LeftToRight) {
2461 if (currentIndex() > 0 || d->wrap) {
2462 int index = currentIndex() - 1;
2463 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2466 if (currentIndex() >= d->columns || d->wrap) {
2467 int index = currentIndex() - d->columns;
2468 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2474 void QDeclarative1GridViewPrivate::positionViewAtIndex(int index, int mode)
2476 Q_Q(QDeclarative1GridView);
2479 if (mode < QDeclarative1GridView::Beginning || mode > QDeclarative1GridView::Contain)
2482 int idx = qMax(qMin(index, model->count()-1), 0);
2484 if (layoutScheduled)
2486 qreal pos = isRightToLeftTopToBottom() ? -position() - size() : position();
2487 FxGridItem1 *item = visibleItem(idx);
2489 if (flow == QDeclarative1GridView::LeftToRight)
2490 maxExtent = -q->maxYExtent();
2492 maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
2495 int itemPos = rowPosAt(idx);
2496 // save the currently visible items in case any of them end up visible again
2497 QList<FxGridItem1*> oldVisible = visibleItems;
2498 visibleItems.clear();
2499 visibleIndex = idx - idx % columns;
2500 if (flow == QDeclarative1GridView::LeftToRight)
2501 maxExtent = -q->maxYExtent();
2503 maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
2504 setPosition(qMin(qreal(itemPos), maxExtent));
2505 // now release the reference to all the old visible items.
2506 for (int i = 0; i < oldVisible.count(); ++i)
2507 releaseItem(oldVisible.at(i));
2508 item = visibleItem(idx);
2511 qreal itemPos = item->rowPos();
2513 case QDeclarative1GridView::Beginning:
2515 if (index < 0 && header) {
2516 pos -= flow == QDeclarative1GridView::LeftToRight
2517 ? header->item->height()
2518 : header->item->width();
2521 case QDeclarative1GridView::Center:
2522 pos = itemPos - (size() - rowSize())/2;
2524 case QDeclarative1GridView::End:
2525 pos = itemPos - size() + rowSize();
2526 if (index >= model->count() && footer) {
2527 pos += flow == QDeclarative1GridView::LeftToRight
2528 ? footer->item->height()
2529 : footer->item->width();
2532 case QDeclarative1GridView::Visible:
2533 if (itemPos > pos + size())
2534 pos = itemPos - size() + rowSize();
2535 else if (item->endRowPos() < pos)
2538 case QDeclarative1GridView::Contain:
2539 if (item->endRowPos() > pos + size())
2540 pos = itemPos - size() + rowSize();
2545 pos = qMin(pos, maxExtent);
2547 if (flow == QDeclarative1GridView::LeftToRight)
2548 minExtent = -q->minYExtent();
2550 minExtent = isRightToLeftTopToBottom() ? q->maxXExtent()-size() : -q->minXExtent();
2551 pos = qMax(pos, minExtent);
2552 moveReason = QDeclarative1GridViewPrivate::Other;
2560 \qmlmethod QtQuick1::GridView::positionViewAtIndex(int index, PositionMode mode)
2562 Positions the view such that the \a index is at the position specified by
2566 \o GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view.
2567 \o GridView.Center - position item in the center of the view.
2568 \o GridView.End - position item at bottom (or right for horizontal orientation) of the view.
2569 \o GridView.Visible - if any part of the item is visible then take no action, otherwise
2570 bring the item into view.
2571 \o GridView.Contain - ensure the entire item is visible. If the item is larger than
2572 the view the item is positioned at the top (or left for \c GridView.TopToBottom flow) of the view.
2575 If positioning the view at the index would cause empty space to be displayed at
2576 the beginning or end of the view, the view will be positioned at the boundary.
2578 It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
2579 at a particular index. This is unreliable since removing items from the start
2580 of the view does not cause all other items to be repositioned.
2581 The correct way to bring an item into view is with \c positionViewAtIndex.
2583 \bold Note: methods should only be called after the Component has completed. To position
2584 the view at startup, this method should be called by Component.onCompleted. For
2585 example, to position the view at the end:
2588 Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
2591 void QDeclarative1GridView::positionViewAtIndex(int index, int mode)
2593 Q_D(QDeclarative1GridView);
2594 if (!d->isValid() || index < 0 || index >= d->model->count())
2596 d->positionViewAtIndex(index, mode);
2600 \qmlmethod QtQuick1::GridView::positionViewAtBeginning()
2601 \qmlmethod QtQuick1::GridView::positionViewAtEnd()
2604 Positions the view at the beginning or end, taking into account any header or footer.
2606 It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
2607 at a particular index. This is unreliable since removing items from the start
2608 of the list does not cause all other items to be repositioned, and because
2609 the actual start of the view can vary based on the size of the delegates.
2611 \bold Note: methods should only be called after the Component has completed. To position
2612 the view at startup, this method should be called by Component.onCompleted. For
2613 example, to position the view at the end on startup:
2616 Component.onCompleted: positionViewAtEnd()
2619 void QDeclarative1GridView::positionViewAtBeginning()
2621 Q_D(QDeclarative1GridView);
2624 d->positionViewAtIndex(-1, Beginning);
2627 void QDeclarative1GridView::positionViewAtEnd()
2629 Q_D(QDeclarative1GridView);
2632 d->positionViewAtIndex(d->model->count(), End);
2636 \qmlmethod int QtQuick1::GridView::indexAt(int x, int y)
2638 Returns the index of the visible item containing the point \a x, \a y in content
2639 coordinates. If there is no item at the point specified, or the item is
2640 not visible -1 is returned.
2642 If the item is outside the visible area, -1 is returned, regardless of
2643 whether an item will exist at that point when scrolled into view.
2645 \bold Note: methods should only be called after the Component has completed.
2647 int QDeclarative1GridView::indexAt(qreal x, qreal y) const
2649 Q_D(const QDeclarative1GridView);
2650 for (int i = 0; i < d->visibleItems.count(); ++i) {
2651 const FxGridItem1 *listItem = d->visibleItems.at(i);
2652 if(listItem->contains(x, y))
2653 return listItem->index;
2659 void QDeclarative1GridView::componentComplete()
2661 Q_D(QDeclarative1GridView);
2662 QDeclarative1Flickable::componentComplete();
2668 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
2669 if (d->currentIndex < 0 && !d->currentIndexCleared)
2670 d->updateCurrent(0);
2672 d->updateCurrent(d->currentIndex);
2673 if (d->highlight && d->currentItem) {
2674 if (d->autoHighlight)
2675 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
2676 d->updateTrackedItem();
2678 d->moveReason = QDeclarative1GridViewPrivate::Other;
2683 void QDeclarative1GridView::trackedPositionChanged()
2685 Q_D(QDeclarative1GridView);
2686 if (!d->trackedItem || !d->currentItem)
2688 if (d->moveReason == QDeclarative1GridViewPrivate::SetIndex) {
2689 const qreal trackedPos = d->trackedItem->rowPos();
2691 qreal highlightStart;
2693 if (d->isRightToLeftTopToBottom()) {
2694 viewPos = -d->position()-d->size();
2695 highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
2696 highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
2698 viewPos = d->position();
2699 highlightStart = d->highlightRangeStart;
2700 highlightEnd = d->highlightRangeEnd;
2702 qreal pos = viewPos;
2703 if (d->haveHighlightRange) {
2704 if (d->highlightRange == StrictlyEnforceRange) {
2705 if (trackedPos > pos + highlightEnd - d->rowSize())
2706 pos = trackedPos - highlightEnd + d->rowSize();
2707 if (trackedPos < pos + highlightStart)
2708 pos = trackedPos - highlightStart;
2710 if (trackedPos < d->startPosition() + highlightStart) {
2711 pos = d->startPosition();
2712 } else if (d->trackedItem->endRowPos() > d->endPosition() - d->size() + highlightEnd) {
2713 pos = d->endPosition() - d->size() + 1;
2714 if (pos < d->startPosition())
2715 pos = d->startPosition();
2717 if (trackedPos > pos + highlightEnd - d->rowSize())
2718 pos = trackedPos - highlightEnd + d->rowSize();
2719 if (trackedPos < pos + highlightStart)
2720 pos = trackedPos - highlightStart;
2724 if (trackedPos < viewPos && d->currentItem->rowPos() < viewPos) {
2725 pos = qMax(trackedPos, d->currentItem->rowPos());
2726 } else if (d->trackedItem->endRowPos() >= viewPos + d->size()
2727 && d->currentItem->endRowPos() >= viewPos + d->size()) {
2728 if (d->trackedItem->endRowPos() <= d->currentItem->endRowPos()) {
2729 pos = d->trackedItem->endRowPos() - d->size() + 1;
2730 if (d->rowSize() > d->size())
2733 pos = d->currentItem->endRowPos() - d->size() + 1;
2734 if (d->rowSize() > d->size())
2735 pos = d->currentItem->rowPos();
2739 if (viewPos != pos) {
2741 d->calcVelocity = true;
2742 d->setPosition(pos);
2743 d->calcVelocity = false;
2748 void QDeclarative1GridView::itemsInserted(int modelIndex, int count)
2750 Q_D(QDeclarative1GridView);
2751 if (!isComponentComplete())
2754 int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
2756 int i = d->visibleItems.count() - 1;
2757 while (i > 0 && d->visibleItems.at(i)->index == -1)
2759 if (d->visibleItems.at(i)->index + 1 == modelIndex) {
2760 // Special case of appending an item to the model.
2761 index = d->visibleIndex + d->visibleItems.count();
2763 if (modelIndex <= d->visibleIndex) {
2764 // Insert before visible items
2765 d->visibleIndex += count;
2766 for (int i = 0; i < d->visibleItems.count(); ++i) {
2767 FxGridItem1 *listItem = d->visibleItems.at(i);
2768 if (listItem->index != -1 && listItem->index >= modelIndex)
2769 listItem->index += count;
2772 if (d->currentIndex >= modelIndex) {
2773 // adjust current item index
2774 d->currentIndex += count;
2776 d->currentItem->index = d->currentIndex;
2777 emit currentIndexChanged();
2779 d->scheduleLayout();
2780 d->itemCount += count;
2781 emit countChanged();
2786 int insertCount = count;
2787 if (index < d->visibleIndex && d->visibleItems.count()) {
2788 insertCount -= d->visibleIndex - index;
2789 index = d->visibleIndex;
2790 modelIndex = d->visibleIndex;
2793 qreal tempPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size()+d->width()+1 : d->position();
2794 int to = d->buffer+tempPos+d->size()-1;
2797 if (d->visibleItems.count()) {
2798 index -= d->visibleIndex;
2799 if (index < d->visibleItems.count()) {
2800 colPos = d->visibleItems.at(index)->colPos();
2801 rowPos = d->visibleItems.at(index)->rowPos();
2803 // appending items to visible list
2804 colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
2805 rowPos = d->visibleItems.at(index-1)->rowPos();
2806 if (colPos > d->colSize() * (d->columns-1)) {
2808 rowPos += d->rowSize();
2811 } else if (d->itemCount == 0 && d->header) {
2812 rowPos = d->headerSize();
2815 // Update the indexes of the following visible items.
2816 for (int i = 0; i < d->visibleItems.count(); ++i) {
2817 FxGridItem1 *listItem = d->visibleItems.at(i);
2818 if (listItem->index != -1 && listItem->index >= modelIndex)
2819 listItem->index += count;
2822 bool addedVisible = false;
2823 QList<FxGridItem1*> added;
2825 while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) {
2826 if (!addedVisible) {
2827 d->scheduleLayout();
2828 addedVisible = true;
2830 FxGridItem1 *item = d->createItem(modelIndex + i);
2831 d->visibleItems.insert(index, item);
2832 item->setPosition(colPos, rowPos);
2834 colPos += d->colSize();
2835 if (colPos > d->colSize() * (d->columns-1)) {
2837 rowPos += d->rowSize();
2842 if (i < insertCount) {
2843 // We didn't insert all our new items, which means anything
2844 // beyond the current index is not visible - remove it.
2845 while (d->visibleItems.count() > index) {
2846 d->releaseItem(d->visibleItems.takeLast());
2850 // update visibleIndex
2851 d->visibleIndex = 0;
2852 for (QList<FxGridItem1*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
2853 if ((*it)->index != -1) {
2854 d->visibleIndex = (*it)->index;
2859 if (d->itemCount && d->currentIndex >= modelIndex) {
2860 // adjust current item index
2861 d->currentIndex += count;
2862 if (d->currentItem) {
2863 d->currentItem->index = d->currentIndex;
2864 d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
2866 emit currentIndexChanged();
2867 } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
2871 // everything is in order now - emit add() signal
2872 for (int j = 0; j < added.count(); ++j)
2873 added.at(j)->attached->emitAdd();
2875 d->itemCount += count;
2876 emit countChanged();
2879 void QDeclarative1GridView::itemsRemoved(int modelIndex, int count)
2881 Q_D(QDeclarative1GridView);
2882 if (!isComponentComplete())
2885 d->itemCount -= count;
2886 bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
2887 bool removedVisible = false;
2889 // Remove the items from the visible list, skipping anything already marked for removal
2890 QList<FxGridItem1*>::Iterator it = d->visibleItems.begin();
2891 while (it != d->visibleItems.end()) {
2892 FxGridItem1 *item = *it;
2893 if (item->index == -1 || item->index < modelIndex) {
2894 // already removed, or before removed items
2895 if (item->index < modelIndex && !removedVisible) {
2896 d->scheduleLayout();
2897 removedVisible = true;
2900 } else if (item->index >= modelIndex + count) {
2901 // after removed items
2902 item->index -= count;
2906 if (!removedVisible) {
2907 d->scheduleLayout();
2908 removedVisible = true;
2910 item->attached->emitRemove();
2911 if (item->attached->delayRemove()) {
2913 connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
2916 it = d->visibleItems.erase(it);
2917 d->releaseItem(item);
2922 // update visibleIndex
2923 d->visibleIndex = 0;
2924 for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
2925 if ((*it)->index != -1) {
2926 d->visibleIndex = (*it)->index;
2932 if (d->currentIndex >= modelIndex + count) {
2933 d->currentIndex -= count;
2935 d->currentItem->index -= count;
2936 emit currentIndexChanged();
2937 } else if (currentRemoved) {
2938 // current item has been removed.
2939 d->releaseItem(d->currentItem);
2941 d->currentIndex = -1;
2943 d->updateCurrent(qMin(modelIndex, d->itemCount-1));
2945 emit currentIndexChanged();
2948 if (removedVisible && d->visibleItems.isEmpty()) {
2949 d->timeline.clear();
2950 if (d->itemCount == 0) {
2958 emit countChanged();
2961 void QDeclarative1GridView::destroyRemoved()
2963 Q_D(QDeclarative1GridView);
2964 for (QList<FxGridItem1*>::Iterator it = d->visibleItems.begin();
2965 it != d->visibleItems.end();) {
2966 FxGridItem1 *listItem = *it;
2967 if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
2968 d->releaseItem(listItem);
2969 it = d->visibleItems.erase(it);
2975 // Correct the positioning of the items
2979 void QDeclarative1GridView::itemsMoved(int from, int to, int count)
2981 Q_D(QDeclarative1GridView);
2982 if (!isComponentComplete())
2984 QHash<int,FxGridItem1*> moved;
2986 FxGridItem1 *firstItem = d->firstVisibleItem();
2988 QList<FxGridItem1*>::Iterator it = d->visibleItems.begin();
2989 while (it != d->visibleItems.end()) {
2990 FxGridItem1 *item = *it;
2991 if (item->index >= from && item->index < from + count) {
2992 // take the items that are moving
2993 item->index += (to-from);
2994 moved.insert(item->index, item);
2995 it = d->visibleItems.erase(it);
2997 if (item->index > from && item->index != -1) {
2998 // move everything after the moved items.
2999 item->index -= count;
3000 if (item->index < d->visibleIndex)
3001 d->visibleIndex = item->index;
3007 int remaining = count;
3008 int endIndex = d->visibleIndex;
3009 it = d->visibleItems.begin();
3010 while (it != d->visibleItems.end()) {
3011 FxGridItem1 *item = *it;
3012 if (remaining && item->index >= to && item->index < to + count) {
3013 // place items in the target position, reusing any existing items
3014 FxGridItem1 *movedItem = moved.take(item->index);
3016 movedItem = d->createItem(item->index);
3017 it = d->visibleItems.insert(it, movedItem);
3018 if (it == d->visibleItems.begin() && firstItem)
3019 movedItem->setPosition(firstItem->colPos(), firstItem->rowPos());
3023 if (item->index != -1) {
3024 if (item->index >= to) {
3025 // update everything after the moved items.
3026 item->index += count;
3028 endIndex = item->index;
3034 // If we have moved items to the end of the visible items
3035 // then add any existing moved items that we have
3036 while (FxGridItem1 *item = moved.take(endIndex+1)) {
3037 d->visibleItems.append(item);
3041 // update visibleIndex
3042 for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
3043 if ((*it)->index != -1) {
3044 d->visibleIndex = (*it)->index;
3049 // Fix current index
3050 if (d->currentIndex >= 0 && d->currentItem) {
3051 int oldCurrent = d->currentIndex;
3052 d->currentIndex = d->model->indexOf(d->currentItem->item, this);
3053 if (oldCurrent != d->currentIndex) {
3054 d->currentItem->index = d->currentIndex;
3055 emit currentIndexChanged();
3059 // Whatever moved items remain are no longer visible items.
3060 while (moved.count()) {
3061 int idx = moved.begin().key();
3062 FxGridItem1 *item = moved.take(idx);
3063 if (d->currentItem && item->item == d->currentItem->item)
3064 item->setPosition(d->colPosAt(idx), d->rowPosAt(idx));
3065 d->releaseItem(item);
3071 void QDeclarative1GridView::modelReset()
3073 Q_D(QDeclarative1GridView);
3076 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
3077 d->updateCurrent(d->currentIndex);
3078 if (d->highlight && d->currentItem) {
3079 if (d->autoHighlight)
3080 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
3081 d->updateTrackedItem();
3083 d->moveReason = QDeclarative1GridViewPrivate::Other;
3085 emit countChanged();
3088 void QDeclarative1GridView::createdItem(int index, QDeclarativeItem *item)
3090 Q_D(QDeclarative1GridView);
3091 if (d->requestedIndex != index) {
3092 item->setParentItem(this);
3093 d->unrequestedItems.insert(item, index);
3094 if (d->flow == QDeclarative1GridView::LeftToRight) {
3095 item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
3097 item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
3102 void QDeclarative1GridView::destroyingItem(QDeclarativeItem *item)
3104 Q_D(QDeclarative1GridView);
3105 d->unrequestedItems.remove(item);
3108 void QDeclarative1GridView::animStopped()
3110 Q_D(QDeclarative1GridView);
3111 d->bufferMode = QDeclarative1GridViewPrivate::NoBuffer;
3112 if (d->haveHighlightRange && d->highlightRange == QDeclarative1GridView::StrictlyEnforceRange)
3113 d->updateHighlight();
3116 void QDeclarative1GridView::refill()
3118 Q_D(QDeclarative1GridView);
3119 if (d->isRightToLeftTopToBottom())
3120 d->refill(-d->position()-d->size()+1, -d->position());
3122 d->refill(d->position(), d->position()+d->size()-1);
3126 QDeclarative1GridViewAttached *QDeclarative1GridView::qmlAttachedProperties(QObject *obj)
3128 return new QDeclarative1GridViewAttached(obj);