src/declarative/graphicsitems/qdeclarativegridview.cpp
changeset 33 3e2da88830cd
parent 30 5dc02b23752f
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
   106     , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0)
   106     , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0)
   107     , highlightRangeStart(0), highlightRangeEnd(0), highlightRange(QDeclarativeGridView::NoHighlightRange)
   107     , highlightRangeStart(0), highlightRangeEnd(0), highlightRange(QDeclarativeGridView::NoHighlightRange)
   108     , highlightComponent(0), highlight(0), trackedItem(0)
   108     , highlightComponent(0), highlight(0), trackedItem(0)
   109     , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
   109     , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0)
   110     , highlightMoveDuration(150)
   110     , highlightMoveDuration(150)
       
   111     , footerComponent(0), footer(0), headerComponent(0), header(0)
   111     , bufferMode(BufferBefore | BufferAfter), snapMode(QDeclarativeGridView::NoSnap)
   112     , bufferMode(BufferBefore | BufferAfter), snapMode(QDeclarativeGridView::NoSnap)
   112     , ownModel(false), wrap(false), autoHighlight(true)
   113     , ownModel(false), wrap(false), autoHighlight(true)
   113     , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
   114     , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
   114     , deferredRelease(false), haveHighlightRange(false) {}
   115     , deferredRelease(false), haveHighlightRange(false) {}
   115 
   116 
   126     void updateUnrequestedPositions();
   127     void updateUnrequestedPositions();
   127     void updateTrackedItem();
   128     void updateTrackedItem();
   128     void createHighlight();
   129     void createHighlight();
   129     void updateHighlight();
   130     void updateHighlight();
   130     void updateCurrent(int modelIndex);
   131     void updateCurrent(int modelIndex);
       
   132     void updateHeader();
       
   133     void updateFooter();
   131     void fixupPosition();
   134     void fixupPosition();
   132 
   135 
   133     FxGridItem *visibleItem(int modelIndex) const {
   136     FxGridItem *visibleItem(int modelIndex) const {
   134         if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
   137         if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
   135             for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
   138             for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
   146         return flow == QDeclarativeGridView::LeftToRight ? q->contentY() : q->contentX();
   149         return flow == QDeclarativeGridView::LeftToRight ? q->contentY() : q->contentX();
   147     }
   150     }
   148     void setPosition(qreal pos) {
   151     void setPosition(qreal pos) {
   149         Q_Q(QDeclarativeGridView);
   152         Q_Q(QDeclarativeGridView);
   150         if (flow == QDeclarativeGridView::LeftToRight)
   153         if (flow == QDeclarativeGridView::LeftToRight)
   151             q->setContentY(pos);
   154             q->QDeclarativeFlickable::setContentY(pos);
   152         else
   155         else
   153             q->setContentX(pos);
   156             q->QDeclarativeFlickable::setContentX(pos);
   154     }
   157     }
   155     int size() const {
   158     int size() const {
   156         Q_Q(const QDeclarativeGridView);
   159         Q_Q(const QDeclarativeGridView);
   157         return flow == QDeclarativeGridView::LeftToRight ? q->height() : q->width();
   160         return flow == QDeclarativeGridView::LeftToRight ? q->height() : q->width();
   158     }
   161     }
   228                 return item;
   231                 return item;
   229         }
   232         }
   230         return visibleItems.count() ? visibleItems.first() : 0;
   233         return visibleItems.count() ? visibleItems.first() : 0;
   231     }
   234     }
   232 
   235 
       
   236     int lastVisibleIndex() const {
       
   237         int lastIndex = -1;
       
   238         for (int i = visibleItems.count()-1; i >= 0; --i) {
       
   239             FxGridItem *gridItem = visibleItems.at(i);
       
   240             if (gridItem->index != -1) {
       
   241                 lastIndex = gridItem->index;
       
   242                 break;
       
   243             }
       
   244         }
       
   245         return lastIndex;
       
   246     }
       
   247 
   233     // Map a model index to visibleItems list index.
   248     // Map a model index to visibleItems list index.
   234     // These may differ if removed items are still present in the visible list,
   249     // These may differ if removed items are still present in the visible list,
   235     // e.g. doing a removal animation
   250     // e.g. doing a removal animation
   236     int mapFromModel(int modelIndex) const {
   251     int mapFromModel(int modelIndex) const {
   237         if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
   252         if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
   244                 return -1;
   259                 return -1;
   245         }
   260         }
   246         return -1; // Not in visibleList
   261         return -1; // Not in visibleList
   247     }
   262     }
   248 
   263 
   249     qreal snapPosAt(qreal pos) {
   264     qreal snapPosAt(qreal pos) const {
       
   265         Q_Q(const QDeclarativeGridView);
   250         qreal snapPos = 0;
   266         qreal snapPos = 0;
   251         if (!visibleItems.isEmpty()) {
   267         if (!visibleItems.isEmpty()) {
   252             pos += rowSize()/2;
   268             pos += rowSize()/2;
   253             snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
   269             snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
   254             snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
   270             snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
       
   271             qreal maxExtent = flow == QDeclarativeGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
       
   272             qreal minExtent = flow == QDeclarativeGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
       
   273             if (snapPos > maxExtent)
       
   274                 snapPos = maxExtent;
       
   275             if (snapPos < minExtent)
       
   276                 snapPos = minExtent;
   255         }
   277         }
   256         return snapPos;
   278         return snapPos;
       
   279     }
       
   280 
       
   281     FxGridItem *snapItemAt(qreal pos) {
       
   282         for (int i = 0; i < visibleItems.count(); ++i) {
       
   283             FxGridItem *item = visibleItems[i];
       
   284             if (item->index == -1)
       
   285                 continue;
       
   286             qreal itemTop = item->rowPos();
       
   287             if (item->index == model->count()-1 || (itemTop+rowSize()/2 >= pos))
       
   288                 return item;
       
   289         }
       
   290         if (visibleItems.count() && visibleItems.first()->rowPos() <= pos)
       
   291             return visibleItems.first();
       
   292         return 0;
   257     }
   293     }
   258 
   294 
   259     int snapIndex() {
   295     int snapIndex() {
   260         int index = currentIndex;
   296         int index = currentIndex;
   261         for (int i = 0; i < visibleItems.count(); ++i) {
   297         for (int i = 0; i < visibleItems.count(); ++i) {
   281                 if (q->isComponentComplete()) {
   317                 if (q->isComponentComplete()) {
   282                     updateGrid();
   318                     updateGrid();
   283                     scheduleLayout();
   319                     scheduleLayout();
   284                 }
   320                 }
   285             }
   321             }
       
   322         } else if ((header && header->item == item) || (footer && footer->item == item)) {
       
   323             updateHeader();
       
   324             updateFooter();
   286         }
   325         }
   287     }
   326     }
   288 
   327 
   289     virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
   328     virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
   290     virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
   329     virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
   328     MovementReason moveReason;
   367     MovementReason moveReason;
   329     int buffer;
   368     int buffer;
   330     QSmoothedAnimation *highlightXAnimator;
   369     QSmoothedAnimation *highlightXAnimator;
   331     QSmoothedAnimation *highlightYAnimator;
   370     QSmoothedAnimation *highlightYAnimator;
   332     int highlightMoveDuration;
   371     int highlightMoveDuration;
       
   372     QDeclarativeComponent *footerComponent;
       
   373     FxGridItem *footer;
       
   374     QDeclarativeComponent *headerComponent;
       
   375     FxGridItem *header;
   333     enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
   376     enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
   334     int bufferMode;
   377     int bufferMode;
   335     QDeclarativeGridView::SnapMode snapMode;
   378     QDeclarativeGridView::SnapMode snapMode;
   336 
   379 
   337     bool ownModel : 1;
   380     bool ownModel : 1;
   376         listItem = new FxGridItem(item, q);
   419         listItem = new FxGridItem(item, q);
   377         listItem->index = modelIndex;
   420         listItem->index = modelIndex;
   378         if (model->completePending()) {
   421         if (model->completePending()) {
   379             // complete
   422             // complete
   380             listItem->item->setZValue(1);
   423             listItem->item->setZValue(1);
   381             listItem->item->setParentItem(q->viewport());
   424             listItem->item->setParentItem(q->contentItem());
   382             model->completeItem();
   425             model->completeItem();
   383         } else {
   426         } else {
   384             listItem->item->setParentItem(q->viewport());
   427             listItem->item->setParentItem(q->contentItem());
   385         }
   428         }
   386         unrequestedItems.remove(listItem->item);
   429         unrequestedItems.remove(listItem->item);
   387     }
   430     }
   388     requestedIndex = -1;
   431     requestedIndex = -1;
   389     return listItem;
   432     return listItem;
   410 void QDeclarativeGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
   453 void QDeclarativeGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
   411 {
   454 {
   412     Q_Q(QDeclarativeGridView);
   455     Q_Q(QDeclarativeGridView);
   413     if (!isValid() || !q->isComponentComplete())
   456     if (!isValid() || !q->isComponentComplete())
   414         return;
   457         return;
   415 
       
   416     itemCount = model->count();
   458     itemCount = model->count();
   417     qreal bufferFrom = from - buffer;
   459     qreal bufferFrom = from - buffer;
   418     qreal bufferTo = to + buffer;
   460     qreal bufferTo = to + buffer;
   419     qreal fillFrom = from;
   461     qreal fillFrom = from;
   420     qreal fillTo = to;
   462     qreal fillTo = to;
   520         deferredRelease = false;
   562         deferredRelease = false;
   521     } else {
   563     } else {
   522         deferredRelease = true;
   564         deferredRelease = true;
   523     }
   565     }
   524     if (changed) {
   566     if (changed) {
       
   567         if (header)
       
   568             updateHeader();
       
   569         if (footer)
       
   570             updateFooter();
   525         if (flow == QDeclarativeGridView::LeftToRight)
   571         if (flow == QDeclarativeGridView::LeftToRight)
   526             q->setContentHeight(endPosition() - startPosition());
   572             q->setContentHeight(endPosition() - startPosition());
   527         else
   573         else
   528             q->setContentWidth(endPosition() - startPosition());
   574             q->setContentWidth(endPosition() - startPosition());
   529     } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
   575     } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
   555 
   601 
   556 void QDeclarativeGridViewPrivate::layout()
   602 void QDeclarativeGridViewPrivate::layout()
   557 {
   603 {
   558     Q_Q(QDeclarativeGridView);
   604     Q_Q(QDeclarativeGridView);
   559     layoutScheduled = false;
   605     layoutScheduled = false;
   560     if (!isValid()) {
   606     if (!isValid() && !visibleItems.count()) {
   561         clear();
   607         clear();
   562         return;
   608         return;
   563     }
   609     }
   564     if (visibleItems.count()) {
   610     if (visibleItems.count()) {
   565         qreal rowPos = visibleItems.first()->rowPos();
   611         qreal rowPos = visibleItems.first()->rowPos();
   577                 rowPos += rowSize();
   623                 rowPos += rowSize();
   578             }
   624             }
   579             item->setPosition(colPos, rowPos);
   625             item->setPosition(colPos, rowPos);
   580         }
   626         }
   581     }
   627     }
       
   628     if (header)
       
   629         updateHeader();
       
   630     if (footer)
       
   631         updateFooter();
   582     q->refill();
   632     q->refill();
   583     updateHighlight();
   633     updateHighlight();
   584     moveReason = Other;
   634     moveReason = Other;
   585     if (flow == QDeclarativeGridView::LeftToRight) {
   635     if (flow == QDeclarativeGridView::LeftToRight) {
   586         q->setContentHeight(endPosition() - startPosition());
   636         q->setContentHeight(endPosition() - startPosition());
   664             } else {
   714             } else {
   665                 delete highlightContext;
   715                 delete highlightContext;
   666             }
   716             }
   667         } else {
   717         } else {
   668             item = new QDeclarativeItem;
   718             item = new QDeclarativeItem;
   669             QDeclarative_setParent_noEvent(item, q->viewport());
   719             QDeclarative_setParent_noEvent(item, q->contentItem());
   670             item->setParentItem(q->viewport());
   720             item->setParentItem(q->contentItem());
   671         }
   721         }
   672         if (item) {
   722         if (item) {
   673             QDeclarative_setParent_noEvent(item, q->viewport());
   723             QDeclarative_setParent_noEvent(item, q->contentItem());
   674             item->setParentItem(q->viewport());
   724             item->setParentItem(q->contentItem());
   675             highlight = new FxGridItem(item, q);
   725             highlight = new FxGridItem(item, q);
   676             highlightXAnimator = new QSmoothedAnimation(q);
   726             highlightXAnimator = new QSmoothedAnimation(q);
   677             highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
   727             highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
   678             highlightXAnimator->userDuration = highlightMoveDuration;
   728             highlightXAnimator->userDuration = highlightMoveDuration;
   679             highlightYAnimator = new QSmoothedAnimation(q);
   729             highlightYAnimator = new QSmoothedAnimation(q);
   740     updateHighlight();
   790     updateHighlight();
   741     emit q->currentIndexChanged();
   791     emit q->currentIndexChanged();
   742     releaseItem(oldCurrentItem);
   792     releaseItem(oldCurrentItem);
   743 }
   793 }
   744 
   794 
       
   795 void QDeclarativeGridViewPrivate::updateFooter()
       
   796 {
       
   797     Q_Q(QDeclarativeGridView);
       
   798     if (!footer && footerComponent) {
       
   799         QDeclarativeItem *item = 0;
       
   800         QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
       
   801         QObject *nobj = footerComponent->create(context);
       
   802         if (nobj) {
       
   803             QDeclarative_setParent_noEvent(context, nobj);
       
   804             item = qobject_cast<QDeclarativeItem *>(nobj);
       
   805             if (!item)
       
   806                 delete nobj;
       
   807         } else {
       
   808             delete context;
       
   809         }
       
   810         if (item) {
       
   811             QDeclarative_setParent_noEvent(item, q->contentItem());
       
   812             item->setParentItem(q->contentItem());
       
   813             item->setZValue(1);
       
   814             QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
       
   815             itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
       
   816             footer = new FxGridItem(item, q);
       
   817         }
       
   818     }
       
   819     if (footer) {
       
   820         if (visibleItems.count()) {
       
   821             qreal endPos = endPosition();
       
   822             if (lastVisibleIndex() == model->count()-1) {
       
   823                 footer->setPosition(0, endPos);
       
   824             } else {
       
   825                 qreal visiblePos = position() + q->height();
       
   826                 if (endPos <= visiblePos || footer->endRowPos() < endPos)
       
   827                     footer->setPosition(0, endPos);
       
   828             }
       
   829         } else {
       
   830             qreal endPos = 0;
       
   831             if (header) {
       
   832                 endPos += flow == QDeclarativeGridView::LeftToRight
       
   833                                    ? header->item->height()
       
   834                                    : header->item->width();
       
   835             }
       
   836             footer->setPosition(0, endPos);
       
   837         }
       
   838     }
       
   839 }
       
   840 
       
   841 void QDeclarativeGridViewPrivate::updateHeader()
       
   842 {
       
   843     Q_Q(QDeclarativeGridView);
       
   844     if (!header && headerComponent) {
       
   845         QDeclarativeItem *item = 0;
       
   846         QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
       
   847         QObject *nobj = headerComponent->create(context);
       
   848         if (nobj) {
       
   849             QDeclarative_setParent_noEvent(context, nobj);
       
   850             item = qobject_cast<QDeclarativeItem *>(nobj);
       
   851             if (!item)
       
   852                 delete nobj;
       
   853         } else {
       
   854             delete context;
       
   855         }
       
   856         if (item) {
       
   857             QDeclarative_setParent_noEvent(item, q->contentItem());
       
   858             item->setParentItem(q->contentItem());
       
   859             item->setZValue(1);
       
   860             QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
       
   861             itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
       
   862             header = new FxGridItem(item, q);
       
   863         }
       
   864     }
       
   865     if (header) {
       
   866         if (visibleItems.count()) {
       
   867             qreal startPos = startPosition();
       
   868             qreal headerSize = flow == QDeclarativeGridView::LeftToRight
       
   869                                ? header->item->height()
       
   870                                : header->item->width();
       
   871             if (visibleIndex == 0) {
       
   872                 header->setPosition(0, startPos - headerSize);
       
   873             } else {
       
   874                 if (position() <= startPos || header->rowPos() > startPos - headerSize)
       
   875                     header->setPosition(0, startPos - headerSize);
       
   876             }
       
   877         } else {
       
   878             header->setPosition(0, 0);
       
   879         }
       
   880     }
       
   881 }
       
   882 
   745 void QDeclarativeGridViewPrivate::fixupPosition()
   883 void QDeclarativeGridViewPrivate::fixupPosition()
   746 {
   884 {
   747     moveReason = Other;
   885     moveReason = Other;
   748     if (flow == QDeclarativeGridView::LeftToRight)
   886     if (flow == QDeclarativeGridView::LeftToRight)
   749         fixupY();
   887         fixupY();
   751         fixupX();
   889         fixupX();
   752 }
   890 }
   753 
   891 
   754 void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
   892 void QDeclarativeGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
   755 {
   893 {
   756     Q_Q(QDeclarativeGridView);
       
   757     if ((flow == QDeclarativeGridView::TopToBottom && &data == &vData)
   894     if ((flow == QDeclarativeGridView::TopToBottom && &data == &vData)
   758         || (flow == QDeclarativeGridView::LeftToRight && &data == &hData))
   895         || (flow == QDeclarativeGridView::LeftToRight && &data == &hData))
   759         return;
   896         return;
   760 
   897 
   761     int oldDuration = fixupDuration;
   898     int oldDuration = fixupDuration;
   762     fixupDuration = moveReason == Mouse ? fixupDuration : 0;
   899     fixupDuration = moveReason == Mouse ? fixupDuration : 0;
   763 
   900 
   764     if (haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) {
   901     if (snapMode != QDeclarativeGridView::NoSnap) {
       
   902         FxGridItem *topItem = snapItemAt(position()+highlightRangeStart);
       
   903         FxGridItem *bottomItem = snapItemAt(position()+highlightRangeEnd);
       
   904         qreal pos;
       
   905         if (topItem && bottomItem && haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) {
       
   906             qreal topPos = qMin(topItem->rowPos() - highlightRangeStart, -maxExtent);
       
   907             qreal bottomPos = qMax(bottomItem->rowPos() - highlightRangeEnd, -minExtent);
       
   908             pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
       
   909         } else if (topItem) {
       
   910             pos = qMax(qMin(topItem->rowPos() - highlightRangeStart, -maxExtent), -minExtent);
       
   911         } else if (bottomItem) {
       
   912             pos = qMax(qMin(bottomItem->rowPos() - highlightRangeStart, -maxExtent), -minExtent);
       
   913         } else {
       
   914             fixupDuration = oldDuration;
       
   915             return;
       
   916         }
       
   917         if (currentItem && haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) {
       
   918             updateHighlight();
       
   919             qreal currPos = currentItem->rowPos();
       
   920             if (pos < currPos + rowSize() - highlightRangeEnd)
       
   921                 pos = currPos + rowSize() - highlightRangeEnd;
       
   922             if (pos > currPos - highlightRangeStart)
       
   923                 pos = currPos - highlightRangeStart;
       
   924         }
       
   925 
       
   926         qreal dist = qAbs(data.move + pos);
       
   927         if (dist > 0) {
       
   928             timeline.reset(data.move);
       
   929             if (fixupDuration)
       
   930                 timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
       
   931             else
       
   932                 timeline.set(data.move, -pos);
       
   933             vTime = timeline.time();
       
   934         }
       
   935     } else if (haveHighlightRange && highlightRange == QDeclarativeGridView::StrictlyEnforceRange) {
   765         if (currentItem) {
   936         if (currentItem) {
   766             updateHighlight();
   937             updateHighlight();
   767             qreal pos = currentItem->rowPos();
   938             qreal pos = currentItem->rowPos();
   768             qreal viewPos = position();
   939             qreal viewPos = position();
   769             if (viewPos < pos + rowSize() - highlightRangeEnd)
   940             if (viewPos < pos + rowSize() - highlightRangeEnd)
   771             if (viewPos > pos - highlightRangeStart)
   942             if (viewPos > pos - highlightRangeStart)
   772                 viewPos = pos - highlightRangeStart;
   943                 viewPos = pos - highlightRangeStart;
   773 
   944 
   774             timeline.reset(data.move);
   945             timeline.reset(data.move);
   775             if (viewPos != position()) {
   946             if (viewPos != position()) {
   776                 if (fixupDuration) {
   947                 if (fixupDuration)
   777                     timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
   948                     timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
   778                 } else {
   949                 else
   779                     data.move.setValue(-viewPos);
   950                     timeline.set(data.move, -viewPos);
   780                     q->viewportMoved();
       
   781                 }
       
   782             }
       
   783             vTime = timeline.time();
       
   784         }
       
   785     } else if (snapMode != QDeclarativeGridView::NoSnap) {
       
   786         qreal pos = -snapPosAt(-(data.move.value() - highlightRangeStart)) + highlightRangeStart;
       
   787         pos = qMin(qMax(pos, maxExtent), minExtent);
       
   788         qreal dist = qAbs(data.move.value() - pos);
       
   789         if (dist > 0) {
       
   790             timeline.reset(data.move);
       
   791             if (fixupDuration) {
       
   792                 timeline.move(data.move, pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
       
   793             } else {
       
   794                 data.move.setValue(pos);
       
   795                 q->viewportMoved();
       
   796             }
   951             }
   797             vTime = timeline.time();
   952             vTime = timeline.time();
   798         }
   953         }
   799     } else {
   954     } else {
   800         QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent);
   955         QDeclarativeFlickablePrivate::fixup(data, minExtent, maxExtent);
   804 
   959 
   805 void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
   960 void QDeclarativeGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
   806                                         QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity)
   961                                         QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity)
   807 {
   962 {
   808     Q_Q(QDeclarativeGridView);
   963     Q_Q(QDeclarativeGridView);
   809 
       
   810     moveReason = Mouse;
   964     moveReason = Mouse;
   811     if ((!haveHighlightRange || highlightRange != QDeclarativeGridView::StrictlyEnforceRange)
   965     if ((!haveHighlightRange || highlightRange != QDeclarativeGridView::StrictlyEnforceRange)
   812         && snapMode == QDeclarativeGridView::NoSnap) {
   966         && snapMode == QDeclarativeGridView::NoSnap) {
   813         QDeclarativeFlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
   967         QDeclarativeFlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
   814         return;
   968         return;
   849                 v = maxVelocity;
  1003                 v = maxVelocity;
   850         }
  1004         }
   851         qreal accel = deceleration;
  1005         qreal accel = deceleration;
   852         qreal v2 = v * v;
  1006         qreal v2 = v * v;
   853         qreal overshootDist = 0.0;
  1007         qreal overshootDist = 0.0;
   854         if (maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) {
  1008         if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QDeclarativeGridView::SnapOneRow) {
   855             // + rowSize()/4 to encourage moving at least one item in the flick direction
  1009             // + rowSize()/4 to encourage moving at least one item in the flick direction
   856             qreal dist = v2 / (accel * 2.0) + rowSize()/4;
  1010             qreal dist = v2 / (accel * 2.0) + rowSize()/4;
       
  1011             dist = qMin(dist, maxDistance);
   857             if (v > 0)
  1012             if (v > 0)
   858                 dist = -dist;
  1013                 dist = -dist;
   859             data.flickTarget = -snapPosAt(-(data.move.value() - highlightRangeStart) + dist) + highlightRangeStart;
  1014             data.flickTarget = -snapPosAt(-(data.move.value() - highlightRangeStart) + dist) + highlightRangeStart;
   860             qreal adjDist = -data.flickTarget + data.move.value();
  1015             qreal adjDist = -data.flickTarget + data.move.value();
   861             if (qAbs(adjDist) > qAbs(dist)) {
  1016             if (qAbs(adjDist) > qAbs(dist)) {
   902     \qmlclass GridView QDeclarativeGridView
  1057     \qmlclass GridView QDeclarativeGridView
   903     \since 4.7
  1058     \since 4.7
   904     \inherits Flickable
  1059     \inherits Flickable
   905     \brief The GridView item provides a grid view of items provided by a model.
  1060     \brief The GridView item provides a grid view of items provided by a model.
   906 
  1061 
   907     The model is typically provided by a QAbstractListModel "C++ model object",
  1062     A GridView displays data from models created from built-in QML elements like ListModel
   908     but can also be created directly in QML.
  1063     and XmlListModel, or custom model classes defined in C++ that inherit from
   909 
  1064     QAbstractListModel.
   910     The items are laid out top to bottom (vertically) or left to right (horizontally)
  1065 
   911     and may be flicked to scroll.
  1066     A GridView has a \l model, which defines the data to be displayed, and
   912 
  1067     a \l delegate, which defines how the data should be displayed. Items in a 
   913     The below example creates a very simple grid, using a QML model.
  1068     GridView are laid out horizontally or vertically. Grid views are inherently flickable
   914 
  1069     as GridView inherits from \l Flickable.
   915     \image gridview.png
  1070 
   916 
  1071     For example, if there is a simple list model defined in a file \c ContactModel.qml like this:
   917     \snippet doc/src/snippets/declarative/gridview/gridview.qml 3
  1072 
   918 
  1073     \snippet doc/src/snippets/declarative/gridview/ContactModel.qml 0
   919     The model is defined as a ListModel using QML:
  1074 
   920     \quotefile doc/src/snippets/declarative/gridview/dummydata/ContactModel.qml
  1075     Another component can display this model data in a GridView, like this:
   921 
  1076 
   922     In this case ListModel is a handy way for us to test our UI.  In practice
  1077     \snippet doc/src/snippets/declarative/gridview/gridview.qml import
   923     the model would be implemented in C++, or perhaps via a SQL data source.
  1078     \codeline
       
  1079     \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs simple
       
  1080     \image gridview-simple.png
       
  1081 
       
  1082     Here, the GridView creates a \c ContactModel component for its model, and a \l Column element
       
  1083     (containing \l Image and \ Text elements) for its delegate. The view will create a new delegate 
       
  1084     for each item in the model. Notice the delegate is able to access the model's \c name and 
       
  1085     \c portrait data directly.
       
  1086 
       
  1087     An improved grid view is shown below. The delegate is visually improved and is moved 
       
  1088     into a separate \c contactDelegate component. Also, the currently selected item is highlighted
       
  1089     with a blue \l Rectangle using the \l highlight property, and \c focus is set to \c true
       
  1090     to enable keyboard navigation for the grid view.
       
  1091     
       
  1092     \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs advanced
       
  1093     \image gridview-highlight.png
   924 
  1094 
   925     Delegates are instantiated as needed and may be destroyed at any time.
  1095     Delegates are instantiated as needed and may be destroyed at any time.
   926     State should \e never be stored in a delegate.
  1096     State should \e never be stored in a delegate.
   927 
  1097 
   928     \bold Note that views do not enable \e clip automatically.  If the view
  1098     \note Views do not enable \e clip automatically.  If the view
   929     is not clipped by another item or the screen, it will be necessary
  1099     is not clipped by another item or the screen, it will be necessary
   930     to set \e {clip: true} in order to have the out of view items clipped
  1100     to set \e {clip: true} in order to have the out of view items clipped
   931     nicely.
  1101     nicely.
       
  1102 
       
  1103     \sa {declarative/modelviews/gridview}{GridView example}
   932 */
  1104 */
   933 QDeclarativeGridView::QDeclarativeGridView(QDeclarativeItem *parent)
  1105 QDeclarativeGridView::QDeclarativeGridView(QDeclarativeItem *parent)
   934     : QDeclarativeFlickable(*(new QDeclarativeGridViewPrivate), parent)
  1106     : QDeclarativeFlickable(*(new QDeclarativeGridViewPrivate), parent)
   935 {
  1107 {
   936     Q_D(QDeclarativeGridView);
  1108     Q_D(QDeclarativeGridView);
   941 {
  1113 {
   942     Q_D(QDeclarativeGridView);
  1114     Q_D(QDeclarativeGridView);
   943     d->clear();
  1115     d->clear();
   944     if (d->ownModel)
  1116     if (d->ownModel)
   945         delete d->model;
  1117         delete d->model;
       
  1118     delete d->header;
       
  1119     delete d->footer;
   946 }
  1120 }
   947 
  1121 
   948 /*!
  1122 /*!
   949     \qmlattachedproperty bool GridView::isCurrentItem
  1123     \qmlattachedproperty bool GridView::isCurrentItem
   950     This attched property is true if this delegate is the current item; otherwise false.
  1124     This attached property is true if this delegate is the current item; otherwise false.
   951 
  1125 
   952     It is attached to each instance of the delegate.
  1126     It is attached to each instance of the delegate.
   953 */
  1127 */
   954 
  1128 
   955 /*!
  1129 /*!
   969     until an animation completes.
  1143     until an animation completes.
   970 
  1144 
   971     The example below ensures that the animation completes before
  1145     The example below ensures that the animation completes before
   972     the item is removed from the grid.
  1146     the item is removed from the grid.
   973 
  1147 
   974     \code
  1148     \snippet doc/src/snippets/declarative/gridview/gridview.qml delayRemove
   975     Component {
       
   976         id: myDelegate
       
   977         Item {
       
   978             id: wrapper
       
   979             GridView.onRemove: SequentialAnimation {
       
   980                 PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: true }
       
   981                 NumberAnimation { target: wrapper; property: "scale"; to: 0; duration: 250; easing.type: Easing.InOutQuad }
       
   982                 PropertyAction { target: wrapper; property: "GridView.delayRemove"; value: false }
       
   983             }
       
   984         }
       
   985     }
       
   986     \endcode
       
   987 */
  1149 */
   988 
  1150 
   989 /*!
  1151 /*!
   990     \qmlattachedsignal GridView::onAdd()
  1152     \qmlattachedsignal GridView::onAdd()
   991     This attached handler is called immediately after an item is added to the view.
  1153     This attached handler is called immediately after an item is added to the view.
   999 
  1161 
  1000 /*!
  1162 /*!
  1001   \qmlproperty model GridView::model
  1163   \qmlproperty model GridView::model
  1002   This property holds the model providing data for the grid.
  1164   This property holds the model providing data for the grid.
  1003 
  1165 
  1004   The model provides a set of data that is used to create the items
  1166     The model provides the set of data that is used to create the items
  1005   for the view.  For large or dynamic datasets the model is usually
  1167     in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
  1006   provided by a C++ model object.  The C++ model object must be a \l
  1168     or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
  1007   {QAbstractItemModel} subclass, a VisualModel, or a simple list.
  1169     used, it must be a subclass of \l QAbstractItemModel or a simple list.
  1008 
  1170 
  1009   \sa {qmlmodels}{Data Models}
  1171   \sa {qmlmodels}{Data Models}
  1010 */
  1172 */
  1011 QVariant QDeclarativeGridView::model() const
  1173 QVariant QDeclarativeGridView::model() const
  1012 {
  1174 {
  1052             if (d->currentIndex >= d->model->count() || d->currentIndex < 0) {
  1214             if (d->currentIndex >= d->model->count() || d->currentIndex < 0) {
  1053                 setCurrentIndex(0);
  1215                 setCurrentIndex(0);
  1054             } else {
  1216             } else {
  1055                 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
  1217                 d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
  1056                 d->updateCurrent(d->currentIndex);
  1218                 d->updateCurrent(d->currentIndex);
       
  1219                 if (d->highlight && d->currentItem) {
       
  1220                     d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
       
  1221                     d->updateTrackedItem();
       
  1222                 }
       
  1223                 d->moveReason = QDeclarativeGridViewPrivate::Other;
  1057             }
  1224             }
  1058         }
  1225         }
  1059         connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
  1226         connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
  1060         connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
  1227         connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
  1061         connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
  1228         connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
  1077     The number of elements in the delegate has a direct effect on the
  1244     The number of elements in the delegate has a direct effect on the
  1078     flicking performance of the view.  If at all possible, place functionality
  1245     flicking performance of the view.  If at all possible, place functionality
  1079     that is not needed for the normal display of the delegate in a \l Loader which
  1246     that is not needed for the normal display of the delegate in a \l Loader which
  1080     can load additional elements when needed.
  1247     can load additional elements when needed.
  1081 
  1248 
  1082     Note that the GridView will layout the items based on the size of the root item
  1249     The GridView will layout the items based on the size of the root item
  1083     in the delegate.
  1250     in the delegate.
  1084 
  1251 
  1085     Here is an example delegate:
  1252     \note Delegates are instantiated as needed and may be destroyed at any time.
  1086     \snippet doc/src/snippets/declarative/gridview/gridview.qml 0
  1253     State should \e never be stored in a delegate.
  1087 */
  1254 */
  1088 QDeclarativeComponent *QDeclarativeGridView::delegate() const
  1255 QDeclarativeComponent *QDeclarativeGridView::delegate() const
  1089 {
  1256 {
  1090     Q_D(const QDeclarativeGridView);
  1257     Q_D(const QDeclarativeGridView);
  1091     if (d->model) {
  1258     if (d->model) {
  1110         dataModel->setDelegate(delegate);
  1277         dataModel->setDelegate(delegate);
  1111         if (isComponentComplete()) {
  1278         if (isComponentComplete()) {
  1112             refill();
  1279             refill();
  1113             d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
  1280             d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
  1114             d->updateCurrent(d->currentIndex);
  1281             d->updateCurrent(d->currentIndex);
       
  1282             if (d->highlight && d->currentItem) {
       
  1283                 d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
       
  1284                 d->updateTrackedItem();
       
  1285             }
       
  1286             d->moveReason = QDeclarativeGridViewPrivate::Other;
  1115         }
  1287         }
  1116         emit delegateChanged();
  1288         emit delegateChanged();
  1117     }
  1289     }
  1118 }
  1290 }
  1119 
  1291 
  1120 /*!
  1292 /*!
  1121   \qmlproperty int GridView::currentIndex
  1293   \qmlproperty int GridView::currentIndex
  1122   \qmlproperty Item GridView::currentItem
  1294   \qmlproperty Item GridView::currentItem
  1123 
  1295 
  1124   \c currentIndex holds the index of the current item.
  1296     The \c currentIndex property holds the index of the current item, and
  1125   \c currentItem is the current item.  Note that the position of the current item
  1297     \c currentItem holds the current item. 
  1126   may only be approximate until it becomes visible in the view.
  1298 
       
  1299     If highlightFollowsCurrentItem is \c true, setting either of these 
       
  1300     properties will smoothly scroll the GridView so that the current 
       
  1301     item becomes visible.
       
  1302     
       
  1303     Note that the position of the current item
       
  1304     may only be approximate until it becomes visible in the view.
  1127 */
  1305 */
  1128 int QDeclarativeGridView::currentIndex() const
  1306 int QDeclarativeGridView::currentIndex() const
  1129 {
  1307 {
  1130     Q_D(const QDeclarativeGridView);
  1308     Q_D(const QDeclarativeGridView);
  1131     return d->currentIndex;
  1309     return d->currentIndex;
  1136     Q_D(QDeclarativeGridView);
  1314     Q_D(QDeclarativeGridView);
  1137     if (d->requestedIndex >= 0) // currently creating item
  1315     if (d->requestedIndex >= 0) // currently creating item
  1138         return;
  1316         return;
  1139     if (isComponentComplete() && d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0) {
  1317     if (isComponentComplete() && d->isValid() && index != d->currentIndex && index < d->model->count() && index >= 0) {
  1140         d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
  1318         d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
  1141         cancelFlick();
       
  1142         d->updateCurrent(index);
  1319         d->updateCurrent(index);
  1143     } else if (index != d->currentIndex) {
  1320     } else if (index != d->currentIndex) {
  1144         d->currentIndex = index;
  1321         d->currentIndex = index;
  1145         emit currentIndexChanged();
  1322         emit currentIndexChanged();
  1146     }
  1323     }
  1155 }
  1332 }
  1156 
  1333 
  1157 /*!
  1334 /*!
  1158   \qmlproperty Item GridView::highlightItem
  1335   \qmlproperty Item GridView::highlightItem
  1159 
  1336 
  1160   \c highlightItem holds the highlight item, which was created
  1337   This holds the highlight item created from the \l highlight component.
  1161   from the \l highlight component.
       
  1162 
  1338 
  1163   The highlightItem is managed by the view unless
  1339   The highlightItem is managed by the view unless
  1164   \l highlightFollowsCurrentItem is set to false.
  1340   \l highlightFollowsCurrentItem is set to false.
  1165 
  1341 
  1166   \sa highlight, highlightFollowsCurrentItem
  1342   \sa highlight, highlightFollowsCurrentItem
  1187 
  1363 
  1188 /*!
  1364 /*!
  1189   \qmlproperty Component GridView::highlight
  1365   \qmlproperty Component GridView::highlight
  1190   This property holds the component to use as the highlight.
  1366   This property holds the component to use as the highlight.
  1191 
  1367 
  1192   An instance of the highlight component will be created for each view.
  1368   An instance of the highlight component is created for each view.
  1193   The geometry of the resultant component instance will be managed by the view
  1369   The geometry of the resulting component instance will be managed by the view
  1194   so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
  1370   so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
  1195 
       
  1196   The below example demonstrates how to make a simple highlight:
       
  1197   \snippet doc/src/snippets/declarative/gridview/gridview.qml 1
       
  1198 
  1371 
  1199   \sa highlightItem, highlightFollowsCurrentItem
  1372   \sa highlightItem, highlightFollowsCurrentItem
  1200 */
  1373 */
  1201 QDeclarativeComponent *QDeclarativeGridView::highlight() const
  1374 QDeclarativeComponent *QDeclarativeGridView::highlight() const
  1202 {
  1375 {
  1216 
  1389 
  1217 /*!
  1390 /*!
  1218   \qmlproperty bool GridView::highlightFollowsCurrentItem
  1391   \qmlproperty bool GridView::highlightFollowsCurrentItem
  1219   This property sets whether the highlight is managed by the view.
  1392   This property sets whether the highlight is managed by the view.
  1220 
  1393 
  1221   If highlightFollowsCurrentItem is true, the highlight will be moved smoothly
  1394     If this property is true (the default value), the highlight is moved smoothly
  1222   to follow the current item.  If highlightFollowsCurrentItem is false, the
  1395     to follow the current item.  Otherwise, the
  1223   highlight will not be moved by the view, and must be implemented
  1396     highlight is not moved by the view, and any movement must be implemented
  1224   by the highlight component, for example:
  1397     by the highlight.  
  1225 
  1398     
  1226   \code
  1399     Here is a highlight with its motion defined by a \l {SpringAnimation} item:
  1227   Component {
  1400 
  1228       id: myHighlight
  1401     \snippet doc/src/snippets/declarative/gridview/gridview.qml highlightFollowsCurrentItem
  1229       Rectangle {
       
  1230           id: wrapper; color: "lightsteelblue"; radius: 4; width: 320; height: 60
       
  1231           SpringFollow on y { source: wrapper.GridView.view.currentItem.y; spring: 3; damping: 0.2 }
       
  1232           SpringFollow on x { source: wrapper.GridView.view.currentItem.x; spring: 3; damping: 0.2 }
       
  1233       }
       
  1234   }
       
  1235   \endcode
       
  1236 */
  1402 */
  1237 bool QDeclarativeGridView::highlightFollowsCurrentItem() const
  1403 bool QDeclarativeGridView::highlightFollowsCurrentItem() const
  1238 {
  1404 {
  1239     Q_D(const QDeclarativeGridView);
  1405     Q_D(const QDeclarativeGridView);
  1240     return d->autoHighlight;
  1406     return d->autoHighlight;
  1288 /*!
  1454 /*!
  1289     \qmlproperty real GridView::preferredHighlightBegin
  1455     \qmlproperty real GridView::preferredHighlightBegin
  1290     \qmlproperty real GridView::preferredHighlightEnd
  1456     \qmlproperty real GridView::preferredHighlightEnd
  1291     \qmlproperty enumeration GridView::highlightRangeMode
  1457     \qmlproperty enumeration GridView::highlightRangeMode
  1292 
  1458 
  1293     These properties set the preferred range of the highlight (current item)
  1459     These properties define the preferred range of the highlight (for the current item)
  1294     within the view.
  1460     within the view. The \c preferredHighlightBegin value must be less than the
  1295 
  1461     \c preferredHighlightEnd value. 
  1296     Note that this is the correct way to influence where the
  1462 
  1297     current item ends up when the view scrolls. For example, if you want the
  1463     These properties affect the position of the current item when the view is scrolled.
  1298     currently selected item to be in the middle of the list, then set the
  1464     For example, if the currently selected item should stay in the middle of the
  1299     highlight range to be where the middle item would go. Then, when the view scrolls,
  1465     view when it is scrolled, set the \c preferredHighlightBegin and 
  1300     the currently selected item will be the item at that spot. This also applies to
  1466     \c preferredHighlightEnd values to the top and bottom coordinates of where the middle 
  1301     when the currently selected item changes - it will scroll to within the preferred
  1467     item would be. If the \c currentItem is changed programmatically, the view will
  1302     highlight range. Furthermore, the behaviour of the current item index will occur
  1468     automatically scroll so that the current item is in the middle of the view.
  1303     whether or not a highlight exists.
  1469     Furthermore, the behavior of the current item index will occur whether or not a
  1304 
  1470     highlight exists.
  1305     If highlightRangeMode is set to \e GridView.ApplyRange the view will
  1471 
  1306     attempt to maintain the highlight within the range, however
  1472     Valid values for \c highlightRangeMode are:
  1307     the highlight can move outside of the range at the ends of the list
  1473 
  1308     or due to a mouse interaction.
  1474     \list
  1309 
  1475     \o GridView.ApplyRange - the view attempts to maintain the highlight within the range.
  1310     If highlightRangeMode is set to \e GridView.StrictlyEnforceRange the highlight will never
  1476        However, the highlight can move outside of the range at the ends of the view or due
  1311     move outside of the range.  This means that the current item will change
  1477        to mouse interaction.
  1312     if a keyboard or mouse action would cause the highlight to move
  1478     \o GridView.StrictlyEnforceRange - the highlight never moves outside of the range.
  1313     outside of the range.
  1479        The current item changes if a keyboard or mouse action would cause the highlight to move
  1314 
  1480        outside of the range.
  1315     The default value is \e GridView.NoHighlightRange.
  1481     \o GridView.NoHighlightRange - this is the default value.
  1316 
  1482     \endlist
  1317     Note that a valid range requires preferredHighlightEnd to be greater
       
  1318     than or equal to preferredHighlightBegin.
       
  1319 */
  1483 */
  1320 qreal QDeclarativeGridView::preferredHighlightBegin() const
  1484 qreal QDeclarativeGridView::preferredHighlightBegin() const
  1321 {
  1485 {
  1322     Q_D(const QDeclarativeGridView);
  1486     Q_D(const QDeclarativeGridView);
  1323     return d->highlightRangeStart;
  1487     return d->highlightRangeStart;
  1368 
  1532 
  1369 /*!
  1533 /*!
  1370   \qmlproperty enumeration GridView::flow
  1534   \qmlproperty enumeration GridView::flow
  1371   This property holds the flow of the grid.
  1535   This property holds the flow of the grid.
  1372 
  1536 
  1373   Possible values are \c GridView.LeftToRight (default) and \c GridView.TopToBottom.
  1537     Possible values:
  1374 
  1538 
  1375   If \a flow is \c GridView.LeftToRight, the view will scroll vertically.
  1539     \list
  1376   If \a flow is \c GridView.TopToBottom, the view will scroll horizontally.
  1540     \o GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically
       
  1541     \o GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally
       
  1542     \endlist
  1377 */
  1543 */
  1378 QDeclarativeGridView::Flow QDeclarativeGridView::flow() const
  1544 QDeclarativeGridView::Flow QDeclarativeGridView::flow() const
  1379 {
  1545 {
  1380     Q_D(const QDeclarativeGridView);
  1546     Q_D(const QDeclarativeGridView);
  1381     return d->flow;
  1547     return d->flow;
  1403 
  1569 
  1404 /*!
  1570 /*!
  1405   \qmlproperty bool GridView::keyNavigationWraps
  1571   \qmlproperty bool GridView::keyNavigationWraps
  1406   This property holds whether the grid wraps key navigation
  1572   This property holds whether the grid wraps key navigation
  1407 
  1573 
  1408   If this property is true then key presses to move off of one end of the grid will cause the
  1574     If this is true, key navigation that would move the current item selection
  1409   selection to jump to the other side.
  1575     past one end of the view instead wraps around and moves the selection to
       
  1576     the other end of the view.
       
  1577 
       
  1578     By default, key navigation is not wrapped.
  1410 */
  1579 */
  1411 bool QDeclarativeGridView::isWrapEnabled() const
  1580 bool QDeclarativeGridView::isWrapEnabled() const
  1412 {
  1581 {
  1413     Q_D(const QDeclarativeGridView);
  1582     Q_D(const QDeclarativeGridView);
  1414     return d->wrap;
  1583     return d->wrap;
  1461 
  1630 
  1462 /*!
  1631 /*!
  1463   \qmlproperty int GridView::cellWidth
  1632   \qmlproperty int GridView::cellWidth
  1464   \qmlproperty int GridView::cellHeight
  1633   \qmlproperty int GridView::cellHeight
  1465 
  1634 
  1466   These properties holds the width and height of each cell in the grid
  1635   These properties holds the width and height of each cell in the grid.
  1467 
  1636 
  1468   The default cell size is 100x100.
  1637   The default cell size is 100x100.
  1469 */
  1638 */
  1470 int QDeclarativeGridView::cellWidth() const
  1639 int QDeclarativeGridView::cellWidth() const
  1471 {
  1640 {
  1501     }
  1670     }
  1502 }
  1671 }
  1503 /*!
  1672 /*!
  1504     \qmlproperty enumeration GridView::snapMode
  1673     \qmlproperty enumeration GridView::snapMode
  1505 
  1674 
  1506     This property determines where the view will settle following a drag or flick.
  1675     This property determines how the view scrolling will settle following a drag or flick.
  1507     The allowed values are:
  1676     The possible values are:
  1508 
  1677 
  1509     \list
  1678     \list
  1510     \o GridView.NoSnap (default) - the view will stop anywhere within the visible area.
  1679     \o GridView.NoSnap (default) - the view stops anywhere within the visible area.
  1511     \o GridView.SnapToRow - the view will settle with a row (or column for TopToBottom flow)
  1680     \o GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow)
  1512     aligned with the start of the view.
  1681     aligned with the start of the view.
  1513     \o GridView.SnapOneRow - the view will settle no more than one row (or column for TopToBottom flow)
  1682     \o GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow)
  1514     away from the first visible row at the time the mouse button is released.
  1683     away from the first visible row at the time the mouse button is released.
  1515     This mode is particularly useful for moving one page at a time.
  1684     This mode is particularly useful for moving one page at a time.
  1516     \endlist
  1685     \endlist
  1517 
  1686 
  1518 */
  1687 */
  1527     Q_D(QDeclarativeGridView);
  1696     Q_D(QDeclarativeGridView);
  1528     if (d->snapMode != mode) {
  1697     if (d->snapMode != mode) {
  1529         d->snapMode = mode;
  1698         d->snapMode = mode;
  1530         emit snapModeChanged();
  1699         emit snapModeChanged();
  1531     }
  1700     }
       
  1701 }
       
  1702 
       
  1703 /*!
       
  1704     \qmlproperty Component GridView::footer
       
  1705     This property holds the component to use as the footer.
       
  1706 
       
  1707     An instance of the footer component is created for each view.  The
       
  1708     footer is positioned at the end of the view, after any items.
       
  1709 
       
  1710     \sa header
       
  1711 */
       
  1712 QDeclarativeComponent *QDeclarativeGridView::footer() const
       
  1713 {
       
  1714     Q_D(const QDeclarativeGridView);
       
  1715     return d->footerComponent;
       
  1716 }
       
  1717 
       
  1718 void QDeclarativeGridView::setFooter(QDeclarativeComponent *footer)
       
  1719 {
       
  1720     Q_D(QDeclarativeGridView);
       
  1721     if (d->footerComponent != footer) {
       
  1722         if (d->footer) {
       
  1723             delete d->footer;
       
  1724             d->footer = 0;
       
  1725         }
       
  1726         d->footerComponent = footer;
       
  1727         d->updateFooter();
       
  1728         d->updateGrid();
       
  1729         emit footerChanged();
       
  1730     }
       
  1731 }
       
  1732 
       
  1733 /*!
       
  1734     \qmlproperty Component GridView::header
       
  1735     This property holds the component to use as the header.
       
  1736 
       
  1737     An instance of the header component is created for each view.  The
       
  1738     header is positioned at the beginning of the view, before any items.
       
  1739 
       
  1740     \sa footer
       
  1741 */
       
  1742 QDeclarativeComponent *QDeclarativeGridView::header() const
       
  1743 {
       
  1744     Q_D(const QDeclarativeGridView);
       
  1745     return d->headerComponent;
       
  1746 }
       
  1747 
       
  1748 void QDeclarativeGridView::setHeader(QDeclarativeComponent *header)
       
  1749 {
       
  1750     Q_D(QDeclarativeGridView);
       
  1751     if (d->headerComponent != header) {
       
  1752         if (d->header) {
       
  1753             delete d->header;
       
  1754             d->header = 0;
       
  1755         }
       
  1756         d->headerComponent = header;
       
  1757         d->updateHeader();
       
  1758         d->updateFooter();
       
  1759         d->updateGrid();
       
  1760         emit headerChanged();
       
  1761     }
       
  1762 }
       
  1763 
       
  1764 void QDeclarativeGridView::setContentX(qreal pos)
       
  1765 {
       
  1766     Q_D(QDeclarativeGridView);
       
  1767     // Positioning the view manually should override any current movement state
       
  1768     d->moveReason = QDeclarativeGridViewPrivate::Other;
       
  1769     QDeclarativeFlickable::setContentX(pos);
       
  1770 }
       
  1771 
       
  1772 void QDeclarativeGridView::setContentY(qreal pos)
       
  1773 {
       
  1774     Q_D(QDeclarativeGridView);
       
  1775     // Positioning the view manually should override any current movement state
       
  1776     d->moveReason = QDeclarativeGridViewPrivate::Other;
       
  1777     QDeclarativeFlickable::setContentY(pos);
  1532 }
  1778 }
  1533 
  1779 
  1534 bool QDeclarativeGridView::event(QEvent *event)
  1780 bool QDeclarativeGridView::event(QEvent *event)
  1535 {
  1781 {
  1536     Q_D(QDeclarativeGridView);
  1782     Q_D(QDeclarativeGridView);
  1595 {
  1841 {
  1596     Q_D(const QDeclarativeGridView);
  1842     Q_D(const QDeclarativeGridView);
  1597     if (d->flow == QDeclarativeGridView::TopToBottom)
  1843     if (d->flow == QDeclarativeGridView::TopToBottom)
  1598         return QDeclarativeFlickable::minYExtent();
  1844         return QDeclarativeFlickable::minYExtent();
  1599     qreal extent = -d->startPosition();
  1845     qreal extent = -d->startPosition();
       
  1846     if (d->header && d->visibleItems.count())
       
  1847         extent += d->header->item->height();
  1600     if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
  1848     if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
  1601         extent += d->highlightRangeStart;
  1849         extent += d->highlightRangeStart;
  1602         extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
  1850         extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
  1603     }
  1851     }
  1604     return extent;
  1852     return extent;
  1608 {
  1856 {
  1609     Q_D(const QDeclarativeGridView);
  1857     Q_D(const QDeclarativeGridView);
  1610     if (d->flow == QDeclarativeGridView::TopToBottom)
  1858     if (d->flow == QDeclarativeGridView::TopToBottom)
  1611         return QDeclarativeFlickable::maxYExtent();
  1859         return QDeclarativeFlickable::maxYExtent();
  1612     qreal extent;
  1860     qreal extent;
  1613     if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
  1861     if (!d->model || !d->model->count()) {
       
  1862         extent = 0;
       
  1863     } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
  1614         extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
  1864         extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
  1615         if (d->highlightRangeEnd != d->highlightRangeStart)
  1865         if (d->highlightRangeEnd != d->highlightRangeStart)
  1616             extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
  1866             extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
  1617     } else {
  1867     } else {
  1618         extent = -(d->endPosition() - height());
  1868         extent = -(d->endPosition() - height());
  1619     }
  1869     }
       
  1870     if (d->footer)
       
  1871         extent -= d->footer->item->height();
  1620     const qreal minY = minYExtent();
  1872     const qreal minY = minYExtent();
  1621     if (extent > minY)
  1873     if (extent > minY)
  1622         extent = minY;
  1874         extent = minY;
  1623     return extent;
  1875     return extent;
  1624 }
  1876 }
  1627 {
  1879 {
  1628     Q_D(const QDeclarativeGridView);
  1880     Q_D(const QDeclarativeGridView);
  1629     if (d->flow == QDeclarativeGridView::LeftToRight)
  1881     if (d->flow == QDeclarativeGridView::LeftToRight)
  1630         return QDeclarativeFlickable::minXExtent();
  1882         return QDeclarativeFlickable::minXExtent();
  1631     qreal extent = -d->startPosition();
  1883     qreal extent = -d->startPosition();
       
  1884     if (d->header && d->visibleItems.count())
       
  1885         extent += d->header->item->width();
  1632     if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
  1886     if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
  1633         extent += d->highlightRangeStart;
  1887         extent += d->highlightRangeStart;
  1634         extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
  1888         extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd));
  1635     }
  1889     }
  1636     return extent;
  1890     return extent;
  1640 {
  1894 {
  1641     Q_D(const QDeclarativeGridView);
  1895     Q_D(const QDeclarativeGridView);
  1642     if (d->flow == QDeclarativeGridView::LeftToRight)
  1896     if (d->flow == QDeclarativeGridView::LeftToRight)
  1643         return QDeclarativeFlickable::maxXExtent();
  1897         return QDeclarativeFlickable::maxXExtent();
  1644     qreal extent;
  1898     qreal extent;
  1645     if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
  1899     if (!d->model || !d->model->count()) {
       
  1900         extent = 0;
       
  1901     } if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
  1646         extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
  1902         extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart);
  1647         if (d->highlightRangeEnd != d->highlightRangeStart)
  1903         if (d->highlightRangeEnd != d->highlightRangeStart)
  1648             extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
  1904             extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1));
  1649     } else {
  1905     } else {
  1650         extent = -(d->endPosition() - height());
  1906         extent = -(d->endPosition() - width());
  1651     }
  1907     }
       
  1908     if (d->footer)
       
  1909         extent -= d->footer->item->width();
  1652     const qreal minX = minXExtent();
  1910     const qreal minX = minXExtent();
  1653     if (extent > minX)
  1911     if (extent > minX)
  1654         extent = minX;
  1912         extent = minX;
  1655     return extent;
  1913     return extent;
  1656 }
  1914 }
  1694     \qmlmethod GridView::moveCurrentIndexUp()
  1952     \qmlmethod GridView::moveCurrentIndexUp()
  1695 
  1953 
  1696     Move the currentIndex up one item in the view.
  1954     Move the currentIndex up one item in the view.
  1697     The current index will wrap if keyNavigationWraps is true and it
  1955     The current index will wrap if keyNavigationWraps is true and it
  1698     is currently at the end.
  1956     is currently at the end.
       
  1957 
       
  1958     \bold Note: methods should only be called after the Component has completed.
  1699 */
  1959 */
  1700 void QDeclarativeGridView::moveCurrentIndexUp()
  1960 void QDeclarativeGridView::moveCurrentIndexUp()
  1701 {
  1961 {
  1702     Q_D(QDeclarativeGridView);
  1962     Q_D(QDeclarativeGridView);
  1703     if (d->flow == QDeclarativeGridView::LeftToRight) {
  1963     if (d->flow == QDeclarativeGridView::LeftToRight) {
  1717     \qmlmethod GridView::moveCurrentIndexDown()
  1977     \qmlmethod GridView::moveCurrentIndexDown()
  1718 
  1978 
  1719     Move the currentIndex down one item in the view.
  1979     Move the currentIndex down one item in the view.
  1720     The current index will wrap if keyNavigationWraps is true and it
  1980     The current index will wrap if keyNavigationWraps is true and it
  1721     is currently at the end.
  1981     is currently at the end.
       
  1982 
       
  1983     \bold Note: methods should only be called after the Component has completed.
  1722 */
  1984 */
  1723 void QDeclarativeGridView::moveCurrentIndexDown()
  1985 void QDeclarativeGridView::moveCurrentIndexDown()
  1724 {
  1986 {
  1725     Q_D(QDeclarativeGridView);
  1987     Q_D(QDeclarativeGridView);
  1726     if (d->flow == QDeclarativeGridView::LeftToRight) {
  1988     if (d->flow == QDeclarativeGridView::LeftToRight) {
  1740     \qmlmethod GridView::moveCurrentIndexLeft()
  2002     \qmlmethod GridView::moveCurrentIndexLeft()
  1741 
  2003 
  1742     Move the currentIndex left one item in the view.
  2004     Move the currentIndex left one item in the view.
  1743     The current index will wrap if keyNavigationWraps is true and it
  2005     The current index will wrap if keyNavigationWraps is true and it
  1744     is currently at the end.
  2006     is currently at the end.
       
  2007 
       
  2008     \bold Note: methods should only be called after the Component has completed.
  1745 */
  2009 */
  1746 void QDeclarativeGridView::moveCurrentIndexLeft()
  2010 void QDeclarativeGridView::moveCurrentIndexLeft()
  1747 {
  2011 {
  1748     Q_D(QDeclarativeGridView);
  2012     Q_D(QDeclarativeGridView);
  1749     if (d->flow == QDeclarativeGridView::LeftToRight) {
  2013     if (d->flow == QDeclarativeGridView::LeftToRight) {
  1763     \qmlmethod GridView::moveCurrentIndexRight()
  2027     \qmlmethod GridView::moveCurrentIndexRight()
  1764 
  2028 
  1765     Move the currentIndex right one item in the view.
  2029     Move the currentIndex right one item in the view.
  1766     The current index will wrap if keyNavigationWraps is true and it
  2030     The current index will wrap if keyNavigationWraps is true and it
  1767     is currently at the end.
  2031     is currently at the end.
       
  2032 
       
  2033     \bold Note: methods should only be called after the Component has completed.
  1768 */
  2034 */
  1769 void QDeclarativeGridView::moveCurrentIndexRight()
  2035 void QDeclarativeGridView::moveCurrentIndexRight()
  1770 {
  2036 {
  1771     Q_D(QDeclarativeGridView);
  2037     Q_D(QDeclarativeGridView);
  1772     if (d->flow == QDeclarativeGridView::LeftToRight) {
  2038     if (d->flow == QDeclarativeGridView::LeftToRight) {
  1787 
  2053 
  1788     Positions the view such that the \a index is at the position specified by
  2054     Positions the view such that the \a index is at the position specified by
  1789     \a mode:
  2055     \a mode:
  1790 
  2056 
  1791     \list
  2057     \list
  1792     \o Beginning - position item at the top (or left for TopToBottom flow) of the view.
  2058     \o GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view.
  1793     \o Center- position item in the center of the view.
  2059     \o GridView.Center - position item in the center of the view.
  1794     \o End - position item at bottom (or right for horizontal orientation) of the view.
  2060     \o GridView.End - position item at bottom (or right for horizontal orientation) of the view.
  1795     \o Visible - if any part of the item is visible then take no action, otherwise
  2061     \o GridView.Visible - if any part of the item is visible then take no action, otherwise
  1796     bring the item into view.
  2062     bring the item into view.
  1797     \o Contain - ensure the entire item is visible.  If the item is larger than
  2063     \o GridView.Contain - ensure the entire item is visible.  If the item is larger than
  1798     the view the item is positioned at the top (or left for TopToBottom flow) of the view.
  2064     the view the item is positioned at the top (or left for \c GridView.TopToBottom flow) of the view.
  1799     \endlist
  2065     \endlist
  1800 
  2066 
  1801     If positioning the view at the index would cause empty space to be displayed at
  2067     If positioning the view at the index would cause empty space to be displayed at
  1802     the beginning or end of the view, the view will be positioned at the boundary.
  2068     the beginning or end of the view, the view will be positioned at the boundary.
  1803 
  2069 
  1804     It is not recommended to use contentX or contentY to position the view
  2070     It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
  1805     at a particular index.  This is unreliable since removing items from the start
  2071     at a particular index.  This is unreliable since removing items from the start
  1806     of the view does not cause all other items to be repositioned.
  2072     of the view does not cause all other items to be repositioned.
  1807     The correct way to bring an item into view is with positionViewAtIndex.
  2073     The correct way to bring an item into view is with \c positionViewAtIndex.
       
  2074 
       
  2075     \bold Note: methods should only be called after the Component has completed.  To position
       
  2076     the view at startup, this method should be called by Component.onCompleted.  For
       
  2077     example, to position the view at the end:
       
  2078 
       
  2079     \code
       
  2080     Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
       
  2081     \endcode
  1808 */
  2082 */
  1809 void QDeclarativeGridView::positionViewAtIndex(int index, int mode)
  2083 void QDeclarativeGridView::positionViewAtIndex(int index, int mode)
  1810 {
  2084 {
  1811     Q_D(QDeclarativeGridView);
  2085     Q_D(QDeclarativeGridView);
  1812     if (!d->isValid() || index < 0 || index >= d->model->count())
  2086     if (!d->isValid() || index < 0 || index >= d->model->count())
  1813         return;
  2087         return;
  1814     if (mode < Beginning || mode > Contain)
  2088     if (mode < Beginning || mode > Contain)
  1815         return;
  2089         return;
  1816 
  2090 
       
  2091     if (d->layoutScheduled)
       
  2092         d->layout();
  1817     qreal pos = d->position();
  2093     qreal pos = d->position();
  1818     FxGridItem *item = d->visibleItem(index);
  2094     FxGridItem *item = d->visibleItem(index);
  1819     if (!item) {
  2095     if (!item) {
  1820         int itemPos = d->rowPosAt(index);
  2096         int itemPos = d->rowPosAt(index);
  1821         // save the currently visible items in case any of them end up visible again
  2097         // save the currently visible items in case any of them end up visible again
  1854         }
  2130         }
  1855         qreal maxExtent = d->flow == QDeclarativeGridView::LeftToRight ? -maxYExtent() : -maxXExtent();
  2131         qreal maxExtent = d->flow == QDeclarativeGridView::LeftToRight ? -maxYExtent() : -maxXExtent();
  1856         pos = qMin(pos, maxExtent);
  2132         pos = qMin(pos, maxExtent);
  1857         qreal minExtent = d->flow == QDeclarativeGridView::LeftToRight ? -minYExtent() : -minXExtent();
  2133         qreal minExtent = d->flow == QDeclarativeGridView::LeftToRight ? -minYExtent() : -minXExtent();
  1858         pos = qMax(pos, minExtent);
  2134         pos = qMax(pos, minExtent);
       
  2135         d->moveReason = QDeclarativeGridViewPrivate::Other;
       
  2136         cancelFlick();
  1859         d->setPosition(pos);
  2137         d->setPosition(pos);
  1860     }
  2138     }
  1861     d->fixupPosition();
  2139     d->fixupPosition();
  1862 }
  2140 }
  1863 
  2141 
  1868     coordinates.  If there is no item at the point specified, or the item is
  2146     coordinates.  If there is no item at the point specified, or the item is
  1869     not visible -1 is returned.
  2147     not visible -1 is returned.
  1870 
  2148 
  1871     If the item is outside the visible area, -1 is returned, regardless of
  2149     If the item is outside the visible area, -1 is returned, regardless of
  1872     whether an item will exist at that point when scrolled into view.
  2150     whether an item will exist at that point when scrolled into view.
       
  2151 
       
  2152     \bold Note: methods should only be called after the Component has completed.
  1873 */
  2153 */
  1874 int QDeclarativeGridView::indexAt(int x, int y) const
  2154 int QDeclarativeGridView::indexAt(int x, int y) const
  1875 {
  2155 {
  1876     Q_D(const QDeclarativeGridView);
  2156     Q_D(const QDeclarativeGridView);
  1877     for (int i = 0; i < d->visibleItems.count(); ++i) {
  2157     for (int i = 0; i < d->visibleItems.count(); ++i) {
  1888     Q_D(QDeclarativeGridView);
  2168     Q_D(QDeclarativeGridView);
  1889     QDeclarativeFlickable::componentComplete();
  2169     QDeclarativeFlickable::componentComplete();
  1890     d->updateGrid();
  2170     d->updateGrid();
  1891     if (d->isValid()) {
  2171     if (d->isValid()) {
  1892         refill();
  2172         refill();
       
  2173         d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
  1893         if (d->currentIndex < 0)
  2174         if (d->currentIndex < 0)
  1894             d->updateCurrent(0);
  2175             d->updateCurrent(0);
  1895         else
  2176         else
  1896             d->updateCurrent(d->currentIndex);
  2177             d->updateCurrent(d->currentIndex);
       
  2178         if (d->highlight && d->currentItem) {
       
  2179             d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
       
  2180             d->updateTrackedItem();
       
  2181         }
       
  2182         d->moveReason = QDeclarativeGridViewPrivate::Other;
  1897         d->fixupPosition();
  2183         d->fixupPosition();
  1898     }
  2184     }
  1899 }
  2185 }
  1900 
  2186 
  1901 void QDeclarativeGridView::trackedPositionChanged()
  2187 void QDeclarativeGridView::trackedPositionChanged()
  1902 {
  2188 {
  1903     Q_D(QDeclarativeGridView);
  2189     Q_D(QDeclarativeGridView);
  1904     if (!d->trackedItem || !d->currentItem)
  2190     if (!d->trackedItem || !d->currentItem)
  1905         return;
  2191         return;
  1906     if (!d->flickingHorizontally && !d->flickingVertically && !d->movingHorizontally && !d->movingVertically
  2192     if (d->moveReason == QDeclarativeGridViewPrivate::SetIndex) {
  1907         && d->moveReason == QDeclarativeGridViewPrivate::SetIndex) {
       
  1908         const qreal trackedPos = d->trackedItem->rowPos();
  2193         const qreal trackedPos = d->trackedItem->rowPos();
  1909         const qreal viewPos = d->position();
  2194         const qreal viewPos = d->position();
       
  2195         qreal pos = viewPos;
  1910         if (d->haveHighlightRange) {
  2196         if (d->haveHighlightRange) {
  1911             if (d->highlightRange == StrictlyEnforceRange) {
  2197             if (d->highlightRange == StrictlyEnforceRange) {
  1912                 qreal pos = viewPos;
       
  1913                 if (trackedPos > pos + d->highlightRangeEnd - d->rowSize())
  2198                 if (trackedPos > pos + d->highlightRangeEnd - d->rowSize())
  1914                     pos = trackedPos - d->highlightRangeEnd + d->rowSize();
  2199                     pos = trackedPos - d->highlightRangeEnd + d->rowSize();
  1915                 if (trackedPos < pos + d->highlightRangeStart)
  2200                 if (trackedPos < pos + d->highlightRangeStart)
  1916                     pos = trackedPos - d->highlightRangeStart;
  2201                     pos = trackedPos - d->highlightRangeStart;
  1917                 d->setPosition(pos);
       
  1918             } else {
  2202             } else {
  1919                 qreal pos = viewPos;
       
  1920                 if (trackedPos < d->startPosition() + d->highlightRangeStart) {
  2203                 if (trackedPos < d->startPosition() + d->highlightRangeStart) {
  1921                     pos = d->startPosition();
  2204                     pos = d->startPosition();
  1922                 } else if (d->trackedItem->endRowPos() > d->endPosition() - d->size() + d->highlightRangeEnd) {
  2205                 } else if (d->trackedItem->endRowPos() > d->endPosition() - d->size() + d->highlightRangeEnd) {
  1923                     pos = d->endPosition() - d->size();
  2206                     pos = d->endPosition() - d->size();
  1924                     if (pos < d->startPosition())
  2207                     if (pos < d->startPosition())
  1928                         pos = trackedPos - d->highlightRangeStart;
  2211                         pos = trackedPos - d->highlightRangeStart;
  1929                     } else if (trackedPos > viewPos + d->highlightRangeEnd - d->rowSize()) {
  2212                     } else if (trackedPos > viewPos + d->highlightRangeEnd - d->rowSize()) {
  1930                         pos = trackedPos - d->highlightRangeEnd + d->rowSize();
  2213                         pos = trackedPos - d->highlightRangeEnd + d->rowSize();
  1931                     }
  2214                     }
  1932                 }
  2215                 }
  1933                 d->setPosition(pos);
       
  1934             }
  2216             }
  1935         } else {
  2217         } else {
  1936             if (trackedPos < viewPos && d->currentItem->rowPos() < viewPos) {
  2218             if (trackedPos < viewPos && d->currentItem->rowPos() < viewPos) {
  1937                 d->setPosition(d->currentItem->rowPos() < trackedPos ? trackedPos : d->currentItem->rowPos());
  2219                 pos = d->currentItem->rowPos() < trackedPos ? trackedPos : d->currentItem->rowPos();
  1938             } else if (d->trackedItem->endRowPos() > viewPos + d->size()
  2220             } else if (d->trackedItem->endRowPos() > viewPos + d->size()
  1939                 && d->currentItem->endRowPos() > viewPos + d->size()) {
  2221                 && d->currentItem->endRowPos() > viewPos + d->size()) {
  1940                 qreal pos;
       
  1941                 if (d->trackedItem->endRowPos() < d->currentItem->endRowPos()) {
  2222                 if (d->trackedItem->endRowPos() < d->currentItem->endRowPos()) {
  1942                     pos = d->trackedItem->endRowPos() - d->size();
  2223                     pos = d->trackedItem->endRowPos() - d->size();
  1943                     if (d->rowSize() > d->size())
  2224                     if (d->rowSize() > d->size())
  1944                         pos = trackedPos;
  2225                         pos = trackedPos;
  1945                 } else {
  2226                 } else {
  1946                     pos = d->currentItem->endRowPos() - d->size();
  2227                     pos = d->currentItem->endRowPos() - d->size();
  1947                     if (d->rowSize() > d->size())
  2228                     if (d->rowSize() > d->size())
  1948                         pos = d->currentItem->rowPos();
  2229                         pos = d->currentItem->rowPos();
  1949                 }
  2230                 }
  1950                 d->setPosition(pos);
  2231             }
  1951             }
  2232         }
       
  2233         if (viewPos != pos) {
       
  2234             cancelFlick();
       
  2235             d->setPosition(pos);
  1952         }
  2236         }
  1953     }
  2237     }
  1954 }
  2238 }
  1955 
  2239 
  1956 void QDeclarativeGridView::itemsInserted(int modelIndex, int count)
  2240 void QDeclarativeGridView::itemsInserted(int modelIndex, int count)
  2160     }
  2444     }
  2161 
  2445 
  2162     if (removedVisible && d->visibleItems.isEmpty()) {
  2446     if (removedVisible && d->visibleItems.isEmpty()) {
  2163         d->timeline.clear();
  2447         d->timeline.clear();
  2164         d->setPosition(0);
  2448         d->setPosition(0);
  2165         if (d->itemCount == 0)
  2449         if (d->itemCount == 0) {
       
  2450             d->updateHeader();
       
  2451             d->updateFooter();
  2166             update();
  2452             update();
       
  2453         }
  2167     }
  2454     }
  2168 
  2455 
  2169     emit countChanged();
  2456     emit countChanged();
  2170 }
  2457 }
  2171 
  2458 
  2292     Q_D(QDeclarativeGridView);
  2579     Q_D(QDeclarativeGridView);
  2293     d->clear();
  2580     d->clear();
  2294     refill();
  2581     refill();
  2295     d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
  2582     d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
  2296     d->updateCurrent(d->currentIndex);
  2583     d->updateCurrent(d->currentIndex);
       
  2584     if (d->highlight && d->currentItem) {
       
  2585         d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos());
       
  2586         d->updateTrackedItem();
       
  2587     }
       
  2588     d->moveReason = QDeclarativeGridViewPrivate::Other;
       
  2589 
  2297     emit countChanged();
  2590     emit countChanged();
  2298 }
  2591 }
  2299 
  2592 
  2300 void QDeclarativeGridView::createdItem(int index, QDeclarativeItem *item)
  2593 void QDeclarativeGridView::createdItem(int index, QDeclarativeItem *item)
  2301 {
  2594 {