ctkModelTester.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. // Qt includes
  15. #include <QDebug>
  16. #include <QStack>
  17. // CTK includes
  18. #include "ctkModelTester.h"
  19. //-----------------------------------------------------------------------------
  20. class ctkModelTesterPrivate
  21. {
  22. public:
  23. ctkModelTesterPrivate();
  24. QAbstractItemModel *Model;
  25. bool ThrowOnError;
  26. bool NestedInserts;
  27. bool TestDataEnabled;
  28. bool Verbose;
  29. struct Change
  30. {
  31. QModelIndex Parent;
  32. Qt::Orientation Orientation;
  33. int Start;
  34. int End;
  35. int Count;
  36. QList<QPersistentModelIndex> Items;
  37. };
  38. QStack<Change> AboutToBeInserted;
  39. QStack<Change> AboutToBeRemoved;
  40. QList<QPersistentModelIndex> LayoutAboutToBeChanged;
  41. };
  42. //-----------------------------------------------------------------------------
  43. // ctkModelTesterPrivate methods
  44. //-----------------------------------------------------------------------------
  45. ctkModelTesterPrivate::ctkModelTesterPrivate()
  46. {
  47. this->Model = 0;
  48. this->ThrowOnError = true;
  49. this->NestedInserts = false;
  50. this->TestDataEnabled = true;
  51. this->Verbose = true;
  52. }
  53. //-----------------------------------------------------------------------------
  54. // ctkModelTester methods
  55. //-----------------------------------------------------------------------------
  56. ctkModelTester::ctkModelTester(QObject *_parent)
  57. :QObject(_parent)
  58. , d_ptr(new ctkModelTesterPrivate)
  59. {
  60. }
  61. //-----------------------------------------------------------------------------
  62. ctkModelTester::ctkModelTester(QAbstractItemModel *_model, QObject *_parent)
  63. :QObject(_parent)
  64. , d_ptr(new ctkModelTesterPrivate)
  65. {
  66. this->setModel(_model);
  67. }
  68. //-----------------------------------------------------------------------------
  69. ctkModelTester::~ctkModelTester()
  70. {
  71. }
  72. //-----------------------------------------------------------------------------
  73. void ctkModelTester::setModel(QAbstractItemModel *_model)
  74. {
  75. Q_D(ctkModelTester);
  76. if (d->Model)
  77. {
  78. // disconnect
  79. d->Model->disconnect(this);
  80. d->AboutToBeInserted.clear();
  81. d->AboutToBeRemoved.clear();
  82. d->LayoutAboutToBeChanged.clear();
  83. }
  84. if (_model)
  85. {
  86. connect(_model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
  87. this, SLOT(onColumnsAboutToBeInserted(QModelIndex,int,int)));
  88. connect(_model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
  89. this, SLOT(onColumnsAboutToBeRemoved(QModelIndex,int,int)));
  90. connect(_model, SIGNAL(columnsInserted(QModelIndex,int,int)),
  91. this, SLOT(onColumnsInserted(QModelIndex,int,int)));
  92. connect(_model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
  93. this, SLOT(onColumnsRemoved(QModelIndex,int,int)));
  94. connect(_model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
  95. this, SLOT(onDataChanged(QModelIndex,QModelIndex)));
  96. connect(_model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
  97. this, SLOT(onHeaderDataChanged(Qt::Orientation,int,int)));
  98. connect(_model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(onLayoutAboutToBeChanged()));
  99. connect(_model, SIGNAL(layoutChanged()), this, SLOT(onLayoutChanged()));
  100. connect(_model, SIGNAL(modelAboutToBeReset()), this, SLOT(onModelAboutToBeReset()));
  101. connect(_model, SIGNAL(modelReset()), this, SLOT(onModelReset()));
  102. connect(_model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
  103. this, SLOT(onRowsAboutToBeInserted(QModelIndex,int,int)));
  104. connect(_model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
  105. this, SLOT(onRowsAboutToBeRemoved(QModelIndex,int,int)));
  106. connect(_model, SIGNAL(rowsInserted(QModelIndex,int,int)),
  107. this, SLOT(onRowsInserted(QModelIndex,int,int)));
  108. connect(_model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
  109. this, SLOT(onRowsRemoved(QModelIndex,int,int)));
  110. }
  111. d->Model = _model;
  112. this->testModel();
  113. }
  114. //-----------------------------------------------------------------------------
  115. QAbstractItemModel* ctkModelTester::model()const
  116. {
  117. Q_D(const ctkModelTester);
  118. return d->Model;
  119. }
  120. //-----------------------------------------------------------------------------
  121. void ctkModelTester::setThrowOnError(bool throwException)
  122. {
  123. Q_D(ctkModelTester);
  124. d->ThrowOnError = throwException;
  125. }
  126. //-----------------------------------------------------------------------------
  127. bool ctkModelTester::throwOnError()const
  128. {
  129. Q_D(const ctkModelTester);
  130. return d->ThrowOnError;
  131. }
  132. //-----------------------------------------------------------------------------
  133. void ctkModelTester::setNestedInserts( bool nestedInsertsValue )
  134. {
  135. Q_D(ctkModelTester);
  136. d->NestedInserts = nestedInsertsValue;
  137. }
  138. //-----------------------------------------------------------------------------
  139. bool ctkModelTester::nestedInserts()const
  140. {
  141. Q_D(const ctkModelTester);
  142. return d->NestedInserts;
  143. }
  144. //-----------------------------------------------------------------------------
  145. void ctkModelTester::setTestDataEnabled( bool enable )
  146. {
  147. Q_D(ctkModelTester);
  148. d->TestDataEnabled = enable;
  149. }
  150. //-----------------------------------------------------------------------------
  151. bool ctkModelTester::testDataEnabled()const
  152. {
  153. Q_D(const ctkModelTester);
  154. return d->TestDataEnabled;
  155. }
  156. //-----------------------------------------------------------------------------
  157. void ctkModelTester::setVerbose(bool verboseValue)
  158. {
  159. Q_D(ctkModelTester);
  160. d->Verbose = verboseValue;
  161. }
  162. //-----------------------------------------------------------------------------
  163. bool ctkModelTester::verbose()const
  164. {
  165. Q_D(const ctkModelTester);
  166. return d->Verbose;
  167. }
  168. //-----------------------------------------------------------------------------
  169. void ctkModelTester::test(bool result, const QString& errorString)const
  170. {
  171. Q_D(const ctkModelTester);
  172. if (result)
  173. {
  174. return;
  175. }
  176. if (d->Verbose)
  177. {
  178. qDebug() << errorString;
  179. }
  180. if (this->throwOnError())
  181. {
  182. throw errorString;
  183. }
  184. }
  185. //-----------------------------------------------------------------------------
  186. void ctkModelTester::testModelIndex(const QModelIndex& index)const
  187. {
  188. Q_D(const ctkModelTester);
  189. if (!index.isValid())
  190. {// invalid index
  191. this->test(index.model() == 0, "An invalid index can't have a valid model.");
  192. this->test(index.column() == -1, "An invalid index can't have a valid column.");
  193. this->test(index.row() == -1, "An invalid index can't have a valid row.");
  194. this->test(index.parent().isValid() == false, "An invalid index can't have a valid parent.");
  195. this->test(index.row() == -1, "An invalid index can't have a valid row.");
  196. for(int i = 0; i < 100; ++i)
  197. {
  198. this->test(index.sibling(i % 10, i / 10).isValid() == false, "An invalid index can't have valid sibling.");
  199. }
  200. }
  201. else
  202. {// valid index
  203. this->test(index.model() == d->Model, "A valid index must have a valid model.");
  204. this->test(index.column() >= 0, "An valid index can't have an invalid column.");
  205. this->test(index.row() >= 0, "An valid index can't have an invalid row.");
  206. this->test(index == index.sibling(index.row(), index.column()), "Index's row and/or column is wrong.");
  207. }
  208. this->testData(index);
  209. this->testParent(index);
  210. }
  211. //-----------------------------------------------------------------------------
  212. void ctkModelTester::testData(const QModelIndex& index)const
  213. {
  214. Q_D(const ctkModelTester);
  215. if (!d->TestDataEnabled)
  216. {
  217. return;
  218. }
  219. if (!index.isValid())
  220. {
  221. this->test(!index.data(Qt::DisplayRole).isValid(),
  222. QString("An invalid index can't have valid data: %1")
  223. .arg(index.data(Qt::DisplayRole).toString()));
  224. }
  225. else
  226. {
  227. this->test(index.data(Qt::DisplayRole).isValid(),
  228. QString("A valid index can't have invalid data: %1, %2, %3")
  229. .arg(index.row()).arg(index.column()).arg(long(index.internalPointer())));
  230. }
  231. }
  232. //-----------------------------------------------------------------------------
  233. void ctkModelTester::testParent(const QModelIndex& vparent)const
  234. {
  235. Q_D(const ctkModelTester);
  236. if (!d->Model)
  237. {
  238. return;
  239. }
  240. if (!d->Model->hasChildren(vparent))
  241. {
  242. // it's asking a lot :-)
  243. //this->test(d->Model->columnCount(vparent) <= 0, "A parent with no children can't have a columnCount > 0.");
  244. this->test(d->Model->rowCount(vparent) <= 0, "A parent with no children can't have a rowCount > 0.");
  245. }
  246. else
  247. {
  248. this->test(d->Model->columnCount(vparent) > 0, "A parent with children can't have a columnCount <= 0.");
  249. this->test(d->Model->rowCount(vparent) > 0 || d->Model->canFetchMore(vparent), "A parent with children can't have a rowCount <= 0. or if it does, canFetchMore should return true");
  250. }
  251. if (!vparent.isValid())
  252. {// otherwise there will be an infinite loop
  253. return;
  254. }
  255. for (int i = 0 ; i < d->Model->rowCount(vparent); ++i)
  256. {
  257. for (int j = 0; j < d->Model->columnCount(vparent); ++j)
  258. {
  259. this->test(d->Model->hasIndex(i, j, vparent), "hasIndex should return true for int range {0->rowCount(), 0->columnCount()}");
  260. QModelIndex child = vparent.child(i, j);
  261. this->test(child.row() == i, "A child's row must be the same as given");
  262. this->test(child.column() == j, "A child's column must be the same as given");
  263. QModelIndex childParent = child.parent();
  264. this->test(childParent == vparent, "A child's parent can't be different from its parent");
  265. this->testModelIndex(child);
  266. }
  267. }
  268. }
  269. //-----------------------------------------------------------------------------
  270. void ctkModelTester::testPersistentModelIndex(const QPersistentModelIndex& index)const
  271. {
  272. Q_D(const ctkModelTester);
  273. //qDebug() << "Test persistent Index: " << index ;
  274. this->test(index.isValid(), "Persistent model index can't be invalid");
  275. // did you forget to call QAbstractItemModel::changePersistentIndex() between
  276. // beginLayoutChanged() and changePersistentIndex() ?
  277. QModelIndex modelIndex = d->Model->index(index.row(), index.column(), index.parent());
  278. this->test(modelIndex == index,
  279. QString("Persistent index (%1, %2) can't be invalid").arg(index.row()).arg(index.column()));
  280. }
  281. //-----------------------------------------------------------------------------
  282. void ctkModelTester::testModel()const
  283. {
  284. Q_D(const ctkModelTester);
  285. if (d->Model == 0)
  286. {
  287. return;
  288. }
  289. for (int i = 0 ; i < d->Model->rowCount(); ++i)
  290. {
  291. for (int j = 0; j < d->Model->columnCount(); ++j)
  292. {
  293. this->test(d->Model->hasIndex(i, j), "hasIndex should return true for int range {0->rowCount(), 0->columnCount()}");
  294. QModelIndex child = d->Model->index(i, j);
  295. this->test(child.row() == i, "Row should be consistent");
  296. this->test(child.column() == j, "Column should be consistent");
  297. this->test(!child.parent().isValid(), "A child's parent can't be different from its parent");
  298. this->testModelIndex(child);
  299. }
  300. }
  301. }
  302. //-----------------------------------------------------------------------------
  303. void ctkModelTester::onColumnsAboutToBeInserted(const QModelIndex & vparent, int start, int end)
  304. {
  305. //qDebug() << "columnsAboutToBeInserted: " << vparent << start << end;
  306. this->onItemsAboutToBeInserted(vparent, Qt::Horizontal, start, end);
  307. }
  308. //-----------------------------------------------------------------------------
  309. void ctkModelTester::onColumnsAboutToBeRemoved(const QModelIndex & vparent, int start, int end)
  310. {
  311. //qDebug() << "columnsAboutToBeRemoved: " << vparent << start << end;
  312. this->onItemsAboutToBeRemoved(vparent, Qt::Horizontal, start, end);
  313. }
  314. //-----------------------------------------------------------------------------
  315. void ctkModelTester::onColumnsInserted(const QModelIndex & vparent, int start, int end)
  316. {
  317. //qDebug() << "columnsInserted: " << vparent << start << end;
  318. this->onItemsInserted(vparent, Qt::Horizontal, start, end);
  319. }
  320. //-----------------------------------------------------------------------------
  321. void ctkModelTester::onColumnsRemoved(const QModelIndex & vparent, int start, int end)
  322. {
  323. //qDebug() << "columnsRemoved: " << vparent << start << end;
  324. this->onItemsRemoved(vparent, Qt::Horizontal, start, end);
  325. }
  326. //-----------------------------------------------------------------------------
  327. void ctkModelTester::onDataChanged(const QModelIndex & topLeft, const QModelIndex & bottomRight)
  328. {
  329. this->test(topLeft.parent() == bottomRight.parent(), "DataChanged support items with the same parent only");
  330. this->test(topLeft.row() >= bottomRight.row(), "topLeft can't have a row lower than bottomRight");
  331. this->test(bottomRight.column() >= topLeft.column(), "topLeft can't have a column lower than bottomRight");
  332. for (int i = topLeft.row(); i <= bottomRight.row(); ++i)
  333. {
  334. for (int j = topLeft.column(); j <= bottomRight.column(); ++j)
  335. {
  336. this->test(topLeft.sibling(i,j).isValid(), "Changed data must be valid");
  337. // do the test on the indexes here, it's easier to debug than in testModel();
  338. this->testModelIndex(topLeft.sibling(i,j));
  339. }
  340. }
  341. this->testModel();
  342. }
  343. //-----------------------------------------------------------------------------
  344. void ctkModelTester::onHeaderDataChanged(Qt::Orientation orientation, int first, int last)
  345. {
  346. Q_D(ctkModelTester);
  347. this->test(first <= last, "Changed headers have wrong indexes");
  348. switch (orientation)
  349. {
  350. case Qt::Horizontal:
  351. this->test(d->Model->columnCount() > last, "There is no more horizontal headers than columns.");
  352. break;
  353. case Qt::Vertical:
  354. this->test(d->Model->rowCount() > last, "There is no more vertical headers than rows.");
  355. break;
  356. }
  357. this->testModel();
  358. }
  359. //-----------------------------------------------------------------------------
  360. QList<QPersistentModelIndex> ctkModelTester::persistentModelIndexes(const QModelIndex& index)const
  361. {
  362. Q_D(const ctkModelTester);
  363. QList<QPersistentModelIndex> list;
  364. for (int i = 0; i < d->Model->rowCount(index); ++i)
  365. {
  366. for (int j = 0; j < d->Model->columnCount(index); ++j)
  367. {
  368. QPersistentModelIndex child = d->Model->index(i, j, index);
  369. list.append(child);
  370. list += this->ctkModelTester::persistentModelIndexes(child);
  371. }
  372. }
  373. return list;
  374. }
  375. //-----------------------------------------------------------------------------
  376. void ctkModelTester::onLayoutAboutToBeChanged()
  377. {
  378. Q_D(ctkModelTester);
  379. d->LayoutAboutToBeChanged = this->persistentModelIndexes(QModelIndex());
  380. this->testModel();
  381. }
  382. //-----------------------------------------------------------------------------
  383. void ctkModelTester::onLayoutChanged()
  384. {
  385. Q_D(ctkModelTester);
  386. foreach (const QPersistentModelIndex& index, d->LayoutAboutToBeChanged)
  387. {
  388. this->testPersistentModelIndex(index);
  389. }
  390. d->LayoutAboutToBeChanged.clear();
  391. this->testModel();
  392. }
  393. //-----------------------------------------------------------------------------
  394. void ctkModelTester::onModelAboutToBeReset()
  395. {
  396. this->testModel();
  397. }
  398. //-----------------------------------------------------------------------------
  399. void ctkModelTester::onModelReset()
  400. {
  401. this->testModel();
  402. }
  403. //-----------------------------------------------------------------------------
  404. void ctkModelTester::onRowsAboutToBeInserted(const QModelIndex &vparent, int start, int end)
  405. {
  406. // if (d->Verbose)
  407. // {
  408. // qDebug() << "rowsAboutToBeInserted: " << vparent << start << end;
  409. // }
  410. this->onItemsAboutToBeInserted(vparent, Qt::Vertical, start, end);
  411. }
  412. //-----------------------------------------------------------------------------
  413. void ctkModelTester::onRowsAboutToBeRemoved(const QModelIndex &vparent, int start, int end)
  414. {
  415. // if (d->Verbose)
  416. // {
  417. // qDebug() << "rowsAboutToBeRemoved: " << vparent << start << end;
  418. // }
  419. this->onItemsAboutToBeRemoved(vparent, Qt::Vertical, start, end);
  420. }
  421. //-----------------------------------------------------------------------------
  422. void ctkModelTester::onRowsInserted(const QModelIndex & vparent, int start, int end)
  423. {
  424. // if (d->Verbose)
  425. // {
  426. // qDebug() << "rowsInserted: " << vparent << start << end;
  427. // }
  428. this->onItemsInserted(vparent, Qt::Vertical, start, end);
  429. }
  430. //-----------------------------------------------------------------------------
  431. void ctkModelTester::onRowsRemoved(const QModelIndex & vparent, int start, int end)
  432. {
  433. // if (d->Verbose)
  434. // {
  435. // qDebug() << "rowsRemoved: " << vparent << start << end;
  436. // }
  437. this->onItemsRemoved(vparent, Qt::Vertical, start, end);
  438. }
  439. //-----------------------------------------------------------------------------
  440. void ctkModelTester::onItemsAboutToBeInserted(const QModelIndex &vparent, Qt::Orientation orientation, int start, int end)
  441. {
  442. Q_D(ctkModelTester);
  443. this->test(start <= end, "Start can't be higher than end");
  444. //Not sure about that
  445. if (!d->NestedInserts)
  446. {
  447. this->test(d->AboutToBeInserted.size() == 0, "While inserting items, you can't insert other items.");
  448. }
  449. //Not sure about that
  450. this->test(d->AboutToBeRemoved.size() == 0, "While removing items, you can't insert other items.");
  451. ctkModelTesterPrivate::Change change;
  452. change.Parent = vparent;
  453. change.Orientation = orientation;
  454. change.Start = start;
  455. change.End = end;
  456. change.Count = (orientation == Qt::Vertical ? d->Model->rowCount(vparent) :d->Model->columnCount(vparent) );
  457. change.Items = this->persistentModelIndexes(vparent);
  458. d->AboutToBeInserted.push(change);
  459. this->testModel();
  460. }
  461. //-----------------------------------------------------------------------------
  462. void ctkModelTester::onItemsAboutToBeRemoved(const QModelIndex &vparent, Qt::Orientation orientation, int start, int end)
  463. {
  464. Q_D(ctkModelTester);
  465. this->test(start <= end, "Start can't be higher than end");
  466. //Not sure about that
  467. this->test(d->AboutToBeInserted.size() == 0, "While inserting items, you can't remove other items.");
  468. //Not sure about that
  469. this->test(d->AboutToBeRemoved.size() == 0, "While removing items, you can't remove other items.");
  470. int count = (orientation == Qt::Vertical ? d->Model->rowCount(vparent) :d->Model->columnCount(vparent) );
  471. this->test(start < count, "Item to remove can't be invalid");
  472. this->test(end < count, "Item to remove can't be invalid");
  473. ctkModelTesterPrivate::Change change;
  474. change.Parent = vparent;
  475. change.Orientation = orientation;
  476. change.Start = start;
  477. change.End = end;
  478. change.Count = count;
  479. for (int i = 0 ; i < count; ++i)
  480. {
  481. QPersistentModelIndex index;
  482. index = (orientation == Qt::Vertical ? d->Model->index(i, 0, vparent) : d->Model->index(0, i, vparent));
  483. this->test(index.isValid(), "Index invalid");
  484. if (orientation == Qt::Vertical && (index.row() < start || index.row() > end))
  485. {
  486. change.Items.append(index);
  487. }
  488. if (orientation == Qt::Horizontal && (index.column() < start || index.column() > end))
  489. {
  490. change.Items.append(index);
  491. }
  492. }
  493. d->AboutToBeRemoved.push(change);
  494. this->testModel();
  495. // if (d->Verbose)
  496. // {
  497. // qDebug() << "About to be removed: " << start << " " << end <<vparent << count << change.Items.count();
  498. // }
  499. }
  500. //-----------------------------------------------------------------------------
  501. void ctkModelTester::onItemsInserted(const QModelIndex & vparent, Qt::Orientation orientation, int start, int end)
  502. {
  503. Q_D(ctkModelTester);
  504. this->test(start <= end, "Start can't be higher end");
  505. this->test(d->AboutToBeInserted.size() != 0, "rowsInserted() has been emitted, but not rowsAboutToBeInserted.");
  506. //Not sure about that
  507. this->test(d->AboutToBeRemoved.size() == 0, "While removing items, you can't insert other items.");
  508. ctkModelTesterPrivate::Change change = d->AboutToBeInserted.pop();
  509. this->test(change.Parent == vparent, "Parent can't be different");
  510. this->test(change.Orientation == orientation, "Orientation can't be different");
  511. this->test(change.Start == start, "Start can't be different");
  512. this->test(change.End == end, "End can't be different");
  513. int count = (orientation == Qt::Vertical ? d->Model->rowCount(vparent) :d->Model->columnCount(vparent) );
  514. this->test(change.Count < count, "The new count number can't be lower");
  515. this->test(count - change.Count == (end - start + 1) , "The new count number can't be lower");
  516. foreach(const QPersistentModelIndex& index, change.Items)
  517. {
  518. this->testPersistentModelIndex(index);
  519. }
  520. change.Items.clear();
  521. this->testModel();
  522. }
  523. //-----------------------------------------------------------------------------
  524. void ctkModelTester::onItemsRemoved(const QModelIndex & vparent, Qt::Orientation orientation, int start, int end)
  525. {
  526. Q_D(ctkModelTester);
  527. this->test(start <= end, "Start can't be higher end");
  528. this->test(d->AboutToBeRemoved.size() != 0, "rowsRemoved() has been emitted, but not rowsAboutToBeRemoved.");
  529. //Not sure about that
  530. this->test(d->AboutToBeInserted.size() == 0, "While inserted items, you can't remove other items.");
  531. ctkModelTesterPrivate::Change change = d->AboutToBeRemoved.pop();
  532. this->test(change.Parent == vparent, "Parent can't be different");
  533. this->test(change.Orientation == orientation, "Orientation can't be different");
  534. this->test(change.Start == start, "Start can't be different");
  535. this->test(change.End == end, "End can't be different");
  536. int count = (orientation == Qt::Vertical ? d->Model->rowCount(vparent) :d->Model->columnCount(vparent) );
  537. this->test(change.Count > count, "The new count number can't be higher");
  538. this->test(change.Count - count == (end - start + 1) , "The new count number can't be higher");
  539. foreach(const QPersistentModelIndex& index, change.Items)
  540. {
  541. this->testPersistentModelIndex(index);
  542. }
  543. change.Items.clear();
  544. this->testModel();
  545. }