00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <QtGui/QtGui>
00025
00026 #include "modeltest.h"
00027
00028 Q_DECLARE_METATYPE( QModelIndex )
00029
00030
00033 ModelTest::ModelTest( QAbstractItemModel* _model, QObject* parent ) : QObject( parent ), model( _model ), fetchingMore( false )
00034 {
00035 Q_ASSERT( model );
00036
00037 connect( model, SIGNAL( columnsAboutToBeInserted( const QModelIndex&, int, int ) ),
00038 this, SLOT( runAllTests() ) );
00039 connect( model, SIGNAL( columnsAboutToBeRemoved( const QModelIndex&, int, int ) ),
00040 this, SLOT( runAllTests() ) );
00041 connect( model, SIGNAL( columnsInserted( const QModelIndex&, int, int ) ),
00042 this, SLOT( runAllTests() ) );
00043 connect( model, SIGNAL( columnsRemoved( const QModelIndex&, int, int ) ),
00044 this, SLOT( runAllTests() ) );
00045 connect( model, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ),
00046 this, SLOT( runAllTests() ) );
00047 connect( model, SIGNAL( headerDataChanged( Qt::Orientation, int, int ) ),
00048 this, SLOT( runAllTests() ) );
00049 connect( model, SIGNAL( layoutAboutToBeChanged() ), this, SLOT( runAllTests() ) );
00050 connect( model, SIGNAL( layoutChanged() ), this, SLOT( runAllTests() ) );
00051 connect( model, SIGNAL( modelReset() ), this, SLOT( runAllTests() ) );
00052 connect( model, SIGNAL( rowsAboutToBeInserted( const QModelIndex&, int, int ) ),
00053 this, SLOT( runAllTests() ) );
00054 connect( model, SIGNAL( rowsAboutToBeRemoved( const QModelIndex&, int, int ) ),
00055 this, SLOT( runAllTests() ) );
00056 connect( model, SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
00057 this, SLOT( runAllTests() ) );
00058 connect( model, SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ),
00059 this, SLOT( runAllTests() ) );
00060
00061
00062 connect( model, SIGNAL( layoutAboutToBeChanged() ),
00063 this, SLOT( layoutAboutToBeChanged() ) );
00064 connect( model, SIGNAL( layoutChanged() ),
00065 this, SLOT( layoutChanged() ) );
00066
00067 connect( model, SIGNAL( rowsAboutToBeInserted( const QModelIndex&, int, int ) ),
00068 this, SLOT( rowsAboutToBeInserted( const QModelIndex&, int, int ) ) );
00069 connect( model, SIGNAL( rowsAboutToBeRemoved( const QModelIndex&, int, int ) ),
00070 this, SLOT( rowsAboutToBeRemoved( const QModelIndex&, int, int ) ) );
00071 connect( model, SIGNAL( rowsInserted( const QModelIndex&, int, int ) ),
00072 this, SLOT( rowsInserted( const QModelIndex&, int, int ) ) );
00073 connect( model, SIGNAL( rowsRemoved( const QModelIndex&, int, int ) ),
00074 this, SLOT( rowsRemoved( const QModelIndex&, int, int ) ) );
00075
00076 runAllTests();
00077 }
00078
00079 void ModelTest::runAllTests()
00080 {
00081 if( fetchingMore )
00082 return;
00083 nonDestructiveBasicTest();
00084 rowCount();
00085 columnCount();
00086 hasIndex();
00087 index();
00088 parent();
00089 data();
00090 }
00091
00096 void ModelTest::nonDestructiveBasicTest()
00097 {
00098 Q_ASSERT( model->buddy( QModelIndex() ) == QModelIndex() );
00099 model->canFetchMore( QModelIndex() );
00100 Q_ASSERT( model->columnCount( QModelIndex() ) >= 0 );
00101 Q_ASSERT( model->data( QModelIndex() ) == QVariant() );
00102 fetchingMore = true;
00103 model->fetchMore( QModelIndex() );
00104 fetchingMore = false;
00105 Qt::ItemFlags flags = model->flags( QModelIndex() );
00106 Q_ASSERT( flags == Qt::ItemIsDropEnabled || flags == 0 );
00107 model->hasChildren( QModelIndex() );
00108 model->hasIndex( 0, 0 );
00109 model->headerData( 0, Qt::Horizontal );
00110 model->index( 0, 0 );
00111 model->itemData( QModelIndex() );
00112 QVariant cache;
00113 model->match( QModelIndex(), -1, cache );
00114 model->mimeTypes();
00115 Q_ASSERT( model->parent( QModelIndex() ) == QModelIndex() );
00116 Q_ASSERT( model->rowCount() >= 0 );
00117 QVariant variant;
00118 model->setData( QModelIndex(), variant, -1 );
00119 model->setHeaderData( -1, Qt::Horizontal, QVariant() );
00120 model->setHeaderData( 999999, Qt::Horizontal, QVariant() );
00121 QMap<int, QVariant> roles;
00122 model->sibling( 0, 0, QModelIndex() );
00123 model->span( QModelIndex() );
00124 model->supportedDropActions();
00125 }
00126
00132 void ModelTest::rowCount()
00133 {
00134
00135 QModelIndex topIndex = model->index( 0, 0, QModelIndex() );
00136 int rows = model->rowCount( topIndex );
00137 Q_ASSERT( rows >= 0 );
00138 if( rows > 0 )
00139 Q_ASSERT( model->hasChildren( topIndex ) == true );
00140
00141 QModelIndex secondLevelIndex = model->index( 0, 0, topIndex );
00142 if( secondLevelIndex.isValid() )
00143 {
00144
00145 rows = model->rowCount( secondLevelIndex );
00146 Q_ASSERT( rows >= 0 );
00147 if( rows > 0 )
00148 Q_ASSERT( model->hasChildren( secondLevelIndex ) == true );
00149 }
00150
00151
00152
00153 }
00154
00158 void ModelTest::columnCount()
00159 {
00160
00161 QModelIndex topIndex = model->index( 0, 0, QModelIndex() );
00162 Q_ASSERT( model->columnCount( topIndex ) >= 0 );
00163
00164
00165 QModelIndex childIndex = model->index( 0, 0, topIndex );
00166 if( childIndex.isValid() )
00167 Q_ASSERT( model->columnCount( childIndex ) >= 0 );
00168
00169
00170
00171 }
00172
00176 void ModelTest::hasIndex()
00177 {
00178
00179 Q_ASSERT( model->hasIndex( -2, -2 ) == false );
00180 Q_ASSERT( model->hasIndex( -2, 0 ) == false );
00181 Q_ASSERT( model->hasIndex( 0, -2 ) == false );
00182
00183 int rows = model->rowCount();
00184 int columns = model->columnCount();
00185
00186
00187 Q_ASSERT( model->hasIndex( rows, columns ) == false );
00188 Q_ASSERT( model->hasIndex( rows + 1, columns + 1 ) == false );
00189
00190 if( rows > 0 )
00191 Q_ASSERT( model->hasIndex( 0, 0 ) == true );
00192
00193
00194
00195 }
00196
00200 void ModelTest::index()
00201 {
00202
00203 Q_ASSERT( model->index( -2, -2 ) == QModelIndex() );
00204 Q_ASSERT( model->index( -2, 0 ) == QModelIndex() );
00205 Q_ASSERT( model->index( 0, -2 ) == QModelIndex() );
00206
00207 int rows = model->rowCount();
00208 int columns = model->columnCount();
00209
00210 if( rows == 0 )
00211 return;
00212
00213
00214 Q_ASSERT( model->index( rows, columns ) == QModelIndex() );
00215 Q_ASSERT( model->index( 0, 0 ).isValid() == true );
00216
00217
00218 QModelIndex a = model->index( 0, 0 );
00219 QModelIndex b = model->index( 0, 0 );
00220 Q_ASSERT( a == b );
00221
00222
00223
00224 }
00225
00229 void ModelTest::parent()
00230 {
00231
00232
00233 Q_ASSERT( model->parent( QModelIndex() ) == QModelIndex() );
00234
00235 if( model->rowCount() == 0 )
00236 return;
00237
00238
00239
00240
00241
00242
00243
00244
00245 QModelIndex topIndex = model->index( 0, 0, QModelIndex() );
00246 Q_ASSERT( model->parent( topIndex ) == QModelIndex() );
00247
00248
00249
00250 if( model->rowCount( topIndex ) > 0 )
00251 {
00252 QModelIndex childIndex = model->index( 0, 0, topIndex );
00253 Q_ASSERT( model->parent( childIndex ) == topIndex );
00254 }
00255
00256
00257
00258
00259 QModelIndex topIndex1 = model->index( 0, 1, QModelIndex() );
00260 if( model->rowCount( topIndex1 ) > 0 )
00261 {
00262 QModelIndex childIndex = model->index( 0, 0, topIndex );
00263 QModelIndex childIndex1 = model->index( 0, 0, topIndex1 );
00264 Q_ASSERT( childIndex != childIndex1 );
00265 }
00266
00267
00268
00269 checkChildren( QModelIndex() );
00270 }
00271
00286 void ModelTest::checkChildren( const QModelIndex& parent, int currentDepth )
00287 {
00288
00289 QModelIndex p = parent;
00290 while( p.isValid() )
00291 p = p.parent();
00292
00293
00294 if( model->canFetchMore( parent ) )
00295 {
00296 fetchingMore = true;
00297 model->fetchMore( parent );
00298 fetchingMore = false;
00299 }
00300
00301 int rows = model->rowCount( parent );
00302 int columns = model->columnCount( parent );
00303
00304 if( rows > 0 )
00305 Q_ASSERT( model->hasChildren( parent ) );
00306
00307
00308 Q_ASSERT( rows >= 0 );
00309 Q_ASSERT( columns >= 0 );
00310 if( rows > 0 )
00311 Q_ASSERT( model->hasChildren( parent ) == true );
00312
00313
00314
00315
00316 Q_ASSERT( model->hasIndex( rows + 1, 0, parent ) == false );
00317 for( int r = 0; r < rows; ++r )
00318 {
00319 if( model->canFetchMore( parent ) )
00320 {
00321 fetchingMore = true;
00322 model->fetchMore( parent );
00323 fetchingMore = false;
00324 }
00325 Q_ASSERT( model->hasIndex( r, columns + 1, parent ) == false );
00326 for( int c = 0; c < columns; ++c )
00327 {
00328 Q_ASSERT( model->hasIndex( r, c, parent ) == true );
00329 QModelIndex index = model->index( r, c, parent );
00330
00331 Q_ASSERT( index.isValid() == true );
00332
00333
00334 QModelIndex modifiedIndex = model->index( r, c, parent );
00335 Q_ASSERT( index == modifiedIndex );
00336
00337
00338 QModelIndex a = model->index( r, c, parent );
00339 QModelIndex b = model->index( r, c, parent );
00340 Q_ASSERT( a == b );
00341
00342
00343 Q_ASSERT( index.model() == model );
00344 Q_ASSERT( index.row() == r );
00345 Q_ASSERT( index.column() == c );
00346
00347
00348 Q_ASSERT( model->data( index, Qt::DisplayRole ).isValid() == true );
00349
00350
00351
00352 if( model->parent( index ) != parent )
00353 {
00354 qDebug() << r << c << currentDepth << model->data( index ).toString()
00355 << model->data( parent ).toString();
00356 qDebug() << index << parent << model->parent( index );
00357
00358
00359
00360
00361 }
00362
00363
00364 Q_ASSERT( model->parent( index ) == parent );
00365
00366
00367 if( model->hasChildren( index ) && currentDepth < 10 )
00368 {
00369
00370 checkChildren( index, ++currentDepth );
00371 }
00372
00373
00374 QModelIndex newerIndex = model->index( r, c, parent );
00375 Q_ASSERT( index == newerIndex );
00376 }
00377 }
00378 }
00379
00383 void ModelTest::data()
00384 {
00385
00386 Q_ASSERT( !model->data( QModelIndex() ).isValid() );
00387
00388 if( model->rowCount() == 0 )
00389 return;
00390
00391
00392 Q_ASSERT( model->index( 0, 0 ).isValid() );
00393
00394
00395 Q_ASSERT( model->setData( QModelIndex(), QLatin1String( "foo" ), Qt::DisplayRole ) == false );
00396
00397
00398 QVariant variant = model->data( model->index( 0, 0 ), Qt::ToolTipRole );
00399 if( variant.isValid() )
00400 {
00401 Q_ASSERT( qVariantCanConvert<QString>( variant ) );
00402 }
00403 variant = model->data( model->index( 0, 0 ), Qt::StatusTipRole );
00404 if( variant.isValid() )
00405 {
00406 Q_ASSERT( qVariantCanConvert<QString>( variant ) );
00407 }
00408 variant = model->data( model->index( 0, 0 ), Qt::WhatsThisRole );
00409 if( variant.isValid() )
00410 {
00411 Q_ASSERT( qVariantCanConvert<QString>( variant ) );
00412 }
00413
00414
00415 variant = model->data( model->index( 0, 0 ), Qt::SizeHintRole );
00416 if( variant.isValid() )
00417 {
00418 Q_ASSERT( qVariantCanConvert<QSize>( variant ) );
00419 }
00420
00421
00422 QVariant fontVariant = model->data( model->index( 0, 0 ), Qt::FontRole );
00423 if( fontVariant.isValid() )
00424 {
00425 Q_ASSERT( qVariantCanConvert<QFont>( fontVariant ) );
00426 }
00427
00428
00429 QVariant textAlignmentVariant = model->data( model->index( 0, 0 ), Qt::TextAlignmentRole );
00430 if( textAlignmentVariant.isValid() )
00431 {
00432 int alignment = textAlignmentVariant.toInt();
00433 Q_ASSERT( alignment == ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) );
00434 }
00435
00436
00437 QVariant colorVariant = model->data( model->index( 0, 0 ), Qt::BackgroundColorRole );
00438 if( colorVariant.isValid() )
00439 {
00440 Q_ASSERT( qVariantCanConvert<QColor>( colorVariant ) );
00441 }
00442
00443 colorVariant = model->data( model->index( 0, 0 ), Qt::TextColorRole );
00444 if( colorVariant.isValid() )
00445 {
00446 Q_ASSERT( qVariantCanConvert<QColor>( colorVariant ) );
00447 }
00448
00449
00450 QVariant checkStateVariant = model->data( model->index( 0, 0 ), Qt::CheckStateRole );
00451 if( checkStateVariant.isValid() )
00452 {
00453 int state = checkStateVariant.toInt();
00454 Q_ASSERT( state == Qt::Unchecked ||
00455 state == Qt::PartiallyChecked ||
00456 state == Qt::Checked );
00457 }
00458 }
00459
00465 void ModelTest::rowsAboutToBeInserted( const QModelIndex& parent, int start, int end )
00466 {
00467 Q_UNUSED( end );
00468 Changing c;
00469 c.parent = parent;
00470 c.oldSize = model->rowCount( parent );
00471 c.last = model->data( model->index( start - 1, 0, parent ) );
00472 c.next = model->data( model->index( start, 0, parent ) );
00473 insert.push( c );
00474 }
00475
00481 void ModelTest::rowsInserted( const QModelIndex& parent, int start, int end )
00482 {
00483 Changing c = insert.pop();
00484 Q_ASSERT( c.parent == parent );
00485 Q_ASSERT( c.oldSize + ( end - start + 1 ) == model->rowCount( parent ) );
00486 Q_ASSERT( c.last == model->data( model->index( start - 1, 0, c.parent ) ) );
00487
00488
00489
00490
00491
00492
00493
00494
00495 Q_ASSERT( c.next == model->data( model->index( end + 1, 0, c.parent ) ) );
00496 }
00497
00498 void ModelTest::layoutAboutToBeChanged()
00499 {
00500 for( int i = 0; i < qBound( 0, model->rowCount(), 100 ); ++i )
00501 changing.append( QPersistentModelIndex( model->index( i, 0 ) ) );
00502 }
00503
00504 void ModelTest::layoutChanged()
00505 {
00506 for( int i = 0; i < changing.count(); ++i )
00507 {
00508 QPersistentModelIndex p = changing[i];
00509 Q_ASSERT( p == model->index( p.row(), p.column(), p.parent() ) );
00510 }
00511 changing.clear();
00512 }
00513
00519 void ModelTest::rowsAboutToBeRemoved( const QModelIndex& parent, int start, int end )
00520 {
00521 Changing c;
00522 c.parent = parent;
00523 c.oldSize = model->rowCount( parent );
00524 c.last = model->data( model->index( start - 1, 0, parent ) );
00525 c.next = model->data( model->index( end + 1, 0, parent ) );
00526 remove.push( c );
00527 }
00528
00534 void ModelTest::rowsRemoved( const QModelIndex& parent, int start, int end )
00535 {
00536 Changing c = remove.pop();
00537 Q_ASSERT( c.parent == parent );
00538 Q_ASSERT( c.oldSize - ( end - start + 1 ) == model->rowCount( parent ) );
00539 Q_ASSERT( c.last == model->data( model->index( start - 1, 0, c.parent ) ) );
00540 Q_ASSERT( c.next == model->data( model->index( start, 0, c.parent ) ) );
00541 }