Skip to content

Commit

Permalink
Auto create corresponding outputs when adding destination style
Browse files Browse the repository at this point in the history
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 058271b
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 7 deletions.
12 changes: 11 additions & 1 deletion python/core/processing/qgsprocessingalgorithm.sip
Expand Up @@ -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
Expand All @@ -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
Expand Down
30 changes: 28 additions & 2 deletions src/core/processing/qgsprocessingalgorithm.cpp
Expand Up @@ -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;
Expand All @@ -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 )
Expand Down Expand Up @@ -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;
}
}


15 changes: 13 additions & 2 deletions src/core/processing/qgsprocessingalgorithm.h
Expand Up @@ -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
Expand All @@ -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()
*/
Expand Down Expand Up @@ -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;
Expand Down
19 changes: 17 additions & 2 deletions tests/src/core/testqgsprocessing.cpp
Expand Up @@ -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
Expand All @@ -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()
Expand Down

0 comments on commit 058271b

Please sign in to comment.