[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)
This commit is contained in:
Nyall Dawson 2017-11-26 15:39:36 +10:00
parent 3d307b4109
commit 4b9986eb8c
7 changed files with 117 additions and 28 deletions

View File

@ -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() )
@ -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

View File

@ -41,7 +41,8 @@ from qgis.core import (QgsMessageLog,
QgsProcessingException,
QgsProcessingParameterDefinition,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputRasterLayer)
QgsProcessingOutputRasterLayer,
QgsProcessingOutputMapLayer)
import processing
from processing.script.ScriptUtils import ScriptUtils
@ -176,7 +177,7 @@ class Processing(object):
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

View File

@ -49,6 +49,7 @@ from qgis.core import (QgsExpressionContext,
QgsProcessingParameterDefinition,
QgsProcessingOutputRasterLayer,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer,
QgsProcessingOutputHtml,
QgsProcessingOutputNumber,
QgsProcessingOutputString,
@ -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':

View File

@ -65,6 +65,7 @@ from qgis.core import (
QgsProcessingFeatureSourceDefinition,
QgsProcessingOutputRasterLayer,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputMapLayer,
QgsProcessingOutputFile,
QgsProcessingOutputString,
QgsProcessingOutputNumber,
@ -295,14 +296,14 @@ class CrsWidgetWrapper(WidgetWrapper):
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
@ -362,16 +363,16 @@ class ExtentWidgetWrapper(WidgetWrapper):
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
@ -540,38 +541,44 @@ class MultipleLayerWidgetWrapper(WidgetWrapper):
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,
@ -760,7 +767,7 @@ class MapLayerWidgetWrapper(WidgetWrapper):
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())
@ -933,7 +940,7 @@ class FeatureSourceWidgetWrapper(WidgetWrapper):
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)
@ -1217,7 +1224,7 @@ class VectorLayerWidgetWrapper(WidgetWrapper):
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:

View File

@ -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 )
{

View File

@ -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();
}

View File

@ -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() )
@ -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