1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtTest/QtTest>
30#include <qabstractitemmodel.h>
31#include <qcoreapplication.h>
32#include <qmap.h>
33#include <qstringlistmodel.h>
34#include <qstringlist.h>
35#include "qmodellistener.h"
36#include <qstringlistmodel.h>
37
38#include <algorithm>
39
40void QModelListener::rowsAboutToBeRemovedOrInserted(const QModelIndex & parent, int start, int end )
41{
42 for (int i = 0; start + i <= end; i++) {
43 QModelIndex mIndex = m_pModel->index(row: start + i, column: 0, parent);
44 QVariant var = m_pModel->data(index: mIndex, role: Qt::DisplayRole);
45 QString str = var.toString();
46
47 QCOMPARE(str, m_pAboutToStringlist->at(i));
48 }
49}
50
51void QModelListener::rowsRemovedOrInserted(const QModelIndex & parent, int , int)
52{
53 // Can the rows that *are* removed be iterated now ?
54
55 // What about rowsAboutToBeInserted - what will the indices be?
56 // will insertRow() overwrite existing, or insert (and conseq. grow the model?)
57 // What will the item then contain? empty data?
58
59 // RemoveColumn. Does that also fire the rowsRemoved-family signals?
60
61 for (int i = 0; i < m_pExpectedStringlist->size(); i++) {
62 QModelIndex mIndex = m_pModel->index(row: i, column: 0, parent);
63 QVariant var = m_pModel->data(index: mIndex, role: Qt::DisplayRole);
64 QString str = var.toString();
65
66 QCOMPARE(str, m_pExpectedStringlist->at(i));
67 }
68}
69
70class tst_QStringListModel : public QObject
71{
72 Q_OBJECT
73
74private slots:
75 void rowsAboutToBeRemoved_rowsRemoved();
76 void rowsAboutToBeRemoved_rowsRemoved_data();
77
78 void rowsAboutToBeInserted_rowsInserted();
79 void rowsAboutToBeInserted_rowsInserted_data();
80
81 void setData_emits_both_roles_data();
82 void setData_emits_both_roles();
83
84 void setData_emits_on_change_only();
85
86 void supportedDragDropActions();
87
88 void moveRows_data();
89 void moveRows();
90 void moveRowsInvalid_data();
91 void moveRowsInvalid();
92
93 void itemData();
94 void setItemData();
95};
96
97void tst_QStringListModel::moveRowsInvalid_data()
98{
99 QTest::addColumn<QStringListModel*>(name: "baseModel");
100 QTest::addColumn<QModelIndex>(name: "startParent");
101 QTest::addColumn<int>(name: "startRow");
102 QTest::addColumn<int>(name: "count");
103 QTest::addColumn<QModelIndex>(name: "destinationParent");
104 QTest::addColumn<int>(name: "destination");
105
106 const auto createModel = [this]() {
107 return new QStringListModel(QStringList{"A", "B", "C", "D", "E", "F"}, this);
108 };
109 constexpr int rowCount = 6;
110
111 QTest::addRow(format: "destination_equal_source") << createModel() << QModelIndex() << 0 << 1 << QModelIndex() << 0;
112 QTest::addRow(format: "count_equal_0") << createModel() << QModelIndex() << 0 << 0 << QModelIndex() << 2;
113 QStringListModel *tempModel = createModel();
114 QTest::addRow(format: "move_child") << tempModel << tempModel->index(row: 0, column: 0) << 0 << 1 << QModelIndex() << 2;
115 tempModel = createModel();
116 QTest::addRow(format: "move_to_child") << tempModel << QModelIndex() << 0 << 1 << tempModel->index(row: 0, column: 0) << 2;
117 QTest::addRow(format: "negative_count") << createModel() << QModelIndex() << 0 << -1 << QModelIndex() << 2;
118 QTest::addRow(format: "negative_source_row") << createModel() << QModelIndex() << -1 << 1 << QModelIndex() << 2;
119 QTest::addRow(format: "negative_destination_row") << createModel() << QModelIndex() << 0 << 1 << QModelIndex() << -1;
120 QTest::addRow(format: "source_row_equal_rowCount") << createModel() << QModelIndex() << rowCount << 1 << QModelIndex() << 1;
121 QTest::addRow(format: "source_row_equal_destination_row") << createModel() << QModelIndex() << 2 << 1 << QModelIndex() << 2;
122 QTest::addRow(format: "source_row_equal_destination_row_plus_1") << createModel() << QModelIndex() << 2 << 1 << QModelIndex() << 3;
123 QTest::addRow(format: "destination_row_greater_rowCount") << createModel() << QModelIndex() << 0 << 1 << QModelIndex() << rowCount + 1;
124 QTest::addRow(format: "move_row_within_source_range") << createModel() << QModelIndex() << 0 << 3 << QModelIndex() << 2;
125}
126
127void tst_QStringListModel::moveRowsInvalid()
128{
129 QFETCH(QStringListModel* const, baseModel);
130 QFETCH(const QModelIndex, startParent);
131 QFETCH(const int, startRow);
132 QFETCH(const int, count);
133 QFETCH(const QModelIndex, destinationParent);
134 QFETCH(const int, destination);
135
136 QSignalSpy rowMovedSpy(baseModel, &QAbstractItemModel::rowsMoved);
137 QSignalSpy rowAboutMovedSpy(baseModel, &QAbstractItemModel::rowsAboutToBeMoved);
138 QVERIFY(rowMovedSpy.isValid());
139 QVERIFY(rowAboutMovedSpy.isValid());
140 QVERIFY(!baseModel->moveRows(startParent, startRow, count, destinationParent, destination));
141 QCOMPARE(rowMovedSpy.size(), 0);
142 QCOMPARE(rowAboutMovedSpy.size(), 0);
143 delete baseModel;
144}
145
146void tst_QStringListModel::moveRows_data()
147{
148 QTest::addColumn<int>(name: "startRow");
149 QTest::addColumn<int>(name: "count");
150 QTest::addColumn<int>(name: "destination");
151 QTest::addColumn<QStringList>(name: "expected");
152
153 QTest::newRow(dataTag: "1_Item_from_top_to_middle") << 0 << 1 << 3 << QStringList{"B", "C", "A", "D", "E", "F"};
154 QTest::newRow(dataTag: "1_Item_from_top_to_bottom") << 0 << 1 << 6 << QStringList{"B", "C", "D", "E", "F", "A"};
155 QTest::newRow(dataTag: "1_Item_from_middle_to_top") << 2 << 1 << 0 << QStringList{"C", "A", "B", "D", "E", "F"};
156 QTest::newRow(dataTag: "1_Item_from_bottom_to_middle") << 5 << 1 << 2 << QStringList{"A", "B", "F", "C", "D", "E"};
157 QTest::newRow(dataTag: "1_Item_from_bottom to_top") << 5 << 1 << 0 << QStringList{"F", "A", "B", "C", "D", "E"};
158 QTest::newRow(dataTag: "1_Item_from_middle_to_bottom") << 2 << 1 << 6 << QStringList{"A", "B", "D", "E", "F", "C"};
159 QTest::newRow(dataTag: "1_Item_from_middle_to_middle_before") << 2 << 1 << 1 << QStringList{"A", "C", "B", "D", "E", "F"};
160 QTest::newRow(dataTag: "1_Item_from_middle_to_middle_after") << 2 << 1 << 4 << QStringList{"A", "B", "D", "C", "E", "F"};
161
162 QTest::newRow(dataTag: "2_Items_from_top_to_middle") << 0 << 2 << 3 << QStringList{"C", "A", "B", "D", "E", "F"};
163 QTest::newRow(dataTag: "2_Items_from_top_to_bottom") << 0 << 2 << 6 << QStringList{"C", "D", "E", "F", "A", "B"};
164 QTest::newRow(dataTag: "2_Items_from_middle_to_top") << 2 << 2 << 0 << QStringList{"C", "D", "A", "B", "E", "F"};
165 QTest::newRow(dataTag: "2_Items_from_bottom_to_middle") << 4 << 2 << 2 << QStringList{"A", "B", "E", "F", "C", "D"};
166 QTest::newRow(dataTag: "2_Items_from_bottom_to_top") << 4 << 2 << 0 << QStringList{"E", "F", "A", "B", "C", "D"};
167 QTest::newRow(dataTag: "2_Items_from_middle_to_bottom") << 2 << 2 << 6 << QStringList{"A", "B", "E", "F", "C", "D"};
168 QTest::newRow(dataTag: "2_Items_from_middle_to_middle_before") << 3 << 2 << 1 << QStringList{"A", "D", "E", "B", "C", "F"};
169 QTest::newRow(dataTag: "2_Items_from_middle_to_middle_after") << 1 << 2 << 5 << QStringList{"A", "D", "E", "B", "C", "F"};
170}
171
172void tst_QStringListModel::moveRows()
173{
174 QFETCH(const int, startRow);
175 QFETCH(const int, count);
176 QFETCH(const int, destination);
177 QFETCH(const QStringList, expected);
178 QStringListModel baseModel(QStringList{"A", "B", "C", "D", "E", "F"});
179 QSignalSpy rowMovedSpy(&baseModel, &QAbstractItemModel::rowsMoved);
180 QSignalSpy rowAboutMovedSpy(&baseModel, &QAbstractItemModel::rowsAboutToBeMoved);
181 QVERIFY(baseModel.moveRows(QModelIndex(), startRow, count, QModelIndex(), destination));
182 QCOMPARE(baseModel.stringList(), expected);
183 QCOMPARE(rowMovedSpy.size(), 1);
184 QCOMPARE(rowAboutMovedSpy.size(), 1);
185 for (const QList<QVariant> &signalArgs : {rowMovedSpy.first(), rowAboutMovedSpy.first()}){
186 QVERIFY(!signalArgs.at(0).value<QModelIndex>().isValid());
187 QCOMPARE(signalArgs.at(1).toInt(), startRow);
188 QCOMPARE(signalArgs.at(2).toInt(), startRow + count - 1);
189 QVERIFY(!signalArgs.at(3).value<QModelIndex>().isValid());
190 QCOMPARE(signalArgs.at(4).toInt(), destination);
191 }
192}
193
194void tst_QStringListModel::rowsAboutToBeRemoved_rowsRemoved_data()
195{
196 QTest::addColumn<QStringList>(name: "input");
197 QTest::addColumn<int>(name: "row");
198 QTest::addColumn<int>(name: "count");
199 QTest::addColumn<QStringList>(name: "aboutto");
200 QTest::addColumn<QStringList>(name: "res");
201
202 QStringList strings0; strings0 << "One" << "Two" << "Three" << "Four" << "Five";
203 QStringList aboutto0; aboutto0 << "Two" << "Three";
204 QStringList res0; res0 << "One" << "Four" << "Five";
205 QTest::newRow( dataTag: "data0" ) << strings0 << 1 << 2 << aboutto0 << res0;
206
207 QStringList strings1; strings1 << "One" << "Two" << "Three" << "Four" << "Five";
208 QStringList aboutto1; aboutto1 << "One" << "Two";
209 QStringList res1; res1 << "Three" << "Four" << "Five";
210 QTest::newRow( dataTag: "data1" ) << strings1 << 0 << 2 << aboutto1 << res1;
211
212 QStringList strings2; strings2 << "One" << "Two" << "Three" << "Four" << "Five";
213 QStringList aboutto2; aboutto2 << "Four" << "Five";
214 QStringList res2; res2 << "One" << "Two" << "Three";
215 QTest::newRow( dataTag: "data2" ) << strings2 << 3 << 2 << aboutto2 << res2;
216
217 QStringList strings3; strings3 << "One" << "Two" << "Three" << "Four" << "Five";
218 QStringList aboutto3; aboutto3 << "One" << "Two" << "Three" << "Four" << "Five";
219 QStringList res3;
220 QTest::newRow( dataTag: "data3" ) << strings3 << 0 << 5 << aboutto3 << res3;
221
222 /*
223 * Keep this, template to add more data
224 QStringList strings2; strings2 << "One" << "Two" << "Three" << "Four" << "Five";
225 QStringList aboutto2; aboutto2 << "One" << "Two" << "Three" << "Four" << "Five";
226 QStringList res2; res2 << "One" << "Two" << "Three" << "Four" << "Five";
227 QTest::newRow( "data2" ) << strings2 << 0 << 5 << aboutto2 << res2;
228*/
229
230}
231
232void tst_QStringListModel::rowsAboutToBeRemoved_rowsRemoved()
233{
234 QFETCH(QStringList, input);
235 QFETCH(int, row);
236 QFETCH(int, count);
237 QFETCH(QStringList, aboutto);
238 QFETCH(QStringList, res);
239
240 QStringListModel model(input);
241 QModelListener listener(&aboutto, &res, &model);
242 connect(sender: &model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
243 receiver: &listener, SLOT(rowsAboutToBeRemovedOrInserted(QModelIndex,int,int)));
244
245 connect(sender: &model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
246 receiver: &listener, SLOT(rowsRemovedOrInserted(QModelIndex,int,int)));
247
248 model.removeRows(row, count);
249 // At this point, control goes to our connected slots inn this order:
250 // 1. rowsAboutToBeRemovedOrInserted
251 // 2. rowsRemovedOrInserted
252 // Control returns here
253}
254
255void tst_QStringListModel::rowsAboutToBeInserted_rowsInserted_data()
256{
257 QTest::addColumn<QStringList>(name: "input");
258 QTest::addColumn<int>(name: "row");
259 QTest::addColumn<int>(name: "count");
260 QTest::addColumn<QStringList>(name: "aboutto");
261 QTest::addColumn<QStringList>(name: "res");
262
263 QStringList strings0; strings0 << "One" << "Two" << "Three" << "Four" << "Five";
264 QStringList aboutto0; aboutto0 << "Two" << "Three";
265 QStringList res0; res0 << "One" << "" << "" << "Two" << "Three" << "Four" << "Five";
266 QTest::newRow( dataTag: "data0" ) << strings0 << 1 << 2 << aboutto0 << res0;
267
268 QStringList strings1; strings1 << "One" << "Two" << "Three" << "Four" << "Five";
269 QStringList aboutto1; aboutto1 << "One" << "Two";
270 QStringList res1; res1 << "" << "" << "One" << "Two" << "Three" << "Four" << "Five";
271 QTest::newRow( dataTag: "data1" ) << strings1 << 0 << 2 << aboutto1 << res1;
272
273 QStringList strings2; strings2 << "One" << "Two" << "Three" << "Four" << "Five";
274 QStringList aboutto2; aboutto2 << "Four" << "Five";
275 QStringList res2; res2 << "One" << "Two" << "Three" << "" << "" << "Four" << "Five";
276 QTest::newRow( dataTag: "data2" ) << strings2 << 3 << 2 << aboutto2 << res2;
277
278 QStringList strings3; strings3 << "One" << "Two" << "Three" << "Four" << "Five";
279 QStringList aboutto3; aboutto3 << "One" << "Two" << "Three" << "Four" << "Five";
280 QStringList res3; res3 << "" << "" << "" << "" << "" << "One" << "Two" << "Three" << "Four" << "Five";
281 QTest::newRow( dataTag: "data3" ) << strings3 << 0 << 5 << aboutto3 << res3;
282
283 /*
284 * Keep this, template to add more data
285 QStringList strings2; strings2 << "One" << "Two" << "Three" << "Four" << "Five";
286 QStringList aboutto2; aboutto2 << "One" << "Two" << "Three" << "Four" << "Five";
287 QStringList res2; res2 << "One" << "Two" << "Three" << "Four" << "Five";
288 QTest::newRow( "data2" ) << strings2 << 0 << 5 << aboutto2 << res2;
289*/
290
291}
292
293void tst_QStringListModel::rowsAboutToBeInserted_rowsInserted()
294{
295 QFETCH(QStringList, input);
296 QFETCH(int, row);
297 QFETCH(int, count);
298 QFETCH(QStringList, aboutto);
299 QFETCH(QStringList, res);
300
301 QStringListModel model(input);
302 QModelListener listener(&aboutto, &res, &model);
303 connect(sender: &model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
304 receiver: &listener, SLOT(rowsAboutToBeRemovedOrInserted(QModelIndex,int,int)));
305
306 connect(sender: &model, SIGNAL(rowsInserted(QModelIndex,int,int)),
307 receiver: &listener, SLOT(rowsRemovedOrInserted(QModelIndex,int,int)));
308
309 model.insertRows(row, count);
310 // At this point, control goes to our connected slots inn this order:
311 // 1. rowsAboutToBeRemovedOrInserted
312 // 2. rowsRemovedOrInserted
313 // Control returns here
314}
315
316void tst_QStringListModel::setData_emits_both_roles_data()
317{
318 QTest::addColumn<int>(name: "row");
319 QTest::addColumn<QString>(name: "data");
320 QTest::addColumn<int>(name: "role");
321
322#define ROW(row, string, role) \
323 QTest::newRow(#row " -> " string) << row << QString(string) << int(Qt::role)
324 ROW(0, "1", EditRole);
325 ROW(1, "2", DisplayRole);
326#undef ROW
327}
328
329template <class C>
330C sorted(C c)
331{
332 std::sort(c.begin(), c.end());
333 return std::move(c);
334}
335
336void tst_QStringListModel::setData_emits_both_roles()
337{
338 QFETCH(int, row);
339 QFETCH(QString, data);
340 QFETCH(int, role);
341
342 QStringListModel model(QStringList() << "one" << "two");
343 QVector<int> expected;
344 expected.reserve(asize: 2);
345 expected.append(t: Qt::DisplayRole);
346 expected.append(t: Qt::EditRole);
347
348 QSignalSpy spy(&model, &QAbstractItemModel::dataChanged);
349 QVERIFY(spy.isValid());
350 model.setData(index: model.index(row, column: 0), value: data, role);
351 QCOMPARE(spy.size(), 1);
352 QCOMPARE(sorted(spy.at(0).at(2).value<QVector<int> >()),
353 expected);
354}
355
356void tst_QStringListModel::itemData()
357{
358 QStringListModel testModel{ QStringList {
359 QStringLiteral("One"),
360 QStringLiteral("Two"),
361 QStringLiteral("Three"),
362 QStringLiteral("Four"),
363 QStringLiteral("Five")
364 }};
365 QMap<int, QVariant> compareMap;
366 QCOMPARE(testModel.itemData(QModelIndex()), compareMap);
367 compareMap.insert(akey: Qt::DisplayRole, QStringLiteral("Two"));
368 compareMap.insert(akey: Qt::EditRole, QStringLiteral("Two"));
369 QCOMPARE(testModel.itemData(testModel.index(1, 0)), compareMap);
370}
371
372void tst_QStringListModel::setItemData()
373{
374 QStringListModel testModel{ QStringList {
375 QStringLiteral("One"),
376 QStringLiteral("Two"),
377 QStringLiteral("Three"),
378 QStringLiteral("Four"),
379 QStringLiteral("Five")
380 }};
381 QSignalSpy dataChangedSpy(&testModel, &QAbstractItemModel::dataChanged);
382 QModelIndex changeIndex = testModel.index(row: 1, column: 0);
383 const QVector<int> changeRoles{Qt::DisplayRole, Qt::EditRole};
384 const QString changedString("Changed");
385 QMap<int, QVariant> newItemData{std::make_pair<int>(x: Qt::DisplayRole, y: changedString)};
386 // invalid index does nothing and returns false
387 QVERIFY(!testModel.setItemData(QModelIndex(), newItemData));
388 // valid data is set, return value is true and dataChanged is emitted once
389 QVERIFY(testModel.setItemData(changeIndex, newItemData));
390 QCOMPARE(changeIndex.data(Qt::DisplayRole).toString(), changedString);
391 QCOMPARE(changeIndex.data(Qt::EditRole).toString(), changedString);
392 QCOMPARE(dataChangedSpy.size(), 1);
393 QVariantList dataChangedArguments = dataChangedSpy.takeFirst();
394 QCOMPARE(dataChangedArguments.at(0).value<QModelIndex>(), changeIndex);
395 QCOMPARE(dataChangedArguments.at(1).value<QModelIndex>(), changeIndex);
396 QCOMPARE(dataChangedArguments.at(2).value<QVector<int> >(), changeRoles);
397 // Unsupported roles do nothing return false
398 newItemData.clear();
399 newItemData.insert(akey: Qt::UserRole, avalue: changedString);
400 QVERIFY(!testModel.setItemData(changeIndex, newItemData));
401 QCOMPARE(dataChangedSpy.size(), 0);
402 // If some but not all the roles are supported it returns false and does nothing
403 newItemData.insert(akey: Qt::EditRole, avalue: changedString);
404 changeIndex = testModel.index(row: 2, column: 0);
405 QVERIFY(!testModel.setItemData(changeIndex, newItemData));
406 QCOMPARE(changeIndex.data(Qt::DisplayRole).toString(), QStringLiteral("Three"));
407 QCOMPARE(changeIndex.data(Qt::EditRole).toString(), QStringLiteral("Three"));
408 QCOMPARE(dataChangedSpy.size(), 0);
409 // Qt::EditRole and Qt::DisplayRole are both set, Qt::EditRole takes precedence
410 newItemData.clear();
411 newItemData.insert(akey: Qt::EditRole, avalue: changedString);
412 newItemData.insert(akey: Qt::DisplayRole, QStringLiteral("Ignored"));
413 changeIndex = testModel.index(row: 3, column: 0);
414 QVERIFY(testModel.setItemData(changeIndex, newItemData));
415 QCOMPARE(changeIndex.data(Qt::DisplayRole).toString(), changedString);
416 QCOMPARE(changeIndex.data(Qt::EditRole).toString(), changedString);
417 QCOMPARE(dataChangedSpy.size(), 1);
418 dataChangedArguments = dataChangedSpy.takeFirst();
419 QCOMPARE(dataChangedArguments.at(0).value<QModelIndex>(), changeIndex);
420 QCOMPARE(dataChangedArguments.at(1).value<QModelIndex>(), changeIndex);
421 QCOMPARE(dataChangedArguments.at(2).value<QVector<int> >(), changeRoles);
422}
423
424void tst_QStringListModel::setData_emits_on_change_only()
425{
426 QStringListModel model(QStringList{QStringLiteral("one"), QStringLiteral("two")});
427 QSignalSpy dataChangedSpy(&model, &QAbstractItemModel::dataChanged);
428 QVERIFY(dataChangedSpy.isValid());
429 const QModelIndex modelIdx = model.index(row: 0, column: 0);
430 const QString newStringData = QStringLiteral("test");
431 QVERIFY(model.setData(modelIdx, newStringData));
432 QCOMPARE(dataChangedSpy.count(), 1);
433 const QList<QVariant> spyList = dataChangedSpy.takeFirst();
434 QCOMPARE(spyList.at(0).value<QModelIndex>(), modelIdx);
435 QCOMPARE(spyList.at(1).value<QModelIndex>(), modelIdx);
436 const QVector<int> expectedRoles{Qt::DisplayRole, Qt::EditRole};
437 QCOMPARE(spyList.at(2).value<QVector<int> >(), expectedRoles);
438 QVERIFY(model.setData(modelIdx, newStringData));
439 QVERIFY(dataChangedSpy.isEmpty());
440}
441
442void tst_QStringListModel::supportedDragDropActions()
443{
444 QStringListModel model;
445 QCOMPARE(model.supportedDragActions(), Qt::CopyAction | Qt::MoveAction);
446 QCOMPARE(model.supportedDropActions(), Qt::CopyAction | Qt::MoveAction);
447}
448
449QTEST_MAIN(tst_QStringListModel)
450#include "tst_qstringlistmodel.moc"
451

source code of qtbase/tests/auto/corelib/itemmodels/qstringlistmodel/tst_qstringlistmodel.cpp