1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: http://www.qt-project.org/
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>
54 #include "qplatformdefs.h"
58 #ifndef QML_FLICK_SNAPONETHRESHOLD
59 #define QML_FLICK_SNAPONETHRESHOLD 30
62 //----------------------------------------------------------------------------
67 FxGridItem1(QDeclarativeItem *i, QDeclarative1GridView *v) : item(i), view(v) {
68 attached = static_cast<QDeclarative1GridViewAttached*>(qmlAttachedPropertiesObject<QDeclarative1GridView>(item));
70 attached->setView(view);
74 qreal rowPos() const {
76 if (view->flow() == QDeclarative1GridView::LeftToRight) {
79 if (view->effectiveLayoutDirection() == Qt::RightToLeft)
80 rowPos = -view->cellWidth()-item->x();
86 qreal colPos() const {
88 if (view->flow() == QDeclarative1GridView::LeftToRight) {
89 if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
90 int colSize = view->cellWidth();
91 int columns = view->width()/colSize;
92 colPos = colSize * (columns-1) - item->x();
103 qreal endRowPos() const {
104 if (view->flow() == QDeclarative1GridView::LeftToRight) {
105 return item->y() + view->cellHeight() - 1;
107 if (view->effectiveLayoutDirection() == Qt::RightToLeft)
108 return -item->x() - 1;
110 return item->x() + view->cellWidth() - 1;
113 void setPosition(qreal col, qreal row) {
114 if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
115 if (view->flow() == QDeclarative1GridView::LeftToRight) {
116 int columns = view->width()/view->cellWidth();
117 item->setPos(QPointF((view->cellWidth() * (columns-1) - col), row));
119 item->setPos(QPointF(-view->cellWidth()-row, col));
122 if (view->flow() == QDeclarative1GridView::LeftToRight)
123 item->setPos(QPointF(col, row));
125 item->setPos(QPointF(row, col));
129 bool contains(qreal x, qreal y) const {
130 return (x >= item->x() && x < item->x() + view->cellWidth() &&
131 y >= item->y() && y < item->y() + view->cellHeight());
134 QDeclarativeItem *item;
135 QDeclarative1GridView *view;
136 QDeclarative1GridViewAttached *attached;
140 //----------------------------------------------------------------------------
142 class QDeclarative1GridViewPrivate : public QDeclarative1FlickablePrivate
144 Q_DECLARE_PUBLIC(QDeclarative1GridView)
147 QDeclarative1GridViewPrivate()
148 : currentItem(0), layoutDirection(Qt::LeftToRight), flow(QDeclarative1GridView::LeftToRight)
149 , visibleIndex(0) , currentIndex(-1)
150 , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0)
151 , highlightRangeStart(0), highlightRangeEnd(0)
152 , highlightRangeStartValid(false), highlightRangeEndValid(false)
153 , highlightRange(QDeclarative1GridView::NoHighlightRange)
154 , highlightComponent(0), highlight(0), trackedItem(0)
155 , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
156 , highlightMoveDuration(150)
157 , footerComponent(0), footer(0), headerComponent(0), header(0)
158 , bufferMode(BufferBefore | BufferAfter), snapMode(QDeclarative1GridView::NoSnap)
159 , ownModel(false), wrap(false), autoHighlight(true)
160 , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
161 , deferredRelease(false), haveHighlightRange(false), currentIndexCleared(false) {}
165 FxGridItem1 *createItem(int modelIndex);
166 void releaseItem(FxGridItem1 *item);
167 void refill(qreal from, qreal to, bool doBuffer=false);
170 void scheduleLayout();
172 void updateUnrequestedIndexes();
173 void updateUnrequestedPositions();
174 void updateTrackedItem();
175 void createHighlight();
176 void updateHighlight();
177 void updateCurrent(int modelIndex);
180 void fixupPosition();
182 FxGridItem1 *visibleItem(int modelIndex) const {
183 if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
184 for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
185 FxGridItem1 *item = visibleItems.at(i);
186 if (item->index == modelIndex)
193 bool isRightToLeftTopToBottom() const {
194 Q_Q(const QDeclarative1GridView);
195 return flow == QDeclarative1GridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
199 Q_Q(QDeclarative1GridView);
200 if (q->isComponentComplete()) {
205 updateCurrent(currentIndex);
209 void mirrorChange() {
210 Q_Q(QDeclarative1GridView);
212 emit q->effectiveLayoutDirectionChanged();
215 qreal position() const {
216 Q_Q(const QDeclarative1GridView);
217 return flow == QDeclarative1GridView::LeftToRight ? q->contentY() : q->contentX();
219 void setPosition(qreal pos) {
220 Q_Q(QDeclarative1GridView);
221 if (flow == QDeclarative1GridView::LeftToRight) {
222 q->QDeclarative1Flickable::setContentY(pos);
223 q->QDeclarative1Flickable::setContentX(0);
225 if (q->effectiveLayoutDirection() == Qt::LeftToRight)
226 q->QDeclarative1Flickable::setContentX(pos);
228 q->QDeclarative1Flickable::setContentX(-pos-size());
229 q->QDeclarative1Flickable::setContentY(0);
233 Q_Q(const QDeclarative1GridView);
234 return flow == QDeclarative1GridView::LeftToRight ? q->height() : q->width();
236 qreal originPosition() const {
238 if (!visibleItems.isEmpty())
239 pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
243 qreal lastPosition() const {
245 if (model && model->count())
246 pos = rowPosAt(model->count() - 1) + rowSize();
250 qreal startPosition() const {
251 return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
254 qreal endPosition() const {
255 return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
259 bool isValid() const {
260 return model && model->count() && model->isValid();
263 int rowSize() const {
264 return flow == QDeclarative1GridView::LeftToRight ? cellHeight : cellWidth;
266 int colSize() const {
267 return flow == QDeclarative1GridView::LeftToRight ? cellWidth : cellHeight;
270 qreal colPosAt(int modelIndex) const {
271 if (FxGridItem1 *item = visibleItem(modelIndex))
272 return item->colPos();
273 if (!visibleItems.isEmpty()) {
274 if (modelIndex < visibleIndex) {
275 int count = (visibleIndex - modelIndex) % columns;
276 int col = visibleItems.first()->colPos() / colSize();
277 col = (columns - count + col) % columns;
278 return col * colSize();
280 int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
281 return visibleItems.last()->colPos() - count * colSize();
284 return (modelIndex % columns) * colSize();
288 qreal rowPosAt(int modelIndex) const {
289 if (FxGridItem1 *item = visibleItem(modelIndex))
290 return item->rowPos();
291 if (!visibleItems.isEmpty()) {
292 if (modelIndex < visibleIndex) {
293 int firstCol = visibleItems.first()->colPos() / colSize();
294 int col = visibleIndex - modelIndex + (columns - firstCol - 1);
295 int rows = col / columns;
296 return visibleItems.first()->rowPos() - rows * rowSize();
298 int count = modelIndex - visibleItems.last()->index;
299 int col = visibleItems.last()->colPos() + count * colSize();
300 int rows = col / (columns * colSize());
301 return visibleItems.last()->rowPos() + rows * rowSize();
304 qreal pos = (modelIndex / columns) * rowSize();
312 FxGridItem1 *firstVisibleItem() const {
313 const qreal pos = isRightToLeftTopToBottom() ? -position()-size() : position();
314 for (int i = 0; i < visibleItems.count(); ++i) {
315 FxGridItem1 *item = visibleItems.at(i);
316 if (item->index != -1 && item->endRowPos() > pos)
319 return visibleItems.count() ? visibleItems.first() : 0;
322 int lastVisibleIndex() const {
323 for (int i = 0; i < visibleItems.count(); ++i) {
324 FxGridItem1 *item = visibleItems.at(i);
325 if (item->index != -1)
331 // Map a model index to visibleItems list index.
332 // These may differ if removed items are still present in the visible list,
333 // e.g. doing a removal animation
334 int mapFromModel(int modelIndex) const {
335 if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
337 for (int i = 0; i < visibleItems.count(); ++i) {
338 FxGridItem1 *listItem = visibleItems.at(i);
339 if (listItem->index == modelIndex)
340 return i + visibleIndex;
341 if (listItem->index > modelIndex)
344 return -1; // Not in visibleList
347 qreal snapPosAt(qreal pos) const {
348 Q_Q(const QDeclarative1GridView);
350 if (!visibleItems.isEmpty()) {
351 qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
352 pos += highlightStart;
354 snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
355 snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
356 snapPos -= highlightStart;
359 if (isRightToLeftTopToBottom()) {
360 maxExtent = q->minXExtent();
361 minExtent = q->maxXExtent();
363 maxExtent = flow == QDeclarative1GridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
364 minExtent = flow == QDeclarative1GridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
366 if (snapPos > maxExtent)
368 if (snapPos < minExtent)
374 FxGridItem1 *snapItemAt(qreal pos) {
375 for (int i = 0; i < visibleItems.count(); ++i) {
376 FxGridItem1 *item = visibleItems[i];
377 if (item->index == -1)
379 qreal itemTop = item->rowPos();
380 if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
387 int index = currentIndex;
388 for (int i = 0; i < visibleItems.count(); ++i) {
389 FxGridItem1 *item = visibleItems[i];
390 if (item->index == -1)
392 qreal itemTop = item->rowPos();
393 if (itemTop >= highlight->rowPos()-rowSize()/2 && itemTop < highlight->rowPos()+rowSize()/2) {
395 if (item->colPos() >= highlight->colPos()-colSize()/2 && item->colPos() < highlight->colPos()+colSize()/2)
402 qreal headerSize() const {
406 return flow == QDeclarative1GridView::LeftToRight
407 ? header->item->height()
408 : header->item->width();
412 virtual void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
413 Q_Q(const QDeclarative1GridView);
414 QDeclarative1FlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
416 if (newGeometry.height() != oldGeometry.height()
417 || newGeometry.width() != oldGeometry.width()) {
418 if (q->isComponentComplete()) {
423 } else if ((header && header->item == item) || (footer && footer->item == item)) {
431 void positionViewAtIndex(int index, int mode);
432 virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
433 virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
434 QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity);
436 // for debugging only
437 void checkVisible() const {
439 for (int i = 0; i < visibleItems.count(); ++i) {
440 FxGridItem1 *listItem = visibleItems.at(i);
441 if (listItem->index == -1) {
443 } else if (listItem->index != visibleIndex + i - skip) {
444 for (int j = 0; j < visibleItems.count(); j++)
445 qDebug() << " index" << j << "item index" << visibleItems.at(j)->index;
446 qFatal("index %d %d %d", visibleIndex, i, listItem->index);
451 QDeclarativeGuard<QDeclarative1VisualModel> model;
452 QVariant modelVariant;
453 QList<FxGridItem1*> visibleItems;
454 QHash<QDeclarativeItem*,int> unrequestedItems;
455 FxGridItem1 *currentItem;
456 Qt::LayoutDirection layoutDirection;
457 QDeclarative1GridView::Flow flow;
465 qreal highlightRangeStart;
466 qreal highlightRangeEnd;
467 bool highlightRangeStartValid;
468 bool highlightRangeEndValid;
469 QDeclarative1GridView::HighlightRangeMode highlightRange;
470 QDeclarativeComponent *highlightComponent;
471 FxGridItem1 *highlight;
472 FxGridItem1 *trackedItem;
473 enum MovementReason { Other, SetIndex, Mouse };
474 MovementReason moveReason;
476 QSmoothedAnimation_1 *highlightXAnimator;
477 QSmoothedAnimation_1 *highlightYAnimator;
478 int highlightMoveDuration;
479 QDeclarativeComponent *footerComponent;
481 QDeclarativeComponent *headerComponent;
483 enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
485 QDeclarative1GridView::SnapMode snapMode;
489 bool autoHighlight : 1;
490 bool fixCurrentVisibility : 1;
491 bool lazyRelease : 1;
492 bool layoutScheduled : 1;
493 bool deferredRelease : 1;
494 bool haveHighlightRange : 1;
495 bool currentIndexCleared : 1;
498 void QDeclarative1GridViewPrivate::init()
500 Q_Q(QDeclarative1GridView);
501 QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
502 q->setFlag(QGraphicsItem::ItemIsFocusScope);
503 q->setFlickableDirection(QDeclarative1Flickable::VerticalFlick);
504 addItemChangeListener(this, Geometry);
507 void QDeclarative1GridViewPrivate::clear()
509 for (int i = 0; i < visibleItems.count(); ++i)
510 releaseItem(visibleItems.at(i));
511 visibleItems.clear();
513 releaseItem(currentItem);
520 FxGridItem1 *QDeclarative1GridViewPrivate::createItem(int modelIndex)
522 Q_Q(QDeclarative1GridView);
524 requestedIndex = modelIndex;
525 FxGridItem1 *listItem = 0;
526 if (QDeclarativeItem *item = model->item(modelIndex, false)) {
527 listItem = new FxGridItem1(item, q);
528 listItem->index = modelIndex;
529 if (model->completePending()) {
531 listItem->item->setZValue(1);
532 listItem->item->setParentItem(q->contentItem());
533 model->completeItem();
535 listItem->item->setParentItem(q->contentItem());
537 unrequestedItems.remove(listItem->item);
544 void QDeclarative1GridViewPrivate::releaseItem(FxGridItem1 *item)
546 Q_Q(QDeclarative1GridView);
549 if (trackedItem == item) {
550 QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
551 QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
554 if (model->release(item->item) == 0) {
555 // item was not destroyed, and we no longer reference it.
556 unrequestedItems.insert(item->item, model->indexOf(item->item, q));
561 void QDeclarative1GridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
563 Q_Q(QDeclarative1GridView);
564 if (!isValid() || !q->isComponentComplete())
566 itemCount = model->count();
567 qreal bufferFrom = from - buffer;
568 qreal bufferTo = to + buffer;
569 qreal fillFrom = from;
571 if (doBuffer && (bufferMode & BufferAfter))
573 if (doBuffer && (bufferMode & BufferBefore))
574 fillFrom = bufferFrom;
576 bool changed = false;
578 int colPos = colPosAt(visibleIndex);
579 int rowPos = rowPosAt(visibleIndex);
580 int modelIndex = visibleIndex;
581 if (visibleItems.count()) {
582 rowPos = visibleItems.last()->rowPos();
583 colPos = visibleItems.last()->colPos() + colSize();
584 if (colPos > colSize() * (columns-1)) {
588 int i = visibleItems.count() - 1;
589 while (i > 0 && visibleItems.at(i)->index == -1)
591 modelIndex = visibleItems.at(i)->index + 1;
594 if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
595 || fillTo < rowPosAt(visibleIndex) - rowSize())) {
596 // We've jumped more than a page. Estimate which items are now
597 // visible and fill from there.
598 int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
599 for (int i = 0; i < visibleItems.count(); ++i)
600 releaseItem(visibleItems.at(i));
601 visibleItems.clear();
603 if (modelIndex >= model->count())
604 modelIndex = model->count() - 1;
605 else if (modelIndex < 0)
607 modelIndex = modelIndex / columns * columns;
608 visibleIndex = modelIndex;
609 colPos = colPosAt(visibleIndex);
610 rowPos = rowPosAt(visibleIndex);
613 int colNum = colPos / colSize();
615 FxGridItem1 *item = 0;
617 // Item creation and release is staggered in order to avoid
618 // creating/releasing multiple items in one frame
619 // while flicking (as much as possible).
620 while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
621 // qDebug() << "refill: append item" << modelIndex;
622 if (!(item = createItem(modelIndex)))
624 item->setPosition(colPos, rowPos);
625 visibleItems.append(item);
628 if (colPos > colSize() * (columns-1)) {
635 if (doBuffer) // never buffer more than one item per frame
639 if (visibleItems.count()) {
640 rowPos = visibleItems.first()->rowPos();
641 colPos = visibleItems.first()->colPos() - colSize();
643 colPos = colSize() * (columns - 1);
647 colNum = colPos / colSize();
648 while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
649 // qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
650 if (!(item = createItem(visibleIndex-1)))
653 item->setPosition(colPos, rowPos);
654 visibleItems.prepend(item);
658 colPos = colSize() * (columns - 1);
663 if (doBuffer) // never buffer more than one item per frame
667 if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
668 while (visibleItems.count() > 1
669 && (item = visibleItems.first())
670 && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
671 if (item->attached->delayRemove())
673 // qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
674 if (item->index != -1)
676 visibleItems.removeFirst();
680 while (visibleItems.count() > 1
681 && (item = visibleItems.last())
682 && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
683 if (item->attached->delayRemove())
685 // qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
686 visibleItems.removeLast();
690 deferredRelease = false;
692 deferredRelease = true;
699 if (flow == QDeclarative1GridView::LeftToRight)
700 q->setContentHeight(endPosition() - startPosition());
702 q->setContentWidth(endPosition() - startPosition());
703 } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
704 refill(from, to, true);
709 void QDeclarative1GridViewPrivate::updateGrid()
711 Q_Q(QDeclarative1GridView);
713 columns = (int)qMax((flow == QDeclarative1GridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
715 if (flow == QDeclarative1GridView::LeftToRight)
716 q->setContentHeight(endPosition() - startPosition());
718 q->setContentWidth(lastPosition() - originPosition());
722 void QDeclarative1GridViewPrivate::scheduleLayout()
724 Q_Q(QDeclarative1GridView);
725 if (!layoutScheduled) {
726 layoutScheduled = true;
727 QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority);
731 void QDeclarative1GridViewPrivate::layout()
733 Q_Q(QDeclarative1GridView);
734 layoutScheduled = false;
735 if (!isValid() && !visibleItems.count()) {
739 if (visibleItems.count()) {
740 qreal rowPos = visibleItems.first()->rowPos();
741 qreal colPos = visibleItems.first()->colPos();
742 int col = visibleIndex % columns;
743 if (colPos != col * colSize()) {
744 colPos = col * colSize();
745 visibleItems.first()->setPosition(colPos, rowPos);
747 for (int i = 1; i < visibleItems.count(); ++i) {
748 FxGridItem1 *item = visibleItems.at(i);
750 if (colPos > colSize() * (columns-1)) {
754 item->setPosition(colPos, rowPos);
764 if (flow == QDeclarative1GridView::LeftToRight) {
765 q->setContentHeight(endPosition() - startPosition());
768 q->setContentWidth(endPosition() - startPosition());
771 updateUnrequestedPositions();
774 void QDeclarative1GridViewPrivate::updateUnrequestedIndexes()
776 Q_Q(QDeclarative1GridView);
777 QHash<QDeclarativeItem*,int>::iterator it;
778 for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
779 *it = model->indexOf(it.key(), q);
782 void QDeclarative1GridViewPrivate::updateUnrequestedPositions()
784 QHash<QDeclarativeItem*,int>::const_iterator it;
785 for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
786 QDeclarativeItem *item = it.key();
787 if (flow == QDeclarative1GridView::LeftToRight) {
788 item->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
790 if (isRightToLeftTopToBottom())
791 item->setPos(QPointF(-rowPosAt(*it)-item->width(), colPosAt(*it)));
793 item->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
798 void QDeclarative1GridViewPrivate::updateTrackedItem()
800 Q_Q(QDeclarative1GridView);
801 FxGridItem1 *item = currentItem;
805 if (trackedItem && item != trackedItem) {
806 QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
807 QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
811 if (!trackedItem && item) {
813 QObject::connect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
814 QObject::connect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
817 q->trackedPositionChanged();
820 void QDeclarative1GridViewPrivate::createHighlight()
822 Q_Q(QDeclarative1GridView);
823 bool changed = false;
825 if (trackedItem == highlight)
827 if (highlight->item->scene())
828 highlight->item->scene()->removeItem(highlight->item);
829 highlight->item->deleteLater();
832 delete highlightXAnimator;
833 delete highlightYAnimator;
834 highlightXAnimator = 0;
835 highlightYAnimator = 0;
840 QDeclarativeItem *item = 0;
841 if (highlightComponent) {
842 QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
843 QObject *nobj = highlightComponent->create(highlightContext);
845 QDeclarative_setParent_noEvent(highlightContext, nobj);
846 item = qobject_cast<QDeclarativeItem *>(nobj);
850 delete highlightContext;
853 item = new QDeclarativeItem;
854 QDeclarative_setParent_noEvent(item, q->contentItem());
855 item->setParentItem(q->contentItem());
858 QDeclarative_setParent_noEvent(item, q->contentItem());
859 item->setParentItem(q->contentItem());
860 highlight = new FxGridItem1(item, q);
861 if (currentItem && autoHighlight)
862 highlight->setPosition(currentItem->colPos(), currentItem->rowPos());
863 highlightXAnimator = new QSmoothedAnimation_1(q);
864 highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
865 highlightXAnimator->userDuration = highlightMoveDuration;
866 highlightYAnimator = new QSmoothedAnimation_1(q);
867 highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y"));
868 highlightYAnimator->userDuration = highlightMoveDuration;
870 highlightXAnimator->restart();
871 highlightYAnimator->restart();
877 emit q->highlightItemChanged();
880 void QDeclarative1GridViewPrivate::updateHighlight()
882 if ((!currentItem && highlight) || (currentItem && !highlight))
884 if (currentItem && autoHighlight && highlight && !hData.moving && !vData.moving) {
885 // auto-update highlight
886 highlightXAnimator->to = currentItem->item->x();
887 highlightYAnimator->to = currentItem->item->y();
888 highlight->item->setWidth(currentItem->item->width());
889 highlight->item->setHeight(currentItem->item->height());
890 highlightXAnimator->restart();
891 highlightYAnimator->restart();
896 void QDeclarative1GridViewPrivate::updateCurrent(int modelIndex)
898 Q_Q(QDeclarative1GridView);
899 if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
901 currentItem->attached->setIsCurrentItem(false);
902 releaseItem(currentItem);
904 currentIndex = modelIndex;
905 emit q->currentIndexChanged();
907 } else if (currentIndex != modelIndex) {
908 currentIndex = modelIndex;
909 emit q->currentIndexChanged();
914 if (currentItem && currentIndex == modelIndex) {
919 FxGridItem1 *oldCurrentItem = currentItem;
920 currentIndex = modelIndex;
921 currentItem = createItem(modelIndex);
922 fixCurrentVisibility = true;
923 if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
924 oldCurrentItem->attached->setIsCurrentItem(false);
926 currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
927 currentItem->item->setFocus(true);
928 currentItem->attached->setIsCurrentItem(true);
931 emit q->currentIndexChanged();
932 releaseItem(oldCurrentItem);
935 void QDeclarative1GridViewPrivate::updateFooter()
937 Q_Q(QDeclarative1GridView);
938 if (!footer && footerComponent) {
939 QDeclarativeItem *item = 0;
940 QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
941 QObject *nobj = footerComponent->create(context);
943 QDeclarative_setParent_noEvent(context, nobj);
944 item = qobject_cast<QDeclarativeItem *>(nobj);
951 QDeclarative_setParent_noEvent(item, q->contentItem());
952 item->setParentItem(q->contentItem());
954 QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
955 itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
956 footer = new FxGridItem1(item, q);
962 if (isRightToLeftTopToBottom()) {
963 rowOffset = footer->item->width()-cellWidth;
966 if (q->effectiveLayoutDirection() == Qt::RightToLeft)
967 colOffset = footer->item->width()-cellWidth;
969 if (visibleItems.count()) {
970 qreal endPos = lastPosition();
971 if (lastVisibleIndex() == model->count()-1) {
972 footer->setPosition(colOffset, endPos + rowOffset);
974 qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
975 if (endPos <= visiblePos || footer->endRowPos() < endPos + rowOffset)
976 footer->setPosition(colOffset, endPos + rowOffset);
981 endPos += flow == QDeclarative1GridView::LeftToRight ? header->item->height() : header->item->width();
983 footer->setPosition(colOffset, endPos);
988 void QDeclarative1GridViewPrivate::updateHeader()
990 Q_Q(QDeclarative1GridView);
991 if (!header && headerComponent) {
992 QDeclarativeItem *item = 0;
993 QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
994 QObject *nobj = headerComponent->create(context);
996 QDeclarative_setParent_noEvent(context, nobj);
997 item = qobject_cast<QDeclarativeItem *>(nobj);
1004 QDeclarative_setParent_noEvent(item, q->contentItem());
1005 item->setParentItem(q->contentItem());
1007 QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
1008 itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
1009 header = new FxGridItem1(item, q);
1013 qreal colOffset = 0;
1015 if (isRightToLeftTopToBottom()) {
1016 rowOffset = -cellWidth;
1018 rowOffset = -headerSize();
1019 if (q->effectiveLayoutDirection() == Qt::RightToLeft)
1020 colOffset = header->item->width()-cellWidth;
1022 if (visibleItems.count()) {
1023 qreal startPos = originPosition();
1024 if (visibleIndex == 0) {
1025 header->setPosition(colOffset, startPos + rowOffset);
1027 qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position();
1028 qreal headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
1029 if (tempPos <= startPos || headerPos > startPos + rowOffset)
1030 header->setPosition(colOffset, startPos + rowOffset);
1033 header->setPosition(colOffset, 0);
1038 void QDeclarative1GridViewPrivate::fixupPosition()
1041 if (flow == QDeclarative1GridView::LeftToRight)
1047 void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
1049 if ((flow == QDeclarative1GridView::TopToBottom && &data == &vData)
1050 || (flow == QDeclarative1GridView::LeftToRight && &data == &hData))
1053 fixupMode = moveReason == Mouse ? fixupMode : Immediate;
1055 qreal highlightStart;
1058 if (isRightToLeftTopToBottom()) {
1059 // Handle Right-To-Left exceptions
1060 viewPos = -position()-size();
1061 highlightStart = highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
1062 highlightEnd = highlightRangeEndValid ? size()-highlightRangeStart : highlightRangeEnd;
1064 viewPos = position();
1065 highlightStart = highlightRangeStart;
1066 highlightEnd = highlightRangeEnd;
1069 bool strictHighlightRange = haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange;
1071 if (snapMode != QDeclarative1GridView::NoSnap) {
1072 qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position();
1073 if (snapMode == QDeclarative1GridView::SnapOneRow && moveReason == Mouse) {
1074 // if we've been dragged < rowSize()/2 then bias towards the next row
1075 qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
1077 if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < rowSize()/2)
1079 else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -rowSize()/2)
1080 bias = -rowSize()/2;
1081 if (isRightToLeftTopToBottom())
1083 tempPosition -= bias;
1085 FxGridItem1 *topItem = snapItemAt(tempPosition+highlightStart);
1086 if (!topItem && strictHighlightRange && currentItem) {
1087 // StrictlyEnforceRange always keeps an item in range
1089 topItem = currentItem;
1091 FxGridItem1 *bottomItem = snapItemAt(tempPosition+highlightEnd);
1092 if (!bottomItem && strictHighlightRange && currentItem) {
1093 // StrictlyEnforceRange always keeps an item in range
1095 bottomItem = currentItem;
1098 bool isInBounds = -position() > maxExtent && -position() <= minExtent;
1099 if (topItem && (isInBounds || strictHighlightRange)) {
1100 if (topItem->index == 0 && header && tempPosition+highlightStart < header->rowPos()+headerSize()/2 && !strictHighlightRange) {
1101 pos = isRightToLeftTopToBottom() ? - header->rowPos() + highlightStart - size() : header->rowPos() - highlightStart;
1103 if (isRightToLeftTopToBottom())
1104 pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
1106 pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
1108 } else if (bottomItem && isInBounds) {
1109 if (isRightToLeftTopToBottom())
1110 pos = qMax(qMin(-bottomItem->rowPos() + highlightEnd - size(), -maxExtent), -minExtent);
1112 pos = qMax(qMin(bottomItem->rowPos() - highlightEnd, -maxExtent), -minExtent);
1114 QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
1117 qreal dist = qAbs(data.move + pos);
1119 timeline.reset(data.move);
1120 if (fixupMode != Immediate) {
1121 timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
1122 data.fixingUp = true;
1124 timeline.set(data.move, -pos);
1126 vTime = timeline.time();
1128 } else if (haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) {
1131 qreal pos = currentItem->rowPos();
1132 if (viewPos < pos + rowSize() - highlightEnd)
1133 viewPos = pos + rowSize() - highlightEnd;
1134 if (viewPos > pos - highlightStart)
1135 viewPos = pos - highlightStart;
1136 if (isRightToLeftTopToBottom())
1137 viewPos = -viewPos-size();
1138 timeline.reset(data.move);
1139 if (viewPos != position()) {
1140 if (fixupMode != Immediate) {
1141 timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
1142 data.fixingUp = true;
1144 timeline.set(data.move, -viewPos);
1147 vTime = timeline.time();
1150 QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
1152 data.inOvershoot = false;
1156 void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
1157 QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity)
1159 Q_Q(QDeclarative1GridView);
1160 data.fixingUp = false;
1162 if ((!haveHighlightRange || highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
1163 && snapMode == QDeclarative1GridView::NoSnap) {
1164 QDeclarative1FlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
1167 qreal maxDistance = 0;
1168 qreal dataValue = isRightToLeftTopToBottom() ? -data.move.value()+size() : data.move.value();
1169 // -ve velocity means list is moving up/left
1171 if (data.move.value() < minExtent) {
1172 if (snapMode == QDeclarative1GridView::SnapOneRow) {
1173 // if we've been dragged < averageSize/2 then bias towards the next item
1174 qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
1175 qreal bias = dist < rowSize()/2 ? rowSize()/2 : 0;
1176 if (isRightToLeftTopToBottom())
1178 data.flickTarget = -snapPosAt(-dataValue - bias);
1179 maxDistance = qAbs(data.flickTarget - data.move.value());
1180 velocity = maxVelocity;
1182 maxDistance = qAbs(minExtent - data.move.value());
1185 if (snapMode == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
1186 data.flickTarget = minExtent;
1188 if (data.move.value() > maxExtent) {
1189 if (snapMode == QDeclarative1GridView::SnapOneRow) {
1190 // if we've been dragged < averageSize/2 then bias towards the next item
1191 qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
1192 qreal bias = -dist < rowSize()/2 ? rowSize()/2 : 0;
1193 if (isRightToLeftTopToBottom())
1195 data.flickTarget = -snapPosAt(-dataValue + bias);
1196 maxDistance = qAbs(data.flickTarget - data.move.value());
1197 velocity = -maxVelocity;
1199 maxDistance = qAbs(maxExtent - data.move.value());
1202 if (snapMode == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
1203 data.flickTarget = maxExtent;
1206 bool overShoot = boundsBehavior == QDeclarative1Flickable::DragAndOvershootBounds;
1208 if (maxDistance > 0 || overShoot) {
1209 // This mode requires the grid to stop exactly on a row boundary.
1211 if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
1217 qreal accel = deceleration;
1219 qreal overshootDist = 0.0;
1220 if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarative1GridView::SnapOneRow) {
1221 // + rowSize()/4 to encourage moving at least one item in the flick direction
1222 qreal dist = v2 / (accel * 2.0) + rowSize()/4;
1223 dist = qMin(dist, maxDistance);
1226 if (snapMode != QDeclarative1GridView::SnapOneRow) {
1227 qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist;
1228 data.flickTarget = -snapPosAt(-dataValue + distTemp);
1230 data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget;
1232 if (data.flickTarget >= minExtent) {
1233 overshootDist = overShootDistance(vSize);
1234 data.flickTarget += overshootDist;
1235 } else if (data.flickTarget <= maxExtent) {
1236 overshootDist = overShootDistance(vSize);
1237 data.flickTarget -= overshootDist;
1240 qreal adjDist = -data.flickTarget + data.move.value();
1241 if (qAbs(adjDist) > qAbs(dist)) {
1242 // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
1243 qreal adjv2 = accel * 2.0f * qAbs(adjDist);
1252 accel = v2 / (2.0f * qAbs(dist));
1254 data.flickTarget = velocity > 0 ? minExtent : maxExtent;
1255 overshootDist = overShoot ? overShootDistance(vSize) : 0;
1257 timeline.reset(data.move);
1258 timeline.accel(data.move, v, accel, maxDistance + overshootDist);
1259 timeline.callback(QDeclarative1TimeLineCallback(&data.move, fixupCallback, this));
1260 if (!hData.flicking && q->xflick()) {
1261 hData.flicking = true;
1262 emit q->flickingChanged();
1263 emit q->flickingHorizontallyChanged();
1264 emit q->flickStarted();
1266 if (!vData.flicking && q->yflick()) {
1267 vData.flicking = true;
1268 emit q->flickingChanged();
1269 emit q->flickingVerticallyChanged();
1270 emit q->flickStarted();
1273 timeline.reset(data.move);
1274 fixup(data, minExtent, maxExtent);
1279 //----------------------------------------------------------------------------
1282 \qmlclass GridView QDeclarative1GridView
1283 \inqmlmodule QtQuick 1
1285 \ingroup qml-view-elements
1288 \brief The GridView item provides a grid view of items provided by a model.
1290 A GridView displays data from models created from built-in QML elements like ListModel
1291 and XmlListModel, or custom model classes defined in C++ that inherit from
1294 A GridView has a \l model, which defines the data to be displayed, and
1295 a \l delegate, which defines how the data should be displayed. Items in a
1296 GridView are laid out horizontally or vertically. Grid views are inherently flickable
1297 as GridView inherits from \l Flickable.
1299 \section1 Example Usage
1301 The following example shows the definition of a simple list model defined
1302 in a file called \c ContactModel.qml:
1304 \snippet doc/src/snippets/qtquick1/gridview/ContactModel.qml 0
1306 \div {class="float-right"}
1307 \inlineimage gridview-simple.png
1310 This model can be referenced as \c ContactModel in other QML files. See \l{QML Modules}
1311 for more information about creating reusable components like this.
1313 Another component can display this model data in a GridView, as in the following
1314 example, which creates a \c ContactModel component for its model, and a \l Column element
1315 (containing \l Image and \l Text elements) for its delegate.
1318 \snippet doc/src/snippets/qtquick1/gridview/gridview.qml import
1320 \snippet doc/src/snippets/qtquick1/gridview/gridview.qml classdocs simple
1322 \div {class="float-right"}
1323 \inlineimage gridview-highlight.png
1326 The view will create a new delegate for each item in the model. Note that the delegate
1327 is able to access the model's \c name and \c portrait data directly.
1329 An improved grid view is shown below. The delegate is visually improved and is moved
1330 into a separate \c contactDelegate component.
1333 \snippet doc/src/snippets/qtquick1/gridview/gridview.qml classdocs advanced
1335 The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
1336 and \c focus is set to \c true to enable keyboard navigation for the grid view.
1337 The grid view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
1339 Delegates are instantiated as needed and may be destroyed at any time.
1340 State should \e never be stored in a delegate.
1342 GridView attaches a number of properties to the root item of the delegate, for example
1343 \c {GridView.isCurrentItem}. In the following example, the root delegate item can access
1344 this attached property directly as \c GridView.isCurrentItem, while the child
1345 \c contactInfo object must refer to this property as \c wrapper.GridView.isCurrentItem.
1347 \snippet doc/src/snippets/qtquick1/gridview/gridview.qml isCurrentItem
1349 \note Views do not set the \l{Item::}{clip} property automatically.
1350 If the view is not clipped by another item or the screen, it will be necessary
1351 to set this property to true in order to clip the items that are partially or
1352 fully outside the view.
1354 \sa {declarative/modelviews/gridview}{GridView example}
1356 QDeclarative1GridView::QDeclarative1GridView(QDeclarativeItem *parent)
1357 : QDeclarative1Flickable(*(new QDeclarative1GridViewPrivate), parent)
1359 Q_D(QDeclarative1GridView);
1363 QDeclarative1GridView::~QDeclarative1GridView()
1365 Q_D(QDeclarative1GridView);
1374 \qmlattachedproperty bool GridView::isCurrentItem
1375 This attached property is true if this delegate is the current item; otherwise false.
1377 It is attached to each instance of the delegate.
1381 \qmlattachedproperty GridView GridView::view
1382 This attached property holds the view that manages this delegate instance.
1384 It is attached to each instance of the delegate.
1386 \snippet doc/src/snippets/qtquick1/gridview/gridview.qml isCurrentItem
1390 \qmlattachedproperty bool GridView::delayRemove
1391 This attached property holds whether the delegate may be destroyed.
1393 It is attached to each instance of the delegate.
1395 It is sometimes necessary to delay the destruction of an item
1396 until an animation completes.
1398 The example below ensures that the animation completes before
1399 the item is removed from the grid.
1401 \snippet doc/src/snippets/qtquick1/gridview/gridview.qml delayRemove
1405 \qmlattachedsignal QtQuick1::GridView::onAdd()
1406 This attached handler is called immediately after an item is added to the view.
1410 \qmlattachedsignal QtQuick1::GridView::onRemove()
1411 This attached handler is called immediately before an item is removed from the view.
1416 \qmlproperty model QtQuick1::GridView::model
1417 This property holds the model providing data for the grid.
1419 The model provides the set of data that is used to create the items
1420 in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
1421 or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
1422 used, it must be a subclass of \l QAbstractItemModel or a simple list.
1424 \sa {qmlmodels}{Data Models}
1426 QVariant QDeclarative1GridView::model() const
1428 Q_D(const QDeclarative1GridView);
1429 return d->modelVariant;
1433 int QDeclarative1GridView::modelCount() const
1435 Q_D(const QDeclarative1GridView);
1436 return d->model->count();
1439 void QDeclarative1GridView::setModel(const QVariant &model)
1441 Q_D(QDeclarative1GridView);
1442 if (d->modelVariant == model)
1445 disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
1446 disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
1447 disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
1448 disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
1449 disconnect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
1450 disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
1453 d->modelVariant = model;
1454 QObject *object = qvariant_cast<QObject*>(model);
1455 QDeclarative1VisualModel *vim = 0;
1456 if (object && (vim = qobject_cast<QDeclarative1VisualModel *>(object))) {
1459 d->ownModel = false;
1464 d->model = new QDeclarative1VisualDataModel(qmlContext(this), this);
1467 if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
1468 dataModel->setModel(model);
1471 d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore | QDeclarative1GridViewPrivate::BufferAfter;
1472 if (isComponentComplete()) {
1474 if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
1477 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
1478 d->updateCurrent(d->currentIndex);
1479 if (d->highlight && d->currentItem) {
1480 if (d->autoHighlight)
1481 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
1482 d->updateTrackedItem();
1484 d->moveReason = QDeclarative1GridViewPrivate::Other;
1487 connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
1488 connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
1489 connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
1490 connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
1491 connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
1492 connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*)));
1493 emit countChanged();
1495 emit modelChanged();
1499 \qmlproperty Component QtQuick1::GridView::delegate
1501 The delegate provides a template defining each item instantiated by the view.
1502 The index is exposed as an accessible \c index property. Properties of the
1503 model are also available depending upon the type of \l {qmlmodels}{Data Model}.
1505 The number of elements in the delegate has a direct effect on the
1506 flicking performance of the view. If at all possible, place functionality
1507 that is not needed for the normal display of the delegate in a \l Loader which
1508 can load additional elements when needed.
1510 The GridView will layout the items based on the size of the root item
1513 \note Delegates are instantiated as needed and may be destroyed at any time.
1514 State should \e never be stored in a delegate.
1516 QDeclarativeComponent *QDeclarative1GridView::delegate() const
1518 Q_D(const QDeclarative1GridView);
1520 if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
1521 return dataModel->delegate();
1527 void QDeclarative1GridView::setDelegate(QDeclarativeComponent *delegate)
1529 Q_D(QDeclarative1GridView);
1530 if (delegate == this->delegate())
1534 d->model = new QDeclarative1VisualDataModel(qmlContext(this));
1537 if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model)) {
1538 int oldCount = dataModel->count();
1539 dataModel->setDelegate(delegate);
1540 if (isComponentComplete()) {
1541 for (int i = 0; i < d->visibleItems.count(); ++i)
1542 d->releaseItem(d->visibleItems.at(i));
1543 d->visibleItems.clear();
1544 d->releaseItem(d->currentItem);
1547 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
1548 d->updateCurrent(d->currentIndex);
1549 if (d->highlight && d->currentItem) {
1550 if (d->autoHighlight)
1551 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
1552 d->updateTrackedItem();
1554 d->moveReason = QDeclarative1GridViewPrivate::Other;
1556 if (oldCount != dataModel->count())
1557 emit countChanged();
1558 emit delegateChanged();
1563 \qmlproperty int QtQuick1::GridView::currentIndex
1564 \qmlproperty Item QtQuick1::GridView::currentItem
1566 The \c currentIndex property holds the index of the current item, and
1567 \c currentItem holds the current item. Setting the currentIndex to -1
1568 will clear the highlight and set currentItem to null.
1570 If highlightFollowsCurrentItem is \c true, setting either of these
1571 properties will smoothly scroll the GridView so that the current
1572 item becomes visible.
1574 Note that the position of the current item
1575 may only be approximate until it becomes visible in the view.
1577 int QDeclarative1GridView::currentIndex() const
1579 Q_D(const QDeclarative1GridView);
1580 return d->currentIndex;
1583 void QDeclarative1GridView::setCurrentIndex(int index)
1585 Q_D(QDeclarative1GridView);
1586 if (d->requestedIndex >= 0) // currently creating item
1588 d->currentIndexCleared = (index == -1);
1589 if (index == d->currentIndex)
1591 if (isComponentComplete() && d->isValid()) {
1592 if (d->layoutScheduled)
1594 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
1595 d->updateCurrent(index);
1597 d->currentIndex = index;
1598 emit currentIndexChanged();
1602 QDeclarativeItem *QDeclarative1GridView::currentItem()
1604 Q_D(QDeclarative1GridView);
1605 if (!d->currentItem)
1607 return d->currentItem->item;
1611 \qmlproperty Item QtQuick1::GridView::highlightItem
1613 This holds the highlight item created from the \l highlight component.
1615 The highlightItem is managed by the view unless
1616 \l highlightFollowsCurrentItem is set to false.
1618 \sa highlight, highlightFollowsCurrentItem
1620 QDeclarativeItem *QDeclarative1GridView::highlightItem()
1622 Q_D(QDeclarative1GridView);
1625 return d->highlight->item;
1629 \qmlproperty int QtQuick1::GridView::count
1630 This property holds the number of items in the view.
1632 int QDeclarative1GridView::count() const
1634 Q_D(const QDeclarative1GridView);
1636 return d->model->count();
1641 \qmlproperty Component QtQuick1::GridView::highlight
1642 This property holds the component to use as the highlight.
1644 An instance of the highlight component is created for each view.
1645 The geometry of the resulting component instance will be managed by the view
1646 so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
1648 \sa highlightItem, highlightFollowsCurrentItem
1650 QDeclarativeComponent *QDeclarative1GridView::highlight() const
1652 Q_D(const QDeclarative1GridView);
1653 return d->highlightComponent;
1656 void QDeclarative1GridView::setHighlight(QDeclarativeComponent *highlight)
1658 Q_D(QDeclarative1GridView);
1659 if (highlight != d->highlightComponent) {
1660 d->highlightComponent = highlight;
1661 d->updateCurrent(d->currentIndex);
1662 emit highlightChanged();
1667 \qmlproperty bool QtQuick1::GridView::highlightFollowsCurrentItem
1668 This property sets whether the highlight is managed by the view.
1670 If this property is true (the default value), the highlight is moved smoothly
1671 to follow the current item. Otherwise, the
1672 highlight is not moved by the view, and any movement must be implemented
1675 Here is a highlight with its motion defined by a \l {SpringAnimation} item:
1677 \snippet doc/src/snippets/qtquick1/gridview/gridview.qml highlightFollowsCurrentItem
1679 bool QDeclarative1GridView::highlightFollowsCurrentItem() const
1681 Q_D(const QDeclarative1GridView);
1682 return d->autoHighlight;
1685 void QDeclarative1GridView::setHighlightFollowsCurrentItem(bool autoHighlight)
1687 Q_D(QDeclarative1GridView);
1688 if (d->autoHighlight != autoHighlight) {
1689 d->autoHighlight = autoHighlight;
1690 if (autoHighlight) {
1691 d->updateHighlight();
1692 } else if (d->highlightXAnimator) {
1693 d->highlightXAnimator->stop();
1694 d->highlightYAnimator->stop();
1700 \qmlproperty int QtQuick1::GridView::highlightMoveDuration
1701 This property holds the move animation duration of the highlight delegate.
1703 highlightFollowsCurrentItem must be true for this property
1706 The default value for the duration is 150ms.
1708 \sa highlightFollowsCurrentItem
1710 int QDeclarative1GridView::highlightMoveDuration() const
1712 Q_D(const QDeclarative1GridView);
1713 return d->highlightMoveDuration;
1716 void QDeclarative1GridView::setHighlightMoveDuration(int duration)
1718 Q_D(QDeclarative1GridView);
1719 if (d->highlightMoveDuration != duration) {
1720 d->highlightMoveDuration = duration;
1721 if (d->highlightYAnimator) {
1722 d->highlightXAnimator->userDuration = d->highlightMoveDuration;
1723 d->highlightYAnimator->userDuration = d->highlightMoveDuration;
1725 emit highlightMoveDurationChanged();
1731 \qmlproperty real QtQuick1::GridView::preferredHighlightBegin
1732 \qmlproperty real QtQuick1::GridView::preferredHighlightEnd
1733 \qmlproperty enumeration QtQuick1::GridView::highlightRangeMode
1735 These properties define the preferred range of the highlight (for the current item)
1736 within the view. The \c preferredHighlightBegin value must be less than the
1737 \c preferredHighlightEnd value.
1739 These properties affect the position of the current item when the view is scrolled.
1740 For example, if the currently selected item should stay in the middle of the
1741 view when it is scrolled, set the \c preferredHighlightBegin and
1742 \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
1743 item would be. If the \c currentItem is changed programmatically, the view will
1744 automatically scroll so that the current item is in the middle of the view.
1745 Furthermore, the behavior of the current item index will occur whether or not a
1748 Valid values for \c highlightRangeMode are:
1751 \o GridView.ApplyRange - the view attempts to maintain the highlight within the range.
1752 However, the highlight can move outside of the range at the ends of the view or due
1753 to mouse interaction.
1754 \o GridView.StrictlyEnforceRange - the highlight never moves outside of the range.
1755 The current item changes if a keyboard or mouse action would cause the highlight to move
1756 outside of the range.
1757 \o GridView.NoHighlightRange - this is the default value.
1760 qreal QDeclarative1GridView::preferredHighlightBegin() const
1762 Q_D(const QDeclarative1GridView);
1763 return d->highlightRangeStart;
1766 void QDeclarative1GridView::setPreferredHighlightBegin(qreal start)
1768 Q_D(QDeclarative1GridView);
1769 d->highlightRangeStartValid = true;
1770 if (d->highlightRangeStart == start)
1772 d->highlightRangeStart = start;
1773 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1774 emit preferredHighlightBeginChanged();
1777 void QDeclarative1GridView::resetPreferredHighlightBegin()
1779 Q_D(QDeclarative1GridView);
1780 d->highlightRangeStartValid = false;
1781 if (d->highlightRangeStart == 0)
1783 d->highlightRangeStart = 0;
1784 emit preferredHighlightBeginChanged();
1787 qreal QDeclarative1GridView::preferredHighlightEnd() const
1789 Q_D(const QDeclarative1GridView);
1790 return d->highlightRangeEnd;
1793 void QDeclarative1GridView::setPreferredHighlightEnd(qreal end)
1795 Q_D(QDeclarative1GridView);
1796 d->highlightRangeEndValid = true;
1797 if (d->highlightRangeEnd == end)
1799 d->highlightRangeEnd = end;
1800 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1801 emit preferredHighlightEndChanged();
1804 void QDeclarative1GridView::resetPreferredHighlightEnd()
1806 Q_D(QDeclarative1GridView);
1807 d->highlightRangeEndValid = false;
1808 if (d->highlightRangeEnd == 0)
1810 d->highlightRangeEnd = 0;
1811 emit preferredHighlightEndChanged();
1814 QDeclarative1GridView::HighlightRangeMode QDeclarative1GridView::highlightRangeMode() const
1816 Q_D(const QDeclarative1GridView);
1817 return d->highlightRange;
1820 void QDeclarative1GridView::setHighlightRangeMode(HighlightRangeMode mode)
1822 Q_D(QDeclarative1GridView);
1823 if (d->highlightRange == mode)
1825 d->highlightRange = mode;
1826 d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1827 emit highlightRangeModeChanged();
1831 \qmlproperty enumeration QtQuick1::GridView::layoutDirection
1832 This property holds the layout direction of the grid.
1837 \o Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is
1838 dependent on the \l GridView::flow property.
1839 \o Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent
1840 on the \l GridView::flow property.
1843 \bold Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if
1844 GridView::layoutDirection is set to Qt.RightToLeft. The GridView.LeftToRight flow value simply
1845 indicates that the flow is horizontal.
1848 Qt::LayoutDirection QDeclarative1GridView::layoutDirection() const
1850 Q_D(const QDeclarative1GridView);
1851 return d->layoutDirection;
1854 void QDeclarative1GridView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
1856 Q_D(QDeclarative1GridView);
1857 if (d->layoutDirection != layoutDirection) {
1858 d->layoutDirection = layoutDirection;
1860 emit layoutDirectionChanged();
1861 emit effectiveLayoutDirectionChanged();
1866 \qmlproperty enumeration QtQuick1::GridView::effectiveLayoutDirection
1867 This property holds the effective layout direction of the grid.
1869 When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
1870 the visual layout direction of the grid will be mirrored. However, the
1871 property \l {GridView::layoutDirection}{layoutDirection} will remain unchanged.
1873 \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
1876 Qt::LayoutDirection QDeclarative1GridView::effectiveLayoutDirection() const
1878 Q_D(const QDeclarative1GridView);
1879 if (d->effectiveLayoutMirror)
1880 return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
1882 return d->layoutDirection;
1886 \qmlproperty enumeration QtQuick1::GridView::flow
1887 This property holds the flow of the grid.
1892 \o GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically
1893 \o GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally
1896 QDeclarative1GridView::Flow QDeclarative1GridView::flow() const
1898 Q_D(const QDeclarative1GridView);
1902 void QDeclarative1GridView::setFlow(Flow flow)
1904 Q_D(QDeclarative1GridView);
1905 if (d->flow != flow) {
1907 if (d->flow == LeftToRight) {
1908 setContentWidth(-1);
1909 setFlickableDirection(QDeclarative1Flickable::VerticalFlick);
1911 setContentHeight(-1);
1912 setFlickableDirection(QDeclarative1Flickable::HorizontalFlick);
1922 \qmlproperty bool QtQuick1::GridView::keyNavigationWraps
1923 This property holds whether the grid wraps key navigation
1925 If this is true, key navigation that would move the current item selection
1926 past one end of the view instead wraps around and moves the selection to
1927 the other end of the view.
1929 By default, key navigation is not wrapped.
1931 bool QDeclarative1GridView::isWrapEnabled() const
1933 Q_D(const QDeclarative1GridView);
1937 void QDeclarative1GridView::setWrapEnabled(bool wrap)
1939 Q_D(QDeclarative1GridView);
1940 if (d->wrap == wrap)
1943 emit keyNavigationWrapsChanged();
1947 \qmlproperty int QtQuick1::GridView::cacheBuffer
1948 This property determines whether delegates are retained outside the
1949 visible area of the view.
1951 If non-zero the view will keep as many delegates
1952 instantiated as will fit within the buffer specified. For example,
1953 if in a vertical view the delegate is 20 pixels high and \c cacheBuffer is
1954 set to 40, then up to 2 delegates above and 2 delegates below the visible
1955 area may be retained.
1957 Note that cacheBuffer is not a pixel buffer - it only maintains additional
1958 instantiated delegates.
1960 Setting this value can make scrolling the list smoother at the expense
1961 of additional memory usage. It is not a substitute for creating efficient
1962 delegates; the fewer elements in a delegate, the faster a view may be
1965 int QDeclarative1GridView::cacheBuffer() const
1967 Q_D(const QDeclarative1GridView);
1971 void QDeclarative1GridView::setCacheBuffer(int buffer)
1973 Q_D(QDeclarative1GridView);
1974 if (d->buffer != buffer) {
1976 if (isComponentComplete())
1978 emit cacheBufferChanged();
1983 \qmlproperty int QtQuick1::GridView::cellWidth
1984 \qmlproperty int QtQuick1::GridView::cellHeight
1986 These properties holds the width and height of each cell in the grid.
1988 The default cell size is 100x100.
1990 int QDeclarative1GridView::cellWidth() const
1992 Q_D(const QDeclarative1GridView);
1993 return d->cellWidth;
1996 void QDeclarative1GridView::setCellWidth(int cellWidth)
1998 Q_D(QDeclarative1GridView);
1999 if (cellWidth != d->cellWidth && cellWidth > 0) {
2000 d->cellWidth = qMax(1, cellWidth);
2002 emit cellWidthChanged();
2007 int QDeclarative1GridView::cellHeight() const
2009 Q_D(const QDeclarative1GridView);
2010 return d->cellHeight;
2013 void QDeclarative1GridView::setCellHeight(int cellHeight)
2015 Q_D(QDeclarative1GridView);
2016 if (cellHeight != d->cellHeight && cellHeight > 0) {
2017 d->cellHeight = qMax(1, cellHeight);
2019 emit cellHeightChanged();
2024 \qmlproperty enumeration QtQuick1::GridView::snapMode
2026 This property determines how the view scrolling will settle following a drag or flick.
2027 The possible values are:
2030 \o GridView.NoSnap (default) - the view stops anywhere within the visible area.
2031 \o GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow)
2032 aligned with the start of the view.
2033 \o GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow)
2034 away from the first visible row at the time the mouse button is released.
2035 This mode is particularly useful for moving one page at a time.
2039 QDeclarative1GridView::SnapMode QDeclarative1GridView::snapMode() const
2041 Q_D(const QDeclarative1GridView);
2045 void QDeclarative1GridView::setSnapMode(SnapMode mode)
2047 Q_D(QDeclarative1GridView);
2048 if (d->snapMode != mode) {
2050 emit snapModeChanged();
2055 \qmlproperty Component QtQuick1::GridView::footer
2056 This property holds the component to use as the footer.
2058 An instance of the footer component is created for each view. The
2059 footer is positioned at the end of the view, after any items.
2063 QDeclarativeComponent *QDeclarative1GridView::footer() const
2065 Q_D(const QDeclarative1GridView);
2066 return d->footerComponent;
2069 void QDeclarative1GridView::setFooter(QDeclarativeComponent *footer)
2071 Q_D(QDeclarative1GridView);
2072 if (d->footerComponent != footer) {
2075 scene()->removeItem(d->footer->item);
2076 d->footer->item->deleteLater();
2080 d->footerComponent = footer;
2081 if (isComponentComplete()) {
2086 emit footerChanged();
2091 \qmlproperty Component QtQuick1::GridView::header
2092 This property holds the component to use as the header.
2094 An instance of the header component is created for each view. The
2095 header is positioned at the beginning of the view, before any items.
2099 QDeclarativeComponent *QDeclarative1GridView::header() const
2101 Q_D(const QDeclarative1GridView);
2102 return d->headerComponent;
2105 void QDeclarative1GridView::setHeader(QDeclarativeComponent *header)
2107 Q_D(QDeclarative1GridView);
2108 if (d->headerComponent != header) {
2111 scene()->removeItem(d->header->item);
2112 d->header->item->deleteLater();
2116 d->headerComponent = header;
2117 if (isComponentComplete()) {
2123 emit headerChanged();
2127 void QDeclarative1GridView::setContentX(qreal pos)
2129 Q_D(QDeclarative1GridView);
2130 // Positioning the view manually should override any current movement state
2131 d->moveReason = QDeclarative1GridViewPrivate::Other;
2132 QDeclarative1Flickable::setContentX(pos);
2135 void QDeclarative1GridView::setContentY(qreal pos)
2137 Q_D(QDeclarative1GridView);
2138 // Positioning the view manually should override any current movement state
2139 d->moveReason = QDeclarative1GridViewPrivate::Other;
2140 QDeclarative1Flickable::setContentY(pos);
2143 bool QDeclarative1GridView::event(QEvent *event)
2145 Q_D(QDeclarative1GridView);
2146 if (event->type() == QEvent::User) {
2147 if (d->layoutScheduled)
2152 return QDeclarative1Flickable::event(event);
2155 void QDeclarative1GridView::viewportMoved()
2157 Q_D(QDeclarative1GridView);
2158 QDeclarative1Flickable::viewportMoved();
2161 d->lazyRelease = true;
2162 if (d->hData.flicking || d->vData.flicking) {
2164 if (d->vData.velocity > 0)
2165 d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore;
2166 else if (d->vData.velocity < 0)
2167 d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter;
2171 if (d->hData.velocity > 0)
2172 d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore;
2173 else if (d->hData.velocity < 0)
2174 d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter;
2178 if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
2179 d->moveReason = QDeclarative1GridViewPrivate::Mouse;
2180 if (d->moveReason != QDeclarative1GridViewPrivate::SetIndex) {
2181 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
2182 // reposition highlight
2183 qreal pos = d->highlight->rowPos();
2185 qreal highlightStart;
2187 if (d->isRightToLeftTopToBottom()) {
2188 highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
2189 highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
2190 viewPos = -d->position()-d->size();
2192 highlightStart = d->highlightRangeStart;
2193 highlightEnd = d->highlightRangeEnd;
2194 viewPos = d->position();
2196 if (pos > viewPos + highlightEnd - d->rowSize())
2197 pos = viewPos + highlightEnd - d->rowSize();
2198 if (pos < viewPos + highlightStart)
2199 pos = viewPos + highlightStart;
2201 d->highlight->setPosition(d->highlight->colPos(), qRound(pos));
2203 // update current index
2204 int idx = d->snapIndex();
2205 if (idx >= 0 && idx != d->currentIndex) {
2206 d->updateCurrent(idx);
2207 if (d->currentItem && d->currentItem->colPos() != d->highlight->colPos() && d->autoHighlight) {
2208 if (d->flow == LeftToRight)
2209 d->highlightXAnimator->to = d->currentItem->item->x();
2211 d->highlightYAnimator->to = d->currentItem->item->y();
2218 qreal QDeclarative1GridView::minYExtent() const
2220 Q_D(const QDeclarative1GridView);
2221 if (d->flow == QDeclarative1GridView::TopToBottom)
2222 return QDeclarative1Flickable::minYExtent();
2223 qreal extent = -d->startPosition();
2224 if (d->header && d->visibleItems.count())
2225 extent += d->header->item->height();
2226 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2227 extent += d->highlightRangeStart;
2228 extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
2233 qreal QDeclarative1GridView::maxYExtent() const
2235 Q_D(const QDeclarative1GridView);
2236 if (d->flow == QDeclarative1GridView::TopToBottom)
2237 return QDeclarative1Flickable::maxYExtent();
2239 if (!d->model || !d->model->count()) {
2241 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2242 extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
2243 if (d->highlightRangeEnd != d->highlightRangeStart)
2244 extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
2246 extent = -(d->endPosition() - height());
2249 extent -= d->footer->item->height();
2250 const qreal minY = minYExtent();
2256 qreal QDeclarative1GridView::minXExtent() const
2258 Q_D(const QDeclarative1GridView);
2259 if (d->flow == QDeclarative1GridView::LeftToRight)
2260 return QDeclarative1Flickable::minXExtent();
2261 qreal extent = -d->startPosition();
2262 qreal highlightStart;
2264 qreal endPositionFirstItem = 0;
2265 if (d->isRightToLeftTopToBottom()) {
2266 if (d->model && d->model->count())
2267 endPositionFirstItem = d->rowPosAt(d->model->count()-1);
2268 highlightStart = d->highlightRangeStartValid
2269 ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
2270 : d->size() - (d->lastPosition()-endPositionFirstItem);
2271 highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
2272 if (d->footer && d->visibleItems.count())
2273 extent += d->footer->item->width();
2275 endPositionFirstItem = d->rowPosAt(0)+d->rowSize();
2276 highlightStart = d->highlightRangeStart;
2277 highlightEnd = d->highlightRangeEnd;
2278 if (d->header && d->visibleItems.count())
2279 extent += d->header->item->width();
2281 if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2282 extent += d->isRightToLeftTopToBottom() ? -highlightStart : highlightStart;
2283 extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
2288 qreal QDeclarative1GridView::maxXExtent() const
2290 Q_D(const QDeclarative1GridView);
2291 if (d->flow == QDeclarative1GridView::LeftToRight)
2292 return QDeclarative1Flickable::maxXExtent();
2294 qreal highlightStart;
2296 qreal lastItemPosition = 0;
2297 if (d->isRightToLeftTopToBottom()){
2298 highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
2299 highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
2300 lastItemPosition = d->endPosition();
2302 highlightStart = d->highlightRangeStart;
2303 highlightEnd = d->highlightRangeEnd;
2304 lastItemPosition = 0;
2305 if (d->model && d->model->count())
2306 lastItemPosition = d->rowPosAt(d->model->count()-1);
2308 if (!d->model || !d->model->count()) {
2310 } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2311 extent = -(lastItemPosition - highlightStart);
2312 if (highlightEnd != highlightStart)
2313 extent = d->isRightToLeftTopToBottom()
2314 ? qMax(extent, -(d->endPosition() - highlightEnd + 1))
2315 : qMin(extent, -(d->endPosition() - highlightEnd + 1));
2317 extent = -(d->endPosition() - width());
2319 if (d->isRightToLeftTopToBottom()) {
2321 extent -= d->header->item->width();
2324 extent -= d->footer->item->width();
2327 const qreal minX = minXExtent();
2333 void QDeclarative1GridView::keyPressEvent(QKeyEvent *event)
2335 Q_D(QDeclarative1GridView);
2336 keyPressPreHandler(event);
2337 if (event->isAccepted())
2339 if (d->model && d->model->count() && d->interactive) {
2340 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
2341 int oldCurrent = currentIndex();
2342 switch (event->key()) {
2344 moveCurrentIndexUp();
2347 moveCurrentIndexDown();
2350 moveCurrentIndexLeft();
2353 moveCurrentIndexRight();
2358 if (oldCurrent != currentIndex()) {
2363 d->moveReason = QDeclarative1GridViewPrivate::Other;
2365 QDeclarative1Flickable::keyPressEvent(event);
2369 \qmlmethod QtQuick1::GridView::moveCurrentIndexUp()
2371 Move the currentIndex up one item in the view.
2372 The current index will wrap if keyNavigationWraps is true and it
2373 is currently at the end. This method has no effect if the \l count is zero.
2375 \bold Note: methods should only be called after the Component has completed.
2377 void QDeclarative1GridView::moveCurrentIndexUp()
2379 Q_D(QDeclarative1GridView);
2380 const int count = d->model ? d->model->count() : 0;
2383 if (d->flow == QDeclarative1GridView::LeftToRight) {
2384 if (currentIndex() >= d->columns || d->wrap) {
2385 int index = currentIndex() - d->columns;
2386 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2389 if (currentIndex() > 0 || d->wrap) {
2390 int index = currentIndex() - 1;
2391 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2397 \qmlmethod QtQuick1::GridView::moveCurrentIndexDown()
2399 Move the currentIndex down one item in the view.
2400 The current index will wrap if keyNavigationWraps is true and it
2401 is currently at the end. This method has no effect if the \l count is zero.
2403 \bold Note: methods should only be called after the Component has completed.
2405 void QDeclarative1GridView::moveCurrentIndexDown()
2407 Q_D(QDeclarative1GridView);
2408 const int count = d->model ? d->model->count() : 0;
2411 if (d->flow == QDeclarative1GridView::LeftToRight) {
2412 if (currentIndex() < count - d->columns || d->wrap) {
2413 int index = currentIndex()+d->columns;
2414 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2417 if (currentIndex() < count - 1 || d->wrap) {
2418 int index = currentIndex() + 1;
2419 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2425 \qmlmethod QtQuick1::GridView::moveCurrentIndexLeft()
2427 Move the currentIndex left one item in the view.
2428 The current index will wrap if keyNavigationWraps is true and it
2429 is currently at the end. This method has no effect if the \l count is zero.
2431 \bold Note: methods should only be called after the Component has completed.
2433 void QDeclarative1GridView::moveCurrentIndexLeft()
2435 Q_D(QDeclarative1GridView);
2436 const int count = d->model ? d->model->count() : 0;
2440 if (effectiveLayoutDirection() == Qt::LeftToRight) {
2441 if (d->flow == QDeclarative1GridView::LeftToRight) {
2442 if (currentIndex() > 0 || d->wrap) {
2443 int index = currentIndex() - 1;
2444 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2447 if (currentIndex() >= d->columns || d->wrap) {
2448 int index = currentIndex() - d->columns;
2449 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2453 if (d->flow == QDeclarative1GridView::LeftToRight) {
2454 if (currentIndex() < count - 1 || d->wrap) {
2455 int index = currentIndex() + 1;
2456 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2459 if (currentIndex() < count - d->columns || d->wrap) {
2460 int index = currentIndex() + d->columns;
2461 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2468 \qmlmethod QtQuick1::GridView::moveCurrentIndexRight()
2470 Move the currentIndex right one item in the view.
2471 The current index will wrap if keyNavigationWraps is true and it
2472 is currently at the end. This method has no effect if the \l count is zero.
2474 \bold Note: methods should only be called after the Component has completed.
2476 void QDeclarative1GridView::moveCurrentIndexRight()
2478 Q_D(QDeclarative1GridView);
2479 const int count = d->model ? d->model->count() : 0;
2483 if (effectiveLayoutDirection() == Qt::LeftToRight) {
2484 if (d->flow == QDeclarative1GridView::LeftToRight) {
2485 if (currentIndex() < count - 1 || d->wrap) {
2486 int index = currentIndex() + 1;
2487 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2490 if (currentIndex() < count - d->columns || d->wrap) {
2491 int index = currentIndex()+d->columns;
2492 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2496 if (d->flow == QDeclarative1GridView::LeftToRight) {
2497 if (currentIndex() > 0 || d->wrap) {
2498 int index = currentIndex() - 1;
2499 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2502 if (currentIndex() >= d->columns || d->wrap) {
2503 int index = currentIndex() - d->columns;
2504 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2510 void QDeclarative1GridViewPrivate::positionViewAtIndex(int index, int mode)
2512 Q_Q(QDeclarative1GridView);
2515 if (mode < QDeclarative1GridView::Beginning || mode > QDeclarative1GridView::Contain)
2518 int idx = qMax(qMin(index, model->count()-1), 0);
2520 if (layoutScheduled)
2522 qreal pos = isRightToLeftTopToBottom() ? -position() - size() : position();
2523 FxGridItem1 *item = visibleItem(idx);
2525 if (flow == QDeclarative1GridView::LeftToRight)
2526 maxExtent = -q->maxYExtent();
2528 maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
2531 int itemPos = rowPosAt(idx);
2532 // save the currently visible items in case any of them end up visible again
2533 QList<FxGridItem1*> oldVisible = visibleItems;
2534 visibleItems.clear();
2535 visibleIndex = idx - idx % columns;
2536 if (flow == QDeclarative1GridView::LeftToRight)
2537 maxExtent = -q->maxYExtent();
2539 maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
2540 setPosition(qMin(qreal(itemPos), maxExtent));
2541 // now release the reference to all the old visible items.
2542 for (int i = 0; i < oldVisible.count(); ++i)
2543 releaseItem(oldVisible.at(i));
2544 item = visibleItem(idx);
2547 qreal itemPos = item->rowPos();
2549 case QDeclarative1GridView::Beginning:
2551 if (index < 0 && header) {
2552 pos -= flow == QDeclarative1GridView::LeftToRight
2553 ? header->item->height()
2554 : header->item->width();
2557 case QDeclarative1GridView::Center:
2558 pos = itemPos - (size() - rowSize())/2;
2560 case QDeclarative1GridView::End:
2561 pos = itemPos - size() + rowSize();
2562 if (index >= model->count() && footer) {
2563 pos += flow == QDeclarative1GridView::LeftToRight
2564 ? footer->item->height()
2565 : footer->item->width();
2568 case QDeclarative1GridView::Visible:
2569 if (itemPos > pos + size())
2570 pos = itemPos - size() + rowSize();
2571 else if (item->endRowPos() < pos)
2574 case QDeclarative1GridView::Contain:
2575 if (item->endRowPos() > pos + size())
2576 pos = itemPos - size() + rowSize();
2581 pos = qMin(pos, maxExtent);
2583 if (flow == QDeclarative1GridView::LeftToRight)
2584 minExtent = -q->minYExtent();
2586 minExtent = isRightToLeftTopToBottom() ? q->maxXExtent()-size() : -q->minXExtent();
2587 pos = qMax(pos, minExtent);
2588 moveReason = QDeclarative1GridViewPrivate::Other;
2596 \qmlmethod QtQuick1::GridView::positionViewAtIndex(int index, PositionMode mode)
2598 Positions the view such that the \a index is at the position specified by
2602 \o GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view.
2603 \o GridView.Center - position item in the center of the view.
2604 \o GridView.End - position item at bottom (or right for horizontal orientation) of the view.
2605 \o GridView.Visible - if any part of the item is visible then take no action, otherwise
2606 bring the item into view.
2607 \o GridView.Contain - ensure the entire item is visible. If the item is larger than
2608 the view the item is positioned at the top (or left for \c GridView.TopToBottom flow) of the view.
2611 If positioning the view at the index would cause empty space to be displayed at
2612 the beginning or end of the view, the view will be positioned at the boundary.
2614 It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
2615 at a particular index. This is unreliable since removing items from the start
2616 of the view does not cause all other items to be repositioned.
2617 The correct way to bring an item into view is with \c positionViewAtIndex.
2619 \bold Note: methods should only be called after the Component has completed. To position
2620 the view at startup, this method should be called by Component.onCompleted. For
2621 example, to position the view at the end:
2624 Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
2627 void QDeclarative1GridView::positionViewAtIndex(int index, int mode)
2629 Q_D(QDeclarative1GridView);
2630 if (!d->isValid() || index < 0 || index >= d->model->count())
2632 d->positionViewAtIndex(index, mode);
2636 \qmlmethod QtQuick1::GridView::positionViewAtBeginning()
2637 \qmlmethod QtQuick1::GridView::positionViewAtEnd()
2640 Positions the view at the beginning or end, taking into account any header or footer.
2642 It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
2643 at a particular index. This is unreliable since removing items from the start
2644 of the list does not cause all other items to be repositioned, and because
2645 the actual start of the view can vary based on the size of the delegates.
2647 \bold Note: methods should only be called after the Component has completed. To position
2648 the view at startup, this method should be called by Component.onCompleted. For
2649 example, to position the view at the end on startup:
2652 Component.onCompleted: positionViewAtEnd()
2655 void QDeclarative1GridView::positionViewAtBeginning()
2657 Q_D(QDeclarative1GridView);
2660 d->positionViewAtIndex(-1, Beginning);
2663 void QDeclarative1GridView::positionViewAtEnd()
2665 Q_D(QDeclarative1GridView);
2668 d->positionViewAtIndex(d->model->count(), End);
2672 \qmlmethod int QtQuick1::GridView::indexAt(int x, int y)
2674 Returns the index of the visible item containing the point \a x, \a y in content
2675 coordinates. If there is no item at the point specified, or the item is
2676 not visible -1 is returned.
2678 If the item is outside the visible area, -1 is returned, regardless of
2679 whether an item will exist at that point when scrolled into view.
2681 \bold Note: methods should only be called after the Component has completed.
2683 int QDeclarative1GridView::indexAt(qreal x, qreal y) const
2685 Q_D(const QDeclarative1GridView);
2686 for (int i = 0; i < d->visibleItems.count(); ++i) {
2687 const FxGridItem1 *listItem = d->visibleItems.at(i);
2688 if(listItem->contains(x, y))
2689 return listItem->index;
2695 void QDeclarative1GridView::componentComplete()
2697 Q_D(QDeclarative1GridView);
2698 QDeclarative1Flickable::componentComplete();
2704 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
2705 if (d->currentIndex < 0 && !d->currentIndexCleared)
2706 d->updateCurrent(0);
2708 d->updateCurrent(d->currentIndex);
2709 if (d->highlight && d->currentItem) {
2710 if (d->autoHighlight)
2711 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
2712 d->updateTrackedItem();
2714 d->moveReason = QDeclarative1GridViewPrivate::Other;
2719 void QDeclarative1GridView::trackedPositionChanged()
2721 Q_D(QDeclarative1GridView);
2722 if (!d->trackedItem || !d->currentItem)
2724 if (d->moveReason == QDeclarative1GridViewPrivate::SetIndex) {
2725 const qreal trackedPos = d->trackedItem->rowPos();
2727 qreal highlightStart;
2729 if (d->isRightToLeftTopToBottom()) {
2730 viewPos = -d->position()-d->size();
2731 highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart;
2732 highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd;
2734 viewPos = d->position();
2735 highlightStart = d->highlightRangeStart;
2736 highlightEnd = d->highlightRangeEnd;
2738 qreal pos = viewPos;
2739 if (d->haveHighlightRange) {
2740 if (d->highlightRange == StrictlyEnforceRange) {
2741 if (trackedPos > pos + highlightEnd - d->rowSize())
2742 pos = trackedPos - highlightEnd + d->rowSize();
2743 if (trackedPos < pos + highlightStart)
2744 pos = trackedPos - highlightStart;
2746 if (trackedPos < d->startPosition() + highlightStart) {
2747 pos = d->startPosition();
2748 } else if (d->trackedItem->endRowPos() > d->endPosition() - d->size() + highlightEnd) {
2749 pos = d->endPosition() - d->size() + 1;
2750 if (pos < d->startPosition())
2751 pos = d->startPosition();
2753 if (trackedPos > pos + highlightEnd - d->rowSize())
2754 pos = trackedPos - highlightEnd + d->rowSize();
2755 if (trackedPos < pos + highlightStart)
2756 pos = trackedPos - highlightStart;
2760 if (trackedPos < viewPos && d->currentItem->rowPos() < viewPos) {
2761 pos = qMax(trackedPos, d->currentItem->rowPos());
2762 } else if (d->trackedItem->endRowPos() >= viewPos + d->size()
2763 && d->currentItem->endRowPos() >= viewPos + d->size()) {
2764 if (d->trackedItem->endRowPos() <= d->currentItem->endRowPos()) {
2765 pos = d->trackedItem->endRowPos() - d->size() + 1;
2766 if (d->rowSize() > d->size())
2769 pos = d->currentItem->endRowPos() - d->size() + 1;
2770 if (d->rowSize() > d->size())
2771 pos = d->currentItem->rowPos();
2775 if (viewPos != pos) {
2777 d->calcVelocity = true;
2778 d->setPosition(pos);
2779 d->calcVelocity = false;
2784 void QDeclarative1GridView::itemsInserted(int modelIndex, int count)
2786 Q_D(QDeclarative1GridView);
2787 if (!isComponentComplete() || !d->model || !d->model->isValid())
2790 int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
2792 int i = d->visibleItems.count() - 1;
2793 while (i > 0 && d->visibleItems.at(i)->index == -1)
2795 if (d->visibleItems.at(i)->index + 1 == modelIndex) {
2796 // Special case of appending an item to the model.
2797 index = d->visibleIndex + d->visibleItems.count();
2799 if (modelIndex <= d->visibleIndex) {
2800 // Insert before visible items
2801 d->visibleIndex += count;
2802 for (int i = 0; i < d->visibleItems.count(); ++i) {
2803 FxGridItem1 *listItem = d->visibleItems.at(i);
2804 if (listItem->index != -1 && listItem->index >= modelIndex)
2805 listItem->index += count;
2808 if (d->currentIndex >= modelIndex) {
2809 // adjust current item index
2810 d->currentIndex += count;
2812 d->currentItem->index = d->currentIndex;
2813 emit currentIndexChanged();
2815 d->scheduleLayout();
2816 d->itemCount += count;
2817 emit countChanged();
2822 int insertCount = count;
2823 if (index < d->visibleIndex && d->visibleItems.count()) {
2824 insertCount -= d->visibleIndex - index;
2825 index = d->visibleIndex;
2826 modelIndex = d->visibleIndex;
2829 qreal tempPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size()+d->width()+1 : d->position();
2830 int to = d->buffer+tempPos+d->size()-1;
2833 if (d->visibleItems.count()) {
2834 index -= d->visibleIndex;
2835 if (index < d->visibleItems.count()) {
2836 colPos = d->visibleItems.at(index)->colPos();
2837 rowPos = d->visibleItems.at(index)->rowPos();
2839 // appending items to visible list
2840 colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
2841 rowPos = d->visibleItems.at(index-1)->rowPos();
2842 if (colPos > d->colSize() * (d->columns-1)) {
2844 rowPos += d->rowSize();
2847 } else if (d->itemCount == 0 && d->header) {
2848 rowPos = d->headerSize();
2851 // Update the indexes of the following visible items.
2852 for (int i = 0; i < d->visibleItems.count(); ++i) {
2853 FxGridItem1 *listItem = d->visibleItems.at(i);
2854 if (listItem->index != -1 && listItem->index >= modelIndex)
2855 listItem->index += count;
2858 bool addedVisible = false;
2859 QList<FxGridItem1*> added;
2861 while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) {
2862 if (!addedVisible) {
2863 d->scheduleLayout();
2864 addedVisible = true;
2866 FxGridItem1 *item = d->createItem(modelIndex + i);
2867 d->visibleItems.insert(index, item);
2868 item->setPosition(colPos, rowPos);
2870 colPos += d->colSize();
2871 if (colPos > d->colSize() * (d->columns-1)) {
2873 rowPos += d->rowSize();
2878 if (i < insertCount) {
2879 // We didn't insert all our new items, which means anything
2880 // beyond the current index is not visible - remove it.
2881 while (d->visibleItems.count() > index) {
2882 d->releaseItem(d->visibleItems.takeLast());
2886 // update visibleIndex
2887 d->visibleIndex = 0;
2888 for (QList<FxGridItem1*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
2889 if ((*it)->index != -1) {
2890 d->visibleIndex = (*it)->index;
2895 if (d->itemCount && d->currentIndex >= modelIndex) {
2896 // adjust current item index
2897 d->currentIndex += count;
2898 if (d->currentItem) {
2899 d->currentItem->index = d->currentIndex;
2900 d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
2902 emit currentIndexChanged();
2903 } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
2907 // everything is in order now - emit add() signal
2908 for (int j = 0; j < added.count(); ++j)
2909 added.at(j)->attached->emitAdd();
2911 d->itemCount += count;
2912 emit countChanged();
2915 void QDeclarative1GridView::itemsRemoved(int modelIndex, int count)
2917 Q_D(QDeclarative1GridView);
2918 if (!isComponentComplete() || !d->model || !d->model->isValid())
2921 d->itemCount -= count;
2922 bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
2923 bool removedVisible = false;
2925 // Remove the items from the visible list, skipping anything already marked for removal
2926 QList<FxGridItem1*>::Iterator it = d->visibleItems.begin();
2927 while (it != d->visibleItems.end()) {
2928 FxGridItem1 *item = *it;
2929 if (item->index == -1 || item->index < modelIndex) {
2930 // already removed, or before removed items
2931 if (item->index < modelIndex && !removedVisible) {
2932 d->scheduleLayout();
2933 removedVisible = true;
2936 } else if (item->index >= modelIndex + count) {
2937 // after removed items
2938 item->index -= count;
2942 if (!removedVisible) {
2943 d->scheduleLayout();
2944 removedVisible = true;
2946 item->attached->emitRemove();
2947 if (item->attached->delayRemove()) {
2949 connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
2952 it = d->visibleItems.erase(it);
2953 d->releaseItem(item);
2958 // update visibleIndex
2959 d->visibleIndex = 0;
2960 for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
2961 if ((*it)->index != -1) {
2962 d->visibleIndex = (*it)->index;
2967 // If we removed items before visible items a layout may be
2968 // required to ensure item 0 is in the first column.
2969 if (!removedVisible && modelIndex < d->visibleIndex)
2970 d->scheduleLayout();
2973 if (d->currentIndex >= modelIndex + count) {
2974 d->currentIndex -= count;
2976 d->currentItem->index -= count;
2977 emit currentIndexChanged();
2978 } else if (currentRemoved) {
2979 // current item has been removed.
2980 d->releaseItem(d->currentItem);
2982 d->currentIndex = -1;
2984 d->updateCurrent(qMin(modelIndex, d->itemCount-1));
2986 emit currentIndexChanged();
2989 if (removedVisible && d->visibleItems.isEmpty()) {
2990 d->timeline.clear();
2991 if (d->itemCount == 0) {
2999 emit countChanged();
3002 void QDeclarative1GridView::destroyRemoved()
3004 Q_D(QDeclarative1GridView);
3005 for (QList<FxGridItem1*>::Iterator it = d->visibleItems.begin();
3006 it != d->visibleItems.end();) {
3007 FxGridItem1 *listItem = *it;
3008 if (listItem->index == -1 && listItem->attached->delayRemove() == false) {
3009 d->releaseItem(listItem);
3010 it = d->visibleItems.erase(it);
3016 // Correct the positioning of the items
3020 void QDeclarative1GridView::itemsMoved(int from, int to, int count)
3022 Q_D(QDeclarative1GridView);
3023 if (!isComponentComplete() || !d->isValid())
3025 QHash<int,FxGridItem1*> moved;
3027 FxGridItem1 *firstItem = d->firstVisibleItem();
3029 QList<FxGridItem1*>::Iterator it = d->visibleItems.begin();
3030 while (it != d->visibleItems.end()) {
3031 FxGridItem1 *item = *it;
3032 if (item->index >= from && item->index < from + count) {
3033 // take the items that are moving
3034 item->index += (to-from);
3035 moved.insert(item->index, item);
3036 it = d->visibleItems.erase(it);
3038 if (item->index > from && item->index != -1) {
3039 // move everything after the moved items.
3040 item->index -= count;
3041 if (item->index < d->visibleIndex)
3042 d->visibleIndex = item->index;
3048 int remaining = count;
3049 int endIndex = d->visibleIndex;
3050 it = d->visibleItems.begin();
3051 while (it != d->visibleItems.end()) {
3052 FxGridItem1 *item = *it;
3053 if (remaining && item->index >= to && item->index < to + count) {
3054 // place items in the target position, reusing any existing items
3055 FxGridItem1 *movedItem = moved.take(item->index);
3057 movedItem = d->createItem(item->index);
3058 it = d->visibleItems.insert(it, movedItem);
3059 if (it == d->visibleItems.begin() && firstItem)
3060 movedItem->setPosition(firstItem->colPos(), firstItem->rowPos());
3064 if (item->index != -1) {
3065 if (item->index >= to) {
3066 // update everything after the moved items.
3067 item->index += count;
3069 endIndex = item->index;
3075 // If we have moved items to the end of the visible items
3076 // then add any existing moved items that we have
3077 while (FxGridItem1 *item = moved.take(endIndex+1)) {
3078 d->visibleItems.append(item);
3082 // update visibleIndex
3083 for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
3084 if ((*it)->index != -1) {
3085 d->visibleIndex = (*it)->index;
3090 // Fix current index
3091 if (d->currentIndex >= 0 && d->currentItem) {
3092 int oldCurrent = d->currentIndex;
3093 d->currentIndex = d->model->indexOf(d->currentItem->item, this);
3094 if (oldCurrent != d->currentIndex) {
3095 d->currentItem->index = d->currentIndex;
3096 emit currentIndexChanged();
3100 // Whatever moved items remain are no longer visible items.
3101 while (moved.count()) {
3102 int idx = moved.begin().key();
3103 FxGridItem1 *item = moved.take(idx);
3104 if (d->currentItem && item->item == d->currentItem->item)
3105 item->setPosition(d->colPosAt(idx), d->rowPosAt(idx));
3106 d->releaseItem(item);
3112 void QDeclarative1GridView::modelReset()
3114 Q_D(QDeclarative1GridView);
3117 d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
3118 d->updateCurrent(d->currentIndex);
3119 if (d->highlight && d->currentItem) {
3120 if (d->autoHighlight)
3121 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
3122 d->updateTrackedItem();
3124 d->moveReason = QDeclarative1GridViewPrivate::Other;
3126 emit countChanged();
3129 void QDeclarative1GridView::createdItem(int index, QDeclarativeItem *item)
3131 Q_D(QDeclarative1GridView);
3132 if (d->requestedIndex != index) {
3133 item->setParentItem(this);
3134 d->unrequestedItems.insert(item, index);
3135 if (d->flow == QDeclarative1GridView::LeftToRight) {
3136 item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
3138 item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
3143 void QDeclarative1GridView::destroyingItem(QDeclarativeItem *item)
3145 Q_D(QDeclarative1GridView);
3146 d->unrequestedItems.remove(item);
3149 void QDeclarative1GridView::animStopped()
3151 Q_D(QDeclarative1GridView);
3152 d->bufferMode = QDeclarative1GridViewPrivate::NoBuffer;
3153 if (d->haveHighlightRange && d->highlightRange == QDeclarative1GridView::StrictlyEnforceRange)
3154 d->updateHighlight();
3157 void QDeclarative1GridView::refill()
3159 Q_D(QDeclarative1GridView);
3160 if (d->isRightToLeftTopToBottom())
3161 d->refill(-d->position()-d->size()+1, -d->position());
3163 d->refill(d->position(), d->position()+d->size()-1);
3167 QDeclarative1GridViewAttached *QDeclarative1GridView::qmlAttachedProperties(QObject *obj)
3169 return new QDeclarative1GridViewAttached(obj);