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