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