Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / qtquick1 / graphicsitems / qdeclarativegridview.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "QtQuick1/private/qdeclarativegridview_p.h"
43
44 #include "QtQuick1/private/qdeclarativevisualitemmodel_p.h"
45 #include "QtQuick1/private/qdeclarativeflickable_p_p.h"
46
47 #include "QtQuick1/private/qdeclarativesmoothedanimation_p_p.h"
48 #include <QtDeclarative/private/qdeclarativeguard_p.h>
49
50 #include <QKeyEvent>
51
52 #include <qmath.h>
53 #include <math.h>
54 #include "qplatformdefs.h"
55
56 QT_BEGIN_NAMESPACE
57
58 #ifndef QML_FLICK_SNAPONETHRESHOLD
59 #define QML_FLICK_SNAPONETHRESHOLD 30
60 #endif
61
62 //----------------------------------------------------------------------------
63
64 class FxGridItem1
65 {
66 public:
67     FxGridItem1(QDeclarativeItem *i, QDeclarative1GridView *v) : item(i), view(v) {
68         attached = static_cast<QDeclarative1GridViewAttached*>(qmlAttachedPropertiesObject<QDeclarative1GridView>(item));
69         if (attached)
70             attached->setView(view);
71     }
72     ~FxGridItem1() {}
73
74     qreal rowPos() const {
75         qreal rowPos = 0;
76         if (view->flow() == QDeclarative1GridView::LeftToRight) {
77             rowPos = item->y();
78         } else {
79             if (view->effectiveLayoutDirection() == Qt::RightToLeft)
80                 rowPos = -view->cellWidth()-item->x();
81             else
82                 rowPos = item->x();
83         }
84         return rowPos;
85     }
86     qreal colPos() const {
87         qreal colPos = 0;
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();
93             } else {
94                 colPos = item->x();
95             }
96         } else {
97             colPos = item->y();
98         }
99
100         return colPos;
101     }
102
103     qreal endRowPos() const {
104         if (view->flow() == QDeclarative1GridView::LeftToRight) {
105             return item->y() + view->cellHeight() - 1;
106         } else {
107             if (view->effectiveLayoutDirection() == Qt::RightToLeft)
108                 return -item->x() - 1;
109             else
110                 return item->x() + view->cellWidth() - 1;
111         }
112     }
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));
118             } else {
119                 item->setPos(QPointF(-view->cellWidth()-row, col));
120             }
121         } else {
122             if (view->flow() == QDeclarative1GridView::LeftToRight)
123                 item->setPos(QPointF(col, row));
124             else
125                 item->setPos(QPointF(row, col));
126         }
127
128     }
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());
132     }
133
134     QDeclarativeItem *item;
135     QDeclarative1GridView *view;
136     QDeclarative1GridViewAttached *attached;
137     int index;
138 };
139
140 //----------------------------------------------------------------------------
141
142 class QDeclarative1GridViewPrivate : public QDeclarative1FlickablePrivate
143 {
144     Q_DECLARE_PUBLIC(QDeclarative1GridView)
145
146 public:
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) {}
162
163     void init();
164     void clear();
165     FxGridItem1 *createItem(int modelIndex);
166     void releaseItem(FxGridItem1 *item);
167     void refill(qreal from, qreal to, bool doBuffer=false);
168
169     void updateGrid();
170     void scheduleLayout();
171     void layout();
172     void updateUnrequestedIndexes();
173     void updateUnrequestedPositions();
174     void updateTrackedItem();
175     void createHighlight();
176     void updateHighlight();
177     void updateCurrent(int modelIndex);
178     void updateHeader();
179     void updateFooter();
180     void fixupPosition();
181
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)
187                     return item;
188             }
189         }
190         return 0;
191     }
192
193     bool isRightToLeftTopToBottom() const {
194         Q_Q(const QDeclarative1GridView);
195         return flow == QDeclarative1GridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
196     }
197
198     void regenerate() {
199         Q_Q(QDeclarative1GridView);
200         if (q->isComponentComplete()) {
201             clear();
202             updateGrid();
203             setPosition(0);
204             q->refill();
205             updateCurrent(currentIndex);
206         }
207     }
208
209     void mirrorChange() {
210         Q_Q(QDeclarative1GridView);
211         regenerate();
212         emit q->effectiveLayoutDirectionChanged();
213     }
214
215     qreal position() const {
216         Q_Q(const QDeclarative1GridView);
217         return flow == QDeclarative1GridView::LeftToRight ? q->contentY() : q->contentX();
218     }
219     void setPosition(qreal pos) {
220         Q_Q(QDeclarative1GridView);
221         if (flow == QDeclarative1GridView::LeftToRight) {
222             q->QDeclarative1Flickable::setContentY(pos);
223             q->QDeclarative1Flickable::setContentX(0);
224         } else {
225             if (q->effectiveLayoutDirection() == Qt::LeftToRight)
226                 q->QDeclarative1Flickable::setContentX(pos);
227             else
228                 q->QDeclarative1Flickable::setContentX(-pos-size());
229             q->QDeclarative1Flickable::setContentY(0);
230         }
231     }
232     int size() const {
233         Q_Q(const QDeclarative1GridView);
234         return flow == QDeclarative1GridView::LeftToRight ? q->height() : q->width();
235     }
236     qreal originPosition() const {
237         qreal pos = 0;
238         if (!visibleItems.isEmpty())
239             pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
240         return pos;
241     }
242
243     qreal lastPosition() const {
244         qreal pos = 0;
245         if (model && model->count())
246             pos = rowPosAt(model->count() - 1) + rowSize();
247         return pos;
248     }
249
250     qreal startPosition() const {
251         return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
252     }
253
254     qreal endPosition() const {
255         return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
256
257     }
258
259     bool isValid() const {
260         return model && model->count() && model->isValid();
261     }
262
263     int rowSize() const {
264         return flow == QDeclarative1GridView::LeftToRight ? cellHeight : cellWidth;
265     }
266     int colSize() const {
267         return flow == QDeclarative1GridView::LeftToRight ? cellWidth : cellHeight;
268     }
269
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();
279             } else {
280                 int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
281                 return visibleItems.last()->colPos() - count * colSize();
282             }
283         } else {
284             return (modelIndex % columns) * colSize();
285         }
286         return 0;
287     }
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();
297             } else {
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();
302             }
303         } else {
304             qreal pos = (modelIndex / columns) * rowSize();
305             if (header)
306                 pos += headerSize();
307             return pos;
308         }
309         return 0;
310     }
311
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)
317                 return item;
318         }
319         return visibleItems.count() ? visibleItems.first() : 0;
320     }
321
322     int lastVisibleIndex() const {
323         for (int i = 0; i < visibleItems.count(); ++i) {
324             FxGridItem1 *item = visibleItems.at(i);
325             if (item->index != -1)
326                 return item->index;
327         }
328         return -1;
329     }
330
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())
336             return -1;
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)
342                 return -1;
343         }
344         return -1; // Not in visibleList
345     }
346
347     qreal snapPosAt(qreal pos) const {
348         Q_Q(const QDeclarative1GridView);
349         qreal snapPos = 0;
350         if (!visibleItems.isEmpty()) {
351             qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart;
352             pos += highlightStart;
353             pos += rowSize()/2;
354             snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
355             snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
356             snapPos -= highlightStart;
357             qreal maxExtent;
358             qreal minExtent;
359             if (isRightToLeftTopToBottom()) {
360                 maxExtent = q->minXExtent();
361                 minExtent = q->maxXExtent();
362             } else {
363                 maxExtent = flow == QDeclarative1GridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
364                 minExtent = flow == QDeclarative1GridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
365             }
366             if (snapPos > maxExtent)
367                 snapPos = maxExtent;
368             if (snapPos < minExtent)
369                 snapPos = minExtent;
370         }
371         return snapPos;
372     }
373
374     FxGridItem1 *snapItemAt(qreal pos) {
375         for (int i = 0; i < visibleItems.count(); ++i) {
376             FxGridItem1 *item = visibleItems[i];
377             if (item->index == -1)
378                 continue;
379             qreal itemTop = item->rowPos();
380             if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
381                 return item;
382         }
383         return 0;
384     }
385
386     int snapIndex() {
387         int index = currentIndex;
388         for (int i = 0; i < visibleItems.count(); ++i) {
389             FxGridItem1 *item = visibleItems[i];
390             if (item->index == -1)
391                 continue;
392             qreal itemTop = item->rowPos();
393             if (itemTop >= highlight->rowPos()-rowSize()/2 && itemTop < highlight->rowPos()+rowSize()/2) {
394                 index = item->index;
395                 if (item->colPos() >= highlight->colPos()-colSize()/2 && item->colPos() < highlight->colPos()+colSize()/2)
396                     return item->index;
397             }
398         }
399         return index;
400     }
401
402     qreal headerSize() const {
403         if (!header)
404             return 0.0;
405
406         return flow == QDeclarative1GridView::LeftToRight
407                        ? header->item->height()
408                        : header->item->width();
409     }
410
411
412     virtual void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
413         Q_Q(const QDeclarative1GridView);
414         QDeclarative1FlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
415         if (item == q) {
416             if (newGeometry.height() != oldGeometry.height()
417                 || newGeometry.width() != oldGeometry.width()) {
418                 if (q->isComponentComplete()) {
419                     updateGrid();
420                     scheduleLayout();
421                 }
422             }
423         } else if ((header && header->item == item) || (footer && footer->item == item)) {
424             if (header)
425                 updateHeader();
426             if (footer)
427                 updateFooter();
428         }
429     }
430
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);
435
436     // for debugging only
437     void checkVisible() const {
438         int skip = 0;
439         for (int i = 0; i < visibleItems.count(); ++i) {
440             FxGridItem1 *listItem = visibleItems.at(i);
441             if (listItem->index == -1) {
442                 ++skip;
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);
447             }
448         }
449     }
450
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;
458     int visibleIndex;
459     int currentIndex;
460     int cellWidth;
461     int cellHeight;
462     int columns;
463     int requestedIndex;
464     int itemCount;
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;
475     int buffer;
476     QSmoothedAnimation_1 *highlightXAnimator;
477     QSmoothedAnimation_1 *highlightYAnimator;
478     int highlightMoveDuration;
479     QDeclarativeComponent *footerComponent;
480     FxGridItem1 *footer;
481     QDeclarativeComponent *headerComponent;
482     FxGridItem1 *header;
483     enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
484     int bufferMode;
485     QDeclarative1GridView::SnapMode snapMode;
486
487     bool ownModel : 1;
488     bool wrap : 1;
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;
496 };
497
498 void QDeclarative1GridViewPrivate::init()
499 {
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);
505 }
506
507 void QDeclarative1GridViewPrivate::clear()
508 {
509     for (int i = 0; i < visibleItems.count(); ++i)
510         releaseItem(visibleItems.at(i));
511     visibleItems.clear();
512     visibleIndex = 0;
513     releaseItem(currentItem);
514     currentItem = 0;
515     createHighlight();
516     trackedItem = 0;
517     itemCount = 0;
518 }
519
520 FxGridItem1 *QDeclarative1GridViewPrivate::createItem(int modelIndex)
521 {
522     Q_Q(QDeclarative1GridView);
523     // create object
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()) {
530             // complete
531             listItem->item->setZValue(1);
532             listItem->item->setParentItem(q->contentItem());
533             model->completeItem();
534         } else {
535             listItem->item->setParentItem(q->contentItem());
536         }
537         unrequestedItems.remove(listItem->item);
538     }
539     requestedIndex = -1;
540     return listItem;
541 }
542
543
544 void QDeclarative1GridViewPrivate::releaseItem(FxGridItem1 *item)
545 {
546     Q_Q(QDeclarative1GridView);
547     if (!item || !model)
548         return;
549     if (trackedItem == item) {
550         QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
551         QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
552         trackedItem = 0;
553     }
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));
557     }
558     delete item;
559 }
560
561 void QDeclarative1GridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
562 {
563     Q_Q(QDeclarative1GridView);
564     if (!isValid() || !q->isComponentComplete())
565         return;
566     itemCount = model->count();
567     qreal bufferFrom = from - buffer;
568     qreal bufferTo = to + buffer;
569     qreal fillFrom = from;
570     qreal fillTo = to;
571     if (doBuffer && (bufferMode & BufferAfter))
572         fillTo = bufferTo;
573     if (doBuffer && (bufferMode & BufferBefore))
574         fillFrom = bufferFrom;
575
576     bool changed = false;
577
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)) {
585             colPos = 0;
586             rowPos += rowSize();
587         }
588         int i = visibleItems.count() - 1;
589         while (i > 0 && visibleItems.at(i)->index == -1)
590             --i;
591         modelIndex = visibleItems.at(i)->index + 1;
592     }
593
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();
602         modelIndex += count;
603         if (modelIndex >= model->count())
604             modelIndex = model->count() - 1;
605         else if (modelIndex < 0)
606             modelIndex = 0;
607         modelIndex = modelIndex / columns * columns;
608         visibleIndex = modelIndex;
609         colPos = colPosAt(visibleIndex);
610         rowPos = rowPosAt(visibleIndex);
611     }
612
613     int colNum = colPos / colSize();
614
615     FxGridItem1 *item = 0;
616
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)))
623             break;
624         item->setPosition(colPos, rowPos);
625         visibleItems.append(item);
626         colPos += colSize();
627         colNum++;
628         if (colPos > colSize() * (columns-1)) {
629             colPos = 0;
630             colNum = 0;
631             rowPos += rowSize();
632         }
633         ++modelIndex;
634         changed = true;
635         if (doBuffer) // never buffer more than one item per frame
636             break;
637     }
638
639     if (visibleItems.count()) {
640         rowPos = visibleItems.first()->rowPos();
641         colPos = visibleItems.first()->colPos() - colSize();
642         if (colPos < 0) {
643             colPos = colSize() * (columns - 1);
644             rowPos -= rowSize();
645         }
646     }
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)))
651             break;
652         --visibleIndex;
653         item->setPosition(colPos, rowPos);
654         visibleItems.prepend(item);
655         colPos -= colSize();
656         colNum--;
657         if (colPos < 0) {
658             colPos = colSize() * (columns - 1);
659             colNum = columns-1;
660             rowPos -= rowSize();
661         }
662         changed = true;
663         if (doBuffer) // never buffer more than one item per frame
664             break;
665     }
666
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())
672                 break;
673 //            qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
674             if (item->index != -1)
675                 visibleIndex++;
676             visibleItems.removeFirst();
677             releaseItem(item);
678             changed = true;
679         }
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())
684                 break;
685 //            qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
686             visibleItems.removeLast();
687             releaseItem(item);
688             changed = true;
689         }
690         deferredRelease = false;
691     } else {
692         deferredRelease = true;
693     }
694     if (changed) {
695         if (header)
696             updateHeader();
697         if (footer)
698             updateFooter();
699         if (flow == QDeclarative1GridView::LeftToRight)
700             q->setContentHeight(endPosition() - startPosition());
701         else
702             q->setContentWidth(endPosition() - startPosition());
703     } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
704         refill(from, to, true);
705     }
706     lazyRelease = false;
707 }
708
709 void QDeclarative1GridViewPrivate::updateGrid()
710 {
711     Q_Q(QDeclarative1GridView);
712
713     columns = (int)qMax((flow == QDeclarative1GridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
714     if (isValid()) {
715         if (flow == QDeclarative1GridView::LeftToRight)
716             q->setContentHeight(endPosition() - startPosition());
717         else
718             q->setContentWidth(lastPosition() - originPosition());
719     }
720 }
721
722 void QDeclarative1GridViewPrivate::scheduleLayout()
723 {
724     Q_Q(QDeclarative1GridView);
725     if (!layoutScheduled) {
726         layoutScheduled = true;
727         QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority);
728     }
729 }
730
731 void QDeclarative1GridViewPrivate::layout()
732 {
733     Q_Q(QDeclarative1GridView);
734     layoutScheduled = false;
735     if (!isValid() && !visibleItems.count()) {
736         clear();
737         return;
738     }
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);
746         }
747         for (int i = 1; i < visibleItems.count(); ++i) {
748             FxGridItem1 *item = visibleItems.at(i);
749             colPos += colSize();
750             if (colPos > colSize() * (columns-1)) {
751                 colPos = 0;
752                 rowPos += rowSize();
753             }
754             item->setPosition(colPos, rowPos);
755         }
756     }
757     if (header)
758         updateHeader();
759     if (footer)
760         updateFooter();
761     q->refill();
762     updateHighlight();
763     moveReason = Other;
764     if (flow == QDeclarative1GridView::LeftToRight) {
765         q->setContentHeight(endPosition() - startPosition());
766         fixupY();
767     } else {
768         q->setContentWidth(endPosition() - startPosition());
769         fixupX();
770     }
771     updateUnrequestedPositions();
772 }
773
774 void QDeclarative1GridViewPrivate::updateUnrequestedIndexes()
775 {
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);
780 }
781
782 void QDeclarative1GridViewPrivate::updateUnrequestedPositions()
783 {
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)));
789         } else {
790             if (isRightToLeftTopToBottom())
791                 item->setPos(QPointF(-rowPosAt(*it)-item->width(), colPosAt(*it)));
792             else
793                 item->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
794         }
795     }
796 }
797
798 void QDeclarative1GridViewPrivate::updateTrackedItem()
799 {
800     Q_Q(QDeclarative1GridView);
801     FxGridItem1 *item = currentItem;
802     if (highlight)
803         item = highlight;
804
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()));
808         trackedItem = 0;
809     }
810
811     if (!trackedItem && item) {
812         trackedItem = item;
813         QObject::connect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged()));
814         QObject::connect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged()));
815     }
816     if (trackedItem)
817         q->trackedPositionChanged();
818 }
819
820 void QDeclarative1GridViewPrivate::createHighlight()
821 {
822     Q_Q(QDeclarative1GridView);
823     bool changed = false;
824     if (highlight) {
825         if (trackedItem == highlight)
826             trackedItem = 0;
827         if (highlight->item->scene())
828             highlight->item->scene()->removeItem(highlight->item);
829         highlight->item->deleteLater();
830         delete highlight;
831         highlight = 0;
832         delete highlightXAnimator;
833         delete highlightYAnimator;
834         highlightXAnimator = 0;
835         highlightYAnimator = 0;
836         changed = true;
837     }
838
839     if (currentItem) {
840         QDeclarativeItem *item = 0;
841         if (highlightComponent) {
842             QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
843             QObject *nobj = highlightComponent->create(highlightContext);
844             if (nobj) {
845                 QDeclarative_setParent_noEvent(highlightContext, nobj);
846                 item = qobject_cast<QDeclarativeItem *>(nobj);
847                 if (!item)
848                     delete nobj;
849             } else {
850                 delete highlightContext;
851             }
852         } else {
853             item = new QDeclarativeItem;
854             QDeclarative_setParent_noEvent(item, q->contentItem());
855             item->setParentItem(q->contentItem());
856         }
857         if (item) {
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;
869             if (autoHighlight) {
870                 highlightXAnimator->restart();
871                 highlightYAnimator->restart();
872             }
873             changed = true;
874         }
875     }
876     if (changed)
877         emit q->highlightItemChanged();
878 }
879
880 void QDeclarative1GridViewPrivate::updateHighlight()
881 {
882     if ((!currentItem && highlight) || (currentItem && !highlight))
883         createHighlight();
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();
892     }
893     updateTrackedItem();
894 }
895
896 void QDeclarative1GridViewPrivate::updateCurrent(int modelIndex)
897 {
898     Q_Q(QDeclarative1GridView);
899     if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) {
900         if (currentItem) {
901             currentItem->attached->setIsCurrentItem(false);
902             releaseItem(currentItem);
903             currentItem = 0;
904             currentIndex = modelIndex;
905             emit q->currentIndexChanged();
906             updateHighlight();
907         } else if (currentIndex != modelIndex) {
908             currentIndex = modelIndex;
909             emit q->currentIndexChanged();
910         }
911         return;
912     }
913
914     if (currentItem && currentIndex == modelIndex) {
915         updateHighlight();
916         return;
917     }
918
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);
925     if (currentItem) {
926         currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex));
927         currentItem->item->setFocus(true);
928         currentItem->attached->setIsCurrentItem(true);
929     }
930     updateHighlight();
931     emit q->currentIndexChanged();
932     releaseItem(oldCurrentItem);
933 }
934
935 void QDeclarative1GridViewPrivate::updateFooter()
936 {
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);
942         if (nobj) {
943             QDeclarative_setParent_noEvent(context, nobj);
944             item = qobject_cast<QDeclarativeItem *>(nobj);
945             if (!item)
946                 delete nobj;
947         } else {
948             delete context;
949         }
950         if (item) {
951             QDeclarative_setParent_noEvent(item, q->contentItem());
952             item->setParentItem(q->contentItem());
953             item->setZValue(1);
954             QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
955             itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
956             footer = new FxGridItem1(item, q);
957         }
958     }
959     if (footer) {
960         qreal colOffset = 0;
961         qreal rowOffset;
962         if (isRightToLeftTopToBottom()) {
963             rowOffset = footer->item->width()-cellWidth;
964         } else {
965             rowOffset = 0;
966             if (q->effectiveLayoutDirection() == Qt::RightToLeft)
967                 colOffset = footer->item->width()-cellWidth;
968         }
969         if (visibleItems.count()) {
970             qreal endPos = lastPosition();
971             if (lastVisibleIndex() == model->count()-1) {
972                 footer->setPosition(colOffset, endPos + rowOffset);
973             } else {
974                 qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
975                 if (endPos <= visiblePos || footer->endRowPos() < endPos + rowOffset)
976                     footer->setPosition(colOffset, endPos + rowOffset);
977             }
978         } else {
979             qreal endPos = 0;
980             if (header) {
981                 endPos += flow == QDeclarative1GridView::LeftToRight ? header->item->height() : header->item->width();
982             }
983             footer->setPosition(colOffset, endPos);
984         }
985     }
986 }
987
988 void QDeclarative1GridViewPrivate::updateHeader()
989 {
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);
995         if (nobj) {
996             QDeclarative_setParent_noEvent(context, nobj);
997             item = qobject_cast<QDeclarativeItem *>(nobj);
998             if (!item)
999                 delete nobj;
1000         } else {
1001             delete context;
1002         }
1003         if (item) {
1004             QDeclarative_setParent_noEvent(item, q->contentItem());
1005             item->setParentItem(q->contentItem());
1006             item->setZValue(1);
1007             QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
1008             itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
1009             header = new FxGridItem1(item, q);
1010         }
1011     }
1012     if (header) {
1013         qreal colOffset = 0;
1014         qreal rowOffset;
1015         if (isRightToLeftTopToBottom()) {
1016             rowOffset = -cellWidth;
1017         } else {
1018             rowOffset = -headerSize();
1019             if (q->effectiveLayoutDirection() == Qt::RightToLeft)
1020                 colOffset = header->item->width()-cellWidth;
1021         }
1022         if (visibleItems.count()) {
1023             qreal startPos = originPosition();
1024             if (visibleIndex == 0) {
1025                 header->setPosition(colOffset, startPos + rowOffset);
1026             } else {
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);
1031             }
1032         } else {
1033             header->setPosition(colOffset, 0);
1034         }
1035     }
1036 }
1037
1038 void QDeclarative1GridViewPrivate::fixupPosition()
1039 {
1040     moveReason = Other;
1041     if (flow == QDeclarative1GridView::LeftToRight)
1042         fixupY();
1043     else
1044         fixupX();
1045 }
1046
1047 void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
1048 {
1049     if ((flow == QDeclarative1GridView::TopToBottom && &data == &vData)
1050         || (flow == QDeclarative1GridView::LeftToRight && &data == &hData))
1051         return;
1052
1053     fixupMode = moveReason == Mouse ? fixupMode : Immediate;
1054
1055     qreal highlightStart;
1056     qreal highlightEnd;
1057     qreal viewPos;
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;
1063     } else {
1064         viewPos = position();
1065         highlightStart = highlightRangeStart;
1066         highlightEnd = highlightRangeEnd;
1067     }
1068
1069     bool strictHighlightRange = haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange;
1070
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);
1076             qreal bias = 0;
1077             if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < rowSize()/2)
1078                 bias = rowSize()/2;
1079             else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -rowSize()/2)
1080                 bias = -rowSize()/2;
1081             if (isRightToLeftTopToBottom())
1082                 bias = -bias;
1083             tempPosition -= bias;
1084         }
1085         FxGridItem1 *topItem = snapItemAt(tempPosition+highlightStart);
1086         if (!topItem && strictHighlightRange && currentItem) {
1087             // StrictlyEnforceRange always keeps an item in range
1088             updateHighlight();
1089             topItem = currentItem;
1090         }
1091         FxGridItem1 *bottomItem = snapItemAt(tempPosition+highlightEnd);
1092         if (!bottomItem && strictHighlightRange && currentItem) {
1093             // StrictlyEnforceRange always keeps an item in range
1094             updateHighlight();
1095             bottomItem = currentItem;
1096         }
1097         qreal pos;
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;
1102             } else {
1103                 if (isRightToLeftTopToBottom())
1104                     pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
1105                 else
1106                     pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
1107             }
1108         } else if (bottomItem && isInBounds) {
1109             if (isRightToLeftTopToBottom())
1110                 pos = qMax(qMin(-bottomItem->rowPos() + highlightEnd - size(), -maxExtent), -minExtent);
1111             else
1112                 pos = qMax(qMin(bottomItem->rowPos() - highlightEnd, -maxExtent), -minExtent);
1113         } else {
1114             QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
1115             return;
1116         }
1117         qreal dist = qAbs(data.move + pos);
1118         if (dist > 0) {
1119             timeline.reset(data.move);
1120             if (fixupMode != Immediate) {
1121                 timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
1122                 data.fixingUp = true;
1123             } else {
1124                 timeline.set(data.move, -pos);
1125             }
1126             vTime = timeline.time();
1127         }
1128     } else if (haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange) {
1129         if (currentItem) {
1130             updateHighlight();
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;
1143                 } else {
1144                     timeline.set(data.move, -viewPos);
1145                 }
1146             }
1147             vTime = timeline.time();
1148         }
1149     } else {
1150         QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent);
1151     }
1152     data.inOvershoot = false;
1153     fixupMode = Normal;
1154 }
1155
1156 void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
1157                                         QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity)
1158 {
1159     Q_Q(QDeclarative1GridView);
1160     data.fixingUp = false;
1161     moveReason = Mouse;
1162     if ((!haveHighlightRange || highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
1163         && snapMode == QDeclarative1GridView::NoSnap) {
1164         QDeclarative1FlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
1165         return;
1166     }
1167     qreal maxDistance = 0;
1168     qreal dataValue = isRightToLeftTopToBottom() ? -data.move.value()+size() : data.move.value();
1169     // -ve velocity means list is moving up/left
1170     if (velocity > 0) {
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())
1177                     bias = -bias;
1178                 data.flickTarget = -snapPosAt(-dataValue - bias);
1179                 maxDistance = qAbs(data.flickTarget - data.move.value());
1180                 velocity = maxVelocity;
1181             } else {
1182                 maxDistance = qAbs(minExtent - data.move.value());
1183             }
1184         }
1185         if (snapMode == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
1186             data.flickTarget = minExtent;
1187     } else {
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())
1194                     bias = -bias;
1195                 data.flickTarget = -snapPosAt(-dataValue + bias);
1196                 maxDistance = qAbs(data.flickTarget - data.move.value());
1197                 velocity = -maxVelocity;
1198             } else {
1199                 maxDistance = qAbs(maxExtent - data.move.value());
1200             }
1201         }
1202         if (snapMode == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange)
1203             data.flickTarget = maxExtent;
1204     }
1205
1206     bool overShoot = boundsBehavior == QDeclarative1Flickable::DragAndOvershootBounds;
1207
1208     if (maxDistance > 0 || overShoot) {
1209         // This mode requires the grid to stop exactly on a row boundary.
1210         qreal v = velocity;
1211         if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
1212             if (v < 0)
1213                 v = -maxVelocity;
1214             else
1215                 v = maxVelocity;
1216         }
1217         qreal accel = deceleration;
1218         qreal v2 = v * v;
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);
1224             if (v > 0)
1225                 dist = -dist;
1226             if (snapMode != QDeclarative1GridView::SnapOneRow) {
1227                 qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist;
1228                 data.flickTarget = -snapPosAt(-dataValue + distTemp);
1229             }
1230             data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget;
1231             if (overShoot) {
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;
1238                 }
1239             }
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);
1244                 if (adjv2 > v2) {
1245                     v2 = adjv2;
1246                     v = qSqrt(v2);
1247                     if (dist > 0)
1248                         v = -v;
1249                 }
1250             }
1251             dist = adjDist;
1252             accel = v2 / (2.0f * qAbs(dist));
1253         } else {
1254             data.flickTarget = velocity > 0 ? minExtent : maxExtent;
1255             overshootDist = overShoot ? overShootDistance(vSize) : 0;
1256         }
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();
1265         }
1266         if (!vData.flicking && q->yflick()) {
1267             vData.flicking = true;
1268             emit q->flickingChanged();
1269             emit q->flickingVerticallyChanged();
1270             emit q->flickStarted();
1271         }
1272     } else {
1273         timeline.reset(data.move);
1274         fixup(data, minExtent, maxExtent);
1275     }
1276 }
1277
1278
1279 //----------------------------------------------------------------------------
1280
1281 /*!
1282     \qmlclass GridView QDeclarative1GridView
1283     \inqmlmodule QtQuick 1
1284     \since QtQuick 1.0
1285     \ingroup qml-view-elements
1286
1287     \inherits Flickable
1288     \brief The GridView item provides a grid view of items provided by a model.
1289
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
1292     QAbstractListModel.
1293
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.
1298
1299     \section1 Example Usage
1300
1301     The following example shows the definition of a simple list model defined
1302     in a file called \c ContactModel.qml:
1303
1304     \snippet doc/src/snippets/qtquick1/gridview/ContactModel.qml 0
1305
1306     \div {class="float-right"}
1307     \inlineimage gridview-simple.png
1308     \enddiv
1309
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.
1312
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.
1316
1317     \clearfloat
1318     \snippet doc/src/snippets/qtquick1/gridview/gridview.qml import
1319     \codeline
1320     \snippet doc/src/snippets/qtquick1/gridview/gridview.qml classdocs simple
1321
1322     \div {class="float-right"}
1323     \inlineimage gridview-highlight.png
1324     \enddiv
1325
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.
1328
1329     An improved grid view is shown below. The delegate is visually improved and is moved 
1330     into a separate \c contactDelegate component.
1331
1332     \clearfloat
1333     \snippet doc/src/snippets/qtquick1/gridview/gridview.qml classdocs advanced
1334
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).
1338
1339     Delegates are instantiated as needed and may be destroyed at any time.
1340     State should \e never be stored in a delegate.
1341
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.
1346
1347     \snippet doc/src/snippets/qtquick1/gridview/gridview.qml isCurrentItem
1348
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.
1353
1354     \sa {declarative/modelviews/gridview}{GridView example}
1355 */
1356 QDeclarative1GridView::QDeclarative1GridView(QDeclarativeItem *parent)
1357     : QDeclarative1Flickable(*(new QDeclarative1GridViewPrivate), parent)
1358 {
1359     Q_D(QDeclarative1GridView);
1360     d->init();
1361 }
1362
1363 QDeclarative1GridView::~QDeclarative1GridView()
1364 {
1365     Q_D(QDeclarative1GridView);
1366     d->clear();
1367     if (d->ownModel)
1368         delete d->model;
1369     delete d->header;
1370     delete d->footer;
1371 }
1372
1373 /*!
1374     \qmlattachedproperty bool GridView::isCurrentItem
1375     This attached property is true if this delegate is the current item; otherwise false.
1376
1377     It is attached to each instance of the delegate.
1378 */
1379
1380 /*!
1381     \qmlattachedproperty GridView GridView::view
1382     This attached property holds the view that manages this delegate instance.
1383
1384     It is attached to each instance of the delegate.
1385
1386     \snippet doc/src/snippets/qtquick1/gridview/gridview.qml isCurrentItem
1387 */
1388
1389 /*!
1390     \qmlattachedproperty bool GridView::delayRemove
1391     This attached property holds whether the delegate may be destroyed.
1392
1393     It is attached to each instance of the delegate.
1394
1395     It is sometimes necessary to delay the destruction of an item
1396     until an animation completes.
1397
1398     The example below ensures that the animation completes before
1399     the item is removed from the grid.
1400
1401     \snippet doc/src/snippets/qtquick1/gridview/gridview.qml delayRemove
1402 */
1403
1404 /*!
1405     \qmlattachedsignal QtQuick1::GridView::onAdd()
1406     This attached handler is called immediately after an item is added to the view.
1407 */
1408
1409 /*!
1410     \qmlattachedsignal QtQuick1::GridView::onRemove()
1411     This attached handler is called immediately before an item is removed from the view.
1412 */
1413
1414
1415 /*!
1416   \qmlproperty model QtQuick1::GridView::model
1417   This property holds the model providing data for the grid.
1418
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.
1423
1424   \sa {qmlmodels}{Data Models}
1425 */
1426 QVariant QDeclarative1GridView::model() const
1427 {
1428     Q_D(const QDeclarative1GridView);
1429     return d->modelVariant;
1430 }
1431
1432 // For internal use
1433 int QDeclarative1GridView::modelCount() const
1434 {
1435     Q_D(const QDeclarative1GridView);
1436     return d->model->count();
1437 }
1438
1439 void QDeclarative1GridView::setModel(const QVariant &model)
1440 {
1441     Q_D(QDeclarative1GridView);
1442     if (d->modelVariant == model)
1443         return;
1444     if (d->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*)));
1451     }
1452     d->clear();
1453     d->modelVariant = model;
1454     QObject *object = qvariant_cast<QObject*>(model);
1455     QDeclarative1VisualModel *vim = 0;
1456     if (object && (vim = qobject_cast<QDeclarative1VisualModel *>(object))) {
1457         if (d->ownModel) {
1458             delete d->model;
1459             d->ownModel = false;
1460         }
1461         d->model = vim;
1462     } else {
1463         if (!d->ownModel) {
1464             d->model = new QDeclarative1VisualDataModel(qmlContext(this), this);
1465             d->ownModel = true;
1466         }
1467         if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
1468             dataModel->setModel(model);
1469     }
1470     if (d->model) {
1471         d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore | QDeclarative1GridViewPrivate::BufferAfter;
1472         if (isComponentComplete()) {
1473             refill();
1474             if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
1475                 setCurrentIndex(0);
1476             } else {
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();
1483                 }
1484                 d->moveReason = QDeclarative1GridViewPrivate::Other;
1485             }
1486         }
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();
1494     }
1495     emit modelChanged();
1496 }
1497
1498 /*!
1499     \qmlproperty Component QtQuick1::GridView::delegate
1500
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}.
1504
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.
1509
1510     The GridView will layout the items based on the size of the root item
1511     in the delegate.
1512
1513     \note Delegates are instantiated as needed and may be destroyed at any time.
1514     State should \e never be stored in a delegate.
1515 */
1516 QDeclarativeComponent *QDeclarative1GridView::delegate() const
1517 {
1518     Q_D(const QDeclarative1GridView);
1519     if (d->model) {
1520         if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model))
1521             return dataModel->delegate();
1522     }
1523
1524     return 0;
1525 }
1526
1527 void QDeclarative1GridView::setDelegate(QDeclarativeComponent *delegate)
1528 {
1529     Q_D(QDeclarative1GridView);
1530     if (delegate == this->delegate())
1531         return;
1532
1533     if (!d->ownModel) {
1534         d->model = new QDeclarative1VisualDataModel(qmlContext(this));
1535         d->ownModel = true;
1536     }
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);
1545             d->currentItem = 0;
1546             refill();
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();
1553             }
1554             d->moveReason = QDeclarative1GridViewPrivate::Other;
1555         }
1556         if (oldCount != dataModel->count())
1557             emit countChanged();
1558         emit delegateChanged();
1559     }
1560 }
1561
1562 /*!
1563   \qmlproperty int QtQuick1::GridView::currentIndex
1564   \qmlproperty Item QtQuick1::GridView::currentItem
1565
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.
1569
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.
1573     
1574     Note that the position of the current item
1575     may only be approximate until it becomes visible in the view.
1576 */
1577 int QDeclarative1GridView::currentIndex() const
1578 {
1579     Q_D(const QDeclarative1GridView);
1580     return d->currentIndex;
1581 }
1582
1583 void QDeclarative1GridView::setCurrentIndex(int index)
1584 {
1585     Q_D(QDeclarative1GridView);
1586     if (d->requestedIndex >= 0) // currently creating item
1587         return;
1588     d->currentIndexCleared = (index == -1);
1589     if (index == d->currentIndex)
1590         return;
1591     if (isComponentComplete() && d->isValid()) {
1592         if (d->layoutScheduled)
1593             d->layout();
1594         d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
1595         d->updateCurrent(index);
1596     } else {
1597         d->currentIndex = index;
1598         emit currentIndexChanged();
1599     }
1600 }
1601
1602 QDeclarativeItem *QDeclarative1GridView::currentItem()
1603 {
1604     Q_D(QDeclarative1GridView);
1605     if (!d->currentItem)
1606         return 0;
1607     return d->currentItem->item;
1608 }
1609
1610 /*!
1611   \qmlproperty Item QtQuick1::GridView::highlightItem
1612
1613   This holds the highlight item created from the \l highlight component.
1614
1615   The highlightItem is managed by the view unless
1616   \l highlightFollowsCurrentItem is set to false.
1617
1618   \sa highlight, highlightFollowsCurrentItem
1619 */
1620 QDeclarativeItem *QDeclarative1GridView::highlightItem()
1621 {
1622     Q_D(QDeclarative1GridView);
1623     if (!d->highlight)
1624         return 0;
1625     return d->highlight->item;
1626 }
1627
1628 /*!
1629   \qmlproperty int QtQuick1::GridView::count
1630   This property holds the number of items in the view.
1631 */
1632 int QDeclarative1GridView::count() const
1633 {
1634     Q_D(const QDeclarative1GridView);
1635     if (d->model)
1636         return d->model->count();
1637     return 0;
1638 }
1639
1640 /*!
1641   \qmlproperty Component QtQuick1::GridView::highlight
1642   This property holds the component to use as the highlight.
1643
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.
1647
1648   \sa highlightItem, highlightFollowsCurrentItem
1649 */
1650 QDeclarativeComponent *QDeclarative1GridView::highlight() const
1651 {
1652     Q_D(const QDeclarative1GridView);
1653     return d->highlightComponent;
1654 }
1655
1656 void QDeclarative1GridView::setHighlight(QDeclarativeComponent *highlight)
1657 {
1658     Q_D(QDeclarative1GridView);
1659     if (highlight != d->highlightComponent) {
1660         d->highlightComponent = highlight;
1661         d->updateCurrent(d->currentIndex);
1662         emit highlightChanged();
1663     }
1664 }
1665
1666 /*!
1667   \qmlproperty bool QtQuick1::GridView::highlightFollowsCurrentItem
1668   This property sets whether the highlight is managed by the view.
1669
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
1673     by the highlight.  
1674     
1675     Here is a highlight with its motion defined by a \l {SpringAnimation} item:
1676
1677     \snippet doc/src/snippets/qtquick1/gridview/gridview.qml highlightFollowsCurrentItem
1678 */
1679 bool QDeclarative1GridView::highlightFollowsCurrentItem() const
1680 {
1681     Q_D(const QDeclarative1GridView);
1682     return d->autoHighlight;
1683 }
1684
1685 void QDeclarative1GridView::setHighlightFollowsCurrentItem(bool autoHighlight)
1686 {
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();
1695         }
1696     }
1697 }
1698
1699 /*!
1700     \qmlproperty int QtQuick1::GridView::highlightMoveDuration
1701     This property holds the move animation duration of the highlight delegate.
1702
1703     highlightFollowsCurrentItem must be true for this property
1704     to have effect.
1705
1706     The default value for the duration is 150ms.
1707
1708     \sa highlightFollowsCurrentItem
1709 */
1710 int QDeclarative1GridView::highlightMoveDuration() const
1711 {
1712     Q_D(const QDeclarative1GridView);
1713     return d->highlightMoveDuration;
1714 }
1715
1716 void QDeclarative1GridView::setHighlightMoveDuration(int duration)
1717 {
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;
1724         }
1725         emit highlightMoveDurationChanged();
1726     }
1727 }
1728
1729
1730 /*!
1731     \qmlproperty real QtQuick1::GridView::preferredHighlightBegin
1732     \qmlproperty real QtQuick1::GridView::preferredHighlightEnd
1733     \qmlproperty enumeration QtQuick1::GridView::highlightRangeMode
1734
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. 
1738
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
1746     highlight exists.
1747
1748     Valid values for \c highlightRangeMode are:
1749
1750     \list
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.
1758     \endlist
1759 */
1760 qreal QDeclarative1GridView::preferredHighlightBegin() const
1761 {
1762     Q_D(const QDeclarative1GridView);
1763     return d->highlightRangeStart;
1764 }
1765
1766 void QDeclarative1GridView::setPreferredHighlightBegin(qreal start)
1767 {
1768     Q_D(QDeclarative1GridView);
1769     d->highlightRangeStartValid = true;
1770     if (d->highlightRangeStart == start)
1771         return;
1772     d->highlightRangeStart = start;
1773     d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1774     emit preferredHighlightBeginChanged();
1775 }
1776
1777 void QDeclarative1GridView::resetPreferredHighlightBegin()
1778 {
1779     Q_D(QDeclarative1GridView);
1780     d->highlightRangeStartValid = false;
1781     if (d->highlightRangeStart == 0)
1782         return;
1783     d->highlightRangeStart = 0;
1784     emit preferredHighlightBeginChanged();
1785 }
1786
1787 qreal QDeclarative1GridView::preferredHighlightEnd() const
1788 {
1789     Q_D(const QDeclarative1GridView);
1790     return d->highlightRangeEnd;
1791 }
1792
1793 void QDeclarative1GridView::setPreferredHighlightEnd(qreal end)
1794 {
1795     Q_D(QDeclarative1GridView);
1796     d->highlightRangeEndValid = true;
1797     if (d->highlightRangeEnd == end)
1798         return;
1799     d->highlightRangeEnd = end;
1800     d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1801     emit preferredHighlightEndChanged();
1802 }
1803
1804 void QDeclarative1GridView::resetPreferredHighlightEnd()
1805 {
1806     Q_D(QDeclarative1GridView);
1807     d->highlightRangeEndValid = false;
1808     if (d->highlightRangeEnd == 0)
1809         return;
1810     d->highlightRangeEnd = 0;
1811     emit preferredHighlightEndChanged();
1812 }
1813
1814 QDeclarative1GridView::HighlightRangeMode QDeclarative1GridView::highlightRangeMode() const
1815 {
1816     Q_D(const QDeclarative1GridView);
1817     return d->highlightRange;
1818 }
1819
1820 void QDeclarative1GridView::setHighlightRangeMode(HighlightRangeMode mode)
1821 {
1822     Q_D(QDeclarative1GridView);
1823     if (d->highlightRange == mode)
1824         return;
1825     d->highlightRange = mode;
1826     d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
1827     emit highlightRangeModeChanged();
1828 }
1829
1830 /*!
1831   \qmlproperty enumeration QtQuick1::GridView::layoutDirection
1832   This property holds the layout direction of the grid.
1833
1834     Possible values:
1835
1836   \list
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.
1841   \endlist
1842
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.
1846 */
1847
1848 Qt::LayoutDirection QDeclarative1GridView::layoutDirection() const
1849 {
1850     Q_D(const QDeclarative1GridView);
1851     return d->layoutDirection;
1852 }
1853
1854 void QDeclarative1GridView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
1855 {
1856     Q_D(QDeclarative1GridView);
1857     if (d->layoutDirection != layoutDirection) {
1858         d->layoutDirection = layoutDirection;
1859         d->regenerate();
1860         emit layoutDirectionChanged();
1861         emit effectiveLayoutDirectionChanged();
1862     }
1863 }
1864
1865 /*!
1866     \qmlproperty enumeration QtQuick1::GridView::effectiveLayoutDirection
1867     This property holds the effective layout direction of the grid.
1868
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.
1872
1873     \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
1874 */
1875
1876 Qt::LayoutDirection QDeclarative1GridView::effectiveLayoutDirection() const
1877 {
1878     Q_D(const QDeclarative1GridView);
1879     if (d->effectiveLayoutMirror)
1880         return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
1881     else
1882         return d->layoutDirection;
1883 }
1884
1885 /*!
1886   \qmlproperty enumeration QtQuick1::GridView::flow
1887   This property holds the flow of the grid.
1888
1889     Possible values:
1890
1891     \list
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
1894     \endlist
1895 */
1896 QDeclarative1GridView::Flow QDeclarative1GridView::flow() const
1897 {
1898     Q_D(const QDeclarative1GridView);
1899     return d->flow;
1900 }
1901
1902 void QDeclarative1GridView::setFlow(Flow flow)
1903 {
1904     Q_D(QDeclarative1GridView);
1905     if (d->flow != flow) {
1906         d->flow = flow;
1907         if (d->flow == LeftToRight) {
1908             setContentWidth(-1);
1909             setFlickableDirection(QDeclarative1Flickable::VerticalFlick);
1910         } else {
1911             setContentHeight(-1);
1912             setFlickableDirection(QDeclarative1Flickable::HorizontalFlick);
1913         }
1914         setContentX(0);
1915         setContentY(0);
1916         d->regenerate();
1917         emit flowChanged();
1918     }
1919 }
1920
1921 /*!
1922   \qmlproperty bool QtQuick1::GridView::keyNavigationWraps
1923   This property holds whether the grid wraps key navigation
1924
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.
1928
1929     By default, key navigation is not wrapped.
1930 */
1931 bool QDeclarative1GridView::isWrapEnabled() const
1932 {
1933     Q_D(const QDeclarative1GridView);
1934     return d->wrap;
1935 }
1936
1937 void QDeclarative1GridView::setWrapEnabled(bool wrap)
1938 {
1939     Q_D(QDeclarative1GridView);
1940     if (d->wrap == wrap)
1941         return;
1942     d->wrap = wrap;
1943     emit keyNavigationWrapsChanged();
1944 }
1945
1946 /*!
1947     \qmlproperty int QtQuick1::GridView::cacheBuffer
1948     This property determines whether delegates are retained outside the
1949     visible area of the view.
1950
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.
1956
1957     Note that cacheBuffer is not a pixel buffer - it only maintains additional
1958     instantiated delegates.
1959
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
1963     scrolled.
1964 */
1965 int QDeclarative1GridView::cacheBuffer() const
1966 {
1967     Q_D(const QDeclarative1GridView);
1968     return d->buffer;
1969 }
1970
1971 void QDeclarative1GridView::setCacheBuffer(int buffer)
1972 {
1973     Q_D(QDeclarative1GridView);
1974     if (d->buffer != buffer) {
1975         d->buffer = buffer;
1976         if (isComponentComplete())
1977             refill();
1978         emit cacheBufferChanged();
1979     }
1980 }
1981
1982 /*!
1983   \qmlproperty int QtQuick1::GridView::cellWidth
1984   \qmlproperty int QtQuick1::GridView::cellHeight
1985
1986   These properties holds the width and height of each cell in the grid.
1987
1988   The default cell size is 100x100.
1989 */
1990 int QDeclarative1GridView::cellWidth() const
1991 {
1992     Q_D(const QDeclarative1GridView);
1993     return d->cellWidth;
1994 }
1995
1996 void QDeclarative1GridView::setCellWidth(int cellWidth)
1997 {
1998     Q_D(QDeclarative1GridView);
1999     if (cellWidth != d->cellWidth && cellWidth > 0) {
2000         d->cellWidth = qMax(1, cellWidth);
2001         d->updateGrid();
2002         emit cellWidthChanged();
2003         d->layout();
2004     }
2005 }
2006
2007 int QDeclarative1GridView::cellHeight() const
2008 {
2009     Q_D(const QDeclarative1GridView);
2010     return d->cellHeight;
2011 }
2012
2013 void QDeclarative1GridView::setCellHeight(int cellHeight)
2014 {
2015     Q_D(QDeclarative1GridView);
2016     if (cellHeight != d->cellHeight && cellHeight > 0) {
2017         d->cellHeight = qMax(1, cellHeight);
2018         d->updateGrid();
2019         emit cellHeightChanged();
2020         d->layout();
2021     }
2022 }
2023 /*!
2024     \qmlproperty enumeration QtQuick1::GridView::snapMode
2025
2026     This property determines how the view scrolling will settle following a drag or flick.
2027     The possible values are:
2028
2029     \list
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.
2036     \endlist
2037
2038 */
2039 QDeclarative1GridView::SnapMode QDeclarative1GridView::snapMode() const
2040 {
2041     Q_D(const QDeclarative1GridView);
2042     return d->snapMode;
2043 }
2044
2045 void QDeclarative1GridView::setSnapMode(SnapMode mode)
2046 {
2047     Q_D(QDeclarative1GridView);
2048     if (d->snapMode != mode) {
2049         d->snapMode = mode;
2050         emit snapModeChanged();
2051     }
2052 }
2053
2054 /*!
2055     \qmlproperty Component QtQuick1::GridView::footer
2056     This property holds the component to use as the footer.
2057
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.
2060
2061     \sa header
2062 */
2063 QDeclarativeComponent *QDeclarative1GridView::footer() const
2064 {
2065     Q_D(const QDeclarative1GridView);
2066     return d->footerComponent;
2067 }
2068
2069 void QDeclarative1GridView::setFooter(QDeclarativeComponent *footer)
2070 {
2071     Q_D(QDeclarative1GridView);
2072     if (d->footerComponent != footer) {
2073         if (d->footer) {
2074             if (scene())
2075                 scene()->removeItem(d->footer->item);
2076             d->footer->item->deleteLater();
2077             delete d->footer;
2078             d->footer = 0;
2079         }
2080         d->footerComponent = footer;
2081         if (isComponentComplete()) {
2082             d->updateFooter();
2083             d->updateGrid();
2084             d->fixupPosition();
2085         }
2086         emit footerChanged();
2087     }
2088 }
2089
2090 /*!
2091     \qmlproperty Component QtQuick1::GridView::header
2092     This property holds the component to use as the header.
2093
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.
2096
2097     \sa footer
2098 */
2099 QDeclarativeComponent *QDeclarative1GridView::header() const
2100 {
2101     Q_D(const QDeclarative1GridView);
2102     return d->headerComponent;
2103 }
2104
2105 void QDeclarative1GridView::setHeader(QDeclarativeComponent *header)
2106 {
2107     Q_D(QDeclarative1GridView);
2108     if (d->headerComponent != header) {
2109         if (d->header) {
2110             if (scene())
2111                 scene()->removeItem(d->header->item);
2112             d->header->item->deleteLater();
2113             delete d->header;
2114             d->header = 0;
2115         }
2116         d->headerComponent = header;
2117         if (isComponentComplete()) {
2118             d->updateHeader();
2119             d->updateFooter();
2120             d->updateGrid();
2121             d->fixupPosition();
2122         }
2123         emit headerChanged();
2124     }
2125 }
2126
2127 void QDeclarative1GridView::setContentX(qreal pos)
2128 {
2129     Q_D(QDeclarative1GridView);
2130     // Positioning the view manually should override any current movement state
2131     d->moveReason = QDeclarative1GridViewPrivate::Other;
2132     QDeclarative1Flickable::setContentX(pos);
2133 }
2134
2135 void QDeclarative1GridView::setContentY(qreal pos)
2136 {
2137     Q_D(QDeclarative1GridView);
2138     // Positioning the view manually should override any current movement state
2139     d->moveReason = QDeclarative1GridViewPrivate::Other;
2140     QDeclarative1Flickable::setContentY(pos);
2141 }
2142
2143 bool QDeclarative1GridView::event(QEvent *event)
2144 {
2145     Q_D(QDeclarative1GridView);
2146     if (event->type() == QEvent::User) {
2147         if (d->layoutScheduled)
2148             d->layout();
2149         return true;
2150     }
2151
2152     return QDeclarative1Flickable::event(event);
2153 }
2154
2155 void QDeclarative1GridView::viewportMoved()
2156 {
2157     Q_D(QDeclarative1GridView);
2158     QDeclarative1Flickable::viewportMoved();
2159     if (!d->itemCount)
2160         return;
2161     d->lazyRelease = true;
2162     if (d->hData.flicking || d->vData.flicking) {
2163         if (yflick()) {
2164             if (d->vData.velocity > 0)
2165                 d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore;
2166             else if (d->vData.velocity < 0)
2167                 d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter;
2168         }
2169
2170         if (xflick()) {
2171             if (d->hData.velocity > 0)
2172                 d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore;
2173             else if (d->hData.velocity < 0)
2174                 d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter;
2175         }
2176     }
2177     refill();
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();
2184             qreal viewPos;
2185             qreal highlightStart;
2186             qreal highlightEnd;
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();
2191             } else {
2192                 highlightStart = d->highlightRangeStart;
2193                 highlightEnd = d->highlightRangeEnd;
2194                 viewPos = d->position();
2195             }
2196             if (pos > viewPos + highlightEnd - d->rowSize())
2197                 pos = viewPos + highlightEnd - d->rowSize();
2198             if (pos < viewPos + highlightStart)
2199                 pos = viewPos + highlightStart;
2200
2201             d->highlight->setPosition(d->highlight->colPos(), qRound(pos));
2202
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();
2210                     else
2211                         d->highlightYAnimator->to = d->currentItem->item->y();
2212                 }
2213             }
2214         }
2215     }
2216 }
2217
2218 qreal QDeclarative1GridView::minYExtent() const
2219 {
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));
2229     }
2230     return extent;
2231 }
2232
2233 qreal QDeclarative1GridView::maxYExtent() const
2234 {
2235     Q_D(const QDeclarative1GridView);
2236     if (d->flow == QDeclarative1GridView::TopToBottom)
2237         return QDeclarative1Flickable::maxYExtent();
2238     qreal extent;
2239     if (!d->model || !d->model->count()) {
2240         extent = 0;
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));
2245     } else {
2246         extent = -(d->endPosition() - height());
2247     }
2248     if (d->footer)
2249         extent -= d->footer->item->height();
2250     const qreal minY = minYExtent();
2251     if (extent > minY)
2252         extent = minY;
2253     return extent;
2254 }
2255
2256 qreal QDeclarative1GridView::minXExtent() const
2257 {
2258     Q_D(const QDeclarative1GridView);
2259     if (d->flow == QDeclarative1GridView::LeftToRight)
2260         return QDeclarative1Flickable::minXExtent();
2261     qreal extent = -d->startPosition();
2262     qreal highlightStart;
2263     qreal highlightEnd;
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();
2274     } else {
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();
2280     }
2281     if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
2282         extent += d->isRightToLeftTopToBottom() ? -highlightStart : highlightStart;
2283         extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
2284     }
2285     return extent;
2286 }
2287
2288 qreal QDeclarative1GridView::maxXExtent() const
2289 {
2290     Q_D(const QDeclarative1GridView);
2291     if (d->flow == QDeclarative1GridView::LeftToRight)
2292         return QDeclarative1Flickable::maxXExtent();
2293     qreal extent;
2294     qreal highlightStart;
2295     qreal highlightEnd;
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();
2301     } else {
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);
2307     }
2308     if (!d->model || !d->model->count()) {
2309         extent = 0;
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));
2316     } else {
2317         extent = -(d->endPosition() - width());
2318     }
2319     if (d->isRightToLeftTopToBottom()) {
2320         if (d->header)
2321             extent -= d->header->item->width();
2322     } else {
2323         if (d->footer)
2324             extent -= d->footer->item->width();
2325     }
2326
2327     const qreal minX = minXExtent();
2328     if (extent > minX)
2329         extent = minX;
2330     return extent;
2331 }
2332
2333 void QDeclarative1GridView::keyPressEvent(QKeyEvent *event)
2334 {
2335     Q_D(QDeclarative1GridView);
2336     keyPressPreHandler(event);
2337     if (event->isAccepted())
2338         return;
2339     if (d->model && d->model->count() && d->interactive) {
2340         d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
2341         int oldCurrent = currentIndex();
2342         switch (event->key()) {
2343         case Qt::Key_Up:
2344             moveCurrentIndexUp();
2345             break;
2346         case Qt::Key_Down:
2347             moveCurrentIndexDown();
2348             break;
2349         case Qt::Key_Left:
2350             moveCurrentIndexLeft();
2351             break;
2352         case Qt::Key_Right:
2353             moveCurrentIndexRight();
2354             break;
2355         default:
2356             break;
2357         }
2358         if (oldCurrent != currentIndex()) {
2359             event->accept();
2360             return;
2361         }
2362     }
2363     d->moveReason = QDeclarative1GridViewPrivate::Other;
2364     event->ignore();
2365     QDeclarative1Flickable::keyPressEvent(event);
2366 }
2367
2368 /*!
2369     \qmlmethod QtQuick1::GridView::moveCurrentIndexUp()
2370
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.
2374
2375     \bold Note: methods should only be called after the Component has completed.
2376 */
2377 void QDeclarative1GridView::moveCurrentIndexUp()
2378 {
2379     Q_D(QDeclarative1GridView);
2380     const int count = d->model ? d->model->count() : 0;
2381     if (!count)
2382         return;
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);
2387         }
2388     } else {
2389         if (currentIndex() > 0 || d->wrap) {
2390             int index = currentIndex() - 1;
2391             setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2392         }
2393     }
2394 }
2395
2396 /*!
2397     \qmlmethod QtQuick1::GridView::moveCurrentIndexDown()
2398
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.
2402
2403     \bold Note: methods should only be called after the Component has completed.
2404 */
2405 void QDeclarative1GridView::moveCurrentIndexDown()
2406 {
2407     Q_D(QDeclarative1GridView);
2408     const int count = d->model ? d->model->count() : 0;
2409     if (!count)
2410         return;
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);
2415         }
2416     } else {
2417         if (currentIndex() < count - 1 || d->wrap) {
2418             int index = currentIndex() + 1;
2419             setCurrentIndex((index >= 0 && index < count) ? index : 0);
2420         }
2421     }
2422 }
2423
2424 /*!
2425     \qmlmethod QtQuick1::GridView::moveCurrentIndexLeft()
2426
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.
2430
2431     \bold Note: methods should only be called after the Component has completed.
2432 */
2433 void QDeclarative1GridView::moveCurrentIndexLeft()
2434 {
2435     Q_D(QDeclarative1GridView);
2436     const int count = d->model ? d->model->count() : 0;
2437     if (!count)
2438         return;
2439
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);
2445             }
2446         } else {
2447             if (currentIndex() >= d->columns || d->wrap) {
2448                 int index = currentIndex() - d->columns;
2449                 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2450             }
2451         }
2452     } else {
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);
2457             }
2458         } else {
2459             if (currentIndex() < count - d->columns || d->wrap) {
2460                 int index = currentIndex() + d->columns;
2461                 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2462             }
2463         }
2464     }
2465 }
2466
2467 /*!
2468     \qmlmethod QtQuick1::GridView::moveCurrentIndexRight()
2469
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.
2473
2474     \bold Note: methods should only be called after the Component has completed.
2475 */
2476 void QDeclarative1GridView::moveCurrentIndexRight()
2477 {
2478     Q_D(QDeclarative1GridView);
2479     const int count = d->model ? d->model->count() : 0;
2480     if (!count)
2481         return;
2482
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);
2488             }
2489         } else {
2490             if (currentIndex() < count - d->columns || d->wrap) {
2491                 int index = currentIndex()+d->columns;
2492                 setCurrentIndex((index >= 0 && index < count) ? index : 0);
2493             }
2494         }
2495     } else {
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);
2500             }
2501         } else {
2502             if (currentIndex() >= d->columns || d->wrap) {
2503                 int index = currentIndex() - d->columns;
2504                 setCurrentIndex((index >= 0 && index < count) ? index : count-1);
2505             }
2506         }
2507     }
2508 }
2509
2510 void QDeclarative1GridViewPrivate::positionViewAtIndex(int index, int mode)
2511 {
2512     Q_Q(QDeclarative1GridView);
2513     if (!isValid())
2514         return;
2515     if (mode < QDeclarative1GridView::Beginning || mode > QDeclarative1GridView::Contain)
2516         return;
2517
2518     int idx = qMax(qMin(index, model->count()-1), 0);
2519
2520     if (layoutScheduled)
2521         layout();
2522     qreal pos = isRightToLeftTopToBottom() ? -position() - size() : position();
2523     FxGridItem1 *item = visibleItem(idx);
2524     qreal maxExtent;
2525     if (flow == QDeclarative1GridView::LeftToRight)
2526         maxExtent = -q->maxYExtent();
2527     else
2528         maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent();
2529
2530     if (!item) {
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();
2538         else
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);
2545     }
2546     if (item) {
2547         qreal itemPos = item->rowPos();
2548         switch (mode) {
2549         case QDeclarative1GridView::Beginning:
2550             pos = itemPos;
2551             if (index < 0 && header) {
2552                 pos -= flow == QDeclarative1GridView::LeftToRight
2553                             ? header->item->height()
2554                             : header->item->width();
2555             }
2556             break;
2557         case QDeclarative1GridView::Center:
2558             pos = itemPos - (size() - rowSize())/2;
2559             break;
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();
2566             }
2567             break;
2568         case QDeclarative1GridView::Visible:
2569             if (itemPos > pos + size())
2570                 pos = itemPos - size() + rowSize();
2571             else if (item->endRowPos() < pos)
2572                 pos = itemPos;
2573             break;
2574         case QDeclarative1GridView::Contain:
2575             if (item->endRowPos() > pos + size())
2576                 pos = itemPos - size() + rowSize();
2577             if (itemPos < pos)
2578                 pos = itemPos;
2579         }
2580
2581         pos = qMin(pos, maxExtent);
2582         qreal minExtent;
2583         if (flow == QDeclarative1GridView::LeftToRight)
2584             minExtent = -q->minYExtent();
2585         else
2586             minExtent = isRightToLeftTopToBottom() ? q->maxXExtent()-size() : -q->minXExtent();
2587         pos = qMax(pos, minExtent);
2588         moveReason = QDeclarative1GridViewPrivate::Other;
2589         q->cancelFlick();
2590         setPosition(pos);
2591     }
2592     fixupPosition();
2593 }
2594
2595 /*!
2596     \qmlmethod QtQuick1::GridView::positionViewAtIndex(int index, PositionMode mode)
2597
2598     Positions the view such that the \a index is at the position specified by
2599     \a mode:
2600
2601     \list
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.
2609     \endlist
2610
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.
2613
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.
2618
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:
2622
2623     \code
2624     Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
2625     \endcode
2626 */
2627 void QDeclarative1GridView::positionViewAtIndex(int index, int mode)
2628 {
2629     Q_D(QDeclarative1GridView);
2630     if (!d->isValid() || index < 0 || index >= d->model->count())
2631         return;
2632     d->positionViewAtIndex(index, mode);
2633 }
2634
2635 /*!
2636     \qmlmethod QtQuick1::GridView::positionViewAtBeginning()
2637     \qmlmethod QtQuick1::GridView::positionViewAtEnd()
2638     \since Quick 1.1
2639
2640     Positions the view at the beginning or end, taking into account any header or footer.
2641
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.
2646
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:
2650
2651     \code
2652     Component.onCompleted: positionViewAtEnd()
2653     \endcode
2654 */
2655 void QDeclarative1GridView::positionViewAtBeginning()
2656 {
2657     Q_D(QDeclarative1GridView);
2658     if (!d->isValid())
2659         return;
2660     d->positionViewAtIndex(-1, Beginning);
2661 }
2662
2663 void QDeclarative1GridView::positionViewAtEnd()
2664 {
2665     Q_D(QDeclarative1GridView);
2666     if (!d->isValid())
2667         return;
2668     d->positionViewAtIndex(d->model->count(), End);
2669 }
2670
2671 /*!
2672     \qmlmethod int QtQuick1::GridView::indexAt(int x, int y)
2673
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.
2677
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.
2680
2681     \bold Note: methods should only be called after the Component has completed.
2682 */
2683 int QDeclarative1GridView::indexAt(qreal x, qreal y) const
2684 {
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;
2690     }
2691
2692     return -1;
2693 }
2694
2695 void QDeclarative1GridView::componentComplete()
2696 {
2697     Q_D(QDeclarative1GridView);
2698     QDeclarative1Flickable::componentComplete();
2699     d->updateHeader();
2700     d->updateFooter();
2701     d->updateGrid();
2702     if (d->isValid()) {
2703         refill();
2704         d->moveReason = QDeclarative1GridViewPrivate::SetIndex;
2705         if (d->currentIndex < 0 && !d->currentIndexCleared)
2706             d->updateCurrent(0);
2707         else
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();
2713         }
2714         d->moveReason = QDeclarative1GridViewPrivate::Other;
2715         d->fixupPosition();
2716     }
2717 }
2718
2719 void QDeclarative1GridView::trackedPositionChanged()
2720 {
2721     Q_D(QDeclarative1GridView);
2722     if (!d->trackedItem || !d->currentItem)
2723         return;
2724     if (d->moveReason == QDeclarative1GridViewPrivate::SetIndex) {
2725         const qreal trackedPos = d->trackedItem->rowPos();
2726         qreal viewPos;
2727         qreal highlightStart;
2728         qreal highlightEnd;
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;
2733         } else {
2734             viewPos = d->position();
2735             highlightStart = d->highlightRangeStart;
2736             highlightEnd = d->highlightRangeEnd;
2737         }
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;
2745             } else {
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();
2752                 } else {
2753                     if (trackedPos > pos + highlightEnd - d->rowSize())
2754                         pos = trackedPos - highlightEnd + d->rowSize();
2755                     if (trackedPos < pos + highlightStart)
2756                         pos = trackedPos - highlightStart;
2757                 }
2758             }
2759         } else {
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())
2767                         pos = trackedPos;
2768                 } else {
2769                     pos = d->currentItem->endRowPos() - d->size() + 1;
2770                     if (d->rowSize() > d->size())
2771                         pos = d->currentItem->rowPos();
2772                 }
2773             }
2774         }
2775         if (viewPos != pos) {
2776             cancelFlick();
2777             d->calcVelocity = true;
2778             d->setPosition(pos);
2779             d->calcVelocity = false;
2780         }
2781     }
2782 }
2783
2784 void QDeclarative1GridView::itemsInserted(int modelIndex, int count)
2785 {
2786     Q_D(QDeclarative1GridView);
2787     if (!isComponentComplete() || !d->model || !d->model->isValid())
2788         return;
2789
2790     int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0;
2791     if (index < 0) {
2792         int i = d->visibleItems.count() - 1;
2793         while (i > 0 && d->visibleItems.at(i)->index == -1)
2794             --i;
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();
2798         } else {
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;
2806                 }
2807             }
2808             if (d->currentIndex >= modelIndex) {
2809                 // adjust current item index
2810                 d->currentIndex += count;
2811                 if (d->currentItem)
2812                     d->currentItem->index = d->currentIndex;
2813                 emit currentIndexChanged();
2814             }
2815             d->scheduleLayout();
2816             d->itemCount += count;
2817             emit countChanged();
2818             return;
2819         }
2820     }
2821
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;
2827     }
2828
2829     qreal tempPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size()+d->width()+1 : d->position();
2830     int to = d->buffer+tempPos+d->size()-1;
2831     int colPos = 0;
2832     int rowPos = 0;
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();
2838         } else {
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)) {
2843                 colPos = 0;
2844                 rowPos += d->rowSize();
2845             }
2846         }
2847     } else if (d->itemCount == 0 && d->header) {
2848         rowPos = d->headerSize();
2849     }
2850
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;
2856     }
2857
2858     bool addedVisible = false;
2859     QList<FxGridItem1*> added;
2860     int i = 0;
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;
2865         }
2866         FxGridItem1 *item = d->createItem(modelIndex + i);
2867         d->visibleItems.insert(index, item);
2868         item->setPosition(colPos, rowPos);
2869         added.append(item);
2870         colPos += d->colSize();
2871         if (colPos > d->colSize() * (d->columns-1)) {
2872             colPos = 0;
2873             rowPos += d->rowSize();
2874         }
2875         ++index;
2876         ++i;
2877     }
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());
2883         }
2884     }
2885
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;
2891             break;
2892         }
2893     }
2894
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));
2901         }
2902         emit currentIndexChanged();
2903     } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
2904         setCurrentIndex(0);
2905     }
2906
2907     // everything is in order now - emit add() signal
2908     for (int j = 0; j < added.count(); ++j)
2909         added.at(j)->attached->emitAdd();
2910
2911     d->itemCount += count;
2912     emit countChanged();
2913 }
2914
2915 void QDeclarative1GridView::itemsRemoved(int modelIndex, int count)
2916 {
2917     Q_D(QDeclarative1GridView);
2918     if (!isComponentComplete() || !d->model || !d->model->isValid())
2919         return;
2920
2921     d->itemCount -= count;
2922     bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count;
2923     bool removedVisible = false;
2924
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;
2934             }
2935             ++it;
2936         } else if (item->index >= modelIndex + count) {
2937             // after removed items
2938             item->index -= count;
2939             ++it;
2940         } else {
2941             // removed item
2942             if (!removedVisible) {
2943                 d->scheduleLayout();
2944                 removedVisible = true;
2945             }
2946             item->attached->emitRemove();
2947             if (item->attached->delayRemove()) {
2948                 item->index = -1;
2949                 connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection);
2950                 ++it;
2951             } else {
2952                 it = d->visibleItems.erase(it);
2953                 d->releaseItem(item);
2954             }
2955         }
2956     }
2957
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;
2963             break;
2964         }
2965     }
2966
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();
2971
2972     // fix current
2973     if (d->currentIndex >= modelIndex + count) {
2974         d->currentIndex -= count;
2975         if (d->currentItem)
2976             d->currentItem->index -= count;
2977         emit currentIndexChanged();
2978     } else if (currentRemoved) {
2979         // current item has been removed.
2980         d->releaseItem(d->currentItem);
2981         d->currentItem = 0;
2982         d->currentIndex = -1;
2983         if (d->itemCount)
2984             d->updateCurrent(qMin(modelIndex, d->itemCount-1));
2985         else
2986             emit currentIndexChanged();
2987     }
2988
2989     if (removedVisible && d->visibleItems.isEmpty()) {
2990         d->timeline.clear();
2991         if (d->itemCount == 0) {
2992             d->setPosition(0);
2993             d->updateHeader();
2994             d->updateFooter();
2995             update();
2996         }
2997     }
2998
2999     emit countChanged();
3000 }
3001
3002 void QDeclarative1GridView::destroyRemoved()
3003 {
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);
3011         } else {
3012             ++it;
3013         }
3014     }
3015
3016     // Correct the positioning of the items
3017     d->layout();
3018 }
3019
3020 void QDeclarative1GridView::itemsMoved(int from, int to, int count)
3021 {
3022     Q_D(QDeclarative1GridView);
3023     if (!isComponentComplete() || !d->isValid())
3024         return;
3025     QHash<int,FxGridItem1*> moved;
3026
3027     FxGridItem1 *firstItem = d->firstVisibleItem();
3028
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);
3037         } else {
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;
3043             }
3044             ++it;
3045         }
3046     }
3047
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);
3056             if (!movedItem)
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());
3061             ++it;
3062             --remaining;
3063         } else {
3064             if (item->index != -1) {
3065                 if (item->index >= to) {
3066                     // update everything after the moved items.
3067                     item->index += count;
3068                 }
3069                 endIndex = item->index;
3070             }
3071             ++it;
3072         }
3073     }
3074
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);
3079         ++endIndex;
3080     }
3081
3082     // update visibleIndex
3083     for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
3084         if ((*it)->index != -1) {
3085             d->visibleIndex = (*it)->index;
3086             break;
3087         }
3088     }
3089
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();
3097         }
3098     }
3099
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);
3107     }
3108
3109     d->layout();
3110 }
3111
3112 void QDeclarative1GridView::modelReset()
3113 {
3114     Q_D(QDeclarative1GridView);
3115     d->clear();
3116     refill();
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();
3123     }
3124     d->moveReason = QDeclarative1GridViewPrivate::Other;
3125
3126     emit countChanged();
3127 }
3128
3129 void QDeclarative1GridView::createdItem(int index, QDeclarativeItem *item)
3130 {
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)));
3137         } else {
3138             item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
3139         }
3140     }
3141 }
3142
3143 void QDeclarative1GridView::destroyingItem(QDeclarativeItem *item)
3144 {
3145     Q_D(QDeclarative1GridView);
3146     d->unrequestedItems.remove(item);
3147 }
3148
3149 void QDeclarative1GridView::animStopped()
3150 {
3151     Q_D(QDeclarative1GridView);
3152     d->bufferMode = QDeclarative1GridViewPrivate::NoBuffer;
3153     if (d->haveHighlightRange && d->highlightRange == QDeclarative1GridView::StrictlyEnforceRange)
3154         d->updateHighlight();
3155 }
3156
3157 void QDeclarative1GridView::refill()
3158 {
3159     Q_D(QDeclarative1GridView);
3160     if (d->isRightToLeftTopToBottom())
3161         d->refill(-d->position()-d->size()+1, -d->position());
3162     else
3163         d->refill(d->position(), d->position()+d->size()-1);
3164 }
3165
3166
3167 QDeclarative1GridViewAttached *QDeclarative1GridView::qmlAttachedProperties(QObject *obj)
3168 {
3169     return new QDeclarative1GridViewAttached(obj);
3170 }
3171
3172
3173
3174 QT_END_NAMESPACE