aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/items/items.pri3
-rw-r--r--src/declarative/items/qsggridview.cpp2032
-rw-r--r--src/declarative/items/qsggridview_p.h151
-rw-r--r--src/declarative/items/qsgitemview.cpp1363
-rw-r--r--src/declarative/items/qsgitemview_p.h285
-rw-r--r--src/declarative/items/qsgitemview_p_p.h208
-rw-r--r--src/declarative/items/qsglistview.cpp2179
-rw-r--r--src/declarative/items/qsglistview_p.h194
-rw-r--r--tests/auto/declarative/qsggridview/tst_qsggridview.cpp4
9 files changed, 2887 insertions, 3532 deletions
diff --git a/src/declarative/items/items.pri b/src/declarative/items/items.pri
index bf92025b75..78199808cc 100644
--- a/src/declarative/items/items.pri
+++ b/src/declarative/items/items.pri
@@ -66,6 +66,8 @@ HEADERS += \
$$PWD/qsgspriteimage_p.h \
$$PWD/qsgevent.h \
$$PWD/qsgdragtarget_p.h \
+ $$PWD/qsgitemview_p.h \
+ $$PWD/qsgitemview_p_p.h
SOURCES += \
$$PWD/qsgevents.cpp \
@@ -109,6 +111,7 @@ SOURCES += \
$$PWD/qsgsprite.cpp \
$$PWD/qsgspriteimage.cpp \
$$PWD/qsgdragtarget.cpp \
+ $$PWD/qsgitemview.cpp
SOURCES += \
$$PWD/qsgshadereffectitem.cpp \
diff --git a/src/declarative/items/qsggridview.cpp b/src/declarative/items/qsggridview.cpp
index 9c67246299..ab02dea33b 100644
--- a/src/declarative/items/qsggridview.cpp
+++ b/src/declarative/items/qsggridview.cpp
@@ -42,6 +42,7 @@
#include "qsggridview_p.h"
#include "qsgvisualitemmodel_p.h"
#include "qsgflickable_p_p.h"
+#include "qsgitemview_p_p.h"
#include <private/qdeclarativesmoothedanimation_p_p.h>
#include <private/qlistmodelinterface_p.h>
@@ -55,43 +56,52 @@ QT_BEGIN_NAMESPACE
//----------------------------------------------------------------------------
-class FxGridItemSG
+class FxGridItemSG : public FxViewItem
{
public:
- FxGridItemSG(QSGItem *i, QSGGridView *v) : item(i), view(v) {
+ FxGridItemSG(QSGItem *i, QSGGridView *v, bool own) : FxViewItem(i, own), view(v) {
attached = static_cast<QSGGridViewAttached*>(qmlAttachedPropertiesObject<QSGGridView>(item));
if (attached)
- attached->setView(view);
+ static_cast<QSGGridViewAttached*>(attached)->setView(view);
}
+
~FxGridItemSG() {}
+ qreal position() const {
+ return rowPos();
+ }
+
+ qreal endPosition() const {
+ return endRowPos();
+ }
+
+ qreal size() const {
+ return view->flow() == QSGGridView::LeftToRight ? view->cellHeight() : view->cellWidth();
+ }
+
+ qreal sectionSize() const {
+ return 0.0;
+ }
+
qreal rowPos() const {
- qreal rowPos = 0;
- if (view->flow() == QSGGridView::LeftToRight) {
- rowPos = item->y();
- } else {
- if (view->effectiveLayoutDirection() == Qt::RightToLeft)
- rowPos = -view->cellWidth()-item->x();
- else
- rowPos = item->x();
- }
- return rowPos;
+ if (view->flow() == QSGGridView::LeftToRight)
+ return item->y();
+ else
+ return (view->effectiveLayoutDirection() == Qt::RightToLeft ? -view->cellWidth()-item->x() : item->x());
}
+
qreal colPos() const {
- qreal colPos = 0;
if (view->flow() == QSGGridView::LeftToRight) {
if (view->effectiveLayoutDirection() == Qt::RightToLeft) {
int colSize = view->cellWidth();
int columns = view->width()/colSize;
- colPos = colSize * (columns-1) - item->x();
+ return colSize * (columns-1) - item->x();
} else {
- colPos = item->x();
+ return item->x();
}
} else {
- colPos = item->y();
+ return item->y();
}
-
- return colPos;
}
qreal endRowPos() const {
if (view->flow() == QSGGridView::LeftToRight) {
@@ -123,464 +133,289 @@ public:
y >= item->y() && y < item->y() + view->cellHeight());
}
- QSGItem *item;
QSGGridView *view;
- QSGGridViewAttached *attached;
- int index;
};
//----------------------------------------------------------------------------
-class QSGGridViewPrivate : public QSGFlickablePrivate
+class QSGGridViewPrivate : public QSGItemViewPrivate
{
Q_DECLARE_PUBLIC(QSGGridView)
public:
- QSGGridViewPrivate()
- : currentItem(0), layoutDirection(Qt::LeftToRight), flow(QSGGridView::LeftToRight)
- , visibleIndex(0) , currentIndex(-1)
- , cellWidth(100), cellHeight(100), columns(1), requestedIndex(-1), itemCount(0)
- , highlightRangeStart(0), highlightRangeEnd(0)
- , highlightRange(QSGGridView::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(QSGGridView::NoSnap)
- , ownModel(false), wrap(false), autoHighlight(true)
- , fixCurrentVisibility(false), lazyRelease(false), layoutScheduled(false)
- , deferredRelease(false), haveHighlightRange(false), currentIndexCleared(false)
- , highlightRangeStartValid(false), highlightRangeEndValid(false) {}
-
- void init();
- void clear();
- FxGridItemSG *createItem(int modelIndex);
- void releaseItem(FxGridItemSG *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();
-
- FxGridItemSG *visibleItem(int modelIndex) const {
- if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
- for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
- FxGridItemSG *item = visibleItems.at(i);
- if (item->index == modelIndex)
- return item;
- }
- }
- return 0;
- }
-
- bool isRightToLeftTopToBottom() const {
- Q_Q(const QSGGridView);
- return flow == QSGGridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
- }
+ virtual Qt::Orientation layoutOrientation() const;
+ virtual bool isContentFlowReversed() const;
+ bool isRightToLeftTopToBottom() const;
+
+ virtual qreal startPosition() const;
+ virtual qreal positionAt(int index) const;
+ virtual qreal endPosition() const;
+ virtual qreal endPositionAt(int index) const;
+ virtual qreal lastPosition() const;
+
+ qreal originPosition() const;
+ int rowSize() const;
+ int colSize() const;
+ qreal colPosAt(int modelIndex) const;
+ qreal rowPosAt(int modelIndex) const;
+ qreal snapPosAt(qreal pos) const;
+ FxViewItem *snapItemAt(qreal pos) const;
+ int snapIndex() const;
+
+ virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer);
+ virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo);
+ virtual void visibleItemsChanged();
+
+ virtual FxViewItem *newViewItem(int index, QSGItem *item);
+ virtual void repositionPackageItemAt(QSGItem *item, int index);
+
+ virtual void createHighlight();
+ virtual void updateHighlight();
+ virtual void resetHighlightPosition();
+
+ virtual void setPosition(qreal pos);
+ virtual void layoutVisibleItems();
+
+ virtual qreal headerSize() const;
+ virtual qreal footerSize() const;
+ virtual void updateHeader();
+ virtual void updateFooter();
+
+ virtual void changedVisibleIndex(int newIndex);
+ virtual void initializeCurrentItem();
+
+ virtual void updateViewport();
+ virtual void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ virtual void fixupPosition();
+ virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
+ virtual void flick(QSGItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
- void regenerate() {
- Q_Q(QSGGridView);
- if (q->isComponentComplete()) {
- clear();
- updateGrid();
- setPosition(0);
- q->refill();
- updateCurrent(currentIndex);
- }
- }
+ QSGGridView::Flow flow;
+ int cellWidth;
+ int cellHeight;
+ int columns;
+ QSGGridView::SnapMode snapMode;
- void mirrorChange() {
- Q_Q(QSGGridView);
- regenerate();
- emit q->effectiveLayoutDirectionChanged();
- }
+ QSmoothedAnimation *highlightXAnimator;
+ QSmoothedAnimation *highlightYAnimator;
- qreal position() const {
- Q_Q(const QSGGridView);
- return flow == QSGGridView::LeftToRight ? q->contentY() : q->contentX();
- }
- void setPosition(qreal pos) {
- Q_Q(QSGGridView);
- if (flow == QSGGridView::LeftToRight) {
- q->QSGFlickable::setContentY(pos);
- q->QSGFlickable::setContentX(0);
- } else {
- if (q->effectiveLayoutDirection() == Qt::LeftToRight)
- q->QSGFlickable::setContentX(pos);
- else
- q->QSGFlickable::setContentX(-pos-size());
- q->QSGFlickable::setContentY(0);
- }
- }
- int size() const {
- Q_Q(const QSGGridView);
- return flow == QSGGridView::LeftToRight ? q->height() : q->width();
- }
- qreal originPosition() const {
- qreal pos = 0;
- if (!visibleItems.isEmpty())
- pos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
- return pos;
- }
+ QSGGridViewPrivate()
+ : flow(QSGGridView::LeftToRight)
+ , cellWidth(100), cellHeight(100), columns(1)
+ , snapMode(QSGGridView::NoSnap)
+ , highlightXAnimator(0), highlightYAnimator(0)
+ {}
+};
- qreal lastPosition() const {
- qreal pos = 0;
- if (model && model->count())
- pos = rowPosAt(model->count() - 1) + rowSize();
- return pos;
- }
+Qt::Orientation QSGGridViewPrivate::layoutOrientation() const
+{
+ return flow == QSGGridView::LeftToRight ? Qt::Vertical : Qt::Horizontal;
+}
- qreal startPosition() const {
- return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
- }
+bool QSGGridViewPrivate::isContentFlowReversed() const
+{
+ return isRightToLeftTopToBottom();
+}
- qreal endPosition() const {
- return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
+bool QSGGridViewPrivate::isRightToLeftTopToBottom() const
+{
+ Q_Q(const QSGGridView);
+ return flow == QSGGridView::TopToBottom && q->effectiveLayoutDirection() == Qt::RightToLeft;
+}
- }
+void QSGGridViewPrivate::changedVisibleIndex(int newIndex)
+{
+ visibleIndex = newIndex / columns * columns;
+}
- bool isValid() const {
- return model && model->count() && model->isValid();
+void QSGGridViewPrivate::setPosition(qreal pos)
+{
+ Q_Q(QSGGridView);
+ if (flow == QSGGridView::LeftToRight) {
+ q->QSGFlickable::setContentY(pos);
+ q->QSGFlickable::setContentX(0);
+ } else {
+ if (q->effectiveLayoutDirection() == Qt::LeftToRight)
+ q->QSGFlickable::setContentX(pos);
+ else
+ q->QSGFlickable::setContentX(-pos-size());
+ q->QSGFlickable::setContentY(0);
}
+}
- int rowSize() const {
- return flow == QSGGridView::LeftToRight ? cellHeight : cellWidth;
- }
- int colSize() const {
- return flow == QSGGridView::LeftToRight ? cellWidth : cellHeight;
- }
+qreal QSGGridViewPrivate::originPosition() const
+{
+ qreal pos = 0;
+ if (!visibleItems.isEmpty())
+ pos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
+ return pos;
+}
- qreal colPosAt(int modelIndex) const {
- if (FxGridItemSG *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 (FxGridItemSG *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;
- }
+qreal QSGGridViewPrivate::lastPosition() const
+{
+ qreal pos = 0;
+ if (model && model->count())
+ pos = rowPosAt(model->count() - 1) + rowSize();
+ return pos;
+}
- FxGridItemSG *firstVisibleItem() const {
- const qreal pos = isRightToLeftTopToBottom() ? -position()-size() : position();
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxGridItemSG *item = visibleItems.at(i);
- if (item->index != -1 && item->endRowPos() > pos)
- return item;
- }
- return visibleItems.count() ? visibleItems.first() : 0;
- }
+qreal QSGGridViewPrivate::startPosition() const
+{
+ return isRightToLeftTopToBottom() ? -lastPosition()+1 : originPosition();
+}
- int lastVisibleIndex() const {
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxGridItemSG *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) {
- FxGridItemSG *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 QSGGridView);
- qreal snapPos = 0;
- if (!visibleItems.isEmpty()) {
- pos += rowSize()/2;
- snapPos = visibleItems.first()->rowPos() - visibleIndex / columns * rowSize();
- snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
- qreal maxExtent;
- qreal minExtent;
- if (isRightToLeftTopToBottom()) {
- maxExtent = q->minXExtent();
- minExtent = q->maxXExtent();
- } else {
- maxExtent = flow == QSGGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
- minExtent = flow == QSGGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
- }
- if (snapPos > maxExtent)
- snapPos = maxExtent;
- if (snapPos < minExtent)
- snapPos = minExtent;
- }
- return snapPos;
- }
+qreal QSGGridViewPrivate::positionAt(int index) const
+{
+ return rowPosAt(index);
+}
- FxGridItemSG *snapItemAt(qreal pos) {
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxGridItemSG *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) {
- FxGridItemSG *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 QSGGridViewPrivate::endPosition() const
+{
+ return isRightToLeftTopToBottom() ? -originPosition()+1 : lastPosition();
- qreal headerSize() const {
- if (!header)
- return 0.0;
+}
- return flow == QSGGridView::LeftToRight
- ? header->item->height()
- : header->item->width();
- }
+qreal QSGGridViewPrivate::endPositionAt(int index) const
+{
+ return rowPosAt(index) + rowSize();
+}
+int QSGGridViewPrivate::rowSize() const {
+ return flow == QSGGridView::LeftToRight ? cellHeight : cellWidth;
+}
+int QSGGridViewPrivate::colSize() const {
+ return flow == QSGGridView::LeftToRight ? cellWidth : cellHeight;
+}
- virtual void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
- Q_Q(const QSGGridView);
- QSGFlickablePrivate::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();
+qreal QSGGridViewPrivate::colPosAt(int modelIndex) const
+{
+ if (FxViewItem *item = visibleItem(modelIndex))
+ return static_cast<FxGridItemSG*>(item)->colPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = (visibleIndex - modelIndex) % columns;
+ int col = static_cast<FxGridItemSG*>(visibleItems.first())->colPos() / colSize();
+ col = (columns - count + col) % columns;
+ return col * colSize();
+ } else {
+ int count = columns - 1 - (modelIndex - visibleItems.last()->index - 1) % columns;
+ return static_cast<FxGridItemSG*>(visibleItems.last())->colPos() - count * colSize();
}
+ } else {
+ return (modelIndex % columns) * colSize();
}
+ return 0;
+}
- 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,
- QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
-
- // for debugging only
- void checkVisible() const {
- int skip = 0;
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxGridItemSG *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);
- }
+qreal QSGGridViewPrivate::rowPosAt(int modelIndex) const
+{
+ if (FxViewItem *item = visibleItem(modelIndex))
+ return static_cast<FxGridItemSG*>(item)->rowPos();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
+ int firstCol = firstItem->colPos() / colSize();
+ int col = visibleIndex - modelIndex + (columns - firstCol - 1);
+ int rows = col / columns;
+ return firstItem->rowPos() - rows * rowSize();
+ } else {
+ FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
+ int count = modelIndex - lastItem->index;
+ int col = lastItem->colPos() + count * colSize();
+ int rows = col / (columns * colSize());
+ return lastItem->rowPos() + rows * rowSize();
}
+ } else {
+ qreal pos = (modelIndex / columns) * rowSize();
+ if (header)
+ pos += headerSize();
+ return pos;
}
+ return 0;
+}
- QDeclarativeGuard<QSGVisualModel> model;
- QVariant modelVariant;
- QList<FxGridItemSG*> visibleItems;
- QHash<QSGItem*,int> unrequestedItems;
- FxGridItemSG *currentItem;
- Qt::LayoutDirection layoutDirection;
- QSGGridView::Flow flow;
- int visibleIndex;
- int currentIndex;
- int cellWidth;
- int cellHeight;
- int columns;
- int requestedIndex;
- int itemCount;
- qreal highlightRangeStart;
- qreal highlightRangeEnd;
- QSGGridView::HighlightRangeMode highlightRange;
- QDeclarativeComponent *highlightComponent;
- FxGridItemSG *highlight;
- FxGridItemSG *trackedItem;
- enum MovementReason { Other, SetIndex, Mouse };
- MovementReason moveReason;
- int buffer;
- QSmoothedAnimation *highlightXAnimator;
- QSmoothedAnimation *highlightYAnimator;
- int highlightMoveDuration;
- QDeclarativeComponent *footerComponent;
- FxGridItemSG *footer;
- QDeclarativeComponent *headerComponent;
- FxGridItemSG *header;
- enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
- int bufferMode;
- QSGGridView::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;
- bool highlightRangeStartValid : 1;
- bool highlightRangeEndValid : 1;
-};
-void QSGGridViewPrivate::init()
+qreal QSGGridViewPrivate::snapPosAt(qreal pos) const
{
- Q_Q(QSGGridView);
- QSGItemPrivate::get(contentItem)->childrenDoNotOverlap = true;
- QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
- q->setFlag(QSGItem::ItemIsFocusScope);
- q->setFlickableDirection(QSGFlickable::VerticalFlick);
- addItemChangeListener(this, Geometry);
+ Q_Q(const QSGGridView);
+ qreal snapPos = 0;
+ if (!visibleItems.isEmpty()) {
+ pos += rowSize()/2;
+ snapPos = static_cast<FxGridItemSG*>(visibleItems.first())->rowPos() - visibleIndex / columns * rowSize();
+ snapPos = pos - fmodf(pos - snapPos, qreal(rowSize()));
+ qreal maxExtent;
+ qreal minExtent;
+ if (isRightToLeftTopToBottom()) {
+ maxExtent = q->minXExtent();
+ minExtent = q->maxXExtent();
+ } else {
+ maxExtent = flow == QSGGridView::LeftToRight ? -q->maxYExtent() : -q->maxXExtent();
+ minExtent = flow == QSGGridView::LeftToRight ? -q->minYExtent() : -q->minXExtent();
+ }
+ if (snapPos > maxExtent)
+ snapPos = maxExtent;
+ if (snapPos < minExtent)
+ snapPos = minExtent;
+ }
+ return snapPos;
}
-void QSGGridViewPrivate::clear()
+FxViewItem *QSGGridViewPrivate::snapItemAt(qreal pos) const
{
- 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;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->position();
+ if (itemTop+rowSize()/2 >= pos && itemTop - rowSize()/2 <= pos)
+ return item;
+ }
+ return 0;
}
-FxGridItemSG *QSGGridViewPrivate::createItem(int modelIndex)
+int QSGGridViewPrivate::snapIndex() const
{
- Q_Q(QSGGridView);
- // create object
- requestedIndex = modelIndex;
- FxGridItemSG *listItem = 0;
- if (QSGItem *item = model->item(modelIndex, false)) {
- listItem = new FxGridItemSG(item, q);
- listItem->index = modelIndex;
- if (model->completePending()) {
- // complete
- listItem->item->setZ(1);
- listItem->item->setParentItem(q->contentItem());
- model->completeItem();
- } else {
- listItem->item->setParentItem(q->contentItem());
+ int index = currentIndex;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->position();
+ FxGridItemSG *hItem = static_cast<FxGridItemSG*>(highlight);
+ if (itemTop >= hItem->rowPos()-rowSize()/2 && itemTop < hItem->rowPos()+rowSize()/2) {
+ index = item->index;
+ if (item->colPos() >= hItem->colPos()-colSize()/2 && item->colPos() < hItem->colPos()+colSize()/2)
+ return item->index;
}
- unrequestedItems.remove(listItem->item);
}
- requestedIndex = -1;
- return listItem;
+ return index;
}
-
-void QSGGridViewPrivate::releaseItem(FxGridItemSG *item)
+FxViewItem *QSGGridViewPrivate::newViewItem(int modelIndex, QSGItem *item)
{
Q_Q(QSGGridView);
- 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;
+ Q_UNUSED(modelIndex);
+ return new FxGridItemSG(item, q, false);
}
-void QSGGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+bool QSGGridViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer)
{
- Q_Q(QSGGridView);
- 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();
+ FxGridItemSG *lastItem = static_cast<FxGridItemSG*>(visibleItems.last());
+ rowPos = lastItem->rowPos();
+ colPos = lastItem->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;
}
+ int modelIndex = findLastVisibleIndex();
+ modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
+
if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
|| fillTo < rowPosAt(visibleIndex) - rowSize())) {
// We've jumped more than a page. Estimate which items are now
@@ -601,15 +436,12 @@ void QSGGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
}
int colNum = colPos / colSize();
-
FxGridItemSG *item = 0;
+ bool changed = false;
- // 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)))
+ if (!(item = static_cast<FxGridItemSG*>(createItem(modelIndex))))
break;
item->setPosition(colPos, rowPos);
visibleItems.append(item);
@@ -627,17 +459,19 @@ void QSGGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
}
if (visibleItems.count()) {
- rowPos = visibleItems.first()->rowPos();
- colPos = visibleItems.first()->colPos() - colSize();
+ FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
+ rowPos = firstItem->rowPos();
+ colPos = firstItem->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)))
+ if (!(item = static_cast<FxGridItemSG*>(createItem(visibleIndex-1))))
break;
--visibleIndex;
item->setPosition(colPos, rowPos);
@@ -654,87 +488,69 @@ void QSGGridViewPrivate::refill(qreal from, qreal to, bool doBuffer)
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;
+ return changed;
+}
+
+bool QSGGridViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
+{
+ FxGridItemSG *item = 0;
+ bool changed = false;
+
+ while (visibleItems.count() > 1
+ && (item = static_cast<FxGridItemSG*>(visibleItems.first()))
+ && item->rowPos()+rowSize()-1 < bufferFrom - rowSize()*(item->colPos()/colSize()+1)/(columns+1)) {
+ if (item->attached->delayRemove())
+ break;
// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endRowPos();
- if (item->index != -1)
- visibleIndex++;
- visibleItems.removeFirst();
- releaseItem(item);
- changed = true;
- }
- while (visibleItems.count() > 1
- && (item = 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 (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
}
- if (changed) {
- if (header)
- updateHeader();
- if (footer)
- updateFooter();
- if (flow == QSGGridView::LeftToRight)
- q->setContentHeight(endPosition() - startPosition());
- else
- q->setContentWidth(endPosition() - startPosition());
- } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
- refill(from, to, true);
+ while (visibleItems.count() > 1
+ && (item = static_cast<FxGridItemSG*>(visibleItems.last()))
+ && item->rowPos() > bufferTo + rowSize()*(columns - item->colPos()/colSize())/(columns+1)) {
+ if (item->attached->delayRemove())
+ break;
+// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1;
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
}
- lazyRelease = false;
+
+ return changed;
}
-void QSGGridViewPrivate::updateGrid()
+void QSGGridViewPrivate::visibleItemsChanged()
{
Q_Q(QSGGridView);
- columns = (int)qMax((flow == QSGGridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
- if (isValid()) {
- if (flow == QSGGridView::LeftToRight)
- q->setContentHeight(endPosition() - startPosition());
- else
- q->setContentWidth(lastPosition() - originPosition());
- }
+
+ updateHeader();
+ updateFooter();
+ updateViewport();
}
-void QSGGridViewPrivate::scheduleLayout()
+void QSGGridViewPrivate::updateViewport()
{
Q_Q(QSGGridView);
- if (!layoutScheduled) {
- layoutScheduled = true;
- q->polish();
- }
+ columns = (int)qMax((flow == QSGGridView::LeftToRight ? q->width() : q->height()) / colSize(), qreal(1.));
+ QSGItemViewPrivate::updateViewport();
}
-void QSGGridViewPrivate::layout()
+void QSGGridViewPrivate::layoutVisibleItems()
{
- Q_Q(QSGGridView);
- layoutScheduled = false;
- if (!isValid() && !visibleItems.count()) {
- clear();
- return;
- }
if (visibleItems.count()) {
- qreal rowPos = visibleItems.first()->rowPos();
- qreal colPos = visibleItems.first()->colPos();
+ FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(visibleItems.first());
+ qreal rowPos = firstItem->rowPos();
+ qreal colPos = firstItem->colPos();
int col = visibleIndex % columns;
if (colPos != col * colSize()) {
colPos = col * colSize();
- visibleItems.first()->setPosition(colPos, rowPos);
+ firstItem->setPosition(colPos, rowPos);
}
for (int i = 1; i < visibleItems.count(); ++i) {
- FxGridItemSG *item = visibleItems.at(i);
+ FxGridItemSG *item = static_cast<FxGridItemSG*>(visibleItems.at(i));
colPos += colSize();
if (colPos > colSize() * (columns-1)) {
colPos = 0;
@@ -743,68 +559,25 @@ void QSGGridViewPrivate::layout()
item->setPosition(colPos, rowPos);
}
}
- if (header)
- updateHeader();
- if (footer)
- updateFooter();
- q->refill();
- updateHighlight();
- moveReason = Other;
- if (flow == QSGGridView::LeftToRight) {
- q->setContentHeight(endPosition() - startPosition());
- fixupY();
- } else {
- q->setContentWidth(endPosition() - startPosition());
- fixupX();
- }
- updateUnrequestedPositions();
}
-void QSGGridViewPrivate::updateUnrequestedIndexes()
+void QSGGridViewPrivate::repositionPackageItemAt(QSGItem *item, int index)
{
Q_Q(QSGGridView);
- QHash<QSGItem*,int>::iterator it;
- for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
- *it = model->indexOf(it.key(), q);
-}
-
-void QSGGridViewPrivate::updateUnrequestedPositions()
-{
- QHash<QSGItem*,int>::const_iterator it;
- for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
- QSGItem *item = it.key();
- if (flow == QSGGridView::LeftToRight) {
- item->setPos(QPointF(colPosAt(*it), rowPosAt(*it)));
- } else {
+ qreal pos = position();
+ if (flow == QSGGridView::LeftToRight) {
+ if (item->y() + item->height() > pos && item->y() < pos + q->height())
+ item->setPos(QPointF(colPosAt(index), rowPosAt(index)));
+ } else {
+ if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
if (isRightToLeftTopToBottom())
- item->setPos(QPointF(-rowPosAt(*it)-item->width(), colPosAt(*it)));
+ item->setPos(QPointF(-rowPosAt(index)-item->width(), colPosAt(index)));
else
- item->setPos(QPointF(rowPosAt(*it), colPosAt(*it)));
+ item->setPos(QPointF(rowPosAt(index), colPosAt(index)));
}
}
}
-void QSGGridViewPrivate::updateTrackedItem()
-{
- Q_Q(QSGGridView);
- FxGridItemSG *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 QSGGridViewPrivate::createHighlight()
{
@@ -813,51 +586,31 @@ void QSGGridViewPrivate::createHighlight()
if (highlight) {
if (trackedItem == highlight)
trackedItem = 0;
- highlight->item->setParentItem(0);
- highlight->item->deleteLater();
delete highlight;
highlight = 0;
+
delete highlightXAnimator;
delete highlightYAnimator;
highlightXAnimator = 0;
highlightYAnimator = 0;
+
changed = true;
}
if (currentItem) {
- QSGItem *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<QSGItem *>(nobj);
- if (!item)
- delete nobj;
- } else {
- delete highlightContext;
- }
- } else {
- item = new QSGItem;
- QDeclarative_setParent_noEvent(item, q->contentItem());
- item->setParentItem(q->contentItem());
- }
+ QSGItem *item = createHighlightItem();
if (item) {
- QDeclarative_setParent_noEvent(item, q->contentItem());
- item->setParentItem(q->contentItem());
- highlight = new FxGridItemSG(item, q);
- if (currentItem && autoHighlight)
- highlight->setPosition(currentItem->colPos(), currentItem->rowPos());
+ FxGridItemSG *newHighlight = new FxGridItemSG(item, q, true);
+ if (autoHighlight)
+ resetHighlightPosition();
highlightXAnimator = new QSmoothedAnimation(q);
- highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
+ highlightXAnimator->target = QDeclarativeProperty(item, QLatin1String("x"));
highlightXAnimator->userDuration = highlightMoveDuration;
highlightYAnimator = new QSmoothedAnimation(q);
- highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y"));
+ highlightYAnimator->target = QDeclarativeProperty(item, QLatin1String("y"));
highlightYAnimator->userDuration = highlightMoveDuration;
- if (autoHighlight) {
- highlightXAnimator->restart();
- highlightYAnimator->restart();
- }
+
+ highlight = newHighlight;
changed = true;
}
}
@@ -875,150 +628,131 @@ void QSGGridViewPrivate::updateHighlight()
highlightYAnimator->to = currentItem->item->y();
highlight->item->setWidth(currentItem->item->width());
highlight->item->setHeight(currentItem->item->height());
+
highlightXAnimator->restart();
highlightYAnimator->restart();
}
updateTrackedItem();
}
-void QSGGridViewPrivate::updateCurrent(int modelIndex)
+void QSGGridViewPrivate::resetHighlightPosition()
{
- Q_Q(QSGGridView);
- 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 (highlight && currentItem) {
+ FxGridItemSG *cItem = static_cast<FxGridItemSG*>(currentItem);
+ static_cast<FxGridItemSG*>(highlight)->setPosition(cItem->colPos(), cItem->rowPos());
}
+}
- if (currentItem && currentIndex == modelIndex) {
- updateHighlight();
- return;
- }
+qreal QSGGridViewPrivate::headerSize() const
+{
+ if (!header)
+ return 0.0;
+ return flow == QSGGridView::LeftToRight ? header->item->height() : header->item->width();
+}
- FxGridItemSG *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);
+qreal QSGGridViewPrivate::footerSize() const
+{
+ if (!footer)
+ return 0.0;
+ return flow == QSGGridView::LeftToRight? footer->item->height() : footer->item->width();
}
void QSGGridViewPrivate::updateFooter()
{
Q_Q(QSGGridView);
- if (!footer && footerComponent) {
- QSGItem *item = 0;
- QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
- QObject *nobj = footerComponent->create(context);
- if (nobj) {
- QDeclarative_setParent_noEvent(context, nobj);
- item = qobject_cast<QSGItem *>(nobj);
- if (!item)
- delete nobj;
- } else {
- delete context;
- }
- if (item) {
- QDeclarative_setParent_noEvent(item, q->contentItem());
- item->setParentItem(q->contentItem());
- item->setZ(1);
- QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
- itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
- footer = new FxGridItemSG(item, q);
- }
+
+ if (!footer) {
+ QSGItem *item = createComponentItem(footerComponent, true);
+ if (!item)
+ return;
+ item->setZ(1);
+ footer = new FxGridItemSG(item, q, true);
}
- if (footer) {
- qreal colOffset = 0;
- qreal rowOffset;
- if (isRightToLeftTopToBottom()) {
- rowOffset = footer->item->width()-cellWidth;
+
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(footer);
+ qreal colOffset = 0;
+ qreal rowOffset;
+ if (isRightToLeftTopToBottom()) {
+ rowOffset = gridItem->item->width()-cellWidth;
+ } else {
+ rowOffset = 0;
+ if (q->effectiveLayoutDirection() == Qt::RightToLeft)
+ colOffset = gridItem->item->width()-cellWidth;
+ }
+ if (visibleItems.count()) {
+ qreal endPos = lastPosition();
+ if (findLastVisibleIndex() == model->count()-1) {
+ gridItem->setPosition(colOffset, endPos + rowOffset);
} else {
- rowOffset = 0;
- if (q->effectiveLayoutDirection() == Qt::RightToLeft)
- colOffset = footer->item->width()-cellWidth;
+ qreal visiblePos = isRightToLeftTopToBottom() ? -position() : position() + size();
+ if (endPos <= visiblePos || gridItem->endPosition() < endPos + rowOffset)
+ gridItem->setPosition(colOffset, endPos + rowOffset);
}
- 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 == QSGGridView::LeftToRight) ? header->item->height() : header->item->width();
- }
- footer->setPosition(colOffset, endPos);
+ } else {
+ qreal endPos = 0;
+ if (header) {
+ endPos += headerSize();
}
+ gridItem->setPosition(colOffset, endPos);
}
}
void QSGGridViewPrivate::updateHeader()
{
Q_Q(QSGGridView);
- if (!header && headerComponent) {
- QSGItem *item = 0;
- QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
- QObject *nobj = headerComponent->create(context);
- if (nobj) {
- QDeclarative_setParent_noEvent(context, nobj);
- item = qobject_cast<QSGItem *>(nobj);
- if (!item)
- delete nobj;
- } else {
- delete context;
- }
- if (item) {
- QDeclarative_setParent_noEvent(item, q->contentItem());
- item->setParentItem(q->contentItem());
- item->setZ(1);
- QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
- itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
- header = new FxGridItemSG(item, q);
- }
+
+ if (!header) {
+ QSGItem *item = createComponentItem(headerComponent, true);
+ if (!item)
+ return;
+ item->setZ(1);
+ header = new FxGridItemSG(item, q, true);
}
- if (header) {
- qreal colOffset = 0;
- qreal rowOffset;
- if (isRightToLeftTopToBottom()) {
- rowOffset = -cellWidth;
+
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(header);
+ qreal colOffset = 0;
+ qreal rowOffset;
+ if (isRightToLeftTopToBottom()) {
+ rowOffset = -cellWidth;
+ } else {
+ rowOffset = -headerSize();
+ if (q->effectiveLayoutDirection() == Qt::RightToLeft)
+ colOffset = gridItem->item->width()-cellWidth;
+ }
+ if (visibleItems.count()) {
+ qreal startPos = originPosition();
+ if (visibleIndex == 0) {
+ gridItem->setPosition(colOffset, startPos + rowOffset);
} else {
- rowOffset = -headerSize();
- if (q->effectiveLayoutDirection() == Qt::RightToLeft)
- colOffset = header->item->width()-cellWidth;
+ qreal tempPos = isRightToLeftTopToBottom() ? -position()-size() : position();
+ qreal headerPos = isRightToLeftTopToBottom() ? gridItem->rowPos() + cellWidth - headerSize() : gridItem->rowPos();
+ if (tempPos <= startPos || headerPos > startPos + rowOffset)
+ gridItem->setPosition(colOffset, startPos + rowOffset);
}
- 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);
+ } else {
+ gridItem->setPosition(colOffset, 0);
+ }
+}
+
+void QSGGridViewPrivate::initializeCurrentItem()
+{
+ if (currentItem && currentIndex >= 0) {
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(currentItem);
+ if (gridItem)
+ gridItem->setPosition(colPosAt(currentIndex), rowPosAt(currentIndex));
+ }
+}
+
+void QSGGridViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_Q(QSGGridView);
+ QSGItemViewPrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
+ if (!q->isComponentComplete())
+ return;
+ if (item == q) {
+ if (newGeometry.height() != oldGeometry.height() || newGeometry.width() != oldGeometry.width()) {
+ updateViewport();
+ scheduleLayout();
}
}
}
@@ -1056,37 +790,37 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
if (snapMode != QSGGridView::NoSnap) {
qreal tempPosition = isRightToLeftTopToBottom() ? -position()-size() : position();
- FxGridItemSG *topItem = snapItemAt(tempPosition+highlightStart);
- FxGridItemSG *bottomItem = snapItemAt(tempPosition+highlightEnd);
+ FxViewItem *topItem = snapItemAt(tempPosition+highlightStart);
+ FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
qreal pos;
if (topItem && bottomItem && haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange) {
- qreal topPos = qMin(topItem->rowPos() - highlightStart, -maxExtent);
- qreal bottomPos = qMax(bottomItem->rowPos() - highlightEnd, -minExtent);
+ qreal topPos = qMin(topItem->position() - highlightStart, -maxExtent);
+ qreal bottomPos = qMax(bottomItem->position() - highlightEnd, -minExtent);
pos = qAbs(data.move + topPos) < qAbs(data.move + bottomPos) ? topPos : bottomPos;
} else if (topItem) {
qreal headerPos = 0;
if (header)
- headerPos = isRightToLeftTopToBottom() ? header->rowPos() + cellWidth - headerSize() : header->rowPos();
+ headerPos = isRightToLeftTopToBottom() ? static_cast<FxGridItemSG*>(header)->rowPos() + cellWidth - headerSize() : static_cast<FxGridItemSG*>(header)->rowPos();
if (topItem->index == 0 && header && tempPosition+highlightStart < headerPos+headerSize()/2) {
pos = isRightToLeftTopToBottom() ? - headerPos + highlightStart - size() : headerPos - highlightStart;
} else {
if (isRightToLeftTopToBottom())
- pos = qMax(qMin(-topItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-topItem->position() + highlightStart - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(topItem->rowPos() - highlightStart, -maxExtent), -minExtent);
+ pos = qMax(qMin(topItem->position() - highlightStart, -maxExtent), -minExtent);
}
} else if (bottomItem) {
if (isRightToLeftTopToBottom())
- pos = qMax(qMin(-bottomItem->rowPos() + highlightStart - size(), -maxExtent), -minExtent);
+ pos = qMax(qMin(-bottomItem->position() + highlightStart - size(), -maxExtent), -minExtent);
else
- pos = qMax(qMin(bottomItem->rowPos() - highlightStart, -maxExtent), -minExtent);
+ pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent);
} else {
- QSGFlickablePrivate::fixup(data, minExtent, maxExtent);
+ QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
return;
}
if (currentItem && haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange) {
updateHighlight();
- qreal currPos = currentItem->rowPos();
+ qreal currPos = static_cast<FxGridItemSG*>(currentItem)->rowPos();
if (isRightToLeftTopToBottom())
pos = -pos-size(); // Transform Pos if required
if (pos < currPos + rowSize() - highlightEnd)
@@ -1111,7 +845,7 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
} else if (haveHighlightRange && highlightRange == QSGGridView::StrictlyEnforceRange) {
if (currentItem) {
updateHighlight();
- qreal pos = currentItem->rowPos();
+ qreal pos = static_cast<FxGridItemSG*>(currentItem)->rowPos();
if (viewPos < pos + rowSize() - highlightEnd)
viewPos = pos + rowSize() - highlightEnd;
if (viewPos > pos - highlightStart)
@@ -1130,7 +864,7 @@ void QSGGridViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
vTime = timeline.time();
}
} else {
- QSGFlickablePrivate::fixup(data, minExtent, maxExtent);
+ QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
}
data.inOvershoot = false;
fixupMode = Normal;
@@ -1144,7 +878,7 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
moveReason = Mouse;
if ((!haveHighlightRange || highlightRange != QSGGridView::StrictlyEnforceRange)
&& snapMode == QSGGridView::NoSnap) {
- QSGFlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
+ QSGItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
return;
}
qreal maxDistance = 0;
@@ -1153,8 +887,8 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
if (velocity > 0) {
if (data.move.value() < minExtent) {
if (snapMode == QSGGridView::SnapOneRow) {
- if (FxGridItemSG *item = firstVisibleItem())
- maxDistance = qAbs(item->rowPos() + dataValue);
+ if (FxViewItem *item = firstVisibleItem())
+ maxDistance = qAbs(item->position() + dataValue);
} else {
maxDistance = qAbs(minExtent - data.move.value());
}
@@ -1238,338 +972,38 @@ void QSGGridViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
//----------------------------------------------------------------------------
QSGGridView::QSGGridView(QSGItem *parent)
- : QSGFlickable(*(new QSGGridViewPrivate), parent)
+ : QSGItemView(*(new QSGGridViewPrivate), parent)
{
- Q_D(QSGGridView);
- d->init();
}
QSGGridView::~QSGGridView()
{
- Q_D(QSGGridView);
- d->clear();
- if (d->ownModel)
- delete d->model;
- delete d->header;
- delete d->footer;
-}
-
-// For internal use
-int QSGGridView::modelCount() const
-{
- Q_D(const QSGGridView);
- return d->model->count();
-}
-
-QVariant QSGGridView::model() const
-{
- Q_D(const QSGGridView);
- return d->modelVariant;
-}
-
-void QSGGridView::setModel(const QVariant &model)
-{
- Q_D(QSGGridView);
- 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,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
- disconnect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
- }
- d->clear();
- d->modelVariant = model;
- QObject *object = qvariant_cast<QObject*>(model);
- QSGVisualModel *vim = 0;
- if (object && (vim = qobject_cast<QSGVisualModel *>(object))) {
- if (d->ownModel) {
- delete d->model;
- d->ownModel = false;
- }
- d->model = vim;
- } else {
- if (!d->ownModel) {
- d->model = new QSGVisualDataModel(qmlContext(this), this);
- d->ownModel = true;
- }
- if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
- dataModel->setModel(model);
- }
- if (d->model) {
- d->bufferMode = QSGGridViewPrivate::BufferBefore | QSGGridViewPrivate::BufferAfter;
- if (isComponentComplete()) {
- refill();
- if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
- setCurrentIndex(0);
- } else {
- d->moveReason = QSGGridViewPrivate::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 = QSGGridViewPrivate::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,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
- connect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
- emit countChanged();
- }
- emit modelChanged();
-}
-
-QDeclarativeComponent *QSGGridView::delegate() const
-{
- Q_D(const QSGGridView);
- if (d->model) {
- if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
- return dataModel->delegate();
- }
-
- return 0;
-}
-
-void QSGGridView::setDelegate(QDeclarativeComponent *delegate)
-{
- Q_D(QSGGridView);
- if (delegate == this->delegate())
- return;
-
- if (!d->ownModel) {
- d->model = new QSGVisualDataModel(qmlContext(this));
- d->ownModel = true;
- }
- if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(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 = QSGGridViewPrivate::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 = QSGGridViewPrivate::Other;
- }
- if (oldCount != dataModel->count())
- emit countChanged();
- emit delegateChanged();
- }
-}
-
-int QSGGridView::currentIndex() const
-{
- Q_D(const QSGGridView);
- return d->currentIndex;
-}
-
-void QSGGridView::setCurrentIndex(int index)
-{
- Q_D(QSGGridView);
- if (d->requestedIndex >= 0) // currently creating item
- return;
- d->currentIndexCleared = (index == -1);
- if (index == d->currentIndex)
- return;
- if (isComponentComplete() && d->isValid()) {
- d->moveReason = QSGGridViewPrivate::SetIndex;
- d->updateCurrent(index);
- } else {
- d->currentIndex = index;
- emit currentIndexChanged();
- }
-}
-
-QSGItem *QSGGridView::currentItem()
-{
- Q_D(QSGGridView);
- if (!d->currentItem)
- return 0;
- return d->currentItem->item;
-}
-
-QSGItem *QSGGridView::highlightItem()
-{
- Q_D(QSGGridView);
- if (!d->highlight)
- return 0;
- return d->highlight->item;
-}
-
-int QSGGridView::count() const
-{
- Q_D(const QSGGridView);
- if (d->model)
- return d->model->count();
- return 0;
-}
-
-QDeclarativeComponent *QSGGridView::highlight() const
-{
- Q_D(const QSGGridView);
- return d->highlightComponent;
-}
-
-void QSGGridView::setHighlight(QDeclarativeComponent *highlight)
-{
- Q_D(QSGGridView);
- if (highlight != d->highlightComponent) {
- d->highlightComponent = highlight;
- d->updateCurrent(d->currentIndex);
- emit highlightChanged();
- }
-}
-
-bool QSGGridView::highlightFollowsCurrentItem() const
-{
- Q_D(const QSGGridView);
- return d->autoHighlight;
}
void QSGGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
{
Q_D(QSGGridView);
if (d->autoHighlight != autoHighlight) {
- d->autoHighlight = autoHighlight;
- if (autoHighlight) {
- d->updateHighlight();
- } else if (d->highlightXAnimator) {
+ if (!autoHighlight && d->highlightXAnimator) {
d->highlightXAnimator->stop();
d->highlightYAnimator->stop();
}
+ QSGItemView::setHighlightFollowsCurrentItem(autoHighlight);
}
}
-int QSGGridView::highlightMoveDuration() const
-{
- Q_D(const QSGGridView);
- return d->highlightMoveDuration;
-}
-
void QSGGridView::setHighlightMoveDuration(int duration)
{
Q_D(QSGGridView);
if (d->highlightMoveDuration != duration) {
- d->highlightMoveDuration = duration;
if (d->highlightYAnimator) {
- d->highlightXAnimator->userDuration = d->highlightMoveDuration;
- d->highlightYAnimator->userDuration = d->highlightMoveDuration;
+ d->highlightXAnimator->userDuration = duration;
+ d->highlightYAnimator->userDuration = duration;
}
- emit highlightMoveDurationChanged();
+ QSGItemView::setHighlightMoveDuration(duration);
}
}
-qreal QSGGridView::preferredHighlightBegin() const
-{
- Q_D(const QSGGridView);
- return d->highlightRangeStart;
-}
-
-void QSGGridView::setPreferredHighlightBegin(qreal start)
-{
- Q_D(QSGGridView);
- d->highlightRangeStartValid = true;
- if (d->highlightRangeStart == start)
- return;
- d->highlightRangeStart = start;
- d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
- emit preferredHighlightBeginChanged();
-}
-
-void QSGGridView::resetPreferredHighlightBegin()
-{
- Q_D(QSGGridView);
- d->highlightRangeStartValid = false;
- if (d->highlightRangeStart == 0)
- return;
- d->highlightRangeStart = 0;
- emit preferredHighlightBeginChanged();
-}
-
-qreal QSGGridView::preferredHighlightEnd() const
-{
- Q_D(const QSGGridView);
- return d->highlightRangeEnd;
-}
-
-void QSGGridView::setPreferredHighlightEnd(qreal end)
-{
- Q_D(QSGGridView);
- d->highlightRangeEndValid = true;
- if (d->highlightRangeEnd == end)
- return;
- d->highlightRangeEnd = end;
- d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
- emit preferredHighlightEndChanged();
-}
-
-void QSGGridView::resetPreferredHighlightEnd()
-{
- Q_D(QSGGridView);
- d->highlightRangeEndValid = false;
- if (d->highlightRangeEnd == 0)
- return;
- d->highlightRangeEnd = 0;
- emit preferredHighlightEndChanged();
-}
-
-QSGGridView::HighlightRangeMode QSGGridView::highlightRangeMode() const
-{
- Q_D(const QSGGridView);
- return d->highlightRange;
-}
-
-void QSGGridView::setHighlightRangeMode(HighlightRangeMode mode)
-{
- Q_D(QSGGridView);
- if (d->highlightRange == mode)
- return;
- d->highlightRange = mode;
- d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
- emit highlightRangeModeChanged();
-}
-
-Qt::LayoutDirection QSGGridView::layoutDirection() const
-{
- Q_D(const QSGGridView);
- return d->layoutDirection;
-}
-
-void QSGGridView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
-{
- Q_D(QSGGridView);
- if (d->layoutDirection != layoutDirection) {
- d->layoutDirection = layoutDirection;
- d->regenerate();
- emit layoutDirectionChanged();
- emit effectiveLayoutDirectionChanged();
- }
-}
-
-Qt::LayoutDirection QSGGridView::effectiveLayoutDirection() const
-{
- Q_D(const QSGGridView);
- if (d->effectiveLayoutMirror)
- return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
- else
- return d->layoutDirection;
-}
-
QSGGridView::Flow QSGGridView::flow() const
{
Q_D(const QSGGridView);
@@ -1583,10 +1017,10 @@ void QSGGridView::setFlow(Flow flow)
d->flow = flow;
if (d->flow == LeftToRight) {
setContentWidth(-1);
- setFlickableDirection(QSGFlickable::VerticalFlick);
+ setFlickableDirection(VerticalFlick);
} else {
setContentHeight(-1);
- setFlickableDirection(QSGFlickable::HorizontalFlick);
+ setFlickableDirection(HorizontalFlick);
}
setContentX(0);
setContentY(0);
@@ -1595,37 +1029,6 @@ void QSGGridView::setFlow(Flow flow)
}
}
-bool QSGGridView::isWrapEnabled() const
-{
- Q_D(const QSGGridView);
- return d->wrap;
-}
-
-void QSGGridView::setWrapEnabled(bool wrap)
-{
- Q_D(QSGGridView);
- if (d->wrap == wrap)
- return;
- d->wrap = wrap;
- emit keyNavigationWrapsChanged();
-}
-
-int QSGGridView::cacheBuffer() const
-{
- Q_D(const QSGGridView);
- return d->buffer;
-}
-
-void QSGGridView::setCacheBuffer(int buffer)
-{
- Q_D(QSGGridView);
- if (d->buffer != buffer) {
- d->buffer = buffer;
- if (isComponentComplete())
- refill();
- emit cacheBufferChanged();
- }
-}
int QSGGridView::cellWidth() const
{
@@ -1638,9 +1041,9 @@ void QSGGridView::setCellWidth(int cellWidth)
Q_D(QSGGridView);
if (cellWidth != d->cellWidth && cellWidth > 0) {
d->cellWidth = qMax(1, cellWidth);
- d->updateGrid();
+ d->updateViewport();
emit cellWidthChanged();
- d->layout();
+ d->layoutVisibleItems();
}
}
@@ -1655,9 +1058,9 @@ void QSGGridView::setCellHeight(int cellHeight)
Q_D(QSGGridView);
if (cellHeight != d->cellHeight && cellHeight > 0) {
d->cellHeight = qMax(1, cellHeight);
- d->updateGrid();
+ d->updateViewport();
emit cellHeightChanged();
- d->layout();
+ d->layoutVisibleItems();
}
}
@@ -1676,90 +1079,17 @@ void QSGGridView::setSnapMode(SnapMode mode)
}
}
-QDeclarativeComponent *QSGGridView::footer() const
-{
- Q_D(const QSGGridView);
- return d->footerComponent;
-}
-
-void QSGGridView::setFooter(QDeclarativeComponent *footer)
-{
- Q_D(QSGGridView);
- if (d->footerComponent != footer) {
- if (d->footer) {
- // XXX todo - the original did scene()->removeItem(). Why?
- d->footer->item->setParentItem(0);
- d->footer->item->deleteLater();
- delete d->footer;
- d->footer = 0;
- }
- d->footerComponent = footer;
- if (isComponentComplete()) {
- d->updateFooter();
- d->updateGrid();
- d->fixupPosition();
- }
- emit footerChanged();
- }
-}
-
-QDeclarativeComponent *QSGGridView::header() const
-{
- Q_D(const QSGGridView);
- return d->headerComponent;
-}
-
-void QSGGridView::setHeader(QDeclarativeComponent *header)
-{
- Q_D(QSGGridView);
- if (d->headerComponent != header) {
- if (d->header) {
- // XXX todo - the original did scene()->removeItem(). Why?
- d->header->item->setParentItem(0);
- 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 QSGGridView::setContentX(qreal pos)
-{
- Q_D(QSGGridView);
- // Positioning the view manually should override any current movement state
- d->moveReason = QSGGridViewPrivate::Other;
- QSGFlickable::setContentX(pos);
-}
-
-void QSGGridView::setContentY(qreal pos)
-{
- Q_D(QSGGridView);
- // Positioning the view manually should override any current movement state
- d->moveReason = QSGGridViewPrivate::Other;
- QSGFlickable::setContentY(pos);
-}
-
-void QSGGridView::updatePolish()
-{
- Q_D(QSGGridView);
- QSGFlickable::updatePolish();
- d->layout();
-}
void QSGGridView::viewportMoved()
{
Q_D(QSGGridView);
- QSGFlickable::viewportMoved();
+ QSGItemView::viewportMoved();
if (!d->itemCount)
return;
+ if (d->inViewportMoved)
+ return;
+ d->inViewportMoved = true;
+
d->lazyRelease = true;
if (d->flickingHorizontally || d->flickingVertically) {
if (yflick()) {
@@ -1776,36 +1106,37 @@ void QSGGridView::viewportMoved()
d->bufferMode = QSGGridViewPrivate::BufferAfter;
}
}
- refill();
+ d->refill();
if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
d->moveReason = QSGGridViewPrivate::Mouse;
if (d->moveReason != QSGGridViewPrivate::SetIndex) {
if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange && d->highlight) {
// reposition highlight
- qreal pos = d->highlight->rowPos();
+ qreal pos = d->highlight->position();
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;
- viewPos = -d->position()-d->size();
} else {
+ viewPos = d->position();
highlightStart = d->highlightRangeStart;
highlightEnd = d->highlightRangeEnd;
- viewPos = d->position();
}
- if (pos > viewPos + highlightEnd - d->rowSize())
- pos = viewPos + highlightEnd - d->rowSize();
+ if (pos > viewPos + highlightEnd - d->highlight->size())
+ pos = viewPos + highlightEnd - d->highlight->size();
if (pos < viewPos + highlightStart)
pos = viewPos + highlightStart;
- d->highlight->setPosition(d->highlight->colPos(), qRound(pos));
+
+ static_cast<FxGridItemSG*>(d->highlight)->setPosition(static_cast<FxGridItemSG*>(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->currentItem && static_cast<FxGridItemSG*>(d->currentItem)->colPos() != static_cast<FxGridItemSG*>(d->highlight)->colPos() && d->autoHighlight) {
if (d->flow == LeftToRight)
d->highlightXAnimator->to = d->currentItem->item->x();
else
@@ -1814,120 +1145,8 @@ void QSGGridView::viewportMoved()
}
}
}
-}
-
-qreal QSGGridView::minYExtent() const
-{
- Q_D(const QSGGridView);
- if (d->flow == QSGGridView::TopToBottom)
- return QSGFlickable::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 QSGGridView::maxYExtent() const
-{
- Q_D(const QSGGridView);
- if (d->flow == QSGGridView::TopToBottom)
- return QSGFlickable::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 QSGGridView::minXExtent() const
-{
- Q_D(const QSGGridView);
- if (d->flow == QSGGridView::LeftToRight)
- return QSGFlickable::minXExtent();
- qreal extent = -d->startPosition();
- qreal highlightStart;
- qreal highlightEnd;
- qreal endPositionFirstItem;
- if (d->isRightToLeftTopToBottom()) {
- 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 += highlightStart;
- extent = qMax(extent, -(endPositionFirstItem - highlightEnd));
- }
- return extent;
-}
-
-qreal QSGGridView::maxXExtent() const
-{
- Q_D(const QSGGridView);
- if (d->flow == QSGGridView::LeftToRight)
- return QSGFlickable::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;
+ d->inViewportMoved = false;
}
void QSGGridView::keyPressEvent(QKeyEvent *event)
@@ -1959,7 +1178,7 @@ void QSGGridView::keyPressEvent(QKeyEvent *event)
}
d->moveReason = QSGGridViewPrivate::Other;
event->ignore();
- QSGFlickable::keyPressEvent(event);
+ QSGItemView::keyPressEvent(event);
}
void QSGGridView::moveCurrentIndexUp()
@@ -2066,214 +1285,6 @@ void QSGGridView::moveCurrentIndexRight()
}
}
-void QSGGridViewPrivate::positionViewAtIndex(int index, int mode)
-{
- Q_Q(QSGGridView);
- if (!isValid())
- return;
- if (mode < QSGGridView::Beginning || mode > QSGGridView::Contain)
- return;
-
- int idx = qMax(qMin(index, model->count()-1), 0);
-
- if (layoutScheduled)
- layout();
- qreal pos = isRightToLeftTopToBottom() ? -position() - size() : position();
- FxGridItemSG *item = visibleItem(idx);
- qreal maxExtent;
- if (flow == QSGGridView::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<FxGridItemSG*> oldVisible = visibleItems;
- visibleItems.clear();
- visibleIndex = idx - idx % columns;
- if (flow == QSGGridView::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 QSGGridView::Beginning:
- pos = itemPos;
- if (index < 0 && header) {
- pos -= flow == QSGGridView::LeftToRight
- ? header->item->height()
- : header->item->width();
- }
- break;
- case QSGGridView::Center:
- pos = itemPos - (size() - rowSize())/2;
- break;
- case QSGGridView::End:
- pos = itemPos - size() + rowSize();
- if (index >= model->count() && footer) {
- pos += flow == QSGGridView::LeftToRight
- ? footer->item->height()
- : footer->item->width();
- }
- break;
- case QSGGridView::Visible:
- if (itemPos > pos + size())
- pos = itemPos - size() + rowSize();
- else if (item->endRowPos() < pos)
- pos = itemPos;
- break;
- case QSGGridView::Contain:
- if (item->endRowPos() > pos + size())
- pos = itemPos - size() + rowSize();
- if (itemPos < pos)
- pos = itemPos;
- }
- pos = qMin(pos, maxExtent);
- qreal minExtent;
- if (flow == QSGGridView::LeftToRight)
- minExtent = -q->minYExtent();
- else
- minExtent = isRightToLeftTopToBottom() ? q->maxXExtent()-size() : -q->minXExtent();
- pos = qMax(pos, minExtent);
- moveReason = QSGGridViewPrivate::Other;
- q->cancelFlick();
- setPosition(pos);
- }
- fixupPosition();
-}
-
-void QSGGridView::positionViewAtIndex(int index, int mode)
-{
- Q_D(QSGGridView);
- if (!d->isValid() || index < 0 || index >= d->model->count())
- return;
- d->positionViewAtIndex(index, mode);
-}
-
-void QSGGridView::positionViewAtBeginning()
-{
- Q_D(QSGGridView);
- if (!d->isValid())
- return;
- d->positionViewAtIndex(-1, Beginning);
-}
-
-void QSGGridView::positionViewAtEnd()
-{
- Q_D(QSGGridView);
- if (!d->isValid())
- return;
- d->positionViewAtIndex(d->model->count(), End);
-}
-
-int QSGGridView::indexAt(qreal x, qreal y) const
-{
- Q_D(const QSGGridView);
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- const FxGridItemSG *listItem = d->visibleItems.at(i);
- if(listItem->contains(x, y))
- return listItem->index;
- }
-
- return -1;
-}
-
-void QSGGridView::componentComplete()
-{
- Q_D(QSGGridView);
- QSGFlickable::componentComplete();
- d->updateHeader();
- d->updateFooter();
- d->updateGrid();
- if (d->isValid()) {
- refill();
- d->moveReason = QSGGridViewPrivate::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 = QSGGridViewPrivate::Other;
- d->fixupPosition();
- }
-}
-
-void QSGGridView::trackedPositionChanged()
-{
- Q_D(QSGGridView);
- if (!d->trackedItem || !d->currentItem)
- return;
- if (d->moveReason == QSGGridViewPrivate::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 < viewPos + highlightStart) {
- pos = trackedPos - highlightStart;
- } else if (trackedPos > viewPos + highlightEnd - d->rowSize()) {
- pos = trackedPos - highlightEnd + d->rowSize();
- }
- }
- }
- } 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 QSGGridView::itemsInserted(int modelIndex, int count)
{
@@ -2294,9 +1305,9 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
// Insert before visible items
d->visibleIndex += count;
for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxGridItemSG *listItem = d->visibleItems.at(i);
- if (listItem->index != -1 && listItem->index >= modelIndex)
- listItem->index += count;
+ FxViewItem *item = d->visibleItems.at(i);
+ if (item->index != -1 && item->index >= modelIndex)
+ item->index += count;
}
}
if (d->currentIndex >= modelIndex) {
@@ -2327,12 +1338,14 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
if (d->visibleItems.count()) {
index -= d->visibleIndex;
if (index < d->visibleItems.count()) {
- colPos = d->visibleItems.at(index)->colPos();
- rowPos = d->visibleItems.at(index)->rowPos();
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(d->visibleItems.at(index));
+ colPos = gridItem->colPos();
+ rowPos = gridItem->rowPos();
} else {
// appending items to visible list
- colPos = d->visibleItems.at(index-1)->colPos() + d->colSize();
- rowPos = d->visibleItems.at(index-1)->rowPos();
+ FxGridItemSG *gridItem = static_cast<FxGridItemSG*>(d->visibleItems.at(index-1));
+ colPos = gridItem->colPos() + d->colSize();
+ rowPos = gridItem->rowPos();
if (colPos > d->colSize() * (d->columns-1)) {
colPos = 0;
rowPos += d->rowSize();
@@ -2344,9 +1357,9 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
// Update the indexes of the following visible items.
for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxGridItemSG *listItem = d->visibleItems.at(i);
- if (listItem->index != -1 && listItem->index >= modelIndex)
- listItem->index += count;
+ FxViewItem *item = d->visibleItems.at(i);
+ if (item->index != -1 && item->index >= modelIndex)
+ item->index += count;
}
bool addedVisible = false;
@@ -2357,7 +1370,7 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
d->scheduleLayout();
addedVisible = true;
}
- FxGridItemSG *item = d->createItem(modelIndex + i);
+ FxGridItemSG *item = static_cast<FxGridItemSG*>(d->createItem(modelIndex + i));
d->visibleItems.insert(index, item);
item->setPosition(colPos, rowPos);
added.append(item);
@@ -2379,7 +1392,7 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
// update visibleIndex
d->visibleIndex = 0;
- for (QList<FxGridItemSG*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
+ for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin(); it != d->visibleItems.end(); ++it) {
if ((*it)->index != -1) {
d->visibleIndex = (*it)->index;
break;
@@ -2391,7 +1404,7 @@ void QSGGridView::itemsInserted(int modelIndex, int count)
d->currentIndex += count;
if (d->currentItem) {
d->currentItem->index = d->currentIndex;
- d->currentItem->setPosition(d->colPosAt(d->currentIndex), d->rowPosAt(d->currentIndex));
+ static_cast<FxGridItemSG*>(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))) {
@@ -2417,9 +1430,9 @@ void QSGGridView::itemsRemoved(int modelIndex, int count)
bool removedVisible = false;
// Remove the items from the visible list, skipping anything already marked for removal
- QList<FxGridItemSG*>::Iterator it = d->visibleItems.begin();
+ QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
- FxGridItemSG *item = *it;
+ FxViewItem *item = *it;
if (item->index == -1 || item->index < modelIndex) {
// already removed, or before removed items
if (item->index < modelIndex && !removedVisible) {
@@ -2487,23 +1500,6 @@ void QSGGridView::itemsRemoved(int modelIndex, int count)
emit countChanged();
}
-void QSGGridView::destroyRemoved()
-{
- Q_D(QSGGridView);
- for (QList<FxGridItemSG*>::Iterator it = d->visibleItems.begin();
- it != d->visibleItems.end();) {
- FxGridItemSG *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 QSGGridView::itemsMoved(int from, int to, int count)
{
@@ -2512,15 +1508,15 @@ void QSGGridView::itemsMoved(int from, int to, int count)
return;
QHash<int,FxGridItemSG*> moved;
- FxGridItemSG *firstItem = d->firstVisibleItem();
+ FxGridItemSG *firstItem = static_cast<FxGridItemSG*>(d->firstVisibleItem());
- QList<FxGridItemSG*>::Iterator it = d->visibleItems.begin();
+ QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
- FxGridItemSG *item = *it;
+ FxViewItem *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);
+ moved.insert(item->index, static_cast<FxGridItemSG*>(item));
it = d->visibleItems.erase(it);
} else {
if (item->index > from && item->index != -1) {
@@ -2537,12 +1533,12 @@ void QSGGridView::itemsMoved(int from, int to, int count)
int endIndex = d->visibleIndex;
it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
- FxGridItemSG *item = *it;
+ FxViewItem *item = *it;
if (remaining && item->index >= to && item->index < to + count) {
// place items in the target position, reusing any existing items
FxGridItemSG *movedItem = moved.take(item->index);
if (!movedItem)
- movedItem = d->createItem(item->index);
+ movedItem = static_cast<FxGridItemSG*>(d->createItem(item->index));
it = d->visibleItems.insert(it, movedItem);
if (it == d->visibleItems.begin() && firstItem)
movedItem->setPosition(firstItem->colPos(), firstItem->rowPos());
@@ -2594,61 +1590,7 @@ void QSGGridView::itemsMoved(int from, int to, int count)
d->releaseItem(item);
}
- d->layout();
-}
-
-void QSGGridView::modelReset()
-{
- Q_D(QSGGridView);
- d->clear();
- refill();
- d->moveReason = QSGGridViewPrivate::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 = QSGGridViewPrivate::Other;
-
- emit countChanged();
-}
-
-void QSGGridView::createdItem(int index, QSGItem *item)
-{
- Q_D(QSGGridView);
- if (d->requestedIndex != index) {
- item->setParentItem(this);
- d->unrequestedItems.insert(item, index);
- if (d->flow == QSGGridView::LeftToRight) {
- item->setPos(QPointF(d->colPosAt(index), d->rowPosAt(index)));
- } else {
- item->setPos(QPointF(d->rowPosAt(index), d->colPosAt(index)));
- }
- }
-}
-
-void QSGGridView::destroyingItem(QSGItem *item)
-{
- Q_D(QSGGridView);
- d->unrequestedItems.remove(item);
-}
-
-void QSGGridView::animStopped()
-{
- Q_D(QSGGridView);
- d->bufferMode = QSGGridViewPrivate::NoBuffer;
- if (d->haveHighlightRange && d->highlightRange == QSGGridView::StrictlyEnforceRange)
- d->updateHighlight();
-}
-
-void QSGGridView::refill()
-{
- Q_D(QSGGridView);
- if (d->isRightToLeftTopToBottom())
- d->refill(-d->position()-d->size()+1, -d->position());
- else
- d->refill(d->position(), d->position()+d->size()-1);
+ d->layoutVisibleItems();
}
diff --git a/src/declarative/items/qsggridview_p.h b/src/declarative/items/qsggridview_p.h
index 8c167c8ab3..ae4ce346db 100644
--- a/src/declarative/items/qsggridview_p.h
+++ b/src/declarative/items/qsggridview_p.h
@@ -43,7 +43,7 @@
#ifndef QSGGRIDVIEW_P_H
#define QSGGRIDVIEW_P_H
-#include "qsgflickable_p.h"
+#include "qsgitemview_p.h"
#include <private/qdeclarativeguard_p.h>
@@ -55,98 +55,32 @@ QT_MODULE(Declarative)
class QSGVisualModel;
class QSGGridViewAttached;
class QSGGridViewPrivate;
-class Q_AUTOTEST_EXPORT QSGGridView : public QSGFlickable
+class Q_AUTOTEST_EXPORT QSGGridView : public QSGItemView
{
Q_OBJECT
Q_DECLARE_PRIVATE(QSGGridView)
- Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
- Q_PROPERTY(QSGItem *currentItem READ currentItem NOTIFY currentIndexChanged)
- Q_PROPERTY(int count READ count NOTIFY countChanged)
-
- Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
- Q_PROPERTY(QSGItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
- Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem)
- Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
-
- Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
- Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
- Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
-
Q_PROPERTY(Flow flow READ flow WRITE setFlow NOTIFY flowChanged)
- Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
- Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
- Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
- Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
Q_PROPERTY(int cellWidth READ cellWidth WRITE setCellWidth NOTIFY cellWidthChanged)
Q_PROPERTY(int cellHeight READ cellHeight WRITE setCellHeight NOTIFY cellHeightChanged)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
- Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
- Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
-
- Q_ENUMS(HighlightRangeMode)
Q_ENUMS(SnapMode)
Q_ENUMS(Flow)
- Q_ENUMS(PositionMode)
Q_CLASSINFO("DefaultProperty", "data")
public:
QSGGridView(QSGItem *parent=0);
~QSGGridView();
- QVariant model() const;
- int modelCount() const;
- void setModel(const QVariant &);
-
- QDeclarativeComponent *delegate() const;
- void setDelegate(QDeclarativeComponent *);
-
- int currentIndex() const;
- void setCurrentIndex(int idx);
-
- QSGItem *currentItem();
- QSGItem *highlightItem();
- int count() const;
-
- QDeclarativeComponent *highlight() const;
- void setHighlight(QDeclarativeComponent *highlight);
-
- bool highlightFollowsCurrentItem() const;
- void setHighlightFollowsCurrentItem(bool);
-
- int highlightMoveDuration() const;
- void setHighlightMoveDuration(int);
-
- enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
- HighlightRangeMode highlightRangeMode() const;
- void setHighlightRangeMode(HighlightRangeMode mode);
-
- qreal preferredHighlightBegin() const;
- void setPreferredHighlightBegin(qreal);
- void resetPreferredHighlightBegin();
-
- qreal preferredHighlightEnd() const;
- void setPreferredHighlightEnd(qreal);
- void resetPreferredHighlightEnd();
-
- Qt::LayoutDirection layoutDirection() const;
- void setLayoutDirection(Qt::LayoutDirection);
- Qt::LayoutDirection effectiveLayoutDirection() const;
+ virtual void setHighlightFollowsCurrentItem(bool);
+ virtual void setHighlightMoveDuration(int);
enum Flow { LeftToRight, TopToBottom };
Flow flow() const;
void setFlow(Flow);
- bool isWrapEnabled() const;
- void setWrapEnabled(bool);
-
- int cacheBuffer() const;
- void setCacheBuffer(int);
-
int cellWidth() const;
void setCellWidth(int);
@@ -157,22 +91,6 @@ public:
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
- QDeclarativeComponent *footer() const;
- void setFooter(QDeclarativeComponent *);
-
- QDeclarativeComponent *header() const;
- void setHeader(QDeclarativeComponent *);
-
- virtual void setContentX(qreal pos);
- virtual void setContentY(qreal pos);
-
- enum PositionMode { Beginning, Center, End, Visible, Contain };
-
- Q_INVOKABLE void positionViewAtIndex(int index, int mode);
- Q_INVOKABLE int indexAt(qreal x, qreal y) const;
- Q_INVOKABLE void positionViewAtBeginning();
- Q_INVOKABLE void positionViewAtEnd();
-
static QSGGridViewAttached *qmlAttachedProperties(QObject *);
public Q_SLOTS:
@@ -182,58 +100,28 @@ public Q_SLOTS:
void moveCurrentIndexRight();
Q_SIGNALS:
- void countChanged();
- void currentIndexChanged();
void cellWidthChanged();
void cellHeightChanged();
- void highlightChanged();
- void highlightItemChanged();
- void preferredHighlightBeginChanged();
- void preferredHighlightEndChanged();
- void highlightRangeModeChanged();
void highlightMoveDurationChanged();
- void modelChanged();
- void delegateChanged();
void flowChanged();
- void layoutDirectionChanged();
- void effectiveLayoutDirectionChanged();
- void keyNavigationWrapsChanged();
- void cacheBufferChanged();
void snapModeChanged();
- void headerChanged();
- void footerChanged();
protected:
- virtual void updatePolish();
virtual void viewportMoved();
- virtual qreal minYExtent() const;
- virtual qreal maxYExtent() const;
- virtual qreal minXExtent() const;
- virtual qreal maxXExtent() const;
virtual void keyPressEvent(QKeyEvent *);
- virtual void componentComplete();
private Q_SLOTS:
- void trackedPositionChanged();
void itemsInserted(int index, int count);
void itemsRemoved(int index, int count);
void itemsMoved(int from, int to, int count);
- void modelReset();
- void destroyRemoved();
- void createdItem(int index, QSGItem *item);
- void destroyingItem(QSGItem *item);
- void animStopped();
-
-private:
- void refill();
};
-class QSGGridViewAttached : public QObject
+class QSGGridViewAttached : public QSGItemViewAttached
{
Q_OBJECT
public:
QSGGridViewAttached(QObject *parent)
- : QObject(parent), m_view(0), m_isCurrent(false), m_delayRemove(false) {}
+ : QSGItemViewAttached(parent), m_view(0) {}
~QSGGridViewAttached() {}
Q_PROPERTY(QSGGridView *view READ view NOTIFY viewChanged)
@@ -245,38 +133,11 @@ public:
}
}
- Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
- bool isCurrentItem() const { return m_isCurrent; }
- void setIsCurrentItem(bool c) {
- if (m_isCurrent != c) {
- m_isCurrent = c;
- emit currentItemChanged();
- }
- }
-
- Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
- bool delayRemove() const { return m_delayRemove; }
- void setDelayRemove(bool delay) {
- if (m_delayRemove != delay) {
- m_delayRemove = delay;
- emit delayRemoveChanged();
- }
- }
-
- void emitAdd() { emit add(); }
- void emitRemove() { emit remove(); }
-
Q_SIGNALS:
- void currentItemChanged();
- void delayRemoveChanged();
- void add();
- void remove();
void viewChanged();
public:
QDeclarativeGuard<QSGGridView> m_view;
- bool m_isCurrent : 1;
- bool m_delayRemove : 1;
};
diff --git a/src/declarative/items/qsgitemview.cpp b/src/declarative/items/qsgitemview.cpp
new file mode 100644
index 0000000000..df242ac09d
--- /dev/null
+++ b/src/declarative/items/qsgitemview.cpp
@@ -0,0 +1,1363 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying ** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsgitemview_p_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+FxViewItem::FxViewItem(QSGItem *i, bool own)
+ : item(i), ownItem(own), index(-1)
+{
+}
+
+FxViewItem::~FxViewItem()
+{
+ if (ownItem && item) {
+ item->setParentItem(0);
+ item->deleteLater();
+ item = 0;
+ }
+}
+
+QSGItemView::QSGItemView(QSGFlickablePrivate &dd, QSGItem *parent)
+ : QSGFlickable(dd, parent)
+{
+ Q_D(QSGItemView);
+ d->init();
+}
+
+QSGItemView::~QSGItemView()
+{
+ Q_D(QSGItemView);
+ d->clear();
+ if (d->ownModel)
+ delete d->model;
+ delete d->header;
+ delete d->footer;
+}
+
+
+QSGItem *QSGItemView::currentItem() const
+{
+ Q_D(const QSGItemView);
+ if (!d->currentItem)
+ return 0;
+ return d->currentItem->item;
+}
+
+QVariant QSGItemView::model() const
+{
+ Q_D(const QSGItemView);
+ return d->modelVariant;
+}
+
+void QSGItemView::setModel(const QVariant &model)
+{
+ Q_D(QSGItemView);
+ 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(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
+ disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ disconnect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
+ disconnect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
+ }
+
+ QSGVisualModel *oldModel = d->model;
+
+ d->clear();
+ d->setPosition(0);
+ d->model = 0;
+ d->modelVariant = model;
+
+ QObject *object = qvariant_cast<QObject*>(model);
+ QSGVisualModel *vim = 0;
+ if (object && (vim = qobject_cast<QSGVisualModel *>(object))) {
+ if (d->ownModel) {
+ delete oldModel;
+ d->ownModel = false;
+ }
+ d->model = vim;
+ } else {
+ if (!d->ownModel) {
+ d->model = new QSGVisualDataModel(qmlContext(this), this);
+ d->ownModel = true;
+ } else {
+ d->model = oldModel;
+ }
+ if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
+ dataModel->setModel(model);
+ }
+
+ if (d->model) {
+ d->bufferMode = QSGItemViewPrivate::BufferBefore | QSGItemViewPrivate::BufferAfter;
+ if (isComponentComplete()) {
+ updateSections();
+ d->refill();
+ if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
+ setCurrentIndex(0);
+ } else {
+ d->moveReason = QSGItemViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->resetHighlightPosition();
+ d->updateTrackedItem();
+ }
+ d->moveReason = QSGItemViewPrivate::Other;
+ }
+ d->updateViewport();
+ }
+ 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(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
+ connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
+ connect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
+ connect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
+ emit countChanged();
+ }
+ emit modelChanged();
+}
+
+QDeclarativeComponent *QSGItemView::delegate() const
+{
+ Q_D(const QSGItemView);
+ if (d->model) {
+ if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
+ return dataModel->delegate();
+ }
+
+ return 0;
+}
+
+void QSGItemView::setDelegate(QDeclarativeComponent *delegate)
+{
+ Q_D(QSGItemView);
+ if (delegate == this->delegate())
+ return;
+ if (!d->ownModel) {
+ d->model = new QSGVisualDataModel(qmlContext(this));
+ d->ownModel = true;
+ }
+ if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(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;
+ updateSections();
+ d->refill();
+ d->moveReason = QSGItemViewPrivate::SetIndex;
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->resetHighlightPosition();
+ d->updateTrackedItem();
+ }
+ d->moveReason = QSGItemViewPrivate::Other;
+ d->updateViewport();
+ }
+ if (oldCount != dataModel->count())
+ emit countChanged();
+ }
+ emit delegateChanged();
+}
+
+
+int QSGItemView::count() const
+{
+ Q_D(const QSGItemView);
+ if (d->model)
+ return d->model->count();
+ return 0;
+}
+
+int QSGItemView::currentIndex() const
+{
+ Q_D(const QSGItemView);
+ return d->currentIndex;
+}
+
+void QSGItemView::setCurrentIndex(int index)
+{
+ Q_D(QSGItemView);
+ if (d->requestedIndex >= 0) // currently creating item
+ return;
+ d->currentIndexCleared = (index == -1);
+ if (index == d->currentIndex)
+ return;
+ if (isComponentComplete() && d->isValid()) {
+ d->moveReason = QSGItemViewPrivate::SetIndex;
+ d->updateCurrent(index);
+ } else if (d->currentIndex != index) {
+ d->currentIndex = index;
+ emit currentIndexChanged();
+ }
+}
+
+
+bool QSGItemView::isWrapEnabled() const
+{
+ Q_D(const QSGItemView);
+ return d->wrap;
+}
+
+void QSGItemView::setWrapEnabled(bool wrap)
+{
+ Q_D(QSGItemView);
+ if (d->wrap == wrap)
+ return;
+ d->wrap = wrap;
+ emit keyNavigationWrapsChanged();
+}
+
+int QSGItemView::cacheBuffer() const
+{
+ Q_D(const QSGItemView);
+ return d->buffer;
+}
+
+void QSGItemView::setCacheBuffer(int b)
+{
+ Q_D(QSGItemView);
+ if (d->buffer != b) {
+ d->buffer = b;
+ if (isComponentComplete()) {
+ d->bufferMode = QSGItemViewPrivate::BufferBefore | QSGItemViewPrivate::BufferAfter;
+ d->refill();
+ }
+ emit cacheBufferChanged();
+ }
+}
+
+
+Qt::LayoutDirection QSGItemView::layoutDirection() const
+{
+ Q_D(const QSGItemView);
+ return d->layoutDirection;
+}
+
+void QSGItemView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
+{
+ Q_D(QSGItemView);
+ if (d->layoutDirection != layoutDirection) {
+ d->layoutDirection = layoutDirection;
+ d->regenerate();
+ emit layoutDirectionChanged();
+ emit effectiveLayoutDirectionChanged();
+ }
+}
+
+Qt::LayoutDirection QSGItemView::effectiveLayoutDirection() const
+{
+ Q_D(const QSGItemView);
+ if (d->effectiveLayoutMirror)
+ return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
+ else
+ return d->layoutDirection;
+}
+
+
+QDeclarativeComponent *QSGItemView::header() const
+{
+ Q_D(const QSGItemView);
+ return d->headerComponent;
+}
+
+void QSGItemView::setHeader(QDeclarativeComponent *headerComponent)
+{
+ Q_D(QSGItemView);
+ if (d->headerComponent != headerComponent) {
+ delete d->header;
+ d->header = 0;
+ d->headerComponent = headerComponent;
+
+ d->minExtentDirty = true;
+ d->maxExtentDirty = true;
+
+ if (isComponentComplete()) {
+ d->updateHeader();
+ d->updateFooter();
+ d->updateViewport();
+ d->fixupPosition();
+ }
+ emit headerChanged();
+ }
+}
+
+QDeclarativeComponent *QSGItemView::footer() const
+{
+ Q_D(const QSGItemView);
+ return d->footerComponent;
+}
+
+void QSGItemView::setFooter(QDeclarativeComponent *footerComponent)
+{
+ Q_D(QSGItemView);
+ if (d->footerComponent != footerComponent) {
+ delete d->footer;
+ d->footer = 0;
+ d->footerComponent = footerComponent;
+
+ if (isComponentComplete()) {
+ d->updateFooter();
+ d->updateViewport();
+ d->fixupPosition();
+ }
+ emit footerChanged();
+ }
+}
+
+QDeclarativeComponent *QSGItemView::highlight() const
+{
+ Q_D(const QSGItemView);
+ return d->highlightComponent;
+}
+
+void QSGItemView::setHighlight(QDeclarativeComponent *highlightComponent)
+{
+ Q_D(QSGItemView);
+ if (highlightComponent != d->highlightComponent) {
+ d->highlightComponent = highlightComponent;
+ d->createHighlight();
+ if (d->currentItem)
+ d->updateHighlight();
+ emit highlightChanged();
+ }
+}
+
+QSGItem *QSGItemView::highlightItem() const
+{
+ Q_D(const QSGItemView);
+ if (!d->highlight)
+ return 0;
+ return d->highlight->item;
+}
+
+bool QSGItemView::highlightFollowsCurrentItem() const
+{
+ Q_D(const QSGItemView);
+ return d->autoHighlight;
+}
+
+void QSGItemView::setHighlightFollowsCurrentItem(bool autoHighlight)
+{
+ Q_D(QSGItemView);
+ if (d->autoHighlight != autoHighlight) {
+ d->autoHighlight = autoHighlight;
+ if (autoHighlight)
+ d->updateHighlight();
+ emit highlightFollowsCurrentItemChanged();
+ }
+}
+
+QSGItemView::HighlightRangeMode QSGItemView::highlightRangeMode() const
+{
+ Q_D(const QSGItemView);
+ return static_cast<QSGItemView::HighlightRangeMode>(d->highlightRange);
+}
+
+void QSGItemView::setHighlightRangeMode(HighlightRangeMode mode)
+{
+ Q_D(QSGItemView);
+ if (d->highlightRange == mode)
+ return;
+ d->highlightRange = mode;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit highlightRangeModeChanged();
+}
+
+//###Possibly rename these properties, since they are very useful even without a highlight?
+qreal QSGItemView::preferredHighlightBegin() const
+{
+ Q_D(const QSGItemView);
+ return d->highlightRangeStart;
+}
+
+void QSGItemView::setPreferredHighlightBegin(qreal start)
+{
+ Q_D(QSGItemView);
+ d->highlightRangeStartValid = true;
+ if (d->highlightRangeStart == start)
+ return;
+ d->highlightRangeStart = start;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit preferredHighlightBeginChanged();
+}
+
+void QSGItemView::resetPreferredHighlightBegin()
+{
+ Q_D(QSGItemView);
+ d->highlightRangeStartValid = false;
+ if (d->highlightRangeStart == 0)
+ return;
+ d->highlightRangeStart = 0;
+ emit preferredHighlightBeginChanged();
+}
+
+qreal QSGItemView::preferredHighlightEnd() const
+{
+ Q_D(const QSGItemView);
+ return d->highlightRangeEnd;
+}
+
+void QSGItemView::setPreferredHighlightEnd(qreal end)
+{
+ Q_D(QSGItemView);
+ d->highlightRangeEndValid = true;
+ if (d->highlightRangeEnd == end)
+ return;
+ d->highlightRangeEnd = end;
+ d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit preferredHighlightEndChanged();
+}
+
+void QSGItemView::resetPreferredHighlightEnd()
+{
+ Q_D(QSGItemView);
+ d->highlightRangeEndValid = false;
+ if (d->highlightRangeEnd == 0)
+ return;
+ d->highlightRangeEnd = 0;
+ emit preferredHighlightEndChanged();
+}
+
+int QSGItemView::highlightMoveDuration() const
+{
+ Q_D(const QSGItemView);
+ return d->highlightMoveDuration;
+}
+
+void QSGItemView::setHighlightMoveDuration(int duration)
+{
+ Q_D(QSGItemView);
+ if (d->highlightMoveDuration != duration) {
+ d->highlightMoveDuration = duration;
+ emit highlightMoveDurationChanged();
+ }
+}
+
+void QSGItemViewPrivate::positionViewAtIndex(int index, int mode)
+{
+ Q_Q(QSGItemView);
+ if (!isValid())
+ return;
+ if (mode < QSGItemView::Beginning || mode > QSGItemView::Contain)
+ return;
+ int idx = qMax(qMin(index, model->count()-1), 0);
+
+ if (layoutScheduled)
+ layout();
+ qreal pos = isContentFlowReversed() ? -position() - size() : position();
+ FxViewItem *item = visibleItem(idx);
+ qreal maxExtent;
+ if (layoutOrientation() == Qt::Vertical)
+ maxExtent = -q->maxYExtent();
+ else
+ maxExtent = isContentFlowReversed() ? q->minXExtent()-size(): -q->maxXExtent();
+ if (!item) {
+ int itemPos = positionAt(idx);
+ changedVisibleIndex(idx);
+ // save the currently visible items in case any of them end up visible again
+ QList<FxViewItem *> oldVisible = visibleItems;
+ visibleItems.clear();
+ 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) {
+ const qreal itemPos = item->position();
+ switch (mode) {
+ case QSGItemView::Beginning:
+ pos = itemPos;
+ if (index < 0 && header)
+ pos -= headerSize();
+ break;
+ case QSGItemView::Center:
+ pos = itemPos - (size() - item->size())/2;
+ break;
+ case QSGItemView::End:
+ pos = itemPos - size() + item->size();
+ if (index >= model->count() && footer)
+ pos += footerSize();
+ break;
+ case QSGItemView::Visible:
+ if (itemPos > pos + size())
+ pos = itemPos - size() + item->size();
+ else if (item->endPosition() < pos)
+ pos = itemPos;
+ break;
+ case QSGItemView::Contain:
+ if (item->endPosition() > pos + size())
+ pos = itemPos - size() + item->size();
+ if (itemPos < pos)
+ pos = itemPos;
+ }
+ pos = qMin(pos, maxExtent);
+ qreal minExtent;
+ if (layoutOrientation() == Qt::Vertical)
+ minExtent = -q->minYExtent();
+ else
+ minExtent = isContentFlowReversed() ? q->maxXExtent()-size(): -q->minXExtent();
+ pos = qMax(pos, minExtent);
+ moveReason = QSGItemViewPrivate::Other;
+ q->cancelFlick();
+ setPosition(pos);
+
+ if (highlight) {
+ if (autoHighlight)
+ resetHighlightPosition();
+ updateHighlight();
+ }
+ }
+ fixupPosition();
+}
+
+void QSGItemView::positionViewAtIndex(int index, int mode)
+{
+ Q_D(QSGItemView);
+ if (!d->isValid() || index < 0 || index >= d->model->count())
+ return;
+ d->positionViewAtIndex(index, mode);
+}
+
+
+void QSGItemView::positionViewAtBeginning()
+{
+ Q_D(QSGItemView);
+ if (!d->isValid())
+ return;
+ d->positionViewAtIndex(-1, Beginning);
+}
+
+void QSGItemView::positionViewAtEnd()
+{
+ Q_D(QSGItemView);
+ if (!d->isValid())
+ return;
+ d->positionViewAtIndex(d->model->count(), End);
+}
+
+int QSGItemView::indexAt(qreal x, qreal y) const
+{
+ Q_D(const QSGItemView);
+ for (int i = 0; i < d->visibleItems.count(); ++i) {
+ const FxViewItem *item = d->visibleItems.at(i);
+ if (item->contains(x, y))
+ return item->index;
+ }
+
+ return -1;
+}
+
+
+// for debugging only
+void QSGItemViewPrivate::checkVisible() const
+{
+ int skip = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
+ if (item->index == -1) {
+ ++skip;
+ } else if (item->index != visibleIndex + i - skip) {
+ qFatal("index %d %d %d", visibleIndex, i, item->index);
+ }
+ }
+}
+
+
+
+void QSGItemViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_Q(QSGItemView);
+ QSGFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
+ if (!q->isComponentComplete())
+ return;
+
+ if (header && header->item == item)
+ updateHeader();
+ else if (footer && footer->item == item)
+ updateFooter();
+
+ if (currentItem && currentItem->item == item)
+ updateHighlight();
+ if (trackedItem && trackedItem->item == item)
+ q->trackedPositionChanged();
+}
+
+void QSGItemView::destroyRemoved()
+{
+ Q_D(QSGItemView);
+ for (QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
+ it != d->visibleItems.end();) {
+ FxViewItem *item = *it;
+ if (item->index == -1 && item->attached->delayRemove() == false) {
+ d->releaseItem(item);
+ it = d->visibleItems.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ // Correct the positioning of the items
+ d->updateSections();
+ d->layout();
+}
+
+void QSGItemView::itemsChanged(int, int)
+{
+ Q_D(QSGItemView);
+ d->updateSections();
+ d->layout();
+}
+
+void QSGItemView::modelReset()
+{
+ Q_D(QSGItemView);
+ d->moveReason = QSGItemViewPrivate::SetIndex;
+ d->regenerate();
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->resetHighlightPosition();
+ d->updateTrackedItem();
+ }
+ d->moveReason = QSGItemViewPrivate::Other;
+
+ emit countChanged();
+}
+
+void QSGItemView::createdItem(int index, QSGItem *item)
+{
+ Q_D(QSGItemView);
+ if (d->requestedIndex != index) {
+ item->setParentItem(contentItem());
+ d->unrequestedItems.insert(item, index);
+ d->repositionPackageItemAt(item, index);
+ }
+}
+
+void QSGItemView::destroyingItem(QSGItem *item)
+{
+ Q_D(QSGItemView);
+ d->unrequestedItems.remove(item);
+}
+
+void QSGItemView::animStopped()
+{
+ Q_D(QSGItemView);
+ d->bufferMode = QSGItemViewPrivate::NoBuffer;
+ if (d->haveHighlightRange && d->highlightRange == QSGItemView::StrictlyEnforceRange)
+ d->updateHighlight();
+}
+
+
+void QSGItemView::trackedPositionChanged()
+{
+ Q_D(QSGItemView);
+ if (!d->trackedItem || !d->currentItem)
+ return;
+ if (d->moveReason == QSGItemViewPrivate::SetIndex) {
+ qreal trackedPos = d->trackedItem->position();
+ qreal trackedSize = d->trackedItem->size();
+ if (d->trackedItem != d->currentItem) {
+ trackedPos -= d->currentItem->sectionSize();
+ trackedSize += d->currentItem->sectionSize();
+ }
+ qreal viewPos;
+ qreal highlightStart;
+ qreal highlightEnd;
+ if (d->isContentFlowReversed()) {
+ 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->trackedItem->size())
+ pos = trackedPos - highlightEnd + d->trackedItem->size();
+ if (trackedPos < pos + highlightStart)
+ pos = trackedPos - highlightStart;
+ } else {
+ if (trackedPos < d->startPosition() + highlightStart) {
+ pos = d->startPosition();
+ } else if (d->trackedItem->endPosition() > d->endPosition() - d->size() + highlightEnd) {
+ pos = d->endPosition() - d->size() + 1;
+ if (pos < d->startPosition())
+ pos = d->startPosition();
+ } else {
+ if (trackedPos < viewPos + highlightStart) {
+ pos = trackedPos - highlightStart;
+ } else if (trackedPos > viewPos + highlightEnd - trackedSize) {
+ pos = trackedPos - highlightEnd + trackedSize;
+ }
+ }
+ }
+ } else {
+ if (trackedPos < viewPos && d->currentItem->position() < viewPos) {
+ pos = qMax(trackedPos, d->currentItem->position());
+ } else if (d->trackedItem->endPosition() >= viewPos + d->size()
+ && d->currentItem->endPosition() >= viewPos + d->size()) {
+ if (d->trackedItem->endPosition() <= d->currentItem->endPosition()) {
+ pos = d->trackedItem->endPosition() - d->size() + 1;
+ if (trackedSize > d->size())
+ pos = trackedPos;
+ } else {
+ pos = d->currentItem->endPosition() - d->size() + 1;
+ if (d->currentItem->size() > d->size())
+ pos = d->currentItem->position();
+ }
+ }
+ }
+ if (viewPos != pos) {
+ cancelFlick();
+ d->calcVelocity = true;
+ d->setPosition(pos);
+ d->calcVelocity = false;
+ }
+ }
+}
+
+
+void QSGItemView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_D(QSGItemView);
+ d->maxExtentDirty = true;
+ d->minExtentDirty = true;
+ QSGFlickable::geometryChanged(newGeometry, oldGeometry);
+}
+
+
+qreal QSGItemView::minYExtent() const
+{
+ Q_D(const QSGItemView);
+ if (d->layoutOrientation() == Qt::Horizontal)
+ return QSGFlickable::minYExtent();
+
+ if (d->minExtentDirty) {
+ d->minExtent = -d->startPosition();
+ if (d->header && d->visibleItems.count())
+ d->minExtent += d->headerSize();
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ d->minExtent += d->highlightRangeStart;
+ if (d->visibleItem(0))
+ d->minExtent -= d->visibleItem(0)->sectionSize();
+ d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1));
+ }
+ d->minExtentDirty = false;
+ }
+
+ return d->minExtent;
+}
+
+qreal QSGItemView::maxYExtent() const
+{
+ Q_D(const QSGItemView);
+ if (d->layoutOrientation() == Qt::Horizontal)
+ return height();
+
+ if (d->maxExtentDirty) {
+ if (!d->model || !d->model->count()) {
+ d->maxExtent = d->header ? -d->headerSize() : 0;
+ d->maxExtent += height();
+ } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
+ if (d->highlightRangeEnd != d->highlightRangeStart)
+ d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd + 1));
+ } else {
+ d->maxExtent = -(d->endPosition() - height() + 1);
+ }
+
+ if (d->footer)
+ d->maxExtent -= d->footerSize();
+ qreal minY = minYExtent();
+ if (d->maxExtent > minY)
+ d->maxExtent = minY;
+ d->maxExtentDirty = false;
+ }
+ return d->maxExtent;
+}
+
+qreal QSGItemView::minXExtent() const
+{
+ Q_D(const QSGItemView);
+ if (d->layoutOrientation() == Qt::Vertical)
+ return QSGFlickable::minXExtent();
+
+ if (d->minExtentDirty) {
+ d->minExtent = -d->startPosition();
+ qreal highlightStart;
+ qreal highlightEnd;
+ qreal endPositionFirstItem = 0;
+ if (d->isContentFlowReversed()) {
+ if (d->model && d->model->count())
+ endPositionFirstItem = d->positionAt(d->model->count()-1);
+ else if (d->header)
+ d->minExtent += d->headerSize();
+ highlightStart = d->highlightRangeStartValid
+ ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
+ : d->size() - (d->lastPosition()-endPositionFirstItem);
+ highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
+ if (d->footer)
+ d->minExtent += d->footerSize();
+ qreal maxX = maxXExtent();
+ if (d->minExtent < maxX)
+ d->minExtent = maxX;
+ } else {
+ endPositionFirstItem = d->endPositionAt(0);
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ if (d->header && d->visibleItems.count())
+ d->minExtent += d->headerSize();
+ }
+ if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ d->minExtent += highlightStart;
+ d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd + 1));
+ }
+ d->minExtentDirty = false;
+ }
+
+ return d->minExtent;
+}
+
+qreal QSGItemView::maxXExtent() const
+{
+ Q_D(const QSGItemView);
+ if (d->layoutOrientation() == Qt::Vertical)
+ return width();
+
+ if (d->maxExtentDirty) {
+ qreal highlightStart;
+ qreal highlightEnd;
+ qreal lastItemPosition = 0;
+ d->maxExtent = 0;
+ if (d->isContentFlowReversed()) {
+ highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
+ highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
+ lastItemPosition = d->endPosition();
+ } else {
+ highlightStart = d->highlightRangeStart;
+ highlightEnd = d->highlightRangeEnd;
+ if (d->model && d->model->count())
+ lastItemPosition = d->positionAt(d->model->count()-1);
+ }
+ if (!d->model || !d->model->count()) {
+ if (!d->isContentFlowReversed())
+ d->maxExtent = d->header ? -d->headerSize() : 0;
+ d->maxExtent += width();
+ } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
+ d->maxExtent = -(lastItemPosition - highlightStart);
+ if (highlightEnd != highlightStart) {
+ d->maxExtent = d->isContentFlowReversed()
+ ? qMax(d->maxExtent, -(d->endPosition() - highlightEnd + 1))
+ : qMin(d->maxExtent, -(d->endPosition() - highlightEnd + 1));
+ }
+ } else {
+ d->maxExtent = -(d->endPosition() - width() + 1);
+ }
+ if (d->isContentFlowReversed()) {
+ if (d->header && d->visibleItems.count())
+ d->maxExtent -= d->headerSize();
+ } else {
+ if (d->footer)
+ d->maxExtent -= d->footerSize();
+ qreal minX = minXExtent();
+ if (d->maxExtent > minX)
+ d->maxExtent = minX;
+ }
+ d->maxExtentDirty = false;
+ }
+
+ return d->maxExtent;
+}
+
+void QSGItemView::setContentX(qreal pos)
+{
+ Q_D(QSGItemView);
+ // Positioning the view manually should override any current movement state
+ d->moveReason = QSGItemViewPrivate::Other;
+ QSGFlickable::setContentX(pos);
+}
+
+void QSGItemView::setContentY(qreal pos)
+{
+ Q_D(QSGItemView);
+ // Positioning the view manually should override any current movement state
+ d->moveReason = QSGItemViewPrivate::Other;
+ QSGFlickable::setContentY(pos);
+}
+
+
+void QSGItemView::updatePolish()
+{
+ Q_D(QSGItemView);
+ QSGFlickable::updatePolish();
+ d->layout();
+}
+
+void QSGItemView::componentComplete()
+{
+ Q_D(QSGItemView);
+ QSGFlickable::componentComplete();
+
+ updateSections();
+ d->updateHeader();
+ d->updateFooter();
+ d->updateViewport();
+ if (d->isValid()) {
+ d->refill();
+ d->moveReason = QSGItemViewPrivate::SetIndex;
+ if (d->currentIndex < 0 && !d->currentIndexCleared)
+ d->updateCurrent(0);
+ else
+ d->updateCurrent(d->currentIndex);
+ if (d->highlight && d->currentItem) {
+ if (d->autoHighlight)
+ d->resetHighlightPosition();
+ d->updateTrackedItem();
+ }
+ d->moveReason = QSGItemViewPrivate::Other;
+ d->fixupPosition();
+ }
+}
+
+
+
+QSGItemViewPrivate::QSGItemViewPrivate()
+ : itemCount(0)
+ , buffer(0), bufferMode(BufferBefore | BufferAfter)
+ , layoutDirection(Qt::LeftToRight)
+ , moveReason(Other)
+ , visibleIndex(0)
+ , currentIndex(-1), currentItem(0)
+ , trackedItem(0), requestedIndex(-1)
+ , highlightComponent(0), highlight(0)
+ , highlightRange(QSGItemView::NoHighlightRange)
+ , highlightRangeStart(0), highlightRangeEnd(0)
+ , highlightMoveDuration(150)
+ , headerComponent(0), header(0), footerComponent(0), footer(0)
+ , minExtent(0), maxExtent(0)
+ , ownModel(false), wrap(false), lazyRelease(false), deferredRelease(false)
+ , layoutScheduled(false), inViewportMoved(false), currentIndexCleared(false)
+ , haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
+ , minExtentDirty(true), maxExtentDirty(true)
+{
+}
+
+bool QSGItemViewPrivate::isValid() const
+{
+ return model && model->count() && model->isValid();
+}
+
+qreal QSGItemViewPrivate::position() const
+{
+ Q_Q(const QSGItemView);
+ return layoutOrientation() == Qt::Vertical ? q->contentY() : q->contentX();
+}
+
+qreal QSGItemViewPrivate::size() const
+{
+ Q_Q(const QSGItemView);
+ return layoutOrientation() == Qt::Vertical ? q->height() : q->width();
+}
+
+int QSGItemViewPrivate::findLastVisibleIndex(int defaultValue) const
+{
+ if (visibleItems.count()) {
+ int i = visibleItems.count() - 1;
+ while (i > 0 && visibleItems.at(i)->index == -1)
+ --i;
+ if (visibleItems.at(i)->index != -1)
+ return visibleItems.at(i)->index;
+ }
+ return defaultValue;
+}
+
+FxViewItem *QSGItemViewPrivate::visibleItem(int modelIndex) const {
+ if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
+ for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return item;
+ }
+ }
+ return 0;
+}
+
+FxViewItem *QSGItemViewPrivate::firstVisibleItem() const {
+ const qreal pos = isContentFlowReversed() ? -position()-size() : position();
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
+ if (item->index != -1 && item->endPosition() > pos)
+ return item;
+ }
+ return visibleItems.count() ? visibleItems.first() : 0;
+}
+
+// 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 QSGItemViewPrivate::mapFromModel(int modelIndex) const
+{
+ if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
+ return -1;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
+ if (item->index == modelIndex)
+ return i + visibleIndex;
+ if (item->index > modelIndex)
+ return -1;
+ }
+ return -1; // Not in visibleList
+}
+
+void QSGItemViewPrivate::init()
+{
+ Q_Q(QSGItemView);
+ QSGItemPrivate::get(contentItem)->childrenDoNotOverlap = true;
+ q->setFlag(QSGItem::ItemIsFocusScope);
+ addItemChangeListener(this, Geometry);
+ QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
+ q->setFlickableDirection(QSGFlickable::VerticalFlick);
+}
+
+void QSGItemViewPrivate::updateCurrent(int modelIndex)
+{
+ Q_Q(QSGItemView);
+ 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;
+ }
+
+ FxViewItem *oldCurrentItem = currentItem;
+ currentIndex = modelIndex;
+ currentItem = createItem(modelIndex);
+ if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
+ oldCurrentItem->attached->setIsCurrentItem(false);
+ if (currentItem) {
+ currentItem->item->setFocus(true);
+ currentItem->attached->setIsCurrentItem(true);
+ initializeCurrentItem();
+ }
+
+ updateHighlight();
+ emit q->currentIndexChanged();
+ releaseItem(oldCurrentItem);
+}
+
+void QSGItemViewPrivate::clear()
+{
+ timeline.clear();
+
+ for (int i = 0; i < visibleItems.count(); ++i)
+ releaseItem(visibleItems.at(i));
+ visibleItems.clear();
+ visibleIndex = 0;
+
+ releaseItem(currentItem);
+ currentItem = 0;
+ createHighlight();
+ trackedItem = 0;
+
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ itemCount = 0;
+}
+
+
+void QSGItemViewPrivate::mirrorChange()
+{
+ Q_Q(QSGItemView);
+ regenerate();
+ emit q->effectiveLayoutDirectionChanged();
+}
+
+void QSGItemViewPrivate::refill()
+{
+ if (isContentFlowReversed())
+ refill(-position()-size()+1, -position());
+ else
+ refill(position(), position()+size()-1);
+}
+
+void QSGItemViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+{
+ Q_Q(QSGItemView);
+ 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;
+
+ // Item creation and release is staggered in order to avoid
+ // creating/releasing multiple items in one frame
+ // while flicking (as much as possible).
+
+ bool changed = addVisibleItems(fillFrom, fillTo, doBuffer);
+
+ if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
+ if (removeNonVisibleItems(bufferFrom, bufferTo))
+ changed = true;
+ deferredRelease = false;
+ } else {
+ deferredRelease = true;
+ }
+
+ if (changed) {
+ minExtentDirty = true;
+ maxExtentDirty = true;
+ visibleItemsChanged();
+ } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
+ refill(from, to, true);
+ }
+
+ lazyRelease = false;
+}
+
+void QSGItemViewPrivate::regenerate()
+{
+ Q_Q(QSGItemView);
+ if (q->isComponentComplete()) {
+ delete header;
+ header = 0;
+ delete footer;
+ footer = 0;
+ updateHeader();
+ updateFooter();
+ clear();
+ updateViewport();
+ setPosition(0);
+ refill();
+ updateCurrent(currentIndex);
+ }
+}
+
+void QSGItemViewPrivate::scheduleLayout()
+{
+ Q_Q(QSGItemView);
+ if (!layoutScheduled) {
+ layoutScheduled = true;
+ q->polish();
+ }
+}
+
+void QSGItemViewPrivate::updateViewport()
+{
+ Q_Q(QSGItemView);
+ if (isValid()) {
+ if (layoutOrientation() == Qt::Vertical)
+ q->setContentHeight(endPosition() - startPosition() + 1);
+ else
+ q->setContentWidth(endPosition() - startPosition() + 1);
+ }
+}
+
+void QSGItemViewPrivate::layout()
+{
+ Q_Q(QSGItemView);
+ layoutScheduled = false;
+ if (!isValid() && !visibleItems.count()) {
+ clear();
+ setPosition(0);
+ return;
+ }
+
+ layoutVisibleItems();
+ refill();
+
+ minExtentDirty = true;
+ maxExtentDirty = true;
+
+ updateHighlight();
+ if (!q->isMoving() && !q->isFlicking()) {
+ fixupPosition();
+ refill();
+ }
+
+ updateHeader();
+ updateFooter();
+ updateViewport();
+ updateUnrequestedPositions();
+}
+
+FxViewItem *QSGItemViewPrivate::createItem(int modelIndex)
+{
+ Q_Q(QSGItemView);
+
+ requestedIndex = modelIndex;
+ FxViewItem *viewItem = 0;
+
+ if (QSGItem *item = model->item(modelIndex, false)) {
+ viewItem = newViewItem(modelIndex, item);
+ if (viewItem) {
+ viewItem->index = modelIndex;
+ if (model->completePending()) {
+ // complete
+ viewItem->item->setZ(1);
+ viewItem->item->setParentItem(q->contentItem());
+ model->completeItem();
+ } else {
+ viewItem->item->setParentItem(q->contentItem());
+ }
+ // do other set up for the new item that should not happen
+ // until after bindings are evaluated
+ initializeViewItem(viewItem);
+
+ unrequestedItems.remove(viewItem->item);
+ }
+ }
+ requestedIndex = -1;
+ return viewItem;
+}
+
+
+void QSGItemViewPrivate::releaseItem(FxViewItem *item)
+{
+ Q_Q(QSGItemView);
+ if (!item || !model)
+ return;
+ if (trackedItem == item)
+ trackedItem = 0;
+ QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item->item);
+ itemPrivate->removeItemChangeListener(this, QSGItemPrivate::Geometry);
+ 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;
+}
+
+QSGItem *QSGItemViewPrivate::createHighlightItem()
+{
+ return createComponentItem(highlightComponent, true, true);
+}
+
+QSGItem *QSGItemViewPrivate::createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault)
+{
+ Q_Q(QSGItemView);
+
+ QSGItem *item = 0;
+ if (component) {
+ QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = component->create(context);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(context, nobj);
+ item = qobject_cast<QSGItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete context;
+ }
+ } else if (createDefault) {
+ item = new QSGItem;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q->contentItem());
+ item->setParentItem(q->contentItem());
+ if (receiveItemGeometryChanges) {
+ QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
+ itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
+ }
+ }
+ return item;
+}
+
+void QSGItemViewPrivate::updateTrackedItem()
+{
+ Q_Q(QSGItemView);
+ FxViewItem *item = currentItem;
+ if (highlight)
+ item = highlight;
+ trackedItem = item;
+
+ if (trackedItem)
+ q->trackedPositionChanged();
+}
+
+void QSGItemViewPrivate::updateUnrequestedIndexes()
+{
+ Q_Q(QSGItemView);
+ for (QHash<QSGItem*,int>::iterator it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ *it = model->indexOf(it.key(), q);
+}
+
+void QSGItemViewPrivate::updateUnrequestedPositions()
+{
+ for (QHash<QSGItem*,int>::const_iterator it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
+ repositionPackageItemAt(it.key(), it.value());
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/items/qsgitemview_p.h b/src/declarative/items/qsgitemview_p.h
new file mode 100644
index 0000000000..fb95e4fd8d
--- /dev/null
+++ b/src/declarative/items/qsgitemview_p.h
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGITEMVIEW_P_H
+#define QSGITEMVIEW_P_H
+
+#include "qsgflickable_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+
+class QSGItemViewPrivate;
+
+class Q_AUTOTEST_EXPORT QSGItemView : public QSGFlickable
+{
+ Q_OBJECT
+
+ Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
+ Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
+
+ Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
+ Q_PROPERTY(QSGItem *currentItem READ currentItem NOTIFY currentIndexChanged)
+
+ Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
+ Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
+
+ Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
+ Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
+ Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
+ Q_PROPERTY(QSGItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
+ Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged)
+ Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+ Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
+ Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
+ Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
+
+ Q_ENUMS(HighlightRangeMode)
+ Q_ENUMS(PositionMode)
+
+public:
+ QSGItemView(QSGFlickablePrivate &dd, QSGItem *parent = 0);
+ ~QSGItemView();
+
+ QVariant model() const;
+ void setModel(const QVariant &);
+
+ QDeclarativeComponent *delegate() const;
+ void setDelegate(QDeclarativeComponent *);
+
+ int count() const;
+
+ int currentIndex() const;
+ void setCurrentIndex(int idx);
+
+ QSGItem *currentItem() const;
+
+ bool isWrapEnabled() const;
+ void setWrapEnabled(bool);
+
+ int cacheBuffer() const;
+ void setCacheBuffer(int);
+
+ Qt::LayoutDirection layoutDirection() const;
+ void setLayoutDirection(Qt::LayoutDirection);
+ Qt::LayoutDirection effectiveLayoutDirection() const;
+
+ QDeclarativeComponent *footer() const;
+ void setFooter(QDeclarativeComponent *);
+
+ QDeclarativeComponent *header() const;
+ void setHeader(QDeclarativeComponent *);
+
+ QDeclarativeComponent *highlight() const;
+ void setHighlight(QDeclarativeComponent *);
+
+ QSGItem *highlightItem() const;
+
+ bool highlightFollowsCurrentItem() const;
+ virtual void setHighlightFollowsCurrentItem(bool);
+
+ enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ HighlightRangeMode highlightRangeMode() const;
+ void setHighlightRangeMode(HighlightRangeMode mode);
+
+ qreal preferredHighlightBegin() const;
+ void setPreferredHighlightBegin(qreal);
+ void resetPreferredHighlightBegin();
+
+ qreal preferredHighlightEnd() const;
+ void setPreferredHighlightEnd(qreal);
+ void resetPreferredHighlightEnd();
+
+ int highlightMoveDuration() const;
+ virtual void setHighlightMoveDuration(int);
+
+ enum PositionMode { Beginning, Center, End, Visible, Contain };
+
+ Q_INVOKABLE void positionViewAtIndex(int index, int mode);
+ Q_INVOKABLE int indexAt(qreal x, qreal y) const;
+ Q_INVOKABLE void positionViewAtBeginning();
+ Q_INVOKABLE void positionViewAtEnd();
+
+ virtual void setContentX(qreal pos);
+ virtual void setContentY(qreal pos);
+
+signals:
+ void modelChanged();
+ void delegateChanged();
+ void countChanged();
+ void currentIndexChanged();
+
+ void keyNavigationWrapsChanged();
+ void cacheBufferChanged();
+
+ void layoutDirectionChanged();
+ void effectiveLayoutDirectionChanged();
+
+ void headerChanged();
+ void footerChanged();
+
+ void highlightChanged();
+ void highlightItemChanged();
+ void highlightFollowsCurrentItemChanged();
+ void highlightRangeModeChanged();
+ void preferredHighlightBeginChanged();
+ void preferredHighlightEndChanged();
+ void highlightMoveDurationChanged();
+
+protected:
+ virtual void updatePolish();
+ virtual void componentComplete();
+ virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ virtual qreal minYExtent() const;
+ virtual qreal maxYExtent() const;
+ virtual qreal minXExtent() const;
+ virtual qreal maxXExtent() const;
+
+protected slots:
+ virtual void updateSections() {}
+ void destroyRemoved();
+ void itemsChanged(int index, int count);
+ void createdItem(int index, QSGItem *item);
+ void modelReset();
+ void destroyingItem(QSGItem *item);
+ void animStopped();
+ void trackedPositionChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QSGItemView)
+};
+
+
+class Q_AUTOTEST_EXPORT QSGItemViewAttached : public QObject
+{
+ Q_OBJECT
+
+ Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
+ Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
+
+ Q_PROPERTY(QString section READ section NOTIFY sectionChanged)
+ Q_PROPERTY(QString previousSection READ prevSection NOTIFY prevSectionChanged)
+ Q_PROPERTY(QString nextSection READ nextSection NOTIFY nextSectionChanged)
+
+public:
+ QSGItemViewAttached(QObject *parent)
+ : QObject(parent), m_isCurrent(false), m_delayRemove(false) {}
+ ~QSGItemViewAttached() {}
+
+ bool isCurrentItem() const { return m_isCurrent; }
+ void setIsCurrentItem(bool c) {
+ if (m_isCurrent != c) {
+ m_isCurrent = c;
+ emit currentItemChanged();
+ }
+ }
+
+ bool delayRemove() const { return m_delayRemove; }
+ void setDelayRemove(bool delay) {
+ if (m_delayRemove != delay) {
+ m_delayRemove = delay;
+ emit delayRemoveChanged();
+ }
+ }
+
+ QString section() const { return m_section; }
+ void setSection(const QString &sect) {
+ if (m_section != sect) {
+ m_section = sect;
+ emit sectionChanged();
+ }
+ }
+
+ QString prevSection() const { return m_prevSection; }
+ void setPrevSection(const QString &sect) {
+ if (m_prevSection != sect) {
+ m_prevSection = sect;
+ emit prevSectionChanged();
+ }
+ }
+
+ QString nextSection() const { return m_nextSection; }
+ void setNextSection(const QString &sect) {
+ if (m_nextSection != sect) {
+ m_nextSection = sect;
+ emit nextSectionChanged();
+ }
+ }
+
+ void emitAdd() { emit add(); }
+ void emitRemove() { emit remove(); }
+
+signals:
+ void currentItemChanged();
+ void delayRemoveChanged();
+
+ void add();
+ void remove();
+
+ void sectionChanged();
+ void prevSectionChanged();
+ void nextSectionChanged();
+
+public:
+ bool m_isCurrent : 1;
+ bool m_delayRemove : 1;
+
+ // current only used by list view
+ mutable QString m_section;
+ QString m_prevSection;
+ QString m_nextSection;
+};
+
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // QSGITEMVIEW_P_H
+
diff --git a/src/declarative/items/qsgitemview_p_p.h b/src/declarative/items/qsgitemview_p_p.h
new file mode 100644
index 0000000000..aa1d14d5be
--- /dev/null
+++ b/src/declarative/items/qsgitemview_p_p.h
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, 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.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSGITEMVIEW_P_P_H
+#define QSGITEMVIEW_P_P_H
+
+#include "qsgitemview_p.h"
+#include "qsgflickable_p_p.h"
+#include "qsgvisualitemmodel_p.h"
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class FxViewItem
+{
+public:
+ FxViewItem(QSGItem *, bool own);
+ ~FxViewItem();
+
+ // these are positions and sizes along the current direction of scrolling/flicking
+ virtual qreal position() const = 0;
+ virtual qreal endPosition() const = 0;
+ virtual qreal size() const = 0;
+ virtual qreal sectionSize() const = 0;
+
+ virtual bool contains(qreal x, qreal y) const = 0;
+
+ QSGItem *item;
+ bool ownItem;
+ int index;
+ QSGItemViewAttached *attached;
+};
+
+class QSGItemViewPrivate : public QSGFlickablePrivate
+{
+ Q_DECLARE_PUBLIC(QSGItemView)
+public:
+ QSGItemViewPrivate();
+
+ enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
+ enum MovementReason { Other, SetIndex, Mouse };
+
+ bool isValid() const;
+ qreal position() const;
+ qreal size() const;
+ int findLastVisibleIndex(int defaultValue = -1) const;
+ FxViewItem *visibleItem(int modelIndex) const;
+ FxViewItem *firstVisibleItem() const;
+ int mapFromModel(int modelIndex) const;
+
+ virtual void init();
+ virtual void updateCurrent(int modelIndex);
+ virtual void clear();
+ virtual void regenerate();
+ virtual void updateViewport();
+ void layout();
+ void refill();
+ void refill(qreal from, qreal to, bool doBuffer = false);
+ void scheduleLayout();
+ void mirrorChange();
+
+ FxViewItem *createItem(int modelIndex);
+ virtual void releaseItem(FxViewItem *item);
+
+ QSGItem *createHighlightItem();
+ QSGItem *createComponentItem(QDeclarativeComponent *component, bool receiveItemGeometryChanges, bool createDefault = false);
+
+ void updateTrackedItem();
+ void updateUnrequestedIndexes();
+ void updateUnrequestedPositions();
+ void positionViewAtIndex(int index, int mode);
+
+ void checkVisible() const;
+
+ QDeclarativeGuard<QSGVisualModel> model;
+ QVariant modelVariant;
+ int itemCount;
+ int buffer;
+ int bufferMode;
+ Qt::LayoutDirection layoutDirection;
+
+ MovementReason moveReason;
+
+ QList<FxViewItem *> visibleItems;
+ int visibleIndex;
+ int currentIndex;
+ FxViewItem *currentItem;
+ FxViewItem *trackedItem;
+ QHash<QSGItem*,int> unrequestedItems;
+ int requestedIndex;
+
+ // XXX split into struct
+ QDeclarativeComponent *highlightComponent;
+ FxViewItem *highlight;
+ int highlightRange; // enum value
+ qreal highlightRangeStart;
+ qreal highlightRangeEnd;
+ int highlightMoveDuration;
+
+ QDeclarativeComponent *headerComponent;
+ FxViewItem *header;
+ QDeclarativeComponent *footerComponent;
+ FxViewItem *footer;
+
+ mutable qreal minExtent;
+ mutable qreal maxExtent;
+
+ bool ownModel : 1;
+ bool wrap : 1;
+ bool lazyRelease : 1;
+ bool deferredRelease : 1;
+ bool layoutScheduled : 1;
+ bool inViewportMoved : 1;
+ bool currentIndexCleared : 1;
+ bool haveHighlightRange : 1;
+ bool autoHighlight : 1;
+ bool highlightRangeStartValid : 1;
+ bool highlightRangeEndValid : 1;
+ mutable bool minExtentDirty : 1;
+ mutable bool maxExtentDirty : 1;
+
+protected:
+ virtual Qt::Orientation layoutOrientation() const = 0;
+ virtual bool isContentFlowReversed() const = 0;
+
+ virtual qreal startPosition() const = 0;
+ virtual qreal positionAt(int index) const = 0;
+ virtual qreal endPosition() const = 0;
+ virtual qreal endPositionAt(int index) const = 0;
+ virtual qreal lastPosition() const = 0;
+
+ virtual qreal headerSize() const = 0;
+ virtual qreal footerSize() const = 0;
+ virtual void updateHeader() = 0;
+ virtual void updateFooter() = 0;
+
+ virtual void createHighlight() = 0;
+ virtual void updateHighlight() = 0;
+ virtual void resetHighlightPosition() = 0;
+
+ virtual void setPosition(qreal pos) = 0;
+ virtual void fixupPosition() = 0;
+
+ virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer) = 0;
+ virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo) = 0;
+ virtual void visibleItemsChanged() = 0;
+
+ virtual FxViewItem *newViewItem(int index, QSGItem *item) = 0;
+ virtual void initializeViewItem(FxViewItem *) {}
+ virtual void repositionPackageItemAt(QSGItem *item, int index) = 0;
+
+ virtual void layoutVisibleItems() = 0;
+
+ virtual void updateSections() {}
+ virtual void changedVisibleIndex(int newIndex) = 0;
+ virtual void initializeCurrentItem() {}
+
+ virtual void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSGITEMVIEW_P_P_H
diff --git a/src/declarative/items/qsglistview.cpp b/src/declarative/items/qsglistview.cpp
index 3e8f02c27e..f190e178c8 100644
--- a/src/declarative/items/qsglistview.cpp
+++ b/src/declarative/items/qsglistview.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
#include "qsglistview_p.h"
-#include "qsgflickable_p_p.h"
+#include "qsgitemview_p_p.h"
#include "qsgvisualitemmodel_p.h"
#include <QtDeclarative/qdeclarativeexpression.h>
@@ -89,15 +89,17 @@ QString QSGViewSection::sectionString(const QString &value)
//----------------------------------------------------------------------------
-class FxListItemSG
+class FxListItemSG : public FxViewItem
{
public:
- FxListItemSG(QSGItem *i, QSGListView *v) : item(i), section(0), view(v) {
+ FxListItemSG(QSGItem *i, QSGListView *v, bool own) : FxViewItem(i, own), section(0), view(v) {
attached = static_cast<QSGListViewAttached*>(qmlAttachedPropertiesObject<QSGListView>(item));
if (attached)
- attached->setView(view);
+ static_cast<QSGListViewAttached*>(attached)->setView(view);
}
+
~FxListItemSG() {}
+
qreal position() const {
if (section) {
if (view->orientation() == QSGListView::Vertical)
@@ -171,580 +173,385 @@ public:
y >= item->y() && y < item->y() + item->height());
}
- QSGItem *item;
QSGItem *section;
QSGListView *view;
- QSGListViewAttached *attached;
- int index;
};
//----------------------------------------------------------------------------
-class QSGListViewPrivate : public QSGFlickablePrivate
+class QSGListViewPrivate : public QSGItemViewPrivate
{
Q_DECLARE_PUBLIC(QSGListView)
-
public:
- QSGListViewPrivate()
- : currentItem(0), orient(QSGListView::Vertical), layoutDirection(Qt::LeftToRight)
- , visiblePos(0), visibleIndex(0)
- , averageSize(100.0), currentIndex(-1), requestedIndex(-1)
- , itemCount(0), highlightRangeStart(0), highlightRangeEnd(0)
- , highlightComponent(0), highlight(0), trackedItem(0)
- , moveReason(Other), buffer(0), highlightPosAnimator(0), highlightSizeAnimator(0)
- , sectionCriteria(0), spacing(0.0)
- , highlightMoveSpeed(400), highlightMoveDuration(-1)
- , highlightResizeSpeed(400), highlightResizeDuration(-1), highlightRange(QSGListView::NoHighlightRange)
- , snapMode(QSGListView::NoSnap), overshootDist(0.0)
- , footerComponent(0), footer(0), headerComponent(0), header(0)
- , bufferMode(BufferBefore | BufferAfter)
- , ownModel(false), wrap(false), autoHighlight(true), haveHighlightRange(false)
- , correctFlick(false), inFlickCorrection(false), lazyRelease(false)
- , deferredRelease(false), layoutScheduled(false), currentIndexCleared(false)
- , inViewportMoved(false)
- , highlightRangeStartValid(false), highlightRangeEndValid(false)
- , minExtentDirty(true), maxExtentDirty(true)
- {}
-
- void init();
- void clear();
- FxListItemSG *createItem(int modelIndex);
- void releaseItem(FxListItemSG *item);
-
- FxListItemSG *visibleItem(int modelIndex) const {
- if (modelIndex >= visibleIndex && modelIndex < visibleIndex + visibleItems.count()) {
- for (int i = modelIndex - visibleIndex; i < visibleItems.count(); ++i) {
- FxListItemSG *item = visibleItems.at(i);
- if (item->index == modelIndex)
- return item;
- }
- }
- return 0;
- }
+ virtual Qt::Orientation layoutOrientation() const;
+ virtual bool isContentFlowReversed() const;
+ bool isRightToLeft() const;
+
+ virtual qreal startPosition() const;
+ virtual qreal positionAt(int index) const;
+ virtual qreal endPosition() const;
+ virtual qreal endPositionAt(int index) const;
+ virtual qreal lastPosition() const;
+
+ qreal originPosition() const;
+ FxViewItem *nextVisibleItem() const;
+ FxViewItem *itemBefore(int modelIndex) const;
+ QString sectionAt(int modelIndex);
+ qreal snapPosAt(qreal pos);
+ FxViewItem *snapItemAt(qreal pos);
+
+ virtual void init();
+ virtual void clear();
+
+ virtual bool addVisibleItems(int fillFrom, int fillTo, bool doBuffer);
+ virtual bool removeNonVisibleItems(int bufferFrom, int bufferTo);
+ virtual void visibleItemsChanged();
+
+ virtual FxViewItem *newViewItem(int index, QSGItem *item);
+ virtual void initializeViewItem(FxViewItem *item);
+ virtual void releaseItem(FxViewItem *item);
+ virtual void repositionPackageItemAt(QSGItem *item, int index);
+
+ virtual void createHighlight();
+ virtual void updateHighlight();
+ virtual void resetHighlightPosition();
+
+ virtual void setPosition(qreal pos);
+ virtual void layoutVisibleItems();
+
+ virtual void updateSections();
+ void createSection(FxListItemSG *);
+ void updateCurrentSection();
- FxListItemSG *firstVisibleItem() const {
- const qreal pos = isRightToLeft() ? -position()-size() : position();
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxListItemSG *item = visibleItems.at(i);
- if (item->index != -1 && item->endPosition() > pos)
- return item;
- }
- return visibleItems.count() ? visibleItems.first() : 0;
- }
+ virtual qreal headerSize() const;
+ virtual qreal footerSize() const;
+ virtual void updateHeader();
+ virtual void updateFooter();
- FxListItemSG *nextVisibleItem() const {
- const qreal pos = isRightToLeft() ? -position()-size() : position();
- bool foundFirst = false;
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxListItemSG *item = visibleItems.at(i);
- if (item->index != -1) {
- if (foundFirst)
- return item;
- else if (item->position() < pos && item->endPosition() > pos)
- foundFirst = true;
- }
- }
- return 0;
- }
+ virtual void changedVisibleIndex(int newIndex);
+ virtual void initializeCurrentItem();
- // Returns the item before modelIndex, if created.
- // May return an item marked for removal.
- FxListItemSG *itemBefore(int modelIndex) const {
- if (modelIndex < visibleIndex)
- return 0;
- int idx = 1;
- int lastIndex = -1;
- while (idx < visibleItems.count()) {
- FxListItemSG *item = visibleItems.at(idx);
- if (item->index != -1)
- lastIndex = item->index;
- if (item->index == modelIndex)
- return visibleItems.at(idx-1);
- ++idx;
- }
- if (lastIndex == modelIndex-1)
- return visibleItems.last();
- return 0;
- }
-
- void regenerate() {
- Q_Q(QSGListView);
- if (q->isComponentComplete()) {
- if (header) {
- // XXX todo - the original did scene()->removeItem(). Why?
- header->item->setParentItem(0);
- header->item->deleteLater();
- delete header;
- header = 0;
- }
- if (footer) {
- // XXX todo - the original did scene()->removeItem(). Why?
- footer->item->setParentItem(0);
- footer->item->deleteLater();
- delete footer;
- footer = 0;
- }
- updateHeader();
- updateFooter();
- clear();
- setPosition(0);
- q->refill();
- updateCurrent(currentIndex);
- }
- }
+ void updateAverage();
- void mirrorChange() {
- Q_Q(QSGListView);
- regenerate();
- emit q->effectiveLayoutDirectionChanged();
- }
+ void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry);
+ virtual void fixupPosition();
+ virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
+ virtual void flick(QSGItemViewPrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
+ QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
- bool isRightToLeft() const {
- Q_Q(const QSGListView);
- return orient == QSGListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft;
- }
+ QSGListView::Orientation orient;
+ qreal visiblePos;
+ qreal averageSize;
+ qreal spacing;
+ QSGListView::SnapMode snapMode;
- qreal position() const {
- Q_Q(const QSGListView);
- return orient == QSGListView::Vertical ? q->contentY() : q->contentX();
- }
- void setPosition(qreal pos) {
- Q_Q(QSGListView);
- if (orient == QSGListView::Vertical) {
- q->QSGFlickable::setContentY(pos);
- } else {
- if (isRightToLeft())
- q->QSGFlickable::setContentX(-pos-size());
- else
- q->QSGFlickable::setContentX(pos);
- }
- }
- qreal size() const {
- Q_Q(const QSGListView);
- return orient == QSGListView::Vertical ? q->height() : q->width();
- }
+ QSmoothedAnimation *highlightPosAnimator;
+ QSmoothedAnimation *highlightSizeAnimator;
+ qreal highlightMoveSpeed;
+ qreal highlightResizeSpeed;
+ int highlightResizeDuration;
- qreal originPosition() const {
- qreal pos = 0;
- if (!visibleItems.isEmpty()) {
- pos = (*visibleItems.constBegin())->position();
- if (visibleIndex > 0)
- pos -= visibleIndex * (averageSize + spacing);
- }
- return pos;
- }
+ QSGViewSection *sectionCriteria;
+ QString currentSection;
+ static const int sectionCacheSize = 4;
+ QSGItem *sectionCache[sectionCacheSize];
- qreal lastPosition() const {
- qreal pos = 0;
- if (!visibleItems.isEmpty()) {
- int invisibleCount = visibleItems.count() - visibleIndex;
- for (int i = visibleItems.count()-1; i >= 0; --i) {
- if (visibleItems.at(i)->index != -1) {
- invisibleCount = model->count() - visibleItems.at(i)->index - 1;
- break;
- }
- }
- pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing);
- } else if (model && model->count()) {
- pos = model->count() * averageSize + (model->count()-1) * spacing;
- }
- return pos;
- }
+ qreal overshootDist;
+ bool correctFlick : 1;
+ bool inFlickCorrection : 1;
- qreal startPosition() const {
- return isRightToLeft() ? -lastPosition()-1 : originPosition();
- }
+ QSGListViewPrivate()
+ : orient(QSGListView::Vertical)
+ , visiblePos(0)
+ , averageSize(100.0), spacing(0.0)
+ , snapMode(QSGListView::NoSnap)
+ , highlightPosAnimator(0), highlightSizeAnimator(0)
+ , highlightMoveSpeed(400), highlightResizeSpeed(400), highlightResizeDuration(-1)
+ , sectionCriteria(0)
+ , overshootDist(0.0), correctFlick(false), inFlickCorrection(false)
+ {}
+};
- qreal endPosition() const {
- return isRightToLeft() ? -originPosition()-1 : lastPosition();
- }
-
- qreal positionAt(int modelIndex) const {
- if (FxListItemSG *item = visibleItem(modelIndex))
- return item->position();
- if (!visibleItems.isEmpty()) {
- if (modelIndex < visibleIndex) {
- int count = visibleIndex - modelIndex;
- qreal cs = 0;
- if (modelIndex == currentIndex && currentItem) {
- cs = currentItem->size() + spacing;
- --count;
- }
- return (*visibleItems.constBegin())->position() - count * (averageSize + spacing) - cs;
- } else {
- int idx = visibleItems.count() - 1;
- while (idx >= 0 && visibleItems.at(idx)->index == -1)
- --idx;
- if (idx < 0)
- idx = visibleIndex;
- else
- idx = visibleItems.at(idx)->index;
- int count = modelIndex - idx - 1;
- return (*(--visibleItems.constEnd()))->endPosition() + spacing + count * (averageSize + spacing) + 1;
- }
- }
- return 0;
- }
+bool QSGListViewPrivate::isContentFlowReversed() const
+{
+ return isRightToLeft();
+}
- qreal endPositionAt(int modelIndex) const {
- if (FxListItemSG *item = visibleItem(modelIndex))
- return item->endPosition();
- if (!visibleItems.isEmpty()) {
- if (modelIndex < visibleIndex) {
- int count = visibleIndex - modelIndex;
- return (*visibleItems.constBegin())->position() - (count - 1) * (averageSize + spacing) - spacing - 1;
- } else {
- int idx = visibleItems.count() - 1;
- while (idx >= 0 && visibleItems.at(idx)->index == -1)
- --idx;
- if (idx < 0)
- idx = visibleIndex;
- else
- idx = visibleItems.at(idx)->index;
- int count = modelIndex - idx - 1;
- return (*(--visibleItems.constEnd()))->endPosition() + count * (averageSize + spacing);
- }
- }
- return 0;
- }
+Qt::Orientation QSGListViewPrivate::layoutOrientation() const
+{
+ return static_cast<Qt::Orientation>(orient);
+}
- QString sectionAt(int modelIndex) {
- if (FxListItemSG *item = visibleItem(modelIndex))
- return item->attached->section();
+bool QSGListViewPrivate::isRightToLeft() const
+{
+ Q_Q(const QSGListView);
+ return orient == QSGListView::Horizontal && q->effectiveLayoutDirection() == Qt::RightToLeft;
+}
- QString section;
- if (sectionCriteria) {
- QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
- section = sectionCriteria->sectionString(propValue);
+FxViewItem *QSGListViewPrivate::nextVisibleItem() const
+{
+ const qreal pos = isRightToLeft() ? -position()-size() : position();
+ bool foundFirst = false;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
+ if (item->index != -1) {
+ if (foundFirst)
+ return item;
+ else if (item->position() < pos && item->endPosition() > pos)
+ foundFirst = true;
}
-
- return section;
}
+ return 0;
+}
- bool isValid() const {
- return model && model->count() && model->isValid();
- }
+// Returns the item before modelIndex, if created.
+// May return an item marked for removal.
+FxViewItem *QSGListViewPrivate::itemBefore(int modelIndex) const
+{
+ if (modelIndex < visibleIndex)
+ return 0;
+ int idx = 1;
+ int lastIndex = -1;
+ while (idx < visibleItems.count()) {
+ FxViewItem *item = visibleItems.at(idx);
+ if (item->index != -1)
+ lastIndex = item->index;
+ if (item->index == modelIndex)
+ return visibleItems.at(idx-1);
+ ++idx;
+ }
+ if (lastIndex == modelIndex-1)
+ return visibleItems.last();
+ return 0;
+}
- qreal snapPosAt(qreal pos) {
- if (FxListItemSG *snapItem = snapItemAt(pos))
- return snapItem->position();
- if (visibleItems.count()) {
- qreal firstPos = visibleItems.first()->position();
- qreal endPos = visibleItems.last()->position();
- if (pos < firstPos) {
- return firstPos - qRound((firstPos - pos) / averageSize) * averageSize;
- } else if (pos > endPos)
- return endPos + qRound((pos - endPos) / averageSize) * averageSize;
- }
- return qRound((pos - originPosition()) / averageSize) * averageSize + originPosition();
+void QSGListViewPrivate::setPosition(qreal pos)
+{
+ Q_Q(QSGListView);
+ if (orient == QSGListView::Vertical) {
+ q->QSGFlickable::setContentY(pos);
+ } else {
+ if (isRightToLeft())
+ q->QSGFlickable::setContentX(-pos-size());
+ else
+ q->QSGFlickable::setContentX(pos);
}
+}
- FxListItemSG *snapItemAt(qreal pos) {
- FxListItemSG *snapItem = 0;
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxListItemSG *item = visibleItems[i];
- if (item->index == -1)
- continue;
- qreal itemTop = item->position();
- if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size() - 1)
- return item;
- if (itemTop+item->size()/2 >= pos && itemTop-item->size()/2 < pos)
- snapItem = item;
- }
- return snapItem;
+qreal QSGListViewPrivate::originPosition() const
+{
+ qreal pos = 0;
+ if (!visibleItems.isEmpty()) {
+ pos = (*visibleItems.constBegin())->position();
+ if (visibleIndex > 0)
+ pos -= visibleIndex * (averageSize + spacing);
}
+ return pos;
+}
- int lastVisibleIndex() const {
- int lastIndex = -1;
+qreal QSGListViewPrivate::lastPosition() const
+{
+ qreal pos = 0;
+ if (!visibleItems.isEmpty()) {
+ int invisibleCount = visibleItems.count() - visibleIndex;
for (int i = visibleItems.count()-1; i >= 0; --i) {
- FxListItemSG *listItem = visibleItems.at(i);
- if (listItem->index != -1) {
- lastIndex = listItem->index;
+ if (visibleItems.at(i)->index != -1) {
+ invisibleCount = model->count() - visibleItems.at(i)->index - 1;
break;
}
}
- return lastIndex;
+ pos = (*(--visibleItems.constEnd()))->endPosition() + invisibleCount * (averageSize + spacing);
+ } else if (model && model->count()) {
+ pos = model->count() * averageSize + (model->count()-1) * spacing;
}
+ return pos;
+}
- // map a model index to visibleItems index.
- int mapFromModel(int modelIndex) const {
- if (modelIndex < visibleIndex || modelIndex >= visibleIndex + visibleItems.count())
- return -1;
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxListItemSG *listItem = visibleItems.at(i);
- if (listItem->index == modelIndex)
- return i;
- if (listItem->index > modelIndex)
- return -1;
+qreal QSGListViewPrivate::startPosition() const
+{
+ return isRightToLeft() ? -lastPosition()-1 : originPosition();
+}
+
+qreal QSGListViewPrivate::endPosition() const
+{
+ return isRightToLeft() ? -originPosition()-1 : lastPosition();
+}
+
+qreal QSGListViewPrivate::positionAt(int modelIndex) const
+{
+ if (FxViewItem *item = visibleItem(modelIndex))
+ return item->position();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = visibleIndex - modelIndex;
+ qreal cs = 0;
+ if (modelIndex == currentIndex && currentItem) {
+ cs = currentItem->size() + spacing;
+ --count;
+ }
+ return (*visibleItems.constBegin())->position() - count * (averageSize + spacing) - cs;
+ } else {
+ int count = modelIndex - findLastVisibleIndex(visibleIndex) - 1;
+ return (*(--visibleItems.constEnd()))->endPosition() + spacing + count * (averageSize + spacing) + 1;
}
- return -1; // Not in visibleList
}
+ return 0;
+}
- void updateViewport() {
- Q_Q(QSGListView);
- if (orient == QSGListView::Vertical) {
- q->setContentHeight(endPosition() - startPosition() + 1);
+qreal QSGListViewPrivate::endPositionAt(int modelIndex) const
+{
+ if (FxViewItem *item = visibleItem(modelIndex))
+ return item->endPosition();
+ if (!visibleItems.isEmpty()) {
+ if (modelIndex < visibleIndex) {
+ int count = visibleIndex - modelIndex;
+ return (*visibleItems.constBegin())->position() - (count - 1) * (averageSize + spacing) - spacing - 1;
} else {
- q->setContentWidth(endPosition() - startPosition() + 1);
+ int count = modelIndex - findLastVisibleIndex(visibleIndex) - 1;
+ return (*(--visibleItems.constEnd()))->endPosition() + count * (averageSize + spacing);
}
}
+ return 0;
+}
- void itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry) {
- Q_Q(QSGListView);
- QSGFlickablePrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
- if (!q->isComponentComplete())
- return;
- if (item != contentItem && (!highlight || item != highlight->item)) {
- if ((orient == QSGListView::Vertical && newGeometry.height() != oldGeometry.height())
- || (orient == QSGListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
- scheduleLayout();
- }
- }
- if ((header && header->item == item) || (footer && footer->item == item)) {
- if (header)
- updateHeader();
- if (footer)
- updateFooter();
- }
- if (currentItem && currentItem->item == item)
- updateHighlight();
- if (trackedItem && trackedItem->item == item)
- q->trackedPositionChanged();
+QString QSGListViewPrivate::sectionAt(int modelIndex)
+{
+ if (FxViewItem *item = visibleItem(modelIndex))
+ return item->attached->section();
+
+ QString section;
+ if (sectionCriteria) {
+ QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
+ section = sectionCriteria->sectionString(propValue);
}
- // for debugging only
- void checkVisible() const {
- int skip = 0;
- for (int i = 0; i < visibleItems.count(); ++i) {
- FxListItemSG *listItem = visibleItems.at(i);
- if (listItem->index == -1) {
- ++skip;
- } else if (listItem->index != visibleIndex + i - skip) {
- qFatal("index %d %d %d", visibleIndex, i, listItem->index);
- }
- }
+ return section;
+}
+
+qreal QSGListViewPrivate::snapPosAt(qreal pos)
+{
+ if (FxViewItem *snapItem = snapItemAt(pos))
+ return snapItem->position();
+ if (visibleItems.count()) {
+ qreal firstPos = (*visibleItems.constBegin())->position();
+ qreal endPos = (*(--visibleItems.constEnd()))->position();
+ if (pos < firstPos) {
+ return firstPos - qRound((firstPos - pos) / averageSize) * averageSize;
+ } else if (pos > endPos)
+ return endPos + qRound((pos - endPos) / averageSize) * averageSize;
}
+ return qRound((pos - originPosition()) / averageSize) * averageSize + originPosition();
+}
- void refill(qreal from, qreal to, bool doBuffer = false);
- void scheduleLayout();
- void layout();
- void updateUnrequestedIndexes();
- void updateUnrequestedPositions();
- void updateTrackedItem();
- void createHighlight();
- void updateHighlight();
- void createSection(FxListItemSG *);
- void updateSections();
- void updateCurrentSection();
- void updateCurrent(int);
- void updateAverage();
- void updateHeader();
- void updateFooter();
- void fixupPosition();
- void positionViewAtIndex(int index, int mode);
- virtual void fixup(AxisData &data, qreal minExtent, qreal maxExtent);
- virtual void flick(QSGFlickablePrivate::AxisData &data, qreal minExtent, qreal maxExtent, qreal vSize,
- QDeclarativeTimeLineCallback::Callback fixupCallback, qreal velocity);
+FxViewItem *QSGListViewPrivate::snapItemAt(qreal pos)
+{
+ FxViewItem *snapItem = 0;
+ for (int i = 0; i < visibleItems.count(); ++i) {
+ FxViewItem *item = visibleItems.at(i);
+ if (item->index == -1)
+ continue;
+ qreal itemTop = item->position();
+ if (highlight && itemTop >= pos && item->endPosition() <= pos + highlight->size() - 1)
+ return item;
+ if (itemTop+item->size()/2 >= pos && itemTop-item->size()/2 < pos)
+ snapItem = item;
+ }
+ return snapItem;
+}
- QDeclarativeGuard<QSGVisualModel> model;
- QVariant modelVariant;
- QList<FxListItemSG*> visibleItems;
- QHash<QSGItem*,int> unrequestedItems;
- FxListItemSG *currentItem;
- QSGListView::Orientation orient;
- Qt::LayoutDirection layoutDirection;
- qreal visiblePos;
- int visibleIndex;
- qreal averageSize;
- int currentIndex;
- int requestedIndex;
- int itemCount;
- qreal highlightRangeStart;
- qreal highlightRangeEnd;
- QDeclarativeComponent *highlightComponent;
- FxListItemSG *highlight;
- FxListItemSG *trackedItem;
- enum MovementReason { Other, SetIndex, Mouse };
- MovementReason moveReason;
- int buffer;
- QSmoothedAnimation *highlightPosAnimator;
- QSmoothedAnimation *highlightSizeAnimator;
- QSGViewSection *sectionCriteria;
- QString currentSection;
- static const int sectionCacheSize = 4;
- QSGItem *sectionCache[sectionCacheSize];
- qreal spacing;
- qreal highlightMoveSpeed;
- int highlightMoveDuration;
- qreal highlightResizeSpeed;
- int highlightResizeDuration;
- QSGListView::HighlightRangeMode highlightRange;
- QSGListView::SnapMode snapMode;
- qreal overshootDist;
- QDeclarativeComponent *footerComponent;
- FxListItemSG *footer;
- QDeclarativeComponent *headerComponent;
- FxListItemSG *header;
- enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
- int bufferMode;
- mutable qreal minExtent;
- mutable qreal maxExtent;
-
- bool ownModel : 1;
- bool wrap : 1;
- bool autoHighlight : 1;
- bool haveHighlightRange : 1;
- bool correctFlick : 1;
- bool inFlickCorrection : 1;
- bool lazyRelease : 1;
- bool deferredRelease : 1;
- bool layoutScheduled : 1;
- bool currentIndexCleared : 1;
- bool inViewportMoved : 1;
- bool highlightRangeStartValid : 1;
- bool highlightRangeEndValid : 1;
- mutable bool minExtentDirty : 1;
- mutable bool maxExtentDirty : 1;
-};
+void QSGListViewPrivate::changedVisibleIndex(int newIndex)
+{
+ visiblePos = positionAt(newIndex);
+ visibleIndex = newIndex;
+}
void QSGListViewPrivate::init()
{
- Q_Q(QSGListView);
- QSGItemPrivate::get(contentItem)->childrenDoNotOverlap = true;
- q->setFlag(QSGItem::ItemIsFocusScope);
- addItemChangeListener(this, Geometry);
- QObject::connect(q, SIGNAL(movementEnded()), q, SLOT(animStopped()));
- q->setFlickableDirection(QSGFlickable::VerticalFlick);
::memset(sectionCache, 0, sizeof(QSGItem*) * sectionCacheSize);
}
void QSGListViewPrivate::clear()
{
- timeline.clear();
- for (int i = 0; i < visibleItems.count(); ++i)
- releaseItem(visibleItems.at(i));
- visibleItems.clear();
for (int i = 0; i < sectionCacheSize; ++i) {
delete sectionCache[i];
sectionCache[i] = 0;
}
- visiblePos = header ? header->size() : 0;
- visibleIndex = 0;
- releaseItem(currentItem);
- currentItem = 0;
- createHighlight();
- trackedItem = 0;
- minExtentDirty = true;
- maxExtentDirty = true;
- itemCount = 0;
+ visiblePos = header ? headerSize() : 0;
+ QSGItemViewPrivate::clear();
}
-FxListItemSG *QSGListViewPrivate::createItem(int modelIndex)
+FxViewItem *QSGListViewPrivate::newViewItem(int modelIndex, QSGItem *item)
{
Q_Q(QSGListView);
- // create object
- requestedIndex = modelIndex;
- FxListItemSG *listItem = 0;
- if (QSGItem *item = model->item(modelIndex, false)) {
- listItem = new FxListItemSG(item, q);
- listItem->index = modelIndex;
- // initialise attached properties
- if (sectionCriteria) {
- QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
- listItem->attached->m_section = sectionCriteria->sectionString(propValue);
- if (modelIndex > 0) {
- if (FxListItemSG *item = itemBefore(modelIndex))
- listItem->attached->m_prevSection = item->attached->section();
- else
- listItem->attached->m_prevSection = sectionAt(modelIndex-1);
- }
- if (modelIndex < model->count()-1) {
- if (FxListItemSG *item = visibleItem(modelIndex+1))
- listItem->attached->m_nextSection = item->attached->section();
- else
- listItem->attached->m_nextSection = sectionAt(modelIndex+1);
- }
- }
- if (model->completePending()) {
- // complete
- listItem->item->setZ(1);
- listItem->item->setParentItem(q->contentItem());
- model->completeItem();
- } else {
- listItem->item->setParentItem(q->contentItem());
+
+ FxListItemSG *listItem = new FxListItemSG(item, q, false);
+ listItem->index = modelIndex;
+
+ // initialise attached properties
+ if (sectionCriteria) {
+ QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
+ listItem->attached->m_section = sectionCriteria->sectionString(propValue);
+ if (modelIndex > 0) {
+ if (FxViewItem *item = itemBefore(modelIndex))
+ listItem->attached->m_prevSection = item->attached->section();
+ else
+ listItem->attached->m_prevSection = sectionAt(modelIndex-1);
}
- QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
- itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
- if (sectionCriteria && sectionCriteria->delegate()) {
- if (listItem->attached->m_prevSection != listItem->attached->m_section)
- createSection(listItem);
+ if (modelIndex < model->count()-1) {
+ if (FxViewItem *item = visibleItem(modelIndex+1))
+ listItem->attached->m_nextSection = static_cast<QSGListViewAttached*>(item->attached)->section();
+ else
+ listItem->attached->m_nextSection = sectionAt(modelIndex+1);
}
- unrequestedItems.remove(listItem->item);
}
- requestedIndex = -1;
return listItem;
}
-void QSGListViewPrivate::releaseItem(FxListItemSG *item)
+void QSGListViewPrivate::initializeViewItem(FxViewItem *item)
{
- Q_Q(QSGListView);
- if (!item || !model)
- return;
- if (trackedItem == item)
- trackedItem = 0;
QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item->item);
- itemPrivate->removeItemChangeListener(this, QSGItemPrivate::Geometry);
- 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));
+ itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
+
+ if (sectionCriteria && sectionCriteria->delegate()) {
+ if (item->attached->m_prevSection != item->attached->m_section)
+ createSection(static_cast<FxListItemSG*>(item));
}
- if (item->section) {
- int i = 0;
- do {
- if (!sectionCache[i]) {
- sectionCache[i] = item->section;
- sectionCache[i]->setVisible(false);
- item->section = 0;
- break;
- }
- ++i;
- } while (i < sectionCacheSize);
- delete item->section;
+}
+
+void QSGListViewPrivate::releaseItem(FxViewItem *item)
+{
+ if (item) {
+ FxListItemSG* listItem = static_cast<FxListItemSG*>(item);
+ if (listItem->section) {
+ int i = 0;
+ do {
+ if (!sectionCache[i]) {
+ sectionCache[i] = listItem->section;
+ sectionCache[i]->setVisible(false);
+ listItem->section = 0;
+ break;
+ }
+ ++i;
+ } while (i < sectionCacheSize);
+ delete listItem->section;
+ }
}
- delete item;
+ QSGItemViewPrivate::releaseItem(item);
}
-void QSGListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
+bool QSGListViewPrivate::addVisibleItems(int fillFrom, int fillTo, bool doBuffer)
{
- Q_Q(QSGListView);
- 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 haveValidItems = false;
- int modelIndex = visibleIndex;
qreal itemEnd = visiblePos-1;
- if (!visibleItems.isEmpty()) {
+ if (visibleItems.count()) {
visiblePos = (*visibleItems.constBegin())->position();
itemEnd = (*(--visibleItems.constEnd()))->endPosition() + spacing;
- int i = visibleItems.count() - 1;
- while (i > 0 && visibleItems.at(i)->index == -1)
- --i;
- if (visibleItems.at(i)->index != -1) {
- haveValidItems = true;
- modelIndex = visibleItems.at(i)->index + 1;
- }
}
+ int modelIndex = findLastVisibleIndex();
+ bool haveValidItems = modelIndex >= 0;
+ modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
+
if (haveValidItems && (fillFrom > itemEnd+averageSize+spacing
|| fillTo < visiblePos - averageSize - spacing)) {
// We've jumped more than a page. Estimate which items are now
@@ -771,7 +578,7 @@ void QSGListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
qreal pos = itemEnd + 1;
while (modelIndex < model->count() && pos <= fillTo) {
// qDebug() << "refill: append item" << modelIndex << "pos" << pos;
- if (!(item = createItem(modelIndex)))
+ if (!(item = static_cast<FxListItemSG*>(createItem(modelIndex))))
break;
item->setPosition(pos);
pos += item->size() + spacing;
@@ -783,7 +590,7 @@ void QSGListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
}
while (visibleIndex > 0 && visibleIndex <= model->count() && visiblePos-1 >= fillFrom) {
// qDebug() << "refill: prepend item" << visibleIndex-1 << "current top pos" << visiblePos;
- if (!(item = createItem(visibleIndex-1)))
+ if (!(item = static_cast<FxListItemSG*>(createItem(visibleIndex-1))))
break;
--visibleIndex;
visiblePos -= item->size() + spacing;
@@ -794,143 +601,90 @@ void QSGListViewPrivate::refill(qreal from, qreal to, bool doBuffer)
break;
}
- if (!lazyRelease || !changed || deferredRelease) { // avoid destroying items in the same frame that we create
- while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < bufferFrom) {
- if (item->attached->delayRemove())
- break;
+ return changed;
+}
+
+bool QSGListViewPrivate::removeNonVisibleItems(int bufferFrom, int bufferTo)
+{
+ FxViewItem *item = 0;
+ bool changed = false;
+
+ while (visibleItems.count() > 1 && (item = visibleItems.first()) && item->endPosition() < bufferFrom) {
+ if (item->attached->delayRemove())
+ break;
// qDebug() << "refill: remove first" << visibleIndex << "top end pos" << item->endPosition();
- if (item->index != -1)
- visibleIndex++;
- visibleItems.removeFirst();
- releaseItem(item);
- changed = true;
- }
- while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
- if (item->attached->delayRemove())
- break;
+ if (item->index != -1)
+ visibleIndex++;
+ visibleItems.removeFirst();
+ releaseItem(item);
+ changed = true;
+ }
+ while (visibleItems.count() > 1 && (item = visibleItems.last()) && item->position() > bufferTo) {
+ if (item->attached->delayRemove())
+ break;
// qDebug() << "refill: remove last" << visibleIndex+visibleItems.count()-1 << item->position();
- visibleItems.removeLast();
- releaseItem(item);
- changed = true;
- }
- deferredRelease = false;
- } else {
- deferredRelease = true;
- }
- if (changed) {
- minExtentDirty = true;
- maxExtentDirty = true;
- if (visibleItems.count())
- visiblePos = (*visibleItems.constBegin())->position();
- updateAverage();
- if (currentIndex >= 0 && currentItem && !visibleItem(currentIndex)) {
- currentItem->setPosition(positionAt(currentIndex));
- updateHighlight();
- }
-
- if (sectionCriteria)
- updateCurrentSection();
- if (header)
- updateHeader();
- if (footer)
- updateFooter();
- updateViewport();
- updateUnrequestedPositions();
- } else if (!doBuffer && buffer && bufferMode != NoBuffer) {
- refill(from, to, true);
+ visibleItems.removeLast();
+ releaseItem(item);
+ changed = true;
}
- lazyRelease = false;
+
+ return changed;
}
-void QSGListViewPrivate::scheduleLayout()
+void QSGListViewPrivate::visibleItemsChanged()
{
- Q_Q(QSGListView);
- if (!layoutScheduled) {
- layoutScheduled = true;
- q->polish();
+ if (visibleItems.count())
+ visiblePos = (*visibleItems.constBegin())->position();
+ updateAverage();
+ if (currentIndex >= 0 && currentItem && !visibleItem(currentIndex)) {
+ static_cast<FxListItemSG*>(currentItem)->setPosition(positionAt(currentIndex));
+ updateHighlight();
}
+ if (sectionCriteria)
+ updateCurrentSection();
+ updateHeader();
+ updateFooter();
+ updateViewport();
+ updateUnrequestedPositions();
}
-void QSGListViewPrivate::layout()
+void QSGListViewPrivate::layoutVisibleItems()
{
- Q_Q(QSGListView);
- layoutScheduled = false;
- if (!isValid() && !visibleItems.count()) {
- clear();
- setPosition(0);
- return;
- }
if (!visibleItems.isEmpty()) {
- bool fixedCurrent = currentItem && visibleItems.first()->item == currentItem->item;
- qreal sum = visibleItems.first()->size();
- qreal pos = visibleItems.first()->position() + visibleItems.first()->size() + spacing;
+ bool fixedCurrent = currentItem && (*visibleItems.constBegin())->item == currentItem->item;
+ qreal sum = (*visibleItems.constBegin())->size();
+ qreal pos = (*visibleItems.constBegin())->position() + (*visibleItems.constBegin())->size() + spacing;
for (int i=1; i < visibleItems.count(); ++i) {
- FxListItemSG *item = visibleItems.at(i);
+ FxListItemSG *item = static_cast<FxListItemSG*>(visibleItems.at(i));
item->setPosition(pos);
pos += item->size() + spacing;
sum += item->size();
fixedCurrent = fixedCurrent || (currentItem && item->item == currentItem->item);
}
averageSize = qRound(sum / visibleItems.count());
- // move current item if it is not a visible item.
- if (currentIndex >= 0 && currentItem && !fixedCurrent)
- currentItem->setPosition(positionAt(currentIndex));
- }
- q->refill();
- minExtentDirty = true;
- maxExtentDirty = true;
- updateHighlight();
- if (!q->isMoving() && !q->isFlicking()) {
- fixupPosition();
- q->refill();
- }
- if (header)
- updateHeader();
- if (footer)
- updateFooter();
- updateViewport();
-}
-
-void QSGListViewPrivate::updateUnrequestedIndexes()
-{
- Q_Q(QSGListView);
- QHash<QSGItem*,int>::iterator it;
- for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it)
- *it = model->indexOf(it.key(), q);
-}
-void QSGListViewPrivate::updateUnrequestedPositions()
-{
- Q_Q(QSGListView);
- if (unrequestedItems.count()) {
- qreal pos = position();
- QHash<QSGItem*,int>::const_iterator it;
- for (it = unrequestedItems.begin(); it != unrequestedItems.end(); ++it) {
- QSGItem *item = it.key();
- if (orient == QSGListView::Vertical) {
- if (item->y() + item->height() > pos && item->y() < pos + q->height())
- item->setY(positionAt(*it));
- } else {
- if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
- if (isRightToLeft())
- item->setX(-positionAt(*it)-item->width());
- else
- item->setX(positionAt(*it));
- }
- }
+ // move current item if it is not a visible item.
+ if (currentIndex >= 0 && currentItem && !fixedCurrent) {
+ static_cast<FxListItemSG*>(currentItem)->setPosition(positionAt(currentIndex));
}
}
}
-void QSGListViewPrivate::updateTrackedItem()
+void QSGListViewPrivate::repositionPackageItemAt(QSGItem *item, int index)
{
Q_Q(QSGListView);
- FxListItemSG *item = currentItem;
- if (highlight)
- item = highlight;
- trackedItem = item;
- if (trackedItem)
- q->trackedPositionChanged();
+ qreal pos = position();
+ if (orient == QSGListView::Vertical) {
+ if (item->y() + item->height() > pos && item->y() < pos + q->height())
+ item->setY(positionAt(index));
+ } else {
+ if (item->x() + item->width() > pos && item->x() < pos + q->width()) {
+ if (isRightToLeft())
+ item->setX(-positionAt(index)-item->width());
+ else
+ item->setX(positionAt(index));
+ }
+ }
}
void QSGListViewPrivate::createHighlight()
@@ -940,61 +694,39 @@ void QSGListViewPrivate::createHighlight()
if (highlight) {
if (trackedItem == highlight)
trackedItem = 0;
- highlight->item->setParentItem(0);
- highlight->item->deleteLater();
delete highlight;
highlight = 0;
+
delete highlightPosAnimator;
delete highlightSizeAnimator;
highlightPosAnimator = 0;
highlightSizeAnimator = 0;
+
changed = true;
}
if (currentItem) {
- QSGItem *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<QSGItem *>(nobj);
- if (!item)
- delete nobj;
- } else {
- delete highlightContext;
- }
- } else {
- item = new QSGItem;
- }
+ QSGItem *item = createHighlightItem();
if (item) {
- QDeclarative_setParent_noEvent(item, q->contentItem());
- item->setParentItem(q->contentItem());
- highlight = new FxListItemSG(item, q);
- if (currentItem && autoHighlight) {
- if (orient == QSGListView::Vertical) {
- highlight->item->setHeight(currentItem->item->height());
- } else {
- highlight->item->setWidth(currentItem->item->width());
- }
- highlight->setPosition(currentItem->itemPosition());
+ FxListItemSG *newHighlight = new FxListItemSG(item, q, true);
+
+ if (autoHighlight) {
+ newHighlight->setSize(static_cast<FxListItemSG*>(currentItem)->itemSize());
+ newHighlight->setPosition(static_cast<FxListItemSG*>(currentItem)->itemPosition());
}
- QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
- itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
const QLatin1String posProp(orient == QSGListView::Vertical ? "y" : "x");
highlightPosAnimator = new QSmoothedAnimation(q);
- highlightPosAnimator->target = QDeclarativeProperty(highlight->item, posProp);
+ highlightPosAnimator->target = QDeclarativeProperty(item, posProp);
highlightPosAnimator->velocity = highlightMoveSpeed;
highlightPosAnimator->userDuration = highlightMoveDuration;
+
const QLatin1String sizeProp(orient == QSGListView::Vertical ? "height" : "width");
highlightSizeAnimator = new QSmoothedAnimation(q);
highlightSizeAnimator->velocity = highlightResizeSpeed;
highlightSizeAnimator->userDuration = highlightResizeDuration;
- highlightSizeAnimator->target = QDeclarativeProperty(highlight->item, sizeProp);
- if (autoHighlight) {
- highlightPosAnimator->restart();
- highlightSizeAnimator->restart();
- }
+ highlightSizeAnimator->target = QDeclarativeProperty(item, sizeProp);
+
+ highlight = newHighlight;
changed = true;
}
}
@@ -1008,10 +740,11 @@ void QSGListViewPrivate::updateHighlight()
createHighlight();
if (currentItem && autoHighlight && highlight && !movingHorizontally && !movingVertically) {
// auto-update highlight
+ FxListItemSG *listItem = static_cast<FxListItemSG*>(currentItem);
highlightPosAnimator->to = isRightToLeft()
- ? -currentItem->itemPosition()-currentItem->itemSize()
- : currentItem->itemPosition();
- highlightSizeAnimator->to = currentItem->itemSize();
+ ? -listItem->itemPosition()-listItem->itemSize()
+ : listItem->itemPosition();
+ highlightSizeAnimator->to = listItem->itemSize();
if (orient == QSGListView::Vertical) {
if (highlight->item->width() == 0)
highlight->item->setWidth(currentItem->item->width());
@@ -1019,12 +752,19 @@ void QSGListViewPrivate::updateHighlight()
if (highlight->item->height() == 0)
highlight->item->setHeight(currentItem->item->height());
}
+
highlightPosAnimator->restart();
highlightSizeAnimator->restart();
}
updateTrackedItem();
}
+void QSGListViewPrivate::resetHighlightPosition()
+{
+ if (highlight && currentItem)
+ static_cast<FxListItemSG*>(highlight)->setPosition(static_cast<FxListItemSG*>(currentItem)->itemPosition());
+}
+
void QSGListViewPrivate::createSection(FxListItemSG *listItem)
{
Q_Q(QSGListView);
@@ -1093,14 +833,14 @@ void QSGListViewPrivate::updateSections()
QSGListViewAttached *prevAtt = 0;
int idx = -1;
for (int i = 0; i < visibleItems.count(); ++i) {
- QSGListViewAttached *attached = visibleItems.at(i)->attached;
+ QSGListViewAttached *attached = static_cast<QSGListViewAttached*>(visibleItems.at(i)->attached);
attached->setPrevSection(prevSection);
if (visibleItems.at(i)->index != -1) {
QString propValue = model->stringValue(visibleItems.at(i)->index, sectionCriteria->property());
attached->setSection(sectionCriteria->sectionString(propValue));
idx = visibleItems.at(i)->index;
}
- createSection(visibleItems.at(i));
+ createSection(static_cast<FxListItemSG*>(visibleItems.at(i)));
if (prevAtt)
prevAtt->setNextSection(attached->section());
prevSection = attached->section();
@@ -1133,63 +873,36 @@ void QSGListViewPrivate::updateCurrentSection()
if (index < visibleItems.count())
newSection = visibleItems.at(index)->attached->section();
else
- newSection = visibleItems.first()->attached->section();
+ newSection = (*visibleItems.constBegin())->attached->section();
if (newSection != currentSection) {
currentSection = newSection;
emit q->currentSectionChanged();
}
}
-void QSGListViewPrivate::updateCurrent(int modelIndex)
+void QSGListViewPrivate::initializeCurrentItem()
{
- Q_Q(QSGListView);
- 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;
- }
- FxListItemSG *oldCurrentItem = currentItem;
- currentIndex = modelIndex;
- currentItem = createItem(modelIndex);
- if (oldCurrentItem && (!currentItem || oldCurrentItem->item != currentItem->item))
- oldCurrentItem->attached->setIsCurrentItem(false);
if (currentItem) {
- if (modelIndex == visibleIndex - 1 && visibleItems.count()) {
+ FxListItemSG *listItem = static_cast<FxListItemSG *>(currentItem);
+
+ if (currentIndex == visibleIndex - 1 && visibleItems.count()) {
// We can calculate exact postion in this case
- currentItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing);
+ listItem->setPosition(visibleItems.first()->position() - currentItem->size() - spacing);
} else {
// Create current item now and position as best we can.
// Its position will be corrected when it becomes visible.
- currentItem->setPosition(positionAt(modelIndex));
+ listItem->setPosition(positionAt(currentIndex));
}
- currentItem->item->setFocus(true);
- currentItem->attached->setIsCurrentItem(true);
+
// Avoid showing section delegate twice. We still need the section heading so that
// currentItem positioning works correctly.
// This is slightly sub-optimal, but section heading caching minimizes the impact.
- if (currentItem->section)
- currentItem->section->setVisible(false);
+ if (listItem->section)
+ listItem->section->setVisible(false);
+
if (visibleItems.isEmpty())
- averageSize = currentItem->size();
+ averageSize = listItem->size();
}
- updateHighlight();
- emit q->currentIndexChanged();
- // Release the old current item
- releaseItem(oldCurrentItem);
}
void QSGListViewPrivate::updateAverage()
@@ -1202,83 +915,82 @@ void QSGListViewPrivate::updateAverage()
averageSize = qRound(sum / visibleItems.count());
}
+qreal QSGListViewPrivate::headerSize() const
+{
+ return header ? header->size() : 0.0;
+}
+
+qreal QSGListViewPrivate::footerSize() const
+{
+ return footer ? footer->size() : 0.0;
+}
+
void QSGListViewPrivate::updateFooter()
{
Q_Q(QSGListView);
- if (!footer && footerComponent) {
- QSGItem *item = 0;
- QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
- QObject *nobj = footerComponent->create(context);
- if (nobj) {
- QDeclarative_setParent_noEvent(context, nobj);
- item = qobject_cast<QSGItem *>(nobj);
- if (!item)
- delete nobj;
- } else {
- delete context;
- }
- if (item) {
- QDeclarative_setParent_noEvent(item, q->contentItem());
- item->setParentItem(q->contentItem());
- item->setZ(1);
- QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
- itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
- footer = new FxListItemSG(item, q);
- }
+
+ if (!footer) {
+ QSGItem *item = createComponentItem(footerComponent, true);
+ if (!item)
+ return;
+ item->setZ(1);
+ footer = new FxListItemSG(item, q, true);
}
- if (footer) {
- if (visibleItems.count()) {
- qreal endPos = lastPosition() + 1;
- if (lastVisibleIndex() == model->count()-1) {
- footer->setPosition(endPos);
- } else {
- qreal visiblePos = position() + q->height();
- if (endPos <= visiblePos || footer->position() < endPos)
- footer->setPosition(endPos);
- }
+
+ FxListItemSG *listItem = static_cast<FxListItemSG*>(footer);
+ if (visibleItems.count()) {
+ qreal endPos = lastPosition() + 1;
+ if (findLastVisibleIndex() == model->count()-1) {
+ listItem->setPosition(endPos);
} else {
- footer->setPosition(visiblePos);
+ qreal visiblePos = position() + q->height();
+ if (endPos <= visiblePos || listItem->position() < endPos)
+ listItem->setPosition(endPos);
}
+ } else {
+ listItem->setPosition(visiblePos);
}
}
void QSGListViewPrivate::updateHeader()
{
Q_Q(QSGListView);
- if (!header && headerComponent) {
- QSGItem *item = 0;
- QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
- QObject *nobj = headerComponent->create(context);
- if (nobj) {
- QDeclarative_setParent_noEvent(context, nobj);
- item = qobject_cast<QSGItem *>(nobj);
- if (!item)
- delete nobj;
- } else {
- delete context;
- }
- if (item) {
- QDeclarative_setParent_noEvent(item, q->contentItem());
- item->setParentItem(q->contentItem());
- item->setZ(1);
- QSGItemPrivate *itemPrivate = QSGItemPrivate::get(item);
- itemPrivate->addItemChangeListener(this, QSGItemPrivate::Geometry);
- header = new FxListItemSG(item, q);
- }
+ if (!header) {
+ QSGItem *item = createComponentItem(headerComponent, true);
+ if (!item)
+ return;
+ item->setZ(1);
+ header = new FxListItemSG(item, q, true);
}
- if (header) {
+
+ FxListItemSG *listItem = static_cast<FxListItemSG*>(header);
+ if (listItem) {
if (visibleItems.count()) {
qreal startPos = originPosition();
if (visibleIndex == 0) {
- header->setPosition(startPos - header->size());
+ listItem->setPosition(startPos - headerSize());
} else {
- if (position() <= startPos || header->position() > startPos - header->size())
- header->setPosition(startPos - header->size());
+ if (position() <= startPos || listItem->position() > startPos - headerSize())
+ listItem->setPosition(startPos - headerSize());
}
} else {
if (itemCount == 0)
- visiblePos = header->size();
- header->setPosition(0);
+ visiblePos = headerSize();
+ listItem->setPosition(0);
+ }
+ }
+}
+
+void QSGListViewPrivate::itemGeometryChanged(QSGItem *item, const QRectF &newGeometry, const QRectF &oldGeometry)
+{
+ Q_Q(QSGListView);
+ QSGItemViewPrivate::itemGeometryChanged(item, newGeometry, oldGeometry);
+ if (!q->isComponentComplete())
+ return;
+ if (item != contentItem && (!highlight || item != highlight->item)) {
+ if ((orient == QSGListView::Vertical && newGeometry.height() != oldGeometry.height())
+ || (orient == QSGListView::Horizontal && newGeometry.width() != oldGeometry.width())) {
+ scheduleLayout();
}
}
}
@@ -1320,9 +1032,9 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
if (currentItem && haveHighlightRange && highlightRange == QSGListView::StrictlyEnforceRange
&& moveReason != QSGListViewPrivate::SetIndex) {
updateHighlight();
- qreal pos = currentItem->itemPosition();
- if (viewPos < pos + currentItem->itemSize() - highlightEnd)
- viewPos = pos + currentItem->itemSize() - highlightEnd;
+ qreal pos = static_cast<FxListItemSG*>(currentItem)->itemPosition();
+ if (viewPos < pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightEnd)
+ viewPos = pos + static_cast<FxListItemSG*>(currentItem)->itemSize() - highlightEnd;
if (viewPos > pos - highlightStart)
viewPos = pos - highlightStart;
if (isRightToLeft())
@@ -1340,12 +1052,12 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
vTime = timeline.time();
} else if (snapMode != QSGListView::NoSnap && moveReason != QSGListViewPrivate::SetIndex) {
qreal tempPosition = isRightToLeft() ? -position()-size() : position();
- FxListItemSG *topItem = snapItemAt(tempPosition+highlightStart);
- FxListItemSG *bottomItem = snapItemAt(tempPosition+highlightEnd);
+ FxViewItem *topItem = snapItemAt(tempPosition+highlightStart);
+ FxViewItem *bottomItem = snapItemAt(tempPosition+highlightEnd);
qreal pos;
bool isInBounds = -position() > maxExtent && -position() < minExtent;
if (topItem && isInBounds) {
- if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+header->size()/2) {
+ if (topItem->index == 0 && header && tempPosition+highlightStart < header->position()+headerSize()/2) {
pos = isRightToLeft() ? - header->position() + highlightStart - size() : header->position() - highlightStart;
} else {
if (isRightToLeft())
@@ -1359,7 +1071,7 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
else
pos = qMax(qMin(bottomItem->position() - highlightStart, -maxExtent), -minExtent);
} else {
- QSGFlickablePrivate::fixup(data, minExtent, maxExtent);
+ QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
return;
}
@@ -1375,7 +1087,7 @@ void QSGListViewPrivate::fixup(AxisData &data, qreal minExtent, qreal maxExtent)
vTime = timeline.time();
}
} else {
- QSGFlickablePrivate::fixup(data, minExtent, maxExtent);
+ QSGItemViewPrivate::fixup(data, minExtent, maxExtent);
}
data.inOvershoot = false;
fixupMode = Normal;
@@ -1390,7 +1102,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
moveReason = Mouse;
if ((!haveHighlightRange || highlightRange != QSGListView::StrictlyEnforceRange) && snapMode == QSGListView::NoSnap) {
correctFlick = true;
- QSGFlickablePrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
+ QSGItemViewPrivate::flick(data, minExtent, maxExtent, vSize, fixupCallback, velocity);
return;
}
qreal maxDistance = 0;
@@ -1399,7 +1111,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
if (velocity > 0) {
if (data.move.value() < minExtent) {
if (snapMode == QSGListView::SnapOneItem) {
- if (FxListItemSG *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem())
+ if (FxViewItem *item = isRightToLeft() ? nextVisibleItem() : firstVisibleItem())
maxDistance = qAbs(item->position() + dataValue);
} else {
maxDistance = qAbs(minExtent - data.move.value());
@@ -1410,7 +1122,7 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
} else {
if (data.move.value() > maxExtent) {
if (snapMode == QSGListView::SnapOneItem) {
- if (FxListItemSG *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem())
+ if (FxViewItem *item = isRightToLeft() ? firstVisibleItem() : nextVisibleItem())
maxDistance = qAbs(item->position() + dataValue);
} else {
maxDistance = qAbs(maxExtent - data.move.value());
@@ -1535,300 +1247,28 @@ void QSGListViewPrivate::flick(AxisData &data, qreal minExtent, qreal maxExtent,
//----------------------------------------------------------------------------
QSGListView::QSGListView(QSGItem *parent)
- : QSGFlickable(*(new QSGListViewPrivate), parent)
+ : QSGItemView(*(new QSGListViewPrivate), parent)
{
- Q_D(QSGListView);
- d->init();
}
QSGListView::~QSGListView()
{
- Q_D(QSGListView);
- d->clear();
- if (d->ownModel)
- delete d->model;
- delete d->header;
- delete d->footer;
-}
-
-QVariant QSGListView::model() const
-{
- Q_D(const QSGListView);
- return d->modelVariant;
-}
-
-void QSGListView::setModel(const QVariant &model)
-{
- Q_D(QSGListView);
- 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(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
- disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
- disconnect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
- disconnect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
- }
- d->clear();
- QSGVisualModel *oldModel = d->model;
- d->model = 0;
- d->setPosition(0);
- d->modelVariant = model;
- QObject *object = qvariant_cast<QObject*>(model);
- QSGVisualModel *vim = 0;
- if (object && (vim = qobject_cast<QSGVisualModel *>(object))) {
- if (d->ownModel) {
- delete oldModel;
- d->ownModel = false;
- }
- d->model = vim;
- } else {
- if (!d->ownModel) {
- d->model = new QSGVisualDataModel(qmlContext(this), this);
- d->ownModel = true;
- } else {
- d->model = oldModel;
- }
- if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
- dataModel->setModel(model);
- }
- if (d->model) {
- d->bufferMode = QSGListViewPrivate::BufferBefore | QSGListViewPrivate::BufferAfter;
- if (isComponentComplete()) {
- updateSections();
- refill();
- if ((d->currentIndex >= d->model->count() || d->currentIndex < 0) && !d->currentIndexCleared) {
- setCurrentIndex(0);
- } else {
- d->moveReason = QSGListViewPrivate::SetIndex;
- d->updateCurrent(d->currentIndex);
- if (d->highlight && d->currentItem) {
- if (d->autoHighlight)
- d->highlight->setPosition(d->currentItem->position());
- d->updateTrackedItem();
- }
- }
- d->updateViewport();
- }
- 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(itemsChanged(int,int)), this, SLOT(itemsChanged(int,int)));
- connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
- connect(d->model, SIGNAL(createdItem(int,QSGItem*)), this, SLOT(createdItem(int,QSGItem*)));
- connect(d->model, SIGNAL(destroyingItem(QSGItem*)), this, SLOT(destroyingItem(QSGItem*)));
- emit countChanged();
- }
- emit modelChanged();
-}
-
-QDeclarativeComponent *QSGListView::delegate() const
-{
- Q_D(const QSGListView);
- if (d->model) {
- if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(d->model))
- return dataModel->delegate();
- }
-
- return 0;
-}
-
-void QSGListView::setDelegate(QDeclarativeComponent *delegate)
-{
- Q_D(QSGListView);
- if (delegate == this->delegate())
- return;
- if (!d->ownModel) {
- d->model = new QSGVisualDataModel(qmlContext(this));
- d->ownModel = true;
- }
- if (QSGVisualDataModel *dataModel = qobject_cast<QSGVisualDataModel*>(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;
- updateSections();
- refill();
- d->moveReason = QSGListViewPrivate::SetIndex;
- d->updateCurrent(d->currentIndex);
- if (d->highlight && d->currentItem) {
- if (d->autoHighlight)
- d->highlight->setPosition(d->currentItem->position());
- d->updateTrackedItem();
- }
- d->updateViewport();
- }
- if (oldCount != dataModel->count())
- emit countChanged();
- }
- emit delegateChanged();
-}
-
-int QSGListView::currentIndex() const
-{
- Q_D(const QSGListView);
- return d->currentIndex;
-}
-
-void QSGListView::setCurrentIndex(int index)
-{
- Q_D(QSGListView);
- if (d->requestedIndex >= 0) // currently creating item
- return;
- d->currentIndexCleared = (index == -1);
- if (index == d->currentIndex)
- return;
- if (isComponentComplete() && d->isValid()) {
- d->moveReason = QSGListViewPrivate::SetIndex;
- d->updateCurrent(index);
- } else if (d->currentIndex != index) {
- d->currentIndex = index;
- emit currentIndexChanged();
- }
-}
-
-QSGItem *QSGListView::currentItem()
-{
- Q_D(QSGListView);
- if (!d->currentItem)
- return 0;
- return d->currentItem->item;
-}
-
-QSGItem *QSGListView::highlightItem()
-{
- Q_D(QSGListView);
- if (!d->highlight)
- return 0;
- return d->highlight->item;
-}
-
-int QSGListView::count() const
-{
- Q_D(const QSGListView);
- if (d->model)
- return d->model->count();
- return 0;
-}
-
-QDeclarativeComponent *QSGListView::highlight() const
-{
- Q_D(const QSGListView);
- return d->highlightComponent;
-}
-
-void QSGListView::setHighlight(QDeclarativeComponent *highlight)
-{
- Q_D(QSGListView);
- if (highlight != d->highlightComponent) {
- d->highlightComponent = highlight;
- d->createHighlight();
- if (d->currentItem)
- d->updateHighlight();
- emit highlightChanged();
- }
-}
-
-bool QSGListView::highlightFollowsCurrentItem() const
-{
- Q_D(const QSGListView);
- return d->autoHighlight;
}
void QSGListView::setHighlightFollowsCurrentItem(bool autoHighlight)
{
Q_D(QSGListView);
if (d->autoHighlight != autoHighlight) {
- d->autoHighlight = autoHighlight;
- if (autoHighlight) {
- d->updateHighlight();
- } else {
+ if (!autoHighlight) {
if (d->highlightPosAnimator)
d->highlightPosAnimator->stop();
if (d->highlightSizeAnimator)
d->highlightSizeAnimator->stop();
}
- emit highlightFollowsCurrentItemChanged();
+ QSGItemView::setHighlightFollowsCurrentItem(autoHighlight);
}
}
-//###Possibly rename these properties, since they are very useful even without a highlight?
-qreal QSGListView::preferredHighlightBegin() const
-{
- Q_D(const QSGListView);
- return d->highlightRangeStart;
-}
-
-void QSGListView::setPreferredHighlightBegin(qreal start)
-{
- Q_D(QSGListView);
- d->highlightRangeStartValid = true;
- if (d->highlightRangeStart == start)
- return;
- d->highlightRangeStart = start;
- d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
- emit preferredHighlightBeginChanged();
-}
-
-void QSGListView::resetPreferredHighlightBegin()
-{
- Q_D(QSGListView);
- d->highlightRangeStartValid = false;
- if (d->highlightRangeStart == 0)
- return;
- d->highlightRangeStart = 0;
- emit preferredHighlightBeginChanged();
-}
-
-qreal QSGListView::preferredHighlightEnd() const
-{
- Q_D(const QSGListView);
- return d->highlightRangeEnd;
-}
-
-void QSGListView::setPreferredHighlightEnd(qreal end)
-{
- Q_D(QSGListView);
- d->highlightRangeEndValid = true;
- if (d->highlightRangeEnd == end)
- return;
- d->highlightRangeEnd = end;
- d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
- emit preferredHighlightEndChanged();
-}
-
-void QSGListView::resetPreferredHighlightEnd()
-{
- Q_D(QSGListView);
- d->highlightRangeEndValid = false;
- if (d->highlightRangeEnd == 0)
- return;
- d->highlightRangeEnd = 0;
- emit preferredHighlightEndChanged();
-}
-
-QSGListView::HighlightRangeMode QSGListView::highlightRangeMode() const
-{
- Q_D(const QSGListView);
- return d->highlightRange;
-}
-
-void QSGListView::setHighlightRangeMode(HighlightRangeMode mode)
-{
- Q_D(QSGListView);
- if (d->highlightRange == mode)
- return;
- d->highlightRange = mode;
- d->haveHighlightRange = d->highlightRange != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
- emit highlightRangeModeChanged();
-}
-
qreal QSGListView::spacing() const
{
Q_D(const QSGListView);
@@ -1856,7 +1296,7 @@ void QSGListView::setOrientation(QSGListView::Orientation orientation)
Q_D(QSGListView);
if (d->orient != orientation) {
d->orient = orientation;
- if (d->orient == QSGListView::Vertical) {
+ if (d->orient == Vertical) {
setContentWidth(-1);
setFlickableDirection(VerticalFlick);
setContentX(0);
@@ -1870,66 +1310,6 @@ void QSGListView::setOrientation(QSGListView::Orientation orientation)
}
}
-Qt::LayoutDirection QSGListView::layoutDirection() const
-{
- Q_D(const QSGListView);
- return d->layoutDirection;
-}
-
-void QSGListView::setLayoutDirection(Qt::LayoutDirection layoutDirection)
-{
- Q_D(QSGListView);
- if (d->layoutDirection != layoutDirection) {
- d->layoutDirection = layoutDirection;
- d->regenerate();
- emit layoutDirectionChanged();
- emit effectiveLayoutDirectionChanged();
- }
-}
-
-Qt::LayoutDirection QSGListView::effectiveLayoutDirection() const
-{
- Q_D(const QSGListView);
- if (d->effectiveLayoutMirror)
- return d->layoutDirection == Qt::RightToLeft ? Qt::LeftToRight : Qt::RightToLeft;
- else
- return d->layoutDirection;
-}
-
-bool QSGListView::isWrapEnabled() const
-{
- Q_D(const QSGListView);
- return d->wrap;
-}
-
-void QSGListView::setWrapEnabled(bool wrap)
-{
- Q_D(QSGListView);
- if (d->wrap == wrap)
- return;
- d->wrap = wrap;
- emit keyNavigationWrapsChanged();
-}
-
-int QSGListView::cacheBuffer() const
-{
- Q_D(const QSGListView);
- return d->buffer;
-}
-
-void QSGListView::setCacheBuffer(int b)
-{
- Q_D(QSGListView);
- if (d->buffer != b) {
- d->buffer = b;
- if (isComponentComplete()) {
- d->bufferMode = QSGListViewPrivate::BufferBefore | QSGListViewPrivate::BufferAfter;
- refill();
- }
- emit cacheBufferChanged();
- }
-}
-
QSGViewSection *QSGListView::sectionCriteria()
{
Q_D(QSGListView);
@@ -1948,13 +1328,13 @@ QString QSGListView::currentSection() const
qreal QSGListView::highlightMoveSpeed() const
{
- Q_D(const QSGListView);\
+ Q_D(const QSGListView);
return d->highlightMoveSpeed;
}
void QSGListView::setHighlightMoveSpeed(qreal speed)
{
- Q_D(QSGListView);\
+ Q_D(QSGListView);
if (d->highlightMoveSpeed != speed) {
d->highlightMoveSpeed = speed;
if (d->highlightPosAnimator)
@@ -1963,32 +1343,25 @@ void QSGListView::setHighlightMoveSpeed(qreal speed)
}
}
-int QSGListView::highlightMoveDuration() const
-{
- Q_D(const QSGListView);
- return d->highlightMoveDuration;
-}
-
void QSGListView::setHighlightMoveDuration(int duration)
{
- Q_D(QSGListView);\
+ Q_D(QSGListView);
if (d->highlightMoveDuration != duration) {
- d->highlightMoveDuration = duration;
if (d->highlightPosAnimator)
- d->highlightPosAnimator->userDuration = d->highlightMoveDuration;
- emit highlightMoveDurationChanged();
+ d->highlightPosAnimator->userDuration = duration;
+ QSGItemView::setHighlightMoveDuration(duration);
}
}
qreal QSGListView::highlightResizeSpeed() const
{
- Q_D(const QSGListView);\
+ Q_D(const QSGListView);
return d->highlightResizeSpeed;
}
void QSGListView::setHighlightResizeSpeed(qreal speed)
{
- Q_D(QSGListView);\
+ Q_D(QSGListView);
if (d->highlightResizeSpeed != speed) {
d->highlightResizeSpeed = speed;
if (d->highlightSizeAnimator)
@@ -2005,7 +1378,7 @@ int QSGListView::highlightResizeDuration() const
void QSGListView::setHighlightResizeDuration(int duration)
{
- Q_D(QSGListView);\
+ Q_D(QSGListView);
if (d->highlightResizeDuration != duration) {
d->highlightResizeDuration = duration;
if (d->highlightSizeAnimator)
@@ -2029,92 +1402,10 @@ void QSGListView::setSnapMode(SnapMode mode)
}
}
-QDeclarativeComponent *QSGListView::footer() const
-{
- Q_D(const QSGListView);
- return d->footerComponent;
-}
-
-void QSGListView::setFooter(QDeclarativeComponent *footer)
-{
- Q_D(QSGListView);
- if (d->footerComponent != footer) {
- if (d->footer) {
- // XXX todo - the original did scene()->removeItem(). Why?
- d->footer->item->setParentItem(0);
- d->footer->item->deleteLater();
- delete d->footer;
- d->footer = 0;
- }
- d->footerComponent = footer;
- d->minExtentDirty = true;
- d->maxExtentDirty = true;
- if (isComponentComplete()) {
- d->updateFooter();
- d->updateViewport();
- d->fixupPosition();
- }
- emit footerChanged();
- }
-}
-
-QDeclarativeComponent *QSGListView::header() const
-{
- Q_D(const QSGListView);
- return d->headerComponent;
-}
-
-void QSGListView::setHeader(QDeclarativeComponent *header)
-{
- Q_D(QSGListView);
- if (d->headerComponent != header) {
- if (d->header) {
- // XXX todo - the original did scene()->removeItem(). Why?
- d->header->item->setParentItem(0);
- d->header->item->deleteLater();
- delete d->header;
- d->header = 0;
- }
- d->headerComponent = header;
- d->minExtentDirty = true;
- d->maxExtentDirty = true;
- if (isComponentComplete()) {
- d->updateHeader();
- d->updateFooter();
- d->updateViewport();
- d->fixupPosition();
- }
- emit headerChanged();
- }
-}
-
-void QSGListView::setContentX(qreal pos)
-{
- Q_D(QSGListView);
- // Positioning the view manually should override any current movement state
- d->moveReason = QSGListViewPrivate::Other;
- QSGFlickable::setContentX(pos);
-}
-
-void QSGListView::setContentY(qreal pos)
-{
- Q_D(QSGListView);
- // Positioning the view manually should override any current movement state
- d->moveReason = QSGListViewPrivate::Other;
- QSGFlickable::setContentY(pos);
-}
-
-void QSGListView::updatePolish()
-{
- Q_D(QSGListView);
- QSGFlickable::updatePolish();
- d->layout();
-}
-
void QSGListView::viewportMoved()
{
Q_D(QSGListView);
- QSGFlickable::viewportMoved();
+ QSGItemView::viewportMoved();
if (!d->itemCount)
return;
// Recursion can occur due to refill changing the content size.
@@ -2122,7 +1413,7 @@ void QSGListView::viewportMoved()
return;
d->inViewportMoved = true;
d->lazyRelease = true;
- refill();
+ d->refill();
if (d->flickingHorizontally || d->flickingVertically || d->movingHorizontally || d->movingVertically)
d->moveReason = QSGListViewPrivate::Mouse;
if (d->moveReason != QSGListViewPrivate::SetIndex) {
@@ -2147,10 +1438,10 @@ void QSGListView::viewportMoved()
if (pos < viewPos + highlightStart)
pos = viewPos + highlightStart;
d->highlightPosAnimator->stop();
- d->highlight->setPosition(qRound(pos));
+ static_cast<FxListItemSG*>(d->highlight)->setPosition(qRound(pos));
// update current index
- if (FxListItemSG *snapItem = d->snapItemAt(d->highlight->position())) {
+ if (FxViewItem *snapItem = d->snapItemAt(d->highlight->position())) {
if (snapItem->index >= 0 && snapItem->index != d->currentIndex)
d->updateCurrent(snapItem->index);
}
@@ -2197,146 +1488,6 @@ void QSGListView::viewportMoved()
d->inViewportMoved = false;
}
-qreal QSGListView::minYExtent() const
-{
- Q_D(const QSGListView);
- if (d->orient == QSGListView::Horizontal)
- return QSGFlickable::minYExtent();
- if (d->minExtentDirty) {
- d->minExtent = -d->startPosition();
- if (d->header && d->visibleItems.count())
- d->minExtent += d->header->size();
- if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
- d->minExtent += d->highlightRangeStart;
- if (d->sectionCriteria) {
- if (d->visibleItem(0))
- d->minExtent -= d->visibleItem(0)->sectionSize();
- }
- d->minExtent = qMax(d->minExtent, -(d->endPositionAt(0) - d->highlightRangeEnd + 1));
- }
- d->minExtentDirty = false;
- }
-
- return d->minExtent;
-}
-
-qreal QSGListView::maxYExtent() const
-{
- Q_D(const QSGListView);
- if (d->orient == QSGListView::Horizontal)
- return height();
- if (d->maxExtentDirty) {
- if (!d->model || !d->model->count()) {
- d->maxExtent = d->header ? -d->header->size() : 0;
- d->maxExtent += height();
- } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
- d->maxExtent = -(d->positionAt(d->model->count()-1) - d->highlightRangeStart);
- if (d->highlightRangeEnd != d->highlightRangeStart)
- d->maxExtent = qMin(d->maxExtent, -(d->endPosition() - d->highlightRangeEnd + 1));
- } else {
- d->maxExtent = -(d->endPosition() - height() + 1);
- }
- if (d->footer)
- d->maxExtent -= d->footer->size();
- qreal minY = minYExtent();
- if (d->maxExtent > minY)
- d->maxExtent = minY;
- d->maxExtentDirty = false;
- }
- return d->maxExtent;
-}
-
-qreal QSGListView::minXExtent() const
-{
- Q_D(const QSGListView);
- if (d->orient == QSGListView::Vertical)
- return QSGFlickable::minXExtent();
- if (d->minExtentDirty) {
- d->minExtent = -d->startPosition();
- qreal highlightStart;
- qreal highlightEnd;
- qreal endPositionFirstItem = 0;
- if (d->isRightToLeft()) {
- if (d->model && d->model->count())
- endPositionFirstItem = d->positionAt(d->model->count()-1);
- else if (d->header)
- d->minExtent += d->header->size();
- highlightStart = d->highlightRangeStartValid
- ? d->highlightRangeStart - (d->lastPosition()-endPositionFirstItem)
- : d->size() - (d->lastPosition()-endPositionFirstItem);
- highlightEnd = d->highlightRangeEndValid ? d->highlightRangeEnd : d->size();
- if (d->footer)
- d->minExtent += d->footer->size();
- qreal maxX = maxXExtent();
- if (d->minExtent < maxX)
- d->minExtent = maxX;
- } else {
- endPositionFirstItem = d->endPositionAt(0);
- highlightStart = d->highlightRangeStart;
- highlightEnd = d->highlightRangeEnd;
- if (d->header && d->visibleItems.count())
- d->minExtent += d->header->size();
- }
- if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
- d->minExtent += highlightStart;
- d->minExtent = qMax(d->minExtent, -(endPositionFirstItem - highlightEnd + 1));
- }
- d->minExtentDirty = false;
- }
-
- return d->minExtent;
-}
-
-qreal QSGListView::maxXExtent() const
-{
- Q_D(const QSGListView);
- if (d->orient == QSGListView::Vertical)
- return width();
- if (d->maxExtentDirty) {
- qreal highlightStart;
- qreal highlightEnd;
- qreal lastItemPosition = 0;
- d->maxExtent = 0;
- if (d->isRightToLeft()) {
- highlightStart = d->highlightRangeStartValid ? d->highlightRangeEnd : d->size();
- highlightEnd = d->highlightRangeEndValid ? d->highlightRangeStart : d->size();
- lastItemPosition = d->endPosition();
- } else {
- highlightStart = d->highlightRangeStart;
- highlightEnd = d->highlightRangeEnd;
- if (d->model && d->model->count())
- lastItemPosition = d->positionAt(d->model->count()-1);
- }
- if (!d->model || !d->model->count()) {
- if (!d->isRightToLeft())
- d->maxExtent = d->header ? -d->header->size() : 0;
- d->maxExtent += width();
- } else if (d->haveHighlightRange && d->highlightRange == StrictlyEnforceRange) {
- d->maxExtent = -(lastItemPosition - highlightStart);
- if (highlightEnd != highlightStart) {
- d->maxExtent = d->isRightToLeft()
- ? qMax(d->maxExtent, -(d->endPosition() - highlightEnd + 1))
- : qMin(d->maxExtent, -(d->endPosition() - highlightEnd + 1));
- }
- } else {
- d->maxExtent = -(d->endPosition() - width() + 1);
- }
- if (d->isRightToLeft()) {
- if (d->header && d->visibleItems.count())
- d->maxExtent -= d->header->size();
- } else {
- if (d->footer)
- d->maxExtent -= d->footer->size();
- qreal minX = minXExtent();
- if (d->maxExtent > minX)
- d->maxExtent = minX;
- }
- d->maxExtentDirty = false;
- }
-
- return d->maxExtent;
-}
-
void QSGListView::keyPressEvent(QKeyEvent *event)
{
Q_D(QSGListView);
@@ -2366,21 +1517,18 @@ void QSGListView::keyPressEvent(QKeyEvent *event)
}
}
event->ignore();
- QSGFlickable::keyPressEvent(event);
+ QSGItemView::keyPressEvent(event);
}
-void QSGListView::geometryChanged(const QRectF &newGeometry,
- const QRectF &oldGeometry)
+void QSGListView::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
{
Q_D(QSGListView);
- d->maxExtentDirty = true;
- d->minExtentDirty = true;
if (d->isRightToLeft() && d->orient == QSGListView::Horizontal) {
// maintain position relative to the right edge
int dx = newGeometry.width() - oldGeometry.width();
setContentX(contentX() - dx);
}
- QSGFlickable::geometryChanged(newGeometry, oldGeometry);
+ QSGItemView::geometryChanged(newGeometry, oldGeometry);
}
@@ -2406,147 +1554,6 @@ void QSGListView::decrementCurrentIndex()
}
}
-void QSGListViewPrivate::positionViewAtIndex(int index, int mode)
-{
- Q_Q(QSGListView);
- if (!isValid())
- return;
- if (mode < QSGListView::Beginning || mode > QSGListView::Contain)
- return;
- int idx = qMax(qMin(index, model->count()-1), 0);
-
- if (layoutScheduled)
- layout();
- qreal pos = isRightToLeft() ? -position() - size() : position();
- FxListItemSG *item = visibleItem(idx);
- qreal maxExtent;
- if (orient == QSGListView::Vertical)
- maxExtent = -q->maxYExtent();
- else
- maxExtent = isRightToLeft() ? q->minXExtent()-size(): -q->maxXExtent();
- if (!item) {
- int itemPos = positionAt(idx);
- // save the currently visible items in case any of them end up visible again
- QList<FxListItemSG*> oldVisible = visibleItems;
- visibleItems.clear();
- visiblePos = itemPos;
- visibleIndex = idx;
- 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) {
- const qreal itemPos = item->position();
- switch (mode) {
- case QSGListView::Beginning:
- pos = itemPos;
- if (index < 0 && header)
- pos -= header->size();
- break;
- case QSGListView::Center:
- pos = itemPos - (size() - item->size())/2;
- break;
- case QSGListView::End:
- pos = itemPos - size() + item->size();
- if (index >= model->count() && footer)
- pos += footer->size();
- break;
- case QSGListView::Visible:
- if (itemPos > pos + size())
- pos = itemPos - size() + item->size();
- else if (item->endPosition() < pos)
- pos = itemPos;
- break;
- case QSGListView::Contain:
- if (item->endPosition() > pos + size())
- pos = itemPos - size() + item->size();
- if (itemPos < pos)
- pos = itemPos;
- }
- pos = qMin(pos, maxExtent);
- qreal minExtent;
- if (orient == QSGListView::Vertical) {
- minExtent = -q->minYExtent();
- } else {
- minExtent = isRightToLeft() ? q->maxXExtent()-size(): -q->minXExtent();
- }
- pos = qMax(pos, minExtent);
- moveReason = QSGListViewPrivate::Other;
- q->cancelFlick();
- setPosition(pos);
- if (highlight) {
- if (autoHighlight) {
- highlight->setPosition(currentItem->itemPosition());
- highlight->setSize(currentItem->itemSize());
- }
- updateHighlight();
- }
- }
- fixupPosition();
-}
-
-void QSGListView::positionViewAtIndex(int index, int mode)
-{
- Q_D(QSGListView);
- if (!d->isValid() || index < 0 || index >= d->model->count())
- return;
- d->positionViewAtIndex(index, mode);
-}
-
-void QSGListView::positionViewAtBeginning()
-{
- Q_D(QSGListView);
- if (!d->isValid())
- return;
- d->positionViewAtIndex(-1, Beginning);
-}
-
-void QSGListView::positionViewAtEnd()
-{
- Q_D(QSGListView);
- if (!d->isValid())
- return;
- d->positionViewAtIndex(d->model->count(), End);
-}
-
-int QSGListView::indexAt(qreal x, qreal y) const
-{
- Q_D(const QSGListView);
- for (int i = 0; i < d->visibleItems.count(); ++i) {
- const FxListItemSG *listItem = d->visibleItems.at(i);
- if(listItem->contains(x, y))
- return listItem->index;
- }
-
- return -1;
-}
-
-void QSGListView::componentComplete()
-{
- Q_D(QSGListView);
- QSGFlickable::componentComplete();
- updateSections();
- d->updateHeader();
- d->updateFooter();
- if (d->isValid()) {
- refill();
- d->moveReason = QSGListViewPrivate::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->position());
- d->updateTrackedItem();
- }
- d->moveReason = QSGListViewPrivate::Other;
- d->fixupPosition();
- }
-}
-
void QSGListView::updateSections()
{
Q_D(QSGListView);
@@ -2561,86 +1568,6 @@ void QSGListView::updateSections()
}
}
-void QSGListView::refill()
-{
- Q_D(QSGListView);
- if (d->isRightToLeft())
- d->refill(-d->position()-d->size()+1, -d->position());
- else
- d->refill(d->position(), d->position()+d->size()-1);
-}
-
-void QSGListView::trackedPositionChanged()
-{
- Q_D(QSGListView);
- if (!d->trackedItem || !d->currentItem)
- return;
- if (d->moveReason == QSGListViewPrivate::SetIndex) {
- qreal trackedPos = qCeil(d->trackedItem->position());
- qreal trackedSize = d->trackedItem->size();
- if (d->trackedItem != d->currentItem) {
- trackedPos -= d->currentItem->sectionSize();
- trackedSize += d->currentItem->sectionSize();
- }
- qreal viewPos;
- qreal highlightStart;
- qreal highlightEnd;
- if (d->isRightToLeft()) {
- 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->trackedItem->size())
- pos = trackedPos - highlightEnd + d->trackedItem->size();
- if (trackedPos < pos + highlightStart)
- pos = trackedPos - highlightStart;
- } else {
- if (trackedPos < d->startPosition() + highlightStart) {
- pos = d->startPosition();
- } else if (d->trackedItem->endPosition() > d->endPosition() - d->size() + highlightEnd) {
- pos = d->endPosition() - d->size() + 1;
- if (pos < d->startPosition())
- pos = d->startPosition();
- } else {
- if (trackedPos < viewPos + highlightStart) {
- pos = trackedPos - highlightStart;
- } else if (trackedPos > viewPos + highlightEnd - trackedSize) {
- pos = trackedPos - highlightEnd + trackedSize;
- }
- }
- }
- } else {
- if (trackedPos < viewPos && d->currentItem->position() < viewPos) {
- pos = d->currentItem->position() < trackedPos ? trackedPos : d->currentItem->position();
- } else if (d->trackedItem->endPosition() >= viewPos + d->size()
- && d->currentItem->endPosition() >= viewPos + d->size()) {
- if (d->trackedItem->endPosition() <= d->currentItem->endPosition()) {
- pos = d->trackedItem->endPosition() - d->size() + 1;
- if (trackedSize > d->size())
- pos = trackedPos;
- } else {
- pos = d->currentItem->endPosition() - d->size() + 1;
- if (d->currentItem->size() > d->size())
- pos = d->currentItem->position();
- }
- }
- }
- if (viewPos != pos) {
- cancelFlick();
- d->calcVelocity = true;
- d->setPosition(pos);
- d->calcVelocity = false;
- }
- }
-}
-
void QSGListView::itemsInserted(int modelIndex, int count)
{
Q_D(QSGListView);
@@ -2667,9 +1594,9 @@ void QSGListView::itemsInserted(int modelIndex, int count)
// Insert before visible items
d->visibleIndex += count;
for (int i = 0; i < d->visibleItems.count(); ++i) {
- FxListItemSG *listItem = d->visibleItems.at(i);
- if (listItem->index != -1 && listItem->index >= modelIndex)
- listItem->index += count;
+ FxViewItem *item = d->visibleItems.at(i);
+ if (item->index != -1 && item->index >= modelIndex)
+ item->index += count;
}
}
if (d->currentIndex >= modelIndex) {
@@ -2692,14 +1619,14 @@ void QSGListView::itemsInserted(int modelIndex, int count)
pos = index < d->visibleItems.count() ? d->visibleItems.at(index)->position()
: d->visibleItems.last()->endPosition()+d->spacing+1;
} else if (d->itemCount == 0 && d->header) {
- pos = d->header->size();
+ pos = d->headerSize();
}
int initialPos = pos;
int diff = 0;
QList<FxListItemSG*> added;
bool addedVisible = false;
- FxListItemSG *firstVisible = d->firstVisibleItem();
+ FxViewItem *firstVisible = d->firstVisibleItem();
if (firstVisible && pos < firstVisible->position()) {
// Insert items before the visible item.
int insertionIdx = index;
@@ -2710,7 +1637,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
d->scheduleLayout();
addedVisible = true;
}
- FxListItemSG *item = d->createItem(modelIndex + i);
+ FxListItemSG *item = static_cast<FxListItemSG*>(d->createItem(modelIndex + i));
d->visibleItems.insert(insertionIdx, item);
pos -= item->size() + d->spacing;
item->setPosition(pos);
@@ -2720,7 +1647,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
// If we didn't insert all our new items - anything
// before the current index is not visible - remove it.
while (insertionIdx--) {
- FxListItemSG *item = d->visibleItems.takeFirst();
+ FxListItemSG *item = static_cast<FxListItemSG*>(d->visibleItems.takeFirst());
if (item->index != -1)
d->visibleIndex++;
d->releaseItem(item);
@@ -2728,7 +1655,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
} else {
// adjust pos of items before inserted items.
for (int i = insertionIdx-1; i >= 0; i--) {
- FxListItemSG *listItem = d->visibleItems.at(i);
+ FxListItemSG *listItem = static_cast<FxListItemSG*>(d->visibleItems.at(i));
listItem->setPosition(listItem->position() - (initialPos - pos));
}
}
@@ -2740,7 +1667,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
d->scheduleLayout();
addedVisible = true;
}
- FxListItemSG *item = d->createItem(modelIndex + i);
+ FxListItemSG *item = static_cast<FxListItemSG*>(d->createItem(modelIndex + i));
d->visibleItems.insert(index, item);
item->setPosition(pos);
added.append(item);
@@ -2760,7 +1687,7 @@ void QSGListView::itemsInserted(int modelIndex, int count)
d->currentIndex += count;
if (d->currentItem) {
d->currentItem->index = d->currentIndex;
- d->currentItem->setPosition(d->currentItem->position() + diff);
+ static_cast<FxListItemSG *>(d->currentItem)->setPosition(static_cast<FxListItemSG *>(d->currentItem)->position() + diff);
}
emit currentIndexChanged();
} else if (!d->itemCount && (!d->currentIndex || (d->currentIndex < 0 && !d->currentIndexCleared))) {
@@ -2768,11 +1695,11 @@ void QSGListView::itemsInserted(int modelIndex, int count)
}
// Update the indexes of the following visible items.
for (; index < d->visibleItems.count(); ++index) {
- FxListItemSG *listItem = d->visibleItems.at(index);
- if (d->currentItem && listItem->item != d->currentItem->item)
- listItem->setPosition(listItem->position() + diff);
- if (listItem->index != -1)
- listItem->index += count;
+ FxViewItem *item = d->visibleItems.at(index);
+ if (d->currentItem && item->item != d->currentItem->item)
+ static_cast<FxListItemSG*>(item)->setPosition(item->position() + diff);
+ if (item->index != -1)
+ item->index += count;
}
// everything is in order now - emit add() signal
for (int j = 0; j < added.count(); ++j)
@@ -2792,13 +1719,13 @@ void QSGListView::itemsRemoved(int modelIndex, int count)
d->updateUnrequestedIndexes();
d->itemCount -= count;
- FxListItemSG *firstVisible = d->firstVisibleItem();
+ FxViewItem *firstVisible = d->firstVisibleItem();
int preRemovedSize = 0;
bool removedVisible = false;
// Remove the items from the visible list, skipping anything already marked for removal
- QList<FxListItemSG*>::Iterator it = d->visibleItems.begin();
+ QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
- FxListItemSG *item = *it;
+ FxViewItem *item = *it;
if (item->index == -1 || item->index < modelIndex) {
// already removed, or before removed items
++it;
@@ -2829,7 +1756,7 @@ void QSGListView::itemsRemoved(int modelIndex, int count)
}
if (firstVisible && d->visibleItems.first() != firstVisible)
- d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + preRemovedSize);
+ static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + preRemovedSize);
// fix current
if (d->currentIndex >= modelIndex + count) {
@@ -2865,7 +1792,7 @@ void QSGListView::itemsRemoved(int modelIndex, int count)
d->timeline.clear();
if (removedVisible && d->itemCount == 0) {
d->visibleIndex = 0;
- d->visiblePos = d->header ? d->header->size() : 0;
+ d->visiblePos = d->header ? d->headerSize() : 0;
d->setPosition(0);
d->updateHeader();
d->updateFooter();
@@ -2880,25 +1807,6 @@ void QSGListView::itemsRemoved(int modelIndex, int count)
emit countChanged();
}
-void QSGListView::destroyRemoved()
-{
- Q_D(QSGListView);
- for (QList<FxListItemSG*>::Iterator it = d->visibleItems.begin();
- it != d->visibleItems.end();) {
- FxListItemSG *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->updateSections();
- d->layout();
-}
-
void QSGListView::itemsMoved(int from, int to, int count)
{
Q_D(QSGListView);
@@ -2907,19 +1815,19 @@ void QSGListView::itemsMoved(int from, int to, int count)
d->updateUnrequestedIndexes();
if (d->visibleItems.isEmpty()) {
- refill();
+ d->refill();
return;
}
d->moveReason = QSGListViewPrivate::Other;
- FxListItemSG *firstVisible = d->firstVisibleItem();
+ FxViewItem *firstVisible = d->firstVisibleItem();
qreal firstItemPos = firstVisible->position();
- QHash<int,FxListItemSG*> moved;
+ QHash<int,FxViewItem*> moved;
int moveBy = 0;
- QList<FxListItemSG*>::Iterator it = d->visibleItems.begin();
+ QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
- FxListItemSG *item = *it;
+ FxViewItem *item = *it;
if (item->index >= from && item->index < from + count) {
// take the items that are moving
item->index += (to-from);
@@ -2939,10 +1847,10 @@ void QSGListView::itemsMoved(int from, int to, int count)
int endIndex = d->visibleIndex;
it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
- FxListItemSG *item = *it;
+ FxViewItem *item = *it;
if (remaining && item->index >= to && item->index < to + count) {
// place items in the target position, reusing any existing items
- FxListItemSG *movedItem = moved.take(item->index);
+ FxViewItem *movedItem = moved.take(item->index);
if (!movedItem)
movedItem = d->createItem(item->index);
if (item->index <= firstVisible->index)
@@ -2964,7 +1872,7 @@ void QSGListView::itemsMoved(int from, int to, int count)
// If we have moved items to the end of the visible items
// then add any existing moved items that we have
- while (FxListItemSG *item = moved.take(endIndex+1)) {
+ while (FxViewItem *item = moved.take(endIndex+1)) {
d->visibleItems.append(item);
++endIndex;
}
@@ -2990,70 +1898,19 @@ void QSGListView::itemsMoved(int from, int to, int count)
// Whatever moved items remain are no longer visible items.
while (moved.count()) {
int idx = moved.begin().key();
- FxListItemSG *item = moved.take(idx);
+ FxViewItem *item = moved.take(idx);
if (d->currentItem && item->item == d->currentItem->item)
- item->setPosition(d->positionAt(idx));
+ static_cast<FxListItemSG*>(item)->setPosition(d->positionAt(idx));
d->releaseItem(item);
}
// Ensure we don't cause an ugly list scroll.
- d->visibleItems.first()->setPosition(d->visibleItems.first()->position() + moveBy);
-
- d->updateSections();
- d->layout();
-}
+ static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + moveBy);
-void QSGListView::itemsChanged(int, int)
-{
- Q_D(QSGListView);
d->updateSections();
d->layout();
}
-void QSGListView::modelReset()
-{
- Q_D(QSGListView);
- d->moveReason = QSGListViewPrivate::SetIndex;
- d->regenerate();
- if (d->highlight && d->currentItem) {
- if (d->autoHighlight)
- d->highlight->setPosition(d->currentItem->position());
- d->updateTrackedItem();
- }
- d->moveReason = QSGListViewPrivate::Other;
- emit countChanged();
-}
-
-void QSGListView::createdItem(int index, QSGItem *item)
-{
- Q_D(QSGListView);
- if (d->requestedIndex != index) {
- item->setParentItem(contentItem());
- d->unrequestedItems.insert(item, index);
- if (d->orient == QSGListView::Vertical) {
- item->setY(d->positionAt(index));
- } else {
- if (d->isRightToLeft())
- item->setX(-d->positionAt(index)-item->width());
- else
- item->setX(d->positionAt(index));
- }
- }
-}
-
-void QSGListView::destroyingItem(QSGItem *item)
-{
- Q_D(QSGListView);
- d->unrequestedItems.remove(item);
-}
-
-void QSGListView::animStopped()
-{
- Q_D(QSGListView);
- d->bufferMode = QSGListViewPrivate::NoBuffer;
- if (d->haveHighlightRange && d->highlightRange == QSGListView::StrictlyEnforceRange)
- d->updateHighlight();
-}
QSGListViewAttached *QSGListView::qmlAttachedProperties(QObject *obj)
{
diff --git a/src/declarative/items/qsglistview_p.h b/src/declarative/items/qsglistview_p.h
index 85602256f9..e45e16b85d 100644
--- a/src/declarative/items/qsglistview_p.h
+++ b/src/declarative/items/qsglistview_p.h
@@ -43,7 +43,7 @@
#ifndef QSGLISTVIEW_P_H
#define QSGLISTVIEW_P_H
-#include "qsgflickable_p.h"
+#include "qsgitemview_p.h"
#include <private/qdeclarativeguard_p.h>
@@ -90,84 +90,33 @@ private:
class QSGVisualModel;
class QSGListViewAttached;
class QSGListViewPrivate;
-class Q_AUTOTEST_EXPORT QSGListView : public QSGFlickable
+class Q_AUTOTEST_EXPORT QSGListView : public QSGItemView
{
Q_OBJECT
Q_DECLARE_PRIVATE(QSGListView)
- Q_PROPERTY(QVariant model READ model WRITE setModel NOTIFY modelChanged)
- Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
- Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
- Q_PROPERTY(QSGItem *currentItem READ currentItem NOTIFY currentIndexChanged)
- Q_PROPERTY(int count READ count NOTIFY countChanged)
-
- Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
- Q_PROPERTY(QSGItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
- Q_PROPERTY(bool highlightFollowsCurrentItem READ highlightFollowsCurrentItem WRITE setHighlightFollowsCurrentItem NOTIFY highlightFollowsCurrentItemChanged)
+ // XXX deprecate these two properties (only duration should be necessary)
Q_PROPERTY(qreal highlightMoveSpeed READ highlightMoveSpeed WRITE setHighlightMoveSpeed NOTIFY highlightMoveSpeedChanged)
- Q_PROPERTY(int highlightMoveDuration READ highlightMoveDuration WRITE setHighlightMoveDuration NOTIFY highlightMoveDurationChanged)
Q_PROPERTY(qreal highlightResizeSpeed READ highlightResizeSpeed WRITE setHighlightResizeSpeed NOTIFY highlightResizeSpeedChanged)
- Q_PROPERTY(int highlightResizeDuration READ highlightResizeDuration WRITE setHighlightResizeDuration NOTIFY highlightResizeDurationChanged)
- Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged RESET resetPreferredHighlightBegin)
- Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged RESET resetPreferredHighlightEnd)
- Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+ Q_PROPERTY(int highlightResizeDuration READ highlightResizeDuration WRITE setHighlightResizeDuration NOTIFY highlightResizeDurationChanged)
Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
Q_PROPERTY(Orientation orientation READ orientation WRITE setOrientation NOTIFY orientationChanged)
- Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection NOTIFY layoutDirectionChanged)
- Q_PROPERTY(Qt::LayoutDirection effectiveLayoutDirection READ effectiveLayoutDirection NOTIFY effectiveLayoutDirectionChanged)
- Q_PROPERTY(bool keyNavigationWraps READ isWrapEnabled WRITE setWrapEnabled NOTIFY keyNavigationWrapsChanged)
- Q_PROPERTY(int cacheBuffer READ cacheBuffer WRITE setCacheBuffer NOTIFY cacheBufferChanged)
+
Q_PROPERTY(QSGViewSection *section READ sectionCriteria CONSTANT)
Q_PROPERTY(QString currentSection READ currentSection NOTIFY currentSectionChanged)
Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged)
- Q_PROPERTY(QDeclarativeComponent *header READ header WRITE setHeader NOTIFY headerChanged)
- Q_PROPERTY(QDeclarativeComponent *footer READ footer WRITE setFooter NOTIFY footerChanged)
-
- Q_ENUMS(HighlightRangeMode)
Q_ENUMS(Orientation)
Q_ENUMS(SnapMode)
- Q_ENUMS(PositionMode)
Q_CLASSINFO("DefaultProperty", "data")
public:
QSGListView(QSGItem *parent=0);
~QSGListView();
- QVariant model() const;
- void setModel(const QVariant &);
-
- QDeclarativeComponent *delegate() const;
- void setDelegate(QDeclarativeComponent *);
-
- int currentIndex() const;
- void setCurrentIndex(int idx);
-
- QSGItem *currentItem();
- QSGItem *highlightItem();
- int count() const;
-
- QDeclarativeComponent *highlight() const;
- void setHighlight(QDeclarativeComponent *highlight);
-
- bool highlightFollowsCurrentItem() const;
- void setHighlightFollowsCurrentItem(bool);
-
- enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
- HighlightRangeMode highlightRangeMode() const;
- void setHighlightRangeMode(HighlightRangeMode mode);
-
- qreal preferredHighlightBegin() const;
- void setPreferredHighlightBegin(qreal);
- void resetPreferredHighlightBegin();
-
- qreal preferredHighlightEnd() const;
- void setPreferredHighlightEnd(qreal);
- void resetPreferredHighlightEnd();
-
qreal spacing() const;
void setSpacing(qreal spacing);
@@ -175,115 +124,62 @@ public:
Orientation orientation() const;
void setOrientation(Orientation);
- Qt::LayoutDirection layoutDirection() const;
- void setLayoutDirection(Qt::LayoutDirection);
- Qt::LayoutDirection effectiveLayoutDirection() const;
-
- bool isWrapEnabled() const;
- void setWrapEnabled(bool);
-
- int cacheBuffer() const;
- void setCacheBuffer(int);
-
QSGViewSection *sectionCriteria();
QString currentSection() const;
+ virtual void setHighlightFollowsCurrentItem(bool);
+
qreal highlightMoveSpeed() const;
void setHighlightMoveSpeed(qreal);
- int highlightMoveDuration() const;
- void setHighlightMoveDuration(int);
-
qreal highlightResizeSpeed() const;
void setHighlightResizeSpeed(qreal);
int highlightResizeDuration() const;
void setHighlightResizeDuration(int);
+ virtual void setHighlightMoveDuration(int);
+
enum SnapMode { NoSnap, SnapToItem, SnapOneItem };
SnapMode snapMode() const;
void setSnapMode(SnapMode mode);
- QDeclarativeComponent *footer() const;
- void setFooter(QDeclarativeComponent *);
-
- QDeclarativeComponent *header() const;
- void setHeader(QDeclarativeComponent *);
-
- virtual void setContentX(qreal pos);
- virtual void setContentY(qreal pos);
-
static QSGListViewAttached *qmlAttachedProperties(QObject *);
- enum PositionMode { Beginning, Center, End, Visible, Contain };
-
- Q_INVOKABLE void positionViewAtIndex(int index, int mode);
- Q_INVOKABLE int indexAt(qreal x, qreal y) const;
- Q_INVOKABLE void positionViewAtBeginning();
- Q_INVOKABLE void positionViewAtEnd();
-
public Q_SLOTS:
void incrementCurrentIndex();
void decrementCurrentIndex();
Q_SIGNALS:
- void countChanged();
void spacingChanged();
void orientationChanged();
- void layoutDirectionChanged();
- void effectiveLayoutDirectionChanged();
- void currentIndexChanged();
void currentSectionChanged();
void highlightMoveSpeedChanged();
- void highlightMoveDurationChanged();
void highlightResizeSpeedChanged();
void highlightResizeDurationChanged();
- void highlightChanged();
- void highlightItemChanged();
- void modelChanged();
- void delegateChanged();
- void highlightFollowsCurrentItemChanged();
- void preferredHighlightBeginChanged();
- void preferredHighlightEndChanged();
- void highlightRangeModeChanged();
- void keyNavigationWrapsChanged();
- void cacheBufferChanged();
void snapModeChanged();
- void headerChanged();
- void footerChanged();
protected:
- virtual void updatePolish();
virtual void viewportMoved();
- virtual qreal minYExtent() const;
- virtual qreal maxYExtent() const;
- virtual qreal minXExtent() const;
- virtual qreal maxXExtent() const;
virtual void keyPressEvent(QKeyEvent *);
virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry);
- virtual void componentComplete();
-private Q_SLOTS:
+protected Q_SLOTS:
void updateSections();
- void refill();
- void trackedPositionChanged();
+
+private Q_SLOTS:
void itemsInserted(int index, int count);
void itemsRemoved(int index, int count);
void itemsMoved(int from, int to, int count);
- void itemsChanged(int index, int count);
- void modelReset();
- void destroyRemoved();
- void createdItem(int index, QSGItem *item);
- void destroyingItem(QSGItem *item);
- void animStopped();
};
-class QSGListViewAttached : public QObject
+class QSGListViewAttached : public QSGItemViewAttached
{
Q_OBJECT
+
public:
QSGListViewAttached(QObject *parent)
- : QObject(parent), m_view(0), m_isCurrent(false), m_delayRemove(false) {}
+ : QSGItemViewAttached(parent), m_view(0) {}
~QSGListViewAttached() {}
Q_PROPERTY(QSGListView *view READ view NOTIFY viewChanged)
@@ -295,71 +191,11 @@ public:
}
}
- Q_PROPERTY(bool isCurrentItem READ isCurrentItem NOTIFY currentItemChanged)
- bool isCurrentItem() const { return m_isCurrent; }
- void setIsCurrentItem(bool c) {
- if (m_isCurrent != c) {
- m_isCurrent = c;
- emit currentItemChanged();
- }
- }
-
- Q_PROPERTY(QString previousSection READ prevSection NOTIFY prevSectionChanged)
- QString prevSection() const { return m_prevSection; }
- void setPrevSection(const QString &sect) {
- if (m_prevSection != sect) {
- m_prevSection = sect;
- emit prevSectionChanged();
- }
- }
-
- Q_PROPERTY(QString nextSection READ nextSection NOTIFY nextSectionChanged)
- QString nextSection() const { return m_nextSection; }
- void setNextSection(const QString &sect) {
- if (m_nextSection != sect) {
- m_nextSection = sect;
- emit nextSectionChanged();
- }
- }
-
- Q_PROPERTY(QString section READ section NOTIFY sectionChanged)
- QString section() const { return m_section; }
- void setSection(const QString &sect) {
- if (m_section != sect) {
- m_section = sect;
- emit sectionChanged();
- }
- }
-
- Q_PROPERTY(bool delayRemove READ delayRemove WRITE setDelayRemove NOTIFY delayRemoveChanged)
- bool delayRemove() const { return m_delayRemove; }
- void setDelayRemove(bool delay) {
- if (m_delayRemove != delay) {
- m_delayRemove = delay;
- emit delayRemoveChanged();
- }
- }
-
- void emitAdd() { emit add(); }
- void emitRemove() { emit remove(); }
-
Q_SIGNALS:
- void currentItemChanged();
- void sectionChanged();
- void prevSectionChanged();
- void nextSectionChanged();
- void delayRemoveChanged();
- void add();
- void remove();
void viewChanged();
public:
QDeclarativeGuard<QSGListView> m_view;
- mutable QString m_section;
- QString m_prevSection;
- QString m_nextSection;
- bool m_isCurrent : 1;
- bool m_delayRemove : 1;
};
diff --git a/tests/auto/declarative/qsggridview/tst_qsggridview.cpp b/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
index ab202e047f..5310632d98 100644
--- a/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
+++ b/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
@@ -1236,7 +1236,7 @@ void tst_QSGGridView::positionViewAtIndex()
// Position on an item that would leave empty space if positioned at the top
gridview->positionViewAtIndex(31, QSGGridView::Beginning);
QTRY_COMPARE(gridview->indexAt(120, 630), 31);
- QTRY_COMPARE(gridview->contentY(), 520.);
+ QTRY_COMPARE(gridview->contentY(), 521.); // 520 then +1 so bottom edge of last item is visible
// Confirm items positioned correctly
itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
@@ -1354,7 +1354,7 @@ void tst_QSGGridView::positionViewAtIndex()
// positionViewAtEnd
gridview->positionViewAtEnd();
- QTRY_COMPARE(gridview->contentX(), 430.);
+ QTRY_COMPARE(gridview->contentX(), 400.); // 8*80 - 240 (8 columns)
gridview->setContentX(80);
canvas->rootObject()->setProperty("showFooter", true);