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.
This commit is contained in:
Nyall Dawson 2017-07-12 07:18:53 +10:00
parent 18b52b22f1
commit 058271b0c1
4 changed files with 69 additions and 7 deletions

View File

@ -392,7 +392,7 @@ 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.
@ -400,6 +400,13 @@ class QgsProcessingAlgorithm
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

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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()