Skip to content

Commit

Permalink
Handle mixed lists of values and lists when evaluating multilayer
Browse files Browse the repository at this point in the history
parameters

This can happen when running models with mixed input types
for multilayer parameters
  • Loading branch information
nyalldawson committed Aug 16, 2017
1 parent e1b0f78 commit c54667c
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 17 deletions.
38 changes: 22 additions & 16 deletions src/core/processing/qgsprocessingparameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "qgsprocessingoutputs.h"
#include "qgssettings.h"
#include "qgsvectorfilewriter.h"
#include <functional>

bool QgsProcessingParameters::isDynamic( const QVariantMap &parameters, const QString &name )
{
Expand Down Expand Up @@ -596,31 +597,36 @@ QList<QgsMapLayer *> QgsProcessingParameters::parameterAsLayerList( const QgsPro

QStringList resultStringList;

if ( val.canConvert<QgsProperty>() )
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<QObject *>( 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<QgsProperty>() )
resultStringList << var.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() );
else if ( QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( var ) ) )
{
resultStringList << s;
layers << layer;
}
}
else
resultStringList << val.toString();
else
{
resultStringList << var.toString();
}
};

processVariant( val );

if ( layers.isEmpty() && ( resultStringList.isEmpty() || resultStringList.at( 0 ).isEmpty() ) )
{
Expand Down
11 changes: 10 additions & 1 deletion tests/src/core/testqgsprocessing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<QgsMapLayer *>() << v1 << r1 );
QgsVectorLayer *v2 = new QgsVectorLayer( "Polygon?crs=EPSG:3111", "V5", "memory" );
p.addMapLayers( QList<QgsMapLayer *>() << v1 << v2 << r1 );
QgsProcessingContext context;
context.setProject( &p );

Expand Down Expand Up @@ -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 );
Expand Down

0 comments on commit c54667c

Please sign in to comment.