From a3036d16f1de88cf86aa9b613c3a4af6ed6e2cf1 Mon Sep 17 00:00:00 2001 From: xtemp09 Date: Fri, 8 Mar 2024 20:00:00 +0700 Subject: [PATCH] Fix the crash described in #12785 Closes #12785. The cause of the segmentation fault is access to the already deleted _QMenu_. Simple setting attribute `Qt::WA_DeleteOnClose` and removal of `delete menu` prevented it. To reproduce the crash, one needs to mess up the `user.cfg` file in the way described in the issue. Here is the fragment from the issue to mess up the `user.cfg` file: ```xml = ``` --- This commit changes also unconnected things: - usage of `QObject::connect` instead of if statements - relocation of a separator and an action inside the if statement (I saw no reason to have a separator and an action for _ExpressionCompleter_ if there is no expression completer) - usage of asynchronous `QMenu::popup()` instead of synchronous `QMenu::exec()`. This way is used within [the source code of Qt] (https://github.com/qt/qtbase/blob/5.15/src/widgets/widgets/ qlineedit.cpp#L2191-L2197). --- src/Gui/ExpressionCompleter.cpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/Gui/ExpressionCompleter.cpp b/src/Gui/ExpressionCompleter.cpp index 27c3cd5338..015a2dc135 100644 --- a/src/Gui/ExpressionCompleter.cpp +++ b/src/Gui/ExpressionCompleter.cpp @@ -959,25 +959,18 @@ void ExpressionLineEdit::keyPressEvent(QKeyEvent* e) void ExpressionLineEdit::contextMenuEvent(QContextMenuEvent* event) { QMenu* menu = createStandardContextMenu(); - menu->addSeparator(); - QAction* match = menu->addAction(tr("Exact match")); if (completer) { + menu->addSeparator(); + QAction *match = menu->addAction(tr("Exact match")); match->setCheckable(true); match->setChecked(completer->filterMode() == Qt::MatchStartsWith); + QObject::connect(match, &QAction::toggled, + this, &Gui::ExpressionLineEdit::setExactMatch); } - else { - match->setVisible(false); - } + menu->setAttribute(Qt::WA_DeleteOnClose); - QAction* action = menu->exec(event->globalPos()); - - if (completer) { - if (action == match) - setExactMatch(match->isChecked()); - } - - delete menu; + menu->popup(event->globalPos()); }