diff options
Diffstat (limited to 'src/qtquick1/graphicsitems/qdeclarativegridview.cpp')
-rw-r--r-- | src/qtquick1/graphicsitems/qdeclarativegridview.cpp | 3174 |
1 files changed, 0 insertions, 3174 deletions
diff --git a/src/qtquick1/graphicsitems/qdeclarativegridview.cpp b/src/qtquick1/graphicsitems/qdeclarativegridview.cpp deleted file mode 100644 index dd002e5b6c..0000000000 --- a/src/qtquick1/graphicsitems/qdeclarativegridview.cpp +++ /dev/null @@ -1,3174 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** 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 "QtQuick1/private/qdeclarativegridview_p.h" - -#include "QtQuick1/private/qdeclarativevisualitemmodel_p.h" -#include "QtQuick1/private/qdeclarativeflickable_p_p.h" - -#include "QtQuick1/private/qdeclarativesmoothedanimation_p_p.h" -#include <QtDeclarative/private/qdeclarativeguard_p.h> - -#include <QKeyEvent> - -#include <qmath.h> -#include <math.h> -#include "qplatformdefs.h" - -QT_BEGIN_NAMESPACE - -#ifndef QML_FLICK_SNAPONETHRESHOLD -#define QML_FLICK_SNAPONETHRESHOLD 30 -#endif - -//---------------------------------------------------------------------------- - -class FxGridItem1 -{ -public: - FxGridItem1(QDeclarativeItem *i, QDeclarative1GridView *v) : item(i), view(v) { - attached = static_cast<QDeclarative1GridViewAttached*>(qmlAttachedPropertiesObject<QDeclarative1GridView>(item)); - if (attached) - attached->setView(view); - } - ~FxGridItem1() {} - - qreal rowPos() const { - qreal rowPos = 0; - if (view->flow() == QDeclarative1GridView::LeftToRight) { - rowPos = item->y(); - } else { - if (view->effectiveLayoutDirection() == Qt::RightToLeft) - rowPos = -view->cellWidth()-item->x(); - else - rowPos = item->x(); - } - return rowPos; - } - qreal colPos() const { - qreal colPos = 0; - if (view->flow() == QDeclarative1GridView::LeftToRight) { - if (view->effectiveLayoutDirection() == Qt::RightToLeft) { - int colSize = view->cellWidth(); - int columns = view->width()/colSize; - colPos = colSize * (columns-1) - item->x(); - } else { - colPos = item->x(); - } - } else { - colPos = item->y(); - } - - return colPos; - } - - qreal endRowPos() const { - if (view->flow() == QDeclarative1GridView::LeftToRight) { - return item->y() + view->cellHeight() - 1; - } else { - if (view->effectiveLayoutDirection() == Qt::RightToLeft) - return -item->x() - 1; - else - return item->x() + view->cellWidth() - 1; - } - } - void setPosition(qreal col, qreal row) { - if (view->effectiveLayoutDirection() == Qt::RightToLeft) { - if (view->flow() == QDeclarative1GridView::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() == QDeclarative1GridView::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()); - } - - QDeclarativeItem *item; - QDeclarative1GridView *view; - QDeclarative1GridViewAttached *attached; - int index; -}; - -//---------------------------------------------------------------------------- - -class QDeclarative1GridViewPrivate : public QDeclarative1FlickablePrivate -{ - Q_DECLARE_PUBLIC(QDeclarative1GridView) - -public: - QDeclarative1GridViewPrivate() - : currentItem(0), layoutDirection(Qt::LeftToRight), flow(QDeclarative1GridView::LeftToRight) - , visibleIndex(0) , currentIndex(-1) - , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0) - , highlightRangeStart(0), highlightRangeEnd(0) - , highlightRangeStartValid(false), highlightRangeEndValid(false) - , highlightRange(QDeclarative1GridView::NoHighlightRange) - , highlightComponent(0), highlight(0), trackedItem(0) - , moveReason(Other), buffer(0), highlightXAnimator(0), highlightYAnimator(0) - , highlightMoveDuration(150) - , footerComponent(0), footer(0), headerComponent(0), header(0) - , bufferMode(BufferBefore | BufferAfter), snapMode(QDeclarative1GridView::NoSnap) - , ownModel(false), wrap(false), autoHighlight(true) - , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false) - , deferredRelease(false), haveHighlightRange(false), currentIndexCleared(false) {} - - void init(); - void clear(); - FxGridItem1 *createItem(int modelIndex); - void releaseItem(FxGridItem1 *item); - void refill(qreal from, qreal to, bool doBuffer=false); - - void updateGrid(); - void scheduleLayout(); - void layout(); - void updateUnrequestedIndexes(); - void updateUnrequestedPositions(); - void updateTrackedItem(); - void createHighlight(); - void updateHighlight(); - void updateCurrent(int modelIndex); - void updateHeader(); - void updateFooter(); - void fixupPosition(); - - FxGridItem1 *visibleItem(int modelIndex) const { - if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) { - for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) { - FxGridItem1 *item = visibleItems.at(i); - if (item->index == modelIndex) - return item; - } - } - return 0; - } - - bool isRightToLeftTopToBottom() const { - Q_Q(const QDeclarative1GridView); - return flow == QDeclarative1GridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft; - } - - void regenerate() { - Q_Q(QDeclarative1GridView); - if (q->isComponentComplete()) { - clear(); - updateGrid(); - setPosition(0); - q->refill(); - updateCurrent(currentIndex); - } - } - - void mirrorChange() { - Q_Q(QDeclarative1GridView); - regenerate(); - emit q->effectiveLayoutDirectionChanged(); - } - - qreal position() const { - Q_Q(const QDeclarative1GridView); - return flow == QDeclarative1GridView::LeftToRight ? q->contentY() : q->contentX(); - } - void setPosition(qreal pos) { - Q_Q(QDeclarative1GridView); - if (flow == QDeclarative1GridView::LeftToRight) { - q->QDeclarative1Flickable::setContentY(pos); - q->QDeclarative1Flickable::setContentX(0); - } else { - if (q->effectiveLayoutDirection() == Qt::LeftToRight) - q->QDeclarative1Flickable::setContentX(pos); - else - q->QDeclarative1Flickable::setContentX(-pos-size()); - q->QDeclarative1Flickable::setContentY(0); - } - } - int size() const { - Q_Q(const QDeclarative1GridView); - return flow == QDeclarative1GridView::LeftToRight ? q->height() : q->width(); - } - qreal originPosition() const { - qreal pos = 0; - if (!visibleItems.isEmpty()) - pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize(); - return pos; - } - - qreal lastPosition() const { - qreal pos = 0; - if (model && model->count()) - pos = rowPosAt(model->count() - 1) + rowSize(); - return pos; - } - - qreal startPosition() const { - return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition(); - } - - qreal endPosition() const { - return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition(); - - } - - bool isValid() const { - return model && model->count() && model->isValid(); - } - - int rowSize() const { - return flow == QDeclarative1GridView::LeftToRight ? cellHeight : cellWidth; - } - int colSize() const { - return flow == QDeclarative1GridView::LeftToRight ? cellWidth : cellHeight; - } - - qreal colPosAt(int modelIndex) const { - if (FxGridItem1 *item = visibleItem(modelIndex)) - return item->colPos(); - if (!visibleItems.isEmpty()) { - if (modelIndex < visibleIndex) { - int count = (visibleIndex - modelIndex) % columns; - int col = visibleItems.first()->colPos() / colSize(); - col = (columns - count + col) % columns; - return col * colSize(); - } else { - int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns; - return visibleItems.last()->colPos() - count * colSize(); - } - } else { - return (modelIndex % columns) * colSize(); - } - return 0; - } - qreal rowPosAt(int modelIndex) const { - if (FxGridItem1 *item = visibleItem(modelIndex)) - return item->rowPos(); - if (!visibleItems.isEmpty()) { - if (modelIndex < visibleIndex) { - int firstCol = visibleItems.first()->colPos() / colSize(); - int col = visibleIndex - modelIndex + (columns - firstCol - 1); - int rows = col / columns; - return visibleItems.first()->rowPos() - rows * rowSize(); - } else { - int count = modelIndex - visibleItems.last()->index; - int col = visibleItems.last()->colPos() + count * colSize(); - int rows = col / (columns * colSize()); - return visibleItems.last()->rowPos() + rows * rowSize(); - } - } else { - qreal pos = (modelIndex / columns) * rowSize(); - if (header) - pos += headerSize(); - return pos; - } - return 0; - } - - FxGridItem1 *firstVisibleItem() const { - const qreal pos = isRightToLeftTopToBottom() ? -position()-size() : position(); - for (int i = 0; i < visibleItems.count(); ++i) { - FxGridItem1 *item = visibleItems.at(i); - if (item->index != -1 && item->endRowPos() > pos) - return item; - } - return visibleItems.count() ? visibleItems.first() : 0; - } - - int lastVisibleIndex() const { - for (int i = 0; i < visibleItems.count(); ++i) { - FxGridItem1 *item = visibleItems.at(i); - if (item->index != -1) - return item->index; - } - return -1; - } - - // Map a model index to visibleItems list index. - // These may differ if removed items are still present in the visible list, - // e.g. doing a removal animation - int mapFromModel(int modelIndex) const { - if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count()) - return -1; - for (int i = 0; i < visibleItems.count(); ++i) { - FxGridItem1 *listItem = visibleItems.at(i); - if (listItem->index == modelIndex) - return i + visibleIndex; - if (listItem->index > modelIndex) - return -1; - } - return -1; // Not in visibleList - } - - qreal snapPosAt(qreal pos) const { - Q_Q(const QDeclarative1GridView); - qreal snapPos = 0; - if (!visibleItems.isEmpty()) { - qreal highlightStart = isRightToLeftTopToBottom() && highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; - pos += highlightStart; - pos += rowSize()/2; - snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize(); - snapPos = pos - fmodf(pos - snapPos, qreal(rowSize())); - snapPos -= highlightStart; - qreal maxExtent; - qreal minExtent; - if (isRightToLeftTopToBottom()) { - maxExtent = q->minXExtent(); - minExtent = q->maxXExtent(); - } else { - maxExtent = flow == QDeclarative1GridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent(); - minExtent = flow == QDeclarative1GridView::LeftToRight ? -q->minYExtent() : -q->minXExtent(); - } - if (snapPos > maxExtent) - snapPos = maxExtent; - if (snapPos < minExtent) - snapPos = minExtent; - } - return snapPos; - } - - FxGridItem1 *snapItemAt(qreal pos) { - for (int i = 0; i < visibleItems.count(); ++i) { - FxGridItem1 *item = visibleItems[i]; - if (item->index == -1) - continue; - qreal itemTop = item->rowPos(); - if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos) - return item; - } - return 0; - } - - int snapIndex() { - int index = currentIndex; - for (int i = 0; i < visibleItems.count(); ++i) { - FxGridItem1 *item = visibleItems[i]; - if (item->index == -1) - continue; - qreal itemTop = item->rowPos(); - if (itemTop >= highlight->rowPos()-rowSize()/2 && itemTop < highlight->rowPos()+rowSize()/2) { - index = item->index; - if (item->colPos() >= highlight->colPos()-colSize()/2 && item->colPos() < highlight->colPos()+colSize()/2) - return item->index; - } - } - return index; - } - - qreal headerSize() const { - if (!header) - return 0.0; - - return flow == QDeclarative1GridView::LeftToRight - ? header->item->height() - : header->item->width(); - } - - - virtual void itemGeometryChanged(QDeclarativeItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) { - Q_Q(const QDeclarative1GridView); - QDeclarative1FlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry); - if (item == q) { - if (newGeometry.height() != oldGeometry.height() - || newGeometry.width() != oldGeometry.width()) { - if (q->isComponentComplete()) { - updateGrid(); - scheduleLayout(); - } - } - } else if ((header && header->item == item) || (footer && footer->item == item)) { - if (header) - updateHeader(); - if (footer) - updateFooter(); - } - } - - void positionViewAtIndex(int index, int mode); - virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent); - virtual void flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, - QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity); - - // for debugging only - void checkVisible() const { - int skip = 0; - for (int i = 0; i < visibleItems.count(); ++i) { - FxGridItem1 *listItem = visibleItems.at(i); - if (listItem->index == -1) { - ++skip; - } else if (listItem->index != visibleIndex + i - skip) { - for (int j = 0; j < visibleItems.count(); j++) - qDebug() << " index" << j << "item index" << visibleItems.at(j)->index; - qFatal("index %d %d %d", visibleIndex, i, listItem->index); - } - } - } - - QDeclarativeGuard<QDeclarative1VisualModel> model; - QVariant modelVariant; - QList<FxGridItem1*> visibleItems; - QHash<QDeclarativeItem*,int> unrequestedItems; - FxGridItem1 *currentItem; - Qt::LayoutDirection layoutDirection; - QDeclarative1GridView::Flow flow; - int visibleIndex; - int currentIndex; - int cellWidth; - int cellHeight; - int columns; - int requestedIndex; - int itemCount; - qreal highlightRangeStart; - qreal highlightRangeEnd; - bool highlightRangeStartValid; - bool highlightRangeEndValid; - QDeclarative1GridView::HighlightRangeMode highlightRange; - QDeclarativeComponent *highlightComponent; - FxGridItem1 *highlight; - FxGridItem1 *trackedItem; - enum MovementReason { Other, SetIndex, Mouse }; - MovementReason moveReason; - int buffer; - QSmoothedAnimation_1 *highlightXAnimator; - QSmoothedAnimation_1 *highlightYAnimator; - int highlightMoveDuration; - QDeclarativeComponent *footerComponent; - FxGridItem1 *footer; - QDeclarativeComponent *headerComponent; - FxGridItem1 *header; - enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 }; - int bufferMode; - QDeclarative1GridView::SnapMode snapMode; - - bool ownModel : 1; - bool wrap : 1; - bool autoHighlight : 1; - bool fixCurrentVisibility : 1; - bool lazyRelease : 1; - bool layoutScheduled : 1; - bool deferredRelease : 1; - bool haveHighlightRange : 1; - bool currentIndexCleared : 1; -}; - -void QDeclarative1GridViewPrivate::init() -{ - Q_Q(QDeclarative1GridView); - QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped())); - q->setFlag(QGraphicsItem::ItemIsFocusScope); - q->setFlickableDirection(QDeclarative1Flickable::VerticalFlick); - addItemChangeListener(this, Geometry); -} - -void QDeclarative1GridViewPrivate::clear() -{ - for (int i = 0; i < visibleItems.count(); ++i) - releaseItem(visibleItems.at(i)); - visibleItems.clear(); - visibleIndex = 0; - releaseItem(currentItem); - currentItem = 0; - createHighlight(); - trackedItem = 0; - itemCount = 0; -} - -FxGridItem1 *QDeclarative1GridViewPrivate::createItem(int modelIndex) -{ - Q_Q(QDeclarative1GridView); - // create object - requestedIndex = modelIndex; - FxGridItem1 *listItem = 0; - if (QDeclarativeItem *item = model->item(modelIndex, false)) { - listItem = new FxGridItem1(item, q); - listItem->index = modelIndex; - if (model->completePending()) { - // complete - listItem->item->setZValue(1); - listItem->item->setParentItem(q->contentItem()); - model->completeItem(); - } else { - listItem->item->setParentItem(q->contentItem()); - } - unrequestedItems.remove(listItem->item); - } - requestedIndex = -1; - return listItem; -} - - -void QDeclarative1GridViewPrivate::releaseItem(FxGridItem1 *item) -{ - Q_Q(QDeclarative1GridView); - if (!item || !model) - return; - if (trackedItem == item) { - QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged())); - QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged())); - trackedItem = 0; - } - if (model->release(item->item) == 0) { - // item was not destroyed, and we no longer reference it. - unrequestedItems.insert(item->item, model->indexOf(item->item, q)); - } - delete item; -} - -void QDeclarative1GridViewPrivate::refill(qreal from, qreal to, bool doBuffer) -{ - Q_Q(QDeclarative1GridView); - if (!isValid() || !q->isComponentComplete()) - return; - itemCount = model->count(); - qreal bufferFrom = from - buffer; - qreal bufferTo = to + buffer; - qreal fillFrom = from; - qreal fillTo = to; - if (doBuffer && (bufferMode & BufferAfter)) - fillTo = bufferTo; - if (doBuffer && (bufferMode & BufferBefore)) - fillFrom = bufferFrom; - - bool changed = false; - - int colPos = colPosAt(visibleIndex); - int rowPos = rowPosAt(visibleIndex); - int modelIndex = visibleIndex; - if (visibleItems.count()) { - rowPos = visibleItems.last()->rowPos(); - colPos = visibleItems.last()->colPos() + colSize(); - if (colPos > colSize() * (columns-1)) { - colPos = 0; - rowPos += rowSize(); - } - int i = visibleItems.count() - 1; - while (i > 0 && visibleItems.at(i)->index == -1) - --i; - modelIndex = visibleItems.at(i)->index + 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 = colPos / colSize(); - - FxGridItem1 *item = 0; - - // Item creation and release is staggered in order to avoid - // creating/releasing multiple items in one frame - // while flicking (as much as possible). - while (modelIndex < model->count() && rowPos <= fillTo + rowSize()*(columns - colNum)/(columns+1)) { -// qDebug() << "refill: append item" << modelIndex; - if (!(item = createItem(modelIndex))) - break; - item->setPosition(colPos, rowPos); - visibleItems.append(item); - colPos += colSize(); - colNum++; - if (colPos > colSize() * (columns-1)) { - colPos = 0; - colNum = 0; - rowPos += rowSize(); - } - ++modelIndex; - changed = true; - if (doBuffer) // never buffer more than one item per frame - break; - } - - if (visibleItems.count()) { - rowPos = visibleItems.first()->rowPos(); - colPos = visibleItems.first()->colPos() - colSize(); - if (colPos < 0) { - colPos = colSize() * (columns - 1); - rowPos -= rowSize(); - } - } - colNum = colPos / 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 = createItem(visibleIndex-1))) - break; - --visibleIndex; - item->setPosition(colPos, rowPos); - visibleItems.prepend(item); - colPos -= colSize(); - colNum--; - if (colPos < 0) { - colPos = colSize() * (columns - 1); - colNum = columns-1; - rowPos -= rowSize(); - } - changed = true; - if (doBuffer) // never buffer more than one item per frame - break; - } - - if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create - while (visibleItems.count() > 1 - && (item = 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 = 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; - } - deferredRelease = false; - } else { - deferredRelease = true; - } - if (changed) { - if (header) - updateHeader(); - if (footer) - updateFooter(); - if (flow == QDeclarative1GridView::LeftToRight) - q->setContentHeight(endPosition() - startPosition()); - else - q->setContentWidth(endPosition() - startPosition()); - } else if (!doBuffer && buffer && bufferMode != NoBuffer) { - refill(from, to, true); - } - lazyRelease = false; -} - -void QDeclarative1GridViewPrivate::updateGrid() -{ - Q_Q(QDeclarative1GridView); - - columns = (int)qMax((flow == QDeclarative1GridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.)); - if (isValid()) { - if (flow == QDeclarative1GridView::LeftToRight) - q->setContentHeight(endPosition() - startPosition()); - else - q->setContentWidth(lastPosition() - originPosition()); - } -} - -void QDeclarative1GridViewPrivate::scheduleLayout() -{ - Q_Q(QDeclarative1GridView); - if (!layoutScheduled) { - layoutScheduled = true; - QCoreApplication::postEvent(q, new QEvent(QEvent::User), Qt::HighEventPriority); - } -} - -void QDeclarative1GridViewPrivate::layout() -{ - Q_Q(QDeclarative1GridView); - layoutScheduled = false; - if (!isValid() && !visibleItems.count()) { - clear(); - return; - } - if (visibleItems.count()) { - qreal rowPos = visibleItems.first()->rowPos(); - qreal colPos = visibleItems.first()->colPos(); - int col = visibleIndex % columns; - if (colPos != col * colSize()) { - colPos = col * colSize(); - visibleItems.first()->setPosition(colPos, rowPos); - } - for (int i = 1; i < visibleItems.count(); ++i) { - FxGridItem1 *item = visibleItems.at(i); - colPos += colSize(); - if (colPos > colSize() * (columns-1)) { - colPos = 0; - rowPos += rowSize(); - } - item->setPosition(colPos, rowPos); - } - } - if (header) - updateHeader(); - if (footer) - updateFooter(); - q->refill(); - updateHighlight(); - moveReason = Other; - if (flow == QDeclarative1GridView::LeftToRight) { - q->setContentHeight(endPosition() - startPosition()); - fixupY(); - } else { - q->setContentWidth(endPosition() - startPosition()); - fixupX(); - } - updateUnrequestedPositions(); -} - -void QDeclarative1GridViewPrivate::updateUnrequestedIndexes() -{ - Q_Q(QDeclarative1GridView); - QHash<QDeclarativeItem*,int>::iterator it; - for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) - *it = model->indexOf(it.key(), q); -} - -void QDeclarative1GridViewPrivate::updateUnrequestedPositions() -{ - QHash<QDeclarativeItem*,int>::const_iterator it; - for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) { - QDeclarativeItem *item = it.key(); - if (flow == QDeclarative1GridView::LeftToRight) { - item->setPos(QPointF(colPosAt(*it), rowPosAt(*it))); - } else { - if (isRightToLeftTopToBottom()) - item->setPos(QPointF(-rowPosAt(*it)-item->width(), colPosAt(*it))); - else - item->setPos(QPointF(rowPosAt(*it), colPosAt(*it))); - } - } -} - -void QDeclarative1GridViewPrivate::updateTrackedItem() -{ - Q_Q(QDeclarative1GridView); - FxGridItem1 *item = currentItem; - if (highlight) - item = highlight; - - if (trackedItem && item != trackedItem) { - QObject::disconnect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged())); - QObject::disconnect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged())); - trackedItem = 0; - } - - if (!trackedItem && item) { - trackedItem = item; - QObject::connect(trackedItem->item, SIGNAL(yChanged()), q, SLOT(trackedPositionChanged())); - QObject::connect(trackedItem->item, SIGNAL(xChanged()), q, SLOT(trackedPositionChanged())); - } - if (trackedItem) - q->trackedPositionChanged(); -} - -void QDeclarative1GridViewPrivate::createHighlight() -{ - Q_Q(QDeclarative1GridView); - bool changed = false; - if (highlight) { - if (trackedItem == highlight) - trackedItem = 0; - if (highlight->item->scene()) - highlight->item->scene()->removeItem(highlight->item); - highlight->item->deleteLater(); - delete highlight; - highlight = 0; - delete highlightXAnimator; - delete highlightYAnimator; - highlightXAnimator = 0; - highlightYAnimator = 0; - changed = true; - } - - if (currentItem) { - QDeclarativeItem *item = 0; - if (highlightComponent) { - QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q)); - QObject *nobj = highlightComponent->create(highlightContext); - if (nobj) { - QDeclarative_setParent_noEvent(highlightContext, nobj); - item = qobject_cast<QDeclarativeItem *>(nobj); - if (!item) - delete nobj; - } else { - delete highlightContext; - } - } else { - item = new QDeclarativeItem; - QDeclarative_setParent_noEvent(item, q->contentItem()); - item->setParentItem(q->contentItem()); - } - if (item) { - QDeclarative_setParent_noEvent(item, q->contentItem()); - item->setParentItem(q->contentItem()); - highlight = new FxGridItem1(item, q); - if (currentItem && autoHighlight) - highlight->setPosition(currentItem->colPos(), currentItem->rowPos()); - highlightXAnimator = new QSmoothedAnimation_1(q); - highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x")); - highlightXAnimator->userDuration = highlightMoveDuration; - highlightYAnimator = new QSmoothedAnimation_1(q); - highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y")); - highlightYAnimator->userDuration = highlightMoveDuration; - if (autoHighlight) { - highlightXAnimator->restart(); - highlightYAnimator->restart(); - } - changed = true; - } - } - if (changed) - emit q->highlightItemChanged(); -} - -void QDeclarative1GridViewPrivate::updateHighlight() -{ - if ((!currentItem && highlight) || (currentItem && !highlight)) - createHighlight(); - if (currentItem && autoHighlight && highlight && !hData.moving && !vData.moving) { - // 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 QDeclarative1GridViewPrivate::updateCurrent(int modelIndex) -{ - Q_Q(QDeclarative1GridView); - if (!q->isComponentComplete() || !isValid() || modelIndex < 0 || modelIndex >= model->count()) { - if (currentItem) { - currentItem->attached->setIsCurrentItem(false); - releaseItem(currentItem); - currentItem = 0; - currentIndex = modelIndex; - emit q->currentIndexChanged(); - updateHighlight(); - } else if (currentIndex != modelIndex) { - currentIndex = modelIndex; - emit q->currentIndexChanged(); - } - return; - } - - if (currentItem && currentIndex == modelIndex) { - updateHighlight(); - return; - } - - FxGridItem1 *oldCurrentItem = currentItem; - currentIndex = modelIndex; - currentItem = createItem(modelIndex); - fixCurrentVisibility = true; - if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item)) - oldCurrentItem->attached->setIsCurrentItem(false); - if (currentItem) { - currentItem->setPosition(colPosAt(modelIndex), rowPosAt(modelIndex)); - currentItem->item->setFocus(true); - currentItem->attached->setIsCurrentItem(true); - } - updateHighlight(); - emit q->currentIndexChanged(); - releaseItem(oldCurrentItem); -} - -void QDeclarative1GridViewPrivate::updateFooter() -{ - Q_Q(QDeclarative1GridView); - if (!footer && footerComponent) { - QDeclarativeItem *item = 0; - QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q)); - QObject *nobj = footerComponent->create(context); - if (nobj) { - QDeclarative_setParent_noEvent(context, nobj); - item = qobject_cast<QDeclarativeItem *>(nobj); - if (!item) - delete nobj; - } else { - delete context; - } - if (item) { - QDeclarative_setParent_noEvent(item, q->contentItem()); - item->setParentItem(q->contentItem()); - item->setZValue(1); - QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item)); - itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry); - footer = new FxGridItem1(item, q); - } - } - if (footer) { - qreal colOffset = 0; - qreal rowOffset; - if (isRightToLeftTopToBottom()) { - rowOffset = footer->item->width()-cellWidth; - } else { - rowOffset = 0; - if (q->effectiveLayoutDirection() == Qt::RightToLeft) - colOffset = footer->item->width()-cellWidth; - } - if (visibleItems.count()) { - qreal endPos = lastPosition(); - if (lastVisibleIndex() == model->count()-1) { - footer->setPosition(colOffset, endPos + rowOffset); - } else { - qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size(); - if (endPos <= visiblePos || footer->endRowPos() < endPos + rowOffset) - footer->setPosition(colOffset, endPos + rowOffset); - } - } else { - qreal endPos = 0; - if (header) { - endPos += flow == QDeclarative1GridView::LeftToRight ? header->item->height() : header->item->width(); - } - footer->setPosition(colOffset, endPos); - } - } -} - -void QDeclarative1GridViewPrivate::updateHeader() -{ - Q_Q(QDeclarative1GridView); - if (!header && headerComponent) { - QDeclarativeItem *item = 0; - QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q)); - QObject *nobj = headerComponent->create(context); - if (nobj) { - QDeclarative_setParent_noEvent(context, nobj); - item = qobject_cast<QDeclarativeItem *>(nobj); - if (!item) - delete nobj; - } else { - delete context; - } - if (item) { - QDeclarative_setParent_noEvent(item, q->contentItem()); - item->setParentItem(q->contentItem()); - item->setZValue(1); - QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item)); - itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry); - header = new FxGridItem1(item, q); - } - } - if (header) { - qreal colOffset = 0; - qreal rowOffset; - if (isRightToLeftTopToBottom()) { - rowOffset = -cellWidth; - } else { - rowOffset = -headerSize(); - if (q->effectiveLayoutDirection() == Qt::RightToLeft) - colOffset = header->item->width()-cellWidth; - } - if (visibleItems.count()) { - qreal startPos = originPosition(); - if (visibleIndex == 0) { - header->setPosition(colOffset, startPos + rowOffset); - } else { - qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position(); - qreal headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos(); - if (tempPos <= startPos || headerPos > startPos + rowOffset) - header->setPosition(colOffset, startPos + rowOffset); - } - } else { - header->setPosition(colOffset, 0); - } - } -} - -void QDeclarative1GridViewPrivate::fixupPosition() -{ - moveReason = Other; - if (flow == QDeclarative1GridView::LeftToRight) - fixupY(); - else - fixupX(); -} - -void QDeclarative1GridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent) -{ - if ((flow == QDeclarative1GridView::TopToBottom && &data == &vData) - || (flow == QDeclarative1GridView::LeftToRight && &data == &hData)) - return; - - fixupMode = moveReason == Mouse ? fixupMode : Immediate; - - qreal highlightStart; - qreal highlightEnd; - qreal viewPos; - if (isRightToLeftTopToBottom()) { - // Handle Right-To-Left exceptions - viewPos = -position()-size(); - highlightStart = highlightRangeStartValid ? size()-highlightRangeEnd : highlightRangeStart; - highlightEnd = highlightRangeEndValid ? size()-highlightRangeStart : highlightRangeEnd; - } else { - viewPos = position(); - highlightStart = highlightRangeStart; - highlightEnd = highlightRangeEnd; - } - - bool strictHighlightRange = haveHighlightRange && highlightRange == QDeclarative1GridView::StrictlyEnforceRange; - - if (snapMode != QDeclarative1GridView::NoSnap) { - qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position(); - if (snapMode == QDeclarative1GridView::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; - } - FxGridItem1 *topItem = snapItemAt(tempPosition+highlightStart); - if (!topItem && strictHighlightRange && currentItem) { - // StrictlyEnforceRange always keeps an item in range - updateHighlight(); - topItem = currentItem; - } - FxGridItem1 *bottomItem = snapItemAt(tempPosition+highlightEnd); - 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)) { - if (topItem->index == 0 && header && tempPosition+highlightStart < header->rowPos()+headerSize()/2 && !strictHighlightRange) { - pos = isRightToLeftTopToBottom() ? - header->rowPos() + highlightStart - size() : header->rowPos() - highlightStart; - } else { - if (isRightToLeftTopToBottom()) - pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent); - else - pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent); - } - } else if (bottomItem && isInBounds) { - if (isRightToLeftTopToBottom()) - pos = qMax(qMin(-bottomItem->rowPos() + highlightEnd - size(), -maxExtent), -minExtent); - else - pos = qMax(qMin(bottomItem->rowPos() - highlightEnd, -maxExtent), -minExtent); - } else { - QDeclarative1FlickablePrivate::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 == QDeclarative1GridView::StrictlyEnforceRange) { - if (currentItem) { - updateHighlight(); - qreal pos = currentItem->rowPos(); - if (viewPos < pos + rowSize() - highlightEnd) - viewPos = pos + rowSize() - highlightEnd; - if (viewPos > pos - highlightStart) - viewPos = pos - highlightStart; - 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 { - QDeclarative1FlickablePrivate::fixup(data, minExtent, maxExtent); - } - data.inOvershoot = false; - fixupMode = Normal; -} - -void QDeclarative1GridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize, - QDeclarative1TimeLineCallback::Callback fixupCallback, qreal velocity) -{ - Q_Q(QDeclarative1GridView); - data.fixingUp = false; - moveReason = Mouse; - if ((!haveHighlightRange || highlightRange != QDeclarative1GridView::StrictlyEnforceRange) - && snapMode == QDeclarative1GridView::NoSnap) { - QDeclarative1FlickablePrivate::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 == QDeclarative1GridView::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 == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange) - data.flickTarget = minExtent; - } else { - if (data.move.value() > maxExtent) { - if (snapMode == QDeclarative1GridView::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 == QDeclarative1GridView::NoSnap && highlightRange != QDeclarative1GridView::StrictlyEnforceRange) - data.flickTarget = maxExtent; - } - - bool overShoot = boundsBehavior == QDeclarative1Flickable::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 == QDeclarative1GridView::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 != QDeclarative1GridView::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(QDeclarative1TimeLineCallback(&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 QDeclarative1GridView - \inqmlmodule QtQuick 1 - \since QtQuick 1.0 - \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/qtquick1/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/qtquick1/gridview/gridview.qml import - \codeline - \snippet doc/src/snippets/qtquick1/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/qtquick1/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/qtquick1/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} -*/ -QDeclarative1GridView::QDeclarative1GridView(QDeclarativeItem *parent) - : QDeclarative1Flickable(*(new QDeclarative1GridViewPrivate), parent) -{ - Q_D(QDeclarative1GridView); - d->init(); -} - -QDeclarative1GridView::~QDeclarative1GridView() -{ - Q_D(QDeclarative1GridView); - d->clear(); - if (d->ownModel) - delete d->model; - delete d->header; - delete d->footer; -} - -/*! - \qmlattachedproperty bool 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 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/qtquick1/gridview/gridview.qml isCurrentItem -*/ - -/*! - \qmlattachedproperty bool 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/qtquick1/gridview/gridview.qml delayRemove -*/ - -/*! - \qmlattachedsignal QtQuick1::GridView::onAdd() - This attached handler is called immediately after an item is added to the view. -*/ - -/*! - \qmlattachedsignal QtQuick1::GridView::onRemove() - This attached handler is called immediately before an item is removed from the view. -*/ - - -/*! - \qmlproperty model QtQuick1::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} -*/ -QVariant QDeclarative1GridView::model() const -{ - Q_D(const QDeclarative1GridView); - return d->modelVariant; -} - -// For internal use -int QDeclarative1GridView::modelCount() const -{ - Q_D(const QDeclarative1GridView); - return d->model->count(); -} - -void QDeclarative1GridView::setModel(const QVariant &model) -{ - Q_D(QDeclarative1GridView); - if (d->modelVariant == model) - return; - if (d->model) { - disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); - disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); - disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); - disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset())); - disconnect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*))); - disconnect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*))); - } - d->clear(); - d->modelVariant = model; - QObject *object = qvariant_cast<QObject*>(model); - QDeclarative1VisualModel *vim = 0; - if (object && (vim = qobject_cast<QDeclarative1VisualModel *>(object))) { - if (d->ownModel) { - delete d->model; - d->ownModel = false; - } - d->model = vim; - } else { - if (!d->ownModel) { - d->model = new QDeclarative1VisualDataModel(qmlContext(this), this); - d->ownModel = true; - } - if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model)) - dataModel->setModel(model); - } - if (d->model) { - d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore | QDeclarative1GridViewPrivate::BufferAfter; - if (isComponentComplete()) { - refill(); - if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) { - setCurrentIndex(0); - } else { - d->moveReason = QDeclarative1GridViewPrivate::SetIndex; - d->updateCurrent(d->currentIndex); - if (d->highlight && d->currentItem) { - if (d->autoHighlight) - d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos()); - d->updateTrackedItem(); - } - d->moveReason = QDeclarative1GridViewPrivate::Other; - } - } - connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int))); - connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int))); - connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int))); - connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset())); - connect(d->model, SIGNAL(createdItem(int,QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*))); - connect(d->model, SIGNAL(destroyingItem(QDeclarativeItem*)), this, SLOT(destroyingItem(QDeclarativeItem*))); - emit countChanged(); - } - emit modelChanged(); -} - -/*! - \qmlproperty Component QtQuick1::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. -*/ -QDeclarativeComponent *QDeclarative1GridView::delegate() const -{ - Q_D(const QDeclarative1GridView); - if (d->model) { - if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model)) - return dataModel->delegate(); - } - - return 0; -} - -void QDeclarative1GridView::setDelegate(QDeclarativeComponent *delegate) -{ - Q_D(QDeclarative1GridView); - if (delegate == this->delegate()) - return; - - if (!d->ownModel) { - d->model = new QDeclarative1VisualDataModel(qmlContext(this)); - d->ownModel = true; - } - if (QDeclarative1VisualDataModel *dataModel = qobject_cast<QDeclarative1VisualDataModel*>(d->model)) { - int oldCount = dataModel->count(); - dataModel->setDelegate(delegate); - if (isComponentComplete()) { - for (int i = 0; i < d->visibleItems.count(); ++i) - d->releaseItem(d->visibleItems.at(i)); - d->visibleItems.clear(); - d->releaseItem(d->currentItem); - d->currentItem = 0; - refill(); - d->moveReason = QDeclarative1GridViewPrivate::SetIndex; - d->updateCurrent(d->currentIndex); - if (d->highlight && d->currentItem) { - if (d->autoHighlight) - d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos()); - d->updateTrackedItem(); - } - d->moveReason = QDeclarative1GridViewPrivate::Other; - } - if (oldCount != dataModel->count()) - emit countChanged(); - emit delegateChanged(); - } -} - -/*! - \qmlproperty int QtQuick1::GridView::currentIndex - \qmlproperty Item QtQuick1::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. -*/ -int QDeclarative1GridView::currentIndex() const -{ - Q_D(const QDeclarative1GridView); - return d->currentIndex; -} - -void QDeclarative1GridView::setCurrentIndex(int index) -{ - Q_D(QDeclarative1GridView); - if (d->requestedIndex >= 0) // currently creating item - return; - d->currentIndexCleared = (index == -1); - if (index == d->currentIndex) - return; - if (isComponentComplete() && d->isValid()) { - if (d->layoutScheduled) - d->layout(); - d->moveReason = QDeclarative1GridViewPrivate::SetIndex; - d->updateCurrent(index); - } else { - d->currentIndex = index; - emit currentIndexChanged(); - } -} - -QDeclarativeItem *QDeclarative1GridView::currentItem() -{ - Q_D(QDeclarative1GridView); - if (!d->currentItem) - return 0; - return d->currentItem->item; -} - -/*! - \qmlproperty Item QtQuick1::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 -*/ -QDeclarativeItem *QDeclarative1GridView::highlightItem() -{ - Q_D(QDeclarative1GridView); - if (!d->highlight) - return 0; - return d->highlight->item; -} - -/*! - \qmlproperty int QtQuick1::GridView::count - This property holds the number of items in the view. -*/ -int QDeclarative1GridView::count() const -{ - Q_D(const QDeclarative1GridView); - if (d->model) - return d->model->count(); - return 0; -} - -/*! - \qmlproperty Component QtQuick1::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 -*/ -QDeclarativeComponent *QDeclarative1GridView::highlight() const -{ - Q_D(const QDeclarative1GridView); - return d->highlightComponent; -} - -void QDeclarative1GridView::setHighlight(QDeclarativeComponent *highlight) -{ - Q_D(QDeclarative1GridView); - if (highlight != d->highlightComponent) { - d->highlightComponent = highlight; - d->updateCurrent(d->currentIndex); - emit highlightChanged(); - } -} - -/*! - \qmlproperty bool QtQuick1::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/qtquick1/gridview/gridview.qml highlightFollowsCurrentItem -*/ -bool QDeclarative1GridView::highlightFollowsCurrentItem() const -{ - Q_D(const QDeclarative1GridView); - return d->autoHighlight; -} - -void QDeclarative1GridView::setHighlightFollowsCurrentItem(bool autoHighlight) -{ - Q_D(QDeclarative1GridView); - if (d->autoHighlight != autoHighlight) { - d->autoHighlight = autoHighlight; - if (autoHighlight) { - d->updateHighlight(); - } else if (d->highlightXAnimator) { - d->highlightXAnimator->stop(); - d->highlightYAnimator->stop(); - } - } -} - -/*! - \qmlproperty int QtQuick1::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 -*/ -int QDeclarative1GridView::highlightMoveDuration() const -{ - Q_D(const QDeclarative1GridView); - return d->highlightMoveDuration; -} - -void QDeclarative1GridView::setHighlightMoveDuration(int duration) -{ - Q_D(QDeclarative1GridView); - if (d->highlightMoveDuration != duration) { - d->highlightMoveDuration = duration; - if (d->highlightYAnimator) { - d->highlightXAnimator->userDuration = d->highlightMoveDuration; - d->highlightYAnimator->userDuration = d->highlightMoveDuration; - } - emit highlightMoveDurationChanged(); - } -} - - -/*! - \qmlproperty real QtQuick1::GridView::preferredHighlightBegin - \qmlproperty real QtQuick1::GridView::preferredHighlightEnd - \qmlproperty enumeration QtQuick1::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 -*/ -qreal QDeclarative1GridView::preferredHighlightBegin() const -{ - Q_D(const QDeclarative1GridView); - return d->highlightRangeStart; -} - -void QDeclarative1GridView::setPreferredHighlightBegin(qreal start) -{ - Q_D(QDeclarative1GridView); - d->highlightRangeStartValid = true; - if (d->highlightRangeStart == start) - return; - d->highlightRangeStart = start; - d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd; - emit preferredHighlightBeginChanged(); -} - -void QDeclarative1GridView::resetPreferredHighlightBegin() -{ - Q_D(QDeclarative1GridView); - d->highlightRangeStartValid = false; - if (d->highlightRangeStart == 0) - return; - d->highlightRangeStart = 0; - emit preferredHighlightBeginChanged(); -} - -qreal QDeclarative1GridView::preferredHighlightEnd() const -{ - Q_D(const QDeclarative1GridView); - return d->highlightRangeEnd; -} - -void QDeclarative1GridView::setPreferredHighlightEnd(qreal end) -{ - Q_D(QDeclarative1GridView); - d->highlightRangeEndValid = true; - if (d->highlightRangeEnd == end) - return; - d->highlightRangeEnd = end; - d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd; - emit preferredHighlightEndChanged(); -} - -void QDeclarative1GridView::resetPreferredHighlightEnd() -{ - Q_D(QDeclarative1GridView); - d->highlightRangeEndValid = false; - if (d->highlightRangeEnd == 0) - return; - d->highlightRangeEnd = 0; - emit preferredHighlightEndChanged(); -} - -QDeclarative1GridView::HighlightRangeMode QDeclarative1GridView::highlightRangeMode() const -{ - Q_D(const QDeclarative1GridView); - return d->highlightRange; -} - -void QDeclarative1GridView::setHighlightRangeMode(HighlightRangeMode mode) -{ - Q_D(QDeclarative1GridView); - if (d->highlightRange == mode) - return; - d->highlightRange = mode; - d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd; - emit highlightRangeModeChanged(); -} - -/*! - \qmlproperty enumeration QtQuick1::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. -*/ - -Qt::LayoutDirection QDeclarative1GridView::layoutDirection() const -{ - Q_D(const QDeclarative1GridView); - return d->layoutDirection; -} - -void QDeclarative1GridView::setLayoutDirection(Qt::LayoutDirection layoutDirection) -{ - Q_D(QDeclarative1GridView); - if (d->layoutDirection != layoutDirection) { - d->layoutDirection = layoutDirection; - d->regenerate(); - emit layoutDirectionChanged(); - emit effectiveLayoutDirectionChanged(); - } -} - -/*! - \qmlproperty enumeration QtQuick1::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} -*/ - -Qt::LayoutDirection QDeclarative1GridView::effectiveLayoutDirection() const -{ - Q_D(const QDeclarative1GridView); - if (d->effectiveLayoutMirror) - return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft; - else - return d->layoutDirection; -} - -/*! - \qmlproperty enumeration QtQuick1::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 -*/ -QDeclarative1GridView::Flow QDeclarative1GridView::flow() const -{ - Q_D(const QDeclarative1GridView); - return d->flow; -} - -void QDeclarative1GridView::setFlow(Flow flow) -{ - Q_D(QDeclarative1GridView); - if (d->flow != flow) { - d->flow = flow; - if (d->flow == LeftToRight) { - setContentWidth(-1); - setFlickableDirection(QDeclarative1Flickable::VerticalFlick); - } else { - setContentHeight(-1); - setFlickableDirection(QDeclarative1Flickable::HorizontalFlick); - } - setContentX(0); - setContentY(0); - d->regenerate(); - emit flowChanged(); - } -} - -/*! - \qmlproperty bool QtQuick1::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. -*/ -bool QDeclarative1GridView::isWrapEnabled() const -{ - Q_D(const QDeclarative1GridView); - return d->wrap; -} - -void QDeclarative1GridView::setWrapEnabled(bool wrap) -{ - Q_D(QDeclarative1GridView); - if (d->wrap == wrap) - return; - d->wrap = wrap; - emit keyNavigationWrapsChanged(); -} - -/*! - \qmlproperty int QtQuick1::GridView::cacheBuffer - This property determines whether delegates are retained outside the - visible area of the view. - - If non-zero the view will 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 and \c cacheBuffer is - set to 40, then up to 2 delegates above and 2 delegates below the visible - area may be retained. - - 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. -*/ -int QDeclarative1GridView::cacheBuffer() const -{ - Q_D(const QDeclarative1GridView); - return d->buffer; -} - -void QDeclarative1GridView::setCacheBuffer(int buffer) -{ - Q_D(QDeclarative1GridView); - if (d->buffer != buffer) { - d->buffer = buffer; - if (isComponentComplete()) - refill(); - emit cacheBufferChanged(); - } -} - -/*! - \qmlproperty int QtQuick1::GridView::cellWidth - \qmlproperty int QtQuick1::GridView::cellHeight - - These properties holds the width and height of each cell in the grid. - - The default cell size is 100x100. -*/ -int QDeclarative1GridView::cellWidth() const -{ - Q_D(const QDeclarative1GridView); - return d->cellWidth; -} - -void QDeclarative1GridView::setCellWidth(int cellWidth) -{ - Q_D(QDeclarative1GridView); - if (cellWidth != d->cellWidth && cellWidth > 0) { - d->cellWidth = qMax(1, cellWidth); - d->updateGrid(); - emit cellWidthChanged(); - d->layout(); - } -} - -int QDeclarative1GridView::cellHeight() const -{ - Q_D(const QDeclarative1GridView); - return d->cellHeight; -} - -void QDeclarative1GridView::setCellHeight(int cellHeight) -{ - Q_D(QDeclarative1GridView); - if (cellHeight != d->cellHeight && cellHeight > 0) { - d->cellHeight = qMax(1, cellHeight); - d->updateGrid(); - emit cellHeightChanged(); - d->layout(); - } -} -/*! - \qmlproperty enumeration QtQuick1::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 - -*/ -QDeclarative1GridView::SnapMode QDeclarative1GridView::snapMode() const -{ - Q_D(const QDeclarative1GridView); - return d->snapMode; -} - -void QDeclarative1GridView::setSnapMode(SnapMode mode) -{ - Q_D(QDeclarative1GridView); - if (d->snapMode != mode) { - d->snapMode = mode; - emit snapModeChanged(); - } -} - -/*! - \qmlproperty Component QtQuick1::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 -*/ -QDeclarativeComponent *QDeclarative1GridView::footer() const -{ - Q_D(const QDeclarative1GridView); - return d->footerComponent; -} - -void QDeclarative1GridView::setFooter(QDeclarativeComponent *footer) -{ - Q_D(QDeclarative1GridView); - if (d->footerComponent != footer) { - if (d->footer) { - if (scene()) - scene()->removeItem(d->footer->item); - d->footer->item->deleteLater(); - delete d->footer; - d->footer = 0; - } - d->footerComponent = footer; - if (isComponentComplete()) { - d->updateFooter(); - d->updateGrid(); - d->fixupPosition(); - } - emit footerChanged(); - } -} - -/*! - \qmlproperty Component QtQuick1::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 -*/ -QDeclarativeComponent *QDeclarative1GridView::header() const -{ - Q_D(const QDeclarative1GridView); - return d->headerComponent; -} - -void QDeclarative1GridView::setHeader(QDeclarativeComponent *header) -{ - Q_D(QDeclarative1GridView); - if (d->headerComponent != header) { - if (d->header) { - if (scene()) - scene()->removeItem(d->header->item); - d->header->item->deleteLater(); - delete d->header; - d->header = 0; - } - d->headerComponent = header; - if (isComponentComplete()) { - d->updateHeader(); - d->updateFooter(); - d->updateGrid(); - d->fixupPosition(); - } - emit headerChanged(); - } -} - -void QDeclarative1GridView::setContentX(qreal pos) -{ - Q_D(QDeclarative1GridView); - // Positioning the view manually should override any current movement state - d->moveReason = QDeclarative1GridViewPrivate::Other; - QDeclarative1Flickable::setContentX(pos); -} - -void QDeclarative1GridView::setContentY(qreal pos) -{ - Q_D(QDeclarative1GridView); - // Positioning the view manually should override any current movement state - d->moveReason = QDeclarative1GridViewPrivate::Other; - QDeclarative1Flickable::setContentY(pos); -} - -bool QDeclarative1GridView::event(QEvent *event) -{ - Q_D(QDeclarative1GridView); - if (event->type() == QEvent::User) { - if (d->layoutScheduled) - d->layout(); - return true; - } - - return QDeclarative1Flickable::event(event); -} - -void QDeclarative1GridView::viewportMoved() -{ - Q_D(QDeclarative1GridView); - QDeclarative1Flickable::viewportMoved(); - if (!d->itemCount) - return; - d->lazyRelease = true; - if (d->hData.flicking || d->vData.flicking) { - if (yflick()) { - if (d->vData.velocity > 0) - d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore; - else if (d->vData.velocity < 0) - d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter; - } - - if (xflick()) { - if (d->hData.velocity > 0) - d->bufferMode = QDeclarative1GridViewPrivate::BufferBefore; - else if (d->hData.velocity < 0) - d->bufferMode = QDeclarative1GridViewPrivate::BufferAfter; - } - } - refill(); - if (d->hData.flicking || d->vData.flicking || d->hData.moving || d->vData.moving) - d->moveReason = QDeclarative1GridViewPrivate::Mouse; - if (d->moveReason != QDeclarative1GridViewPrivate::SetIndex) { - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) { - // reposition highlight - qreal pos = d->highlight->rowPos(); - qreal viewPos; - qreal highlightStart; - qreal highlightEnd; - if (d->isRightToLeftTopToBottom()) { - highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart; - highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd; - viewPos = -d->position()-d->size(); - } else { - highlightStart = d->highlightRangeStart; - highlightEnd = d->highlightRangeEnd; - viewPos = d->position(); - } - if (pos > viewPos + highlightEnd - d->rowSize()) - pos = viewPos + highlightEnd - d->rowSize(); - if (pos < viewPos + highlightStart) - pos = viewPos + highlightStart; - - d->highlight->setPosition(d->highlight->colPos(), qRound(pos)); - - // update current index - int idx = d->snapIndex(); - if (idx >= 0 && idx != d->currentIndex) { - d->updateCurrent(idx); - if (d->currentItem && d->currentItem->colPos() != d->highlight->colPos() && d->autoHighlight) { - if (d->flow == LeftToRight) - d->highlightXAnimator->to = d->currentItem->item->x(); - else - d->highlightYAnimator->to = d->currentItem->item->y(); - } - } - } - } -} - -qreal QDeclarative1GridView::minYExtent() const -{ - Q_D(const QDeclarative1GridView); - if (d->flow == QDeclarative1GridView::TopToBottom) - return QDeclarative1Flickable::minYExtent(); - qreal extent = -d->startPosition(); - if (d->header && d->visibleItems.count()) - extent += d->header->item->height(); - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { - extent += d->highlightRangeStart; - extent = qMax(extent, -(d->rowPosAt(0) + d->rowSize() - d->highlightRangeEnd)); - } - return extent; -} - -qreal QDeclarative1GridView::maxYExtent() const -{ - Q_D(const QDeclarative1GridView); - if (d->flow == QDeclarative1GridView::TopToBottom) - return QDeclarative1Flickable::maxYExtent(); - qreal extent; - if (!d->model || !d->model->count()) { - extent = 0; - } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { - extent = -(d->rowPosAt(d->model->count()-1) - d->highlightRangeStart); - if (d->highlightRangeEnd != d->highlightRangeStart) - extent = qMin(extent, -(d->endPosition() - d->highlightRangeEnd + 1)); - } else { - extent = -(d->endPosition() - height()); - } - if (d->footer) - extent -= d->footer->item->height(); - const qreal minY = minYExtent(); - if (extent > minY) - extent = minY; - return extent; -} - -qreal QDeclarative1GridView::minXExtent() const -{ - Q_D(const QDeclarative1GridView); - if (d->flow == QDeclarative1GridView::LeftToRight) - return QDeclarative1Flickable::minXExtent(); - qreal extent = -d->startPosition(); - qreal highlightStart; - qreal highlightEnd; - qreal endPositionFirstItem = 0; - if (d->isRightToLeftTopToBottom()) { - if (d->model && d->model->count()) - endPositionFirstItem = d->rowPosAt(d->model->count()-1); - highlightStart = d->highlightRangeStartValid - ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem) - : d->size() - (d->lastPosition()-endPositionFirstItem); - highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size(); - if (d->footer && d->visibleItems.count()) - extent += d->footer->item->width(); - } else { - endPositionFirstItem = d->rowPosAt(0)+d->rowSize(); - highlightStart = d->highlightRangeStart; - highlightEnd = d->highlightRangeEnd; - if (d->header && d->visibleItems.count()) - extent += d->header->item->width(); - } - if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { - extent += d->isRightToLeftTopToBottom() ? -highlightStart : highlightStart; - extent = qMax(extent, -(endPositionFirstItem - highlightEnd)); - } - return extent; -} - -qreal QDeclarative1GridView::maxXExtent() const -{ - Q_D(const QDeclarative1GridView); - if (d->flow == QDeclarative1GridView::LeftToRight) - return QDeclarative1Flickable::maxXExtent(); - qreal extent; - qreal highlightStart; - qreal highlightEnd; - qreal lastItemPosition = 0; - if (d->isRightToLeftTopToBottom()){ - highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size(); - highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size(); - lastItemPosition = d->endPosition(); - } else { - highlightStart = d->highlightRangeStart; - highlightEnd = d->highlightRangeEnd; - lastItemPosition = 0; - if (d->model && d->model->count()) - lastItemPosition = d->rowPosAt(d->model->count()-1); - } - if (!d->model || !d->model->count()) { - extent = 0; - } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) { - extent = -(lastItemPosition - highlightStart); - if (highlightEnd != highlightStart) - extent = d->isRightToLeftTopToBottom() - ? qMax(extent, -(d->endPosition() - highlightEnd + 1)) - : qMin(extent, -(d->endPosition() - highlightEnd + 1)); - } else { - extent = -(d->endPosition() - width()); - } - if (d->isRightToLeftTopToBottom()) { - if (d->header) - extent -= d->header->item->width(); - } else { - if (d->footer) - extent -= d->footer->item->width(); - } - - const qreal minX = minXExtent(); - if (extent > minX) - extent = minX; - return extent; -} - -void QDeclarative1GridView::keyPressEvent(QKeyEvent *event) -{ - Q_D(QDeclarative1GridView); - keyPressPreHandler(event); - if (event->isAccepted()) - return; - if (d->model && d->model->count() && d->interactive) { - d->moveReason = QDeclarative1GridViewPrivate::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; - } - } - d->moveReason = QDeclarative1GridViewPrivate::Other; - event->ignore(); - QDeclarative1Flickable::keyPressEvent(event); -} - -/*! - \qmlmethod QtQuick1::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 QDeclarative1GridView::moveCurrentIndexUp() -{ - Q_D(QDeclarative1GridView); - const int count = d->model ? d->model->count() : 0; - if (!count) - return; - if (d->flow == QDeclarative1GridView::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 QtQuick1::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 QDeclarative1GridView::moveCurrentIndexDown() -{ - Q_D(QDeclarative1GridView); - const int count = d->model ? d->model->count() : 0; - if (!count) - return; - if (d->flow == QDeclarative1GridView::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 QtQuick1::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 QDeclarative1GridView::moveCurrentIndexLeft() -{ - Q_D(QDeclarative1GridView); - const int count = d->model ? d->model->count() : 0; - if (!count) - return; - - if (effectiveLayoutDirection() == Qt::LeftToRight) { - if (d->flow == QDeclarative1GridView::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 == QDeclarative1GridView::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 QtQuick1::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 QDeclarative1GridView::moveCurrentIndexRight() -{ - Q_D(QDeclarative1GridView); - const int count = d->model ? d->model->count() : 0; - if (!count) - return; - - if (effectiveLayoutDirection() == Qt::LeftToRight) { - if (d->flow == QDeclarative1GridView::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 == QDeclarative1GridView::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); - } - } - } -} - -void QDeclarative1GridViewPrivate::positionViewAtIndex(int index, int mode) -{ - Q_Q(QDeclarative1GridView); - if (!isValid()) - return; - if (mode < QDeclarative1GridView::Beginning || mode > QDeclarative1GridView::Contain) - return; - - int idx = qMax(qMin(index, model->count()-1), 0); - - if (layoutScheduled) - layout(); - qreal pos = isRightToLeftTopToBottom() ? -position() - size() : position(); - FxGridItem1 *item = visibleItem(idx); - qreal maxExtent; - if (flow == QDeclarative1GridView::LeftToRight) - maxExtent = -q->maxYExtent(); - else - maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent(); - - if (!item) { - int itemPos = rowPosAt(idx); - // save the currently visible items in case any of them end up visible again - QList<FxGridItem1*> oldVisible = visibleItems; - visibleItems.clear(); - visibleIndex = idx - idx % columns; - if (flow == QDeclarative1GridView::LeftToRight) - maxExtent = -q->maxYExtent(); - else - maxExtent = isRightToLeftTopToBottom() ? q->minXExtent()-size() : -q->maxXExtent(); - setPosition(qMin(qreal(itemPos), maxExtent)); - // now release the reference to all the old visible items. - for (int i = 0; i < oldVisible.count(); ++i) - releaseItem(oldVisible.at(i)); - item = visibleItem(idx); - } - if (item) { - qreal itemPos = item->rowPos(); - switch (mode) { - case QDeclarative1GridView::Beginning: - pos = itemPos; - if (index < 0 && header) { - pos -= flow == QDeclarative1GridView::LeftToRight - ? header->item->height() - : header->item->width(); - } - break; - case QDeclarative1GridView::Center: - pos = itemPos - (size() - rowSize())/2; - break; - case QDeclarative1GridView::End: - pos = itemPos - size() + rowSize(); - if (index >= model->count() && footer) { - pos += flow == QDeclarative1GridView::LeftToRight - ? footer->item->height() - : footer->item->width(); - } - break; - case QDeclarative1GridView::Visible: - if (itemPos > pos + size()) - pos = itemPos - size() + rowSize(); - else if (item->endRowPos() < pos) - pos = itemPos; - break; - case QDeclarative1GridView::Contain: - if (item->endRowPos() > pos + size()) - pos = itemPos - size() + rowSize(); - if (itemPos < pos) - pos = itemPos; - } - - pos = qMin(pos, maxExtent); - qreal minExtent; - if (flow == QDeclarative1GridView::LeftToRight) - minExtent = -q->minYExtent(); - else - minExtent = isRightToLeftTopToBottom() ? q->maxXExtent()-size() : -q->minXExtent(); - pos = qMax(pos, minExtent); - moveReason = QDeclarative1GridViewPrivate::Other; - q->cancelFlick(); - setPosition(pos); - } - fixupPosition(); -} - -/*! - \qmlmethod QtQuick1::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 -*/ -void QDeclarative1GridView::positionViewAtIndex(int index, int mode) -{ - Q_D(QDeclarative1GridView); - if (!d->isValid() || index < 0 || index >= d->model->count()) - return; - d->positionViewAtIndex(index, mode); -} - -/*! - \qmlmethod QtQuick1::GridView::positionViewAtBeginning() - \qmlmethod QtQuick1::GridView::positionViewAtEnd() - \since Quick 1.1 - - 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 -*/ -void QDeclarative1GridView::positionViewAtBeginning() -{ - Q_D(QDeclarative1GridView); - if (!d->isValid()) - return; - d->positionViewAtIndex(-1, Beginning); -} - -void QDeclarative1GridView::positionViewAtEnd() -{ - Q_D(QDeclarative1GridView); - if (!d->isValid()) - return; - d->positionViewAtIndex(d->model->count(), End); -} - -/*! - \qmlmethod int QtQuick1::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. -*/ -int QDeclarative1GridView::indexAt(qreal x, qreal y) const -{ - Q_D(const QDeclarative1GridView); - for (int i = 0; i < d->visibleItems.count(); ++i) { - const FxGridItem1 *listItem = d->visibleItems.at(i); - if(listItem->contains(x, y)) - return listItem->index; - } - - return -1; -} - -void QDeclarative1GridView::componentComplete() -{ - Q_D(QDeclarative1GridView); - QDeclarative1Flickable::componentComplete(); - d->updateHeader(); - d->updateFooter(); - d->updateGrid(); - if (d->isValid()) { - refill(); - d->moveReason = QDeclarative1GridViewPrivate::SetIndex; - if (d->currentIndex < 0 && !d->currentIndexCleared) - d->updateCurrent(0); - else - d->updateCurrent(d->currentIndex); - if (d->highlight && d->currentItem) { - if (d->autoHighlight) - d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos()); - d->updateTrackedItem(); - } - d->moveReason = QDeclarative1GridViewPrivate::Other; - d->fixupPosition(); - } -} - -void QDeclarative1GridView::trackedPositionChanged() -{ - Q_D(QDeclarative1GridView); - if (!d->trackedItem || !d->currentItem) - return; - if (d->moveReason == QDeclarative1GridViewPrivate::SetIndex) { - const qreal trackedPos = d->trackedItem->rowPos(); - qreal viewPos; - qreal highlightStart; - qreal highlightEnd; - if (d->isRightToLeftTopToBottom()) { - viewPos = -d->position()-d->size(); - highlightStart = d->highlightRangeStartValid ? d->size()-d->highlightRangeEnd : d->highlightRangeStart; - highlightEnd = d->highlightRangeEndValid ? d->size()-d->highlightRangeStart : d->highlightRangeEnd; - } else { - viewPos = d->position(); - highlightStart = d->highlightRangeStart; - highlightEnd = d->highlightRangeEnd; - } - qreal pos = viewPos; - if (d->haveHighlightRange) { - if (d->highlightRange == StrictlyEnforceRange) { - if (trackedPos > pos + highlightEnd - d->rowSize()) - pos = trackedPos - highlightEnd + d->rowSize(); - if (trackedPos < pos + highlightStart) - pos = trackedPos - highlightStart; - } else { - if (trackedPos < d->startPosition() + highlightStart) { - pos = d->startPosition(); - } else if (d->trackedItem->endRowPos() > d->endPosition() - d->size() + highlightEnd) { - pos = d->endPosition() - d->size() + 1; - if (pos < d->startPosition()) - pos = d->startPosition(); - } else { - if (trackedPos > pos + highlightEnd - d->rowSize()) - pos = trackedPos - highlightEnd + d->rowSize(); - if (trackedPos < pos + highlightStart) - pos = trackedPos - highlightStart; - } - } - } else { - if (trackedPos < viewPos && d->currentItem->rowPos() < viewPos) { - pos = qMax(trackedPos, d->currentItem->rowPos()); - } else if (d->trackedItem->endRowPos() >= viewPos + d->size() - && d->currentItem->endRowPos() >= viewPos + d->size()) { - if (d->trackedItem->endRowPos() <= d->currentItem->endRowPos()) { - pos = d->trackedItem->endRowPos() - d->size() + 1; - if (d->rowSize() > d->size()) - pos = trackedPos; - } else { - pos = d->currentItem->endRowPos() - d->size() + 1; - if (d->rowSize() > d->size()) - pos = d->currentItem->rowPos(); - } - } - } - if (viewPos != pos) { - cancelFlick(); - d->calcVelocity = true; - d->setPosition(pos); - d->calcVelocity = false; - } - } -} - -void QDeclarative1GridView::itemsInserted(int modelIndex, int count) -{ - Q_D(QDeclarative1GridView); - if (!isComponentComplete() || !d->model || !d->model->isValid()) - return; - - int index = d->visibleItems.count() ? d->mapFromModel(modelIndex) : 0; - if (index < 0) { - int i = d->visibleItems.count() - 1; - while (i > 0 && d->visibleItems.at(i)->index == -1) - --i; - if (d->visibleItems.at(i)->index + 1 == modelIndex) { - // Special case of appending an item to the model. - index = d->visibleIndex + d->visibleItems.count(); - } else { - if (modelIndex <= d->visibleIndex) { - // Insert before visible items - d->visibleIndex += count; - for (int i = 0; i < d->visibleItems.count(); ++i) { - FxGridItem1 *listItem = d->visibleItems.at(i); - if (listItem->index != -1 && listItem->index >= modelIndex) - listItem->index += count; - } - } - if (d->currentIndex >= modelIndex) { - // adjust current item index - d->currentIndex += count; - if (d->currentItem) - d->currentItem->index = d->currentIndex; - emit currentIndexChanged(); - } - d->scheduleLayout(); - d->itemCount += count; - emit countChanged(); - return; - } - } - - int insertCount = count; - if (index < d->visibleIndex && d->visibleItems.count()) { - insertCount -= d->visibleIndex - index; - index = d->visibleIndex; - modelIndex = d->visibleIndex; - } - - qreal tempPos = d->isRightToLeftTopToBottom() ? -d->position()-d->size()+d->width()+1 : d->position(); - int to = d->buffer+tempPos+d->size()-1; - int colPos = 0; - int rowPos = 0; - if (d->visibleItems.count()) { - index -= d->visibleIndex; - if (index < d->visibleItems.count()) { - colPos = d->visibleItems.at(index)->colPos(); - rowPos = d->visibleItems.at(index)->rowPos(); - } else { - // appending items to visible list - colPos = d->visibleItems.at(index-1)->colPos() + d->colSize(); - rowPos = d->visibleItems.at(index-1)->rowPos(); - if (colPos > d->colSize() * (d->columns-1)) { - colPos = 0; - rowPos += d->rowSize(); - } - } - } else if (d->itemCount == 0 && d->header) { - rowPos = d->headerSize(); - } - - // Update the indexes of the following visible items. - for (int i = 0; i < d->visibleItems.count(); ++i) { - FxGridItem1 *listItem = d->visibleItems.at(i); - if (listItem->index != -1 && listItem->index >= modelIndex) - listItem->index += count; - } - - bool addedVisible = false; - QList<FxGridItem1*> added; - int i = 0; - while (i < insertCount && rowPos <= to + d->rowSize()*(d->columns - (colPos/d->colSize()))/qreal(d->columns)) { - if (!addedVisible) { - d->scheduleLayout(); - addedVisible = true; - } - FxGridItem1 *item = d->createItem(modelIndex + i); - d->visibleItems.insert(index, item); - item->setPosition(colPos, rowPos); - added.append(item); - colPos += d->colSize(); - if (colPos > d->colSize() * (d->columns-1)) { - colPos = 0; - rowPos += d->rowSize(); - } - ++index; - ++i; - } - if (i < insertCount) { - // We didn't insert all our new items, which means anything - // beyond the current index is not visible - remove it. - while (d->visibleItems.count() > index) { - d->releaseItem(d->visibleItems.takeLast()); - } - } - - // update visibleIndex - d->visibleIndex = 0; - for (QList<FxGridItem1*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) { - if ((*it)->index != -1) { - d->visibleIndex = (*it)->index; - break; - } - } - - if (d->itemCount && d->currentIndex >= modelIndex) { - // adjust current item index - d->currentIndex += count; - if (d->currentItem) { - d->currentItem->index = d->currentIndex; - d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex)); - } - emit currentIndexChanged(); - } else if (d->itemCount == 0 && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) { - setCurrentIndex(0); - } - - // everything is in order now - emit add() signal - for (int j = 0; j < added.count(); ++j) - added.at(j)->attached->emitAdd(); - - d->itemCount += count; - emit countChanged(); -} - -void QDeclarative1GridView::itemsRemoved(int modelIndex, int count) -{ - Q_D(QDeclarative1GridView); - if (!isComponentComplete() || !d->model || !d->model->isValid()) - return; - - d->itemCount -= count; - bool currentRemoved = d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count; - bool removedVisible = false; - - // Remove the items from the visible list, skipping anything already marked for removal - QList<FxGridItem1*>::Iterator it = d->visibleItems.begin(); - while (it != d->visibleItems.end()) { - FxGridItem1 *item = *it; - if (item->index == -1 || item->index < modelIndex) { - // already removed, or before removed items - if (item->index < modelIndex && !removedVisible) { - d->scheduleLayout(); - removedVisible = true; - } - ++it; - } else if (item->index >= modelIndex + count) { - // after removed items - item->index -= count; - ++it; - } else { - // removed item - if (!removedVisible) { - d->scheduleLayout(); - removedVisible = true; - } - item->attached->emitRemove(); - if (item->attached->delayRemove()) { - item->index = -1; - connect(item->attached, SIGNAL(delayRemoveChanged()), this, SLOT(destroyRemoved()), Qt::QueuedConnection); - ++it; - } else { - it = d->visibleItems.erase(it); - d->releaseItem(item); - } - } - } - - // update visibleIndex - d->visibleIndex = 0; - for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) { - if ((*it)->index != -1) { - d->visibleIndex = (*it)->index; - break; - } - } - - // If we removed items before visible items a layout may be - // required to ensure item 0 is in the first column. - if (!removedVisible && modelIndex < d->visibleIndex) - d->scheduleLayout(); - - // fix current - if (d->currentIndex >= modelIndex + count) { - d->currentIndex -= count; - if (d->currentItem) - d->currentItem->index -= count; - emit currentIndexChanged(); - } else if (currentRemoved) { - // current item has been removed. - d->releaseItem(d->currentItem); - d->currentItem = 0; - d->currentIndex = -1; - if (d->itemCount) - d->updateCurrent(qMin(modelIndex, d->itemCount-1)); - else - emit currentIndexChanged(); - } - - if (removedVisible && d->visibleItems.isEmpty()) { - d->timeline.clear(); - if (d->itemCount == 0) { - d->setPosition(0); - d->updateHeader(); - d->updateFooter(); - update(); - } - } - - emit countChanged(); -} - -void QDeclarative1GridView::destroyRemoved() -{ - Q_D(QDeclarative1GridView); - for (QList<FxGridItem1*>::Iterator it = d->visibleItems.begin(); - it != d->visibleItems.end();) { - FxGridItem1 *listItem = *it; - if (listItem->index == -1 && listItem->attached->delayRemove() == false) { - d->releaseItem(listItem); - it = d->visibleItems.erase(it); - } else { - ++it; - } - } - - // Correct the positioning of the items - d->layout(); -} - -void QDeclarative1GridView::itemsMoved(int from, int to, int count) -{ - Q_D(QDeclarative1GridView); - if (!isComponentComplete() || !d->isValid()) - return; - QHash<int,FxGridItem1*> moved; - - FxGridItem1 *firstItem = d->firstVisibleItem(); - - QList<FxGridItem1*>::Iterator it = d->visibleItems.begin(); - while (it != d->visibleItems.end()) { - FxGridItem1 *item = *it; - if (item->index >= from && item->index < from + count) { - // take the items that are moving - item->index += (to-from); - moved.insert(item->index, item); - it = d->visibleItems.erase(it); - } else { - if (item->index > from && item->index != -1) { - // move everything after the moved items. - item->index -= count; - if (item->index < d->visibleIndex) - d->visibleIndex = item->index; - } - ++it; - } - } - - int remaining = count; - int endIndex = d->visibleIndex; - it = d->visibleItems.begin(); - while (it != d->visibleItems.end()) { - FxGridItem1 *item = *it; - if (remaining && item->index >= to && item->index < to + count) { - // place items in the target position, reusing any existing items - FxGridItem1 *movedItem = moved.take(item->index); - if (!movedItem) - movedItem = d->createItem(item->index); - it = d->visibleItems.insert(it, movedItem); - if (it == d->visibleItems.begin() && firstItem) - movedItem->setPosition(firstItem->colPos(), firstItem->rowPos()); - ++it; - --remaining; - } else { - if (item->index != -1) { - if (item->index >= to) { - // update everything after the moved items. - item->index += count; - } - endIndex = item->index; - } - ++it; - } - } - - // If we have moved items to the end of the visible items - // then add any existing moved items that we have - while (FxGridItem1 *item = moved.take(endIndex+1)) { - d->visibleItems.append(item); - ++endIndex; - } - - // update visibleIndex - for (it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) { - if ((*it)->index != -1) { - d->visibleIndex = (*it)->index; - break; - } - } - - // Fix current index - if (d->currentIndex >= 0 && d->currentItem) { - int oldCurrent = d->currentIndex; - d->currentIndex = d->model->indexOf(d->currentItem->item, this); - if (oldCurrent != d->currentIndex) { - d->currentItem->index = d->currentIndex; - emit currentIndexChanged(); - } - } - - // Whatever moved items remain are no longer visible items. - while (moved.count()) { - int idx = moved.begin().key(); - FxGridItem1 *item = moved.take(idx); - if (d->currentItem && item->item == d->currentItem->item) - item->setPosition(d->colPosAt(idx), d->rowPosAt(idx)); - d->releaseItem(item); - } - - d->layout(); -} - -void QDeclarative1GridView::modelReset() -{ - Q_D(QDeclarative1GridView); - d->clear(); - refill(); - d->moveReason = QDeclarative1GridViewPrivate::SetIndex; - d->updateCurrent(d->currentIndex); - if (d->highlight && d->currentItem) { - if (d->autoHighlight) - d->highlight->setPosition(d->currentItem->colPos(), d->currentItem->rowPos()); - d->updateTrackedItem(); - } - d->moveReason = QDeclarative1GridViewPrivate::Other; - - emit countChanged(); -} - -void QDeclarative1GridView::createdItem(int index, QDeclarativeItem *item) -{ - Q_D(QDeclarative1GridView); - if (d->requestedIndex != index) { - item->setParentItem(this); - d->unrequestedItems.insert(item, index); - if (d->flow == QDeclarative1GridView::LeftToRight) { - item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index))); - } else { - item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index))); - } - } -} - -void QDeclarative1GridView::destroyingItem(QDeclarativeItem *item) -{ - Q_D(QDeclarative1GridView); - d->unrequestedItems.remove(item); -} - -void QDeclarative1GridView::animStopped() -{ - Q_D(QDeclarative1GridView); - d->bufferMode = QDeclarative1GridViewPrivate::NoBuffer; - if (d->haveHighlightRange && d->highlightRange == QDeclarative1GridView::StrictlyEnforceRange) - d->updateHighlight(); -} - -void QDeclarative1GridView::refill() -{ - Q_D(QDeclarative1GridView); - if (d->isRightToLeftTopToBottom()) - d->refill(-d->position()-d->size()+1, -d->position()); - else - d->refill(d->position(), d->position()+d->size()-1); -} - - -QDeclarative1GridViewAttached *QDeclarative1GridView::qmlAttachedProperties(QObject *obj) -{ - return new QDeclarative1GridViewAttached(obj); -} - - - -QT_END_NAMESPACE |