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

kleopatra

  • sources
  • kde-4.12
  • kdepim
  • kleopatra
  • models
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 <config-kleopatra.h>
27 
28 #include <QtGui>
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(QModelIndex,int,int)),
40  this, SLOT(runAllTests()));
41  connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
42  this, SLOT(runAllTests()));
43  connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
44  this, SLOT(runAllTests()));
45  connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
46  this, SLOT(runAllTests()));
47  connect(model, SIGNAL(dataChanged(QModelIndex,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(QModelIndex,int,int)),
55  this, SLOT(runAllTests()));
56  connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
57  this, SLOT(runAllTests()));
58  connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
59  this, SLOT(runAllTests()));
60  connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
61  this, SLOT(runAllTests()));
62 
63  // Special checks for inserting/removing
64  connect(model, SIGNAL(layoutAboutToBeChanged()),
65  this, SLOT(layoutAboutToBeChanged()));
66  connect(model, SIGNAL(layoutChanged()),
67  this, SLOT(layoutChanged()));
68 
69  connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
70  this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)));
71  connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
72  this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
73  connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
74  this, SLOT(rowsInserted(QModelIndex,int,int)));
75  connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
76  this, SLOT(rowsRemoved(QModelIndex,int,int)));
77 
78  runAllTests();
79 }
80 
81 void ModelTest::runAllTests()
82 {
83  if (fetchingMore)
84  return;
85  nonDestructiveBasicTest();
86  rowCount();
87  columnCount();
88  hasIndex();
89  index();
90  parent();
91  data();
92 }
93 
98 void ModelTest::nonDestructiveBasicTest()
99 {
100  Q_ASSERT(model->buddy(QModelIndex()) == QModelIndex());
101  model->canFetchMore(QModelIndex());
102  Q_ASSERT(model->columnCount(QModelIndex()) >= 0);
103  Q_ASSERT(model->data(QModelIndex()) == QVariant());
104  fetchingMore = true;
105  model->fetchMore(QModelIndex());
106  fetchingMore = false;
107  Qt::ItemFlags flags = model->flags(QModelIndex());
108  Q_ASSERT(flags == Qt::ItemIsDropEnabled || flags == 0);
109  model->hasChildren(QModelIndex());
110  model->hasIndex(0, 0);
111  model->headerData(0, Qt::Horizontal);
112  model->index(0, 0);
113  model->itemData(QModelIndex());
114  QVariant cache;
115  model->match(QModelIndex(), -1, cache);
116  model->mimeTypes();
117  Q_ASSERT(model->parent(QModelIndex()) == QModelIndex());
118  Q_ASSERT(model->rowCount() >= 0);
119  QVariant variant;
120  model->setData(QModelIndex(), variant, -1);
121  model->setHeaderData(-1, Qt::Horizontal, QVariant());
122  model->setHeaderData(0, Qt::Horizontal, QVariant());
123  model->setHeaderData(999999, Qt::Horizontal, QVariant());
124  QMap<int, QVariant> roles;
125  model->sibling(0, 0, QModelIndex());
126  model->span(QModelIndex());
127  model->supportedDropActions();
128 }
129 
135 void ModelTest::rowCount()
136 {
137  // check top row
138  QModelIndex topIndex = model->index(0, 0, QModelIndex());
139  int rows = model->rowCount(topIndex);
140  Q_ASSERT(rows >= 0);
141  if (rows > 0)
142  Q_ASSERT(model->hasChildren(topIndex) == true);
143 
144  QModelIndex secondLevelIndex = model->index(0, 0, topIndex);
145  if (secondLevelIndex.isValid()) { // not the top level
146  // check a row count where parent is valid
147  rows = model->rowCount(secondLevelIndex);
148  Q_ASSERT(rows >= 0);
149  if (rows > 0)
150  Q_ASSERT(model->hasChildren(secondLevelIndex) == true);
151  }
152 
153  // The models rowCount() is tested more extensively in checkChildren(),
154  // but this catches the big mistakes
155 }
156 
160 void ModelTest::columnCount()
161 {
162  // check top row
163  QModelIndex topIndex = model->index(0, 0, QModelIndex());
164  Q_ASSERT(model->columnCount(topIndex) >= 0);
165 
166  // check a column count where parent is valid
167  QModelIndex childIndex = model->index(0, 0, topIndex);
168  if (childIndex.isValid())
169  Q_ASSERT(model->columnCount(childIndex) >= 0);
170 
171  // columnCount() is tested more extensively in checkChildren(),
172  // but this catches the big mistakes
173 }
174 
178 void ModelTest::hasIndex()
179 {
180  // Make sure that invalid values returns an invalid index
181  Q_ASSERT(model->hasIndex(-2, -2) == false);
182  Q_ASSERT(model->hasIndex(-2, 0) == false);
183  Q_ASSERT(model->hasIndex(0, -2) == false);
184 
185  int rows = model->rowCount();
186  int columns = model->columnCount();
187 
188  // check out of bounds
189  Q_ASSERT(model->hasIndex(rows, columns) == false);
190  Q_ASSERT(model->hasIndex(rows + 1, columns + 1) == false);
191 
192  if (rows > 0)
193  Q_ASSERT(model->hasIndex(0, 0) == true);
194 
195  // hasIndex() is tested more extensively in checkChildren(),
196  // but this catches the big mistakes
197 }
198 
202 void ModelTest::index()
203 {
204  // Make sure that invalid values returns an invalid index
205  Q_ASSERT(model->index(-2, -2) == QModelIndex());
206  Q_ASSERT(model->index(-2, 0) == QModelIndex());
207  Q_ASSERT(model->index(0, -2) == QModelIndex());
208 
209  int rows = model->rowCount();
210  int columns = model->columnCount();
211 
212  if (rows == 0)
213  return;
214 
215  // Catch off by one errors
216  Q_ASSERT(model->index(rows, columns) == QModelIndex());
217  Q_ASSERT(model->index(0, 0).isValid() == true);
218 
219  // Make sure that the same index is *always* returned
220  QModelIndex a = model->index(0, 0);
221  QModelIndex b = model->index(0, 0);
222  Q_ASSERT(a == b);
223 
224  // index() is tested more extensively in checkChildren(),
225  // but this catches the big mistakes
226 }
227 
231 void ModelTest::parent()
232 {
233  // Make sure the model wont crash and will return an invalid QModelIndex
234  // when asked for the parent of an invalid index.
235  Q_ASSERT(model->parent(QModelIndex()) == QModelIndex());
236 
237  if (model->rowCount() == 0)
238  return;
239 
240  // Column 0 | Column 1 |
241  // QModelIndex() | |
242  // \- topIndex | topIndex1 |
243  // \- childIndex | childIndex1 |
244 
245  // Common error test #1, make sure that a top level index has a parent
246  // that is a invalid QModelIndex.
247  QModelIndex topIndex = model->index(0, 0, QModelIndex());
248  Q_ASSERT(model->parent(topIndex) == QModelIndex());
249 
250  // Common error test #2, make sure that a second level index has a parent
251  // that is the first level index.
252  if (model->rowCount(topIndex) > 0) {
253  QModelIndex childIndex = model->index(0, 0, topIndex);
254  Q_ASSERT(model->parent(childIndex) == topIndex);
255  }
256 
257  // Common error test #3, the second column should NOT have the same children
258  // as the first column in a row.
259  // Usually the second column shouldn't have children.
260  QModelIndex topIndex1 = model->index(0, 1, QModelIndex());
261  if (model->rowCount(topIndex1) > 0) {
262  QModelIndex childIndex = model->index(0, 0, topIndex);
263  QModelIndex childIndex1 = model->index(0, 0, topIndex1);
264  Q_ASSERT(childIndex != childIndex1);
265  }
266 
267  // Full test, walk n levels deep through the model making sure that all
268  // parent's children correctly specify their parent.
269  checkChildren(QModelIndex());
270 }
271 
286 void ModelTest::checkChildren(const QModelIndex &parent, int currentDepth)
287 {
288  // First just try walking back up the tree.
289  QModelIndex p = parent;
290  while (p.isValid())
291  p = p.parent();
292 
293  // For models that are dynamically populated
294  if (model->canFetchMore(parent)) {
295  fetchingMore = true;
296  model->fetchMore(parent);
297  fetchingMore = false;
298  }
299 
300  int rows = model->rowCount(parent);
301  int columns = model->columnCount(parent);
302 
303  if (rows > 0)
304  Q_ASSERT(model->hasChildren(parent));
305 
306  // Some further testing against rows(), columns(), and hasChildren()
307  Q_ASSERT(rows >= 0);
308  Q_ASSERT(columns >= 0);
309  if (rows > 0)
310  Q_ASSERT(model->hasChildren(parent) == true);
311 
312  //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
313  // << "columns:" << columns << "parent column:" << parent.column();
314 
315  Q_ASSERT(model->hasIndex(rows + 1, 0, parent) == false);
316  for (int r = 0; r < rows; ++r) {
317  if (model->canFetchMore(parent)) {
318  fetchingMore = true;
319  model->fetchMore(parent);
320  fetchingMore = false;
321  }
322  Q_ASSERT(model->hasIndex(r, columns + 1, parent) == false);
323  for (int c = 0; c < columns; ++c) {
324  Q_ASSERT(model->hasIndex(r, c, parent) == true);
325  QModelIndex index = model->index(r, c, parent);
326  // rowCount() and columnCount() said that it existed...
327  Q_ASSERT(index.isValid() == true);
328 
329  // index() should always return the same index when called twice in a row
330  QModelIndex modifiedIndex = model->index(r, c, parent);
331  Q_ASSERT(index == modifiedIndex);
332 
333  // Make sure we get the same index if we request it twice in a row
334  QModelIndex a = model->index(r, c, parent);
335  QModelIndex b = model->index(r, c, parent);
336  Q_ASSERT(a == b);
337 
338  // Some basic checking on the index that is returned
339  Q_ASSERT(index.model() == model);
340  Q_ASSERT(index.row() == r);
341  Q_ASSERT(index.column() == c);
342  // While you can technically return a QVariant usually this is a sign
343  // of an bug in data() Disable if this really is ok in your model.
344  Q_ASSERT(model->data(index, Qt::DisplayRole).isValid() == true);
345 
346  // If the next test fails here is some somewhat useful debug you play with.
347  /*
348  if (model->parent(index) != parent) {
349  qDebug() << r << c << currentDepth << model->data(index).toString()
350  << model->data(parent).toString();
351  qDebug() << index << parent << model->parent(index);
352  // And a view that you can even use to show the model.
353  //QTreeView view;
354  //view.setModel(model);
355  //view.show();
356  }*/
357 
358  // Check that we can get back our real parent.
359  Q_ASSERT(model->parent(index) == parent);
360 
361  // recursively go down the children
362  if (model->hasChildren(index) && currentDepth < 10 ) {
363  //qDebug() << r << c << "has children" << model->rowCount(index);
364  checkChildren(index, ++currentDepth);
365  }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
366 
367  // make sure that after testing the children that the index doesn't change.
368  QModelIndex newerIndex = model->index(r, c, parent);
369  Q_ASSERT(index == newerIndex);
370  }
371  }
372 }
373 
377 void ModelTest::data()
378 {
379  // Invalid index should return an invalid qvariant
380  Q_ASSERT(!model->data(QModelIndex()).isValid());
381 
382  if (model->rowCount() == 0)
383  return;
384 
385  // A valid index should have a valid QVariant data
386  Q_ASSERT(model->index(0, 0).isValid());
387 
388  // shouldn't be able to set data on an invalid index
389  Q_ASSERT(model->setData(QModelIndex(), QLatin1String("foo"), Qt::DisplayRole) == false);
390 
391  // General Purpose roles that should return a QString
392  QVariant variant = model->data(model->index(0, 0), Qt::ToolTipRole);
393  if (variant.isValid()) {
394  Q_ASSERT(qVariantCanConvert<QString>(variant));
395  }
396  variant = model->data(model->index(0, 0), Qt::StatusTipRole);
397  if (variant.isValid()) {
398  Q_ASSERT(qVariantCanConvert<QString>(variant));
399  }
400  variant = model->data(model->index(0, 0), Qt::WhatsThisRole);
401  if (variant.isValid()) {
402  Q_ASSERT(qVariantCanConvert<QString>(variant));
403  }
404 
405  // General Purpose roles that should return a QSize
406  variant = model->data(model->index(0, 0), Qt::SizeHintRole);
407  if (variant.isValid()) {
408  Q_ASSERT(qVariantCanConvert<QSize>(variant));
409  }
410 
411  // General Purpose roles that should return a QFont
412  QVariant fontVariant = model->data(model->index(0, 0), Qt::FontRole);
413  if (fontVariant.isValid()) {
414  Q_ASSERT(qVariantCanConvert<QFont>(fontVariant));
415  }
416 
417  // Check that the alignment is one we know about
418  QVariant textAlignmentVariant = model->data(model->index(0, 0), Qt::TextAlignmentRole);
419  if (textAlignmentVariant.isValid()) {
420  int alignment = textAlignmentVariant.toInt();
421  Q_ASSERT(alignment == Qt::AlignLeft ||
422  alignment == Qt::AlignRight ||
423  alignment == Qt::AlignHCenter ||
424  alignment == Qt::AlignJustify ||
425  alignment == Qt::AlignTop ||
426  alignment == Qt::AlignBottom ||
427  alignment == Qt::AlignVCenter ||
428  alignment == Qt::AlignCenter ||
429  alignment == Qt::AlignAbsolute ||
430  alignment == Qt::AlignLeading ||
431  alignment == Qt::AlignTrailing);
432  }
433 
434  // General Purpose roles that should return a QColor
435  QVariant colorVariant = model->data(model->index(0, 0), Qt::BackgroundColorRole);
436  if (colorVariant.isValid()) {
437  Q_ASSERT(qVariantCanConvert<QColor>(colorVariant));
438  }
439 
440  colorVariant = model->data(model->index(0, 0), Qt::TextColorRole);
441  if (colorVariant.isValid()) {
442  Q_ASSERT(qVariantCanConvert<QColor>(colorVariant));
443  }
444 
445  // Check that the "check state" is one we know about.
446  QVariant checkStateVariant = model->data(model->index(0, 0), Qt::CheckStateRole);
447  if (checkStateVariant.isValid()) {
448  int state = checkStateVariant.toInt();
449  Q_ASSERT(state == Qt::Unchecked ||
450  state == Qt::PartiallyChecked ||
451  state == Qt::Checked);
452  }
453 }
454 
460 void ModelTest::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
461 {
462  Q_UNUSED(end);
463  Changing c;
464  c.parent = parent;
465  c.oldSize = model->rowCount(parent);
466  c.last = model->data(model->index(start - 1, 0, parent));
467  c.next = model->data(model->index(start, 0, parent));
468  insert.push(c);
469 }
470 
476 void ModelTest::rowsInserted(const QModelIndex & parent, int start, int end)
477 {
478  Changing c = insert.pop();
479  Q_ASSERT(c.parent == parent);
480  Q_ASSERT(c.oldSize + (end - start + 1) == model->rowCount(parent));
481  Q_ASSERT(c.last == model->data(model->index(start - 1, 0, c.parent)));
482  /*
483  if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
484  qDebug() << start << end;
485  for (int i=0; i < model->rowCount(); ++i)
486  qDebug() << model->index(i, 0).data().toString();
487  qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
488  }
489  */
490  Q_ASSERT(c.next == model->data(model->index(end + 1, 0, c.parent)));
491 }
492 
493 void ModelTest::layoutAboutToBeChanged()
494 {
495  for (int i = 0; i < qBound(0, model->rowCount(), 100); ++i)
496  changing.append(QPersistentModelIndex(model->index(i, 0)));
497 }
498 
499 void ModelTest::layoutChanged()
500 {
501  for (int i = 0; i < changing.count(); ++i) {
502  QPersistentModelIndex p = changing[i];
503  Q_ASSERT(p == model->index(p.row(), p.column(), p.parent()));
504  }
505  changing.clear();
506 }
507 
513 void ModelTest::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
514 {
515  Changing c;
516  c.parent = parent;
517  c.oldSize = model->rowCount(parent);
518  c.last = model->data(model->index(start - 1, 0, parent));
519  c.next = model->data(model->index(end + 1, 0, parent));
520  remove.push(c);
521 }
522 
528 void ModelTest::rowsRemoved(const QModelIndex & parent, int start, int end)
529 {
530  Changing c = remove.pop();
531  Q_ASSERT(c.parent == parent);
532  Q_ASSERT(c.oldSize - (end - start + 1) == model->rowCount(parent));
533  Q_ASSERT(c.last == model->data(model->index(start - 1, 0, c.parent)));
534  Q_ASSERT(c.next == model->data(model->index(start, 0, c.parent)));
535 }
536 
flags
static const char * flags[]
Definition: readerstatus.cpp:115
ModelTest::runAllTests
void runAllTests()
Definition: modeltest.cpp:81
ModelTest::rowsInserted
void rowsInserted(const QModelIndex &parent, int start, int end)
Definition: modeltest.cpp:476
ModelTest::rowsAboutToBeRemoved
void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
Definition: modeltest.cpp:513
ModelTest::rowsAboutToBeInserted
void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
Definition: modeltest.cpp:460
modeltest.h
QAbstractItemModel
ModelTest::rowsRemoved
void rowsRemoved(const QModelIndex &parent, int start, int end)
Definition: modeltest.cpp:528
ModelTest::layoutChanged
void layoutChanged()
Definition: modeltest.cpp:499
ModelTest
Definition: modeltest.h:31
ModelTest::layoutAboutToBeChanged
void layoutAboutToBeChanged()
Definition: modeltest.cpp:493
QMap
Definition: signingcertificateselectiondialog.h:41
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:56:41 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kleopatra

Skip menu "kleopatra"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

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