88from qgis .PyQt .QtGui import QIcon
99from qgis .PyQt .QtWidgets import (
1010 QAction ,
11+ QToolBar ,
1112 QDockWidget ,
1213 QWidget ,
1314 QVBoxLayout ,
4142from .map_tools import PointPromptTool , BoxPromptTool
4243
4344
45+ TOOLBAR_OBJECT_NAME = "SamGeo"
46+ MENU_TITLE = "&SamGeo"
47+
4448class SamGeoPlugin :
4549 """QGIS Plugin for remote sensing image segmentation using SamGeo."""
4650
@@ -57,8 +61,10 @@ def __init__(self, iface):
5761 # Initialize plugin attributes
5862 self .actions = []
5963 self .menu = "&SamGeo"
64+ self ._remove_toolbars_by_object_name ()
65+ self ._remove_menus_by_title ()
6066 self .toolbar = self .iface .addToolBar ("SamGeo" )
61- self .toolbar .setObjectName ("SamGeo" )
67+ self .toolbar .setObjectName (TOOLBAR_OBJECT_NAME )
6268
6369 # Dock widget
6470 self .dock_widget = None
@@ -133,6 +139,93 @@ def initGui(self):
133139 status_tip = self .tr ("Open SamGeo Segmentation Panel" ),
134140 )
135141
142+
143+ def _remove_toolbar (self , toolbar ):
144+ """Detach and schedule deletion of a plugin toolbar widget."""
145+ if toolbar is None :
146+ return
147+
148+ main_window = self .iface .mainWindow ()
149+ actions = []
150+ try :
151+ actions = list (toolbar .actions ())
152+ except Exception :
153+ pass # nosec B110
154+ try :
155+ toolbar .clear ()
156+ except Exception :
157+ pass # nosec B110
158+ for action in actions :
159+ try :
160+ action .deleteLater ()
161+ except Exception :
162+ pass # nosec B110
163+ try :
164+ main_window .removeToolBar (toolbar )
165+ except Exception :
166+ pass # nosec B110
167+ try :
168+ toolbar .hide ()
169+ except Exception :
170+ pass # nosec B110
171+ try :
172+ toolbar .setParent (None )
173+ except Exception :
174+ pass # nosec B110
175+ try :
176+ toolbar .deleteLater ()
177+ except Exception :
178+ pass # nosec B110
179+
180+ def _remove_toolbars_by_object_name (self ):
181+ """Remove current or stale plugin toolbars from QGIS."""
182+ main_window = self .iface .mainWindow ()
183+ for toolbar in main_window .findChildren (QToolBar , TOOLBAR_OBJECT_NAME ):
184+ self ._remove_toolbar (toolbar )
185+
186+ def _plugin_menu_titles (self ):
187+ """Return possible translated and untranslated plugin menu titles."""
188+ titles = {MENU_TITLE }
189+ translator = getattr (self , "tr" , None )
190+ if callable (translator ):
191+ try :
192+ titles .add (translator (MENU_TITLE ))
193+ except Exception :
194+ pass # nosec B110
195+ return titles
196+
197+ def _remove_menu (self , menu ):
198+ """Detach and schedule deletion of a plugin menu."""
199+ if menu is None :
200+ return
201+
202+ main_window = self .iface .mainWindow ()
203+ try :
204+ menu .clear ()
205+ except Exception :
206+ pass # nosec B110
207+ try :
208+ main_window .menuBar ().removeAction (menu .menuAction ())
209+ except Exception :
210+ pass # nosec B110
211+ try :
212+ menu .setParent (None )
213+ except Exception :
214+ pass # nosec B110
215+ try :
216+ menu .deleteLater ()
217+ except Exception :
218+ pass # nosec B110
219+
220+ def _remove_menus_by_title (self ):
221+ """Remove current or stale plugin menus from QGIS."""
222+ menu_bar = self .iface .mainWindow ().menuBar ()
223+ titles = self ._plugin_menu_titles ()
224+ for action in menu_bar .actions ():
225+ menu = action .menu ()
226+ if menu is not None and menu .title () in titles :
227+ self ._remove_menu (menu )
228+
136229 def unload (self ):
137230 """Remove the plugin menu item and icon from QGIS GUI."""
138231 for action in self .actions :
@@ -151,6 +244,9 @@ def unload(self):
151244 del self .sam
152245 self .sam = None
153246
247+ self ._remove_toolbars_by_object_name ()
248+ self ._remove_menus_by_title ()
249+
154250 def run (self ):
155251 """Run the plugin - show the dock widget."""
156252 if self .dock_widget is None :
0 commit comments