From cdadc701ee4f0e9ee44256578110c8f9aa3b825a Mon Sep 17 00:00:00 2001 From: Alexia Mondot Date: Fri, 17 Jan 2014 19:01:08 +0100 Subject: [PATCH] add ParameterMultipleExternalInput parameter type --- .../gui/AlgorithmExecutionDialog.py | 15 +++ .../gui/MultipleExternalInputDialog.py | 111 ++++++++++++++++++ .../gui/MultipleExternalInputPanel.py | 75 ++++++++++++ .../plugins/processing/gui/ParametersPanel.py | 8 ++ .../processing/parameters/ParameterFactory.py | 12 +- .../ParameterMultipleExternalInput.py | 106 +++++++++++++++++ 6 files changed, 326 insertions(+), 1 deletion(-) create mode 100644 python/plugins/processing/gui/MultipleExternalInputDialog.py create mode 100644 python/plugins/processing/gui/MultipleExternalInputPanel.py create mode 100644 python/plugins/processing/parameters/ParameterMultipleExternalInput.py diff --git a/python/plugins/processing/gui/AlgorithmExecutionDialog.py b/python/plugins/processing/gui/AlgorithmExecutionDialog.py index f0469b0d9b7..a2935efe86b 100644 --- a/python/plugins/processing/gui/AlgorithmExecutionDialog.py +++ b/python/plugins/processing/gui/AlgorithmExecutionDialog.py @@ -6,7 +6,11 @@ --------------------- Date : August 2012 Copyright : (C) 2012 by Victor Olaya + (C) 2013 by CS Systemes d'information (CS SI) 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 * @@ -50,6 +54,7 @@ from processing.parameters.ParameterFile import ParameterFile from processing.parameters.ParameterCrs import ParameterCrs from processing.parameters.ParameterExtent import ParameterExtent from processing.parameters.ParameterString import ParameterString +from processing.parameters.ParameterMultipleExternalInput import ParameterMultipleExternalInput from processing.outputs.OutputRaster import OutputRaster from processing.outputs.OutputVector import OutputVector from processing.outputs.OutputTable import OutputTable @@ -162,6 +167,13 @@ class AlgorithmExecutionDialog(QtGui.QDialog): return True def setParamValue(self, param, widget): + """ + set the .value of the parameter according to the given widget + the way to get the value is different for each value, + so there is a code for each kind of parameter + + param : -il or -method ... + """ if isinstance(param, ParameterRaster): return param.setValue(widget.getValue()) elif isinstance(param, (ParameterVector, ParameterTable)): @@ -188,6 +200,9 @@ class AlgorithmExecutionDialog(QtGui.QDialog): for index in widget.selectedoptions: value.append(options[index]) return param.setValue(value) + elif isinstance(param, ParameterMultipleExternalInput): + value = widget.selectedoptions + return param.setValue(value) elif isinstance(param, (ParameterNumber, ParameterFile, ParameterCrs, ParameterExtent)): return param.setValue(widget.getValue()) diff --git a/python/plugins/processing/gui/MultipleExternalInputDialog.py b/python/plugins/processing/gui/MultipleExternalInputDialog.py new file mode 100644 index 00000000000..4bea23101fa --- /dev/null +++ b/python/plugins/processing/gui/MultipleExternalInputDialog.py @@ -0,0 +1,111 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + MultipleExternalInputDialog.py + --------------------- + Date : August 2012 + Copyright : (C) 2012 by Victor Olaya + (C) 2013 by CS Systemes d'information (CS SI) + Email : volayaf at gmail dot com + otb at c-s dot fr (CS SI) + Contributors : Victor Olaya - basis from MultipleInputDialog + Alexia Mondot (CS SI) - new parameter +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = 'Victor Olaya' +__date__ = 'August 2012' +__copyright__ = '(C) 2012, Victor Olaya' +# This will get replaced with a git SHA1 when you do a git archive +__revision__ = '$Format:%H$' + +from PyQt4 import QtCore, QtGui +import os + +class MultipleExternalInputDialog(QtGui.QDialog): + def __init__(self, selectedoptions): + self.selectedoptions = selectedoptions + self.options=selectedoptions + QtGui.QDialog.__init__(self) + self.setModal(True) + self.setupUi() + self.selectedoptions = None + + def setupUi(self): + self.resize(381, 320) + self.setWindowTitle("Multiple selection") + self.horizontalLayout = QtGui.QHBoxLayout(self) + self.horizontalLayout.setSpacing(2) + self.horizontalLayout.setMargin(0) + self.buttonBox = QtGui.QDialogButtonBox() + self.buttonBox.setOrientation(QtCore.Qt.Vertical) + self.buttonBox.setStandardButtons(QtGui.QDialogButtonBox.Cancel|QtGui.QDialogButtonBox.Ok) + self.buttonPlus = QtGui.QPushButton("+") + self.buttonBox.addButton(self.buttonPlus, QtGui.QDialogButtonBox.ActionRole) + self.buttonMoins = QtGui.QPushButton("-") + self.buttonBox.addButton(self.buttonMoins, QtGui.QDialogButtonBox.ActionRole) + self.table = QtGui.QTableWidget() + self.table.setColumnCount(1) + self.table.setColumnWidth(0,270) + self.table.verticalHeader().setVisible(False) + self.table.horizontalHeader().setVisible(False) + self.table.horizontalHeader().setResizeMode(QtGui.QHeaderView.Stretch) + self.horizontalLayout.addWidget(self.table) + self.horizontalLayout.addWidget(self.buttonBox) + self.setLayout(self.horizontalLayout) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("accepted()"), self.okPressed) + QtCore.QObject.connect(self.buttonBox, QtCore.SIGNAL("rejected()"), self.cancelPressed) + QtCore.QObject.connect(self.buttonPlus, QtCore.SIGNAL("clicked()"), self.addFile) + QtCore.QObject.connect(self.buttonMoins, QtCore.SIGNAL("clicked()"), self.removeFile) + QtCore.QMetaObject.connectSlotsByName(self) + + def setTableContent(self): + # "self.options :", ['/temp/confmat1-1.csv', '/temp/confmat2-1.csv'] + self.table.setRowCount(len(self.options)) + for i in range(len(self.options)): + item = QtGui.QLabel() + item.setText(self.options[i]) + self.table.setCellWidget(i,0, item) + + def okPressed(self): + self.selectedoptions = [] + self.selectedoptions = self.options + # "self.selectedoptions :", ['/temp/confmat1-1.csv', '/temp/confmat2-1.csv'] + self.close() + + def cancelPressed(self): + self.selectedoptions = None + self.close() + + def addFile(self): + settings = QtCore.QSettings() + lastfolder = settings.value("processingFilesLastFolder") + if lastfolder : + path = lastfolder + else : + path = QtCore.QDir.currentPath() + + filesOpened = QtGui.QFileDialog.getOpenFileNames( None, "Select the file(s) to use", path, "All files (*.*)" ) + + lastfile = "" + for item in filesOpened: + self.options.append( str(item) ) + lastfile=item + + self.setTableContent() + folder = os.path.dirname( str( lastfile ) ) + settings.setValue("processingFilesLastFolder", folder) + + def removeFile(self): + indexRow = self.table.currentRow() + itemToRemove = self.options[indexRow] + self.options.remove(itemToRemove) + self.setTableContent() diff --git a/python/plugins/processing/gui/MultipleExternalInputPanel.py b/python/plugins/processing/gui/MultipleExternalInputPanel.py new file mode 100644 index 00000000000..7f7c0dbee70 --- /dev/null +++ b/python/plugins/processing/gui/MultipleExternalInputPanel.py @@ -0,0 +1,75 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + MultipleExternalInputPanel.py + --------------------- + Date : August 2012 + Copyright : (C) 2012 by Victor Olaya + (C) 2013 by CS Systemes d'information (CS SI) + Email : volayaf at gmail dot com + otb at c-s dot fr (CS SI) + Contributors : Victor Olaya - basis from MultipleInputPanel + Alexia Mondot (CS SI) - adapt for a new parameter +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = 'Victor Olaya' +__date__ = 'August 2012' +__copyright__ = '(C) 2012, Victor Olaya' +# This will get replaced with a git SHA1 when you do a git archive +__revision__ = '$Format:%H$' + +from PyQt4 import QtCore, QtGui +from processing.gui.MultipleExternalInputDialog import MultipleExternalInputDialog + +class MultipleExternalInputPanel(QtGui.QWidget): + + def __init__(self, parent = None): + super(MultipleExternalInputPanel, self).__init__(parent) + self.selectedoptions = [] + self.horizontalLayout = QtGui.QHBoxLayout(self) + self.horizontalLayout.setSpacing(2) + self.horizontalLayout.setMargin(0) + self.label = QtGui.QLabel() + self.label.setText("0 elements selected") + self.label.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) + self.horizontalLayout.addWidget(self.label) + self.pushButton = QtGui.QPushButton() + self.pushButton.setText("...") + self.pushButton.clicked.connect(self.showSelectionDialog) + self.horizontalLayout.addWidget(self.pushButton) + self.setLayout(self.horizontalLayout) + + def setSelectedItems(self, selected): + #no checking is performed! + self.selectedoptions = selected + self.label.setText(str(len(self.selectedoptions)) + " elements selected") + + def showSelectionDialog(self): + #======================================================================= + # #If there is a datatype, we use it to create the list of options + # if self.datatype is not None: + # if self.datatype == ParameterMultipleInput.TYPE_RASTER: + # options = QGisLayers.getRasterLayers() + # elif self.datatype == ParameterMultipleInput.TYPE_VECTOR_ANY: + # options = QGisLayers.getVectorLayers() + # else: + # options = QGisLayers.getVectorLayers(self.datatype) + # opts = [] + # for opt in options: + # opts.append(opt.name()) + # self.options = opts + #======================================================================= + dlg = MultipleExternalInputDialog(self.selectedoptions) + dlg.exec_() + if dlg.selectedoptions != None: + self.selectedoptions = dlg.selectedoptions + self.label.setText(str(len(self.selectedoptions)) + " elements selected") diff --git a/python/plugins/processing/gui/ParametersPanel.py b/python/plugins/processing/gui/ParametersPanel.py index 78c568e06cb..c9e803c1f02 100644 --- a/python/plugins/processing/gui/ParametersPanel.py +++ b/python/plugins/processing/gui/ParametersPanel.py @@ -6,7 +6,11 @@ --------------------- Date : August 2012 Copyright : (C) 2012 by Victor Olaya + (C) 2013 by CS Systemes d'information (CS SI) 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 * @@ -42,6 +46,7 @@ from processing.gui.NumberInputPanel import NumberInputPanel from processing.gui.ExtentSelectionPanel import ExtentSelectionPanel from processing.gui.FileSelectionPanel import FileSelectionPanel from processing.gui.CrsSelectionPanel import CrsSelectionPanel +from processing.gui.MultipleExternalInputPanel import MultipleExternalInputPanel from processing.parameters.ParameterRaster import ParameterRaster from processing.parameters.ParameterVector import ParameterVector @@ -57,6 +62,7 @@ from processing.parameters.ParameterExtent import ParameterExtent from processing.parameters.ParameterFile import ParameterFile from processing.parameters.ParameterCrs import ParameterCrs from processing.parameters.ParameterString import ParameterString +from processing.parameters.ParameterMultipleExternalInput import ParameterMultipleExternalInput from processing.outputs.OutputRaster import OutputRaster from processing.outputs.OutputTable import OutputTable @@ -276,6 +282,8 @@ class ParametersPanel(QtGui.QWidget): for opt in options: opts.append(self.getExtendedLayerName(opt)) item = MultipleInputPanel(opts) + elif isinstance(param, ParameterMultipleExternalInput): + item = MultipleExternalInputPanel() elif isinstance(param, ParameterNumber): item = NumberInputPanel(param.default, param.min, param.max, param.isInteger) diff --git a/python/plugins/processing/parameters/ParameterFactory.py b/python/plugins/processing/parameters/ParameterFactory.py index 780b943de8f..2bc644d3e41 100644 --- a/python/plugins/processing/parameters/ParameterFactory.py +++ b/python/plugins/processing/parameters/ParameterFactory.py @@ -6,7 +6,11 @@ --------------------- Date : August 2012 Copyright : (C) 2012 by Victor Olaya + (C) 2013 by CS Systemes d'information (CS SI) 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 * @@ -39,12 +43,17 @@ from processing.parameters.ParameterFixedTable import ParameterFixedTable from processing.parameters.ParameterExtent import ParameterExtent from processing.parameters.ParameterFile import ParameterFile from processing.parameters.ParameterCrs import ParameterCrs +from processing.parameters.ParameterMultipleExternalInput import ParameterMultipleExternalInput class ParameterFactory: @staticmethod def getFromString(s): + """ + In : ParameterNumber|-nodatalabel|Label for the NoData class|None|None|0 + Out : returns the object from class pointed by s with information extracted from s + """ classes = [ ParameterBoolean, ParameterMultipleInput, @@ -60,7 +69,8 @@ class ParameterFactory: ParameterExtent, ParameterFile, ParameterCrs, + ParameterMultipleExternalInput ] for clazz in classes: if s.startswith(clazz().parameterName()): - return clazz().deserialize(s) + return clazz().deserialize(s) \ No newline at end of file diff --git a/python/plugins/processing/parameters/ParameterMultipleExternalInput.py b/python/plugins/processing/parameters/ParameterMultipleExternalInput.py new file mode 100644 index 00000000000..c5ddbb308fc --- /dev/null +++ b/python/plugins/processing/parameters/ParameterMultipleExternalInput.py @@ -0,0 +1,106 @@ +# -*- coding: utf-8 -*- + +""" +*************************************************************************** + ParameterMultipleExternalInput.py + --------------------- + Date : August 2012 + Copyright : (C) 2012 by Victor Olaya + (C) 2013 by CS Systemes d'information (CS SI) + Email : volayaf at gmail dot com + otb at c-s dot fr (CS SI) + Contributors : Victor Olaya - basis from ParameterMultipleInput + Alexia Mondot (CS SI) - managing the new parameter ParameterMultipleExternalInput +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +__author__ = 'Victor Olaya' +__date__ = 'August 2012' +__copyright__ = '(C) 2012, Victor Olaya' +# This will get replaced with a git SHA1 when you do a git archive +__revision__ = '$Format:%H$' + +from processing.parameters.ParameterDataObject import ParameterDataObject +from processing.core.QGisLayers import QGisLayers +from qgis.core import * +from processing.core.LayerExporter import LayerExporter + +class ParameterMultipleExternalInput(ParameterDataObject): + '''A parameter representing several data objects. + Its value is a string with substrings separated by semicolons, each of which + represents the data source location of each element''' + + exported = None + + def __init__(self, name="", description="", optional = False): + ParameterDataObject.__init__(self, name, description) + self.datatype = None # to delete + self.optional = optional + self.value = None + self.exported = None + self.default="" + + def setValue(self, obj): + if isinstance(obj, list): + if len(obj) == 0: + if self.optional: + return True + else: + return False + s = "" + idx = 0 + for filename in obj: + s += filename + if idx < len(obj) - 1: + s+=" " + idx=idx+1; + self.value = s; + return True + + + def getSafeExportedLayers(self): + '''Returns not the value entered by the user, but a string with semicolon-separated filenames + which contains the data of the selected layers, but saved in a standard format (currently + shapefiles for vector layers and GeoTiff for raster) so that they can be opened by most + external applications. + If there is a selection and QGIS is configured to use just the selection, if exports + the layer even if it is already in a suitable format. + Works only if the layer represented by the parameter value is currently loaded in QGIS. + Otherwise, it will not perform any export and return the current value string. + If the current value represents a layer in a suitable format, it does no export at all + and returns that value. + Currently, it works just for vector layer. In the case of raster layers, it returns the + parameter value. + The layers are exported just the first time the method is called. The method can be called + several times and it will always return the same string, performing the export only the first time.''' + if self.exported: + return self.exported + self.exported = self.value + layers = self.value.split(";") + if layers == None or len(layers) == 0: + return self.value + + return layers + + + + def serialize(self): + return self.__module__.split(".")[-1] + "|" + self.name + "|" + self.description + "|" + str(self.optional) + + def deserialize(self, s): + """ + in : string : ParameterNumber|-nodatalabel|Label for the NoData class|None|None|0 + returns the current class object from extracted information from s + """ + tokens = s.split("|") + return ParameterMultipleExternalInput(tokens[1], tokens[2], tokens[3] == str(True)) + + def getAsScriptCode(self): + return "##" + self.name