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