File indexing completed on 2024-04-28 17:02:21

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