QGIS/python/plugins/processing/gui/ParametersPanel.py
Alexander Bruy bec113b1bc [processing] refactor algortim dialog
Now we have base class AlgorithmDialogBase for all algortims. Dialogs
for algorithms and batch processes should be created by subclassing this
base dialog and adding to it corresponding parameters panel.

ParametersPanel for single algorthm already updated to this approach.
2014-11-17 20:03:31 +02:00

364 lines
15 KiB
Python

# -*- coding: utf-8 -*-
"""
***************************************************************************
ParametersPanel.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
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$'
import os
import locale
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from processing.core.ProcessingConfig import ProcessingConfig
from processing.gui.OutputSelectionPanel import OutputSelectionPanel
from processing.gui.InputLayerSelectorPanel import InputLayerSelectorPanel
from processing.gui.FixedTablePanel import FixedTablePanel
from processing.gui.RangePanel import RangePanel
from processing.gui.MultipleInputPanel import MultipleInputPanel
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.core.parameters import ParameterRaster
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterTable
from processing.core.parameters import ParameterBoolean
from processing.core.parameters import ParameterTableField
from processing.core.parameters import ParameterSelection
from processing.core.parameters import ParameterFixedTable
from processing.core.parameters import ParameterRange
from processing.core.parameters import ParameterMultipleInput
from processing.core.parameters import ParameterNumber
from processing.core.parameters import ParameterExtent
from processing.core.parameters import ParameterFile
from processing.core.parameters import ParameterCrs
from processing.core.parameters import ParameterString
from processing.core.outputs import OutputRaster
from processing.core.outputs import OutputTable
from processing.core.outputs import OutputVector
from processing.tools import dataobjects
from processing.ui.ui_widgetParametersPanel import Ui_Form
class ParametersPanel(QWidget, Ui_Form):
NOT_SELECTED = QCoreApplication.translate('ParametersPanel', '[Not selected]')
def __init__(self, parent, alg):
QWidget.__init__(self)
self.setupUi(self)
self.grpAdvanced.hide()
self.layoutMain = self.scrollAreaWidgetContents.layout()
self.layoutAdvanced = self.grpAdvanced.layout()
self.parent = parent
self.alg = alg
self.valueItems = {}
self.labels = {}
self.widgets = {}
self.checkBoxes = {}
self.dependentItems = {}
self.iterateButtons = {}
self.initWidgets()
def initWidgets(self):
#tooltips = self.alg.getParameterDescriptions()
# If there are advanced parameters — show corresponding groupbox
for param in self.alg.parameters:
if param.isAdvanced:
self.grpAdvanced.show()
break
# Create widgets and put them in layouts
for param in self.alg.parameters:
if param.hidden:
continue
desc = param.description
if isinstance(param, ParameterExtent):
desc += self.tr(' (xmin, xmax, ymin, ymax)')
try:
if param.optional:
desc += self.tr(' [optional]')
except:
pass
widget = self.getWidgetFromParameter(param)
self.valueItems[param.name] = widget
if isinstance(param, ParameterVector) and \
not self.alg.allowOnlyOpenedLayers:
layout = QHBoxLayout()
layout.setSpacing(2)
layout.setMargin(0)
layout.addWidget(widget)
button = QToolButton()
icon = QIcon(
os.path.dirname(__file__) + '/../images/iterate.png')
button.setIcon(icon)
button.setToolTip(self.tr('Iterate over this layer'))
button.setCheckable(True)
layout.addWidget(button)
self.iterateButtons[param.name] = button
button.toggled.connect(self.buttonToggled)
widget = QWidget()
widget.setLayout(layout)
#~ if param.name in tooltips.keys():
#~ tooltip = tooltips[param.name]
#~ else:
#~ tooltip = param.description
#~ widget.setToolTip(tooltip)
if isinstance(param, ParameterBoolean):
widget.setText(desc)
if param.isAdvanced:
self.layoutAdvanced.addWidget(widget)
else:
self.layoutMain.insertWidget(
self.layoutMain.count() - 2, widget)
else:
label = QLabel(desc)
#label.setToolTip(tooltip)
self.labels[param.name] = label
if param.isAdvanced:
self.layoutAdvanced.addWidget(label)
self.layoutAdvanced.addWidget(widget)
else:
self.layoutMain.insertWidget(
self.layoutMain.count() - 2, label)
self.layoutMain.insertWidget(
self.layoutMain.count() - 2, widget)
self.widgets[param.name] = widget
for output in self.alg.outputs:
if output.hidden:
continue
label = QLabel(output.description)
widget = OutputSelectionPanel(output, self.alg)
self.layoutMain.insertWidget(self.layoutMain.count() - 1, label)
self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget)
if isinstance(output, (OutputRaster, OutputVector, OutputTable)):
check = QCheckBox()
check.setText(self.tr('Open output file after running algorithm'))
check.setChecked(True)
self.layoutMain.insertWidget(self.layoutMain.count() - 1, check)
self.checkBoxes[output.name] = check
self.valueItems[output.name] = widget
def buttonToggled(self, value):
if value:
sender = self.sender()
for button in self.iterateButtons.values():
if button is not sender:
button.setChecked(False)
def getExtendedLayerName(self, layer):
authid = layer.crs().authid()
if ProcessingConfig.getSetting(ProcessingConfig.SHOW_CRS_DEF) \
and authid is not None:
return '{} [{}]'.format(layer.name(), authid)
else:
return layer.name()
def getWidgetFromParameter(self, param):
# TODO Create Parameter widget class that holds the logic
# for creating a widget that belongs to the parameter.
if isinstance(param, ParameterRaster):
layers = dataobjects.getRasterLayers()
items = []
if param.optional:
items.append((self.NOT_SELECTED, None))
for layer in layers:
items.append((self.getExtendedLayerName(layer), layer))
item = InputLayerSelectorPanel(items, param)
elif isinstance(param, ParameterVector):
if self.somethingDependsOnThisParameter(param) or self.alg.allowOnlyOpenedLayers:
item = QComboBox()
layers = dataobjects.getVectorLayers(param.shapetype)
if param.optional:
item.addItem(self.NOT_SELECTED, None)
for layer in layers:
item.addItem(self.getExtendedLayerName(layer), layer)
item.currentIndexChanged.connect(self.updateDependentFields)
item.name = param.name
else:
layers = dataobjects.getVectorLayers(param.shapetype)
items = []
if param.optional:
items.append((self.NOT_SELECTED, None))
for layer in layers:
items.append((self.getExtendedLayerName(layer), layer))
# if already set, put first in list
for i,(name,layer) in enumerate(items):
if layer and layer.source() == param.value:
items.insert(0, items.pop(i))
item = InputLayerSelectorPanel(items, param)
elif isinstance(param, ParameterTable):
if self.somethingDependsOnThisParameter(param):
item = QComboBox()
layers = dataobjects.getTables()
if param.optional:
item.addItem(self.NOT_SELECTED, None)
for layer in layers:
item.addItem(layer.name(), layer)
item.currentIndexChanged.connect(self.updateDependentFields)
item.name = param.name
else:
layers = dataobjects.getTables()
items = []
if param.optional:
items.append((self.NOT_SELECTED, None))
for layer in layers:
items.append((layer.name(), layer))
# if already set, put first in list
for i,(name,layer) in enumerate(items):
if layer and layer.source() == param.value:
items.insert(0, items.pop(i))
item = InputLayerSelectorPanel(items, param)
elif isinstance(param, ParameterBoolean):
item = QCheckBox()
if param.default:
item.setChecked(True)
else:
item.setChecked(False)
elif isinstance(param, ParameterTableField):
item = QComboBox()
if param.parent in self.dependentItems:
items = self.dependentItems[param.parent]
else:
items = []
self.dependentItems[param.parent] = items
items.append(param.name)
parent = self.alg.getParameterFromName(param.parent)
if isinstance(parent, ParameterVector):
layers = dataobjects.getVectorLayers(parent.shapetype)
else:
layers = dataobjects.getTables()
if len(layers) > 0:
if param.optional:
item.addItem(self.tr('[not set]'))
item.addItems(self.getFields(layers[0], param.datatype))
elif isinstance(param, ParameterSelection):
item = QComboBox()
item.addItems(param.options)
item.setCurrentIndex(param.default)
elif isinstance(param, ParameterFixedTable):
item = FixedTablePanel(param)
elif isinstance(param, ParameterRange):
item = RangePanel(param)
elif isinstance(param, ParameterFile):
item = FileSelectionPanel(param.isFolder, param.ext)
elif isinstance(param, ParameterMultipleInput):
if param.datatype == ParameterMultipleInput.TYPE_FILE:
item = MultipleInputPanel(datatype=ParameterMultipleInput.TYPE_FILE)
else:
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 = []
for opt in options:
opts.append(self.getExtendedLayerName(opt))
item = MultipleInputPanel(opts)
elif isinstance(param, ParameterNumber):
item = NumberInputPanel(param.default, param.min, param.max,
param.isInteger)
elif isinstance(param, ParameterExtent):
item = ExtentSelectionPanel(self.parent, self.alg, param.default)
elif isinstance(param, ParameterCrs):
item = CrsSelectionPanel(param.default)
elif isinstance(param, ParameterString):
if param.multiline:
verticalLayout = QVBoxLayout()
verticalLayout.setSizeConstraint(
QLayout.SetDefaultConstraint)
textEdit = QPlainTextEdit()
textEdit.setPlainText(param.default)
verticalLayout.addWidget(textEdit)
item = textEdit
else:
item = QLineEdit()
item.setText(str(param.default))
else:
item = QLineEdit()
item.setText(str(param.default))
return item
def updateDependentFields(self):
sender = self.sender()
if not isinstance(sender, QComboBox):
return
if not sender.name in self.dependentItems:
return
layer = sender.itemData(sender.currentIndex())
children = self.dependentItems[sender.name]
for child in children:
widget = self.valueItems[child]
widget.clear()
if self.alg.getParameterFromName(child).optional:
widget.addItem(self.tr('[not set]'))
widget.addItems(self.getFields(layer,
self.alg.getParameterFromName(child).datatype))
def getFields(self, layer, datatype):
fieldTypes = []
if datatype == ParameterTableField.DATA_TYPE_STRING:
fieldTypes = [QVariant.String]
elif datatype == ParameterTableField.DATA_TYPE_NUMBER:
fieldTypes = [QVariant.Int, QVariant.Double]
fieldNames = set()
for field in layer.pendingFields():
if not fieldTypes or field.type() in fieldTypes:
fieldNames.add(unicode(field.name()))
return sorted(list(fieldNames), cmp=locale.strcoll)
def somethingDependsOnThisParameter(self, parent):
for param in self.alg.parameters:
if isinstance(param, ParameterTableField):
if param.parent == parent.name:
return True
return False