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