void removed();
void clear();
void moved();
+ void moved_data();
+ void multipleChanges();
+ void multipleChanges_data();
void swapWithFirstItem();
void changeFlow();
void currentIndex();
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;
{
}
+
+
class TestModel : public QAbstractListModel
{
public:
emit endInsertRows();
}
+ void insertItems(int index, const QList<QPair<QString, QString> > &items) {
+ emit beginInsertRows(QModelIndex(), index, index + items.count() - 1);
+ for (int i=0; i<items.count(); i++)
+ list.insert(index + i, QPair<QString,QString>(items[i].first, items[i].second));
+ emit endInsertRows();
+ }
+
void removeItem(int index) {
emit beginRemoveRows(QModelIndex(), index, index);
list.removeAt(index);
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));
QTRY_VERIFY(contentItem != 0);
model.insertItem(1, "Will", "9876");
- QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QTRY_COMPARE(contentItem->childItems().count(), model.count()+1); // assumes all are visible, +1 for the (default) highlight item
QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
QTRY_VERIFY(contentItem != 0);
model.removeItem(1);
- QCOMPARE(canvas->rootObject()->property("count").toInt(), model.count());
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QSGText *name = findItem<QSGText>(contentItem, "textName", 1);
QTRY_VERIFY(name != 0);
QTRY_VERIFY(number != 0);
QTRY_COMPARE(number->text(), model.number(1));
+
// Checks that onRemove is called
QString removed = canvas->rootObject()->property("removed").toString();
QTRY_COMPARE(removed, QString("Item1"));
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);
}
// Remove first item (which is the current item);
model.removeItem(0);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
name = findItem<QSGText>(contentItem, "textName", 0);
QTRY_VERIFY(name != 0);
QTRY_VERIFY(number != 0);
QTRY_COMPARE(number->text(), model.number(0));
+
// Confirm items positioned correctly
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);
}
// Remove items not visible
model.removeItem(25);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
// Confirm items positioned correctly
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);
}
QTRY_COMPARE(gridview->contentY(), 120.0);
model.removeItem(1);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
// Confirm items positioned correctly
for (int i = 6; i < 18; ++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);
}
// Remove currentIndex
QSGItem *oldCurrent = gridview->currentItem();
model.removeItem(9);
+ QTRY_COMPARE(canvas->rootObject()->property("count").toInt(), model.count());
QTRY_COMPARE(gridview->currentIndex(), 9);
QTRY_VERIFY(gridview->currentItem() != oldCurrent);
gridview->setContentY(0);
// let transitions settle.
- QTest::qWait(100);
+ QTest::qWait(300);
// Confirm items positioned correctly
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);
}
// confirm sanity when adding an item to cleared list
model.addItem("New", "1");
- QVERIFY(gridview->count() == 1);
+ QTRY_COMPARE(gridview->count(), 1);
QVERIFY(gridview->currentItem() != 0);
QVERIFY(gridview->currentIndex() == 0);
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++)
QSGItem *contentItem = gridview->contentItem();
QTRY_VERIFY(contentItem != 0);
- model.moveItem(1, 8);
+ QSGItem *currentItem = gridview->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));
+ gridview->setContentY(contentY);
+ model.moveItems(from, to, count);
- 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));
+ // wait for items to move
+ QTest::qWait(300);
- // 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) {
+ 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_VERIFY(item->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
- }
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
- gridview->setContentY(120);
-
- // move outside visible area
- model.moveItem(1, 25);
+ QTRY_COMPARE(item->x(), (i%3)*80.0);
+ QTRY_COMPARE(item->y(), (i/3)*60.0 + itemsOffsetAfterMove);
- // 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) {
- 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);
+ 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);
}
- // move from outside visible into visible
- model.moveItem(28, 8);
+ delete canvas;
+}
- // Confirm items positioned correctly and indexes correct
- for (int i = 6; i < model.count()-6 && i < itemCount+6; ++i) {
+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; // only 1 item was removed from the 1st row, so it doesn't move down
+
+ QTest::newRow("move 1 forwards, from non-visible -> visible (move first item)")
+ << 120.0 // // show 6-23
+ << 0 << 6 << 1
+ << 0.0; // only 1 item was removed from the 1st row, so it doesn't move down
+
+ 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, within visible items (to first index)")
+ << 0.0
+ << 10 << 0 << 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;
+
+ QTest::newRow("move 1 backwards, from visible -> non-visible")
+ << 120.0 // show 6-23
+ << 7 << 1 << 1
+ << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
+
+ QTest::newRow("move 1 backwards, from visible -> non-visible (move first item)")
+ << 120.0 // show 6-23
+ << 7 << 0 << 1
+ << 0.0; // only 1 item moved back, so items shift accordingly and first row doesn't move
+
+
+ QTest::newRow("move multiple forwards, within visible items")
+ << 0.0
+ << 0 << 5 << 3
+ << 60.0; // moved 3 items (i.e. 1 row) down
+
+ QTest::newRow("move multiple forwards, from non-visible -> visible")
+ << 120.0 // show 6-23
+ << 1 << 6 << 3
+ << 60.0; // 1st row (it's above visible area) disappears, 0 drops down 1 row, first visible item (6) stays where it is
+
+ QTest::newRow("move multiple forwards, from non-visible -> visible (move first item)")
+ << 120.0 // show 6-23
+ << 0 << 6 << 3
+ << 60.0; // top row moved and shifted to below 3rd row, all items should shift down by 1 row
+
+ QTest::newRow("move multiple forwards, from visible -> non-visible")
+ << 0.0
+ << 1 << 16 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple forwards, from visible -> non-visible (move first item)")
+ << 0.0
+ << 0 << 16 << 3
+ << 60.0;
+
+
+ QTest::newRow("move multiple backwards, within visible items")
+ << 0.0
+ << 4 << 1 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, from non-visible -> visible")
+ << 0.0
+ << 20 << 4 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, from non-visible -> visible (move last item)")
+ << 0.0
+ << 27 << 10 << 3
+ << 0.0;
+
+ QTest::newRow("move multiple backwards, from visible -> non-visible")
+ << 120.0 // show 6-23
+ << 16 << 1 << 3
+ << -60.0; // to minimize movement, items are added above visible area, all items move up by 1 row
+
+ QTest::newRow("move multiple backwards, from visible -> non-visible (move first item)")
+ << 120.0 // show 6-23
+ << 16 << 0 << 3
+ << -60.0; // 16,17,18 move to above item 0, all items move up by 1 row
+}
+
+struct ListChange {
+ enum { Inserted, Removed, Moved, SetCurrent } type;
+ int index;
+ int count;
+ int to; // Move
+
+ static ListChange insert(int index, int count = 1) { ListChange c = { Inserted, index, count, -1 }; return c; }
+ static ListChange remove(int index, int count = 1) { ListChange c = { Removed, index, count, -1 }; return c; }
+ static ListChange move(int index, int to, int count) { ListChange c = { Moved, index, count, to }; return c; }
+ static ListChange setCurrent(int index) { ListChange c = { SetCurrent, index, -1, -1 }; return c; }
+};
+Q_DECLARE_METATYPE(QList<ListChange>)
+
+void tst_QSGGridView::multipleChanges()
+{
+ QFETCH(int, startCount);
+ QFETCH(QList<ListChange>, changes);
+ QFETCH(int, newCount);
+ QFETCH(int, newCurrentIndex);
+
+ QSGView *canvas = createView();
+ canvas->show();
+
+ TestModel model;
+ for (int i = 0; i < startCount; i++)
+ model.addItem("Item" + QString::number(i), "");
+
+ QDeclarativeContext *ctxt = canvas->rootContext();
+ ctxt->setContextProperty("testModel", &model);
+ ctxt->setContextProperty("testRightToLeft", QVariant(false));
+ ctxt->setContextProperty("testTopToBottom", QVariant(false));
+
+ canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/gridview1.qml"));
+ qApp->processEvents();
+
+ QSGGridView *gridview = findItem<QSGGridView>(canvas->rootObject(), "grid");
+ QTRY_VERIFY(gridview != 0);
+
+ for (int i=0; i<changes.count(); i++) {
+ switch (changes[i].type) {
+ case ListChange::Inserted:
+ {
+ QList<QPair<QString, QString> > items;
+ for (int j=changes[i].index; j<changes[i].index + changes[i].count; ++j)
+ items << qMakePair(QString("new item " + j), QString::number(j));
+ model.insertItems(changes[i].index, items);
+ break;
+ }
+ case ListChange::Removed:
+ model.removeItems(changes[i].index, changes[i].count);
+ break;
+ case ListChange::Moved:
+ model.moveItems(changes[i].index, changes[i].to, changes[i].count);
+ break;
+ case ListChange::SetCurrent:
+ gridview->setCurrentIndex(changes[i].index);
+ break;
+ }
+ }
+
+ QTRY_COMPARE(gridview->count(), newCount);
+ QCOMPARE(gridview->count(), model.count());
+ QTRY_COMPARE(gridview->currentIndex(), newCurrentIndex);
+
+ QSGText *name;
+ QSGText *number;
+ QSGItem *contentItem = gridview->contentItem();
+ QTRY_VERIFY(contentItem != 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->x() == (i%3)*80);
- QTRY_VERIFY(item->y() == (i/3)*60);
+ QVERIFY2(item, QTest::toString(QString("Item %1 not found").arg(i)));
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));
}
delete canvas;
}
+void tst_QSGGridView::multipleChanges_data()
+{
+ QTest::addColumn<int>("startCount");
+ QTest::addColumn<QList<ListChange> >("changes");
+ QTest::addColumn<int>("newCount");
+ QTest::addColumn<int>("newCurrentIndex");
+
+ QList<ListChange> changes;
+
+ for (int i=1; i<30; i++)
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all but 1, first->last") << 30 << changes << 1 << 0;
+
+ changes << ListChange::remove(0);
+ QTest::newRow("remove all") << 30 << changes << 0 << -1;
+
+ changes.clear();
+ changes << ListChange::setCurrent(29);
+ for (int i=29; i>0; i--)
+ changes << ListChange::remove(i);
+ QTest::newRow("remove last (current) -> first") << 30 << changes << 1 << 0;
+
+ QTest::newRow("remove then insert at 0") << 10 << (QList<ListChange>()
+ << ListChange::remove(0, 1)
+ << ListChange::insert(0, 1)
+ ) << 10 << 1;
+
+ QTest::newRow("remove then insert at non-zero index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(2, 1)
+ << ListChange::insert(2, 1)
+ ) << 10 << 3;
+
+ QTest::newRow("remove current then insert below it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1, 3)
+ << ListChange::insert(2, 2)
+ ) << 9 << 1;
+
+ QTest::newRow("remove current index then move it down") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::remove(1, 3)
+ << ListChange::move(1, 5, 1)
+ ) << 7 << 5;
+
+ QTest::newRow("remove current index then move it up") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::remove(4, 3)
+ << ListChange::move(4, 1, 1)
+ ) << 7 << 1;
+
+
+ QTest::newRow("insert multiple times") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ ) << 12 << 10;
+
+ QTest::newRow("insert multiple times with current index changes") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 2)
+ << ListChange::insert(0, 4)
+ << ListChange::insert(0, 6)
+ << ListChange::setCurrent(3)
+ << ListChange::insert(3, 2)
+ ) << 14 << 5;
+
+ QTest::newRow("insert and remove all") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 30)
+ << ListChange::remove(0, 30)
+ ) << 0 << -1;
+
+ QTest::newRow("insert and remove current") << 30 << (QList<ListChange>()
+ << ListChange::insert(1)
+ << ListChange::setCurrent(1)
+ << ListChange::remove(1)
+ ) << 30 << 1;
+
+ QTest::newRow("insert before 0, then remove cross section of new and old items") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 10)
+ << ListChange::remove(5, 10)
+ ) << 10 << 5;
+
+ QTest::newRow("insert multiple, then move new items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 10, 3)
+ ) << 13 << 0;
+
+ QTest::newRow("insert multiple, then move new and some old items to end") << 10 << (QList<ListChange>()
+ << ListChange::insert(0, 3)
+ << ListChange::move(0, 8, 5)
+ ) << 13 << 11;
+
+ QTest::newRow("insert multiple at end, then move new and some old items to start") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(9)
+ << ListChange::insert(10, 3)
+ << ListChange::move(8, 0, 5)
+ ) << 13 << 1;
+
+
+ QTest::newRow("move back and forth to same index") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(1, 2, 2)
+ << ListChange::move(2, 1, 2)
+ ) << 10 << 1;
+
+ QTest::newRow("move forwards then back") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(2)
+ << ListChange::move(1, 2, 3)
+ << ListChange::move(3, 0, 5)
+ ) << 10 << 0;
+
+ QTest::newRow("move current, then remove it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::remove(0)
+ ) << 9 << 0;
+
+ QTest::newRow("move current, then insert before it") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 0, 1)
+ << ListChange::insert(0)
+ ) << 11 << 1;
+
+ QTest::newRow("move multiple, then remove them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(1)
+ << ListChange::move(5, 1, 3)
+ << ListChange::remove(1, 3)
+ ) << 7 << 1;
+
+ QTest::newRow("move multiple, then insert before them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(5)
+ << ListChange::move(5, 1, 3)
+ << ListChange::insert(1, 5)
+ ) << 15 << 6;
+
+ QTest::newRow("move multiple, then insert after them") << 10 << (QList<ListChange>()
+ << ListChange::setCurrent(3)
+ << ListChange::move(0, 1, 2)
+ << ListChange::insert(3, 5)
+ ) << 15 << 8;
+
+
+ QTest::newRow("clear current") << 0 << (QList<ListChange>()
+ << ListChange::insert(0, 5)
+ << ListChange::setCurrent(-1)
+ << ListChange::remove(0, 5)
+ << ListChange::insert(0, 5)
+ ) << 5 << -1;
+}
+
+
void tst_QSGGridView::swapWithFirstItem()
{
// QTBUG_9697
QTRY_COMPARE(gridview->contentY(), 0.0);
+
+ // footer should become visible if it is out of view, and then current index moves to the first row
+ canvas->rootObject()->setProperty("showFooter", true);
+ QTRY_VERIFY(gridview->footerItem());
+ gridview->setCurrentIndex(model.count()-3);
+ QTRY_VERIFY(gridview->footerItem()->y() > gridview->contentY() + gridview->height());
+ gridview->setCurrentIndex(model.count()-2);
+ QTRY_COMPARE(gridview->contentY() + gridview->height(), (60.0 * model.count()/3) + gridview->footerItem()->height());
+ canvas->rootObject()->setProperty("showFooter", false);
+
+ // header should become visible if it is out of view, and then current index moves to the last row
+ canvas->rootObject()->setProperty("showHeader", true);
+ QTRY_VERIFY(gridview->headerItem());
+ gridview->setCurrentIndex(3);
+ QTRY_VERIFY(gridview->headerItem()->y() + gridview->headerItem()->height() < gridview->contentY());
+ gridview->setCurrentIndex(1);
+ QTRY_COMPARE(gridview->contentY(), -gridview->headerItem()->height());
+ canvas->rootObject()->setProperty("showHeader", false);
+
+
// Test keys
qApp->setActiveWindow(canvas);
#ifdef Q_WS_X11
QTRY_VERIFY(canvas->hasFocus());
qApp->processEvents();
+ gridview->setCurrentIndex(0);
+
QTest::keyClick(canvas, Qt::Key_Down);
QCOMPARE(gridview->currentIndex(), 3);
QTest::keyClick(canvas, Qt::Key_Up);
QCOMPARE(gridview->currentIndex(), 0);
+ // hold down Key_Down
+ for (int i=0; i<(model.count() / 3) - 1; i++) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Down, Qt::NoModifier, "", true);
+ QTRY_COMPARE(gridview->currentIndex(), i*3 + 3);
+ }
+ QTest::keyRelease(canvas, Qt::Key_Down);
+ QTRY_COMPARE(gridview->currentIndex(), 57);
+ QTRY_COMPARE(gridview->contentY(), 880.0);
+
+ // hold down Key_Up
+ for (int i=(model.count() / 3) - 1; i > 0; i--) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Up, Qt::NoModifier, "", true);
+ QTRY_COMPARE(gridview->currentIndex(), i*3 - 3);
+ }
+ QTest::keyRelease(canvas, Qt::Key_Up);
+ QTRY_COMPARE(gridview->currentIndex(), 0);
+ QTRY_COMPARE(gridview->contentY(), 0.0);
+
+
gridview->setFlow(QSGGridView::TopToBottom);
qApp->setActiveWindow(canvas);
QTest::keyClick(canvas, Qt::Key_Up);
QCOMPARE(gridview->currentIndex(), 0);
+ // hold down Key_Right
+ for (int i=0; i<(model.count() / 5) - 1; i++) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Right, Qt::NoModifier, "", true);
+ QTRY_COMPARE(gridview->currentIndex(), i*5 + 5);
+ }
+ QTest::keyRelease(canvas, Qt::Key_Right);
+ QTRY_COMPARE(gridview->currentIndex(), 55);
+ QTRY_COMPARE(gridview->contentX(), 720.0);
+
+ // hold down Key_Left
+ for (int i=(model.count() / 5) - 1; i > 0; i--) {
+ QTest::simulateEvent(canvas, true, Qt::Key_Left, Qt::NoModifier, "", true);
+ QTRY_COMPARE(gridview->currentIndex(), i*5 - 5);
+ }
+ QTest::keyRelease(canvas, Qt::Key_Left);
+ QTRY_COMPARE(gridview->currentIndex(), 0);
+ QTRY_COMPARE(gridview->contentX(), 0.0);
+
// turn off auto highlight
gridview->setHighlightFollowsCurrentItem(false);
QDeclarativeListModel *alternateModel = canvas->rootObject()->findChild<QDeclarativeListModel*>("alternateModel");
QTRY_VERIFY(alternateModel);
- QVariant modelVariant = QVariant::fromValue(alternateModel);
+ QVariant modelVariant = QVariant::fromValue<QObject *>(alternateModel);
QSignalSpy modelSpy(gridView, SIGNAL(modelChanged()));
gridView->setModel(modelVariant);
QFETCH(QPointF, initialContentPos);
QFETCH(QPointF, changedContentPos);
QFETCH(QPointF, firstDelegatePos);
+ QFETCH(QPointF, resizeContentPos);
QSGView *canvas = createView();
canvas->show();
QVERIFY(item);
QCOMPARE(item->pos(), firstDelegatePos);
+ gridview->positionViewAtEnd();
+ footer->setHeight(10);
+ footer->setWidth(40);
+ QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
+
delete canvas;
}
QTest::addColumn<QPointF>("initialContentPos");
QTest::addColumn<QPointF>("changedContentPos");
QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
// footer1 = 100 x 30
- // footer2 = 100 x 20
+ // footer2 = 50 x 20
// cells = 80 * 60
// view width = 240
+ // view height = 320
// footer below items, bottom left
QTest::newRow("flow left to right") << QSGGridView::LeftToRight << Qt::LeftToRight
<< QPointF(0, 10 * 60) // 30 items = 10 rows
<< QPointF(0, 0)
<< QPointF(0, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(0, 10 * 60 - 320 + 10);
// footer below items, bottom right
QTest::newRow("flow left to right, layout right to left") << QSGGridView::LeftToRight << Qt::RightToLeft
<< QPointF((240 - 100) + 50, 10 * 60) // 50 = width diff between old and new footers
<< QPointF(0, 0)
<< QPointF(0, 0)
- << QPointF(240 - 80, 0);
+ << QPointF(240 - 80, 0)
+ << QPointF(0, 10 * 60 - 320 + 10);
// footer to right of items
QTest::newRow("flow top to bottom, layout left to right") << QSGGridView::TopToBottom << Qt::LeftToRight
<< QPointF(6 * 80, 0) // 30 items = 6 columns
<< QPointF(0, 0)
<< QPointF(0, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(6 * 80 - 240 + 40, 0);
// footer to left of items
QTest::newRow("flow top to bottom, layout right to left") << QSGGridView::TopToBottom << Qt::RightToLeft
<< QPointF(-(6 * 80) - 50, 0) // 50 = new footer width
<< QPointF(-240, 0)
<< QPointF(-240, 0) // unchanged, footer change doesn't change content pos
- << QPointF(-80, 0);
+ << QPointF(-80, 0)
+ << QPointF(-(6 * 80) - 40, 0);
}
void tst_QSGGridView::header()
QFETCH(QPointF, initialContentPos);
QFETCH(QPointF, changedContentPos);
QFETCH(QPointF, firstDelegatePos);
+ QFETCH(QPointF, resizeContentPos);
QSGView *canvas = createView();
QVERIFY(item);
QCOMPARE(item->pos(), firstDelegatePos);
+ header->setHeight(10);
+ header->setWidth(40);
+ QTRY_COMPARE(QPointF(gridview->contentX(), gridview->contentY()), resizeContentPos);
+
delete canvas;
}
QTest::addColumn<QPointF>("initialContentPos");
QTest::addColumn<QPointF>("changedContentPos");
QTest::addColumn<QPointF>("firstDelegatePos");
+ QTest::addColumn<QPointF>("resizeContentPos");
// header1 = 100 x 30
- // header2 = 100 x 20
+ // header2 = 50 x 20
// cells = 80 x 60
// view width = 240
<< QPointF(0, -20)
<< QPointF(0, -30)
<< QPointF(0, -20)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(0, -10);
// header above items, top right
QTest::newRow("flow left to right, layout right to left") << QSGGridView::LeftToRight << Qt::RightToLeft
<< QPointF((240 - 100) + 50, -20) // 50 = width diff between old and new headers
<< QPointF(0, -30)
<< QPointF(0, -20)
- << QPointF(160, 0);
+ << QPointF(160, 0)
+ << QPointF(0, -10);
// header to left of items
QTest::newRow("flow top to bottom, layout left to right") << QSGGridView::TopToBottom << Qt::LeftToRight
<< QPointF(-50, 0)
<< QPointF(-100, 0)
<< QPointF(-50, 0)
- << QPointF(0, 0);
+ << QPointF(0, 0)
+ << QPointF(-40, 0);
// header to right of items
QTest::newRow("flow top to bottom, layout right to left") << QSGGridView::TopToBottom << Qt::RightToLeft
<< QPointF(0, 0)
<< QPointF(-(240 - 100), 0)
<< QPointF(-(240 - 50), 0)
- << QPointF(-80, 0);
+ << QPointF(-80, 0)
+ << QPointF(-(240 - 40), 0);
}
void tst_QSGGridView::indexAt()
items << qMakePair(QString("value %1").arg(i), QString::number(i));
model.addItems(items);
+ QTRY_COMPARE(model.count(), qobject_cast<QSGGridView*>(canvas->rootObject())->count());
qApp->processEvents();
QVariantList result = object->property("addedDelegates").toList();
- QCOMPARE(result.count(), items.count());
+ QTRY_COMPARE(result.count(), items.count());
for (int i=0; i<items.count(); i++)
QCOMPARE(result[i].toString(), items[i].first);
canvas->setSource(QUrl::fromLocalFile(SRCDIR "/data/attachedSignals.qml"));
QObject *object = canvas->rootObject();
- qApp->processEvents();
-
model.removeItems(indexToRemove, removeCount);
- qApp->processEvents();
+ QTRY_COMPARE(model.count(), qobject_cast<QSGGridView*>(canvas->rootObject())->count());
QCOMPARE(object->property("removedDelegateCount"), QVariant(removeCount));
delete canvas;
QTEST_MAIN(tst_QSGGridView)
#include "tst_qsggridview.moc"
+