From 8609a2fa88dfb7e85919689ccc96abcf97c3aaac Mon Sep 17 00:00:00 2001 From: Martin Dobias Date: Thu, 21 Jun 2018 00:50:17 +0200 Subject: [PATCH] Do not crash on exit due to dangling layer pointer (fixes #18732) When using attribute dialog to edit attributes of multiple selected features, the dialog may stay alive until QGIS exits (parented to QgisApp) and its internal QgsActionMenu would try to reload actions when they get removed in ~QgisApp, referring to a deleted map layer, so let's clean things up when the layer gets deleted to avoid trouble later. --- src/gui/qgsactionmenu.cpp | 10 ++++++++++ src/gui/qgsactionmenu.h | 1 + 2 files changed, 11 insertions(+) diff --git a/src/gui/qgsactionmenu.cpp b/src/gui/qgsactionmenu.cpp index 3b0eda3e9952..9e9b4d0b0830 100644 --- a/src/gui/qgsactionmenu.cpp +++ b/src/gui/qgsactionmenu.cpp @@ -47,6 +47,7 @@ void QgsActionMenu::init() connect( mLayer, &QgsVectorLayer::editingStarted, this, &QgsActionMenu::reloadActions ); connect( mLayer, &QgsVectorLayer::editingStopped, this, &QgsActionMenu::reloadActions ); connect( mLayer, &QgsVectorLayer::readOnlyChanged, this, &QgsActionMenu::reloadActions ); + connect( mLayer, &QgsMapLayer::willBeDeleted, this, &QgsActionMenu::layerWillBeDeleted ); reloadActions(); } @@ -167,6 +168,15 @@ void QgsActionMenu::reloadActions() emit reinit(); } +void QgsActionMenu::layerWillBeDeleted() +{ + // here we are just making sure that we are not going to have reloadActions() called again + // with a dangling pointer to a layer when actions get removed on QGIS exit + clear(); + mLayer = nullptr; + disconnect( QgsGui::mapLayerActionRegistry(), &QgsMapLayerActionRegistry::changed, this, &QgsActionMenu::reloadActions ); +} + QgsActionMenu::ActionData::ActionData( QgsMapLayerAction *action, QgsFeatureId featureId, QgsMapLayer *mapLayer ) : actionType( MapLayerAction ) diff --git a/src/gui/qgsactionmenu.h b/src/gui/qgsactionmenu.h index 52ac5e6f677e..8ed0f445a84b 100644 --- a/src/gui/qgsactionmenu.h +++ b/src/gui/qgsactionmenu.h @@ -119,6 +119,7 @@ class GUI_EXPORT QgsActionMenu : public QMenu private slots: void triggerAction(); void reloadActions(); + void layerWillBeDeleted(); private: void init();