diff options
author | Stephen Kelly <steveire@gmail.com> | 2009-07-31 11:00:40 (GMT) |
---|---|---|
committer | Olivier Goffart <ogoffart@trolltech.com> | 2009-08-28 09:34:24 (GMT) |
commit | 4d197ec0eaeae61499d8ee6dc0e98147800f583e (patch) | |
tree | 606dd9392cc8e3bab799c38b118fc0f2c761a30f /tests/auto | |
parent | 7091ec8cd1ec94fb889230d69fc70d40a9f69b2d (diff) | |
download | Qt-4d197ec0eaeae61499d8ee6dc0e98147800f583e.zip Qt-4d197ec0eaeae61499d8ee6dc0e98147800f583e.tar.gz Qt-4d197ec0eaeae61499d8ee6dc0e98147800f583e.tar.bz2 |
Fix the API for resetting QAbstractItemModels.
This commit deprecates the QAIM::reset() method, and adds beginResetModel()
and endResetModel() methods, addressing Qt issue 247023.
http://www.qtsoftware.com/developer/task-tracker/index_html?method=entry&id=247023
If models and proxies use QAIM::reset() alone, then proxies will
emit modelAboutToBeReset after its source model is reset. This means that mapToSource
will not behave as expected (Will always return an invalid index) in a slot connected
to modelAboutToBeReset.
The usecase for this is maintaining viewstate (which items are selected, expanded)
when the model is reset. See BrowserWidget::modelChanged here:
http://websvn.kde.org/trunk/KDE/kdepim/akonadi/akonadiconsole/browserwidget.cpp?view=markup
Task-number: 247023
Reviewed-by: Olivier Goffart <ogoffart@trolltech.com>
Merge-request: 1072
Diffstat (limited to 'tests/auto')
-rw-r--r-- | tests/auto/qabstractitemmodel/dynamictreemodel.cpp | 118 | ||||
-rw-r--r-- | tests/auto/qabstractitemmodel/dynamictreemodel.h | 39 | ||||
-rw-r--r-- | tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp | 106 |
3 files changed, 234 insertions, 29 deletions
diff --git a/tests/auto/qabstractitemmodel/dynamictreemodel.cpp b/tests/auto/qabstractitemmodel/dynamictreemodel.cpp index 6c3e0cb..374b7db 100644 --- a/tests/auto/qabstractitemmodel/dynamictreemodel.cpp +++ b/tests/auto/qabstractitemmodel/dynamictreemodel.cpp @@ -204,42 +204,106 @@ ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent) { } +bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) +{ + return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow); +} 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 ); + QModelIndex srcParent = findIndex(m_rowNumbers); + QModelIndex destParent = findIndex(m_destRowNumbers); - for (int i = m_startRow; i <= m_endRow ; i++) + if (!emitPreSignal(srcParent, m_startRow, m_endRow, destParent, m_destRow)) { - 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; + return; } - foreach(const qint64 id, l) + for (int column = 0; column < m_numCols; ++column) { - m_model->m_childItems[destParent.internalId()][column].insert(d++, id); + 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(); + emitPostSignal(); +} + +void ModelMoveCommand::emitPostSignal() +{ + m_model->endMoveRows(); +} + +ModelResetCommand::ModelResetCommand(DynamicTreeModel* model, QObject* parent) + : ModelMoveCommand(model, parent) +{ + +} + +ModelResetCommand::~ModelResetCommand() +{ + +} + +bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) +{ + Q_UNUSED(srcParent); + Q_UNUSED(srcStart); + Q_UNUSED(srcEnd); + Q_UNUSED(destParent); + Q_UNUSED(destRow); + + return true; +} + +void ModelResetCommand::emitPostSignal() +{ + m_model->reset(); +} + +ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent) + : ModelMoveCommand(model, parent) +{ + +} + +ModelResetCommandFixed::~ModelResetCommandFixed() +{ + +} + +bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow) +{ + Q_UNUSED(srcParent); + Q_UNUSED(srcStart); + Q_UNUSED(srcEnd); + Q_UNUSED(destParent); + Q_UNUSED(destRow); + + m_model->beginResetModel(); + return true; +} + +void ModelResetCommandFixed::emitPostSignal() +{ + m_model->endResetModel(); } diff --git a/tests/auto/qabstractitemmodel/dynamictreemodel.h b/tests/auto/qabstractitemmodel/dynamictreemodel.h index 88e293c..c19ed9d 100644 --- a/tests/auto/qabstractitemmodel/dynamictreemodel.h +++ b/tests/auto/qabstractitemmodel/dynamictreemodel.h @@ -70,6 +70,8 @@ private: friend class ModelInsertCommand; friend class ModelMoveCommand; + friend class ModelResetCommand; + friend class ModelResetCommandFixed; }; @@ -118,6 +120,7 @@ public: virtual void doCommand(); }; + class ModelMoveCommand : public ModelChangeCommand { Q_OBJECT @@ -126,8 +129,12 @@ public: virtual ~ModelMoveCommand() {} + virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); + virtual void doCommand(); + virtual void emitPostSignal(); + void setDestAncestors( QList<int> rows ) { m_destRowNumbers = rows; } void setDestRow(int row) { m_destRow = row; } @@ -137,5 +144,37 @@ protected: int m_destRow; }; +/** + A command which does a move and emits a reset signal. +*/ +class ModelResetCommand : public ModelMoveCommand +{ + Q_OBJECT +public: + ModelResetCommand(DynamicTreeModel* model, QObject* parent = 0); + + virtual ~ModelResetCommand(); + + virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); + virtual void emitPostSignal(); + +}; + +/** + A command which does a move and emits a beginResetModel and endResetModel signals. +*/ +class ModelResetCommandFixed : public ModelMoveCommand +{ + Q_OBJECT +public: + ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent = 0); + + virtual ~ModelResetCommandFixed(); + + virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow); + virtual void emitPostSignal(); + +}; + #endif diff --git a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp index 9c83474..61eeae7 100644 --- a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp +++ b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp @@ -43,6 +43,8 @@ #include <QtTest/QtTest> #include <QtCore/QtCore> +#include <QSortFilterProxyModel> + //TESTED_CLASS=QAbstractListModel QAbstractTableModel //TESTED_FILES= @@ -110,6 +112,8 @@ private slots: void testMoveWithinOwnRange_data(); void testMoveWithinOwnRange(); + void testReset(); + private: DynamicTreeModel *m_model; @@ -814,7 +818,7 @@ void tst_QAbstractItemModel::complexChangesWithPersistent() //remove a bunch of columns model.removeColumns(2, 4); - + QVERIFY(a == model.index(1, 1, QModelIndex())); QVERIFY(b == model.index(9, 3, QModelIndex())); QVERIFY(c == model.index(5, 2, QModelIndex())); @@ -825,7 +829,7 @@ void tst_QAbstractItemModel::complexChangesWithPersistent() QVERIFY(!e[i].isValid()); for (int i=6; i <10 ; i++) QVERIFY(e[i] == model.index(2, i-4 , QModelIndex())); - + //move some indexes around model.setPersistent(model.index(1, 1 , QModelIndex()), model.index(9, 3 , QModelIndex())); model.setPersistent(model.index(9, 3 , QModelIndex()), model.index(8, 4 , QModelIndex())); @@ -1652,6 +1656,104 @@ void tst_QAbstractItemModel::testMoveWithinOwnRange() } +class ListenerObject : public QObject +{ + Q_OBJECT +public: + ListenerObject(QAbstractProxyModel *parent); + +protected: + void fillIndexStores(const QModelIndex &parent); + +public slots: + void slotAboutToBeReset(); + void slotReset(); + +private: + QAbstractProxyModel *m_model; + QList<QPersistentModelIndex> m_persistentIndexes; + QModelIndexList m_nonPersistentIndexes; +}; + + +ListenerObject::ListenerObject(QAbstractProxyModel *parent) + : QObject(parent), m_model(parent) +{ + connect(m_model, SIGNAL(modelAboutToBeReset()), SLOT(slotAboutToBeReset())); + connect(m_model, SIGNAL(modelReset()), SLOT(slotReset())); + + fillIndexStores(QModelIndex()); +} + +void ListenerObject::fillIndexStores(const QModelIndex &parent) +{ + const int column = 0; + int row = 0; + QModelIndex idx = m_model->index(row, column, parent); + while (idx.isValid()) + { + m_persistentIndexes << QPersistentModelIndex(idx); + m_nonPersistentIndexes << idx; + if (m_model->hasChildren(idx)) + { + fillIndexStores(idx); + } + ++row; + idx = m_model->index(row, column, parent); + } +} + +void ListenerObject::slotAboutToBeReset() +{ + // Nothing has been changed yet. All indexes should be the same. + for (int i = 0; i < m_persistentIndexes.size(); ++i) + { + QModelIndex idx = m_persistentIndexes.at(i); + QVERIFY(idx == m_nonPersistentIndexes.at(i)); + QVERIFY(m_model->mapToSource(idx).isValid()); + } +} + +void ListenerObject::slotReset() +{ + foreach(const QModelIndex &idx, m_persistentIndexes) + { + QVERIFY(!idx.isValid()); + } +} + + +void tst_QAbstractItemModel::testReset() +{ + QSignalSpy beforeResetSpy(m_model, SIGNAL(modelAboutToBeReset())); + QSignalSpy afterResetSpy(m_model, SIGNAL(modelReset())); + + + QSortFilterProxyModel *nullProxy = new QSortFilterProxyModel(this); + nullProxy->setSourceModel(m_model); + + // Makes sure the model and proxy are in a consistent state. before and after reset. + new ListenerObject(nullProxy); + + ModelResetCommandFixed *resetCommand = new ModelResetCommandFixed(m_model, this); + + resetCommand->setNumCols(4); + resetCommand->setStartRow(0); + resetCommand->setEndRow(0); + resetCommand->setDestRow(0); + resetCommand->setDestAncestors(QList<int>() << 5); + resetCommand->doCommand(); + + // Verify that the correct signals were emitted + QVERIFY(beforeResetSpy.size() == 1); + QVERIFY(afterResetSpy.size() == 1); + + // Verify that the move actually happened. + QVERIFY(m_model->rowCount() == 9); + QModelIndex destIndex = m_model->index(4, 0); + QVERIFY(m_model->rowCount(destIndex) == 11); + +} QTEST_MAIN(tst_QAbstractItemModel) |