tests/auto/qitemmodel/modelstotest.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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 <QtTest/QtTest>
       
    44 #include <QtCore/QtCore>
       
    45 #include <QtSql/QtSql>
       
    46 #include <QtGui/QtGui>
       
    47 #include <QSortFilterProxyModel>
       
    48 
       
    49 /*
       
    50     To add a model to be tested add the header file to the includes
       
    51     and impliment what is needed in the four functions below.
       
    52 
       
    53     You can add more then one model, several Qt models and included as examples.
       
    54 
       
    55     In tst_qitemmodel.cpp a new ModelsToTest object is created for each test.
       
    56 
       
    57     When you have errors fix the first ones first.  Later tests depend upon them working
       
    58 */
       
    59 
       
    60 class ModelsToTest {
       
    61 
       
    62 public:
       
    63     ModelsToTest();
       
    64 
       
    65     QAbstractItemModel *createModel(const QString &modelType);
       
    66     QModelIndex populateTestArea(QAbstractItemModel *model);
       
    67     void cleanupTestArea(QAbstractItemModel *model);
       
    68 
       
    69     enum Read {
       
    70         ReadOnly, // wont perform remove(), insert(), and setData()
       
    71         ReadWrite
       
    72     };
       
    73     enum Contains {
       
    74         Empty,  // Confirm that rowCount() == 0 etc throughout the test
       
    75         HasData // Confirm that rowCount() != 0 etc throughout the test
       
    76     };
       
    77 
       
    78     struct test {
       
    79             test(QString m, Read r, Contains c) : modelType(m), read(r), contains(c){};
       
    80 
       
    81             QString modelType;
       
    82             Read read;
       
    83             Contains contains;
       
    84     };
       
    85 
       
    86     QList<test> tests;
       
    87 
       
    88     static void setupDatabase();
       
    89 };
       
    90 
       
    91 
       
    92 /*!
       
    93     Add new tests, they can be the same model, but in a different state.
       
    94 
       
    95     The name of the model is passed to createModel
       
    96     If readOnly is true the remove tests will be skipped.  Example: QDirModel is disabled.
       
    97     If createModel returns an empty model.  Example: QDirModel does not
       
    98  */
       
    99 ModelsToTest::ModelsToTest()
       
   100 {
       
   101     setupDatabase();
       
   102 
       
   103     tests.append(test("QDirModel", ReadOnly, HasData));
       
   104     tests.append(test("QStringListModel", ReadWrite, HasData));
       
   105     tests.append(test("QStringListModelEmpty", ReadWrite, Empty));
       
   106 
       
   107     tests.append(test("QStandardItemModel", ReadWrite, HasData));
       
   108     tests.append(test("QStandardItemModelEmpty", ReadWrite, Empty));
       
   109 
       
   110     // QSortFilterProxyModel test uses QStandardItemModel so test it first
       
   111     tests.append(test("QSortFilterProxyModel", ReadWrite, HasData));
       
   112     tests.append(test("QSortFilterProxyModelEmpty", ReadWrite, Empty));
       
   113     tests.append(test("QSortFilterProxyModelRegExp", ReadWrite, HasData));
       
   114 
       
   115     tests.append(test("QListModel", ReadWrite, HasData));
       
   116     tests.append(test("QListModelEmpty", ReadWrite, Empty));
       
   117     tests.append(test("QTableModel", ReadWrite, HasData));
       
   118     tests.append(test("QTableModelEmpty", ReadWrite, Empty));
       
   119 
       
   120     tests.append(test("QTreeModel", ReadWrite, HasData));
       
   121     tests.append(test("QTreeModelEmpty", ReadWrite, Empty));
       
   122 
       
   123     tests.append(test("QSqlQueryModel", ReadOnly, HasData));
       
   124     tests.append(test("QSqlQueryModelEmpty", ReadOnly, Empty));
       
   125 
       
   126     // Fails on remove
       
   127     tests.append(test("QSqlTableModel", ReadOnly, HasData));
       
   128 }
       
   129 
       
   130 /*!
       
   131     Return a new modelType.
       
   132  */
       
   133 QAbstractItemModel *ModelsToTest::createModel(const QString &modelType)
       
   134 {
       
   135     if (modelType == "QStringListModelEmpty")
       
   136         return new QStringListModel();
       
   137 
       
   138     if (modelType == "QStringListModel") {
       
   139         QStringListModel *model = new QStringListModel();
       
   140         populateTestArea(model);
       
   141         return model;
       
   142     }
       
   143 
       
   144     if (modelType == "QStandardItemModelEmpty") {
       
   145         return new QStandardItemModel();
       
   146     }
       
   147 
       
   148     if (modelType == "QStandardItemModel") {
       
   149         QStandardItemModel *model = new QStandardItemModel();
       
   150         populateTestArea(model);
       
   151         return model;
       
   152     }
       
   153 
       
   154     if (modelType == "QSortFilterProxyModelEmpty") {
       
   155         QSortFilterProxyModel *model = new QSortFilterProxyModel;
       
   156         QStandardItemModel *standardItemModel = new QStandardItemModel;
       
   157         model->setSourceModel(standardItemModel);
       
   158         return model;
       
   159     }
       
   160 
       
   161     if (modelType == "QSortFilterProxyModelRegExp") {
       
   162         QSortFilterProxyModel *model = new QSortFilterProxyModel;
       
   163         QStandardItemModel *standardItemModel = new QStandardItemModel;
       
   164         model->setSourceModel(standardItemModel);
       
   165         populateTestArea(model);
       
   166         model->setFilterRegExp(QRegExp("(^$|0.*)"));
       
   167         return model;
       
   168     }
       
   169 
       
   170     if (modelType == "QSortFilterProxyModel") {
       
   171         QSortFilterProxyModel *model = new QSortFilterProxyModel;
       
   172         QStandardItemModel *standardItemModel = new QStandardItemModel;
       
   173         model->setSourceModel(standardItemModel);
       
   174         populateTestArea(model);
       
   175         return model;
       
   176     }
       
   177 
       
   178     if (modelType == "QDirModel") {
       
   179         QDirModel *model = new QDirModel();
       
   180         model->setReadOnly(false);
       
   181         return model;
       
   182     }
       
   183 
       
   184     if (modelType == "QSqlQueryModel") {
       
   185         QSqlQueryModel *model = new QSqlQueryModel();
       
   186         populateTestArea(model);
       
   187         return model;
       
   188     }
       
   189 
       
   190     if (modelType == "QSqlQueryModelEmpty") {
       
   191         QSqlQueryModel *model = new QSqlQueryModel();
       
   192         return model;
       
   193     }
       
   194 
       
   195     if (modelType == "QSqlTableModel") {
       
   196         QSqlTableModel *model = new QSqlTableModel();
       
   197         populateTestArea(model);
       
   198         return model;
       
   199     }
       
   200 
       
   201     if (modelType == "QListModelEmpty")
       
   202         return (new QListWidget)->model();
       
   203 
       
   204     if (modelType == "QListModel") {
       
   205         QListWidget *widget = new QListWidget;
       
   206         populateTestArea(widget->model());
       
   207         return widget->model();
       
   208     }
       
   209 
       
   210     if (modelType == "QTableModelEmpty")
       
   211         return (new QTableWidget)->model();
       
   212 
       
   213     if (modelType == "QTableModel") {
       
   214         QTableWidget *widget = new QTableWidget;
       
   215         populateTestArea(widget->model());
       
   216         return widget->model();
       
   217     }
       
   218 
       
   219     if (modelType == "QTreeModelEmpty") {
       
   220         QTreeWidget *widget = new QTreeWidget;
       
   221         return widget->model();
       
   222     }
       
   223 
       
   224     if (modelType == "QTreeModel") {
       
   225         QTreeWidget *widget = new QTreeWidget;
       
   226         populateTestArea(widget->model());
       
   227         return widget->model();
       
   228     }
       
   229 
       
   230     Q_ASSERT(false);
       
   231     return 0;
       
   232 }
       
   233 
       
   234 /*!
       
   235     Fills model with some test data at least twenty rows and if possible twenty or more columns.
       
   236     Return the parent of a row/column that can be tested.
       
   237 
       
   238     NOTE: If readOnly is true tests will try to remove and add rows and columns.
       
   239     If you have a tree model returning not the root index will help catch more errors.
       
   240  */
       
   241 QModelIndex ModelsToTest::populateTestArea(QAbstractItemModel *model)
       
   242 {
       
   243     if (QStringListModel *stringListModel = qobject_cast<QStringListModel *>(model)) {
       
   244         QString alphabet = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z";
       
   245         stringListModel->setStringList( alphabet.split(",") );
       
   246         return QModelIndex();
       
   247     }
       
   248 
       
   249     if (qobject_cast<QStandardItemModel *>(model)) {
       
   250         // Basic tree StandardItemModel
       
   251         QModelIndex parent;
       
   252         QVariant blue = QVariant(QColor(Qt::blue));
       
   253 #ifndef Q_OS_WINCE
       
   254         for (int i = 0; i < 4; ++i) {
       
   255 #else
       
   256         for (int i = 0; i < 2; ++i) {
       
   257 #endif
       
   258             parent = model->index(0, 0, parent);
       
   259             model->insertRows(0, 26 + i, parent);
       
   260 #ifndef Q_OS_WINCE
       
   261             model->insertColumns(0, 26 + i, parent);
       
   262 #else
       
   263             model->insertColumns(0, 4 + i, parent);
       
   264 #endif
       
   265             // Fill in some values to make it easier to debug
       
   266             /*
       
   267             for (int x = 0; x < 26 + i; ++x) {
       
   268                 QString xval = QString::number(x);
       
   269                 for (int y = 0; y < 26 + i; ++y) {
       
   270                     QString val = xval + QString::number(y) + QString::number(i);
       
   271                     QModelIndex index = model->index(x, y, parent);
       
   272                     model->setData(index, val);
       
   273                     model->setData(index, blue, Qt::TextColorRole);
       
   274                 }
       
   275             }
       
   276             */
       
   277         }
       
   278         return model->index(0,0);
       
   279     }
       
   280 
       
   281     if (qobject_cast<QSortFilterProxyModel *>(model)) {
       
   282         QAbstractItemModel *realModel = (qobject_cast<QSortFilterProxyModel *>(model))->sourceModel();
       
   283         // Basic tree StandardItemModel
       
   284         QModelIndex parent;
       
   285         QVariant blue = QVariant(QColor(Qt::blue));
       
   286 #ifndef Q_OS_WINCE
       
   287         for (int i = 0; i < 4; ++i) {
       
   288 #else
       
   289         for (int i = 0; i < 2; ++i) {
       
   290 #endif
       
   291             parent = realModel->index(0, 0, parent);
       
   292             realModel->insertRows(0, 26+i, parent);
       
   293 #ifndef Q_OS_WINCE
       
   294             realModel->insertColumns(0, 26+i, parent);
       
   295 #else
       
   296             realModel->insertColumns(0, 4, parent);
       
   297 #endif
       
   298             // Fill in some values to make it easier to debug
       
   299             /*
       
   300             for (int x = 0; x < 26+i; ++x) {
       
   301                 QString xval = QString::number(x);
       
   302                 for (int y = 0; y < 26 + i; ++y) {
       
   303                     QString val = xval + QString::number(y) + QString::number(i);
       
   304                     QModelIndex index = realModel->index(x, y, parent);
       
   305                     realModel->setData(index, val);
       
   306                     realModel->setData(index, blue, Qt::TextColorRole);
       
   307                 }
       
   308             }
       
   309             */
       
   310         }
       
   311         QModelIndex returnIndex = model->index(0,0);
       
   312         Q_ASSERT(returnIndex.isValid());
       
   313         return returnIndex;
       
   314     }
       
   315 
       
   316     if (QDirModel *dirModel = qobject_cast<QDirModel *>(model)) {
       
   317         // Don't risk somthing bad happening, assert if this fails
       
   318         Q_ASSERT(QDir(QDir::currentPath()).mkdir("test"));
       
   319         for (int i = 0; i < 26; ++i)
       
   320             Q_ASSERT(QDir(QDir::currentPath()).mkdir(QString("test/foo_%1").arg(i)));
       
   321         return dirModel->index(QDir::currentPath()+"/test");
       
   322     }
       
   323 
       
   324     if (QSqlQueryModel *queryModel = qobject_cast<QSqlQueryModel *>(model)) {
       
   325         QSqlQuery q;
       
   326         q.exec("CREATE TABLE test(id int primary key, name varchar(30))");
       
   327         q.prepare("INSERT INTO test(id, name) values (?, ?)");
       
   328 #ifndef Q_OS_WINCE
       
   329         for (int i = 0; i < 1024; ++i) {
       
   330 #else
       
   331         for (int i = 0; i < 512; ++i) {
       
   332 #endif
       
   333             q.addBindValue(i);
       
   334             q.addBindValue("Mr. Smith" + QString::number(i));
       
   335             q.exec();
       
   336         }
       
   337         if (QSqlTableModel *tableModel = qobject_cast<QSqlTableModel *>(model)) {
       
   338             tableModel->setTable("test");
       
   339             tableModel->setEditStrategy(QSqlTableModel::OnManualSubmit);
       
   340             tableModel->select();
       
   341         } else {
       
   342             queryModel->setQuery("select * from test");
       
   343         }
       
   344         return QModelIndex();
       
   345     }
       
   346 
       
   347     if (QListWidget *listWidget = qobject_cast<QListWidget *>(model->parent())) {
       
   348 #ifndef Q_OS_WINCE
       
   349         int items = 100;
       
   350 #else
       
   351         int items = 50;
       
   352 #endif
       
   353         while (items--)
       
   354             listWidget->addItem(QString("item %1").arg(items));
       
   355         return QModelIndex();
       
   356     }
       
   357 
       
   358     if (QTableWidget *tableWidget = qobject_cast<QTableWidget *>(model->parent())) {
       
   359         tableWidget->setColumnCount(20);
       
   360         tableWidget->setRowCount(20);
       
   361         return QModelIndex();
       
   362     }
       
   363 
       
   364     if (QTreeWidget *treeWidget = qobject_cast<QTreeWidget *>(model->parent())) {
       
   365         int topItems = 20;
       
   366         treeWidget->setColumnCount(1);
       
   367         QTreeWidgetItem *parent;
       
   368         while (topItems--){
       
   369             parent = new QTreeWidgetItem(treeWidget, QStringList(QString("top %1").arg(topItems)));
       
   370             for (int i = 0; i < 20; ++i)
       
   371                 new QTreeWidgetItem(parent, QStringList(QString("child %1").arg(topItems)));
       
   372         }
       
   373         return QModelIndex();
       
   374     }
       
   375 
       
   376     Q_ASSERT(false);
       
   377     return QModelIndex();
       
   378 }
       
   379 
       
   380 /*!
       
   381     If you need to cleanup from populateTest() do it here.
       
   382     Note that this is called after every test even if populateTestArea isn't called.
       
   383  */
       
   384 void ModelsToTest::cleanupTestArea(QAbstractItemModel *model)
       
   385 {
       
   386     if (qobject_cast<QDirModel *>(model))
       
   387     {
       
   388         if (QDir(QDir::currentPath()+"/test").exists())
       
   389         {
       
   390             for (int i = 0; i < 26; ++i)
       
   391                 QDir::current().rmdir(QString("test/foo_%1").arg(i));
       
   392             Q_ASSERT(QDir::current().rmdir("test"));
       
   393         }
       
   394     } else if (qobject_cast<QSqlQueryModel *>(model)) {
       
   395         QSqlQuery q("DROP TABLE test");
       
   396     }
       
   397 }
       
   398 
       
   399 void ModelsToTest::setupDatabase()
       
   400 {
       
   401     if (!QSqlDatabase::database().isValid()) {
       
   402         QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
       
   403         db.setDatabaseName(":memory:");
       
   404         if (!db.open()) {
       
   405             qWarning() << "Unable to open database" << db.lastError();
       
   406             return;
       
   407         }
       
   408     }
       
   409 }
       
   410