summaryrefslogtreecommitdiffstats
path: root/tests/auto/qabstractitemmodel
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2009-07-23 10:04:25 (GMT)
committerOlivier Goffart <ogoffart@trolltech.com>2009-08-26 14:26:12 (GMT)
commitfad842cebeab8cba78141edd10756a51885f448b (patch)
treea7712e07626199caf2d77e24fce12cfb1196ab1e /tests/auto/qabstractitemmodel
parent743117fa94b5e8807b0b9f9b16f2a712e6bfb47f (diff)
downloadQt-fad842cebeab8cba78141edd10756a51885f448b.zip
Qt-fad842cebeab8cba78141edd10756a51885f448b.tar.gz
Qt-fad842cebeab8cba78141edd10756a51885f448b.tar.bz2
Add move API to QAbstractItemModel.
This adds the function beginMoveRows, endMoveRows, beginMoveColumns, endMoveColumns Reviewed-by: Olivier Goffart <ogoffart@trolltech.com> Acknowledged-by: Thierry Merge-request: 972
Diffstat (limited to 'tests/auto/qabstractitemmodel')
-rw-r--r--tests/auto/qabstractitemmodel/dynamictreemodel.cpp245
-rw-r--r--tests/auto/qabstractitemmodel/dynamictreemodel.h141
-rw-r--r--tests/auto/qabstractitemmodel/qabstractitemmodel.pro5
-rw-r--r--tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp841
4 files changed, 1230 insertions, 2 deletions
diff --git a/tests/auto/qabstractitemmodel/dynamictreemodel.cpp b/tests/auto/qabstractitemmodel/dynamictreemodel.cpp
new file mode 100644
index 0000000..6c3e0cb
--- /dev/null
+++ b/tests/auto/qabstractitemmodel/dynamictreemodel.cpp
@@ -0,0 +1,245 @@
+/*
+ Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#include "dynamictreemodel.h"
+
+#include <QHash>
+#include <QList>
+#include <QTimer>
+
+#include <QDebug>
+
+#include <kdebug.h>
+
+DynamicTreeModel::DynamicTreeModel(QObject *parent)
+ : QAbstractItemModel(parent),
+ nextId(1)
+{
+}
+
+QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &parent) const
+{
+// if (column != 0)
+// return QModelIndex();
+
+
+ if ( column < 0 || row < 0 )
+ return QModelIndex();
+
+ QList<QList<qint64> > childIdColumns = m_childItems.value(parent.internalId());
+
+
+ if (childIdColumns.size() == 0)
+ return QModelIndex();
+
+ if (column >= childIdColumns.size())
+ return QModelIndex();
+
+ QList<qint64> rowIds = childIdColumns.at(column);
+
+ if ( row >= rowIds.size())
+ return QModelIndex();
+
+ qint64 id = rowIds.at(row);
+
+ return createIndex(row, column, reinterpret_cast<void *>(id));
+
+}
+
+qint64 DynamicTreeModel::findParentId(qint64 searchId) const
+{
+ if (searchId <= 0)
+ return -1;
+
+ QHashIterator<qint64, QList<QList<qint64> > > i(m_childItems);
+ while (i.hasNext())
+ {
+ i.next();
+ QListIterator<QList<qint64> > j(i.value());
+ while (j.hasNext())
+ {
+ QList<qint64> l = j.next();
+ if (l.contains(searchId))
+ {
+ return i.key();
+ }
+ }
+ }
+ return -1;
+}
+
+QModelIndex DynamicTreeModel::parent(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QModelIndex();
+
+ qint64 searchId = index.internalId();
+ qint64 parentId = findParentId(searchId);
+ // Will never happen for valid index, but what the hey...
+ if (parentId <= 0)
+ return QModelIndex();
+
+ qint64 grandParentId = findParentId(parentId);
+ if (grandParentId < 0)
+ grandParentId = 0;
+
+ int column = 0;
+ QList<qint64> childList = m_childItems.value(grandParentId).at(column);
+
+ int row = childList.indexOf(parentId);
+
+ return createIndex(row, column, reinterpret_cast<void *>(parentId));
+
+}
+
+int DynamicTreeModel::rowCount(const QModelIndex &index ) const
+{
+ QList<QList<qint64> > cols = m_childItems.value(index.internalId());
+
+ if (cols.size() == 0 )
+ return 0;
+
+ if (index.column() > 0)
+ return 0;
+
+ return cols.at(0).size();
+}
+
+int DynamicTreeModel::columnCount(const QModelIndex &index ) const
+{
+// Q_UNUSED(index);
+ return m_childItems.value(index.internalId()).size();
+}
+
+QVariant DynamicTreeModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid())
+ return QVariant();
+
+ if (Qt::DisplayRole == role)
+ {
+ return m_items.value(index.internalId());
+ }
+ return QVariant();
+}
+
+void DynamicTreeModel::clear()
+{
+ m_items.clear();
+ m_childItems.clear();
+ nextId = 1;
+ reset();
+}
+
+
+ModelChangeCommand::ModelChangeCommand( DynamicTreeModel *model, QObject *parent )
+ : QObject(parent), m_model(model), m_numCols(1), m_startRow(-1), m_endRow(-1)
+{
+
+}
+
+QModelIndex ModelChangeCommand::findIndex(QList<int> rows)
+{
+ const int col = 0;
+ QModelIndex parent = QModelIndex();
+ QListIterator<int> i(rows);
+ while (i.hasNext())
+ {
+ parent = m_model->index(i.next(), col, parent);
+ Q_ASSERT(parent.isValid());
+ }
+ return parent;
+}
+
+ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent )
+ : ModelChangeCommand(model, parent)
+{
+
+}
+
+void ModelInsertCommand::doCommand()
+{
+ QModelIndex parent = findIndex(m_rowNumbers);
+ m_model->beginInsertRows(parent, m_startRow, m_endRow);
+ qint64 parentId = parent.internalId();
+ for (int row = m_startRow; row <= m_endRow; row++)
+ {
+ for(int col = 0; col < m_numCols; col++ )
+ {
+ if (m_model->m_childItems[parentId].size() <= col)
+ {
+ m_model->m_childItems[parentId].append(QList<qint64>());
+ }
+// QString name = QUuid::createUuid().toString();
+ qint64 id = m_model->newId();
+ QString name = QString::number(id);
+
+ m_model->m_items.insert(id, name);
+ m_model->m_childItems[parentId][col].insert(row, id);
+
+ }
+ }
+ m_model->endInsertRows();
+}
+
+
+ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent)
+ : ModelChangeCommand(model, parent)
+{
+
+}
+
+void ModelMoveCommand::doCommand()
+{
+ QModelIndex srcParent = findIndex(m_rowNumbers);
+ QModelIndex destParent = findIndex(m_destRowNumbers);
+
+ if (!m_model->beginMoveRows(srcParent, m_startRow, m_endRow, destParent, m_destRow))
+ {
+ return;
+ }
+
+ for (int column = 0; column < m_numCols; ++column)
+ {
+ QList<qint64> l = m_model->m_childItems.value(srcParent.internalId())[column].mid(m_startRow, m_endRow - m_startRow + 1 );
+
+ for (int i = m_startRow; i <= m_endRow ; i++)
+ {
+ m_model->m_childItems[srcParent.internalId()][column].removeAt(m_startRow);
+ }
+ int d;
+ if (m_destRow < m_startRow)
+ d = m_destRow;
+ else
+ {
+ if (srcParent == destParent)
+ d = m_destRow - (m_endRow - m_startRow + 1);
+ else
+ d = m_destRow - (m_endRow - m_startRow) + 1;
+ }
+
+ foreach(const qint64 id, l)
+ {
+ m_model->m_childItems[destParent.internalId()][column].insert(d++, id);
+ }
+ }
+
+ m_model->endMoveRows();
+}
+
diff --git a/tests/auto/qabstractitemmodel/dynamictreemodel.h b/tests/auto/qabstractitemmodel/dynamictreemodel.h
new file mode 100644
index 0000000..88e293c
--- /dev/null
+++ b/tests/auto/qabstractitemmodel/dynamictreemodel.h
@@ -0,0 +1,141 @@
+/*
+ Copyright (c) 2009 Stephen Kelly <steveire@gmail.com>
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or (at your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
+*/
+
+#ifndef DYNAMICTREEMODEL_H
+#define DYNAMICTREEMODEL_H
+
+#include <QAbstractItemModel>
+
+#include <QHash>
+#include <QList>
+
+#include <QDebug>
+
+#include <kdebug.h>
+
+template<typename T> class QList;
+
+class DynamicTreeModel : public QAbstractItemModel
+{
+ Q_OBJECT
+
+public:
+ DynamicTreeModel(QObject *parent = 0);
+
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &index) const;
+ int rowCount(const QModelIndex &index = QModelIndex()) const;
+ int columnCount(const QModelIndex &index = QModelIndex()) const;
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+
+ void clear();
+
+protected slots:
+
+ /**
+ Finds the parent id of the string with id @p searchId.
+
+ Returns -1 if not found.
+ */
+ qint64 findParentId(qint64 searchId) const;
+
+private:
+ QHash<qint64, QString> m_items;
+ QHash<qint64, QList<QList<qint64> > > m_childItems;
+ qint64 nextId;
+ qint64 newId() { return nextId++; };
+
+ QModelIndex m_nextParentIndex;
+ int m_nextRow;
+
+ int m_depth;
+ int maxDepth;
+
+ friend class ModelInsertCommand;
+ friend class ModelMoveCommand;
+
+};
+
+
+class ModelChangeCommand : public QObject
+{
+ Q_OBJECT
+public:
+
+ ModelChangeCommand( DynamicTreeModel *model, QObject *parent = 0 );
+
+ virtual ~ModelChangeCommand() {}
+
+ void setAncestorRowNumbers(QList<int> rowNumbers) { m_rowNumbers = rowNumbers; }
+
+ QModelIndex findIndex(QList<int> rows);
+
+ void setStartRow(int row) { m_startRow = row; }
+
+ void setEndRow(int row) { m_endRow = row; }
+
+ void setNumCols(int cols) { m_numCols = cols; }
+
+ virtual void doCommand() = 0;
+
+protected:
+ DynamicTreeModel* m_model;
+ QList<int> m_rowNumbers;
+ int m_numCols;
+ int m_startRow;
+ int m_endRow;
+
+};
+
+typedef QList<ModelChangeCommand*> ModelChangeCommandList;
+
+class ModelInsertCommand : public ModelChangeCommand
+{
+ Q_OBJECT
+
+public:
+
+ ModelInsertCommand(DynamicTreeModel *model, QObject *parent = 0 );
+ virtual ~ModelInsertCommand() {}
+
+ virtual void doCommand();
+};
+
+class ModelMoveCommand : public ModelChangeCommand
+{
+ Q_OBJECT
+public:
+ ModelMoveCommand(DynamicTreeModel *model, QObject *parent);
+
+ virtual ~ModelMoveCommand() {}
+
+ virtual void doCommand();
+
+ void setDestAncestors( QList<int> rows ) { m_destRowNumbers = rows; }
+
+ void setDestRow(int row) { m_destRow = row; }
+
+protected:
+ QList<int> m_destRowNumbers;
+ int m_destRow;
+};
+
+
+#endif
diff --git a/tests/auto/qabstractitemmodel/qabstractitemmodel.pro b/tests/auto/qabstractitemmodel/qabstractitemmodel.pro
index 5ad1020..84ed5a2 100644
--- a/tests/auto/qabstractitemmodel/qabstractitemmodel.pro
+++ b/tests/auto/qabstractitemmodel/qabstractitemmodel.pro
@@ -1,3 +1,6 @@
load(qttest_p4)
-SOURCES += tst_qabstractitemmodel.cpp
+SOURCES += tst_qabstractitemmodel.cpp dynamictreemodel.cpp
+HEADERS += dynamictreemodel.h
+
QT = core
+
diff --git a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp
index e99ce06..9c83474 100644
--- a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp
+++ b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp
@@ -46,6 +46,10 @@
//TESTED_CLASS=QAbstractListModel QAbstractTableModel
//TESTED_FILES=
+#include "dynamictreemodel.h"
+
+Q_DECLARE_METATYPE(QModelIndex)
+
/*!
Note that this doesn't test models, but any functionality that QAbstractItemModel shoudl provide
*/
@@ -86,6 +90,30 @@ private slots:
void complexChangesWithPersistent();
+ void testMoveSameParentUp_data();
+ void testMoveSameParentUp();
+
+ void testMoveSameParentDown_data();
+ void testMoveSameParentDown();
+
+ void testMoveToGrandParent_data();
+ void testMoveToGrandParent();
+
+ void testMoveToSibling_data();
+ void testMoveToSibling();
+
+ void testMoveToUncle_data();
+ void testMoveToUncle();
+
+ void testMoveToDescendants();
+
+ void testMoveWithinOwnRange_data();
+ void testMoveWithinOwnRange();
+
+
+private:
+ DynamicTreeModel *m_model;
+
};
/*!
@@ -242,7 +270,20 @@ void tst_QAbstractItemModel::cleanupTestCase()
void tst_QAbstractItemModel::init()
{
-
+ m_model = new DynamicTreeModel(this);
+
+ ModelInsertCommand *insertCommand = new ModelInsertCommand(m_model, this);
+ insertCommand->setNumCols(4);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(9);
+ insertCommand->doCommand();
+
+ insertCommand = new ModelInsertCommand(m_model, this);
+ insertCommand->setAncestorRowNumbers(QList<int>() << 5);
+ insertCommand->setNumCols(4);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(9);
+ insertCommand->doCommand();
}
void tst_QAbstractItemModel::cleanup()
@@ -815,5 +856,803 @@ void tst_QAbstractItemModel::complexChangesWithPersistent()
}
+void tst_QAbstractItemModel::testMoveSameParentDown_data()
+{
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("endRow");
+ QTest::addColumn<int>("destRow");
+
+ // Move from the start to the middle
+ QTest::newRow("move01") << 0 << 2 << 8;
+ // Move from the start to the end
+ QTest::newRow("move02") << 0 << 2 << 10;
+ // Move from the middle to the middle
+ QTest::newRow("move03") << 3 << 5 << 8;
+ // Move from the middle to the end
+ QTest::newRow("move04") << 3 << 5 << 10;
+}
+
+void tst_QAbstractItemModel::testMoveSameParentDown()
+{
+ QFETCH( int, startRow);
+ QFETCH( int, endRow);
+ QFETCH( int, destRow);
+
+ QList<QPersistentModelIndex> persistentList;
+ QModelIndexList indexList;
+
+ for (int column = 0; column < m_model->columnCount(); ++column)
+ {
+ for (int row= 0; row < m_model->rowCount(); ++row)
+ {
+ QModelIndex idx = m_model->index(row, column);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ persistentList << QPersistentModelIndex(idx);
+ }
+ }
+
+ QModelIndex parent = m_model->index(5, 0);
+ for (int column = 0; column < m_model->columnCount(); ++column)
+ {
+ for (int row= 0; row < m_model->rowCount(parent); ++row)
+ {
+ QModelIndex idx = m_model->index(row, column, parent);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ persistentList << QPersistentModelIndex(idx);
+ }
+ }
+
+ QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+
+ ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
+ moveCommand->setNumCols(4);
+ moveCommand->setStartRow(startRow);
+ moveCommand->setEndRow(endRow);
+ moveCommand->setDestRow(destRow);
+ moveCommand->doCommand();
+
+ QVariantList beforeSignal = beforeSpy.takeAt(0);
+ QVariantList afterSignal = afterSpy.takeAt(0);
+
+ QCOMPARE(beforeSignal.size(), 5);
+ QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(beforeSignal.at(1).toInt(), startRow);
+ QCOMPARE(beforeSignal.at(2).toInt(), endRow);
+ QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(beforeSignal.at(4).toInt(), destRow);
+
+ QCOMPARE(afterSignal.size(), 5);
+ QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(afterSignal.at(1).toInt(), startRow);
+ QCOMPARE(afterSignal.at(2).toInt(), endRow);
+ QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(afterSignal.at(4).toInt(), destRow);
+
+ for (int i = 0; i < indexList.size(); i++)
+ {
+ QModelIndex idx = indexList.at(i);
+ QModelIndex persistentIndex = persistentList.at(i);
+ if (idx.parent() == QModelIndex())
+ {
+ int row = idx.row();
+ if ( row >= startRow)
+ {
+ if (row <= endRow)
+ {
+ QCOMPARE(row + destRow - endRow - 1, persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(idx.parent(), persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+ } else if ( row < destRow)
+ {
+ QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(idx.parent(), persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+ } else
+ {
+ QCOMPARE(idx, persistentIndex);
+ }
+ } else
+ {
+ QCOMPARE(idx, persistentIndex);
+ }
+ } else
+ {
+ QCOMPARE(idx, persistentIndex);
+ }
+ }
+}
+
+void tst_QAbstractItemModel::testMoveSameParentUp_data()
+{
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("endRow");
+ QTest::addColumn<int>("destRow");
+
+ // Move from the middle to the start
+ QTest::newRow("move01") << 5 << 7 << 0;
+ // Move from the end to the start
+ QTest::newRow("move02") << 8 << 9 << 0;
+ // Move from the middle to the middle
+ QTest::newRow("move03") << 5 << 7 << 2;
+ // Move from the end to the middle
+ QTest::newRow("move04") << 8 << 9 << 5;
+}
+
+void tst_QAbstractItemModel::testMoveSameParentUp()
+{
+
+ QFETCH( int, startRow);
+ QFETCH( int, endRow);
+ QFETCH( int, destRow);
+
+ QList<QPersistentModelIndex> persistentList;
+ QModelIndexList indexList;
+
+ for (int column = 0; column < m_model->columnCount(); ++column)
+ {
+ for (int row= 0; row < m_model->rowCount(); ++row)
+ {
+ QModelIndex idx = m_model->index(row, column);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ persistentList << QPersistentModelIndex(idx);
+ }
+ }
+
+ QModelIndex parent = m_model->index(2, 0);
+ for (int column = 0; column < m_model->columnCount(); ++column)
+ {
+ for (int row= 0; row < m_model->rowCount(parent); ++row)
+ {
+ QModelIndex idx = m_model->index(row, column, parent);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ persistentList << QPersistentModelIndex(idx);
+ }
+ }
+
+ QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+
+
+ ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
+ moveCommand->setNumCols(4);
+ moveCommand->setStartRow(startRow);
+ moveCommand->setEndRow(endRow);
+ moveCommand->setDestRow(destRow);
+ moveCommand->doCommand();
+
+ QVariantList beforeSignal = beforeSpy.takeAt(0);
+ QVariantList afterSignal = afterSpy.takeAt(0);
+
+ QCOMPARE(beforeSignal.size(), 5);
+ QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(beforeSignal.at(1).toInt(), startRow);
+ QCOMPARE(beforeSignal.at(2).toInt(), endRow);
+ QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(beforeSignal.at(4).toInt(), destRow);
+
+ QCOMPARE(afterSignal.size(), 5);
+ QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(afterSignal.at(1).toInt(), startRow);
+ QCOMPARE(afterSignal.at(2).toInt(), endRow);
+ QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(afterSignal.at(4).toInt(), destRow);
+
+
+ for (int i = 0; i < indexList.size(); i++)
+ {
+ QModelIndex idx = indexList.at(i);
+ QModelIndex persistentIndex = persistentList.at(i);
+ if (idx.parent() == QModelIndex())
+ {
+ int row = idx.row();
+ if ( row >= destRow)
+ {
+ if (row < startRow)
+ {
+ QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(idx.parent(), persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+ } else if ( row <= endRow)
+ {
+ QCOMPARE(row + destRow - startRow, persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(idx.parent(), persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+ } else
+ {
+ QCOMPARE(idx, persistentIndex);
+ }
+ } else
+ {
+ QCOMPARE(idx, persistentIndex);
+ }
+ } else
+ {
+ QCOMPARE(idx, persistentIndex);
+ }
+ }
+}
+
+void tst_QAbstractItemModel::testMoveToGrandParent_data()
+{
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("endRow");
+ QTest::addColumn<int>("destRow");
+
+ // Move from the start to the middle
+ QTest::newRow("move01") << 0 << 2 << 8;
+ // Move from the start to the end
+ QTest::newRow("move02") << 0 << 2 << 10;
+ // Move from the middle to the middle
+ QTest::newRow("move03") << 3 << 5 << 8;
+ // Move from the middle to the end
+ QTest::newRow("move04") << 3 << 5 << 10;
+
+ // Move from the middle to the start
+ QTest::newRow("move05") << 5 << 7 << 0;
+ // Move from the end to the start
+ QTest::newRow("move06") << 8 << 9 << 0;
+ // Move from the middle to the middle
+ QTest::newRow("move07") << 5 << 7 << 2;
+ // Move from the end to the middle
+ QTest::newRow("move08") << 8 << 9 << 5;
+
+ // Moving to the same row in a different parent doesn't confuse things.
+ QTest::newRow("move09") << 8 << 8 << 8;
+
+ // Moving to the row of my parent and its neighbours doesn't confuse things
+ QTest::newRow("move09") << 8 << 8 << 4;
+ QTest::newRow("move10") << 8 << 8 << 5;
+ QTest::newRow("move11") << 8 << 8 << 6;
+
+ // Moving everything from one parent to another
+ QTest::newRow("move12") << 0 << 9 << 10;
+}
+
+void tst_QAbstractItemModel::testMoveToGrandParent()
+{
+
+ QFETCH( int, startRow);
+ QFETCH( int, endRow);
+ QFETCH( int, destRow);
+
+ QList<QPersistentModelIndex> persistentList;
+ QModelIndexList indexList;
+ QModelIndexList parentsList;
+
+ for (int column = 0; column < m_model->columnCount(); ++column)
+ {
+ for (int row= 0; row < m_model->rowCount(); ++row)
+ {
+ QModelIndex idx = m_model->index(row, column);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ parentsList << idx.parent();
+ persistentList << QPersistentModelIndex(idx);
+ }
+ }
+
+ QModelIndex sourceIndex = m_model->index(5, 0);
+ for (int column = 0; column < m_model->columnCount(); ++column)
+ {
+ for (int row= 0; row < m_model->rowCount(sourceIndex); ++row)
+ {
+ QModelIndex idx = m_model->index(row, column, sourceIndex);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ parentsList << idx.parent();
+ persistentList << QPersistentModelIndex(idx);
+ }
+ }
+
+ QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+
+
+ ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
+ moveCommand->setAncestorRowNumbers(QList<int>() << 5);
+ moveCommand->setNumCols(4);
+ moveCommand->setStartRow(startRow);
+ moveCommand->setEndRow(endRow);
+ moveCommand->setDestRow(destRow);
+ moveCommand->doCommand();
+
+ QVariantList beforeSignal = beforeSpy.takeAt(0);
+ QVariantList afterSignal = afterSpy.takeAt(0);
+
+ QCOMPARE(beforeSignal.size(), 5);
+ QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), sourceIndex);
+ QCOMPARE(beforeSignal.at(1).toInt(), startRow);
+ QCOMPARE(beforeSignal.at(2).toInt(), endRow);
+ QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(beforeSignal.at(4).toInt(), destRow);
+
+ QCOMPARE(afterSignal.size(), 5);
+ QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex);
+ QCOMPARE(afterSignal.at(1).toInt(), startRow);
+ QCOMPARE(afterSignal.at(2).toInt(), endRow);
+ QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex());
+ QCOMPARE(afterSignal.at(4).toInt(), destRow);
+
+ for (int i = 0; i < indexList.size(); i++)
+ {
+ QModelIndex idx = indexList.at(i);
+ QModelIndex idxParent = parentsList.at(i);
+ QModelIndex persistentIndex = persistentList.at(i);
+ int row = idx.row();
+ if (idxParent == QModelIndex())
+ {
+ if ( row >= destRow)
+ {
+ QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(idxParent, persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+ } else
+ {
+ QCOMPARE(idx, persistentIndex);
+ }
+ } else
+ {
+ if (row < startRow)
+ {
+ QCOMPARE(idx, persistentIndex);
+ } else if (row <= endRow)
+ {
+ QCOMPARE(row + destRow - startRow, persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(QModelIndex(), persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+ } else {
+ QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+
+ if (idxParent.row() >= destRow)
+ {
+ QModelIndex adjustedParent;
+ adjustedParent = idxParent.sibling( idxParent.row() + endRow - startRow + 1, idxParent.column());
+ QCOMPARE(adjustedParent, persistentIndex.parent());
+ } else
+ {
+ QCOMPARE(idxParent, persistentIndex.parent());
+ }
+ QCOMPARE(idx.model(), persistentIndex.model());
+ }
+ }
+ }
+}
+
+void tst_QAbstractItemModel::testMoveToSibling_data()
+{
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("endRow");
+ QTest::addColumn<int>("destRow");
+
+ // Move from the start to the middle
+ QTest::newRow("move01") << 0 << 2 << 8;
+ // Move from the start to the end
+ QTest::newRow("move02") << 0 << 2 << 10;
+ // Move from the middle to the middle
+ QTest::newRow("move03") << 2 << 4 << 8;
+ // Move from the middle to the end
+ QTest::newRow("move04") << 2 << 4 << 10;
+
+ // Move from the middle to the start
+ QTest::newRow("move05") << 8 << 8 << 0;
+ // Move from the end to the start
+ QTest::newRow("move06") << 8 << 9 << 0;
+ // Move from the middle to the middle
+ QTest::newRow("move07") << 6 << 8 << 2;
+ // Move from the end to the middle
+ QTest::newRow("move08") << 8 << 9 << 5;
+
+ // Moving to the same row in a different parent doesn't confuse things.
+ QTest::newRow("move09") << 8 << 8 << 8;
+
+ // Moving to the row of my target and its neighbours doesn't confuse things
+ QTest::newRow("move09") << 8 << 8 << 4;
+ QTest::newRow("move10") << 8 << 8 << 5;
+ QTest::newRow("move11") << 8 << 8 << 6;
+}
+
+void tst_QAbstractItemModel::testMoveToSibling()
+{
+
+ QFETCH( int, startRow);
+ QFETCH( int, endRow);
+ QFETCH( int, destRow);
+
+ QList<QPersistentModelIndex> persistentList;
+ QModelIndexList indexList;
+ QModelIndexList parentsList;
+
+ const int column = 0;
+
+ for (int i= 0; i < m_model->rowCount(); ++i)
+ {
+ QModelIndex idx = m_model->index(i, column);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ parentsList << idx.parent();
+ persistentList << QPersistentModelIndex(idx);
+ }
+
+ QModelIndex destIndex = m_model->index(5, 0);
+ QModelIndex sourceIndex;
+ for (int i= 0; i < m_model->rowCount(destIndex); ++i)
+ {
+ QModelIndex idx = m_model->index(i, column, destIndex);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ parentsList << idx.parent();
+ persistentList << QPersistentModelIndex(idx);
+ }
+
+ QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+
+
+ ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
+ moveCommand->setNumCols(4);
+ moveCommand->setStartRow(startRow);
+ moveCommand->setEndRow(endRow);
+ moveCommand->setDestAncestors(QList<int>() << 5);
+ moveCommand->setDestRow(destRow);
+ moveCommand->doCommand();
+
+ QVariantList beforeSignal = beforeSpy.takeAt(0);
+ QVariantList afterSignal = afterSpy.takeAt(0);
+
+ QCOMPARE(beforeSignal.size(), 5);
+ QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), sourceIndex);
+ QCOMPARE(beforeSignal.at(1).toInt(), startRow);
+ QCOMPARE(beforeSignal.at(2).toInt(), endRow);
+ QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), destIndex);
+ QCOMPARE(beforeSignal.at(4).toInt(), destRow);
+
+ QCOMPARE(afterSignal.size(), 5);
+ QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex);
+ QCOMPARE(afterSignal.at(1).toInt(), startRow);
+ QCOMPARE(afterSignal.at(2).toInt(), endRow);
+ QCOMPARE(afterSignal.at(3).value<QModelIndex>(), destIndex);
+ QCOMPARE(afterSignal.at(4).toInt(), destRow);
+
+ for (int i = 0; i < indexList.size(); i++)
+ {
+ QModelIndex idx = indexList.at(i);
+ QModelIndex idxParent = parentsList.at(i);
+ QModelIndex persistentIndex = persistentList.at(i);
+
+ QModelIndex adjustedDestination = destIndex.sibling(destIndex.row() - (endRow - startRow + 1), destIndex.column());
+ int row = idx.row();
+ if (idxParent == destIndex)
+ {
+ if ( row >= destRow)
+ {
+ QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ if (idxParent.row() > startRow)
+ {
+ QCOMPARE(adjustedDestination, persistentIndex.parent());
+ } else {
+ QCOMPARE(destIndex, persistentIndex.parent());
+ }
+ QCOMPARE(idx.model(), persistentIndex.model());
+ } else
+ {
+ QCOMPARE(idx, persistentIndex);
+ }
+ } else
+ {
+ if (row < startRow)
+ {
+ QCOMPARE(idx, persistentIndex);
+ } else if (row <= endRow)
+ {
+ QCOMPARE(row + destRow - startRow, persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ if (destIndex.row() > startRow)
+ {
+ QCOMPARE(adjustedDestination, persistentIndex.parent());
+ } else {
+ QCOMPARE(destIndex, persistentIndex.parent());
+ }
+
+ QCOMPARE(idx.model(), persistentIndex.model());
+
+ } else {
+ QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(idxParent, persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+ }
+ }
+ }
+}
+
+void tst_QAbstractItemModel::testMoveToUncle_data()
+{
+
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("endRow");
+ QTest::addColumn<int>("destRow");
+
+ // Move from the start to the middle
+ QTest::newRow("move01") << 0 << 2 << 8;
+ // Move from the start to the end
+ QTest::newRow("move02") << 0 << 2 << 10;
+ // Move from the middle to the middle
+ QTest::newRow("move03") << 3 << 5 << 8;
+ // Move from the middle to the end
+ QTest::newRow("move04") << 3 << 5 << 10;
+
+ // Move from the middle to the start
+ QTest::newRow("move05") << 5 << 7 << 0;
+ // Move from the end to the start
+ QTest::newRow("move06") << 8 << 9 << 0;
+ // Move from the middle to the middle
+ QTest::newRow("move07") << 5 << 7 << 2;
+ // Move from the end to the middle
+ QTest::newRow("move08") << 8 << 9 << 5;
+
+ // Moving to the same row in a different parent doesn't confuse things.
+ QTest::newRow("move09") << 8 << 8 << 8;
+
+ // Moving to the row of my parent and its neighbours doesn't confuse things
+ QTest::newRow("move09") << 8 << 8 << 4;
+ QTest::newRow("move10") << 8 << 8 << 5;
+ QTest::newRow("move11") << 8 << 8 << 6;
+
+ // Moving everything from one parent to another
+ QTest::newRow("move12") << 0 << 9 << 10;
+}
+
+void tst_QAbstractItemModel::testMoveToUncle()
+{
+ // Need to have some extra rows available.
+ ModelInsertCommand *insertCommand = new ModelInsertCommand(m_model, this);
+ insertCommand->setAncestorRowNumbers(QList<int>() << 9);
+ insertCommand->setNumCols(4);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(9);
+ insertCommand->doCommand();
+
+ QFETCH( int, startRow);
+ QFETCH( int, endRow);
+ QFETCH( int, destRow);
+
+ QList<QPersistentModelIndex> persistentList;
+ QModelIndexList indexList;
+ QModelIndexList parentsList;
+
+ const int column = 0;
+
+ QModelIndex sourceIndex = m_model->index(9, 0);
+ for (int i= 0; i < m_model->rowCount(sourceIndex); ++i)
+ {
+ QModelIndex idx = m_model->index(i, column, sourceIndex);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ parentsList << idx.parent();
+ persistentList << QPersistentModelIndex(idx);
+ }
+
+ QModelIndex destIndex = m_model->index(5, 0);
+ for (int i= 0; i < m_model->rowCount(destIndex); ++i)
+ {
+ QModelIndex idx = m_model->index(i, column, destIndex);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ parentsList << idx.parent();
+ persistentList << QPersistentModelIndex(idx);
+ }
+
+ QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+
+ ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
+ moveCommand->setAncestorRowNumbers(QList<int>() << 9);
+ moveCommand->setNumCols(4);
+ moveCommand->setStartRow(startRow);
+ moveCommand->setEndRow(endRow);
+ moveCommand->setDestAncestors(QList<int>() << 5);
+ moveCommand->setDestRow(destRow);
+ moveCommand->doCommand();
+
+ QVariantList beforeSignal = beforeSpy.takeAt(0);
+ QVariantList afterSignal = afterSpy.takeAt(0);
+
+ QCOMPARE(beforeSignal.size(), 5);
+ QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), sourceIndex);
+ QCOMPARE(beforeSignal.at(1).toInt(), startRow);
+ QCOMPARE(beforeSignal.at(2).toInt(), endRow);
+ QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), destIndex);
+ QCOMPARE(beforeSignal.at(4).toInt(), destRow);
+
+ QCOMPARE(afterSignal.size(), 5);
+ QCOMPARE(afterSignal.at(0).value<QModelIndex>(), sourceIndex);
+ QCOMPARE(afterSignal.at(1).toInt(), startRow);
+ QCOMPARE(afterSignal.at(2).toInt(), endRow);
+ QCOMPARE(afterSignal.at(3).value<QModelIndex>(), destIndex);
+ QCOMPARE(afterSignal.at(4).toInt(), destRow);
+
+ for (int i = 0; i < indexList.size(); i++)
+ {
+ QModelIndex idx = indexList.at(i);
+ QModelIndex idxParent = parentsList.at(i);
+ QModelIndex persistentIndex = persistentList.at(i);
+
+ int row = idx.row();
+ if (idxParent == destIndex)
+ {
+ if ( row >= destRow)
+ {
+ QCOMPARE(row + endRow - startRow + 1, persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(destIndex, persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+ } else
+ {
+ QCOMPARE(idx, persistentIndex);
+ }
+ } else
+ {
+ if (row < startRow)
+ {
+ QCOMPARE(idx, persistentIndex);
+ } else if (row <= endRow)
+ {
+ QCOMPARE(row + destRow - startRow, persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(destIndex, persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+
+ } else {
+ QCOMPARE(row - (endRow - startRow + 1), persistentIndex.row() );
+ QCOMPARE(idx.column(), persistentIndex.column());
+ QCOMPARE(idxParent, persistentIndex.parent());
+ QCOMPARE(idx.model(), persistentIndex.model());
+ }
+ }
+ }
+}
+
+void tst_QAbstractItemModel::testMoveToDescendants()
+{
+ // Attempt to move a row to its ancestors depth rows deep.
+ const int depth = 6;
+
+ // Need to have some extra rows available in a tree.
+ QList<int> rows;
+ ModelInsertCommand *insertCommand;
+ for (int i = 0; i < depth; i++)
+ {
+ insertCommand = new ModelInsertCommand(m_model, this);
+ insertCommand->setAncestorRowNumbers(rows);
+ insertCommand->setNumCols(4);
+ insertCommand->setStartRow(0);
+ insertCommand->setEndRow(9);
+ insertCommand->doCommand();
+ rows << 9;
+ }
+
+ QList<QPersistentModelIndex> persistentList;
+ QModelIndexList indexList;
+ QModelIndexList parentsList;
+
+ const int column = 0;
+
+ QModelIndex sourceIndex = m_model->index(9, 0);
+ for (int i= 0; i < m_model->rowCount(sourceIndex); ++i)
+ {
+ QModelIndex idx = m_model->index(i, column, sourceIndex);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ parentsList << idx.parent();
+ persistentList << QPersistentModelIndex(idx);
+ }
+
+ QModelIndex destIndex = m_model->index(5, 0);
+ for (int i= 0; i < m_model->rowCount(destIndex); ++i)
+ {
+ QModelIndex idx = m_model->index(i, column, destIndex);
+ QVERIFY(idx.isValid());
+ indexList << idx;
+ parentsList << idx.parent();
+ persistentList << QPersistentModelIndex(idx);
+ }
+
+ QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+
+ ModelMoveCommand *moveCommand;
+ QList<int> ancestors;
+ while (ancestors.size() < depth)
+ {
+ ancestors << 9;
+ for (int row = 0; row <= 9; row++)
+ {
+ moveCommand = new ModelMoveCommand(m_model, this);
+ moveCommand->setNumCols(4);
+ moveCommand->setStartRow(9);
+ moveCommand->setEndRow(9);
+ moveCommand->setDestAncestors(ancestors);
+ moveCommand->setDestRow(row);
+ moveCommand->doCommand();
+
+ QVERIFY(beforeSpy.size() == 0);
+ QVERIFY(afterSpy.size() == 0);
+ }
+ }
+}
+
+void tst_QAbstractItemModel::testMoveWithinOwnRange_data()
+{
+ QTest::addColumn<int>("startRow");
+ QTest::addColumn<int>("endRow");
+ QTest::addColumn<int>("destRow");
+
+ QTest::newRow("move01") << 0 << 0 << 0;
+ QTest::newRow("move02") << 0 << 0 << 1;
+ QTest::newRow("move03") << 0 << 5 << 0;
+ QTest::newRow("move04") << 0 << 5 << 1;
+ QTest::newRow("move05") << 0 << 5 << 2;
+ QTest::newRow("move06") << 0 << 5 << 3;
+ QTest::newRow("move07") << 0 << 5 << 4;
+ QTest::newRow("move08") << 0 << 5 << 5;
+ QTest::newRow("move09") << 0 << 5 << 6;
+ QTest::newRow("move08") << 3 << 5 << 5;
+ QTest::newRow("move08") << 3 << 5 << 6;
+ QTest::newRow("move09") << 4 << 5 << 5;
+ QTest::newRow("move10") << 4 << 5 << 6;
+ QTest::newRow("move11") << 5 << 5 << 5;
+ QTest::newRow("move12") << 5 << 5 << 6;
+ QTest::newRow("move13") << 5 << 9 << 9;
+ QTest::newRow("move14") << 5 << 9 << 10;
+ QTest::newRow("move15") << 6 << 9 << 9;
+ QTest::newRow("move16") << 6 << 9 << 10;
+ QTest::newRow("move17") << 7 << 9 << 9;
+ QTest::newRow("move18") << 7 << 9 << 10;
+ QTest::newRow("move19") << 8 << 9 << 9;
+ QTest::newRow("move20") << 8 << 9 << 10;
+ QTest::newRow("move21") << 9 << 9 << 9;
+ QTest::newRow("move22") << 0 << 9 << 10;
+
+}
+
+void tst_QAbstractItemModel::testMoveWithinOwnRange()
+{
+
+ QFETCH( int, startRow);
+ QFETCH( int, endRow);
+ QFETCH( int, destRow);
+
+
+ QSignalSpy beforeSpy(m_model, SIGNAL(rowsAboutToBeMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+ QSignalSpy afterSpy(m_model, SIGNAL(rowsMoved(const QModelIndex &, int, int, const QModelIndex &, int)));
+
+ ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this);
+ moveCommand->setNumCols(4);
+ moveCommand->setStartRow(startRow);
+ moveCommand->setEndRow(endRow);
+ moveCommand->setDestRow(destRow);
+ moveCommand->doCommand();
+
+ QVERIFY(beforeSpy.size() == 0);
+ QVERIFY(afterSpy.size() == 0);
+
+
+}
+
+
+
QTEST_MAIN(tst_QAbstractItemModel)
#include "tst_qabstractitemmodel.moc"