Skip to content
Permalink
Browse files

Port parameter checking to c++

  • Loading branch information
nyalldawson committed Jun 5, 2017
1 parent a23a6ac commit ef59d0c4540e9f3204db0f790a4241a8b4f7ecec
@@ -139,6 +139,17 @@ class QgsProcessingAlgorithm
:rtype: bool
%End

virtual bool checkParameterValues( const QVariantMap &parameters,
QgsProcessingContext &context, QString *message /Out/ = 0 ) const;
%Docstring
Checks the supplied ``parameter`` values to verify that they satisfy the requirements
of this algorithm in the supplied ``context``. The ``message`` parameter will be
filled with explanatory text if validation fails.
Overridden implementations should also check this base class implementation.
:return: true if parameters are acceptable for the algorithm.
:rtype: bool
%End

QgsProcessingProvider *provider() const;
%Docstring
Returns the provider to which this algorithm belongs.
@@ -168,6 +168,13 @@ class QgsProcessingParameterDefinition
@see flags()
%End

virtual bool checkValueIsAcceptable( const QVariant &input ) const;
%Docstring
Checks whether the specified ``input`` value is acceptable for the
parameter. Returns true if the value can be accepted.
:rtype: bool
%End

protected:


@@ -356,7 +363,6 @@ class QgsProcessingParameterBoolean : QgsProcessingParameterDefinition
%End

virtual QString type() const;

};

class QgsProcessingParameterCrs : QgsProcessingParameterDefinition
@@ -421,7 +427,6 @@ class QgsProcessingParameterExtent : QgsProcessingParameterDefinition

virtual QString type() const;


};


@@ -444,6 +449,8 @@ class QgsProcessingParameterPoint : QgsProcessingParameterDefinition
%End

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input ) const;


};

@@ -472,6 +479,8 @@ class QgsProcessingParameterFile : QgsProcessingParameterDefinition
%End

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input ) const;


Behavior behavior() const;
%Docstring
@@ -522,6 +531,8 @@ class QgsProcessingParameterMatrix : QgsProcessingParameterDefinition
%End

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input ) const;


QStringList headers() const;
%Docstring
@@ -590,6 +601,8 @@ class QgsProcessingParameterMultipleLayers : QgsProcessingParameterDefinition
%End

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input ) const;


QgsProcessingParameterDefinition::LayerType layerType() const;
%Docstring
@@ -602,6 +615,21 @@ class QgsProcessingParameterMultipleLayers : QgsProcessingParameterDefinition
%Docstring
Sets the layer ``type`` for layers acceptable by the parameter.
.. seealso:: layerType()
%End

int minimumNumberInputs() const;
%Docstring
Returns the minimum number of layers required for the parameter. If the return value is < 1
then the parameter accepts any number of layers.
.. seealso:: setMinimumNumberInputs()
:rtype: int
%End

void setMinimumNumberInputs( int minimum );
%Docstring
Sets the ``minimum`` number of layers required for the parameter. The minimum must be >= 1
if the parameter is not optional.
.. seealso:: minimumNumberInputs()
%End

};
@@ -636,6 +664,8 @@ class QgsProcessingParameterNumber : QgsProcessingParameterDefinition
%End

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input ) const;


double minimum() const;
%Docstring
@@ -699,6 +729,8 @@ class QgsProcessingParameterRange : QgsProcessingParameterDefinition
%End

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input ) const;


QgsProcessingParameterNumber::Type dataType() const;
%Docstring
@@ -758,6 +790,8 @@ class QgsProcessingParameterEnum : QgsProcessingParameterDefinition
%End

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input ) const;


QStringList options() const;
%Docstring
@@ -911,6 +945,8 @@ class QgsProcessingParameterTableField : QgsProcessingParameterDefinition
%End

virtual QString type() const;
virtual bool checkValueIsAcceptable( const QVariant &input ) const;


QString parentLayerParameter() const;
%Docstring
@@ -115,6 +115,6 @@ def parametersHaveChanged(self):
commands = [c for c in commands if c not in ['cmd.exe', '/C ']]
self.text.setPlainText(" ".join(commands))
except AlgorithmDialogBase.InvalidParameterValue as e:
self.text.setPlainText(self.tr("Invalid value for parameter '{0}'").format(e.parameter.description))
self.text.setPlainText(self.tr("Invalid value for parameter '{0}'").format(e.parameter.description()))
except:
self.text.setPlainText("")
@@ -36,7 +36,8 @@
from qgis.core import (QgsRasterLayer,
QgsApplication,
QgsProcessingUtils,
QgsMessageLog)
QgsMessageLog,
QgsProcessingAlgorithm)
from qgis.utils import iface

from processing.core.GeoAlgorithm import GeoAlgorithm
@@ -578,9 +579,9 @@ def canExecute(self):
message = Grass7Utils.checkGrass7IsInstalled()
return not message, message

def checkParameterValuesBeforeExecuting(self):
def checkParameterValues(self, parameters, context):
if self.module:
if hasattr(self.module, 'checkParameterValuesBeforeExecuting'):
func = getattr(self.module, 'checkParameterValuesBeforeExecuting')
return func(self)
return
return func(self), None
return super(Grass7Algorithm, self).checkParameterValues(parameters, context)
@@ -184,6 +184,6 @@ def processAlgorithm(self, parameters, context, feedback):

del writer

def checkParameterValuesBeforeExecuting(self):
def checkParameterValues(self, parameters, context):
# TODO check that formula is correct and fields exist
pass
return super(FieldsPyculator, self).checkParameterValues(parameters, context)
@@ -164,11 +164,12 @@ def processAlgorithm(self, parameters, context, feedback):
self.tr('An error occurred while evaluating the calculation '
'string:\n{0}').format(error))

def checkParameterValuesBeforeExecuting(self):
def checkParameterValues(self, parameters, context):
newField = self.getParameterValue(self.NEW_FIELD)
fieldName = self.getParameterValue(self.FIELD_NAME).strip()
if newField and len(fieldName) == 0:
return self.tr('Field name is not set. Please enter a field name')
return super(FieldsCalculator, self).checkParameterValues(parameters, context)

def createCustomParametersWidget(self, parent):
return FieldsCalculatorDialog(self)
@@ -209,8 +209,10 @@ def getParamValues(self):
parameters['FORMULA'] = self.builder.expressionText()
parameters['OUTPUT_LAYER'] = self.leOutputFile.text().strip() or None

msg = self.alg.checkParameterValuesBeforeExecuting()
if msg:
context = dataobjects.createContext()

ok, msg = self.alg.checkParameterValues(parameters, context)
if not ok:
QMessageBox.warning(
self, self.tr('Unable to execute algorithm'), msg)
return {}
@@ -342,17 +342,16 @@ def exportRasterLayer(self, source):
sessionExportedLayers[source] = destFilename
return 'io_gdal 0 -TRANSFORM 1 -RESAMPLING 0 -GRIDS "' + destFilename + '" -FILES "' + source + '"'

def checkParameterValuesBeforeExecuting(self):
def checkParameterValues(self, parameters, context):
"""
We check that there are no multiband layers, which are not
supported by SAGA, and that raster layers have the same grid extent
"""
extent = None
context = dataobjects.createContext()
for param in self.parameters:
for param in self.parameterDefinitions():
files = []
if isinstance(param, ParameterRaster):
files = [param.value]
files = [parameters[param.name()]]
elif (isinstance(param, ParameterMultipleInput) and
param.datatype == dataobjects.TYPE_RASTER):
if param.value is not None:
@@ -362,12 +361,13 @@ def checkParameterValuesBeforeExecuting(self):
if layer is None:
continue
if layer.bandCount() > 1:
return self.tr('Input layer {0} has more than one band.\n'
'Multiband layers are not supported by SAGA').format(layer.name())
return False, self.tr('Input layer {0} has more than one band.\n'
'Multiband layers are not supported by SAGA').format(layer.name())
if not self.allowUnmatchingGridExtents:
if extent is None:
extent = (layer.extent(), layer.height(), layer.width())
else:
extent2 = (layer.extent(), layer.height(), layer.width())
if extent != extent2:
return self.tr("Input layers do not have the same grid extent.")
return False, self.tr("Input layers do not have the same grid extent.")
return super(SagaAlgorithm, self).checkParameterValues(parameters, context)
@@ -90,18 +90,6 @@ def getCustomModelerParametersDialog(self, modelAlg, algName=None):
"""
return None

def checkParameterValuesBeforeExecuting(self):
"""If there is any check to do before launching the execution
of the algorithm, it should be done here.
If values are not correct, a message should be returned
explaining the problem.
This check is called from the parameters dialog, and also when
calling from the console.
"""
return None

def processBeforeAddingToModeler(self, alg, model):
"""Add here any task that has to be performed before adding an algorithm
to a model, such as changing the value of a parameter depending on value
@@ -150,23 +138,6 @@ def execute(self, parameters, context=None, feedback=None, model=None):
QgsMessageLog.logMessage('\n'.join(lines), self.tr('Processing'), QgsMessageLog.CRITICAL)
raise GeoAlgorithmExecutionException(str(e) + self.tr('\nSee log for more details'), lines, e)

def _checkParameterValuesBeforeExecuting(self, context=None):
if context is None:
context = dataobjects.createContext()
for param in self.parameters:
if isinstance(param, (ParameterRaster, ParameterVector,
ParameterMultipleInput)):
if param.value:
if isinstance(param, ParameterMultipleInput):
inputlayers = param.value.split(';')
else:
inputlayers = [param.value]
for inputlayer in inputlayers:
obj = QgsProcessingUtils.mapLayerFromString(inputlayer, context)
if obj is None:
return "Wrong parameter value: " + param.value
return self.checkParameterValuesBeforeExecuting()

def runPostExecutionScript(self, feedback):
scriptFile = ProcessingConfig.getSetting(
ProcessingConfig.POST_EXECUTION_SCRIPT)
@@ -204,8 +204,8 @@ def runAlgorithm(algOrName, onFinish, *args, **kwargs):
else:
context = dataobjects.createContext()

msg = alg._checkParameterValuesBeforeExecuting(context)
if msg:
ok, msg = alg.checkParameterValues(parameters, context)
if not ok:
# fix_print_with_import
print('Unable to execute algorithm\n' + str(msg))
QgsMessageLog.logMessage(Processing.tr('Unable to execute algorithm\n{0}').format(msg),
@@ -101,18 +101,15 @@ def getParamValues(self):
continue
if not param.isDestination():
wrapper = self.mainWidget.wrappers[param.name()]
value = None
if wrapper.widget:
value = wrapper.value()
parameters[param.name()] = value

#TODO
#if not self.setParamValue(param, wrapper):
# raise AlgorithmDialogBase.InvalidParameterValue(param, wrapper.widget)
if not param.checkValueIsAcceptable(value):
raise AlgorithmDialogBase.InvalidParameterValue(param, wrapper.widget)
else:
parameters[param.name()] = self.mainWidget.outputWidgets[param.name()].getValue()
# TODO
#if isinstance(output, (OutputRaster, OutputVector, OutputTable)):
# output.open = self.mainWidget.checkBoxes[param.name()].isChecked()

return parameters

@@ -127,12 +124,6 @@ def getLayersToOpen(self):

return layer_outputs

def setParamValue(self, param, wrapper):
if wrapper.widget:
return param.setValue(wrapper.value())
else:
return True

def checkExtentCRS(self):
unmatchingCRS = False
hasExtent = False
@@ -199,9 +190,7 @@ def accept(self):
QMessageBox.No)
if reply == QMessageBox.No:
return
# TODO
#msg = self.alg._checkParameterValuesBeforeExecuting(context)
msg = None
ok, msg = self.alg.checkParameterValues(parameters, context)
if msg:
QMessageBox.warning(
self, self.tr('Unable to execute algorithm'), msg)
@@ -258,7 +247,7 @@ def accept(self):
except:
pass
self.bar.clearWidgets()
self.bar.pushMessage("", self.tr("Wrong or missing parameter value: {0}").format(e.parameter.description),
self.bar.pushMessage("", self.tr("Wrong or missing parameter value: {0}").format(e.parameter.description()),
level=QgsMessageBar.WARNING, duration=5)

def finish(self, result, context):
@@ -222,9 +222,6 @@ def setText(self, text):
def getParamValues(self):
return {}

def setParamValue(self, param, widget, alg=None):
pass

def accept(self):
pass

@@ -73,6 +73,8 @@ def accept(self):
self.load = []
self.canceled = False

context = dataobjects.createContext()

for row in range(self.mainWidget.tblParameters.rowCount()):
col = 0
parameters = {}
@@ -81,9 +83,9 @@ def accept(self):
continue
wrapper = self.mainWidget.wrappers[row][col]
parameters[param.name()] = wrapper.value()
if not self.mainWidget.setParamValue(param, wrapper, alg):
if not param.checkValueIsAcceptable(wrapper.value(), context):
self.bar.pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format(
param.description, row + 1),
param.description(), row + 1),
level=QgsMessageBar.WARNING, duration=5)
self.algs = None
return
@@ -122,8 +124,6 @@ def accept(self):
except:
pass

context = dataobjects.createContext()

for count, parameters in enumerate(self.alg_parameters):
self.setText(self.tr('\nProcessing algorithm {0}/{1}...').format(count + 1, len(self.alg_parameters)))
self.setInfo(self.tr('<b>Algorithm {0} starting...</b>').format(self.alg.displayName()))

0 comments on commit ef59d0c

Please sign in to comment.
You can’t perform that action at this time.