Don't call virtual methods after the source model is destroyed.

Calling clear_mapping causes the persistent indexes to be queried, and
mapped using map_to_source, so that they can be restored later. That
is not the appropriate response to the source model being deleted
because there won't be anything to restore.

Simply clear the stored mapping information instead so that the source model
actually exists when mapToSource is called by the framework.

Change-Id: I99692ee7aa9c6714aec45c68fe4a2d62be189d60
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
bb10
Stephen Kelly 2013-04-02 17:52:54 +02:00 committed by The Qt Project
parent a658d26d84
commit 722798a359
3 changed files with 38 additions and 1 deletions

View File

@ -91,6 +91,7 @@ QT_BEGIN_NAMESPACE
//detects the deletion of the source model
void QAbstractProxyModelPrivate::_q_sourceModelDestroyed()
{
invalidatePersistentIndexes();
model = QAbstractItemModelPrivate::staticEmptyModel();
}

View File

@ -295,7 +295,8 @@ typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed()
{
QAbstractProxyModelPrivate::_q_sourceModelDestroyed();
_q_clearMapping();
qDeleteAll(source_index_mapping);
source_index_mapping.clear();
}
void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent)

View File

@ -148,6 +148,7 @@ private slots:
void chainedProxyModelRoleNames();
void noMapAfterSourceDelete();
protected:
void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
void checkHierarchy(const QStringList &data, const QAbstractItemModel *model);
@ -3809,5 +3810,39 @@ void tst_QSortFilterProxyModel::chainedProxyModelRoleNames()
QVERIFY(proxy2.roleNames().value(Qt::UserRole + 1) == "custom");
}
class SourceAssertion : public QSortFilterProxyModel
{
Q_OBJECT
public:
explicit SourceAssertion(QObject *parent = 0)
: QSortFilterProxyModel(parent)
{
}
QModelIndex mapToSource(const QModelIndex &proxyIndex) const
{
Q_ASSERT(sourceModel());
return QSortFilterProxyModel::mapToSource(proxyIndex);
}
};
void tst_QSortFilterProxyModel::noMapAfterSourceDelete()
{
SourceAssertion proxy;
QStringListModel *model = new QStringListModel(QStringList() << "Foo" << "Bar");
proxy.setSourceModel(model);
// Create mappings
QPersistentModelIndex persistent = proxy.index(0, 0);
QVERIFY(persistent.isValid());
delete model;
QVERIFY(!persistent.isValid());
}
QTEST_MAIN(tst_QSortFilterProxyModel)
#include "tst_qsortfilterproxymodel.moc"