From 4c34871f0aed14fe3f6390ff47d352300f6484f5 Mon Sep 17 00:00:00 2001 From: volaya Date: Mon, 18 Jan 2016 14:16:31 +0100 Subject: [PATCH] [processing] fixed problems when opening/removing layers while alg dialog is open --- .../algs/gdal/GdalAlgorithmDialog.py | 4 +- .../plugins/processing/gui/AlgorithmDialog.py | 11 +++ .../processing/gui/MultipleInputPanel.py | 13 ++++ .../plugins/processing/gui/ParametersPanel.py | 73 +++++++++++++++++-- .../plugins/processing/tools/dataobjects.py | 29 ++++---- 5 files changed, 110 insertions(+), 20 deletions(-) diff --git a/python/plugins/processing/algs/gdal/GdalAlgorithmDialog.py b/python/plugins/processing/algs/gdal/GdalAlgorithmDialog.py index 3f4b2020f46..cc334180193 100644 --- a/python/plugins/processing/algs/gdal/GdalAlgorithmDialog.py +++ b/python/plugins/processing/algs/gdal/GdalAlgorithmDialog.py @@ -25,7 +25,7 @@ __copyright__ = '(C) 2015, Victor Olaya' __revision__ = '$Format:%H$' - +from qgis.core import * from PyQt4.QtGui import * from processing.gui.AlgorithmDialog import AlgorithmDialog from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase @@ -55,6 +55,8 @@ class GdalAlgorithmDialog(AlgorithmDialog): self.mainWidget.parametersHaveChanged() + QgsMapLayerRegistry.instance().layerWasAdded.connect(self.mainWidget.layerAdded) + QgsMapLayerRegistry.instance().layersWillBeRemoved.connect(self.mainWidget.layersWillBeRemoved) class GdalParametersPanel(ParametersPanel): diff --git a/python/plugins/processing/gui/AlgorithmDialog.py b/python/plugins/processing/gui/AlgorithmDialog.py index f800f8dafa7..727ad3f4d66 100644 --- a/python/plugins/processing/gui/AlgorithmDialog.py +++ b/python/plugins/processing/gui/AlgorithmDialog.py @@ -29,6 +29,8 @@ from PyQt4.QtCore import Qt from PyQt4.QtGui import QMessageBox, QApplication, QCursor, QColor, QPalette, QPushButton, QWidget,\ QVBoxLayout +from qgis.core import * + from processing.core.ProcessingLog import ProcessingLog from processing.core.ProcessingConfig import ProcessingConfig @@ -81,6 +83,10 @@ class AlgorithmDialog(AlgorithmDialogBase): cornerWidget.setLayout(layout) self.tabWidget.setCornerWidget(cornerWidget) + QgsMapLayerRegistry.instance().layerWasAdded.connect(self.mainWidget.layerAdded) + QgsMapLayerRegistry.instance().layersWillBeRemoved.connect(self.mainWidget.layersWillBeRemoved) + + def runAsBatch(self): dlg = BatchAlgorithmDialog(self.alg) dlg.show() @@ -256,3 +262,8 @@ class AlgorithmDialog(AlgorithmDialogBase): self.setInfo( self.tr('HTML output has been generated by this algorithm.' '\nOpen the results dialog to check it.')) + + def closeEvent(self, evt): + QgsMapLayerRegistry.instance().layerWasAdded.disconnect(self.mainWidget.layerAdded) + QgsMapLayerRegistry.instance().layersWillBeRemoved.disconnect(self.mainWidget.layersWillBeRemoved) + super(AlgorithmDialog, self).closeEvent(evt) diff --git a/python/plugins/processing/gui/MultipleInputPanel.py b/python/plugins/processing/gui/MultipleInputPanel.py index e0660021ae8..fc63aa0cbb0 100644 --- a/python/plugins/processing/gui/MultipleInputPanel.py +++ b/python/plugins/processing/gui/MultipleInputPanel.py @@ -73,3 +73,16 @@ class MultipleInputPanel(BASE, WIDGET): self.leText.setText( self.tr('%d elements selected') % len(self.selectedoptions)) self.selectionChanged.emit() + + def updateForOptions(self, options): + selectedoptions = [] + selected = [self.options[i] for i in self.selectedoptions] + for sel in selected: + try: + idx = options.index(sel) + selectedoptions.append(idx) + except ValueError: + pass + self.options = options + self.setSelectedItems(selectedoptions) + diff --git a/python/plugins/processing/gui/ParametersPanel.py b/python/plugins/processing/gui/ParametersPanel.py index 314684e3504..27dc9d8ef7c 100644 --- a/python/plugins/processing/gui/ParametersPanel.py +++ b/python/plugins/processing/gui/ParametersPanel.py @@ -10,8 +10,7 @@ Email : volayaf at gmail dot com otb at c-s dot fr (CS SI) Contributors : Victor Olaya - Alexia Mondot (CS SI) - managing the new parameter - ParameterMultipleExternalInput + *************************************************************************** * * * This program is free software; you can redistribute it and/or modify * @@ -33,6 +32,8 @@ __revision__ = '$Format:%H$' import os import locale +from qgis.core import * + from PyQt4 import uic from PyQt4.QtCore import QCoreApplication, QVariant from PyQt4.QtGui import QWidget, QLayout, QVBoxLayout, QHBoxLayout, QToolButton, QIcon, QLabel, QCheckBox, QComboBox, QLineEdit, QPlainTextEdit @@ -102,6 +103,70 @@ class ParametersPanel(BASE, WIDGET): self.initWidgets() + def layerAdded(self, layer): + if layer.type() == QgsMapLayer.VectorLayer: + for param in self.alg.parameters: + if param.hidden: + continue + if isinstance(param, ParameterVector): + if dataobjects.canUseVectorLayer(layer, param.shapetype): + widget = self.valueItems[param.name] + if isinstance(widget, InputLayerSelectorPanel): + widget = widget.cmbText + widget.addItem(self.getExtendedLayerName(layer), layer) + elif layer.type() == QgsMapLayer.RasterLayer and dataobjects.canUseRasterLayer(layer): + for param in self.alg.parameters: + if param.hidden: + continue + if isinstance(param, ParameterRaster): + widget = self.valueItems[param.name].cmbText + widget.addItem(self.getExtendedLayerName(layer), layer) + + self.updateMultipleInputs() + + def layersWillBeRemoved(self, layers): + for layer in layers: + self.layerRemoved(layer) + + def layerRemoved(self, layer): + layer = QgsMapLayerRegistry.instance().mapLayer(layer) + widget = None + if layer.type() == QgsMapLayer.VectorLayer: + for param in self.alg.parameters: + if param.hidden: + continue + if isinstance(param, ParameterVector): + widget = self.valueItems[param.name] + if isinstance(widget, InputLayerSelectorPanel): + widget = widget.cmbText + + elif layer.type() == QgsMapLayer.RasterLayer: + for param in self.alg.parameters: + if param.hidden: + continue + if isinstance(param, ParameterRaster): + widget = self.valueItems[param.name].cmbText + + if widget is not None: + idx = widget.findData(layer) + if idx != -1: + widget.removeItem(idx) + + self.updateMultipleInputs() + + def updateMultipleInputs(self): + for param in self.alg.parameters: + if isinstance(param, ParameterMultipleInput) and param.datatype != ParameterMultipleInput.TYPE_FILE: + if param.datatype == ParameterMultipleInput.TYPE_RASTER: + options = dataobjects.getRasterLayers(sorting=False) + elif param.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY: + options = dataobjects.getVectorLayers(sorting=False) + else: + options = dataobjects.getVectorLayers([param.datatype], sorting=False) + opts = [self.getExtendedLayerName(opt) for opt in options] + widget = self.valueItems[param.name] + widget.updateForOptions(opts) + def initWidgets(self): #tooltips = self.alg.getParameterDescriptions() @@ -304,9 +369,7 @@ class ParametersPanel(BASE, WIDGET): options = dataobjects.getVectorLayers(sorting=False) else: options = dataobjects.getVectorLayers([param.datatype], sorting=False) - opts = [] - for opt in options: - opts.append(self.getExtendedLayerName(opt)) + opts = [self.getExtendedLayerName(opt) for opt in options] item = MultipleInputPanel(opts) elif isinstance(param, ParameterNumber): item = NumberInputPanel(param.default, param.min, param.max, diff --git a/python/plugins/processing/tools/dataobjects.py b/python/plugins/processing/tools/dataobjects.py index 8ab290b5b72..2cce2a304ff 100644 --- a/python/plugins/processing/tools/dataobjects.py +++ b/python/plugins/processing/tools/dataobjects.py @@ -74,13 +74,7 @@ def getSupportedOutputTableExtensions(): def getRasterLayers(sorting=True): layers = QgsProject.instance().layerTreeRoot().findLayers() - raster = [] - - for layer in layers: - mapLayer = layer.layer() - if mapLayer.type() == QgsMapLayer.RasterLayer: - if mapLayer.providerType() == 'gdal': # only gdal file-based layers - raster.append(mapLayer) + raster = [lay.layer() for lay in layers if lay.layer() is not None and canUseRasterLayer(lay.layer())] if sorting: return sorted(raster, key=lambda layer: layer.name().lower()) else: @@ -89,18 +83,25 @@ def getRasterLayers(sorting=True): def getVectorLayers(shapetype=[-1], sorting=True): layers = QgsProject.instance().layerTreeRoot().findLayers() - vector = [] - for layer in layers: - mapLayer = layer.layer() - if mapLayer.type() == QgsMapLayer.VectorLayer and mapLayer.dataProvider().name() != "grass": - if (mapLayer.hasGeometryType() and - (shapetype == ALL_TYPES or mapLayer.geometryType() in shapetype)): - vector.append(mapLayer) + vector = [lay.layer() for lay in layers if canUseVectorLayer(lay.layer(), shapetype)] if sorting: return sorted(vector, key=lambda layer: layer.name().lower()) else: return vector +def canUseVectorLayer(layer, shapetype): + if layer.type() == QgsMapLayer.VectorLayer and layer.dataProvider().name() != "grass": + if (layer.hasGeometryType() and + (shapetype == ALL_TYPES or layer.geometryType() in shapetype)): + return True + return False + +def canUseRasterLayer(layer): + if layer.type() == QgsMapLayer.RasterLayer: + if layer.providerType() == 'gdal': # only gdal file-based layers + return True + + return False def getAllLayers(): layers = []