Skip to content

Commit

Permalink
Add framework for algorithm outputs
Browse files Browse the repository at this point in the history
This somewhat changes the meaning of outputs from processing 2.x.
In 2.x processing outputs were used both as a method of specifying
inputs to algorithms (file paths to destination layers created
by the algorithm) AND pure outputs (such as statistics calculated
by the algorithm).

This is now split. The old input-type-outputs (destination layers)
are now input parameters (since the parameter value IS an input to the
algorithm). To differentiate them from parameters indicating pure
input layers a new "isDestination()" method was added to
QgsProcessingParameterDefinition.

Output definitions are now purely indications of values CREATED
by the algorithms. Suitable candidates are the existing calculated
stats and actual file path/URI of any layers created by the algorithm.
Moving forward we should ensure all algorithms output as much
useful information as possible - e.g. number of features processed,
number of skipped features, count null geometries encountered, etc...
  • Loading branch information
nyalldawson committed Jun 5, 2017
1 parent fac8ca4 commit fb81176
Show file tree
Hide file tree
Showing 20 changed files with 600 additions and 44 deletions.
1 change: 1 addition & 0 deletions python/core/core.sip
Expand Up @@ -287,6 +287,7 @@
%Include processing/qgsprocessingalgorithm.sip
%Include processing/qgsprocessingcontext.sip
%Include processing/qgsprocessingfeedback.sip
%Include processing/qgsprocessingoutputs.sip
%Include processing/qgsprocessingparameters.sip
%Include processing/qgsprocessingprovider.sip
%Include processing/qgsprocessingregistry.sip
Expand Down
35 changes: 35 additions & 0 deletions python/core/processing/qgsprocessingalgorithm.sip
Expand Up @@ -124,6 +124,7 @@ class QgsProcessingAlgorithm
Returns an ordered list of parameter definitions utilized by the algorithm.
.. seealso:: addParameter()
.. seealso:: parameterDefinition()
.. seealso:: destinationParameterDefinitions()
:rtype: QgsProcessingParameterDefinitions
%End

Expand All @@ -142,6 +143,30 @@ class QgsProcessingAlgorithm
:rtype: int
%End

QgsProcessingParameterDefinitions destinationParameterDefinitions() const;
%Docstring
Returns a list of destination parameters definitions utilized by the algorithm.
.. seealso:: QgsProcessingParameterDefinition.isDestination()
.. seealso:: parameterDefinitions()
:rtype: QgsProcessingParameterDefinitions
%End

QgsProcessingOutputDefinitions outputDefinitions() const;
%Docstring
Returns an ordered list of output definitions utilized by the algorithm.
.. seealso:: addOutput()
.. seealso:: outputDefinition()
:rtype: QgsProcessingOutputDefinitions
%End

const QgsProcessingOutputDefinition *outputDefinition( const QString &name ) const;
%Docstring
Returns a matching output by ``name``. Matching is done in a case-insensitive
manner.
.. seealso:: outputDefinitions()
:rtype: QgsProcessingOutputDefinition
%End

virtual QVariantMap run( const QVariantMap &parameters,
QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const;
%Docstring
Expand All @@ -166,6 +191,16 @@ class QgsProcessingAlgorithm
Adds a parameter ``definition`` to the algorithm. Ownership of the definition is transferred to the algorithm.
Returns true if parameter could be successfully added, or false if the parameter could not be added (e.g.
as a result of a duplicate name).
.. seealso:: addOutput()
:rtype: bool
%End

bool addOutput( QgsProcessingOutputDefinition *outputDefinition /Transfer/ );
%Docstring
Adds an output ``definition`` to the algorithm. Ownership of the definition is transferred to the algorithm.
Returns true if the output could be successfully added, or false if the output could not be added (e.g.
as a result of a duplicate name).
.. seealso:: addParameter()
:rtype: bool
%End

Expand Down
125 changes: 125 additions & 0 deletions python/core/processing/qgsprocessingoutputs.sip
@@ -0,0 +1,125 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/core/processing/qgsprocessingoutputs.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/






class QgsProcessingOutputDefinition
{
%Docstring

Base class for the definition of processing outputs.

Output definitions encapsulate the properties regarding the outputs from algorithms, such
as generated layers or calculated values.

.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsprocessingoutputs.h"
%End
public:

QgsProcessingOutputDefinition( const QString &name, const QString &description = QString() );
%Docstring
Constructor for QgsProcessingOutputDefinition.
%End

virtual ~QgsProcessingOutputDefinition();

virtual QString type() const = 0;
%Docstring
Unique output type name.
:rtype: str
%End

QString name() const;
%Docstring
Returns the name of the output. This is the internal identifier by which
algorithms access this output.
@see setName()
:rtype: str
%End

void setName( const QString &name );
%Docstring
Sets the ``name`` of the output. This is the internal identifier by which
algorithms access this output.
@see name()
%End

QString description() const;
%Docstring
Returns the description for the output. This is the user-visible string
used to identify this output.
@see setDescription()
:rtype: str
%End

void setDescription( const QString &description );
%Docstring
Sets the ``description`` for the output. This is the user-visible string
used to identify this output.
@see description()
%End

protected:



};

typedef QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions;

class QgsProcessingOutputVectorLayer : QgsProcessingOutputDefinition
{
%Docstring
A vector layer output for processing algorithms.
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsprocessingoutputs.h"
%End
public:

QgsProcessingOutputVectorLayer( const QString &name, const QString &description = QString(), QgsProcessingParameterDefinition::LayerType type = QgsProcessingParameterDefinition::TypeVectorAny );
%Docstring
Constructor for QgsProcessingOutputVectorLayer.
%End

virtual QString type() const;

QgsProcessingParameterDefinition::LayerType dataType() const;
%Docstring
Returns the layer type for the output layer.
.. seealso:: setDataType()
:rtype: QgsProcessingParameterDefinition.LayerType
%End

void setDataType( QgsProcessingParameterDefinition::LayerType type );
%Docstring
Sets the layer ``type`` for the output layer.
.. seealso:: dataType()
%End

};




/************************************************************************
* This file has been generated automatically from *
* *
* src/core/processing/qgsprocessingoutputs.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
55 changes: 51 additions & 4 deletions python/core/processing/qgsprocessingparameters.sip
Expand Up @@ -64,6 +64,14 @@ class QgsProcessingParameterDefinition
:rtype: str
%End

virtual bool isDestination() const;
%Docstring
Returns true if this parameter represents a file or layer destination, e.g. parameters
which are used for the destination for layers output by an algorithm will return
true.
:rtype: bool
%End

QString name() const;
%Docstring
Returns the name of the parameter. This is the internal identifier by which
Expand Down Expand Up @@ -906,7 +914,7 @@ class QgsProcessingParameterTableField : QgsProcessingParameterDefinition

};

class QgsProcessingParameterVector : QgsProcessingParameterDefinition
class QgsProcessingParameterVectorLayer : QgsProcessingParameterDefinition
{
%Docstring
A vector layer parameter for processing algorithms.
Expand All @@ -918,10 +926,10 @@ class QgsProcessingParameterVector : QgsProcessingParameterDefinition
%End
public:

QgsProcessingParameterVector( const QString &name, const QString &description = QString(), QgsProcessingParameterDefinition::LayerType type = QgsProcessingParameterDefinition::TypeVectorAny, const QVariant &defaultValue = QVariant(),
bool optional = false );
QgsProcessingParameterVectorLayer( const QString &name, const QString &description = QString(), QgsProcessingParameterDefinition::LayerType type = QgsProcessingParameterDefinition::TypeVectorAny, const QVariant &defaultValue = QVariant(),
bool optional = false );
%Docstring
Constructor for QgsProcessingParameterVector.
Constructor for QgsProcessingParameterVectorLayer.
%End

virtual QString type() const;
Expand All @@ -943,6 +951,45 @@ class QgsProcessingParameterVector : QgsProcessingParameterDefinition
};


class QgsProcessingParameterOutputVectorLayer : QgsProcessingParameterDefinition
{
%Docstring
A vector layer output for processing algorithms.

A parameter which represents the destination for a vector layer created by an algorithm.
.. versionadded:: 3.0
%End

%TypeHeaderCode
#include "qgsprocessingparameters.h"
%End
public:

QgsProcessingParameterOutputVectorLayer( const QString &name, const QString &description = QString(), QgsProcessingParameterDefinition::LayerType type = QgsProcessingParameterDefinition::TypeVectorAny, const QVariant &defaultValue = QVariant(),
bool optional = false );
%Docstring
Constructor for QgsProcessingParameterOutputVectorLayer.
%End

virtual QString type() const;
virtual bool isDestination() const;

QgsProcessingParameterDefinition::LayerType dataType() const;
%Docstring
Returns the layer type for the output layer associated with the parameter.
.. seealso:: setDataType()
:rtype: QgsProcessingParameterDefinition.LayerType
%End

void setDataType( QgsProcessingParameterDefinition::LayerType type );
%Docstring
Sets the layer ``type`` for the output layer associated with the parameter.
.. seealso:: dataType()
%End

};



/************************************************************************
* This file has been generated automatically from *
Expand Down
9 changes: 0 additions & 9 deletions python/plugins/processing/core/GeoAlgorithm.py
Expand Up @@ -398,15 +398,6 @@ def setOutputValue(self, outputName, value):
if out.name == outputName:
out.setValue(value)

def getVisibleOutputsCount(self):
"""Returns the number of non-hidden outputs.
"""
i = 0
for out in self.outputs:
if not out.hidden:
i += 1
return i

def getHTMLOutputsCount(self):
"""Returns the number of HTML outputs.
"""
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/core/Processing.py
Expand Up @@ -165,7 +165,7 @@ def runAlgorithm(algOrName, onFinish, *args, **kwargs):
Processing.tr("Processing"))
return
else:
if len(args) != alg.countVisibleParameters() + alg.getVisibleOutputsCount():
if len(args) != alg.countVisibleParameters():
# fix_print_with_import
print('Error: Wrong number of parameters')
QgsMessageLog.logMessage(Processing.tr('Error: Wrong number of parameters'),
Expand Down
8 changes: 4 additions & 4 deletions python/plugins/processing/gui/BatchAlgorithmDialog.py
Expand Up @@ -74,8 +74,8 @@ def accept(self):
for row in range(self.mainWidget.tblParameters.rowCount()):
alg = self.alg
col = 0
for param in alg.parameters:
if param.hidden:
for param in alg.parameterDefinitions():
if param.hidden or param.isDestination():
continue
wrapper = self.mainWidget.wrappers[row][col]
if not self.mainWidget.setParamValue(param, wrapper, alg):
Expand All @@ -85,7 +85,7 @@ def accept(self):
self.algs = None
return
col += 1
for out in alg.outputs:
for out in alg.destinationParameterDefinitions():
if out.hidden:
continue

Expand All @@ -102,7 +102,7 @@ def accept(self):
return

self.algs.append(alg)
if self.alg.getVisibleOutputsCount():
if len(self.alg.destinationParameterDefinitions()) > 0:
widget = self.mainWidget.tblParameters.cellWidget(row, col)
self.load.append(widget.currentIndex() == 0)
else:
Expand Down
20 changes: 11 additions & 9 deletions python/plugins/processing/gui/BatchPanel.py
Expand Up @@ -97,30 +97,32 @@ def initWidgets(self):
break

# Determine column count
nOutputs = self.alg.getVisibleOutputsCount() + 1
nOutputs = len(self.alg.destinationParameterDefinitions()) + 1
if nOutputs == 1:
nOutputs = 0

self.tblParameters.setColumnCount(
self.alg.countVisibleParameters() + nOutputs)
self.alg.countVisibleParameters())

# Table headers
column = 0
for param in self.alg.parameters:
for param in self.alg.parameterDefinitions():
if param.isDestination():
continue
self.tblParameters.setHorizontalHeaderItem(
column, QTableWidgetItem(param.description))
if param.isAdvanced:
self.tblParameters.setColumnHidden(column, True)
column += 1

for out in self.alg.outputs:
for out in self.alg.destinationParameterDefinitions():
if not out.hidden:
self.tblParameters.setHorizontalHeaderItem(
column, QTableWidgetItem(out.description))
column += 1

# Last column for indicating if output will be added to canvas
if self.alg.getVisibleOutputsCount():
if len(self.alg.destinationParameterDefinitions()) > 0:
self.tblParameters.setHorizontalHeaderItem(
column, QTableWidgetItem(self.tr('Load in QGIS')))

Expand Down Expand Up @@ -233,16 +235,16 @@ def addRow(self):
wrappers = {}
row = self.tblParameters.rowCount() - 1
column = 0
for param in self.alg.parameters:
if param.hidden:
for param in self.alg.parameterDefinitions():
if param.hidden or param.isDestination():
continue

wrapper = param.wrapper(self.parent, row, column)
wrappers[param.name] = wrapper
self.setCellWrapper(row, column, wrapper)
column += 1

for out in self.alg.outputs:
for out in self.alg.destinationParameterDefinitions():
if out.hidden:
continue

Expand All @@ -251,7 +253,7 @@ def addRow(self):
out, self.alg, row, column, self))
column += 1

if self.alg.getVisibleOutputsCount():
if len(self.alg.destinationParameterDefinitions()) > 0:
item = QComboBox()
item.addItem(self.tr('Yes'))
item.addItem(self.tr('No'))
Expand Down

0 comments on commit fb81176

Please sign in to comment.