public:
FxGridItemSG(QQuickItem *i, QQuickGridView *v, bool own, bool trackGeometry) : FxViewItem(i, own, trackGeometry), view(v) {
attached = static_cast<QQuickGridViewAttached*>(qmlAttachedPropertiesObject<QQuickGridView>(item));
- if (attached)
- static_cast<QQuickGridViewAttached*>(attached)->setView(view);
if (trackGeometry) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
void resetColumns();
- virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer);
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer);
virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
virtual FxViewItem *newViewItem(int index, QQuickItem *item);
itemPrivate->addItemChangeListener(this, QQuickItemPrivate::Geometry);
}
-bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer)
+bool QQuickGridViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer)
{
qreal colPos = colPosAt(visibleIndex);
qreal rowPos = rowPosAt(visibleIndex);
int modelIndex = findLastVisibleIndex();
modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
- if (visibleItems.count() && (fillFrom > rowPos + rowSize()*2
- || fillTo < rowPosAt(visibleIndex) - rowSize())) {
+ if (visibleItems.count() && (bufferFrom > rowPos + rowSize()*2
+ || bufferTo < rowPosAt(visibleIndex) - rowSize())) {
// We've jumped more than a page. Estimate which items are now
// visible and fill from there.
int count = (fillFrom - (rowPos + rowSize())) / (rowSize()) * columns;
QQuickItemView::geometryChanged(newGeometry, oldGeometry);
}
+void QQuickGridView::initItem(int index, QQuickItem *item)
+{
+ QQuickItemView::initItem(index, item);
+ QQuickGridViewAttached *attached = static_cast<QQuickGridViewAttached *>(
+ qmlAttachedPropertiesObject<QQuickGridView>(item));
+ if (attached)
+ attached->setView(this);
+}
+
/*!
\qmlmethod QtQuick2::GridView::moveCurrentIndexUp()
virtual void viewportMoved(Qt::Orientations);
virtual void keyPressEvent(QKeyEvent *);
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
+ virtual void initItem(int index, QQuickItem *item);
};
class QQuickGridViewAttached : public QQuickItemViewAttached
void QQuickItemView::setCurrentIndex(int index)
{
Q_D(QQuickItemView);
- if (d->requestedIndex >= 0 && !d->requestedAsync) // currently creating item
+ if (d->inRequest) // currently creating item
return;
d->currentIndexCleared = (index == -1);
, moveReason(Other)
, visibleIndex(0)
, currentIndex(-1), currentItem(0)
- , trackedItem(0), requestedIndex(-1), requestedItem(0)
+ , trackedItem(0), requestedIndex(-1)
, highlightComponent(0), highlight(0)
, highlightRange(QQuickItemView::NoHighlightRange)
, highlightRangeStart(0), highlightRangeEnd(0)
, ownModel(false), wrap(false)
, inLayout(false), inViewportMoved(false), forceLayout(false), currentIndexCleared(false)
, haveHighlightRange(false), autoHighlight(true), highlightRangeStartValid(false), highlightRangeEndValid(false)
- , fillCacheBuffer(false), inRequest(false), requestedAsync(false)
+ , fillCacheBuffer(false), inRequest(false)
, runDelayedRemoveTransition(false)
{
bufferPause.addAnimationChangeListener(this, QAbstractAnimationJob::Completion);
createHighlight();
trackedItem = 0;
- if (requestedIndex >= 0 && requestedAsync) {
+ if (requestedIndex >= 0) {
if (model)
model->cancel(requestedIndex);
requestedIndex = -1;
qreal fillFrom = from;
qreal fillTo = to;
- bool added = addVisibleItems(fillFrom, fillTo, false);
+ bool added = addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, false);
bool removed = removeNonVisibleItems(bufferFrom, bufferTo);
if (requestedIndex == -1 && buffer && bufferMode != NoBuffer) {
fillTo = bufferTo;
if (bufferMode & BufferBefore)
fillFrom = bufferFrom;
- added |= addVisibleItems(fillFrom, fillTo, true);
+ added |= addVisibleItems(fillFrom, fillTo, bufferFrom, bufferTo, true);
}
}
{
Q_Q(QQuickItemView);
- if (requestedIndex == modelIndex && (asynchronous || requestedAsync == asynchronous))
+ if (requestedIndex == modelIndex && asynchronous)
return 0;
- if (requestedIndex != -1 && requestedIndex != modelIndex) {
- if (requestedItem && requestedItem->item)
- requestedItem->item->setParentItem(0);
- delete requestedItem;
- requestedItem = 0;
- }
-
for (int i=0; i<releasePendingTransition.count(); i++) {
if (releasePendingTransition[i]->index == modelIndex
&& !releasePendingTransition[i]->isPendingRemoval()) {
}
}
- requestedIndex = modelIndex;
- requestedAsync = asynchronous;
+ if (asynchronous)
+ requestedIndex = modelIndex;
inRequest = true;
if (QQuickItem *item = model->item(modelIndex, asynchronous)) {
item->setParentItem(q->contentItem());
- requestedIndex = -1;
- FxViewItem *viewItem = requestedItem;
- if (!viewItem)
- viewItem = newViewItem(modelIndex, item); // already in cache, so viewItem not initialized in initItem()
+ if (requestedIndex == modelIndex)
+ requestedIndex = -1;
+ FxViewItem *viewItem = newViewItem(modelIndex, item);
if (viewItem) {
viewItem->index = modelIndex;
// do other set up for the new item that should not happen
initializeViewItem(viewItem);
unrequestedItems.remove(item);
}
- requestedItem = 0;
inRequest = false;
return viewItem;
}
void QQuickItemView::createdItem(int index, QQuickItem *item)
{
Q_D(QQuickItemView);
- if (d->requestedIndex != index) {
- item->setParentItem(contentItem());
+
+ if (!d->inRequest) {
d->unrequestedItems.insert(item, index);
- QQuickItemPrivate::get(item)->setCulled(true);
- d->repositionPackageItemAt(item, index);
- } else {
d->requestedIndex = -1;
- if (!d->inRequest) {
- if (index == d->currentIndex)
- d->updateCurrent(index);
+ if (d->hasPendingChanges())
+ d->layout();
+ else
d->refill();
- }
+ if (d->unrequestedItems.contains(item))
+ d->repositionPackageItemAt(item, index);
+ else if (index == d->currentIndex)
+ d->updateCurrent(index);
}
}
-void QQuickItemView::initItem(int index, QQuickItem *item)
+void QQuickItemView::initItem(int, QQuickItem *item)
{
- Q_D(QQuickItemView);
item->setZ(1);
- if (d->requestedIndex == index) {
- if (d->requestedAsync)
- QQuickItemPrivate::get(item)->setCulled(true);
- item->setParentItem(contentItem());
- d->requestedItem = d->newViewItem(index, item);
- }
+ item->setParentItem(contentItem());
+ QQuickItemPrivate::get(item)->setCulled(true);
}
void QQuickItemView::destroyingItem(QQuickItem *item)
virtual void updateSections() {}
void destroyRemoved();
void createdItem(int index, QQuickItem *item);
- void initItem(int index, QQuickItem *item);
+ virtual void initItem(int index, QQuickItem *item);
void modelUpdated(const QQuickChangeSet &changeSet, bool reset);
void destroyingItem(QQuickItem *item);
void animStopped();
FxViewItem *trackedItem;
QHash<QQuickItem*,int> unrequestedItems;
int requestedIndex;
- FxViewItem *requestedItem;
QQuickItemViewChangeSet currentChanges;
QQuickItemViewChangeSet bufferedChanges;
QPauseAnimationJob bufferPause;
bool highlightRangeEndValid : 1;
bool fillCacheBuffer : 1;
bool inRequest : 1;
- bool requestedAsync : 1;
bool runDelayedRemoveTransition : 1;
protected:
virtual void setPosition(qreal pos) = 0;
virtual void fixupPosition() = 0;
- virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer) = 0;
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer) = 0;
virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo) = 0;
virtual void visibleItemsChanged() {}
virtual void init();
virtual void clear();
- virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer);
+ virtual bool addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer);
virtual bool removeNonVisibleItems(qreal bufferFrom, qreal bufferTo);
virtual void visibleItemsChanged();
public:
FxListItemSG(QQuickItem *i, QQuickListView *v, bool own, bool trackGeometry) : FxViewItem(i, own, trackGeometry), view(v) {
attached = static_cast<QQuickListViewAttached*>(qmlAttachedPropertiesObject<QQuickListView>(item));
- if (attached)
- static_cast<QQuickListViewAttached*>(attached)->setView(view);
if (trackGeometry) {
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
itemPrivate->addItemChangeListener(QQuickItemViewPrivate::get(view), QQuickItemPrivate::Geometry);
// initialise attached properties
if (sectionCriteria) {
QString propValue = model->stringValue(modelIndex, sectionCriteria->property());
- listItem->attached->m_section = sectionCriteria->sectionString(propValue);
+ listItem->attached->setSection(sectionCriteria->sectionString(propValue));
if (modelIndex > 0) {
if (FxViewItem *item = itemBefore(modelIndex))
- listItem->attached->m_prevSection = item->attached->section();
+ listItem->attached->setPrevSection(item->attached->section());
else
- listItem->attached->m_prevSection = sectionAt(modelIndex-1);
+ listItem->attached->setPrevSection(sectionAt(modelIndex-1));
}
if (modelIndex < model->count()-1) {
if (FxViewItem *item = visibleItem(modelIndex+1))
- listItem->attached->m_nextSection = static_cast<QQuickListViewAttached*>(item->attached)->section();
+ listItem->attached->setNextSection(static_cast<QQuickListViewAttached*>(item->attached)->section());
else
- listItem->attached->m_nextSection = sectionAt(modelIndex+1);
+ listItem->attached->setNextSection(sectionAt(modelIndex+1));
}
}
return released;
}
-bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, bool doBuffer)
+bool QQuickListViewPrivate::addVisibleItems(qreal fillFrom, qreal fillTo, qreal bufferFrom, qreal bufferTo, bool doBuffer)
{
qreal itemEnd = visiblePos;
if (visibleItems.count()) {
bool haveValidItems = modelIndex >= 0;
modelIndex = modelIndex < 0 ? visibleIndex : modelIndex + 1;
- if (haveValidItems && (fillFrom > itemEnd+averageSize+spacing
- || fillTo < visiblePos - averageSize - spacing)) {
+ if (haveValidItems && (bufferFrom > itemEnd+averageSize+spacing
+ || bufferTo < visiblePos - averageSize - spacing)) {
// We've jumped more than a page. Estimate which items are now
// visible and fill from there.
int count = (fillFrom - itemEnd) / (averageSize + spacing);
QQuickItemView::geometryChanged(newGeometry, oldGeometry);
}
+void QQuickListView::initItem(int index, QQuickItem *item)
+{
+ QQuickItemView::initItem(index, item);
+ QQuickListViewAttached *attached = static_cast<QQuickListViewAttached *>(
+ qmlAttachedPropertiesObject<QQuickListView>(item));
+ if (attached)
+ attached->setView(this);
+}
+
/*!
\qmlmethod QtQuick2::ListView::incrementCurrentIndex()
virtual void viewportMoved(Qt::Orientations orient);
virtual void keyPressEvent(QKeyEvent *);
virtual void geometryChanged(const QRectF &newGeometry,const QRectF &oldGeometry);
+ virtual void initItem(int index, QQuickItem *item);
protected Q_SLOTS:
void updateSections();
void qAbstractItemModel_sections();
void sectionsPositioning();
void sectionsDelegate();
+ void sectionsDragOutsideBounds_data();
+ void sectionsDragOutsideBounds();
void sectionPropertyChange();
void cacheBuffer();
void positionViewAtIndex();
int itemCount = findItems<QQuickItem>(contentItem, "wrapper").count();
for (int i = 0; i < model.count() && i < itemCount; ++i) {
QQuickItem *item = findItem<QQuickItem>(contentItem, "wrapper", i);
- QTRY_VERIFY(item);
+ QVERIFY(item);
QTRY_COMPARE(item->y(), qreal(i*20 + ((i+4)/5) * 20));
QQuickText *next = findItem<QQuickText>(item, "nextSection");
QCOMPARE(next->text().toInt(), (i+1)/5);
QTRY_COMPARE(item->y(), qreal(i*20*4));
}
+ delete canvas;
+}
+
+void tst_QQuickListView::sectionsDragOutsideBounds_data()
+{
+ QTest::addColumn<int>("distance");
+ QTest::addColumn<int>("cacheBuffer");
+
+ QTest::newRow("500, no cache buffer") << 500 << 0;
+ QTest::newRow("1000, no cache buffer") << 1000 << 0;
+ QTest::newRow("500, cache buffer") << 500 << 320;
+ QTest::newRow("1000, cache buffer") << 1000 << 320;
+}
+
+void tst_QQuickListView::sectionsDragOutsideBounds()
+{
+ QFETCH(int, distance);
+ QFETCH(int, cacheBuffer);
+
+ QQuickView *canvas = getView();
+
+ QmlListModel model;
+ for (int i = 0; i < 10; i++)
+ model.addItem("Item" + QString::number(i), QString::number(i/5));
+
+ QQmlContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+
+ canvas->setSource(testFileUrl("listview-sections_delegate.qml"));
+ canvas->show();
+ qApp->processEvents();
+
+ QQuickListView *listview = findItem<QQuickListView>(canvas->rootObject(), "list");
+ QTRY_VERIFY(listview != 0);
+ listview->setCacheBuffer(cacheBuffer);
+
+ QQuickItem *contentItem = listview->contentItem();
+ QTRY_VERIFY(contentItem != 0);
+
+ QTRY_COMPARE(QQuickItemPrivate::get(listview)->polishScheduled, false);
+
// QTBUG-17769
- model.removeItems(10, 20);
- // ensure view has settled.
- QTRY_COMPARE(findItems<QQuickItem>(contentItem, "wrapper").count(), 10);
// Drag view up beyond bounds
QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(20,20));
- {
- QMouseEvent mv(QEvent::MouseMove, QPoint(20,0), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QGuiApplication::sendEvent(canvas, &mv);
- }
- {
- QMouseEvent mv(QEvent::MouseMove, QPoint(20,-50), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QGuiApplication::sendEvent(canvas, &mv);
- }
- {
- QMouseEvent mv(QEvent::MouseMove, QPoint(20,-200), Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
- QGuiApplication::sendEvent(canvas, &mv);
- }
- QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(20,-200));
+ QTest::mouseMove(canvas, QPoint(20,0));
+ QTest::mouseMove(canvas, QPoint(20,-50));
+ QTest::mouseMove(canvas, QPoint(20,-distance));
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(20,-distance));
// view should settle back at 0
QTRY_COMPARE(listview->contentY(), 0.0);
- delete canvas;
+ QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(20,0));
+ QTest::mouseMove(canvas, QPoint(20,20));
+ QTest::mouseMove(canvas, QPoint(20,70));
+ QTest::mouseMove(canvas, QPoint(20,distance));
+
+ QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(20,distance));
+ // view should settle back at 0
+ QTRY_COMPARE(listview->contentY(), 0.0);
+
+ releaseView(canvas);
}
void tst_QQuickListView::sectionsPositioning()