Skip to content
Permalink
Browse files

Auto create corresponding outputs when adding destination style

parameters to an algorithm

QgsProcessingAlgorithm::addParameter() has a new createOuput
argument (true by default).

If the createOutput argument is true, then a corresponding
output definition will also be created (and added to the
algorithm) where appropriate. E.g. when adding a
QgsProcessingParameterVectorDestination and createOutput is
true, then a QgsProcessingOutputVectorLayer output will be
created and added to the algorithm. There is no need to call
addOutput() to manually add a corresponding output for this
vector. If createOutput is false then this automatic output
creation will not occur.

This should simplify declaration of outputs for algorithms
as it avoids the need to manually declare these corresponding
outputs.
  • Loading branch information
nyalldawson committed Jul 11, 2017
1 parent 18b52b2 commit 058271b0c1a1c7cee94c6aae7662c682cd09a410
@@ -392,14 +392,21 @@ class QgsProcessingAlgorithm
.. seealso:: addOutput()
%End

bool addParameter( QgsProcessingParameterDefinition *parameterDefinition /Transfer/ );
bool addParameter( QgsProcessingParameterDefinition *parameterDefinition /Transfer/, bool createOutput = true );
%Docstring
Adds a parameter ``definition`` to the algorithm. Ownership of the definition is transferred to the algorithm.
Returns true if parameter could be successfully added, or false if the parameter could not be added (e.g.
as a result of a duplicate name).

This should usually be called from a subclass' initAlgorithm() implementation.

If the ``createOutput`` argument is true, then a corresponding output definition will also be created
(and added to the algorithm) where appropriate. E.g. when adding a QgsProcessingParameterVectorDestination
and ``createOutput`` is true, then a QgsProcessingOutputVectorLayer output will be created and
added to the algorithm. There is no need to call addOutput() to manually add a corresponding output
for this vector. If ``createOutput`` is false then this automatic output creation will not
occur.

.. seealso:: initAlgorithm()
.. seealso:: addOutput()
:rtype: bool
@@ -419,6 +426,9 @@ class QgsProcessingAlgorithm

This should usually be called from a subclass' initAlgorithm() implementation.

Note that in some cases output creation can be automatically performed when calling addParameter().
See the notes in addParameter() for a description of when this occurs.

.. seealso:: addParameter()
.. seealso:: initAlgorithm()
:rtype: bool
@@ -226,7 +226,7 @@ QString QgsProcessingAlgorithm::asPythonCommand( const QVariantMap &parameters,
return s;
}

bool QgsProcessingAlgorithm::addParameter( QgsProcessingParameterDefinition *definition )
bool QgsProcessingAlgorithm::addParameter( QgsProcessingParameterDefinition *definition, bool createOutput )
{
if ( !definition )
return false;
@@ -242,7 +242,11 @@ bool QgsProcessingAlgorithm::addParameter( QgsProcessingParameterDefinition *def
}

mParameters << definition;
return true;

if ( createOutput )
return createAutoOutputForParameter( definition );
else
return true;
}

void QgsProcessingAlgorithm::removeParameter( const QString &name )
@@ -581,4 +585,26 @@ QStringList QgsProcessingAlgorithm::parameterAsFields( const QVariantMap &parame
return QgsProcessingParameters::parameterAsFields( parameterDefinition( name ), parameters, context );
}

bool QgsProcessingAlgorithm::createAutoOutputForParameter( QgsProcessingParameterDefinition *parameter )
{
if ( !parameter->isDestination() )
return true; // nothing created, but nothing went wrong - so return true

QgsProcessingDestinationParameter *dest = static_cast< QgsProcessingDestinationParameter * >( parameter );
QgsProcessingOutputDefinition *output( dest->toOutputDefinition() );
if ( !output )
return true; // nothing created - but nothing went wrong - so return true

if ( !addOutput( output ) )
{
// couldn't add output - probably a duplicate name
delete output;
return false;
}
else
{
return true;
}
}


@@ -391,10 +391,17 @@ class CORE_EXPORT QgsProcessingAlgorithm
*
* This should usually be called from a subclass' initAlgorithm() implementation.
*
* If the \a createOutput argument is true, then a corresponding output definition will also be created
* (and added to the algorithm) where appropriate. E.g. when adding a QgsProcessingParameterVectorDestination
* and \a createOutput is true, then a QgsProcessingOutputVectorLayer output will be created and
* added to the algorithm. There is no need to call addOutput() to manually add a corresponding output
* for this vector. If \a createOutput is false then this automatic output creation will not
* occur.
*
* \see initAlgorithm()
* \see addOutput()
*/
bool addParameter( QgsProcessingParameterDefinition *parameterDefinition SIP_TRANSFER );
bool addParameter( QgsProcessingParameterDefinition *parameterDefinition SIP_TRANSFER, bool createOutput = true );

/**
* Removes the parameter with matching \a name from the algorithm, and deletes any existing
@@ -409,6 +416,9 @@ class CORE_EXPORT QgsProcessingAlgorithm
*
* This should usually be called from a subclass' initAlgorithm() implementation.
*
* Note that in some cases output creation can be automatically performed when calling addParameter().
* See the notes in addParameter() for a description of when this occurs.
*
* \see addParameter()
* \see initAlgorithm()
*/
@@ -672,7 +682,8 @@ class CORE_EXPORT QgsProcessingAlgorithm
bool mHasPostProcessed = false;
std::unique_ptr< QgsProcessingContext > mLocalContext;

// friend class to access setProvider() - we do not want this public!
bool createAutoOutputForParameter( QgsProcessingParameterDefinition *parameter );

friend class QgsProcessingProvider;
friend class TestQgsProcessing;
friend class QgsProcessingModelAlgorithm;
@@ -101,10 +101,10 @@ class DummyAlgorithm : public QgsProcessingAlgorithm
//destination styleparameters
QVERIFY( destinationParameterDefinitions().isEmpty() );
QgsProcessingParameterFeatureSink *p5 = new QgsProcessingParameterFeatureSink( "p5" );
QVERIFY( addParameter( p5 ) );
QVERIFY( addParameter( p5, false ) );
QCOMPARE( destinationParameterDefinitions(), QgsProcessingParameterDefinitions() << p5 );
QgsProcessingParameterFeatureSink *p6 = new QgsProcessingParameterFeatureSink( "p6" );
QVERIFY( addParameter( p6 ) );
QVERIFY( addParameter( p6, false ) );
QCOMPARE( destinationParameterDefinitions(), QgsProcessingParameterDefinitions() << p5 << p6 );

// remove parameter
@@ -113,6 +113,21 @@ class DummyAlgorithm : public QgsProcessingAlgorithm
QCOMPARE( destinationParameterDefinitions(), QgsProcessingParameterDefinitions() << p5 );
removeParameter( "p5" );
QVERIFY( destinationParameterDefinitions().isEmpty() );

// try with auto output creation
QgsProcessingParameterVectorDestination *p7 = new QgsProcessingParameterVectorDestination( "p7", "my output" );
QVERIFY( addParameter( p7 ) );
QCOMPARE( destinationParameterDefinitions(), QgsProcessingParameterDefinitions() << p7 );
QVERIFY( outputDefinition( "p7" ) );
QCOMPARE( outputDefinition( "p7" )->name(), QStringLiteral( "p7" ) );
QCOMPARE( outputDefinition( "p7" )->type(), QStringLiteral( "outputVector" ) );
QCOMPARE( outputDefinition( "p7" )->description(), QStringLiteral( "my output" ) );

// duplicate output name
QVERIFY( addOutput( new QgsProcessingOutputVectorLayer( "p8" ) ) );
QgsProcessingParameterVectorDestination *p8 = new QgsProcessingParameterVectorDestination( "p8" );
// this should fail - it would result in a duplicate output name
QVERIFY( !addParameter( p8 ) );
}

void runOutputChecks()

0 comments on commit 058271b

Please sign in to comment.
You can’t perform that action at this time.