Skip to content

Commit ef59d0c

Browse files
committed
Port parameter checking to c++
1 parent a23a6ac commit ef59d0c

22 files changed

+1197
-553
lines changed

python/core/processing/qgsprocessingalgorithm.sip

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ class QgsProcessingAlgorithm
139139
:rtype: bool
140140
%End
141141

142+
virtual bool checkParameterValues( const QVariantMap &parameters,
143+
QgsProcessingContext &context, QString *message /Out/ = 0 ) const;
144+
%Docstring
145+
Checks the supplied ``parameter`` values to verify that they satisfy the requirements
146+
of this algorithm in the supplied ``context``. The ``message`` parameter will be
147+
filled with explanatory text if validation fails.
148+
Overridden implementations should also check this base class implementation.
149+
:return: true if parameters are acceptable for the algorithm.
150+
:rtype: bool
151+
%End
152+
142153
QgsProcessingProvider *provider() const;
143154
%Docstring
144155
Returns the provider to which this algorithm belongs.

python/core/processing/qgsprocessingparameters.sip

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,13 @@ class QgsProcessingParameterDefinition
168168
@see flags()
169169
%End
170170

171+
virtual bool checkValueIsAcceptable( const QVariant &input ) const;
172+
%Docstring
173+
Checks whether the specified ``input`` value is acceptable for the
174+
parameter. Returns true if the value can be accepted.
175+
:rtype: bool
176+
%End
177+
171178
protected:
172179

173180

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

358365
virtual QString type() const;
359-
360366
};
361367

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

422428
virtual QString type() const;
423429

424-
425430
};
426431

427432

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

446451
virtual QString type() const;
452+
virtual bool checkValueIsAcceptable( const QVariant &input ) const;
453+
447454

448455
};
449456

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

474481
virtual QString type() const;
482+
virtual bool checkValueIsAcceptable( const QVariant &input ) const;
483+
475484

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

524533
virtual QString type() const;
534+
virtual bool checkValueIsAcceptable( const QVariant &input ) const;
535+
525536

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

592603
virtual QString type() const;
604+
virtual bool checkValueIsAcceptable( const QVariant &input ) const;
605+
593606

594607
QgsProcessingParameterDefinition::LayerType layerType() const;
595608
%Docstring
@@ -602,6 +615,21 @@ class QgsProcessingParameterMultipleLayers : QgsProcessingParameterDefinition
602615
%Docstring
603616
Sets the layer ``type`` for layers acceptable by the parameter.
604617
.. seealso:: layerType()
618+
%End
619+
620+
int minimumNumberInputs() const;
621+
%Docstring
622+
Returns the minimum number of layers required for the parameter. If the return value is < 1
623+
then the parameter accepts any number of layers.
624+
.. seealso:: setMinimumNumberInputs()
625+
:rtype: int
626+
%End
627+
628+
void setMinimumNumberInputs( int minimum );
629+
%Docstring
630+
Sets the ``minimum`` number of layers required for the parameter. The minimum must be >= 1
631+
if the parameter is not optional.
632+
.. seealso:: minimumNumberInputs()
605633
%End
606634

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

638666
virtual QString type() const;
667+
virtual bool checkValueIsAcceptable( const QVariant &input ) const;
668+
639669

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

701731
virtual QString type() const;
732+
virtual bool checkValueIsAcceptable( const QVariant &input ) const;
733+
702734

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

760792
virtual QString type() const;
793+
virtual bool checkValueIsAcceptable( const QVariant &input ) const;
794+
761795

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

913947
virtual QString type() const;
948+
virtual bool checkValueIsAcceptable( const QVariant &input ) const;
949+
914950

915951
QString parentLayerParameter() const;
916952
%Docstring

python/plugins/processing/algs/gdal/GdalAlgorithmDialog.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,6 @@ def parametersHaveChanged(self):
115115
commands = [c for c in commands if c not in ['cmd.exe', '/C ']]
116116
self.text.setPlainText(" ".join(commands))
117117
except AlgorithmDialogBase.InvalidParameterValue as e:
118-
self.text.setPlainText(self.tr("Invalid value for parameter '{0}'").format(e.parameter.description))
118+
self.text.setPlainText(self.tr("Invalid value for parameter '{0}'").format(e.parameter.description()))
119119
except:
120120
self.text.setPlainText("")

python/plugins/processing/algs/grass7/Grass7Algorithm.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636
from qgis.core import (QgsRasterLayer,
3737
QgsApplication,
3838
QgsProcessingUtils,
39-
QgsMessageLog)
39+
QgsMessageLog,
40+
QgsProcessingAlgorithm)
4041
from qgis.utils import iface
4142

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

581-
def checkParameterValuesBeforeExecuting(self):
582+
def checkParameterValues(self, parameters, context):
582583
if self.module:
583584
if hasattr(self.module, 'checkParameterValuesBeforeExecuting'):
584585
func = getattr(self.module, 'checkParameterValuesBeforeExecuting')
585-
return func(self)
586-
return
586+
return func(self), None
587+
return super(Grass7Algorithm, self).checkParameterValues(parameters, context)

python/plugins/processing/algs/qgis/FieldPyculator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,6 @@ def processAlgorithm(self, parameters, context, feedback):
184184

185185
del writer
186186

187-
def checkParameterValuesBeforeExecuting(self):
187+
def checkParameterValues(self, parameters, context):
188188
# TODO check that formula is correct and fields exist
189-
pass
189+
return super(FieldsPyculator, self).checkParameterValues(parameters, context)

python/plugins/processing/algs/qgis/FieldsCalculator.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,11 +164,12 @@ def processAlgorithm(self, parameters, context, feedback):
164164
self.tr('An error occurred while evaluating the calculation '
165165
'string:\n{0}').format(error))
166166

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

173174
def createCustomParametersWidget(self, parent):
174175
return FieldsCalculatorDialog(self)

python/plugins/processing/algs/qgis/ui/FieldsCalculatorDialog.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,8 +209,10 @@ def getParamValues(self):
209209
parameters['FORMULA'] = self.builder.expressionText()
210210
parameters['OUTPUT_LAYER'] = self.leOutputFile.text().strip() or None
211211

212-
msg = self.alg.checkParameterValuesBeforeExecuting()
213-
if msg:
212+
context = dataobjects.createContext()
213+
214+
ok, msg = self.alg.checkParameterValues(parameters, context)
215+
if not ok:
214216
QMessageBox.warning(
215217
self, self.tr('Unable to execute algorithm'), msg)
216218
return {}

python/plugins/processing/algs/saga/SagaAlgorithm.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -342,17 +342,16 @@ def exportRasterLayer(self, source):
342342
sessionExportedLayers[source] = destFilename
343343
return 'io_gdal 0 -TRANSFORM 1 -RESAMPLING 0 -GRIDS "' + destFilename + '" -FILES "' + source + '"'
344344

345-
def checkParameterValuesBeforeExecuting(self):
345+
def checkParameterValues(self, parameters, context):
346346
"""
347347
We check that there are no multiband layers, which are not
348348
supported by SAGA, and that raster layers have the same grid extent
349349
"""
350350
extent = None
351-
context = dataobjects.createContext()
352-
for param in self.parameters:
351+
for param in self.parameterDefinitions():
353352
files = []
354353
if isinstance(param, ParameterRaster):
355-
files = [param.value]
354+
files = [parameters[param.name()]]
356355
elif (isinstance(param, ParameterMultipleInput) and
357356
param.datatype == dataobjects.TYPE_RASTER):
358357
if param.value is not None:
@@ -362,12 +361,13 @@ def checkParameterValuesBeforeExecuting(self):
362361
if layer is None:
363362
continue
364363
if layer.bandCount() > 1:
365-
return self.tr('Input layer {0} has more than one band.\n'
366-
'Multiband layers are not supported by SAGA').format(layer.name())
364+
return False, self.tr('Input layer {0} has more than one band.\n'
365+
'Multiband layers are not supported by SAGA').format(layer.name())
367366
if not self.allowUnmatchingGridExtents:
368367
if extent is None:
369368
extent = (layer.extent(), layer.height(), layer.width())
370369
else:
371370
extent2 = (layer.extent(), layer.height(), layer.width())
372371
if extent != extent2:
373-
return self.tr("Input layers do not have the same grid extent.")
372+
return False, self.tr("Input layers do not have the same grid extent.")
373+
return super(SagaAlgorithm, self).checkParameterValues(parameters, context)

python/plugins/processing/core/GeoAlgorithm.py

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -90,18 +90,6 @@ def getCustomModelerParametersDialog(self, modelAlg, algName=None):
9090
"""
9191
return None
9292

93-
def checkParameterValuesBeforeExecuting(self):
94-
"""If there is any check to do before launching the execution
95-
of the algorithm, it should be done here.
96-
97-
If values are not correct, a message should be returned
98-
explaining the problem.
99-
100-
This check is called from the parameters dialog, and also when
101-
calling from the console.
102-
"""
103-
return None
104-
10593
def processBeforeAddingToModeler(self, alg, model):
10694
"""Add here any task that has to be performed before adding an algorithm
10795
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):
150138
QgsMessageLog.logMessage('\n'.join(lines), self.tr('Processing'), QgsMessageLog.CRITICAL)
151139
raise GeoAlgorithmExecutionException(str(e) + self.tr('\nSee log for more details'), lines, e)
152140

153-
def _checkParameterValuesBeforeExecuting(self, context=None):
154-
if context is None:
155-
context = dataobjects.createContext()
156-
for param in self.parameters:
157-
if isinstance(param, (ParameterRaster, ParameterVector,
158-
ParameterMultipleInput)):
159-
if param.value:
160-
if isinstance(param, ParameterMultipleInput):
161-
inputlayers = param.value.split(';')
162-
else:
163-
inputlayers = [param.value]
164-
for inputlayer in inputlayers:
165-
obj = QgsProcessingUtils.mapLayerFromString(inputlayer, context)
166-
if obj is None:
167-
return "Wrong parameter value: " + param.value
168-
return self.checkParameterValuesBeforeExecuting()
169-
170141
def runPostExecutionScript(self, feedback):
171142
scriptFile = ProcessingConfig.getSetting(
172143
ProcessingConfig.POST_EXECUTION_SCRIPT)

python/plugins/processing/core/Processing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ def runAlgorithm(algOrName, onFinish, *args, **kwargs):
204204
else:
205205
context = dataobjects.createContext()
206206

207-
msg = alg._checkParameterValuesBeforeExecuting(context)
208-
if msg:
207+
ok, msg = alg.checkParameterValues(parameters, context)
208+
if not ok:
209209
# fix_print_with_import
210210
print('Unable to execute algorithm\n' + str(msg))
211211
QgsMessageLog.logMessage(Processing.tr('Unable to execute algorithm\n{0}').format(msg),

python/plugins/processing/gui/AlgorithmDialog.py

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -101,18 +101,15 @@ def getParamValues(self):
101101
continue
102102
if not param.isDestination():
103103
wrapper = self.mainWidget.wrappers[param.name()]
104+
value = None
104105
if wrapper.widget:
105106
value = wrapper.value()
106107
parameters[param.name()] = value
107108

108-
#TODO
109-
#if not self.setParamValue(param, wrapper):
110-
# raise AlgorithmDialogBase.InvalidParameterValue(param, wrapper.widget)
109+
if not param.checkValueIsAcceptable(value):
110+
raise AlgorithmDialogBase.InvalidParameterValue(param, wrapper.widget)
111111
else:
112112
parameters[param.name()] = self.mainWidget.outputWidgets[param.name()].getValue()
113-
# TODO
114-
#if isinstance(output, (OutputRaster, OutputVector, OutputTable)):
115-
# output.open = self.mainWidget.checkBoxes[param.name()].isChecked()
116113

117114
return parameters
118115

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

128125
return layer_outputs
129126

130-
def setParamValue(self, param, wrapper):
131-
if wrapper.widget:
132-
return param.setValue(wrapper.value())
133-
else:
134-
return True
135-
136127
def checkExtentCRS(self):
137128
unmatchingCRS = False
138129
hasExtent = False
@@ -199,9 +190,7 @@ def accept(self):
199190
QMessageBox.No)
200191
if reply == QMessageBox.No:
201192
return
202-
# TODO
203-
#msg = self.alg._checkParameterValuesBeforeExecuting(context)
204-
msg = None
193+
ok, msg = self.alg.checkParameterValues(parameters, context)
205194
if msg:
206195
QMessageBox.warning(
207196
self, self.tr('Unable to execute algorithm'), msg)
@@ -258,7 +247,7 @@ def accept(self):
258247
except:
259248
pass
260249
self.bar.clearWidgets()
261-
self.bar.pushMessage("", self.tr("Wrong or missing parameter value: {0}").format(e.parameter.description),
250+
self.bar.pushMessage("", self.tr("Wrong or missing parameter value: {0}").format(e.parameter.description()),
262251
level=QgsMessageBar.WARNING, duration=5)
263252

264253
def finish(self, result, context):

python/plugins/processing/gui/AlgorithmDialogBase.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,9 +222,6 @@ def setText(self, text):
222222
def getParamValues(self):
223223
return {}
224224

225-
def setParamValue(self, param, widget, alg=None):
226-
pass
227-
228225
def accept(self):
229226
pass
230227

python/plugins/processing/gui/BatchAlgorithmDialog.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ def accept(self):
7373
self.load = []
7474
self.canceled = False
7575

76+
context = dataobjects.createContext()
77+
7678
for row in range(self.mainWidget.tblParameters.rowCount()):
7779
col = 0
7880
parameters = {}
@@ -81,9 +83,9 @@ def accept(self):
8183
continue
8284
wrapper = self.mainWidget.wrappers[row][col]
8385
parameters[param.name()] = wrapper.value()
84-
if not self.mainWidget.setParamValue(param, wrapper, alg):
86+
if not param.checkValueIsAcceptable(wrapper.value(), context):
8587
self.bar.pushMessage("", self.tr('Wrong or missing parameter value: {0} (row {1})').format(
86-
param.description, row + 1),
88+
param.description(), row + 1),
8789
level=QgsMessageBar.WARNING, duration=5)
8890
self.algs = None
8991
return
@@ -122,8 +124,6 @@ def accept(self):
122124
except:
123125
pass
124126

125-
context = dataobjects.createContext()
126-
127127
for count, parameters in enumerate(self.alg_parameters):
128128
self.setText(self.tr('\nProcessing algorithm {0}/{1}...').format(count + 1, len(self.alg_parameters)))
129129
self.setInfo(self.tr('<b>Algorithm {0} starting...</b>').format(self.alg.displayName()))

0 commit comments

Comments
 (0)