aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/declarative/items/qsggridview.cpp16
-rw-r--r--src/declarative/items/qsglistview.cpp13
-rw-r--r--tests/auto/declarative/qsggridview/tst_qsggridview.cpp163
-rw-r--r--tests/auto/declarative/qsglistview/tst_qsglistview.cpp189
4 files changed, 274 insertions, 107 deletions
diff --git a/src/declarative/items/qsggridview.cpp b/src/declarative/items/qsggridview.cpp
index 1aa7292060..8559379d20 100644
--- a/src/declarative/items/qsggridview.cpp
+++ b/src/declarative/items/qsggridview.cpp
@@ -1500,10 +1500,18 @@ void QSGGridView::itemsMoved(int from, int to, int count)
d->moveReason = QSGGridViewPrivate::Other;
FxGridItemSG *firstVisible = static_cast<FxGridItemSG*>(d->firstVisibleItem());
QHash<int,FxGridItemSG*> moved;
+ int moveByCount = 0;
bool movingBackwards = from > to;
int firstItemIndex = firstVisible ? firstVisible->index : -1;
+ // if visibleItems.first() is above the content start pos, and the items
+ // beneath it are moved, ensure this first item is later repositioned correctly
+ // (to above the next visible item) so that subsequent layout() is correct
+ bool repositionFirstItem = firstVisible
+ && d->visibleItems.first()->position() < firstVisible->position()
+ && from > d->visibleItems.first()->index;
+
QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
FxViewItem *item = *it;
@@ -1511,6 +1519,8 @@ void QSGGridView::itemsMoved(int from, int to, int count)
// take the items that are moving
item->index += (to-from);
moved.insert(item->index, static_cast<FxGridItemSG*>(item));
+ if (repositionFirstItem)
+ moveByCount++;
it = d->visibleItems.erase(it);
} else {
if (item->index > from && item->index != -1) {
@@ -1594,6 +1604,12 @@ void QSGGridView::itemsMoved(int from, int to, int count)
d->releaseItem(item);
}
+ // Ensure we don't cause an ugly list scroll.
+ if (d->visibleItems.count() && moveByCount > 0) {
+ FxGridItemSG *first = static_cast<FxGridItemSG*>(d->visibleItems.first());
+ first->setPosition(first->colPos(), first->rowPos() + ((moveByCount / d->columns) * d->rowSize()));
+ }
+
d->layout();
}
diff --git a/src/declarative/items/qsglistview.cpp b/src/declarative/items/qsglistview.cpp
index 0d6a4947f4..abfb4fe9a0 100644
--- a/src/declarative/items/qsglistview.cpp
+++ b/src/declarative/items/qsglistview.cpp
@@ -1815,13 +1815,19 @@ void QSGListView::itemsMoved(int from, int to, int count)
d->moveReason = QSGListViewPrivate::Other;
FxViewItem *firstVisible = d->firstVisibleItem();
- qreal firstItemPos = firstVisible->position();
QHash<int,FxViewItem*> moved;
int moveBy = 0;
bool movingBackwards = from > to;
int firstItemIndex = firstVisible ? firstVisible->index : -1;
+ // if visibleItems.first() is above the content start pos, and the items
+ // beneath it are moved, ensure this first item is later repositioned correctly
+ // (to above the next visible item) so that subsequent layout() is correct
+ bool repositionFirstItem = firstVisible
+ && d->visibleItems.first()->position() < firstVisible->position()
+ && from > d->visibleItems.first()->index;
+
QList<FxViewItem*>::Iterator it = d->visibleItems.begin();
while (it != d->visibleItems.end()) {
FxViewItem *item = *it;
@@ -1829,7 +1835,7 @@ void QSGListView::itemsMoved(int from, int to, int count)
// take the items that are moving
item->index += (to-from);
moved.insert(item->index, item);
- if (item->position() < firstItemPos)
+ if (repositionFirstItem)
moveBy += item->size();
it = d->visibleItems.erase(it);
} else {
@@ -1913,7 +1919,8 @@ void QSGListView::itemsMoved(int from, int to, int count)
}
// Ensure we don't cause an ugly list scroll.
- static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + moveBy);
+ if (d->visibleItems.count())
+ static_cast<FxListItemSG*>(d->visibleItems.first())->setPosition(d->visibleItems.first()->position() + moveBy);
d->updateSections();
d->layout();
diff --git a/tests/auto/declarative/qsggridview/tst_qsggridview.cpp b/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
index 76b30322c6..d2115e123d 100644
--- a/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
+++ b/tests/auto/declarative/qsggridview/tst_qsggridview.cpp
@@ -77,6 +77,7 @@ private slots:
void removed();
void clear();
void moved();
+ void moved_data();
void swapWithFirstItem();
void changeFlow();
void currentIndex();
@@ -115,6 +116,29 @@ private:
QList<T*> findItems(QSGItem *parent, const QString &objectName);
void dumpTree(QSGItem *parent, int depth = 0);
};
+
+template<typename T>
+void tst_qsggridview_move(int from, int to, int n, T *items)
+{
+ if (n == 1) {
+ items->move(from, to);
+ } else {
+ T replaced;
+ int i=0;
+ typename T::ConstIterator it=items->begin(); it += from+n;
+ for (; i<to-from; ++i,++it)
+ replaced.append(*it);
+ i=0;
+ it=items->begin(); it += from;
+ for (; i<n; ++i,++it)
+ replaced.append(*it);
+ typename T::ConstIterator f=replaced.begin();
+ typename T::Iterator t=items->begin(); t += from;
+ for (; f != replaced.end(); ++f, ++t)
+ *t = *f;
+ }
+}
+
void tst_QSGGridView::initTestCase()
{
QSGView canvas;
@@ -191,6 +215,12 @@ public:
emit endMoveRows();
}
+ void moveItems(int from, int to, int count) {
+ emit beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
+ tst_qsggridview_move(from, to, count, &list);
+ emit endMoveRows();
+ }
+
void modifyItem(int idx, const QString &name, const QString &number) {
list[idx] = QPair<QString,QString>(name, number);
emit dataChanged(index(idx,0), index(idx,0));
@@ -566,7 +596,16 @@ void tst_QSGGridView::clear()
void tst_QSGGridView::moved()
{
+ QFETCH(qreal, contentY);
+ QFETCH(int, from);
+ QFETCH(int, to);
+ QFETCH(int, count);
+ QFETCH(qreal, itemsOffsetAfterMove);
+
+ QSGText *name;
+ QSGText *number;
QSGView *canvas = createView();
+ canvas->show();
TestModel model;
for (int i = 0; i < 30; i++)
@@ -586,74 +625,93 @@ void tst_QSGGridView::moved()
QSGItem *contentItem = gridview->contentItem();
QTRY_VERIFY(contentItem != 0);
- model.moveItem(1, 8);
-
- QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(1));
- QSGText *number = findItem<QSGText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(1));
+ QSGItem *currentItem = gridview->currentItem();
+ QTRY_VERIFY(currentItem != 0);
- name = findItem<QSGText>(contentItem, "textName", 8);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(8));
- number = findItem<QSGText>(contentItem, "textNumber", 8);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(8));
+ gridview->setContentY(contentY);
+ model.moveItems(from, to, count);
- // Confirm items positioned correctly
+ // Confirm items positioned correctly and indexes correct
+ int firstVisibleIndex = qCeil(contentY / 60.0) * 3;
int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
- }
- gridview->setContentY(120);
-
- // move outside visible area
- model.moveItem(1, 25);
-
- // Confirm items positioned correctly and indexes correct
- itemCount = findItems<QSGItem>(contentItem, "wrapper").count()-1;
- for (int i = 6; i < model.count()-6 && i < itemCount+6; ++i) {
+ for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
+ if (i >= firstVisibleIndex + 18) // index has moved out of view
+ continue;
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->x(), qreal((i%3)*80));
- QTRY_COMPARE(item->y(), qreal((i/3)*60));
- name = findItem<QSGText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- number = findItem<QSGText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
- }
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
- // move from outside visible into visible
- model.moveItem(28, 8);
-
- // Confirm items positioned correctly and indexes correct
- for (int i = 6; i < model.count()-6 && i < itemCount+6; ++i) {
- QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
QTRY_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
+ QTRY_VERIFY(item->y() == (i/3)*60 + itemsOffsetAfterMove);
+
name = findItem<QSGText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
+ QVERIFY(name != 0);
QTRY_COMPARE(name->text(), model.name(i));
number = findItem<QSGText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
+ QVERIFY(number != 0);
QTRY_COMPARE(number->text(), model.number(i));
+
+ // current index should have been updated
+ if (item == currentItem)
+ QTRY_COMPARE(gridview->currentIndex(), i);
}
delete canvas;
}
+void tst_QSGGridView::moved_data()
+{
+ QTest::addColumn<qreal>("contentY");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<qreal>("itemsOffsetAfterMove");
+
+ // model starts with 30 items, each 80x60, in area 240x320
+ // 18 items should be visible at a time
+
+ QTest::newRow("move 1 forwards, within visible items")
+ << 0.0
+ << 1 << 8 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from non-visible -> visible")
+ << 120.0 // show 6-23
+ << 1 << 23 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
+ << 120.0 // // show 6-23
+ << 0 << 6 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from visible -> non-visible")
+ << 0.0
+ << 1 << 20 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
+ << 0.0
+ << 0 << 20 << 1
+ << 0.0;
+
+
+ QTest::newRow("move 1 backwards, within visible items")
+ << 0.0
+ << 10 << 5 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from non-visible -> visible")
+ << 0.0
+ << 28 << 8 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
+ << 0.0
+ << 29 << 14 << 1
+ << 0.0;
+}
+
void tst_QSGGridView::swapWithFirstItem()
{
// QTBUG_9697
@@ -2395,3 +2453,4 @@ void tst_QSGGridView::dumpTree(QSGItem *parent, int depth)
QTEST_MAIN(tst_QSGGridView)
#include "tst_qsggridview.moc"
+
diff --git a/tests/auto/declarative/qsglistview/tst_qsglistview.cpp b/tests/auto/declarative/qsglistview/tst_qsglistview.cpp
index 19bc0f0e8a..30daeb85ef 100644
--- a/tests/auto/declarative/qsglistview/tst_qsglistview.cpp
+++ b/tests/auto/declarative/qsglistview/tst_qsglistview.cpp
@@ -86,7 +86,9 @@ private slots:
void qAbstractItemModel_removed();
void qListModelInterface_moved();
+ void qListModelInterface_moved_data();
void qAbstractItemModel_moved();
+ void qAbstractItemModel_moved_data();
void qListModelInterface_clear();
void qAbstractItemModel_clear();
@@ -141,6 +143,8 @@ private:
template<typename T>
QList<T*> findItems(QSGItem *parent, const QString &objectName);
void dumpTree(QSGItem *parent, int depth = 0);
+
+ void moved_data();
};
void tst_QSGListView::initTestCase()
@@ -193,6 +197,36 @@ public:
int mCacheBuffer;
};
+template<typename T>
+void tst_qsglistview_move(int from, int to, int n, T *items)
+{
+ if (from > to) {
+ // Only move forwards - flip if backwards moving
+ int tfrom = from;
+ int tto = to;
+ from = tto;
+ to = tto+n;
+ n = tfrom-tto;
+ }
+ if (n == 1) {
+ items->move(from, to);
+ } else {
+ T replaced;
+ int i=0;
+ typename T::ConstIterator it=items->begin(); it += from+n;
+ for (; i<to-from; ++i,++it)
+ replaced.append(*it);
+ i=0;
+ it=items->begin(); it += from;
+ for (; i<n; ++i,++it)
+ replaced.append(*it);
+ typename T::ConstIterator f=replaced.begin();
+ typename T::Iterator t=items->begin(); t += from;
+ for (; f != replaced.end(); ++f, ++t)
+ *t = *f;
+ }
+}
+
class TestModel : public QListModelInterface
{
Q_OBJECT
@@ -275,6 +309,11 @@ public:
emit itemsMoved(from, to, 1);
}
+ void moveItems(int from, int to, int count) {
+ tst_qsglistview_move(from, to, count, &list);
+ emit itemsMoved(from, to, count);
+ }
+
void modifyItem(int index, const QString &name, const QString &number) {
list[index] = QPair<QString,QString>(name, number);
emit itemsChanged(index, 1, roles());
@@ -356,6 +395,12 @@ public:
emit endMoveRows();
}
+ void moveItems(int from, int to, int count) {
+ emit beginMoveRows(QModelIndex(), from, from+count-1, QModelIndex(), to > from ? to+count : to);
+ tst_qsglistview_move(from, to, count, &list);
+ emit endMoveRows();
+ }
+
void modifyItem(int idx, const QString &name, const QString &number) {
list[idx] = QPair<QString,QString>(name, number);
emit dataChanged(index(idx,0), index(idx,0));
@@ -592,7 +637,6 @@ void tst_QSGListView::removed(bool animated)
ctxt->setContextProperty("testModel", &model);
TestObject *testObject = new TestObject;
- testObject->setAnimate(animated);
ctxt->setContextProperty("testObject", testObject);
canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/listviewtest.qml"));
@@ -790,11 +834,19 @@ void tst_QSGListView::clear()
delete testObject;
}
-
template <class T>
void tst_QSGListView::moved()
{
+ QFETCH(qreal, contentY);
+ QFETCH(int, from);
+ QFETCH(int, to);
+ QFETCH(int, count);
+ QFETCH(qreal, itemsOffsetAfterMove);
+
+ QSGText *name;
+ QSGText *number;
QSGView *canvas = createView();
+ canvas->show();
T model;
for (int i = 0; i < 30; i++)
@@ -815,71 +867,93 @@ void tst_QSGListView::moved()
QSGItem *contentItem = listview->contentItem();
QTRY_VERIFY(contentItem != 0);
- model.moveItem(1, 4);
+ QSGItem *currentItem = listview->currentItem();
+ QTRY_VERIFY(currentItem != 0);
- QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(1));
- QSGText *number = findItem<QSGText>(contentItem, "textNumber", 1);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(1));
-
- name = findItem<QSGText>(contentItem, "textName", 4);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(4));
- number = findItem<QSGText>(contentItem, "textNumber", 4);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(4));
+ listview->setContentY(contentY);
+ model.moveItems(from, to, count);
+ qApp->processEvents();
- // Confirm items positioned correctly
+ // Confirm items positioned correctly and indexes correct
+ int firstVisibleIndex = qCeil(contentY / 20.0);
int itemCount = findItems<QSGItem>(contentItem, "wrapper").count();
- for (int i = 0; i < model.count() && i < itemCount; ++i) {
- QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_VERIFY(item->y() == i*20);
- }
-
- listview->setContentY(80);
-
- // move outside visible area
- model.moveItem(1, 18);
- // Confirm items positioned correctly and indexes correct
- for (int i = 3; i < model.count() && i < itemCount; ++i) {
+ for (int i = firstVisibleIndex; i < model.count() && i < itemCount; ++i) {
+ if (i >= firstVisibleIndex + 16) // index has moved out of view
+ continue;
QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.0 + 20);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
+ QTRY_COMPARE(item->y(), i*20.0 + itemsOffsetAfterMove);
name = findItem<QSGText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
+ QVERIFY(name != 0);
QTRY_COMPARE(name->text(), model.name(i));
number = findItem<QSGText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
+ QVERIFY(number != 0);
QTRY_COMPARE(number->text(), model.number(i));
- }
-
- // move from outside visible into visible
- model.moveItem(20, 4);
- // Confirm items positioned correctly and indexes correct
- for (int i = 3; i < model.count() && i < itemCount; ++i) {
- QSGItem *item = findItem<QSGItem>(contentItem, "wrapper", i);
- if (!item) qWarning() << "Item" << i << "not found";
- QTRY_VERIFY(item);
- QTRY_COMPARE(item->y(), i*20.0 + 20);
- name = findItem<QSGText>(contentItem, "textName", i);
- QTRY_VERIFY(name != 0);
- QTRY_COMPARE(name->text(), model.name(i));
- number = findItem<QSGText>(contentItem, "textNumber", i);
- QTRY_VERIFY(number != 0);
- QTRY_COMPARE(number->text(), model.number(i));
+ // current index should have been updated
+ if (item == currentItem)
+ QTRY_COMPARE(listview->currentIndex(), i);
}
delete canvas;
delete testObject;
}
+void tst_QSGListView::moved_data()
+{
+ QTest::addColumn<qreal>("contentY");
+ QTest::addColumn<int>("from");
+ QTest::addColumn<int>("to");
+ QTest::addColumn<int>("count");
+ QTest::addColumn<qreal>("itemsOffsetAfterMove");
+
+ // model starts with 30 items, each 20px high, in area 320px high
+ // 16 items should be visible at a time
+ // itemsOffsetAfterMove should be > 0 whenever items above the visible pos have moved
+
+ QTest::newRow("move 1 forwards, within visible items")
+ << 0.0
+ << 1 << 4 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from non-visible -> visible")
+ << 80.0 // show 4-19
+ << 1 << 18 << 1
+ << 20.0;
+
+ QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
+ << 80.0 // show 4-19
+ << 0 << 4 << 1
+ << 20.0;
+
+ QTest::newRow("move 1 forwards, from visible -> non-visible")
+ << 0.0
+ << 1 << 16 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 forwards, from visible -> non-visible (move first item)")
+ << 0.0
+ << 0 << 16 << 1
+ << 20.0;
+
+
+ QTest::newRow("move 1 backwards, within visible items")
+ << 0.0
+ << 4 << 1 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from non-visible -> visible")
+ << 0.0
+ << 20 << 4 << 1
+ << 0.0;
+
+ QTest::newRow("move 1 backwards, from non-visible -> visible (move last item)")
+ << 0.0
+ << 29 << 15 << 1
+ << 0.0;
+}
+
void tst_QSGListView::swapWithFirstItem()
{
QSGView *canvas = createView();
@@ -903,7 +977,7 @@ void tst_QSGListView::swapWithFirstItem()
// ensure content position is stable
listview->setContentY(0);
- model.moveItem(10, 0);
+ model.moveItem(1, 0);
QTRY_VERIFY(listview->contentY() == 0);
delete testObject;
@@ -2848,11 +2922,21 @@ void tst_QSGListView::qListModelInterface_moved()
moved<TestModel>();
}
+void tst_QSGListView::qListModelInterface_moved_data()
+{
+ moved_data();
+}
+
void tst_QSGListView::qAbstractItemModel_moved()
{
moved<TestModel2>();
}
+void tst_QSGListView::qAbstractItemModel_moved_data()
+{
+ moved_data();
+}
+
void tst_QSGListView::qListModelInterface_clear()
{
clear<TestModel>();
@@ -2937,3 +3021,4 @@ void tst_QSGListView::dumpTree(QSGItem *parent, int depth)
QTEST_MAIN(tst_QSGListView)
#include "tst_qsglistview.moc"
+