File indexing completed on 2024-05-05 05:47:26

0001 /****************************************************************************
0002 **
0003 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
0004 ** All rights reserved.
0005 ** Contact: Nokia Corporation (qt-info@nokia.com)
0006 **
0007 ** This file is part of the test suite of the Qt Toolkit.
0008 **
0009 ** $QT_BEGIN_LICENSE:LGPL$
0010 ** No Commercial Usage
0011 ** This file contains pre-release code and may not be distributed.
0012 ** You may use this file in accordance with the terms and conditions
0013 ** contained in the Technology Preview License Agreement accompanying
0014 ** this package.
0015 **
0016 ** GNU Lesser General Public License Usage
0017 ** Alternatively, this file may be used under the terms of the GNU Lesser
0018 ** General Public License version 2.1 as published by the Free Software
0019 ** Foundation and appearing in the file LICENSE.LGPL included in the
0020 ** packaging of this file.  Please review the following information to
0021 ** ensure the GNU Lesser General Public License version 2.1 requirements
0022 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
0023 **
0024 ** In addition, as a special exception, Nokia gives you certain additional
0025 ** rights.  These rights are described in the Nokia Qt LGPL Exception
0026 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
0027 **
0028 ** If you have questions regarding the use of this file, please contact
0029 ** Nokia at qt-info@nokia.com.
0030 **
0031 **
0032 **
0033 **
0034 **
0035 **
0036 **
0037 **
0038 ** $QT_END_LICENSE$
0039 **
0040 ****************************************************************************/
0041 
0042 
0043 #include "modeltest.h"
0044 
0045 #include <QtTest/QtTest>
0046 #undef Q_ASSERT
0047 #define Q_ASSERT  QVERIFY
0048 
0049 Q_DECLARE_METATYPE ( QModelIndex )
0050 
0051 /*!
0052     Connect to all of the models signals.  Whenever anything happens recheck everything.
0053 */
0054 ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false )
0055 {
0056     Q_ASSERT ( model );
0057 
0058     connect ( model, SIGNAL ( columnsAboutToBeInserted ( const QModelIndex &, int, int ) ),
0059               this, SLOT ( runAllTests() ) );
0060     connect ( model, SIGNAL ( columnsAboutToBeRemoved ( const QModelIndex &, int, int ) ),
0061               this, SLOT ( runAllTests() ) );
0062     connect ( model, SIGNAL ( columnsInserted ( const QModelIndex &, int, int ) ),
0063               this, SLOT ( runAllTests() ) );
0064     connect ( model, SIGNAL ( columnsRemoved ( const QModelIndex &, int, int ) ),
0065               this, SLOT ( runAllTests() ) );
0066     connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ),
0067               this, SLOT ( runAllTests() ) );
0068     connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ),
0069               this, SLOT ( runAllTests() ) );
0070     connect ( model, SIGNAL ( layoutAboutToBeChanged () ), this, SLOT ( runAllTests() ) );
0071     connect ( model, SIGNAL ( layoutChanged () ), this, SLOT ( runAllTests() ) );
0072     connect ( model, SIGNAL ( modelReset () ), this, SLOT ( runAllTests() ) );
0073     connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ),
0074               this, SLOT ( runAllTests() ) );
0075     connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ),
0076               this, SLOT ( runAllTests() ) );
0077     connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ),
0078               this, SLOT ( runAllTests() ) );
0079     connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ),
0080               this, SLOT ( runAllTests() ) );
0081 
0082     // Special checks for inserting/removing
0083     connect ( model, SIGNAL ( layoutAboutToBeChanged() ),
0084               this, SLOT ( layoutAboutToBeChanged() ) );
0085     connect ( model, SIGNAL ( layoutChanged() ),
0086               this, SLOT ( layoutChanged() ) );
0087 
0088     connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ),
0089               this, SLOT ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ) );
0090     connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ),
0091               this, SLOT ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ) );
0092     connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ),
0093               this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) );
0094     connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ),
0095               this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) );
0096 
0097     runAllTests();
0098 }
0099 
0100 void ModelTest::runAllTests()
0101 {
0102     if ( fetchingMore )
0103         return;
0104     nonDestructiveBasicTest();
0105     rowCount();
0106     columnCount();
0107     hasIndex();
0108     index();
0109     parent();
0110     data();
0111 }
0112 
0113 /*!
0114     nonDestructiveBasicTest tries to call a number of the basic functions (not all)
0115     to make sure the model doesn't outright segfault, testing the functions that makes sense.
0116 */
0117 void ModelTest::nonDestructiveBasicTest()
0118 {
0119     Q_ASSERT ( model->buddy ( QModelIndex() ) == QModelIndex() );
0120     model->canFetchMore ( QModelIndex() );
0121     Q_ASSERT ( model->columnCount ( QModelIndex() ) >= 0 );
0122     Q_ASSERT ( model->data ( QModelIndex() ) == QVariant() );
0123     fetchingMore = true;
0124     model->fetchMore ( QModelIndex() );
0125     fetchingMore = false;
0126     Qt::ItemFlags flags = model->flags ( QModelIndex() );
0127     Q_ASSERT ( flags == Qt::ItemIsDropEnabled || flags == 0 );
0128     model->hasChildren ( QModelIndex() );
0129     model->hasIndex ( 0, 0 );
0130     model->headerData ( 0, Qt::Horizontal );
0131     model->index ( 0, 0 );
0132     model->itemData ( QModelIndex() );
0133     QVariant cache;
0134     model->match ( QModelIndex(), -1, cache );
0135     model->mimeTypes();
0136     Q_ASSERT ( model->parent ( QModelIndex() ) == QModelIndex() );
0137     Q_ASSERT ( model->rowCount() >= 0 );
0138     QVariant variant;
0139     model->setData ( QModelIndex(), variant, -1 );
0140     model->setHeaderData ( -1, Qt::Horizontal, QVariant() );
0141     model->setHeaderData ( 999999, Qt::Horizontal, QVariant() );
0142     QMap<int, QVariant> roles;
0143     model->sibling ( 0, 0, QModelIndex() );
0144     model->span ( QModelIndex() );
0145     model->supportedDropActions();
0146 }
0147 
0148 /*!
0149     Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren()
0150 
0151     Models that are dynamically populated are not as fully tested here.
0152  */
0153 void ModelTest::rowCount()
0154 {
0155 //     qDebug() << "rc";
0156     // check top row
0157     QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
0158     int rows = model->rowCount ( topIndex );
0159     Q_ASSERT ( rows >= 0 );
0160     if ( rows > 0 )
0161         Q_ASSERT ( model->hasChildren ( topIndex ) == true );
0162 
0163     QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex );
0164     if ( secondLevelIndex.isValid() ) { // not the top level
0165         // check a row count where parent is valid
0166         rows = model->rowCount ( secondLevelIndex );
0167         Q_ASSERT ( rows >= 0 );
0168         if ( rows > 0 )
0169             Q_ASSERT ( model->hasChildren ( secondLevelIndex ) == true );
0170     }
0171 
0172     // The models rowCount() is tested more extensively in checkChildren(),
0173     // but this catches the big mistakes
0174 }
0175 
0176 /*!
0177     Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren()
0178  */
0179 void ModelTest::columnCount()
0180 {
0181     // check top row
0182     QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
0183     Q_ASSERT ( model->columnCount ( topIndex ) >= 0 );
0184 
0185     // check a column count where parent is valid
0186     QModelIndex childIndex = model->index ( 0, 0, topIndex );
0187     if ( childIndex.isValid() )
0188         Q_ASSERT ( model->columnCount ( childIndex ) >= 0 );
0189 
0190     // columnCount() is tested more extensively in checkChildren(),
0191     // but this catches the big mistakes
0192 }
0193 
0194 /*!
0195     Tests model's implementation of QAbstractItemModel::hasIndex()
0196  */
0197 void ModelTest::hasIndex()
0198 {
0199 //     qDebug() << "hi";
0200     // Make sure that invalid values returns an invalid index
0201     Q_ASSERT ( model->hasIndex ( -2, -2 ) == false );
0202     Q_ASSERT ( model->hasIndex ( -2, 0 ) == false );
0203     Q_ASSERT ( model->hasIndex ( 0, -2 ) == false );
0204 
0205     int rows = model->rowCount();
0206     int columns = model->columnCount();
0207 
0208     // check out of bounds
0209     Q_ASSERT ( model->hasIndex ( rows, columns ) == false );
0210     Q_ASSERT ( model->hasIndex ( rows + 1, columns + 1 ) == false );
0211 
0212     if ( rows > 0 )
0213         Q_ASSERT ( model->hasIndex ( 0, 0 ) == true );
0214 
0215     // hasIndex() is tested more extensively in checkChildren(),
0216     // but this catches the big mistakes
0217 }
0218 
0219 /*!
0220     Tests model's implementation of QAbstractItemModel::index()
0221  */
0222 void ModelTest::index()
0223 {
0224 //     qDebug() << "i";
0225     // Make sure that invalid values returns an invalid index
0226     Q_ASSERT ( model->index ( -2, -2 ) == QModelIndex() );
0227     Q_ASSERT ( model->index ( -2, 0 ) == QModelIndex() );
0228     Q_ASSERT ( model->index ( 0, -2 ) == QModelIndex() );
0229 
0230     int rows = model->rowCount();
0231     int columns = model->columnCount();
0232 
0233     if ( rows == 0 )
0234         return;
0235 
0236     // Catch off by one errors
0237     Q_ASSERT ( model->index ( rows, columns ) == QModelIndex() );
0238     Q_ASSERT ( model->index ( 0, 0 ).isValid() == true );
0239 
0240     // Make sure that the same index is *always* returned
0241     QModelIndex a = model->index ( 0, 0 );
0242     QModelIndex b = model->index ( 0, 0 );
0243     Q_ASSERT ( a == b );
0244 
0245     // index() is tested more extensively in checkChildren(),
0246     // but this catches the big mistakes
0247 }
0248 
0249 /*!
0250     Tests model's implementation of QAbstractItemModel::parent()
0251  */
0252 void ModelTest::parent()
0253 {
0254 //     qDebug() << "p";
0255     // Make sure the model wont crash and will return an invalid QModelIndex
0256     // when asked for the parent of an invalid index.
0257     Q_ASSERT ( model->parent ( QModelIndex() ) == QModelIndex() );
0258 
0259     if ( model->rowCount() == 0 )
0260         return;
0261 
0262     // Column 0                | Column 1    |
0263     // QModelIndex()           |             |
0264     //    \- topIndex          | topIndex1   |
0265     //         \- childIndex   | childIndex1 |
0266 
0267     // Common error test #1, make sure that a top level index has a parent
0268     // that is a invalid QModelIndex.
0269     QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
0270     Q_ASSERT ( model->parent ( topIndex ) == QModelIndex() );
0271 
0272     // Common error test #2, make sure that a second level index has a parent
0273     // that is the first level index.
0274     if ( model->rowCount ( topIndex ) > 0 ) {
0275         QModelIndex childIndex = model->index ( 0, 0, topIndex );
0276         Q_ASSERT ( model->parent ( childIndex ) == topIndex );
0277     }
0278 
0279     // Common error test #3, the second column should NOT have the same children
0280     // as the first column in a row.
0281     // Usually the second column shouldn't have children.
0282     QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() );
0283     if ( model->rowCount ( topIndex1 ) > 0 ) {
0284         QModelIndex childIndex = model->index ( 0, 0, topIndex );
0285         QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 );
0286         Q_ASSERT ( childIndex != childIndex1 );
0287     }
0288 
0289     // Full test, walk n levels deep through the model making sure that all
0290     // parent's children correctly specify their parent.
0291     checkChildren ( QModelIndex() );
0292 }
0293 
0294 /*!
0295     Called from the parent() test.
0296 
0297     A model that returns an index of parent X should also return X when asking
0298     for the parent of the index.
0299 
0300     This recursive function does pretty extensive testing on the whole model in an
0301     effort to catch edge cases.
0302 
0303     This function assumes that rowCount(), columnCount() and index() already work.
0304     If they have a bug it will point it out, but the above tests should have already
0305     found the basic bugs because it is easier to figure out the problem in
0306     those tests then this one.
0307  */
0308 void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
0309 {
0310     // First just try walking back up the tree.
0311     QModelIndex p = parent;
0312     while ( p.isValid() )
0313         p = p.parent();
0314 
0315     // For models that are dynamically populated
0316     if ( model->canFetchMore ( parent ) ) {
0317         fetchingMore = true;
0318         model->fetchMore ( parent );
0319         fetchingMore = false;
0320     }
0321 
0322     int rows = model->rowCount ( parent );
0323     int columns = model->columnCount ( parent );
0324 
0325     if ( rows > 0 )
0326         Q_ASSERT ( model->hasChildren ( parent ) );
0327 
0328     // Some further testing against rows(), columns(), and hasChildren()
0329     Q_ASSERT ( rows >= 0 );
0330     Q_ASSERT ( columns >= 0 );
0331     if ( rows > 0 )
0332         Q_ASSERT ( model->hasChildren ( parent ) == true );
0333 
0334     //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
0335     //         << "columns:" << columns << "parent column:" << parent.column();
0336 
0337     Q_ASSERT ( model->hasIndex ( rows + 1, 0, parent ) == false );
0338     for ( int r = 0; r < rows; ++r ) {
0339         if ( model->canFetchMore ( parent ) ) {
0340             fetchingMore = true;
0341             model->fetchMore ( parent );
0342             fetchingMore = false;
0343         }
0344         Q_ASSERT ( model->hasIndex ( r, columns + 1, parent ) == false );
0345         for ( int c = 0; c < columns; ++c ) {
0346             Q_ASSERT ( model->hasIndex ( r, c, parent ) == true );
0347             QModelIndex index = model->index ( r, c, parent );
0348             // rowCount() and columnCount() said that it existed...
0349             Q_ASSERT ( index.isValid() == true );
0350 
0351             // index() should always return the same index when called twice in a row
0352             QModelIndex modifiedIndex = model->index ( r, c, parent );
0353             Q_ASSERT ( index == modifiedIndex );
0354 
0355             // Make sure we get the same index if we request it twice in a row
0356             QModelIndex a = model->index ( r, c, parent );
0357             QModelIndex b = model->index ( r, c, parent );
0358             Q_ASSERT ( a == b );
0359 
0360             // Some basic checking on the index that is returned
0361             Q_ASSERT ( index.model() == model );
0362             Q_ASSERT ( index.row() == r );
0363             Q_ASSERT ( index.column() == c );
0364             // While you can technically return a QVariant usually this is a sign
0365             // of an bug in data()  Disable if this really is ok in your model.
0366 //            Q_ASSERT ( model->data ( index, Qt::DisplayRole ).isValid() == true );
0367 
0368             // If the next test fails here is some somewhat useful debug you play with.
0369 
0370             if (model->parent(index) != parent) {
0371                 qDebug() << r << c << currentDepth << model->data(index).toString()
0372                          << model->data(parent).toString();
0373                 qDebug() << index << parent << model->parent(index);
0374 //                 And a view that you can even use to show the model.
0375 //                 QTreeView view;
0376 //                 view.setModel(model);
0377 //                 view.show();
0378             }
0379 
0380             // Check that we can get back our real parent.
0381 //             qDebug() << model->parent ( index ) << parent ;
0382             Q_ASSERT ( model->parent ( index ) == parent );
0383 
0384             // recursively go down the children
0385             if ( model->hasChildren ( index ) && currentDepth < 10 ) {
0386                 //qDebug() << r << c << "has children" << model->rowCount(index);
0387                 checkChildren ( index, ++currentDepth );
0388             }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
0389 
0390             // make sure that after testing the children that the index doesn't change.
0391             QModelIndex newerIndex = model->index ( r, c, parent );
0392             Q_ASSERT ( index == newerIndex );
0393         }
0394     }
0395 }
0396 
0397 /*!
0398     Tests model's implementation of QAbstractItemModel::data()
0399  */
0400 void ModelTest::data()
0401 {
0402     // Invalid index should return an invalid qvariant
0403     Q_ASSERT ( !model->data ( QModelIndex() ).isValid() );
0404 
0405     if ( model->rowCount() == 0 )
0406         return;
0407 
0408     // A valid index should have a valid QVariant data
0409     Q_ASSERT ( model->index ( 0, 0 ).isValid() );
0410 
0411     // shouldn't be able to set data on an invalid index
0412     Q_ASSERT ( model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) == false );
0413 
0414     // General Purpose roles that should return a QString
0415     QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole );
0416     if ( variant.isValid() ) {
0417         Q_ASSERT ( variant.canConvert<QString>() );
0418     }
0419     variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole );
0420     if ( variant.isValid() ) {
0421         Q_ASSERT ( variant.canConvert<QString>() );
0422     }
0423     variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole );
0424     if ( variant.isValid() ) {
0425         Q_ASSERT ( variant.canConvert<QString>() );
0426     }
0427 
0428     // General Purpose roles that should return a QSize
0429     variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole );
0430     if ( variant.isValid() ) {
0431         Q_ASSERT ( variant.canConvert<QSize>() );
0432     }
0433 
0434     // General Purpose roles that should return a QFont
0435     QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole );
0436     if ( fontVariant.isValid() ) {
0437         Q_ASSERT ( fontVariant.canConvert<QFont>() );
0438     }
0439 
0440     // Check that the alignment is one we know about
0441     QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole );
0442     if ( textAlignmentVariant.isValid() ) {
0443         int alignment = textAlignmentVariant.toInt();
0444         Q_ASSERT ( alignment == ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) );
0445     }
0446 
0447     // General Purpose roles that should return a QColor
0448     QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole );
0449     if ( colorVariant.isValid() ) {
0450         Q_ASSERT ( colorVariant.canConvert<QColor>() );
0451     }
0452 
0453     colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole );
0454     if ( colorVariant.isValid() ) {
0455         Q_ASSERT ( colorVariant.canConvert<QColor>() );
0456     }
0457 
0458     // Check that the "check state" is one we know about.
0459     QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole );
0460     if ( checkStateVariant.isValid() ) {
0461         int state = checkStateVariant.toInt();
0462         Q_ASSERT ( state == Qt::Unchecked ||
0463                    state == Qt::PartiallyChecked ||
0464                    state == Qt::Checked );
0465     }
0466 }
0467 
0468 /*!
0469     Store what is about to be inserted to make sure it actually happens
0470 
0471     \sa rowsInserted()
0472  */
0473 void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end )
0474 {
0475     Q_UNUSED(end);
0476 
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     Q_ASSERT ( 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     Q_ASSERT ( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) );
0507     Q_ASSERT ( 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     Q_ASSERT ( 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         Q_ASSERT ( 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     Q_ASSERT ( c.parent == parent );
0560     Q_ASSERT ( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) );
0561     Q_ASSERT ( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) );
0562     Q_ASSERT ( c.next == model->data ( model->index ( start, 0, c.parent ) ) );
0563 }
0564 
0565 #include "moc_modeltest.cpp"