From a61f9162f10e54f31dcc5b0221e11b5ca81f186b Mon Sep 17 00:00:00 2001 From: David Faure Date: Wed, 29 Nov 2023 10:46:55 +0100 Subject: 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. Fixes: QTCREATORBUG-30035 Change-Id: I41dbc81b5a2275521ece6b865115e1428e07ecf7 Reviewed-by: Reviewed-by: hjk (cherry picked from commit 9124833a63e9b933587a4df2aff9b5a7066568d2) Reviewed-by: David Faure --- src/libs/utils/treemodel.cpp | 20 ++++++++++++++++---- src/libs/utils/treemodel.h | 4 +++- src/plugins/cppeditor/cppoutlinemodel.cpp | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/libs/utils/treemodel.cpp b/src/libs/utils/treemodel.cpp index fe96b9c83e..4649bb43c8 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(); + removeChildrenSilently(); } TreeItem *TreeItem::childAt(int pos) const @@ -714,6 +714,13 @@ void TreeItem::removeChildren() } } +void TreeItem::removeChildrenSilently() +{ + if (childCount() == 0) + return; + clear(); +} + void TreeItem::sortChildren(const std::function &cmp) { if (m_model) { @@ -1060,6 +1067,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 +1081,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->removeChildrenSilently(); 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 a8cc073fcf..fa960698b6 100644 --- a/src/libs/utils/treemodel.h +++ b/src/libs/utils/treemodel.h @@ -39,6 +39,7 @@ public: void removeChildAt(int pos); void removeChildren(); + void removeChildrenSilently(); void sortChildren(const std::function &cmp); void update(); void updateAll(); @@ -180,7 +181,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 068dc310b1..c03236f274 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(); } -- cgit v1.2.3