forked from qt-creator/qt-creator
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: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -604,7 +604,7 @@ TreeItem::~TreeItem()
|
|||||||
{
|
{
|
||||||
QTC_CHECK(m_parent == nullptr);
|
QTC_CHECK(m_parent == nullptr);
|
||||||
QTC_CHECK(m_model == nullptr);
|
QTC_CHECK(m_model == nullptr);
|
||||||
removeChildren();
|
removeChildren(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeItem *TreeItem::childAt(int pos) const
|
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)
|
if (childCount() == 0)
|
||||||
return;
|
return;
|
||||||
if (m_model) {
|
if (m_model) {
|
||||||
QModelIndex idx = index();
|
QModelIndex idx = index();
|
||||||
m_model->beginRemoveRows(idx, 0, childCount() - 1);
|
if (emitSignals)
|
||||||
|
m_model->beginRemoveRows(idx, 0, childCount() - 1);
|
||||||
clear();
|
clear();
|
||||||
m_model->endRemoveRows();
|
if (emitSignals)
|
||||||
|
m_model->endRemoveRows();
|
||||||
} else {
|
} else {
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
@@ -1060,6 +1062,13 @@ TreeItem *BaseTreeModel::rootItem() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void BaseTreeModel::setRootItem(TreeItem *item)
|
void BaseTreeModel::setRootItem(TreeItem *item)
|
||||||
|
{
|
||||||
|
beginResetModel();
|
||||||
|
setRootItemInternal(item);
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BaseTreeModel::setRootItemInternal(TreeItem *item)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(item, return);
|
QTC_ASSERT(item, return);
|
||||||
QTC_ASSERT(item->m_model == nullptr, return);
|
QTC_ASSERT(item->m_model == nullptr, return);
|
||||||
@@ -1067,19 +1076,17 @@ void BaseTreeModel::setRootItem(TreeItem *item)
|
|||||||
QTC_ASSERT(item != m_root, return);
|
QTC_ASSERT(item != m_root, return);
|
||||||
QTC_CHECK(m_root);
|
QTC_CHECK(m_root);
|
||||||
|
|
||||||
beginResetModel();
|
|
||||||
if (m_root) {
|
if (m_root) {
|
||||||
QTC_CHECK(m_root->m_parent == nullptr);
|
QTC_CHECK(m_root->m_parent == nullptr);
|
||||||
QTC_CHECK(m_root->m_model == this);
|
QTC_CHECK(m_root->m_model == this);
|
||||||
// needs to be done explicitly before setting the model to 0, otherwise it might lead to a
|
// 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
|
// 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;
|
m_root->m_model = nullptr;
|
||||||
delete m_root;
|
delete m_root;
|
||||||
}
|
}
|
||||||
m_root = item;
|
m_root = item;
|
||||||
item->propagateModel(this);
|
item->propagateModel(this);
|
||||||
endResetModel();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseTreeModel::setHeader(const QStringList &displays)
|
void BaseTreeModel::setHeader(const QStringList &displays)
|
||||||
|
@@ -38,7 +38,7 @@ public:
|
|||||||
const std::function<bool(const TreeItem *, const TreeItem *)> &cmp);
|
const std::function<bool(const TreeItem *, const TreeItem *)> &cmp);
|
||||||
|
|
||||||
void removeChildAt(int pos);
|
void removeChildAt(int pos);
|
||||||
void removeChildren();
|
void removeChildren(bool emitSignals = true);
|
||||||
void sortChildren(const std::function<bool(const TreeItem *, const TreeItem *)> &cmp);
|
void sortChildren(const std::function<bool(const TreeItem *, const TreeItem *)> &cmp);
|
||||||
void update();
|
void update();
|
||||||
void updateAll();
|
void updateAll();
|
||||||
@@ -180,7 +180,8 @@ protected:
|
|||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
TreeItem *rootItem() const;
|
TreeItem *rootItem() const;
|
||||||
void setRootItem(TreeItem *item);
|
void setRootItem(TreeItem *item); // resets the model
|
||||||
|
void setRootItemInternal(TreeItem *item);
|
||||||
TreeItem *itemForIndex(const QModelIndex &) const;
|
TreeItem *itemForIndex(const QModelIndex &) const;
|
||||||
QModelIndex indexForItem(const TreeItem *needle) const;
|
QModelIndex indexForItem(const TreeItem *needle) const;
|
||||||
|
|
||||||
|
@@ -219,7 +219,7 @@ void OutlineModel::rebuild()
|
|||||||
auto root = new SymbolItem;
|
auto root = new SymbolItem;
|
||||||
if (m_cppDocument)
|
if (m_cppDocument)
|
||||||
buildTree(root, true);
|
buildTree(root, true);
|
||||||
setRootItem(root);
|
setRootItemInternal(root);
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user