Fix incorrect layer names used when loading result layers from models

This commit is contained in:
Nyall Dawson 2017-07-03 17:08:52 +10:00
parent 846f81023b
commit bdaba00a01
5 changed files with 92 additions and 5 deletions

View File

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

View File

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

View File

@ -219,6 +219,7 @@ QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingPar
}
QgsProject *destinationProject = nullptr;
QString destName;
QVariantMap createOptions;
if ( val.canConvert<QgsProcessingOutputLayerDefinition>() )
{
@ -227,6 +228,7 @@ QgsFeatureSink *QgsProcessingParameters::parameterAsSink( const QgsProcessingPar
destinationProject = fromVar.destinationProject;
createOptions = fromVar.createOptions;
val = fromVar.sink;
destName = fromVar.destinationName;
}
QString dest;
@ -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();
}
@ -371,6 +379,7 @@ 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
@ -378,6 +387,7 @@ QString QgsProcessingParameters::parameterAsRasterOutputLayer( const QgsProcessi
destinationProject = fromVar.destinationProject;
createOptions = fromVar.createOptions;
val = fromVar.sink;
destName = fromVar.destinationName;
}
QString dest;
@ -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;
}

View File

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

View File

@ -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()
@ -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()
@ -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 );
@ -4704,12 +4742,22 @@ 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' );
@ -4717,11 +4765,13 @@ void TestQgsProcessing::modelExecution()
"##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 );
}