File indexing completed on 2025-01-19 04:51:59

0001 /****************************************************************************
0002 **
0003 ** Copyright (C) 2016 The Qt Company Ltd.
0004 ** Contact: https://www.qt.io/licensing/
0005 **
0006 ** This file is part of the test suite of the Qt Toolkit.
0007 **
0008 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
0009 ** Commercial License Usage
0010 ** Licensees holding valid commercial Qt licenses may use this file in
0011 ** accordance with the commercial license agreement provided with the
0012 ** Software or, alternatively, in accordance with the terms contained in
0013 ** a written agreement between you and The Qt Company. For licensing terms
0014 ** and conditions see https://www.qt.io/terms-conditions. For further
0015 ** information use the contact form at https://www.qt.io/contact-us.
0016 **
0017 ** GNU General Public License Usage
0018 ** Alternatively, this file may be used under the terms of the GNU
0019 ** General Public License version 3 as published by the Free Software
0020 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
0021 ** included in the packaging of this file. Please review the following
0022 ** information to ensure the GNU General Public License requirements will
0023 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
0024 **
0025 ** $QT_END_LICENSE$
0026 **
0027 ****************************************************************************/
0028 
0029 #include "modeltest.h"
0030 
0031 #include <QtCore/QtCore>
0032 #include <QtTest/QtTest>
0033 
0034 #include <QDebug>
0035 /*!
0036     Connect to all of the models signals.  Whenever anything happens recheck everything.
0037 */
0038 ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false )
0039 {
0040     if (!model)
0041         qFatal("%s: model must not be null", Q_FUNC_INFO);
0042 
0043     connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
0044             this, SLOT(runAllTests()) );
0045     connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
0046             this, SLOT(runAllTests()) );
0047     connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
0048             this, SLOT(runAllTests()) );
0049     connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
0050             this, SLOT(runAllTests()) );
0051     connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
0052             this, SLOT(runAllTests()) );
0053     connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
0054             this, SLOT(runAllTests()) );
0055     connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests()) );
0056     connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests()) );
0057     connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests()) );
0058     connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
0059             this, SLOT(runAllTests()) );
0060     connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
0061             this, SLOT(runAllTests()) );
0062     connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
0063             this, SLOT(runAllTests()) );
0064     connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
0065             this, SLOT(runAllTests()) );
0066 
0067     // Special checks for changes
0068     connect(model, SIGNAL(layoutAboutToBeChanged()),
0069             this, SLOT(layoutAboutToBeChanged()) );
0070     connect(model, SIGNAL(layoutChanged()),
0071             this, SLOT(layoutChanged()) );
0072 
0073     connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
0074             this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)) );
0075     connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
0076             this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)) );
0077     connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
0078             this, SLOT(rowsInserted(QModelIndex,int,int)) );
0079     connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
0080             this, SLOT(rowsRemoved(QModelIndex,int,int)) );
0081     connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
0082             this, SLOT(dataChanged(QModelIndex,QModelIndex)) );
0083     connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
0084             this, SLOT(headerDataChanged(Qt::Orientation,int,int)) );
0085 
0086     runAllTests();
0087 }
0088 
0089 void ModelTest::runAllTests()
0090 {
0091     if ( fetchingMore )
0092         return;
0093     nonDestructiveBasicTest();
0094     rowCount();
0095     columnCount();
0096     hasIndex();
0097     index();
0098     parent();
0099     data();
0100 }
0101 
0102 /*!
0103     nonDestructiveBasicTest tries to call a number of the basic functions (not all)
0104     to make sure the model doesn't outright segfault, testing the functions that makes sense.
0105 */
0106 void ModelTest::nonDestructiveBasicTest()
0107 {
0108     QVERIFY( model->buddy ( QModelIndex() ) == QModelIndex() );
0109     model->canFetchMore ( QModelIndex() );
0110     QVERIFY( model->columnCount ( QModelIndex() ) >= 0 );
0111     QVERIFY( model->data ( QModelIndex() ) == QVariant() );
0112     fetchingMore = true;
0113     model->fetchMore ( QModelIndex() );
0114     fetchingMore = false;
0115     Qt::ItemFlags flags = model->flags ( QModelIndex() );
0116     QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 );
0117     model->hasChildren ( QModelIndex() );
0118     model->hasIndex ( 0, 0 );
0119     model->headerData ( 0, Qt::Horizontal );
0120     model->index ( 0, 0 );
0121     model->itemData ( QModelIndex() );
0122     QVariant cache;
0123     model->match ( QModelIndex(), -1, cache );
0124     model->mimeTypes();
0125     QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() );
0126     QVERIFY( model->rowCount() >= 0 );
0127     QVariant variant;
0128     model->setData ( QModelIndex(), variant, -1 );
0129     model->setHeaderData ( -1, Qt::Horizontal, QVariant() );
0130     model->setHeaderData ( 999999, Qt::Horizontal, QVariant() );
0131     QMap<int, QVariant> roles;
0132     model->sibling ( 0, 0, QModelIndex() );
0133     model->span ( QModelIndex() );
0134     model->supportedDropActions();
0135 }
0136 
0137 /*!
0138     Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren()
0139 
0140     Models that are dynamically populated are not as fully tested here.
0141  */
0142 void ModelTest::rowCount()
0143 {
0144 //     qDebug() << "rc";
0145     // check top row
0146     QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
0147     int rows = model->rowCount ( topIndex );
0148     QVERIFY( rows >= 0 );
0149     if ( rows > 0 )
0150         QVERIFY( model->hasChildren ( topIndex ) );
0151 
0152     QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex );
0153     if ( secondLevelIndex.isValid() ) { // not the top level
0154         // check a row count where parent is valid
0155         rows = model->rowCount ( secondLevelIndex );
0156         QVERIFY( rows >= 0 );
0157         if ( rows > 0 )
0158             QVERIFY( model->hasChildren ( secondLevelIndex ) );
0159     }
0160 
0161     // The models rowCount() is tested more extensively in checkChildren(),
0162     // but this catches the big mistakes
0163 }
0164 
0165 /*!
0166     Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren()
0167  */
0168 void ModelTest::columnCount()
0169 {
0170     // check top row
0171     QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
0172     QVERIFY( model->columnCount ( topIndex ) >= 0 );
0173 
0174     // check a column count where parent is valid
0175     QModelIndex childIndex = model->index ( 0, 0, topIndex );
0176     if ( childIndex.isValid() )
0177         QVERIFY( model->columnCount ( childIndex ) >= 0 );
0178 
0179     // columnCount() is tested more extensively in checkChildren(),
0180     // but this catches the big mistakes
0181 }
0182 
0183 /*!
0184     Tests model's implementation of QAbstractItemModel::hasIndex()
0185  */
0186 void ModelTest::hasIndex()
0187 {
0188 //     qDebug() << "hi";
0189     // Make sure that invalid values returns an invalid index
0190     QVERIFY( !model->hasIndex ( -2, -2 ) );
0191     QVERIFY( !model->hasIndex ( -2, 0 ) );
0192     QVERIFY( !model->hasIndex ( 0, -2 ) );
0193 
0194     int rows = model->rowCount();
0195     int columns = model->columnCount();
0196 
0197     // check out of bounds
0198     QVERIFY( !model->hasIndex ( rows, columns ) );
0199     QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) );
0200 
0201     if ( rows > 0 )
0202         QVERIFY( model->hasIndex ( 0, 0 ) );
0203 
0204     // hasIndex() is tested more extensively in checkChildren(),
0205     // but this catches the big mistakes
0206 }
0207 
0208 /*!
0209     Tests model's implementation of QAbstractItemModel::index()
0210  */
0211 void ModelTest::index()
0212 {
0213 //     qDebug() << "i";
0214     // Make sure that invalid values returns an invalid index
0215     QVERIFY( model->index ( -2, -2 ) == QModelIndex() );
0216     QVERIFY( model->index ( -2, 0 ) == QModelIndex() );
0217     QVERIFY( model->index ( 0, -2 ) == QModelIndex() );
0218 
0219     int rows = model->rowCount();
0220     int columns = model->columnCount();
0221 
0222     if ( rows == 0 )
0223         return;
0224 
0225     // Catch off by one errors
0226     QVERIFY( model->index ( rows, columns ) == QModelIndex() );
0227     QVERIFY( model->index ( 0, 0 ).isValid() );
0228 
0229     // Make sure that the same index is *always* returned
0230     QModelIndex a = model->index ( 0, 0 );
0231     QModelIndex b = model->index ( 0, 0 );
0232     QVERIFY( a == b );
0233 
0234     // index() is tested more extensively in checkChildren(),
0235     // but this catches the big mistakes
0236 }
0237 
0238 /*!
0239     Tests model's implementation of QAbstractItemModel::parent()
0240  */
0241 void ModelTest::parent()
0242 {
0243 //     qDebug() << "p";
0244     // Make sure the model won't crash and will return an invalid QModelIndex
0245     // when asked for the parent of an invalid index.
0246     QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() );
0247 
0248     if ( model->rowCount() == 0 )
0249         return;
0250 
0251     // Column 0                | Column 1    |
0252     // QModelIndex()           |             |
0253     //    \- topIndex          | topIndex1   |
0254     //         \- childIndex   | childIndex1 |
0255 
0256     // Common error test #1, make sure that a top level index has a parent
0257     // that is a invalid QModelIndex.
0258     QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
0259     QVERIFY( model->parent ( topIndex ) == QModelIndex() );
0260 
0261     // Common error test #2, make sure that a second level index has a parent
0262     // that is the first level index.
0263     if ( model->rowCount ( topIndex ) > 0 ) {
0264         QModelIndex childIndex = model->index ( 0, 0, topIndex );
0265         QVERIFY( model->parent ( childIndex ) == topIndex );
0266     }
0267 
0268     // Common error test #3, the second column should NOT have the same children
0269     // as the first column in a row.
0270     // Usually the second column shouldn't have children.
0271     QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() );
0272     if ( model->rowCount ( topIndex1 ) > 0 ) {
0273         QModelIndex childIndex = model->index ( 0, 0, topIndex );
0274         QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 );
0275         QVERIFY( childIndex != childIndex1 );
0276     }
0277 
0278     // Full test, walk n levels deep through the model making sure that all
0279     // parent's children correctly specify their parent.
0280     checkChildren ( QModelIndex() );
0281 }
0282 
0283 /*!
0284     Called from the parent() test.
0285 
0286     A model that returns an index of parent X should also return X when asking
0287     for the parent of the index.
0288 
0289     This recursive function does pretty extensive testing on the whole model in an
0290     effort to catch edge cases.
0291 
0292     This function assumes that rowCount(), columnCount() and index() already work.
0293     If they have a bug it will point it out, but the above tests should have already
0294     found the basic bugs because it is easier to figure out the problem in
0295     those tests then this one.
0296  */
0297 void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
0298 {
0299     // First just try walking back up the tree.
0300     QModelIndex p = parent;
0301     while ( p.isValid() )
0302         p = p.parent();
0303 
0304     // For models that are dynamically populated
0305     if ( model->canFetchMore ( parent ) ) {
0306         fetchingMore = true;
0307         model->fetchMore ( parent );
0308         fetchingMore = false;
0309     }
0310 
0311     int rows = model->rowCount ( parent );
0312     int columns = model->columnCount ( parent );
0313 
0314     if ( rows > 0 )
0315         QVERIFY( model->hasChildren ( parent ) );
0316 
0317     // Some further testing against rows(), columns(), and hasChildren()
0318     QVERIFY( rows >= 0 );
0319     QVERIFY( columns >= 0 );
0320     if ( rows > 0 )
0321         QVERIFY( model->hasChildren ( parent ) );
0322 
0323     qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
0324              << "columns:" << columns << "parent column:" << parent.column();
0325 
0326     const QModelIndex topLeftChild = model->index( 0, 0, parent );
0327 
0328     QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) );
0329     for ( int r = 0; r < rows; ++r ) {
0330         if ( model->canFetchMore ( parent ) ) {
0331             fetchingMore = true;
0332             model->fetchMore ( parent );
0333             fetchingMore = false;
0334         }
0335         QVERIFY( !model->hasIndex ( r, columns + 1, parent ) );
0336         for ( int c = 0; c < columns; ++c ) {
0337             QVERIFY( model->hasIndex ( r, c, parent ) );
0338             QModelIndex index = model->index ( r, c, parent );
0339             // rowCount() and columnCount() said that it existed...
0340             QVERIFY( index.isValid() );
0341 
0342             qDebug() << "\tchild("<< r <<", " << c << ", " << index.column() << "):" << model->data(index).toString() << index.internalPointer();
0343 
0344             // index() should always return the same index when called twice in a row
0345             QModelIndex modifiedIndex = model->index ( r, c, parent );
0346             QVERIFY( index == modifiedIndex );
0347 
0348             // Make sure we get the same index if we request it twice in a row
0349             QModelIndex a = model->index ( r, c, parent );
0350             QModelIndex b = model->index ( r, c, parent );
0351             QVERIFY( a == b );
0352 
0353             {
0354                 const QModelIndex sibling = model->sibling( r, c, topLeftChild );
0355                 QVERIFY( index == sibling );
0356             }
0357             {
0358                 const QModelIndex sibling = topLeftChild.sibling( r, c );
0359                 QVERIFY( index == sibling );
0360             }
0361 
0362             // Some basic checking on the index that is returned
0363             QVERIFY( index.model() == model );
0364             QCOMPARE( index.row(), r );
0365             QCOMPARE( index.column(), c );
0366             // While you can technically return a QVariant usually this is a sign
0367             // of a bug in data().  Disable if this really is ok in your model.
0368 //            QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() );
0369 
0370             // If the next test fails here is some somewhat useful debug you play with.
0371 
0372             if (model->parent(index) != parent) {
0373                 qDebug() << r << c << currentDepth << model->data(index).toString()
0374                          << model->data(parent).toString();
0375                 qDebug() << index << parent << model->parent(index);
0376 //                 And a view that you can even use to show the model.
0377 //                 QTreeView view;
0378 //                 view.setModel(model);
0379 //                 view.show();
0380             }
0381 
0382             // Check that we can get back our real parent.
0383             QCOMPARE( model->parent ( index ), parent );
0384 
0385             // recursively go down the children
0386             if ( model->hasChildren ( index ) && currentDepth < 10 ) {
0387                 qDebug() << r << c << "has children" << model->rowCount(index);
0388                 checkChildren ( index, ++currentDepth );
0389             }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
0390 
0391             // make sure that after testing the children that the index doesn't change.
0392             QModelIndex newerIndex = model->index ( r, c, parent );
0393             QVERIFY( index == newerIndex );
0394         }
0395     }
0396 }
0397 
0398 /*!
0399     Tests model's implementation of QAbstractItemModel::data()
0400  */
0401 void ModelTest::data()
0402 {
0403     // Invalid index should return an invalid qvariant
0404     QVERIFY( !model->data ( QModelIndex() ).isValid() );
0405 
0406     if ( model->rowCount() == 0 )
0407         return;
0408 
0409     // A valid index should have a valid QVariant data
0410     QVERIFY( model->index ( 0, 0 ).isValid() );
0411 
0412     // shouldn't be able to set data on an invalid index
0413     QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) );
0414 
0415     // General Purpose roles that should return a QString
0416     QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole );
0417     if ( variant.isValid() ) {
0418         QVERIFY( variant.canConvert<QString>() );
0419     }
0420     variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole );
0421     if ( variant.isValid() ) {
0422         QVERIFY( variant.canConvert<QString>() );
0423     }
0424     variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole );
0425     if ( variant.isValid() ) {
0426         QVERIFY( variant.canConvert<QString>() );
0427     }
0428 
0429     // General Purpose roles that should return a QSize
0430     variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole );
0431     if ( variant.isValid() ) {
0432         QVERIFY( variant.canConvert<QSize>() );
0433     }
0434 
0435     // General Purpose roles that should return a QFont
0436     QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole );
0437     if ( fontVariant.isValid() ) {
0438         QVERIFY( fontVariant.canConvert<QFont>() );
0439     }
0440 
0441     // Check that the alignment is one we know about
0442     QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole );
0443     if ( textAlignmentVariant.isValid() ) {
0444         int alignment = textAlignmentVariant.toInt();
0445         QCOMPARE( alignment, int( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) );
0446     }
0447 
0448     // General Purpose roles that should return a QColor
0449     QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundRole );
0450     if ( colorVariant.isValid() ) {
0451         QVERIFY( colorVariant.canConvert<QColor>() );
0452     }
0453 
0454     colorVariant = model->data ( model->index ( 0, 0 ), Qt::ForegroundRole );
0455     if ( colorVariant.isValid() ) {
0456         QVERIFY( colorVariant.canConvert<QColor>() );
0457     }
0458 
0459     // Check that the "check state" is one we know about.
0460     QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole );
0461     if ( checkStateVariant.isValid() ) {
0462         int state = checkStateVariant.toInt();
0463         QVERIFY( state == Qt::Unchecked ||
0464                  state == Qt::PartiallyChecked ||
0465                  state == Qt::Checked );
0466     }
0467 }
0468 
0469 /*!
0470     Store what is about to be inserted to make sure it actually happens
0471 
0472     \sa rowsInserted()
0473  */
0474 void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */)
0475 {
0476 //     Q_UNUSED(end);
0477 //    qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString()
0478 //    << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) );
0479 //     qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) );
0480     Changing c;
0481     c.parent = parent;
0482     c.oldSize = model->rowCount ( parent );
0483     c.last = model->data ( model->index ( start - 1, 0, parent ) );
0484     c.next = model->data ( model->index ( start, 0, parent ) );
0485     insert.push ( c );
0486 }
0487 
0488 /*!
0489     Confirm that what was said was going to happen actually did
0490 
0491     \sa rowsAboutToBeInserted()
0492  */
0493 void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end )
0494 {
0495     Changing c = insert.pop();
0496     QVERIFY( c.parent == parent );
0497 //    qDebug() << "rowsInserted"  << "start=" << start << "end=" << end << "oldsize=" << c.oldSize
0498 //    << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent );
0499 
0500 //    for (int ii=start; ii <= end; ii++)
0501 //    {
0502 //      qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent ));
0503 //    }
0504 //    qDebug();
0505 
0506     QVERIFY( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) );
0507     QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
0508 
0509     if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
0510         qDebug() << start << end;
0511         for (int i=0; i < model->rowCount(); ++i)
0512             qDebug() << model->index(i, 0).data().toString();
0513         qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
0514     }
0515 
0516     QVERIFY( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) );
0517 }
0518 
0519 void ModelTest::layoutAboutToBeChanged()
0520 {
0521     for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i )
0522         changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) );
0523 }
0524 
0525 void ModelTest::layoutChanged()
0526 {
0527     for ( int i = 0; i < changing.count(); ++i ) {
0528         QPersistentModelIndex p = changing[i];
0529         QVERIFY( p == model->index ( p.row(), p.column(), p.parent() ) );
0530     }
0531     changing.clear();
0532 }
0533 
0534 /*!
0535     Store what is about to be inserted to make sure it actually happens
0536 
0537     \sa rowsRemoved()
0538  */
0539 void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end )
0540 {
0541 qDebug() << "ratbr" << parent << start << end;
0542     Changing c;
0543     c.parent = parent;
0544     c.oldSize = model->rowCount ( parent );
0545     c.last = model->data ( model->index ( start - 1, 0, parent ) );
0546     c.next = model->data ( model->index ( end + 1, 0, parent ) );
0547     remove.push ( c );
0548 }
0549 
0550 /*!
0551     Confirm that what was said was going to happen actually did
0552 
0553     \sa rowsAboutToBeRemoved()
0554  */
0555 void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end )
0556 {
0557   qDebug() << "rr" << parent << start << end;
0558     Changing c = remove.pop();
0559     QVERIFY( c.parent == parent );
0560     QVERIFY( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) );
0561     QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
0562     QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) );
0563 }
0564 
0565 void ModelTest::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
0566 {
0567     QVERIFY(topLeft.isValid());
0568     QVERIFY(bottomRight.isValid());
0569     QModelIndex commonParent = bottomRight.parent();
0570     QCOMPARE(topLeft.parent(), commonParent);
0571     QVERIFY(topLeft.row() <= bottomRight.row());
0572     QVERIFY(topLeft.column() <= bottomRight.column());
0573     int rowCount = model->rowCount(commonParent);
0574     int columnCount = model->columnCount(commonParent);
0575     QVERIFY(bottomRight.row() < rowCount);
0576     QVERIFY(bottomRight.column() < columnCount);
0577 }
0578 
0579 void ModelTest::headerDataChanged(Qt::Orientation orientation, int start, int end)
0580 {
0581     QVERIFY(start >= 0);
0582     QVERIFY(end >= 0);
0583     QVERIFY(start <= end);
0584     int itemCount = orientation == Qt::Vertical ? model->rowCount() : model->columnCount();
0585     QVERIFY(start < itemCount);
0586     QVERIFY(end < itemCount);
0587 }
0588