1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL21$
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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** $QT_END_LICENSE$
31 **
32 ****************************************************************************/
33
34 #include "modeltest.h"
35
36 #include <QtCore>
37 #include <QtTest>
38
39 /*!
40 Connect to all of the models signals. Whenever anything happens recheck everything.
41 */
ModelTest(QAbstractItemModel * _model,QObject * parent)42 ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false )
43 {
44 if (!model)
45 qFatal("%s: model must not be null", Q_FUNC_INFO);
46
47 connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
48 this, SLOT(runAllTests()) );
49 connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
50 this, SLOT(runAllTests()) );
51 connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
52 this, SLOT(runAllTests()) );
53 connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
54 this, SLOT(runAllTests()) );
55 connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
56 this, SLOT(runAllTests()) );
57 connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
58 this, SLOT(runAllTests()) );
59 connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests()) );
60 connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests()) );
61 connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests()) );
62 connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
63 this, SLOT(runAllTests()) );
64 connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
65 this, SLOT(runAllTests()) );
66 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
67 this, SLOT(runAllTests()) );
68 connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
69 this, SLOT(runAllTests()) );
70
71 // Special checks for changes
72 connect(model, SIGNAL(layoutAboutToBeChanged()),
73 this, SLOT(layoutAboutToBeChanged()) );
74 connect(model, SIGNAL(layoutChanged()),
75 this, SLOT(layoutChanged()) );
76
77 connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
78 this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)) );
79 connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
80 this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)) );
81 connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
82 this, SLOT(rowsInserted(QModelIndex,int,int)) );
83 connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
84 this, SLOT(rowsRemoved(QModelIndex,int,int)) );
85 connect(model, SIGNAL (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
86 this, SLOT (rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)) );
87 connect(model, SIGNAL (rowsMoved(QModelIndex,int,int,QModelIndex,int)),
88 this, SLOT (rowsMoved(QModelIndex,int,int,QModelIndex,int)) );
89 connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
90 this, SLOT(dataChanged(QModelIndex,QModelIndex)) );
91 connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
92 this, SLOT(headerDataChanged(Qt::Orientation,int,int)) );
93
94 runAllTests();
95 }
96
runAllTests()97 void ModelTest::runAllTests()
98 {
99 if ( fetchingMore )
100 return;
101 nonDestructiveBasicTest();
102 rowCount();
103 columnCount();
104 hasIndex();
105 index();
106 parent();
107 data();
108 }
109
110 /*!
111 nonDestructiveBasicTest tries to call a number of the basic functions (not all)
112 to make sure the model doesn't outright segfault, testing the functions that makes sense.
113 */
nonDestructiveBasicTest()114 void ModelTest::nonDestructiveBasicTest()
115 {
116 QVERIFY( model->buddy ( QModelIndex() ) == QModelIndex() );
117 model->canFetchMore ( QModelIndex() );
118 QVERIFY( model->columnCount ( QModelIndex() ) >= 0 );
119 QVERIFY( model->data ( QModelIndex() ) == QVariant() );
120 fetchingMore = true;
121 model->fetchMore ( QModelIndex() );
122 fetchingMore = false;
123 Qt::ItemFlags flags = model->flags ( QModelIndex() );
124 QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 );
125 model->hasChildren ( QModelIndex() );
126 model->hasIndex ( 0, 0 );
127 model->headerData ( 0, Qt::Horizontal );
128 model->index ( 0, 0 );
129 model->itemData ( QModelIndex() );
130 QVariant cache;
131 model->match ( QModelIndex(), -1, cache );
132 model->mimeTypes();
133 QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() );
134 QVERIFY( model->rowCount() >= 0 );
135 QVariant variant;
136 model->setData ( QModelIndex(), variant, -1 );
137 model->setHeaderData ( -1, Qt::Horizontal, QVariant() );
138 model->setHeaderData ( 999999, Qt::Horizontal, QVariant() );
139 QMap<int, QVariant> roles;
140 model->sibling ( 0, 0, QModelIndex() );
141 model->span ( QModelIndex() );
142 model->supportedDropActions();
143 }
144
145 /*!
146 Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren()
147
148 Models that are dynamically populated are not as fully tested here.
149 */
rowCount()150 void ModelTest::rowCount()
151 {
152 // qDebug() << "rc";
153 // check top row
154 QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
155 int rows = model->rowCount ( topIndex );
156 QVERIFY( rows >= 0 );
157 if ( rows > 0 )
158 QVERIFY( model->hasChildren ( topIndex ) );
159
160 QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex );
161 if ( secondLevelIndex.isValid() ) { // not the top level
162 // check a row count where parent is valid
163 rows = model->rowCount ( secondLevelIndex );
164 QVERIFY( rows >= 0 );
165 if ( rows > 0 )
166 QVERIFY( model->hasChildren ( secondLevelIndex ) );
167 }
168
169 // The models rowCount() is tested more extensively in checkChildren(),
170 // but this catches the big mistakes
171 }
172
173 /*!
174 Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren()
175 */
columnCount()176 void ModelTest::columnCount()
177 {
178 // check top row
179 QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
180 QVERIFY( model->columnCount ( topIndex ) >= 0 );
181
182 // check a column count where parent is valid
183 QModelIndex childIndex = model->index ( 0, 0, topIndex );
184 if ( childIndex.isValid() )
185 QVERIFY( model->columnCount ( childIndex ) >= 0 );
186
187 // columnCount() is tested more extensively in checkChildren(),
188 // but this catches the big mistakes
189 }
190
191 /*!
192 Tests model's implementation of QAbstractItemModel::hasIndex()
193 */
hasIndex()194 void ModelTest::hasIndex()
195 {
196 // qDebug() << "hi";
197 // Make sure that invalid values returns an invalid index
198 QVERIFY( !model->hasIndex ( -2, -2 ) );
199 QVERIFY( !model->hasIndex ( -2, 0 ) );
200 QVERIFY( !model->hasIndex ( 0, -2 ) );
201
202 int rows = model->rowCount();
203 int columns = model->columnCount();
204
205 // check out of bounds
206 QVERIFY( !model->hasIndex ( rows, columns ) );
207 QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) );
208
209 if ( rows > 0 )
210 QVERIFY( model->hasIndex ( 0, 0 ) );
211
212 // hasIndex() is tested more extensively in checkChildren(),
213 // but this catches the big mistakes
214 }
215
216 /*!
217 Tests model's implementation of QAbstractItemModel::index()
218 */
index()219 void ModelTest::index()
220 {
221 // qDebug() << "i";
222 // Make sure that invalid values returns an invalid index
223 QVERIFY( model->index ( -2, -2 ) == QModelIndex() );
224 QVERIFY( model->index ( -2, 0 ) == QModelIndex() );
225 QVERIFY( model->index ( 0, -2 ) == QModelIndex() );
226
227 int rows = model->rowCount();
228 int columns = model->columnCount();
229
230 if ( rows == 0 )
231 return;
232
233 // Catch off by one errors
234 QVERIFY( model->index ( rows, columns ) == QModelIndex() );
235 QVERIFY( model->index ( 0, 0 ).isValid() );
236
237 // Make sure that the same index is *always* returned
238 QModelIndex a = model->index ( 0, 0 );
239 QModelIndex b = model->index ( 0, 0 );
240 QVERIFY( a == b );
241
242 // index() is tested more extensively in checkChildren(),
243 // but this catches the big mistakes
244 }
245
246 /*!
247 Tests model's implementation of QAbstractItemModel::parent()
248 */
parent()249 void ModelTest::parent()
250 {
251 // qDebug() << "p";
252 // Make sure the model won't crash and will return an invalid QModelIndex
253 // when asked for the parent of an invalid index.
254 QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() );
255
256 if ( model->rowCount() == 0 )
257 return;
258
259 // Column 0 | Column 1 |
260 // QModelIndex() | |
261 // \- topIndex | topIndex1 |
262 // \- childIndex | childIndex1 |
263
264 // Common error test #1, make sure that a top level index has a parent
265 // that is a invalid QModelIndex.
266 QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
267 QVERIFY( model->parent ( topIndex ) == QModelIndex() );
268
269 // Common error test #2, make sure that a second level index has a parent
270 // that is the first level index.
271 if ( model->rowCount ( topIndex ) > 0 ) {
272 QModelIndex childIndex = model->index ( 0, 0, topIndex );
273 QVERIFY( model->parent ( childIndex ) == topIndex );
274 }
275
276 // Common error test #3, the second column should NOT have the same children
277 // as the first column in a row.
278 // Usually the second column shouldn't have children.
279 QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() );
280 if ( model->rowCount ( topIndex1 ) > 0 ) {
281 QModelIndex childIndex = model->index ( 0, 0, topIndex );
282 QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 );
283 QVERIFY( childIndex != childIndex1 );
284 }
285
286 // Full test, walk n levels deep through the model making sure that all
287 // parent's children correctly specify their parent.
288 checkChildren ( QModelIndex() );
289 }
290
291 /*!
292 Called from the parent() test.
293
294 A model that returns an index of parent X should also return X when asking
295 for the parent of the index.
296
297 This recursive function does pretty extensive testing on the whole model in an
298 effort to catch edge cases.
299
300 This function assumes that rowCount(), columnCount() and index() already work.
301 If they have a bug it will point it out, but the above tests should have already
302 found the basic bugs because it is easier to figure out the problem in
303 those tests then this one.
304 */
checkChildren(const QModelIndex & parent,int currentDepth)305 void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
306 {
307 // First just try walking back up the tree.
308 QModelIndex p = parent;
309 while ( p.isValid() )
310 p = p.parent();
311
312 // For models that are dynamically populated
313 if ( model->canFetchMore ( parent ) ) {
314 fetchingMore = true;
315 model->fetchMore ( parent );
316 fetchingMore = false;
317 }
318
319 int rows = model->rowCount ( parent );
320 int columns = model->columnCount ( parent );
321
322 if ( rows > 0 )
323 QVERIFY( model->hasChildren ( parent ) );
324
325 // Some further testing against rows(), columns(), and hasChildren()
326 QVERIFY( rows >= 0 );
327 QVERIFY( columns >= 0 );
328 if ( rows > 0 )
329 QVERIFY( model->hasChildren ( parent ) );
330
331 //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
332 // << "columns:" << columns << "parent column:" << parent.column();
333
334 const QModelIndex topLeftChild = model->index( 0, 0, parent );
335
336 QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) );
337 for ( int r = 0; r < rows; ++r ) {
338 if ( model->canFetchMore ( parent ) ) {
339 fetchingMore = true;
340 model->fetchMore ( parent );
341 fetchingMore = false;
342 }
343 QVERIFY( !model->hasIndex ( r, columns + 1, parent ) );
344 for ( int c = 0; c < columns; ++c ) {
345 QVERIFY( model->hasIndex ( r, c, parent ) );
346 QModelIndex index = model->index ( r, c, parent );
347 // rowCount() and columnCount() said that it existed...
348 QVERIFY( index.isValid() );
349
350 // index() should always return the same index when called twice in a row
351 QModelIndex modifiedIndex = model->index ( r, c, parent );
352 QVERIFY( index == modifiedIndex );
353
354 // Make sure we get the same index if we request it twice in a row
355 QModelIndex a = model->index ( r, c, parent );
356 QModelIndex b = model->index ( r, c, parent );
357 QVERIFY( a == b );
358
359 {
360 const QModelIndex sibling = model->sibling( r, c, topLeftChild );
361 QVERIFY( index == sibling );
362 }
363 {
364 const QModelIndex sibling = topLeftChild.sibling( r, c );
365 QVERIFY( index == sibling );
366 }
367
368 // Some basic checking on the index that is returned
369 QVERIFY( index.model() == model );
370 QCOMPARE( index.row(), r );
371 QCOMPARE( index.column(), c );
372 // While you can technically return a QVariant usually this is a sign
373 // of a bug in data(). Disable if this really is ok in your model.
374 // QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() );
375
376 // If the next test fails here is some somewhat useful debug you play with.
377
378 if (model->parent(index) != parent) {
379 qDebug() << r << c << currentDepth << model->data(index).toString()
380 << model->data(parent).toString();
381 qDebug() << index << parent << model->parent(index);
382 // And a view that you can even use to show the model.
383 // QTreeView view;
384 // view.setModel(model);
385 // view.show();
386 }
387
388 // Check that we can get back our real parent.
389 QCOMPARE( model->parent ( index ), parent );
390
391 // recursively go down the children
392 if ( model->hasChildren ( index ) && currentDepth < 10 ) {
393 //qDebug() << r << c << "has children" << model->rowCount(index);
394 checkChildren ( index, ++currentDepth );
395 }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
396
397 // make sure that after testing the children that the index doesn't change.
398 QModelIndex newerIndex = model->index ( r, c, parent );
399 QVERIFY( index == newerIndex );
400 }
401 }
402 }
403
404 /*!
405 Tests model's implementation of QAbstractItemModel::data()
406 */
data()407 void ModelTest::data()
408 {
409 // Invalid index should return an invalid qvariant
410 QVERIFY( !model->data ( QModelIndex() ).isValid() );
411
412 if ( model->rowCount() == 0 )
413 return;
414
415 // A valid index should have a valid QVariant data
416 QVERIFY( model->index ( 0, 0 ).isValid() );
417
418 // shouldn't be able to set data on an invalid index
419 QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) );
420
421 // General Purpose roles that should return a QString
422 QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole );
423 if ( variant.isValid() ) {
424 QVERIFY( variant.canConvert<QString>() );
425 }
426 variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole );
427 if ( variant.isValid() ) {
428 QVERIFY( variant.canConvert<QString>() );
429 }
430 variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole );
431 if ( variant.isValid() ) {
432 QVERIFY( variant.canConvert<QString>() );
433 }
434
435 // General Purpose roles that should return a QSize
436 variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole );
437 if ( variant.isValid() ) {
438 QVERIFY( variant.canConvert<QSize>() );
439 }
440
441 // General Purpose roles that should return a QFont
442 QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole );
443 if ( fontVariant.isValid() ) {
444 QVERIFY( fontVariant.canConvert<QFont>() );
445 }
446
447 // Check that the alignment is one we know about
448 QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole );
449 if ( textAlignmentVariant.isValid() ) {
450 int alignment = textAlignmentVariant.toInt();
451 QCOMPARE( alignment, static_cast<int>( alignment & ( Qt::AlignHorizontal_Mask
452 | Qt::AlignVertical_Mask ) ) );
453 }
454
455 // General Purpose roles that should return a QColor
456 QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole );
457 if ( colorVariant.isValid() ) {
458 QVERIFY( colorVariant.canConvert<QColor>() );
459 }
460
461 colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole );
462 if ( colorVariant.isValid() ) {
463 QVERIFY( colorVariant.canConvert<QColor>() );
464 }
465
466 // Check that the "check state" is one we know about.
467 QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole );
468 if ( checkStateVariant.isValid() ) {
469 int state = checkStateVariant.toInt();
470 QVERIFY( state == Qt::Unchecked ||
471 state == Qt::PartiallyChecked ||
472 state == Qt::Checked );
473 }
474 }
475
476 /*!
477 Store what is about to be inserted to make sure it actually happens
478
479 \sa rowsInserted()
480 */
rowsAboutToBeInserted(const QModelIndex & parent,int start,int)481 void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */)
482 {
483 // Q_UNUSED(end);
484 // qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString()
485 // << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) );
486 // qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) );
487 Changing c;
488 c.parent = parent;
489 c.oldSize = model->rowCount ( parent );
490 c.last = model->data ( model->index ( start - 1, 0, parent ) );
491 c.next = model->data ( model->index ( start, 0, parent ) );
492 insert.push ( c );
493 }
494
495 /*!
496 Confirm that what was said was going to happen actually did
497
498 \sa rowsAboutToBeInserted()
499 */
rowsInserted(const QModelIndex & parent,int start,int end)500 void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end )
501 {
502 Changing c = insert.pop();
503 QVERIFY( c.parent == parent );
504 // qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize
505 // << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent );
506
507 // for (int ii=start; ii <= end; ii++)
508 // {
509 // qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent ));
510 // }
511 // qDebug();
512
513 QVERIFY( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) );
514 QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
515
516 if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
517 qDebug() << start << end;
518 for (int i=0; i < model->rowCount(); ++i)
519 qDebug() << model->index(i, 0).data().toString();
520 qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
521 }
522
523 QVERIFY( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) );
524 }
525
layoutAboutToBeChanged()526 void ModelTest::layoutAboutToBeChanged()
527 {
528 for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i )
529 changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) );
530 }
531
layoutChanged()532 void ModelTest::layoutChanged()
533 {
534 for ( int i = 0; i < changing.count(); ++i ) {
535 QPersistentModelIndex p = changing[i];
536 QVERIFY( p == model->index ( p.row(), p.column(), p.parent() ) );
537 }
538 changing.clear();
539 }
540
541 /*!
542 Store what is about to be inserted to make sure it actually happens
543
544 \sa rowsRemoved()
545 */
rowsAboutToBeRemoved(const QModelIndex & parent,int start,int end)546 void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end )
547 {
548 //qDebug() << "ratbr" << parent << start << end;
549 Changing c;
550 c.parent = parent;
551 c.oldSize = model->rowCount ( parent );
552 c.last = model->data ( model->index ( start - 1, 0, parent ) );
553 c.next = model->data ( model->index ( end + 1, 0, parent ) );
554 remove.push ( c );
555 }
556
557 /*!
558 Confirm that what was said was going to happen actually did
559
560 \sa rowsAboutToBeRemoved()
561 */
rowsRemoved(const QModelIndex & parent,int start,int end)562 void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end )
563 {
564 // qDebug() << "rr" << parent << start << end;
565 Changing c = remove.pop();
566 QVERIFY( c.parent == parent );
567 QVERIFY( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) );
568 QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
569 QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) );
570 }
571
dataChanged(const QModelIndex & topLeft,const QModelIndex & bottomRight)572 void ModelTest::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
573 {
574 QVERIFY(topLeft.isValid());
575 QVERIFY(bottomRight.isValid());
576 QModelIndex commonParent = bottomRight.parent();
577 QVERIFY(topLeft.parent() == commonParent);
578 QVERIFY(topLeft.row() <= bottomRight.row());
579 QVERIFY(topLeft.column() <= bottomRight.column());
580 int rowCount = model->rowCount(commonParent);
581 int columnCount = model->columnCount(commonParent);
582 QVERIFY(bottomRight.row() < rowCount);
583 QVERIFY(bottomRight.column() < columnCount);
584 }
585
headerDataChanged(Qt::Orientation orientation,int start,int end)586 void ModelTest::headerDataChanged(Qt::Orientation orientation, int start, int end)
587 {
588 QVERIFY(start >= 0);
589 QVERIFY(end >= 0);
590 QVERIFY(start <= end);
591 int itemCount = orientation == Qt::Vertical ? model->rowCount() : model->columnCount();
592 QVERIFY(start < itemCount);
593 QVERIFY(end < itemCount);
594 }
595
rowsAboutToBeMoved(const QModelIndex & srcParent,int start,int end,const QModelIndex & destParent,int destinationRow)596 void ModelTest::rowsAboutToBeMoved( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow )
597 {
598 Changing cs;
599 cs.parent = srcParent;
600 cs.oldSize = model->rowCount ( srcParent );
601 cs.last = model->data ( model->index ( start - 1, 0, srcParent ) );
602 cs.next = model->data ( model->index ( end + 1, 0, srcParent ) );
603 remove.push ( cs );
604 Changing cd;
605 cd.parent = destParent;
606 cd.oldSize = model->rowCount ( destParent );
607 cd.last = model->data ( model->index ( destinationRow - 1, 0, destParent ) );
608 cd.next = model->data ( model->index ( destinationRow, 0, destParent ) );
609 insert.push ( cd );
610 }
611
rowsMoved(const QModelIndex & srcParent,int start,int end,const QModelIndex & destParent,int destinationRow)612 void ModelTest::rowsMoved( const QModelIndex &srcParent, int start, int end, const QModelIndex &destParent, int destinationRow )
613 {
614 Changing cd = insert.pop();
615 QVERIFY ( cd.parent == destParent );
616 if (srcParent == destParent) {
617 QVERIFY ( cd.oldSize == model->rowCount ( destParent ) );
618
619 // TODO: Find out what I can assert here about last and next.
620 // Q_ASSERT ( cd.last == model->data ( model->index ( destinationRow - 1, 0, cd.parent ) ) );
621 // Q_ASSERT ( cd.next == model->data ( model->index ( destinationRow + (end - start + 1), 0, cd.parent ) ) );
622 }
623 else {
624 QVERIFY ( cd.oldSize + ( end - start + 1 ) == model->rowCount ( destParent ) );
625
626 QVERIFY ( cd.last == model->data ( model->index ( destinationRow - 1, 0, cd.parent ) ) );
627 QVERIFY ( cd.next == model->data ( model->index ( destinationRow + (end - start + 1), 0, cd.parent ) ) );
628 }
629
630 Changing cs = remove.pop();
631 QVERIFY ( cs.parent == srcParent );
632 if (srcParent == destParent) {
633 QVERIFY ( cs.oldSize == model->rowCount ( srcParent ) );
634 }
635 else {
636 QVERIFY ( cs.oldSize - ( end - start + 1 ) == model->rowCount ( srcParent ) );
637
638 QVERIFY ( cs.last == model->data ( model->index ( start - 1, 0, srcParent ) ) );
639 QVERIFY ( cs.next == model->data ( model->index ( start, 0, srcParent ) ) );
640 }
641 }
642