Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[processing] Add a generic map layer output type
For occasions when an algorithm creates a map layer, but the type
is not known in advance (i.e. could be raster OR vector)
  • Loading branch information
nyalldawson committed Nov 26, 2017
1 parent 3d307b4 commit 4b9986e
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 28 deletions.
34 changes: 34 additions & 0 deletions python/core/processing/qgsprocessingoutputs.sip
Expand Up @@ -31,6 +31,8 @@ class QgsProcessingOutputDefinition
sipType = sipType_QgsProcessingOutputVectorLayer;
else if ( sipCpp->type() == QgsProcessingOutputRasterLayer::typeName() )
sipType = sipType_QgsProcessingOutputRasterLayer;
else if ( sipCpp->type() == QgsProcessingOutputMapLayer::typeName() )
sipType = sipType_QgsProcessingOutputMapLayer;
else if ( sipCpp->type() == QgsProcessingOutputHtml::typeName() )
sipType = sipType_QgsProcessingOutputHtml;
else if ( sipCpp->type() == QgsProcessingOutputNumber::typeName() )
Expand Down Expand Up @@ -97,6 +99,38 @@ class QgsProcessingOutputDefinition

typedef QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions;

class QgsProcessingOutputMapLayer : QgsProcessingOutputDefinition
{
%Docstring
A map layer output for processing algorithms, where layers may be either vector or raster.

If the actual layer output type is known (e.g. always vector or always raster), use
QgsProcessingOutputVectorLayer or QgsProcessingOutputRasterLayer instead.

.. versionadded:: 3.0
%End

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

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

static QString typeName();
%Docstring
Returns the type name for the output class.
:rtype: str
%End

virtual QString type() const;


};

class QgsProcessingOutputVectorLayer : QgsProcessingOutputDefinition
{
%Docstring
Expand Down
5 changes: 3 additions & 2 deletions python/plugins/processing/core/Processing.py
Expand Up @@ -41,7 +41,8 @@
QgsProcessingException,
QgsProcessingParameterDefinition,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputRasterLayer)
QgsProcessingOutputRasterLayer,
QgsProcessingOutputMapLayer)

import processing
from processing.script.ScriptUtils import ScriptUtils
Expand Down Expand Up @@ -176,7 +177,7 @@ def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=No
else:
# auto convert layer references in results to map layers
for out in alg.outputDefinitions():
if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer)):
if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer, QgsProcessingOutputMapLayer)):
result = results[out.name()]
if not isinstance(result, QgsMapLayer):
layer = context.takeResultLayer(result) # transfer layer ownership out of context
Expand Down
3 changes: 3 additions & 0 deletions python/plugins/processing/core/outputs.py
Expand Up @@ -49,6 +49,7 @@
QgsProcessingParameterDefinition,
QgsProcessingOutputRasterLayer,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer,
QgsProcessingOutputHtml,
QgsProcessingOutputNumber,
QgsProcessingOutputString,
Expand Down Expand Up @@ -412,6 +413,8 @@ def getOutputFromString(s):
out = QgsProcessingOutputRasterLayer(name, description)
elif token.lower().strip() == 'outputvector':
out = QgsProcessingOutputVectorLayer(name, description)
elif token.lower().strip() == 'outputlayer':
out = QgsProcessingOutputMapLayer(name, description)
# elif token.lower().strip() == 'vector point':
# out = OutputVector(datatype=[dataobjects.TYPE_VECTOR_POINT])
# elif token.lower().strip() == 'vector line':
Expand Down
57 changes: 32 additions & 25 deletions python/plugins/processing/gui/wrappers.py
Expand Up @@ -65,6 +65,7 @@
QgsProcessingFeatureSourceDefinition,
QgsProcessingOutputRasterLayer,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer,
QgsProcessingOutputFile,
QgsProcessingOutputString,
QgsProcessingOutputNumber,
Expand Down Expand Up @@ -295,14 +296,14 @@ def createWidget(self):
crss = self.dialog.getAvailableValuesOfType((QgsProcessingParameterCrs, QgsProcessingParameterString), QgsProcessingOutputString)
for crs in crss:
self.combo.addItem(self.dialog.resolveValueDescription(crs), crs)
raster = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer,
QgsProcessingOutputRasterLayer)
vector = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource,
QgsProcessingOutputVectorLayer)
for r in raster:
self.combo.addItem("Crs of layer " + self.dialog.resolveValueDescription(r), r)
for v in vector:
self.combo.addItem("Crs of layer " + self.dialog.resolveValueDescription(v), v)
layers = self.dialog.getAvailableValuesOfType([QgsProcessingParameterRasterLayer,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterFeatureSource],
[QgsProcessingOutputVectorLayer,
QgsProcessingOutputRasterLayer,
QgsProcessingOutputMapLayer])
for l in layers:
self.combo.addItem("Crs of layer " + self.dialog.resolveValueDescription(l), l)
if self.param.defaultValue():
self.combo.setEditText(self.param.defaultValue())
return widget
Expand Down Expand Up @@ -362,16 +363,16 @@ def createWidget(self):
extents = self.dialog.getAvailableValuesOfType(QgsProcessingParameterExtent, (OutputExtent, QgsProcessingOutputString))
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
widget.addItem(self.USE_MIN_COVERING_EXTENT, None)
raster = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer,
QgsProcessingOutputRasterLayer)
vector = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource,
QgsProcessingOutputVectorLayer)
layers = self.dialog.getAvailableValuesOfType([QgsProcessingParameterFeatureSource,
QgsProcessingParameterRasterLayer,
QgsProcessingParameterVectorLayer],
[QgsProcessingOutputRasterLayer,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer])
for ex in extents:
widget.addItem(self.dialog.resolveValueDescription(ex), ex)
for r in raster:
widget.addItem("Extent of " + self.dialog.resolveValueDescription(r), r)
for v in vector:
widget.addItem("Extent of " + self.dialog.resolveValueDescription(v), v)
for l in layers:
widget.addItem("Extent of " + self.dialog.resolveValueDescription(l), l)
if not self.param.defaultValue():
widget.setEditText(self.param.defaultValue())
return widget
Expand Down Expand Up @@ -540,38 +541,44 @@ def _getOptions(self):
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMultipleLayers),
QgsProcessingOutputVectorLayer)
[QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer])
elif self.param.layerType() == QgsProcessing.TypeVector:
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMultipleLayers),
QgsProcessingOutputVectorLayer,
[QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer],
[QgsProcessing.TypeVector])
elif self.param.layerType() == QgsProcessing.TypeVectorPoint:
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMultipleLayers),
QgsProcessingOutputVectorLayer,
[QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer],
[QgsProcessing.TypeVectorPoint,
QgsProcessing.TypeVectorAnyGeometry])
elif self.param.layerType() == QgsProcessing.TypeVectorLine:
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMultipleLayers),
QgsProcessingOutputVectorLayer,
[QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer],
[QgsProcessing.TypeVectorLine,
QgsProcessing.TypeVectorAnyGeometry])
elif self.param.layerType() == QgsProcessing.TypeVectorPolygon:
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMultipleLayers),
QgsProcessingOutputVectorLayer,
[QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer],
[QgsProcessing.TypeVectorPolygon,
QgsProcessing.TypeVectorAnyGeometry])
elif self.param.layerType() == QgsProcessing.TypeRaster:
options = self.dialog.getAvailableValuesOfType(
(QgsProcessingParameterRasterLayer, QgsProcessingParameterMultipleLayers),
QgsProcessingOutputRasterLayer)
[QgsProcessingOutputRasterLayer,
QgsProcessingOutputMapLayer])
elif self.param.layerType() == QgsProcessing.TypeVector:
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
Expand Down Expand Up @@ -760,7 +767,7 @@ def setComboBoxFilters(self, combo):
def getAvailableLayers(self):
return self.dialog.getAvailableValuesOfType(
[QgsProcessingParameterRasterLayer, QgsProcessingParameterVectorLayer, QgsProcessingParameterMapLayer, QgsProcessingParameterString],
[QgsProcessingOutputRasterLayer, QgsProcessingOutputVectorLayer, QgsProcessingOutputString, QgsProcessingOutputFile])
[QgsProcessingOutputRasterLayer, QgsProcessingOutputVectorLayer, QgsProcessingOutputMapLayer, QgsProcessingOutputString, QgsProcessingOutputFile])

def selectFile(self):
filename, selected_filter = self.getFileName(self.combo.currentText())
Expand Down Expand Up @@ -933,7 +940,7 @@ def createWidget(self):
self.combo = QComboBox()
layers = self.dialog.getAvailableValuesOfType(
(QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer),
(QgsProcessingOutputVectorLayer, QgsProcessingOutputString, QgsProcessingOutputFile), self.param.dataTypes())
(QgsProcessingOutputVectorLayer, QgsProcessingOutputMapLayer, QgsProcessingOutputString, QgsProcessingOutputFile), self.param.dataTypes())
self.combo.setEditable(True)
for layer in layers:
self.combo.addItem(self.dialog.resolveValueDescription(layer), layer)
Expand Down Expand Up @@ -1217,7 +1224,7 @@ def createWidget(self):
self.combo = QComboBox()
self.combo.setEditable(True)
tables = self.dialog.getAvailableValuesOfType((QgsProcessingParameterVectorLayer, QgsProcessingParameterString),
(QgsProcessingOutputVectorLayer, QgsProcessingOutputFile, QgsProcessingOutputString))
(QgsProcessingOutputVectorLayer, QgsProcessingOutputMapLayer, QgsProcessingOutputFile, QgsProcessingOutputString))
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
self.combo.addItem(self.NOT_SELECTED, None)
for table in tables:
Expand Down
3 changes: 2 additions & 1 deletion src/core/processing/models/qgsprocessingmodelalgorithm.cpp
Expand Up @@ -466,7 +466,8 @@ QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> QgsProcessingMode
<< QgsProcessingParameterVectorLayer::typeName()
<< QgsProcessingParameterRasterLayer::typeName(),
QStringList() << QgsProcessingOutputVectorLayer::typeName()
<< QgsProcessingOutputRasterLayer::typeName() );
<< QgsProcessingOutputRasterLayer::typeName()
<< QgsProcessingOutputMapLayer::typeName() );

Q_FOREACH ( const QgsProcessingModelChildParameterSource &source, sources )
{
Expand Down
13 changes: 13 additions & 0 deletions src/core/processing/qgsprocessingoutputs.cpp
Expand Up @@ -62,3 +62,16 @@ QgsProcessingOutputFolder::QgsProcessingOutputFolder( const QString &name, const
QgsProcessingOutputFile::QgsProcessingOutputFile( const QString &name, const QString &description )
: QgsProcessingOutputDefinition( name, description )
{}

QgsProcessingOutputMapLayer::QgsProcessingOutputMapLayer( const QString &name, const QString &description )
: QgsProcessingOutputDefinition( name, description )
{

}



QString QgsProcessingOutputMapLayer::type() const
{
return typeName();
}
30 changes: 30 additions & 0 deletions src/core/processing/qgsprocessingoutputs.h
Expand Up @@ -47,6 +47,8 @@ class CORE_EXPORT QgsProcessingOutputDefinition
sipType = sipType_QgsProcessingOutputVectorLayer;
else if ( sipCpp->type() == QgsProcessingOutputRasterLayer::typeName() )
sipType = sipType_QgsProcessingOutputRasterLayer;
else if ( sipCpp->type() == QgsProcessingOutputMapLayer::typeName() )
sipType = sipType_QgsProcessingOutputMapLayer;
else if ( sipCpp->type() == QgsProcessingOutputHtml::typeName() )
sipType = sipType_QgsProcessingOutputHtml;
else if ( sipCpp->type() == QgsProcessingOutputNumber::typeName() )
Expand Down Expand Up @@ -117,6 +119,34 @@ class CORE_EXPORT QgsProcessingOutputDefinition
//! List of processing parameters
typedef QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions;

/**
* \class QgsProcessingOutputVectorLayer
* \ingroup core
* A map layer output for processing algorithms, where layers may be either vector or raster.
*
* If the actual layer output type is known (e.g. always vector or always raster), use
* QgsProcessingOutputVectorLayer or QgsProcessingOutputRasterLayer instead.
*
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProcessingOutputMapLayer : public QgsProcessingOutputDefinition
{
public:

/**
* Constructor for QgsProcessingOutputMapLayer.
*/
QgsProcessingOutputMapLayer( const QString &name, const QString &description = QString() );

/**
* Returns the type name for the output class.
*/
static QString typeName() { return QStringLiteral( "outputLayer" ); }

QString type() const override;

};

/**
* \class QgsProcessingOutputVectorLayer
* \ingroup core
Expand Down

0 comments on commit 4b9986e

Please sign in to comment.