From 1058ece953b4fc4b4766934f835ff66bb1cb71bb Mon Sep 17 00:00:00 2001 From: Eike Ziller Date: Mon, 6 Nov 2023 15:51:31 +0100 Subject: [PATCH] QmlJsEditor: Fix crash when updating outline view If the outline view is set to not show all bindings, it can crash after writing code that temporarily produces an element after the cursor that is interpreted as the child of a NonElementBindingType. In the bug report that is a temporary structure of * Window (element) * ... * Rectangle (element) * ... * y (non-element binding) * y (element binding) * Text (element) <- this gets selected in the global outline When an element is selected in the global outline, the outline view searches for the first element in the parent hierarchy for which the source index is successfully mapped to its filtermodel. (QmlJSOutlineWidget::updateSelectionInTree) Since filterAcceptsRow only explicitly filters out items that are non- element bindings, the "Text" element in the above example is "not filtered out", and is set as the selection in the outline view, even though it is not visible because one of its parents is filtered out. That leads to a crash later on. Make sure that filterAcceptsRow explicitly filters out any item that has a NonElementBindingType in its parent hierarchy. Fixes: QTCREATORBUG-28862 Change-Id: I1091daae140f13ea7fea7bb637953f51348c3b63 Reviewed-by: Ulf Hermann --- src/plugins/qmljseditor/qmljsoutline.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/plugins/qmljseditor/qmljsoutline.cpp b/src/plugins/qmljseditor/qmljsoutline.cpp index 89d2dd68320..73a9b2b0b33 100644 --- a/src/plugins/qmljseditor/qmljsoutline.cpp +++ b/src/plugins/qmljseditor/qmljsoutline.cpp @@ -44,9 +44,13 @@ bool QmlJSOutlineFilterModel::filterAcceptsRow(int sourceRow, { if (m_filterBindings) { QModelIndex sourceIndex = sourceModel()->index(sourceRow, 0, sourceParent); - QVariant itemType = sourceIndex.data(QmlOutlineModel::ItemTypeRole); - if (itemType == QmlOutlineModel::NonElementBindingType) - return false; + while (sourceIndex.isValid()) { + if (sourceIndex.data(QmlOutlineModel::ItemTypeRole) + == QmlOutlineModel::NonElementBindingType) { + return false; + } + sourceIndex = sourceIndex.parent(); + } } return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); }