Add direct method to retrieve QgsFeatureSink from parameter

This commit is contained in:
Nyall Dawson 2017-06-05 11:14:34 +10:00
parent f41eb41131
commit ffce9c9f1e
9 changed files with 180 additions and 52 deletions

View File

@ -10,6 +10,7 @@
class QgsProcessingAlgorithm
{
%Docstring
@ -306,6 +307,25 @@ class QgsProcessingAlgorithm
:rtype: bool
%End
QgsFeatureSink *parameterAsSink( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context,
const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs,
QString &destinationIdentifier /Out/ ) const /Factory/;
%Docstring
Evaluates the parameter with matching ``name`` to a feature sink.
Sinks will either be taken from ``context``'s active project, or created from external
providers and stored temporarily in the ``context``.
The ``encoding``, ``fields``, ``geometryType`` and ``crs`` parameters dictate the properties
of the resulting feature sink.
The ``destinationIdentifier`` argument will be set to a string which can be used to retrieve the layer corresponding
to the sink, e.g. via calling QgsProcessingUtils.mapLayerFromString().
This function creates a new object and the caller takes responsibility for deleting the returned object.
:rtype: QgsFeatureSink
%End
QgsMapLayer *parameterAsLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const;
%Docstring
Evaluates the parameter with matching ``name`` to a map layer.

View File

@ -12,6 +12,7 @@
class QgsProcessingParameterDefinition
{
%Docstring
@ -222,51 +223,69 @@ class QgsProcessingParameters
:rtype: bool
%End
static QString parameterAsString( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context );
static QString parameterAsString( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a static string value.
Evaluates the parameter with matching ``definition`` to a static string value.
:rtype: str
%End
static QString parameterAsExpression( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context );
static QString parameterAsExpression( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to an expression.
Evaluates the parameter with matching ``definition`` to an expression.
:rtype: str
%End
static double parameterAsDouble( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context );
static double parameterAsDouble( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a static double value.
Evaluates the parameter with matching ``definition`` to a static double value.
:rtype: float
%End
static int parameterAsInt( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context );
static int parameterAsInt( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a static integer value.
Evaluates the parameter with matching ``definition`` to a static integer value.
:rtype: int
%End
static int parameterAsEnum( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context );
static int parameterAsEnum( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a enum value.
Evaluates the parameter with matching ``definition`` to a enum value.
:rtype: int
%End
static QList<int> parameterAsEnums( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context );
static QList<int> parameterAsEnums( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to list of enum values.
Evaluates the parameter with matching ``definition`` to list of enum values.
:rtype: list of int
%End
static bool parameterAsBool( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context );
static bool parameterAsBool( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a static boolean value.
Evaluates the parameter with matching ``definition`` to a static boolean value.
:rtype: bool
%End
static QgsMapLayer *parameterAsLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QgsFeatureSink *parameterAsSink( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters,
const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs,
QgsProcessingContext &context, QString &destinationIdentifier /Out/ ) /Factory/;
%Docstring
Evaluates the parameter with matching ``name`` to a map layer.
Evaluates the parameter with matching ``definition`` to a feature sink.
The ``encoding``, ``fields``, ``geometryType`` and ``crs`` parameters dictate the properties
of the resulting feature sink.
Sinks will either be taken from ``context``'s active project, or created from external
providers and stored temporarily in the ``context``. The ``destinationIdentifier``
argument will be set to a string which can be used to retrieve the layer corresponding
to the sink, e.g. via calling QgsProcessingUtils.mapLayerFromString().
This function creates a new object and the caller takes responsibility for deleting the returned object.
:rtype: QgsFeatureSink
%End
static QgsMapLayer *parameterAsLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``definition`` to a map layer.
Layers will either be taken from ``context``'s active project, or loaded from external
sources and stored temporarily in the ``context``. In either case, callers do not
@ -274,9 +293,9 @@ class QgsProcessingParameters
:rtype: QgsMapLayer
%End
static QgsRasterLayer *parameterAsRasterLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QgsRasterLayer *parameterAsRasterLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a raster layer.
Evaluates the parameter with matching ``definition`` to a raster layer.
Layers will either be taken from ``context``'s active project, or loaded from external
sources and stored temporarily in the ``context``. In either case, callers do not
@ -284,9 +303,9 @@ class QgsProcessingParameters
:rtype: QgsRasterLayer
%End
static QgsVectorLayer *parameterAsVectorLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QgsVectorLayer *parameterAsVectorLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a vector layer.
Evaluates the parameter with matching ``definition`` to a vector layer.
Layers will either be taken from ``context``'s active project, or loaded from external
sources and stored temporarily in the ``context``. In either case, callers do not
@ -294,52 +313,52 @@ class QgsProcessingParameters
:rtype: QgsVectorLayer
%End
static QgsCoordinateReferenceSystem parameterAsCrs( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QgsCoordinateReferenceSystem parameterAsCrs( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a coordinate reference system.
Evaluates the parameter with matching ``definition`` to a coordinate reference system.
:rtype: QgsCoordinateReferenceSystem
%End
static QgsRectangle parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QgsRectangle parameterAsExtent( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a rectangular extent.
Evaluates the parameter with matching ``definition`` to a rectangular extent.
:rtype: QgsRectangle
%End
static QgsPointXY parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QgsPointXY parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a point.
Evaluates the parameter with matching ``definition`` to a point.
:rtype: QgsPointXY
%End
static QString parameterAsFile( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QString parameterAsFile( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a file/folder name.
Evaluates the parameter with matching ``definition`` to a file/folder name.
:rtype: str
%End
static QVariantList parameterAsMatrix( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QVariantList parameterAsMatrix( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a matrix/table of values.
Evaluates the parameter with matching ``definition`` to a matrix/table of values.
Tables are collapsed to a 1 dimensional list.
:rtype: QVariantList
%End
static QList< QgsMapLayer *> parameterAsLayerList( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QList< QgsMapLayer *> parameterAsLayerList( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a list of map layers.
Evaluates the parameter with matching ``definition`` to a list of map layers.
:rtype: list of QgsMapLayer
%End
static QList<double> parameterAsRange( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QList<double> parameterAsRange( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a range of values.
Evaluates the parameter with matching ``definition`` to a range of values.
:rtype: list of float
%End
static QStringList parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &name, QgsProcessingContext &context );
static QStringList parameterAsFields( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context );
%Docstring
Evaluates the parameter with matching ``name`` to a list of fields.
Evaluates the parameter with matching ``definition`` to a list of fields.
:rtype: list of str
%End

View File

@ -82,13 +82,15 @@ class Boundary(QgisAlgorithm):
if QgsWkbTypes.hasM(input_wkb):
output_wkb = QgsWkbTypes.addM(output_wkb)
dest = self.parameterAsString(parameters, self.OUTPUT_LAYER, context)
(writer, dest_layer) = QgsProcessingUtils.createFeatureSink(dest, '', layer.fields(), output_wkb, layer.crs(), context)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LAYER, context, '',
layer.fields(), output_wkb, layer.crs())
features = QgsProcessingUtils.getFeatures(layer, context)
total = 100.0 / QgsProcessingUtils.featureCount(layer, context)
for current, input_feature in enumerate(features):
if feedback.isCanceled():
break
output_feature = input_feature
input_geometry = input_feature.geometry()
if input_geometry:
@ -99,7 +101,7 @@ class Boundary(QgisAlgorithm):
output_feature.setGeometry(output_geometry)
writer.addFeature(output_feature)
sink.addFeature(output_feature)
feedback.setProgress(int(current * total))
return {self.OUTPUT_LAYER: dest_layer}
return {self.OUTPUT_LAYER: dest_id}

View File

@ -78,12 +78,12 @@ QString QgsCentroidAlgorithm::shortHelpString() const
QVariantMap QgsCentroidAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( parameterAsLayer( parameters, QStringLiteral( "INPUT" ), context ) );
QgsVectorLayer *layer = parameterAsVectorLayer( parameters, QStringLiteral( "INPUT" ), context );
if ( !layer )
return QVariantMap();
QString dest = parameterAsString( parameters, QStringLiteral( "OUTPUT_LAYER" ), context );
std::unique_ptr< QgsFeatureSink > writer( QgsProcessingUtils::createFeatureSink( dest, QString(), layer->fields(), QgsWkbTypes::Point, layer->crs(), context ) );
QString dest;
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT_LAYER" ), context, QString(), layer->fields(), QgsWkbTypes::Point, layer->crs(), dest ) );
long count = QgsProcessingUtils::featureCount( layer, context );
if ( count <= 0 )
@ -110,7 +110,7 @@ QVariantMap QgsCentroidAlgorithm::processAlgorithm( const QVariantMap &parameter
QgsMessageLog::logMessage( QObject::tr( "Error calculating centroid for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), QgsMessageLog::WARNING );
}
}
writer->addFeature( out );
sink->addFeature( out );
feedback->setProgress( current * step );
current++;
@ -151,12 +151,12 @@ QString QgsBufferAlgorithm::shortHelpString() const
QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const
{
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( parameterAsLayer( parameters, QStringLiteral( "INPUT" ), context ) );
QgsVectorLayer *layer = parameterAsVectorLayer( parameters, QStringLiteral( "INPUT" ), context );
if ( !layer )
return QVariantMap();
QString dest = parameterAsString( parameters, QStringLiteral( "OUTPUT_LAYER" ), context );
std::unique_ptr< QgsFeatureSink > writer( QgsProcessingUtils::createFeatureSink( dest, QString(), layer->fields(), QgsWkbTypes::Polygon, layer->crs(), context ) );
QString dest;
std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT_LAYER" ), context, QString(), layer->fields(), QgsWkbTypes::Polygon, layer->crs(), dest ) );
// fixed parameters
//bool dissolve = QgsProcessingParameters::parameterAsBool( parameters, QStringLiteral( "DISSOLVE" ), context );
@ -199,7 +199,7 @@ QVariantMap QgsBufferAlgorithm::processAlgorithm( const QVariantMap &parameters,
QgsMessageLog::logMessage( QObject::tr( "Error calculating buffer for feature %1" ).arg( f.id() ), QObject::tr( "Processing" ), QgsMessageLog::WARNING );
}
}
writer->addFeature( out );
sink->addFeature( out );
feedback->setProgress( current * step );
current++;

View File

@ -210,6 +210,11 @@ bool QgsProcessingAlgorithm::parameterAsBool( const QVariantMap &parameters, con
return QgsProcessingParameters::parameterAsBool( parameterDefinition( name ), parameters, context );
}
QgsFeatureSink *QgsProcessingAlgorithm::parameterAsSink( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QString &destinationIdentifier ) const
{
return QgsProcessingParameters::parameterAsSink( parameterDefinition( name ), parameters, encoding, fields, geometryType, crs, context, destinationIdentifier );
}
QgsMapLayer *QgsProcessingAlgorithm::parameterAsLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
{
return QgsProcessingParameters::parameterAsLayer( parameterDefinition( name ), parameters, context );

View File

@ -29,7 +29,8 @@
class QgsProcessingProvider;
class QgsProcessingContext;
class QgsProcessingFeedback;
class QWidget;
class QgsFeatureSink;
/**
* \class QgsProcessingAlgorithm
@ -297,6 +298,24 @@ class CORE_EXPORT QgsProcessingAlgorithm
*/
bool parameterAsBool( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const;
/**
* Evaluates the parameter with matching \a name to a feature sink.
*
* Sinks will either be taken from \a context's active project, or created from external
* providers and stored temporarily in the \a context.
*
* The \a encoding, \a fields, \a geometryType and \a crs parameters dictate the properties
* of the resulting feature sink.
*
* The \a destinationIdentifier argument will be set to a string which can be used to retrieve the layer corresponding
* to the sink, e.g. via calling QgsProcessingUtils::mapLayerFromString().
*
* This function creates a new object and the caller takes responsibility for deleting the returned object.
*/
QgsFeatureSink *parameterAsSink( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context,
const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs,
QString &destinationIdentifier SIP_OUT ) const SIP_FACTORY;
/**
* Evaluates the parameter with matching \a name to a map layer.
*

View File

@ -202,6 +202,17 @@ bool QgsProcessingParameters::parameterAsBool( const QgsProcessingParameterDefin
return def.toBool();
}
QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QString &encoding, const QgsFields &fields,
QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs,
QgsProcessingContext &context, QString &destinationIdentifier )
{
QString dest = parameterAsString( definition, parameters, context );
std::unique_ptr< QgsFeatureSink > sink( QgsProcessingUtils::createFeatureSink( dest, encoding, fields, geometryType, crs, context ) );
destinationIdentifier = dest;
return sink.release();
}
QgsMapLayer *QgsProcessingParameters::parameterAsLayer( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
{
if ( !definition )
@ -290,10 +301,10 @@ QgsRectangle QgsProcessingParameters::parameterAsExtent( const QgsProcessingPara
return QgsRectangle();
}
QgsPoint QgsProcessingParameters::parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
QgsPointXY QgsProcessingParameters::parameterAsPoint( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, QgsProcessingContext &context )
{
if ( !definition )
return QgsPoint();
return QgsPointXY();
QString pointText = parameterAsString( definition, parameters, context );
if ( pointText.isEmpty() )

View File

@ -28,6 +28,8 @@
class QgsProcessingContext;
class QgsRasterLayer;
class QgsVectorLayer;
class QgsFeatureSink;
//
// Parameter definitions
@ -280,6 +282,23 @@ class CORE_EXPORT QgsProcessingParameters
*/
static bool parameterAsBool( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters, const QgsProcessingContext &context );
/**
* Evaluates the parameter with matching \a definition to a feature sink.
*
* The \a encoding, \a fields, \a geometryType and \a crs parameters dictate the properties
* of the resulting feature sink.
*
* Sinks will either be taken from \a context's active project, or created from external
* providers and stored temporarily in the \a context. The \a destinationIdentifier
* argument will be set to a string which can be used to retrieve the layer corresponding
* to the sink, e.g. via calling QgsProcessingUtils::mapLayerFromString().
*
* This function creates a new object and the caller takes responsibility for deleting the returned object.
*/
static QgsFeatureSink *parameterAsSink( const QgsProcessingParameterDefinition *definition, const QVariantMap &parameters,
const QString &encoding, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs,
QgsProcessingContext &context, QString &destinationIdentifier SIP_OUT ) SIP_FACTORY;
/**
* Evaluates the parameter with matching \a definition to a map layer.
*

View File

@ -1003,7 +1003,7 @@ void TestQgsProcessing::parameters()
// correctly setup feature
QgsFields fields;
fields.append( QgsField( "a_field", QVariant::String ) );
fields.append( QgsField( "a_field", QVariant::String, QString(), 30 ) );
QgsFeature f( fields );
f.setAttribute( 0, QStringLiteral( "field value" ) );
context.expressionContext().setFeature( f );
@ -1061,6 +1061,39 @@ void TestQgsProcessing::parameters()
QVERIFY( QgsProcessingParameters::parameterAsLayer( def, params, context ) );
// make sure layer was loaded
QVERIFY( !context.temporaryLayerStore()->mapLayers().isEmpty() );
// as sink
QString encoding;
QgsWkbTypes::Type wkbType = QgsWkbTypes::PolygonM;
QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem( "epsg:3111" );
QString destId;
def->setName( QStringLiteral( "string" ) );
params.insert( QStringLiteral( "string" ), QStringLiteral( "memory:mem" ) );
std::unique_ptr< QgsFeatureSink > sink;
sink.reset( QgsProcessingParameters::parameterAsSink( def, params, encoding, fields, wkbType, crs, context, destId ) );
QVERIFY( sink.get() );
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destId, context ) );
QVERIFY( layer );
QVERIFY( layer->isValid() );
QCOMPARE( layer->fields().count(), 1 );
QCOMPARE( layer->fields().at( 0 ).name(), QStringLiteral( "a_field" ) );
QCOMPARE( layer->wkbType(), wkbType );
QCOMPARE( layer->crs(), crs );
// property defined sink destination
params.insert( QStringLiteral( "prop" ), QgsProperty::fromExpression( "'memory:mem2'" ) );
def->setName( QStringLiteral( "prop" ) );
crs = QgsCoordinateReferenceSystem( "epsg:3113" );
sink.reset( QgsProcessingParameters::parameterAsSink( def, params, encoding, fields, wkbType, crs, context, destId ) );
QVERIFY( sink.get() );
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destId, context ) );
QVERIFY( layer );
QVERIFY( layer->isValid() );
QCOMPARE( layer->fields().count(), 1 );
QCOMPARE( layer->fields().at( 0 ).name(), QStringLiteral( "a_field" ) );
QCOMPARE( layer->wkbType(), wkbType );
QCOMPARE( layer->crs(), crs );
delete def;
}