Cleanup iface signal connections when unloading processing

plugin

Fixes #53455
This commit is contained in:
Nyall Dawson 2023-06-14 08:59:06 +10:00
parent 371f51eabf
commit 30acad6819

View File

@ -22,6 +22,7 @@ __copyright__ = '(C) 2012, Victor Olaya'
import shutil import shutil
import os import os
import sys import sys
from typing import List
from functools import partial from functools import partial
from qgis.core import (QgsApplication, from qgis.core import (QgsApplication,
@ -38,9 +39,25 @@ from qgis.gui import (QgsGui,
QgsOptionsWidgetFactory, QgsOptionsWidgetFactory,
QgsCustomDropHandler, QgsCustomDropHandler,
QgsProcessingHistoryDialog) QgsProcessingHistoryDialog)
from qgis.PyQt.QtCore import QObject, Qt, QItemSelectionModel, QCoreApplication, QDir, QFileInfo, pyqtSlot from qgis.PyQt.QtCore import (
from qgis.PyQt.QtWidgets import QWidget, QMenu, QAction QObject,
from qgis.PyQt.QtGui import QIcon, QKeySequence Qt,
QItemSelectionModel,
QCoreApplication,
QDir,
QFileInfo,
pyqtSlot,
QMetaObject
)
from qgis.PyQt.QtWidgets import (
QWidget,
QMenu,
QAction
)
from qgis.PyQt.QtGui import (
QIcon,
QKeySequence
)
from qgis.utils import iface from qgis.utils import iface
from processing.core.Processing import Processing from processing.core.Processing import Processing
@ -177,6 +194,7 @@ class ProcessingPlugin(QObject):
self.locator_filter = None self.locator_filter = None
self.edit_features_locator_filter = None self.edit_features_locator_filter = None
self.initialized = False self.initialized = False
self._gui_connections: List[QMetaObject.Connection] = []
self.initProcessing() self.initProcessing()
def initProcessing(self): def initProcessing(self):
@ -203,7 +221,9 @@ class ProcessingPlugin(QObject):
self.locator_filter = AlgorithmLocatorFilter() self.locator_filter = AlgorithmLocatorFilter()
iface.registerLocatorFilter(self.locator_filter) iface.registerLocatorFilter(self.locator_filter)
# Invalidate the locator filter for in-place when active layer changes # Invalidate the locator filter for in-place when active layer changes
iface.currentLayerChanged.connect(lambda _: self.iface.invalidateLocatorResults()) self._gui_connections.append(
iface.currentLayerChanged.connect(lambda _: self.iface.invalidateLocatorResults())
)
self.edit_features_locator_filter = InPlaceAlgorithmLocatorFilter() self.edit_features_locator_filter = InPlaceAlgorithmLocatorFilter()
iface.registerLocatorFilter(self.edit_features_locator_filter) iface.registerLocatorFilter(self.edit_features_locator_filter)
@ -303,9 +323,19 @@ class ProcessingPlugin(QObject):
createButtons() createButtons()
# In-place editing button state sync # In-place editing button state sync
self.iface.currentLayerChanged.connect(self.sync_in_place_button_state)
self.iface.mapCanvas().selectionChanged.connect(self.sync_in_place_button_state) # we need to explicitly store and disconnect these connections
self.iface.actionToggleEditing().triggered.connect(partial(self.sync_in_place_button_state, None)) # on plugin unload -- they aren't cleaned up automatically (see
# https://github.com/qgis/QGIS/issues/53455)
self._gui_connections.append(
self.iface.currentLayerChanged.connect(self.sync_in_place_button_state)
)
self._gui_connections.append(
self.iface.mapCanvas().selectionChanged.connect(self.sync_in_place_button_state)
)
self._gui_connections.append(
self.iface.actionToggleEditing().triggered.connect(partial(self.sync_in_place_button_state, None))
)
self.sync_in_place_button_state() self.sync_in_place_button_state()
# Sync project models # Sync project models
@ -314,7 +344,9 @@ class ProcessingPlugin(QObject):
self.projectMenuSeparator = None self.projectMenuSeparator = None
self.projectProvider = QgsApplication.instance().processingRegistry().providerById("project") self.projectProvider = QgsApplication.instance().processingRegistry().providerById("project")
self.projectProvider.algorithmsLoaded.connect(self.updateProjectModelMenu) self._gui_connections.append(
self.projectProvider.algorithmsLoaded.connect(self.updateProjectModelMenu)
)
def updateProjectModelMenu(self): def updateProjectModelMenu(self):
"""Add projects models to menu""" """Add projects models to menu"""
@ -433,6 +465,9 @@ class ProcessingPlugin(QObject):
self.iface.showOptionsDialog(self.iface.mainWindow(), currentPage='processingOptions') self.iface.showOptionsDialog(self.iface.mainWindow(), currentPage='processingOptions')
def unload(self): def unload(self):
for connection in self._gui_connections:
self.disconnect(connection)
self._gui_connections = []
self.toolbox.setVisible(False) self.toolbox.setVisible(False)
self.iface.removeDockWidget(self.toolbox) self.iface.removeDockWidget(self.toolbox)
self.iface.attributesToolBar().removeAction(self.toolboxAction) self.iface.attributesToolBar().removeAction(self.toolboxAction)