tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
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 
       
    46 #include <QtGui/QSortFilterProxyModel>
       
    47 
       
    48 //TESTED_CLASS=QAbstractListModel QAbstractTableModel
       
    49 //TESTED_FILES=
       
    50 
       
    51 #include "dynamictreemodel.h"
       
    52 
       
    53 Q_DECLARE_METATYPE(QModelIndex)
       
    54 
       
    55 /*!
       
    56     Note that this doesn't test models, but any functionality that QAbstractItemModel shoudl provide
       
    57  */
       
    58 class tst_QAbstractItemModel : public QObject
       
    59 {
       
    60     Q_OBJECT
       
    61 
       
    62 public:
       
    63     tst_QAbstractItemModel();
       
    64     virtual ~tst_QAbstractItemModel();
       
    65 
       
    66 public slots:
       
    67     void initTestCase();
       
    68     void cleanupTestCase();
       
    69     void init();
       
    70     void cleanup();
       
    71 
       
    72 private slots:
       
    73     void index();
       
    74     void parent();
       
    75     void hasChildren();
       
    76     void _data();
       
    77     void headerData();
       
    78     void itemData();
       
    79     void itemFlags();
       
    80     void match();
       
    81     void dropMimeData_data();
       
    82     void dropMimeData();
       
    83     void changePersistentIndex();
       
    84     void movePersistentIndex();
       
    85 
       
    86     void insertRows();
       
    87     void insertColumns();
       
    88     void removeRows();
       
    89     void removeColumns();
       
    90 
       
    91     void reset();
       
    92 
       
    93     void complexChangesWithPersistent();
       
    94 
       
    95     void testMoveSameParentUp_data();
       
    96     void testMoveSameParentUp();
       
    97 
       
    98     void testMoveSameParentDown_data();
       
    99     void testMoveSameParentDown();
       
   100 
       
   101     void testMoveToGrandParent_data();
       
   102     void testMoveToGrandParent();
       
   103 
       
   104     void testMoveToSibling_data();
       
   105     void testMoveToSibling();
       
   106 
       
   107     void testMoveToUncle_data();
       
   108     void testMoveToUncle();
       
   109 
       
   110     void testMoveToDescendants();
       
   111 
       
   112     void testMoveWithinOwnRange_data();
       
   113     void testMoveWithinOwnRange();
       
   114 
       
   115     void testReset();
       
   116 
       
   117 
       
   118 private:
       
   119     DynamicTreeModel *m_model;
       
   120 
       
   121 };
       
   122 
       
   123 /*!
       
   124     Test model that impliments the pure vitual functions and anything else that is
       
   125     needed.
       
   126 
       
   127     It is a table implimented as a vector of vectors of strings.
       
   128  */
       
   129 class QtTestModel: public QAbstractItemModel
       
   130 {
       
   131 public:
       
   132     QtTestModel(int rows, int columns, QObject *parent = 0);
       
   133     QtTestModel(const QVector<QVector<QString> > tbl, QObject *parent = 0);
       
   134     QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
       
   135     QModelIndex parent(const QModelIndex &) const;
       
   136     int rowCount(const QModelIndex &parent) const;
       
   137     int columnCount(const QModelIndex &parent) const;
       
   138     bool hasChildren(const QModelIndex &) const;
       
   139     QVariant data(const QModelIndex &idx, int) const;
       
   140     bool setData(const QModelIndex &idx, const QVariant &value, int);
       
   141     bool insertRows(int row, int count, const QModelIndex &parent= QModelIndex());
       
   142     bool insertColumns(int column, int count, const QModelIndex &parent= QModelIndex());
       
   143     void setPersistent(const QModelIndex &from, const QModelIndex &to);
       
   144     bool removeRows ( int row, int count, const QModelIndex & parent = QModelIndex() );
       
   145     bool removeColumns( int column, int count, const QModelIndex & parent = QModelIndex());
       
   146     void reset();
       
   147 
       
   148     int cCount, rCount;
       
   149     mutable bool wrongIndex;
       
   150     QVector<QVector<QString> > table;
       
   151 };
       
   152 
       
   153 QtTestModel::QtTestModel(int rows, int columns, QObject *parent)
       
   154     : QAbstractItemModel(parent), cCount(columns), rCount(rows), wrongIndex(false) {
       
   155 
       
   156     table.resize(rows);
       
   157     for (int r = 0; r < rows; ++r) {
       
   158         table[r].resize(columns);
       
   159         for (int c = 0; c < columns; ++c)
       
   160             table[r][c] = QString("%1/%2").arg(r).arg(c);
       
   161     }
       
   162 }
       
   163 
       
   164 QtTestModel::QtTestModel(const QVector<QVector<QString> > tbl, QObject *parent)
       
   165     : QAbstractItemModel(parent), wrongIndex(false) {
       
   166     table = tbl;
       
   167     rCount = tbl.count();
       
   168     cCount = tbl.at(0).count();
       
   169 }
       
   170 
       
   171 QModelIndex QtTestModel::index(int row, int column, const QModelIndex &parent) const
       
   172         { return hasIndex(row, column, parent) ? createIndex(row, column, 0) : QModelIndex(); }
       
   173 
       
   174 QModelIndex QtTestModel::parent(const QModelIndex &) const { return QModelIndex(); }
       
   175 int QtTestModel::rowCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : rCount; }
       
   176 int QtTestModel::columnCount(const QModelIndex &parent) const { return parent.isValid() ? 0 : cCount; }
       
   177 bool QtTestModel::hasChildren(const QModelIndex &) const { return false; }
       
   178 
       
   179 QVariant QtTestModel::data(const QModelIndex &idx, int) const
       
   180 {
       
   181     if (idx.row() < 0 || idx.column() < 0 || idx.column() > cCount || idx.row() > rCount) {
       
   182         wrongIndex = true;
       
   183         qWarning("got invalid modelIndex %d/%d", idx.row(), idx.column());
       
   184         return QVariant();
       
   185     }
       
   186     return table.at(idx.row()).at(idx.column());
       
   187 }
       
   188 
       
   189 bool QtTestModel::setData(const QModelIndex &idx, const QVariant &value, int)
       
   190 {
       
   191     table[idx.row()][idx.column()] = value.toString();
       
   192     return true;
       
   193 }
       
   194 
       
   195 bool QtTestModel::insertRows(int row, int count, const QModelIndex &parent)
       
   196 {
       
   197     QAbstractItemModel::beginInsertRows(parent, row, row + count - 1);
       
   198     int cc = columnCount(parent);
       
   199     table.insert(row, count, QVector<QString>(cc));
       
   200     rCount = table.count();
       
   201     QAbstractItemModel::endInsertRows();
       
   202     return true;
       
   203 }
       
   204 
       
   205 bool QtTestModel::insertColumns(int column, int count, const QModelIndex &parent)
       
   206 {
       
   207     QAbstractItemModel::beginInsertColumns(parent, column, column + count - 1);
       
   208     int rc = rowCount(parent);
       
   209     for (int i = 0; i < rc; ++i)
       
   210         table[i].insert(column, 1, "");
       
   211     cCount = table.at(0).count();
       
   212     QAbstractItemModel::endInsertColumns();
       
   213     return true;
       
   214 }
       
   215 
       
   216 void QtTestModel::setPersistent(const QModelIndex &from, const QModelIndex &to)
       
   217 {
       
   218     changePersistentIndex(from, to);
       
   219 }
       
   220 
       
   221 bool QtTestModel::removeRows( int row, int count, const QModelIndex & parent)
       
   222 {
       
   223     QAbstractItemModel::beginRemoveRows(parent, row, row + count - 1);
       
   224 
       
   225     for (int r = row+count-1; r >= row; --r)
       
   226         table.remove(r);
       
   227     rCount = table.count();
       
   228 
       
   229     QAbstractItemModel::endRemoveRows();
       
   230     return true;
       
   231 }
       
   232 
       
   233 bool QtTestModel::removeColumns(int column, int count, const QModelIndex & parent)
       
   234 {
       
   235     QAbstractItemModel::beginRemoveColumns(parent, column, column + count - 1);
       
   236 
       
   237     for (int c = column+count-1; c > column; --c)
       
   238         for (int r = 0; r < rCount; ++r)
       
   239             table[r].remove(c);
       
   240 
       
   241     cCount = table.at(0).count();
       
   242 
       
   243     QAbstractItemModel::endRemoveColumns();
       
   244     return true;
       
   245 }
       
   246 
       
   247 void QtTestModel::reset()
       
   248 {
       
   249     QAbstractItemModel::reset();
       
   250 }
       
   251 
       
   252 tst_QAbstractItemModel::tst_QAbstractItemModel()
       
   253 {
       
   254 }
       
   255 
       
   256 tst_QAbstractItemModel::~tst_QAbstractItemModel()
       
   257 {
       
   258 }
       
   259 
       
   260 /**
       
   261  * The source Model *must* be initialized before the _data function, since the _data function uses QModelIndexes to reference the items in the tables.
       
   262  * Therefore, we must initialize it globally.
       
   263  */
       
   264 
       
   265 void tst_QAbstractItemModel::initTestCase()
       
   266 {
       
   267     qRegisterMetaType<QModelIndex>("QModelIndex");
       
   268 }
       
   269 
       
   270 void tst_QAbstractItemModel::cleanupTestCase()
       
   271 {
       
   272 
       
   273 }
       
   274 
       
   275 void tst_QAbstractItemModel::init()
       
   276 {
       
   277     m_model = new DynamicTreeModel(this);
       
   278 
       
   279     ModelInsertCommand *insertCommand = new ModelInsertCommand(m_model, this);
       
   280     insertCommand->setNumCols(4);
       
   281     insertCommand->setStartRow(0);
       
   282     insertCommand->setEndRow(9);
       
   283     insertCommand->doCommand();
       
   284 
       
   285     insertCommand = new ModelInsertCommand(m_model, this);
       
   286     insertCommand->setAncestorRowNumbers(QList<int>() << 5);
       
   287     insertCommand->setNumCols(4);
       
   288     insertCommand->setStartRow(0);
       
   289     insertCommand->setEndRow(9);
       
   290     insertCommand->doCommand();
       
   291 }
       
   292 
       
   293 void tst_QAbstractItemModel::cleanup()
       
   294 {
       
   295 
       
   296 }
       
   297 
       
   298 /*
       
   299   tests
       
   300 */
       
   301 
       
   302 void tst_QAbstractItemModel::index()
       
   303 {
       
   304     QtTestModel model(1, 1);
       
   305     QModelIndex idx = model.index(0, 0, QModelIndex());
       
   306     QVERIFY(idx.isValid());
       
   307 }
       
   308 
       
   309 void tst_QAbstractItemModel::parent()
       
   310 {
       
   311     QtTestModel model(1, 1);
       
   312     QModelIndex idx = model.index(0, 0, QModelIndex());
       
   313     QModelIndex par = model.parent(idx);
       
   314     QVERIFY(!par.isValid());
       
   315 }
       
   316 
       
   317 void tst_QAbstractItemModel::hasChildren()
       
   318 {
       
   319     QtTestModel model(1, 1);
       
   320     QModelIndex idx = model.index(0, 0, QModelIndex());
       
   321     QVERIFY(model.hasChildren(idx) == false);
       
   322 }
       
   323 
       
   324 void tst_QAbstractItemModel::_data()
       
   325 {
       
   326     QtTestModel model(1, 1);
       
   327     QModelIndex idx = model.index(0, 0, QModelIndex());
       
   328     QVERIFY(idx.isValid());
       
   329     QCOMPARE(model.data(idx, Qt::DisplayRole).toString(), QString("0/0"));
       
   330 
       
   331     // Default does nothing
       
   332     QCOMPARE(model.setHeaderData(0, Qt::Horizontal, QVariant(0), 0), false);
       
   333 }
       
   334 
       
   335 void tst_QAbstractItemModel::headerData()
       
   336 {
       
   337     QtTestModel model(1, 1);
       
   338     QCOMPARE(model.headerData(0, Qt::Horizontal, Qt::DisplayRole).toString(),
       
   339             QString("1"));
       
   340 
       
   341     // Default text alignment for header must be invalid
       
   342     QVERIFY( !model.headerData(0, Qt::Horizontal, Qt::TextAlignmentRole).isValid() );
       
   343 }
       
   344 
       
   345 void tst_QAbstractItemModel::itemData()
       
   346 {
       
   347     QtTestModel model(1, 1);
       
   348     QModelIndex idx = model.index(0, 0, QModelIndex());
       
   349     QVERIFY(idx.isValid());
       
   350     QMap<int, QVariant> dat = model.itemData(idx);
       
   351     QCOMPARE(dat.count(Qt::DisplayRole), 1);
       
   352     QCOMPARE(dat.value(Qt::DisplayRole).toString(), QString("0/0"));
       
   353 }
       
   354 
       
   355 void tst_QAbstractItemModel::itemFlags()
       
   356 {
       
   357     QtTestModel model(1, 1);
       
   358     QModelIndex idx = model.index(0, 0, QModelIndex());
       
   359     QVERIFY(idx.isValid());
       
   360     Qt::ItemFlags flags = model.flags(idx);
       
   361     QCOMPARE(Qt::ItemIsSelectable|Qt::ItemIsEnabled, flags);
       
   362 }
       
   363 
       
   364 void tst_QAbstractItemModel::match()
       
   365 {
       
   366     QtTestModel model(4, 1);
       
   367     QModelIndex start = model.index(0, 0, QModelIndex());
       
   368     QVERIFY(start.isValid());
       
   369     QModelIndexList res = model.match(start, Qt::DisplayRole, QVariant("1"), 3);
       
   370     QCOMPARE(res.count(), 1);
       
   371     QModelIndex idx = model.index(1, 0, QModelIndex());
       
   372     bool areEqual = (idx == res.first());
       
   373     QVERIFY(areEqual);
       
   374 
       
   375     model.setData(model.index(0, 0, QModelIndex()), "bat", Qt::DisplayRole);
       
   376     model.setData(model.index(1, 0, QModelIndex()), "cat", Qt::DisplayRole);
       
   377     model.setData(model.index(2, 0, QModelIndex()), "dog", Qt::DisplayRole);
       
   378     model.setData(model.index(3, 0, QModelIndex()), "boar", Qt::DisplayRole);
       
   379 
       
   380     res = model.match(start, Qt::DisplayRole, QVariant("dog"), -1, Qt::MatchExactly);
       
   381     QCOMPARE(res.count(), 1);
       
   382     res = model.match(start, Qt::DisplayRole, QVariant("a"), -1, Qt::MatchContains);
       
   383     QCOMPARE(res.count(), 3);
       
   384     res = model.match(start, Qt::DisplayRole, QVariant("b"), -1, Qt::MatchStartsWith);
       
   385     QCOMPARE(res.count(), 2);
       
   386     res = model.match(start, Qt::DisplayRole, QVariant("t"), -1, Qt::MatchEndsWith);
       
   387     QCOMPARE(res.count(), 2);
       
   388     res = model.match(start, Qt::DisplayRole, QVariant("*a*"), -1, Qt::MatchWildcard);
       
   389     QCOMPARE(res.count(), 3);
       
   390     res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1, Qt::MatchRegExp);
       
   391     QCOMPARE(res.count(), 2);
       
   392     res = model.match(start, Qt::DisplayRole, QVariant(".*O.*"), -1, Qt::MatchRegExp | Qt::MatchCaseSensitive);
       
   393     QCOMPARE(res.count(), 0);
       
   394     res = model.match(start, Qt::DisplayRole, QVariant("BOAR"), -1, Qt::MatchFixedString);
       
   395     QCOMPARE(res.count(), 1);
       
   396     res = model.match(start, Qt::DisplayRole, QVariant("bat"), -1,
       
   397                       Qt::MatchFixedString | Qt::MatchCaseSensitive);
       
   398     QCOMPARE(res.count(), 1);
       
   399 }
       
   400 
       
   401 typedef QPair<int, int> Position;
       
   402 typedef QVector<QPair<int, int> > Selection;
       
   403 typedef QVector<QVector<QString> > StringTable;
       
   404 typedef QVector<QString> StringTableRow;
       
   405 Q_DECLARE_METATYPE(Position)
       
   406 Q_DECLARE_METATYPE(Selection)
       
   407 Q_DECLARE_METATYPE(StringTable)
       
   408 
       
   409 static StringTableRow qStringTableRow(const QString &s1, const QString &s2, const QString &s3)
       
   410 {
       
   411     StringTableRow row;
       
   412     row << s1 << s2 << s3;
       
   413     return row;
       
   414 }
       
   415 
       
   416 #ifdef Q_CC_MSVC
       
   417 # define STRINGTABLE (StringTable())
       
   418 #else
       
   419 # define STRINGTABLE StringTable()
       
   420 #endif
       
   421 
       
   422 void tst_QAbstractItemModel::dropMimeData_data()
       
   423 {
       
   424     QTest::addColumn<StringTable>("src_table"); // drag source
       
   425     QTest::addColumn<StringTable>("dst_table"); // drop target
       
   426     QTest::addColumn<Selection>("selection"); // dragged items
       
   427     QTest::addColumn<Position>("dst_position"); // drop position
       
   428     QTest::addColumn<StringTable>("res_table"); // expected result
       
   429 
       
   430     {
       
   431         QTest::newRow("2x2 dropped at [0, 0]")
       
   432             << (STRINGTABLE // source table
       
   433                 << (qStringTableRow("A", "B", "C"))
       
   434                 << (qStringTableRow("D", "E", "F")))
       
   435             << (STRINGTABLE // destination table
       
   436                 << (qStringTableRow("0", "1", "2"))
       
   437                 << (qStringTableRow("3", "4", "5")))
       
   438             << (Selection() // selection
       
   439                 << Position(0, 0) << Position(0, 1)
       
   440                 << Position(1, 0) << Position(1, 1))
       
   441             << Position(0, 0) // drop position
       
   442             << (STRINGTABLE // resulting table
       
   443                 << (qStringTableRow("A", "B", "" ))
       
   444                 << (qStringTableRow("D", "E", "" ))
       
   445                 << (qStringTableRow("0", "1", "2"))
       
   446                 << (qStringTableRow("3", "4", "5")));
       
   447     }
       
   448 
       
   449     {
       
   450         QTest::newRow("2x2 dropped at [1, 0]")
       
   451             << (STRINGTABLE // source table
       
   452                 << (qStringTableRow("A", "B", "C"))
       
   453                 << (qStringTableRow("D", "E", "F")))
       
   454             << (STRINGTABLE // destination table
       
   455                 << (qStringTableRow("0", "1", "2"))
       
   456                 << (qStringTableRow("3", "4", "5")))
       
   457             << (Selection() // selection
       
   458                 << Position(0, 0) << Position(0, 1)
       
   459                 << Position(1, 0) << Position(1, 1))
       
   460             << Position(1, 0) // drop position
       
   461             << (STRINGTABLE // resulting table
       
   462                 << (qStringTableRow("0", "1", "2"))
       
   463                 << (qStringTableRow("A", "B", "" ))
       
   464                 << (qStringTableRow("D", "E", "" ))
       
   465                 << (qStringTableRow("3", "4", "5")));
       
   466     }
       
   467 
       
   468     {
       
   469         QTest::newRow("2x2 dropped at [3, 0]")
       
   470             << (STRINGTABLE // source table
       
   471                 << (qStringTableRow("A", "B", "C"))
       
   472                 << (qStringTableRow("D", "E", "F")))
       
   473             << (STRINGTABLE // destination table
       
   474                 << (qStringTableRow("0", "1", "2"))
       
   475                 << (qStringTableRow("3", "4", "5")))
       
   476             << (Selection() // selection
       
   477                 << Position(0, 0) << Position(0, 1)
       
   478                 << Position(1, 0) << Position(1, 1))
       
   479             << Position(3, 0) // drop position
       
   480             << (STRINGTABLE // resulting table
       
   481                 << (qStringTableRow("0", "1", "2"))
       
   482                 << (qStringTableRow("3", "4", "5"))
       
   483                 << (qStringTableRow("A", "B", "" ))
       
   484                 << (qStringTableRow("D", "E", "" )));
       
   485     }
       
   486 
       
   487     {
       
   488         QTest::newRow("2x2 dropped at [0, 1]")
       
   489             << (STRINGTABLE // source table
       
   490                 << (qStringTableRow("A", "B", "C"))
       
   491                 << (qStringTableRow("D", "E", "F")))
       
   492             << (STRINGTABLE // destination table
       
   493                 << (qStringTableRow("0", "1", "2"))
       
   494                 << (qStringTableRow("3", "4", "5")))
       
   495             << (Selection() // selection
       
   496                 << Position(0, 0) << Position(0, 1)
       
   497                 << Position(1, 0) << Position(1, 1))
       
   498             << Position(0, 1) // drop position
       
   499             << (STRINGTABLE // resulting table
       
   500                 << (qStringTableRow("" , "A", "B"))
       
   501                 << (qStringTableRow("" , "D", "E"))
       
   502                 << (qStringTableRow("0", "1", "2"))
       
   503                 << (qStringTableRow("3", "4", "5")));
       
   504     }
       
   505 
       
   506     {
       
   507         QTest::newRow("2x2 dropped at [0, 2] (line break)")
       
   508             << (STRINGTABLE // source table
       
   509                 << (qStringTableRow("A", "B", "C"))
       
   510                 << (qStringTableRow("D", "E", "F")))
       
   511             << (STRINGTABLE // destination table
       
   512                 << (qStringTableRow("0", "1", "2"))
       
   513                 << (qStringTableRow("3", "4", "5")))
       
   514             << (Selection() // selection
       
   515                 << Position(0, 0) << Position(0, 1)
       
   516                 << Position(1, 0) << Position(1, 1))
       
   517             << Position(0, 2) // drop position
       
   518             << (STRINGTABLE // resulting table
       
   519                 << (qStringTableRow("" , "" , "A"))
       
   520                 << (qStringTableRow("" , "" , "D"))
       
   521                 << (qStringTableRow("" , "" , "B"))
       
   522                 << (qStringTableRow("" , "" , "E"))
       
   523                 << (qStringTableRow("0", "1", "2"))
       
   524                 << (qStringTableRow("3", "4", "5")));
       
   525     }
       
   526 
       
   527     {
       
   528         QTest::newRow("2x2 dropped at [3, 2] (line break)")
       
   529             << (STRINGTABLE // source table
       
   530                 << (qStringTableRow("A", "B", "C"))
       
   531                 << (qStringTableRow("D", "E", "F")))
       
   532             << (STRINGTABLE // destination table
       
   533                 << (qStringTableRow("0", "1", "2"))
       
   534                 << (qStringTableRow("3", "4", "5")))
       
   535             << (Selection() // selection
       
   536                 << Position(0, 0) << Position(0, 1)
       
   537                 << Position(1, 0) << Position(1, 1))
       
   538             << Position(3, 2) // drop position
       
   539             << (STRINGTABLE // resulting table
       
   540                 << (qStringTableRow("0", "1", "2"))
       
   541                 << (qStringTableRow("3", "4", "5"))
       
   542                 << (qStringTableRow("" , "" , "A"))
       
   543                 << (qStringTableRow("" , "" , "D"))
       
   544                 << (qStringTableRow("" , "" , "B"))
       
   545                 << (qStringTableRow("" , "" , "E")));
       
   546     }
       
   547 
       
   548     {
       
   549         QTest::newRow("non-square dropped at [0, 0]")
       
   550             << (STRINGTABLE // source table
       
   551                 << (qStringTableRow("A", "B", "C"))
       
   552                 << (qStringTableRow("D", "E", "F")))
       
   553             << (STRINGTABLE // destination table
       
   554                 << (qStringTableRow("0", "1", "2"))
       
   555                 << (qStringTableRow("3", "4", "5")))
       
   556             << (Selection() // selection
       
   557                 << Position(0, 0) << Position(0, 1)
       
   558                 << Position(1, 0))
       
   559             << Position(0, 0) // drop position
       
   560             << (STRINGTABLE // resulting table
       
   561                 << (qStringTableRow("A", "B", "" ))
       
   562                 << (qStringTableRow("D", "" , "" ))
       
   563                 << (qStringTableRow("0", "1", "2"))
       
   564                 << (qStringTableRow("3", "4", "5")));
       
   565     }
       
   566 
       
   567     {
       
   568         QTest::newRow("non-square dropped at [0, 2]")
       
   569             << (STRINGTABLE // source table
       
   570                 << (qStringTableRow("A", "B", "C"))
       
   571                 << (qStringTableRow("D", "E", "F")))
       
   572             << (STRINGTABLE // destination table
       
   573                 << (qStringTableRow("0", "1", "2"))
       
   574                 << (qStringTableRow("3", "4", "5")))
       
   575             << (Selection() // selection
       
   576                 << Position(0, 0) << Position(0, 1)
       
   577                 << Position(1, 0))
       
   578             << Position(0, 2) // drop position
       
   579             << (STRINGTABLE // resulting table
       
   580                 << (qStringTableRow("" , "" , "A"))
       
   581                 << (qStringTableRow("" , "" , "D"))
       
   582                 << (qStringTableRow("" , "" , "B"))
       
   583                 << (qStringTableRow("0", "1", "2"))
       
   584                 << (qStringTableRow("3", "4", "5")));
       
   585     }
       
   586 
       
   587     {
       
   588         QTest::newRow("2x 1x2 dropped at [0, 0] (duplicates)")
       
   589             << (STRINGTABLE // source table
       
   590                 << (qStringTableRow("A", "B", "C"))
       
   591                 << (qStringTableRow("D", "E", "F")))
       
   592             << (STRINGTABLE // destination table
       
   593                 << (qStringTableRow("0", "1", "2"))
       
   594                 << (qStringTableRow("3", "4", "5")))
       
   595             << (Selection() // selection; 2x the same row (to simulate selections in hierarchy)
       
   596                 << Position(0, 0) << Position(0, 1)
       
   597                 << Position(0, 0) << Position(0, 1))
       
   598             << Position(0, 0) // drop position
       
   599             << (STRINGTABLE // resulting table
       
   600                 << (qStringTableRow("A", "B", "" ))
       
   601                 << (qStringTableRow("A", "" , "" ))
       
   602                 << (qStringTableRow("" , "B", "" )) // ### FIXME: strange behavior, but rare case
       
   603                 << (qStringTableRow("0", "1", "2"))
       
   604                 << (qStringTableRow("3", "4", "5")));
       
   605     }
       
   606 
       
   607     {
       
   608         QTest::newRow("2x 1x2 dropped at [3, 2] (duplicates)")
       
   609             << (STRINGTABLE // source table
       
   610                 << (qStringTableRow("A", "B", "C"))
       
   611                 << (qStringTableRow("D", "E", "F")))
       
   612             << (STRINGTABLE // destination table
       
   613                 << (qStringTableRow("0", "1", "2"))
       
   614                 << (qStringTableRow("3", "4", "5")))
       
   615             << (Selection() // selection; 2x the same row (to simulate selections in hierarchy)
       
   616                 << Position(0, 0) << Position(0, 1)
       
   617                 << Position(0, 0) << Position(0, 1))
       
   618             << Position(3, 2) // drop position
       
   619             << (STRINGTABLE // resulting table
       
   620                 << (qStringTableRow("0", "1", "2"))
       
   621                 << (qStringTableRow("3", "4", "5"))
       
   622                 << (qStringTableRow("" , "" , "A"))
       
   623                 << (qStringTableRow("" , "" , "B"))
       
   624                 << (qStringTableRow("" , "" , "A"))
       
   625                 << (qStringTableRow("" , "" , "B")));
       
   626     }
       
   627     {
       
   628         QTest::newRow("2x 1x2 dropped at [3, 2] (different rows)")
       
   629             << (STRINGTABLE // source table
       
   630                 << (qStringTableRow("A", "B", "C"))
       
   631                 << (qStringTableRow("D", "E", "F"))
       
   632                 << (qStringTableRow("G", "H", "I")))
       
   633             << (STRINGTABLE // destination table
       
   634                 << (qStringTableRow("0", "1", "2"))
       
   635                 << (qStringTableRow("3", "4", "5")))
       
   636             << (Selection() // selection; 2x the same row (to simulate selections in hierarchy)
       
   637                 << Position(0, 0) << Position(0, 1)
       
   638                 << Position(2, 0) << Position(2, 1))
       
   639             << Position(2, 1) // drop position
       
   640             << (STRINGTABLE // resulting table
       
   641                 << (qStringTableRow("0", "1", "2"))
       
   642                 << (qStringTableRow("3", "4", "5"))
       
   643                 << (qStringTableRow("" , "A" , "B"))
       
   644                 << (qStringTableRow("" , "G" , "H")));
       
   645     }
       
   646 
       
   647     {
       
   648         QTest::newRow("2x 1x2 dropped at [3, 2] (different rows, over the edge)")
       
   649             << (STRINGTABLE // source table
       
   650                 << (qStringTableRow("A", "B", "C"))
       
   651                 << (qStringTableRow("D", "E", "F"))
       
   652                 << (qStringTableRow("G", "H", "I")))
       
   653             << (STRINGTABLE // destination table
       
   654                 << (qStringTableRow("0", "1", "2"))
       
   655                 << (qStringTableRow("3", "4", "5")))
       
   656             << (Selection() // selection; 2x the same row (to simulate selections in hierarchy)
       
   657                 << Position(0, 0) << Position(0, 1)
       
   658                 << Position(2, 0) << Position(2, 1))
       
   659             << Position(3, 2) // drop position
       
   660             << (STRINGTABLE // resulting table
       
   661                 << (qStringTableRow("0", "1", "2"))
       
   662                 << (qStringTableRow("3", "4", "5"))
       
   663                 << (qStringTableRow("" , "" , "A"))
       
   664                 << (qStringTableRow("" , "" , "G"))
       
   665                 << (qStringTableRow("" , "" , "B"))
       
   666                 << (qStringTableRow("" , "" , "H")));
       
   667     }
       
   668 }
       
   669 
       
   670 void tst_QAbstractItemModel::dropMimeData()
       
   671 {
       
   672     QFETCH(StringTable, src_table);
       
   673     QFETCH(StringTable, dst_table);
       
   674     QFETCH(Selection, selection);
       
   675     QFETCH(Position, dst_position);
       
   676     QFETCH(StringTable, res_table);
       
   677 
       
   678     QtTestModel src(src_table);
       
   679     QtTestModel dst(dst_table);
       
   680     QtTestModel res(res_table);
       
   681 
       
   682 //     qDebug() << "src" << src.rowCount(QModelIndex()) << src.columnCount(QModelIndex());
       
   683 //     qDebug() << "dst" << dst.rowCount(QModelIndex()) << dst.columnCount(QModelIndex());
       
   684 //     qDebug() << "res" << res.rowCount(QModelIndex()) << res.columnCount(QModelIndex());
       
   685 
       
   686     // get the mimeData from the "selected" indexes
       
   687     QModelIndexList selectedIndexes;
       
   688     for (int i = 0; i < selection.count(); ++i)
       
   689         selectedIndexes << src.index(selection.at(i).first, selection.at(i).second, QModelIndex());
       
   690     QMimeData *md = src.mimeData(selectedIndexes);
       
   691     // do the drop
       
   692     dst.dropMimeData(md, Qt::CopyAction, dst_position.first, dst_position.second, QModelIndex());
       
   693     delete md;
       
   694 
       
   695     // compare to the expected results
       
   696     QCOMPARE(dst.rowCount(QModelIndex()), res.rowCount(QModelIndex()));
       
   697     QCOMPARE(dst.columnCount(QModelIndex()), res.columnCount(QModelIndex()));
       
   698     for (int r = 0; r < dst.rowCount(QModelIndex()); ++r) {
       
   699         for (int c = 0; c < dst.columnCount(QModelIndex()); ++c) {
       
   700             QModelIndex dst_idx = dst.index(r, c, QModelIndex());
       
   701             QModelIndex res_idx = res.index(r, c, QModelIndex());
       
   702             QMap<int, QVariant> dst_data = dst.itemData(dst_idx);
       
   703             QMap<int, QVariant> res_data = res.itemData(res_idx);
       
   704             //if(dst_data != res_data)
       
   705             //    qDebug() << r << c << dst_data.value(0).toString() << res_data.value(0).toString();
       
   706             QCOMPARE(dst_data , res_data);
       
   707         }
       
   708     }
       
   709 
       
   710 }
       
   711 
       
   712 
       
   713 void tst_QAbstractItemModel::changePersistentIndex()
       
   714 {
       
   715     QtTestModel model(3, 3);
       
   716     QModelIndex a = model.index(1, 2, QModelIndex());
       
   717     QModelIndex b = model.index(2, 1, QModelIndex());
       
   718     QPersistentModelIndex p(a);
       
   719     QVERIFY(p == a);
       
   720     model.setPersistent(a, b);
       
   721     QVERIFY(p == b);
       
   722 }
       
   723 
       
   724 void tst_QAbstractItemModel::movePersistentIndex()
       
   725 {
       
   726     QtTestModel model(3, 3);
       
   727 
       
   728     QPersistentModelIndex a = model.index(1, 1);
       
   729     QVERIFY(a.isValid());
       
   730     QCOMPARE(a.row(), 1);
       
   731     QCOMPARE(a.column(), 1);
       
   732 
       
   733     model.insertRow(0);
       
   734     QCOMPARE(a.row(), 2);
       
   735 
       
   736     model.insertRow(1);
       
   737     QCOMPARE(a.row(), 3);
       
   738 
       
   739     model.insertColumn(0);
       
   740     QCOMPARE(a.column(), 2);
       
   741 }
       
   742 
       
   743 void tst_QAbstractItemModel::removeRows()
       
   744 {
       
   745     QtTestModel model(10, 10);
       
   746 
       
   747     QSignalSpy rowsAboutToBeRemovedSpy(&model, SIGNAL(rowsAboutToBeRemoved( const QModelIndex &, int , int )));
       
   748     QSignalSpy rowsRemovedSpy(&model, SIGNAL(rowsRemoved( const QModelIndex &, int, int )));
       
   749 
       
   750     QCOMPARE(model.removeRows(6, 4), true);
       
   751     QCOMPARE(rowsAboutToBeRemovedSpy.count(), 1);
       
   752     QCOMPARE(rowsRemovedSpy.count(), 1);
       
   753 }
       
   754 
       
   755 void tst_QAbstractItemModel::removeColumns()
       
   756 {
       
   757     QtTestModel model(10, 10);
       
   758 
       
   759     QSignalSpy columnsAboutToBeRemovedSpy(&model, SIGNAL(columnsAboutToBeRemoved( const QModelIndex &, int , int )));
       
   760     QSignalSpy columnsRemovedSpy(&model, SIGNAL(columnsRemoved( const QModelIndex &, int, int )));
       
   761 
       
   762     QCOMPARE(model.removeColumns(6, 4), true);
       
   763     QCOMPARE(columnsAboutToBeRemovedSpy.count(), 1);
       
   764     QCOMPARE(columnsRemovedSpy.count(), 1);
       
   765 }
       
   766 
       
   767 void tst_QAbstractItemModel::insertRows()
       
   768 {
       
   769     QtTestModel model(10, 10);
       
   770 
       
   771     QSignalSpy rowsAboutToBeInsertedSpy(&model, SIGNAL(rowsAboutToBeInserted( const QModelIndex &, int , int )));
       
   772     QSignalSpy rowsInsertedSpy(&model, SIGNAL(rowsInserted( const QModelIndex &, int, int )));
       
   773 
       
   774     QCOMPARE(model.insertRows(6, 4), true);
       
   775     QCOMPARE(rowsAboutToBeInsertedSpy.count(), 1);
       
   776     QCOMPARE(rowsInsertedSpy.count(), 1);
       
   777 }
       
   778 
       
   779 void tst_QAbstractItemModel::insertColumns()
       
   780 {
       
   781     QtTestModel model(10, 10);
       
   782 
       
   783     QSignalSpy columnsAboutToBeInsertedSpy(&model, SIGNAL(columnsAboutToBeInserted( const QModelIndex &, int , int )));
       
   784     QSignalSpy columnsInsertedSpy(&model, SIGNAL(columnsInserted( const QModelIndex &, int, int )));
       
   785 
       
   786     QCOMPARE(model.insertColumns(6, 4), true);
       
   787     QCOMPARE(columnsAboutToBeInsertedSpy.count(), 1);
       
   788     QCOMPARE(columnsInsertedSpy.count(), 1);
       
   789 }
       
   790 
       
   791 void tst_QAbstractItemModel::reset()
       
   792 {
       
   793     QtTestModel model(10, 10);
       
   794 
       
   795     QSignalSpy resetSpy(&model, SIGNAL(modelReset()));
       
   796     model.reset();
       
   797     QCOMPARE(resetSpy.count(), 1);
       
   798 }
       
   799 
       
   800 void tst_QAbstractItemModel::complexChangesWithPersistent()
       
   801 {
       
   802     QtTestModel model(10, 10);
       
   803     QPersistentModelIndex a = model.index(1, 1, QModelIndex());
       
   804     QPersistentModelIndex b = model.index(9, 7, QModelIndex());
       
   805     QPersistentModelIndex c = model.index(5, 6, QModelIndex());
       
   806     QPersistentModelIndex d = model.index(3, 9, QModelIndex());
       
   807     QPersistentModelIndex e[10];
       
   808     for (int i=0; i <10 ; i++) {
       
   809         e[i] = model.index(2, i , QModelIndex());
       
   810     }
       
   811 
       
   812     QVERIFY(a == model.index(1, 1, QModelIndex()));
       
   813     QVERIFY(b == model.index(9, 7, QModelIndex()));
       
   814     QVERIFY(c == model.index(5, 6, QModelIndex()));
       
   815     QVERIFY(d == model.index(3, 9, QModelIndex()));
       
   816     for (int i=0; i <8 ; i++)
       
   817         QVERIFY(e[i] == model.index(2, i , QModelIndex()));
       
   818 
       
   819     //remove a bunch of columns
       
   820     model.removeColumns(2, 4);
       
   821 
       
   822     QVERIFY(a == model.index(1, 1, QModelIndex()));
       
   823     QVERIFY(b == model.index(9, 3, QModelIndex()));
       
   824     QVERIFY(c == model.index(5, 2, QModelIndex()));
       
   825     QVERIFY(d == model.index(3, 5, QModelIndex()));
       
   826     for (int i=0; i <2 ; i++)
       
   827         QVERIFY(e[i] == model.index(2, i , QModelIndex()));
       
   828     for (int i=2; i <6 ; i++)
       
   829         QVERIFY(!e[i].isValid());
       
   830     for (int i=6; i <10 ; i++)
       
   831         QVERIFY(e[i] == model.index(2, i-4 , QModelIndex()));
       
   832 
       
   833     //move some indexes around
       
   834     model.setPersistent(model.index(1, 1 , QModelIndex()), model.index(9, 3 , QModelIndex()));
       
   835     model.setPersistent(model.index(9, 3 , QModelIndex()), model.index(8, 4 , QModelIndex()));
       
   836 
       
   837     QVERIFY(a == model.index(9, 3, QModelIndex()));
       
   838     QVERIFY(b == model.index(8, 4, QModelIndex()));
       
   839     QVERIFY(c == model.index(5, 2, QModelIndex()));
       
   840     QVERIFY(d == model.index(3, 5, QModelIndex()));
       
   841     for (int i=0; i <2 ; i++)
       
   842         QVERIFY(e[i] == model.index(2, i , QModelIndex()));
       
   843     for (int i=2; i <6 ; i++)
       
   844         QVERIFY(!e[i].isValid());
       
   845     for (int i=6; i <10 ; i++)
       
   846         QVERIFY(e[i] == model.index(2, i-4 , QModelIndex()));
       
   847 
       
   848     //inserting a bunch of columns
       
   849     model.insertColumns(2, 2);
       
   850     QVERIFY(a == model.index(9, 5, QModelIndex()));
       
   851     QVERIFY(b == model.index(8, 6, QModelIndex()));
       
   852     QVERIFY(c == model.index(5, 4, QModelIndex()));
       
   853     QVERIFY(d == model.index(3, 7, QModelIndex()));
       
   854     for (int i=0; i <2 ; i++)
       
   855         QVERIFY(e[i] == model.index(2, i , QModelIndex()));
       
   856     for (int i=2; i <6 ; i++)
       
   857         QVERIFY(!e[i].isValid());
       
   858     for (int i=6; i <10 ; i++)
       
   859         QVERIFY(e[i] == model.index(2, i-2 , QModelIndex()));
       
   860 
       
   861 }
       
   862 
       
   863 void tst_QAbstractItemModel::testMoveSameParentDown_data()
       
   864 {
       
   865     QTest::addColumn<int>("startRow");
       
   866     QTest::addColumn<int>("endRow");
       
   867     QTest::addColumn<int>("destRow");
       
   868 
       
   869     // Move from the start to the middle
       
   870     QTest::newRow("move01") << 0 << 2 << 8;
       
   871     // Move from the start to the end
       
   872     QTest::newRow("move02") << 0 << 2 << 10;
       
   873     // Move from the middle to the middle
       
   874     QTest::newRow("move03") << 3 << 5 << 8;
       
   875     // Move from the middle to the end
       
   876     QTest::newRow("move04") << 3 << 5 << 10;
       
   877 }
       
   878 
       
   879 void tst_QAbstractItemModel::testMoveSameParentDown()
       
   880 {
       
   881     QFETCH( int, startRow);
       
   882     QFETCH( int, endRow);
       
   883     QFETCH( int, destRow);
       
   884 
       
   885     QList<QPersistentModelIndex> persistentList;
       
   886     QModelIndexList indexList;
       
   887 
       
   888     for (int column = 0; column < m_model->columnCount(); ++column)
       
   889     {
       
   890         for (int row= 0; row < m_model->rowCount(); ++row)
       
   891         {
       
   892             QModelIndex idx = m_model->index(row, column);
       
   893             QVERIFY(idx.isValid());
       
   894             indexList << idx;
       
   895             persistentList << QPersistentModelIndex(idx);
       
   896         }
       
   897     }
       
   898 
       
   899     QModelIndex parent = m_model->index(5, 0);
       
   900     for (int column = 0; column < m_model->columnCount(); ++column)
       
   901     {
       
   902         for (int row= 0; row < m_model->rowCount(parent); ++row)
       
   903         {
       
   904             QModelIndex idx = m_model->index(row, column, parent);
       
   905             QVERIFY(idx.isValid());
       
   906             indexList << idx;
       
   907             persistentList << QPersistentModelIndex(idx);
       
   908         }
       
   909     }
       
   910 
       
   911     QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
   912     QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
   913 
       
   914     ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
       
   915     moveCommand->setNumCols(4);
       
   916     moveCommand->setStartRow(startRow);
       
   917     moveCommand->setEndRow(endRow);
       
   918     moveCommand->setDestRow(destRow);
       
   919     moveCommand->doCommand();
       
   920 
       
   921     QVariantList beforeSignal = beforeSpy.takeAt(0);
       
   922     QVariantList afterSignal = afterSpy.takeAt(0);
       
   923 
       
   924     QCOMPARE(beforeSignal.size(), 5);
       
   925     QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), QModelIndex());
       
   926     QCOMPARE(beforeSignal.at(1).toInt(), startRow);
       
   927     QCOMPARE(beforeSignal.at(2).toInt(), endRow);
       
   928     QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex());
       
   929     QCOMPARE(beforeSignal.at(4).toInt(), destRow);
       
   930 
       
   931     QCOMPARE(afterSignal.size(), 5);
       
   932     QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex());
       
   933     QCOMPARE(afterSignal.at(1).toInt(), startRow);
       
   934     QCOMPARE(afterSignal.at(2).toInt(), endRow);
       
   935     QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex());
       
   936     QCOMPARE(afterSignal.at(4).toInt(), destRow);
       
   937 
       
   938     for (int i = 0; i < indexList.size(); i++)
       
   939     {
       
   940         QModelIndex idx = indexList.at(i);
       
   941         QModelIndex persistentIndex = persistentList.at(i);
       
   942         if (idx.parent() == QModelIndex())
       
   943         {
       
   944             int row = idx.row();
       
   945             if ( row >= startRow)
       
   946             {
       
   947                 if (row <= endRow)
       
   948                 {
       
   949                     QCOMPARE(row + destRow - endRow - 1, persistentIndex.row() );
       
   950                     QCOMPARE(idx.column(), persistentIndex.column());
       
   951                     QCOMPARE(idx.parent(), persistentIndex.parent());
       
   952                     QCOMPARE(idx.model(), persistentIndex.model());
       
   953                 } else if ( row < destRow)
       
   954                 {
       
   955                     QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() );
       
   956                     QCOMPARE(idx.column(), persistentIndex.column());
       
   957                     QCOMPARE(idx.parent(), persistentIndex.parent());
       
   958                     QCOMPARE(idx.model(), persistentIndex.model());
       
   959                 } else
       
   960                 {
       
   961                      QCOMPARE(idx, persistentIndex);
       
   962                 }
       
   963             } else
       
   964             {
       
   965                 QCOMPARE(idx, persistentIndex);
       
   966             }
       
   967         } else
       
   968         {
       
   969             QCOMPARE(idx, persistentIndex);
       
   970         }
       
   971     }
       
   972 }
       
   973 
       
   974 void tst_QAbstractItemModel::testMoveSameParentUp_data()
       
   975 {
       
   976     QTest::addColumn<int>("startRow");
       
   977     QTest::addColumn<int>("endRow");
       
   978     QTest::addColumn<int>("destRow");
       
   979 
       
   980     // Move from the middle to the start
       
   981     QTest::newRow("move01") << 5 << 7 << 0;
       
   982     // Move from the end to the start
       
   983     QTest::newRow("move02") << 8 << 9 << 0;
       
   984     // Move from the middle to the middle
       
   985     QTest::newRow("move03") << 5 << 7 << 2;
       
   986     // Move from the end to the middle
       
   987     QTest::newRow("move04") << 8 << 9 << 5;
       
   988 }
       
   989 
       
   990 void tst_QAbstractItemModel::testMoveSameParentUp()
       
   991 {
       
   992 
       
   993     QFETCH( int, startRow);
       
   994     QFETCH( int, endRow);
       
   995     QFETCH( int, destRow);
       
   996 
       
   997     QList<QPersistentModelIndex> persistentList;
       
   998     QModelIndexList indexList;
       
   999 
       
  1000     for (int column = 0; column < m_model->columnCount(); ++column)
       
  1001     {
       
  1002         for (int row= 0; row < m_model->rowCount(); ++row)
       
  1003         {
       
  1004             QModelIndex idx = m_model->index(row, column);
       
  1005             QVERIFY(idx.isValid());
       
  1006             indexList << idx;
       
  1007             persistentList << QPersistentModelIndex(idx);
       
  1008         }
       
  1009     }
       
  1010 
       
  1011     QModelIndex parent = m_model->index(2, 0);
       
  1012     for (int column = 0; column < m_model->columnCount(); ++column)
       
  1013     {
       
  1014         for (int row= 0; row < m_model->rowCount(parent); ++row)
       
  1015         {
       
  1016             QModelIndex idx = m_model->index(row, column, parent);
       
  1017             QVERIFY(idx.isValid());
       
  1018             indexList << idx;
       
  1019             persistentList << QPersistentModelIndex(idx);
       
  1020         }
       
  1021     }
       
  1022 
       
  1023     QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1024     QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1025 
       
  1026 
       
  1027     ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
       
  1028     moveCommand->setNumCols(4);
       
  1029     moveCommand->setStartRow(startRow);
       
  1030     moveCommand->setEndRow(endRow);
       
  1031     moveCommand->setDestRow(destRow);
       
  1032     moveCommand->doCommand();
       
  1033 
       
  1034     QVariantList beforeSignal = beforeSpy.takeAt(0);
       
  1035     QVariantList afterSignal = afterSpy.takeAt(0);
       
  1036 
       
  1037     QCOMPARE(beforeSignal.size(), 5);
       
  1038     QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), QModelIndex());
       
  1039     QCOMPARE(beforeSignal.at(1).toInt(), startRow);
       
  1040     QCOMPARE(beforeSignal.at(2).toInt(), endRow);
       
  1041     QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex());
       
  1042     QCOMPARE(beforeSignal.at(4).toInt(), destRow);
       
  1043 
       
  1044     QCOMPARE(afterSignal.size(), 5);
       
  1045     QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex());
       
  1046     QCOMPARE(afterSignal.at(1).toInt(), startRow);
       
  1047     QCOMPARE(afterSignal.at(2).toInt(), endRow);
       
  1048     QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex());
       
  1049     QCOMPARE(afterSignal.at(4).toInt(), destRow);
       
  1050 
       
  1051 
       
  1052     for (int i = 0; i < indexList.size(); i++)
       
  1053     {
       
  1054         QModelIndex idx = indexList.at(i);
       
  1055         QModelIndex persistentIndex = persistentList.at(i);
       
  1056         if (idx.parent() == QModelIndex())
       
  1057         {
       
  1058             int row = idx.row();
       
  1059             if ( row >= destRow)
       
  1060             {
       
  1061                 if (row < startRow)
       
  1062                 {
       
  1063                     QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() );
       
  1064                     QCOMPARE(idx.column(), persistentIndex.column());
       
  1065                     QCOMPARE(idx.parent(), persistentIndex.parent());
       
  1066                     QCOMPARE(idx.model(), persistentIndex.model());
       
  1067                 } else if ( row <= endRow)
       
  1068                 {
       
  1069                     QCOMPARE(row + destRow - startRow, persistentIndex.row() );
       
  1070                     QCOMPARE(idx.column(), persistentIndex.column());
       
  1071                     QCOMPARE(idx.parent(), persistentIndex.parent());
       
  1072                     QCOMPARE(idx.model(), persistentIndex.model());
       
  1073                 } else
       
  1074                 {
       
  1075                     QCOMPARE(idx, persistentIndex);
       
  1076                 }
       
  1077             } else
       
  1078             {
       
  1079                 QCOMPARE(idx, persistentIndex);
       
  1080             }
       
  1081         } else
       
  1082         {
       
  1083             QCOMPARE(idx, persistentIndex);
       
  1084         }
       
  1085     }
       
  1086 }
       
  1087 
       
  1088 void tst_QAbstractItemModel::testMoveToGrandParent_data()
       
  1089 {
       
  1090     QTest::addColumn<int>("startRow");
       
  1091     QTest::addColumn<int>("endRow");
       
  1092     QTest::addColumn<int>("destRow");
       
  1093 
       
  1094     // Move from the start to the middle
       
  1095     QTest::newRow("move01") << 0 << 2 << 8;
       
  1096     // Move from the start to the end
       
  1097     QTest::newRow("move02") << 0 << 2 << 10;
       
  1098     // Move from the middle to the middle
       
  1099     QTest::newRow("move03") << 3 << 5 << 8;
       
  1100     // Move from the middle to the end
       
  1101     QTest::newRow("move04") << 3 << 5 << 10;
       
  1102 
       
  1103     // Move from the middle to the start
       
  1104     QTest::newRow("move05") << 5 << 7 << 0;
       
  1105     // Move from the end to the start
       
  1106     QTest::newRow("move06") << 8 << 9 << 0;
       
  1107     // Move from the middle to the middle
       
  1108     QTest::newRow("move07") << 5 << 7 << 2;
       
  1109     // Move from the end to the middle
       
  1110     QTest::newRow("move08") << 8 << 9 << 5;
       
  1111 
       
  1112     // Moving to the same row in a different parent doesn't confuse things.
       
  1113     QTest::newRow("move09") << 8 << 8 << 8;
       
  1114 
       
  1115     // Moving to the row of my parent and its neighbours doesn't confuse things
       
  1116     QTest::newRow("move09") << 8 << 8 << 4;
       
  1117     QTest::newRow("move10") << 8 << 8 << 5;
       
  1118     QTest::newRow("move11") << 8 << 8 << 6;
       
  1119 
       
  1120     // Moving everything from one parent to another
       
  1121     QTest::newRow("move12") << 0 << 9 << 10;
       
  1122 }
       
  1123 
       
  1124 void tst_QAbstractItemModel::testMoveToGrandParent()
       
  1125 {
       
  1126 
       
  1127     QFETCH( int, startRow);
       
  1128     QFETCH( int, endRow);
       
  1129     QFETCH( int, destRow);
       
  1130 
       
  1131     QList<QPersistentModelIndex> persistentList;
       
  1132     QModelIndexList indexList;
       
  1133     QModelIndexList parentsList;
       
  1134 
       
  1135     for (int column = 0; column < m_model->columnCount(); ++column)
       
  1136     {
       
  1137         for (int row= 0; row < m_model->rowCount(); ++row)
       
  1138         {
       
  1139             QModelIndex idx = m_model->index(row, column);
       
  1140             QVERIFY(idx.isValid());
       
  1141             indexList << idx;
       
  1142             parentsList << idx.parent();
       
  1143             persistentList << QPersistentModelIndex(idx);
       
  1144         }
       
  1145     }
       
  1146 
       
  1147     QModelIndex sourceIndex = m_model->index(5, 0);
       
  1148     for (int column = 0; column < m_model->columnCount(); ++column)
       
  1149     {
       
  1150         for (int row= 0; row < m_model->rowCount(sourceIndex); ++row)
       
  1151         {
       
  1152             QModelIndex idx = m_model->index(row, column, sourceIndex);
       
  1153             QVERIFY(idx.isValid());
       
  1154             indexList << idx;
       
  1155             parentsList << idx.parent();
       
  1156             persistentList << QPersistentModelIndex(idx);
       
  1157         }
       
  1158     }
       
  1159 
       
  1160     QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1161     QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1162 
       
  1163 
       
  1164     ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
       
  1165     moveCommand->setAncestorRowNumbers(QList<int>() << 5);
       
  1166     moveCommand->setNumCols(4);
       
  1167     moveCommand->setStartRow(startRow);
       
  1168     moveCommand->setEndRow(endRow);
       
  1169     moveCommand->setDestRow(destRow);
       
  1170     moveCommand->doCommand();
       
  1171 
       
  1172     QVariantList beforeSignal = beforeSpy.takeAt(0);
       
  1173     QVariantList afterSignal = afterSpy.takeAt(0);
       
  1174 
       
  1175     QCOMPARE(beforeSignal.size(), 5);
       
  1176     QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), sourceIndex);
       
  1177     QCOMPARE(beforeSignal.at(1).toInt(), startRow);
       
  1178     QCOMPARE(beforeSignal.at(2).toInt(), endRow);
       
  1179     QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex());
       
  1180     QCOMPARE(beforeSignal.at(4).toInt(), destRow);
       
  1181 
       
  1182     QCOMPARE(afterSignal.size(), 5);
       
  1183     QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex);
       
  1184     QCOMPARE(afterSignal.at(1).toInt(), startRow);
       
  1185     QCOMPARE(afterSignal.at(2).toInt(), endRow);
       
  1186     QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex());
       
  1187     QCOMPARE(afterSignal.at(4).toInt(), destRow);
       
  1188 
       
  1189     for (int i = 0; i < indexList.size(); i++)
       
  1190     {
       
  1191         QModelIndex idx = indexList.at(i);
       
  1192         QModelIndex idxParent = parentsList.at(i);
       
  1193         QModelIndex persistentIndex = persistentList.at(i);
       
  1194         int row = idx.row();
       
  1195         if (idxParent == QModelIndex())
       
  1196         {
       
  1197             if ( row >= destRow)
       
  1198             {
       
  1199                     QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() );
       
  1200                     QCOMPARE(idx.column(), persistentIndex.column());
       
  1201                     QCOMPARE(idxParent, persistentIndex.parent());
       
  1202                     QCOMPARE(idx.model(), persistentIndex.model());
       
  1203             } else
       
  1204             {
       
  1205                 QCOMPARE(idx, persistentIndex);
       
  1206             }
       
  1207         } else
       
  1208         {
       
  1209             if (row < startRow)
       
  1210             {
       
  1211                 QCOMPARE(idx, persistentIndex);
       
  1212             } else if (row <= endRow)
       
  1213             {
       
  1214                 QCOMPARE(row + destRow - startRow, persistentIndex.row() );
       
  1215                 QCOMPARE(idx.column(), persistentIndex.column());
       
  1216                 QCOMPARE(QModelIndex(), persistentIndex.parent());
       
  1217                 QCOMPARE(idx.model(), persistentIndex.model());
       
  1218             } else {
       
  1219                 QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() );
       
  1220                 QCOMPARE(idx.column(), persistentIndex.column());
       
  1221 
       
  1222                 if (idxParent.row() >= destRow)
       
  1223                 {
       
  1224                     QModelIndex adjustedParent;
       
  1225                     adjustedParent = idxParent.sibling( idxParent.row() + endRow - startRow + 1,    idxParent.column());
       
  1226                     QCOMPARE(adjustedParent, persistentIndex.parent());
       
  1227                 } else
       
  1228                 {
       
  1229                     QCOMPARE(idxParent, persistentIndex.parent());
       
  1230                 }
       
  1231                 QCOMPARE(idx.model(), persistentIndex.model());
       
  1232             }
       
  1233         }
       
  1234     }
       
  1235 }
       
  1236 
       
  1237 void tst_QAbstractItemModel::testMoveToSibling_data()
       
  1238 {
       
  1239     QTest::addColumn<int>("startRow");
       
  1240     QTest::addColumn<int>("endRow");
       
  1241     QTest::addColumn<int>("destRow");
       
  1242 
       
  1243     // Move from the start to the middle
       
  1244     QTest::newRow("move01") << 0 << 2 << 8;
       
  1245     // Move from the start to the end
       
  1246     QTest::newRow("move02") << 0 << 2 << 10;
       
  1247     // Move from the middle to the middle
       
  1248     QTest::newRow("move03") << 2 << 4 << 8;
       
  1249     // Move from the middle to the end
       
  1250     QTest::newRow("move04") << 2 << 4 << 10;
       
  1251 
       
  1252     // Move from the middle to the start
       
  1253     QTest::newRow("move05") << 8 << 8 << 0;
       
  1254     // Move from the end to the start
       
  1255     QTest::newRow("move06") << 8 << 9 << 0;
       
  1256     // Move from the middle to the middle
       
  1257     QTest::newRow("move07") << 6 << 8 << 2;
       
  1258     // Move from the end to the middle
       
  1259     QTest::newRow("move08") << 8 << 9 << 5;
       
  1260 
       
  1261     // Moving to the same row in a different parent doesn't confuse things.
       
  1262     QTest::newRow("move09") << 8 << 8 << 8;
       
  1263 
       
  1264     // Moving to the row of my target and its neighbours doesn't confuse things
       
  1265     QTest::newRow("move09") << 8 << 8 << 4;
       
  1266     QTest::newRow("move10") << 8 << 8 << 5;
       
  1267     QTest::newRow("move11") << 8 << 8 << 6;
       
  1268 }
       
  1269 
       
  1270 void tst_QAbstractItemModel::testMoveToSibling()
       
  1271 {
       
  1272 
       
  1273     QFETCH( int, startRow);
       
  1274     QFETCH( int, endRow);
       
  1275     QFETCH( int, destRow);
       
  1276 
       
  1277     QList<QPersistentModelIndex> persistentList;
       
  1278     QModelIndexList indexList;
       
  1279     QModelIndexList parentsList;
       
  1280 
       
  1281     const int column = 0;
       
  1282 
       
  1283     for (int i= 0; i < m_model->rowCount(); ++i)
       
  1284     {
       
  1285         QModelIndex idx = m_model->index(i, column);
       
  1286         QVERIFY(idx.isValid());
       
  1287         indexList << idx;
       
  1288         parentsList << idx.parent();
       
  1289         persistentList << QPersistentModelIndex(idx);
       
  1290     }
       
  1291 
       
  1292     QModelIndex destIndex = m_model->index(5, 0);
       
  1293     QModelIndex sourceIndex;
       
  1294     for (int i= 0; i < m_model->rowCount(destIndex); ++i)
       
  1295     {
       
  1296         QModelIndex idx = m_model->index(i, column, destIndex);
       
  1297         QVERIFY(idx.isValid());
       
  1298         indexList << idx;
       
  1299         parentsList << idx.parent();
       
  1300         persistentList << QPersistentModelIndex(idx);
       
  1301     }
       
  1302 
       
  1303     QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1304     QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1305 
       
  1306 
       
  1307     ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
       
  1308     moveCommand->setNumCols(4);
       
  1309     moveCommand->setStartRow(startRow);
       
  1310     moveCommand->setEndRow(endRow);
       
  1311     moveCommand->setDestAncestors(QList<int>() << 5);
       
  1312     moveCommand->setDestRow(destRow);
       
  1313     moveCommand->doCommand();
       
  1314 
       
  1315     QVariantList beforeSignal = beforeSpy.takeAt(0);
       
  1316     QVariantList afterSignal = afterSpy.takeAt(0);
       
  1317 
       
  1318     QCOMPARE(beforeSignal.size(), 5);
       
  1319     QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), sourceIndex);
       
  1320     QCOMPARE(beforeSignal.at(1).toInt(), startRow);
       
  1321     QCOMPARE(beforeSignal.at(2).toInt(), endRow);
       
  1322     QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), destIndex);
       
  1323     QCOMPARE(beforeSignal.at(4).toInt(), destRow);
       
  1324 
       
  1325     QCOMPARE(afterSignal.size(), 5);
       
  1326     QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex);
       
  1327     QCOMPARE(afterSignal.at(1).toInt(), startRow);
       
  1328     QCOMPARE(afterSignal.at(2).toInt(), endRow);
       
  1329     QCOMPARE(afterSignal.at(3).value<QModelIndex>(), destIndex);
       
  1330     QCOMPARE(afterSignal.at(4).toInt(), destRow);
       
  1331 
       
  1332     for (int i = 0; i < indexList.size(); i++)
       
  1333     {
       
  1334         QModelIndex idx = indexList.at(i);
       
  1335         QModelIndex idxParent = parentsList.at(i);
       
  1336         QModelIndex persistentIndex = persistentList.at(i);
       
  1337 
       
  1338         QModelIndex adjustedDestination = destIndex.sibling(destIndex.row() - (endRow - startRow + 1), destIndex.column());
       
  1339         int row = idx.row();
       
  1340         if (idxParent == destIndex)
       
  1341         {
       
  1342             if ( row >= destRow)
       
  1343             {
       
  1344                     QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() );
       
  1345                     QCOMPARE(idx.column(), persistentIndex.column());
       
  1346                     if (idxParent.row() > startRow)
       
  1347                     {
       
  1348                         QCOMPARE(adjustedDestination, persistentIndex.parent());
       
  1349                     } else {
       
  1350                         QCOMPARE(destIndex, persistentIndex.parent());
       
  1351                     }
       
  1352                     QCOMPARE(idx.model(), persistentIndex.model());
       
  1353             } else
       
  1354             {
       
  1355                 QCOMPARE(idx, persistentIndex);
       
  1356             }
       
  1357         } else
       
  1358         {
       
  1359             if (row < startRow)
       
  1360             {
       
  1361                 QCOMPARE(idx, persistentIndex);
       
  1362             } else if (row <= endRow)
       
  1363             {
       
  1364                 QCOMPARE(row + destRow - startRow, persistentIndex.row() );
       
  1365                 QCOMPARE(idx.column(), persistentIndex.column());
       
  1366                 if (destIndex.row() > startRow)
       
  1367                 {
       
  1368                     QCOMPARE(adjustedDestination, persistentIndex.parent());
       
  1369                 } else {
       
  1370                     QCOMPARE(destIndex, persistentIndex.parent());
       
  1371                 }
       
  1372 
       
  1373                 QCOMPARE(idx.model(), persistentIndex.model());
       
  1374 
       
  1375             } else {
       
  1376                 QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() );
       
  1377                 QCOMPARE(idx.column(), persistentIndex.column());
       
  1378                 QCOMPARE(idxParent, persistentIndex.parent());
       
  1379                 QCOMPARE(idx.model(), persistentIndex.model());
       
  1380             }
       
  1381         }
       
  1382     }
       
  1383 }
       
  1384 
       
  1385 void tst_QAbstractItemModel::testMoveToUncle_data()
       
  1386 {
       
  1387 
       
  1388     QTest::addColumn<int>("startRow");
       
  1389     QTest::addColumn<int>("endRow");
       
  1390     QTest::addColumn<int>("destRow");
       
  1391 
       
  1392     // Move from the start to the middle
       
  1393     QTest::newRow("move01") << 0 << 2 << 8;
       
  1394     // Move from the start to the end
       
  1395     QTest::newRow("move02") << 0 << 2 << 10;
       
  1396     // Move from the middle to the middle
       
  1397     QTest::newRow("move03") << 3 << 5 << 8;
       
  1398     // Move from the middle to the end
       
  1399     QTest::newRow("move04") << 3 << 5 << 10;
       
  1400 
       
  1401     // Move from the middle to the start
       
  1402     QTest::newRow("move05") << 5 << 7 << 0;
       
  1403     // Move from the end to the start
       
  1404     QTest::newRow("move06") << 8 << 9 << 0;
       
  1405     // Move from the middle to the middle
       
  1406     QTest::newRow("move07") << 5 << 7 << 2;
       
  1407     // Move from the end to the middle
       
  1408     QTest::newRow("move08") << 8 << 9 << 5;
       
  1409 
       
  1410     // Moving to the same row in a different parent doesn't confuse things.
       
  1411     QTest::newRow("move09") << 8 << 8 << 8;
       
  1412 
       
  1413     // Moving to the row of my parent and its neighbours doesn't confuse things
       
  1414     QTest::newRow("move09") << 8 << 8 << 4;
       
  1415     QTest::newRow("move10") << 8 << 8 << 5;
       
  1416     QTest::newRow("move11") << 8 << 8 << 6;
       
  1417 
       
  1418     // Moving everything from one parent to another
       
  1419     QTest::newRow("move12") << 0 << 9 << 10;
       
  1420 }
       
  1421 
       
  1422 void tst_QAbstractItemModel::testMoveToUncle()
       
  1423 {
       
  1424     // Need to have some extra rows available.
       
  1425     ModelInsertCommand *insertCommand = new ModelInsertCommand(m_model, this);
       
  1426     insertCommand->setAncestorRowNumbers(QList<int>() << 9);
       
  1427     insertCommand->setNumCols(4);
       
  1428     insertCommand->setStartRow(0);
       
  1429     insertCommand->setEndRow(9);
       
  1430     insertCommand->doCommand();
       
  1431 
       
  1432     QFETCH( int, startRow);
       
  1433     QFETCH( int, endRow);
       
  1434     QFETCH( int, destRow);
       
  1435 
       
  1436     QList<QPersistentModelIndex> persistentList;
       
  1437     QModelIndexList indexList;
       
  1438     QModelIndexList parentsList;
       
  1439 
       
  1440     const int column = 0;
       
  1441 
       
  1442     QModelIndex sourceIndex = m_model->index(9, 0);
       
  1443     for (int i= 0; i < m_model->rowCount(sourceIndex); ++i)
       
  1444     {
       
  1445         QModelIndex idx = m_model->index(i, column, sourceIndex);
       
  1446         QVERIFY(idx.isValid());
       
  1447         indexList << idx;
       
  1448         parentsList << idx.parent();
       
  1449         persistentList << QPersistentModelIndex(idx);
       
  1450     }
       
  1451 
       
  1452     QModelIndex destIndex = m_model->index(5, 0);
       
  1453     for (int i= 0; i < m_model->rowCount(destIndex); ++i)
       
  1454     {
       
  1455         QModelIndex idx = m_model->index(i, column, destIndex);
       
  1456         QVERIFY(idx.isValid());
       
  1457         indexList << idx;
       
  1458         parentsList << idx.parent();
       
  1459         persistentList << QPersistentModelIndex(idx);
       
  1460     }
       
  1461 
       
  1462     QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1463     QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1464 
       
  1465     ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
       
  1466     moveCommand->setAncestorRowNumbers(QList<int>() << 9);
       
  1467     moveCommand->setNumCols(4);
       
  1468     moveCommand->setStartRow(startRow);
       
  1469     moveCommand->setEndRow(endRow);
       
  1470     moveCommand->setDestAncestors(QList<int>() << 5);
       
  1471     moveCommand->setDestRow(destRow);
       
  1472     moveCommand->doCommand();
       
  1473 
       
  1474     QVariantList beforeSignal = beforeSpy.takeAt(0);
       
  1475     QVariantList afterSignal = afterSpy.takeAt(0);
       
  1476 
       
  1477     QCOMPARE(beforeSignal.size(), 5);
       
  1478     QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), sourceIndex);
       
  1479     QCOMPARE(beforeSignal.at(1).toInt(), startRow);
       
  1480     QCOMPARE(beforeSignal.at(2).toInt(), endRow);
       
  1481     QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), destIndex);
       
  1482     QCOMPARE(beforeSignal.at(4).toInt(), destRow);
       
  1483 
       
  1484     QCOMPARE(afterSignal.size(), 5);
       
  1485     QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex);
       
  1486     QCOMPARE(afterSignal.at(1).toInt(), startRow);
       
  1487     QCOMPARE(afterSignal.at(2).toInt(), endRow);
       
  1488     QCOMPARE(afterSignal.at(3).value<QModelIndex>(), destIndex);
       
  1489     QCOMPARE(afterSignal.at(4).toInt(), destRow);
       
  1490 
       
  1491     for (int i = 0; i < indexList.size(); i++)
       
  1492     {
       
  1493         QModelIndex idx = indexList.at(i);
       
  1494         QModelIndex idxParent = parentsList.at(i);
       
  1495         QModelIndex persistentIndex = persistentList.at(i);
       
  1496 
       
  1497         int row = idx.row();
       
  1498         if (idxParent == destIndex)
       
  1499         {
       
  1500             if ( row >= destRow)
       
  1501             {
       
  1502                     QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() );
       
  1503                     QCOMPARE(idx.column(), persistentIndex.column());
       
  1504                     QCOMPARE(destIndex, persistentIndex.parent());
       
  1505                     QCOMPARE(idx.model(), persistentIndex.model());
       
  1506             } else
       
  1507             {
       
  1508                 QCOMPARE(idx, persistentIndex);
       
  1509             }
       
  1510         } else
       
  1511         {
       
  1512             if (row < startRow)
       
  1513             {
       
  1514                 QCOMPARE(idx, persistentIndex);
       
  1515             } else if (row <= endRow)
       
  1516             {
       
  1517                 QCOMPARE(row + destRow - startRow, persistentIndex.row() );
       
  1518                 QCOMPARE(idx.column(), persistentIndex.column());
       
  1519                 QCOMPARE(destIndex, persistentIndex.parent());
       
  1520                 QCOMPARE(idx.model(), persistentIndex.model());
       
  1521 
       
  1522             } else {
       
  1523                 QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() );
       
  1524                 QCOMPARE(idx.column(), persistentIndex.column());
       
  1525                 QCOMPARE(idxParent, persistentIndex.parent());
       
  1526                 QCOMPARE(idx.model(), persistentIndex.model());
       
  1527             }
       
  1528         }
       
  1529     }
       
  1530 }
       
  1531 
       
  1532 void tst_QAbstractItemModel::testMoveToDescendants()
       
  1533 {
       
  1534     // Attempt to move a row to its ancestors depth rows deep.
       
  1535     const int depth = 6;
       
  1536 
       
  1537     // Need to have some extra rows available in a tree.
       
  1538     QList<int> rows;
       
  1539     ModelInsertCommand *insertCommand;
       
  1540     for (int i = 0; i < depth; i++)
       
  1541     {
       
  1542         insertCommand = new ModelInsertCommand(m_model, this);
       
  1543         insertCommand->setAncestorRowNumbers(rows);
       
  1544         insertCommand->setNumCols(4);
       
  1545         insertCommand->setStartRow(0);
       
  1546         insertCommand->setEndRow(9);
       
  1547         insertCommand->doCommand();
       
  1548         rows << 9;
       
  1549     }
       
  1550 
       
  1551     QList<QPersistentModelIndex> persistentList;
       
  1552     QModelIndexList indexList;
       
  1553     QModelIndexList parentsList;
       
  1554 
       
  1555     const int column = 0;
       
  1556 
       
  1557     QModelIndex sourceIndex = m_model->index(9, 0);
       
  1558     for (int i= 0; i < m_model->rowCount(sourceIndex); ++i)
       
  1559     {
       
  1560         QModelIndex idx = m_model->index(i, column, sourceIndex);
       
  1561         QVERIFY(idx.isValid());
       
  1562         indexList << idx;
       
  1563         parentsList << idx.parent();
       
  1564         persistentList << QPersistentModelIndex(idx);
       
  1565     }
       
  1566 
       
  1567     QModelIndex destIndex = m_model->index(5, 0);
       
  1568     for (int i= 0; i < m_model->rowCount(destIndex); ++i)
       
  1569     {
       
  1570         QModelIndex idx = m_model->index(i, column, destIndex);
       
  1571         QVERIFY(idx.isValid());
       
  1572         indexList << idx;
       
  1573         parentsList << idx.parent();
       
  1574         persistentList << QPersistentModelIndex(idx);
       
  1575     }
       
  1576 
       
  1577     QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1578     QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1579 
       
  1580     ModelMoveCommand *moveCommand;
       
  1581     QList<int> ancestors;
       
  1582     while (ancestors.size() < depth)
       
  1583     {
       
  1584         ancestors << 9;
       
  1585         for (int row = 0; row <= 9; row++)
       
  1586         {
       
  1587             moveCommand = new ModelMoveCommand(m_model, this);
       
  1588             moveCommand->setNumCols(4);
       
  1589             moveCommand->setStartRow(9);
       
  1590             moveCommand->setEndRow(9);
       
  1591             moveCommand->setDestAncestors(ancestors);
       
  1592             moveCommand->setDestRow(row);
       
  1593             moveCommand->doCommand();
       
  1594 
       
  1595             QVERIFY(beforeSpy.size() == 0);
       
  1596             QVERIFY(afterSpy.size() == 0);
       
  1597         }
       
  1598     }
       
  1599 }
       
  1600 
       
  1601 void tst_QAbstractItemModel::testMoveWithinOwnRange_data()
       
  1602 {
       
  1603     QTest::addColumn<int>("startRow");
       
  1604     QTest::addColumn<int>("endRow");
       
  1605     QTest::addColumn<int>("destRow");
       
  1606 
       
  1607     QTest::newRow("move01") << 0 << 0 << 0;
       
  1608     QTest::newRow("move02") << 0 << 0 << 1;
       
  1609     QTest::newRow("move03") << 0 << 5 << 0;
       
  1610     QTest::newRow("move04") << 0 << 5 << 1;
       
  1611     QTest::newRow("move05") << 0 << 5 << 2;
       
  1612     QTest::newRow("move06") << 0 << 5 << 3;
       
  1613     QTest::newRow("move07") << 0 << 5 << 4;
       
  1614     QTest::newRow("move08") << 0 << 5 << 5;
       
  1615     QTest::newRow("move09") << 0 << 5 << 6;
       
  1616     QTest::newRow("move08") << 3 << 5 << 5;
       
  1617     QTest::newRow("move08") << 3 << 5 << 6;
       
  1618     QTest::newRow("move09") << 4 << 5 << 5;
       
  1619     QTest::newRow("move10") << 4 << 5 << 6;
       
  1620     QTest::newRow("move11") << 5 << 5 << 5;
       
  1621     QTest::newRow("move12") << 5 << 5 << 6;
       
  1622     QTest::newRow("move13") << 5 << 9 << 9;
       
  1623     QTest::newRow("move14") << 5 << 9 << 10;
       
  1624     QTest::newRow("move15") << 6 << 9 << 9;
       
  1625     QTest::newRow("move16") << 6 << 9 << 10;
       
  1626     QTest::newRow("move17") << 7 << 9 << 9;
       
  1627     QTest::newRow("move18") << 7 << 9 << 10;
       
  1628     QTest::newRow("move19") << 8 << 9 << 9;
       
  1629     QTest::newRow("move20") << 8 << 9 << 10;
       
  1630     QTest::newRow("move21") << 9 << 9 << 9;
       
  1631     QTest::newRow("move22") << 0 << 9 << 10;
       
  1632 
       
  1633 }
       
  1634 
       
  1635 void tst_QAbstractItemModel::testMoveWithinOwnRange()
       
  1636 {
       
  1637 
       
  1638     QFETCH( int, startRow);
       
  1639     QFETCH( int, endRow);
       
  1640     QFETCH( int, destRow);
       
  1641 
       
  1642 
       
  1643     QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1644     QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
       
  1645 
       
  1646     ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
       
  1647     moveCommand->setNumCols(4);
       
  1648     moveCommand->setStartRow(startRow);
       
  1649     moveCommand->setEndRow(endRow);
       
  1650     moveCommand->setDestRow(destRow);
       
  1651     moveCommand->doCommand();
       
  1652 
       
  1653     QVERIFY(beforeSpy.size() == 0);
       
  1654     QVERIFY(afterSpy.size() == 0);
       
  1655 
       
  1656 
       
  1657 }
       
  1658 
       
  1659 class ListenerObject : public QObject
       
  1660 {
       
  1661   Q_OBJECT
       
  1662 public:
       
  1663     ListenerObject(QAbstractProxyModel *parent);
       
  1664 
       
  1665 protected:
       
  1666     void fillIndexStores(const QModelIndex &parent);
       
  1667 
       
  1668 public slots:
       
  1669     void slotAboutToBeReset();
       
  1670     void slotReset();
       
  1671 
       
  1672 private:
       
  1673     QAbstractProxyModel *m_model;
       
  1674     QList<QPersistentModelIndex> m_persistentIndexes;
       
  1675     QModelIndexList m_nonPersistentIndexes;
       
  1676 };
       
  1677 
       
  1678 
       
  1679 ListenerObject::ListenerObject(QAbstractProxyModel *parent)
       
  1680     : QObject(parent), m_model(parent)
       
  1681 {
       
  1682     connect(m_model, SIGNAL(modelAboutToBeReset()), SLOT(slotAboutToBeReset()));
       
  1683     connect(m_model, SIGNAL(modelReset()), SLOT(slotReset()));
       
  1684 
       
  1685     fillIndexStores(QModelIndex());
       
  1686 }
       
  1687 
       
  1688 void ListenerObject::fillIndexStores(const QModelIndex &parent)
       
  1689 {
       
  1690     const int column = 0;
       
  1691     int row = 0;
       
  1692     QModelIndex idx = m_model->index(row, column, parent);
       
  1693     while (idx.isValid())
       
  1694     {
       
  1695         m_persistentIndexes << QPersistentModelIndex(idx);
       
  1696         m_nonPersistentIndexes << idx;
       
  1697         if (m_model->hasChildren(idx))
       
  1698         {
       
  1699             fillIndexStores(idx);
       
  1700         }
       
  1701         ++row;
       
  1702         idx = m_model->index(row, column, parent);
       
  1703     }
       
  1704 }
       
  1705 
       
  1706 void ListenerObject::slotAboutToBeReset()
       
  1707 {
       
  1708     // Nothing has been changed yet. All indexes should be the same.
       
  1709     for (int i = 0; i < m_persistentIndexes.size(); ++i)
       
  1710     {
       
  1711         QModelIndex idx = m_persistentIndexes.at(i);
       
  1712         QVERIFY(idx == m_nonPersistentIndexes.at(i));
       
  1713         QVERIFY(m_model->mapToSource(idx).isValid());
       
  1714     }
       
  1715 }
       
  1716 
       
  1717 void ListenerObject::slotReset()
       
  1718 {
       
  1719     foreach(const QModelIndex &idx, m_persistentIndexes)
       
  1720     {
       
  1721         QVERIFY(!idx.isValid());
       
  1722     }
       
  1723 }
       
  1724 
       
  1725 
       
  1726 void tst_QAbstractItemModel::testReset()
       
  1727 {
       
  1728     QSignalSpy beforeResetSpy(m_model, SIGNAL(modelAboutToBeReset()));
       
  1729     QSignalSpy afterResetSpy(m_model, SIGNAL(modelReset()));
       
  1730 
       
  1731 
       
  1732     QSortFilterProxyModel *nullProxy = new QSortFilterProxyModel(this);
       
  1733     nullProxy->setSourceModel(m_model);
       
  1734 
       
  1735     // Makes sure the model and proxy are in a consistent state. before and after reset.
       
  1736     new ListenerObject(nullProxy);
       
  1737 
       
  1738     ModelResetCommandFixed *resetCommand = new ModelResetCommandFixed(m_model, this);
       
  1739 
       
  1740     resetCommand->setNumCols(4);
       
  1741     resetCommand->setStartRow(0);
       
  1742     resetCommand->setEndRow(0);
       
  1743     resetCommand->setDestRow(0);
       
  1744     resetCommand->setDestAncestors(QList<int>() << 5);
       
  1745     resetCommand->doCommand();
       
  1746 
       
  1747     // Verify that the correct signals were emitted
       
  1748     QVERIFY(beforeResetSpy.size() == 1);
       
  1749     QVERIFY(afterResetSpy.size() == 1);
       
  1750 
       
  1751     // Verify that the move actually happened.
       
  1752     QVERIFY(m_model->rowCount() == 9);
       
  1753     QModelIndex destIndex = m_model->index(4, 0);
       
  1754     QVERIFY(m_model->rowCount(destIndex) == 11);
       
  1755 
       
  1756 }
       
  1757 
       
  1758 
       
  1759 QTEST_MAIN(tst_QAbstractItemModel)
       
  1760 #include "tst_qabstractitemmodel.moc"