Skip to content

Commit

Permalink
Fix generation of destination parameters for models
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jun 21, 2017
1 parent c36169a commit fe0f249
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 0 deletions.
15 changes: 15 additions & 0 deletions python/core/processing/qgsprocessingmodelalgorithm.sip
Expand Up @@ -502,6 +502,10 @@ Copies are protected to avoid slicing
%Docstring
Returns the final model output with matching ``name``. If no output
exists with the name, a new one will be created and returned.

If child model outputs are altered by this method, QgsProcessingModelAlgorithm.updateDestinationParameters()
must be called on the parent model.

.. seealso:: modelOutputs()
.. seealso:: setModelOutputs()
:rtype: QgsProcessingModelAlgorithm.ModelOutput
Expand All @@ -512,6 +516,10 @@ Copies are protected to avoid slicing
Sets the map of final model ``outputs`` which are generated by this child algorithm.
The keys are the output names from this child algorithm. Only outputs which are
part of the final outputs from the model should be included in this map.

If child model outputs are altered by this method, QgsProcessingModelAlgorithm.updateDestinationParameters()
must be called on the parent model.

.. seealso:: modelOutputs()
%End

Expand Down Expand Up @@ -728,6 +736,13 @@ Copies are protected to avoid slicing
:rtype: QgsProcessingModelAlgorithm.ModelParameter
%End

void updateDestinationParameters();
%Docstring
Updates the model's parameter definitions to include all relevant destination
parameters as required by child algorithm ModelOutputs.
Must be called whenever child algorithm ModelOutputs are altered.
%End

bool toFile( const QString &path ) const;
%Docstring
Writes the model to a file, at the specified ``path``.
Expand Down
45 changes: 45 additions & 0 deletions src/core/processing/qgsprocessingmodelalgorithm.cpp
Expand Up @@ -327,6 +327,43 @@ QgsProcessingModelAlgorithm::ModelParameter &QgsProcessingModelAlgorithm::parame
return mParameterComponents[ name ];
}

void QgsProcessingModelAlgorithm::updateDestinationParameters()
{
//delete existing destination parameters
QMutableListIterator<const QgsProcessingParameterDefinition *> it( mParameters );
while ( it.hasNext() )
{
const QgsProcessingParameterDefinition *def = it.next();
if ( def->isDestination() )
{
delete def;
it.remove();
}
}

QMap< QString, ChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
{
QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> outputs = childIt->modelOutputs();
QMap<QString, QgsProcessingModelAlgorithm::ModelOutput>::const_iterator outputIt = outputs.constBegin();
for ( ; outputIt != outputs.constEnd(); ++outputIt )
{
if ( !childIt->isActive() || !childIt->algorithm() )
continue;

// child algorithm has a destination parameter set, copy it to the model
const QgsProcessingParameterDefinition *source = childIt->algorithm()->parameterDefinition( outputIt->outputName() );
if ( !source )
continue;

QgsProcessingParameterDefinition *param = QgsProcessingParameters::parameterFromVariantMap( source->toVariantMap() );
param->setName( outputIt->childId() + ':' + outputIt->outputName() );
param->setDescription( outputIt->description() );
addParameter( param );
}
}
}

QVariant QgsProcessingModelAlgorithm::toVariant() const
{
QVariantMap map;
Expand Down Expand Up @@ -403,6 +440,8 @@ bool QgsProcessingModelAlgorithm::loadVariant( const QVariant &model )
addParameter( param );
}

updateDestinationParameters();

return true;
}

Expand Down Expand Up @@ -443,11 +482,13 @@ bool QgsProcessingModelAlgorithm::fromFile( const QString &path )
void QgsProcessingModelAlgorithm::setChildAlgorithms( const QMap<QString, ChildAlgorithm> &childAlgorithms )
{
mChildAlgorithms = childAlgorithms;
updateDestinationParameters();
}

void QgsProcessingModelAlgorithm::setChildAlgorithm( const QgsProcessingModelAlgorithm::ChildAlgorithm &algorithm )
{
mChildAlgorithms.insert( algorithm.childId(), algorithm );
updateDestinationParameters();
}

QString QgsProcessingModelAlgorithm::addChildAlgorithm( ChildAlgorithm &algorithm )
Expand All @@ -456,6 +497,7 @@ QString QgsProcessingModelAlgorithm::addChildAlgorithm( ChildAlgorithm &algorith
algorithm.generateChildId( *this );

mChildAlgorithms.insert( algorithm.childId(), algorithm );
updateDestinationParameters();
return algorithm.childId();
}

Expand All @@ -470,6 +512,7 @@ bool QgsProcessingModelAlgorithm::removeChildAlgorithm( const QString &id )
return false;

mChildAlgorithms.remove( id );
updateDestinationParameters();
return true;
}

Expand All @@ -480,6 +523,7 @@ void QgsProcessingModelAlgorithm::deactivateChildAlgorithm( const QString &id )
childAlgorithm( child ).setActive( false );
}
childAlgorithm( id ).setActive( false );
updateDestinationParameters();
}

bool QgsProcessingModelAlgorithm::activateChildAlgorithm( const QString &id )
Expand All @@ -490,6 +534,7 @@ bool QgsProcessingModelAlgorithm::activateChildAlgorithm( const QString &id )
return false;
}
childAlgorithm( id ).setActive( true );
updateDestinationParameters();
return true;
}

Expand Down
15 changes: 15 additions & 0 deletions src/core/processing/qgsprocessingmodelalgorithm.h
Expand Up @@ -491,6 +491,10 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
/**
* Returns the final model output with matching \a name. If no output
* exists with the name, a new one will be created and returned.
*
* If child model outputs are altered by this method, QgsProcessingModelAlgorithm::updateDestinationParameters()
* must be called on the parent model.
*
* \see modelOutputs()
* \see setModelOutputs()
*/
Expand All @@ -500,6 +504,10 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
* Sets the map of final model \a outputs which are generated by this child algorithm.
* The keys are the output names from this child algorithm. Only outputs which are
* part of the final outputs from the model should be included in this map.
*
* If child model outputs are altered by this method, QgsProcessingModelAlgorithm::updateDestinationParameters()
* must be called on the parent model.
*
* \see modelOutputs()
*/
void setModelOutputs( const QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> &outputs );
Expand Down Expand Up @@ -720,6 +728,13 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
*/
QgsProcessingModelAlgorithm::ModelParameter &parameterComponent( const QString &name );

/**
* Updates the model's parameter definitions to include all relevant destination
* parameters as required by child algorithm ModelOutputs.
* Must be called whenever child algorithm ModelOutputs are altered.
*/
void updateDestinationParameters();

/**
* Writes the model to a file, at the specified \a path.
* \see fromFile()
Expand Down
41 changes: 41 additions & 0 deletions tests/src/core/testqgsprocessing.cpp
Expand Up @@ -3752,6 +3752,47 @@ void TestQgsProcessing::modelerAlgorithm()
QCOMPARE( alg6.parameterDefinitions().count(), 1 );
QCOMPARE( alg6.parameterDefinitions().at( 0 )->type(), QStringLiteral( "boolean" ) );

// destination parameters
QgsProcessingModelAlgorithm alg7( "test", "testGroup" );
QgsProcessingModelAlgorithm::ChildAlgorithm alg7c1;
alg7c1.setChildId( "cx1" );
alg7c1.setAlgorithmId( "native:centroids" );
QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> alg7c1outputs;
QgsProcessingModelAlgorithm::ModelOutput alg7c1out1;
alg7c1out1.setChildId( "cx1" );
alg7c1out1.setOutputName( "OUTPUT_LAYER" );
alg7c1out1.setDescription( QStringLiteral( "my output" ) );
alg7c1outputs.insert( QStringLiteral( "OUTPUT_LAYER" ), alg7c1out1 );
alg7c1.setModelOutputs( alg7c1outputs );
alg7.addChildAlgorithm( alg7c1 );
// verify that model has destination parameter created
QCOMPARE( alg7.destinationParameterDefinitions().count(), 1 );
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->name(), QStringLiteral( "cx1:OUTPUT_LAYER" ) );
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->description(), QStringLiteral( "my output" ) );

QgsProcessingModelAlgorithm::ChildAlgorithm alg7c2;
alg7c2.setChildId( "cx2" );
alg7c2.setAlgorithmId( "native:centroids" );
QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> alg7c2outputs;
QgsProcessingModelAlgorithm::ModelOutput alg7c2out1;
alg7c2out1.setChildId( "cx2" );
alg7c2out1.setOutputName( "OUTPUT_LAYER" );
alg7c2out1.setDescription( QStringLiteral( "my output2" ) );
alg7c2outputs.insert( QStringLiteral( "OUTPUT_LAYER" ), alg7c2out1 );
alg7c2.setModelOutputs( alg7c2outputs );
alg7.addChildAlgorithm( alg7c2 );

QCOMPARE( alg7.destinationParameterDefinitions().count(), 2 );
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->name(), QStringLiteral( "cx1:OUTPUT_LAYER" ) );
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->description(), QStringLiteral( "my output" ) );
QCOMPARE( alg7.destinationParameterDefinitions().at( 1 )->name(), QStringLiteral( "cx2:OUTPUT_LAYER" ) );
QCOMPARE( alg7.destinationParameterDefinitions().at( 1 )->description(), QStringLiteral( "my output2" ) );

alg7.removeChildAlgorithm( "cx1" );
QCOMPARE( alg7.destinationParameterDefinitions().count(), 1 );
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->name(), QStringLiteral( "cx2:OUTPUT_LAYER" ) );
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->description(), QStringLiteral( "my output2" ) );

}

QGSTEST_MAIN( TestQgsProcessing )
Expand Down

0 comments on commit fe0f249

Please sign in to comment.