summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Kelly <stephen.kelly@kdab.com>2010-09-23 14:14:18 +0200
committerGabriel de Dietrich <gabriel.dietrich-de@nokia.com>2011-06-27 18:13:45 +0200
commit0f6853e9c775dd8fbb64f66119c2c9b2ea23da29 (patch)
tree880ec281b07648a14b0a4b95473001b5fb8b5eb5
parent031958c130904c16a4bafa5617aaa197469efa9e (diff)
Provide the resetInternalData slot to cleanly reset data in proxy subclasses.
Direct subclasses of QAbstractItemModel are unnaffected as they can update internal data in a slot connected to the sourceModel's modelReset signal or layoutChanged signal. Rehabilitated for 4.8. Should be reverted again in Qt 5. Reviewed-by: gabi Merge-request: 694
-rw-r--r--doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp35
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp22
-rw-r--r--src/corelib/kernel/qabstractitemmodel.h3
-rw-r--r--tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp138
4 files changed, 198 insertions, 0 deletions
diff --git a/doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp b/doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp
index 5919c01085..cf40f9a05a 100644
--- a/doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp
+++ b/doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp
@@ -86,3 +86,38 @@ beginMoveRows(parent, 2, 2, parent, 0);
//! [9]
beginMoveRows(parent, 2, 2, parent, 4);
//! [9]
+
+
+//! [10]
+class CustomDataProxy : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ CustomDataProxy(QObject *parent)
+ : QSortFilterProxyModel(parent)
+ {
+ }
+
+ ...
+
+ QVariant data(const QModelIndex &index, int role)
+ {
+ if (role != Qt::BackgroundRole)
+ return QSortFilterProxyModel::data(index, role);
+
+ if (m_customData.contains(index.row()))
+ return m_customData.value(index.row());
+ return QSortFilterProxyModel::data(index, role);
+ }
+
+private slots:
+ void resetInternalData()
+ {
+ m_customData.clear();
+ }
+
+private:
+ QHash<int, QVariant> m_customData;
+};
+//! [10]
+
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index b7ac6aa594..54cc301194 100644
--- a/src/corelib/kernel/qabstractitemmodel.cpp
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -1348,6 +1348,26 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
*/
/*!
+ \since 4.8
+
+ This slot is called just after the internal data of a model is cleared
+ while it is being reset.
+
+ This slot is provided the convenience of subclasses of concrete proxy
+ models, such as subclasses of QSortFilterProxyModel which maintain extra
+ data.
+
+ \snippet doc/src/snippets/code/src_corelib_kernel_qabstractitemmodel.cpp 10
+
+ \sa modelAboutToBeReset(), modelReset()
+*/
+void QAbstractItemModel::resetInternalData()
+{
+
+}
+
+
+/*!
Constructs an abstract item model with the given \a parent.
*/
QAbstractItemModel::QAbstractItemModel(QObject *parent)
@@ -2888,6 +2908,7 @@ void QAbstractItemModel::reset()
Q_D(QAbstractItemModel);
emit modelAboutToBeReset();
d->invalidatePersistentIndexes();
+ QMetaObject::invokeMethod(this, "resetInternalData");
emit modelReset();
}
@@ -2930,6 +2951,7 @@ void QAbstractItemModel::endResetModel()
{
Q_D(QAbstractItemModel);
d->invalidatePersistentIndexes();
+ QMetaObject::invokeMethod(this, "resetInternalData");
emit modelReset();
}
diff --git a/src/corelib/kernel/qabstractitemmodel.h b/src/corelib/kernel/qabstractitemmodel.h
index c7af7a284f..43d8ac2526 100644
--- a/src/corelib/kernel/qabstractitemmodel.h
+++ b/src/corelib/kernel/qabstractitemmodel.h
@@ -303,6 +303,9 @@ protected:
void setRoleNames(const QHash<int,QByteArray> &roleNames);
+protected slots:
+ void resetInternalData();
+
private:
Q_DECLARE_PRIVATE(QAbstractItemModel)
Q_DISABLE_COPY(QAbstractItemModel)
diff --git a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
index 613c611843..30589a89f6 100644
--- a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
@@ -149,6 +149,7 @@ private slots:
void testMultipleProxiesWithSelection();
void mapSelectionFromSource();
+ void testResetInternalData();
void filteredColumns();
protected:
@@ -3271,5 +3272,142 @@ void tst_QSortFilterProxyModel::taskQTBUG_17812_resetInvalidate()
QCOMPARE(ok, works);
}
+/**
+ * A proxy which changes the background color for items ending in 'y' or 'r'
+ */
+class CustomDataProxy : public QSortFilterProxyModel
+{
+ Q_OBJECT
+
+public:
+ CustomDataProxy(QObject *parent = 0)
+ : QSortFilterProxyModel(parent)
+ {
+ setDynamicSortFilter(true);
+ }
+
+ void setSourceModel(QAbstractItemModel *sourceModel)
+ {
+ // It would be possible to use only the modelReset signal of the source model to clear
+ // the data in *this, however, this requires that the slot is connected
+ // before QSortFilterProxyModel::setSourceModel is called, and even then depends
+ // on the order of invokation of slots being the same as the order of connection.
+ // ie, not reliable.
+// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData()));
+ QSortFilterProxyModel::setSourceModel(sourceModel);
+ // Making the connect after the setSourceModel call clears the data too late.
+// connect(sourceModel, SIGNAL(modelReset()), SLOT(resetInternalData()));
+
+ // This could be done in data(), but the point is to need to cache something in the proxy
+ // which needs to be cleared on reset.
+ for (int i = 0; i < sourceModel->rowCount(); ++i)
+ {
+ if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('y')))
+ {
+ m_backgroundColours.insert(i, Qt::blue);
+ } else if (sourceModel->index(i, 0).data().toString().endsWith(QLatin1Char('r')))
+ {
+ m_backgroundColours.insert(i, Qt::red);
+ }
+ }
+ }
+
+ QVariant data(const QModelIndex &index, int role) const
+ {
+ if (role != Qt::BackgroundRole)
+ return QSortFilterProxyModel::data(index, role);
+ return m_backgroundColours.value(index.row());
+ }
+
+private slots:
+ void resetInternalData()
+ {
+ m_backgroundColours.clear();
+ }
+
+private:
+ QHash<int, QColor> m_backgroundColours;
+};
+
+class ModelObserver : public QObject
+{
+ Q_OBJECT
+public:
+ ModelObserver(QAbstractItemModel *model, QObject *parent = 0)
+ : QObject(parent), m_model(model)
+ {
+ connect(m_model, SIGNAL(modelAboutToBeReset()), SLOT(modelAboutToBeReset()));
+ connect(m_model, SIGNAL(modelReset()), SLOT(modelReset()));
+ }
+
+public slots:
+ void modelAboutToBeReset()
+ {
+ int reds = 0, blues = 0;
+ for (int i = 0; i < m_model->rowCount(); ++i)
+ {
+ QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value<QColor>();
+ if (color == Qt::blue)
+ ++blues;
+ if (color == Qt::red)
+ ++reds;
+ }
+ QCOMPARE(blues, 11);
+ QCOMPARE(reds, 4);
+ }
+
+ void modelReset()
+ {
+ int reds = 0, blues = 0;
+ for (int i = 0; i < m_model->rowCount(); ++i)
+ {
+ QColor color = m_model->index(i, 0).data(Qt::BackgroundRole).value<QColor>();
+ if (color == Qt::blue)
+ ++blues;
+ if (color == Qt::red)
+ ++reds;
+ }
+ QCOMPARE(reds, 0);
+ QCOMPARE(blues, 0);
+ }
+
+private:
+ QAbstractItemModel * const m_model;
+
+};
+
+void tst_QSortFilterProxyModel::testResetInternalData()
+{
+
+ QStringListModel model(QStringList() << "Monday"
+ << "Tuesday"
+ << "Wednesday"
+ << "Thursday"
+ << "Friday"
+ << "January"
+ << "February"
+ << "March"
+ << "April"
+ << "May"
+ << "Saturday"
+ << "June"
+ << "Sunday"
+ << "July"
+ << "August"
+ << "September"
+ << "October"
+ << "November"
+ << "December");
+
+ CustomDataProxy proxy;
+ proxy.setSourceModel(&model);
+
+ ModelObserver observer(&proxy);
+
+ // Cause the source model to reset.
+ model.setStringList(QStringList() << "Spam" << "Eggs");
+
+}
+
QTEST_MAIN(tst_QSortFilterProxyModel)
#include "tst_qsortfilterproxymodel.moc"