• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

parley

  • sources
  • kde-4.12
  • kdeedu
  • parley
  • src
  • modeltest
modeltest.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2007 Trolltech ASA. All rights reserved.
4 **
5 ** This file is part of the Qt Concurrent project on Trolltech Labs.
6 **
7 ** This file may be used under the terms of the GNU General Public
8 ** License version 2.0 as published by the Free Software Foundation
9 ** and appearing in the file LICENSE.GPL included in the packaging of
10 ** this file. Please review the following information to ensure GNU
11 ** General Public Licensing requirements will be met:
12 ** http://www.trolltech.com/products/qt/opensource.html
13 **
14 ** If you are unsure which license is appropriate for your use, please
15 ** review the following information:
16 ** http://www.trolltech.com/products/qt/licensing.html or contact the
17 ** sales department at sales@trolltech.com.
18 **
19 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 **
22 ****************************************************************************/
23 
24 #include "modeltest.h"
25 
26 #include <QtGui/QtGui>
27 
28 #include <KDebug>
29 
30 Q_DECLARE_METATYPE(QModelIndex)
31 
32 
35 ModelTest::ModelTest(QAbstractItemModel *_model, QObject *parent) : QObject(parent), model(_model), fetchingMore(false)
36 {
37  Q_ASSERT(model);
38 
39  connect(model, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
40  this, SLOT(runAllTests()));
41  connect(model, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
42  this, SLOT(runAllTests()));
43  connect(model, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
44  this, SLOT(runAllTests()));
45  connect(model, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
46  this, SLOT(runAllTests()));
47  connect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
48  this, SLOT(runAllTests()));
49  connect(model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)),
50  this, SLOT(runAllTests()));
51  connect(model, SIGNAL(layoutAboutToBeChanged ()), this, SLOT(runAllTests()));
52  connect(model, SIGNAL(layoutChanged ()), this, SLOT(runAllTests()));
53  connect(model, SIGNAL(modelReset ()), this, SLOT(runAllTests()));
54  connect(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
55  this, SLOT(runAllTests()));
56  connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
57  this, SLOT(runAllTests()));
58  connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
59  this, SLOT(runAllTests()));
60  connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
61  this, SLOT(runAllTests()));
62 
63  // Special checks for inserting/removing
64  connect(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
65  this, SLOT(rowsAboutToBeInserted(const QModelIndex &, int, int)));
66  connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
67  this, SLOT(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
68  connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
69  this, SLOT(rowsInserted(const QModelIndex &, int, int)));
70  connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
71  this, SLOT(rowsRemoved(const QModelIndex &, int, int)));
72 
73  runAllTests();
74 }
75 
76 void ModelTest::runAllTests()
77 {
78  if (fetchingMore)
79  return;
80  nonDestructiveBasicTest();
81  rowCount();
82  columnCount();
83  hasIndex();
84  index();
85  parent();
86  data();
87 }
88 
93 void ModelTest::nonDestructiveBasicTest()
94 {
95  Q_ASSERT(model->buddy(QModelIndex()) == QModelIndex());
96  model->canFetchMore(QModelIndex());
97  Q_ASSERT(model->columnCount(QModelIndex()) >= 0);
98  Q_ASSERT(model->data(QModelIndex()) == QVariant());
99  fetchingMore = true;
100  model->fetchMore(QModelIndex());
101  fetchingMore = false;
102  Qt::ItemFlags flags = model->flags(QModelIndex());
103  Q_ASSERT(flags == Qt::ItemIsDropEnabled || flags == 0);
104  model->hasChildren(QModelIndex());
105  model->hasIndex(0, 0);
106  model->headerData(0, Qt::Horizontal);
107  model->index(0, 0);
108  model->itemData(QModelIndex());
109  QVariant cache;
110  model->match(QModelIndex(), -1, cache);
111  model->mimeTypes();
112  Q_ASSERT(model->parent(QModelIndex()) == QModelIndex());
113  Q_ASSERT(model->rowCount() >= 0);
114  QVariant variant;
115  model->setData(QModelIndex(), variant, -1);
116  model->setHeaderData(-1, Qt::Horizontal, QVariant());
117  model->setHeaderData(0, Qt::Horizontal, QVariant());
118  model->setHeaderData(999999, Qt::Horizontal, QVariant());
119  QMap<int, QVariant> roles;
120  model->sibling(0, 0, QModelIndex());
121  model->span(QModelIndex());
122  model->supportedDropActions();
123 }
124 
130 void ModelTest::rowCount()
131 {
132  // check top row
133  QModelIndex topIndex = model->index(0, 0, QModelIndex());
134  int rows = model->rowCount(topIndex);
135  Q_ASSERT(rows >= 0);
136  if (rows > 0)
137  Q_ASSERT(model->hasChildren(topIndex) == true);
138 
139  QModelIndex secondLevelIndex = model->index(0, 0, topIndex);
140  if (secondLevelIndex.isValid()) { // not the top level
141  // check a row count where parent is valid
142  rows = model->rowCount(secondLevelIndex);
143  Q_ASSERT(rows >= 0);
144  if (rows > 0)
145  Q_ASSERT(model->hasChildren(secondLevelIndex) == true);
146  }
147 
148  // The models rowCount() is tested more extensively in checkChildren(),
149  // but this catches the big mistakes
150 }
151 
155 void ModelTest::columnCount()
156 {
157  // check top row
158  QModelIndex topIndex = model->index(0, 0, QModelIndex());
159  Q_ASSERT(model->columnCount(topIndex) >= 0);
160 
161  // check a column count where parent is valid
162  QModelIndex childIndex = model->index(0, 0, topIndex);
163  if (childIndex.isValid())
164  Q_ASSERT(model->columnCount(childIndex) >= 0);
165 
166  // columnCount() is tested more extensively in checkChildren(),
167  // but this catches the big mistakes
168 }
169 
173 void ModelTest::hasIndex()
174 {
175  // Make sure that invalid values returns an invalid index
176  Q_ASSERT(model->hasIndex(-2, -2) == false);
177  Q_ASSERT(model->hasIndex(-2, 0) == false);
178  Q_ASSERT(model->hasIndex(0, -2) == false);
179 
180  int rows = model->rowCount();
181  int columns = model->columnCount();
182 
183  // check out of bounds
184  Q_ASSERT(model->hasIndex(rows, columns) == false);
185  Q_ASSERT(model->hasIndex(rows + 1, columns + 1) == false);
186 
187  if (rows > 0)
188  Q_ASSERT(model->hasIndex(0, 0) == true);
189 
190  // hasIndex() is tested more extensively in checkChildren(),
191  // but this catches the big mistakes
192 }
193 
197 void ModelTest::index()
198 {
199  // Make sure that invalid values returns an invalid index
200  Q_ASSERT(model->index(-2, -2) == QModelIndex());
201  Q_ASSERT(model->index(-2, 0) == QModelIndex());
202  Q_ASSERT(model->index(0, -2) == QModelIndex());
203 
204  int rows = model->rowCount();
205  int columns = model->columnCount();
206 
207  if (rows == 0)
208  return;
209 
210  // Catch off by one errors
211  Q_ASSERT(model->index(rows, columns) == QModelIndex());
212  Q_ASSERT(model->index(0, 0).isValid() == true);
213 
214  // Make sure that the same index is *always* returned
215  QModelIndex a = model->index(0, 0);
216  QModelIndex b = model->index(0, 0);
217  Q_ASSERT(a == b);
218 
219  // index() is tested more extensively in checkChildren(),
220  // but this catches the big mistakes
221 }
222 
226 void ModelTest::parent()
227 {
228  // Make sure the model wont crash and will return an invalid QModelIndex
229  // when asked for the parent of an invalid index.
230  Q_ASSERT(model->parent(QModelIndex()) == QModelIndex());
231 
232  if (model->rowCount() == 0)
233  return;
234 
235  // Column 0 | Column 1 |
236  // QModelIndex() | |
237  // \- topIndex | topIndex1 |
238  // \- childIndex | childIndex1 |
239 
240  // Common error test #1, make sure that a top level index has a parent
241  // that is a invalid QModelIndex.
242  QModelIndex topIndex = model->index(0, 0, QModelIndex());
243  Q_ASSERT(model->parent(topIndex) == QModelIndex());
244 
245  // Common error test #2, make sure that a second level index has a parent
246  // that is the first level index.
247  if (model->rowCount(topIndex) > 0) {
248  QModelIndex childIndex = model->index(0, 0, topIndex);
249  Q_ASSERT(model->parent(childIndex) == topIndex);
250  }
251 
252  // Common error test #3, the second column should NOT have the same children
253  // as the first column in a row.
254  // Usually the second column shouldn't have children.
255  QModelIndex topIndex1 = model->index(0, 1, QModelIndex());
256  if (model->rowCount(topIndex1) > 0) {
257  QModelIndex childIndex = model->index(0, 0, topIndex);
258  QModelIndex childIndex1 = model->index(0, 0, topIndex1);
259  Q_ASSERT(childIndex != childIndex1);
260  }
261 
262  // Full test, walk n levels deep through the model making sure that all
263  // parent's children correctly specify their parent.
264  checkChildren(QModelIndex());
265 }
266 
281 void ModelTest::checkChildren(const QModelIndex &parent, int currentDepth)
282 {
283  // First just try walking back up the tree.
284  QModelIndex p = parent;
285  while (p.isValid())
286  p = p.parent();
287 
288  // For models that are dynamically populated
289  if (model->canFetchMore(parent)) {
290  fetchingMore = true;
291  model->fetchMore(parent);
292  fetchingMore = false;
293  }
294 
295  int rows = model->rowCount(parent);
296  int columns = model->columnCount(parent);
297 
298  if (rows > 0)
299  Q_ASSERT(model->hasChildren(parent));
300 
301  // Some further testing against rows(), columns(), and hasChildren()
302  Q_ASSERT(rows >= 0);
303  Q_ASSERT(columns >= 0);
304  if (rows > 0)
305  Q_ASSERT(model->hasChildren(parent) == true);
306 
307  //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
308  // << "columns:" << columns << "parent column:" << parent.column();
309 
310  Q_ASSERT(model->hasIndex(rows + 1, 0, parent) == false);
311  for (int r = 0; r < rows; ++r) {
312  if (model->canFetchMore(parent)) {
313  fetchingMore = true;
314  model->fetchMore(parent);
315  fetchingMore = false;
316  }
317  Q_ASSERT(model->hasIndex(r, columns + 1, parent) == false);
318  for (int c = 0; c < columns; ++c) {
319  Q_ASSERT(model->hasIndex(r, c, parent) == true);
320  QModelIndex index = model->index(r, c, parent);
321  // rowCount() and columnCount() said that it existed...
322  Q_ASSERT(index.isValid() == true);
323 
324  // index() should always return the same index when called twice in a row
325  QModelIndex modifiedIndex = model->index(r, c, parent);
326  Q_ASSERT(index == modifiedIndex);
327 
328  // Make sure we get the same index if we request it twice in a row
329  QModelIndex a = model->index(r, c, parent);
330  QModelIndex b = model->index(r, c, parent);
331  Q_ASSERT(a == b);
332 
333  // Some basic checking on the index that is returned
334  Q_ASSERT(index.model() == model);
335  Q_ASSERT(index.row() == r);
336  Q_ASSERT(index.column() == c);
337  // While you can technically return a QVariant usually this is a sign
338  // of an bug in data() Disable if this really is ok in your model.
339 
340 // Parley has lots of columns that are empty. Disable this test.
341 // Q_ASSERT(model->data(index, Qt::DisplayRole).isValid() == true);
342 
343  // If the next test fails here is some somewhat useful debug you play with.
344  /*
345  if (model->parent(index) != parent) {
346  qDebug() << r << c << currentDepth << model->data(index).toString()
347  << model->data(parent).toString();
348  qDebug() << index << parent << model->parent(index);
349  // And a view that you can even use to show the model.
350  //QTreeView view;
351  //view.setModel(model);
352  //view.show();
353  }*/
354 
355  // Check that we can get back our real parent.
356  Q_ASSERT(model->parent(index) == parent);
357 
358  // recursively go down the children
359  if (model->hasChildren(index) && currentDepth < 10 ) {
360  //qDebug() << r << c << "has children" << model->rowCount(index);
361  checkChildren(index, ++currentDepth);
362  }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
363 
364  // make sure that after testing the children that the index doesn't change.
365  QModelIndex newerIndex = model->index(r, c, parent);
366  Q_ASSERT(index == newerIndex);
367  }
368  }
369 }
370 
374 void ModelTest::data()
375 {
376  // Invalid index should return an invalid qvariant
377  Q_ASSERT(!model->data(QModelIndex()).isValid());
378 
379  if (model->rowCount() == 0)
380  return;
381 
382  // A valid index should have a valid QVariant data
383  Q_ASSERT(model->index(0, 0).isValid());
384 
385  // shouldn't be able to set data on an invalid index
386  Q_ASSERT(model->setData(QModelIndex(), QLatin1String("foo"), Qt::DisplayRole) == false);
387 
388  // General Purpose roles that should return a QString
389  QVariant variant = model->data(model->index(0, 0), Qt::ToolTipRole);
390  if (variant.isValid()) {
391  Q_ASSERT(qVariantCanConvert<QString>(variant));
392  }
393  variant = model->data(model->index(0, 0), Qt::StatusTipRole);
394  if (variant.isValid()) {
395  Q_ASSERT(qVariantCanConvert<QString>(variant));
396  }
397  variant = model->data(model->index(0, 0), Qt::WhatsThisRole);
398  if (variant.isValid()) {
399  Q_ASSERT(qVariantCanConvert<QString>(variant));
400  }
401 
402  // General Purpose roles that should return a QSize
403  variant = model->data(model->index(0, 0), Qt::SizeHintRole);
404  if (variant.isValid()) {
405  Q_ASSERT(qVariantCanConvert<QSize>(variant));
406  }
407 
408  // General Purpose roles that should return a QFont
409  QVariant fontVariant = model->data(model->index(0, 0), Qt::FontRole);
410  if (fontVariant.isValid()) {
411  Q_ASSERT(qVariantCanConvert<QFont>(fontVariant));
412  }
413 
414  // Check that the alignment is one we know about
415  QVariant textAlignmentVariant = model->data(model->index(0, 0), Qt::TextAlignmentRole);
416  if (textAlignmentVariant.isValid()) {
417  int alignment = textAlignmentVariant.toInt();
418  Q_ASSERT(alignment == Qt::AlignLeft ||
419  alignment == Qt::AlignRight ||
420  alignment == Qt::AlignHCenter ||
421  alignment == Qt::AlignJustify ||
422  alignment == Qt::AlignTop ||
423  alignment == Qt::AlignBottom ||
424  alignment == Qt::AlignVCenter ||
425  alignment == Qt::AlignCenter ||
426  alignment == Qt::AlignAbsolute ||
427  alignment == Qt::AlignLeading ||
428  alignment == Qt::AlignTrailing);
429  }
430 
431  // General Purpose roles that should return a QColor
432  QVariant colorVariant = model->data(model->index(0, 0), Qt::BackgroundColorRole);
433  if (colorVariant.isValid()) {
434  Q_ASSERT(qVariantCanConvert<QColor>(colorVariant));
435  }
436 
437  colorVariant = model->data(model->index(0, 0), Qt::TextColorRole);
438  if (colorVariant.isValid()) {
439  Q_ASSERT(qVariantCanConvert<QColor>(colorVariant));
440  }
441 
442  // Check that the "check state" is one we know about.
443  QVariant checkStateVariant = model->data(model->index(0, 0), Qt::CheckStateRole);
444  if (checkStateVariant.isValid()) {
445  int state = checkStateVariant.toInt();
446  Q_ASSERT(state == Qt::Unchecked ||
447  state == Qt::PartiallyChecked ||
448  state == Qt::Checked);
449  }
450 }
451 
457 void ModelTest::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
458 {
459  Q_UNUSED(end);
460  Changing c;
461  c.parent = parent;
462  c.oldSize = model->rowCount(parent);
463  c.last = model->data(model->index(start - 1, 0, parent));
464  c.next = model->data(model->index(start, 0, parent));
465  insert.push(c);
466 }
467 
473 void ModelTest::rowsInserted(const QModelIndex & parent, int start, int end)
474 {
475  Changing c = insert.pop();
476  Q_ASSERT(c.parent == parent);
477  Q_ASSERT(c.oldSize + (end - start + 1) == model->rowCount(parent));
478  Q_ASSERT(c.last == model->data(model->index(start - 1, 0, c.parent)));
479  /*
480  if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
481  qDebug() << start << end;
482  for (int i=0; i < model->rowCount(); ++i)
483  qDebug() << model->index(i, 0).data().toString();
484  qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
485  }
486  */
487  Q_ASSERT(c.next == model->data(model->index(end + 1, 0, c.parent)));
488 }
489 
495 void ModelTest::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
496 {
497  Changing c;
498  c.parent = parent;
499  c.oldSize = model->rowCount(parent);
500  c.last = model->data(model->index(start - 1, 0, parent));
501  c.next = model->data(model->index(end + 1, 0, parent));
502  remove.push(c);
503 }
504 
510 void ModelTest::rowsRemoved(const QModelIndex & parent, int start, int end)
511 {
512  Changing c = remove.pop();
513  Q_ASSERT(c.parent == parent);
514  Q_ASSERT(c.oldSize - (end - start + 1) == model->rowCount(parent));
515  Q_ASSERT(c.last == model->data(model->index(start - 1, 0, c.parent)));
516  Q_ASSERT(c.next == model->data(model->index(start, 0, c.parent)));
517 }
518 
ModelTest::runAllTests
void runAllTests()
Definition: modeltest.cpp:76
ModelTest::rowsInserted
void rowsInserted(const QModelIndex &parent, int start, int end)
Definition: modeltest.cpp:473
ModelTest::rowsAboutToBeRemoved
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
Definition: modeltest.cpp:495
QObject
ModelTest::rowsAboutToBeInserted
void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
Definition: modeltest.cpp:457
modeltest.h
QAbstractItemModel
ModelTest::rowsRemoved
void rowsRemoved(const QModelIndex &parent, int start, int end)
Definition: modeltest.cpp:510
ModelTest
Definition: modeltest.h:31
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:42:06 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

parley

Skip menu "parley"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal