From 9124833a63e9b933587a4df2aff9b5a7066568d2 Mon Sep 17 00:00:00 2001 From: David Faure Date: Wed, 29 Nov 2023 10:46:55 +0100 Subject: [PATCH] Fix TreeModel emitting nested QAbstractItemModel signals This led to an assert in QSFPM because it got confused by the nested reset signals. Detected by adding new QAbstractItemModelTester(this, QAbstractItemModelTester::FailureReportingMode::Fatal); to the OutlineModel constructor, and just opening QtCreator on a small qmake-based project. Change-Id: I41dbc81b5a2275521ece6b865115e1428e07ecf7 Reviewed-by: Reviewed-by: hjk --- src/libs/utils/treemodel.cpp | 21 ++++++++++++++------- src/libs/utils/treemodel.h | 5 +++-- src/plugins/cppeditor/cppoutlinemodel.cpp | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/libs/utils/treemodel.cpp b/src/libs/utils/treemodel.cpp index fe96b9c83e4..72e80c636e7 100644 --- a/src/libs/utils/treemodel.cpp +++ b/src/libs/utils/treemodel.cpp @@ -604,7 +604,7 @@ TreeItem::~TreeItem() { QTC_CHECK(m_parent == nullptr); QTC_CHECK(m_model == nullptr); - removeChildren(); + removeChildren(false); } TreeItem *TreeItem::childAt(int pos) const @@ -700,15 +700,17 @@ void TreeItem::removeChildAt(int pos) } } -void TreeItem::removeChildren() +void TreeItem::removeChildren(bool emitSignals) { if (childCount() == 0) return; if (m_model) { QModelIndex idx = index(); - m_model->beginRemoveRows(idx, 0, childCount() - 1); + if (emitSignals) + m_model->beginRemoveRows(idx, 0, childCount() - 1); clear(); - m_model->endRemoveRows(); + if (emitSignals) + m_model->endRemoveRows(); } else { clear(); } @@ -1060,6 +1062,13 @@ TreeItem *BaseTreeModel::rootItem() const } void BaseTreeModel::setRootItem(TreeItem *item) +{ + beginResetModel(); + setRootItemInternal(item); + endResetModel(); +} + +void BaseTreeModel::setRootItemInternal(TreeItem *item) { QTC_ASSERT(item, return); QTC_ASSERT(item->m_model == nullptr, return); @@ -1067,19 +1076,17 @@ void BaseTreeModel::setRootItem(TreeItem *item) QTC_ASSERT(item != m_root, return); QTC_CHECK(m_root); - beginResetModel(); if (m_root) { QTC_CHECK(m_root->m_parent == nullptr); QTC_CHECK(m_root->m_model == this); // needs to be done explicitly before setting the model to 0, otherwise it might lead to a // crash inside a view or proxy model, especially if there are selected items - m_root->removeChildren(); + m_root->removeChildren(false); m_root->m_model = nullptr; delete m_root; } m_root = item; item->propagateModel(this); - endResetModel(); } void BaseTreeModel::setHeader(const QStringList &displays) diff --git a/src/libs/utils/treemodel.h b/src/libs/utils/treemodel.h index a8cc073fcff..13d340cdf6f 100644 --- a/src/libs/utils/treemodel.h +++ b/src/libs/utils/treemodel.h @@ -38,7 +38,7 @@ public: const std::function &cmp); void removeChildAt(int pos); - void removeChildren(); + void removeChildren(bool emitSignals = true); void sortChildren(const std::function &cmp); void update(); void updateAll(); @@ -180,7 +180,8 @@ protected: void clear(); TreeItem *rootItem() const; - void setRootItem(TreeItem *item); + void setRootItem(TreeItem *item); // resets the model + void setRootItemInternal(TreeItem *item); TreeItem *itemForIndex(const QModelIndex &) const; QModelIndex indexForItem(const TreeItem *needle) const; diff --git a/src/plugins/cppeditor/cppoutlinemodel.cpp b/src/plugins/cppeditor/cppoutlinemodel.cpp index 068dc310b1e..c03236f274e 100644 --- a/src/plugins/cppeditor/cppoutlinemodel.cpp +++ b/src/plugins/cppeditor/cppoutlinemodel.cpp @@ -219,7 +219,7 @@ void OutlineModel::rebuild() auto root = new SymbolItem; if (m_cppDocument) buildTree(root, true); - setRootItem(root); + setRootItemInternal(root); endResetModel(); }