~ubuntu-branches/ubuntu/wily/qtdeclarative-opensource-src/wily-proposed

« back to all changes in this revision

Viewing changes to .pc/Make-ItemViews-displayMargin-work-correctly-when-set.patch/src/quick/items/qquickgridview.cpp

  • Committer: Package Import Robot
  • Author(s): Ricardo Salveti de Araujo, Ricardo Salveti de Araujo, Timo Jyrinki
  • Date: 2014-06-19 02:39:21 UTC
  • mfrom: (0.1.18 experimental)
  • Revision ID: package-import@ubuntu.com-20140619023921-yb2oasnuetz9b0fc
Tags: 5.3.0-3ubuntu4
[ Ricardo Salveti de Araujo ]
* debian/control:
  - Updating dependencies as we now also have libqt5quickwidgets5-gles
* libqt5quickwidgets5.symbols: updating to allow gles variant

[ Timo Jyrinki ]
* Update libqt5quickparticles5.symbols from build logs

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtQuick module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
36
**
 
37
**
 
38
** $QT_END_LICENSE$
 
39
**
 
40
****************************************************************************/
 
41
 
 
42
#include "qquickgridview_p.h"
 
43
#include "qquickflickable_p_p.h"
 
44
#include "qquickitemview_p_p.h"
 
45
 
 
46
#include <private/qqmlobjectmodel_p.h>
 
47
#include <private/qquicksmoothedanimation_p_p.h>
 
48
 
 
49
#include <QtGui/qevent.h>
 
50
#include <QtCore/qmath.h>
 
51
#include <QtCore/qcoreapplication.h>
 
52
#include <math.h>
 
53
#include "qplatformdefs.h"
 
54
 
 
55
QT_BEGIN_NAMESPACE
 
56
 
 
57
#ifndef QML_FLICK_SNAPONETHRESHOLD
 
58
#define QML_FLICK_SNAPONETHRESHOLD 30
 
59
#endif
 
60
 
 
61
//#define DEBUG_DELEGATE_LIFECYCLE
 
62
 
 
63
//----------------------------------------------------------------------------
 
64
 
 
65
class FxGridItemSG : public FxViewItem
 
66
{
 
67
public:
 
68
    FxGridItemSG(QQuickItem *i, QQuickGridView *v, bool own) : FxViewItem(i, v, own, static_cast<QQuickItemViewAttached*>(qmlAttachedPropertiesObject<QQuickGridView>(i))), view(v)
 
69
    {
 
70
    }
 
71
 
 
72
    qreal position() const {
 
73
        return rowPos();
 
74
    }
 
75
 
 
76
    qreal endPosition() const {
 
77
        return endRowPos();
 
78
    }
 
79
 
 
80
    qreal size() const {
 
81
        return view->flow() == QQuickGridView::FlowLeftToRight ? view->cellHeight() : view->cellWidth();
 
82
    }
 
83
 
 
84
    qreal sectionSize() const {
 
85
        return 0.0;
 
86
    }
 
87
 
 
88
    qreal rowPos() const {
 
89
        if (view->flow() == QQuickGridView::FlowLeftToRight)
 
90
            return (view->verticalLayoutDirection() == QQuickItemView::BottomToTop ? -view->cellHeight()-itemY() : itemY());
 
91
        else
 
92
            return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -view->cellWidth()-itemX() : itemX());
 
93
    }
 
94
 
 
95
    qreal colPos() const {
 
96
        if (view->flow() == QQuickGridView::FlowLeftToRight) {
 
97
            if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
 
98
                qreal colSize = view->cellWidth();
 
99
                int columns = view->width()/colSize;
 
100
                return colSize * (columns-1) - itemX();
 
101
            } else {
 
102
                return itemX();
 
103
            }
 
104
        } else {
 
105
            if (view->verticalLayoutDirection() == QQuickItemView::BottomToTop) {
 
106
                return -view->cellHeight() - itemY();
 
107
            } else {
 
108
                return itemY();
 
109
            }
 
110
        }
 
111
    }
 
112
    qreal endRowPos() const {
 
113
        if (view->flow() == QQuickGridView::FlowLeftToRight) {
 
114
            if (view->verticalLayoutDirection() == QQuickItemView::BottomToTop)
 
115
                return -itemY();
 
116
            else
 
117
                return itemY() + view->cellHeight();
 
118
        } else {
 
119
            if (view->effectiveLayoutDirection() == Qt::RightToLeft)
 
120
                return -itemX();
 
121
            else
 
122
                return itemX() + view->cellWidth();
 
123
        }
 
124
    }
 
125
    void setPosition(qreal col, qreal row, bool immediate = false) {
 
126
        moveTo(pointForPosition(col, row), immediate);
 
127
    }
 
128
    bool contains(qreal x, qreal y) const {
 
129
        return (x >= itemX() && x < itemX() + view->cellWidth() &&
 
130
                y >= itemY() && y < itemY() + view->cellHeight());
 
131
    }
 
132
 
 
133
    QQuickGridView *view;
 
134
 
 
135
private:
 
136
    QPointF pointForPosition(qreal col, qreal row) const {
 
137
        qreal x;
 
138
        qreal y;
 
139
        if (view->flow() == QQuickGridView::FlowLeftToRight) {
 
140
            x = col;
 
141
            y = row;
 
142
            if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
 
143
                int columns = view->width()/view->cellWidth();
 
144
                x = view->cellWidth() * (columns-1) - col;
 
145
            }
 
146
        } else {
 
147
            x = row;
 
148
            y = col;
 
149
            if (view->effectiveLayoutDirection() == Qt::RightToLeft)
 
150
                x = -view->cellWidth() - row;
 
151
        }
 
152
        if (view->verticalLayoutDirection() == QQuickItemView::BottomToTop)
 
153
            y = -view->cellHeight() - y;
 
154
        return QPointF(x, y);
 
155
    }
 
156
};
 
157
 
 
158
//----------------------------------------------------------------------------
 
159
 
 
160
class QQuickGridViewPrivate : public QQuickItemViewPrivate
 
161
{
 
162
    Q_DECLARE_PUBLIC(QQuickGridView)
 
163
 
 
164
public:
 
165
    virtual Qt::Orientation layoutOrientation() const;
 
166
    virtual bool isContentFlowReversed() const;
 
167
 
 
168
    virtual qreal positionAt(int index) const;
 
169
    virtual qreal endPositionAt(int index) const;
 
170
    virtual qreal originPosition() const;
 
171
    virtual qreal lastPosition() const;
 
172
 
 
173
    qreal rowSize() const;
 
174
    qreal colSize() const;
 
175
    qreal colPosAt(int modelIndex) const;
 
176
    qreal rowPosAt(int modelIndex) const;
 
177
    qreal snapPosAt(qreal pos) const;
 
178
    FxViewItem *snapItemAt(qreal pos) const;
 
179
    int snapIndex() const;
 
180
    qreal contentXForPosition(qreal pos) const;
 
181
    qreal contentYForPosition(qreal pos) const;
 
182
 
 
183
    void resetColumns();
 
184
 
 
185
    virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer);
 
186
    virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
 
187
 
 
188
    virtual FxViewItem *newViewItem(int index, QQuickItem *item);
 
189
    virtual void initializeViewItem(FxViewItem *item);
 
190
    virtual void repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer);
 
191
    virtual void repositionPackageItemAt(QQuickItem *item, int index);
 
192
    virtual void resetFirstItemPosition(qreal pos = 0.0);
 
193
    virtual void adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible);
 
194
 
 
195
    virtual void createHighlight();
 
196
    virtual void updateHighlight();
 
197
    virtual void resetHighlightPosition();
 
198
 
 
199
    virtual void setPosition(qreal pos);
 
200
    virtual void layoutVisibleItems(int fromModelIndex = 0);
 
201
    virtual bool applyInsertionChange(const QQmlChangeSet::Insert &insert, ChangeResult *changeResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView);
 
202
    virtual void translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult);
 
203
    virtual bool needsRefillForAddedOrRemovedIndex(int index) const;
 
204
 
 
205
    virtual qreal headerSize() const;
 
206
    virtual qreal footerSize() const;
 
207
    virtual bool showHeaderForIndex(int index) const;
 
208
    virtual bool showFooterForIndex(int index) const;
 
209
    virtual void updateHeader();
 
210
    virtual void updateFooter();
 
211
 
 
212
    virtual void changedVisibleIndex(int newIndex);
 
213
    virtual void initializeCurrentItem();
 
214
 
 
215
    virtual void updateViewport();
 
216
    virtual void fixupPosition();
 
217
    virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
 
218
    virtual bool flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
 
219
                        QQuickTimeLineCallback::Callback fixupCallback, qreal velocity);
 
220
 
 
221
    QQuickGridView::Flow flow;
 
222
    qreal cellWidth;
 
223
    qreal cellHeight;
 
224
    int columns;
 
225
    QQuickGridView::SnapMode snapMode;
 
226
 
 
227
    QSmoothedAnimation *highlightXAnimator;
 
228
    QSmoothedAnimation *highlightYAnimator;
 
229
 
 
230
    QQuickGridViewPrivate()
 
231
        : flow(QQuickGridView::FlowLeftToRight)
 
232
        , cellWidth(100), cellHeight(100), columns(1)
 
233
        , snapMode(QQuickGridView::NoSnap)
 
234
        , highlightXAnimator(0), highlightYAnimator(0)
 
235
    {}
 
236
    ~QQuickGridViewPrivate()
 
237
    {
 
238
        delete highlightXAnimator;
 
239
        delete highlightYAnimator;
 
240
    }
 
241
};
 
242
 
 
243
Qt::Orientation QQuickGridViewPrivate::layoutOrientation() const
 
244
{
 
245
    return flow == QQuickGridView::FlowLeftToRight ? Qt::Vertical : Qt::Horizontal;
 
246
}
 
247
 
 
248
bool QQuickGridViewPrivate::isContentFlowReversed() const
 
249
{
 
250
    Q_Q(const QQuickGridView);
 
251
 
 
252
    return (flow == QQuickGridView::FlowLeftToRight && verticalLayoutDirection == QQuickItemView::BottomToTop)
 
253
            || (flow == QQuickGridView::FlowTopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft);
 
254
}
 
255
 
 
256
void QQuickGridViewPrivate::changedVisibleIndex(int newIndex)
 
257
{
 
258
    visibleIndex = newIndex / columns * columns;
 
259
}
 
260
 
 
261
void QQuickGridViewPrivate::setPosition(qreal pos)
 
262
{
 
263
    Q_Q(QQuickGridView);
 
264
    q->QQuickFlickable::setContentX(contentXForPosition(pos));
 
265
    q->QQuickFlickable::setContentY(contentYForPosition(pos));
 
266
}
 
267
 
 
268
qreal QQuickGridViewPrivate::originPosition() const
 
269
{
 
270
    qreal pos = 0;
 
271
    if (!visibleItems.isEmpty())
 
272
        pos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
 
273
    return pos;
 
274
}
 
275
 
 
276
qreal QQuickGridViewPrivate::lastPosition() const
 
277
{
 
278
    qreal pos = 0;
 
279
    if (model && model->count()) {
 
280
        // get end position of last item
 
281
        pos = (rowPosAt(model->count() - 1) + rowSize());
 
282
    }
 
283
    return pos;
 
284
}
 
285
 
 
286
qreal QQuickGridViewPrivate::positionAt(int index) const
 
287
{
 
288
    return rowPosAt(index);
 
289
}
 
290
 
 
291
qreal QQuickGridViewPrivate::endPositionAt(int index) const
 
292
{
 
293
    return rowPosAt(index) + rowSize();
 
294
}
 
295
 
 
296
qreal QQuickGridViewPrivate::rowSize() const {
 
297
    return flow == QQuickGridView::FlowLeftToRight ? cellHeight : cellWidth;
 
298
}
 
299
qreal QQuickGridViewPrivate::colSize() const {
 
300
    return flow == QQuickGridView::FlowLeftToRight ? cellWidth : cellHeight;
 
301
}
 
302
 
 
303
qreal QQuickGridViewPrivate::colPosAt(int modelIndex) const
 
304
{
 
305
    if (FxViewItem *item = visibleItem(modelIndex))
 
306
        return static_cast<FxGridItemSG*>(item)->colPos();
 
307
    if (!visibleItems.isEmpty()) {
 
308
        if (modelIndex == visibleIndex) {
 
309
            FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
 
310
            return firstItem->colPos();
 
311
        } else if (modelIndex < visibleIndex) {
 
312
            int count = (visibleIndex - modelIndex) % columns;
 
313
            int col = static_cast<FxGridItemSG*>(visibleItems.first())->colPos() / colSize();
 
314
            col = (columns - count + col) % columns;
 
315
            return col * colSize();
 
316
        } else {
 
317
            FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
 
318
            int count = modelIndex - lastItem->index;
 
319
            int col = lastItem->colPos() / colSize();
 
320
            col = (col + count) % columns;
 
321
            return col * colSize();
 
322
        }
 
323
    }
 
324
    return (modelIndex % columns) * colSize();
 
325
}
 
326
 
 
327
qreal QQuickGridViewPrivate::rowPosAt(int modelIndex) const
 
328
{
 
329
    if (FxViewItem *item = visibleItem(modelIndex))
 
330
        return static_cast<FxGridItemSG*>(item)->rowPos();
 
331
    if (!visibleItems.isEmpty()) {
 
332
        if (modelIndex == visibleIndex) {
 
333
            FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
 
334
            return firstItem->rowPos();
 
335
        } else if (modelIndex < visibleIndex) {
 
336
            FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
 
337
            int firstCol = firstItem->colPos() / colSize();
 
338
            int col = visibleIndex - modelIndex + (columns - firstCol - 1);
 
339
            int rows = col / columns;
 
340
            return firstItem->rowPos() - rows * rowSize();
 
341
        } else {
 
342
            FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
 
343
            int count = modelIndex - lastItem->index;
 
344
            int col = lastItem->colPos() + count * colSize();
 
345
            int rows = col / (columns * colSize());
 
346
            return lastItem->rowPos() + rows * rowSize();
 
347
        }
 
348
    }
 
349
    return (modelIndex / columns) * rowSize();
 
350
}
 
351
 
 
352
 
 
353
qreal QQuickGridViewPrivate::snapPosAt(qreal pos) const
 
354
{
 
355
    Q_Q(const QQuickGridView);
 
356
    qreal snapPos = 0;
 
357
    if (!visibleItems.isEmpty()) {
 
358
        qreal highlightStart = highlightRangeStart;
 
359
        pos += highlightStart;
 
360
        pos += rowSize()/2;
 
361
        snapPos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
 
362
        snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
 
363
        snapPos -= highlightStart;
 
364
        qreal maxExtent;
 
365
        qreal minExtent;
 
366
        if (isContentFlowReversed()) {
 
367
            maxExtent = q->minXExtent()-size();
 
368
            minExtent = q->maxXExtent()-size();
 
369
        } else {
 
370
            maxExtent = flow == QQuickGridView::FlowLeftToRight ? -q->maxYExtent() : -q->maxXExtent();
 
371
            minExtent = flow == QQuickGridView::FlowLeftToRight ? -q->minYExtent() : -q->minXExtent();
 
372
        }
 
373
        if (snapPos > maxExtent)
 
374
            snapPos = maxExtent;
 
375
        if (snapPos < minExtent)
 
376
            snapPos = minExtent;
 
377
    }
 
378
    return snapPos;
 
379
}
 
380
 
 
381
FxViewItem *QQuickGridViewPrivate::snapItemAt(qreal pos) const
 
382
{
 
383
    for (int i = 0; i < visibleItems.count(); ++i) {
 
384
        FxViewItem *item = visibleItems.at(i);
 
385
        if (item->index == -1)
 
386
            continue;
 
387
        qreal itemTop = item->position();
 
388
        if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
 
389
            return item;
 
390
    }
 
391
    return 0;
 
392
}
 
393
 
 
394
int QQuickGridViewPrivate::snapIndex() const
 
395
{
 
396
    int index = currentIndex;
 
397
    for (int i = 0; i < visibleItems.count(); ++i) {
 
398
        FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
 
399
        if (item->index == -1)
 
400
            continue;
 
401
        qreal itemTop = item->position();
 
402
        FxGridItemSG *hItem = static_cast<FxGridItemSG*>(highlight);
 
403
        if (itemTop >= hItem->rowPos()-rowSize()/2 && itemTop < hItem->rowPos()+rowSize()/2) {
 
404
            index = item->index;
 
405
            if (item->colPos() >= hItem->colPos()-colSize()/2 && item->colPos() < hItem->colPos()+colSize()/2)
 
406
                return item->index;
 
407
        }
 
408
    }
 
409
    return index;
 
410
}
 
411
 
 
412
qreal QQuickGridViewPrivate::contentXForPosition(qreal pos) const
 
413
{
 
414
    Q_Q(const QQuickGridView);
 
415
    if (flow == QQuickGridView::FlowLeftToRight) {
 
416
        // vertical scroll
 
417
        if (q->effectiveLayoutDirection() == Qt::LeftToRight) {
 
418
            return 0;
 
419
        } else {
 
420
            qreal colSize = cellWidth;
 
421
            int columns = q->width()/colSize;
 
422
            return -q->width() + (cellWidth * columns);
 
423
        }
 
424
    } else {
 
425
        // horizontal scroll
 
426
        if (q->effectiveLayoutDirection() == Qt::LeftToRight)
 
427
            return pos;
 
428
        else
 
429
            return -pos - q->width();
 
430
    }
 
431
}
 
432
 
 
433
qreal QQuickGridViewPrivate::contentYForPosition(qreal pos) const
 
434
{
 
435
    Q_Q(const QQuickGridView);
 
436
    if (flow == QQuickGridView::FlowLeftToRight) {
 
437
        // vertical scroll
 
438
        if (verticalLayoutDirection == QQuickItemView::TopToBottom)
 
439
            return pos;
 
440
        else
 
441
            return -pos - q->height();
 
442
    } else {
 
443
        // horizontal scroll
 
444
        if (verticalLayoutDirection == QQuickItemView::TopToBottom)
 
445
            return 0;
 
446
        else
 
447
            return -q->height();
 
448
    }
 
449
}
 
450
 
 
451
void QQuickGridViewPrivate::resetColumns()
 
452
{
 
453
    Q_Q(QQuickGridView);
 
454
    qreal length = flow == QQuickGridView::FlowLeftToRight ? q->width() : q->height();
 
455
    columns = qMax(1, qFloor(length / colSize()));
 
456
}
 
457
 
 
458
FxViewItem *QQuickGridViewPrivate::newViewItem(int modelIndex, QQuickItem *item)
 
459
{
 
460
    Q_Q(QQuickGridView);
 
461
    Q_UNUSED(modelIndex);
 
462
    return new FxGridItemSG(item, q, false);
 
463
}
 
464
 
 
465
void QQuickGridViewPrivate::initializeViewItem(FxViewItem *item)
 
466
{
 
467
    QQuickItemViewPrivate::initializeViewItem(item);
 
468
 
 
469
    // need to track current items that are animating
 
470
    item->trackGeometry(true);
 
471
}
 
472
 
 
473
bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer)
 
474
{
 
475
    qreal colPos = colPosAt(visibleIndex);
 
476
    qreal rowPos = rowPosAt(visibleIndex);
 
477
    if (visibleItems.count()) {
 
478
        FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
 
479
        rowPos = lastItem->rowPos();
 
480
        int colNum = qFloor((lastItem->colPos()+colSize()/2) / colSize());
 
481
        if (++colNum >= columns) {
 
482
            colNum = 0;
 
483
            rowPos += rowSize();
 
484
        }
 
485
        colPos = colNum * colSize();
 
486
    }
 
487
 
 
488
    int modelIndex = findLastVisibleIndex();
 
489
    modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
 
490
 
 
491
    if (visibleItems.count() && (bufferFrom > rowPos + rowSize()*2
 
492
        || bufferTo < rowPosAt(visibleIndex) - rowSize())) {
 
493
        // We've jumped more than a page.  Estimate which items are now
 
494
        // visible and fill from there.
 
495
        int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
 
496
        for (int i = 0; i < visibleItems.count(); ++i)
 
497
            releaseItem(visibleItems.at(i));
 
498
        visibleItems.clear();
 
499
        modelIndex += count;
 
500
        if (modelIndex >= model->count())
 
501
            modelIndex = model->count() - 1;
 
502
        else if (modelIndex < 0)
 
503
            modelIndex = 0;
 
504
        modelIndex = modelIndex / columns * columns;
 
505
        visibleIndex = modelIndex;
 
506
        colPos = colPosAt(visibleIndex);
 
507
        rowPos = rowPosAt(visibleIndex);
 
508
    }
 
509
 
 
510
    int colNum = qFloor((colPos+colSize()/2) / colSize());
 
511
    FxGridItemSG *item = 0;
 
512
    bool changed = false;
 
513
 
 
514
    while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
 
515
#ifdef DEBUG_DELEGATE_LIFECYCLE
 
516
        qDebug() << "refill: append item" << modelIndex << colPos << rowPos;
 
517
#endif
 
518
        if (!(item = static_cast<FxGridItemSG*>(createItem(modelIndex, doBuffer))))
 
519
            break;
 
520
        if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
 
521
            item->setPosition(colPos, rowPos, true);
 
522
        QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
 
523
        visibleItems.append(item);
 
524
        if (++colNum >= columns) {
 
525
            colNum = 0;
 
526
            rowPos += rowSize();
 
527
        }
 
528
        colPos = colNum * colSize();
 
529
        ++modelIndex;
 
530
        changed = true;
 
531
    }
 
532
 
 
533
    if (doBuffer && requestedIndex != -1) // already waiting for an item
 
534
        return changed;
 
535
 
 
536
    // Find first column
 
537
    if (visibleItems.count()) {
 
538
        FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
 
539
        rowPos = firstItem->rowPos();
 
540
        colNum = qFloor((firstItem->colPos()+colSize()/2) / colSize());
 
541
        if (--colNum < 0) {
 
542
            colNum = columns - 1;
 
543
            rowPos -= rowSize();
 
544
        }
 
545
    } else {
 
546
        colNum = qFloor((colPos+colSize()/2) / colSize());
 
547
    }
 
548
 
 
549
    // Prepend
 
550
    colPos = colNum * colSize();
 
551
    while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
 
552
#ifdef DEBUG_DELEGATE_LIFECYCLE
 
553
        qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
 
554
#endif
 
555
        if (!(item = static_cast<FxGridItemSG*>(createItem(visibleIndex-1, doBuffer))))
 
556
            break;
 
557
        --visibleIndex;
 
558
        if (!transitioner || !transitioner->canTransition(QQuickItemViewTransitioner::PopulateTransition, true)) // pos will be set by layoutVisibleItems()
 
559
            item->setPosition(colPos, rowPos, true);
 
560
        QQuickItemPrivate::get(item->item)->setCulled(doBuffer);
 
561
        visibleItems.prepend(item);
 
562
        if (--colNum < 0) {
 
563
            colNum = columns-1;
 
564
            rowPos -= rowSize();
 
565
        }
 
566
        colPos = colNum * colSize();
 
567
        changed = true;
 
568
    }
 
569
 
 
570
    return changed;
 
571
}
 
572
 
 
573
bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
 
574
{
 
575
    FxGridItemSG *item = 0;
 
576
    bool changed = false;
 
577
 
 
578
    while (visibleItems.count() > 1
 
579
           && (item = static_cast<FxGridItemSG*>(visibleItems.first()))
 
580
                && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
 
581
        if (item->attached->delayRemove())
 
582
            break;
 
583
#ifdef DEBUG_DELEGATE_LIFECYCLE
 
584
        qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
 
585
#endif
 
586
        if (item->index != -1)
 
587
            visibleIndex++;
 
588
        visibleItems.removeFirst();
 
589
        if (item->transitionScheduledOrRunning()) {
 
590
#ifdef DEBUG_DELEGATE_LIFECYCLE
 
591
            qDebug() << "\tnot releasing animating item:" << item->index << item->item->objectName();
 
592
#endif
 
593
            item->releaseAfterTransition = true;
 
594
            releasePendingTransition.append(item);
 
595
        } else {
 
596
            releaseItem(item);
 
597
        }
 
598
        changed = true;
 
599
    }
 
600
    while (visibleItems.count() > 1
 
601
           && (item = static_cast<FxGridItemSG*>(visibleItems.last()))
 
602
                && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
 
603
        if (item->attached->delayRemove())
 
604
            break;
 
605
#ifdef DEBUG_DELEGATE_LIFECYCLE
 
606
        qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
 
607
#endif
 
608
        visibleItems.removeLast();
 
609
        if (item->transitionScheduledOrRunning()) {
 
610
#ifdef DEBUG_DELEGATE_LIFECYCLE
 
611
            qDebug() << "\tnot releasing animating item:" << item->index << item->item->objectName();
 
612
#endif
 
613
            item->releaseAfterTransition = true;
 
614
            releasePendingTransition.append(item);
 
615
        } else {
 
616
            releaseItem(item);
 
617
        }
 
618
        changed = true;
 
619
    }
 
620
 
 
621
    return changed;
 
622
}
 
623
 
 
624
void QQuickGridViewPrivate::updateViewport()
 
625
{
 
626
    resetColumns();
 
627
    QQuickItemViewPrivate::updateViewport();
 
628
}
 
629
 
 
630
void QQuickGridViewPrivate::layoutVisibleItems(int fromModelIndex)
 
631
{
 
632
    if (visibleItems.count()) {
 
633
        const qreal from = isContentFlowReversed() ? -position()-displayMarginBeginning-size() : position()-displayMarginBeginning;
 
634
        const qreal to = isContentFlowReversed() ? -position()+displayMarginEnd : position()+size()+displayMarginEnd;
 
635
 
 
636
        FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
 
637
        qreal rowPos = firstItem->rowPos();
 
638
        qreal colPos = firstItem->colPos();
 
639
        int col = visibleIndex % columns;
 
640
        if (colPos != col * colSize()) {
 
641
            colPos = col * colSize();
 
642
            firstItem->setPosition(colPos, rowPos);
 
643
            firstItem->setVisible(firstItem->rowPos() + rowSize() >= from && firstItem->rowPos() <= to);
 
644
        }
 
645
        for (int i = 1; i < visibleItems.count(); ++i) {
 
646
            FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
 
647
            if (++col >= columns) {
 
648
                col = 0;
 
649
                rowPos += rowSize();
 
650
            }
 
651
            colPos = col * colSize();
 
652
            if (item->index >= fromModelIndex) {
 
653
                item->setPosition(colPos, rowPos);
 
654
                item->setVisible(item->rowPos() + rowSize() >= from && item->rowPos() <= to);
 
655
            }
 
656
        }
 
657
    }
 
658
}
 
659
 
 
660
void QQuickGridViewPrivate::repositionItemAt(FxViewItem *item, int index, qreal sizeBuffer)
 
661
{
 
662
    int count = sizeBuffer / rowSize();
 
663
    static_cast<FxGridItemSG *>(item)->setPosition(colPosAt(index + count), rowPosAt(index + count));
 
664
}
 
665
 
 
666
void QQuickGridViewPrivate::repositionPackageItemAt(QQuickItem *item, int index)
 
667
{
 
668
    Q_Q(QQuickGridView);
 
669
    qreal pos = position();
 
670
    if (flow == QQuickGridView::FlowLeftToRight) {
 
671
        if (item->y() + item->height() > pos && item->y() < pos + q->height()) {
 
672
            qreal y = (verticalLayoutDirection == QQuickItemView::TopToBottom)
 
673
                    ? rowPosAt(index)
 
674
                    : -rowPosAt(index) - item->height();
 
675
            item->setPosition(QPointF(colPosAt(index), y));
 
676
        }
 
677
    } else {
 
678
        if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
 
679
            qreal y = (verticalLayoutDirection == QQuickItemView::TopToBottom)
 
680
                    ? colPosAt(index)
 
681
                    : -colPosAt(index) - item->height();
 
682
            if (flow == QQuickGridView::FlowTopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft)
 
683
                item->setPosition(QPointF(-rowPosAt(index)-item->width(), y));
 
684
            else
 
685
                item->setPosition(QPointF(rowPosAt(index), y));
 
686
        }
 
687
    }
 
688
}
 
689
 
 
690
void QQuickGridViewPrivate::resetFirstItemPosition(qreal pos)
 
691
{
 
692
    FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.first());
 
693
    item->setPosition(0, pos);
 
694
}
 
695
 
 
696
void QQuickGridViewPrivate::adjustFirstItem(qreal forwards, qreal backwards, int changeBeforeVisible)
 
697
{
 
698
    if (!visibleItems.count())
 
699
        return;
 
700
 
 
701
    int moveCount = (forwards - backwards) / rowSize();
 
702
    if (moveCount == 0 && changeBeforeVisible != 0)
 
703
        moveCount += (changeBeforeVisible % columns) - (columns - 1);
 
704
 
 
705
    FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.first());
 
706
    gridItem->setPosition(gridItem->colPos(), gridItem->rowPos() + ((moveCount / columns) * rowSize()));
 
707
}
 
708
 
 
709
void QQuickGridViewPrivate::createHighlight()
 
710
{
 
711
    Q_Q(QQuickGridView);
 
712
    bool changed = false;
 
713
    if (highlight) {
 
714
        if (trackedItem == highlight)
 
715
            trackedItem = 0;
 
716
        delete highlight;
 
717
        highlight = 0;
 
718
 
 
719
        delete highlightXAnimator;
 
720
        delete highlightYAnimator;
 
721
        highlightXAnimator = 0;
 
722
        highlightYAnimator = 0;
 
723
 
 
724
        changed = true;
 
725
    }
 
726
 
 
727
    if (currentItem) {
 
728
        QQuickItem *item = createHighlightItem();
 
729
        if (item) {
 
730
            FxGridItemSG *newHighlight = new FxGridItemSG(item, q, true);
 
731
            newHighlight->trackGeometry(true);
 
732
            if (autoHighlight)
 
733
                resetHighlightPosition();
 
734
            highlightXAnimator = new QSmoothedAnimation;
 
735
            highlightXAnimator->target = QQmlProperty(item, QLatin1String("x"));
 
736
            highlightXAnimator->userDuration = highlightMoveDuration;
 
737
            highlightYAnimator = new QSmoothedAnimation;
 
738
            highlightYAnimator->target = QQmlProperty(item, QLatin1String("y"));
 
739
            highlightYAnimator->userDuration = highlightMoveDuration;
 
740
 
 
741
            highlight = newHighlight;
 
742
            changed = true;
 
743
        }
 
744
    }
 
745
    if (changed)
 
746
        emit q->highlightItemChanged();
 
747
}
 
748
 
 
749
void QQuickGridViewPrivate::updateHighlight()
 
750
{
 
751
    applyPendingChanges();
 
752
 
 
753
    if ((!currentItem && highlight) || (currentItem && !highlight))
 
754
        createHighlight();
 
755
    bool strictHighlight = haveHighlightRange && highlightRange == QQuickGridView::StrictlyEnforceRange;
 
756
    if (currentItem && autoHighlight && highlight && (!strictHighlight || !pressed)) {
 
757
        // auto-update highlight
 
758
        highlightXAnimator->to = currentItem->itemX();
 
759
        highlightYAnimator->to = currentItem->itemY();
 
760
        highlight->item->setWidth(currentItem->item->width());
 
761
        highlight->item->setHeight(currentItem->item->height());
 
762
 
 
763
        highlightXAnimator->restart();
 
764
        highlightYAnimator->restart();
 
765
    }
 
766
    updateTrackedItem();
 
767
}
 
768
 
 
769
void QQuickGridViewPrivate::resetHighlightPosition()
 
770
{
 
771
    if (highlight && currentItem) {
 
772
        FxGridItemSG *cItem = static_cast<FxGridItemSG*>(currentItem);
 
773
        static_cast<FxGridItemSG*>(highlight)->setPosition(cItem->colPos(), cItem->rowPos());
 
774
    }
 
775
}
 
776
 
 
777
qreal QQuickGridViewPrivate::headerSize() const
 
778
{
 
779
    if (!header)
 
780
        return 0.0;
 
781
    return flow == QQuickGridView::FlowLeftToRight ? header->item->height() : header->item->width();
 
782
}
 
783
 
 
784
qreal QQuickGridViewPrivate::footerSize() const
 
785
{
 
786
    if (!footer)
 
787
        return 0.0;
 
788
    return flow == QQuickGridView::FlowLeftToRight? footer->item->height() : footer->item->width();
 
789
}
 
790
 
 
791
bool QQuickGridViewPrivate::showHeaderForIndex(int index) const
 
792
{
 
793
    return index / columns == 0;
 
794
}
 
795
 
 
796
bool QQuickGridViewPrivate::showFooterForIndex(int index) const
 
797
{
 
798
    return index / columns == (model->count()-1) / columns;
 
799
}
 
800
 
 
801
void QQuickGridViewPrivate::updateFooter()
 
802
{
 
803
    Q_Q(QQuickGridView);
 
804
    bool created = false;
 
805
    if (!footer) {
 
806
        QQuickItem *item = createComponentItem(footerComponent, 1.0);
 
807
        if (!item)
 
808
            return;
 
809
        footer = new FxGridItemSG(item, q, true);
 
810
        footer->trackGeometry(true);
 
811
        created = true;
 
812
    }
 
813
 
 
814
    FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(footer);
 
815
    qreal colOffset = 0;
 
816
    qreal rowOffset = 0;
 
817
    if (q->effectiveLayoutDirection() == Qt::RightToLeft) {
 
818
        if (flow == QQuickGridView::FlowTopToBottom)
 
819
            rowOffset += gridItem->item->width() - cellWidth;
 
820
        else
 
821
            colOffset += gridItem->item->width() - cellWidth;
 
822
    }
 
823
    if (verticalLayoutDirection == QQuickItemView::BottomToTop) {
 
824
        if (flow == QQuickGridView::FlowTopToBottom)
 
825
            colOffset += gridItem->item->height() - cellHeight;
 
826
        else
 
827
            rowOffset += gridItem->item->height() - cellHeight;
 
828
    }
 
829
    if (visibleItems.count()) {
 
830
        qreal endPos = lastPosition();
 
831
        if (findLastVisibleIndex() == model->count()-1) {
 
832
            gridItem->setPosition(colOffset, endPos + rowOffset);
 
833
        } else {
 
834
            qreal visiblePos = isContentFlowReversed() ? -position() : position() + size();
 
835
            if (endPos <= visiblePos || gridItem->endPosition() <= endPos + rowOffset)
 
836
                gridItem->setPosition(colOffset, endPos + rowOffset);
 
837
        }
 
838
    } else {
 
839
        gridItem->setPosition(colOffset, rowOffset);
 
840
    }
 
841
 
 
842
    if (created)
 
843
        emit q->footerItemChanged();
 
844
}
 
845
 
 
846
void QQuickGridViewPrivate::updateHeader()
 
847
{
 
848
    Q_Q(QQuickGridView);
 
849
    bool created = false;
 
850
    if (!header) {
 
851
        QQuickItem *item = createComponentItem(headerComponent, 1.0);
 
852
        if (!item)
 
853
            return;
 
854
        header = new FxGridItemSG(item, q, true);
 
855
        header->trackGeometry(true);
 
856
        created = true;
 
857
    }
 
858
 
 
859
    FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(header);
 
860
    qreal colOffset = 0;
 
861
    qreal rowOffset = -headerSize();
 
862
    if (q->effectiveLayoutDirection() == Qt::RightToLeft) {
 
863
        if (flow == QQuickGridView::FlowTopToBottom)
 
864
            rowOffset += gridItem->item->width() - cellWidth;
 
865
        else
 
866
            colOffset += gridItem->item->width() - cellWidth;
 
867
    }
 
868
    if (verticalLayoutDirection == QQuickItemView::BottomToTop) {
 
869
        if (flow == QQuickGridView::FlowTopToBottom)
 
870
            colOffset += gridItem->item->height() - cellHeight;
 
871
        else
 
872
            rowOffset += gridItem->item->height() - cellHeight;
 
873
    }
 
874
    if (visibleItems.count()) {
 
875
        qreal startPos = originPosition();
 
876
        if (visibleIndex == 0) {
 
877
            gridItem->setPosition(colOffset, startPos + rowOffset);
 
878
        } else {
 
879
            qreal tempPos = isContentFlowReversed() ? -position()-size() : position();
 
880
            qreal headerPos = isContentFlowReversed() ? gridItem->rowPos() + cellWidth - headerSize() : gridItem->rowPos();
 
881
            if (tempPos <= startPos || headerPos > startPos + rowOffset)
 
882
                gridItem->setPosition(colOffset, startPos + rowOffset);
 
883
        }
 
884
    } else {
 
885
        if (isContentFlowReversed())
 
886
            gridItem->setPosition(colOffset, rowOffset);
 
887
        else
 
888
            gridItem->setPosition(colOffset, -headerSize());
 
889
    }
 
890
 
 
891
    if (created)
 
892
        emit q->headerItemChanged();
 
893
}
 
894
 
 
895
void QQuickGridViewPrivate::initializeCurrentItem()
 
896
{
 
897
    if (currentItem && currentIndex >= 0) {
 
898
        FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(currentItem);
 
899
        FxViewItem *actualItem = visibleItem(currentIndex);
 
900
 
 
901
        // don't reposition the item if it's about to be transitioned to another position
 
902
        if ((!actualItem || !actualItem->transitionScheduledOrRunning()))
 
903
            gridItem->setPosition(colPosAt(currentIndex), rowPosAt(currentIndex));
 
904
    }
 
905
}
 
906
 
 
907
void QQuickGridViewPrivate::fixupPosition()
 
908
{
 
909
    moveReason = Other;
 
910
    if (flow == QQuickGridView::FlowLeftToRight)
 
911
        fixupY();
 
912
    else
 
913
        fixupX();
 
914
}
 
915
 
 
916
void QQuickGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
 
917
{
 
918
    if ((flow == QQuickGridView::FlowTopToBottom && &data == &vData)
 
919
        || (flow == QQuickGridView::FlowLeftToRight && &data == &hData))
 
920
        return;
 
921
 
 
922
    fixupMode = moveReason == Mouse ? fixupMode : Immediate;
 
923
 
 
924
    qreal viewPos = isContentFlowReversed() ? -position()-size() : position();
 
925
 
 
926
    bool strictHighlightRange = haveHighlightRange && highlightRange == QQuickGridView::StrictlyEnforceRange;
 
927
    if (snapMode != QQuickGridView::NoSnap) {
 
928
        qreal tempPosition = isContentFlowReversed() ? -position()-size() : position();
 
929
        if (snapMode == QQuickGridView::SnapOneRow && moveReason == Mouse) {
 
930
            // if we've been dragged < rowSize()/2 then bias towards the next row
 
931
            qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
 
932
            qreal bias = 0;
 
933
            if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < rowSize()/2)
 
934
                bias = rowSize()/2;
 
935
            else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -rowSize()/2)
 
936
                bias = -rowSize()/2;
 
937
            if (isContentFlowReversed())
 
938
                bias = -bias;
 
939
            tempPosition -= bias;
 
940
        }
 
941
        FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
 
942
        if (!topItem && strictHighlightRange && currentItem) {
 
943
            // StrictlyEnforceRange always keeps an item in range
 
944
            updateHighlight();
 
945
            topItem = currentItem;
 
946
        }
 
947
        FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
 
948
        if (!bottomItem && strictHighlightRange && currentItem) {
 
949
            // StrictlyEnforceRange always keeps an item in range
 
950
            updateHighlight();
 
951
            bottomItem = currentItem;
 
952
        }
 
953
        qreal pos;
 
954
        bool isInBounds = -position() > maxExtent && -position() <= minExtent;
 
955
        if (topItem && (isInBounds || strictHighlightRange)) {
 
956
            qreal headerPos = header ? static_cast<FxGridItemSG*>(header)->rowPos() : 0;
 
957
            if (topItem->index == 0 && header && tempPosition+highlightRangeStart < headerPos+headerSize()/2 && !strictHighlightRange) {
 
958
                pos = isContentFlowReversed() ? - headerPos + highlightRangeStart - size() : headerPos - highlightRangeStart;
 
959
            } else {
 
960
                if (isContentFlowReversed())
 
961
                    pos = qMax(qMin(-topItem->position() + highlightRangeStart - size(), -maxExtent), -minExtent);
 
962
                else
 
963
                    pos = qMax(qMin(topItem->position() - highlightRangeStart, -maxExtent), -minExtent);
 
964
            }
 
965
        } else if (bottomItem && isInBounds) {
 
966
            if (isContentFlowReversed())
 
967
                pos = qMax(qMin(-bottomItem->position() + highlightRangeEnd - size(), -maxExtent), -minExtent);
 
968
            else
 
969
                pos = qMax(qMin(bottomItem->position() - highlightRangeEnd, -maxExtent), -minExtent);
 
970
        } else {
 
971
            QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
 
972
            return;
 
973
        }
 
974
 
 
975
        qreal dist = qAbs(data.move + pos);
 
976
        if (dist > 0) {
 
977
            timeline.reset(data.move);
 
978
            if (fixupMode != Immediate) {
 
979
                timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
 
980
                data.fixingUp = true;
 
981
            } else {
 
982
                timeline.set(data.move, -pos);
 
983
            }
 
984
            vTime = timeline.time();
 
985
        }
 
986
    } else if (haveHighlightRange && highlightRange == QQuickGridView::StrictlyEnforceRange) {
 
987
        if (currentItem) {
 
988
            updateHighlight();
 
989
            qreal pos = static_cast<FxGridItemSG*>(currentItem)->rowPos();
 
990
            if (viewPos < pos + rowSize() - highlightRangeEnd)
 
991
                viewPos = pos + rowSize() - highlightRangeEnd;
 
992
            if (viewPos > pos - highlightRangeStart)
 
993
                viewPos = pos - highlightRangeStart;
 
994
            if (isContentFlowReversed())
 
995
                viewPos = -viewPos-size();
 
996
            timeline.reset(data.move);
 
997
            if (viewPos != position()) {
 
998
                if (fixupMode != Immediate) {
 
999
                    timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
 
1000
                    data.fixingUp = true;
 
1001
                } else {
 
1002
                    timeline.set(data.move, -viewPos);
 
1003
                }
 
1004
            }
 
1005
            vTime = timeline.time();
 
1006
        }
 
1007
    } else {
 
1008
        QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
 
1009
    }
 
1010
    data.inOvershoot = false;
 
1011
    fixupMode = Normal;
 
1012
}
 
1013
 
 
1014
bool QQuickGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
 
1015
                                        QQuickTimeLineCallback::Callback fixupCallback, qreal velocity)
 
1016
{
 
1017
    data.fixingUp = false;
 
1018
    moveReason = Mouse;
 
1019
    if ((!haveHighlightRange || highlightRange != QQuickGridView::StrictlyEnforceRange)
 
1020
        && snapMode == QQuickGridView::NoSnap) {
 
1021
        return QQuickItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
 
1022
    }
 
1023
    qreal maxDistance = 0;
 
1024
    qreal dataValue = isContentFlowReversed() ? -data.move.value()+size() : data.move.value();
 
1025
    // -ve velocity means list is moving up/left
 
1026
    if (velocity > 0) {
 
1027
        if (data.move.value() < minExtent) {
 
1028
            if (snapMode == QQuickGridView::SnapOneRow) {
 
1029
                // if we've been dragged < averageSize/2 then bias towards the next item
 
1030
                qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
 
1031
                qreal bias = dist < rowSize()/2 ? rowSize()/2 : 0;
 
1032
                if (isContentFlowReversed())
 
1033
                    bias = -bias;
 
1034
                data.flickTarget = -snapPosAt(-dataValue - bias);
 
1035
                maxDistance = qAbs(data.flickTarget - data.move.value());
 
1036
                velocity = maxVelocity;
 
1037
            } else {
 
1038
                maxDistance = qAbs(minExtent - data.move.value());
 
1039
            }
 
1040
        }
 
1041
        if (snapMode == QQuickGridView::NoSnap && highlightRange != QQuickGridView::StrictlyEnforceRange)
 
1042
            data.flickTarget = minExtent;
 
1043
    } else {
 
1044
        if (data.move.value() > maxExtent) {
 
1045
            if (snapMode == QQuickGridView::SnapOneRow) {
 
1046
                // if we've been dragged < averageSize/2 then bias towards the next item
 
1047
                qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
 
1048
                qreal bias = -dist < rowSize()/2 ? rowSize()/2 : 0;
 
1049
                if (isContentFlowReversed())
 
1050
                    bias = -bias;
 
1051
                data.flickTarget = -snapPosAt(-dataValue + bias);
 
1052
                maxDistance = qAbs(data.flickTarget - data.move.value());
 
1053
                velocity = -maxVelocity;
 
1054
            } else {
 
1055
                maxDistance = qAbs(maxExtent - data.move.value());
 
1056
            }
 
1057
        }
 
1058
        if (snapMode == QQuickGridView::NoSnap && highlightRange != QQuickGridView::StrictlyEnforceRange)
 
1059
            data.flickTarget = maxExtent;
 
1060
    }
 
1061
    bool overShoot = boundsBehavior == QQuickFlickable::DragAndOvershootBounds;
 
1062
    if (maxDistance > 0 || overShoot) {
 
1063
        // This mode requires the grid to stop exactly on a row boundary.
 
1064
        qreal v = velocity;
 
1065
        if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
 
1066
            if (v < 0)
 
1067
                v = -maxVelocity;
 
1068
            else
 
1069
                v = maxVelocity;
 
1070
        }
 
1071
        qreal accel = deceleration;
 
1072
        qreal v2 = v * v;
 
1073
        qreal overshootDist = 0.0;
 
1074
        if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QQuickGridView::SnapOneRow) {
 
1075
            // + rowSize()/4 to encourage moving at least one item in the flick direction
 
1076
            qreal dist = v2 / (accel * 2.0) + rowSize()/4;
 
1077
            dist = qMin(dist, maxDistance);
 
1078
            if (v > 0)
 
1079
                dist = -dist;
 
1080
            if (snapMode != QQuickGridView::SnapOneRow) {
 
1081
                qreal distTemp = isContentFlowReversed() ? -dist : dist;
 
1082
                data.flickTarget = -snapPosAt(-dataValue + distTemp);
 
1083
            }
 
1084
            data.flickTarget = isContentFlowReversed() ? -data.flickTarget+size() : data.flickTarget;
 
1085
            if (overShoot) {
 
1086
                if (data.flickTarget >= minExtent) {
 
1087
                    overshootDist = overShootDistance(vSize);
 
1088
                    data.flickTarget += overshootDist;
 
1089
                } else if (data.flickTarget <= maxExtent) {
 
1090
                    overshootDist = overShootDistance(vSize);
 
1091
                    data.flickTarget -= overshootDist;
 
1092
                }
 
1093
            }
 
1094
            qreal adjDist = -data.flickTarget + data.move.value();
 
1095
            if (qAbs(adjDist) > qAbs(dist)) {
 
1096
                // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
 
1097
                qreal adjv2 = accel * 2.0f * qAbs(adjDist);
 
1098
                if (adjv2 > v2) {
 
1099
                    v2 = adjv2;
 
1100
                    v = qSqrt(v2);
 
1101
                    if (dist > 0)
 
1102
                        v = -v;
 
1103
                }
 
1104
            }
 
1105
            dist = adjDist;
 
1106
            accel = v2 / (2.0f * qAbs(dist));
 
1107
        } else {
 
1108
            data.flickTarget = velocity > 0 ? minExtent : maxExtent;
 
1109
            overshootDist = overShoot ? overShootDistance(vSize) : 0;
 
1110
        }
 
1111
        timeline.reset(data.move);
 
1112
        timeline.accel(data.move, v, accel, maxDistance + overshootDist);
 
1113
        timeline.callback(QQuickTimeLineCallback(&data.move, fixupCallback, this));
 
1114
        return true;
 
1115
    } else {
 
1116
        timeline.reset(data.move);
 
1117
        fixup(data, minExtent, maxExtent);
 
1118
        return false;
 
1119
    }
 
1120
}
 
1121
 
 
1122
 
 
1123
//----------------------------------------------------------------------------
 
1124
/*!
 
1125
    \qmltype GridView
 
1126
    \instantiates QQuickGridView
 
1127
    \inqmlmodule QtQuick
 
1128
    \ingroup qtquick-views
 
1129
 
 
1130
    \inherits Flickable
 
1131
    \brief For specifying a grid view of items provided by a model
 
1132
 
 
1133
    A GridView displays data from models created from built-in QML types like ListModel
 
1134
    and XmlListModel, or custom model classes defined in C++ that inherit from
 
1135
    QAbstractListModel.
 
1136
 
 
1137
    A GridView has a \l model, which defines the data to be displayed, and
 
1138
    a \l delegate, which defines how the data should be displayed. Items in a
 
1139
    GridView are laid out horizontally or vertically. Grid views are inherently flickable
 
1140
    as GridView inherits from \l Flickable.
 
1141
 
 
1142
    \section1 Example Usage
 
1143
 
 
1144
    The following example shows the definition of a simple list model defined
 
1145
    in a file called \c ContactModel.qml:
 
1146
 
 
1147
    \snippet qml/gridview/ContactModel.qml 0
 
1148
 
 
1149
    \div {class="float-right"}
 
1150
    \inlineimage gridview-simple.png
 
1151
    \enddiv
 
1152
 
 
1153
    This model can be referenced as \c ContactModel in other QML files. See \l{QML Modules}
 
1154
    for more information about creating reusable components like this.
 
1155
 
 
1156
    Another component can display this model data in a GridView, as in the following
 
1157
    example, which creates a \c ContactModel component for its model, and a \l Column
 
1158
    (containing \l Image and \l Text items) for its delegate.
 
1159
 
 
1160
    \clearfloat
 
1161
    \snippet qml/gridview/gridview.qml import
 
1162
    \codeline
 
1163
    \snippet qml/gridview/gridview.qml classdocs simple
 
1164
 
 
1165
    \div {class="float-right"}
 
1166
    \inlineimage gridview-highlight.png
 
1167
    \enddiv
 
1168
 
 
1169
    The view will create a new delegate for each item in the model. Note that the delegate
 
1170
    is able to access the model's \c name and \c portrait data directly.
 
1171
 
 
1172
    An improved grid view is shown below. The delegate is visually improved and is moved
 
1173
    into a separate \c contactDelegate component.
 
1174
 
 
1175
    \clearfloat
 
1176
    \snippet qml/gridview/gridview.qml classdocs advanced
 
1177
 
 
1178
    The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
 
1179
    and \c focus is set to \c true to enable keyboard navigation for the grid view.
 
1180
    The grid view itself is a focus scope (see \l{Keyboard Focus in Qt Quick} for more details).
 
1181
 
 
1182
    Delegates are instantiated as needed and may be destroyed at any time.
 
1183
    State should \e never be stored in a delegate.
 
1184
 
 
1185
    GridView attaches a number of properties to the root item of the delegate, for example
 
1186
    \c {GridView.isCurrentItem}.  In the following example, the root delegate item can access
 
1187
    this attached property directly as \c GridView.isCurrentItem, while the child
 
1188
    \c contactInfo object must refer to this property as \c wrapper.GridView.isCurrentItem.
 
1189
 
 
1190
    \snippet qml/gridview/gridview.qml isCurrentItem
 
1191
 
 
1192
    \note Views do not set the \l{Item::}{clip} property automatically.
 
1193
    If the view is not clipped by another item or the screen, it will be necessary
 
1194
    to set this property to true in order to clip the items that are partially or
 
1195
    fully outside the view.
 
1196
 
 
1197
 
 
1198
    \section1 GridView layouts
 
1199
 
 
1200
    The layout of the items in a GridView can be controlled by these properties:
 
1201
 
 
1202
    \list
 
1203
    \li \l flow - controls whether items flow from left to right (as a series of rows)
 
1204
        or from top to bottom (as a series of columns). This value can be either
 
1205
        GridView.FlowLeftToRight or GridView.FlowTopToBottom.
 
1206
    \li \l layoutDirection - controls the horizontal layout direction: that is, whether items
 
1207
        are laid out from the left side of the view to the right, or vice-versa. This value can
 
1208
        be either Qt.LeftToRight or Qt.RightToLeft.
 
1209
    \li \l verticalLayoutDirection - controls the vertical layout direction: that is, whether items
 
1210
        are laid out from the top of the view down towards the bottom of the view, or vice-versa.
 
1211
        This value can be either GridView.TopToBottom or GridView.BottomToTop.
 
1212
    \endlist
 
1213
 
 
1214
    By default, a GridView flows from left to right, and items are laid out from left to right
 
1215
    horizontally, and from top to bottom vertically.
 
1216
 
 
1217
    These properties can be combined to produce a variety of layouts, as shown in the table below.
 
1218
    The GridViews in the first row all have a \l flow value of GridView.FlowLeftToRight, but use
 
1219
    different combinations of horizontal and vertical layout directions (specified by \l layoutDirection
 
1220
    and \l verticalLayoutDirection respectively). Similarly, the GridViews in the second row below
 
1221
    all have a \l flow value of GridView.FlowTopToBottom, but use different combinations of horizontal and
 
1222
    vertical layout directions to lay out their items in different ways.
 
1223
 
 
1224
    \table
 
1225
    \header
 
1226
        \li {4, 1}
 
1227
            \b GridViews with GridView.FlowLeftToRight flow
 
1228
    \row
 
1229
        \li \b (H) Left to right \b (V) Top to bottom
 
1230
            \image gridview-layout-lefttoright-ltr-ttb.png
 
1231
        \li \b (H) Right to left \b (V) Top to bottom
 
1232
            \image gridview-layout-lefttoright-rtl-ttb.png
 
1233
        \li \b (H) Left to right \b (V) Bottom to top
 
1234
            \image gridview-layout-lefttoright-ltr-btt.png
 
1235
        \li \b (H) Right to left \b (V) Bottom to top
 
1236
            \image gridview-layout-lefttoright-rtl-btt.png
 
1237
    \header
 
1238
        \li {4, 1}
 
1239
            \b GridViews with GridView.FlowTopToBottom flow
 
1240
    \row
 
1241
        \li \b (H) Left to right \b (V) Top to bottom
 
1242
            \image gridview-layout-toptobottom-ltr-ttb.png
 
1243
        \li \b (H) Right to left \b (V) Top to bottom
 
1244
            \image gridview-layout-toptobottom-rtl-ttb.png
 
1245
        \li \b (H) Left to right \b (V) Bottom to top
 
1246
            \image gridview-layout-toptobottom-ltr-btt.png
 
1247
        \li \b (H) Right to left \b (V) Bottom to top
 
1248
            \image gridview-layout-toptobottom-rtl-btt.png
 
1249
    \endtable
 
1250
 
 
1251
    \sa {QML Data Models}, ListView, PathView, {Qt Quick Examples - Views}
 
1252
*/
 
1253
 
 
1254
QQuickGridView::QQuickGridView(QQuickItem *parent)
 
1255
    : QQuickItemView(*(new QQuickGridViewPrivate), parent)
 
1256
{
 
1257
}
 
1258
 
 
1259
QQuickGridView::~QQuickGridView()
 
1260
{
 
1261
}
 
1262
 
 
1263
void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
 
1264
{
 
1265
    Q_D(QQuickGridView);
 
1266
    if (d->autoHighlight != autoHighlight) {
 
1267
        if (!autoHighlight && d->highlightXAnimator) {
 
1268
            d->highlightXAnimator->stop();
 
1269
            d->highlightYAnimator->stop();
 
1270
        }
 
1271
        QQuickItemView::setHighlightFollowsCurrentItem(autoHighlight);
 
1272
    }
 
1273
}
 
1274
 
 
1275
/*!
 
1276
    \qmlattachedproperty bool QtQuick::GridView::isCurrentItem
 
1277
    This attached property is true if this delegate is the current item; otherwise false.
 
1278
 
 
1279
    It is attached to each instance of the delegate.
 
1280
*/
 
1281
 
 
1282
/*!
 
1283
    \qmlattachedproperty GridView QtQuick::GridView::view
 
1284
    This attached property holds the view that manages this delegate instance.
 
1285
 
 
1286
    It is attached to each instance of the delegate and also to the header, the footer
 
1287
    and the highlight delegates.
 
1288
 
 
1289
    \snippet qml/gridview/gridview.qml isCurrentItem
 
1290
*/
 
1291
 
 
1292
/*!
 
1293
    \qmlattachedproperty bool QtQuick::GridView::delayRemove
 
1294
    This attached property holds whether the delegate may be destroyed. It
 
1295
    is attached to each instance of the delegate. The default value is false.
 
1296
 
 
1297
    It is sometimes necessary to delay the destruction of an item
 
1298
    until an animation completes. The example delegate below ensures that the
 
1299
    animation completes before the item is removed from the list.
 
1300
 
 
1301
    \snippet qml/gridview/gridview.qml delayRemove
 
1302
 
 
1303
    If a \l remove transition has been specified, it will not be applied until
 
1304
    delayRemove is returned to \c false.
 
1305
*/
 
1306
 
 
1307
/*!
 
1308
    \qmlattachedsignal QtQuick::GridView::add()
 
1309
    This attached signal is emitted immediately after an item is added to the view.
 
1310
 
 
1311
    The corresponding handler is \c onAdd.
 
1312
*/
 
1313
 
 
1314
/*!
 
1315
    \qmlattachedsignal QtQuick::GridView::remove()
 
1316
    This attached signal is emitted immediately before an item is removed from the view.
 
1317
 
 
1318
    If a \l remove transition has been specified, it is applied after
 
1319
    this signal is handled, providing that \l delayRemove is false.
 
1320
 
 
1321
    The corresponding handler is \c onRemove.
 
1322
*/
 
1323
 
 
1324
 
 
1325
/*!
 
1326
  \qmlproperty model QtQuick::GridView::model
 
1327
  This property holds the model providing data for the grid.
 
1328
 
 
1329
    The model provides the set of data that is used to create the items
 
1330
    in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
 
1331
    or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
 
1332
    used, it must be a subclass of \l QAbstractItemModel or a simple list.
 
1333
 
 
1334
  \sa {qml-data-models}{Data Models}
 
1335
*/
 
1336
 
 
1337
/*!
 
1338
    \qmlproperty Component QtQuick::GridView::delegate
 
1339
 
 
1340
    The delegate provides a template defining each item instantiated by the view.
 
1341
    The index is exposed as an accessible \c index property.  Properties of the
 
1342
    model are also available depending upon the type of \l {qml-data-models}{Data Model}.
 
1343
 
 
1344
    The number of objects and bindings in the delegate has a direct effect on the
 
1345
    flicking performance of the view.  If at all possible, place functionality
 
1346
    that is not needed for the normal display of the delegate in a \l Loader which
 
1347
    can load additional components when needed.
 
1348
 
 
1349
    The item size of the GridView is determined by cellHeight and cellWidth. It will not resize the items
 
1350
    based on the size of the root item in the delegate.
 
1351
 
 
1352
    The default \l {QQuickItem::z}{stacking order} of delegate instances is \c 1.
 
1353
 
 
1354
    \note Delegates are instantiated as needed and may be destroyed at any time.
 
1355
    State should \e never be stored in a delegate.
 
1356
*/
 
1357
 
 
1358
/*!
 
1359
  \qmlproperty int QtQuick::GridView::currentIndex
 
1360
  \qmlproperty Item QtQuick::GridView::currentItem
 
1361
 
 
1362
    The \c currentIndex property holds the index of the current item, and
 
1363
    \c currentItem holds the current item.  Setting the currentIndex to -1
 
1364
    will clear the highlight and set currentItem to null.
 
1365
 
 
1366
    If highlightFollowsCurrentItem is \c true, setting either of these
 
1367
    properties will smoothly scroll the GridView so that the current
 
1368
    item becomes visible.
 
1369
 
 
1370
    Note that the position of the current item
 
1371
    may only be approximate until it becomes visible in the view.
 
1372
*/
 
1373
 
 
1374
 
 
1375
/*!
 
1376
  \qmlproperty Item QtQuick::GridView::highlightItem
 
1377
 
 
1378
  This holds the highlight item created from the \l highlight component.
 
1379
 
 
1380
  The highlightItem is managed by the view unless
 
1381
  \l highlightFollowsCurrentItem is set to false.
 
1382
  The default \l {QQuickItem::z}{stacking order}
 
1383
  of the highlight item is \c 0.
 
1384
 
 
1385
  \sa highlight, highlightFollowsCurrentItem
 
1386
*/
 
1387
 
 
1388
 
 
1389
/*!
 
1390
  \qmlproperty int QtQuick::GridView::count
 
1391
  This property holds the number of items in the view.
 
1392
*/
 
1393
 
 
1394
 
 
1395
/*!
 
1396
  \qmlproperty Component QtQuick::GridView::highlight
 
1397
  This property holds the component to use as the highlight.
 
1398
 
 
1399
  An instance of the highlight component is created for each view.
 
1400
  The geometry of the resulting component instance will be managed by the view
 
1401
  so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
 
1402
  The default \l {QQuickItem::z}{stacking order} of the highlight item is \c 0.
 
1403
 
 
1404
  \sa highlightItem, highlightFollowsCurrentItem
 
1405
*/
 
1406
 
 
1407
/*!
 
1408
  \qmlproperty bool QtQuick::GridView::highlightFollowsCurrentItem
 
1409
  This property sets whether the highlight is managed by the view.
 
1410
 
 
1411
    If this property is true (the default value), the highlight is moved smoothly
 
1412
    to follow the current item.  Otherwise, the
 
1413
    highlight is not moved by the view, and any movement must be implemented
 
1414
    by the highlight.
 
1415
 
 
1416
    Here is a highlight with its motion defined by a \l {SpringAnimation} item:
 
1417
 
 
1418
    \snippet qml/gridview/gridview.qml highlightFollowsCurrentItem
 
1419
*/
 
1420
 
 
1421
 
 
1422
/*!
 
1423
    \qmlproperty int QtQuick::GridView::highlightMoveDuration
 
1424
    This property holds the move animation duration of the highlight delegate.
 
1425
 
 
1426
    highlightFollowsCurrentItem must be true for this property
 
1427
    to have effect.
 
1428
 
 
1429
    The default value for the duration is 150ms.
 
1430
 
 
1431
    \sa highlightFollowsCurrentItem
 
1432
*/
 
1433
 
 
1434
/*!
 
1435
    \qmlproperty real QtQuick::GridView::preferredHighlightBegin
 
1436
    \qmlproperty real QtQuick::GridView::preferredHighlightEnd
 
1437
    \qmlproperty enumeration QtQuick::GridView::highlightRangeMode
 
1438
 
 
1439
    These properties define the preferred range of the highlight (for the current item)
 
1440
    within the view. The \c preferredHighlightBegin value must be less than the
 
1441
    \c preferredHighlightEnd value.
 
1442
 
 
1443
    These properties affect the position of the current item when the view is scrolled.
 
1444
    For example, if the currently selected item should stay in the middle of the
 
1445
    view when it is scrolled, set the \c preferredHighlightBegin and
 
1446
    \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
 
1447
    item would be. If the \c currentItem is changed programmatically, the view will
 
1448
    automatically scroll so that the current item is in the middle of the view.
 
1449
    Furthermore, the behavior of the current item index will occur whether or not a
 
1450
    highlight exists.
 
1451
 
 
1452
    Valid values for \c highlightRangeMode are:
 
1453
 
 
1454
    \list
 
1455
    \li GridView.ApplyRange - the view attempts to maintain the highlight within the range.
 
1456
       However, the highlight can move outside of the range at the ends of the view or due
 
1457
       to mouse interaction.
 
1458
    \li GridView.StrictlyEnforceRange - the highlight never moves outside of the range.
 
1459
       The current item changes if a keyboard or mouse action would cause the highlight to move
 
1460
       outside of the range.
 
1461
    \li GridView.NoHighlightRange - this is the default value.
 
1462
    \endlist
 
1463
*/
 
1464
 
 
1465
 
 
1466
/*!
 
1467
  \qmlproperty enumeration QtQuick::GridView::layoutDirection
 
1468
  This property holds the layout direction of the grid.
 
1469
 
 
1470
    Possible values:
 
1471
 
 
1472
  \list
 
1473
  \li Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is
 
1474
  dependent on the \l GridView::flow property.
 
1475
  \li Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent
 
1476
  on the \l GridView::flow property.
 
1477
  \endlist
 
1478
 
 
1479
  \b Note: If GridView::flow is set to GridView.FlowLeftToRight, this is not to be confused if
 
1480
  GridView::layoutDirection is set to Qt.RightToLeft. The GridView.FlowLeftToRight flow value simply
 
1481
  indicates that the flow is horizontal.
 
1482
 
 
1483
  \sa GridView::effectiveLayoutDirection, GridView::verticalLayoutDirection
 
1484
*/
 
1485
 
 
1486
 
 
1487
/*!
 
1488
    \qmlproperty enumeration QtQuick::GridView::effectiveLayoutDirection
 
1489
    This property holds the effective layout direction of the grid.
 
1490
 
 
1491
    When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
 
1492
    the visual layout direction of the grid will be mirrored. However, the
 
1493
    property \l {GridView::layoutDirection}{layoutDirection} will remain unchanged.
 
1494
 
 
1495
    \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
 
1496
*/
 
1497
 
 
1498
/*!
 
1499
  \qmlproperty enumeration QtQuick::GridView::verticalLayoutDirection
 
1500
  This property holds the vertical layout direction of the grid.
 
1501
 
 
1502
  Possible values:
 
1503
 
 
1504
  \list
 
1505
  \li GridView.TopToBottom (default) - Items are laid out from the top of the view down to the bottom of the view.
 
1506
  \li GridView.BottomToTop - Items are laid out from the bottom of the view up to the top of the view.
 
1507
  \endlist
 
1508
 
 
1509
  \sa GridView::layoutDirection
 
1510
*/
 
1511
 
 
1512
/*!
 
1513
  \qmlproperty bool QtQuick::GridView::keyNavigationWraps
 
1514
  This property holds whether the grid wraps key navigation
 
1515
 
 
1516
    If this is true, key navigation that would move the current item selection
 
1517
    past one end of the view instead wraps around and moves the selection to
 
1518
    the other end of the view.
 
1519
 
 
1520
    By default, key navigation is not wrapped.
 
1521
*/
 
1522
/*!
 
1523
    \qmlproperty int QtQuick::GridView::cacheBuffer
 
1524
    This property determines whether delegates are retained outside the
 
1525
    visible area of the view.
 
1526
 
 
1527
    If non-zero the view may keep as many delegates
 
1528
    instantiated as will fit within the buffer specified.  For example,
 
1529
    if in a vertical view the delegate is 20 pixels high, there are 3
 
1530
    columns and \c cacheBuffer is
 
1531
    set to 40, then up to 6 delegates above and 6 delegates below the visible
 
1532
    area may be created/retained.  The buffered delegates are created asynchronously,
 
1533
    allowing creation to occur across multiple frames and reducing the
 
1534
    likelihood of skipping frames.  In order to improve painting performance
 
1535
    delegates outside the visible area are not painted.
 
1536
 
 
1537
    The default value of this property is platform dependent, but will usually
 
1538
    be a non-zero value.
 
1539
 
 
1540
    Note that cacheBuffer is not a pixel buffer - it only maintains additional
 
1541
    instantiated delegates.
 
1542
 
 
1543
    Setting this value can make scrolling the list smoother at the expense
 
1544
    of additional memory usage.  It is not a substitute for creating efficient
 
1545
    delegates; the fewer objects and bindings in a delegate, the faster a view may be
 
1546
    scrolled.
 
1547
 
 
1548
    The cacheBuffer operates outside of any display margins specified by
 
1549
    displayMarginBeginning or displayMarginEnd.
 
1550
*/
 
1551
 
 
1552
/*!
 
1553
    \qmlproperty int QtQuick::GridView::displayMarginBeginning
 
1554
    \qmlproperty int QtQuick::GridView::displayMarginEnd
 
1555
    \since QtQuick 2.3
 
1556
 
 
1557
    This property allows delegates to be displayed outside of the view geometry.
 
1558
 
 
1559
    If this value is non-zero, the view will create extra delegates before the
 
1560
    start of the view, or after the end. The view will create as many delegates
 
1561
    as it can fit into the pixel size specified.
 
1562
 
 
1563
    For example, if in a vertical view the delegate is 20 pixels high,
 
1564
    there are 3 columns, and
 
1565
    \c displayMarginBeginning and \c displayMarginEnd are both set to 40,
 
1566
    then 6 delegates above and 6 delegates below will be created and shown.
 
1567
 
 
1568
    The default value is 0.
 
1569
 
 
1570
    This property is meant for allowing certain UI configurations,
 
1571
    and not as a performance optimization. If you wish to create delegates
 
1572
    outside of the view geometry for performance reasons, you probably
 
1573
    want to use the cacheBuffer property instead.
 
1574
*/
 
1575
 
 
1576
void QQuickGridView::setHighlightMoveDuration(int duration)
 
1577
{
 
1578
    Q_D(QQuickGridView);
 
1579
    if (d->highlightMoveDuration != duration) {
 
1580
        if (d->highlightYAnimator) {
 
1581
            d->highlightXAnimator->userDuration = duration;
 
1582
            d->highlightYAnimator->userDuration = duration;
 
1583
        }
 
1584
        QQuickItemView::setHighlightMoveDuration(duration);
 
1585
    }
 
1586
}
 
1587
 
 
1588
/*!
 
1589
  \qmlproperty enumeration QtQuick::GridView::flow
 
1590
  This property holds the flow of the grid.
 
1591
 
 
1592
    Possible values:
 
1593
 
 
1594
    \list
 
1595
    \li GridView.FlowLeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically
 
1596
    \li GridView.FlowTopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally
 
1597
    \endlist
 
1598
*/
 
1599
QQuickGridView::Flow QQuickGridView::flow() const
 
1600
{
 
1601
    Q_D(const QQuickGridView);
 
1602
    return d->flow;
 
1603
}
 
1604
 
 
1605
void QQuickGridView::setFlow(Flow flow)
 
1606
{
 
1607
    Q_D(QQuickGridView);
 
1608
    if (d->flow != flow) {
 
1609
        d->flow = flow;
 
1610
        if (d->flow == FlowLeftToRight) {
 
1611
            setContentWidth(-1);
 
1612
            setFlickableDirection(VerticalFlick);
 
1613
        } else {
 
1614
            setContentHeight(-1);
 
1615
            setFlickableDirection(HorizontalFlick);
 
1616
        }
 
1617
        setContentX(0);
 
1618
        setContentY(0);
 
1619
        d->regenerate();
 
1620
        emit flowChanged();
 
1621
    }
 
1622
}
 
1623
 
 
1624
 
 
1625
/*!
 
1626
  \qmlproperty real QtQuick::GridView::cellWidth
 
1627
  \qmlproperty real QtQuick::GridView::cellHeight
 
1628
 
 
1629
  These properties holds the width and height of each cell in the grid.
 
1630
 
 
1631
  The default cell size is 100x100.
 
1632
*/
 
1633
qreal QQuickGridView::cellWidth() const
 
1634
{
 
1635
    Q_D(const QQuickGridView);
 
1636
    return d->cellWidth;
 
1637
}
 
1638
 
 
1639
void QQuickGridView::setCellWidth(qreal cellWidth)
 
1640
{
 
1641
    Q_D(QQuickGridView);
 
1642
    if (cellWidth != d->cellWidth && cellWidth > 0) {
 
1643
        d->cellWidth = qMax(qreal(1), cellWidth);
 
1644
        d->updateViewport();
 
1645
        emit cellWidthChanged();
 
1646
        d->forceLayoutPolish();
 
1647
    }
 
1648
}
 
1649
 
 
1650
qreal QQuickGridView::cellHeight() const
 
1651
{
 
1652
    Q_D(const QQuickGridView);
 
1653
    return d->cellHeight;
 
1654
}
 
1655
 
 
1656
void QQuickGridView::setCellHeight(qreal cellHeight)
 
1657
{
 
1658
    Q_D(QQuickGridView);
 
1659
    if (cellHeight != d->cellHeight && cellHeight > 0) {
 
1660
        d->cellHeight = qMax(qreal(1), cellHeight);
 
1661
        d->updateViewport();
 
1662
        emit cellHeightChanged();
 
1663
        d->forceLayoutPolish();
 
1664
    }
 
1665
}
 
1666
/*!
 
1667
    \qmlproperty enumeration QtQuick::GridView::snapMode
 
1668
 
 
1669
    This property determines how the view scrolling will settle following a drag or flick.
 
1670
    The possible values are:
 
1671
 
 
1672
    \list
 
1673
    \li GridView.NoSnap (default) - the view stops anywhere within the visible area.
 
1674
    \li GridView.SnapToRow - the view settles with a row (or column for \c GridView.FlowTopToBottom flow)
 
1675
    aligned with the start of the view.
 
1676
    \li GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.FlowTopToBottom flow)
 
1677
    away from the first visible row at the time the mouse button is released.
 
1678
    This mode is particularly useful for moving one page at a time.
 
1679
    \endlist
 
1680
 
 
1681
*/
 
1682
QQuickGridView::SnapMode QQuickGridView::snapMode() const
 
1683
{
 
1684
    Q_D(const QQuickGridView);
 
1685
    return d->snapMode;
 
1686
}
 
1687
 
 
1688
void QQuickGridView::setSnapMode(SnapMode mode)
 
1689
{
 
1690
    Q_D(QQuickGridView);
 
1691
    if (d->snapMode != mode) {
 
1692
        d->snapMode = mode;
 
1693
        emit snapModeChanged();
 
1694
    }
 
1695
}
 
1696
 
 
1697
 
 
1698
/*!
 
1699
    \qmlproperty Component QtQuick::GridView::footer
 
1700
    This property holds the component to use as the footer.
 
1701
 
 
1702
    An instance of the footer component is created for each view.  The
 
1703
    footer is positioned at the end of the view, after any items. The
 
1704
    default \l {QQuickItem::z}{stacking order} of the footer is \c 1.
 
1705
 
 
1706
    \sa header, footerItem
 
1707
*/
 
1708
/*!
 
1709
    \qmlproperty Component QtQuick::GridView::header
 
1710
    This property holds the component to use as the header.
 
1711
 
 
1712
    An instance of the header component is created for each view.  The
 
1713
    header is positioned at the beginning of the view, before any items.
 
1714
    The default \l {QQuickItem::z}{stacking order} of the header is \c 1.
 
1715
 
 
1716
    \sa footer, headerItem
 
1717
*/
 
1718
 
 
1719
/*!
 
1720
    \qmlproperty Item QtQuick::GridView::headerItem
 
1721
    This holds the header item created from the \l header component.
 
1722
 
 
1723
    An instance of the header component is created for each view.  The
 
1724
    header is positioned at the beginning of the view, before any items.
 
1725
    The default \l {QQuickItem::z}{stacking order} of the header is \c 1.
 
1726
 
 
1727
    \sa header, footerItem
 
1728
*/
 
1729
 
 
1730
/*!
 
1731
    \qmlproperty Item QtQuick::GridView::footerItem
 
1732
    This holds the footer item created from the \l footer component.
 
1733
 
 
1734
    An instance of the footer component is created for each view.  The
 
1735
    footer is positioned at the end of the view, after any items. The
 
1736
    default \l {QQuickItem::z}{stacking order} of the footer is \c 1.
 
1737
 
 
1738
    \sa footer, headerItem
 
1739
*/
 
1740
 
 
1741
/*!
 
1742
    \qmlproperty Transition QtQuick::GridView::populate
 
1743
 
 
1744
    This property holds the transition to apply to the items that are initially created
 
1745
    for a view.
 
1746
 
 
1747
    It is applied to all items that are created when:
 
1748
 
 
1749
    \list
 
1750
    \li The view is first created
 
1751
    \li The view's \l model changes
 
1752
    \li The view's \l model is \l {QAbstractItemModel::reset()}{reset}, if the model is a QAbstractItemModel subclass
 
1753
    \endlist
 
1754
 
 
1755
    For example, here is a view that specifies such a transition:
 
1756
 
 
1757
    \code
 
1758
    GridView {
 
1759
        ...
 
1760
        populate: Transition {
 
1761
            NumberAnimation { properties: "x,y"; duration: 1000 }
 
1762
        }
 
1763
    }
 
1764
    \endcode
 
1765
 
 
1766
    When the view is initialized, the view will create all the necessary items for the view,
 
1767
    then animate them to their correct positions within the view over one second.
 
1768
 
 
1769
    For more details and examples on how to use view transitions, see the ViewTransition
 
1770
    documentation.
 
1771
 
 
1772
    \sa add, ViewTransition
 
1773
*/
 
1774
 
 
1775
/*!
 
1776
    \qmlproperty Transition QtQuick::GridView::add
 
1777
 
 
1778
    This property holds the transition to apply to items that are added to the view.
 
1779
 
 
1780
    For example, here is a view that specifies such a transition:
 
1781
 
 
1782
    \code
 
1783
    GridView {
 
1784
        ...
 
1785
        add: Transition {
 
1786
            NumberAnimation { properties: "x,y"; from: 100; duration: 1000 }
 
1787
        }
 
1788
    }
 
1789
    \endcode
 
1790
 
 
1791
    Whenever an item is added to the above view, the item will be animated from the position (100,100)
 
1792
    to its final x,y position within the view, over one second. The transition only applies to
 
1793
    the new items that are added to the view; it does not apply to the items below that are
 
1794
    displaced by the addition of the new items. To animate the displaced items, set the \l displaced
 
1795
    or \l addDisplaced properties.
 
1796
 
 
1797
    For more details and examples on how to use view transitions, see the ViewTransition
 
1798
    documentation.
 
1799
 
 
1800
    \note This transition is not applied to the items that are created when the view is initially
 
1801
    populated, or when the view's \l model changes. (In those cases, the \l populate transition is
 
1802
    applied instead.) Additionally, this transition should \e not animate the height of the new item;
 
1803
    doing so will cause any items beneath the new item to be laid out at the wrong position. Instead,
 
1804
    the height can be animated within the \l {add}{onAdd} handler in the delegate.
 
1805
 
 
1806
    \sa addDisplaced, populate, ViewTransition
 
1807
*/
 
1808
 
 
1809
/*!
 
1810
    \qmlproperty Transition QtQuick::GridView::addDisplaced
 
1811
 
 
1812
    This property holds the transition to apply to items within the view that are displaced by
 
1813
    the addition of other items to the view.
 
1814
 
 
1815
    For example, here is a view that specifies such a transition:
 
1816
 
 
1817
    \code
 
1818
    GridView {
 
1819
        ...
 
1820
        addDisplaced: Transition {
 
1821
            NumberAnimation { properties: "x,y"; duration: 1000 }
 
1822
        }
 
1823
    }
 
1824
    \endcode
 
1825
 
 
1826
    Whenever an item is added to the above view, all items beneath the new item are displaced, causing
 
1827
    them to move down (or sideways, if horizontally orientated) within the view. As this
 
1828
    displacement occurs, the items' movement to their new x,y positions within the view will be
 
1829
    animated by a NumberAnimation over one second, as specified. This transition is not applied to
 
1830
    the new item that has been added to the view; to animate the added items, set the \l add
 
1831
    property.
 
1832
 
 
1833
    If an item is displaced by multiple types of operations at the same time, it is not defined as to
 
1834
    whether the addDisplaced, moveDisplaced or removeDisplaced transition will be applied. Additionally,
 
1835
    if it is not necessary to specify different transitions depending on whether an item is displaced
 
1836
    by an add, move or remove operation, consider setting the \l displaced property instead.
 
1837
 
 
1838
    For more details and examples on how to use view transitions, see the ViewTransition
 
1839
    documentation.
 
1840
 
 
1841
    \note This transition is not applied to the items that are created when the view is initially
 
1842
    populated, or when the view's \l model changes. In those cases, the \l populate transition is
 
1843
    applied instead.
 
1844
 
 
1845
    \sa displaced, add, populate, ViewTransition
 
1846
*/
 
1847
/*!
 
1848
    \qmlproperty Transition QtQuick::GridView::move
 
1849
 
 
1850
    This property holds the transition to apply to items in the view that are being moved due
 
1851
    to a move operation in the view's \l model.
 
1852
 
 
1853
    For example, here is a view that specifies such a transition:
 
1854
 
 
1855
    \code
 
1856
    GridView {
 
1857
        ...
 
1858
        move: Transition {
 
1859
            NumberAnimation { properties: "x,y"; duration: 1000 }
 
1860
        }
 
1861
    }
 
1862
    \endcode
 
1863
 
 
1864
    Whenever the \l model performs a move operation to move a particular set of indexes, the
 
1865
    respective items in the view will be animated to their new positions in the view over one
 
1866
    second. The transition only applies to the items that are the subject of the move operation
 
1867
    in the model; it does not apply to items below them that are displaced by the move operation.
 
1868
    To animate the displaced items, set the \l displaced or \l moveDisplaced properties.
 
1869
 
 
1870
    For more details and examples on how to use view transitions, see the ViewTransition
 
1871
    documentation.
 
1872
 
 
1873
    \sa moveDisplaced, ViewTransition
 
1874
*/
 
1875
 
 
1876
/*!
 
1877
    \qmlproperty Transition QtQuick::GridView::moveDisplaced
 
1878
 
 
1879
    This property holds the transition to apply to items that are displaced by a move operation in
 
1880
    the view's \l model.
 
1881
 
 
1882
    For example, here is a view that specifies such a transition:
 
1883
 
 
1884
    \code
 
1885
    GridView {
 
1886
        ...
 
1887
        moveDisplaced: Transition {
 
1888
            NumberAnimation { properties: "x,y"; duration: 1000 }
 
1889
        }
 
1890
    }
 
1891
    \endcode
 
1892
 
 
1893
    Whenever the \l model performs a move operation to move a particular set of indexes, the items
 
1894
    between the source and destination indexes of the move operation are displaced, causing them
 
1895
    to move upwards or downwards (or sideways, if horizontally orientated) within the view. As this
 
1896
    displacement occurs, the items' movement to their new x,y positions within the view will be
 
1897
    animated by a NumberAnimation over one second, as specified. This transition is not applied to
 
1898
    the items that are the actual subjects of the move operation; to animate the moved items, set
 
1899
    the \l move property.
 
1900
 
 
1901
    If an item is displaced by multiple types of operations at the same time, it is not defined as to
 
1902
    whether the addDisplaced, moveDisplaced or removeDisplaced transition will be applied. Additionally,
 
1903
    if it is not necessary to specify different transitions depending on whether an item is displaced
 
1904
    by an add, move or remove operation, consider setting the \l displaced property instead.
 
1905
 
 
1906
    For more details and examples on how to use view transitions, see the ViewTransition
 
1907
    documentation.
 
1908
 
 
1909
    \sa displaced, move, ViewTransition
 
1910
*/
 
1911
 
 
1912
/*!
 
1913
    \qmlproperty Transition QtQuick::GridView::remove
 
1914
 
 
1915
    This property holds the transition to apply to items that are removed from the view.
 
1916
 
 
1917
    For example, here is a view that specifies such a transition:
 
1918
 
 
1919
    \code
 
1920
    GridView {
 
1921
        ...
 
1922
        remove: Transition {
 
1923
            ParallelAnimation {
 
1924
                NumberAnimation { property: "opacity"; to: 0; duration: 1000 }
 
1925
                NumberAnimation { properties: "x,y"; to: 100; duration: 1000 }
 
1926
            }
 
1927
        }
 
1928
    }
 
1929
    \endcode
 
1930
 
 
1931
    Whenever an item is removed from the above view, the item will be animated to the position (100,100)
 
1932
    over one second, and in parallel will also change its opacity to 0. The transition
 
1933
    only applies to the items that are removed from the view; it does not apply to the items below
 
1934
    them that are displaced by the removal of the items. To animate the displaced items, set the
 
1935
    \l displaced or \l removeDisplaced properties.
 
1936
 
 
1937
    Note that by the time the transition is applied, the item has already been removed from the
 
1938
    model; any references to the model data for the removed index will not be valid.
 
1939
 
 
1940
    Additionally, if the \l delayRemove attached property has been set for a delegate item, the
 
1941
    remove transition will not be applied until \l delayRemove becomes false again.
 
1942
 
 
1943
    For more details and examples on how to use view transitions, see the ViewTransition
 
1944
    documentation.
 
1945
 
 
1946
    \sa removeDisplaced, ViewTransition
 
1947
*/
 
1948
 
 
1949
/*!
 
1950
    \qmlproperty Transition QtQuick::GridView::removeDisplaced
 
1951
 
 
1952
    This property holds the transition to apply to items in the view that are displaced by the
 
1953
    removal of other items in the view.
 
1954
 
 
1955
    For example, here is a view that specifies such a transition:
 
1956
 
 
1957
    \code
 
1958
    GridView {
 
1959
        ...
 
1960
        removeDisplaced: Transition {
 
1961
            NumberAnimation { properties: "x,y"; duration: 1000 }
 
1962
        }
 
1963
    }
 
1964
    \endcode
 
1965
 
 
1966
    Whenever an item is removed from the above view, all items beneath it are displaced, causing
 
1967
    them to move upwards (or sideways, if horizontally orientated) within the view. As this
 
1968
    displacement occurs, the items' movement to their new x,y positions within the view will be
 
1969
    animated by a NumberAnimation over one second, as specified. This transition is not applied to
 
1970
    the item that has actually been removed from the view; to animate the removed items, set the
 
1971
    \l remove property.
 
1972
 
 
1973
    If an item is displaced by multiple types of operations at the same time, it is not defined as to
 
1974
    whether the addDisplaced, moveDisplaced or removeDisplaced transition will be applied. Additionally,
 
1975
    if it is not necessary to specify different transitions depending on whether an item is displaced
 
1976
    by an add, move or remove operation, consider setting the \l displaced property instead.
 
1977
 
 
1978
    For more details and examples on how to use view transitions, see the ViewTransition
 
1979
    documentation.
 
1980
 
 
1981
    \sa displaced, remove, ViewTransition
 
1982
*/
 
1983
 
 
1984
/*!
 
1985
    \qmlproperty Transition QtQuick::GridView::displaced
 
1986
    This property holds the generic transition to apply to items that have been displaced by
 
1987
    any model operation that affects the view.
 
1988
 
 
1989
    This is a convenience for specifying a generic transition for items that are displaced
 
1990
    by add, move or remove operations, without having to specify the individual addDisplaced,
 
1991
    moveDisplaced and removeDisplaced properties. For example, here is a view that specifies
 
1992
    a displaced transition:
 
1993
 
 
1994
    \code
 
1995
    GridView {
 
1996
        ...
 
1997
        displaced: Transition {
 
1998
            NumberAnimation { properties: "x,y"; duration: 1000 }
 
1999
        }
 
2000
    }
 
2001
    \endcode
 
2002
 
 
2003
    When any item is added, moved or removed within the above view, the items below it are
 
2004
    displaced, causing them to move down (or sideways, if horizontally orientated) within the
 
2005
    view. As this displacement occurs, the items' movement to their new x,y positions within
 
2006
    the view will be animated by a NumberAnimation over one second, as specified.
 
2007
 
 
2008
    If a view specifies this generic displaced transition as well as a specific addDisplaced,
 
2009
    moveDisplaced or removeDisplaced transition, the more specific transition will be used
 
2010
    instead of the generic displaced transition when the relevant operation occurs, providing that
 
2011
    the more specific transition has not been disabled (by setting \l {Transition::enabled}{enabled}
 
2012
    to false). If it has indeed been disabled, the generic displaced transition is applied instead.
 
2013
 
 
2014
    For more details and examples on how to use view transitions, see the ViewTransition
 
2015
    documentation.
 
2016
 
 
2017
    \sa addDisplaced, moveDisplaced, removeDisplaced, ViewTransition
 
2018
*/
 
2019
 
 
2020
void QQuickGridView::viewportMoved(Qt::Orientations orient)
 
2021
{
 
2022
    Q_D(QQuickGridView);
 
2023
    QQuickItemView::viewportMoved(orient);
 
2024
    if (!d->itemCount)
 
2025
        return;
 
2026
    if (d->inViewportMoved)
 
2027
        return;
 
2028
    d->inViewportMoved = true;
 
2029
 
 
2030
    if (yflick()) {
 
2031
        if (d->isContentFlowReversed())
 
2032
            d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickItemViewPrivate::BufferAfter : QQuickItemViewPrivate::BufferBefore;
 
2033
        else
 
2034
            d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickItemViewPrivate::BufferBefore : QQuickItemViewPrivate::BufferAfter;
 
2035
    } else {
 
2036
        if (d->isContentFlowReversed())
 
2037
            d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickItemViewPrivate::BufferAfter : QQuickItemViewPrivate::BufferBefore;
 
2038
        else
 
2039
            d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickItemViewPrivate::BufferBefore : QQuickItemViewPrivate::BufferAfter;
 
2040
    }
 
2041
 
 
2042
    d->refillOrLayout();
 
2043
 
 
2044
    // Set visibility of items to eliminate cost of items outside the visible area.
 
2045
    qreal from = d->isContentFlowReversed() ? -d->position()-d->displayMarginBeginning-d->size() : d->position()-d->displayMarginBeginning;
 
2046
    qreal to = d->isContentFlowReversed() ? -d->position()+d->displayMarginEnd : d->position()+d->size()+d->displayMarginEnd;
 
2047
    for (int i = 0; i < d->visibleItems.count(); ++i) {
 
2048
        FxGridItemSG *item = static_cast<FxGridItemSG*>(d->visibleItems.at(i));
 
2049
        QQuickItemPrivate::get(item->item)->setCulled(item->rowPos() + d->rowSize() < from || item->rowPos() > to);
 
2050
    }
 
2051
    if (d->currentItem) {
 
2052
        FxGridItemSG *item = static_cast<FxGridItemSG*>(d->currentItem);
 
2053
        QQuickItemPrivate::get(item->item)->setCulled(item->rowPos() + d->rowSize() < from || item->rowPos() > to);
 
2054
    }
 
2055
 
 
2056
    if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
 
2057
        d->moveReason = QQuickGridViewPrivate::Mouse;
 
2058
    if (d->moveReason != QQuickGridViewPrivate::SetIndex) {
 
2059
        if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
 
2060
            // reposition highlight
 
2061
            qreal pos = d->highlight->position();
 
2062
            qreal viewPos = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
 
2063
            if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
 
2064
                pos = viewPos + d->highlightRangeEnd - d->highlight->size();
 
2065
            if (pos < viewPos + d->highlightRangeStart)
 
2066
                pos = viewPos + d->highlightRangeStart;
 
2067
 
 
2068
            if (pos != d->highlight->position()) {
 
2069
                d->highlightXAnimator->stop();
 
2070
                d->highlightYAnimator->stop();
 
2071
                static_cast<FxGridItemSG*>(d->highlight)->setPosition(static_cast<FxGridItemSG*>(d->highlight)->colPos(), pos);
 
2072
            } else {
 
2073
                d->updateHighlight();
 
2074
            }
 
2075
 
 
2076
            // update current index
 
2077
            int idx = d->snapIndex();
 
2078
            if (idx >= 0 && idx != d->currentIndex) {
 
2079
                d->updateCurrent(idx);
 
2080
                if (d->currentItem && static_cast<FxGridItemSG*>(d->currentItem)->colPos() != static_cast<FxGridItemSG*>(d->highlight)->colPos() && d->autoHighlight) {
 
2081
                    if (d->flow == FlowLeftToRight)
 
2082
                        d->highlightXAnimator->to = d->currentItem->itemX();
 
2083
                    else
 
2084
                        d->highlightYAnimator->to = d->currentItem->itemY();
 
2085
                }
 
2086
            }
 
2087
        }
 
2088
    }
 
2089
 
 
2090
    d->inViewportMoved = false;
 
2091
}
 
2092
 
 
2093
void QQuickGridView::keyPressEvent(QKeyEvent *event)
 
2094
{
 
2095
    Q_D(QQuickGridView);
 
2096
    if (d->model && d->model->count() && d->interactive) {
 
2097
        d->moveReason = QQuickGridViewPrivate::SetIndex;
 
2098
        int oldCurrent = currentIndex();
 
2099
        switch (event->key()) {
 
2100
        case Qt::Key_Up:
 
2101
            moveCurrentIndexUp();
 
2102
            break;
 
2103
        case Qt::Key_Down:
 
2104
            moveCurrentIndexDown();
 
2105
            break;
 
2106
        case Qt::Key_Left:
 
2107
            moveCurrentIndexLeft();
 
2108
            break;
 
2109
        case Qt::Key_Right:
 
2110
            moveCurrentIndexRight();
 
2111
            break;
 
2112
        default:
 
2113
            break;
 
2114
        }
 
2115
        if (oldCurrent != currentIndex() || d->wrap) {
 
2116
            event->accept();
 
2117
            return;
 
2118
        }
 
2119
    }
 
2120
    event->ignore();
 
2121
    QQuickItemView::keyPressEvent(event);
 
2122
}
 
2123
 
 
2124
void QQuickGridView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
 
2125
{
 
2126
    Q_D(QQuickGridView);
 
2127
    d->resetColumns();
 
2128
 
 
2129
    if (newGeometry.width() != oldGeometry.width()
 
2130
            && newGeometry.height() != oldGeometry.height()) {
 
2131
        d->setPosition(d->position());
 
2132
    } else if (newGeometry.width() != oldGeometry.width()) {
 
2133
        QQuickFlickable::setContentX(d->contentXForPosition(d->position()));
 
2134
    } else if (newGeometry.height() != oldGeometry.height()) {
 
2135
        QQuickFlickable::setContentY(d->contentYForPosition(d->position()));
 
2136
    }
 
2137
 
 
2138
    QQuickItemView::geometryChanged(newGeometry, oldGeometry);
 
2139
}
 
2140
 
 
2141
void QQuickGridView::initItem(int index, QObject *obj)
 
2142
{
 
2143
    QQuickItemView::initItem(index, obj);
 
2144
 
 
2145
    // setting the view from the FxViewItem wrapper is too late if the delegate
 
2146
    // needs access to the view in Component.onCompleted
 
2147
    QQuickItem *item = qmlobject_cast<QQuickItem*>(obj);
 
2148
    if (item) {
 
2149
        QQuickGridViewAttached *attached = static_cast<QQuickGridViewAttached *>(
 
2150
                qmlAttachedPropertiesObject<QQuickGridView>(item));
 
2151
        if (attached)
 
2152
            attached->setView(this);
 
2153
    }
 
2154
}
 
2155
 
 
2156
/*!
 
2157
    \qmlmethod QtQuick::GridView::moveCurrentIndexUp()
 
2158
 
 
2159
    Move the currentIndex up one item in the view.
 
2160
    The current index will wrap if keyNavigationWraps is true and it
 
2161
    is currently at the end. This method has no effect if the \l count is zero.
 
2162
 
 
2163
    \b Note: methods should only be called after the Component has completed.
 
2164
*/
 
2165
 
 
2166
 
 
2167
void QQuickGridView::moveCurrentIndexUp()
 
2168
{
 
2169
    Q_D(QQuickGridView);
 
2170
    const int count = d->model ? d->model->count() : 0;
 
2171
    if (!count)
 
2172
        return;
 
2173
    if (d->verticalLayoutDirection == QQuickItemView::TopToBottom) {
 
2174
        if (d->flow == QQuickGridView::FlowLeftToRight) {
 
2175
            if (currentIndex() >= d->columns || d->wrap) {
 
2176
                int index = currentIndex() - d->columns;
 
2177
                setCurrentIndex((index >= 0 && index < count) ? index : count-1);
 
2178
            }
 
2179
        } else {
 
2180
            if (currentIndex() > 0 || d->wrap) {
 
2181
                int index = currentIndex() - 1;
 
2182
                setCurrentIndex((index >= 0 && index < count) ? index : count-1);
 
2183
            }
 
2184
        }
 
2185
    } else {
 
2186
        if (d->flow == QQuickGridView::FlowLeftToRight) {
 
2187
            if (currentIndex() < count - d->columns || d->wrap) {
 
2188
                int index = currentIndex()+d->columns;
 
2189
                setCurrentIndex((index >= 0 && index < count) ? index : 0);
 
2190
            }
 
2191
        } else {
 
2192
            if (currentIndex() < count - 1 || d->wrap) {
 
2193
                int index = currentIndex() + 1;
 
2194
                setCurrentIndex((index >= 0 && index < count) ? index : 0);
 
2195
            }
 
2196
        }
 
2197
    }
 
2198
}
 
2199
 
 
2200
/*!
 
2201
    \qmlmethod QtQuick::GridView::moveCurrentIndexDown()
 
2202
 
 
2203
    Move the currentIndex down one item in the view.
 
2204
    The current index will wrap if keyNavigationWraps is true and it
 
2205
    is currently at the end. This method has no effect if the \l count is zero.
 
2206
 
 
2207
    \b Note: methods should only be called after the Component has completed.
 
2208
*/
 
2209
void QQuickGridView::moveCurrentIndexDown()
 
2210
{
 
2211
    Q_D(QQuickGridView);
 
2212
    const int count = d->model ? d->model->count() : 0;
 
2213
    if (!count)
 
2214
        return;
 
2215
 
 
2216
    if (d->verticalLayoutDirection == QQuickItemView::TopToBottom) {
 
2217
        if (d->flow == QQuickGridView::FlowLeftToRight) {
 
2218
            if (currentIndex() < count - d->columns || d->wrap) {
 
2219
                int index = currentIndex()+d->columns;
 
2220
                setCurrentIndex((index >= 0 && index < count) ? index : 0);
 
2221
            }
 
2222
        } else {
 
2223
            if (currentIndex() < count - 1 || d->wrap) {
 
2224
                int index = currentIndex() + 1;
 
2225
                setCurrentIndex((index >= 0 && index < count) ? index : 0);
 
2226
            }
 
2227
        }
 
2228
    } else {
 
2229
        if (d->flow == QQuickGridView::FlowLeftToRight) {
 
2230
            if (currentIndex() >= d->columns || d->wrap) {
 
2231
                int index = currentIndex() - d->columns;
 
2232
                setCurrentIndex((index >= 0 && index < count) ? index : count-1);
 
2233
            }
 
2234
        } else {
 
2235
            if (currentIndex() > 0 || d->wrap) {
 
2236
                int index = currentIndex() - 1;
 
2237
                setCurrentIndex((index >= 0 && index < count) ? index : count-1);
 
2238
            }
 
2239
        }
 
2240
    }
 
2241
}
 
2242
 
 
2243
/*!
 
2244
    \qmlmethod QtQuick::GridView::moveCurrentIndexLeft()
 
2245
 
 
2246
    Move the currentIndex left one item in the view.
 
2247
    The current index will wrap if keyNavigationWraps is true and it
 
2248
    is currently at the end. This method has no effect if the \l count is zero.
 
2249
 
 
2250
    \b Note: methods should only be called after the Component has completed.
 
2251
*/
 
2252
void QQuickGridView::moveCurrentIndexLeft()
 
2253
{
 
2254
    Q_D(QQuickGridView);
 
2255
    const int count = d->model ? d->model->count() : 0;
 
2256
    if (!count)
 
2257
        return;
 
2258
    if (effectiveLayoutDirection() == Qt::LeftToRight) {
 
2259
        if (d->flow == QQuickGridView::FlowLeftToRight) {
 
2260
            if (currentIndex() > 0 || d->wrap) {
 
2261
                int index = currentIndex() - 1;
 
2262
                setCurrentIndex((index >= 0 && index < count) ? index : count-1);
 
2263
            }
 
2264
        } else {
 
2265
            if (currentIndex() >= d->columns || d->wrap) {
 
2266
                int index = currentIndex() - d->columns;
 
2267
                setCurrentIndex((index >= 0 && index < count) ? index : count-1);
 
2268
            }
 
2269
        }
 
2270
    } else {
 
2271
        if (d->flow == QQuickGridView::FlowLeftToRight) {
 
2272
            if (currentIndex() < count - 1 || d->wrap) {
 
2273
                int index = currentIndex() + 1;
 
2274
                setCurrentIndex((index >= 0 && index < count) ? index : 0);
 
2275
            }
 
2276
        } else {
 
2277
            if (currentIndex() < count - d->columns || d->wrap) {
 
2278
                int index = currentIndex() + d->columns;
 
2279
                setCurrentIndex((index >= 0 && index < count) ? index : 0);
 
2280
            }
 
2281
        }
 
2282
    }
 
2283
}
 
2284
 
 
2285
 
 
2286
/*!
 
2287
    \qmlmethod QtQuick::GridView::moveCurrentIndexRight()
 
2288
 
 
2289
    Move the currentIndex right one item in the view.
 
2290
    The current index will wrap if keyNavigationWraps is true and it
 
2291
    is currently at the end. This method has no effect if the \l count is zero.
 
2292
 
 
2293
    \b Note: methods should only be called after the Component has completed.
 
2294
*/
 
2295
void QQuickGridView::moveCurrentIndexRight()
 
2296
{
 
2297
    Q_D(QQuickGridView);
 
2298
    const int count = d->model ? d->model->count() : 0;
 
2299
    if (!count)
 
2300
        return;
 
2301
    if (effectiveLayoutDirection() == Qt::LeftToRight) {
 
2302
        if (d->flow == QQuickGridView::FlowLeftToRight) {
 
2303
            if (currentIndex() < count - 1 || d->wrap) {
 
2304
                int index = currentIndex() + 1;
 
2305
                setCurrentIndex((index >= 0 && index < count) ? index : 0);
 
2306
            }
 
2307
        } else {
 
2308
            if (currentIndex() < count - d->columns || d->wrap) {
 
2309
                int index = currentIndex()+d->columns;
 
2310
                setCurrentIndex((index >= 0 && index < count) ? index : 0);
 
2311
            }
 
2312
        }
 
2313
    } else {
 
2314
        if (d->flow == QQuickGridView::FlowLeftToRight) {
 
2315
            if (currentIndex() > 0 || d->wrap) {
 
2316
                int index = currentIndex() - 1;
 
2317
                setCurrentIndex((index >= 0 && index < count) ? index : count-1);
 
2318
            }
 
2319
        } else {
 
2320
            if (currentIndex() >= d->columns || d->wrap) {
 
2321
                int index = currentIndex() - d->columns;
 
2322
                setCurrentIndex((index >= 0 && index < count) ? index : count-1);
 
2323
            }
 
2324
        }
 
2325
    }
 
2326
}
 
2327
 
 
2328
bool QQuickGridViewPrivate::applyInsertionChange(const QQmlChangeSet::Insert &change, ChangeResult *insertResult, QList<FxViewItem *> *addedItems, QList<MovedItem> *movingIntoView)
 
2329
{
 
2330
    Q_Q(QQuickGridView);
 
2331
 
 
2332
    int modelIndex = change.index;
 
2333
    int count = change.count;
 
2334
 
 
2335
    int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;
 
2336
 
 
2337
    if (index < 0) {
 
2338
        int i = visibleItems.count() - 1;
 
2339
        while (i > 0 && visibleItems.at(i)->index == -1)
 
2340
            --i;
 
2341
        if (visibleItems.at(i)->index + 1 == modelIndex) {
 
2342
            // Special case of appending an item to the model.
 
2343
            index = visibleItems.count();
 
2344
        } else {
 
2345
            if (modelIndex <= visibleIndex) {
 
2346
                // Insert before visible items
 
2347
                visibleIndex += count;
 
2348
                for (int i = 0; i < visibleItems.count(); ++i) {
 
2349
                    FxViewItem *item = visibleItems.at(i);
 
2350
                    if (item->index != -1 && item->index >= modelIndex)
 
2351
                        item->index += count;
 
2352
                }
 
2353
            }
 
2354
            return true;
 
2355
        }
 
2356
    }
 
2357
 
 
2358
    qreal tempPos = isContentFlowReversed() ? -position()-size()+q->width()+1 : position();
 
2359
    qreal colPos = 0;
 
2360
    qreal rowPos = 0;
 
2361
    int colNum = 0;
 
2362
    if (visibleItems.count()) {
 
2363
        if (index < visibleItems.count()) {
 
2364
            FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.at(index));
 
2365
            colPos = gridItem->colPos();
 
2366
            rowPos = gridItem->rowPos();
 
2367
            colNum = qFloor((colPos+colSize()/2) / colSize());
 
2368
        } else {
 
2369
            // appending items to visible list
 
2370
            FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.at(index-1));
 
2371
            rowPos = gridItem->rowPos();
 
2372
            colNum = qFloor((gridItem->colPos()+colSize()/2) / colSize());
 
2373
            if (++colNum >= columns) {
 
2374
                colNum = 0;
 
2375
                rowPos += rowSize();
 
2376
            }
 
2377
            colPos = colNum * colSize();
 
2378
        }
 
2379
    }
 
2380
 
 
2381
    // Update the indexes of the following visible items.
 
2382
    for (int i = 0; i < visibleItems.count(); ++i) {
 
2383
        FxViewItem *item = visibleItems.at(i);
 
2384
        if (item->index != -1 && item->index >= modelIndex) {
 
2385
            item->index += count;
 
2386
            if (change.isMove())
 
2387
                item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::MoveTransition, false);
 
2388
            else
 
2389
                item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, false);
 
2390
        }
 
2391
    }
 
2392
 
 
2393
    int prevVisibleCount = visibleItems.count();
 
2394
    if (insertResult->visiblePos.isValid() && rowPos < insertResult->visiblePos) {
 
2395
        // Insert items before the visible item.
 
2396
        int insertionIdx = index;
 
2397
        int i = count - 1;
 
2398
        int from = tempPos - buffer - displayMarginBeginning;
 
2399
 
 
2400
        while (i >= 0) {
 
2401
            if (rowPos > from && insertionIdx < visibleIndex) {
 
2402
                // item won't be visible, just note the size for repositioning
 
2403
                insertResult->countChangeBeforeVisible++;
 
2404
            } else {
 
2405
                // item is before first visible e.g. in cache buffer
 
2406
                FxViewItem *item = 0;
 
2407
                if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
 
2408
                    item->index = modelIndex + i;
 
2409
                if (!item)
 
2410
                    item = createItem(modelIndex + i);
 
2411
                if (!item)
 
2412
                    return false;
 
2413
 
 
2414
                QQuickItemPrivate::get(item->item)->setCulled(false);
 
2415
                visibleItems.insert(insertionIdx, item);
 
2416
                if (insertionIdx == 0)
 
2417
                    insertResult->changedFirstItem = true;
 
2418
                if (!change.isMove()) {
 
2419
                    addedItems->append(item);
 
2420
                    item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
 
2421
                }
 
2422
                insertResult->sizeChangesBeforeVisiblePos += rowSize();
 
2423
            }
 
2424
 
 
2425
            if (--colNum < 0 ) {
 
2426
                colNum = columns - 1;
 
2427
                rowPos -= rowSize();
 
2428
            }
 
2429
            colPos = colNum * colSize();
 
2430
            index++;
 
2431
            i--;
 
2432
        }
 
2433
    } else {
 
2434
        int i = 0;
 
2435
        int to = buffer+displayMarginEnd+tempPos+size()-1;
 
2436
        while (i < count && rowPos <= to + rowSize()*(columns - colNum)/qreal(columns+1)) {
 
2437
            FxViewItem *item = 0;
 
2438
            if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i))))
 
2439
                item->index = modelIndex + i;
 
2440
            bool newItem = !item;
 
2441
            if (!item)
 
2442
                item = createItem(modelIndex + i);
 
2443
            if (!item)
 
2444
                return false;
 
2445
 
 
2446
            QQuickItemPrivate::get(item->item)->setCulled(false);
 
2447
            visibleItems.insert(index, item);
 
2448
            if (index == 0)
 
2449
                insertResult->changedFirstItem = true;
 
2450
            if (change.isMove()) {
 
2451
                // we know this is a move target, since move displaced items that are
 
2452
                // shuffled into view due to a move would be added in refill()
 
2453
                if (newItem && transitioner && transitioner->canTransition(QQuickItemViewTransitioner::MoveTransition, true))
 
2454
                    movingIntoView->append(MovedItem(item, change.moveKey(item->index)));
 
2455
            } else {
 
2456
                addedItems->append(item);
 
2457
                item->transitionNextReposition(transitioner, QQuickItemViewTransitioner::AddTransition, true);
 
2458
            }
 
2459
            insertResult->sizeChangesAfterVisiblePos += rowSize();
 
2460
 
 
2461
            if (++colNum >= columns) {
 
2462
                colNum = 0;
 
2463
                rowPos += rowSize();
 
2464
            }
 
2465
            colPos = colNum * colSize();
 
2466
            ++index;
 
2467
            ++i;
 
2468
        }
 
2469
    }
 
2470
 
 
2471
    updateVisibleIndex();
 
2472
 
 
2473
    return visibleItems.count() > prevVisibleCount;
 
2474
}
 
2475
 
 
2476
void QQuickGridViewPrivate::translateAndTransitionItemsAfter(int afterModelIndex, const ChangeResult &insertionResult, const ChangeResult &removalResult)
 
2477
{
 
2478
    if (!transitioner)
 
2479
        return;
 
2480
 
 
2481
    int markerItemIndex = -1;
 
2482
    for (int i=0; i<visibleItems.count(); i++) {
 
2483
        if (visibleItems[i]->index == afterModelIndex) {
 
2484
            markerItemIndex = i;
 
2485
            break;
 
2486
        }
 
2487
    }
 
2488
    if (markerItemIndex < 0)
 
2489
        return;
 
2490
 
 
2491
    const qreal viewEndPos = isContentFlowReversed() ? -position() : position() + size();
 
2492
    int countItemsRemoved = -(removalResult.sizeChangesAfterVisiblePos / rowSize());
 
2493
 
 
2494
    // account for whether first item has changed if < 1 row was removed before visible
 
2495
    int changeBeforeVisible = insertionResult.countChangeBeforeVisible - removalResult.countChangeBeforeVisible;
 
2496
    if (changeBeforeVisible != 0)
 
2497
        countItemsRemoved += (changeBeforeVisible % columns) - (columns - 1);
 
2498
 
 
2499
    countItemsRemoved -= removalResult.countChangeAfterVisibleItems;
 
2500
 
 
2501
    for (int i=markerItemIndex+1; i<visibleItems.count() && visibleItems.at(i)->position() < viewEndPos; i++) {
 
2502
        FxGridItemSG *gridItem = static_cast<FxGridItemSG *>(visibleItems[i]);
 
2503
        if (!gridItem->transitionScheduledOrRunning()) {
 
2504
            qreal origRowPos = gridItem->colPos();
 
2505
            qreal origColPos = gridItem->rowPos();
 
2506
            int indexDiff = gridItem->index - countItemsRemoved;
 
2507
            gridItem->setPosition((indexDiff % columns) * colSize(), (indexDiff / columns) * rowSize());
 
2508
            gridItem->transitionNextReposition(transitioner, QQuickItemViewTransitioner::RemoveTransition, false);
 
2509
            gridItem->setPosition(origRowPos, origColPos);
 
2510
        }
 
2511
    }
 
2512
}
 
2513
 
 
2514
bool QQuickGridViewPrivate::needsRefillForAddedOrRemovedIndex(int modelIndex) const
 
2515
{
 
2516
    // If we add or remove items before visible items, a layout may be
 
2517
    // required to ensure item 0 is in the first column.
 
2518
    return modelIndex < visibleIndex;
 
2519
}
 
2520
 
 
2521
/*!
 
2522
    \qmlmethod QtQuick::GridView::positionViewAtIndex(int index, PositionMode mode)
 
2523
 
 
2524
    Positions the view such that the \a index is at the position specified by
 
2525
    \a mode:
 
2526
 
 
2527
    \list
 
2528
    \li GridView.Beginning - position item at the top (or left for \c GridView.FlowTopToBottom flow) of the view.
 
2529
    \li GridView.Center - position item in the center of the view.
 
2530
    \li GridView.End - position item at bottom (or right for horizontal orientation) of the view.
 
2531
    \li GridView.Visible - if any part of the item is visible then take no action, otherwise
 
2532
    bring the item into view.
 
2533
    \li GridView.Contain - ensure the entire item is visible.  If the item is larger than
 
2534
    the view the item is positioned at the top (or left for \c GridView.FlowTopToBottom flow) of the view.
 
2535
    \li GridView.SnapPosition - position the item at \l preferredHighlightBegin.  This mode
 
2536
    is only valid if \l highlightRangeMode is StrictlyEnforceRange or snapping is enabled
 
2537
    via \l snapMode.
 
2538
    \endlist
 
2539
 
 
2540
    If positioning the view at the index would cause empty space to be displayed at
 
2541
    the beginning or end of the view, the view will be positioned at the boundary.
 
2542
 
 
2543
    It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
 
2544
    at a particular index.  This is unreliable since removing items from the start
 
2545
    of the view does not cause all other items to be repositioned.
 
2546
    The correct way to bring an item into view is with \c positionViewAtIndex.
 
2547
 
 
2548
    \b Note: methods should only be called after the Component has completed.  To position
 
2549
    the view at startup, this method should be called by Component.onCompleted.  For
 
2550
    example, to position the view at the end:
 
2551
 
 
2552
    \code
 
2553
    Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
 
2554
    \endcode
 
2555
*/
 
2556
 
 
2557
/*!
 
2558
    \qmlmethod QtQuick::GridView::positionViewAtBeginning()
 
2559
    \qmlmethod QtQuick::GridView::positionViewAtEnd()
 
2560
 
 
2561
    Positions the view at the beginning or end, taking into account any header or footer.
 
2562
 
 
2563
    It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
 
2564
    at a particular index.  This is unreliable since removing items from the start
 
2565
    of the list does not cause all other items to be repositioned, and because
 
2566
    the actual start of the view can vary based on the size of the delegates.
 
2567
 
 
2568
    \b Note: methods should only be called after the Component has completed.  To position
 
2569
    the view at startup, this method should be called by Component.onCompleted.  For
 
2570
    example, to position the view at the end on startup:
 
2571
 
 
2572
    \code
 
2573
    Component.onCompleted: positionViewAtEnd()
 
2574
    \endcode
 
2575
*/
 
2576
 
 
2577
/*!
 
2578
    \qmlmethod int QtQuick::GridView::indexAt(int x, int y)
 
2579
 
 
2580
    Returns the index of the visible item containing the point \a x, \a y in content
 
2581
    coordinates.  If there is no item at the point specified, or the item is
 
2582
    not visible -1 is returned.
 
2583
 
 
2584
    If the item is outside the visible area, -1 is returned, regardless of
 
2585
    whether an item will exist at that point when scrolled into view.
 
2586
 
 
2587
    \b Note: methods should only be called after the Component has completed.
 
2588
*/
 
2589
 
 
2590
/*!
 
2591
    \qmlmethod Item QtQuick::GridView::itemAt(int x, int y)
 
2592
 
 
2593
    Returns the visible item containing the point \a x, \a y in content
 
2594
    coordinates.  If there is no item at the point specified, or the item is
 
2595
    not visible null is returned.
 
2596
 
 
2597
    If the item is outside the visible area, null is returned, regardless of
 
2598
    whether an item will exist at that point when scrolled into view.
 
2599
 
 
2600
    \b Note: methods should only be called after the Component has completed.
 
2601
*/
 
2602
 
 
2603
 
 
2604
/*!
 
2605
    \qmlmethod QtQuick::GridView::forceLayout()
 
2606
 
 
2607
    Responding to changes in the model is usually batched to happen only once
 
2608
    per frame. This means that inside script blocks it is possible for the
 
2609
    underlying model to have changed, but the GridView has not caught up yet.
 
2610
 
 
2611
    This method forces the GridView to immediately respond to any outstanding
 
2612
    changes in the model.
 
2613
 
 
2614
    \since 5.1
 
2615
 
 
2616
    \b Note: methods should only be called after the Component has completed.
 
2617
*/
 
2618
 
 
2619
QQuickGridViewAttached *QQuickGridView::qmlAttachedProperties(QObject *obj)
 
2620
{
 
2621
    return new QQuickGridViewAttached(obj);
 
2622
}
 
2623
 
 
2624
QT_END_NAMESPACE