Skip to content

Commit 4b9986e

Browse files
committed
[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)
1 parent 3d307b4 commit 4b9986e

File tree

7 files changed

+117
-28
lines changed

7 files changed

+117
-28
lines changed

python/core/processing/qgsprocessingoutputs.sip

+34
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ class QgsProcessingOutputDefinition
3131
sipType = sipType_QgsProcessingOutputVectorLayer;
3232
else if ( sipCpp->type() == QgsProcessingOutputRasterLayer::typeName() )
3333
sipType = sipType_QgsProcessingOutputRasterLayer;
34+
else if ( sipCpp->type() == QgsProcessingOutputMapLayer::typeName() )
35+
sipType = sipType_QgsProcessingOutputMapLayer;
3436
else if ( sipCpp->type() == QgsProcessingOutputHtml::typeName() )
3537
sipType = sipType_QgsProcessingOutputHtml;
3638
else if ( sipCpp->type() == QgsProcessingOutputNumber::typeName() )
@@ -97,6 +99,38 @@ class QgsProcessingOutputDefinition
9799

98100
typedef QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions;
99101

102+
class QgsProcessingOutputMapLayer : QgsProcessingOutputDefinition
103+
{
104+
%Docstring
105+
A map layer output for processing algorithms, where layers may be either vector or raster.
106+
107+
If the actual layer output type is known (e.g. always vector or always raster), use
108+
QgsProcessingOutputVectorLayer or QgsProcessingOutputRasterLayer instead.
109+
110+
.. versionadded:: 3.0
111+
%End
112+
113+
%TypeHeaderCode
114+
#include "qgsprocessingoutputs.h"
115+
%End
116+
public:
117+
118+
QgsProcessingOutputMapLayer( const QString &name, const QString &description = QString() );
119+
%Docstring
120+
Constructor for QgsProcessingOutputMapLayer.
121+
%End
122+
123+
static QString typeName();
124+
%Docstring
125+
Returns the type name for the output class.
126+
:rtype: str
127+
%End
128+
129+
virtual QString type() const;
130+
131+
132+
};
133+
100134
class QgsProcessingOutputVectorLayer : QgsProcessingOutputDefinition
101135
{
102136
%Docstring

python/plugins/processing/core/Processing.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@
4141
QgsProcessingException,
4242
QgsProcessingParameterDefinition,
4343
QgsProcessingOutputVectorLayer,
44-
QgsProcessingOutputRasterLayer)
44+
QgsProcessingOutputRasterLayer,
45+
QgsProcessingOutputMapLayer)
4546

4647
import processing
4748
from processing.script.ScriptUtils import ScriptUtils
@@ -176,7 +177,7 @@ def runAlgorithm(algOrName, parameters, onFinish=None, feedback=None, context=No
176177
else:
177178
# auto convert layer references in results to map layers
178179
for out in alg.outputDefinitions():
179-
if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer)):
180+
if isinstance(out, (QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer, QgsProcessingOutputMapLayer)):
180181
result = results[out.name()]
181182
if not isinstance(result, QgsMapLayer):
182183
layer = context.takeResultLayer(result) # transfer layer ownership out of context

python/plugins/processing/core/outputs.py

+3
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
QgsProcessingParameterDefinition,
5050
QgsProcessingOutputRasterLayer,
5151
QgsProcessingOutputVectorLayer,
52+
QgsProcessingOutputMapLayer,
5253
QgsProcessingOutputHtml,
5354
QgsProcessingOutputNumber,
5455
QgsProcessingOutputString,
@@ -412,6 +413,8 @@ def getOutputFromString(s):
412413
out = QgsProcessingOutputRasterLayer(name, description)
413414
elif token.lower().strip() == 'outputvector':
414415
out = QgsProcessingOutputVectorLayer(name, description)
416+
elif token.lower().strip() == 'outputlayer':
417+
out = QgsProcessingOutputMapLayer(name, description)
415418
# elif token.lower().strip() == 'vector point':
416419
# out = OutputVector(datatype=[dataobjects.TYPE_VECTOR_POINT])
417420
# elif token.lower().strip() == 'vector line':

python/plugins/processing/gui/wrappers.py

+32-25
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
QgsProcessingFeatureSourceDefinition,
6666
QgsProcessingOutputRasterLayer,
6767
QgsProcessingOutputVectorLayer,
68+
QgsProcessingOutputMapLayer,
6869
QgsProcessingOutputFile,
6970
QgsProcessingOutputString,
7071
QgsProcessingOutputNumber,
@@ -295,14 +296,14 @@ def createWidget(self):
295296
crss = self.dialog.getAvailableValuesOfType((QgsProcessingParameterCrs, QgsProcessingParameterString), QgsProcessingOutputString)
296297
for crs in crss:
297298
self.combo.addItem(self.dialog.resolveValueDescription(crs), crs)
298-
raster = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer,
299-
QgsProcessingOutputRasterLayer)
300-
vector = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource,
301-
QgsProcessingOutputVectorLayer)
302-
for r in raster:
303-
self.combo.addItem("Crs of layer " + self.dialog.resolveValueDescription(r), r)
304-
for v in vector:
305-
self.combo.addItem("Crs of layer " + self.dialog.resolveValueDescription(v), v)
299+
layers = self.dialog.getAvailableValuesOfType([QgsProcessingParameterRasterLayer,
300+
QgsProcessingParameterVectorLayer,
301+
QgsProcessingParameterFeatureSource],
302+
[QgsProcessingOutputVectorLayer,
303+
QgsProcessingOutputRasterLayer,
304+
QgsProcessingOutputMapLayer])
305+
for l in layers:
306+
self.combo.addItem("Crs of layer " + self.dialog.resolveValueDescription(l), l)
306307
if self.param.defaultValue():
307308
self.combo.setEditText(self.param.defaultValue())
308309
return widget
@@ -362,16 +363,16 @@ def createWidget(self):
362363
extents = self.dialog.getAvailableValuesOfType(QgsProcessingParameterExtent, (OutputExtent, QgsProcessingOutputString))
363364
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
364365
widget.addItem(self.USE_MIN_COVERING_EXTENT, None)
365-
raster = self.dialog.getAvailableValuesOfType(QgsProcessingParameterRasterLayer,
366-
QgsProcessingOutputRasterLayer)
367-
vector = self.dialog.getAvailableValuesOfType(QgsProcessingParameterFeatureSource,
368-
QgsProcessingOutputVectorLayer)
366+
layers = self.dialog.getAvailableValuesOfType([QgsProcessingParameterFeatureSource,
367+
QgsProcessingParameterRasterLayer,
368+
QgsProcessingParameterVectorLayer],
369+
[QgsProcessingOutputRasterLayer,
370+
QgsProcessingOutputVectorLayer,
371+
QgsProcessingOutputMapLayer])
369372
for ex in extents:
370373
widget.addItem(self.dialog.resolveValueDescription(ex), ex)
371-
for r in raster:
372-
widget.addItem("Extent of " + self.dialog.resolveValueDescription(r), r)
373-
for v in vector:
374-
widget.addItem("Extent of " + self.dialog.resolveValueDescription(v), v)
374+
for l in layers:
375+
widget.addItem("Extent of " + self.dialog.resolveValueDescription(l), l)
375376
if not self.param.defaultValue():
376377
widget.setEditText(self.param.defaultValue())
377378
return widget
@@ -540,38 +541,44 @@ def _getOptions(self):
540541
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
541542
QgsProcessingParameterVectorLayer,
542543
QgsProcessingParameterMultipleLayers),
543-
QgsProcessingOutputVectorLayer)
544+
[QgsProcessingOutputVectorLayer,
545+
QgsProcessingOutputMapLayer])
544546
elif self.param.layerType() == QgsProcessing.TypeVector:
545547
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
546548
QgsProcessingParameterVectorLayer,
547549
QgsProcessingParameterMultipleLayers),
548-
QgsProcessingOutputVectorLayer,
550+
[QgsProcessingOutputVectorLayer,
551+
QgsProcessingOutputMapLayer],
549552
[QgsProcessing.TypeVector])
550553
elif self.param.layerType() == QgsProcessing.TypeVectorPoint:
551554
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
552555
QgsProcessingParameterVectorLayer,
553556
QgsProcessingParameterMultipleLayers),
554-
QgsProcessingOutputVectorLayer,
557+
[QgsProcessingOutputVectorLayer,
558+
QgsProcessingOutputMapLayer],
555559
[QgsProcessing.TypeVectorPoint,
556560
QgsProcessing.TypeVectorAnyGeometry])
557561
elif self.param.layerType() == QgsProcessing.TypeVectorLine:
558562
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
559563
QgsProcessingParameterVectorLayer,
560564
QgsProcessingParameterMultipleLayers),
561-
QgsProcessingOutputVectorLayer,
565+
[QgsProcessingOutputVectorLayer,
566+
QgsProcessingOutputMapLayer],
562567
[QgsProcessing.TypeVectorLine,
563568
QgsProcessing.TypeVectorAnyGeometry])
564569
elif self.param.layerType() == QgsProcessing.TypeVectorPolygon:
565570
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
566571
QgsProcessingParameterVectorLayer,
567572
QgsProcessingParameterMultipleLayers),
568-
QgsProcessingOutputVectorLayer,
573+
[QgsProcessingOutputVectorLayer,
574+
QgsProcessingOutputMapLayer],
569575
[QgsProcessing.TypeVectorPolygon,
570576
QgsProcessing.TypeVectorAnyGeometry])
571577
elif self.param.layerType() == QgsProcessing.TypeRaster:
572578
options = self.dialog.getAvailableValuesOfType(
573579
(QgsProcessingParameterRasterLayer, QgsProcessingParameterMultipleLayers),
574-
QgsProcessingOutputRasterLayer)
580+
[QgsProcessingOutputRasterLayer,
581+
QgsProcessingOutputMapLayer])
575582
elif self.param.layerType() == QgsProcessing.TypeVector:
576583
options = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource,
577584
QgsProcessingParameterVectorLayer,
@@ -760,7 +767,7 @@ def setComboBoxFilters(self, combo):
760767
def getAvailableLayers(self):
761768
return self.dialog.getAvailableValuesOfType(
762769
[QgsProcessingParameterRasterLayer, QgsProcessingParameterVectorLayer, QgsProcessingParameterMapLayer, QgsProcessingParameterString],
763-
[QgsProcessingOutputRasterLayer, QgsProcessingOutputVectorLayer, QgsProcessingOutputString, QgsProcessingOutputFile])
770+
[QgsProcessingOutputRasterLayer, QgsProcessingOutputVectorLayer, QgsProcessingOutputMapLayer, QgsProcessingOutputString, QgsProcessingOutputFile])
764771

765772
def selectFile(self):
766773
filename, selected_filter = self.getFileName(self.combo.currentText())
@@ -933,7 +940,7 @@ def createWidget(self):
933940
self.combo = QComboBox()
934941
layers = self.dialog.getAvailableValuesOfType(
935942
(QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer),
936-
(QgsProcessingOutputVectorLayer, QgsProcessingOutputString, QgsProcessingOutputFile), self.param.dataTypes())
943+
(QgsProcessingOutputVectorLayer, QgsProcessingOutputMapLayer, QgsProcessingOutputString, QgsProcessingOutputFile), self.param.dataTypes())
937944
self.combo.setEditable(True)
938945
for layer in layers:
939946
self.combo.addItem(self.dialog.resolveValueDescription(layer), layer)
@@ -1217,7 +1224,7 @@ def createWidget(self):
12171224
self.combo = QComboBox()
12181225
self.combo.setEditable(True)
12191226
tables = self.dialog.getAvailableValuesOfType((QgsProcessingParameterVectorLayer, QgsProcessingParameterString),
1220-
(QgsProcessingOutputVectorLayer, QgsProcessingOutputFile, QgsProcessingOutputString))
1227+
(QgsProcessingOutputVectorLayer, QgsProcessingOutputMapLayer, QgsProcessingOutputFile, QgsProcessingOutputString))
12211228
if self.param.flags() & QgsProcessingParameterDefinition.FlagOptional:
12221229
self.combo.addItem(self.NOT_SELECTED, None)
12231230
for table in tables:

src/core/processing/models/qgsprocessingmodelalgorithm.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,8 @@ QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> QgsProcessingMode
466466
<< QgsProcessingParameterVectorLayer::typeName()
467467
<< QgsProcessingParameterRasterLayer::typeName(),
468468
QStringList() << QgsProcessingOutputVectorLayer::typeName()
469-
<< QgsProcessingOutputRasterLayer::typeName() );
469+
<< QgsProcessingOutputRasterLayer::typeName()
470+
<< QgsProcessingOutputMapLayer::typeName() );
470471

471472
Q_FOREACH ( const QgsProcessingModelChildParameterSource &source, sources )
472473
{

src/core/processing/qgsprocessingoutputs.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -62,3 +62,16 @@ QgsProcessingOutputFolder::QgsProcessingOutputFolder( const QString &name, const
6262
QgsProcessingOutputFile::QgsProcessingOutputFile( const QString &name, const QString &description )
6363
: QgsProcessingOutputDefinition( name, description )
6464
{}
65+
66+
QgsProcessingOutputMapLayer::QgsProcessingOutputMapLayer( const QString &name, const QString &description )
67+
: QgsProcessingOutputDefinition( name, description )
68+
{
69+
70+
}
71+
72+
73+
74+
QString QgsProcessingOutputMapLayer::type() const
75+
{
76+
return typeName();
77+
}

src/core/processing/qgsprocessingoutputs.h

+30
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class CORE_EXPORT QgsProcessingOutputDefinition
4747
sipType = sipType_QgsProcessingOutputVectorLayer;
4848
else if ( sipCpp->type() == QgsProcessingOutputRasterLayer::typeName() )
4949
sipType = sipType_QgsProcessingOutputRasterLayer;
50+
else if ( sipCpp->type() == QgsProcessingOutputMapLayer::typeName() )
51+
sipType = sipType_QgsProcessingOutputMapLayer;
5052
else if ( sipCpp->type() == QgsProcessingOutputHtml::typeName() )
5153
sipType = sipType_QgsProcessingOutputHtml;
5254
else if ( sipCpp->type() == QgsProcessingOutputNumber::typeName() )
@@ -117,6 +119,34 @@ class CORE_EXPORT QgsProcessingOutputDefinition
117119
//! List of processing parameters
118120
typedef QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions;
119121

122+
/**
123+
* \class QgsProcessingOutputVectorLayer
124+
* \ingroup core
125+
* A map layer output for processing algorithms, where layers may be either vector or raster.
126+
*
127+
* If the actual layer output type is known (e.g. always vector or always raster), use
128+
* QgsProcessingOutputVectorLayer or QgsProcessingOutputRasterLayer instead.
129+
*
130+
* \since QGIS 3.0
131+
*/
132+
class CORE_EXPORT QgsProcessingOutputMapLayer : public QgsProcessingOutputDefinition
133+
{
134+
public:
135+
136+
/**
137+
* Constructor for QgsProcessingOutputMapLayer.
138+
*/
139+
QgsProcessingOutputMapLayer( const QString &name, const QString &description = QString() );
140+
141+
/**
142+
* Returns the type name for the output class.
143+
*/
144+
static QString typeName() { return QStringLiteral( "outputLayer" ); }
145+
146+
QString type() const override;
147+
148+
};
149+
120150
/**
121151
* \class QgsProcessingOutputVectorLayer
122152
* \ingroup core

0 commit comments

Comments
 (0)