aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/items/qquickgridview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/items/qquickgridview.cpp')
-rw-r--r--src/declarative/items/qquickgridview.cpp1958
1 files changed, 0 insertions, 1958 deletions
diff --git a/src/declarative/items/qquickgridview.cpp b/src/declarative/items/qquickgridview.cpp
deleted file mode 100644
index 44e1f14c6f..0000000000
--- a/src/declarative/items/qquickgridview.cpp
+++ /dev/null
@@ -1,1958 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qquickgridview_p.h"
-#include "qquickvisualitemmodel_p.h"
-#include "qquickflickable_p_p.h"
-#include "qquickitemview_p_p.h"
-
-#include <private/qdeclarativesmoothedanimation_p_p.h>
-#include <private/qlistmodelinterface_p.h>
-
-#include <QtGui/qevent.h>
-#include <QtCore/qmath.h>
-#include <QtCore/qcoreapplication.h>
-#include <math.h>
-#include "qplatformdefs.h"
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QML_FLICK_SNAPONETHRESHOLD
-#define QML_FLICK_SNAPONETHRESHOLD 30
-#endif
-
-//----------------------------------------------------------------------------
-
-class FxGridItemSG : public FxViewItem
-{
-public:
- FxGridItemSG(QQuickItem *i, QQuickGridView *v, bool own) : FxViewItem(i, own), view(v) {
- attached = static_cast<QQuickGridViewAttached*>(qmlAttachedPropertiesObject<QQuickGridView>(item));
- if (attached)
- static_cast<QQuickGridViewAttached*>(attached)->setView(view);
- }
-
- ~FxGridItemSG() {}
-
- qreal position() const {
- return rowPos();
- }
-
- qreal endPosition() const {
- return endRowPos();
- }
-
- qreal size() const {
- return view->flow() == QQuickGridView::LeftToRight ? view->cellHeight() : view->cellWidth();
- }
-
- qreal sectionSize() const {
- return 0.0;
- }
-
- qreal rowPos() const {
- if (view->flow() == QQuickGridView::LeftToRight)
- return item->y();
- else
- return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -view->cellWidth()-item->x() : item->x());
- }
-
- qreal colPos() const {
- if (view->flow() == QQuickGridView::LeftToRight) {
- if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
- qreal colSize = view->cellWidth();
- int columns = view->width()/colSize;
- return colSize * (columns-1) - item->x();
- } else {
- return item->x();
- }
- } else {
- return item->y();
- }
- }
- qreal endRowPos() const {
- if (view->flow() == QQuickGridView::LeftToRight) {
- return item->y() + view->cellHeight();
- } else {
- if (view->effectiveLayoutDirection() == Qt::RightToLeft)
- return -item->x();
- else
- return item->x() + view->cellWidth();
- }
- }
- void setPosition(qreal col, qreal row) {
- if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
- if (view->flow() == QQuickGridView::LeftToRight) {
- int columns = view->width()/view->cellWidth();
- item->setPos(QPointF((view->cellWidth() * (columns-1) - col), row));
- } else {
- item->setPos(QPointF(-view->cellWidth()-row, col));
- }
- } else {
- if (view->flow() == QQuickGridView::LeftToRight)
- item->setPos(QPointF(col, row));
- else
- item->setPos(QPointF(row, col));
- }
- }
- bool contains(qreal x, qreal y) const {
- return (x >= item->x() && x < item->x() + view->cellWidth() &&
- y >= item->y() && y < item->y() + view->cellHeight());
- }
-
- QQuickGridView *view;
-};
-
-//----------------------------------------------------------------------------
-
-class QQuickGridViewPrivate : public QQuickItemViewPrivate
-{
- Q_DECLARE_PUBLIC(QQuickGridView)
-
-public:
- virtual Qt::Orientation layoutOrientation() const;
- virtual bool isContentFlowReversed() const;
- bool isRightToLeftTopToBottom() const;
-
- virtual qreal positionAt(int index) const;
- virtual qreal endPositionAt(int index) const;
- virtual qreal originPosition() const;
- virtual qreal lastPosition() const;
-
- qreal rowSize() const;
- qreal colSize() const;
- qreal colPosAt(int modelIndex) const;
- qreal rowPosAt(int modelIndex) const;
- qreal snapPosAt(qreal pos) const;
- FxViewItem *snapItemAt(qreal pos) const;
- int snapIndex() const;
-
- virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer);
- virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
- virtual void visibleItemsChanged();
-
- virtual FxViewItem *newViewItem(int index, QQuickItem *item);
- virtual void repositionPackageItemAt(QQuickItem *item, int index);
- virtual void resetItemPosition(FxViewItem *item, FxViewItem *toItem);
- virtual void resetFirstItemPosition();
- virtual void moveItemBy(FxViewItem *item, qreal forwards, qreal backwards);
-
- virtual void createHighlight();
- virtual void updateHighlight();
- virtual void resetHighlightPosition();
-
- virtual void setPosition(qreal pos);
- virtual void layoutVisibleItems();
- bool applyInsertionChange(const QDeclarativeChangeSet::Insert &, FxViewItem *, InsertionsResult *);
- virtual bool needsRefillForAddedOrRemovedIndex(int index) const;
-
- virtual qreal headerSize() const;
- virtual qreal footerSize() const;
- virtual bool showHeaderForIndex(int index) const;
- virtual bool showFooterForIndex(int index) const;
- virtual void updateHeader();
- virtual void updateFooter();
-
- virtual void changedVisibleIndex(int newIndex);
- virtual void initializeCurrentItem();
-
- virtual void updateViewport();
- virtual void itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
- virtual void fixupPosition();
- virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
- virtual void flick(QQuickItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
- QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
-
- QQuickGridView::Flow flow;
- qreal cellWidth;
- qreal cellHeight;
- int columns;
- QQuickGridView::SnapMode snapMode;
-
- QSmoothedAnimation *highlightXAnimator;
- QSmoothedAnimation *highlightYAnimator;
-
- QQuickGridViewPrivate()
- : flow(QQuickGridView::LeftToRight)
- , cellWidth(100), cellHeight(100), columns(1)
- , snapMode(QQuickGridView::NoSnap)
- , highlightXAnimator(0), highlightYAnimator(0)
- {}
-};
-
-Qt::Orientation QQuickGridViewPrivate::layoutOrientation() const
-{
- return flow == QQuickGridView::LeftToRight ? Qt::Vertical : Qt::Horizontal;
-}
-
-bool QQuickGridViewPrivate::isContentFlowReversed() const
-{
- return isRightToLeftTopToBottom();
-}
-
-bool QQuickGridViewPrivate::isRightToLeftTopToBottom() const
-{
- Q_Q(const QQuickGridView);
- return flow == QQuickGridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
-}
-
-void QQuickGridViewPrivate::changedVisibleIndex(int newIndex)
-{
- visibleIndex = newIndex / columns * columns;
-}
-
-void QQuickGridViewPrivate::setPosition(qreal pos)
-{
- Q_Q(QQuickGridView);
- if (flow == QQuickGridView::LeftToRight) {
- q->QQuickFlickable::setContentY(pos);
- q->QQuickFlickable::setContentX(0);
- } else {
- if (q->effectiveLayoutDirection() == Qt::LeftToRight)
- q->QQuickFlickable::setContentX(pos);
- else
- q->QQuickFlickable::setContentX(-pos-size());
- q->QQuickFlickable::setContentY(0);
- }
-}
-
-qreal QQuickGridViewPrivate::originPosition() const
-{
- qreal pos = 0;
- if (!visibleItems.isEmpty())
- pos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
- return pos;
-}
-
-qreal QQuickGridViewPrivate::lastPosition() const
-{
- qreal pos = 0;
- if (model && model->count()) {
- // get end position of last item
- pos = (rowPosAt(model->count() - 1) + rowSize());
- }
- return pos;
-}
-
-qreal QQuickGridViewPrivate::positionAt(int index) const
-{
- return rowPosAt(index);
-}
-
-qreal QQuickGridViewPrivate::endPositionAt(int index) const
-{
- return rowPosAt(index) + rowSize();
-}
-
-qreal QQuickGridViewPrivate::rowSize() const {
- return flow == QQuickGridView::LeftToRight ? cellHeight : cellWidth;
-}
-qreal QQuickGridViewPrivate::colSize() const {
- return flow == QQuickGridView::LeftToRight ? cellWidth : cellHeight;
-}
-
-qreal QQuickGridViewPrivate::colPosAt(int modelIndex) const
-{
- if (FxViewItem *item = visibleItem(modelIndex))
- return static_cast<FxGridItemSG*>(item)->colPos();
- if (!visibleItems.isEmpty()) {
- if (modelIndex == visibleIndex) {
- FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
- return firstItem->colPos();
- } else if (modelIndex < visibleIndex) {
- int count = (visibleIndex - modelIndex) % columns;
- int col = static_cast<FxGridItemSG*>(visibleItems.first())->colPos() / colSize();
- col = (columns - count + col) % columns;
- return col * colSize();
- } else {
- int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
- return static_cast<FxGridItemSG*>(visibleItems.last())->colPos() - count * colSize();
- }
- }
- return (modelIndex % columns) * colSize();
-}
-
-qreal QQuickGridViewPrivate::rowPosAt(int modelIndex) const
-{
- if (FxViewItem *item = visibleItem(modelIndex))
- return static_cast<FxGridItemSG*>(item)->rowPos();
- if (!visibleItems.isEmpty()) {
- if (modelIndex == visibleIndex) {
- FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
- return firstItem->rowPos();
- } else if (modelIndex < visibleIndex) {
- FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
- int firstCol = firstItem->colPos() / colSize();
- int col = visibleIndex - modelIndex + (columns - firstCol - 1);
- int rows = col / columns;
- return firstItem->rowPos() - rows * rowSize();
- } else {
- FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
- int count = modelIndex - lastItem->index;
- int col = lastItem->colPos() + count * colSize();
- int rows = col / (columns * colSize());
- return lastItem->rowPos() + rows * rowSize();
- }
- }
- return (modelIndex / columns) * rowSize();
-}
-
-
-qreal QQuickGridViewPrivate::snapPosAt(qreal pos) const
-{
- Q_Q(const QQuickGridView);
- qreal snapPos = 0;
- if (!visibleItems.isEmpty()) {
- qreal highlightStart = highlightRangeStart;
- pos += highlightStart;
- pos += rowSize()/2;
- snapPos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
- snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
- snapPos -= highlightStart;
- qreal maxExtent;
- qreal minExtent;
- if (isRightToLeftTopToBottom()) {
- maxExtent = q->minXExtent()-size();
- minExtent = q->maxXExtent()-size();
- } else {
- maxExtent = flow == QQuickGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
- minExtent = flow == QQuickGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
- }
- if (snapPos > maxExtent)
- snapPos = maxExtent;
- if (snapPos < minExtent)
- snapPos = minExtent;
- }
- return snapPos;
-}
-
-FxViewItem *QQuickGridViewPrivate::snapItemAt(qreal pos) const
-{
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxViewItem *item = visibleItems.at(i);
- if (item->index == -1)
- continue;
- qreal itemTop = item->position();
- if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
- return item;
- }
- return 0;
-}
-
-int QQuickGridViewPrivate::snapIndex() const
-{
- int index = currentIndex;
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
- if (item->index == -1)
- continue;
- qreal itemTop = item->position();
- FxGridItemSG *hItem = static_cast<FxGridItemSG*>(highlight);
- if (itemTop >= hItem->rowPos()-rowSize()/2 && itemTop < hItem->rowPos()+rowSize()/2) {
- index = item->index;
- if (item->colPos() >= hItem->colPos()-colSize()/2 && item->colPos() < hItem->colPos()+colSize()/2)
- return item->index;
- }
- }
- return index;
-}
-
-FxViewItem *QQuickGridViewPrivate::newViewItem(int modelIndex, QQuickItem *item)
-{
- Q_Q(QQuickGridView);
- Q_UNUSED(modelIndex);
- return new FxGridItemSG(item, q, false);
-}
-
-bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer)
-{
- qreal colPos = colPosAt(visibleIndex);
- qreal rowPos = rowPosAt(visibleIndex);
- if (visibleItems.count()) {
- FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
- rowPos = lastItem->rowPos();
- int colNum = qFloor((lastItem->colPos()+colSize()/2) / colSize());
- if (++colNum >= columns) {
- colNum = 0;
- rowPos += rowSize();
- }
- colPos = colNum * colSize();
- }
-
- int modelIndex = findLastVisibleIndex();
- modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
-
- if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
- || fillTo < rowPosAt(visibleIndex) - rowSize())) {
- // We've jumped more than a page. Estimate which items are now
- // visible and fill from there.
- int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
- for (int i = 0; i < visibleItems.count(); ++i)
- releaseItem(visibleItems.at(i));
- visibleItems.clear();
- modelIndex += count;
- if (modelIndex >= model->count())
- modelIndex = model->count() - 1;
- else if (modelIndex < 0)
- modelIndex = 0;
- modelIndex = modelIndex / columns * columns;
- visibleIndex = modelIndex;
- colPos = colPosAt(visibleIndex);
- rowPos = rowPosAt(visibleIndex);
- }
-
- int colNum = qFloor((colPos+colSize()/2) / colSize());
- FxGridItemSG *item = 0;
- bool changed = false;
-
- while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) {
-// qDebug() << "refill: append item" << modelIndex << colPos << rowPos;
- if (!(item = static_cast<FxGridItemSG*>(createItem(modelIndex, doBuffer))))
- break;
- item->setPosition(colPos, rowPos);
- item->item->setVisible(!doBuffer);
- visibleItems.append(item);
- if (++colNum >= columns) {
- colNum = 0;
- rowPos += rowSize();
- }
- colPos = colNum * colSize();
- ++modelIndex;
- changed = true;
- }
-
- // Find first column
- if (visibleItems.count()) {
- FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
- rowPos = firstItem->rowPos();
- colNum = qFloor((firstItem->colPos()+colSize()/2) / colSize());
- if (--colNum < 0) {
- colNum = columns - 1;
- rowPos -= rowSize();
- }
- } else {
- colNum = qFloor((colPos+colSize()/2) / colSize());
- }
-
- // Prepend
- colPos = colNum * colSize();
- while (visibleIndex > 0 && rowPos + rowSize() - 1 >= fillFrom - rowSize()*(colNum+1)/(columns+1)){
-// qDebug() << "refill: prepend item" << visibleIndex-1 << "top pos" << rowPos << colPos;
- if (!(item = static_cast<FxGridItemSG*>(createItem(visibleIndex-1, doBuffer))))
- break;
- --visibleIndex;
- item->setPosition(colPos, rowPos);
- item->item->setVisible(!doBuffer);
- visibleItems.prepend(item);
- if (--colNum < 0) {
- colNum = columns-1;
- rowPos -= rowSize();
- }
- colPos = colNum * colSize();
- changed = true;
- }
-
- return changed;
-}
-
-bool QQuickGridViewPrivate::removeNonVisibleItems(qreal bufferFrom, qreal bufferTo)
-{
- Q_Q(QQuickGridView);
- FxGridItemSG *item = 0;
- bool changed = false;
-
- while (visibleItems.count() > 1
- && (item = static_cast<FxGridItemSG*>(visibleItems.first()))
- && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
- if (item->attached->delayRemove())
- break;
-// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
- if (item->index != -1)
- visibleIndex++;
- visibleItems.removeFirst();
- releaseItem(item);
- changed = true;
- }
- while (visibleItems.count() > 1
- && (item = static_cast<FxGridItemSG*>(visibleItems.last()))
- && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
- if (item->attached->delayRemove())
- break;
-// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
- visibleItems.removeLast();
- releaseItem(item);
- changed = true;
- }
-
- return changed;
-}
-
-void QQuickGridViewPrivate::visibleItemsChanged()
-{
- updateHeader();
- updateFooter();
- updateViewport();
-}
-
-void QQuickGridViewPrivate::updateViewport()
-{
- Q_Q(QQuickGridView);
- qreal length = flow == QQuickGridView::LeftToRight ? q->width() : q->height();
- columns = (int)qMax((length + colSize()/2) / colSize(), qreal(1.));
- QQuickItemViewPrivate::updateViewport();
-}
-
-void QQuickGridViewPrivate::layoutVisibleItems()
-{
- if (visibleItems.count()) {
- FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
- qreal rowPos = firstItem->rowPos();
- qreal colPos = firstItem->colPos();
- int col = visibleIndex % columns;
- if (colPos != col * colSize()) {
- colPos = col * colSize();
- firstItem->setPosition(colPos, rowPos);
- }
- for (int i = 1; i < visibleItems.count(); ++i) {
- FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
- if (++col >= columns) {
- col = 0;
- rowPos += rowSize();
- }
- colPos = col * colSize();
- item->setPosition(colPos, rowPos);
- }
- }
-}
-
-void QQuickGridViewPrivate::repositionPackageItemAt(QQuickItem *item, int index)
-{
- Q_Q(QQuickGridView);
- qreal pos = position();
- if (flow == QQuickGridView::LeftToRight) {
- if (item->y() + item->height() > pos && item->y() < pos + q->height())
- item->setPos(QPointF(colPosAt(index), rowPosAt(index)));
- } else {
- if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
- if (isRightToLeftTopToBottom())
- item->setPos(QPointF(-rowPosAt(index)-item->width(), colPosAt(index)));
- else
- item->setPos(QPointF(rowPosAt(index), colPosAt(index)));
- }
- }
-}
-
-void QQuickGridViewPrivate::resetItemPosition(FxViewItem *item, FxViewItem *toItem)
-{
- if (item == toItem)
- return;
- FxGridItemSG *toGridItem = static_cast<FxGridItemSG*>(toItem);
- static_cast<FxGridItemSG*>(item)->setPosition(toGridItem->colPos(), toGridItem->rowPos());
-}
-
-void QQuickGridViewPrivate::resetFirstItemPosition()
-{
- FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.first());
- item->setPosition(0, 0);
-}
-
-void QQuickGridViewPrivate::moveItemBy(FxViewItem *item, qreal forwards, qreal backwards)
-{
- int moveCount = (forwards / rowSize()) - (backwards / rowSize());
-
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(item);
- gridItem->setPosition(gridItem->colPos(), gridItem->rowPos() + ((moveCount / columns) * rowSize()));
-}
-
-void QQuickGridViewPrivate::createHighlight()
-{
- Q_Q(QQuickGridView);
- bool changed = false;
- if (highlight) {
- if (trackedItem == highlight)
- trackedItem = 0;
- delete highlight;
- highlight = 0;
-
- delete highlightXAnimator;
- delete highlightYAnimator;
- highlightXAnimator = 0;
- highlightYAnimator = 0;
-
- changed = true;
- }
-
- if (currentItem) {
- QQuickItem *item = createHighlightItem();
- if (item) {
- FxGridItemSG *newHighlight = new FxGridItemSG(item, q, true);
- if (autoHighlight)
- resetHighlightPosition();
- highlightXAnimator = new QSmoothedAnimation(q);
- highlightXAnimator->target = QDeclarativeProperty(item, QLatin1String("x"));
- highlightXAnimator->userDuration = highlightMoveDuration;
- highlightYAnimator = new QSmoothedAnimation(q);
- highlightYAnimator->target = QDeclarativeProperty(item, QLatin1String("y"));
- highlightYAnimator->userDuration = highlightMoveDuration;
-
- highlight = newHighlight;
- changed = true;
- }
- }
- if (changed)
- emit q->highlightItemChanged();
-}
-
-void QQuickGridViewPrivate::updateHighlight()
-{
- applyPendingChanges();
-
- if ((!currentItem && highlight) || (currentItem && !highlight))
- createHighlight();
- bool strictHighlight = haveHighlightRange && highlightRange == QQuickGridView::StrictlyEnforceRange;
- if (currentItem && autoHighlight && highlight && (!strictHighlight || !pressed)) {
- // auto-update highlight
- highlightXAnimator->to = currentItem->item->x();
- highlightYAnimator->to = currentItem->item->y();
- highlight->item->setWidth(currentItem->item->width());
- highlight->item->setHeight(currentItem->item->height());
-
- highlightXAnimator->restart();
- highlightYAnimator->restart();
- }
- updateTrackedItem();
-}
-
-void QQuickGridViewPrivate::resetHighlightPosition()
-{
- if (highlight && currentItem) {
- FxGridItemSG *cItem = static_cast<FxGridItemSG*>(currentItem);
- static_cast<FxGridItemSG*>(highlight)->setPosition(cItem->colPos(), cItem->rowPos());
- }
-}
-
-qreal QQuickGridViewPrivate::headerSize() const
-{
- if (!header)
- return 0.0;
- return flow == QQuickGridView::LeftToRight ? header->item->height() : header->item->width();
-}
-
-qreal QQuickGridViewPrivate::footerSize() const
-{
- if (!footer)
- return 0.0;
- return flow == QQuickGridView::LeftToRight? footer->item->height() : footer->item->width();
-}
-
-bool QQuickGridViewPrivate::showHeaderForIndex(int index) const
-{
- return index / columns == 0;
-}
-
-bool QQuickGridViewPrivate::showFooterForIndex(int index) const
-{
- return index / columns == (model->count()-1) / columns;
-}
-
-void QQuickGridViewPrivate::updateFooter()
-{
- Q_Q(QQuickGridView);
- bool created = false;
- if (!footer) {
- QQuickItem *item = createComponentItem(footerComponent, true);
- if (!item)
- return;
- item->setZ(1);
- footer = new FxGridItemSG(item, q, true);
- created = true;
- }
-
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(footer);
- qreal colOffset = 0;
- qreal rowOffset = 0;
- if (q->effectiveLayoutDirection() == Qt::RightToLeft) {
- if (flow == QQuickGridView::TopToBottom)
- rowOffset = gridItem->item->width() - cellWidth;
- else
- colOffset = gridItem->item->width() - cellWidth;
- }
- if (visibleItems.count()) {
- qreal endPos = lastPosition();
- if (findLastVisibleIndex() == model->count()-1) {
- gridItem->setPosition(colOffset, endPos + rowOffset);
- } else {
- qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
- if (endPos <= visiblePos || gridItem->endPosition() <= endPos + rowOffset)
- gridItem->setPosition(colOffset, endPos + rowOffset);
- }
- } else {
- gridItem->setPosition(colOffset, rowOffset);
- }
-
- if (created)
- emit q->footerItemChanged();
-}
-
-void QQuickGridViewPrivate::updateHeader()
-{
- Q_Q(QQuickGridView);
- bool created = false;
- if (!header) {
- QQuickItem *item = createComponentItem(headerComponent, true);
- if (!item)
- return;
- item->setZ(1);
- header = new FxGridItemSG(item, q, true);
- created = true;
- }
-
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(header);
- qreal colOffset = 0;
- qreal rowOffset = -headerSize();
- if (q->effectiveLayoutDirection() == Qt::RightToLeft) {
- if (flow == QQuickGridView::TopToBottom)
- rowOffset += gridItem->item->width()-cellWidth;
- else
- colOffset = gridItem->item->width()-cellWidth;
- }
- if (visibleItems.count()) {
- qreal startPos = originPosition();
- if (visibleIndex == 0) {
- gridItem->setPosition(colOffset, startPos + rowOffset);
- } else {
- qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position();
- qreal headerPos = isRightToLeftTopToBottom() ? gridItem->rowPos() + cellWidth - headerSize() : gridItem->rowPos();
- if (tempPos <= startPos || headerPos > startPos + rowOffset)
- gridItem->setPosition(colOffset, startPos + rowOffset);
- }
- } else {
- if (isRightToLeftTopToBottom())
- gridItem->setPosition(colOffset, rowOffset);
- else
- gridItem->setPosition(colOffset, -headerSize());
- }
-
- if (created)
- emit q->headerItemChanged();
-}
-
-void QQuickGridViewPrivate::initializeCurrentItem()
-{
- if (currentItem && currentIndex >= 0) {
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(currentItem);
- if (gridItem)
- gridItem->setPosition(colPosAt(currentIndex), rowPosAt(currentIndex));
- }
-}
-
-void QQuickGridViewPrivate::itemGeometryChanged(QQuickItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
-{
- Q_Q(QQuickGridView);
- QQuickItemViewPrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
- if (!q->isComponentComplete())
- return;
- if (item == q) {
- if (newGeometry.height() != oldGeometry.height() || newGeometry.width() != oldGeometry.width()) {
- updateViewport();
- forceLayout = true;
- q->polish();
- }
- }
-}
-
-void QQuickGridViewPrivate::fixupPosition()
-{
- moveReason = Other;
- if (flow == QQuickGridView::LeftToRight)
- fixupY();
- else
- fixupX();
-}
-
-void QQuickGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
-{
- if ((flow == QQuickGridView::TopToBottom && &data == &vData)
- || (flow == QQuickGridView::LeftToRight && &data == &hData))
- return;
-
- fixupMode = moveReason == Mouse ? fixupMode : Immediate;
-
- qreal viewPos = isRightToLeftTopToBottom() ? -position()-size() : position();
-
- bool strictHighlightRange = haveHighlightRange && highlightRange == QQuickGridView::StrictlyEnforceRange;
- if (snapMode != QQuickGridView::NoSnap) {
- qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position();
- if (snapMode == QQuickGridView::SnapOneRow && moveReason == Mouse) {
- // if we've been dragged < rowSize()/2 then bias towards the next row
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
- qreal bias = 0;
- if (data.velocity > 0 && dist > QML_FLICK_SNAPONETHRESHOLD && dist < rowSize()/2)
- bias = rowSize()/2;
- else if (data.velocity < 0 && dist < -QML_FLICK_SNAPONETHRESHOLD && dist > -rowSize()/2)
- bias = -rowSize()/2;
- if (isRightToLeftTopToBottom())
- bias = -bias;
- tempPosition -= bias;
- }
- FxViewItem *topItem = snapItemAt(tempPosition+highlightRangeStart);
- if (!topItem && strictHighlightRange && currentItem) {
- // StrictlyEnforceRange always keeps an item in range
- updateHighlight();
- topItem = currentItem;
- }
- FxViewItem *bottomItem = snapItemAt(tempPosition+highlightRangeEnd);
- if (!bottomItem && strictHighlightRange && currentItem) {
- // StrictlyEnforceRange always keeps an item in range
- updateHighlight();
- bottomItem = currentItem;
- }
- qreal pos;
- bool isInBounds = -position() > maxExtent && -position() <= minExtent;
- if (topItem && (isInBounds || strictHighlightRange)) {
- qreal headerPos = header ? static_cast<FxGridItemSG*>(header)->rowPos() : 0;
- if (topItem->index == 0 && header && tempPosition+highlightRangeStart < headerPos+headerSize()/2 && !strictHighlightRange) {
- pos = isRightToLeftTopToBottom() ? - headerPos + highlightRangeStart - size() : headerPos - highlightRangeStart;
- } else {
- if (isRightToLeftTopToBottom())
- pos = qMax(qMin(-topItem->position() + highlightRangeStart - size(), -maxExtent), -minExtent);
- else
- pos = qMax(qMin(topItem->position() - highlightRangeStart, -maxExtent), -minExtent);
- }
- } else if (bottomItem && isInBounds) {
- if (isRightToLeftTopToBottom())
- pos = qMax(qMin(-bottomItem->position() + highlightRangeEnd - size(), -maxExtent), -minExtent);
- else
- pos = qMax(qMin(bottomItem->position() - highlightRangeEnd, -maxExtent), -minExtent);
- } else {
- QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
- return;
- }
-
- qreal dist = qAbs(data.move + pos);
- if (dist > 0) {
- timeline.reset(data.move);
- if (fixupMode != Immediate) {
- timeline.move(data.move, -pos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
- data.fixingUp = true;
- } else {
- timeline.set(data.move, -pos);
- }
- vTime = timeline.time();
- }
- } else if (haveHighlightRange && highlightRange == QQuickGridView::StrictlyEnforceRange) {
- if (currentItem) {
- updateHighlight();
- qreal pos = static_cast<FxGridItemSG*>(currentItem)->rowPos();
- if (viewPos < pos + rowSize() - highlightRangeEnd)
- viewPos = pos + rowSize() - highlightRangeEnd;
- if (viewPos > pos - highlightRangeStart)
- viewPos = pos - highlightRangeStart;
- if (isRightToLeftTopToBottom())
- viewPos = -viewPos-size();
- timeline.reset(data.move);
- if (viewPos != position()) {
- if (fixupMode != Immediate) {
- timeline.move(data.move, -viewPos, QEasingCurve(QEasingCurve::InOutQuad), fixupDuration/2);
- data.fixingUp = true;
- } else {
- timeline.set(data.move, -viewPos);
- }
- }
- vTime = timeline.time();
- }
- } else {
- QQuickItemViewPrivate::fixup(data, minExtent, maxExtent);
- }
- data.inOvershoot = false;
- fixupMode = Normal;
-}
-
-void QQuickGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
- QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity)
-{
- Q_Q(QQuickGridView);
- data.fixingUp = false;
- moveReason = Mouse;
- if ((!haveHighlightRange || highlightRange != QQuickGridView::StrictlyEnforceRange)
- && snapMode == QQuickGridView::NoSnap) {
- QQuickItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
- return;
- }
- qreal maxDistance = 0;
- qreal dataValue = isRightToLeftTopToBottom() ? -data.move.value()+size() : data.move.value();
- // -ve velocity means list is moving up/left
- if (velocity > 0) {
- if (data.move.value() < minExtent) {
- if (snapMode == QQuickGridView::SnapOneRow) {
- // if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
- qreal bias = dist < rowSize()/2 ? rowSize()/2 : 0;
- if (isRightToLeftTopToBottom())
- bias = -bias;
- data.flickTarget = -snapPosAt(-dataValue - bias);
- maxDistance = qAbs(data.flickTarget - data.move.value());
- velocity = maxVelocity;
- } else {
- maxDistance = qAbs(minExtent - data.move.value());
- }
- }
- if (snapMode == QQuickGridView::NoSnap && highlightRange != QQuickGridView::StrictlyEnforceRange)
- data.flickTarget = minExtent;
- } else {
- if (data.move.value() > maxExtent) {
- if (snapMode == QQuickGridView::SnapOneRow) {
- // if we've been dragged < averageSize/2 then bias towards the next item
- qreal dist = data.move.value() - (data.pressPos - data.dragStartOffset);
- qreal bias = -dist < rowSize()/2 ? rowSize()/2 : 0;
- if (isRightToLeftTopToBottom())
- bias = -bias;
- data.flickTarget = -snapPosAt(-dataValue + bias);
- maxDistance = qAbs(data.flickTarget - data.move.value());
- velocity = -maxVelocity;
- } else {
- maxDistance = qAbs(maxExtent - data.move.value());
- }
- }
- if (snapMode == QQuickGridView::NoSnap && highlightRange != QQuickGridView::StrictlyEnforceRange)
- data.flickTarget = maxExtent;
- }
- bool overShoot = boundsBehavior == QQuickFlickable::DragAndOvershootBounds;
- if (maxDistance > 0 || overShoot) {
- // This mode requires the grid to stop exactly on a row boundary.
- qreal v = velocity;
- if (maxVelocity != -1 && maxVelocity < qAbs(v)) {
- if (v < 0)
- v = -maxVelocity;
- else
- v = maxVelocity;
- }
- qreal accel = deceleration;
- qreal v2 = v * v;
- qreal overshootDist = 0.0;
- if ((maxDistance > 0.0 && v2 / (2.0f * maxDistance) < accel) || snapMode == QQuickGridView::SnapOneRow) {
- // + rowSize()/4 to encourage moving at least one item in the flick direction
- qreal dist = v2 / (accel * 2.0) + rowSize()/4;
- dist = qMin(dist, maxDistance);
- if (v > 0)
- dist = -dist;
- if (snapMode != QQuickGridView::SnapOneRow) {
- qreal distTemp = isRightToLeftTopToBottom() ? -dist : dist;
- data.flickTarget = -snapPosAt(-dataValue + distTemp);
- }
- data.flickTarget = isRightToLeftTopToBottom() ? -data.flickTarget+size() : data.flickTarget;
- if (overShoot) {
- if (data.flickTarget >= minExtent) {
- overshootDist = overShootDistance(vSize);
- data.flickTarget += overshootDist;
- } else if (data.flickTarget <= maxExtent) {
- overshootDist = overShootDistance(vSize);
- data.flickTarget -= overshootDist;
- }
- }
- qreal adjDist = -data.flickTarget + data.move.value();
- if (qAbs(adjDist) > qAbs(dist)) {
- // Prevent painfully slow flicking - adjust velocity to suit flickDeceleration
- qreal adjv2 = accel * 2.0f * qAbs(adjDist);
- if (adjv2 > v2) {
- v2 = adjv2;
- v = qSqrt(v2);
- if (dist > 0)
- v = -v;
- }
- }
- dist = adjDist;
- accel = v2 / (2.0f * qAbs(dist));
- } else {
- data.flickTarget = velocity > 0 ? minExtent : maxExtent;
- overshootDist = overShoot ? overShootDistance(vSize) : 0;
- }
- timeline.reset(data.move);
- timeline.accel(data.move, v, accel, maxDistance + overshootDist);
- timeline.callback(QDeclarativeTimeLineCallback(&data.move, fixupCallback, this));
- if (!hData.flicking && q->xflick()) {
- hData.flicking = true;
- emit q->flickingChanged();
- emit q->flickingHorizontallyChanged();
- emit q->flickStarted();
- }
- if (!vData.flicking && q->yflick()) {
- vData.flicking = true;
- emit q->flickingChanged();
- emit q->flickingVerticallyChanged();
- emit q->flickStarted();
- }
- } else {
- timeline.reset(data.move);
- fixup(data, minExtent, maxExtent);
- }
-}
-
-
-//----------------------------------------------------------------------------
-/*!
- \qmlclass GridView QQuickGridView
- \inqmlmodule QtQuick 2
- \ingroup qml-view-elements
-
- \inherits Flickable
- \brief The GridView item provides a grid view of items provided by a model.
-
- A GridView displays data from models created from built-in QML elements like ListModel
- and XmlListModel, or custom model classes defined in C++ that inherit from
- QAbstractListModel.
-
- A GridView has a \l model, which defines the data to be displayed, and
- a \l delegate, which defines how the data should be displayed. Items in a
- GridView are laid out horizontally or vertically. Grid views are inherently flickable
- as GridView inherits from \l Flickable.
-
- \section1 Example Usage
-
- The following example shows the definition of a simple list model defined
- in a file called \c ContactModel.qml:
-
- \snippet doc/src/snippets/declarative/gridview/ContactModel.qml 0
-
- \div {class="float-right"}
- \inlineimage gridview-simple.png
- \enddiv
-
- This model can be referenced as \c ContactModel in other QML files. See \l{QML Modules}
- for more information about creating reusable components like this.
-
- Another component can display this model data in a GridView, as in the following
- example, which creates a \c ContactModel component for its model, and a \l Column element
- (containing \l Image and \l Text elements) for its delegate.
-
- \clearfloat
- \snippet doc/src/snippets/declarative/gridview/gridview.qml import
- \codeline
- \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs simple
-
- \div {class="float-right"}
- \inlineimage gridview-highlight.png
- \enddiv
-
- The view will create a new delegate for each item in the model. Note that the delegate
- is able to access the model's \c name and \c portrait data directly.
-
- An improved grid view is shown below. The delegate is visually improved and is moved
- into a separate \c contactDelegate component.
-
- \clearfloat
- \snippet doc/src/snippets/declarative/gridview/gridview.qml classdocs advanced
-
- The currently selected item is highlighted with a blue \l Rectangle using the \l highlight property,
- and \c focus is set to \c true to enable keyboard navigation for the grid view.
- The grid view itself is a focus scope (see \l{qmlfocus#Acquiring Focus and Focus Scopes}{the focus documentation page} for more details).
-
- Delegates are instantiated as needed and may be destroyed at any time.
- State should \e never be stored in a delegate.
-
- GridView attaches a number of properties to the root item of the delegate, for example
- \c {GridView.isCurrentItem}. In the following example, the root delegate item can access
- this attached property directly as \c GridView.isCurrentItem, while the child
- \c contactInfo object must refer to this property as \c wrapper.GridView.isCurrentItem.
-
- \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
-
- \note Views do not set the \l{Item::}{clip} property automatically.
- If the view is not clipped by another item or the screen, it will be necessary
- to set this property to true in order to clip the items that are partially or
- fully outside the view.
-
- \sa {declarative/modelviews/gridview}{GridView example}
-*/
-
-QQuickGridView::QQuickGridView(QQuickItem *parent)
- : QQuickItemView(*(new QQuickGridViewPrivate), parent)
-{
-}
-
-QQuickGridView::~QQuickGridView()
-{
-}
-
-void QQuickGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
-{
- Q_D(QQuickGridView);
- if (d->autoHighlight != autoHighlight) {
- if (!autoHighlight && d->highlightXAnimator) {
- d->highlightXAnimator->stop();
- d->highlightYAnimator->stop();
- }
- QQuickItemView::setHighlightFollowsCurrentItem(autoHighlight);
- }
-}
-
-/*!
- \qmlattachedproperty bool QtQuick2::GridView::isCurrentItem
- This attached property is true if this delegate is the current item; otherwise false.
-
- It is attached to each instance of the delegate.
-*/
-
-/*!
- \qmlattachedproperty GridView QtQuick2::GridView::view
- This attached property holds the view that manages this delegate instance.
-
- It is attached to each instance of the delegate.
-
- \snippet doc/src/snippets/declarative/gridview/gridview.qml isCurrentItem
-*/
-
-/*!
- \qmlattachedproperty bool QtQuick2::GridView::delayRemove
- This attached property holds whether the delegate may be destroyed.
-
- It is attached to each instance of the delegate.
-
- It is sometimes necessary to delay the destruction of an item
- until an animation completes.
-
- The example below ensures that the animation completes before
- the item is removed from the grid.
-
- \snippet doc/src/snippets/declarative/gridview/gridview.qml delayRemove
-*/
-
-/*!
- \qmlattachedsignal QtQuick2::GridView::onAdd()
- This attached handler is called immediately after an item is added to the view.
-*/
-
-/*!
- \qmlattachedsignal QtQuick2::GridView::onRemove()
- This attached handler is called immediately before an item is removed from the view.
-*/
-
-
-/*!
- \qmlproperty model QtQuick2::GridView::model
- This property holds the model providing data for the grid.
-
- The model provides the set of data that is used to create the items
- in the view. Models can be created directly in QML using \l ListModel, \l XmlListModel
- or \l VisualItemModel, or provided by C++ model classes. If a C++ model class is
- used, it must be a subclass of \l QAbstractItemModel or a simple list.
-
- \sa {qmlmodels}{Data Models}
-*/
-
-/*!
- \qmlproperty Component QtQuick2::GridView::delegate
-
- The delegate provides a template defining each item instantiated by the view.
- The index is exposed as an accessible \c index property. Properties of the
- model are also available depending upon the type of \l {qmlmodels}{Data Model}.
-
- The number of elements in the delegate has a direct effect on the
- flicking performance of the view. If at all possible, place functionality
- that is not needed for the normal display of the delegate in a \l Loader which
- can load additional elements when needed.
-
- The GridView will layout the items based on the size of the root item
- in the delegate.
-
- \note Delegates are instantiated as needed and may be destroyed at any time.
- State should \e never be stored in a delegate.
-*/
-
-/*!
- \qmlproperty int QtQuick2::GridView::currentIndex
- \qmlproperty Item QtQuick2::GridView::currentItem
-
- The \c currentIndex property holds the index of the current item, and
- \c currentItem holds the current item. Setting the currentIndex to -1
- will clear the highlight and set currentItem to null.
-
- If highlightFollowsCurrentItem is \c true, setting either of these
- properties will smoothly scroll the GridView so that the current
- item becomes visible.
-
- Note that the position of the current item
- may only be approximate until it becomes visible in the view.
-*/
-
-
-/*!
- \qmlproperty Item QtQuick2::GridView::highlightItem
-
- This holds the highlight item created from the \l highlight component.
-
- The highlightItem is managed by the view unless
- \l highlightFollowsCurrentItem is set to false.
-
- \sa highlight, highlightFollowsCurrentItem
-*/
-
-
-/*!
- \qmlproperty int QtQuick2::GridView::count
- This property holds the number of items in the view.
-*/
-
-
-/*!
- \qmlproperty Component QtQuick2::GridView::highlight
- This property holds the component to use as the highlight.
-
- An instance of the highlight component is created for each view.
- The geometry of the resulting component instance will be managed by the view
- so as to stay with the current item, unless the highlightFollowsCurrentItem property is false.
-
- \sa highlightItem, highlightFollowsCurrentItem
-*/
-
-/*!
- \qmlproperty bool QtQuick2::GridView::highlightFollowsCurrentItem
- This property sets whether the highlight is managed by the view.
-
- If this property is true (the default value), the highlight is moved smoothly
- to follow the current item. Otherwise, the
- highlight is not moved by the view, and any movement must be implemented
- by the highlight.
-
- Here is a highlight with its motion defined by a \l {SpringAnimation} item:
-
- \snippet doc/src/snippets/declarative/gridview/gridview.qml highlightFollowsCurrentItem
-*/
-
-
-/*!
- \qmlproperty int QtQuick2::GridView::highlightMoveDuration
- This property holds the move animation duration of the highlight delegate.
-
- highlightFollowsCurrentItem must be true for this property
- to have effect.
-
- The default value for the duration is 150ms.
-
- \sa highlightFollowsCurrentItem
-*/
-
-/*!
- \qmlproperty real QtQuick2::GridView::preferredHighlightBegin
- \qmlproperty real QtQuick2::GridView::preferredHighlightEnd
- \qmlproperty enumeration QtQuick2::GridView::highlightRangeMode
-
- These properties define the preferred range of the highlight (for the current item)
- within the view. The \c preferredHighlightBegin value must be less than the
- \c preferredHighlightEnd value.
-
- These properties affect the position of the current item when the view is scrolled.
- For example, if the currently selected item should stay in the middle of the
- view when it is scrolled, set the \c preferredHighlightBegin and
- \c preferredHighlightEnd values to the top and bottom coordinates of where the middle
- item would be. If the \c currentItem is changed programmatically, the view will
- automatically scroll so that the current item is in the middle of the view.
- Furthermore, the behavior of the current item index will occur whether or not a
- highlight exists.
-
- Valid values for \c highlightRangeMode are:
-
- \list
- \o GridView.ApplyRange - the view attempts to maintain the highlight within the range.
- However, the highlight can move outside of the range at the ends of the view or due
- to mouse interaction.
- \o GridView.StrictlyEnforceRange - the highlight never moves outside of the range.
- The current item changes if a keyboard or mouse action would cause the highlight to move
- outside of the range.
- \o GridView.NoHighlightRange - this is the default value.
- \endlist
-*/
-
-
-/*!
- \qmlproperty enumeration QtQuick2::GridView::layoutDirection
- This property holds the layout direction of the grid.
-
- Possible values:
-
- \list
- \o Qt.LeftToRight (default) - Items will be laid out starting in the top, left corner. The flow is
- dependent on the \l GridView::flow property.
- \o Qt.RightToLeft - Items will be laid out starting in the top, right corner. The flow is dependent
- on the \l GridView::flow property.
- \endlist
-
- \bold Note: If GridView::flow is set to GridView.LeftToRight, this is not to be confused if
- GridView::layoutDirection is set to Qt.RightToLeft. The GridView.LeftToRight flow value simply
- indicates that the flow is horizontal.
-*/
-
-
-/*!
- \qmlproperty enumeration QtQuick2::GridView::effectiveLayoutDirection
- This property holds the effective layout direction of the grid.
-
- When using the attached property \l {LayoutMirroring::enabled}{LayoutMirroring::enabled} for locale layouts,
- the visual layout direction of the grid will be mirrored. However, the
- property \l {GridView::layoutDirection}{layoutDirection} will remain unchanged.
-
- \sa GridView::layoutDirection, {LayoutMirroring}{LayoutMirroring}
-*/
-/*!
- \qmlproperty bool QtQuick2::GridView::keyNavigationWraps
- This property holds whether the grid wraps key navigation
-
- If this is true, key navigation that would move the current item selection
- past one end of the view instead wraps around and moves the selection to
- the other end of the view.
-
- By default, key navigation is not wrapped.
-*/
-/*!
- \qmlproperty int QtQuick2::GridView::cacheBuffer
- This property determines whether delegates are retained outside the
- visible area of the view.
-
- If non-zero the view may keep as many delegates
- instantiated as will fit within the buffer specified. For example,
- if in a vertical view the delegate is 20 pixels high, there are 3
- columns and \c cacheBuffer is
- set to 40, then up to 6 delegates above and 6 delegates below the visible
- area may be created/retained. The buffered delegates are created asynchronously,
- allowing creation to occur across multiple frames and reducing the
- likelihood of skipping frames. In order to improve painting performance
- delegates outside the visible area have their \l visible property set to
- false until they are moved into the visible area.
-
- Note that cacheBuffer is not a pixel buffer - it only maintains additional
- instantiated delegates.
-
- Setting this value can make scrolling the list smoother at the expense
- of additional memory usage. It is not a substitute for creating efficient
- delegates; the fewer elements in a delegate, the faster a view may be
- scrolled.
-*/
-void QQuickGridView::setHighlightMoveDuration(int duration)
-{
- Q_D(QQuickGridView);
- if (d->highlightMoveDuration != duration) {
- if (d->highlightYAnimator) {
- d->highlightXAnimator->userDuration = duration;
- d->highlightYAnimator->userDuration = duration;
- }
- QQuickItemView::setHighlightMoveDuration(duration);
- }
-}
-
-/*!
- \qmlproperty enumeration QtQuick2::GridView::flow
- This property holds the flow of the grid.
-
- Possible values:
-
- \list
- \o GridView.LeftToRight (default) - Items are laid out from left to right, and the view scrolls vertically
- \o GridView.TopToBottom - Items are laid out from top to bottom, and the view scrolls horizontally
- \endlist
-*/
-QQuickGridView::Flow QQuickGridView::flow() const
-{
- Q_D(const QQuickGridView);
- return d->flow;
-}
-
-void QQuickGridView::setFlow(Flow flow)
-{
- Q_D(QQuickGridView);
- if (d->flow != flow) {
- d->flow = flow;
- if (d->flow == LeftToRight) {
- setContentWidth(-1);
- setFlickableDirection(VerticalFlick);
- } else {
- setContentHeight(-1);
- setFlickableDirection(HorizontalFlick);
- }
- setContentX(0);
- setContentY(0);
- d->regenerate();
- emit flowChanged();
- }
-}
-
-
-/*!
- \qmlproperty real QtQuick2::GridView::cellWidth
- \qmlproperty real QtQuick2::GridView::cellHeight
-
- These properties holds the width and height of each cell in the grid.
-
- The default cell size is 100x100.
-*/
-qreal QQuickGridView::cellWidth() const
-{
- Q_D(const QQuickGridView);
- return d->cellWidth;
-}
-
-void QQuickGridView::setCellWidth(qreal cellWidth)
-{
- Q_D(QQuickGridView);
- if (cellWidth != d->cellWidth && cellWidth > 0) {
- d->cellWidth = qMax(qreal(1), cellWidth);
- d->updateViewport();
- emit cellWidthChanged();
- d->forceLayout = true;
- d->layout();
- }
-}
-
-qreal QQuickGridView::cellHeight() const
-{
- Q_D(const QQuickGridView);
- return d->cellHeight;
-}
-
-void QQuickGridView::setCellHeight(qreal cellHeight)
-{
- Q_D(QQuickGridView);
- if (cellHeight != d->cellHeight && cellHeight > 0) {
- d->cellHeight = qMax(qreal(1), cellHeight);
- d->updateViewport();
- emit cellHeightChanged();
- d->forceLayout = true;
- d->layout();
- }
-}
-/*!
- \qmlproperty enumeration QtQuick2::GridView::snapMode
-
- This property determines how the view scrolling will settle following a drag or flick.
- The possible values are:
-
- \list
- \o GridView.NoSnap (default) - the view stops anywhere within the visible area.
- \o GridView.SnapToRow - the view settles with a row (or column for \c GridView.TopToBottom flow)
- aligned with the start of the view.
- \o GridView.SnapOneRow - the view will settle no more than one row (or column for \c GridView.TopToBottom flow)
- away from the first visible row at the time the mouse button is released.
- This mode is particularly useful for moving one page at a time.
- \endlist
-
-*/
-QQuickGridView::SnapMode QQuickGridView::snapMode() const
-{
- Q_D(const QQuickGridView);
- return d->snapMode;
-}
-
-void QQuickGridView::setSnapMode(SnapMode mode)
-{
- Q_D(QQuickGridView);
- if (d->snapMode != mode) {
- d->snapMode = mode;
- emit snapModeChanged();
- }
-}
-
-
-/*!
- \qmlproperty Component QtQuick2::GridView::footer
- This property holds the component to use as the footer.
-
- An instance of the footer component is created for each view. The
- footer is positioned at the end of the view, after any items.
-
- \sa header
-*/
-/*!
- \qmlproperty Component QtQuick2::GridView::header
- This property holds the component to use as the header.
-
- An instance of the header component is created for each view. The
- header is positioned at the beginning of the view, before any items.
-
- \sa footer
-*/
-void QQuickGridView::viewportMoved()
-{
- Q_D(QQuickGridView);
- QQuickItemView::viewportMoved();
- if (!d->itemCount)
- return;
- if (d->inViewportMoved)
- return;
- d->inViewportMoved = true;
-
- // Set visibility of items to eliminate cost of items outside the visible area.
- qreal from = d->isContentFlowReversed() ? -d->position()-d->size() : d->position();
- qreal to = d->isContentFlowReversed() ? -d->position() : d->position()+d->size();
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxGridItemSG *item = static_cast<FxGridItemSG*>(d->visibleItems.at(i));
- item->item->setVisible(item->rowPos() + d->rowSize() >= from && item->rowPos() <= to);
- }
-
- if (yflick())
- d->bufferMode = d->vData.smoothVelocity < 0 ? QQuickItemViewPrivate::BufferBefore : QQuickItemViewPrivate::BufferAfter;
- else if (d->isRightToLeftTopToBottom())
- d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickItemViewPrivate::BufferAfter : QQuickItemViewPrivate::BufferBefore;
- else
- d->bufferMode = d->hData.smoothVelocity < 0 ? QQuickItemViewPrivate::BufferBefore : QQuickItemViewPrivate::BufferAfter;
-
- d->refill();
- if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving)
- d->moveReason = QQuickGridViewPrivate::Mouse;
- if (d->moveReason != QQuickGridViewPrivate::SetIndex) {
- if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
- // reposition highlight
- qreal pos = d->highlight->position();
- qreal viewPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size() : d->position();
- if (pos > viewPos + d->highlightRangeEnd - d->highlight->size())
- pos = viewPos + d->highlightRangeEnd - d->highlight->size();
- if (pos < viewPos + d->highlightRangeStart)
- pos = viewPos + d->highlightRangeStart;
-
- if (pos != d->highlight->position()) {
- d->highlightXAnimator->stop();
- d->highlightYAnimator->stop();
- static_cast<FxGridItemSG*>(d->highlight)->setPosition(static_cast<FxGridItemSG*>(d->highlight)->colPos(), pos);
- } else {
- d->updateHighlight();
- }
-
- // update current index
- int idx = d->snapIndex();
- if (idx >= 0 && idx != d->currentIndex) {
- d->updateCurrent(idx);
- if (d->currentItem && static_cast<FxGridItemSG*>(d->currentItem)->colPos() != static_cast<FxGridItemSG*>(d->highlight)->colPos() && d->autoHighlight) {
- if (d->flow == LeftToRight)
- d->highlightXAnimator->to = d->currentItem->item->x();
- else
- d->highlightYAnimator->to = d->currentItem->item->y();
- }
- }
- }
- }
-
- d->inViewportMoved = false;
-}
-
-void QQuickGridView::keyPressEvent(QKeyEvent *event)
-{
- Q_D(QQuickGridView);
- if (d->model && d->model->count() && d->interactive) {
- d->moveReason = QQuickGridViewPrivate::SetIndex;
- int oldCurrent = currentIndex();
- switch (event->key()) {
- case Qt::Key_Up:
- moveCurrentIndexUp();
- break;
- case Qt::Key_Down:
- moveCurrentIndexDown();
- break;
- case Qt::Key_Left:
- moveCurrentIndexLeft();
- break;
- case Qt::Key_Right:
- moveCurrentIndexRight();
- break;
- default:
- break;
- }
- if (oldCurrent != currentIndex()) {
- event->accept();
- return;
- }
- }
- event->ignore();
- QQuickItemView::keyPressEvent(event);
-}
-/*!
- \qmlmethod QtQuick2::GridView::moveCurrentIndexUp()
-
- Move the currentIndex up one item in the view.
- The current index will wrap if keyNavigationWraps is true and it
- is currently at the end. This method has no effect if the \l count is zero.
-
- \bold Note: methods should only be called after the Component has completed.
-*/
-
-
-void QQuickGridView::moveCurrentIndexUp()
-{
- Q_D(QQuickGridView);
- const int count = d->model ? d->model->count() : 0;
- if (!count)
- return;
- if (d->flow == QQuickGridView::LeftToRight) {
- if (currentIndex() >= d->columns || d->wrap) {
- int index = currentIndex() - d->columns;
- setCurrentIndex((index >= 0 && index < count) ? index : count-1);
- }
- } else {
- if (currentIndex() > 0 || d->wrap) {
- int index = currentIndex() - 1;
- setCurrentIndex((index >= 0 && index < count) ? index : count-1);
- }
- }
-}
-
-/*!
- \qmlmethod QtQuick2::GridView::moveCurrentIndexDown()
-
- Move the currentIndex down one item in the view.
- The current index will wrap if keyNavigationWraps is true and it
- is currently at the end. This method has no effect if the \l count is zero.
-
- \bold Note: methods should only be called after the Component has completed.
-*/
-void QQuickGridView::moveCurrentIndexDown()
-{
- Q_D(QQuickGridView);
- const int count = d->model ? d->model->count() : 0;
- if (!count)
- return;
- if (d->flow == QQuickGridView::LeftToRight) {
- if (currentIndex() < count - d->columns || d->wrap) {
- int index = currentIndex()+d->columns;
- setCurrentIndex((index >= 0 && index < count) ? index : 0);
- }
- } else {
- if (currentIndex() < count - 1 || d->wrap) {
- int index = currentIndex() + 1;
- setCurrentIndex((index >= 0 && index < count) ? index : 0);
- }
- }
-}
-
-/*!
- \qmlmethod QtQuick2::GridView::moveCurrentIndexLeft()
-
- Move the currentIndex left one item in the view.
- The current index will wrap if keyNavigationWraps is true and it
- is currently at the end. This method has no effect if the \l count is zero.
-
- \bold Note: methods should only be called after the Component has completed.
-*/
-void QQuickGridView::moveCurrentIndexLeft()
-{
- Q_D(QQuickGridView);
- const int count = d->model ? d->model->count() : 0;
- if (!count)
- return;
- if (effectiveLayoutDirection() == Qt::LeftToRight) {
- if (d->flow == QQuickGridView::LeftToRight) {
- if (currentIndex() > 0 || d->wrap) {
- int index = currentIndex() - 1;
- setCurrentIndex((index >= 0 && index < count) ? index : count-1);
- }
- } else {
- if (currentIndex() >= d->columns || d->wrap) {
- int index = currentIndex() - d->columns;
- setCurrentIndex((index >= 0 && index < count) ? index : count-1);
- }
- }
- } else {
- if (d->flow == QQuickGridView::LeftToRight) {
- if (currentIndex() < count - 1 || d->wrap) {
- int index = currentIndex() + 1;
- setCurrentIndex((index >= 0 && index < count) ? index : 0);
- }
- } else {
- if (currentIndex() < count - d->columns || d->wrap) {
- int index = currentIndex() + d->columns;
- setCurrentIndex((index >= 0 && index < count) ? index : 0);
- }
- }
- }
-}
-
-
-/*!
- \qmlmethod QtQuick2::GridView::moveCurrentIndexRight()
-
- Move the currentIndex right one item in the view.
- The current index will wrap if keyNavigationWraps is true and it
- is currently at the end. This method has no effect if the \l count is zero.
-
- \bold Note: methods should only be called after the Component has completed.
-*/
-void QQuickGridView::moveCurrentIndexRight()
-{
- Q_D(QQuickGridView);
- const int count = d->model ? d->model->count() : 0;
- if (!count)
- return;
- if (effectiveLayoutDirection() == Qt::LeftToRight) {
- if (d->flow == QQuickGridView::LeftToRight) {
- if (currentIndex() < count - 1 || d->wrap) {
- int index = currentIndex() + 1;
- setCurrentIndex((index >= 0 && index < count) ? index : 0);
- }
- } else {
- if (currentIndex() < count - d->columns || d->wrap) {
- int index = currentIndex()+d->columns;
- setCurrentIndex((index >= 0 && index < count) ? index : 0);
- }
- }
- } else {
- if (d->flow == QQuickGridView::LeftToRight) {
- if (currentIndex() > 0 || d->wrap) {
- int index = currentIndex() - 1;
- setCurrentIndex((index >= 0 && index < count) ? index : count-1);
- }
- } else {
- if (currentIndex() >= d->columns || d->wrap) {
- int index = currentIndex() - d->columns;
- setCurrentIndex((index >= 0 && index < count) ? index : count-1);
- }
- }
- }
-}
-
-bool QQuickGridViewPrivate::applyInsertionChange(const QDeclarativeChangeSet::Insert &change, FxViewItem *firstVisible, InsertionsResult *insertResult)
-{
- Q_Q(QQuickGridView);
-
- int modelIndex = change.index;
- int count = change.count;
-
- int index = visibleItems.count() ? mapFromModel(modelIndex) : 0;
-
- if (index < 0) {
- int i = visibleItems.count() - 1;
- while (i > 0 && visibleItems.at(i)->index == -1)
- --i;
- if (visibleItems.at(i)->index + 1 == modelIndex) {
- // Special case of appending an item to the model.
- index = visibleItems.count();
- } else {
- if (modelIndex <= visibleIndex) {
- // Insert before visible items
- visibleIndex += count;
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxViewItem *item = visibleItems.at(i);
- if (item->index != -1 && item->index >= modelIndex)
- item->index += count;
- }
- }
- return true;
- }
- }
-
- qreal tempPos = isRightToLeftTopToBottom() ? -position()-size()+q->width()+1 : position();
- qreal colPos = 0;
- qreal rowPos = 0;
- int colNum = 0;
- if (visibleItems.count()) {
- if (index < visibleItems.count()) {
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.at(index));
- colPos = gridItem->colPos();
- rowPos = gridItem->rowPos();
- colNum = qFloor((colPos+colSize()/2) / colSize());
- } else {
- // appending items to visible list
- FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(visibleItems.at(index-1));
- rowPos = gridItem->rowPos();
- colNum = qFloor((gridItem->colPos()+colSize()/2) / colSize());
- if (++colNum >= columns) {
- colNum = 0;
- rowPos += rowSize();
- }
- colPos = colNum * colSize();
- }
- }
-
- // Update the indexes of the following visible items.
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxViewItem *item = visibleItems.at(i);
- if (item->index != -1 && item->index >= modelIndex)
- item->index += count;
- }
-
- int prevAddedCount = insertResult->addedItems.count();
- if (firstVisible && rowPos < firstVisible->position()) {
- // Insert items before the visible item.
- int insertionIdx = index;
- int i = count - 1;
- int from = tempPos - buffer;
-
- while (i >= 0) {
- if (rowPos > from && insertionIdx < visibleIndex) {
- // item won't be visible, just note the size for repositioning
- insertResult->sizeAddedBeforeVisible += rowSize();
- } else {
- // item is before first visible e.g. in cache buffer
- FxViewItem *item = 0;
- if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
- if (item->index > modelIndex + i)
- insertResult->movedBackwards.append(item);
- item->index = modelIndex + i;
- }
- if (!item)
- item = createItem(modelIndex + i);
- if (!item)
- return false;
-
- item->item->setVisible(true);
- visibleItems.insert(insertionIdx, item);
- if (!change.isMove()) {
- insertResult->addedItems.append(item);
- insertResult->sizeAddedBeforeVisible += rowSize();
- }
- }
-
- if (--colNum < 0 ) {
- colNum = columns - 1;
- rowPos -= rowSize();
- }
- colPos = colNum * colSize();
- index++;
- i--;
- }
- } else {
- int i = 0;
- int to = buffer+tempPos+size()-1;
- while (i < count && rowPos <= to + rowSize()*(columns - (colPos/colSize()))/qreal(columns)) {
- FxViewItem *item = 0;
- if (change.isMove() && (item = currentChanges.removedItems.take(change.moveKey(modelIndex + i)))) {
- if (item->index > modelIndex + i)
- insertResult->movedBackwards.append(item);
- item->index = modelIndex + i;
- }
- if (!item)
- item = createItem(modelIndex + i);
- if (!item)
- return false;
-
- item->item->setVisible(true);
- visibleItems.insert(index, item);
- if (!change.isMove())
- insertResult->addedItems.append(item);
- if (++colNum >= columns) {
- colNum = 0;
- rowPos += rowSize();
- }
- colPos = colNum * colSize();
- ++index;
- ++i;
- }
- }
-
- updateVisibleIndex();
-
- return insertResult->addedItems.count() > prevAddedCount;
-}
-
-bool QQuickGridViewPrivate::needsRefillForAddedOrRemovedIndex(int modelIndex) const
-{
- // If we add or remove items before visible items, a layout may be
- // required to ensure item 0 is in the first column.
- return modelIndex < visibleIndex;
-}
-
-/*!
- \qmlmethod QtQuick2::GridView::positionViewAtIndex(int index, PositionMode mode)
-
- Positions the view such that the \a index is at the position specified by
- \a mode:
-
- \list
- \o GridView.Beginning - position item at the top (or left for \c GridView.TopToBottom flow) of the view.
- \o GridView.Center - position item in the center of the view.
- \o GridView.End - position item at bottom (or right for horizontal orientation) of the view.
- \o GridView.Visible - if any part of the item is visible then take no action, otherwise
- bring the item into view.
- \o GridView.Contain - ensure the entire item is visible. If the item is larger than
- the view the item is positioned at the top (or left for \c GridView.TopToBottom flow) of the view.
- \endlist
-
- If positioning the view at the index would cause empty space to be displayed at
- the beginning or end of the view, the view will be positioned at the boundary.
-
- It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
- at a particular index. This is unreliable since removing items from the start
- of the view does not cause all other items to be repositioned.
- The correct way to bring an item into view is with \c positionViewAtIndex.
-
- \bold Note: methods should only be called after the Component has completed. To position
- the view at startup, this method should be called by Component.onCompleted. For
- example, to position the view at the end:
-
- \code
- Component.onCompleted: positionViewAtIndex(count - 1, GridView.Beginning)
- \endcode
-*/
-
-/*!
- \qmlmethod QtQuick2::GridView::positionViewAtBeginning()
- \qmlmethod QtQuick2::GridView::positionViewAtEnd()
-
- Positions the view at the beginning or end, taking into account any header or footer.
-
- It is not recommended to use \l {Flickable::}{contentX} or \l {Flickable::}{contentY} to position the view
- at a particular index. This is unreliable since removing items from the start
- of the list does not cause all other items to be repositioned, and because
- the actual start of the view can vary based on the size of the delegates.
-
- \bold Note: methods should only be called after the Component has completed. To position
- the view at startup, this method should be called by Component.onCompleted. For
- example, to position the view at the end on startup:
-
- \code
- Component.onCompleted: positionViewAtEnd()
- \endcode
-*/
-
-/*!
- \qmlmethod int QtQuick2::GridView::indexAt(int x, int y)
-
- Returns the index of the visible item containing the point \a x, \a y in content
- coordinates. If there is no item at the point specified, or the item is
- not visible -1 is returned.
-
- If the item is outside the visible area, -1 is returned, regardless of
- whether an item will exist at that point when scrolled into view.
-
- \bold Note: methods should only be called after the Component has completed.
-*/
-
-QQuickGridViewAttached *QQuickGridView::qmlAttachedProperties(QObject *obj)
-{
- return new QQuickGridViewAttached(obj);
-}
-
-QT_END_NAMESPACE