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