| 1 |
/**************************************************************************** |
| 2 |
** |
| 3 |
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). |
| 4 |
** All rights reserved. |
| 5 |
** Contact: Nokia Corporation (qt-info@nokia.com) |
| 6 |
** |
| 7 |
** This file is part of the test suite of the Qt Toolkit. |
| 8 |
** |
| 9 |
** $QT_BEGIN_LICENSE:LGPL$ |
| 10 |
** GNU Lesser General Public License Usage |
| 11 |
** This file may be used under the terms of the GNU Lesser General Public |
| 12 |
** License version 2.1 as published by the Free Software Foundation and |
| 13 |
** appearing in the file LICENSE.LGPL included in the packaging of this |
| 14 |
** file. Please review the following information to ensure the GNU Lesser |
| 15 |
** General Public License version 2.1 requirements will be met: |
| 16 |
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
| 17 |
** |
| 18 |
** In addition, as a special exception, Nokia gives you certain additional |
| 19 |
** rights. These rights are described in the Nokia Qt LGPL Exception |
| 20 |
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
| 21 |
** |
| 22 |
** GNU General Public License Usage |
| 23 |
** Alternatively, this file may be used under the terms of the GNU General |
| 24 |
** Public License version 3.0 as published by the Free Software Foundation |
| 25 |
** and appearing in the file LICENSE.GPL included in the packaging of this |
| 26 |
** file. Please review the following information to ensure the GNU General |
| 27 |
** Public License version 3.0 requirements will be met: |
| 28 |
** http://www.gnu.org/copyleft/gpl.html. |
| 29 |
** |
| 30 |
** Other Usage |
| 31 |
** Alternatively, this file may be used in accordance with the terms and |
| 32 |
** conditions contained in a signed written agreement between you and Nokia. |
| 33 |
** |
| 34 |
** |
| 35 |
** |
| 36 |
** |
| 37 |
** |
| 38 |
** $QT_END_LICENSE$ |
| 39 |
** |
| 40 |
****************************************************************************/ |
| 41 |
|
| 42 |
|
| 43 |
#include <QtGui/QtGui> |
| 44 |
|
| 45 |
#include "modeltest.h" |
| 46 |
|
| 47 |
#include <QtTest/QtTest> |
| 48 |
|
| 49 |
Q_DECLARE_METATYPE ( QModelIndex ) |
| 50 |
|
| 51 |
/*! |
| 52 |
Connect to all of the models signals. Whenever anything happens recheck everything. |
| 53 |
*/ |
| 54 |
ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false ) |
| 55 |
{ |
| 56 |
if (!model) |
| 57 |
qFatal("%s: model must not be null", Q_FUNC_INFO); |
| 58 |
|
| 59 |
connect ( model, SIGNAL ( columnsAboutToBeInserted ( const QModelIndex &, int, int ) ), |
| 60 |
this, SLOT ( runAllTests() ) ); |
| 61 |
connect ( model, SIGNAL ( columnsAboutToBeRemoved ( const QModelIndex &, int, int ) ), |
| 62 |
this, SLOT ( runAllTests() ) ); |
| 63 |
connect ( model, SIGNAL ( columnsInserted ( const QModelIndex &, int, int ) ), |
| 64 |
this, SLOT ( runAllTests() ) ); |
| 65 |
connect ( model, SIGNAL ( columnsRemoved ( const QModelIndex &, int, int ) ), |
| 66 |
this, SLOT ( runAllTests() ) ); |
| 67 |
connect ( model, SIGNAL ( dataChanged ( const QModelIndex &, const QModelIndex & ) ), |
| 68 |
this, SLOT ( runAllTests() ) ); |
| 69 |
connect ( model, SIGNAL ( headerDataChanged ( Qt::Orientation, int, int ) ), |
| 70 |
this, SLOT ( runAllTests() ) ); |
| 71 |
connect ( model, SIGNAL ( layoutAboutToBeChanged () ), this, SLOT ( runAllTests() ) ); |
| 72 |
connect ( model, SIGNAL ( layoutChanged () ), this, SLOT ( runAllTests() ) ); |
| 73 |
connect ( model, SIGNAL ( modelReset () ), this, SLOT ( runAllTests() ) ); |
| 74 |
connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), |
| 75 |
this, SLOT ( runAllTests() ) ); |
| 76 |
connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), |
| 77 |
this, SLOT ( runAllTests() ) ); |
| 78 |
connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), |
| 79 |
this, SLOT ( runAllTests() ) ); |
| 80 |
connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), |
| 81 |
this, SLOT ( runAllTests() ) ); |
| 82 |
|
| 83 |
// Special checks for inserting/removing |
| 84 |
connect ( model, SIGNAL ( layoutAboutToBeChanged() ), |
| 85 |
this, SLOT ( layoutAboutToBeChanged() ) ); |
| 86 |
connect ( model, SIGNAL ( layoutChanged() ), |
| 87 |
this, SLOT ( layoutChanged() ) ); |
| 88 |
|
| 89 |
connect ( model, SIGNAL ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ), |
| 90 |
this, SLOT ( rowsAboutToBeInserted ( const QModelIndex &, int, int ) ) ); |
| 91 |
connect ( model, SIGNAL ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ), |
| 92 |
this, SLOT ( rowsAboutToBeRemoved ( const QModelIndex &, int, int ) ) ); |
| 93 |
connect ( model, SIGNAL ( rowsInserted ( const QModelIndex &, int, int ) ), |
| 94 |
this, SLOT ( rowsInserted ( const QModelIndex &, int, int ) ) ); |
| 95 |
connect ( model, SIGNAL ( rowsRemoved ( const QModelIndex &, int, int ) ), |
| 96 |
this, SLOT ( rowsRemoved ( const QModelIndex &, int, int ) ) ); |
| 97 |
|
| 98 |
runAllTests(); |
| 99 |
} |
| 100 |
|
| 101 |
void ModelTest::runAllTests() |
| 102 |
{ |
| 103 |
if ( fetchingMore ) |
| 104 |
return; |
| 105 |
nonDestructiveBasicTest(); |
| 106 |
rowCount(); |
| 107 |
columnCount(); |
| 108 |
hasIndex(); |
| 109 |
index(); |
| 110 |
parent(); |
| 111 |
data(); |
| 112 |
} |
| 113 |
|
| 114 |
/*! |
| 115 |
nonDestructiveBasicTest tries to call a number of the basic functions (not all) |
| 116 |
to make sure the model doesn't outright segfault, testing the functions that makes sense. |
| 117 |
*/ |
| 118 |
void ModelTest::nonDestructiveBasicTest() |
| 119 |
{ |
| 120 |
QVERIFY( model->buddy ( QModelIndex() ) == QModelIndex() ); |
| 121 |
model->canFetchMore ( QModelIndex() ); |
| 122 |
QVERIFY( model->columnCount ( QModelIndex() ) >= 0 ); |
| 123 |
QVERIFY( model->data ( QModelIndex() ) == QVariant() ); |
| 124 |
fetchingMore = true; |
| 125 |
model->fetchMore ( QModelIndex() ); |
| 126 |
fetchingMore = false; |
| 127 |
Qt::ItemFlags flags = model->flags ( QModelIndex() ); |
| 128 |
QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 ); |
| 129 |
model->hasChildren ( QModelIndex() ); |
| 130 |
model->hasIndex ( 0, 0 ); |
| 131 |
model->headerData ( 0, Qt::Horizontal ); |
| 132 |
model->index ( 0, 0 ); |
| 133 |
model->itemData ( QModelIndex() ); |
| 134 |
QVariant cache; |
| 135 |
model->match ( QModelIndex(), -1, cache ); |
| 136 |
model->mimeTypes(); |
| 137 |
QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); |
| 138 |
QVERIFY( model->rowCount() >= 0 ); |
| 139 |
QVariant variant; |
| 140 |
model->setData ( QModelIndex(), variant, -1 ); |
| 141 |
model->setHeaderData ( -1, Qt::Horizontal, QVariant() ); |
| 142 |
model->setHeaderData ( 999999, Qt::Horizontal, QVariant() ); |
| 143 |
QMap<int, QVariant> roles; |
| 144 |
model->sibling ( 0, 0, QModelIndex() ); |
| 145 |
model->span ( QModelIndex() ); |
| 146 |
model->supportedDropActions(); |
| 147 |
} |
| 148 |
|
| 149 |
/*! |
| 150 |
Tests model's implementation of QAbstractItemModel::rowCount() and hasChildren() |
| 151 |
|
| 152 |
Models that are dynamically populated are not as fully tested here. |
| 153 |
*/ |
| 154 |
void ModelTest::rowCount() |
| 155 |
{ |
| 156 |
// qDebug() << "rc"; |
| 157 |
// check top row |
| 158 |
QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); |
| 159 |
int rows = model->rowCount ( topIndex ); |
| 160 |
QVERIFY( rows >= 0 ); |
| 161 |
if ( rows > 0 ) |
| 162 |
QVERIFY( model->hasChildren ( topIndex ) ); |
| 163 |
|
| 164 |
QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex ); |
| 165 |
if ( secondLevelIndex.isValid() ) { // not the top level |
| 166 |
// check a row count where parent is valid |
| 167 |
rows = model->rowCount ( secondLevelIndex ); |
| 168 |
QVERIFY( rows >= 0 ); |
| 169 |
if ( rows > 0 ) |
| 170 |
QVERIFY( model->hasChildren ( secondLevelIndex ) ); |
| 171 |
} |
| 172 |
|
| 173 |
// The models rowCount() is tested more extensively in checkChildren(), |
| 174 |
// but this catches the big mistakes |
| 175 |
} |
| 176 |
|
| 177 |
/*! |
| 178 |
Tests model's implementation of QAbstractItemModel::columnCount() and hasChildren() |
| 179 |
*/ |
| 180 |
void ModelTest::columnCount() |
| 181 |
{ |
| 182 |
// check top row |
| 183 |
QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); |
| 184 |
QVERIFY( model->columnCount ( topIndex ) >= 0 ); |
| 185 |
|
| 186 |
// check a column count where parent is valid |
| 187 |
QModelIndex childIndex = model->index ( 0, 0, topIndex ); |
| 188 |
if ( childIndex.isValid() ) |
| 189 |
QVERIFY( model->columnCount ( childIndex ) >= 0 ); |
| 190 |
|
| 191 |
// columnCount() is tested more extensively in checkChildren(), |
| 192 |
// but this catches the big mistakes |
| 193 |
} |
| 194 |
|
| 195 |
/*! |
| 196 |
Tests model's implementation of QAbstractItemModel::hasIndex() |
| 197 |
*/ |
| 198 |
void ModelTest::hasIndex() |
| 199 |
{ |
| 200 |
// qDebug() << "hi"; |
| 201 |
// Make sure that invalid values returns an invalid index |
| 202 |
QVERIFY( !model->hasIndex ( -2, -2 ) ); |
| 203 |
QVERIFY( !model->hasIndex ( -2, 0 ) ); |
| 204 |
QVERIFY( !model->hasIndex ( 0, -2 ) ); |
| 205 |
|
| 206 |
int rows = model->rowCount(); |
| 207 |
int columns = model->columnCount(); |
| 208 |
|
| 209 |
// check out of bounds |
| 210 |
QVERIFY( !model->hasIndex ( rows, columns ) ); |
| 211 |
QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) ); |
| 212 |
|
| 213 |
if ( rows > 0 ) |
| 214 |
QVERIFY( model->hasIndex ( 0, 0 ) ); |
| 215 |
|
| 216 |
// hasIndex() is tested more extensively in checkChildren(), |
| 217 |
// but this catches the big mistakes |
| 218 |
} |
| 219 |
|
| 220 |
/*! |
| 221 |
Tests model's implementation of QAbstractItemModel::index() |
| 222 |
*/ |
| 223 |
void ModelTest::index() |
| 224 |
{ |
| 225 |
// qDebug() << "i"; |
| 226 |
// Make sure that invalid values returns an invalid index |
| 227 |
QVERIFY( model->index ( -2, -2 ) == QModelIndex() ); |
| 228 |
QVERIFY( model->index ( -2, 0 ) == QModelIndex() ); |
| 229 |
QVERIFY( model->index ( 0, -2 ) == QModelIndex() ); |
| 230 |
|
| 231 |
int rows = model->rowCount(); |
| 232 |
int columns = model->columnCount(); |
| 233 |
|
| 234 |
if ( rows == 0 ) |
| 235 |
return; |
| 236 |
|
| 237 |
// Catch off by one errors |
| 238 |
QVERIFY( model->index ( rows, columns ) == QModelIndex() ); |
| 239 |
QVERIFY( model->index ( 0, 0 ).isValid() ); |
| 240 |
|
| 241 |
// Make sure that the same index is *always* returned |
| 242 |
QModelIndex a = model->index ( 0, 0 ); |
| 243 |
QModelIndex b = model->index ( 0, 0 ); |
| 244 |
QVERIFY( a == b ); |
| 245 |
|
| 246 |
// index() is tested more extensively in checkChildren(), |
| 247 |
// but this catches the big mistakes |
| 248 |
} |
| 249 |
|
| 250 |
/*! |
| 251 |
Tests model's implementation of QAbstractItemModel::parent() |
| 252 |
*/ |
| 253 |
void ModelTest::parent() |
| 254 |
{ |
| 255 |
// qDebug() << "p"; |
| 256 |
// Make sure the model wont crash and will return an invalid QModelIndex |
| 257 |
// when asked for the parent of an invalid index. |
| 258 |
QVERIFY( model->parent ( QModelIndex() ) == QModelIndex() ); |
| 259 |
|
| 260 |
if ( model->rowCount() == 0 ) |
| 261 |
return; |
| 262 |
|
| 263 |
// Column 0 | Column 1 | |
| 264 |
// QModelIndex() | | |
| 265 |
// \- topIndex | topIndex1 | |
| 266 |
// \- childIndex | childIndex1 | |
| 267 |
|
| 268 |
// Common error test #1, make sure that a top level index has a parent |
| 269 |
// that is a invalid QModelIndex. |
| 270 |
QModelIndex topIndex = model->index ( 0, 0, QModelIndex() ); |
| 271 |
QVERIFY( model->parent ( topIndex ) == QModelIndex() ); |
| 272 |
|
| 273 |
// Common error test #2, make sure that a second level index has a parent |
| 274 |
// that is the first level index. |
| 275 |
if ( model->rowCount ( topIndex ) > 0 ) { |
| 276 |
QModelIndex childIndex = model->index ( 0, 0, topIndex ); |
| 277 |
QVERIFY( model->parent ( childIndex ) == topIndex ); |
| 278 |
} |
| 279 |
|
| 280 |
// Common error test #3, the second column should NOT have the same children |
| 281 |
// as the first column in a row. |
| 282 |
// Usually the second column shouldn't have children. |
| 283 |
QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() ); |
| 284 |
if ( model->rowCount ( topIndex1 ) > 0 ) { |
| 285 |
QModelIndex childIndex = model->index ( 0, 0, topIndex ); |
| 286 |
QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 ); |
| 287 |
QVERIFY( childIndex != childIndex1 ); |
| 288 |
} |
| 289 |
|
| 290 |
// Full test, walk n levels deep through the model making sure that all |
| 291 |
// parent's children correctly specify their parent. |
| 292 |
checkChildren ( QModelIndex() ); |
| 293 |
} |
| 294 |
|
| 295 |
/*! |
| 296 |
Called from the parent() test. |
| 297 |
|
| 298 |
A model that returns an index of parent X should also return X when asking |
| 299 |
for the parent of the index. |
| 300 |
|
| 301 |
This recursive function does pretty extensive testing on the whole model in an |
| 302 |
effort to catch edge cases. |
| 303 |
|
| 304 |
This function assumes that rowCount(), columnCount() and index() already work. |
| 305 |
If they have a bug it will point it out, but the above tests should have already |
| 306 |
found the basic bugs because it is easier to figure out the problem in |
| 307 |
those tests then this one. |
| 308 |
*/ |
| 309 |
void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth ) |
| 310 |
{ |
| 311 |
// First just try walking back up the tree. |
| 312 |
QModelIndex p = parent; |
| 313 |
while ( p.isValid() ) |
| 314 |
p = p.parent(); |
| 315 |
|
| 316 |
// For models that are dynamically populated |
| 317 |
if ( model->canFetchMore ( parent ) ) { |
| 318 |
fetchingMore = true; |
| 319 |
model->fetchMore ( parent ); |
| 320 |
fetchingMore = false; |
| 321 |
} |
| 322 |
|
| 323 |
int rows = model->rowCount ( parent ); |
| 324 |
int columns = model->columnCount ( parent ); |
| 325 |
|
| 326 |
if ( rows > 0 ) |
| 327 |
QVERIFY( model->hasChildren ( parent ) ); |
| 328 |
|
| 329 |
// Some further testing against rows(), columns(), and hasChildren() |
| 330 |
QVERIFY( rows >= 0 ); |
| 331 |
QVERIFY( columns >= 0 ); |
| 332 |
if ( rows > 0 ) |
| 333 |
QVERIFY( model->hasChildren ( parent ) ); |
| 334 |
|
| 335 |
//qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows |
| 336 |
// << "columns:" << columns << "parent column:" << parent.column(); |
| 337 |
|
| 338 |
QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) ); |
| 339 |
for ( int r = 0; r < rows; ++r ) { |
| 340 |
if ( model->canFetchMore ( parent ) ) { |
| 341 |
fetchingMore = true; |
| 342 |
model->fetchMore ( parent ); |
| 343 |
fetchingMore = false; |
| 344 |
} |
| 345 |
QVERIFY( !model->hasIndex ( r, columns + 1, parent ) ); |
| 346 |
for ( int c = 0; c < columns; ++c ) { |
| 347 |
QVERIFY( model->hasIndex ( r, c, parent ) ); |
| 348 |
QModelIndex index = model->index ( r, c, parent ); |
| 349 |
// rowCount() and columnCount() said that it existed... |
| 350 |
QVERIFY( index.isValid() ); |
| 351 |
|
| 352 |
// index() should always return the same index when called twice in a row |
| 353 |
QModelIndex modifiedIndex = model->index ( r, c, parent ); |
| 354 |
QVERIFY( index == modifiedIndex ); |
| 355 |
|
| 356 |
// Make sure we get the same index if we request it twice in a row |
| 357 |
QModelIndex a = model->index ( r, c, parent ); |
| 358 |
QModelIndex b = model->index ( r, c, parent ); |
| 359 |
QVERIFY( a == b ); |
| 360 |
|
| 361 |
// Some basic checking on the index that is returned |
| 362 |
QVERIFY( index.model() == model ); |
| 363 |
QCOMPARE( index.row(), r ); |
| 364 |
QCOMPARE( index.column(), c ); |
| 365 |
// While you can technically return a QVariant usually this is a sign |
| 366 |
// of a bug in data(). Disable if this really is ok in your model. |
| 367 |
// QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() ); |
| 368 |
|
| 369 |
// If the next test fails here is some somewhat useful debug you play with. |
| 370 |
|
| 371 |
if (model->parent(index) != parent) { |
| 372 |
qDebug() << r << c << currentDepth << model->data(index).toString() |
| 373 |
<< model->data(parent).toString(); |
| 374 |
qDebug() << index << parent << model->parent(index); |
| 375 |
// And a view that you can even use to show the model. |
| 376 |
// QTreeView view; |
| 377 |
// view.setModel(model); |
| 378 |
// view.show(); |
| 379 |
} |
| 380 |
|
| 381 |
// Check that we can get back our real parent. |
| 382 |
QCOMPARE( model->parent ( index ), parent ); |
| 383 |
|
| 384 |
// recursively go down the children |
| 385 |
if ( model->hasChildren ( index ) && currentDepth < 10 ) { |
| 386 |
//qDebug() << r << c << "has children" << model->rowCount(index); |
| 387 |
checkChildren ( index, ++currentDepth ); |
| 388 |
}/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/ |
| 389 |
|
| 390 |
// make sure that after testing the children that the index doesn't change. |
| 391 |
QModelIndex newerIndex = model->index ( r, c, parent ); |
| 392 |
QVERIFY( index == newerIndex ); |
| 393 |
} |
| 394 |
} |
| 395 |
} |
| 396 |
|
| 397 |
/*! |
| 398 |
Tests model's implementation of QAbstractItemModel::data() |
| 399 |
*/ |
| 400 |
void ModelTest::data() |
| 401 |
{ |
| 402 |
// Invalid index should return an invalid qvariant |
| 403 |
QVERIFY( !model->data ( QModelIndex() ).isValid() ); |
| 404 |
|
| 405 |
if ( model->rowCount() == 0 ) |
| 406 |
return; |
| 407 |
|
| 408 |
// A valid index should have a valid QVariant data |
| 409 |
QVERIFY( model->index ( 0, 0 ).isValid() ); |
| 410 |
|
| 411 |
// shouldn't be able to set data on an invalid index |
| 412 |
QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) ); |
| 413 |
|
| 414 |
// General Purpose roles that should return a QString |
| 415 |
QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole ); |
| 416 |
if ( variant.isValid() ) { |
| 417 |
QVERIFY( qVariantCanConvert<QString> ( variant ) ); |
| 418 |
} |
| 419 |
variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole ); |
| 420 |
if ( variant.isValid() ) { |
| 421 |
QVERIFY( qVariantCanConvert<QString> ( variant ) ); |
| 422 |
} |
| 423 |
variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole ); |
| 424 |
if ( variant.isValid() ) { |
| 425 |
QVERIFY( qVariantCanConvert<QString> ( variant ) ); |
| 426 |
} |
| 427 |
|
| 428 |
// General Purpose roles that should return a QSize |
| 429 |
variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole ); |
| 430 |
if ( variant.isValid() ) { |
| 431 |
QVERIFY( qVariantCanConvert<QSize> ( variant ) ); |
| 432 |
} |
| 433 |
|
| 434 |
// General Purpose roles that should return a QFont |
| 435 |
QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole ); |
| 436 |
if ( fontVariant.isValid() ) { |
| 437 |
QVERIFY( qVariantCanConvert<QFont> ( fontVariant ) ); |
| 438 |
} |
| 439 |
|
| 440 |
// Check that the alignment is one we know about |
| 441 |
QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole ); |
| 442 |
if ( textAlignmentVariant.isValid() ) { |
| 443 |
int alignment = textAlignmentVariant.toInt(); |
| 444 |
QCOMPARE( alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) ); |
| 445 |
} |
| 446 |
|
| 447 |
// General Purpose roles that should return a QColor |
| 448 |
QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole ); |
| 449 |
if ( colorVariant.isValid() ) { |
| 450 |
QVERIFY( qVariantCanConvert<QColor> ( colorVariant ) ); |
| 451 |
} |
| 452 |
|
| 453 |
colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole ); |
| 454 |
if ( colorVariant.isValid() ) { |
| 455 |
QVERIFY( qVariantCanConvert<QColor> ( colorVariant ) ); |
| 456 |
} |
| 457 |
|
| 458 |
// Check that the "check state" is one we know about. |
| 459 |
QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole ); |
| 460 |
if ( checkStateVariant.isValid() ) { |
| 461 |
int state = checkStateVariant.toInt(); |
| 462 |
QVERIFY( state == Qt::Unchecked || |
| 463 |
state == Qt::PartiallyChecked || |
| 464 |
state == Qt::Checked ); |
| 465 |
} |
| 466 |
} |
| 467 |
|
| 468 |
/*! |
| 469 |
Store what is about to be inserted to make sure it actually happens |
| 470 |
|
| 471 |
\sa rowsInserted() |
| 472 |
*/ |
| 473 |
void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int end ) |
| 474 |
{ |
| 475 |
// Q_UNUSED(end); |
| 476 |
// qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString() |
| 477 |
// << "current count of parent=" << model->rowCount ( parent ); // << "display of last=" << model->data( model->index(start-1, 0, parent) ); |
| 478 |
// qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) ); |
| 479 |
Changing c; |
| 480 |
c.parent = parent; |
| 481 |
c.oldSize = model->rowCount ( parent ); |
| 482 |
c.last = model->data ( model->index ( start - 1, 0, parent ) ); |
| 483 |
c.next = model->data ( model->index ( start, 0, parent ) ); |
| 484 |
insert.push ( c ); |
| 485 |
} |
| 486 |
|
| 487 |
/*! |
| 488 |
Confirm that what was said was going to happen actually did |
| 489 |
|
| 490 |
\sa rowsAboutToBeInserted() |
| 491 |
*/ |
| 492 |
void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end ) |
| 493 |
{ |
| 494 |
Changing c = insert.pop(); |
| 495 |
QVERIFY( c.parent == parent ); |
| 496 |
// qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize |
| 497 |
// << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent ); |
| 498 |
|
| 499 |
// for (int ii=start; ii <= end; ii++) |
| 500 |
// { |
| 501 |
// qDebug() << "itemWasInserted:" << ii << model->data ( model->index ( ii, 0, parent )); |
| 502 |
// } |
| 503 |
// qDebug(); |
| 504 |
|
| 505 |
QVERIFY( c.oldSize + ( end - start + 1 ) == model->rowCount ( parent ) ); |
| 506 |
QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); |
| 507 |
|
| 508 |
if (c.next != model->data(model->index(end + 1, 0, c.parent))) { |
| 509 |
qDebug() << start << end; |
| 510 |
for (int i=0; i < model->rowCount(); ++i) |
| 511 |
qDebug() << model->index(i, 0).data().toString(); |
| 512 |
qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent)); |
| 513 |
} |
| 514 |
|
| 515 |
QVERIFY( c.next == model->data ( model->index ( end + 1, 0, c.parent ) ) ); |
| 516 |
} |
| 517 |
|
| 518 |
void ModelTest::layoutAboutToBeChanged() |
| 519 |
{ |
| 520 |
for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i ) |
| 521 |
changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) ); |
| 522 |
} |
| 523 |
|
| 524 |
void ModelTest::layoutChanged() |
| 525 |
{ |
| 526 |
for ( int i = 0; i < changing.count(); ++i ) { |
| 527 |
QPersistentModelIndex p = changing[i]; |
| 528 |
QVERIFY( p == model->index ( p.row(), p.column(), p.parent() ) ); |
| 529 |
} |
| 530 |
changing.clear(); |
| 531 |
} |
| 532 |
|
| 533 |
/*! |
| 534 |
Store what is about to be inserted to make sure it actually happens |
| 535 |
|
| 536 |
\sa rowsRemoved() |
| 537 |
*/ |
| 538 |
void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end ) |
| 539 |
{ |
| 540 |
qDebug() << "ratbr" << parent << start << end; |
| 541 |
Changing c; |
| 542 |
c.parent = parent; |
| 543 |
c.oldSize = model->rowCount ( parent ); |
| 544 |
c.last = model->data ( model->index ( start - 1, 0, parent ) ); |
| 545 |
c.next = model->data ( model->index ( end + 1, 0, parent ) ); |
| 546 |
remove.push ( c ); |
| 547 |
} |
| 548 |
|
| 549 |
/*! |
| 550 |
Confirm that what was said was going to happen actually did |
| 551 |
|
| 552 |
\sa rowsAboutToBeRemoved() |
| 553 |
*/ |
| 554 |
void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end ) |
| 555 |
{ |
| 556 |
qDebug() << "rr" << parent << start << end; |
| 557 |
Changing c = remove.pop(); |
| 558 |
QVERIFY( c.parent == parent ); |
| 559 |
QVERIFY( c.oldSize - ( end - start + 1 ) == model->rowCount ( parent ) ); |
| 560 |
QVERIFY( c.last == model->data ( model->index ( start - 1, 0, c.parent ) ) ); |
| 561 |
QVERIFY( c.next == model->data ( model->index ( start, 0, c.parent ) ) ); |
| 562 |
} |