Details
-
Bug
-
Resolution: Duplicate
-
P2: Important
-
None
-
5.4.0
-
None
-
Mac OS X 10.9.5, Qt 5.3.2, Qt 5.4.0, Qt be35b9f
Description
I have a fairly complex hierarchy of nested models, and I have no idea if this is relevant (from source to proxy):
MyListModel -> MySortModel -> MyFilterModel -> MyIdentityModel -> MyIdentityModel2
The FilterModel also makes some columns editable and directly modifies the underlying data-source.
This hierarchy is the model of a tree view.
When I edit one of the columns in the model, QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged triggers QItemSelectionProxyModel::_q_layoutAboutToBeChanged, which saves some persistent indexes.
In the subsequent call of QSortFilterProxyModelPrivate::_q_sourceLayoutChanged its persistent indexes are cleared (update_persistent_indexes) and QItemSelectionModelPrivate::_q_layoutChanged is triggered, which does not update its own persistent indexes.
Therefor mergeRowLengths uses invalid persistent indexes, which leads to the following crash, since the internal pointer to the Mapping-iterator is no longer valid:
0 QSortFilterProxyModel::sibling(int, int, QModelIndex const&) const QSortFilterProxyModel::sibling(int, int, QModelIndex const&) const 0x102211507 1 QIdentityProxyModel::sibling(int, int, QModelIndex const&) const QIdentityProxyModel::sibling(int, int, QModelIndex const&) const 0x102205178 2 QIdentityProxyModel::sibling(int, int, QModelIndex const&) const QIdentityProxyModel::sibling(int, int, QModelIndex const&) const 0x102205178 3 QPersistentModelIndex::sibling(int, int) const QPersistentModelIndex::sibling(int, int) const 0x1021e9be5 4 mergeRowLengths(QVector<QPair<QPersistentModelIndex, unsigned int>> const&) mergeRowLengths(QVector<QPair<QPersistentModelIndex, unsigned int> > const&) 0x1021fdd05 5 QItemSelectionModelPrivate::_q_layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) QItemSelectionModelPrivate::_q_layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) 0x1021fd409 6 QItemSelectionModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) QItemSelectionModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) 0x102201249 7 QMetaObject::activate(QObject*, int, int, void**) QMetaObject::activate(QObject*, int, int, void**) 0x10226e9db 8 QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) 0x1022e9df3 9 QIdentityProxyModelPrivate::_q_sourceLayoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) QIdentityProxyModelPrivate::_q_sourceLayoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) 0x102206f1c 10 QIdentityProxyModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) QIdentityProxyModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) 0x1022074d0 11 QMetaObject::activate(QObject*, int, int, void**) QMetaObject::activate(QObject*, int, int, void**) 0x10226e9db 12 QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) 0x1022e9df3 13 QIdentityProxyModelPrivate::_q_sourceLayoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) QIdentityProxyModelPrivate::_q_sourceLayoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) 0x102206f1c 14 QIdentityProxyModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) QIdentityProxyModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) 0x1022074d0 15 QMetaObject::activate(QObject*, int, int, void**) QMetaObject::activate(QObject*, int, int, void**) 0x10226e9db 16 QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) 0x1022e9df3 17 QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) QSortFilterProxyModelPrivate::_q_sourceLayoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) 0x10220f73a 18 QSortFilterProxyModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) QSortFilterProxyModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) 0x102213d03 19 QMetaObject::activate(QObject*, int, int, void**) QMetaObject::activate(QObject*, int, int, void**) 0x10226e9db 20 QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) QAbstractItemModel::layoutChanged(QList<QPersistentModelIndex> const&, QAbstractItemModel::LayoutChangeHint) 0x1022e9df3 21 QSortFilterProxyModelPrivate::_q_sourceDataChanged(QModelIndex const&, QModelIndex const&) QSortFilterProxyModelPrivate::_q_sourceDataChanged(QModelIndex const&, QModelIndex const&) 0x10220e1ce 22 QSortFilterProxyModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) QSortFilterProxyModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) 0x102213c93 23 QMetaObject::activate(QObject*, int, int, void**) QMetaObject::activate(QObject*, int, int, void**) 0x10226e9db 24 QAbstractItemModel::dataChanged(QModelIndex const&, QModelIndex const&, QVector<int> const&) QAbstractItemModel::dataChanged(QModelIndex const&, QModelIndex const&, QVector<int> const&) 0x1022e9d1d 25 QpObjectListModelBase::objectUpdated(QSharedPointer<QObject>) objectlistmodel.cpp 200 0x100503c29 26 QtPrivate::FunctorCall<QtPrivate::IndexesList<0>, QtPrivate::List<QSharedPointer<QObject>>, void, void (QpObjectListModelBase::*)(QSharedPointer<QObject>)>::call(void (QpObjectListModelBase::*)(QSharedPointer<QObject>), QpObjectListModelBase*, void**) qobjectdefs_impl.h 500 0x10050678a 27 void QtPrivate::FunctionPointer<void (QpObjectListModelBase::*)(QSharedPointer<QObject>)>::call<QtPrivate::List<QSharedPointer<QObject>>, void>(void (QpObjectListModelBase::*)(QSharedPointer<QObject>), QpObjectListModelBase*, void**) qobjectdefs_impl.h 519 0x1005066d0 28 QtPrivate::QSlotObject<void (QpObjectListModelBase::*)(QSharedPointer<QObject>), QtPrivate::List<QSharedPointer<QObject>>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) qobject_impl.h 143 0x1005065f8 29 QMetaObject::activate(QObject*, int, int, void**) QMetaObject::activate(QObject*, int, int, void**) 0x10226e5f2 30 QpDataAccessObjectBase::objectUpdated(QSharedPointer<QObject>) moc_dataaccessobject.cpp 291 0x100533ad2 31 QpDataAccessObjectBase::updateObject(QSharedPointer<QObject>) dataaccessobject.cpp 334 0x1004c2e4f 32 QpStorage::update(QSharedPointer<QObject>) storage.cpp 320 0x1005292a9 33 Qp::UpdateResult QpStorage::update<libdBase2::CustomerPallet>(QSharedPointer<libdBase2::CustomerPallet>) storage.h 164 0x10030bc7d 34 Qp::UpdateResult Qp::update<libdBase2::CustomerPallet>(QSharedPointer<libdBase2::CustomerPallet>) defaultstorage.h 50 0x10030b823 35 libdBase2::CustomerPalletsModel::setData(QModelIndex const&, QVariant const&, int) customerPalletsModel.cpp 129 0x10030b284 36 QSortFilterProxyModel::setData(QModelIndex const&, QVariant const&, int) QSortFilterProxyModel::setData(QModelIndex const&, QVariant const&, int) 0x102211826 37 QSortFilterProxyModel::setData(QModelIndex const&, QVariant const&, int) QSortFilterProxyModel::setData(QModelIndex const&, QVariant const&, int) 0x102211826 38 QAbstractProxyModel::setData(QModelIndex const&, QVariant const&, int) QAbstractProxyModel::setData(QModelIndex const&, QVariant const&, int) 0x1021f6794 39 QAbstractProxyModel::setData(QModelIndex const&, QVariant const&, int) QAbstractProxyModel::setData(QModelIndex const&, QVariant const&, int) 0x1021f6794 ... <More>
I was not able to reproduce the bug with a simple example, but I was able to "fix" the bug by updating the QItemSelectionModel persistent indexes with something like the following being called in _q_layoutChanged:
void QItemSelectionModelPrivate::updatePersistentIndexes() { QVector<QPersistentModelIndex> _savedPersistentIndexes; for(int i = 0; i < savedPersistentIndexes.size(); ++i) { QModelIndex old_index = savedPersistentIndexes.at(i); _savedPersistentIndexes << model->index(old_index.row(), old_index.column()); } savedPersistentIndexes = _savedPersistentIndexes; QVector<QPersistentModelIndex> _savedPersistentCurrentIndexes; for(int i = 0; i < savedPersistentCurrentIndexes.size(); ++i) { QModelIndex old_index = savedPersistentCurrentIndexes.at(i); _savedPersistentCurrentIndexes << model->index(old_index.row(), old_index.column()); } savedPersistentCurrentIndexes = _savedPersistentCurrentIndexes; QVector<QPair<QPersistentModelIndex, uint> > _savedPersistentRowLengths; for(int i = 0; i < savedPersistentRowLengths.size(); ++i) { QModelIndex old_index = savedPersistentRowLengths.at(i).first; _savedPersistentRowLengths << qMakePair(QPersistentModelIndex(model->index(old_index.row(), old_index.column())), savedPersistentRowLengths.at(i).second); } savedPersistentRowLengths = _savedPersistentRowLengths; QVector<QPair<QPersistentModelIndex, uint> > _savedPersistentCurrentRowLengths; for(int i = 0; i < savedPersistentCurrentRowLengths.size(); ++i) { QModelIndex old_index = savedPersistentCurrentRowLengths.at(i).first; _savedPersistentCurrentRowLengths << qMakePair(QPersistentModelIndex(model->index(old_index.row(), old_index.column())), savedPersistentCurrentRowLengths.at(i).second); } savedPersistentCurrentRowLengths = _savedPersistentCurrentRowLengths; currentIndex = model->index(currentIndex.row(), currentIndex.column()); tableParent = model->index(tableParent.row(), tableParent.column()); }
Attachments
Issue Links
- relates to
-
QTBUG-47711 QSortFilterProxyModel policy on invalidating QModelndexes isn't consistent, can lead to crashes
- Reported
-
QTBUG-32981 QIdentityProxyModel not working when chained with a QSortFilterProxyModel
- Closed