[KLF Application][KLF Tools][KLF Backend][KLF Home]
KLatexFormula Project

src/modeltest.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2007 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the Qt Concurrent project on Trolltech Labs.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #ifdef KLF_DEBUG_USE_MODELTEST
00025 
00026 #include <QtGui/QtGui>
00027 
00028 #include "modeltest.h"
00029 
00030 Q_DECLARE_METATYPE(QModelIndex)
00031 
00032 
00035 ModelTest::ModelTest(QAbstractItemModel *_model, QObject *parent) : QObject(parent), model(_model), fetchingMore(false)
00036 {
00037     Q_ASSERT(model);
00038 
00039     connect(model, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
00040             this, SLOT(runAllTests()));
00041     connect(model, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
00042             this, SLOT(runAllTests()));
00043     connect(model, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
00044             this, SLOT(runAllTests()));
00045     connect(model, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
00046             this, SLOT(runAllTests()));
00047     connect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
00048             this, SLOT(runAllTests()));
00049     connect(model, SIGNAL(headerDataChanged(Qt::Orientation, int, int)),
00050             this, SLOT(runAllTests()));
00051     connect(model, SIGNAL(layoutAboutToBeChanged ()), this, SLOT(runAllTests()));
00052     connect(model, SIGNAL(layoutChanged ()), this, SLOT(runAllTests()));
00053     connect(model, SIGNAL(modelReset ()), this, SLOT(runAllTests()));
00054     connect(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
00055             this, SLOT(runAllTests()));
00056     connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
00057             this, SLOT(runAllTests()));
00058     connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
00059             this, SLOT(runAllTests()));
00060     connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
00061             this, SLOT(runAllTests()));
00062 
00063     // Special checks for inserting/removing
00064     connect(model, SIGNAL(layoutAboutToBeChanged()),
00065             this, SLOT(layoutAboutToBeChanged()));
00066     connect(model, SIGNAL(layoutChanged()),
00067             this, SLOT(layoutChanged()));
00068 
00069     connect(model, SIGNAL(rowsAboutToBeInserted(const QModelIndex &, int, int)),
00070             this, SLOT(rowsAboutToBeInserted(const QModelIndex &, int, int)));
00071     connect(model, SIGNAL(rowsAboutToBeRemoved(const QModelIndex &, int, int)),
00072             this, SLOT(rowsAboutToBeRemoved(const QModelIndex &, int, int)));
00073     connect(model, SIGNAL(rowsInserted(const QModelIndex &, int, int)),
00074             this, SLOT(rowsInserted(const QModelIndex &, int, int)));
00075     connect(model, SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
00076             this, SLOT(rowsRemoved(const QModelIndex &, int, int)));
00077 
00078     runAllTests();
00079 }
00080 
00081 void ModelTest::runAllTests()
00082 {
00083     if (fetchingMore)
00084         return;
00085     nonDestructiveBasicTest();
00086     rowCount();
00087     columnCount();
00088     hasIndex();
00089     index();
00090     parent();
00091     data();
00092 }
00093 
00098 void ModelTest::nonDestructiveBasicTest()
00099 {
00100     Q_ASSERT(model->buddy(QModelIndex()) == QModelIndex());
00101     model->canFetchMore(QModelIndex());
00102     Q_ASSERT(model->columnCount(QModelIndex()) >= 0);
00103     Q_ASSERT(model->data(QModelIndex()) == QVariant());
00104     fetchingMore = true;
00105     model->fetchMore(QModelIndex());
00106     fetchingMore = false;
00107     Qt::ItemFlags flags = model->flags(QModelIndex());
00108     Q_ASSERT(flags == Qt::ItemIsDropEnabled || flags == 0);
00109     model->hasChildren(QModelIndex());
00110     model->hasIndex(0, 0);
00111     model->headerData(0, Qt::Horizontal);
00112     model->index(0, 0);
00113     Q_ASSERT(model->index(-1, -1) == QModelIndex());
00114     model->itemData(QModelIndex());
00115     QVariant cache;
00116     model->match(QModelIndex(), -1, cache);
00117     model->mimeTypes();
00118     Q_ASSERT(model->parent(QModelIndex()) == QModelIndex());
00119     Q_ASSERT(model->rowCount() >= 0);
00120     QVariant variant;
00121     model->setData(QModelIndex(), variant, -1);
00122     model->setHeaderData(-1, Qt::Horizontal, QVariant());
00123     model->setHeaderData(0, Qt::Horizontal, QVariant());
00124     model->setHeaderData(999999, Qt::Horizontal, QVariant());
00125     QMap<int, QVariant> roles;
00126     model->sibling(0, 0, QModelIndex());
00127     model->span(QModelIndex());
00128     model->supportedDropActions();
00129 }
00130 
00136 void ModelTest::rowCount()
00137 {
00138     // check top row
00139     QModelIndex topIndex = model->index(0, 0, QModelIndex());
00140     int rows = model->rowCount(topIndex);
00141     Q_ASSERT(rows >= 0);
00142     if (rows > 0)
00143         Q_ASSERT(model->hasChildren(topIndex) == true);
00144 
00145     QModelIndex secondLevelIndex = model->index(0, 0, topIndex);
00146     if (secondLevelIndex.isValid()) { // not the top level
00147         // check a row count where parent is valid
00148         rows = model->rowCount(secondLevelIndex);
00149         Q_ASSERT(rows >= 0);
00150         if (rows > 0)
00151             Q_ASSERT(model->hasChildren(secondLevelIndex) == true);
00152     }
00153 
00154     // The models rowCount() is tested more extensively in checkChildren(),
00155     // but this catches the big mistakes
00156 }
00157 
00161 void ModelTest::columnCount()
00162 {
00163     // check top row
00164     QModelIndex topIndex = model->index(0, 0, QModelIndex());
00165     Q_ASSERT(model->columnCount(topIndex) >= 0);
00166 
00167     // check a column count where parent is valid
00168     QModelIndex childIndex = model->index(0, 0, topIndex);
00169     if (childIndex.isValid())
00170         Q_ASSERT(model->columnCount(childIndex) >= 0);
00171 
00172     // columnCount() is tested more extensively in checkChildren(),
00173     // but this catches the big mistakes
00174 }
00175 
00179 void ModelTest::hasIndex()
00180 {
00181     // Make sure that invalid values returns an invalid index
00182     Q_ASSERT(model->hasIndex(-2, -2) == false);
00183     Q_ASSERT(model->hasIndex(-2, 0) == false);
00184     Q_ASSERT(model->hasIndex(0, -2) == false);
00185 
00186     int rows = model->rowCount();
00187     int columns = model->columnCount();
00188 
00189     // check out of bounds
00190     Q_ASSERT(model->hasIndex(rows, columns) == false);
00191     Q_ASSERT(model->hasIndex(rows + 1, columns + 1) == false);
00192 
00193     if (rows > 0)
00194         Q_ASSERT(model->hasIndex(0, 0) == true);
00195 
00196     // hasIndex() is tested more extensively in checkChildren(),
00197     // but this catches the big mistakes
00198 }
00199 
00203 void ModelTest::index()
00204 {
00205     // Make sure that invalid values returns an invalid index
00206     Q_ASSERT(model->index(-2, -2) == QModelIndex());
00207     Q_ASSERT(model->index(-2, 0) == QModelIndex());
00208     Q_ASSERT(model->index(0, -2) == QModelIndex());
00209 
00210     int rows = model->rowCount();
00211     int columns = model->columnCount();
00212 
00213     if (rows == 0)
00214         return;
00215 
00216     // Catch off by one errors
00217     Q_ASSERT(model->index(rows, columns) == QModelIndex());
00218     Q_ASSERT(model->index(0, 0).isValid() == true);
00219 
00220     // Make sure that the same index is *always* returned
00221     QModelIndex a = model->index(0, 0);
00222     QModelIndex b = model->index(0, 0);
00223     Q_ASSERT(a == b);
00224 
00225     // index() is tested more extensively in checkChildren(),
00226     // but this catches the big mistakes
00227 }
00228 
00232 void ModelTest::parent()
00233 {
00234     // Make sure the model wont crash and will return an invalid QModelIndex
00235     // when asked for the parent of an invalid index.
00236     Q_ASSERT(model->parent(QModelIndex()) == QModelIndex());
00237 
00238     if (model->rowCount() == 0)
00239         return;
00240 
00241     // Column 0                | Column 1    |
00242     // QModelIndex()           |             |
00243     //    \- topIndex          | topIndex1   |
00244     //         \- childIndex   | childIndex1 |
00245 
00246     // Common error test #1, make sure that a top level index has a parent
00247     // that is a invalid QModelIndex.
00248     QModelIndex topIndex = model->index(0, 0, QModelIndex());
00249     Q_ASSERT(model->parent(topIndex) == QModelIndex());
00250 
00251     // Common error test #2, make sure that a second level index has a parent
00252     // that is the first level index.
00253     if (model->rowCount(topIndex) > 0) {
00254         QModelIndex childIndex = model->index(0, 0, topIndex);
00255         Q_ASSERT(model->parent(childIndex) == topIndex);
00256     }
00257 
00258     // Common error test #3, the second column should NOT have the same children
00259     // as the first column in a row.
00260     // Usually the second column shouldn't have children.
00261     QModelIndex topIndex1 = model->index(0, 1, QModelIndex());
00262     if (model->rowCount(topIndex1) > 0) {
00263         QModelIndex childIndex = model->index(0, 0, topIndex);
00264         QModelIndex childIndex1 = model->index(0, 0, topIndex1);
00265         Q_ASSERT(childIndex != childIndex1);
00266     }
00267 
00268     // Full test, walk n levels deep through the model making sure that all
00269     // parent's children correctly specify their parent.
00270     checkChildren(QModelIndex());
00271 }
00272 
00287 void ModelTest::checkChildren(const QModelIndex &parent, int currentDepth)
00288 {
00289     // First just try walking back up the tree.
00290     QModelIndex p = parent;
00291     while (p.isValid())
00292         p = p.parent();
00293 
00294     // For models that are dynamically populated
00295     if (model->canFetchMore(parent)) {
00296         fetchingMore = true;
00297         model->fetchMore(parent);
00298         fetchingMore = false;
00299     }
00300 
00301     int rows = model->rowCount(parent);
00302     int columns = model->columnCount(parent);
00303 
00304     if (rows > 0)
00305         Q_ASSERT(model->hasChildren(parent));
00306 
00307     // Some further testing against rows(), columns(), and hasChildren()
00308     Q_ASSERT(rows >= 0);
00309     Q_ASSERT(columns >= 0);
00310     if (rows > 0)
00311         Q_ASSERT(model->hasChildren(parent) == true);
00312 
00313     //qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
00314     //         << "columns:" << columns << "parent column:" << parent.column();
00315 
00316     Q_ASSERT(model->hasIndex(rows + 1, 0, parent) == false);
00317     for (int r = 0; r < rows; ++r) {
00318         if (model->canFetchMore(parent)) {
00319             fetchingMore = true;
00320             model->fetchMore(parent);
00321             fetchingMore = false;
00322         }
00323         Q_ASSERT(model->hasIndex(r, columns + 1, parent) == false);
00324         for (int c = 0; c < columns; ++c) {
00325             qDebug()<<"index info is r="<<r<<" c="<<c<<"; parent="<<parent<<"; model->index(...)="<<model->index(r,c,parent);
00326             Q_ASSERT(model->hasIndex(r, c, parent) == true);
00327             QModelIndex index = model->index(r, c, parent);
00328             // rowCount() and columnCount() said that it existed...
00329             Q_ASSERT(index.isValid() == true);
00330 
00331             // index() should always return the same index when called twice in a row
00332             QModelIndex modifiedIndex = model->index(r, c, parent);
00333             Q_ASSERT(index == modifiedIndex);
00334 
00335             // Make sure we get the same index if we request it twice in a row
00336             QModelIndex a = model->index(r, c, parent);
00337             QModelIndex b = model->index(r, c, parent);
00338             Q_ASSERT(a == b);
00339 
00340             // Some basic checking on the index that is returned
00341             Q_ASSERT(index.model() == model);
00342             Q_ASSERT(index.row() == r);
00343             Q_ASSERT(index.column() == c);
00344             // While you can technically return a QVariant usually this is a sign
00345             // of an bug in data()  Disable if this really is ok in your model.
00346             //Q_ASSERT(model->data(index, Qt::DisplayRole).isValid() == true);
00347 
00348             // If the next test fails here is some somewhat useful debug you play with.
00349             
00350             if (model->parent(index) != parent) {
00351                 qDebug() << "Bad parent!";
00352                 qDebug() << r << c << currentDepth << model->data(index).toString()
00353                          << model->data(parent).toString();
00354                 qDebug() << index << parent << model->parent(index);
00355                 // And a view that you can even use to show the model.
00356                 //QTreeView view;
00357                 //view.setModel(model);
00358                 //view.show();
00359             }
00360 
00361             // Check that we can get back our real parent.
00362             QModelIndex p = model->parent(index);
00363             //qDebug() << "child:" << index;
00364             //qDebug() << p;
00365             //qDebug() << parent;
00366             Q_ASSERT(model->parent(index) == parent);
00367 
00368             // recursively go down the children
00369             if (model->hasChildren(index) && currentDepth < 10 ) {
00370                 //qDebug() << r << c << "has children" << model->rowCount(index);
00371                 checkChildren(index, ++currentDepth);
00372             }/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
00373 
00374             // make sure that after testing the children that the index doesn't change.
00375             QModelIndex newerIndex = model->index(r, c, parent);
00376             Q_ASSERT(index == newerIndex);
00377         }
00378     }
00379 }
00380 
00384 void ModelTest::data()
00385 {
00386     // Invalid index should return an invalid qvariant
00387     Q_ASSERT(!model->data(QModelIndex()).isValid());
00388 
00389     if (model->rowCount() == 0)
00390         return;
00391 
00392     // A valid index should have a valid QVariant data
00393     Q_ASSERT(model->index(0, 0).isValid());
00394 
00395     // shouldn't be able to set data on an invalid index
00396     Q_ASSERT(model->setData(QModelIndex(), QLatin1String("foo"), Qt::DisplayRole) == false);
00397 
00398     // General Purpose roles that should return a QString
00399     QVariant variant = model->data(model->index(0, 0), Qt::ToolTipRole);
00400     if (variant.isValid()) {
00401         Q_ASSERT(qVariantCanConvert<QString>(variant));
00402     }
00403     variant = model->data(model->index(0, 0), Qt::StatusTipRole);
00404     if (variant.isValid()) {
00405         Q_ASSERT(qVariantCanConvert<QString>(variant));
00406     }
00407     variant = model->data(model->index(0, 0), Qt::WhatsThisRole);
00408     if (variant.isValid()) {
00409         Q_ASSERT(qVariantCanConvert<QString>(variant));
00410     }
00411 
00412     // General Purpose roles that should return a QSize
00413     variant = model->data(model->index(0, 0), Qt::SizeHintRole);
00414     if (variant.isValid()) {
00415         Q_ASSERT(qVariantCanConvert<QSize>(variant));
00416     }
00417 
00418     // General Purpose roles that should return a QFont
00419     QVariant fontVariant = model->data(model->index(0, 0), Qt::FontRole);
00420     if (fontVariant.isValid()) {
00421         Q_ASSERT(qVariantCanConvert<QFont>(fontVariant));
00422     }
00423 
00424     // Check that the alignment is one we know about
00425     QVariant textAlignmentVariant = model->data(model->index(0, 0), Qt::TextAlignmentRole);
00426     if (textAlignmentVariant.isValid()) {
00427         int alignment = textAlignmentVariant.toInt();
00428         Q_ASSERT(alignment == Qt::AlignLeft ||
00429                  alignment == Qt::AlignRight ||
00430                  alignment == Qt::AlignHCenter ||
00431                  alignment == Qt::AlignJustify ||
00432                  alignment == Qt::AlignTop ||
00433                  alignment == Qt::AlignBottom ||
00434                  alignment == Qt::AlignVCenter ||
00435                  alignment == Qt::AlignCenter ||
00436                  alignment == Qt::AlignAbsolute ||
00437                  alignment == Qt::AlignLeading ||
00438                  alignment == Qt::AlignTrailing);
00439     }
00440 
00441     // General Purpose roles that should return a QColor
00442     QVariant colorVariant = model->data(model->index(0, 0), Qt::BackgroundColorRole);
00443     if (colorVariant.isValid()) {
00444         Q_ASSERT(qVariantCanConvert<QColor>(colorVariant));
00445     }
00446 
00447     colorVariant = model->data(model->index(0, 0), Qt::TextColorRole);
00448     if (colorVariant.isValid()) {
00449         Q_ASSERT(qVariantCanConvert<QColor>(colorVariant));
00450     }
00451 
00452     // Check that the "check state" is one we know about.
00453     QVariant checkStateVariant = model->data(model->index(0, 0), Qt::CheckStateRole);
00454     if (checkStateVariant.isValid()) {
00455         int state = checkStateVariant.toInt();
00456         Q_ASSERT(state == Qt::Unchecked ||
00457                  state == Qt::PartiallyChecked ||
00458                  state == Qt::Checked);
00459     }
00460 }
00461 
00467 void ModelTest::rowsAboutToBeInserted(const QModelIndex &parent, int start, int end)
00468 {
00469     Q_UNUSED(end);
00470     Changing c;
00471     c.parent = parent;
00472     c.oldSize = model->rowCount(parent);
00473     c.last = model->data(model->index(start - 1, 0, parent));
00474     c.next = model->data(model->index(start, 0, parent));
00475     insert.push(c);
00476 }
00477 
00483 void ModelTest::rowsInserted(const QModelIndex & parent, int start, int end)
00484 {
00485     Changing c = insert.pop();
00486     Q_ASSERT(c.parent == parent);
00487     Q_ASSERT(c.oldSize + (end - start + 1) == model->rowCount(parent));
00488     Q_ASSERT(c.last == model->data(model->index(start - 1, 0, c.parent)));
00489     /*
00490     if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
00491         qDebug() << start << end;
00492         for (int i=0; i < model->rowCount(); ++i)
00493             qDebug() << model->index(i, 0).data().toString();
00494         qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
00495     }
00496     */
00497     Q_ASSERT(c.next == model->data(model->index(end + 1, 0, c.parent)));
00498 }
00499 
00500 void ModelTest::layoutAboutToBeChanged()
00501 {
00502     for (int i = 0; i < qBound(0, model->rowCount(), 100); ++i)
00503         changing.append(QPersistentModelIndex(model->index(i, 0)));
00504 }
00505 
00506 void ModelTest::layoutChanged()
00507 {
00508     for (int i = 0; i < changing.count(); ++i) {
00509         QPersistentModelIndex p = changing[i];
00510         Q_ASSERT(p == model->index(p.row(), p.column(), p.parent()));
00511     }
00512     changing.clear();
00513 }
00514 
00520 void ModelTest::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
00521 {
00522     Changing c;
00523     c.parent = parent;
00524     c.oldSize = model->rowCount(parent);
00525     c.last = model->data(model->index(start - 1, 0, parent));
00526     c.next = model->data(model->index(end + 1, 0, parent));
00527     remove.push(c);
00528 }
00529 
00535 void ModelTest::rowsRemoved(const QModelIndex & parent, int start, int end)
00536 {
00537     Changing c = remove.pop();
00538     Q_ASSERT(c.parent == parent);
00539     Q_ASSERT(c.oldSize - (end - start + 1) == model->rowCount(parent));
00540     Q_ASSERT(c.last == model->data(model->index(start - 1, 0, c.parent)));
00541     Q_ASSERT(c.next == model->data(model->index(start, 0, c.parent)));
00542 }
00543 
00544 
00545 
00546 
00547 #endif

Generated by doxygen 1.7.3