Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix incorrect layer names used when loading result layers from models
  • Loading branch information
nyalldawson committed Jul 3, 2017
1 parent 846f810 commit bdaba00
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 5 deletions.
5 changes: 5 additions & 0 deletions python/core/processing/qgsprocessingparameters.sip
Expand Up @@ -95,6 +95,11 @@ class QgsProcessingOutputLayerDefinition
The default behavior is not to load the result into any project (None).
%End

QString destinationName;
%Docstring
Name to use for sink if it's to be loaded into a destination project.
%End

QVariantMap createOptions;
%Docstring
Map of optional sink/layer creation options, which
Expand Down
13 changes: 12 additions & 1 deletion src/core/processing/qgsprocessingmodelalgorithm.cpp
Expand Up @@ -407,7 +407,18 @@ QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( const Chil
{
QString paramName = child.childId() + ':' + outputIt.key();
if ( modelParameters.contains( paramName ) )
childParams.insert( destParam->name(), modelParameters.value( paramName ) );
{
QVariant value = modelParameters.value( paramName );
if ( value.canConvert<QgsProcessingOutputLayerDefinition>() )
{
// make sure layout output name is correctly set
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( value );
fromVar.destinationName = outputIt.key();
value = QVariant::fromValue( fromVar );
}

childParams.insert( destParam->name(), value );
}
isFinalOutput = true;
break;
}
Expand Down
20 changes: 18 additions & 2 deletions src/core/processing/qgsprocessingparameters.cpp
Expand Up @@ -219,6 +219,7 @@ QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingPar
}

QgsProject *destinationProject = nullptr;
QString destName;
QVariantMap createOptions;
if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
{
Expand All @@ -227,6 +228,7 @@ QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingPar
destinationProject = fromVar.destinationProject;
createOptions = fromVar.createOptions;
val = fromVar.sink;
destName = fromVar.destinationName;
}

QString dest;
Expand Down Expand Up @@ -256,7 +258,13 @@ QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingPar
destinationIdentifier = dest;

if ( destinationProject )
context.addLayerToLoadOnCompletion( destinationIdentifier, QgsProcessingContext::LayerDetails( definition ? definition->description() : QString(), destinationProject ) );
{
if ( destName.isEmpty() && definition )
{
destName = definition->description();
}
context.addLayerToLoadOnCompletion( destinationIdentifier, QgsProcessingContext::LayerDetails( destName, destinationProject ) );
}

return sink.release();
}
Expand Down Expand Up @@ -371,13 +379,15 @@ QString QgsProcessingParameters::parameterAsRasterOutputLayer( const QgsProcessi

QgsProject *destinationProject = nullptr;
QVariantMap createOptions;
QString destName;
if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
{
// input is a QgsProcessingOutputLayerDefinition - get extra properties from it
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( val );
destinationProject = fromVar.destinationProject;
createOptions = fromVar.createOptions;
val = fromVar.sink;
destName = fromVar.destinationName;
}

QString dest;
Expand All @@ -396,7 +406,13 @@ QString QgsProcessingParameters::parameterAsRasterOutputLayer( const QgsProcessi
}

if ( destinationProject )
context.addLayerToLoadOnCompletion( dest, QgsProcessingContext::LayerDetails( definition ? definition->description() : QString(), destinationProject ) );
{
if ( destName.isEmpty() && definition )
{
destName = definition->description();
}
context.addLayerToLoadOnCompletion( dest, QgsProcessingContext::LayerDetails( destName, destinationProject ) );
}

return dest;
}
Expand Down
5 changes: 5 additions & 0 deletions src/core/processing/qgsprocessingparameters.h
Expand Up @@ -128,6 +128,11 @@ class CORE_EXPORT QgsProcessingOutputLayerDefinition
*/
QgsProject *destinationProject;

/**
* Name to use for sink if it's to be loaded into a destination project.
*/
QString destinationName;

/**
* Map of optional sink/layer creation options, which
* are passed to the underlying provider when creating new layers. Known options also
Expand Down
54 changes: 52 additions & 2 deletions tests/src/core/testqgsprocessing.cpp
Expand Up @@ -1292,6 +1292,18 @@ void TestQgsProcessing::parameters()
QCOMPARE( context.layersToLoadOnCompletion().size(), 1 );
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), destId );
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "desc" ) );

// with name overloading
QgsProcessingContext context2;
fs = QgsProcessingOutputLayerDefinition( QStringLiteral( "test.shp" ) );
fs.destinationProject = &p;
fs.destinationName = QStringLiteral( "my_dest" );
params.insert( QStringLiteral( "fs" ), QVariant::fromValue( fs ) );
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, fields, wkbType, crs, context2, destId ) );
QVERIFY( sink.get() );
QCOMPARE( context2.layersToLoadOnCompletion().size(), 1 );
QCOMPARE( context2.layersToLoadOnCompletion().keys().at( 0 ), destId );
QCOMPARE( context2.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "my_dest" ) );
}

void TestQgsProcessing::algorithmParameters()
Expand Down Expand Up @@ -3687,6 +3699,29 @@ void TestQgsProcessing::parameterRasterOut()
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
QCOMPARE( fromCode->flags(), def->flags() );
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );

// test layers to load on completion
def.reset( new QgsProcessingParameterRasterOutput( "x", QStringLiteral( "desc" ), QStringLiteral( "default.tif" ), true ) );
QgsProcessingOutputLayerDefinition fs = QgsProcessingOutputLayerDefinition( QStringLiteral( "test.tif" ) );
fs.destinationProject = &p;
params.insert( QStringLiteral( "x" ), QVariant::fromValue( fs ) );
QCOMPARE( QgsProcessingParameters::parameterAsRasterOutputLayer( def.get(), params, context ), QStringLiteral( "test.tif" ) );

// make sure layer was automatically added to list to load on completion
QCOMPARE( context.layersToLoadOnCompletion().size(), 1 );
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), QStringLiteral( "test.tif" ) );
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "desc" ) );

// with name overloading
QgsProcessingContext context2;
fs = QgsProcessingOutputLayerDefinition( QStringLiteral( "test.tif" ) );
fs.destinationProject = &p;
fs.destinationName = QStringLiteral( "my_dest" );
params.insert( QStringLiteral( "x" ), QVariant::fromValue( fs ) );
QCOMPARE( QgsProcessingParameters::parameterAsRasterOutputLayer( def.get(), params, context2 ), QStringLiteral( "test.tif" ) );
QCOMPARE( context2.layersToLoadOnCompletion().size(), 1 );
QCOMPARE( context2.layersToLoadOnCompletion().keys().at( 0 ), QStringLiteral( "test.tif" ) );
QCOMPARE( context2.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "my_dest" ) );
}

void TestQgsProcessing::parameterFileOut()
Expand Down Expand Up @@ -4672,6 +4707,9 @@ void TestQgsProcessing::modelExecution()
modelInputs.insert( "SOURCE_LAYER", "my_layer_id" );
modelInputs.insert( "DIST", 271 );
modelInputs.insert( "cx1:MODEL_OUT_LAYER", "dest.shp" );
QgsProcessingOutputLayerDefinition layerDef( "memory:" );
layerDef.destinationName = "my_dest";
modelInputs.insert( "cx3:MY_OUT", QVariant::fromValue( layerDef ) );
QMap<QString, QVariantMap> childResults;
QVariantMap params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx1" ), modelInputs, childResults );
QCOMPARE( params.value( "DISSOLVE" ).toBool(), false );
Expand Down Expand Up @@ -4704,24 +4742,36 @@ void TestQgsProcessing::modelExecution()
alg2c3.setAlgorithmId( "native:extractbyexpression" );
alg2c3.addParameterSources( "INPUT", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromChildOutput( "cx1", "OUTPUT_LAYER" ) );
alg2c3.addParameterSources( "EXPRESSION", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromStaticValue( "true" ) );
alg2c3.addParameterSources( "OUTPUT", QgsProcessingModelAlgorithm::ChildParameterSources() << QgsProcessingModelAlgorithm::ChildParameterSource::fromModelParameter( "MY_OUT" ) );
alg2c3.setDependencies( QStringList() << "cx2" );
QMap<QString, QgsProcessingModelAlgorithm::ModelOutput> outputs3;
QgsProcessingModelAlgorithm::ModelOutput out2( "MY_OUT" );
out2.setChildOutputName( "OUTPUT" );
outputs3.insert( QStringLiteral( "MY_OUT" ), out2 );
alg2c3.setModelOutputs( outputs3 );

model2.addChildAlgorithm( alg2c3 );
params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx3" ), modelInputs, childResults );
QCOMPARE( params.value( "INPUT" ).toString(), QStringLiteral( "dest.shp" ) );
QCOMPARE( params.value( "EXPRESSION" ).toString(), QStringLiteral( "true" ) );
QCOMPARE( params.value( "OUTPUT" ).toString(), QStringLiteral( "memory:" ) );
QVERIFY( params.value( "OUTPUT" ).canConvert<QgsProcessingOutputLayerDefinition>() );
QgsProcessingOutputLayerDefinition outDef = qvariant_cast<QgsProcessingOutputLayerDefinition>( params.value( "OUTPUT" ) );
QCOMPARE( outDef.destinationName, QStringLiteral( "MY_OUT" ) );
QCOMPARE( outDef.sink.staticValue().toString(), QStringLiteral( "memory:" ) );
QCOMPARE( params.count(), 3 ); // don't want FAIL_OUTPUT set!

QStringList actualParts = model2.asPythonCode().split( '\n' );
QStringList expectedParts = QStringLiteral( "##model=name\n"
"##DIST=number\n"
"##SOURCE_LAYER=source\n"
"##model_out_layer=output outputVector\n"
"##my_out=output outputVector\n"
"results={}\n"
"outputs['cx1']=processing.run('native:buffer', {'DISSOLVE':false,'DISTANCE':parameters['DIST'],'END_CAP_STYLE':1,'INPUT':parameters['SOURCE_LAYER'],'JOIN_STYLE':2,'SEGMENTS':16}, context=context, feedback=feedback)\n"
"results['MODEL_OUT_LAYER']=outputs['cx1']['OUTPUT_LAYER']\n"
"outputs['cx2']=processing.run('native:centroids', {'INPUT':outputs['cx1']['OUTPUT_LAYER']}, context=context, feedback=feedback)\n"
"outputs['cx3']=processing.run('native:extractbyexpression', {'EXPRESSION':true,'INPUT':outputs['cx1']['OUTPUT_LAYER']}, context=context, feedback=feedback)\n"
"outputs['cx3']=processing.run('native:extractbyexpression', {'EXPRESSION':true,'INPUT':outputs['cx1']['OUTPUT_LAYER'],'OUTPUT':parameters['MY_OUT']}, context=context, feedback=feedback)\n"
"results['MY_OUT']=outputs['cx3']['OUTPUT']\n"
"return results" ).split( '\n' );
QCOMPARE( actualParts, expectedParts );
}
Expand Down

0 comments on commit bdaba00

Please sign in to comment.