aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2018-05-22 14:04:53 +0200
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2018-05-25 11:21:59 +0000
commitcf9c07539c3e6a30f5f73fd1b2d5feebf03d716a (patch)
tree06e15e9018afafbc1dd851ebb81f9499f5a1653f
parent444e5c1c4a087a080914e1cedd3c6ab00875ff94 (diff)
TableView: check if the model can produce items before loading
If you assign a non-empty model, the model can still return a count of zero if something else is amiss, like the delegate being null. So we need to do en extra check for this before we load the first top-left item, otherwise we'll hit an assert later in the loading process. Change-Id: I747868faf7955b8784b2957505ae03e5b1aa0b45 Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
-rw-r--r--src/quick/items/qquicktableview.cpp8
-rw-r--r--tests/auto/quick/qquicktableview/data/plaintableview.qml1
-rw-r--r--tests/auto/quick/qquicktableview/tst_qquicktableview.cpp44
3 files changed, 50 insertions, 3 deletions
diff --git a/src/quick/items/qquicktableview.cpp b/src/quick/items/qquicktableview.cpp
index 5bc47a2b07..b3802b7694 100644
--- a/src/quick/items/qquicktableview.cpp
+++ b/src/quick/items/qquicktableview.cpp
@@ -965,6 +965,9 @@ void QQuickTableViewPrivate::loadInitialTopLeftItem()
if (tableSize.isEmpty())
return;
+ if (model->count() == 0)
+ return;
+
// Load top-left item. After loaded, loadItemsInsideRect() will take
// care of filling out the rest of the table.
loadRequest.begin(QPoint(0, 0), QQmlIncubator::AsynchronousIfNested);
@@ -1007,8 +1010,7 @@ void QQuickTableViewPrivate::loadAndUnloadVisibleEdges()
if (loadedItems.isEmpty()) {
// We need at least the top-left item to be loaded before we can
// start loading edges around it. Not having a top-left item at
- // this point means that the model is empty (or row and and column
- // is 0) since we have no active load request.
+ // this point means that the model is empty (or no delegate).
return;
}
@@ -1115,7 +1117,7 @@ void QQuickTableViewPrivate::updatePolish()
endRebuildTable();
if (loadedItems.isEmpty()) {
- qCDebug(lcTableViewDelegateLifecycle()) << "no items loaded, meaning empty model or row/column == 0";
+ qCDebug(lcTableViewDelegateLifecycle()) << "no items loaded, meaning empty model or no delegate";
return;
}
diff --git a/tests/auto/quick/qquicktableview/data/plaintableview.qml b/tests/auto/quick/qquicktableview/data/plaintableview.qml
index f4457006e6..a073941faa 100644
--- a/tests/auto/quick/qquicktableview/data/plaintableview.qml
+++ b/tests/auto/quick/qquicktableview/data/plaintableview.qml
@@ -48,6 +48,7 @@ Item {
property alias tableView: tableView
property real delegateWidth: 100
property real delegateHeight: 50
+ property Component delegate: tableViewDelegate
TableView {
id: tableView
diff --git a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
index 33437b6eac..16b3acab99 100644
--- a/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
+++ b/tests/auto/quick/qquicktableview/tst_qquicktableview.cpp
@@ -86,6 +86,7 @@ private slots:
void emptyModel_data();
void emptyModel();
void checkZeroSizedDelegate();
+ void noDelegate();
void countDelegateItems_data();
void countDelegateItems();
void checkLayoutOfEqualSizedDelegateItems_data();
@@ -208,6 +209,49 @@ void tst_QQuickTableView::checkZeroSizedDelegate()
}
}
+void tst_QQuickTableView::noDelegate()
+{
+ // Check that you can skip setting a delegate without
+ // it causing any problems (like crashing or asserting).
+ // And then set a delegate, and do a quick check that the
+ // view gets populated as expected.
+ LOAD_TABLEVIEW("plaintableview.qml");
+
+ const int rows = 5;
+ const int columns = 5;
+ auto model = TestModelAsVariant(columns, rows);
+ tableView->setModel(model);
+
+ // Start with no delegate, and check
+ // that we end up with no items in the table.
+ tableView->setDelegate(nullptr);
+
+ WAIT_UNTIL_POLISHED;
+
+ auto items = tableViewPrivate->loadedItems;
+ QVERIFY(items.isEmpty());
+
+ // Set a delegate, and check that we end
+ // up with the expected number of items.
+ auto delegate = view->rootObject()->property("delegate").value<QQmlComponent *>();
+ QVERIFY(delegate);
+ tableView->setDelegate(delegate);
+
+ WAIT_UNTIL_POLISHED;
+
+ items = tableViewPrivate->loadedItems;
+ QCOMPARE(items.count(), rows * columns);
+
+ // And then unset the delegate again, and check
+ // that we end up with no items.
+ tableView->setDelegate(nullptr);
+
+ WAIT_UNTIL_POLISHED;
+
+ items = tableViewPrivate->loadedItems;
+ QVERIFY(items.isEmpty());
+}
+
void tst_QQuickTableView::countDelegateItems_data()
{
QTest::addColumn<QVariant>("model");