From c54667c3b142ff156194e70bd2a6d0df8890664e Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 17 Aug 2017 05:00:47 +1000 Subject: [PATCH] Handle mixed lists of values and lists when evaluating multilayer parameters This can happen when running models with mixed input types for multilayer parameters --- .../processing/qgsprocessingparameters.cpp | 38 +++++++++++-------- tests/src/core/testqgsprocessing.cpp | 11 +++++- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/src/core/processing/qgsprocessingparameters.cpp b/src/core/processing/qgsprocessingparameters.cpp index 0e7574b2afbf..af1d1271667b 100644 --- a/src/core/processing/qgsprocessingparameters.cpp +++ b/src/core/processing/qgsprocessingparameters.cpp @@ -22,6 +22,7 @@ #include "qgsprocessingoutputs.h" #include "qgssettings.h" #include "qgsvectorfilewriter.h" +#include bool QgsProcessingParameters::isDynamic( const QVariantMap ¶meters, const QString &name ) { @@ -596,31 +597,36 @@ QList QgsProcessingParameters::parameterAsLayerList( const QgsPro QStringList resultStringList; - if ( val.canConvert() ) - resultStringList << val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() ); - else if ( val.type() == QVariant::List ) + std::function< void( const QVariant &var ) > processVariant; + processVariant = [ &resultStringList, &layers, &context, &definition, &processVariant ]( const QVariant & var ) { - Q_FOREACH ( const QVariant &var, val.toList() ) + if ( var.type() == QVariant::List ) { - if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast( var ) ) ) + Q_FOREACH ( const QVariant &listVar, var.toList() ) { - layers << layer; + processVariant( listVar ); } - else + } + else if ( var.type() == QVariant::StringList ) + { + Q_FOREACH ( const QString &s, var.toStringList() ) { - resultStringList << var.toString(); + resultStringList << s; } } - } - else if ( val.type() == QVariant::StringList ) - { - Q_FOREACH ( const QString &s, val.toStringList() ) + else if ( var.canConvert() ) + resultStringList << var.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() ); + else if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast( var ) ) ) { - resultStringList << s; + layers << layer; } - } - else - resultStringList << val.toString(); + else + { + resultStringList << var.toString(); + } + }; + + processVariant( val ); if ( layers.isEmpty() && ( resultStringList.isEmpty() || resultStringList.at( 0 ).isEmpty() ) ) { diff --git a/tests/src/core/testqgsprocessing.cpp b/tests/src/core/testqgsprocessing.cpp index 6055079e74ae..87ff8bcb6b05 100644 --- a/tests/src/core/testqgsprocessing.cpp +++ b/tests/src/core/testqgsprocessing.cpp @@ -2183,7 +2183,8 @@ void TestQgsProcessing::parameterLayerList() QFileInfo fi1( raster1 ); QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" ); QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon?crs=EPSG:3111", "V4", "memory" ); - p.addMapLayers( QList() << v1 << r1 ); + QgsVectorLayer *v2 = new QgsVectorLayer( "Polygon?crs=EPSG:3111", "V5", "memory" ); + p.addMapLayers( QList() << v1 << v2 << r1 ); QgsProcessingContext context; context.setProject( &p ); @@ -2225,6 +2226,14 @@ void TestQgsProcessing::parameterLayerList() params.insert( "non_optional", QVariantList() << QVariant::fromValue( v1 ) << QVariant::fromValue( r1 ) ); QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << r1 ); + // mix of list and single layers (happens from models) + params.insert( "non_optional", QVariantList() << QVariant( QVariantList() << QVariant::fromValue( v1 ) << QVariant::fromValue( v2 ) ) << QVariant::fromValue( r1 ) ); + QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << v2 << r1 ); + + // mix of two lists (happens from models) + params.insert( "non_optional", QVariantList() << QVariant( QVariantList() << QVariant::fromValue( v1 ) << QVariant::fromValue( v2 ) ) << QVariant( QVariantList() << QVariant::fromValue( r1 ) ) ); + QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << v2 << r1 ); + // mix of existing layers and non project layer string params.insert( "non_optional", QVariantList() << v1->id() << raster2 ); QList< QgsMapLayer *> layers = QgsProcessingParameters::parameterAsLayerList( def.get(), params, context );