Skip to content

Commit

Permalink
Add API to flag that a sink supports appending features to existing l…
Browse files Browse the repository at this point in the history
…ayers
  • Loading branch information
nyalldawson committed Apr 7, 2020
1 parent 11b67c2 commit bb9b25f
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 7 deletions.
Expand Up @@ -2869,7 +2869,7 @@ A parameter which represents the destination feature sink for features created b
public:

QgsProcessingParameterFeatureSink( const QString &name, const QString &description = QString(), QgsProcessing::SourceType type = QgsProcessing::TypeVectorAnyGeometry, const QVariant &defaultValue = QVariant(),
bool optional = false, bool createByDefault = true );
bool optional = false, bool createByDefault = true, bool supportsAppend = false );
%Docstring
Constructor for QgsProcessingParameterFeatureSink.

Expand Down Expand Up @@ -2926,6 +2926,30 @@ cannot be reliably determined in advance, this method will default to returning
Sets the layer ``type`` for the sinks associated with the parameter.

.. seealso:: :py:func:`dataType`
%End

bool supportsAppend() const;
%Docstring
Returns ``True`` if the sink supports appending features to an existing table.

A sink only supports appending if the algorithm implements QgsProcessingAlgorithm.sinkProperties for the sink parameter.

.. seealso:: :py:func:`setSupportsAppend`

.. versionadded:: 3.14
%End

void setSupportsAppend( bool supportsAppend );
%Docstring
Sets whether the sink supports appending features to an existing table.

.. warning::

A sink only supports appending if the algorithm implements QgsProcessingAlgorithm.sinkProperties for the sink parameter.

.. seealso:: :py:func:`supportsAppend`

.. versionadded:: 3.14
%End

virtual QVariantMap toVariantMap() const;
Expand Down
2 changes: 1 addition & 1 deletion src/analysis/processing/qgsalgorithmbuffer.cpp
Expand Up @@ -62,7 +62,7 @@ void QgsBufferAlgorithm::initAlgorithm( const QVariantMap & )
addParameter( new QgsProcessingParameterNumber( QStringLiteral( "MITER_LIMIT" ), QObject::tr( "Miter limit" ), QgsProcessingParameterNumber::Double, 2, false, 1 ) );

addParameter( new QgsProcessingParameterBoolean( QStringLiteral( "DISSOLVE" ), QObject::tr( "Dissolve result" ), false ) );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Buffered" ), QgsProcessing::TypeVectorPolygon ) );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Buffered" ), QgsProcessing::TypeVectorPolygon, QVariant(), false, true, true ) );
}

QString QgsBufferAlgorithm::shortHelpString() const
Expand Down
2 changes: 1 addition & 1 deletion src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -875,7 +875,7 @@ void QgsProcessingFeatureBasedAlgorithm::initAlgorithm( const QVariantMap &confi
{
addParameter( new QgsProcessingParameterFeatureSource( inputParameterName(), inputParameterDescription(), inputLayerTypes() ) );
initParameters( config );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), outputName(), outputLayerType() ) );
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), outputName(), outputLayerType(), QVariant(), false, true, true ) );
}

QString QgsProcessingFeatureBasedAlgorithm::inputParameterName() const
Expand Down
17 changes: 16 additions & 1 deletion src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -4904,9 +4904,10 @@ QgsProcessingParameterFeatureSource *QgsProcessingParameterFeatureSource::fromSc
return new QgsProcessingParameterFeatureSource( name, description, types, def, isOptional );
}

QgsProcessingParameterFeatureSink::QgsProcessingParameterFeatureSink( const QString &name, const QString &description, QgsProcessing::SourceType type, const QVariant &defaultValue, bool optional, bool createByDefault )
QgsProcessingParameterFeatureSink::QgsProcessingParameterFeatureSink( const QString &name, const QString &description, QgsProcessing::SourceType type, const QVariant &defaultValue, bool optional, bool createByDefault, bool supportsAppend )
: QgsProcessingDestinationParameter( name, description, defaultValue, optional, createByDefault )
, mDataType( type )
, mSupportsAppend( supportsAppend )
{
}

Expand Down Expand Up @@ -5047,6 +5048,8 @@ QString QgsProcessingParameterFeatureSink::asPythonString( const QgsProcessing::
code += QStringLiteral( ", type=QgsProcessing.%1" ).arg( QgsProcessing::sourceTypeToString( mDataType ) );

code += QStringLiteral( ", createByDefault=%1" ).arg( createByDefault() ? QStringLiteral( "True" ) : QStringLiteral( "False" ) );
if ( mSupportsAppend )
code += QStringLiteral( ", supportsAppend=True" );

QgsProcessingContext c;
code += QStringLiteral( ", defaultValue=%1)" ).arg( valueAsPythonString( mDefault, c ) );
Expand Down Expand Up @@ -5124,13 +5127,15 @@ QVariantMap QgsProcessingParameterFeatureSink::toVariantMap() const
{
QVariantMap map = QgsProcessingDestinationParameter::toVariantMap();
map.insert( QStringLiteral( "data_type" ), mDataType );
map.insert( QStringLiteral( "supports_append" ), mSupportsAppend );
return map;
}

bool QgsProcessingParameterFeatureSink::fromVariantMap( const QVariantMap &map )
{
QgsProcessingDestinationParameter::fromVariantMap( map );
mDataType = static_cast< QgsProcessing::SourceType >( map.value( QStringLiteral( "data_type" ) ).toInt() );
mSupportsAppend = map.value( QStringLiteral( "supports_append" ), false ).toBool();
return true;
}

Expand Down Expand Up @@ -5170,6 +5175,16 @@ QgsProcessingParameterFeatureSink *QgsProcessingParameterFeatureSink::fromScript
return new QgsProcessingParameterFeatureSink( name, description, type, definition, isOptional );
}

bool QgsProcessingParameterFeatureSink::supportsAppend() const
{
return mSupportsAppend;
}

void QgsProcessingParameterFeatureSink::setSupportsAppend( bool supportsAppend )
{
mSupportsAppend = supportsAppend;
}

QgsProcessingParameterRasterDestination::QgsProcessingParameterRasterDestination( const QString &name, const QString &description, const QVariant &defaultValue, bool optional, bool createByDefault )
: QgsProcessingDestinationParameter( name, description, defaultValue, optional, createByDefault )
{
Expand Down
23 changes: 22 additions & 1 deletion src/core/processing/qgsprocessingparameters.h
Expand Up @@ -2763,7 +2763,7 @@ class CORE_EXPORT QgsProcessingParameterFeatureSink : public QgsProcessingDestin
* output will not be created by default.
*/
QgsProcessingParameterFeatureSink( const QString &name, const QString &description = QString(), QgsProcessing::SourceType type = QgsProcessing::TypeVectorAnyGeometry, const QVariant &defaultValue = QVariant(),
bool optional = false, bool createByDefault = true );
bool optional = false, bool createByDefault = true, bool supportsAppend = false );

/**
* Returns the type name for the parameter class.
Expand Down Expand Up @@ -2804,6 +2804,26 @@ class CORE_EXPORT QgsProcessingParameterFeatureSink : public QgsProcessingDestin
*/
void setDataType( QgsProcessing::SourceType type );

/**
* Returns TRUE if the sink supports appending features to an existing table.
*
* A sink only supports appending if the algorithm implements QgsProcessingAlgorithm::sinkProperties for the sink parameter.
*
* \see setSupportsAppend()
* \since QGIS 3.14
*/
bool supportsAppend() const;

/**
* Sets whether the sink supports appending features to an existing table.
*
* \warning A sink only supports appending if the algorithm implements QgsProcessingAlgorithm::sinkProperties for the sink parameter.
*
* \see supportsAppend()
* \since QGIS 3.14
*/
void setSupportsAppend( bool supportsAppend );

QVariantMap toVariantMap() const override;
bool fromVariantMap( const QVariantMap &map ) override;
QString generateTemporaryDestination() const override;
Expand All @@ -2816,6 +2836,7 @@ class CORE_EXPORT QgsProcessingParameterFeatureSink : public QgsProcessingDestin
private:

QgsProcessing::SourceType mDataType = QgsProcessing::TypeVectorAnyGeometry;
bool mSupportsAppend = false;
};


Expand Down
20 changes: 18 additions & 2 deletions tests/src/analysis/testqgsprocessing.cpp
Expand Up @@ -8023,7 +8023,7 @@ void TestQgsProcessing::processingFeatureSink()
context.setProject( &p );

// first using static string definition
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterFeatureSink( QStringLiteral( "layer" ) ) );
std::unique_ptr< QgsProcessingParameterFeatureSink > def( new QgsProcessingParameterFeatureSink( QStringLiteral( "layer" ) ) );
QVariantMap params;
params.insert( QStringLiteral( "layer" ), QgsProcessingOutputLayerDefinition( "memory:test", nullptr ) );
QString dest;
Expand Down Expand Up @@ -8091,6 +8091,22 @@ void TestQgsProcessing::processingFeatureSink()
params.insert( QStringLiteral( "layer" ), QVariant() );
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem( "EPSG:3113" ), context, dest ) );
QVERIFY( sink.get() );

// appendable
def->setSupportsAppend( true );
QVERIFY( def->supportsAppend() );
QString pythonCode = def->asPythonString();
QCOMPARE( pythonCode, QStringLiteral( "QgsProcessingParameterFeatureSink('layer', '', optional=True, type=QgsProcessing.TypeMapLayer, createByDefault=True, supportsAppend=True, defaultValue='memory:defaultlayer')" ) );

QVariantMap val = def->toVariantMap();
QgsProcessingParameterFeatureSink fromMap( "x" );
QVERIFY( fromMap.fromVariantMap( val ) );
QVERIFY( fromMap.supportsAppend() );

def->setSupportsAppend( false );
QVERIFY( !def->supportsAppend() );
pythonCode = def->asPythonString();
QCOMPARE( pythonCode, QStringLiteral( "QgsProcessingParameterFeatureSink('layer', '', optional=True, type=QgsProcessing.TypeMapLayer, createByDefault=True, defaultValue='memory:defaultlayer')" ) );
}

void TestQgsProcessing::algorithmScope()
Expand Down Expand Up @@ -9370,7 +9386,7 @@ void TestQgsProcessing::modelExecution()
" param = QgsProcessingParameterCrs('CRS', '', defaultValue=QgsCoordinateReferenceSystem('EPSG:28355'))\n"
" param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)\n"
" self.addParameter(param)\n"
" self.addParameter(QgsProcessingParameterFeatureSink('MyModelOutput', 'my model output', type=QgsProcessing.TypeVectorPolygon, createByDefault=True, defaultValue=None))\n"
" self.addParameter(QgsProcessingParameterFeatureSink('MyModelOutput', 'my model output', type=QgsProcessing.TypeVectorPolygon, createByDefault=True, supportsAppend=True, defaultValue=None))\n"
" self.addParameter(QgsProcessingParameterFeatureSink('cx3:MY_OUT', '', type=QgsProcessing.TypeVectorAnyGeometry, createByDefault=True, defaultValue=None))\n"
"\n"
" def processAlgorithm(self, parameters, context, model_feedback):\n"
Expand Down

0 comments on commit bb9b25f

Please sign in to comment.