|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the test suite of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 |
|
43 #include <QtTest/QtTest> |
|
44 #include <QtCore/QtCore> |
|
45 |
|
46 #include <QtGui/QSortFilterProxyModel> |
|
47 |
|
48 //TESTED_CLASS=QAbstractListModel QAbstractTableModel |
|
49 //TESTED_FILES= |
|
50 |
|
51 #include "dynamictreemodel.h" |
|
52 |
|
53 Q_DECLARE_METATYPE(QModelIndex) |
|
54 |
|
55 /*! |
|
56 Note that this doesn't test models, but any functionality that QAbstractItemModel shoudl provide |
|
57 */ |
|
58 class tst_QAbstractItemModel : public QObject |
|
59 { |
|
60 Q_OBJECT |
|
61 |
|
62 public: |
|
63 tst_QAbstractItemModel(); |
|
64 virtual ~tst_QAbstractItemModel(); |
|
65 |
|
66 public slots: |
|
67 void initTestCase(); |
|
68 void cleanupTestCase(); |
|
69 void init(); |
|
70 void cleanup(); |
|
71 |
|
72 private slots: |
|
73 void index(); |
|
74 void parent(); |
|
75 void hasChildren(); |
|
76 void _data(); |
|
77 void headerData(); |
|
78 void itemData(); |
|
79 void itemFlags(); |
|
80 void match(); |
|
81 void dropMimeData_data(); |
|
82 void dropMimeData(); |
|
83 void changePersistentIndex(); |
|
84 void movePersistentIndex(); |
|
85 |
|
86 void insertRows(); |
|
87 void insertColumns(); |
|
88 void removeRows(); |
|
89 void removeColumns(); |
|
90 |
|
91 void reset(); |
|
92 |
|
93 void complexChangesWithPersistent(); |
|
94 |
|
95 void testMoveSameParentUp_data(); |
|
96 void testMoveSameParentUp(); |
|
97 |
|
98 void testMoveSameParentDown_data(); |
|
99 void testMoveSameParentDown(); |
|
100 |
|
101 void testMoveToGrandParent_data(); |
|
102 void testMoveToGrandParent(); |
|
103 |
|
104 void testMoveToSibling_data(); |
|
105 void testMoveToSibling(); |
|
106 |
|
107 void testMoveToUncle_data(); |
|
108 void testMoveToUncle(); |
|
109 |
|
110 void testMoveToDescendants(); |
|
111 |
|
112 void testMoveWithinOwnRange_data(); |
|
113 void testMoveWithinOwnRange(); |
|
114 |
|
115 void testReset(); |
|
116 |
|
117 |
|
118 private: |
|
119 DynamicTreeModel *m_model; |
|
120 |
|
121 }; |
|
122 |
|
123 /*! |
|
124 Test model that impliments the pure vitual functions and anything else that is |
|
125 needed. |
|
126 |
|
127 It is a table implimented as a vector of vectors of strings. |
|
128 */ |
|
129 class QtTestModel: public QAbstractItemModel |
|
130 { |
|
131 public: |
|
132 QtTestModel(int rows, int columns, QObject *parent = 0); |
|
133 QtTestModel(const QVector<QVector<QString> > tbl, QObject *parent = 0); |
|
134 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; |
|
135 QModelIndex parent(const QModelIndex &) const; |
|
136 int rowCount(const QModelIndex &parent) const; |
|
137 int columnCount(const QModelIndex &parent) const; |
|
138 bool hasChildren(const QModelIndex &) const; |
|
139 QVariant data(const QModelIndex &idx, int) const; |
|
140 bool setData(const QModelIndex &idx, const QVariant &value, int); |
|
141 bool insertRows(int row, int count, const QModelIndex &parent= QModelIndex()); |
|
142 bool insertColumns(int column, int count, const QModelIndex &parent= QModelIndex()); |
|
143 void setPersistent(const QModelIndex &from, const QModelIndex &to); |
|
144 bool removeRows ( int row, int count, const QModelIndex & parent = QModelIndex() ); |
|
145 bool removeColumns( int column, int count, const QModelIndex & parent = QModelIndex()); |
|
146 void reset(); |
|
147 |
|
148 int cCount, rCount; |
|
149 mutable bool wrongIndex; |
|
150 QVector<QVector<QString> > table; |
|
151 }; |
|
152 |
|
153 QtTestModel::QtTestModel(int rows, int columns, QObject *parent) |
|
154 : QAbstractItemModel(parent), cCount(columns), rCount(rows), wrongIndex(false) { |
|
155 |
|
156 table.resize(rows); |
|
157 for (int r = 0; r < rows; ++r) { |
|
158 table[r].resize(columns); |
|
159 for (int c = 0; c < columns; ++c) |
|
160 table[r][c] = QString("%1/%2").arg(r).arg(c); |
|
161 } |
|
162 } |
|
163 |
|
164 QtTestModel::QtTestModel(const QVector<QVector<QString> > tbl, QObject *parent) |
|
165 : QAbstractItemModel(parent), wrongIndex(false) { |
|
166 table = tbl; |
|
167 rCount = tbl.count(); |
|
168 cCount = tbl.at(0).count(); |
|
169 } |
|
170 |
|
171 QModelIndex QtTestModel::index(int row, int column, const QModelIndex &parent) const |
|
172 { return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex(); } |
|
173 |
|
174 QModelIndex QtTestModel::parent(const QModelIndex &) const { return QModelIndex(); } |
|
175 int QtTestModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : rCount; } |
|
176 int QtTestModel::columnCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : cCount; } |
|
177 bool QtTestModel::hasChildren(const QModelIndex &) const { return false; } |
|
178 |
|
179 QVariant QtTestModel::data(const QModelIndex &idx, int) const |
|
180 { |
|
181 if (idx.row() < 0 || idx.column() < 0 || idx.column() > cCount || idx.row() > rCount) { |
|
182 wrongIndex = true; |
|
183 qWarning("got invalid modelIndex %d/%d", idx.row(), idx.column()); |
|
184 return QVariant(); |
|
185 } |
|
186 return table.at(idx.row()).at(idx.column()); |
|
187 } |
|
188 |
|
189 bool QtTestModel::setData(const QModelIndex &idx, const QVariant &value, int) |
|
190 { |
|
191 table[idx.row()][idx.column()] = value.toString(); |
|
192 return true; |
|
193 } |
|
194 |
|
195 bool QtTestModel::insertRows(int row, int count, const QModelIndex &parent) |
|
196 { |
|
197 QAbstractItemModel::beginInsertRows(parent, row, row + count - 1); |
|
198 int cc = columnCount(parent); |
|
199 table.insert(row, count, QVector<QString>(cc)); |
|
200 rCount = table.count(); |
|
201 QAbstractItemModel::endInsertRows(); |
|
202 return true; |
|
203 } |
|
204 |
|
205 bool QtTestModel::insertColumns(int column, int count, const QModelIndex &parent) |
|
206 { |
|
207 QAbstractItemModel::beginInsertColumns(parent, column, column + count - 1); |
|
208 int rc = rowCount(parent); |
|
209 for (int i = 0; i < rc; ++i) |
|
210 table[i].insert(column, 1, ""); |
|
211 cCount = table.at(0).count(); |
|
212 QAbstractItemModel::endInsertColumns(); |
|
213 return true; |
|
214 } |
|
215 |
|
216 void QtTestModel::setPersistent(const QModelIndex &from, const QModelIndex &to) |
|
217 { |
|
218 changePersistentIndex(from, to); |
|
219 } |
|
220 |
|
221 bool QtTestModel::removeRows( int row, int count, const QModelIndex & parent) |
|
222 { |
|
223 QAbstractItemModel::beginRemoveRows(parent, row, row + count - 1); |
|
224 |
|
225 for (int r = row+count-1; r >= row; --r) |
|
226 table.remove(r); |
|
227 rCount = table.count(); |
|
228 |
|
229 QAbstractItemModel::endRemoveRows(); |
|
230 return true; |
|
231 } |
|
232 |
|
233 bool QtTestModel::removeColumns(int column, int count, const QModelIndex & parent) |
|
234 { |
|
235 QAbstractItemModel::beginRemoveColumns(parent, column, column + count - 1); |
|
236 |
|
237 for (int c = column+count-1; c > column; --c) |
|
238 for (int r = 0; r < rCount; ++r) |
|
239 table[r].remove(c); |
|
240 |
|
241 cCount = table.at(0).count(); |
|
242 |
|
243 QAbstractItemModel::endRemoveColumns(); |
|
244 return true; |
|
245 } |
|
246 |
|
247 void QtTestModel::reset() |
|
248 { |
|
249 QAbstractItemModel::reset(); |
|
250 } |
|
251 |
|
252 tst_QAbstractItemModel::tst_QAbstractItemModel() |
|
253 { |
|
254 } |
|
255 |
|
256 tst_QAbstractItemModel::~tst_QAbstractItemModel() |
|
257 { |
|
258 } |
|
259 |
|
260 /** |
|
261 * The source Model *must* be initialized before the _data function, since the _data function uses QModelIndexes to reference the items in the tables. |
|
262 * Therefore, we must initialize it globally. |
|
263 */ |
|
264 |
|
265 void tst_QAbstractItemModel::initTestCase() |
|
266 { |
|
267 qRegisterMetaType<QModelIndex>("QModelIndex"); |
|
268 } |
|
269 |
|
270 void tst_QAbstractItemModel::cleanupTestCase() |
|
271 { |
|
272 |
|
273 } |
|
274 |
|
275 void tst_QAbstractItemModel::init() |
|
276 { |
|
277 m_model = new DynamicTreeModel(this); |
|
278 |
|
279 ModelInsertCommand *insertCommand = new ModelInsertCommand(m_model, this); |
|
280 insertCommand->setNumCols(4); |
|
281 insertCommand->setStartRow(0); |
|
282 insertCommand->setEndRow(9); |
|
283 insertCommand->doCommand(); |
|
284 |
|
285 insertCommand = new ModelInsertCommand(m_model, this); |
|
286 insertCommand->setAncestorRowNumbers(QList<int>() << 5); |
|
287 insertCommand->setNumCols(4); |
|
288 insertCommand->setStartRow(0); |
|
289 insertCommand->setEndRow(9); |
|
290 insertCommand->doCommand(); |
|
291 } |
|
292 |
|
293 void tst_QAbstractItemModel::cleanup() |
|
294 { |
|
295 |
|
296 } |
|
297 |
|
298 /* |
|
299 tests |
|
300 */ |
|
301 |
|
302 void tst_QAbstractItemModel::index() |
|
303 { |
|
304 QtTestModel model(1, 1); |
|
305 QModelIndex idx = model.index(0, 0, QModelIndex()); |
|
306 QVERIFY(idx.isValid()); |
|
307 } |
|
308 |
|
309 void tst_QAbstractItemModel::parent() |
|
310 { |
|
311 QtTestModel model(1, 1); |
|
312 QModelIndex idx = model.index(0, 0, QModelIndex()); |
|
313 QModelIndex par = model.parent(idx); |
|
314 QVERIFY(!par.isValid()); |
|
315 } |
|
316 |
|
317 void tst_QAbstractItemModel::hasChildren() |
|
318 { |
|
319 QtTestModel model(1, 1); |
|
320 QModelIndex idx = model.index(0, 0, QModelIndex()); |
|
321 QVERIFY(model.hasChildren(idx) == false); |
|
322 } |
|
323 |
|
324 void tst_QAbstractItemModel::_data() |
|
325 { |
|
326 QtTestModel model(1, 1); |
|
327 QModelIndex idx = model.index(0, 0, QModelIndex()); |
|
328 QVERIFY(idx.isValid()); |
|
329 QCOMPARE(model.data(idx, Qt::DisplayRole).toString(), QString("0/0")); |
|
330 |
|
331 // Default does nothing |
|
332 QCOMPARE(model.setHeaderData(0, Qt::Horizontal, QVariant(0), 0), false); |
|
333 } |
|
334 |
|
335 void tst_QAbstractItemModel::headerData() |
|
336 { |
|
337 QtTestModel model(1, 1); |
|
338 QCOMPARE(model.headerData(0, Qt::Horizontal, Qt::DisplayRole).toString(), |
|
339 QString("1")); |
|
340 |
|
341 // Default text alignment for header must be invalid |
|
342 QVERIFY( !model.headerData(0, Qt::Horizontal, Qt::TextAlignmentRole).isValid() ); |
|
343 } |
|
344 |
|
345 void tst_QAbstractItemModel::itemData() |
|
346 { |
|
347 QtTestModel model(1, 1); |
|
348 QModelIndex idx = model.index(0, 0, QModelIndex()); |
|
349 QVERIFY(idx.isValid()); |
|
350 QMap<int, QVariant> dat = model.itemData(idx); |
|
351 QCOMPARE(dat.count(Qt::DisplayRole), 1); |
|
352 QCOMPARE(dat.value(Qt::DisplayRole).toString(), QString("0/0")); |
|
353 } |
|
354 |
|
355 void tst_QAbstractItemModel::itemFlags() |
|
356 { |
|
357 QtTestModel model(1, 1); |
|
358 QModelIndex idx = model.index(0, 0, QModelIndex()); |
|
359 QVERIFY(idx.isValid()); |
|
360 Qt::ItemFlags flags = model.flags(idx); |
|
361 QCOMPARE(Qt::ItemIsSelectable|Qt::ItemIsEnabled, flags); |
|
362 } |
|
363 |
|
364 void tst_QAbstractItemModel::match() |
|
365 { |
|
366 QtTestModel model(4, 1); |
|
367 QModelIndex start = model.index(0, 0, QModelIndex()); |
|
368 QVERIFY(start.isValid()); |
|
369 QModelIndexList res = model.match(start, Qt::DisplayRole, QVariant("1"), 3); |
|
370 QCOMPARE(res.count(), 1); |
|
371 QModelIndex idx = model.index(1, 0, QModelIndex()); |
|
372 bool areEqual = (idx == res.first()); |
|
373 QVERIFY(areEqual); |
|
374 |
|
375 model.setData(model.index(0, 0, QModelIndex()), "bat", Qt::DisplayRole); |
|
376 model.setData(model.index(1, 0, QModelIndex()), "cat", Qt::DisplayRole); |
|
377 model.setData(model.index(2, 0, QModelIndex()), "dog", Qt::DisplayRole); |
|
378 model.setData(model.index(3, 0, QModelIndex()), "boar", Qt::DisplayRole); |
|
379 |
|
380 res = model.match(start, Qt::DisplayRole, QVariant("dog"), -1, Qt::MatchExactly); |
|
381 QCOMPARE(res.count(), 1); |
|
382 res = model.match(start, Qt::DisplayRole, QVariant("a"), -1, Qt::MatchContains); |
|
383 QCOMPARE(res.count(), 3); |
|
384 res = model.match(start, Qt::DisplayRole, QVariant("b"), -1, Qt::MatchStartsWith); |
|
385 QCOMPARE(res.count(), 2); |
|
386 res = model.match(start, Qt::DisplayRole, QVariant("t"), -1, Qt::MatchEndsWith); |
|
387 QCOMPARE(res.count(), 2); |
|
388 res = model.match(start, Qt::DisplayRole, QVariant("*a*"), -1, Qt::MatchWildcard); |
|
389 QCOMPARE(res.count(), 3); |
|
390 res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1, Qt::MatchRegExp); |
|
391 QCOMPARE(res.count(), 2); |
|
392 res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1, Qt::MatchRegExp | Qt::MatchCaseSensitive); |
|
393 QCOMPARE(res.count(), 0); |
|
394 res = model.match(start, Qt::DisplayRole, QVariant("BOAR"), -1, Qt::MatchFixedString); |
|
395 QCOMPARE(res.count(), 1); |
|
396 res = model.match(start, Qt::DisplayRole, QVariant("bat"), -1, |
|
397 Qt::MatchFixedString | Qt::MatchCaseSensitive); |
|
398 QCOMPARE(res.count(), 1); |
|
399 } |
|
400 |
|
401 typedef QPair<int, int> Position; |
|
402 typedef QVector<QPair<int, int> > Selection; |
|
403 typedef QVector<QVector<QString> > StringTable; |
|
404 typedef QVector<QString> StringTableRow; |
|
405 Q_DECLARE_METATYPE(Position) |
|
406 Q_DECLARE_METATYPE(Selection) |
|
407 Q_DECLARE_METATYPE(StringTable) |
|
408 |
|
409 static StringTableRow qStringTableRow(const QString &s1, const QString &s2, const QString &s3) |
|
410 { |
|
411 StringTableRow row; |
|
412 row << s1 << s2 << s3; |
|
413 return row; |
|
414 } |
|
415 |
|
416 #ifdef Q_CC_MSVC |
|
417 # define STRINGTABLE (StringTable()) |
|
418 #else |
|
419 # define STRINGTABLE StringTable() |
|
420 #endif |
|
421 |
|
422 void tst_QAbstractItemModel::dropMimeData_data() |
|
423 { |
|
424 QTest::addColumn<StringTable>("src_table"); // drag source |
|
425 QTest::addColumn<StringTable>("dst_table"); // drop target |
|
426 QTest::addColumn<Selection>("selection"); // dragged items |
|
427 QTest::addColumn<Position>("dst_position"); // drop position |
|
428 QTest::addColumn<StringTable>("res_table"); // expected result |
|
429 |
|
430 { |
|
431 QTest::newRow("2x2 dropped at [0, 0]") |
|
432 << (STRINGTABLE // source table |
|
433 << (qStringTableRow("A", "B", "C")) |
|
434 << (qStringTableRow("D", "E", "F"))) |
|
435 << (STRINGTABLE // destination table |
|
436 << (qStringTableRow("0", "1", "2")) |
|
437 << (qStringTableRow("3", "4", "5"))) |
|
438 << (Selection() // selection |
|
439 << Position(0, 0) << Position(0, 1) |
|
440 << Position(1, 0) << Position(1, 1)) |
|
441 << Position(0, 0) // drop position |
|
442 << (STRINGTABLE // resulting table |
|
443 << (qStringTableRow("A", "B", "" )) |
|
444 << (qStringTableRow("D", "E", "" )) |
|
445 << (qStringTableRow("0", "1", "2")) |
|
446 << (qStringTableRow("3", "4", "5"))); |
|
447 } |
|
448 |
|
449 { |
|
450 QTest::newRow("2x2 dropped at [1, 0]") |
|
451 << (STRINGTABLE // source table |
|
452 << (qStringTableRow("A", "B", "C")) |
|
453 << (qStringTableRow("D", "E", "F"))) |
|
454 << (STRINGTABLE // destination table |
|
455 << (qStringTableRow("0", "1", "2")) |
|
456 << (qStringTableRow("3", "4", "5"))) |
|
457 << (Selection() // selection |
|
458 << Position(0, 0) << Position(0, 1) |
|
459 << Position(1, 0) << Position(1, 1)) |
|
460 << Position(1, 0) // drop position |
|
461 << (STRINGTABLE // resulting table |
|
462 << (qStringTableRow("0", "1", "2")) |
|
463 << (qStringTableRow("A", "B", "" )) |
|
464 << (qStringTableRow("D", "E", "" )) |
|
465 << (qStringTableRow("3", "4", "5"))); |
|
466 } |
|
467 |
|
468 { |
|
469 QTest::newRow("2x2 dropped at [3, 0]") |
|
470 << (STRINGTABLE // source table |
|
471 << (qStringTableRow("A", "B", "C")) |
|
472 << (qStringTableRow("D", "E", "F"))) |
|
473 << (STRINGTABLE // destination table |
|
474 << (qStringTableRow("0", "1", "2")) |
|
475 << (qStringTableRow("3", "4", "5"))) |
|
476 << (Selection() // selection |
|
477 << Position(0, 0) << Position(0, 1) |
|
478 << Position(1, 0) << Position(1, 1)) |
|
479 << Position(3, 0) // drop position |
|
480 << (STRINGTABLE // resulting table |
|
481 << (qStringTableRow("0", "1", "2")) |
|
482 << (qStringTableRow("3", "4", "5")) |
|
483 << (qStringTableRow("A", "B", "" )) |
|
484 << (qStringTableRow("D", "E", "" ))); |
|
485 } |
|
486 |
|
487 { |
|
488 QTest::newRow("2x2 dropped at [0, 1]") |
|
489 << (STRINGTABLE // source table |
|
490 << (qStringTableRow("A", "B", "C")) |
|
491 << (qStringTableRow("D", "E", "F"))) |
|
492 << (STRINGTABLE // destination table |
|
493 << (qStringTableRow("0", "1", "2")) |
|
494 << (qStringTableRow("3", "4", "5"))) |
|
495 << (Selection() // selection |
|
496 << Position(0, 0) << Position(0, 1) |
|
497 << Position(1, 0) << Position(1, 1)) |
|
498 << Position(0, 1) // drop position |
|
499 << (STRINGTABLE // resulting table |
|
500 << (qStringTableRow("" , "A", "B")) |
|
501 << (qStringTableRow("" , "D", "E")) |
|
502 << (qStringTableRow("0", "1", "2")) |
|
503 << (qStringTableRow("3", "4", "5"))); |
|
504 } |
|
505 |
|
506 { |
|
507 QTest::newRow("2x2 dropped at [0, 2] (line break)") |
|
508 << (STRINGTABLE // source table |
|
509 << (qStringTableRow("A", "B", "C")) |
|
510 << (qStringTableRow("D", "E", "F"))) |
|
511 << (STRINGTABLE // destination table |
|
512 << (qStringTableRow("0", "1", "2")) |
|
513 << (qStringTableRow("3", "4", "5"))) |
|
514 << (Selection() // selection |
|
515 << Position(0, 0) << Position(0, 1) |
|
516 << Position(1, 0) << Position(1, 1)) |
|
517 << Position(0, 2) // drop position |
|
518 << (STRINGTABLE // resulting table |
|
519 << (qStringTableRow("" , "" , "A")) |
|
520 << (qStringTableRow("" , "" , "D")) |
|
521 << (qStringTableRow("" , "" , "B")) |
|
522 << (qStringTableRow("" , "" , "E")) |
|
523 << (qStringTableRow("0", "1", "2")) |
|
524 << (qStringTableRow("3", "4", "5"))); |
|
525 } |
|
526 |
|
527 { |
|
528 QTest::newRow("2x2 dropped at [3, 2] (line break)") |
|
529 << (STRINGTABLE // source table |
|
530 << (qStringTableRow("A", "B", "C")) |
|
531 << (qStringTableRow("D", "E", "F"))) |
|
532 << (STRINGTABLE // destination table |
|
533 << (qStringTableRow("0", "1", "2")) |
|
534 << (qStringTableRow("3", "4", "5"))) |
|
535 << (Selection() // selection |
|
536 << Position(0, 0) << Position(0, 1) |
|
537 << Position(1, 0) << Position(1, 1)) |
|
538 << Position(3, 2) // drop position |
|
539 << (STRINGTABLE // resulting table |
|
540 << (qStringTableRow("0", "1", "2")) |
|
541 << (qStringTableRow("3", "4", "5")) |
|
542 << (qStringTableRow("" , "" , "A")) |
|
543 << (qStringTableRow("" , "" , "D")) |
|
544 << (qStringTableRow("" , "" , "B")) |
|
545 << (qStringTableRow("" , "" , "E"))); |
|
546 } |
|
547 |
|
548 { |
|
549 QTest::newRow("non-square dropped at [0, 0]") |
|
550 << (STRINGTABLE // source table |
|
551 << (qStringTableRow("A", "B", "C")) |
|
552 << (qStringTableRow("D", "E", "F"))) |
|
553 << (STRINGTABLE // destination table |
|
554 << (qStringTableRow("0", "1", "2")) |
|
555 << (qStringTableRow("3", "4", "5"))) |
|
556 << (Selection() // selection |
|
557 << Position(0, 0) << Position(0, 1) |
|
558 << Position(1, 0)) |
|
559 << Position(0, 0) // drop position |
|
560 << (STRINGTABLE // resulting table |
|
561 << (qStringTableRow("A", "B", "" )) |
|
562 << (qStringTableRow("D", "" , "" )) |
|
563 << (qStringTableRow("0", "1", "2")) |
|
564 << (qStringTableRow("3", "4", "5"))); |
|
565 } |
|
566 |
|
567 { |
|
568 QTest::newRow("non-square dropped at [0, 2]") |
|
569 << (STRINGTABLE // source table |
|
570 << (qStringTableRow("A", "B", "C")) |
|
571 << (qStringTableRow("D", "E", "F"))) |
|
572 << (STRINGTABLE // destination table |
|
573 << (qStringTableRow("0", "1", "2")) |
|
574 << (qStringTableRow("3", "4", "5"))) |
|
575 << (Selection() // selection |
|
576 << Position(0, 0) << Position(0, 1) |
|
577 << Position(1, 0)) |
|
578 << Position(0, 2) // drop position |
|
579 << (STRINGTABLE // resulting table |
|
580 << (qStringTableRow("" , "" , "A")) |
|
581 << (qStringTableRow("" , "" , "D")) |
|
582 << (qStringTableRow("" , "" , "B")) |
|
583 << (qStringTableRow("0", "1", "2")) |
|
584 << (qStringTableRow("3", "4", "5"))); |
|
585 } |
|
586 |
|
587 { |
|
588 QTest::newRow("2x 1x2 dropped at [0, 0] (duplicates)") |
|
589 << (STRINGTABLE // source table |
|
590 << (qStringTableRow("A", "B", "C")) |
|
591 << (qStringTableRow("D", "E", "F"))) |
|
592 << (STRINGTABLE // destination table |
|
593 << (qStringTableRow("0", "1", "2")) |
|
594 << (qStringTableRow("3", "4", "5"))) |
|
595 << (Selection() // selection; 2x the same row (to simulate selections in hierarchy) |
|
596 << Position(0, 0) << Position(0, 1) |
|
597 << Position(0, 0) << Position(0, 1)) |
|
598 << Position(0, 0) // drop position |
|
599 << (STRINGTABLE // resulting table |
|
600 << (qStringTableRow("A", "B", "" )) |
|
601 << (qStringTableRow("A", "" , "" )) |
|
602 << (qStringTableRow("" , "B", "" )) // ### FIXME: strange behavior, but rare case |
|
603 << (qStringTableRow("0", "1", "2")) |
|
604 << (qStringTableRow("3", "4", "5"))); |
|
605 } |
|
606 |
|
607 { |
|
608 QTest::newRow("2x 1x2 dropped at [3, 2] (duplicates)") |
|
609 << (STRINGTABLE // source table |
|
610 << (qStringTableRow("A", "B", "C")) |
|
611 << (qStringTableRow("D", "E", "F"))) |
|
612 << (STRINGTABLE // destination table |
|
613 << (qStringTableRow("0", "1", "2")) |
|
614 << (qStringTableRow("3", "4", "5"))) |
|
615 << (Selection() // selection; 2x the same row (to simulate selections in hierarchy) |
|
616 << Position(0, 0) << Position(0, 1) |
|
617 << Position(0, 0) << Position(0, 1)) |
|
618 << Position(3, 2) // drop position |
|
619 << (STRINGTABLE // resulting table |
|
620 << (qStringTableRow("0", "1", "2")) |
|
621 << (qStringTableRow("3", "4", "5")) |
|
622 << (qStringTableRow("" , "" , "A")) |
|
623 << (qStringTableRow("" , "" , "B")) |
|
624 << (qStringTableRow("" , "" , "A")) |
|
625 << (qStringTableRow("" , "" , "B"))); |
|
626 } |
|
627 { |
|
628 QTest::newRow("2x 1x2 dropped at [3, 2] (different rows)") |
|
629 << (STRINGTABLE // source table |
|
630 << (qStringTableRow("A", "B", "C")) |
|
631 << (qStringTableRow("D", "E", "F")) |
|
632 << (qStringTableRow("G", "H", "I"))) |
|
633 << (STRINGTABLE // destination table |
|
634 << (qStringTableRow("0", "1", "2")) |
|
635 << (qStringTableRow("3", "4", "5"))) |
|
636 << (Selection() // selection; 2x the same row (to simulate selections in hierarchy) |
|
637 << Position(0, 0) << Position(0, 1) |
|
638 << Position(2, 0) << Position(2, 1)) |
|
639 << Position(2, 1) // drop position |
|
640 << (STRINGTABLE // resulting table |
|
641 << (qStringTableRow("0", "1", "2")) |
|
642 << (qStringTableRow("3", "4", "5")) |
|
643 << (qStringTableRow("" , "A" , "B")) |
|
644 << (qStringTableRow("" , "G" , "H"))); |
|
645 } |
|
646 |
|
647 { |
|
648 QTest::newRow("2x 1x2 dropped at [3, 2] (different rows, over the edge)") |
|
649 << (STRINGTABLE // source table |
|
650 << (qStringTableRow("A", "B", "C")) |
|
651 << (qStringTableRow("D", "E", "F")) |
|
652 << (qStringTableRow("G", "H", "I"))) |
|
653 << (STRINGTABLE // destination table |
|
654 << (qStringTableRow("0", "1", "2")) |
|
655 << (qStringTableRow("3", "4", "5"))) |
|
656 << (Selection() // selection; 2x the same row (to simulate selections in hierarchy) |
|
657 << Position(0, 0) << Position(0, 1) |
|
658 << Position(2, 0) << Position(2, 1)) |
|
659 << Position(3, 2) // drop position |
|
660 << (STRINGTABLE // resulting table |
|
661 << (qStringTableRow("0", "1", "2")) |
|
662 << (qStringTableRow("3", "4", "5")) |
|
663 << (qStringTableRow("" , "" , "A")) |
|
664 << (qStringTableRow("" , "" , "G")) |
|
665 << (qStringTableRow("" , "" , "B")) |
|
666 << (qStringTableRow("" , "" , "H"))); |
|
667 } |
|
668 } |
|
669 |
|
670 void tst_QAbstractItemModel::dropMimeData() |
|
671 { |
|
672 QFETCH(StringTable, src_table); |
|
673 QFETCH(StringTable, dst_table); |
|
674 QFETCH(Selection, selection); |
|
675 QFETCH(Position, dst_position); |
|
676 QFETCH(StringTable, res_table); |
|
677 |
|
678 QtTestModel src(src_table); |
|
679 QtTestModel dst(dst_table); |
|
680 QtTestModel res(res_table); |
|
681 |
|
682 // qDebug() << "src" << src.rowCount(QModelIndex()) << src.columnCount(QModelIndex()); |
|
683 // qDebug() << "dst" << dst.rowCount(QModelIndex()) << dst.columnCount(QModelIndex()); |
|
684 // qDebug() << "res" << res.rowCount(QModelIndex()) << res.columnCount(QModelIndex()); |
|
685 |
|
686 // get the mimeData from the "selected" indexes |
|
687 QModelIndexList selectedIndexes; |
|
688 for (int i = 0; i < selection.count(); ++i) |
|
689 selectedIndexes << src.index(selection.at(i).first, selection.at(i).second, QModelIndex()); |
|
690 QMimeData *md = src.mimeData(selectedIndexes); |
|
691 // do the drop |
|
692 dst.dropMimeData(md, Qt::CopyAction, dst_position.first, dst_position.second, QModelIndex()); |
|
693 delete md; |
|
694 |
|
695 // compare to the expected results |
|
696 QCOMPARE(dst.rowCount(QModelIndex()), res.rowCount(QModelIndex())); |
|
697 QCOMPARE(dst.columnCount(QModelIndex()), res.columnCount(QModelIndex())); |
|
698 for (int r = 0; r < dst.rowCount(QModelIndex()); ++r) { |
|
699 for (int c = 0; c < dst.columnCount(QModelIndex()); ++c) { |
|
700 QModelIndex dst_idx = dst.index(r, c, QModelIndex()); |
|
701 QModelIndex res_idx = res.index(r, c, QModelIndex()); |
|
702 QMap<int, QVariant> dst_data = dst.itemData(dst_idx); |
|
703 QMap<int, QVariant> res_data = res.itemData(res_idx); |
|
704 //if(dst_data != res_data) |
|
705 // qDebug() << r << c << dst_data.value(0).toString() << res_data.value(0).toString(); |
|
706 QCOMPARE(dst_data , res_data); |
|
707 } |
|
708 } |
|
709 |
|
710 } |
|
711 |
|
712 |
|
713 void tst_QAbstractItemModel::changePersistentIndex() |
|
714 { |
|
715 QtTestModel model(3, 3); |
|
716 QModelIndex a = model.index(1, 2, QModelIndex()); |
|
717 QModelIndex b = model.index(2, 1, QModelIndex()); |
|
718 QPersistentModelIndex p(a); |
|
719 QVERIFY(p == a); |
|
720 model.setPersistent(a, b); |
|
721 QVERIFY(p == b); |
|
722 } |
|
723 |
|
724 void tst_QAbstractItemModel::movePersistentIndex() |
|
725 { |
|
726 QtTestModel model(3, 3); |
|
727 |
|
728 QPersistentModelIndex a = model.index(1, 1); |
|
729 QVERIFY(a.isValid()); |
|
730 QCOMPARE(a.row(), 1); |
|
731 QCOMPARE(a.column(), 1); |
|
732 |
|
733 model.insertRow(0); |
|
734 QCOMPARE(a.row(), 2); |
|
735 |
|
736 model.insertRow(1); |
|
737 QCOMPARE(a.row(), 3); |
|
738 |
|
739 model.insertColumn(0); |
|
740 QCOMPARE(a.column(), 2); |
|
741 } |
|
742 |
|
743 void tst_QAbstractItemModel::removeRows() |
|
744 { |
|
745 QtTestModel model(10, 10); |
|
746 |
|
747 QSignalSpy rowsAboutToBeRemovedSpy(&model, SIGNAL(rowsAboutToBeRemoved( const QModelIndex &, int , int ))); |
|
748 QSignalSpy rowsRemovedSpy(&model, SIGNAL(rowsRemoved( const QModelIndex &, int, int ))); |
|
749 |
|
750 QCOMPARE(model.removeRows(6, 4), true); |
|
751 QCOMPARE(rowsAboutToBeRemovedSpy.count(), 1); |
|
752 QCOMPARE(rowsRemovedSpy.count(), 1); |
|
753 } |
|
754 |
|
755 void tst_QAbstractItemModel::removeColumns() |
|
756 { |
|
757 QtTestModel model(10, 10); |
|
758 |
|
759 QSignalSpy columnsAboutToBeRemovedSpy(&model, SIGNAL(columnsAboutToBeRemoved( const QModelIndex &, int , int ))); |
|
760 QSignalSpy columnsRemovedSpy(&model, SIGNAL(columnsRemoved( const QModelIndex &, int, int ))); |
|
761 |
|
762 QCOMPARE(model.removeColumns(6, 4), true); |
|
763 QCOMPARE(columnsAboutToBeRemovedSpy.count(), 1); |
|
764 QCOMPARE(columnsRemovedSpy.count(), 1); |
|
765 } |
|
766 |
|
767 void tst_QAbstractItemModel::insertRows() |
|
768 { |
|
769 QtTestModel model(10, 10); |
|
770 |
|
771 QSignalSpy rowsAboutToBeInsertedSpy(&model, SIGNAL(rowsAboutToBeInserted( const QModelIndex &, int , int ))); |
|
772 QSignalSpy rowsInsertedSpy(&model, SIGNAL(rowsInserted( const QModelIndex &, int, int ))); |
|
773 |
|
774 QCOMPARE(model.insertRows(6, 4), true); |
|
775 QCOMPARE(rowsAboutToBeInsertedSpy.count(), 1); |
|
776 QCOMPARE(rowsInsertedSpy.count(), 1); |
|
777 } |
|
778 |
|
779 void tst_QAbstractItemModel::insertColumns() |
|
780 { |
|
781 QtTestModel model(10, 10); |
|
782 |
|
783 QSignalSpy columnsAboutToBeInsertedSpy(&model, SIGNAL(columnsAboutToBeInserted( const QModelIndex &, int , int ))); |
|
784 QSignalSpy columnsInsertedSpy(&model, SIGNAL(columnsInserted( const QModelIndex &, int, int ))); |
|
785 |
|
786 QCOMPARE(model.insertColumns(6, 4), true); |
|
787 QCOMPARE(columnsAboutToBeInsertedSpy.count(), 1); |
|
788 QCOMPARE(columnsInsertedSpy.count(), 1); |
|
789 } |
|
790 |
|
791 void tst_QAbstractItemModel::reset() |
|
792 { |
|
793 QtTestModel model(10, 10); |
|
794 |
|
795 QSignalSpy resetSpy(&model, SIGNAL(modelReset())); |
|
796 model.reset(); |
|
797 QCOMPARE(resetSpy.count(), 1); |
|
798 } |
|
799 |
|
800 void tst_QAbstractItemModel::complexChangesWithPersistent() |
|
801 { |
|
802 QtTestModel model(10, 10); |
|
803 QPersistentModelIndex a = model.index(1, 1, QModelIndex()); |
|
804 QPersistentModelIndex b = model.index(9, 7, QModelIndex()); |
|
805 QPersistentModelIndex c = model.index(5, 6, QModelIndex()); |
|
806 QPersistentModelIndex d = model.index(3, 9, QModelIndex()); |
|
807 QPersistentModelIndex e[10]; |
|
808 for (int i=0; i <10 ; i++) { |
|
809 e[i] = model.index(2, i , QModelIndex()); |
|
810 } |
|
811 |
|
812 QVERIFY(a == model.index(1, 1, QModelIndex())); |
|
813 QVERIFY(b == model.index(9, 7, QModelIndex())); |
|
814 QVERIFY(c == model.index(5, 6, QModelIndex())); |
|
815 QVERIFY(d == model.index(3, 9, QModelIndex())); |
|
816 for (int i=0; i <8 ; i++) |
|
817 QVERIFY(e[i] == model.index(2, i , QModelIndex())); |
|
818 |
|
819 //remove a bunch of columns |
|
820 model.removeColumns(2, 4); |
|
821 |
|
822 QVERIFY(a == model.index(1, 1, QModelIndex())); |
|
823 QVERIFY(b == model.index(9, 3, QModelIndex())); |
|
824 QVERIFY(c == model.index(5, 2, QModelIndex())); |
|
825 QVERIFY(d == model.index(3, 5, QModelIndex())); |
|
826 for (int i=0; i <2 ; i++) |
|
827 QVERIFY(e[i] == model.index(2, i , QModelIndex())); |
|
828 for (int i=2; i <6 ; i++) |
|
829 QVERIFY(!e[i].isValid()); |
|
830 for (int i=6; i <10 ; i++) |
|
831 QVERIFY(e[i] == model.index(2, i-4 , QModelIndex())); |
|
832 |
|
833 //move some indexes around |
|
834 model.setPersistent(model.index(1, 1 , QModelIndex()), model.index(9, 3 , QModelIndex())); |
|
835 model.setPersistent(model.index(9, 3 , QModelIndex()), model.index(8, 4 , QModelIndex())); |
|
836 |
|
837 QVERIFY(a == model.index(9, 3, QModelIndex())); |
|
838 QVERIFY(b == model.index(8, 4, QModelIndex())); |
|
839 QVERIFY(c == model.index(5, 2, QModelIndex())); |
|
840 QVERIFY(d == model.index(3, 5, QModelIndex())); |
|
841 for (int i=0; i <2 ; i++) |
|
842 QVERIFY(e[i] == model.index(2, i , QModelIndex())); |
|
843 for (int i=2; i <6 ; i++) |
|
844 QVERIFY(!e[i].isValid()); |
|
845 for (int i=6; i <10 ; i++) |
|
846 QVERIFY(e[i] == model.index(2, i-4 , QModelIndex())); |
|
847 |
|
848 //inserting a bunch of columns |
|
849 model.insertColumns(2, 2); |
|
850 QVERIFY(a == model.index(9, 5, QModelIndex())); |
|
851 QVERIFY(b == model.index(8, 6, QModelIndex())); |
|
852 QVERIFY(c == model.index(5, 4, QModelIndex())); |
|
853 QVERIFY(d == model.index(3, 7, QModelIndex())); |
|
854 for (int i=0; i <2 ; i++) |
|
855 QVERIFY(e[i] == model.index(2, i , QModelIndex())); |
|
856 for (int i=2; i <6 ; i++) |
|
857 QVERIFY(!e[i].isValid()); |
|
858 for (int i=6; i <10 ; i++) |
|
859 QVERIFY(e[i] == model.index(2, i-2 , QModelIndex())); |
|
860 |
|
861 } |
|
862 |
|
863 void tst_QAbstractItemModel::testMoveSameParentDown_data() |
|
864 { |
|
865 QTest::addColumn<int>("startRow"); |
|
866 QTest::addColumn<int>("endRow"); |
|
867 QTest::addColumn<int>("destRow"); |
|
868 |
|
869 // Move from the start to the middle |
|
870 QTest::newRow("move01") << 0 << 2 << 8; |
|
871 // Move from the start to the end |
|
872 QTest::newRow("move02") << 0 << 2 << 10; |
|
873 // Move from the middle to the middle |
|
874 QTest::newRow("move03") << 3 << 5 << 8; |
|
875 // Move from the middle to the end |
|
876 QTest::newRow("move04") << 3 << 5 << 10; |
|
877 } |
|
878 |
|
879 void tst_QAbstractItemModel::testMoveSameParentDown() |
|
880 { |
|
881 QFETCH( int, startRow); |
|
882 QFETCH( int, endRow); |
|
883 QFETCH( int, destRow); |
|
884 |
|
885 QList<QPersistentModelIndex> persistentList; |
|
886 QModelIndexList indexList; |
|
887 |
|
888 for (int column = 0; column < m_model->columnCount(); ++column) |
|
889 { |
|
890 for (int row= 0; row < m_model->rowCount(); ++row) |
|
891 { |
|
892 QModelIndex idx = m_model->index(row, column); |
|
893 QVERIFY(idx.isValid()); |
|
894 indexList << idx; |
|
895 persistentList << QPersistentModelIndex(idx); |
|
896 } |
|
897 } |
|
898 |
|
899 QModelIndex parent = m_model->index(5, 0); |
|
900 for (int column = 0; column < m_model->columnCount(); ++column) |
|
901 { |
|
902 for (int row= 0; row < m_model->rowCount(parent); ++row) |
|
903 { |
|
904 QModelIndex idx = m_model->index(row, column, parent); |
|
905 QVERIFY(idx.isValid()); |
|
906 indexList << idx; |
|
907 persistentList << QPersistentModelIndex(idx); |
|
908 } |
|
909 } |
|
910 |
|
911 QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
912 QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
913 |
|
914 ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); |
|
915 moveCommand->setNumCols(4); |
|
916 moveCommand->setStartRow(startRow); |
|
917 moveCommand->setEndRow(endRow); |
|
918 moveCommand->setDestRow(destRow); |
|
919 moveCommand->doCommand(); |
|
920 |
|
921 QVariantList beforeSignal = beforeSpy.takeAt(0); |
|
922 QVariantList afterSignal = afterSpy.takeAt(0); |
|
923 |
|
924 QCOMPARE(beforeSignal.size(), 5); |
|
925 QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), QModelIndex()); |
|
926 QCOMPARE(beforeSignal.at(1).toInt(), startRow); |
|
927 QCOMPARE(beforeSignal.at(2).toInt(), endRow); |
|
928 QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex()); |
|
929 QCOMPARE(beforeSignal.at(4).toInt(), destRow); |
|
930 |
|
931 QCOMPARE(afterSignal.size(), 5); |
|
932 QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex()); |
|
933 QCOMPARE(afterSignal.at(1).toInt(), startRow); |
|
934 QCOMPARE(afterSignal.at(2).toInt(), endRow); |
|
935 QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex()); |
|
936 QCOMPARE(afterSignal.at(4).toInt(), destRow); |
|
937 |
|
938 for (int i = 0; i < indexList.size(); i++) |
|
939 { |
|
940 QModelIndex idx = indexList.at(i); |
|
941 QModelIndex persistentIndex = persistentList.at(i); |
|
942 if (idx.parent() == QModelIndex()) |
|
943 { |
|
944 int row = idx.row(); |
|
945 if ( row >= startRow) |
|
946 { |
|
947 if (row <= endRow) |
|
948 { |
|
949 QCOMPARE(row + destRow - endRow - 1, persistentIndex.row() ); |
|
950 QCOMPARE(idx.column(), persistentIndex.column()); |
|
951 QCOMPARE(idx.parent(), persistentIndex.parent()); |
|
952 QCOMPARE(idx.model(), persistentIndex.model()); |
|
953 } else if ( row < destRow) |
|
954 { |
|
955 QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() ); |
|
956 QCOMPARE(idx.column(), persistentIndex.column()); |
|
957 QCOMPARE(idx.parent(), persistentIndex.parent()); |
|
958 QCOMPARE(idx.model(), persistentIndex.model()); |
|
959 } else |
|
960 { |
|
961 QCOMPARE(idx, persistentIndex); |
|
962 } |
|
963 } else |
|
964 { |
|
965 QCOMPARE(idx, persistentIndex); |
|
966 } |
|
967 } else |
|
968 { |
|
969 QCOMPARE(idx, persistentIndex); |
|
970 } |
|
971 } |
|
972 } |
|
973 |
|
974 void tst_QAbstractItemModel::testMoveSameParentUp_data() |
|
975 { |
|
976 QTest::addColumn<int>("startRow"); |
|
977 QTest::addColumn<int>("endRow"); |
|
978 QTest::addColumn<int>("destRow"); |
|
979 |
|
980 // Move from the middle to the start |
|
981 QTest::newRow("move01") << 5 << 7 << 0; |
|
982 // Move from the end to the start |
|
983 QTest::newRow("move02") << 8 << 9 << 0; |
|
984 // Move from the middle to the middle |
|
985 QTest::newRow("move03") << 5 << 7 << 2; |
|
986 // Move from the end to the middle |
|
987 QTest::newRow("move04") << 8 << 9 << 5; |
|
988 } |
|
989 |
|
990 void tst_QAbstractItemModel::testMoveSameParentUp() |
|
991 { |
|
992 |
|
993 QFETCH( int, startRow); |
|
994 QFETCH( int, endRow); |
|
995 QFETCH( int, destRow); |
|
996 |
|
997 QList<QPersistentModelIndex> persistentList; |
|
998 QModelIndexList indexList; |
|
999 |
|
1000 for (int column = 0; column < m_model->columnCount(); ++column) |
|
1001 { |
|
1002 for (int row= 0; row < m_model->rowCount(); ++row) |
|
1003 { |
|
1004 QModelIndex idx = m_model->index(row, column); |
|
1005 QVERIFY(idx.isValid()); |
|
1006 indexList << idx; |
|
1007 persistentList << QPersistentModelIndex(idx); |
|
1008 } |
|
1009 } |
|
1010 |
|
1011 QModelIndex parent = m_model->index(2, 0); |
|
1012 for (int column = 0; column < m_model->columnCount(); ++column) |
|
1013 { |
|
1014 for (int row= 0; row < m_model->rowCount(parent); ++row) |
|
1015 { |
|
1016 QModelIndex idx = m_model->index(row, column, parent); |
|
1017 QVERIFY(idx.isValid()); |
|
1018 indexList << idx; |
|
1019 persistentList << QPersistentModelIndex(idx); |
|
1020 } |
|
1021 } |
|
1022 |
|
1023 QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1024 QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1025 |
|
1026 |
|
1027 ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); |
|
1028 moveCommand->setNumCols(4); |
|
1029 moveCommand->setStartRow(startRow); |
|
1030 moveCommand->setEndRow(endRow); |
|
1031 moveCommand->setDestRow(destRow); |
|
1032 moveCommand->doCommand(); |
|
1033 |
|
1034 QVariantList beforeSignal = beforeSpy.takeAt(0); |
|
1035 QVariantList afterSignal = afterSpy.takeAt(0); |
|
1036 |
|
1037 QCOMPARE(beforeSignal.size(), 5); |
|
1038 QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), QModelIndex()); |
|
1039 QCOMPARE(beforeSignal.at(1).toInt(), startRow); |
|
1040 QCOMPARE(beforeSignal.at(2).toInt(), endRow); |
|
1041 QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex()); |
|
1042 QCOMPARE(beforeSignal.at(4).toInt(), destRow); |
|
1043 |
|
1044 QCOMPARE(afterSignal.size(), 5); |
|
1045 QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex()); |
|
1046 QCOMPARE(afterSignal.at(1).toInt(), startRow); |
|
1047 QCOMPARE(afterSignal.at(2).toInt(), endRow); |
|
1048 QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex()); |
|
1049 QCOMPARE(afterSignal.at(4).toInt(), destRow); |
|
1050 |
|
1051 |
|
1052 for (int i = 0; i < indexList.size(); i++) |
|
1053 { |
|
1054 QModelIndex idx = indexList.at(i); |
|
1055 QModelIndex persistentIndex = persistentList.at(i); |
|
1056 if (idx.parent() == QModelIndex()) |
|
1057 { |
|
1058 int row = idx.row(); |
|
1059 if ( row >= destRow) |
|
1060 { |
|
1061 if (row < startRow) |
|
1062 { |
|
1063 QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() ); |
|
1064 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1065 QCOMPARE(idx.parent(), persistentIndex.parent()); |
|
1066 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1067 } else if ( row <= endRow) |
|
1068 { |
|
1069 QCOMPARE(row + destRow - startRow, persistentIndex.row() ); |
|
1070 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1071 QCOMPARE(idx.parent(), persistentIndex.parent()); |
|
1072 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1073 } else |
|
1074 { |
|
1075 QCOMPARE(idx, persistentIndex); |
|
1076 } |
|
1077 } else |
|
1078 { |
|
1079 QCOMPARE(idx, persistentIndex); |
|
1080 } |
|
1081 } else |
|
1082 { |
|
1083 QCOMPARE(idx, persistentIndex); |
|
1084 } |
|
1085 } |
|
1086 } |
|
1087 |
|
1088 void tst_QAbstractItemModel::testMoveToGrandParent_data() |
|
1089 { |
|
1090 QTest::addColumn<int>("startRow"); |
|
1091 QTest::addColumn<int>("endRow"); |
|
1092 QTest::addColumn<int>("destRow"); |
|
1093 |
|
1094 // Move from the start to the middle |
|
1095 QTest::newRow("move01") << 0 << 2 << 8; |
|
1096 // Move from the start to the end |
|
1097 QTest::newRow("move02") << 0 << 2 << 10; |
|
1098 // Move from the middle to the middle |
|
1099 QTest::newRow("move03") << 3 << 5 << 8; |
|
1100 // Move from the middle to the end |
|
1101 QTest::newRow("move04") << 3 << 5 << 10; |
|
1102 |
|
1103 // Move from the middle to the start |
|
1104 QTest::newRow("move05") << 5 << 7 << 0; |
|
1105 // Move from the end to the start |
|
1106 QTest::newRow("move06") << 8 << 9 << 0; |
|
1107 // Move from the middle to the middle |
|
1108 QTest::newRow("move07") << 5 << 7 << 2; |
|
1109 // Move from the end to the middle |
|
1110 QTest::newRow("move08") << 8 << 9 << 5; |
|
1111 |
|
1112 // Moving to the same row in a different parent doesn't confuse things. |
|
1113 QTest::newRow("move09") << 8 << 8 << 8; |
|
1114 |
|
1115 // Moving to the row of my parent and its neighbours doesn't confuse things |
|
1116 QTest::newRow("move09") << 8 << 8 << 4; |
|
1117 QTest::newRow("move10") << 8 << 8 << 5; |
|
1118 QTest::newRow("move11") << 8 << 8 << 6; |
|
1119 |
|
1120 // Moving everything from one parent to another |
|
1121 QTest::newRow("move12") << 0 << 9 << 10; |
|
1122 } |
|
1123 |
|
1124 void tst_QAbstractItemModel::testMoveToGrandParent() |
|
1125 { |
|
1126 |
|
1127 QFETCH( int, startRow); |
|
1128 QFETCH( int, endRow); |
|
1129 QFETCH( int, destRow); |
|
1130 |
|
1131 QList<QPersistentModelIndex> persistentList; |
|
1132 QModelIndexList indexList; |
|
1133 QModelIndexList parentsList; |
|
1134 |
|
1135 for (int column = 0; column < m_model->columnCount(); ++column) |
|
1136 { |
|
1137 for (int row= 0; row < m_model->rowCount(); ++row) |
|
1138 { |
|
1139 QModelIndex idx = m_model->index(row, column); |
|
1140 QVERIFY(idx.isValid()); |
|
1141 indexList << idx; |
|
1142 parentsList << idx.parent(); |
|
1143 persistentList << QPersistentModelIndex(idx); |
|
1144 } |
|
1145 } |
|
1146 |
|
1147 QModelIndex sourceIndex = m_model->index(5, 0); |
|
1148 for (int column = 0; column < m_model->columnCount(); ++column) |
|
1149 { |
|
1150 for (int row= 0; row < m_model->rowCount(sourceIndex); ++row) |
|
1151 { |
|
1152 QModelIndex idx = m_model->index(row, column, sourceIndex); |
|
1153 QVERIFY(idx.isValid()); |
|
1154 indexList << idx; |
|
1155 parentsList << idx.parent(); |
|
1156 persistentList << QPersistentModelIndex(idx); |
|
1157 } |
|
1158 } |
|
1159 |
|
1160 QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1161 QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1162 |
|
1163 |
|
1164 ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); |
|
1165 moveCommand->setAncestorRowNumbers(QList<int>() << 5); |
|
1166 moveCommand->setNumCols(4); |
|
1167 moveCommand->setStartRow(startRow); |
|
1168 moveCommand->setEndRow(endRow); |
|
1169 moveCommand->setDestRow(destRow); |
|
1170 moveCommand->doCommand(); |
|
1171 |
|
1172 QVariantList beforeSignal = beforeSpy.takeAt(0); |
|
1173 QVariantList afterSignal = afterSpy.takeAt(0); |
|
1174 |
|
1175 QCOMPARE(beforeSignal.size(), 5); |
|
1176 QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), sourceIndex); |
|
1177 QCOMPARE(beforeSignal.at(1).toInt(), startRow); |
|
1178 QCOMPARE(beforeSignal.at(2).toInt(), endRow); |
|
1179 QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex()); |
|
1180 QCOMPARE(beforeSignal.at(4).toInt(), destRow); |
|
1181 |
|
1182 QCOMPARE(afterSignal.size(), 5); |
|
1183 QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex); |
|
1184 QCOMPARE(afterSignal.at(1).toInt(), startRow); |
|
1185 QCOMPARE(afterSignal.at(2).toInt(), endRow); |
|
1186 QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex()); |
|
1187 QCOMPARE(afterSignal.at(4).toInt(), destRow); |
|
1188 |
|
1189 for (int i = 0; i < indexList.size(); i++) |
|
1190 { |
|
1191 QModelIndex idx = indexList.at(i); |
|
1192 QModelIndex idxParent = parentsList.at(i); |
|
1193 QModelIndex persistentIndex = persistentList.at(i); |
|
1194 int row = idx.row(); |
|
1195 if (idxParent == QModelIndex()) |
|
1196 { |
|
1197 if ( row >= destRow) |
|
1198 { |
|
1199 QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() ); |
|
1200 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1201 QCOMPARE(idxParent, persistentIndex.parent()); |
|
1202 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1203 } else |
|
1204 { |
|
1205 QCOMPARE(idx, persistentIndex); |
|
1206 } |
|
1207 } else |
|
1208 { |
|
1209 if (row < startRow) |
|
1210 { |
|
1211 QCOMPARE(idx, persistentIndex); |
|
1212 } else if (row <= endRow) |
|
1213 { |
|
1214 QCOMPARE(row + destRow - startRow, persistentIndex.row() ); |
|
1215 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1216 QCOMPARE(QModelIndex(), persistentIndex.parent()); |
|
1217 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1218 } else { |
|
1219 QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() ); |
|
1220 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1221 |
|
1222 if (idxParent.row() >= destRow) |
|
1223 { |
|
1224 QModelIndex adjustedParent; |
|
1225 adjustedParent = idxParent.sibling( idxParent.row() + endRow - startRow + 1, idxParent.column()); |
|
1226 QCOMPARE(adjustedParent, persistentIndex.parent()); |
|
1227 } else |
|
1228 { |
|
1229 QCOMPARE(idxParent, persistentIndex.parent()); |
|
1230 } |
|
1231 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1232 } |
|
1233 } |
|
1234 } |
|
1235 } |
|
1236 |
|
1237 void tst_QAbstractItemModel::testMoveToSibling_data() |
|
1238 { |
|
1239 QTest::addColumn<int>("startRow"); |
|
1240 QTest::addColumn<int>("endRow"); |
|
1241 QTest::addColumn<int>("destRow"); |
|
1242 |
|
1243 // Move from the start to the middle |
|
1244 QTest::newRow("move01") << 0 << 2 << 8; |
|
1245 // Move from the start to the end |
|
1246 QTest::newRow("move02") << 0 << 2 << 10; |
|
1247 // Move from the middle to the middle |
|
1248 QTest::newRow("move03") << 2 << 4 << 8; |
|
1249 // Move from the middle to the end |
|
1250 QTest::newRow("move04") << 2 << 4 << 10; |
|
1251 |
|
1252 // Move from the middle to the start |
|
1253 QTest::newRow("move05") << 8 << 8 << 0; |
|
1254 // Move from the end to the start |
|
1255 QTest::newRow("move06") << 8 << 9 << 0; |
|
1256 // Move from the middle to the middle |
|
1257 QTest::newRow("move07") << 6 << 8 << 2; |
|
1258 // Move from the end to the middle |
|
1259 QTest::newRow("move08") << 8 << 9 << 5; |
|
1260 |
|
1261 // Moving to the same row in a different parent doesn't confuse things. |
|
1262 QTest::newRow("move09") << 8 << 8 << 8; |
|
1263 |
|
1264 // Moving to the row of my target and its neighbours doesn't confuse things |
|
1265 QTest::newRow("move09") << 8 << 8 << 4; |
|
1266 QTest::newRow("move10") << 8 << 8 << 5; |
|
1267 QTest::newRow("move11") << 8 << 8 << 6; |
|
1268 } |
|
1269 |
|
1270 void tst_QAbstractItemModel::testMoveToSibling() |
|
1271 { |
|
1272 |
|
1273 QFETCH( int, startRow); |
|
1274 QFETCH( int, endRow); |
|
1275 QFETCH( int, destRow); |
|
1276 |
|
1277 QList<QPersistentModelIndex> persistentList; |
|
1278 QModelIndexList indexList; |
|
1279 QModelIndexList parentsList; |
|
1280 |
|
1281 const int column = 0; |
|
1282 |
|
1283 for (int i= 0; i < m_model->rowCount(); ++i) |
|
1284 { |
|
1285 QModelIndex idx = m_model->index(i, column); |
|
1286 QVERIFY(idx.isValid()); |
|
1287 indexList << idx; |
|
1288 parentsList << idx.parent(); |
|
1289 persistentList << QPersistentModelIndex(idx); |
|
1290 } |
|
1291 |
|
1292 QModelIndex destIndex = m_model->index(5, 0); |
|
1293 QModelIndex sourceIndex; |
|
1294 for (int i= 0; i < m_model->rowCount(destIndex); ++i) |
|
1295 { |
|
1296 QModelIndex idx = m_model->index(i, column, destIndex); |
|
1297 QVERIFY(idx.isValid()); |
|
1298 indexList << idx; |
|
1299 parentsList << idx.parent(); |
|
1300 persistentList << QPersistentModelIndex(idx); |
|
1301 } |
|
1302 |
|
1303 QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1304 QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1305 |
|
1306 |
|
1307 ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); |
|
1308 moveCommand->setNumCols(4); |
|
1309 moveCommand->setStartRow(startRow); |
|
1310 moveCommand->setEndRow(endRow); |
|
1311 moveCommand->setDestAncestors(QList<int>() << 5); |
|
1312 moveCommand->setDestRow(destRow); |
|
1313 moveCommand->doCommand(); |
|
1314 |
|
1315 QVariantList beforeSignal = beforeSpy.takeAt(0); |
|
1316 QVariantList afterSignal = afterSpy.takeAt(0); |
|
1317 |
|
1318 QCOMPARE(beforeSignal.size(), 5); |
|
1319 QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), sourceIndex); |
|
1320 QCOMPARE(beforeSignal.at(1).toInt(), startRow); |
|
1321 QCOMPARE(beforeSignal.at(2).toInt(), endRow); |
|
1322 QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), destIndex); |
|
1323 QCOMPARE(beforeSignal.at(4).toInt(), destRow); |
|
1324 |
|
1325 QCOMPARE(afterSignal.size(), 5); |
|
1326 QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex); |
|
1327 QCOMPARE(afterSignal.at(1).toInt(), startRow); |
|
1328 QCOMPARE(afterSignal.at(2).toInt(), endRow); |
|
1329 QCOMPARE(afterSignal.at(3).value<QModelIndex>(), destIndex); |
|
1330 QCOMPARE(afterSignal.at(4).toInt(), destRow); |
|
1331 |
|
1332 for (int i = 0; i < indexList.size(); i++) |
|
1333 { |
|
1334 QModelIndex idx = indexList.at(i); |
|
1335 QModelIndex idxParent = parentsList.at(i); |
|
1336 QModelIndex persistentIndex = persistentList.at(i); |
|
1337 |
|
1338 QModelIndex adjustedDestination = destIndex.sibling(destIndex.row() - (endRow - startRow + 1), destIndex.column()); |
|
1339 int row = idx.row(); |
|
1340 if (idxParent == destIndex) |
|
1341 { |
|
1342 if ( row >= destRow) |
|
1343 { |
|
1344 QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() ); |
|
1345 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1346 if (idxParent.row() > startRow) |
|
1347 { |
|
1348 QCOMPARE(adjustedDestination, persistentIndex.parent()); |
|
1349 } else { |
|
1350 QCOMPARE(destIndex, persistentIndex.parent()); |
|
1351 } |
|
1352 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1353 } else |
|
1354 { |
|
1355 QCOMPARE(idx, persistentIndex); |
|
1356 } |
|
1357 } else |
|
1358 { |
|
1359 if (row < startRow) |
|
1360 { |
|
1361 QCOMPARE(idx, persistentIndex); |
|
1362 } else if (row <= endRow) |
|
1363 { |
|
1364 QCOMPARE(row + destRow - startRow, persistentIndex.row() ); |
|
1365 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1366 if (destIndex.row() > startRow) |
|
1367 { |
|
1368 QCOMPARE(adjustedDestination, persistentIndex.parent()); |
|
1369 } else { |
|
1370 QCOMPARE(destIndex, persistentIndex.parent()); |
|
1371 } |
|
1372 |
|
1373 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1374 |
|
1375 } else { |
|
1376 QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() ); |
|
1377 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1378 QCOMPARE(idxParent, persistentIndex.parent()); |
|
1379 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1380 } |
|
1381 } |
|
1382 } |
|
1383 } |
|
1384 |
|
1385 void tst_QAbstractItemModel::testMoveToUncle_data() |
|
1386 { |
|
1387 |
|
1388 QTest::addColumn<int>("startRow"); |
|
1389 QTest::addColumn<int>("endRow"); |
|
1390 QTest::addColumn<int>("destRow"); |
|
1391 |
|
1392 // Move from the start to the middle |
|
1393 QTest::newRow("move01") << 0 << 2 << 8; |
|
1394 // Move from the start to the end |
|
1395 QTest::newRow("move02") << 0 << 2 << 10; |
|
1396 // Move from the middle to the middle |
|
1397 QTest::newRow("move03") << 3 << 5 << 8; |
|
1398 // Move from the middle to the end |
|
1399 QTest::newRow("move04") << 3 << 5 << 10; |
|
1400 |
|
1401 // Move from the middle to the start |
|
1402 QTest::newRow("move05") << 5 << 7 << 0; |
|
1403 // Move from the end to the start |
|
1404 QTest::newRow("move06") << 8 << 9 << 0; |
|
1405 // Move from the middle to the middle |
|
1406 QTest::newRow("move07") << 5 << 7 << 2; |
|
1407 // Move from the end to the middle |
|
1408 QTest::newRow("move08") << 8 << 9 << 5; |
|
1409 |
|
1410 // Moving to the same row in a different parent doesn't confuse things. |
|
1411 QTest::newRow("move09") << 8 << 8 << 8; |
|
1412 |
|
1413 // Moving to the row of my parent and its neighbours doesn't confuse things |
|
1414 QTest::newRow("move09") << 8 << 8 << 4; |
|
1415 QTest::newRow("move10") << 8 << 8 << 5; |
|
1416 QTest::newRow("move11") << 8 << 8 << 6; |
|
1417 |
|
1418 // Moving everything from one parent to another |
|
1419 QTest::newRow("move12") << 0 << 9 << 10; |
|
1420 } |
|
1421 |
|
1422 void tst_QAbstractItemModel::testMoveToUncle() |
|
1423 { |
|
1424 // Need to have some extra rows available. |
|
1425 ModelInsertCommand *insertCommand = new ModelInsertCommand(m_model, this); |
|
1426 insertCommand->setAncestorRowNumbers(QList<int>() << 9); |
|
1427 insertCommand->setNumCols(4); |
|
1428 insertCommand->setStartRow(0); |
|
1429 insertCommand->setEndRow(9); |
|
1430 insertCommand->doCommand(); |
|
1431 |
|
1432 QFETCH( int, startRow); |
|
1433 QFETCH( int, endRow); |
|
1434 QFETCH( int, destRow); |
|
1435 |
|
1436 QList<QPersistentModelIndex> persistentList; |
|
1437 QModelIndexList indexList; |
|
1438 QModelIndexList parentsList; |
|
1439 |
|
1440 const int column = 0; |
|
1441 |
|
1442 QModelIndex sourceIndex = m_model->index(9, 0); |
|
1443 for (int i= 0; i < m_model->rowCount(sourceIndex); ++i) |
|
1444 { |
|
1445 QModelIndex idx = m_model->index(i, column, sourceIndex); |
|
1446 QVERIFY(idx.isValid()); |
|
1447 indexList << idx; |
|
1448 parentsList << idx.parent(); |
|
1449 persistentList << QPersistentModelIndex(idx); |
|
1450 } |
|
1451 |
|
1452 QModelIndex destIndex = m_model->index(5, 0); |
|
1453 for (int i= 0; i < m_model->rowCount(destIndex); ++i) |
|
1454 { |
|
1455 QModelIndex idx = m_model->index(i, column, destIndex); |
|
1456 QVERIFY(idx.isValid()); |
|
1457 indexList << idx; |
|
1458 parentsList << idx.parent(); |
|
1459 persistentList << QPersistentModelIndex(idx); |
|
1460 } |
|
1461 |
|
1462 QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1463 QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1464 |
|
1465 ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); |
|
1466 moveCommand->setAncestorRowNumbers(QList<int>() << 9); |
|
1467 moveCommand->setNumCols(4); |
|
1468 moveCommand->setStartRow(startRow); |
|
1469 moveCommand->setEndRow(endRow); |
|
1470 moveCommand->setDestAncestors(QList<int>() << 5); |
|
1471 moveCommand->setDestRow(destRow); |
|
1472 moveCommand->doCommand(); |
|
1473 |
|
1474 QVariantList beforeSignal = beforeSpy.takeAt(0); |
|
1475 QVariantList afterSignal = afterSpy.takeAt(0); |
|
1476 |
|
1477 QCOMPARE(beforeSignal.size(), 5); |
|
1478 QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), sourceIndex); |
|
1479 QCOMPARE(beforeSignal.at(1).toInt(), startRow); |
|
1480 QCOMPARE(beforeSignal.at(2).toInt(), endRow); |
|
1481 QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), destIndex); |
|
1482 QCOMPARE(beforeSignal.at(4).toInt(), destRow); |
|
1483 |
|
1484 QCOMPARE(afterSignal.size(), 5); |
|
1485 QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex); |
|
1486 QCOMPARE(afterSignal.at(1).toInt(), startRow); |
|
1487 QCOMPARE(afterSignal.at(2).toInt(), endRow); |
|
1488 QCOMPARE(afterSignal.at(3).value<QModelIndex>(), destIndex); |
|
1489 QCOMPARE(afterSignal.at(4).toInt(), destRow); |
|
1490 |
|
1491 for (int i = 0; i < indexList.size(); i++) |
|
1492 { |
|
1493 QModelIndex idx = indexList.at(i); |
|
1494 QModelIndex idxParent = parentsList.at(i); |
|
1495 QModelIndex persistentIndex = persistentList.at(i); |
|
1496 |
|
1497 int row = idx.row(); |
|
1498 if (idxParent == destIndex) |
|
1499 { |
|
1500 if ( row >= destRow) |
|
1501 { |
|
1502 QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() ); |
|
1503 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1504 QCOMPARE(destIndex, persistentIndex.parent()); |
|
1505 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1506 } else |
|
1507 { |
|
1508 QCOMPARE(idx, persistentIndex); |
|
1509 } |
|
1510 } else |
|
1511 { |
|
1512 if (row < startRow) |
|
1513 { |
|
1514 QCOMPARE(idx, persistentIndex); |
|
1515 } else if (row <= endRow) |
|
1516 { |
|
1517 QCOMPARE(row + destRow - startRow, persistentIndex.row() ); |
|
1518 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1519 QCOMPARE(destIndex, persistentIndex.parent()); |
|
1520 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1521 |
|
1522 } else { |
|
1523 QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() ); |
|
1524 QCOMPARE(idx.column(), persistentIndex.column()); |
|
1525 QCOMPARE(idxParent, persistentIndex.parent()); |
|
1526 QCOMPARE(idx.model(), persistentIndex.model()); |
|
1527 } |
|
1528 } |
|
1529 } |
|
1530 } |
|
1531 |
|
1532 void tst_QAbstractItemModel::testMoveToDescendants() |
|
1533 { |
|
1534 // Attempt to move a row to its ancestors depth rows deep. |
|
1535 const int depth = 6; |
|
1536 |
|
1537 // Need to have some extra rows available in a tree. |
|
1538 QList<int> rows; |
|
1539 ModelInsertCommand *insertCommand; |
|
1540 for (int i = 0; i < depth; i++) |
|
1541 { |
|
1542 insertCommand = new ModelInsertCommand(m_model, this); |
|
1543 insertCommand->setAncestorRowNumbers(rows); |
|
1544 insertCommand->setNumCols(4); |
|
1545 insertCommand->setStartRow(0); |
|
1546 insertCommand->setEndRow(9); |
|
1547 insertCommand->doCommand(); |
|
1548 rows << 9; |
|
1549 } |
|
1550 |
|
1551 QList<QPersistentModelIndex> persistentList; |
|
1552 QModelIndexList indexList; |
|
1553 QModelIndexList parentsList; |
|
1554 |
|
1555 const int column = 0; |
|
1556 |
|
1557 QModelIndex sourceIndex = m_model->index(9, 0); |
|
1558 for (int i= 0; i < m_model->rowCount(sourceIndex); ++i) |
|
1559 { |
|
1560 QModelIndex idx = m_model->index(i, column, sourceIndex); |
|
1561 QVERIFY(idx.isValid()); |
|
1562 indexList << idx; |
|
1563 parentsList << idx.parent(); |
|
1564 persistentList << QPersistentModelIndex(idx); |
|
1565 } |
|
1566 |
|
1567 QModelIndex destIndex = m_model->index(5, 0); |
|
1568 for (int i= 0; i < m_model->rowCount(destIndex); ++i) |
|
1569 { |
|
1570 QModelIndex idx = m_model->index(i, column, destIndex); |
|
1571 QVERIFY(idx.isValid()); |
|
1572 indexList << idx; |
|
1573 parentsList << idx.parent(); |
|
1574 persistentList << QPersistentModelIndex(idx); |
|
1575 } |
|
1576 |
|
1577 QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1578 QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1579 |
|
1580 ModelMoveCommand *moveCommand; |
|
1581 QList<int> ancestors; |
|
1582 while (ancestors.size() < depth) |
|
1583 { |
|
1584 ancestors << 9; |
|
1585 for (int row = 0; row <= 9; row++) |
|
1586 { |
|
1587 moveCommand = new ModelMoveCommand(m_model, this); |
|
1588 moveCommand->setNumCols(4); |
|
1589 moveCommand->setStartRow(9); |
|
1590 moveCommand->setEndRow(9); |
|
1591 moveCommand->setDestAncestors(ancestors); |
|
1592 moveCommand->setDestRow(row); |
|
1593 moveCommand->doCommand(); |
|
1594 |
|
1595 QVERIFY(beforeSpy.size() == 0); |
|
1596 QVERIFY(afterSpy.size() == 0); |
|
1597 } |
|
1598 } |
|
1599 } |
|
1600 |
|
1601 void tst_QAbstractItemModel::testMoveWithinOwnRange_data() |
|
1602 { |
|
1603 QTest::addColumn<int>("startRow"); |
|
1604 QTest::addColumn<int>("endRow"); |
|
1605 QTest::addColumn<int>("destRow"); |
|
1606 |
|
1607 QTest::newRow("move01") << 0 << 0 << 0; |
|
1608 QTest::newRow("move02") << 0 << 0 << 1; |
|
1609 QTest::newRow("move03") << 0 << 5 << 0; |
|
1610 QTest::newRow("move04") << 0 << 5 << 1; |
|
1611 QTest::newRow("move05") << 0 << 5 << 2; |
|
1612 QTest::newRow("move06") << 0 << 5 << 3; |
|
1613 QTest::newRow("move07") << 0 << 5 << 4; |
|
1614 QTest::newRow("move08") << 0 << 5 << 5; |
|
1615 QTest::newRow("move09") << 0 << 5 << 6; |
|
1616 QTest::newRow("move08") << 3 << 5 << 5; |
|
1617 QTest::newRow("move08") << 3 << 5 << 6; |
|
1618 QTest::newRow("move09") << 4 << 5 << 5; |
|
1619 QTest::newRow("move10") << 4 << 5 << 6; |
|
1620 QTest::newRow("move11") << 5 << 5 << 5; |
|
1621 QTest::newRow("move12") << 5 << 5 << 6; |
|
1622 QTest::newRow("move13") << 5 << 9 << 9; |
|
1623 QTest::newRow("move14") << 5 << 9 << 10; |
|
1624 QTest::newRow("move15") << 6 << 9 << 9; |
|
1625 QTest::newRow("move16") << 6 << 9 << 10; |
|
1626 QTest::newRow("move17") << 7 << 9 << 9; |
|
1627 QTest::newRow("move18") << 7 << 9 << 10; |
|
1628 QTest::newRow("move19") << 8 << 9 << 9; |
|
1629 QTest::newRow("move20") << 8 << 9 << 10; |
|
1630 QTest::newRow("move21") << 9 << 9 << 9; |
|
1631 QTest::newRow("move22") << 0 << 9 << 10; |
|
1632 |
|
1633 } |
|
1634 |
|
1635 void tst_QAbstractItemModel::testMoveWithinOwnRange() |
|
1636 { |
|
1637 |
|
1638 QFETCH( int, startRow); |
|
1639 QFETCH( int, endRow); |
|
1640 QFETCH( int, destRow); |
|
1641 |
|
1642 |
|
1643 QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1644 QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int))); |
|
1645 |
|
1646 ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); |
|
1647 moveCommand->setNumCols(4); |
|
1648 moveCommand->setStartRow(startRow); |
|
1649 moveCommand->setEndRow(endRow); |
|
1650 moveCommand->setDestRow(destRow); |
|
1651 moveCommand->doCommand(); |
|
1652 |
|
1653 QVERIFY(beforeSpy.size() == 0); |
|
1654 QVERIFY(afterSpy.size() == 0); |
|
1655 |
|
1656 |
|
1657 } |
|
1658 |
|
1659 class ListenerObject : public QObject |
|
1660 { |
|
1661 Q_OBJECT |
|
1662 public: |
|
1663 ListenerObject(QAbstractProxyModel *parent); |
|
1664 |
|
1665 protected: |
|
1666 void fillIndexStores(const QModelIndex &parent); |
|
1667 |
|
1668 public slots: |
|
1669 void slotAboutToBeReset(); |
|
1670 void slotReset(); |
|
1671 |
|
1672 private: |
|
1673 QAbstractProxyModel *m_model; |
|
1674 QList<QPersistentModelIndex> m_persistentIndexes; |
|
1675 QModelIndexList m_nonPersistentIndexes; |
|
1676 }; |
|
1677 |
|
1678 |
|
1679 ListenerObject::ListenerObject(QAbstractProxyModel *parent) |
|
1680 : QObject(parent), m_model(parent) |
|
1681 { |
|
1682 connect(m_model, SIGNAL(modelAboutToBeReset()), SLOT(slotAboutToBeReset())); |
|
1683 connect(m_model, SIGNAL(modelReset()), SLOT(slotReset())); |
|
1684 |
|
1685 fillIndexStores(QModelIndex()); |
|
1686 } |
|
1687 |
|
1688 void ListenerObject::fillIndexStores(const QModelIndex &parent) |
|
1689 { |
|
1690 const int column = 0; |
|
1691 int row = 0; |
|
1692 QModelIndex idx = m_model->index(row, column, parent); |
|
1693 while (idx.isValid()) |
|
1694 { |
|
1695 m_persistentIndexes << QPersistentModelIndex(idx); |
|
1696 m_nonPersistentIndexes << idx; |
|
1697 if (m_model->hasChildren(idx)) |
|
1698 { |
|
1699 fillIndexStores(idx); |
|
1700 } |
|
1701 ++row; |
|
1702 idx = m_model->index(row, column, parent); |
|
1703 } |
|
1704 } |
|
1705 |
|
1706 void ListenerObject::slotAboutToBeReset() |
|
1707 { |
|
1708 // Nothing has been changed yet. All indexes should be the same. |
|
1709 for (int i = 0; i < m_persistentIndexes.size(); ++i) |
|
1710 { |
|
1711 QModelIndex idx = m_persistentIndexes.at(i); |
|
1712 QVERIFY(idx == m_nonPersistentIndexes.at(i)); |
|
1713 QVERIFY(m_model->mapToSource(idx).isValid()); |
|
1714 } |
|
1715 } |
|
1716 |
|
1717 void ListenerObject::slotReset() |
|
1718 { |
|
1719 foreach(const QModelIndex &idx, m_persistentIndexes) |
|
1720 { |
|
1721 QVERIFY(!idx.isValid()); |
|
1722 } |
|
1723 } |
|
1724 |
|
1725 |
|
1726 void tst_QAbstractItemModel::testReset() |
|
1727 { |
|
1728 QSignalSpy beforeResetSpy(m_model, SIGNAL(modelAboutToBeReset())); |
|
1729 QSignalSpy afterResetSpy(m_model, SIGNAL(modelReset())); |
|
1730 |
|
1731 |
|
1732 QSortFilterProxyModel *nullProxy = new QSortFilterProxyModel(this); |
|
1733 nullProxy->setSourceModel(m_model); |
|
1734 |
|
1735 // Makes sure the model and proxy are in a consistent state. before and after reset. |
|
1736 new ListenerObject(nullProxy); |
|
1737 |
|
1738 ModelResetCommandFixed *resetCommand = new ModelResetCommandFixed(m_model, this); |
|
1739 |
|
1740 resetCommand->setNumCols(4); |
|
1741 resetCommand->setStartRow(0); |
|
1742 resetCommand->setEndRow(0); |
|
1743 resetCommand->setDestRow(0); |
|
1744 resetCommand->setDestAncestors(QList<int>() << 5); |
|
1745 resetCommand->doCommand(); |
|
1746 |
|
1747 // Verify that the correct signals were emitted |
|
1748 QVERIFY(beforeResetSpy.size() == 1); |
|
1749 QVERIFY(afterResetSpy.size() == 1); |
|
1750 |
|
1751 // Verify that the move actually happened. |
|
1752 QVERIFY(m_model->rowCount() == 9); |
|
1753 QModelIndex destIndex = m_model->index(4, 0); |
|
1754 QVERIFY(m_model->rowCount(destIndex) == 11); |
|
1755 |
|
1756 } |
|
1757 |
|
1758 |
|
1759 QTEST_MAIN(tst_QAbstractItemModel) |
|
1760 #include "tst_qabstractitemmodel.moc" |