mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-31 00:04:24 -05:00
their underlying algorithm's provider E.g. for model outputs generated by a saga algorithm, only sdat and shp files are valid outputs. So only give users choices of these instead of all formats. Also fixes temporary file names generated as part of model execution may use formats which are not compatible with the algorithm's provider. Fixes #18908
6760 lines
359 KiB
C++
6760 lines
359 KiB
C++
/***************************************************************************
|
|
testqgsprocessing.cpp
|
|
---------------------
|
|
begin : January 2017
|
|
copyright : (C) 2017 by Nyall Dawson
|
|
email : nyall dot dawson at gmail dot com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include "qgsprocessingregistry.h"
|
|
#include "qgsprocessingprovider.h"
|
|
#include "qgsprocessingutils.h"
|
|
#include "qgsprocessingalgorithm.h"
|
|
#include "qgsprocessingcontext.h"
|
|
#include "qgsprocessingparametertype.h"
|
|
#include "qgsprocessingmodelalgorithm.h"
|
|
#include "qgsnativealgorithms.h"
|
|
#include <QObject>
|
|
#include <QtTest/QSignalSpy>
|
|
#include "qgis.h"
|
|
#include "qgstest.h"
|
|
#include "qgsrasterlayer.h"
|
|
#include "qgsproject.h"
|
|
#include "qgspoint.h"
|
|
#include "qgsgeometry.h"
|
|
#include "qgsvectorfilewriter.h"
|
|
#include "qgsexpressioncontext.h"
|
|
#include "qgsxmlutils.h"
|
|
#include "qgsreferencedgeometry.h"
|
|
#include "qgssettings.h"
|
|
|
|
class DummyAlgorithm : public QgsProcessingAlgorithm
|
|
{
|
|
public:
|
|
|
|
DummyAlgorithm( const QString &name ) : mName( name ) { mFlags = QgsProcessingAlgorithm::flags(); }
|
|
|
|
void initAlgorithm( const QVariantMap & = QVariantMap() ) override {}
|
|
QString name() const override { return mName; }
|
|
QString displayName() const override { return mName; }
|
|
QVariantMap processAlgorithm( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * ) override { return QVariantMap(); }
|
|
|
|
Flags flags() const override { return mFlags; }
|
|
DummyAlgorithm *createInstance() const override { return new DummyAlgorithm( name() ); }
|
|
|
|
QString mName;
|
|
|
|
Flags mFlags;
|
|
|
|
void checkParameterVals()
|
|
{
|
|
addParameter( new QgsProcessingParameterString( "p1" ) );
|
|
QVariantMap params;
|
|
QgsProcessingContext context;
|
|
|
|
QVERIFY( !checkParameterValues( params, context ) );
|
|
params.insert( "p1", "a" );
|
|
QVERIFY( checkParameterValues( params, context ) );
|
|
// optional param
|
|
addParameter( new QgsProcessingParameterString( "p2", QString(), QVariant(), false, true ) );
|
|
QVERIFY( checkParameterValues( params, context ) );
|
|
params.insert( "p2", "a" );
|
|
QVERIFY( checkParameterValues( params, context ) );
|
|
}
|
|
|
|
void runParameterChecks()
|
|
{
|
|
QVERIFY( parameterDefinitions().isEmpty() );
|
|
QVERIFY( addParameter( new QgsProcessingParameterBoolean( "p1" ) ) );
|
|
QCOMPARE( parameterDefinitions().count(), 1 );
|
|
QCOMPARE( parameterDefinitions().at( 0 )->name(), QString( "p1" ) );
|
|
QCOMPARE( parameterDefinitions().at( 0 )->algorithm(), this );
|
|
|
|
QVERIFY( !addParameter( nullptr ) );
|
|
QCOMPARE( parameterDefinitions().count(), 1 );
|
|
// duplicate name!
|
|
QgsProcessingParameterBoolean *p2 = new QgsProcessingParameterBoolean( "p1" );
|
|
QVERIFY( !addParameter( p2 ) );
|
|
QCOMPARE( parameterDefinitions().count(), 1 );
|
|
|
|
QCOMPARE( parameterDefinition( "p1" ), parameterDefinitions().at( 0 ) );
|
|
// parameterDefinition should be case insensitive
|
|
QCOMPARE( parameterDefinition( "P1" ), parameterDefinitions().at( 0 ) );
|
|
QVERIFY( !parameterDefinition( "invalid" ) );
|
|
|
|
QCOMPARE( countVisibleParameters(), 1 );
|
|
QgsProcessingParameterBoolean *p3 = new QgsProcessingParameterBoolean( "p3" );
|
|
QVERIFY( addParameter( p3 ) );
|
|
QCOMPARE( countVisibleParameters(), 2 );
|
|
QgsProcessingParameterBoolean *p4 = new QgsProcessingParameterBoolean( "p4" );
|
|
p4->setFlags( QgsProcessingParameterDefinition::FlagHidden );
|
|
QVERIFY( addParameter( p4 ) );
|
|
QCOMPARE( countVisibleParameters(), 2 );
|
|
|
|
|
|
//destination styleparameters
|
|
QVERIFY( destinationParameterDefinitions().isEmpty() );
|
|
QgsProcessingParameterFeatureSink *p5 = new QgsProcessingParameterFeatureSink( "p5" );
|
|
QVERIFY( addParameter( p5, false ) );
|
|
QCOMPARE( destinationParameterDefinitions(), QgsProcessingParameterDefinitions() << p5 );
|
|
QgsProcessingParameterFeatureSink *p6 = new QgsProcessingParameterFeatureSink( "p6" );
|
|
QVERIFY( addParameter( p6, false ) );
|
|
QCOMPARE( destinationParameterDefinitions(), QgsProcessingParameterDefinitions() << p5 << p6 );
|
|
|
|
// remove parameter
|
|
removeParameter( "non existent" );
|
|
removeParameter( "p6" );
|
|
QCOMPARE( destinationParameterDefinitions(), QgsProcessingParameterDefinitions() << p5 );
|
|
removeParameter( "p5" );
|
|
QVERIFY( destinationParameterDefinitions().isEmpty() );
|
|
|
|
// try with auto output creation
|
|
QgsProcessingParameterVectorDestination *p7 = new QgsProcessingParameterVectorDestination( "p7", "my output" );
|
|
QVERIFY( addParameter( p7 ) );
|
|
QCOMPARE( destinationParameterDefinitions(), QgsProcessingParameterDefinitions() << p7 );
|
|
QVERIFY( outputDefinition( "p7" ) );
|
|
QCOMPARE( outputDefinition( "p7" )->name(), QStringLiteral( "p7" ) );
|
|
QCOMPARE( outputDefinition( "p7" )->type(), QStringLiteral( "outputVector" ) );
|
|
QCOMPARE( outputDefinition( "p7" )->description(), QStringLiteral( "my output" ) );
|
|
|
|
// duplicate output name
|
|
QVERIFY( addOutput( new QgsProcessingOutputVectorLayer( "p8" ) ) );
|
|
QgsProcessingParameterVectorDestination *p8 = new QgsProcessingParameterVectorDestination( "p8" );
|
|
// this should fail - it would result in a duplicate output name
|
|
QVERIFY( !addParameter( p8 ) );
|
|
|
|
// default vector format extension
|
|
QgsProcessingParameterFeatureSink *sinkParam = new QgsProcessingParameterFeatureSink( "sink" );
|
|
QCOMPARE( sinkParam->defaultFileExtension(), QStringLiteral( "shp" ) ); // before alg is accessible
|
|
QVERIFY( !sinkParam->algorithm() );
|
|
QVERIFY( !sinkParam->provider() );
|
|
QVERIFY( addParameter( sinkParam ) );
|
|
QCOMPARE( sinkParam->defaultFileExtension(), QStringLiteral( "shp" ) );
|
|
QCOMPARE( sinkParam->algorithm(), this );
|
|
QVERIFY( !sinkParam->provider() );
|
|
|
|
// default raster format extension
|
|
QgsProcessingParameterRasterDestination *rasterParam = new QgsProcessingParameterRasterDestination( "raster" );
|
|
QCOMPARE( rasterParam->defaultFileExtension(), QStringLiteral( "tif" ) ); // before alg is accessible
|
|
QVERIFY( addParameter( rasterParam ) );
|
|
QCOMPARE( rasterParam->defaultFileExtension(), QStringLiteral( "tif" ) );
|
|
|
|
// should allow parameters with same name but different case (required for grass provider)
|
|
QgsProcessingParameterBoolean *p1C = new QgsProcessingParameterBoolean( "P1" );
|
|
QVERIFY( addParameter( p1C ) );
|
|
QCOMPARE( parameterDefinitions().count(), 8 );
|
|
|
|
// parameterDefinition should be case insensitive, but prioritize correct case matches
|
|
QCOMPARE( parameterDefinition( "p1" ), parameterDefinitions().at( 0 ) );
|
|
QCOMPARE( parameterDefinition( "P1" ), parameterDefinitions().at( 7 ) );
|
|
}
|
|
|
|
void runParameterChecks2()
|
|
{
|
|
// default vector format extension, taken from provider
|
|
QgsProcessingParameterFeatureSink *sinkParam = new QgsProcessingParameterFeatureSink( "sink2" );
|
|
QCOMPARE( sinkParam->defaultFileExtension(), QStringLiteral( "shp" ) ); // before alg is accessible
|
|
QVERIFY( !sinkParam->algorithm() );
|
|
QVERIFY( !sinkParam->provider() );
|
|
QVERIFY( addParameter( sinkParam ) );
|
|
QCOMPARE( sinkParam->defaultFileExtension(), QStringLiteral( "xshp" ) );
|
|
QCOMPARE( sinkParam->algorithm(), this );
|
|
QCOMPARE( sinkParam->provider(), provider() );
|
|
|
|
// default raster format extension
|
|
QgsProcessingParameterRasterDestination *rasterParam = new QgsProcessingParameterRasterDestination( "raster2" );
|
|
QCOMPARE( rasterParam->defaultFileExtension(), QStringLiteral( "tif" ) ); // before alg is accessible
|
|
QVERIFY( addParameter( rasterParam ) );
|
|
QCOMPARE( rasterParam->defaultFileExtension(), QStringLiteral( "pcx" ) );
|
|
}
|
|
|
|
void runOutputChecks()
|
|
{
|
|
QVERIFY( outputDefinitions().isEmpty() );
|
|
QVERIFY( addOutput( new QgsProcessingOutputVectorLayer( "p1" ) ) );
|
|
QCOMPARE( outputDefinitions().count(), 1 );
|
|
QCOMPARE( outputDefinitions().at( 0 )->name(), QString( "p1" ) );
|
|
|
|
QVERIFY( !addOutput( nullptr ) );
|
|
QCOMPARE( outputDefinitions().count(), 1 );
|
|
// duplicate name!
|
|
QgsProcessingOutputVectorLayer *p2 = new QgsProcessingOutputVectorLayer( "p1" );
|
|
QVERIFY( !addOutput( p2 ) );
|
|
QCOMPARE( outputDefinitions().count(), 1 );
|
|
|
|
QCOMPARE( outputDefinition( "p1" ), outputDefinitions().at( 0 ) );
|
|
// parameterDefinition should be case insensitive
|
|
QCOMPARE( outputDefinition( "P1" ), outputDefinitions().at( 0 ) );
|
|
QVERIFY( !outputDefinition( "invalid" ) );
|
|
|
|
QVERIFY( !hasHtmlOutputs() );
|
|
QgsProcessingOutputHtml *p3 = new QgsProcessingOutputHtml( "p3" );
|
|
QVERIFY( addOutput( p3 ) );
|
|
QVERIFY( hasHtmlOutputs() );
|
|
}
|
|
|
|
void runValidateInputCrsChecks()
|
|
{
|
|
addParameter( new QgsProcessingParameterMapLayer( "p1" ) );
|
|
addParameter( new QgsProcessingParameterMapLayer( "p2" ) );
|
|
QVariantMap parameters;
|
|
|
|
QgsVectorLayer *layer3111 = new QgsVectorLayer( "Point?crs=epsg:3111", "v1", "memory" );
|
|
QgsProject p;
|
|
p.addMapLayer( layer3111 );
|
|
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QFileInfo fi1( raster1 );
|
|
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
|
QVERIFY( r1->isValid() );
|
|
p.addMapLayer( r1 );
|
|
|
|
QgsVectorLayer *layer4326 = new QgsVectorLayer( "Point?crs=epsg:4326", "v1", "memory" );
|
|
p.addMapLayer( layer4326 );
|
|
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// flag not set
|
|
mFlags = 0;
|
|
parameters.insert( "p1", QVariant::fromValue( layer3111 ) );
|
|
QVERIFY( validateInputCrs( parameters, context ) );
|
|
mFlags = FlagRequiresMatchingCrs;
|
|
QVERIFY( validateInputCrs( parameters, context ) );
|
|
|
|
// two layers, different crs
|
|
parameters.insert( "p2", QVariant::fromValue( layer4326 ) );
|
|
// flag not set
|
|
mFlags = 0;
|
|
QVERIFY( validateInputCrs( parameters, context ) );
|
|
mFlags = FlagRequiresMatchingCrs;
|
|
QVERIFY( !validateInputCrs( parameters, context ) );
|
|
|
|
// raster layer
|
|
parameters.remove( "p2" );
|
|
addParameter( new QgsProcessingParameterRasterLayer( "p3" ) );
|
|
parameters.insert( "p3", QVariant::fromValue( r1 ) );
|
|
QVERIFY( !validateInputCrs( parameters, context ) );
|
|
|
|
// feature source
|
|
parameters.remove( "p3" );
|
|
addParameter( new QgsProcessingParameterFeatureSource( "p4" ) );
|
|
parameters.insert( "p4", layer4326->id() );
|
|
QVERIFY( !validateInputCrs( parameters, context ) );
|
|
|
|
parameters.remove( "p4" );
|
|
addParameter( new QgsProcessingParameterMultipleLayers( "p5" ) );
|
|
parameters.insert( "p5", QVariantList() << layer4326->id() << r1->id() );
|
|
QVERIFY( !validateInputCrs( parameters, context ) );
|
|
|
|
// extent
|
|
parameters.clear();
|
|
parameters.insert( "p1", QVariant::fromValue( layer3111 ) );
|
|
addParameter( new QgsProcessingParameterExtent( "extent" ) );
|
|
parameters.insert( "extent", QgsReferencedRectangle( QgsRectangle( 1, 2, 3, 4 ), QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) ) );
|
|
QVERIFY( !validateInputCrs( parameters, context ) );
|
|
parameters.insert( "extent", QgsReferencedRectangle( QgsRectangle( 1, 2, 3, 4 ), QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) ) );
|
|
QVERIFY( validateInputCrs( parameters, context ) );
|
|
|
|
// point
|
|
parameters.clear();
|
|
parameters.insert( "p1", QVariant::fromValue( layer3111 ) );
|
|
addParameter( new QgsProcessingParameterPoint( "point" ) );
|
|
parameters.insert( "point", QgsReferencedPointXY( QgsPointXY( 1, 2 ), QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:4326" ) ) ) );
|
|
QVERIFY( !validateInputCrs( parameters, context ) );
|
|
parameters.insert( "point", QgsReferencedPointXY( QgsPointXY( 1, 2 ), QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) ) );
|
|
QVERIFY( validateInputCrs( parameters, context ) );
|
|
}
|
|
|
|
void runAsPythonCommandChecks()
|
|
{
|
|
addParameter( new QgsProcessingParameterString( "p1" ) );
|
|
addParameter( new QgsProcessingParameterString( "p2" ) );
|
|
QgsProcessingParameterString *hidden = new QgsProcessingParameterString( "p3" );
|
|
hidden->setFlags( QgsProcessingParameterDefinition::FlagHidden );
|
|
addParameter( hidden );
|
|
|
|
QVariantMap params;
|
|
QgsProcessingContext context;
|
|
|
|
QCOMPARE( asPythonCommand( params, context ), QStringLiteral( "processing.run(\"test\", {})" ) );
|
|
params.insert( "p1", "a" );
|
|
QCOMPARE( asPythonCommand( params, context ), QStringLiteral( "processing.run(\"test\", {'p1':'a'})" ) );
|
|
params.insert( "p2", QVariant() );
|
|
QCOMPARE( asPythonCommand( params, context ), QStringLiteral( "processing.run(\"test\", {'p1':'a','p2':None})" ) );
|
|
params.insert( "p2", "b" );
|
|
QCOMPARE( asPythonCommand( params, context ), QStringLiteral( "processing.run(\"test\", {'p1':'a','p2':'b'})" ) );
|
|
|
|
// hidden, shouldn't be shown
|
|
params.insert( "p3", "b" );
|
|
QCOMPARE( asPythonCommand( params, context ), QStringLiteral( "processing.run(\"test\", {'p1':'a','p2':'b'})" ) );
|
|
}
|
|
|
|
void addDestParams()
|
|
{
|
|
QgsProcessingParameterFeatureSink *sinkParam1 = new QgsProcessingParameterFeatureSink( "supports" );
|
|
sinkParam1->setSupportsNonFileBasedOutput( true );
|
|
addParameter( sinkParam1 );
|
|
QgsProcessingParameterFeatureSink *sinkParam2 = new QgsProcessingParameterFeatureSink( "non_supports" );
|
|
sinkParam2->setSupportsNonFileBasedOutput( false );
|
|
addParameter( sinkParam2 );
|
|
}
|
|
|
|
};
|
|
|
|
//dummy provider for testing
|
|
class DummyProvider : public QgsProcessingProvider
|
|
{
|
|
public:
|
|
|
|
DummyProvider( const QString &id ) : mId( id ) {}
|
|
|
|
QString id() const override { return mId; }
|
|
|
|
QString name() const override { return "dummy"; }
|
|
|
|
void unload() override { if ( unloaded ) { *unloaded = true; } }
|
|
|
|
QString defaultVectorFileExtension( bool ) const override
|
|
{
|
|
return "xshp"; // shape-X. Just like shapefiles, but to the max!
|
|
}
|
|
|
|
QString defaultRasterFileExtension() const override
|
|
{
|
|
return "pcx"; // next-gen raster storage
|
|
}
|
|
|
|
bool supportsNonFileBasedOutput() const override
|
|
{
|
|
return supportsNonFileOutputs;
|
|
}
|
|
|
|
bool isActive() const override
|
|
{
|
|
return active;
|
|
}
|
|
|
|
bool active = true;
|
|
bool *unloaded = nullptr;
|
|
bool supportsNonFileOutputs = false;
|
|
|
|
protected:
|
|
|
|
void loadAlgorithms() override
|
|
{
|
|
QVERIFY( addAlgorithm( new DummyAlgorithm( "alg1" ) ) );
|
|
QVERIFY( addAlgorithm( new DummyAlgorithm( "alg2" ) ) );
|
|
|
|
//dupe name
|
|
QgsProcessingAlgorithm *a = new DummyAlgorithm( "alg1" );
|
|
QVERIFY( !addAlgorithm( a ) );
|
|
delete a;
|
|
|
|
QVERIFY( !addAlgorithm( nullptr ) );
|
|
}
|
|
|
|
QString mId;
|
|
|
|
friend class TestQgsProcessing;
|
|
};
|
|
|
|
class DummyProviderNoLoad : public DummyProvider
|
|
{
|
|
public:
|
|
|
|
DummyProviderNoLoad( const QString &id ) : DummyProvider( id ) {}
|
|
|
|
bool load() override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
};
|
|
|
|
class DummyProvider3 : public QgsProcessingProvider
|
|
{
|
|
public:
|
|
|
|
DummyProvider3() = default;
|
|
QString id() const override { return QStringLiteral( "dummy3" ); }
|
|
QString name() const override { return QStringLiteral( "dummy3" ); }
|
|
|
|
QStringList supportedOutputVectorLayerExtensions() const override
|
|
{
|
|
return QStringList() << QStringLiteral( "mif" ) << QStringLiteral( "tab" );
|
|
}
|
|
|
|
QStringList supportedOutputRasterLayerExtensions() const override
|
|
{
|
|
return QStringList() << QStringLiteral( "mig" ) << QStringLiteral( "asc" );
|
|
}
|
|
|
|
void loadAlgorithms() override {}
|
|
|
|
};
|
|
|
|
class DummyAlgorithm2 : public QgsProcessingAlgorithm
|
|
{
|
|
public:
|
|
|
|
DummyAlgorithm2( const QString &name ) : mName( name ) { mFlags = QgsProcessingAlgorithm::flags(); }
|
|
|
|
void initAlgorithm( const QVariantMap & = QVariantMap() ) override
|
|
{
|
|
addParameter( new QgsProcessingParameterVectorDestination( QStringLiteral( "vector_dest" ) ) );
|
|
addParameter( new QgsProcessingParameterRasterDestination( QStringLiteral( "raster_dest" ) ) );
|
|
addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "sink" ) ) );
|
|
}
|
|
QString name() const override { return mName; }
|
|
QString displayName() const override { return mName; }
|
|
QVariantMap processAlgorithm( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * ) override { return QVariantMap(); }
|
|
|
|
Flags flags() const override { return mFlags; }
|
|
DummyAlgorithm2 *createInstance() const override { return new DummyAlgorithm2( name() ); }
|
|
|
|
QString mName;
|
|
|
|
Flags mFlags;
|
|
|
|
};
|
|
|
|
|
|
class DummyProvider4 : public QgsProcessingProvider
|
|
{
|
|
public:
|
|
|
|
DummyProvider4() = default;
|
|
QString id() const override { return QStringLiteral( "dummy4" ); }
|
|
QString name() const override { return QStringLiteral( "dummy4" ); }
|
|
|
|
bool supportsNonFileBasedOutput() const override
|
|
{
|
|
return false;
|
|
}
|
|
|
|
QStringList supportedOutputVectorLayerExtensions() const override
|
|
{
|
|
return QStringList() << QStringLiteral( "mif" );
|
|
}
|
|
|
|
QStringList supportedOutputRasterLayerExtensions() const override
|
|
{
|
|
return QStringList() << QStringLiteral( "mig" );
|
|
}
|
|
|
|
void loadAlgorithms() override
|
|
{
|
|
QVERIFY( addAlgorithm( new DummyAlgorithm2( "alg1" ) ) );
|
|
}
|
|
|
|
};
|
|
|
|
class DummyParameterType : public QgsProcessingParameterType
|
|
{
|
|
|
|
|
|
// QgsProcessingParameterType interface
|
|
public:
|
|
QgsProcessingParameterDefinition *create( const QString &name ) const
|
|
{
|
|
return new QgsProcessingParameterString( name );
|
|
}
|
|
|
|
QString description() const
|
|
{
|
|
return QStringLiteral( "Description" );
|
|
}
|
|
|
|
QString name() const
|
|
{
|
|
return QStringLiteral( "ParamType" );
|
|
}
|
|
|
|
QString id() const
|
|
{
|
|
return QStringLiteral( "paramType" );
|
|
}
|
|
};
|
|
|
|
class TestQgsProcessing: public QObject
|
|
{
|
|
Q_OBJECT
|
|
|
|
private slots:
|
|
void initTestCase();// will be called before the first testfunction is executed.
|
|
void cleanupTestCase(); // will be called after the last testfunction was executed.
|
|
void init() {} // will be called before each testfunction is executed.
|
|
void cleanup() {} // will be called after every testfunction.
|
|
void instance();
|
|
void addProvider();
|
|
void providerById();
|
|
void removeProvider();
|
|
void compatibleLayers();
|
|
void normalizeLayerSource();
|
|
void context();
|
|
void mapLayers();
|
|
void mapLayerFromStore();
|
|
void mapLayerFromString();
|
|
void algorithm();
|
|
void features();
|
|
void uniqueValues();
|
|
void createIndex();
|
|
void parseDestinationString();
|
|
void createFeatureSink();
|
|
void parameters();
|
|
void algorithmParameters();
|
|
void algorithmOutputs();
|
|
void parameterGeneral();
|
|
void parameterBoolean();
|
|
void parameterCrs();
|
|
void parameterLayer();
|
|
void parameterExtent();
|
|
void parameterPoint();
|
|
void parameterFile();
|
|
void parameterMatrix();
|
|
void parameterLayerList();
|
|
void parameterNumber();
|
|
void parameterDistance();
|
|
void parameterRange();
|
|
void parameterRasterLayer();
|
|
void parameterEnum();
|
|
void parameterString();
|
|
void parameterExpression();
|
|
void parameterField();
|
|
void parameterVectorLayer();
|
|
void parameterFeatureSource();
|
|
void parameterFeatureSink();
|
|
void parameterVectorOut();
|
|
void parameterRasterOut();
|
|
void parameterFileOut();
|
|
void parameterFolderOut();
|
|
void parameterBand();
|
|
void checkParamValues();
|
|
void combineLayerExtent();
|
|
void processingFeatureSource();
|
|
void processingFeatureSink();
|
|
void algorithmScope();
|
|
void validateInputCrs();
|
|
void generateIteratingDestination();
|
|
void asPythonCommand();
|
|
void modelerAlgorithm();
|
|
void modelExecution();
|
|
void modelWithProviderWithLimitedTypes();
|
|
void modelVectorOutputIsCompatibleType();
|
|
void modelAcceptableValues();
|
|
void tempUtils();
|
|
void convertCompatible();
|
|
void create();
|
|
void combineFields();
|
|
void fieldNamesToIndices();
|
|
void indicesToFields();
|
|
void stringToPythonLiteral();
|
|
void defaultExtensionsForProvider();
|
|
void supportsNonFileBasedOutput();
|
|
void addParameterType();
|
|
void removeParameterType();
|
|
void parameterTypes();
|
|
void parameterType();
|
|
|
|
private:
|
|
|
|
};
|
|
|
|
void TestQgsProcessing::initTestCase()
|
|
{
|
|
QgsApplication::init();
|
|
QgsApplication::initQgis();
|
|
|
|
// Set up the QgsSettings environment
|
|
QCoreApplication::setOrganizationName( QStringLiteral( "QGIS" ) );
|
|
QCoreApplication::setOrganizationDomain( QStringLiteral( "qgis.org" ) );
|
|
QCoreApplication::setApplicationName( QStringLiteral( "QGIS-TEST" ) );
|
|
|
|
QgsSettings settings;
|
|
settings.remove( QStringLiteral( "Processing/DefaultOutputVectorLayerExt" ), QgsSettings::Core );
|
|
settings.remove( QStringLiteral( "Processing/DefaultOutputRasterLayerExt" ), QgsSettings::Core );
|
|
|
|
QgsApplication::processingRegistry()->addProvider( new QgsNativeAlgorithms( QgsApplication::processingRegistry() ) );
|
|
}
|
|
|
|
void TestQgsProcessing::cleanupTestCase()
|
|
{
|
|
QFile::remove( QDir::tempPath() + "/create_feature_sink.tab" );
|
|
QgsVectorFileWriter::deleteShapeFile( QDir::tempPath() + "/create_feature_sink2.gpkg" );
|
|
|
|
QgsApplication::exitQgis();
|
|
}
|
|
|
|
void TestQgsProcessing::instance()
|
|
{
|
|
// test that application has a registry instance
|
|
QVERIFY( QgsApplication::processingRegistry() );
|
|
}
|
|
|
|
void TestQgsProcessing::addProvider()
|
|
{
|
|
QgsProcessingRegistry r;
|
|
QSignalSpy spyProviderAdded( &r, &QgsProcessingRegistry::providerAdded );
|
|
|
|
QVERIFY( r.providers().isEmpty() );
|
|
|
|
QVERIFY( !r.addProvider( nullptr ) );
|
|
|
|
// add a provider
|
|
DummyProvider *p = new DummyProvider( "p1" );
|
|
QVERIFY( r.addProvider( p ) );
|
|
QCOMPARE( r.providers(), QList< QgsProcessingProvider * >() << p );
|
|
QCOMPARE( spyProviderAdded.count(), 1 );
|
|
QCOMPARE( spyProviderAdded.last().at( 0 ).toString(), QString( "p1" ) );
|
|
|
|
//try adding another provider
|
|
DummyProvider *p2 = new DummyProvider( "p2" );
|
|
QVERIFY( r.addProvider( p2 ) );
|
|
QCOMPARE( r.providers().toSet(), QSet< QgsProcessingProvider * >() << p << p2 );
|
|
QCOMPARE( spyProviderAdded.count(), 2 );
|
|
QCOMPARE( spyProviderAdded.last().at( 0 ).toString(), QString( "p2" ) );
|
|
|
|
//try adding a provider with duplicate id
|
|
DummyProvider *p3 = new DummyProvider( "p2" );
|
|
QVERIFY( !r.addProvider( p3 ) );
|
|
QCOMPARE( r.providers().toSet(), QSet< QgsProcessingProvider * >() << p << p2 );
|
|
QCOMPARE( spyProviderAdded.count(), 2 );
|
|
|
|
// test that adding a provider which does not load means it is not added to registry
|
|
DummyProviderNoLoad *p4 = new DummyProviderNoLoad( "p4" );
|
|
QVERIFY( !r.addProvider( p4 ) );
|
|
QCOMPARE( r.providers().toSet(), QSet< QgsProcessingProvider * >() << p << p2 );
|
|
QCOMPARE( spyProviderAdded.count(), 2 );
|
|
}
|
|
|
|
void TestQgsProcessing::providerById()
|
|
{
|
|
QgsProcessingRegistry r;
|
|
|
|
// no providers
|
|
QVERIFY( !r.providerById( "p1" ) );
|
|
|
|
// add a provider
|
|
DummyProvider *p = new DummyProvider( "p1" );
|
|
QVERIFY( r.addProvider( p ) );
|
|
QCOMPARE( r.providerById( "p1" ), p );
|
|
QVERIFY( !r.providerById( "p2" ) );
|
|
|
|
//try adding another provider
|
|
DummyProvider *p2 = new DummyProvider( "p2" );
|
|
QVERIFY( r.addProvider( p2 ) );
|
|
QCOMPARE( r.providerById( "p1" ), p );
|
|
QCOMPARE( r.providerById( "p2" ), p2 );
|
|
QVERIFY( !r.providerById( "p3" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::removeProvider()
|
|
{
|
|
QgsProcessingRegistry r;
|
|
QSignalSpy spyProviderRemoved( &r, &QgsProcessingRegistry::providerRemoved );
|
|
|
|
QVERIFY( !r.removeProvider( nullptr ) );
|
|
QVERIFY( !r.removeProvider( "p1" ) );
|
|
// provider not in registry
|
|
DummyProvider *p = new DummyProvider( "p1" );
|
|
QVERIFY( !r.removeProvider( p ) );
|
|
QCOMPARE( spyProviderRemoved.count(), 0 );
|
|
|
|
// add some providers
|
|
QVERIFY( r.addProvider( p ) );
|
|
DummyProvider *p2 = new DummyProvider( "p2" );
|
|
QVERIFY( r.addProvider( p2 ) );
|
|
|
|
// remove one by pointer
|
|
bool unloaded = false;
|
|
p->unloaded = &unloaded;
|
|
QVERIFY( r.removeProvider( p ) );
|
|
QCOMPARE( spyProviderRemoved.count(), 1 );
|
|
QCOMPARE( spyProviderRemoved.last().at( 0 ).toString(), QString( "p1" ) );
|
|
QCOMPARE( r.providers(), QList< QgsProcessingProvider * >() << p2 );
|
|
|
|
//test that provider was unloaded
|
|
QVERIFY( unloaded );
|
|
|
|
// should fail, already removed
|
|
QVERIFY( !r.removeProvider( "p1" ) );
|
|
|
|
// remove one by id
|
|
QVERIFY( r.removeProvider( "p2" ) );
|
|
QCOMPARE( spyProviderRemoved.count(), 2 );
|
|
QCOMPARE( spyProviderRemoved.last().at( 0 ).toString(), QString( "p2" ) );
|
|
QVERIFY( r.providers().isEmpty() );
|
|
}
|
|
|
|
void TestQgsProcessing::compatibleLayers()
|
|
{
|
|
QgsProject p;
|
|
|
|
// add a bunch of layers to a project
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QString raster2 = testDataDir + "landsat.tif";
|
|
QString raster3 = testDataDir + "/raster/band1_float32_noct_epsg4326.tif";
|
|
QFileInfo fi1( raster1 );
|
|
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
|
QVERIFY( r1->isValid() );
|
|
QFileInfo fi2( raster2 );
|
|
QgsRasterLayer *r2 = new QgsRasterLayer( fi2.filePath(), "ar2" );
|
|
QVERIFY( r2->isValid() );
|
|
QFileInfo fi3( raster3 );
|
|
QgsRasterLayer *r3 = new QgsRasterLayer( fi3.filePath(), "zz" );
|
|
QVERIFY( r3->isValid() );
|
|
|
|
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon", "V4", "memory" );
|
|
QgsVectorLayer *v2 = new QgsVectorLayer( "Point", "v1", "memory" );
|
|
QgsVectorLayer *v3 = new QgsVectorLayer( "LineString", "v3", "memory" );
|
|
QgsVectorLayer *v4 = new QgsVectorLayer( "none", "vvvv4", "memory" );
|
|
|
|
p.addMapLayers( QList<QgsMapLayer *>() << r1 << r2 << r3 << v1 << v2 << v3 << v4 );
|
|
|
|
// compatibleRasterLayers
|
|
QVERIFY( QgsProcessingUtils::compatibleRasterLayers( nullptr ).isEmpty() );
|
|
|
|
// sorted
|
|
QStringList lIds;
|
|
Q_FOREACH ( QgsRasterLayer *rl, QgsProcessingUtils::compatibleRasterLayers( &p ) )
|
|
lIds << rl->name();
|
|
QCOMPARE( lIds, QStringList() << "ar2" << "R1" << "zz" );
|
|
|
|
// unsorted
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsRasterLayer *rl, QgsProcessingUtils::compatibleRasterLayers( &p, false ) )
|
|
lIds << rl->name();
|
|
QCOMPARE( lIds, QStringList() << "R1" << "ar2" << "zz" );
|
|
|
|
|
|
// compatibleVectorLayers
|
|
QVERIFY( QgsProcessingUtils::compatibleVectorLayers( nullptr ).isEmpty() );
|
|
|
|
// sorted
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p ) )
|
|
lIds << vl->name();
|
|
QCOMPARE( lIds, QStringList() << "v1" << "v3" << "V4" << "vvvv4" );
|
|
|
|
// unsorted
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<int>(), false ) )
|
|
lIds << vl->name();
|
|
QCOMPARE( lIds, QStringList() << "V4" << "v1" << "v3" << "vvvv4" );
|
|
|
|
// point only
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<int>() << QgsProcessing::TypeVectorPoint ) )
|
|
lIds << vl->name();
|
|
QCOMPARE( lIds, QStringList() << "v1" );
|
|
|
|
// polygon only
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<int>() << QgsProcessing::TypeVectorPolygon ) )
|
|
lIds << vl->name();
|
|
QCOMPARE( lIds, QStringList() << "V4" );
|
|
|
|
// line only
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<int>() << QgsProcessing::TypeVectorLine ) )
|
|
lIds << vl->name();
|
|
QCOMPARE( lIds, QStringList() << "v3" );
|
|
|
|
// point and line only
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<int>() << QgsProcessing::TypeVectorPoint << QgsProcessing::TypeVectorLine ) )
|
|
lIds << vl->name();
|
|
QCOMPARE( lIds, QStringList() << "v1" << "v3" );
|
|
|
|
// any vector w geometry
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<int>() << QgsProcessing::TypeVectorAnyGeometry ) )
|
|
lIds << vl->name();
|
|
QCOMPARE( lIds, QStringList() << "v1" << "v3" << "V4" );
|
|
|
|
// any vector
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsVectorLayer *vl, QgsProcessingUtils::compatibleVectorLayers( &p, QList<int>() << QgsProcessing::TypeVector ) )
|
|
lIds << vl->name();
|
|
QCOMPARE( lIds, QStringList() << "v1" << "v3" << "V4" << "vvvv4" );
|
|
|
|
// all layers
|
|
QVERIFY( QgsProcessingUtils::compatibleLayers( nullptr ).isEmpty() );
|
|
|
|
// sorted
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsMapLayer *l, QgsProcessingUtils::compatibleLayers( &p ) )
|
|
lIds << l->name();
|
|
QCOMPARE( lIds, QStringList() << "ar2" << "R1" << "v1" << "v3" << "V4" << "vvvv4" << "zz" );
|
|
|
|
// unsorted
|
|
lIds.clear();
|
|
Q_FOREACH ( QgsMapLayer *l, QgsProcessingUtils::compatibleLayers( &p, false ) )
|
|
lIds << l->name();
|
|
QCOMPARE( lIds, QStringList() << "R1" << "ar2" << "zz" << "V4" << "v1" << "v3" << "vvvv4" );
|
|
}
|
|
|
|
void TestQgsProcessing::normalizeLayerSource()
|
|
{
|
|
QCOMPARE( QgsProcessingUtils::normalizeLayerSource( "data\\layers\\test.shp" ), QString( "data/layers/test.shp" ) );
|
|
QCOMPARE( QgsProcessingUtils::normalizeLayerSource( "data\\layers \"new\"\\test.shp" ), QString( "data/layers \"new\"/test.shp" ) );
|
|
}
|
|
|
|
|
|
class TestPostProcessor : public QgsProcessingLayerPostProcessorInterface
|
|
{
|
|
public:
|
|
|
|
TestPostProcessor( bool *deleted )
|
|
: deleted( deleted )
|
|
{}
|
|
|
|
~TestPostProcessor()
|
|
{
|
|
*deleted = true;
|
|
}
|
|
|
|
bool *deleted = nullptr;
|
|
|
|
void postProcessLayer( QgsMapLayer *, QgsProcessingContext &, QgsProcessingFeedback * ) override
|
|
{
|
|
}
|
|
};
|
|
|
|
|
|
void TestQgsProcessing::context()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// simple tests for getters/setters
|
|
context.setDefaultEncoding( "my_enc" );
|
|
QCOMPARE( context.defaultEncoding(), QStringLiteral( "my_enc" ) );
|
|
|
|
context.setFlags( QgsProcessingContext::Flags( 0 ) );
|
|
QCOMPARE( context.flags(), QgsProcessingContext::Flags( 0 ) );
|
|
|
|
QgsProject p;
|
|
context.setProject( &p );
|
|
QCOMPARE( context.project(), &p );
|
|
|
|
context.setInvalidGeometryCheck( QgsFeatureRequest::GeometrySkipInvalid );
|
|
QCOMPARE( context.invalidGeometryCheck(), QgsFeatureRequest::GeometrySkipInvalid );
|
|
|
|
QgsVectorLayer *vector = new QgsVectorLayer( "Polygon", "vector", "memory" );
|
|
context.temporaryLayerStore()->addMapLayer( vector );
|
|
QCOMPARE( context.temporaryLayerStore()->mapLayer( vector->id() ), vector );
|
|
|
|
QgsProcessingContext context2;
|
|
context2.copyThreadSafeSettings( context );
|
|
QCOMPARE( context2.defaultEncoding(), context.defaultEncoding() );
|
|
QCOMPARE( context2.invalidGeometryCheck(), context.invalidGeometryCheck() );
|
|
QCOMPARE( context2.flags(), context.flags() );
|
|
QCOMPARE( context2.project(), context.project() );
|
|
// layers from temporaryLayerStore must not be copied by copyThreadSafeSettings
|
|
QVERIFY( context2.temporaryLayerStore()->mapLayers().isEmpty() );
|
|
|
|
// layers to load on completion
|
|
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon", "V1", "memory" );
|
|
QgsVectorLayer *v2 = new QgsVectorLayer( "Polygon", "V2", "memory" );
|
|
QVERIFY( context.layersToLoadOnCompletion().isEmpty() );
|
|
QVERIFY( !context.willLoadLayerOnCompletion( v1->id() ) );
|
|
QVERIFY( !context.willLoadLayerOnCompletion( v2->id() ) );
|
|
QMap< QString, QgsProcessingContext::LayerDetails > layers;
|
|
QgsProcessingContext::LayerDetails details( QStringLiteral( "v1" ), &p );
|
|
bool ppDeleted = false;
|
|
TestPostProcessor *pp = new TestPostProcessor( &ppDeleted );
|
|
details.setPostProcessor( pp );
|
|
layers.insert( v1->id(), details );
|
|
context.setLayersToLoadOnCompletion( layers );
|
|
QCOMPARE( context.layersToLoadOnCompletion().count(), 1 );
|
|
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), v1->id() );
|
|
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "v1" ) );
|
|
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).postProcessor(), pp );
|
|
QVERIFY( context.willLoadLayerOnCompletion( v1->id() ) );
|
|
QCOMPARE( context.layerToLoadOnCompletionDetails( v1->id() ).name, QStringLiteral( "v1" ) );
|
|
QVERIFY( !context.willLoadLayerOnCompletion( v2->id() ) );
|
|
context.addLayerToLoadOnCompletion( v2->id(), QgsProcessingContext::LayerDetails( QStringLiteral( "v2" ), &p ) );
|
|
QCOMPARE( context.layersToLoadOnCompletion().count(), 2 );
|
|
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), v1->id() );
|
|
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "v1" ) );
|
|
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).postProcessor(), pp );
|
|
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 1 ), v2->id() );
|
|
QCOMPARE( context.layersToLoadOnCompletion().values().at( 1 ).name, QStringLiteral( "v2" ) );
|
|
QVERIFY( !context.layersToLoadOnCompletion().values().at( 1 ).postProcessor() );
|
|
QCOMPARE( context.layerToLoadOnCompletionDetails( v1->id() ).name, QStringLiteral( "v1" ) );
|
|
QCOMPARE( context.layerToLoadOnCompletionDetails( v2->id() ).name, QStringLiteral( "v2" ) );
|
|
QVERIFY( context.willLoadLayerOnCompletion( v1->id() ) );
|
|
QVERIFY( context.willLoadLayerOnCompletion( v2->id() ) );
|
|
|
|
// ensure that copyThreadSafeSettings doesn't copy layersToLoadOnCompletion()
|
|
context2.copyThreadSafeSettings( context );
|
|
QVERIFY( context2.layersToLoadOnCompletion().isEmpty() );
|
|
|
|
layers.clear();
|
|
layers.insert( v2->id(), QgsProcessingContext::LayerDetails( QStringLiteral( "v2" ), &p ) );
|
|
context.setLayersToLoadOnCompletion( layers );
|
|
QVERIFY( ppDeleted );
|
|
|
|
QCOMPARE( context.layersToLoadOnCompletion().count(), 1 );
|
|
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), v2->id() );
|
|
QCOMPARE( context.layersToLoadOnCompletion().values().at( 0 ).name, QStringLiteral( "v2" ) );
|
|
context.addLayerToLoadOnCompletion( v1->id(), QgsProcessingContext::LayerDetails( QString(), &p ) );
|
|
QCOMPARE( context.layersToLoadOnCompletion().count(), 2 );
|
|
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 0 ), v1->id() );
|
|
QCOMPARE( context.layersToLoadOnCompletion().keys().at( 1 ), v2->id() );
|
|
|
|
context.temporaryLayerStore()->addMapLayer( v1 );
|
|
context.temporaryLayerStore()->addMapLayer( v2 );
|
|
|
|
// test takeResultsFrom
|
|
context2.takeResultsFrom( context );
|
|
QVERIFY( context.temporaryLayerStore()->mapLayers().isEmpty() );
|
|
QVERIFY( context.layersToLoadOnCompletion().isEmpty() );
|
|
// should now be in context2
|
|
QCOMPARE( context2.temporaryLayerStore()->mapLayer( v1->id() ), v1 );
|
|
QCOMPARE( context2.temporaryLayerStore()->mapLayer( v2->id() ), v2 );
|
|
QCOMPARE( context2.layersToLoadOnCompletion().count(), 2 );
|
|
QCOMPARE( context2.layersToLoadOnCompletion().keys().at( 0 ), v1->id() );
|
|
QCOMPARE( context2.layersToLoadOnCompletion().keys().at( 1 ), v2->id() );
|
|
|
|
// make sure postprocessor is correctly deleted
|
|
ppDeleted = false;
|
|
pp = new TestPostProcessor( &ppDeleted );
|
|
details = QgsProcessingContext::LayerDetails( QStringLiteral( "v1" ), &p );
|
|
details.setPostProcessor( pp );
|
|
layers.insert( v1->id(), details );
|
|
context.setLayersToLoadOnCompletion( layers );
|
|
// overwrite with existing
|
|
context.setLayersToLoadOnCompletion( layers );
|
|
QVERIFY( !ppDeleted );
|
|
QCOMPARE( context.layerToLoadOnCompletionDetails( v1->id() ).postProcessor(), pp );
|
|
bool pp2Deleted = false;
|
|
TestPostProcessor *pp2 = new TestPostProcessor( &pp2Deleted );
|
|
details = QgsProcessingContext::LayerDetails( QStringLiteral( "v1" ), &p );
|
|
details.setPostProcessor( pp2 );
|
|
layers.insert( v1->id(), details );
|
|
context.setLayersToLoadOnCompletion( layers );
|
|
QVERIFY( ppDeleted );
|
|
QVERIFY( !pp2Deleted );
|
|
QCOMPARE( context.layerToLoadOnCompletionDetails( v1->id() ).postProcessor(), pp2 );
|
|
ppDeleted = false;
|
|
pp = new TestPostProcessor( &ppDeleted );
|
|
details = QgsProcessingContext::LayerDetails( QStringLiteral( "v1" ), &p );
|
|
details.setPostProcessor( pp );
|
|
context.addLayerToLoadOnCompletion( v1->id(), details );
|
|
QVERIFY( !ppDeleted );
|
|
QVERIFY( pp2Deleted );
|
|
QCOMPARE( context.layerToLoadOnCompletionDetails( v1->id() ).postProcessor(), pp );
|
|
pp2Deleted = false;
|
|
pp2 = new TestPostProcessor( &pp2Deleted );
|
|
context.layerToLoadOnCompletionDetails( v1->id() ).setPostProcessor( pp2 );
|
|
QVERIFY( ppDeleted );
|
|
QVERIFY( !pp2Deleted );
|
|
QCOMPARE( context.layerToLoadOnCompletionDetails( v1->id() ).postProcessor(), pp2 );
|
|
|
|
// take result layer
|
|
QgsMapLayer *result = context2.takeResultLayer( v1->id() );
|
|
QCOMPARE( result, v1 );
|
|
QString id = v1->id();
|
|
delete v1;
|
|
QVERIFY( !context2.temporaryLayerStore()->mapLayer( id ) );
|
|
QVERIFY( !context2.takeResultLayer( id ) );
|
|
result = context2.takeResultLayer( v2->id() );
|
|
QCOMPARE( result, v2 );
|
|
id = v2->id();
|
|
delete v2;
|
|
QVERIFY( !context2.temporaryLayerStore()->mapLayer( id ) );
|
|
}
|
|
|
|
void TestQgsProcessing::mapLayers()
|
|
{
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster = testDataDir + "landsat.tif";
|
|
QString vector = testDataDir + "points.shp";
|
|
|
|
// test loadMapLayerFromString with raster
|
|
QgsMapLayer *l = QgsProcessingUtils::loadMapLayerFromString( raster );
|
|
QVERIFY( l->isValid() );
|
|
QCOMPARE( l->type(), QgsMapLayer::RasterLayer );
|
|
QCOMPARE( l->name(), QStringLiteral( "landsat" ) );
|
|
|
|
delete l;
|
|
|
|
//test with vector
|
|
l = QgsProcessingUtils::loadMapLayerFromString( vector );
|
|
QVERIFY( l->isValid() );
|
|
QCOMPARE( l->type(), QgsMapLayer::VectorLayer );
|
|
QCOMPARE( l->name(), QStringLiteral( "points" ) );
|
|
delete l;
|
|
|
|
l = QgsProcessingUtils::loadMapLayerFromString( QString() );
|
|
QVERIFY( !l );
|
|
l = QgsProcessingUtils::loadMapLayerFromString( QStringLiteral( "so much room for activities!" ) );
|
|
QVERIFY( !l );
|
|
l = QgsProcessingUtils::loadMapLayerFromString( testDataDir + "multipoint.shp" );
|
|
QVERIFY( l->isValid() );
|
|
QCOMPARE( l->type(), QgsMapLayer::VectorLayer );
|
|
QCOMPARE( l->name(), QStringLiteral( "multipoint" ) );
|
|
delete l;
|
|
|
|
// Test layers from a string with parameters
|
|
QString osmFilePath = testDataDir + "openstreetmap/testdata.xml";
|
|
std::unique_ptr< QgsVectorLayer > osm( qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::loadMapLayerFromString( osmFilePath ) ) );
|
|
QVERIFY( osm->isValid() );
|
|
QCOMPARE( osm->geometryType(), QgsWkbTypes::PointGeometry );
|
|
|
|
osm.reset( qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::loadMapLayerFromString( osmFilePath + "|layerid=3" ) ) );
|
|
QVERIFY( osm->isValid() );
|
|
QCOMPARE( osm->geometryType(), QgsWkbTypes::PolygonGeometry );
|
|
|
|
osm.reset( qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::loadMapLayerFromString( osmFilePath + "|layerid=3|subset=\"building\" is not null" ) ) );
|
|
QVERIFY( osm->isValid() );
|
|
QCOMPARE( osm->geometryType(), QgsWkbTypes::PolygonGeometry );
|
|
QCOMPARE( osm->subsetString(), QStringLiteral( "\"building\" is not null" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::mapLayerFromStore()
|
|
{
|
|
// test mapLayerFromStore
|
|
|
|
QgsMapLayerStore store;
|
|
|
|
// add a bunch of layers to a project
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QString raster2 = testDataDir + "landsat.tif";
|
|
QFileInfo fi1( raster1 );
|
|
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
|
QVERIFY( r1->isValid() );
|
|
QFileInfo fi2( raster2 );
|
|
QgsRasterLayer *r2 = new QgsRasterLayer( fi2.filePath(), "ar2" );
|
|
QVERIFY( r2->isValid() );
|
|
|
|
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon", "V4", "memory" );
|
|
QgsVectorLayer *v2 = new QgsVectorLayer( "Point", "v1", "memory" );
|
|
store.addMapLayers( QList<QgsMapLayer *>() << r1 << r2 << v1 << v2 );
|
|
|
|
QVERIFY( ! QgsProcessingUtils::mapLayerFromStore( QString(), nullptr ) );
|
|
QVERIFY( ! QgsProcessingUtils::mapLayerFromStore( QStringLiteral( "v1" ), nullptr ) );
|
|
QVERIFY( ! QgsProcessingUtils::mapLayerFromStore( QString(), &store ) );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromStore( raster1, &store ), r1 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromStore( raster2, &store ), r2 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromStore( "R1", &store ), r1 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromStore( "ar2", &store ), r2 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromStore( "V4", &store ), v1 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromStore( "v1", &store ), v2 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromStore( r1->id(), &store ), r1 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromStore( v1->id(), &store ), v1 );
|
|
}
|
|
|
|
void TestQgsProcessing::mapLayerFromString()
|
|
{
|
|
// test mapLayerFromString
|
|
|
|
QgsProcessingContext c;
|
|
QgsProject p;
|
|
|
|
// add a bunch of layers to a project
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QString raster2 = testDataDir + "landsat.tif";
|
|
QFileInfo fi1( raster1 );
|
|
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
|
QVERIFY( r1->isValid() );
|
|
QFileInfo fi2( raster2 );
|
|
QgsRasterLayer *r2 = new QgsRasterLayer( fi2.filePath(), "ar2" );
|
|
QVERIFY( r2->isValid() );
|
|
|
|
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon", "V4", "memory" );
|
|
QgsVectorLayer *v2 = new QgsVectorLayer( "Point", "v1", "memory" );
|
|
p.addMapLayers( QList<QgsMapLayer *>() << r1 << r2 << v1 << v2 );
|
|
|
|
// no project set yet
|
|
QVERIFY( ! QgsProcessingUtils::mapLayerFromString( QString(), c ) );
|
|
QVERIFY( !c.getMapLayer( QString() ) );
|
|
QVERIFY( ! QgsProcessingUtils::mapLayerFromString( QStringLiteral( "v1" ), c ) );
|
|
QVERIFY( !c.getMapLayer( QStringLiteral( "v1" ) ) );
|
|
|
|
c.setProject( &p );
|
|
|
|
// layers from current project
|
|
QVERIFY( ! QgsProcessingUtils::mapLayerFromString( QString(), c ) );
|
|
QVERIFY( !c.getMapLayer( QString() ) );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( raster1, c ), r1 );
|
|
QCOMPARE( c.getMapLayer( raster1 ), r1 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( raster2, c ), r2 );
|
|
QCOMPARE( c.getMapLayer( raster2 ), r2 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( "R1", c ), r1 );
|
|
QCOMPARE( c.getMapLayer( "R1" ), r1 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( "ar2", c ), r2 );
|
|
QCOMPARE( c.getMapLayer( "ar2" ), r2 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( "V4", c ), v1 );
|
|
QCOMPARE( c.getMapLayer( "V4" ), v1 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( "v1", c ), v2 );
|
|
QCOMPARE( c.getMapLayer( "v1" ), v2 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( r1->id(), c ), r1 );
|
|
QCOMPARE( c.getMapLayer( r1->id() ), r1 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( v1->id(), c ), v1 );
|
|
QCOMPARE( c.getMapLayer( v1->id() ), v1 );
|
|
|
|
// check that layers in context temporary store are used
|
|
QgsVectorLayer *v5 = new QgsVectorLayer( "Polygon", "V5", "memory" );
|
|
QgsVectorLayer *v6 = new QgsVectorLayer( "Point", "v6", "memory" );
|
|
c.temporaryLayerStore()->addMapLayers( QList<QgsMapLayer *>() << v5 << v6 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( "V5", c ), v5 );
|
|
QCOMPARE( c.getMapLayer( "V5" ), v5 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( "v6", c ), v6 );
|
|
QCOMPARE( c.getMapLayer( "v6" ), v6 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( v5->id(), c ), v5 );
|
|
QCOMPARE( c.getMapLayer( v5->id() ), v5 );
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( v6->id(), c ), v6 );
|
|
QCOMPARE( c.getMapLayer( v6->id() ), v6 );
|
|
QVERIFY( ! QgsProcessingUtils::mapLayerFromString( "aaaaa", c ) );
|
|
QVERIFY( !c.getMapLayer( "aaaa" ) );
|
|
|
|
// if specified, check that layers can be loaded
|
|
QVERIFY( ! QgsProcessingUtils::mapLayerFromString( "aaaaa", c ) );
|
|
QString newRaster = testDataDir + "requires_warped_vrt.tif";
|
|
// don't allow loading
|
|
QVERIFY( ! QgsProcessingUtils::mapLayerFromString( newRaster, c, false ) );
|
|
QVERIFY( !c.getMapLayer( newRaster ) );
|
|
// allow loading
|
|
QgsMapLayer *loadedLayer = QgsProcessingUtils::mapLayerFromString( newRaster, c, true );
|
|
QVERIFY( loadedLayer->isValid() );
|
|
QCOMPARE( loadedLayer->type(), QgsMapLayer::RasterLayer );
|
|
// should now be in temporary store
|
|
QCOMPARE( c.temporaryLayerStore()->mapLayer( loadedLayer->id() ), loadedLayer );
|
|
|
|
// since it's now in temporary store, should be accessible even if we deny loading new layers
|
|
QCOMPARE( QgsProcessingUtils::mapLayerFromString( newRaster, c, false ), loadedLayer );
|
|
QCOMPARE( c.getMapLayer( newRaster ), loadedLayer );
|
|
}
|
|
|
|
void TestQgsProcessing::algorithm()
|
|
{
|
|
DummyAlgorithm alg( "test" );
|
|
DummyProvider *p = new DummyProvider( "p1" );
|
|
QCOMPARE( alg.id(), QString( "test" ) );
|
|
alg.setProvider( p );
|
|
QCOMPARE( alg.provider(), p );
|
|
QCOMPARE( alg.id(), QString( "p1:test" ) );
|
|
|
|
QVERIFY( p->algorithms().isEmpty() );
|
|
|
|
QSignalSpy providerRefreshed( p, &DummyProvider::algorithmsLoaded );
|
|
p->refreshAlgorithms();
|
|
QCOMPARE( providerRefreshed.count(), 1 );
|
|
|
|
for ( int i = 0; i < 2; ++i )
|
|
{
|
|
QCOMPARE( p->algorithms().size(), 2 );
|
|
QCOMPARE( p->algorithm( "alg1" )->name(), QStringLiteral( "alg1" ) );
|
|
QCOMPARE( p->algorithm( "alg1" )->provider(), p );
|
|
QCOMPARE( p->algorithm( "alg2" )->provider(), p );
|
|
QCOMPARE( p->algorithm( "alg2" )->name(), QStringLiteral( "alg2" ) );
|
|
QVERIFY( !p->algorithm( "aaaa" ) );
|
|
QVERIFY( p->algorithms().contains( p->algorithm( "alg1" ) ) );
|
|
QVERIFY( p->algorithms().contains( p->algorithm( "alg2" ) ) );
|
|
|
|
// reload, then retest on next loop
|
|
// must be safe for providers to reload their algorithms
|
|
p->refreshAlgorithms();
|
|
QCOMPARE( providerRefreshed.count(), 2 + i );
|
|
}
|
|
|
|
// inactive provider, should not load algorithms
|
|
p->active = false;
|
|
p->refreshAlgorithms();
|
|
QCOMPARE( providerRefreshed.count(), 3 );
|
|
QVERIFY( p->algorithms().empty() );
|
|
p->active = true;
|
|
p->refreshAlgorithms();
|
|
QCOMPARE( providerRefreshed.count(), 4 );
|
|
QVERIFY( !p->algorithms().empty() );
|
|
|
|
QgsProcessingRegistry r;
|
|
QVERIFY( r.addProvider( p ) );
|
|
QCOMPARE( r.algorithms().size(), 2 );
|
|
QVERIFY( r.algorithms().contains( p->algorithm( "alg1" ) ) );
|
|
QVERIFY( r.algorithms().contains( p->algorithm( "alg2" ) ) );
|
|
|
|
// algorithmById
|
|
QCOMPARE( r.algorithmById( "p1:alg1" ), p->algorithm( "alg1" ) );
|
|
QCOMPARE( r.algorithmById( "p1:alg2" ), p->algorithm( "alg2" ) );
|
|
QVERIFY( !r.algorithmById( "p1:alg3" ) );
|
|
QVERIFY( !r.algorithmById( "px:alg1" ) );
|
|
|
|
// test that algorithmById can transparently map 'qgis' algorithms across to matching 'native' algorithms
|
|
// this allows us the freedom to convert qgis python algs to c++ without breaking api or existing models
|
|
QCOMPARE( QgsApplication::processingRegistry()->algorithmById( QStringLiteral( "qgis:dissolve" ) )->id(), QStringLiteral( "native:dissolve" ) );
|
|
QCOMPARE( QgsApplication::processingRegistry()->algorithmById( QStringLiteral( "qgis:clip" ) )->id(), QStringLiteral( "native:clip" ) );
|
|
QVERIFY( !QgsApplication::processingRegistry()->algorithmById( QStringLiteral( "qgis:notanalg" ) ) );
|
|
|
|
// createAlgorithmById
|
|
QVERIFY( !r.createAlgorithmById( "p1:alg3" ) );
|
|
std::unique_ptr< QgsProcessingAlgorithm > creation( r.createAlgorithmById( "p1:alg1" ) );
|
|
QVERIFY( creation.get() );
|
|
QCOMPARE( creation->provider()->id(), QStringLiteral( "p1" ) );
|
|
QCOMPARE( creation->id(), QStringLiteral( "p1:alg1" ) );
|
|
creation.reset( r.createAlgorithmById( "p1:alg2" ) );
|
|
QVERIFY( creation.get() );
|
|
QCOMPARE( creation->provider()->id(), QStringLiteral( "p1" ) );
|
|
QCOMPARE( creation->id(), QStringLiteral( "p1:alg2" ) );
|
|
|
|
//test that loading a provider triggers an algorithm refresh
|
|
DummyProvider *p2 = new DummyProvider( "p2" );
|
|
QVERIFY( p2->algorithms().isEmpty() );
|
|
p2->load();
|
|
QCOMPARE( p2->algorithms().size(), 2 );
|
|
delete p2;
|
|
|
|
// test that adding a provider to the registry automatically refreshes algorithms (via load)
|
|
DummyProvider *p3 = new DummyProvider( "p3" );
|
|
QVERIFY( p3->algorithms().isEmpty() );
|
|
QVERIFY( r.addProvider( p3 ) );
|
|
QCOMPARE( p3->algorithms().size(), 2 );
|
|
}
|
|
|
|
void TestQgsProcessing::features()
|
|
{
|
|
QgsVectorLayer *layer = new QgsVectorLayer( "Point", "v1", "memory" );
|
|
for ( int i = 1; i < 6; ++i )
|
|
{
|
|
QgsFeature f( i );
|
|
f.setGeometry( QgsGeometry( new QgsPoint( 1, 2 ) ) );
|
|
layer->dataProvider()->addFeatures( QgsFeatureList() << f );
|
|
}
|
|
|
|
QgsProject p;
|
|
p.addMapLayer( layer );
|
|
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
// disable check for geometry validity
|
|
context.setFlags( QgsProcessingContext::Flags( 0 ) );
|
|
|
|
std::function< QgsFeatureIds( QgsFeatureIterator it ) > getIds = []( QgsFeatureIterator it )
|
|
{
|
|
QgsFeature f;
|
|
QgsFeatureIds ids;
|
|
while ( it.nextFeature( f ) )
|
|
{
|
|
ids << f.id();
|
|
}
|
|
return ids;
|
|
};
|
|
|
|
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterString( QStringLiteral( "layer" ) ) );
|
|
QVariantMap params;
|
|
params.insert( QStringLiteral( "layer" ), layer->id() );
|
|
|
|
std::unique_ptr< QgsFeatureSource > source( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
|
|
// test with all features
|
|
QgsFeatureIds ids = getIds( source->getFeatures() );
|
|
QCOMPARE( ids, QgsFeatureIds() << 1 << 2 << 3 << 4 << 5 );
|
|
QCOMPARE( source->featureCount(), 5L );
|
|
|
|
// test with selected features
|
|
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( QgsProcessingFeatureSourceDefinition( layer->id(), true ) ) );
|
|
layer->selectByIds( QgsFeatureIds() << 2 << 4 );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
ids = getIds( source->getFeatures() );
|
|
QCOMPARE( ids, QgsFeatureIds() << 2 << 4 );
|
|
QCOMPARE( source->featureCount(), 2L );
|
|
|
|
// selection, but not using selected features
|
|
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( QgsProcessingFeatureSourceDefinition( layer->id(), false ) ) );
|
|
layer->selectByIds( QgsFeatureIds() << 2 << 4 );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
ids = getIds( source->getFeatures() );
|
|
QCOMPARE( ids, QgsFeatureIds() << 1 << 2 << 3 << 4 << 5 );
|
|
QCOMPARE( source->featureCount(), 5L );
|
|
|
|
// using selected features, but no selection
|
|
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( QgsProcessingFeatureSourceDefinition( layer->id(), true ) ) );
|
|
layer->removeSelection();
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
ids = getIds( source->getFeatures() );
|
|
QVERIFY( ids.isEmpty() );
|
|
QCOMPARE( source->featureCount(), 0L );
|
|
|
|
|
|
// test that feature request is honored
|
|
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( QgsProcessingFeatureSourceDefinition( layer->id(), false ) ) );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
ids = getIds( source->getFeatures( QgsFeatureRequest().setFilterFids( QgsFeatureIds() << 1 << 3 << 5 ) ) );
|
|
QCOMPARE( ids, QgsFeatureIds() << 1 << 3 << 5 );
|
|
|
|
// count is only rough - but we expect (for now) to see full layer count
|
|
QCOMPARE( source->featureCount(), 5L );
|
|
|
|
//test that feature request is honored when using selections
|
|
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( QgsProcessingFeatureSourceDefinition( layer->id(), true ) ) );
|
|
layer->selectByIds( QgsFeatureIds() << 2 << 4 );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
ids = getIds( source->getFeatures( QgsFeatureRequest().setFlags( QgsFeatureRequest::NoGeometry ) ) );
|
|
QCOMPARE( ids, QgsFeatureIds() << 2 << 4 );
|
|
|
|
// test callback is hit when filtering invalid geoms
|
|
bool encountered = false;
|
|
std::function< void( const QgsFeature & ) > callback = [ &encountered ]( const QgsFeature & )
|
|
{
|
|
encountered = true;
|
|
};
|
|
|
|
context.setInvalidGeometryCheck( QgsFeatureRequest::GeometryAbortOnInvalid );
|
|
context.setInvalidGeometryCallback( callback );
|
|
QgsVectorLayer *polyLayer = new QgsVectorLayer( "Polygon", "v2", "memory" );
|
|
QgsFeature f;
|
|
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 1 0, 0 1, 1 1, 0 0))" ) ) );
|
|
polyLayer->dataProvider()->addFeatures( QgsFeatureList() << f );
|
|
p.addMapLayer( polyLayer );
|
|
params.insert( QStringLiteral( "layer" ), polyLayer->id() );
|
|
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
ids = getIds( source->getFeatures() );
|
|
QVERIFY( encountered );
|
|
|
|
encountered = false;
|
|
context.setInvalidGeometryCheck( QgsFeatureRequest::GeometryNoCheck );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
ids = getIds( source->getFeatures() );
|
|
QVERIFY( !encountered );
|
|
|
|
// equality operator
|
|
QVERIFY( QgsProcessingFeatureSourceDefinition( layer->id(), true ) == QgsProcessingFeatureSourceDefinition( layer->id(), true ) );
|
|
QVERIFY( QgsProcessingFeatureSourceDefinition( layer->id(), true ) != QgsProcessingFeatureSourceDefinition( "b", true ) );
|
|
QVERIFY( QgsProcessingFeatureSourceDefinition( layer->id(), true ) != QgsProcessingFeatureSourceDefinition( layer->id(), false ) );
|
|
}
|
|
|
|
void TestQgsProcessing::uniqueValues()
|
|
{
|
|
QgsVectorLayer *layer = new QgsVectorLayer( "Point?field=a:integer&field=b:string", "v1", "memory" );
|
|
for ( int i = 0; i < 6; ++i )
|
|
{
|
|
QgsFeature f( i );
|
|
f.setAttributes( QgsAttributes() << i % 3 + 1 << QString( QChar( ( i % 3 ) + 65 ) ) );
|
|
layer->dataProvider()->addFeatures( QgsFeatureList() << f );
|
|
}
|
|
|
|
QgsProcessingContext context;
|
|
context.setFlags( QgsProcessingContext::Flags( 0 ) );
|
|
|
|
QgsProject p;
|
|
p.addMapLayer( layer );
|
|
context.setProject( &p );
|
|
|
|
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterString( QStringLiteral( "layer" ) ) );
|
|
QVariantMap params;
|
|
params.insert( QStringLiteral( "layer" ), layer->id() );
|
|
|
|
std::unique_ptr< QgsFeatureSource > source( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
|
|
// some bad checks
|
|
QVERIFY( source->uniqueValues( -1 ).isEmpty() );
|
|
QVERIFY( source->uniqueValues( 10001 ).isEmpty() );
|
|
|
|
// good checks
|
|
QSet< QVariant > vals = source->uniqueValues( 0 );
|
|
QCOMPARE( vals.count(), 3 );
|
|
QVERIFY( vals.contains( 1 ) );
|
|
QVERIFY( vals.contains( 2 ) );
|
|
QVERIFY( vals.contains( 3 ) );
|
|
vals = source->uniqueValues( 1 );
|
|
QCOMPARE( vals.count(), 3 );
|
|
QVERIFY( vals.contains( QString( "A" ) ) );
|
|
QVERIFY( vals.contains( QString( "B" ) ) );
|
|
QVERIFY( vals.contains( QString( "C" ) ) );
|
|
|
|
//using only selected features
|
|
layer->selectByIds( QgsFeatureIds() << 1 << 2 << 4 );
|
|
// but not using selection yet...
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
vals = source->uniqueValues( 0 );
|
|
QCOMPARE( vals.count(), 3 );
|
|
QVERIFY( vals.contains( 1 ) );
|
|
QVERIFY( vals.contains( 2 ) );
|
|
QVERIFY( vals.contains( 3 ) );
|
|
vals = source->uniqueValues( 1 );
|
|
QCOMPARE( vals.count(), 3 );
|
|
QVERIFY( vals.contains( QString( "A" ) ) );
|
|
QVERIFY( vals.contains( QString( "B" ) ) );
|
|
QVERIFY( vals.contains( QString( "C" ) ) );
|
|
|
|
// selection and using selection
|
|
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( QgsProcessingFeatureSourceDefinition( layer->id(), true ) ) );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
QVERIFY( source->uniqueValues( -1 ).isEmpty() );
|
|
QVERIFY( source->uniqueValues( 10001 ).isEmpty() );
|
|
vals = source->uniqueValues( 0 );
|
|
QCOMPARE( vals.count(), 2 );
|
|
QVERIFY( vals.contains( 1 ) );
|
|
QVERIFY( vals.contains( 2 ) );
|
|
vals = source->uniqueValues( 1 );
|
|
QCOMPARE( vals.count(), 2 );
|
|
QVERIFY( vals.contains( QString( "A" ) ) );
|
|
QVERIFY( vals.contains( QString( "B" ) ) );
|
|
}
|
|
|
|
void TestQgsProcessing::createIndex()
|
|
{
|
|
QgsVectorLayer *layer = new QgsVectorLayer( "Point", "v1", "memory" );
|
|
for ( int i = 1; i < 6; ++i )
|
|
{
|
|
QgsFeature f( i );
|
|
f.setGeometry( QgsGeometry( new QgsPoint( i, 2 ) ) );
|
|
layer->dataProvider()->addFeatures( QgsFeatureList() << f );
|
|
}
|
|
|
|
QgsProcessingContext context;
|
|
QgsProject p;
|
|
p.addMapLayer( layer );
|
|
context.setProject( &p );
|
|
|
|
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterString( QStringLiteral( "layer" ) ) );
|
|
QVariantMap params;
|
|
params.insert( QStringLiteral( "layer" ), layer->id() );
|
|
|
|
// disable selected features check
|
|
std::unique_ptr< QgsFeatureSource > source( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
QVERIFY( source.get() );
|
|
QgsSpatialIndex index( *source );
|
|
QList<QgsFeatureId> ids = index.nearestNeighbor( QgsPointXY( 2.1, 2 ), 1 );
|
|
QCOMPARE( ids, QList<QgsFeatureId>() << 2 );
|
|
|
|
// selected features check, but none selected
|
|
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( QgsProcessingFeatureSourceDefinition( layer->id(), true ) ) );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
index = QgsSpatialIndex( *source );
|
|
ids = index.nearestNeighbor( QgsPointXY( 2.1, 2 ), 1 );
|
|
QCOMPARE( ids, QList<QgsFeatureId>() );
|
|
|
|
// create selection
|
|
layer->selectByIds( QgsFeatureIds() << 4 << 5 );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
index = QgsSpatialIndex( *source );
|
|
ids = index.nearestNeighbor( QgsPointXY( 2.1, 2 ), 1 );
|
|
QCOMPARE( ids, QList<QgsFeatureId>() << 4 );
|
|
|
|
// selection but not using selection mode
|
|
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( QgsProcessingFeatureSourceDefinition( layer->id(), false ) ) );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
index = QgsSpatialIndex( *source );
|
|
ids = index.nearestNeighbor( QgsPointXY( 2.1, 2 ), 1 );
|
|
QCOMPARE( ids, QList<QgsFeatureId>() << 2 );
|
|
}
|
|
|
|
void TestQgsProcessing::parseDestinationString()
|
|
{
|
|
QString providerKey;
|
|
QString uri;
|
|
QString layerName;
|
|
QString format;
|
|
QVariantMap options;
|
|
bool useWriter = false;
|
|
|
|
// simple shapefile output
|
|
QString destination = QStringLiteral( "d:/test.shp" );
|
|
QgsProcessingUtils::parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter );
|
|
QCOMPARE( destination, QStringLiteral( "d:/test.shp" ) );
|
|
QCOMPARE( providerKey, QStringLiteral( "ogr" ) );
|
|
QCOMPARE( uri, QStringLiteral( "d:/test.shp" ) );
|
|
QCOMPARE( format, QStringLiteral( "ESRI Shapefile" ) );
|
|
QVERIFY( useWriter );
|
|
|
|
// postgis output
|
|
destination = QStringLiteral( "postgis:dbname='db' host=DBHOST port=5432 table=\"calcs\".\"output\" (geom) sql=" );
|
|
QgsProcessingUtils::parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter );
|
|
QCOMPARE( providerKey, QStringLiteral( "postgres" ) );
|
|
QCOMPARE( uri, QStringLiteral( "dbname='db' host=DBHOST port=5432 table=\"calcs\".\"output\" (geom) sql=" ) );
|
|
QVERIFY( !useWriter );
|
|
// postgres key should also work
|
|
destination = QStringLiteral( "postgres:dbname='db' host=DBHOST port=5432 table=\"calcs\".\"output\" (geom) sql=" );
|
|
QgsProcessingUtils::parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter );
|
|
QCOMPARE( providerKey, QStringLiteral( "postgres" ) );
|
|
QCOMPARE( uri, QStringLiteral( "dbname='db' host=DBHOST port=5432 table=\"calcs\".\"output\" (geom) sql=" ) );
|
|
QVERIFY( !useWriter );
|
|
|
|
// full uri shp output
|
|
options.clear();
|
|
destination = QStringLiteral( "ogr:d:/test.shp" );
|
|
QgsProcessingUtils::parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter );
|
|
QCOMPARE( providerKey, QStringLiteral( "ogr" ) );
|
|
QCOMPARE( uri, QStringLiteral( "d:/test.shp" ) );
|
|
QCOMPARE( options.value( QStringLiteral( "update" ) ).toBool(), true );
|
|
QVERIFY( !options.contains( QStringLiteral( "layerName" ) ) );
|
|
QVERIFY( !useWriter );
|
|
|
|
// full uri geopackage output
|
|
options.clear();
|
|
destination = QStringLiteral( "ogr:d:/test.gpkg" );
|
|
QgsProcessingUtils::parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter );
|
|
QCOMPARE( providerKey, QStringLiteral( "ogr" ) );
|
|
QCOMPARE( uri, QStringLiteral( "d:/test.gpkg" ) );
|
|
QCOMPARE( options.value( QStringLiteral( "update" ) ).toBool(), true );
|
|
QVERIFY( !options.contains( QStringLiteral( "layerName" ) ) );
|
|
QVERIFY( !useWriter );
|
|
|
|
// full uri geopackage table output with layer name
|
|
options.clear();
|
|
destination = QStringLiteral( "ogr:dbname='d:/package.gpkg' table=\"mylayer\" (geom) sql=" );
|
|
QgsProcessingUtils::parseDestinationString( destination, providerKey, uri, layerName, format, options, useWriter );
|
|
QCOMPARE( providerKey, QStringLiteral( "ogr" ) );
|
|
QCOMPARE( uri, QStringLiteral( "d:/package.gpkg" ) );
|
|
QCOMPARE( options.value( QStringLiteral( "update" ) ).toBool(), true );
|
|
QCOMPARE( options.value( QStringLiteral( "layerName" ) ).toString(), QStringLiteral( "mylayer" ) );
|
|
QVERIFY( !useWriter );
|
|
}
|
|
|
|
void TestQgsProcessing::createFeatureSink()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// empty destination
|
|
QString destination;
|
|
destination = QString();
|
|
QgsVectorLayer *layer = nullptr;
|
|
|
|
// should create a memory layer
|
|
std::unique_ptr< QgsFeatureSink > sink( QgsProcessingUtils::createFeatureSink( destination, context, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem() ) );
|
|
QVERIFY( sink.get() );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
|
|
QVERIFY( layer );
|
|
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink.get() )->destinationSink(), layer->dataProvider() );
|
|
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
|
QCOMPARE( destination, layer->id() );
|
|
QCOMPARE( context.temporaryLayerStore()->mapLayer( layer->id() ), layer ); // layer should be in store
|
|
QgsFeature f;
|
|
QCOMPARE( layer->featureCount(), 0L );
|
|
QVERIFY( sink->addFeature( f ) );
|
|
QCOMPARE( layer->featureCount(), 1L );
|
|
context.temporaryLayerStore()->removeAllMapLayers();
|
|
layer = nullptr;
|
|
|
|
// specific memory layer output
|
|
destination = QStringLiteral( "memory:mylayer" );
|
|
sink.reset( QgsProcessingUtils::createFeatureSink( destination, context, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem() ) );
|
|
QVERIFY( sink.get() );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
|
|
QVERIFY( layer );
|
|
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink.get() )->destinationSink(), layer->dataProvider() );
|
|
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
|
QCOMPARE( layer->name(), QStringLiteral( "mylayer" ) );
|
|
QCOMPARE( destination, layer->id() );
|
|
QCOMPARE( context.temporaryLayerStore()->mapLayer( layer->id() ), layer ); // layer should be in store
|
|
QCOMPARE( layer->featureCount(), 0L );
|
|
QVERIFY( sink->addFeature( f ) );
|
|
QCOMPARE( layer->featureCount(), 1L );
|
|
context.temporaryLayerStore()->removeAllMapLayers();
|
|
layer = nullptr;
|
|
|
|
// nameless memory layer
|
|
destination = QStringLiteral( "memory:" );
|
|
sink.reset( QgsProcessingUtils::createFeatureSink( destination, context, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem() ) );
|
|
QVERIFY( sink.get() );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
|
|
QVERIFY( layer );
|
|
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink.get() )->destinationSink(), layer->dataProvider() );
|
|
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
|
QCOMPARE( layer->name(), QString( "output" ) ); // should fall back to "output" name
|
|
QCOMPARE( destination, layer->id() );
|
|
QCOMPARE( context.temporaryLayerStore()->mapLayer( layer->id() ), layer ); // layer should be in store
|
|
QCOMPARE( layer->featureCount(), 0L );
|
|
QVERIFY( sink->addFeature( f ) );
|
|
QCOMPARE( layer->featureCount(), 1L );
|
|
context.temporaryLayerStore()->removeAllMapLayers();
|
|
layer = nullptr;
|
|
|
|
// memory layer parameters
|
|
destination = QStringLiteral( "memory:mylayer" );
|
|
QgsFields fields;
|
|
fields.append( QgsField( QStringLiteral( "my_field" ), QVariant::String, QString(), 100 ) );
|
|
sink.reset( QgsProcessingUtils::createFeatureSink( destination, context, fields, QgsWkbTypes::PointZM, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ) ) );
|
|
QVERIFY( sink.get() );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, false ) );
|
|
QVERIFY( layer );
|
|
QCOMPARE( static_cast< QgsProxyFeatureSink *>( sink.get() )->destinationSink(), layer->dataProvider() );
|
|
QCOMPARE( layer->dataProvider()->name(), QStringLiteral( "memory" ) );
|
|
QCOMPARE( layer->name(), QStringLiteral( "mylayer" ) );
|
|
QCOMPARE( layer->wkbType(), QgsWkbTypes::PointZM );
|
|
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
|
|
QCOMPARE( layer->fields().size(), 1 );
|
|
QCOMPARE( layer->fields().at( 0 ).name(), QStringLiteral( "my_field" ) );
|
|
QCOMPARE( layer->fields().at( 0 ).type(), QVariant::String );
|
|
QCOMPARE( destination, layer->id() );
|
|
QCOMPARE( context.temporaryLayerStore()->mapLayer( layer->id() ), layer ); // layer should be in store
|
|
QCOMPARE( layer->featureCount(), 0L );
|
|
QVERIFY( sink->addFeature( f ) );
|
|
QCOMPARE( layer->featureCount(), 1L );
|
|
context.temporaryLayerStore()->removeAllMapLayers();
|
|
|
|
// non memory layer output
|
|
destination = QDir::tempPath() + "/create_feature_sink.tab";
|
|
QString prevDest = destination;
|
|
sink.reset( QgsProcessingUtils::createFeatureSink( destination, context, fields, QgsWkbTypes::Polygon, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ) ) );
|
|
QVERIFY( sink.get() );
|
|
f = QgsFeature( fields );
|
|
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 0 1, 1 1, 1 0, 0 0 ))" ) ) );
|
|
f.setAttributes( QgsAttributes() << "val" );
|
|
QVERIFY( sink->addFeature( f ) );
|
|
QCOMPARE( destination, prevDest );
|
|
sink.reset( nullptr );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, true ) );
|
|
QVERIFY( layer->isValid() );
|
|
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
|
|
QCOMPARE( layer->fields().size(), 1 );
|
|
QCOMPARE( layer->fields().at( 0 ).name(), QStringLiteral( "my_field" ) );
|
|
QCOMPARE( layer->fields().at( 0 ).type(), QVariant::String );
|
|
QCOMPARE( layer->featureCount(), 1L );
|
|
|
|
// no extension, should default to shp
|
|
destination = QDir::tempPath() + "/create_feature_sink2";
|
|
prevDest = QDir::tempPath() + "/create_feature_sink2.gpkg";
|
|
sink.reset( QgsProcessingUtils::createFeatureSink( destination, context, fields, QgsWkbTypes::Point25D, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ) ) );
|
|
QVERIFY( sink.get() );
|
|
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "PointZ(1 2 3)" ) ) );
|
|
QVERIFY( sink->addFeature( f ) );
|
|
QCOMPARE( destination, prevDest );
|
|
sink.reset( nullptr );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, true ) );
|
|
QCOMPARE( layer->wkbType(), QgsWkbTypes::Point25D );
|
|
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
|
|
QCOMPARE( layer->fields().size(), 2 );
|
|
QCOMPARE( layer->fields().at( 0 ).name(), QStringLiteral( "fid" ) );
|
|
QCOMPARE( layer->fields().at( 1 ).name(), QStringLiteral( "my_field" ) );
|
|
QCOMPARE( layer->fields().at( 1 ).type(), QVariant::String );
|
|
QCOMPARE( layer->featureCount(), 1L );
|
|
|
|
//windows style path
|
|
destination = "d:\\temp\\create_feature_sink.tab";
|
|
sink.reset( QgsProcessingUtils::createFeatureSink( destination, context, fields, QgsWkbTypes::Polygon, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ) ) );
|
|
QVERIFY( sink.get() );
|
|
|
|
// save to geopackage
|
|
QString geopackagePath = QDir::tempPath() + "/packaged.gpkg";
|
|
if ( QFileInfo::exists( geopackagePath ) )
|
|
QFile::remove( geopackagePath );
|
|
destination = QStringLiteral( "ogr:dbname='%1' table=\"polygons\" (geom) sql=" ).arg( geopackagePath );
|
|
sink.reset( QgsProcessingUtils::createFeatureSink( destination, context, fields, QgsWkbTypes::Polygon, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ) ) );
|
|
QVERIFY( sink.get() );
|
|
f = QgsFeature( fields );
|
|
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Polygon((0 0, 0 1, 1 1, 1 0, 0 0 ))" ) ) );
|
|
f.setAttributes( QgsAttributes() << "val" );
|
|
QVERIFY( sink->addFeature( f ) );
|
|
sink.reset( nullptr );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, true ) );
|
|
QVERIFY( layer->isValid() );
|
|
QCOMPARE( layer->wkbType(), QgsWkbTypes::Polygon );
|
|
QVERIFY( layer->getFeatures().nextFeature( f ) );
|
|
QCOMPARE( f.attribute( "my_field" ).toString(), QStringLiteral( "val" ) );
|
|
|
|
// add another output to the same geopackage
|
|
QString destination2 = QStringLiteral( "ogr:dbname='%1' table=\"points\" (geom) sql=" ).arg( geopackagePath );
|
|
sink.reset( QgsProcessingUtils::createFeatureSink( destination2, context, fields, QgsWkbTypes::Point, QgsCoordinateReferenceSystem::fromEpsgId( 3111 ) ) );
|
|
QVERIFY( sink.get() );
|
|
f = QgsFeature( fields );
|
|
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "Point(0 0)" ) ) );
|
|
f.setAttributes( QgsAttributes() << "val2" );
|
|
QVERIFY( sink->addFeature( f ) );
|
|
sink.reset( nullptr );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination2, context, true ) );
|
|
QVERIFY( layer->isValid() );
|
|
QCOMPARE( layer->wkbType(), QgsWkbTypes::Point );
|
|
QVERIFY( layer->getFeatures().nextFeature( f ) );
|
|
QCOMPARE( f.attribute( "my_field" ).toString(), QStringLiteral( "val2" ) );
|
|
|
|
// original polygon layer should remain
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destination, context, true ) );
|
|
QVERIFY( layer->isValid() );
|
|
QCOMPARE( layer->wkbType(), QgsWkbTypes::Polygon );
|
|
QVERIFY( layer->getFeatures().nextFeature( f ) );
|
|
QCOMPARE( f.attribute( "my_field" ).toString(), QStringLiteral( "val" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::parameters()
|
|
{
|
|
// test parameter utilities
|
|
|
|
std::unique_ptr< QgsProcessingParameterDefinition > def;
|
|
|
|
QVariantMap params;
|
|
params.insert( QStringLiteral( "prop" ), QgsProperty::fromField( "a_field" ) );
|
|
params.insert( QStringLiteral( "string" ), QStringLiteral( "a string" ) );
|
|
params.insert( QStringLiteral( "double" ), 5.2 );
|
|
params.insert( QStringLiteral( "int" ), 15 );
|
|
params.insert( QStringLiteral( "bool" ), true );
|
|
|
|
QgsProcessingContext context;
|
|
|
|
// isDynamic
|
|
QVERIFY( QgsProcessingParameters::isDynamic( params, QStringLiteral( "prop" ) ) );
|
|
QVERIFY( !QgsProcessingParameters::isDynamic( params, QStringLiteral( "string" ) ) );
|
|
QVERIFY( !QgsProcessingParameters::isDynamic( params, QStringLiteral( "bad" ) ) );
|
|
|
|
// parameterAsString
|
|
def.reset( new QgsProcessingParameterString( QStringLiteral( "string" ), QStringLiteral( "desc" ) ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QStringLiteral( "a string" ) );
|
|
def->setName( QStringLiteral( "double" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ).left( 3 ), QStringLiteral( "5.2" ) );
|
|
def->setName( QStringLiteral( "int" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QStringLiteral( "15" ) );
|
|
def->setName( QStringLiteral( "bool" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QStringLiteral( "true" ) );
|
|
def->setName( QStringLiteral( "bad" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QString() );
|
|
|
|
def->setIsDynamic( true );
|
|
QVERIFY( def->isDynamic() );
|
|
def->setDynamicPropertyDefinition( QgsPropertyDefinition( QStringLiteral( "Distance" ), QObject::tr( "Buffer distance" ), QgsPropertyDefinition::Double ) );
|
|
QCOMPARE( def->dynamicPropertyDefinition().name(), QStringLiteral( "Distance" ) );
|
|
def->setDynamicLayerParameterName( "parent" );
|
|
QCOMPARE( def->dynamicLayerParameterName(), QStringLiteral( "parent" ) );
|
|
|
|
// string with dynamic property (feature not set)
|
|
def->setName( QStringLiteral( "prop" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QString() );
|
|
|
|
// correctly setup feature
|
|
QgsFields fields;
|
|
fields.append( QgsField( "a_field", QVariant::String, QString(), 30 ) );
|
|
QgsFeature f( fields );
|
|
f.setAttribute( 0, QStringLiteral( "field value" ) );
|
|
context.expressionContext().setFeature( f );
|
|
context.expressionContext().setFields( fields );
|
|
def->setName( QStringLiteral( "prop" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QStringLiteral( "field value" ) );
|
|
|
|
// as double
|
|
def->setName( QStringLiteral( "double" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsDouble( def.get(), params, context ), 5.2 );
|
|
def->setName( QStringLiteral( "int" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsDouble( def.get(), params, context ), 15.0 );
|
|
f.setAttribute( 0, QStringLiteral( "6.2" ) );
|
|
context.expressionContext().setFeature( f );
|
|
def->setName( QStringLiteral( "prop" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsDouble( def.get(), params, context ), 6.2 );
|
|
|
|
// as int
|
|
def->setName( QStringLiteral( "double" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsInt( def.get(), params, context ), 5 );
|
|
def->setName( QStringLiteral( "int" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsInt( def.get(), params, context ), 15 );
|
|
def->setName( QStringLiteral( "prop" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsInt( def.get(), params, context ), 6 );
|
|
|
|
// as bool
|
|
def->setName( QStringLiteral( "double" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
def->setName( QStringLiteral( "int" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
def->setName( QStringLiteral( "bool" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
def->setName( QStringLiteral( "prop" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
f.setAttribute( 0, false );
|
|
context.expressionContext().setFeature( f );
|
|
def->setName( QStringLiteral( "prop" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
|
|
// as layer
|
|
def->setName( QStringLiteral( "double" ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsLayer( def.get(), params, context ) );
|
|
def->setName( QStringLiteral( "int" ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsLayer( def.get(), params, context ) );
|
|
def->setName( QStringLiteral( "bool" ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsLayer( def.get(), params, context ) );
|
|
def->setName( QStringLiteral( "prop" ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsLayer( def.get(), params, context ) );
|
|
|
|
QVERIFY( context.temporaryLayerStore()->mapLayers().isEmpty() );
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
f.setAttribute( 0, testDataDir + "/raster/band1_float32_noct_epsg4326.tif" );
|
|
context.expressionContext().setFeature( f );
|
|
def->setName( QStringLiteral( "prop" ) );
|
|
QVERIFY( QgsProcessingParameters::parameterAsLayer( def.get(), params, context ) );
|
|
// make sure layer was loaded
|
|
QVERIFY( !context.temporaryLayerStore()->mapLayers().isEmpty() );
|
|
|
|
// parameters as sinks
|
|
|
|
QgsWkbTypes::Type wkbType = QgsWkbTypes::PolygonM;
|
|
QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem( QStringLiteral( "epsg:3111" ) );
|
|
QString destId;
|
|
def->setName( QStringLiteral( "string" ) );
|
|
params.insert( QStringLiteral( "string" ), QStringLiteral( "memory:mem" ) );
|
|
std::unique_ptr< QgsFeatureSink > sink;
|
|
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, fields, wkbType, crs, context, destId ) );
|
|
QVERIFY( sink.get() );
|
|
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destId, context ) );
|
|
QVERIFY( layer );
|
|
QVERIFY( layer->isValid() );
|
|
QCOMPARE( layer->fields().count(), 1 );
|
|
QCOMPARE( layer->fields().at( 0 ).name(), QStringLiteral( "a_field" ) );
|
|
QCOMPARE( layer->wkbType(), wkbType );
|
|
QCOMPARE( layer->crs(), crs );
|
|
|
|
// property defined sink destination
|
|
params.insert( QStringLiteral( "prop" ), QgsProperty::fromExpression( "'memory:mem2'" ) );
|
|
def->setName( QStringLiteral( "prop" ) );
|
|
crs = QgsCoordinateReferenceSystem( QStringLiteral( "epsg:3113" ) );
|
|
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, fields, wkbType, crs, context, destId ) );
|
|
QVERIFY( sink.get() );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destId, context ) );
|
|
QVERIFY( layer );
|
|
QVERIFY( layer->isValid() );
|
|
QCOMPARE( layer->fields().count(), 1 );
|
|
QCOMPARE( layer->fields().at( 0 ).name(), QStringLiteral( "a_field" ) );
|
|
QCOMPARE( layer->wkbType(), wkbType );
|
|
QCOMPARE( layer->crs(), crs );
|
|
|
|
// QgsProcessingFeatureSinkDefinition as parameter
|
|
QgsProject p;
|
|
QgsProcessingOutputLayerDefinition fs( QStringLiteral( "test.shp" ) );
|
|
fs.destinationProject = &p;
|
|
QVERIFY( context.layersToLoadOnCompletion().isEmpty() );
|
|
params.insert( QStringLiteral( "fs" ), QVariant::fromValue( fs ) );
|
|
def->setName( QStringLiteral( "fs" ) );
|
|
crs = QgsCoordinateReferenceSystem( QStringLiteral( "epsg:28356" ) );
|
|
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, fields, wkbType, crs, context, destId ) );
|
|
QVERIFY( sink.get() );
|
|
QgsVectorFileWriter *writer = dynamic_cast< QgsVectorFileWriter *>( dynamic_cast< QgsProcessingFeatureSink * >( sink.get() )->destinationSink() );
|
|
QVERIFY( writer );
|
|
layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( destId, context ) );
|
|
QVERIFY( layer );
|
|
QVERIFY( layer->isValid() );
|
|
QCOMPARE( layer->wkbType(), wkbType );
|
|
QCOMPARE( layer->crs(), crs );
|
|
|
|
// make sure layer was automatically added to list to load on completion
|
|
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" ) );
|
|
QCOMPARE( context2.layersToLoadOnCompletion().values().at( 0 ).outputName, QStringLiteral( "fs" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::algorithmParameters()
|
|
{
|
|
DummyAlgorithm *alg = new DummyAlgorithm( "test" );
|
|
DummyProvider p( "test" );
|
|
alg->runParameterChecks();
|
|
|
|
p.addAlgorithm( alg );
|
|
alg->runParameterChecks2();
|
|
}
|
|
|
|
void TestQgsProcessing::algorithmOutputs()
|
|
{
|
|
DummyAlgorithm alg( "test" );
|
|
alg.runOutputChecks();
|
|
}
|
|
|
|
void TestQgsProcessing::parameterGeneral()
|
|
{
|
|
// test constructor
|
|
QgsProcessingParameterBoolean param( "p1", "desc", true, true );
|
|
QCOMPARE( param.name(), QString( "p1" ) );
|
|
QCOMPARE( param.description(), QString( "desc" ) );
|
|
QCOMPARE( param.defaultValue(), QVariant( true ) );
|
|
QVERIFY( param.flags() & QgsProcessingParameterDefinition::FlagOptional );
|
|
QVERIFY( param.dependsOnOtherParameters().isEmpty() );
|
|
|
|
// test getters and setters
|
|
param.setDescription( "p2" );
|
|
QCOMPARE( param.description(), QString( "p2" ) );
|
|
param.setDefaultValue( false );
|
|
QCOMPARE( param.defaultValue(), QVariant( false ) );
|
|
param.setFlags( QgsProcessingParameterDefinition::FlagHidden );
|
|
QCOMPARE( param.flags(), QgsProcessingParameterDefinition::FlagHidden );
|
|
param.setDefaultValue( true );
|
|
QCOMPARE( param.defaultValue(), QVariant( true ) );
|
|
param.setDefaultValue( QVariant() );
|
|
QCOMPARE( param.defaultValue(), QVariant() );
|
|
|
|
QVariantMap metadata;
|
|
metadata.insert( "p1", 5 );
|
|
metadata.insert( "p2", 7 );
|
|
param.setMetadata( metadata );
|
|
QCOMPARE( param.metadata(), metadata );
|
|
param.metadata().insert( "p3", 9 );
|
|
QCOMPARE( param.metadata().value( "p3" ).toInt(), 9 );
|
|
|
|
QVariantMap map = param.toVariantMap();
|
|
QgsProcessingParameterBoolean fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), param.name() );
|
|
QCOMPARE( fromMap.description(), param.description() );
|
|
QCOMPARE( fromMap.flags(), param.flags() );
|
|
QCOMPARE( fromMap.defaultValue(), param.defaultValue() );
|
|
QCOMPARE( fromMap.metadata(), param.metadata() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterBoolean()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// test no def
|
|
QVariantMap params;
|
|
params.insert( "no_def", false );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( nullptr, params, context ), false );
|
|
params.insert( "no_def", "false" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( nullptr, params, context ), false );
|
|
params.insert( "no_def", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( nullptr, params, context ), false );
|
|
params.remove( "no_def" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( nullptr, params, context ), false );
|
|
|
|
// with defs
|
|
|
|
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterBoolean( "non_optional_default_false" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "false" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "true" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "non_optional_default_false", false );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
params.insert( "non_optional_default_false", true );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.insert( "non_optional_default_false", "true" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.insert( "non_optional_default_false", "false" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
|
|
//non-optional - behavior is undefined, but internally default to false
|
|
params.insert( "non_optional_default_false", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
params.remove( "non_optional_default_false" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
|
|
QCOMPARE( def->valueAsPythonString( false, context ), QStringLiteral( "False" ) );
|
|
QCOMPARE( def->valueAsPythonString( true, context ), QStringLiteral( "True" ) );
|
|
QCOMPARE( def->valueAsPythonString( "false", context ), QStringLiteral( "False" ) );
|
|
QCOMPARE( def->valueAsPythonString( "true", context ), QStringLiteral( "True" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional_default_false=boolean false" ) );
|
|
std::unique_ptr< QgsProcessingParameterBoolean > fromCode( dynamic_cast< QgsProcessingParameterBoolean * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional default false" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue().toBool(), false );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterBoolean fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
def.reset( QgsProcessingParameters::parameterFromVariantMap( map ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterBoolean *>( def.get() ) );
|
|
|
|
|
|
def.reset( new QgsProcessingParameterBoolean( "optional_default_true", QString(), true, true ) );
|
|
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "false" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "true" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional_default_true", false );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
params.insert( "optional_default_true", true );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.insert( "optional_default_true", "true" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.insert( "optional_default_true", "false" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
//optional - should be default
|
|
params.insert( "optional_default_true", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.remove( "optional_default_true" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional_default_true=optional boolean true" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterBoolean * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional default true" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue().toBool(), true );
|
|
|
|
def.reset( new QgsProcessingParameterBoolean( "optional_default_false", QString(), false, true ) );
|
|
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "false" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "true" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "false" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "true" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional_default_false", false );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
params.insert( "optional_default_false", true );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.insert( "optional_default_false", "true" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.insert( "optional_default_false", "false" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
//optional - should be default
|
|
params.insert( "optional_default_false", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
params.remove( "optional_default_false" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
|
|
code = def->asScriptCode();
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterBoolean * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional default false" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue().toBool(), false );
|
|
|
|
def.reset( new QgsProcessingParameterBoolean( "non_optional_default_true", QString(), true, false ) );
|
|
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "false" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "true" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) ); // should be acceptable, because it falls back to default value
|
|
|
|
params.insert( "non_optional_default_true", false );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
params.insert( "non_optional_default_true", true );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.insert( "non_optional_default_true", "true" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.insert( "non_optional_default_true", "false" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), false );
|
|
//non-optional - behavior is undefined, but internally fallback to default
|
|
params.insert( "non_optional_default_true", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
params.remove( "non_optional_default_true" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsBool( def.get(), params, context ), true );
|
|
|
|
code = def->asScriptCode();
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterBoolean * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional default true" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue().toBool(), true );
|
|
|
|
def.reset( new QgsProcessingParameterBoolean( "non_optional_no_default", QString(), QVariant(), false ) );
|
|
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "false" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "true" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) ); // should NOT be acceptable, because it falls back to invalid default value
|
|
}
|
|
|
|
void TestQgsProcessing::parameterCrs()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QString raster2 = testDataDir + "landsat.tif";
|
|
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 );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterCrs > def( new QgsProcessingParameterCrs( "non_optional", QString(), QString( "EPSG:3113" ), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "EPSG:12003" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "EPSG:3111" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( r1 ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingFeatureSourceDefinition( r1->id() ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingFeatureSourceDefinition( QgsProperty::fromValue( QVariant::fromValue( r1 ) ) ) ) );
|
|
|
|
// using map layer
|
|
QVariantMap params;
|
|
params.insert( "non_optional", v1->id() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).authid(), QString( "EPSG:3111" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( v1->id() ) );
|
|
params.insert( "non_optional", QVariant::fromValue( v1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).authid(), QString( "EPSG:3111" ) );
|
|
|
|
// special ProjectCrs string
|
|
params.insert( "non_optional", QStringLiteral( "ProjectCrs" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).authid(), QString( "EPSG:28353" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringLiteral( "ProjectCrs" ) ) );
|
|
|
|
// string representing a project layer source
|
|
params.insert( "non_optional", raster1 );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).authid(), QString( "EPSG:4326" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( raster1 ) );
|
|
|
|
// string representing a non-project layer source
|
|
params.insert( "non_optional", raster2 );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).authid(), QString( "EPSG:32633" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( raster2 ) );
|
|
|
|
// string representation of a crs
|
|
params.insert( "non_optional", QString( "EPSG:28355" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).authid(), QString( "EPSG:28355" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringLiteral( "EPSG:28355" ) ) );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a crs, and nothing you can do will make me one" ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).isValid() );
|
|
|
|
// using feature source definition
|
|
params.insert( "non_optional", QgsProcessingFeatureSourceDefinition( v1->id() ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).authid(), QString( "EPSG:3111" ) );
|
|
params.insert( "non_optional", QgsProcessingFeatureSourceDefinition( QgsProperty::fromValue( QVariant::fromValue( v1 ) ) ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).authid(), QString( "EPSG:3111" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( "EPSG:12003", context ), QStringLiteral( "'EPSG:12003'" ) );
|
|
QCOMPARE( def->valueAsPythonString( "ProjectCrs", context ), QStringLiteral( "'ProjectCrs'" ) );
|
|
QCOMPARE( def->valueAsPythonString( raster1, context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( r1->id(), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\\'complex\\' username=\\\"complex\\\"'" ) );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterCrs fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterCrs *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterCrs *>( def.get() ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=crs EPSG:3113" ) );
|
|
std::unique_ptr< QgsProcessingParameterCrs > fromCode( dynamic_cast< QgsProcessingParameterCrs * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterCrs( "optional", QString(), QString( "EPSG:3113" ), true ) );
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsCrs( def.get(), params, context ).authid(), QString( "EPSG:3113" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "EPSG:12003" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "EPSG:3111" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional crs EPSG:3113" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterCrs * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
code = QStringLiteral( "##optional=optional crs None" );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterCrs * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QVERIFY( !fromCode->defaultValue().isValid() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterLayer()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QString raster2 = testDataDir + "landsat.tif";
|
|
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 );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterMapLayer > def( new QgsProcessingParameterMapLayer( "non_optional", QString(), QString(), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( r1 ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( v1 ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
// should be OK
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
// ... unless we use context, when the check that the layer actually exists is performed
|
|
QVERIFY( !def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
|
|
// using existing map layer ID
|
|
QVariantMap params;
|
|
params.insert( "non_optional", v1->id() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayer( def.get(), params, context )->id(), v1->id() );
|
|
QVERIFY( def->checkValueIsAcceptable( v1->id() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( v1->id(), &context ) );
|
|
|
|
// string representing a project layer source
|
|
params.insert( "non_optional", raster1 );
|
|
QVERIFY( def->checkValueIsAcceptable( raster1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayer( def.get(), params, context )->id(), r1->id() );
|
|
// string representing a non-project layer source
|
|
params.insert( "non_optional", raster2 );
|
|
QVERIFY( def->checkValueIsAcceptable( raster2 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayer( def.get(), params, context )->publicSource(), raster2 );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a layer, and nothing you can do will make me one" ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsLayer( def.get(), params, context ) );
|
|
|
|
// layer
|
|
params.insert( "non_optional", QVariant::fromValue( r1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayer( def.get(), params, context ), r1 );
|
|
params.insert( "non_optional", QVariant::fromValue( v1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayer( def.get(), params, context ), v1 );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( raster1, context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( r1->id(), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( r1 ), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=layer" ) );
|
|
std::unique_ptr< QgsProcessingParameterMapLayer > fromCode( dynamic_cast< QgsProcessingParameterMapLayer * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterMapLayer fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterMapLayer *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterMapLayer *>( def.get() ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterMapLayer( "optional", QString(), v1->id(), true ) );
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayer( def.get(), params, context )->id(), v1->id() );
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( r1 ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( v1 ) ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional layer " ) + v1->id() );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterMapLayer * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterExtent()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QString raster2 = testDataDir + "landsat.tif";
|
|
QFileInfo fi1( raster1 );
|
|
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
|
p.addMapLayers( QList<QgsMapLayer *>() << r1 );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterExtent > def( new QgsProcessingParameterExtent( "non_optional", QString(), QString( "1,2,3,4" ), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1,2,3,4" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( " 1, 2 ,3 , 4 " ) );
|
|
QVERIFY( def->checkValueIsAcceptable( " 1, 2 ,3 , 4 ", &context ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "-1.1,2,-3,-4" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "-1.1,2,-3,-4", &context ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "-1.1,-2.2,-3.3,-4.4" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "-1.1,-2.2,-3.3,-4.4", &context ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2,3,4.4[EPSG:4326]" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2,3,4.4[EPSG:4326]", &context ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2,3,4.4 [EPSG:4326]" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2,3,4.4 [EPSG:4326]", &context ) );
|
|
QVERIFY( def->checkValueIsAcceptable( " -1.1, -2, -3, -4.4 [EPSG:4326] " ) );
|
|
QVERIFY( def->checkValueIsAcceptable( " -1.1, -2, -3, -4.4 [EPSG:4326] ", &context ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "121774.38859446358,948723.6921024882,-264546.200347173,492749.6672022904 [EPSG:3785]" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "121774.38859446358,948723.6921024882,-264546.200347173,492749.6672022904 [EPSG:3785]", &context ) );
|
|
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsRectangle( 1, 2, 3, 4 ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsRectangle() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsReferencedRectangle( QgsRectangle( 1, 2, 3, 4 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsReferencedRectangle( QgsRectangle(), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) );
|
|
|
|
// these checks require a context - otherwise we could potentially be referring to a layer source
|
|
QVERIFY( def->checkValueIsAcceptable( "1,2,3" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1,2,3,a" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1,2,3", &context ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1,2,3,a", &context ) );
|
|
|
|
// using map layer
|
|
QVariantMap params;
|
|
params.insert( "non_optional", r1->id() );
|
|
QVERIFY( def->checkValueIsAcceptable( r1->id() ) );
|
|
QgsRectangle ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
|
|
QCOMPARE( ext, r1->extent() );
|
|
|
|
// string representing a project layer source
|
|
params.insert( "non_optional", raster1 );
|
|
QVERIFY( def->checkValueIsAcceptable( raster1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtent( def.get(), params, context ), r1->extent() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtentCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:4326" ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1535375, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 1535475, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 5083255, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 5083355, 100 );
|
|
|
|
// layer as parameter
|
|
params.insert( "non_optional", QVariant::fromValue( r1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( r1 ) ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtent( def.get(), params, context ), r1->extent() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtentCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:4326" ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1535375, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 1535475, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 5083255, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 5083355, 100 );
|
|
QgsGeometry gExt = QgsProcessingParameters::parameterAsExtentGeometry( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:4326" ) );
|
|
QCOMPARE( gExt.constGet()->vertexCount(), 5 );
|
|
ext = gExt.boundingBox();
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1535375, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 1535475, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 5083255, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 5083355, 100 );
|
|
|
|
// using feature source definition
|
|
params.insert( "non_optional", QgsProcessingFeatureSourceDefinition( r1->id() ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtentCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:4326" ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1535375, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 1535475, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 5083255, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 5083355, 100 );
|
|
gExt = QgsProcessingParameters::parameterAsExtentGeometry( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:4326" ) );
|
|
QCOMPARE( gExt.constGet()->vertexCount(), 5 );
|
|
ext = gExt.boundingBox();
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1535375, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 1535475, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 5083255, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 5083355, 100 );
|
|
params.insert( "non_optional", QgsProcessingFeatureSourceDefinition( QgsProperty::fromValue( QVariant::fromValue( r1 ) ) ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtentCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:4326" ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1535375, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 1535475, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 5083255, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 5083355, 100 );
|
|
gExt = QgsProcessingParameters::parameterAsExtentGeometry( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:4326" ) );
|
|
QCOMPARE( gExt.constGet()->vertexCount(), 5 );
|
|
ext = gExt.boundingBox();
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1535375, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 1535475, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 5083255, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 5083355, 100 );
|
|
|
|
// string representing a non-project layer source
|
|
params.insert( "non_optional", raster2 );
|
|
QVERIFY( def->checkValueIsAcceptable( raster2 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtentCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:32633" ) );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 781662.375000, 10 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 793062.375000, 10 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 3339523.125000, 10 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 3350923.125000, 10 );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:4326" ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 17.924273, 0.01 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 18.045658, 0.01 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 30.151856, 0.01 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 30.257289, 0.01 );
|
|
gExt = QgsProcessingParameters::parameterAsExtentGeometry( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:4326" ) );
|
|
QCOMPARE( gExt.constGet()->vertexCount(), 85 );
|
|
ext = gExt.boundingBox();
|
|
QGSCOMPARENEAR( ext.xMinimum(), 17.924273, 0.01 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 18.045658, 0.01 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 30.151856, 0.01 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 30.257289, 0.01 );
|
|
|
|
// string representation of an extent
|
|
params.insert( "non_optional", QString( "1.1,2.2,3.3,4.4" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringLiteral( "1.1,2.2,3.3,4.4" ) ) );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 2.2, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 3.3, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 4.4, 0.001 );
|
|
|
|
// with target CRS - should make no difference, because source CRS is unknown
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 2.2, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 3.3, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 4.4, 0.001 );
|
|
|
|
// with crs in string
|
|
params.insert( "non_optional", QString( "1.1,3.3,2.2,4.4 [EPSG:4326]" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtentCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 3.3, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 2.2, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 4.4, 0.001 );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 122451, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 367354, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 244963, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 490287, 100 );
|
|
gExt = QgsProcessingParameters::parameterAsExtentGeometry( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QCOMPARE( gExt.constGet()->vertexCount(), 85 );
|
|
ext = gExt.boundingBox();
|
|
QGSCOMPARENEAR( ext.xMinimum(), 122451, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 367354, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 244963, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 490287, 100 );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a crs, and nothing you can do will make me one" ) );
|
|
QVERIFY( QgsProcessingParameters::parameterAsExtent( def.get(), params, context ).isNull() );
|
|
|
|
// QgsRectangle
|
|
params.insert( "non_optional", QgsRectangle( 11.1, 12.2, 13.3, 14.4 ) );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 11.1, 0.001 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 13.3, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 12.2, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 14.4, 0.001 );
|
|
|
|
// with target CRS - should make no difference, because source CRS is unknown
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 11.1, 0.001 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 13.3, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 12.2, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 14.4, 0.001 );
|
|
|
|
gExt = QgsProcessingParameters::parameterAsExtentGeometry( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QCOMPARE( gExt.asWkt( 1 ), QStringLiteral( "Polygon ((11.1 12.2, 13.3 12.2, 13.3 14.4, 11.1 14.4, 11.1 12.2))" ) );
|
|
|
|
p.setCrs( QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtentCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:3785" ) );
|
|
|
|
// QgsReferencedRectangle
|
|
params.insert( "non_optional", QgsReferencedRectangle( QgsRectangle( 1.1, 2.2, 3.3, 4.4 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 3.3, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 2.2, 0.001 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 4.4, 0.001 );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExtentCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
|
|
// with target CRS
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 122451, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 367354, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 244963, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 490287, 100 );
|
|
|
|
// as reprojected geometry
|
|
gExt = QgsProcessingParameters::parameterAsExtentGeometry( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QCOMPARE( gExt.constGet()->vertexCount(), 85 );
|
|
ext = gExt.boundingBox();
|
|
QGSCOMPARENEAR( ext.xMinimum(), 122451, 100 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 367354, 100 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 244963, 100 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 490287, 100 );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( "1,2,3,4", context ), QStringLiteral( "'1,2,3,4'" ) );
|
|
QCOMPARE( def->valueAsPythonString( r1->id(), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( r1 ), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( raster2, context ), QString( "'" ) + testDataDir + QStringLiteral( "landsat.tif'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( QgsRectangle( 11, 12, 13, 14 ), context ), QStringLiteral( "'11, 13, 12, 14'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QgsReferencedRectangle( QgsRectangle( 11, 12, 13, 14 ), QgsCoordinateReferenceSystem( "epsg:4326" ) ), context ), QStringLiteral( "'11, 13, 12, 14 [EPSG:4326]'" ) );
|
|
QCOMPARE( def->valueAsPythonString( "1,2,3,4 [EPSG:4326]", context ), QStringLiteral( "'1,2,3,4 [EPSG:4326]'" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\\'complex\\' username=\\\"complex\\\"'" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=extent 1,2,3,4" ) );
|
|
std::unique_ptr< QgsProcessingParameterExtent > fromCode( dynamic_cast< QgsProcessingParameterExtent * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterExtent fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterExtent *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterExtent *>( def.get() ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterExtent( "optional", QString(), QString( "5,6,7,8" ), true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1,2,3,4" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
// Extent is unique in that it will let you set invalid, whereas other
|
|
// optional parameters become "default" when assigning invalid.
|
|
params.insert( "optional", QVariant() );
|
|
ext = QgsProcessingParameters::parameterAsExtent( def.get(), params, context );
|
|
QVERIFY( ext.isNull() );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional extent 5,6,7,8" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterExtent * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterPoint()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterPoint > def( new QgsProcessingParameterPoint( "non_optional", QString(), QString( "1,2" ), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "(1.1,2)" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( " 1.1, 2 " ) );
|
|
QVERIFY( def->checkValueIsAcceptable( " ( 1.1, 2 ) " ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "-1.1,2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,-2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "-1.1,-2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "(-1.1,-2)" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2[EPSG:4326]" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2 [EPSG:4326]" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "(1.1,2 [EPSG:4326] )" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( " -1.1, -2 [EPSG:4326] " ) );
|
|
QVERIFY( def->checkValueIsAcceptable( " ( -1.1, -2 [EPSG:4326] ) " ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1,a" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "(1.1,a)" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "(layer12312312)" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "()" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( " ( ) " ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsPointXY( 1, 2 ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsReferencedPointXY( QgsPointXY( 1, 2 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) ) );
|
|
|
|
// string representing a point
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QString( "1.1,2.2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2.2" ) );
|
|
QgsPointXY point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
|
|
QGSCOMPARENEAR( point.x(), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( point.y(), 2.2, 0.001 );
|
|
|
|
// with target CRS - should make no difference, because source CRS is unknown
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( point.x(), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( point.y(), 2.2, 0.001 );
|
|
|
|
// with optional brackets
|
|
params.insert( "non_optional", QString( "(1.1,2.2)" ) );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
|
|
QGSCOMPARENEAR( point.x(), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( point.y(), 2.2, 0.001 );
|
|
|
|
params.insert( "non_optional", QString( " ( -1.1 ,-2.2 ) " ) );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
|
|
QGSCOMPARENEAR( point.x(), -1.1, 0.001 );
|
|
QGSCOMPARENEAR( point.y(), -2.2, 0.001 );
|
|
|
|
// with CRS as string
|
|
params.insert( "non_optional", QString( "1.1,2.2[EPSG:4326]" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsPointCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( point.x(), 122451, 100 );
|
|
QGSCOMPARENEAR( point.y(), 244963, 100 );
|
|
params.insert( "non_optional", QString( "1.1,2.2 [EPSG:4326]" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsPointCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( point.x(), 122451, 100 );
|
|
QGSCOMPARENEAR( point.y(), 244963, 100 );
|
|
|
|
params.insert( "non_optional", QString( " ( 1.1,2.2 [EPSG:4326] ) " ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsPointCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( point.x(), 122451, 100 );
|
|
QGSCOMPARENEAR( point.y(), 244963, 100 );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a crs, and nothing you can do will make me one" ) );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
|
|
QCOMPARE( point.x(), 0.0 );
|
|
QCOMPARE( point.y(), 0.0 );
|
|
|
|
params.insert( "non_optional", QString( " ( ) " ) );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
|
|
QCOMPARE( point.x(), 0.0 );
|
|
QCOMPARE( point.y(), 0.0 );
|
|
|
|
// QgsPointXY
|
|
params.insert( "non_optional", QgsPointXY( 11.1, 12.2 ) );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
|
|
QGSCOMPARENEAR( point.x(), 11.1, 0.001 );
|
|
QGSCOMPARENEAR( point.y(), 12.2, 0.001 );
|
|
|
|
// with target CRS - should make no difference, because source CRS is unknown
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( point.x(), 11.1, 0.001 );
|
|
QGSCOMPARENEAR( point.y(), 12.2, 0.001 );
|
|
|
|
// QgsReferencedPointXY
|
|
params.insert( "non_optional", QgsReferencedPointXY( QgsPointXY( 1.1, 2.2 ), QgsCoordinateReferenceSystem( "EPSG:4326" ) ) );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
|
|
QGSCOMPARENEAR( point.x(), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( point.y(), 2.2, 0.001 );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsPointCrs( def.get(), params, context ).authid(), QStringLiteral( "EPSG:4326" ) );
|
|
|
|
// with target CRS
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context, QgsCoordinateReferenceSystem( "EPSG:3785" ) );
|
|
QGSCOMPARENEAR( point.x(), 122451, 100 );
|
|
QGSCOMPARENEAR( point.y(), 244963, 100 );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( "1,2", context ), QStringLiteral( "'1,2'" ) );
|
|
QCOMPARE( def->valueAsPythonString( "1,2 [EPSG:4326]", context ), QStringLiteral( "'1,2 [EPSG:4326]'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QgsPointXY( 11, 12 ), context ), QStringLiteral( "'11,12'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QgsReferencedPointXY( QgsPointXY( 11, 12 ), QgsCoordinateReferenceSystem( "epsg:4326" ) ), context ), QStringLiteral( "'11,12 [EPSG:4326]'" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=point 1,2" ) );
|
|
std::unique_ptr< QgsProcessingParameterPoint > fromCode( dynamic_cast< QgsProcessingParameterPoint * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterPoint fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterPoint *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterPoint *>( def.get() ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterPoint( "optional", QString(), QString( "5.1,6.2" ), true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1,a" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
point = QgsProcessingParameters::parameterAsPoint( def.get(), params, context );
|
|
QGSCOMPARENEAR( point.x(), 5.1, 0.001 );
|
|
QGSCOMPARENEAR( point.y(), 6.2, 0.001 );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional point 5.1,6.2" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterPoint * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterFile()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterFile > def( new QgsProcessingParameterFile( "non_optional", QString(), QgsProcessingParameterFile::File, QString(), QString( "abc.bmp" ), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "bricks.bmp" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( " " ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
// string representing a file
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QString( "def.bmp" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsFile( def.get(), params, context ), QString( "def.bmp" ) );
|
|
|
|
// with extension
|
|
def.reset( new QgsProcessingParameterFile( "non_optional", QString(), QgsProcessingParameterFile::File, QStringLiteral( ".bmp" ), QString( "abc.bmp" ), false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "bricks.bmp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "bricks.BMP" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "bricks.pcx" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( "bricks.bmp", context ), QStringLiteral( "'bricks.bmp'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\\'complex\\' username=\\\"complex\\\"'" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=file abc.bmp" ) );
|
|
std::unique_ptr< QgsProcessingParameterFile > fromCode( dynamic_cast< QgsProcessingParameterFile * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->behavior(), def->behavior() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterFile fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.extension(), def->extension() );
|
|
QCOMPARE( fromMap.behavior(), def->behavior() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterFile *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterFile *>( def.get() ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterFile( "optional", QString(), QgsProcessingParameterFile::File, QString(), QString( "gef.bmp" ), true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "bricks.bmp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( " " ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsFile( def.get(), params, context ), QString( "gef.bmp" ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional file gef.bmp" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFile * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->behavior(), def->behavior() );
|
|
|
|
// folder
|
|
def.reset( new QgsProcessingParameterFile( "optional", QString(), QgsProcessingParameterFile::Folder, QString(), QString( "/home/me" ), true ) );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional folder /home/me" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFile * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->behavior(), def->behavior() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterMatrix()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterMatrix > def( new QgsProcessingParameterMatrix( "non_optional", QString(), 3, false, QStringList(), QString(), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1,2,3" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << 1 << 2 << 3 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << ( QVariantList() << 1 << 2 << 3 ) << ( QVariantList() << 1 << 2 << 3 ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
// list
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QVariantList() << 1 << 2 << 3 );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsMatrix( def.get(), params, context ), QVariantList() << 1 << 2 << 3 );
|
|
|
|
//string
|
|
params.insert( "non_optional", QString( "4,5,6" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsMatrix( def.get(), params, context ), QVariantList() << 4 << 5 << 6 );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( 5, context ), QStringLiteral( "[5]" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariantList() << 1 << 2 << 3, context ), QStringLiteral( "[1,2,3]" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariantList() << ( QVariantList() << 1 << 2 << 3 ) << ( QVariantList() << 1 << 2 << 3 ), context ), QStringLiteral( "[1,2,3,1,2,3]" ) );
|
|
QCOMPARE( def->valueAsPythonString( "1,2,3", context ), QStringLiteral( "[1,2,3]" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=matrix" ) );
|
|
std::unique_ptr< QgsProcessingParameterMatrix > fromCode( dynamic_cast< QgsProcessingParameterMatrix * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QVERIFY( !fromCode->defaultValue().isValid() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterMatrix fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.headers(), def->headers() );
|
|
QCOMPARE( fromMap.numberRows(), def->numberRows() );
|
|
QCOMPARE( fromMap.hasFixedNumberRows(), def->hasFixedNumberRows() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterMatrix *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterMatrix *>( def.get() ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterMatrix( "optional", QString(), 3, false, QStringList(), QVariantList() << 4 << 5 << 6, true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1,2,3" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << 1 << 2 << 3 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional matrix" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterMatrix * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QVERIFY( !fromCode->defaultValue().isValid() );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsMatrix( def.get(), params, context ), QVariantList() << 4 << 5 << 6 );
|
|
def.reset( new QgsProcessingParameterMatrix( "optional", QString(), 3, false, QStringList(), QString( "1,2,3" ), true ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional matrix 1,2,3" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterMatrix * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsMatrix( def.get(), params, context ), QVariantList() << 1 << 2 << 3 );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterLayerList()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QString raster2 = testDataDir + "landsat.tif";
|
|
QFileInfo fi1( raster1 );
|
|
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
|
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon?crs=EPSG:3111", "V4", "memory" );
|
|
QgsVectorLayer *v2 = new QgsVectorLayer( "Polygon?crs=EPSG:3111", "V5", "memory" );
|
|
p.addMapLayers( QList<QgsMapLayer *>() << v1 << v2 << r1 );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterMultipleLayers > def( new QgsProcessingParameterMultipleLayers( "non_optional", QString(), QgsProcessing::TypeMapLayer, QString(), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( r1 ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( v1 ) ) );
|
|
|
|
// should be OK
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
|
|
// ... unless we use context, when the check that the layer actually exists is performed
|
|
QVERIFY( !def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QStringList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
|
|
|
|
// using existing map layer ID
|
|
QVariantMap params;
|
|
params.insert( "non_optional", v1->id() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 );
|
|
// using existing map layer
|
|
params.insert( "non_optional", QVariant::fromValue( v1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 );
|
|
|
|
// using two existing map layer ID
|
|
params.insert( "non_optional", QVariantList() << v1->id() << r1->id() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << r1 );
|
|
|
|
// using two existing map layers
|
|
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 );
|
|
QCOMPARE( layers.at( 0 ), v1 );
|
|
QCOMPARE( layers.at( 1 )->publicSource(), raster2 );
|
|
|
|
// empty string
|
|
params.insert( "non_optional", QString( "" ) );
|
|
QVERIFY( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ).isEmpty() );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a layer, and nothing you can do will make me one" ) );
|
|
QVERIFY( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ).isEmpty() );
|
|
|
|
// with 2 min inputs
|
|
def->setMinimumNumberInputs( 2 );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QStringList() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringList() << "layer12312312" << "layerB" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << "layer12312312" << "layerB" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QStringList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QStringList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
|
|
def->setMinimumNumberInputs( 3 );
|
|
QVERIFY( !def->checkValueIsAcceptable( QStringList() << "layer12312312" << "layerB" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "layer12312312" << "layerB" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( "layer12312312", context ), QStringLiteral( "'layer12312312'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( r1 ), context ), QStringLiteral( "['" ) + testDataDir + QStringLiteral( "tenbytenraster.asc']" ) );
|
|
QCOMPARE( def->valueAsPythonString( r1->id(), context ), QStringLiteral( "['" ) + testDataDir + QStringLiteral( "tenbytenraster.asc']" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringList() << r1->id() << raster2, context ), QStringLiteral( "['" ) + testDataDir + QStringLiteral( "tenbytenraster.asc','" ) + testDataDir + QStringLiteral( "landsat.tif']" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\\'complex\\' username=\\\"complex\\\"'" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=multiple vector" ) );
|
|
std::unique_ptr< QgsProcessingParameterMultipleLayers > fromCode( dynamic_cast< QgsProcessingParameterMultipleLayers * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QVERIFY( !fromCode->defaultValue().isValid() );
|
|
QCOMPARE( fromCode->layerType(), QgsProcessing::TypeVectorAnyGeometry );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterMultipleLayers fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.layerType(), def->layerType() );
|
|
QCOMPARE( fromMap.minimumNumberInputs(), def->minimumNumberInputs() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterMultipleLayers *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterMultipleLayers *>( def.get() ) );
|
|
|
|
// optional with one default layer
|
|
def.reset( new QgsProcessingParameterMultipleLayers( "optional", QString(), QgsProcessing::TypeMapLayer, v1->id(), true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
// should be OK
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
|
|
// ... unless we use context, when the check that the layer actually exists is performed
|
|
QVERIFY( !def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QStringList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 );
|
|
|
|
params.insert( "optional", QVariantList() << QVariant::fromValue( r1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << r1 );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional multiple vector " ) + v1->id() );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterMultipleLayers * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->layerType(), QgsProcessing::TypeVectorAnyGeometry );
|
|
|
|
// optional with two default layers
|
|
def.reset( new QgsProcessingParameterMultipleLayers( "optional", QString(), QgsProcessing::TypeMapLayer, QVariantList() << v1->id() << r1->publicSource(), true ) );
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << r1 );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional multiple vector " ) + v1->id() + "," + r1->publicSource() );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterMultipleLayers * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue().toString(), v1->id() + "," + r1->publicSource() );
|
|
QCOMPARE( fromCode->layerType(), QgsProcessing::TypeVectorAnyGeometry );
|
|
|
|
// optional with one default direct layer
|
|
def.reset( new QgsProcessingParameterMultipleLayers( "optional", QString(), QgsProcessing::TypeMapLayer, QVariant::fromValue( v1 ), true ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 );
|
|
|
|
// optional with two default direct layers
|
|
def.reset( new QgsProcessingParameterMultipleLayers( "optional", QString(), QgsProcessing::TypeMapLayer, QVariantList() << QVariant::fromValue( v1 ) << QVariant::fromValue( r1 ), true ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsLayerList( def.get(), params, context ), QList< QgsMapLayer *>() << v1 << r1 );
|
|
|
|
def.reset( new QgsProcessingParameterMultipleLayers( "type", QString(), QgsProcessing::TypeRaster ) );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##type=multiple raster" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterMultipleLayers * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "type" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QVERIFY( !fromCode->defaultValue().isValid() );
|
|
QCOMPARE( fromCode->layerType(), QgsProcessing::TypeRaster );
|
|
|
|
def.reset( new QgsProcessingParameterMultipleLayers( "type", QString(), QgsProcessing::TypeFile ) );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##type=multiple file" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterMultipleLayers * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "type" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QVERIFY( !fromCode->defaultValue().isValid() );
|
|
QCOMPARE( fromCode->layerType(), def->layerType() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterDistance()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterDistance > def( new QgsProcessingParameterDistance( "non_optional", QString(), 5, QStringLiteral( "parent" ), false ) );
|
|
QCOMPARE( def->parentParameterName(), QStringLiteral( "parent" ) );
|
|
def->setParentParameterName( QStringLiteral( "parent2" ) );
|
|
QCOMPARE( def->parentParameterName(), QStringLiteral( "parent2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1,2" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) ); // should be acceptable, falls back to default value
|
|
|
|
// string representing a number
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QString( "1.1" ) );
|
|
double number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 1.1, 0.001 );
|
|
|
|
// double
|
|
params.insert( "non_optional", 1.1 );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 1.1, 0.001 );
|
|
// int
|
|
params.insert( "non_optional", 1 );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 1, 0.001 );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a number, and nothing you can do will make me one" ) );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QCOMPARE( number, 5.0 );
|
|
|
|
// with min value
|
|
def->setMinimum( 11 );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 25 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "21.1" ) );
|
|
// with max value
|
|
def->setMaximum( 21 );
|
|
QVERIFY( !def->checkValueIsAcceptable( 35 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "31.1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 15 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "11.1" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( 5, context ), QStringLiteral( "5" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "1.1" ), context ), QStringLiteral( "1.1" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterDistance fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.minimum(), def->minimum() );
|
|
QCOMPARE( fromMap.maximum(), def->maximum() );
|
|
QCOMPARE( fromMap.dataType(), def->dataType() );
|
|
QCOMPARE( fromMap.parentParameterName(), QStringLiteral( "parent2" ) );
|
|
def.reset( dynamic_cast< QgsProcessingParameterDistance *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterDistance *>( def.get() ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterDistance( "optional", QString(), 5.4, QStringLiteral( "parent" ), true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 5.4, 0.001 );
|
|
// unconvertible string
|
|
params.insert( "optional", QVariant( "aaaa" ) );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 5.4, 0.001 );
|
|
|
|
// non-optional, invalid default
|
|
def.reset( new QgsProcessingParameterDistance( "non_optional", QString(), QVariant(), QStringLiteral( "parent" ), false ) );
|
|
QCOMPARE( def->parentParameterName(), QStringLiteral( "parent" ) );
|
|
def->setParentParameterName( QStringLiteral( "parent2" ) );
|
|
QCOMPARE( def->parentParameterName(), QStringLiteral( "parent2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1,2" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) ); // should NOT be acceptable, falls back to invalid default value
|
|
}
|
|
|
|
void TestQgsProcessing::parameterNumber()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterNumber > def( new QgsProcessingParameterNumber( "non_optional", QString(), QgsProcessingParameterNumber::Double, 5, false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1,2" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) ); // should be acceptable, falls back to default value
|
|
|
|
// string representing a number
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QString( "1.1" ) );
|
|
double number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 1.1, 0.001 );
|
|
int iNumber = QgsProcessingParameters::parameterAsInt( def.get(), params, context );
|
|
QCOMPARE( iNumber, 1 );
|
|
|
|
// double
|
|
params.insert( "non_optional", 1.1 );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 1.1, 0.001 );
|
|
iNumber = QgsProcessingParameters::parameterAsInt( def.get(), params, context );
|
|
QCOMPARE( iNumber, 1 );
|
|
|
|
// int
|
|
params.insert( "non_optional", 1 );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 1, 0.001 );
|
|
iNumber = QgsProcessingParameters::parameterAsInt( def.get(), params, context );
|
|
QCOMPARE( iNumber, 1 );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a number, and nothing you can do will make me one" ) );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QCOMPARE( number, 5.0 );
|
|
iNumber = QgsProcessingParameters::parameterAsInt( def.get(), params, context );
|
|
QCOMPARE( iNumber, 5 );
|
|
|
|
// with min value
|
|
def->setMinimum( 11 );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 25 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "21.1" ) );
|
|
// with max value
|
|
def->setMaximum( 21 );
|
|
QVERIFY( !def->checkValueIsAcceptable( 35 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "31.1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 15 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "11.1" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( 5, context ), QStringLiteral( "5" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "1.1" ), context ), QStringLiteral( "1.1" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=number 5" ) );
|
|
std::unique_ptr< QgsProcessingParameterNumber > fromCode( dynamic_cast< QgsProcessingParameterNumber * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterNumber fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.minimum(), def->minimum() );
|
|
QCOMPARE( fromMap.maximum(), def->maximum() );
|
|
QCOMPARE( fromMap.dataType(), def->dataType() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterNumber *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterNumber *>( def.get() ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterNumber( "optional", QString(), QgsProcessingParameterNumber::Double, 5.4, true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 5.4, 0.001 );
|
|
iNumber = QgsProcessingParameters::parameterAsInt( def.get(), params, context );
|
|
QCOMPARE( iNumber, 5 );
|
|
// unconvertible string
|
|
params.insert( "optional", QVariant( "aaaa" ) );
|
|
number = QgsProcessingParameters::parameterAsDouble( def.get(), params, context );
|
|
QGSCOMPARENEAR( number, 5.4, 0.001 );
|
|
iNumber = QgsProcessingParameters::parameterAsInt( def.get(), params, context );
|
|
QCOMPARE( iNumber, 5 );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code.left( 30 ), QStringLiteral( "##optional=optional number 5.4" ) ); // truncate code to 30, to avoid Qt 5.6 rounding issues
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterNumber * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterNumber * >( QgsProcessingParameters::parameterFromScriptCode( QStringLiteral( "##optional=optional number None" ) ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QVERIFY( !fromCode->defaultValue().isValid() );
|
|
|
|
// non-optional, invalid default
|
|
def.reset( new QgsProcessingParameterNumber( "non_optional", QString(), QgsProcessingParameterNumber::Double, QVariant(), false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1,2" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) ); // should NOT be acceptable, falls back to invalid default value
|
|
}
|
|
|
|
void TestQgsProcessing::parameterRange()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterRange > def( new QgsProcessingParameterRange( "non_optional", QString(), QgsProcessingParameterNumber::Double, QString( "5,6" ), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1.1,2,3" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1,a" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << 1.1 << 2 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << 1.1 << 2 << 3 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
// string representing a range of numbers
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QString( "1.1,1.2" ) );
|
|
QList< double > range = QgsProcessingParameters::parameterAsRange( def.get(), params, context );
|
|
QGSCOMPARENEAR( range.at( 0 ), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( range.at( 1 ), 1.2, 0.001 );
|
|
|
|
// list
|
|
params.insert( "non_optional", QVariantList() << 1.1 << 1.2 );
|
|
range = QgsProcessingParameters::parameterAsRange( def.get(), params, context );
|
|
QGSCOMPARENEAR( range.at( 0 ), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( range.at( 1 ), 1.2, 0.001 );
|
|
|
|
// too many elements:
|
|
params.insert( "non_optional", QString( "1.1,1.2,1.3" ) );
|
|
range = QgsProcessingParameters::parameterAsRange( def.get(), params, context );
|
|
QGSCOMPARENEAR( range.at( 0 ), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( range.at( 1 ), 1.2, 0.001 );
|
|
params.insert( "non_optional", QVariantList() << 1.1 << 1.2 << 1.3 );
|
|
range = QgsProcessingParameters::parameterAsRange( def.get(), params, context );
|
|
QGSCOMPARENEAR( range.at( 0 ), 1.1, 0.001 );
|
|
QGSCOMPARENEAR( range.at( 1 ), 1.2, 0.001 );
|
|
|
|
// not enough elements - don't care about the result, just don't crash!
|
|
params.insert( "non_optional", QString( "1.1" ) );
|
|
range = QgsProcessingParameters::parameterAsRange( def.get(), params, context );
|
|
params.insert( "non_optional", QVariantList() << 1.1 );
|
|
range = QgsProcessingParameters::parameterAsRange( def.get(), params, context );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( "1.1,2", context ), QStringLiteral( "[1.1,2]" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariantList() << 1.1 << 2, context ), QStringLiteral( "[1.1,2]" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=range 5,6" ) );
|
|
std::unique_ptr< QgsProcessingParameterRange > fromCode( dynamic_cast< QgsProcessingParameterRange * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterRange fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.dataType(), def->dataType() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterRange *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterRange *>( def.get() ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterRange( "optional", QString(), QgsProcessingParameterNumber::Double, QString( "5.4,7.4" ), true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1.1,2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << 1.1 << 2 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
range = QgsProcessingParameters::parameterAsRange( def.get(), params, context );
|
|
QGSCOMPARENEAR( range.at( 0 ), 5.4, 0.001 );
|
|
QGSCOMPARENEAR( range.at( 1 ), 7.4, 0.001 );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional range 5.4,7.4" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterRange * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterRasterLayer()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QString raster2 = testDataDir + "landsat.tif";
|
|
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 );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterRasterLayer > def( new QgsProcessingParameterRasterLayer( "non_optional", QString(), QVariant(), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( r1 ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant::fromValue( v1 ) ) );
|
|
|
|
// should be OK
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.tif" ) );
|
|
// ... unless we use context, when the check that the layer actually exists is performed
|
|
QVERIFY( !def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.tif", &context ) );
|
|
|
|
// using existing map layer ID
|
|
QVariantMap params;
|
|
params.insert( "non_optional", r1->id() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context )->id(), r1->id() );
|
|
|
|
// using existing map layer
|
|
params.insert( "non_optional", QVariant::fromValue( r1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context )->id(), r1->id() );
|
|
|
|
// not raster layer
|
|
params.insert( "non_optional", v1->id() );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context ) );
|
|
|
|
// using existing vector layer
|
|
params.insert( "non_optional", QVariant::fromValue( v1 ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context ) );
|
|
|
|
// string representing a project layer source
|
|
params.insert( "non_optional", raster1 );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context )->id(), r1->id() );
|
|
// string representing a non-project layer source
|
|
params.insert( "non_optional", raster2 );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context )->publicSource(), raster2 );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a layer, and nothing you can do will make me one" ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( raster1, context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( r1->id(), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( r1 ), context ), QString( "'" ) + testDataDir + QStringLiteral( "tenbytenraster.asc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=raster" ) );
|
|
std::unique_ptr< QgsProcessingParameterRasterLayer > fromCode( dynamic_cast< QgsProcessingParameterRasterLayer * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterRasterLayer( "optional", QString(), r1->id(), true ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context )->id(), r1->id() );
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.tif" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context )->id(), r1->id() );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional raster " ) + r1->id() );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterRasterLayer * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterRasterLayer fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterRasterLayer *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterRasterLayer *>( def.get() ) );
|
|
|
|
// optional with direct layer
|
|
def.reset( new QgsProcessingParameterRasterLayer( "optional", QString(), QVariant::fromValue( r1 ), true ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsRasterLayer( def.get(), params, context )->id(), r1->id() );
|
|
|
|
// invalidRasterError
|
|
params.clear();
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidRasterError( params, QStringLiteral( "MISSING" ) ), QStringLiteral( "Could not load source layer for MISSING: no value specified for parameter" ) );
|
|
params.insert( QStringLiteral( "INPUT" ), QStringLiteral( "my layer" ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidRasterError( params, QStringLiteral( "INPUT" ) ), QStringLiteral( "Could not load source layer for INPUT: my layer not found" ) );
|
|
params.insert( QStringLiteral( "INPUT" ), QgsProperty::fromValue( "my prop layer" ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidRasterError( params, QStringLiteral( "INPUT" ) ), QStringLiteral( "Could not load source layer for INPUT: my prop layer not found" ) );
|
|
params.insert( QStringLiteral( "INPUT" ), QVariant::fromValue( v1 ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidRasterError( params, QStringLiteral( "INPUT" ) ), QStringLiteral( "Could not load source layer for INPUT: invalid value" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterEnum()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterEnum > def( new QgsProcessingParameterEnum( "non_optional", QString(), QStringList() << "A" << "B" << "C", false, 2, false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1,2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 0 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << 1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "a" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 15 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( -1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) ); // should be acceptable, because falls back to default value
|
|
|
|
// string representing a number
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QString( "1" ) );
|
|
int iNumber = QgsProcessingParameters::parameterAsEnum( def.get(), params, context );
|
|
QCOMPARE( iNumber, 1 );
|
|
|
|
// double
|
|
params.insert( "non_optional", 2.2 );
|
|
iNumber = QgsProcessingParameters::parameterAsEnum( def.get(), params, context );
|
|
QCOMPARE( iNumber, 2 );
|
|
|
|
// int
|
|
params.insert( "non_optional", 1 );
|
|
iNumber = QgsProcessingParameters::parameterAsEnum( def.get(), params, context );
|
|
QCOMPARE( iNumber, 1 );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a number, and nothing you can do will make me one" ) );
|
|
iNumber = QgsProcessingParameters::parameterAsEnum( def.get(), params, context );
|
|
QCOMPARE( iNumber, 2 );
|
|
|
|
// out of range
|
|
params.insert( "non_optional", 4 );
|
|
iNumber = QgsProcessingParameters::parameterAsEnum( def.get(), params, context );
|
|
QCOMPARE( iNumber, 2 );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( 5, context ), QStringLiteral( "5" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "1.1" ), context ), QStringLiteral( "1" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=enum A;B;C 2" ) );
|
|
std::unique_ptr< QgsProcessingParameterEnum > fromCode( dynamic_cast< QgsProcessingParameterEnum * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->options(), def->options() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterEnum fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.options(), def->options() );
|
|
QCOMPARE( fromMap.allowMultiple(), def->allowMultiple() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterEnum *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterEnum *>( def.get() ) );
|
|
|
|
// multiple
|
|
def.reset( new QgsProcessingParameterEnum( "non_optional", QString(), QStringList() << "A" << "B" << "C", true, 5, false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1,2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 0 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() ) ); // since non-optional, empty list not allowed
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << 1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "a" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 15 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( -1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "non_optional", QString( "1,2" ) );
|
|
QList< int > iNumbers = QgsProcessingParameters::parameterAsEnums( def.get(), params, context );
|
|
QCOMPARE( iNumbers, QList<int>() << 1 << 2 );
|
|
params.insert( "non_optional", QVariantList() << 0 << 2 );
|
|
iNumbers = QgsProcessingParameters::parameterAsEnums( def.get(), params, context );
|
|
QCOMPARE( iNumbers, QList<int>() << 0 << 2 );
|
|
|
|
// empty list
|
|
params.insert( "non_optional", QVariantList() );
|
|
iNumbers = QgsProcessingParameters::parameterAsEnums( def.get(), params, context );
|
|
QCOMPARE( iNumbers, QList<int>() );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariantList() << 1 << 2, context ), QStringLiteral( "[1,2]" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "1,2" ), context ), QStringLiteral( "[1,2]" ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=enum multiple A;B;C 5" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterEnum * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->options(), def->options() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterEnum( "optional", QString(), QStringList() << "a" << "b", false, 5, true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1,2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 0 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << 1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "a" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 15 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( -1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional enum a;b 5" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterEnum * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->options(), def->options() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
iNumber = QgsProcessingParameters::parameterAsEnum( def.get(), params, context );
|
|
QCOMPARE( iNumber, 5 );
|
|
// unconvertible string
|
|
params.insert( "optional", QVariant( "aaaa" ) );
|
|
iNumber = QgsProcessingParameters::parameterAsEnum( def.get(), params, context );
|
|
QCOMPARE( iNumber, 5 );
|
|
//optional with multiples
|
|
def.reset( new QgsProcessingParameterEnum( "optional", QString(), QStringList() << "A" << "B" << "C", true, QVariantList() << 1 << 2, true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1,2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 0 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << 1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "a" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 15 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( -1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
iNumbers = QgsProcessingParameters::parameterAsEnums( def.get(), params, context );
|
|
QCOMPARE( iNumbers, QList<int>() << 1 << 2 );
|
|
def.reset( new QgsProcessingParameterEnum( "optional", QString(), QStringList() << "A" << "B" << "C", true, "1,2", true ) );
|
|
params.insert( "optional", QVariant() );
|
|
iNumbers = QgsProcessingParameters::parameterAsEnums( def.get(), params, context );
|
|
QCOMPARE( iNumbers, QList<int>() << 1 << 2 );
|
|
// empty list
|
|
params.insert( "optional", QVariantList() );
|
|
iNumbers = QgsProcessingParameters::parameterAsEnums( def.get(), params, context );
|
|
QCOMPARE( iNumbers, QList<int>() );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional enum multiple A;B;C 1,2" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterEnum * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->options(), def->options() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
// non optional, no default
|
|
def.reset( new QgsProcessingParameterEnum( "non_optional", QString(), QStringList() << "A" << "B" << "C", false, QVariant(), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "1,2" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 0 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << 1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "a" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 15 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( -1 ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) ); // should NOT be acceptable, because falls back to invalid default value
|
|
}
|
|
|
|
void TestQgsProcessing::parameterString()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterString > def( new QgsProcessingParameterString( "non_optional", QString(), QString(), false, false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
// string
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QString( "abcdef" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QString( "abcdef" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( 5, context ), QStringLiteral( "'5'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc\ndef" ), context ), QStringLiteral( "'abc\\ndef'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\'complex\' username=\"complex\"'" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=string" ) );
|
|
std::unique_ptr< QgsProcessingParameterString > fromCode( dynamic_cast< QgsProcessingParameterString * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->multiLine(), def->multiLine() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterString fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.multiLine(), def->multiLine() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterString *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterString *>( def.get() ) );
|
|
|
|
def->setMultiLine( true );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=string long" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterString * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->multiLine(), def->multiLine() );
|
|
def->setMultiLine( false );
|
|
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterString * >( QgsProcessingParameters::parameterFromScriptCode( QStringLiteral( "##non_optional=string None" ) ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QVERIFY( !fromCode->defaultValue().isValid() );
|
|
QCOMPARE( fromCode->multiLine(), def->multiLine() );
|
|
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterString * >( QgsProcessingParameters::parameterFromScriptCode( QStringLiteral( "##non_optional=string it's mario" ) ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue().toString(), QStringLiteral( "it's mario" ) );
|
|
QCOMPARE( fromCode->multiLine(), def->multiLine() );
|
|
|
|
def->setDefaultValue( QStringLiteral( "it's mario" ) );
|
|
code = def->asScriptCode();
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterString * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->multiLine(), def->multiLine() );
|
|
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterString * >( QgsProcessingParameters::parameterFromScriptCode( QStringLiteral( "##non_optional=string 'my val'" ) ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue().toString(), QStringLiteral( "my val" ) );
|
|
QCOMPARE( fromCode->multiLine(), def->multiLine() );
|
|
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterString * >( QgsProcessingParameters::parameterFromScriptCode( QStringLiteral( "##non_optional=string \"my val\"" ) ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue().toString(), QStringLiteral( "my val" ) );
|
|
QCOMPARE( fromCode->multiLine(), def->multiLine() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterString( "optional", QString(), QString( "default" ), false, true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QString( "default" ) );
|
|
params.insert( "optional", QString() ); //empty string should not result in default value
|
|
QCOMPARE( QgsProcessingParameters::parameterAsString( def.get(), params, context ), QString() );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional string default" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterString * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->multiLine(), def->multiLine() );
|
|
|
|
def->setMultiLine( true );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional string long default" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterString * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->multiLine(), def->multiLine() );
|
|
|
|
// not optional, valid default!
|
|
def.reset( new QgsProcessingParameterString( "non_optional", QString(), QString( "def" ), false, false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) ); // should be valid, falls back to valid default
|
|
}
|
|
|
|
void TestQgsProcessing::parameterExpression()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterExpression > def( new QgsProcessingParameterExpression( "non_optional", QString(), QString( "1+1" ), QString(), false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) ); // should be acceptable, because it will fallback to default value
|
|
|
|
// string
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QString( "abcdef" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExpression( def.get(), params, context ), QString( "abcdef" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( 5, context ), QStringLiteral( "'5'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc\ndef" ), context ), QStringLiteral( "'abc\\ndef'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=expression 1+1" ) );
|
|
std::unique_ptr< QgsProcessingParameterExpression > fromCode( dynamic_cast< QgsProcessingParameterExpression * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterExpression fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.parentLayerParameterName(), def->parentLayerParameterName() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterExpression *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterExpression *>( def.get() ) );
|
|
|
|
QVERIFY( def->dependsOnOtherParameters().isEmpty() );
|
|
def->setParentLayerParameterName( QStringLiteral( "test_layer" ) );
|
|
QCOMPARE( def->dependsOnOtherParameters(), QStringList() << QStringLiteral( "test_layer" ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterExpression( "optional", QString(), QString( "default" ), QString(), true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExpression( def.get(), params, context ), QString( "default" ) );
|
|
// valid expression, should not fallback
|
|
params.insert( "optional", QVariant( "1+2" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExpression( def.get(), params, context ), QString( "1+2" ) );
|
|
// invalid expression, should fallback
|
|
params.insert( "optional", QVariant( "1+" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsExpression( def.get(), params, context ), QString( "default" ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional expression default" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterExpression * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
// non optional, no default
|
|
def.reset( new QgsProcessingParameterExpression( "non_optional", QString(), QString(), QString(), false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) ); // should NOT be acceptable, because it will fallback to invalid default value
|
|
|
|
}
|
|
|
|
void TestQgsProcessing::parameterField()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterField > def( new QgsProcessingParameterField( "non_optional", QString(), QVariant(), QString(), QgsProcessingParameterField::Any, false, false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QStringList() << "a" << "b" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "a" << "b" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
// string
|
|
QVariantMap params;
|
|
params.insert( "non_optional", QString( "a" ) );
|
|
QStringList fields = QgsProcessingParameters::parameterAsFields( def.get(), params, context );
|
|
QCOMPARE( fields, QStringList() << "a" );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "probably\'invalid\"field", context ), QStringLiteral( "'probably\\'invalid\\\"field'" ) );
|
|
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=field" ) );
|
|
std::unique_ptr< QgsProcessingParameterField > fromCode( dynamic_cast< QgsProcessingParameterField * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
QVERIFY( def->dependsOnOtherParameters().isEmpty() );
|
|
def->setParentLayerParameterName( "my_parent" );
|
|
QCOMPARE( def->dependsOnOtherParameters(), QStringList() << QStringLiteral( "my_parent" ) );
|
|
|
|
code = def->asScriptCode();
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterField * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
def->setDataType( QgsProcessingParameterField::Numeric );
|
|
code = def->asScriptCode();
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterField * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
def->setDataType( QgsProcessingParameterField::String );
|
|
code = def->asScriptCode();
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterField * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
def->setDataType( QgsProcessingParameterField::DateTime );
|
|
code = def->asScriptCode();
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterField * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
// multiple
|
|
def.reset( new QgsProcessingParameterField( "non_optional", QString(), QVariant(), QString(), QgsProcessingParameterField::Any, true, false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringList() << "a" << "b" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << "a" << "b" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QStringList() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() ) );
|
|
|
|
params.insert( "non_optional", QString( "a;b" ) );
|
|
fields = QgsProcessingParameters::parameterAsFields( def.get(), params, context );
|
|
QCOMPARE( fields, QStringList() << "a" << "b" );
|
|
params.insert( "non_optional", QVariantList() << "a" << "b" );
|
|
fields = QgsProcessingParameters::parameterAsFields( def.get(), params, context );
|
|
QCOMPARE( fields, QStringList() << "a" << "b" );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringList() << "a" << "b", context ), QStringLiteral( "['a','b']" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringList() << "a" << "b", context ), QStringLiteral( "['a','b']" ) );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterField fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.parentLayerParameterName(), def->parentLayerParameterName() );
|
|
QCOMPARE( fromMap.dataType(), def->dataType() );
|
|
QCOMPARE( fromMap.allowMultiple(), def->allowMultiple() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterField *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterField *>( def.get() ) );
|
|
|
|
code = def->asScriptCode();
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterField * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterField( "optional", QString(), QString( "def" ), QString(), QgsProcessingParameterField::Any, false, true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QStringList() << "a" << "b" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariantList() << "a" << "b" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
fields = QgsProcessingParameters::parameterAsFields( def.get(), params, context );
|
|
QCOMPARE( fields, QStringList() << "def" );
|
|
|
|
// optional, no default
|
|
def.reset( new QgsProcessingParameterField( "optional", QString(), QVariant(), QString(), QgsProcessingParameterField::Any, false, true ) );
|
|
params.insert( "optional", QVariant() );
|
|
fields = QgsProcessingParameters::parameterAsFields( def.get(), params, context );
|
|
QVERIFY( fields.isEmpty() );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional field" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterField * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
QCOMPARE( fromCode->allowMultiple(), def->allowMultiple() );
|
|
|
|
//optional with multiples
|
|
def.reset( new QgsProcessingParameterField( "optional", QString(), QString( "abc;def" ), QString(), QgsProcessingParameterField::Any, true, true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "test" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringList() << "a" << "b" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariantList() << "a" << "b" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
fields = QgsProcessingParameters::parameterAsFields( def.get(), params, context );
|
|
QCOMPARE( fields, QStringList() << "abc" << "def" );
|
|
def.reset( new QgsProcessingParameterField( "optional", QString(), QVariantList() << "abc" << "def", QString(), QgsProcessingParameterField::Any, true, true ) );
|
|
params.insert( "optional", QVariant() );
|
|
fields = QgsProcessingParameters::parameterAsFields( def.get(), params, context );
|
|
QCOMPARE( fields, QStringList() << "abc" << "def" );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterVectorLayer()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString vector1 = testDataDir + "multipoint.shp";
|
|
QString raster = testDataDir + "landsat.tif";
|
|
QFileInfo fi1( raster );
|
|
QFileInfo fi2( vector1 );
|
|
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
|
QgsVectorLayer *v1 = new QgsVectorLayer( fi2.filePath(), "V4", "ogr" );
|
|
p.addMapLayers( QList<QgsMapLayer *>() << v1 << r1 );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterVectorLayer > def( new QgsProcessingParameterVectorLayer( "non_optional", QString(), QList< int >(), QString( "somelayer" ), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProcessingFeatureSourceDefinition( "layer1231123" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( v1 ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant::fromValue( r1 ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( QStringLiteral( "layer12312312" ) ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProperty::fromValue( QString() ) ) );
|
|
|
|
// should be OK
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
// ... unless we use context, when the check that the layer actually exists is performed
|
|
QVERIFY( !def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
|
|
// using existing map layer ID
|
|
QVariantMap params;
|
|
params.insert( "non_optional", v1->id() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->id(), v1->id() );
|
|
|
|
// using existing layer
|
|
params.insert( "non_optional", QVariant::fromValue( v1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->id(), v1->id() );
|
|
|
|
// not vector layer
|
|
params.insert( "non_optional", r1->id() );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context ) );
|
|
|
|
// using existing non-vector layer
|
|
params.insert( "non_optional", QVariant::fromValue( r1 ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context ) );
|
|
|
|
// string representing a layer source
|
|
params.insert( "non_optional", vector1 );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->publicSource(), vector1 );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a layer, and nothing you can do will make me one" ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( vector1, context ), QString( "'" ) + testDataDir + QStringLiteral( "multipoint.shp'" ) );
|
|
QCOMPARE( def->valueAsPythonString( v1->id(), context ), QString( "'" ) + testDataDir + QStringLiteral( "multipoint.shp'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( v1 ), context ), QString( "'" ) + testDataDir + QStringLiteral( "multipoint.shp'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=vector somelayer" ) );
|
|
std::unique_ptr< QgsProcessingParameterVectorLayer > fromCode( dynamic_cast< QgsProcessingParameterVectorLayer * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterVectorLayer fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterVectorLayer *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterVectorLayer *>( def.get() ) );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterVectorLayer( "optional", QString(), QList< int >(), v1->id(), true ) );
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->id(), v1->id() );
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingFeatureSourceDefinition( "layer1231123" ) ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional vector " ) + v1->id() );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterVectorLayer * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
//optional with direct layer default
|
|
def.reset( new QgsProcessingParameterVectorLayer( "optional", QString(), QList< int >(), QVariant::fromValue( v1 ), true ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->id(), v1->id() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterFeatureSource()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString vector1 = testDataDir + "multipoint.shp";
|
|
QString vector2 = testDataDir + "lines.shp";
|
|
QString raster = testDataDir + "landsat.tif";
|
|
QFileInfo fi1( raster );
|
|
QgsRasterLayer *r1 = new QgsRasterLayer( fi1.filePath(), "R1" );
|
|
QgsVectorLayer *v1 = new QgsVectorLayer( "Polygon?crs=EPSG:3111", "V4", "memory" );
|
|
QgsVectorLayer *v2 = new QgsVectorLayer( vector2, "V5", "ogr" );
|
|
p.addMapLayers( QList<QgsMapLayer *>() << v1 << r1 << v2 );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterFeatureSource > def( new QgsProcessingParameterFeatureSource( "non_optional", QString(), QList< int >() << QgsProcessing::TypeVectorAnyGeometry, QString(), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingFeatureSourceDefinition( "layer1231123" ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProcessingFeatureSourceDefinition( "" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant::fromValue( v1 ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant::fromValue( r1 ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( QStringLiteral( "layer12312312" ) ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProperty::fromValue( QString() ) ) );
|
|
|
|
// should be OK
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
// ... unless we use context, when the check that the layer actually exists is performed
|
|
QVERIFY( !def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
|
|
// using existing map layer ID
|
|
QVariantMap params;
|
|
params.insert( "non_optional", v1->id() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->id(), v1->id() );
|
|
|
|
// using existing layer
|
|
params.insert( "non_optional", QVariant::fromValue( v1 ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->id(), v1->id() );
|
|
|
|
// not vector layer
|
|
params.insert( "non_optional", r1->id() );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context ) );
|
|
|
|
// using existing non-vector layer
|
|
params.insert( "non_optional", QVariant::fromValue( r1 ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context ) );
|
|
|
|
// string representing a layer source
|
|
params.insert( "non_optional", vector1 );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->publicSource(), vector1 );
|
|
|
|
// nonsense string
|
|
params.insert( "non_optional", QString( "i'm not a layer, and nothing you can do will make me one" ) );
|
|
QVERIFY( !QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingFeatureSourceDefinition( "abc" ) ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingFeatureSourceDefinition( v2->id() ) ), context ), QStringLiteral( "'%1'" ).arg( vector2 ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingFeatureSourceDefinition( QgsProperty::fromValue( "abc" ), true ) ), context ), QStringLiteral( "QgsProcessingFeatureSourceDefinition('abc', True)" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingFeatureSourceDefinition( QgsProperty::fromExpression( "\"abc\" || \"def\"" ) ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"abc\" || \"def\"')" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( v2 ), context ), QStringLiteral( "'%1'" ).arg( vector2 ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\'complex\' username=\"complex\"'" ) );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterFeatureSource fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.dataTypes(), def->dataTypes() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterFeatureSource *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterFeatureSource *>( def.get() ) );
|
|
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=source" ) );
|
|
std::unique_ptr< QgsProcessingParameterFeatureSource > fromCode( dynamic_cast< QgsProcessingParameterFeatureSource * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
def->setDataTypes( QList< int >() << QgsProcessing::TypeVectorPoint );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=source point" ) );
|
|
def->setDataTypes( QList< int >() << QgsProcessing::TypeVectorLine );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=source line" ) );
|
|
def->setDataTypes( QList< int >() << QgsProcessing::TypeVectorPolygon );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=source polygon" ) );
|
|
def->setDataTypes( QList< int >() << QgsProcessing::TypeVectorPoint << QgsProcessing::TypeVectorLine );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=source point line" ) );
|
|
def->setDataTypes( QList< int >() << QgsProcessing::TypeVectorPoint << QgsProcessing::TypeVectorPolygon );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=source point polygon" ) );
|
|
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterFeatureSource( "optional", QString(), QList< int >() << QgsProcessing::TypeVectorAnyGeometry, v1->id(), true ) );
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->id(), v1->id() );
|
|
QVERIFY( def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingFeatureSourceDefinition( "layer1231123" ) ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional source " ) + v1->id() );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFeatureSource * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
|
|
//optional with direct layer default
|
|
def.reset( new QgsProcessingParameterFeatureSource( "optional", QString(), QList< int >() << QgsProcessing::TypeVectorAnyGeometry, QVariant::fromValue( v1 ), true ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsVectorLayer( def.get(), params, context )->id(), v1->id() );
|
|
|
|
// invalidSourceError
|
|
params.clear();
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSourceError( params, QStringLiteral( "MISSING" ) ), QStringLiteral( "Could not load source layer for MISSING: no value specified for parameter" ) );
|
|
params.insert( QStringLiteral( "INPUT" ), QStringLiteral( "my layer" ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSourceError( params, QStringLiteral( "INPUT" ) ), QStringLiteral( "Could not load source layer for INPUT: my layer not found" ) );
|
|
params.insert( QStringLiteral( "INPUT" ), QgsProperty::fromValue( "my prop layer" ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSourceError( params, QStringLiteral( "INPUT" ) ), QStringLiteral( "Could not load source layer for INPUT: my prop layer not found" ) );
|
|
params.insert( QStringLiteral( "INPUT" ), QgsProcessingFeatureSourceDefinition( QStringLiteral( "my prop layer" ) ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSourceError( params, QStringLiteral( "INPUT" ) ), QStringLiteral( "Could not load source layer for INPUT: my prop layer not found" ) );
|
|
params.insert( QStringLiteral( "INPUT" ), QVariant::fromValue( v1 ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSourceError( params, QStringLiteral( "INPUT" ) ), QStringLiteral( "Could not load source layer for INPUT: invalid value" ) );
|
|
|
|
}
|
|
|
|
void TestQgsProcessing::parameterFeatureSink()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterFeatureSink > def( new QgsProcessingParameterFeatureSink( "non_optional", QString(), QgsProcessing::TypeVectorAnyGeometry, QString(), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( QStringLiteral( "layer12312312" ) ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProperty::fromValue( QString() ) ) );
|
|
|
|
// should be OK with or without context - it's an output layer!
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( "abc" ) ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( QgsProperty::fromValue( "abc" ) ) ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( QgsProperty::fromExpression( "\"abc\" || \"def\"" ) ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"abc\" || \"def\"')" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\'complex\' username=\"complex\"'" ) );
|
|
|
|
QCOMPARE( def->defaultFileExtension(), QStringLiteral( "shp" ) );
|
|
QCOMPARE( def->generateTemporaryDestination(), QStringLiteral( "memory:" ) );
|
|
def->setSupportsNonFileBasedOutput( false );
|
|
QVERIFY( def->generateTemporaryDestination().endsWith( QStringLiteral( ".shp" ) ) );
|
|
QVERIFY( def->generateTemporaryDestination().startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterFeatureSink fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.dataType(), def->dataType() );
|
|
QCOMPARE( fromMap.supportsNonFileBasedOutput(), def->supportsNonFileBasedOutput() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterFeatureSink *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterFeatureSink *>( def.get() ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=sink" ) );
|
|
std::unique_ptr< QgsProcessingParameterFeatureSink > fromCode( dynamic_cast< QgsProcessingParameterFeatureSink * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
|
|
def->setDataType( QgsProcessing::TypeVectorPoint );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=sink point" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFeatureSink * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
def->setDataType( QgsProcessing::TypeVectorLine );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=sink line" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFeatureSink * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
def->setDataType( QgsProcessing::TypeVectorPolygon );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=sink polygon" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFeatureSink * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
def->setDataType( QgsProcessing::TypeVector );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=sink table" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFeatureSink * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterFeatureSink( "optional", QString(), QgsProcessing::TypeVectorAnyGeometry, QString(), true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
|
|
def->setCreateByDefault( false );
|
|
QVERIFY( !def->createByDefault() );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional sink" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFeatureSink * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
QVERIFY( !def->createByDefault() );
|
|
|
|
// test hasGeometry
|
|
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessing::TypeMapLayer ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessing::TypeVectorAnyGeometry ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessing::TypeVectorPoint ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessing::TypeVectorLine ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessing::TypeVectorPolygon ).hasGeometry() );
|
|
QVERIFY( !QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessing::TypeRaster ).hasGeometry() );
|
|
QVERIFY( !QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessing::TypeFile ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterFeatureSink( "test", QString(), QgsProcessing::TypeVector ).hasGeometry() );
|
|
|
|
// invalidSinkError
|
|
QVariantMap params;
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSinkError( params, QStringLiteral( "MISSING" ) ), QStringLiteral( "Could not create destination layer for MISSING: no value specified for parameter" ) );
|
|
params.insert( QStringLiteral( "OUTPUT" ), QStringLiteral( "d:/test.shp" ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSinkError( params, QStringLiteral( "OUTPUT" ) ), QStringLiteral( "Could not create destination layer for OUTPUT: d:/test.shp" ) );
|
|
params.insert( QStringLiteral( "OUTPUT" ), QgsProperty::fromValue( QStringLiteral( "d:/test2.shp" ) ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSinkError( params, QStringLiteral( "OUTPUT" ) ), QStringLiteral( "Could not create destination layer for OUTPUT: d:/test2.shp" ) );
|
|
params.insert( QStringLiteral( "OUTPUT" ), QgsProcessingOutputLayerDefinition( QStringLiteral( "d:/test3.shp" ) ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSinkError( params, QStringLiteral( "OUTPUT" ) ), QStringLiteral( "Could not create destination layer for OUTPUT: d:/test3.shp" ) );
|
|
params.insert( QStringLiteral( "OUTPUT" ), QgsProcessingFeatureSourceDefinition( QStringLiteral( "source" ) ) );
|
|
QCOMPARE( QgsProcessingAlgorithm::invalidSinkError( params, QStringLiteral( "OUTPUT" ) ), QStringLiteral( "Could not create destination layer for OUTPUT: invalid value" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterVectorOut()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterVectorDestination > def( new QgsProcessingParameterVectorDestination( "non_optional", QString(), QgsProcessing::TypeVectorAnyGeometry, QString(), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( QStringLiteral( "layer1231123" ) ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProperty::fromValue( QString() ) ) );
|
|
|
|
// should be OK with or without context - it's an output layer!
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp", &context ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( "abc" ) ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( QgsProperty::fromValue( "abc" ) ) ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( QgsProperty::fromExpression( "\"abc\" || \"def\"" ) ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"abc\" || \"def\"')" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\'complex\' username=\"complex\"'" ) );
|
|
|
|
QCOMPARE( def->defaultFileExtension(), QStringLiteral( "shp" ) );
|
|
QVERIFY( def->generateTemporaryDestination().endsWith( QStringLiteral( ".shp" ) ) );
|
|
QVERIFY( def->generateTemporaryDestination().startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterVectorDestination fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.dataType(), def->dataType() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterVectorDestination *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterVectorDestination *>( def.get() ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=vectorDestination" ) );
|
|
std::unique_ptr< QgsProcessingParameterVectorDestination > fromCode( dynamic_cast< QgsProcessingParameterVectorDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
|
|
def->setDataType( QgsProcessing::TypeVectorPoint );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=vectorDestination point" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterVectorDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
def->setDataType( QgsProcessing::TypeVectorLine );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=vectorDestination line" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterVectorDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
def->setDataType( QgsProcessing::TypeVectorPolygon );
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=vectorDestination polygon" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterVectorDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterVectorDestination( "optional", QString(), QgsProcessing::TypeVectorAnyGeometry, QString(), true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.shp" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional vectorDestination" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterVectorDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->dataType(), def->dataType() );
|
|
|
|
// test hasGeometry
|
|
QVERIFY( QgsProcessingParameterVectorDestination( "test", QString(), QgsProcessing::TypeMapLayer ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterVectorDestination( "test", QString(), QgsProcessing::TypeVectorAnyGeometry ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterVectorDestination( "test", QString(), QgsProcessing::TypeVectorPoint ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterVectorDestination( "test", QString(), QgsProcessing::TypeVectorLine ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterVectorDestination( "test", QString(), QgsProcessing::TypeVectorPolygon ).hasGeometry() );
|
|
QVERIFY( !QgsProcessingParameterVectorDestination( "test", QString(), QgsProcessing::TypeRaster ).hasGeometry() );
|
|
QVERIFY( !QgsProcessingParameterVectorDestination( "test", QString(), QgsProcessing::TypeFile ).hasGeometry() );
|
|
QVERIFY( QgsProcessingParameterVectorDestination( "test", QString(), QgsProcessing::TypeVector ).hasGeometry() );
|
|
|
|
}
|
|
|
|
void TestQgsProcessing::parameterRasterOut()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterRasterDestination > def( new QgsProcessingParameterRasterDestination( "non_optional", QString(), QVariant(), false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( QStringLiteral( "layer12312312" ) ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProperty::fromValue( QString() ) ) );
|
|
|
|
// should be OK with or without context - it's an output layer!
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.tif" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.tif", &context ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->defaultFileExtension(), QStringLiteral( "tif" ) );
|
|
QVERIFY( def->generateTemporaryDestination().endsWith( QStringLiteral( ".tif" ) ) );
|
|
QVERIFY( def->generateTemporaryDestination().startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
|
|
QVariantMap params;
|
|
params.insert( "non_optional", "test.tif" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsOutputLayer( def.get(), params, context ), QStringLiteral( "test.tif" ) );
|
|
params.insert( "non_optional", QgsProcessingOutputLayerDefinition( "test.tif" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsOutputLayer( def.get(), params, context ), QStringLiteral( "test.tif" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( "abc" ) ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( QgsProperty::fromValue( "abc" ) ) ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( QgsProperty::fromExpression( "\"abc\" || \"def\"" ) ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"abc\" || \"def\"')" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\'complex\' username=\"complex\"'" ) );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterRasterDestination fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.supportsNonFileBasedOutput(), def->supportsNonFileBasedOutput() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterRasterDestination *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterRasterDestination *>( def.get() ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=rasterDestination" ) );
|
|
std::unique_ptr< QgsProcessingParameterRasterDestination > fromCode( dynamic_cast< QgsProcessingParameterRasterDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterRasterDestination( "optional", QString(), QString( "default.tif" ), true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.tif" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsOutputLayer( def.get(), params, context ), QStringLiteral( "default.tif" ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional rasterDestination default.tif" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterRasterDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
// test layers to load on completion
|
|
def.reset( new QgsProcessingParameterRasterDestination( "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::parameterAsOutputLayer( 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::parameterAsOutputLayer( 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" ) );
|
|
QCOMPARE( context2.layersToLoadOnCompletion().values().at( 0 ).outputName, QStringLiteral( "x" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterFileOut()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
p.setCrs( QgsCoordinateReferenceSystem::fromEpsgId( 28353 ) );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterFileDestination > def( new QgsProcessingParameterFileDestination( "non_optional", QString(), QStringLiteral( "BMP files (*.bmp)" ), QVariant(), false ) );
|
|
QCOMPARE( def->fileFilter(), QStringLiteral( "BMP files (*.bmp)" ) );
|
|
QCOMPARE( def->defaultFileExtension(), QStringLiteral( "bmp" ) );
|
|
QVERIFY( def->generateTemporaryDestination().endsWith( QStringLiteral( ".bmp" ) ) );
|
|
QVERIFY( def->generateTemporaryDestination().startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
def->setFileFilter( QStringLiteral( "PCX files (*.pcx)" ) );
|
|
QCOMPARE( def->fileFilter(), QStringLiteral( "PCX files (*.pcx)" ) );
|
|
QCOMPARE( def->defaultFileExtension(), QStringLiteral( "pcx" ) );
|
|
def->setFileFilter( QStringLiteral( "PCX files (*.pcx *.picx)" ) );
|
|
QCOMPARE( def->defaultFileExtension(), QStringLiteral( "pcx" ) );
|
|
def->setFileFilter( QStringLiteral( "PCX files (*.pcx *.picx);;BMP files (*.bmp)" ) );
|
|
QCOMPARE( def->defaultFileExtension(), QStringLiteral( "pcx" ) );
|
|
def->setFileFilter( QString() );
|
|
QCOMPARE( def->defaultFileExtension(), QStringLiteral( "file" ) );
|
|
QVERIFY( def->generateTemporaryDestination().endsWith( QStringLiteral( ".file" ) ) );
|
|
QVERIFY( def->generateTemporaryDestination().startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( QStringLiteral( "layer12312312" ) ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProperty::fromValue( QString() ) ) );
|
|
|
|
// should be OK with or without context - it's an output file!
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.txt" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.txt", &context ) );
|
|
|
|
QVariantMap params;
|
|
params.insert( "non_optional", "test.txt" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "test.txt" ) );
|
|
params.insert( "non_optional", QgsProcessingOutputLayerDefinition( "test.txt" ) );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "test.txt" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( "abc" ) ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( QgsProperty::fromValue( "abc" ) ) ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProcessingOutputLayerDefinition( QgsProperty::fromExpression( "\"abc\" || \"def\"" ) ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"abc\" || \"def\"')" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\'complex\' username=\"complex\"'" ) );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterFileDestination fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.fileFilter(), def->fileFilter() );
|
|
QCOMPARE( fromMap.supportsNonFileBasedOutput(), def->supportsNonFileBasedOutput() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterFileDestination *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterFileDestination *>( def.get() ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=fileDestination" ) );
|
|
std::unique_ptr< QgsProcessingParameterFileDestination > fromCode( dynamic_cast< QgsProcessingParameterFileDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterFileDestination( "optional", QString(), QString(), QString( "default.txt" ), true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/roads_clipped_transformed_v1_reprojected_final_clipped_aAAA.txt" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "layer1231123" ) ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "default.txt" ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional fileDestination default.txt" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFileDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
// outputs definitio test
|
|
def.reset( new QgsProcessingParameterFileDestination( "html", QString(), QString( "HTML files" ), QString(), false ) );
|
|
std::unique_ptr< QgsProcessingOutputDefinition > outputDef( def->toOutputDefinition() );
|
|
QVERIFY( dynamic_cast< QgsProcessingOutputHtml *>( outputDef.get() ) );
|
|
def.reset( new QgsProcessingParameterFileDestination( "html", QString(), QString( "Text files (*.htm)" ), QString(), false ) );
|
|
outputDef.reset( def->toOutputDefinition() );
|
|
QVERIFY( dynamic_cast< QgsProcessingOutputHtml *>( outputDef.get() ) );
|
|
def.reset( new QgsProcessingParameterFileDestination( "file", QString(), QString( "Text files (*.txt)" ), QString(), false ) );
|
|
outputDef.reset( def->toOutputDefinition() );
|
|
QVERIFY( dynamic_cast< QgsProcessingOutputFile *>( outputDef.get() ) );
|
|
def.reset( new QgsProcessingParameterFileDestination( "file", QString(), QString(), QString(), false ) );
|
|
outputDef.reset( def->toOutputDefinition() );
|
|
QVERIFY( dynamic_cast< QgsProcessingOutputFile *>( outputDef.get() ) );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterFolderOut()
|
|
{
|
|
// setup a context
|
|
QgsProject p;
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterFolderDestination > def( new QgsProcessingParameterFolderDestination( "non_optional", QString(), QVariant(), false ) );
|
|
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "asdasd" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( QStringLiteral( "asdasdas" ) ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QgsProperty::fromValue( QString() ) ) );
|
|
|
|
// should be OK with or without context - it's an output folder!
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/", &context ) );
|
|
|
|
// check that temporary destination does not have dot at the end when there is no extension
|
|
QVERIFY( !def->generateTemporaryDestination().endsWith( QStringLiteral( "." ) ) );
|
|
QVERIFY( def->generateTemporaryDestination().startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
|
|
QVariantMap params;
|
|
params.insert( "non_optional", "c:/mine" );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "c:/mine" ) );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) );
|
|
QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) );
|
|
QCOMPARE( def->valueAsPythonString( "uri='complex' username=\"complex\"", context ), QStringLiteral( "'uri=\\'complex\\' username=\\\"complex\\\"'" ) );
|
|
|
|
QVariantMap map = def->toVariantMap();
|
|
QgsProcessingParameterFolderDestination fromMap( "x" );
|
|
QVERIFY( fromMap.fromVariantMap( map ) );
|
|
QCOMPARE( fromMap.name(), def->name() );
|
|
QCOMPARE( fromMap.description(), def->description() );
|
|
QCOMPARE( fromMap.flags(), def->flags() );
|
|
QCOMPARE( fromMap.defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromMap.supportsNonFileBasedOutput(), def->supportsNonFileBasedOutput() );
|
|
def.reset( dynamic_cast< QgsProcessingParameterFolderDestination *>( QgsProcessingParameters::parameterFromVariantMap( map ) ) );
|
|
QVERIFY( dynamic_cast< QgsProcessingParameterFolderDestination *>( def.get() ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=folderDestination" ) );
|
|
std::unique_ptr< QgsProcessingParameterFolderDestination > fromCode( dynamic_cast< QgsProcessingParameterFolderDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterFolderDestination( "optional", QString(), QString( "c:/junk" ), true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( false ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( true ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "layer12312312" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "c:/Users/admin/Desktop/" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "c:/junk" ) );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional folderDestination c:/junk" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterFolderDestination * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterBand()
|
|
{
|
|
QgsProcessingContext context;
|
|
|
|
// not optional!
|
|
std::unique_ptr< QgsProcessingParameterBand > def( new QgsProcessingParameterBand( "non_optional", QString(), QVariant(), QString(), false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
// string representing a band
|
|
QVariantMap params;
|
|
params.insert( "non_optional", "1" );
|
|
int band = QgsProcessingParameters::parameterAsInt( def.get(), params, context );
|
|
QCOMPARE( band, 1 );
|
|
|
|
QCOMPARE( def->valueAsPythonString( QVariant(), context ), QStringLiteral( "None" ) );
|
|
QCOMPARE( def->valueAsPythonString( 5, context ), QStringLiteral( "5" ) );
|
|
|
|
QString code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##non_optional=band" ) );
|
|
std::unique_ptr< QgsProcessingParameterBand > fromCode( dynamic_cast< QgsProcessingParameterBand * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
|
|
QVERIFY( def->dependsOnOtherParameters().isEmpty() );
|
|
def->setParentLayerParameterName( "my_parent" );
|
|
QCOMPARE( def->dependsOnOtherParameters(), QStringList() << QStringLiteral( "my_parent" ) );
|
|
|
|
code = def->asScriptCode();
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterBand * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "non optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
|
|
// optional
|
|
def.reset( new QgsProcessingParameterBand( "optional", QString(), 1, QString(), true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( 1 ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "1" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( "" ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
|
|
params.insert( "optional", QVariant() );
|
|
band = QgsProcessingParameters::parameterAsInt( def.get(), params, context );
|
|
QCOMPARE( band, 1 );
|
|
|
|
// optional, no default
|
|
def.reset( new QgsProcessingParameterBand( "optional", QString(), QVariant(), QString(), true ) );
|
|
params.insert( "optional", QVariant() );
|
|
band = QgsProcessingParameters::parameterAsInt( def.get(), params, context );
|
|
QCOMPARE( band, 0 );
|
|
|
|
code = def->asScriptCode();
|
|
QCOMPARE( code, QStringLiteral( "##optional=optional band" ) );
|
|
fromCode.reset( dynamic_cast< QgsProcessingParameterBand * >( QgsProcessingParameters::parameterFromScriptCode( code ) ) );
|
|
QVERIFY( fromCode.get() );
|
|
QCOMPARE( fromCode->name(), def->name() );
|
|
QCOMPARE( fromCode->description(), QStringLiteral( "optional" ) );
|
|
QCOMPARE( fromCode->flags(), def->flags() );
|
|
QCOMPARE( fromCode->defaultValue(), def->defaultValue() );
|
|
QCOMPARE( fromCode->parentLayerParameterName(), def->parentLayerParameterName() );
|
|
}
|
|
|
|
void TestQgsProcessing::checkParamValues()
|
|
{
|
|
DummyAlgorithm a( "asd" );
|
|
a.checkParameterVals();
|
|
}
|
|
|
|
void TestQgsProcessing::combineLayerExtent()
|
|
{
|
|
QgsRectangle ext = QgsProcessingUtils::combineLayerExtents( QList< QgsMapLayer *>() );
|
|
QVERIFY( ext.isNull() );
|
|
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
|
|
QString raster1 = testDataDir + "tenbytenraster.asc";
|
|
QString raster2 = testDataDir + "landsat.tif";
|
|
QFileInfo fi1( raster1 );
|
|
std::unique_ptr< QgsRasterLayer > r1( new QgsRasterLayer( fi1.filePath(), "R1" ) );
|
|
QFileInfo fi2( raster2 );
|
|
std::unique_ptr< QgsRasterLayer > r2( new QgsRasterLayer( fi2.filePath(), "R2" ) );
|
|
|
|
ext = QgsProcessingUtils::combineLayerExtents( QList< QgsMapLayer *>() << r1.get() );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1535375.000000, 10 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 1535475, 10 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 5083255, 10 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 5083355, 10 );
|
|
|
|
ext = QgsProcessingUtils::combineLayerExtents( QList< QgsMapLayer *>() << r1.get() << r2.get() );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 781662, 10 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 1535475, 10 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 3339523, 10 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 5083355, 10 );
|
|
|
|
// with reprojection
|
|
ext = QgsProcessingUtils::combineLayerExtents( QList< QgsMapLayer *>() << r1.get() << r2.get(), QgsCoordinateReferenceSystem::fromEpsgId( 3785 ) );
|
|
QGSCOMPARENEAR( ext.xMinimum(), 1995320, 10 );
|
|
QGSCOMPARENEAR( ext.xMaximum(), 2008833, 10 );
|
|
QGSCOMPARENEAR( ext.yMinimum(), 3523084, 10 );
|
|
QGSCOMPARENEAR( ext.yMaximum(), 3536664, 10 );
|
|
}
|
|
|
|
void TestQgsProcessing::processingFeatureSource()
|
|
{
|
|
QString sourceString = QStringLiteral( "test.shp" );
|
|
QgsProcessingFeatureSourceDefinition fs( sourceString, true );
|
|
QCOMPARE( fs.source.staticValue().toString(), sourceString );
|
|
QVERIFY( fs.selectedFeaturesOnly );
|
|
|
|
// test storing QgsProcessingFeatureSource in variant and retrieving
|
|
QVariant fsInVariant = QVariant::fromValue( fs );
|
|
QVERIFY( fsInVariant.isValid() );
|
|
|
|
QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( fsInVariant );
|
|
QCOMPARE( fromVar.source.staticValue().toString(), sourceString );
|
|
QVERIFY( fromVar.selectedFeaturesOnly );
|
|
|
|
// test evaluating parameter as source
|
|
QgsVectorLayer *layer = new QgsVectorLayer( "Point", "v1", "memory" );
|
|
QgsFeature f( 10001 );
|
|
f.setGeometry( QgsGeometry( new QgsPoint( 1, 2 ) ) );
|
|
layer->dataProvider()->addFeatures( QgsFeatureList() << f );
|
|
|
|
QgsProject p;
|
|
p.addMapLayer( layer );
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// first using static string definition
|
|
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterString( QStringLiteral( "layer" ) ) );
|
|
QVariantMap params;
|
|
params.insert( QStringLiteral( "layer" ), QgsProcessingFeatureSourceDefinition( layer->id(), false ) );
|
|
std::unique_ptr< QgsFeatureSource > source( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
// can't directly match it to layer, so instead just get the feature and test that it matches what we expect
|
|
QgsFeature f2;
|
|
QVERIFY( source.get() );
|
|
QVERIFY( source->getFeatures().nextFeature( f2 ) );
|
|
QCOMPARE( f2.geometry(), f.geometry() );
|
|
|
|
// direct map layer
|
|
params.insert( QStringLiteral( "layer" ), QVariant::fromValue( layer ) );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
// can't directly match it to layer, so instead just get the feature and test that it matches what we expect
|
|
QVERIFY( source.get() );
|
|
QVERIFY( source->getFeatures().nextFeature( f2 ) );
|
|
QCOMPARE( f2.geometry(), f.geometry() );
|
|
|
|
|
|
// next using property based definition
|
|
params.insert( QStringLiteral( "layer" ), QgsProcessingFeatureSourceDefinition( QgsProperty::fromExpression( QStringLiteral( "trim('%1' + ' ')" ).arg( layer->id() ) ), false ) );
|
|
source.reset( QgsProcessingParameters::parameterAsSource( def.get(), params, context ) );
|
|
// can't directly match it to layer, so instead just get the feature and test that it matches what we expect
|
|
QVERIFY( source.get() );
|
|
QVERIFY( source->getFeatures().nextFeature( f2 ) );
|
|
QCOMPARE( f2.geometry(), f.geometry() );
|
|
}
|
|
|
|
void TestQgsProcessing::processingFeatureSink()
|
|
{
|
|
QString sinkString( QStringLiteral( "test.shp" ) );
|
|
QgsProject p;
|
|
QgsProcessingOutputLayerDefinition fs( sinkString, &p );
|
|
QCOMPARE( fs.sink.staticValue().toString(), sinkString );
|
|
QCOMPARE( fs.destinationProject, &p );
|
|
|
|
// test storing QgsProcessingFeatureSink in variant and retrieving
|
|
QVariant fsInVariant = QVariant::fromValue( fs );
|
|
QVERIFY( fsInVariant.isValid() );
|
|
|
|
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( fsInVariant );
|
|
QCOMPARE( fromVar.sink.staticValue().toString(), sinkString );
|
|
QCOMPARE( fromVar.destinationProject, &p );
|
|
|
|
// test evaluating parameter as sink
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
|
|
// first using static string definition
|
|
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterString( QStringLiteral( "layer" ) ) );
|
|
QVariantMap params;
|
|
params.insert( QStringLiteral( "layer" ), QgsProcessingOutputLayerDefinition( "memory:test", nullptr ) );
|
|
QString dest;
|
|
std::unique_ptr< QgsFeatureSink > sink( QgsProcessingParameters::parameterAsSink( def.get(), params, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem( "EPSG:3111" ), context, dest ) );
|
|
QVERIFY( sink.get() );
|
|
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( dest, context, false ) );
|
|
QVERIFY( layer );
|
|
QCOMPARE( layer->crs().authid(), QStringLiteral( "EPSG:3111" ) );
|
|
|
|
// next using property based definition
|
|
params.insert( QStringLiteral( "layer" ), QgsProcessingOutputLayerDefinition( QgsProperty::fromExpression( QStringLiteral( "trim('memory' + ':test2')" ) ), nullptr ) );
|
|
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem( "EPSG:3113" ), context, dest ) );
|
|
QVERIFY( sink.get() );
|
|
QgsVectorLayer *layer2 = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( dest, context, false ) );
|
|
QVERIFY( layer2 );
|
|
QCOMPARE( layer2->crs().authid(), QStringLiteral( "EPSG:3113" ) );
|
|
|
|
|
|
// non optional sink
|
|
def.reset( new QgsProcessingParameterFeatureSink( QStringLiteral( "layer" ), QString(), QgsProcessing::TypeMapLayer, QVariant(), false ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringLiteral( "memory:test" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "memory:test" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( "memory:test" ) ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QString() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
params.insert( QStringLiteral( "layer" ), QStringLiteral( "memory:test" ) );
|
|
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem( "EPSG:3113" ), context, dest ) );
|
|
QVERIFY( sink.get() );
|
|
|
|
// optional sink
|
|
def.reset( new QgsProcessingParameterFeatureSink( QStringLiteral( "layer" ), QString(), QgsProcessing::TypeMapLayer, QVariant(), true ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QStringLiteral( "memory:test" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProcessingOutputLayerDefinition( "memory:test" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QgsProperty::fromValue( "memory:test" ) ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QString() ) );
|
|
QVERIFY( def->checkValueIsAcceptable( QVariant() ) );
|
|
QVERIFY( !def->checkValueIsAcceptable( 5 ) );
|
|
params.insert( QStringLiteral( "layer" ), QStringLiteral( "memory:test" ) );
|
|
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem( "EPSG:3113" ), context, dest ) );
|
|
QVERIFY( sink.get() );
|
|
// optional sink, not set - should be no sink
|
|
params.insert( QStringLiteral( "layer" ), QVariant() );
|
|
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem( "EPSG:3113" ), context, dest ) );
|
|
QVERIFY( !sink.get() );
|
|
|
|
//.... unless there's a default set
|
|
def.reset( new QgsProcessingParameterFeatureSink( QStringLiteral( "layer" ), QString(), QgsProcessing::TypeMapLayer, QStringLiteral( "memory:defaultlayer" ), true ) );
|
|
params.insert( QStringLiteral( "layer" ), QVariant() );
|
|
sink.reset( QgsProcessingParameters::parameterAsSink( def.get(), params, QgsFields(), QgsWkbTypes::Point, QgsCoordinateReferenceSystem( "EPSG:3113" ), context, dest ) );
|
|
QVERIFY( sink.get() );
|
|
}
|
|
|
|
void TestQgsProcessing::algorithmScope()
|
|
{
|
|
QgsProcessingContext pc;
|
|
|
|
// no alg
|
|
std::unique_ptr< QgsExpressionContextScope > scope( QgsExpressionContextUtils::processingAlgorithmScope( nullptr, QVariantMap(), pc ) );
|
|
QVERIFY( scope.get() );
|
|
|
|
// with alg
|
|
std::unique_ptr< QgsProcessingAlgorithm > alg( new DummyAlgorithm( "alg1" ) );
|
|
QVariantMap params;
|
|
params.insert( QStringLiteral( "a_param" ), 5 );
|
|
scope.reset( QgsExpressionContextUtils::processingAlgorithmScope( alg.get(), params, pc ) );
|
|
QVERIFY( scope.get() );
|
|
QCOMPARE( scope->variable( QStringLiteral( "algorithm_id" ) ).toString(), alg->id() );
|
|
|
|
QgsExpressionContext context;
|
|
context.appendScope( scope.release() );
|
|
QgsExpression exp( "parameter('bad')" );
|
|
QVERIFY( !exp.evaluate( &context ).isValid() );
|
|
QgsExpression exp2( "parameter('a_param')" );
|
|
QCOMPARE( exp2.evaluate( &context ).toInt(), 5 );
|
|
}
|
|
|
|
void TestQgsProcessing::validateInputCrs()
|
|
{
|
|
DummyAlgorithm alg( "test" );
|
|
alg.runValidateInputCrsChecks();
|
|
}
|
|
|
|
void TestQgsProcessing::generateIteratingDestination()
|
|
{
|
|
QgsProcessingContext context;
|
|
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "memory:x", 1, context ).toString(), QStringLiteral( "memory:x_1" ) );
|
|
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "memory:x", 2, context ).toString(), QStringLiteral( "memory:x_2" ) );
|
|
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "ape.shp", 1, context ).toString(), QStringLiteral( "ape_1.shp" ) );
|
|
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "ape.shp", 2, context ).toString(), QStringLiteral( "ape_2.shp" ) );
|
|
QCOMPARE( QgsProcessingUtils::generateIteratingDestination( "/home/bif.o/ape.shp", 2, context ).toString(), QStringLiteral( "/home/bif.o/ape_2.shp" ) );
|
|
|
|
QgsProject p;
|
|
QgsProcessingOutputLayerDefinition def;
|
|
def.sink = QgsProperty::fromValue( "ape.shp" );
|
|
def.destinationProject = &p;
|
|
QVariant res = QgsProcessingUtils::generateIteratingDestination( def, 2, context );
|
|
QVERIFY( res.canConvert<QgsProcessingOutputLayerDefinition>() );
|
|
QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( res );
|
|
QCOMPARE( fromVar.sink.staticValue().toString(), QStringLiteral( "ape_2.shp" ) );
|
|
QCOMPARE( fromVar.destinationProject, &p );
|
|
|
|
def.sink = QgsProperty::fromExpression( "'ape' || '.shp'" );
|
|
res = QgsProcessingUtils::generateIteratingDestination( def, 2, context );
|
|
QVERIFY( res.canConvert<QgsProcessingOutputLayerDefinition>() );
|
|
fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( res );
|
|
QCOMPARE( fromVar.sink.staticValue().toString(), QStringLiteral( "ape_2.shp" ) );
|
|
QCOMPARE( fromVar.destinationProject, &p );
|
|
}
|
|
|
|
void TestQgsProcessing::asPythonCommand()
|
|
{
|
|
DummyAlgorithm alg( "test" );
|
|
alg.runAsPythonCommandChecks();
|
|
}
|
|
|
|
void TestQgsProcessing::modelerAlgorithm()
|
|
{
|
|
//static value source
|
|
QgsProcessingModelChildParameterSource svSource = QgsProcessingModelChildParameterSource::fromStaticValue( 5 );
|
|
QCOMPARE( svSource.source(), QgsProcessingModelChildParameterSource::StaticValue );
|
|
QCOMPARE( svSource.staticValue().toInt(), 5 );
|
|
svSource.setStaticValue( 7 );
|
|
QCOMPARE( svSource.staticValue().toInt(), 7 );
|
|
svSource = QgsProcessingModelChildParameterSource::fromModelParameter( "a" );
|
|
// check that calling setStaticValue flips source to StaticValue
|
|
QCOMPARE( svSource.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
svSource.setStaticValue( 7 );
|
|
QCOMPARE( svSource.staticValue().toInt(), 7 );
|
|
QCOMPARE( svSource.source(), QgsProcessingModelChildParameterSource::StaticValue );
|
|
|
|
// model parameter source
|
|
QgsProcessingModelChildParameterSource mpSource = QgsProcessingModelChildParameterSource::fromModelParameter( "a" );
|
|
QCOMPARE( mpSource.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( mpSource.parameterName(), QStringLiteral( "a" ) );
|
|
mpSource.setParameterName( "b" );
|
|
QCOMPARE( mpSource.parameterName(), QStringLiteral( "b" ) );
|
|
mpSource = QgsProcessingModelChildParameterSource::fromStaticValue( 5 );
|
|
// check that calling setParameterName flips source to ModelParameter
|
|
QCOMPARE( mpSource.source(), QgsProcessingModelChildParameterSource::StaticValue );
|
|
mpSource.setParameterName( "c" );
|
|
QCOMPARE( mpSource.parameterName(), QStringLiteral( "c" ) );
|
|
QCOMPARE( mpSource.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
|
|
// child alg output source
|
|
QgsProcessingModelChildParameterSource oSource = QgsProcessingModelChildParameterSource::fromChildOutput( "a", "b" );
|
|
QCOMPARE( oSource.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( oSource.outputChildId(), QStringLiteral( "a" ) );
|
|
QCOMPARE( oSource.outputName(), QStringLiteral( "b" ) );
|
|
oSource.setOutputChildId( "c" );
|
|
QCOMPARE( oSource.outputChildId(), QStringLiteral( "c" ) );
|
|
oSource.setOutputName( "d" );
|
|
QCOMPARE( oSource.outputName(), QStringLiteral( "d" ) );
|
|
oSource = QgsProcessingModelChildParameterSource::fromStaticValue( 5 );
|
|
// check that calling setOutputChildId flips source to ChildOutput
|
|
QCOMPARE( oSource.source(), QgsProcessingModelChildParameterSource::StaticValue );
|
|
oSource.setOutputChildId( "c" );
|
|
QCOMPARE( oSource.outputChildId(), QStringLiteral( "c" ) );
|
|
QCOMPARE( oSource.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
oSource = QgsProcessingModelChildParameterSource::fromStaticValue( 5 );
|
|
// check that calling setOutputName flips source to ChildOutput
|
|
QCOMPARE( oSource.source(), QgsProcessingModelChildParameterSource::StaticValue );
|
|
oSource.setOutputName( "d" );
|
|
QCOMPARE( oSource.outputName(), QStringLiteral( "d" ) );
|
|
QCOMPARE( oSource.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
|
|
// expression source
|
|
QgsProcessingModelChildParameterSource expSource = QgsProcessingModelChildParameterSource::fromExpression( "1+2" );
|
|
QCOMPARE( expSource.source(), QgsProcessingModelChildParameterSource::Expression );
|
|
QCOMPARE( expSource.expression(), QStringLiteral( "1+2" ) );
|
|
expSource.setExpression( "1+3" );
|
|
QCOMPARE( expSource.expression(), QStringLiteral( "1+3" ) );
|
|
expSource = QgsProcessingModelChildParameterSource::fromStaticValue( 5 );
|
|
// check that calling setExpression flips source to Expression
|
|
QCOMPARE( expSource.source(), QgsProcessingModelChildParameterSource::StaticValue );
|
|
expSource.setExpression( "1+4" );
|
|
QCOMPARE( expSource.expression(), QStringLiteral( "1+4" ) );
|
|
QCOMPARE( expSource.source(), QgsProcessingModelChildParameterSource::Expression );
|
|
|
|
// source equality operator
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromStaticValue( 5 ) ==
|
|
QgsProcessingModelChildParameterSource::fromStaticValue( 5 ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromStaticValue( 5 ) !=
|
|
QgsProcessingModelChildParameterSource::fromStaticValue( 7 ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromStaticValue( 5 ) !=
|
|
QgsProcessingModelChildParameterSource::fromModelParameter( QStringLiteral( "a" ) ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromModelParameter( QStringLiteral( "a" ) ) ==
|
|
QgsProcessingModelChildParameterSource::fromModelParameter( QStringLiteral( "a" ) ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromModelParameter( QStringLiteral( "a" ) ) !=
|
|
QgsProcessingModelChildParameterSource::fromModelParameter( QStringLiteral( "b" ) ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromModelParameter( QStringLiteral( "a" ) ) !=
|
|
QgsProcessingModelChildParameterSource::fromChildOutput( QStringLiteral( "alg" ), QStringLiteral( "out" ) ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromChildOutput( QStringLiteral( "alg" ), QStringLiteral( "out" ) ) ==
|
|
QgsProcessingModelChildParameterSource::fromChildOutput( QStringLiteral( "alg" ), QStringLiteral( "out" ) ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromChildOutput( QStringLiteral( "alg" ), QStringLiteral( "out" ) ) !=
|
|
QgsProcessingModelChildParameterSource::fromChildOutput( QStringLiteral( "alg2" ), QStringLiteral( "out" ) ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromChildOutput( QStringLiteral( "alg" ), QStringLiteral( "out" ) ) !=
|
|
QgsProcessingModelChildParameterSource::fromChildOutput( QStringLiteral( "alg" ), QStringLiteral( "out2" ) ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromExpression( QStringLiteral( "a" ) ) ==
|
|
QgsProcessingModelChildParameterSource::fromExpression( QStringLiteral( "a" ) ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromExpression( QStringLiteral( "a" ) ) !=
|
|
QgsProcessingModelChildParameterSource::fromExpression( QStringLiteral( "b" ) ) );
|
|
QVERIFY( QgsProcessingModelChildParameterSource::fromExpression( QStringLiteral( "a" ) ) !=
|
|
QgsProcessingModelChildParameterSource::fromStaticValue( QStringLiteral( "b" ) ) );
|
|
|
|
|
|
|
|
|
|
|
|
QgsProcessingModelChildAlgorithm child( QStringLiteral( "some_id" ) );
|
|
QCOMPARE( child.algorithmId(), QStringLiteral( "some_id" ) );
|
|
QVERIFY( !child.algorithm() );
|
|
child.setAlgorithmId( QStringLiteral( "native:centroids" ) );
|
|
QVERIFY( child.algorithm() );
|
|
QCOMPARE( child.algorithm()->id(), QStringLiteral( "native:centroids" ) );
|
|
QVariantMap myConfig;
|
|
myConfig.insert( QStringLiteral( "some_key" ), 11 );
|
|
child.setConfiguration( myConfig );
|
|
QCOMPARE( child.configuration(), myConfig );
|
|
|
|
child.setDescription( QStringLiteral( "desc" ) );
|
|
QCOMPARE( child.description(), QStringLiteral( "desc" ) );
|
|
QVERIFY( child.isActive() );
|
|
child.setActive( false );
|
|
QVERIFY( !child.isActive() );
|
|
child.setPosition( QPointF( 1, 2 ) );
|
|
QCOMPARE( child.position(), QPointF( 1, 2 ) );
|
|
QVERIFY( child.parametersCollapsed() );
|
|
child.setParametersCollapsed( false );
|
|
QVERIFY( !child.parametersCollapsed() );
|
|
QVERIFY( child.outputsCollapsed() );
|
|
child.setOutputsCollapsed( false );
|
|
QVERIFY( !child.outputsCollapsed() );
|
|
|
|
child.setChildId( QStringLiteral( "my_id" ) );
|
|
QCOMPARE( child.childId(), QStringLiteral( "my_id" ) );
|
|
|
|
child.setDependencies( QStringList() << "a" << "b" );
|
|
QCOMPARE( child.dependencies(), QStringList() << "a" << "b" );
|
|
|
|
QMap< QString, QgsProcessingModelChildParameterSources > sources;
|
|
sources.insert( QStringLiteral( "a" ), QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromStaticValue( 5 ) );
|
|
child.setParameterSources( sources );
|
|
QCOMPARE( child.parameterSources().value( QStringLiteral( "a" ) ).at( 0 ).staticValue().toInt(), 5 );
|
|
child.addParameterSources( QStringLiteral( "b" ), QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromStaticValue( 7 ) << QgsProcessingModelChildParameterSource::fromStaticValue( 9 ) );
|
|
QCOMPARE( child.parameterSources().value( QStringLiteral( "a" ) ).at( 0 ).staticValue().toInt(), 5 );
|
|
QCOMPARE( child.parameterSources().value( QStringLiteral( "b" ) ).count(), 2 );
|
|
QCOMPARE( child.parameterSources().value( QStringLiteral( "b" ) ).at( 0 ).staticValue().toInt(), 7 );
|
|
QCOMPARE( child.parameterSources().value( QStringLiteral( "b" ) ).at( 1 ).staticValue().toInt(), 9 );
|
|
|
|
QgsProcessingModelOutput testModelOut;
|
|
testModelOut.setChildId( QStringLiteral( "my_id" ) );
|
|
QCOMPARE( testModelOut.childId(), QStringLiteral( "my_id" ) );
|
|
testModelOut.setChildOutputName( QStringLiteral( "my_output" ) );
|
|
QCOMPARE( testModelOut.childOutputName(), QStringLiteral( "my_output" ) );
|
|
testModelOut.setDefaultValue( QStringLiteral( "my_value" ) );
|
|
QCOMPARE( testModelOut.defaultValue().toString(), QStringLiteral( "my_value" ) );
|
|
testModelOut.setMandatory( true );
|
|
QVERIFY( testModelOut.isMandatory() );
|
|
|
|
QgsProcessingOutputLayerDefinition layerDef( QStringLiteral( "my_path" ) );
|
|
layerDef.createOptions["fileEncoding"] = QStringLiteral( "my_encoding" );
|
|
testModelOut.setDefaultValue( layerDef );
|
|
QCOMPARE( testModelOut.defaultValue().value<QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QStringLiteral( "my_path" ) );
|
|
QVariantMap map = testModelOut.toVariant().toMap();
|
|
QCOMPARE( map["default_value"].toMap()["sink"].toMap()["val"].toString(), QStringLiteral( "my_path" ) );
|
|
QCOMPARE( map["default_value"].toMap()["create_options"].toMap()["fileEncoding"].toString(), QStringLiteral( "my_encoding" ) );
|
|
QgsProcessingModelOutput out;
|
|
out.loadVariant( map );
|
|
QVERIFY( out.defaultValue().canConvert<QgsProcessingOutputLayerDefinition>() );
|
|
layerDef = out.defaultValue().value<QgsProcessingOutputLayerDefinition>();
|
|
QCOMPARE( layerDef.sink.staticValue().toString(), QStringLiteral( "my_path" ) );
|
|
QCOMPARE( layerDef.createOptions["fileEncoding"].toString(), QStringLiteral( "my_encoding" ) );
|
|
|
|
QMap<QString, QgsProcessingModelOutput> outputs;
|
|
QgsProcessingModelOutput out1;
|
|
out1.setDescription( QStringLiteral( "my output" ) );
|
|
outputs.insert( QStringLiteral( "a" ), out1 );
|
|
child.setModelOutputs( outputs );
|
|
QCOMPARE( child.modelOutputs().count(), 1 );
|
|
QCOMPARE( child.modelOutputs().value( QStringLiteral( "a" ) ).description(), QStringLiteral( "my output" ) );
|
|
QCOMPARE( child.modelOutput( "a" ).description(), QStringLiteral( "my output" ) );
|
|
child.modelOutput( "a" ).setDescription( QStringLiteral( "my output 2" ) );
|
|
QCOMPARE( child.modelOutput( "a" ).description(), QStringLiteral( "my output 2" ) );
|
|
// no existent
|
|
child.modelOutput( "b" ).setDescription( QStringLiteral( "my output 3" ) );
|
|
QCOMPARE( child.modelOutput( "b" ).description(), QStringLiteral( "my output 3" ) );
|
|
QCOMPARE( child.modelOutputs().count(), 2 );
|
|
child.removeModelOutput( QStringLiteral( "a" ) );
|
|
QCOMPARE( child.modelOutputs().count(), 1 );
|
|
|
|
|
|
// model algorithm tests
|
|
|
|
|
|
QgsProcessingModelAlgorithm alg( "test", "testGroup" );
|
|
QCOMPARE( alg.name(), QStringLiteral( "test" ) );
|
|
QCOMPARE( alg.displayName(), QStringLiteral( "test" ) );
|
|
QCOMPARE( alg.group(), QStringLiteral( "testGroup" ) );
|
|
alg.setName( QStringLiteral( "test2" ) );
|
|
QCOMPARE( alg.name(), QStringLiteral( "test2" ) );
|
|
QCOMPARE( alg.displayName(), QStringLiteral( "test2" ) );
|
|
alg.setGroup( QStringLiteral( "group2" ) );
|
|
QCOMPARE( alg.group(), QStringLiteral( "group2" ) );
|
|
|
|
// child algorithms
|
|
QMap<QString, QgsProcessingModelChildAlgorithm> algs;
|
|
QgsProcessingModelChildAlgorithm a1;
|
|
a1.setDescription( QStringLiteral( "alg1" ) );
|
|
QgsProcessingModelChildAlgorithm a2;
|
|
a2.setDescription( QStringLiteral( "alg2" ) );
|
|
algs.insert( QStringLiteral( "a" ), a1 );
|
|
algs.insert( QStringLiteral( "b" ), a2 );
|
|
alg.setChildAlgorithms( algs );
|
|
QCOMPARE( alg.childAlgorithms().count(), 2 );
|
|
QCOMPARE( alg.childAlgorithms().value( QStringLiteral( "a" ) ).description(), QStringLiteral( "alg1" ) );
|
|
QCOMPARE( alg.childAlgorithms().value( QStringLiteral( "b" ) ).description(), QStringLiteral( "alg2" ) );
|
|
QgsProcessingModelChildAlgorithm a3;
|
|
a3.setChildId( QStringLiteral( "c" ) );
|
|
a3.setDescription( QStringLiteral( "alg3" ) );
|
|
QCOMPARE( alg.addChildAlgorithm( a3 ), QStringLiteral( "c" ) );
|
|
QCOMPARE( alg.childAlgorithms().count(), 3 );
|
|
QCOMPARE( alg.childAlgorithms().value( QStringLiteral( "a" ) ).description(), QStringLiteral( "alg1" ) );
|
|
QCOMPARE( alg.childAlgorithms().value( QStringLiteral( "b" ) ).description(), QStringLiteral( "alg2" ) );
|
|
QCOMPARE( alg.childAlgorithms().value( QStringLiteral( "c" ) ).description(), QStringLiteral( "alg3" ) );
|
|
QCOMPARE( alg.childAlgorithm( "a" ).description(), QStringLiteral( "alg1" ) );
|
|
QCOMPARE( alg.childAlgorithm( "b" ).description(), QStringLiteral( "alg2" ) );
|
|
QCOMPARE( alg.childAlgorithm( "c" ).description(), QStringLiteral( "alg3" ) );
|
|
// initially non-existent
|
|
QVERIFY( alg.childAlgorithm( "d" ).description().isEmpty() );
|
|
alg.childAlgorithm( "d" ).setDescription( QStringLiteral( "alg4" ) );
|
|
QCOMPARE( alg.childAlgorithm( "d" ).description(), QStringLiteral( "alg4" ) );
|
|
// overwrite existing
|
|
QgsProcessingModelChildAlgorithm a4a;
|
|
a4a.setChildId( "d" );
|
|
a4a.setDescription( "new" );
|
|
alg.setChildAlgorithm( a4a );
|
|
QCOMPARE( alg.childAlgorithm( "d" ).description(), QStringLiteral( "new" ) );
|
|
|
|
|
|
// generating child ids
|
|
QgsProcessingModelChildAlgorithm c1;
|
|
c1.setAlgorithmId( QStringLiteral( "buffer" ) );
|
|
c1.generateChildId( alg );
|
|
QCOMPARE( c1.childId(), QStringLiteral( "buffer_1" ) );
|
|
QCOMPARE( alg.addChildAlgorithm( c1 ), QStringLiteral( "buffer_1" ) );
|
|
QgsProcessingModelChildAlgorithm c2;
|
|
c2.setAlgorithmId( QStringLiteral( "buffer" ) );
|
|
c2.generateChildId( alg );
|
|
QCOMPARE( c2.childId(), QStringLiteral( "buffer_2" ) );
|
|
QCOMPARE( alg.addChildAlgorithm( c2 ), QStringLiteral( "buffer_2" ) );
|
|
QgsProcessingModelChildAlgorithm c3;
|
|
c3.setAlgorithmId( QStringLiteral( "centroid" ) );
|
|
c3.generateChildId( alg );
|
|
QCOMPARE( c3.childId(), QStringLiteral( "centroid_1" ) );
|
|
QCOMPARE( alg.addChildAlgorithm( c3 ), QStringLiteral( "centroid_1" ) );
|
|
QgsProcessingModelChildAlgorithm c4;
|
|
c4.setAlgorithmId( QStringLiteral( "centroid" ) );
|
|
c4.setChildId( QStringLiteral( "centroid_1" ) );// dupe id
|
|
QCOMPARE( alg.addChildAlgorithm( c4 ), QStringLiteral( "centroid_2" ) );
|
|
QCOMPARE( alg.childAlgorithm( QStringLiteral( "centroid_2" ) ).childId(), QStringLiteral( "centroid_2" ) );
|
|
|
|
// parameter components
|
|
QMap<QString, QgsProcessingModelParameter> pComponents;
|
|
QgsProcessingModelParameter pc1;
|
|
pc1.setParameterName( QStringLiteral( "my_param" ) );
|
|
QCOMPARE( pc1.parameterName(), QStringLiteral( "my_param" ) );
|
|
pComponents.insert( QStringLiteral( "my_param" ), pc1 );
|
|
alg.setParameterComponents( pComponents );
|
|
QCOMPARE( alg.parameterComponents().count(), 1 );
|
|
QCOMPARE( alg.parameterComponents().value( QStringLiteral( "my_param" ) ).parameterName(), QStringLiteral( "my_param" ) );
|
|
QCOMPARE( alg.parameterComponent( "my_param" ).parameterName(), QStringLiteral( "my_param" ) );
|
|
alg.parameterComponent( "my_param" ).setDescription( QStringLiteral( "my param 2" ) );
|
|
QCOMPARE( alg.parameterComponent( "my_param" ).description(), QStringLiteral( "my param 2" ) );
|
|
// no existent
|
|
alg.parameterComponent( "b" ).setDescription( QStringLiteral( "my param 3" ) );
|
|
QCOMPARE( alg.parameterComponent( "b" ).description(), QStringLiteral( "my param 3" ) );
|
|
QCOMPARE( alg.parameterComponent( "b" ).parameterName(), QStringLiteral( "b" ) );
|
|
QCOMPARE( alg.parameterComponents().count(), 2 );
|
|
|
|
// parameter definitions
|
|
QgsProcessingModelAlgorithm alg1a( "test", "testGroup" );
|
|
QgsProcessingModelParameter bool1;
|
|
bool1.setPosition( QPointF( 1, 2 ) );
|
|
alg1a.addModelParameter( new QgsProcessingParameterBoolean( "p1", "desc" ), bool1 );
|
|
QCOMPARE( alg1a.parameterDefinitions().count(), 1 );
|
|
QCOMPARE( alg1a.parameterDefinition( "p1" )->type(), QStringLiteral( "boolean" ) );
|
|
QCOMPARE( alg1a.parameterComponent( "p1" ).position().x(), 1.0 );
|
|
QCOMPARE( alg1a.parameterComponent( "p1" ).position().y(), 2.0 );
|
|
alg1a.updateModelParameter( new QgsProcessingParameterBoolean( "p1", "descx" ) );
|
|
QCOMPARE( alg1a.parameterDefinition( "p1" )->description(), QStringLiteral( "descx" ) );
|
|
alg1a.removeModelParameter( "bad" );
|
|
QCOMPARE( alg1a.parameterDefinitions().count(), 1 );
|
|
alg1a.removeModelParameter( "p1" );
|
|
QVERIFY( alg1a.parameterDefinitions().isEmpty() );
|
|
QVERIFY( alg1a.parameterComponents().isEmpty() );
|
|
|
|
|
|
// test canExecute
|
|
QgsProcessingModelAlgorithm alg2( "test", "testGroup" );
|
|
QVERIFY( alg2.canExecute() );
|
|
QgsProcessingModelChildAlgorithm c5;
|
|
c5.setAlgorithmId( "native:centroids" );
|
|
alg2.addChildAlgorithm( c5 );
|
|
QVERIFY( alg2.canExecute() );
|
|
// non-existing alg
|
|
QgsProcessingModelChildAlgorithm c6;
|
|
c6.setAlgorithmId( "i'm not an alg" );
|
|
alg2.addChildAlgorithm( c6 );
|
|
QVERIFY( !alg2.canExecute() );
|
|
|
|
|
|
|
|
// dependencies
|
|
QgsProcessingModelAlgorithm alg3( "test", "testGroup" );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "notvalid" ).isEmpty() );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "notvalid" ).isEmpty() );
|
|
|
|
// add a child
|
|
QgsProcessingModelChildAlgorithm c7;
|
|
c7.setChildId( "c7" );
|
|
alg3.addChildAlgorithm( c7 );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c7" ).isEmpty() );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c7" ).isEmpty() );
|
|
|
|
// direct dependency
|
|
QgsProcessingModelChildAlgorithm c8;
|
|
c8.setChildId( "c8" );
|
|
c8.setDependencies( QStringList() << "c7" );
|
|
alg3.addChildAlgorithm( c8 );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c8" ).isEmpty() );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c7" ).isEmpty() );
|
|
QCOMPARE( alg3.dependentChildAlgorithms( "c7" ).count(), 1 );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c7" ).contains( "c8" ) );
|
|
QCOMPARE( alg3.dependsOnChildAlgorithms( "c8" ).count(), 1 );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c8" ).contains( "c7" ) );
|
|
|
|
// dependency via parameter source
|
|
QgsProcessingModelChildAlgorithm c9;
|
|
c9.setChildId( "c9" );
|
|
c9.addParameterSources( "x", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromChildOutput( "c8", "x" ) );
|
|
alg3.addChildAlgorithm( c9 );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c9" ).isEmpty() );
|
|
QCOMPARE( alg3.dependentChildAlgorithms( "c8" ).count(), 1 );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c8" ).contains( "c9" ) );
|
|
QCOMPARE( alg3.dependentChildAlgorithms( "c7" ).count(), 2 );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c7" ).contains( "c8" ) );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c7" ).contains( "c9" ) );
|
|
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c7" ).isEmpty() );
|
|
QCOMPARE( alg3.dependsOnChildAlgorithms( "c8" ).count(), 1 );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c8" ).contains( "c7" ) );
|
|
QCOMPARE( alg3.dependsOnChildAlgorithms( "c9" ).count(), 2 );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c9" ).contains( "c7" ) );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c9" ).contains( "c8" ) );
|
|
|
|
QgsProcessingModelChildAlgorithm c9b;
|
|
c9b.setChildId( "c9b" );
|
|
c9b.addParameterSources( "x", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromChildOutput( "c9", "x" ) );
|
|
alg3.addChildAlgorithm( c9b );
|
|
|
|
QCOMPARE( alg3.dependentChildAlgorithms( "c9" ).count(), 1 );
|
|
QCOMPARE( alg3.dependentChildAlgorithms( "c8" ).count(), 2 );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c8" ).contains( "c9" ) );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c8" ).contains( "c9b" ) );
|
|
QCOMPARE( alg3.dependentChildAlgorithms( "c7" ).count(), 3 );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c7" ).contains( "c8" ) );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c7" ).contains( "c9" ) );
|
|
QVERIFY( alg3.dependentChildAlgorithms( "c7" ).contains( "c9b" ) );
|
|
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c7" ).isEmpty() );
|
|
QCOMPARE( alg3.dependsOnChildAlgorithms( "c8" ).count(), 1 );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c8" ).contains( "c7" ) );
|
|
QCOMPARE( alg3.dependsOnChildAlgorithms( "c9" ).count(), 2 );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c9" ).contains( "c7" ) );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c9" ).contains( "c8" ) );
|
|
QCOMPARE( alg3.dependsOnChildAlgorithms( "c9b" ).count(), 3 );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c9b" ).contains( "c7" ) );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c9b" ).contains( "c8" ) );
|
|
QVERIFY( alg3.dependsOnChildAlgorithms( "c9b" ).contains( "c9" ) );
|
|
|
|
alg3.removeChildAlgorithm( "c9b" );
|
|
|
|
|
|
// (de)activate child algorithm
|
|
alg3.deactivateChildAlgorithm( "c9" );
|
|
QVERIFY( !alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( alg3.activateChildAlgorithm( "c9" ) );
|
|
QVERIFY( alg3.childAlgorithm( "c9" ).isActive() );
|
|
alg3.deactivateChildAlgorithm( "c8" );
|
|
QVERIFY( !alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( !alg3.childAlgorithm( "c8" ).isActive() );
|
|
QVERIFY( !alg3.activateChildAlgorithm( "c9" ) );
|
|
QVERIFY( !alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( !alg3.childAlgorithm( "c8" ).isActive() );
|
|
QVERIFY( alg3.activateChildAlgorithm( "c8" ) );
|
|
QVERIFY( !alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( alg3.childAlgorithm( "c8" ).isActive() );
|
|
QVERIFY( alg3.activateChildAlgorithm( "c9" ) );
|
|
QVERIFY( alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( alg3.childAlgorithm( "c8" ).isActive() );
|
|
alg3.deactivateChildAlgorithm( "c7" );
|
|
QVERIFY( !alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( !alg3.childAlgorithm( "c8" ).isActive() );
|
|
QVERIFY( !alg3.childAlgorithm( "c7" ).isActive() );
|
|
QVERIFY( !alg3.activateChildAlgorithm( "c9" ) );
|
|
QVERIFY( !alg3.activateChildAlgorithm( "c8" ) );
|
|
QVERIFY( !alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( !alg3.childAlgorithm( "c8" ).isActive() );
|
|
QVERIFY( !alg3.childAlgorithm( "c7" ).isActive() );
|
|
QVERIFY( !alg3.activateChildAlgorithm( "c8" ) );
|
|
QVERIFY( alg3.activateChildAlgorithm( "c7" ) );
|
|
QVERIFY( !alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( !alg3.childAlgorithm( "c8" ).isActive() );
|
|
QVERIFY( alg3.childAlgorithm( "c7" ).isActive() );
|
|
QVERIFY( !alg3.activateChildAlgorithm( "c9" ) );
|
|
QVERIFY( alg3.activateChildAlgorithm( "c8" ) );
|
|
QVERIFY( !alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( alg3.childAlgorithm( "c8" ).isActive() );
|
|
QVERIFY( alg3.childAlgorithm( "c7" ).isActive() );
|
|
QVERIFY( alg3.activateChildAlgorithm( "c9" ) );
|
|
QVERIFY( alg3.childAlgorithm( "c9" ).isActive() );
|
|
QVERIFY( alg3.childAlgorithm( "c8" ).isActive() );
|
|
QVERIFY( alg3.childAlgorithm( "c7" ).isActive() );
|
|
|
|
|
|
|
|
//remove child algorithm
|
|
QVERIFY( !alg3.removeChildAlgorithm( "c7" ) );
|
|
QVERIFY( !alg3.removeChildAlgorithm( "c8" ) );
|
|
QVERIFY( alg3.removeChildAlgorithm( "c9" ) );
|
|
QCOMPARE( alg3.childAlgorithms().count(), 2 );
|
|
QVERIFY( alg3.childAlgorithms().contains( "c7" ) );
|
|
QVERIFY( alg3.childAlgorithms().contains( "c8" ) );
|
|
QVERIFY( !alg3.removeChildAlgorithm( "c7" ) );
|
|
QVERIFY( alg3.removeChildAlgorithm( "c8" ) );
|
|
QCOMPARE( alg3.childAlgorithms().count(), 1 );
|
|
QVERIFY( alg3.childAlgorithms().contains( "c7" ) );
|
|
QVERIFY( alg3.removeChildAlgorithm( "c7" ) );
|
|
QVERIFY( alg3.childAlgorithms().isEmpty() );
|
|
|
|
// parameter dependencies
|
|
QgsProcessingModelAlgorithm alg4( "test", "testGroup" );
|
|
QVERIFY( !alg4.childAlgorithmsDependOnParameter( "not a param" ) );
|
|
QgsProcessingModelChildAlgorithm c10;
|
|
c10.setChildId( "c10" );
|
|
alg4.addChildAlgorithm( c10 );
|
|
QVERIFY( !alg4.childAlgorithmsDependOnParameter( "not a param" ) );
|
|
QgsProcessingModelParameter bool2;
|
|
alg4.addModelParameter( new QgsProcessingParameterBoolean( "p1", "desc" ), bool2 );
|
|
QVERIFY( !alg4.childAlgorithmsDependOnParameter( "p1" ) );
|
|
c10.addParameterSources( "x", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromModelParameter( "p2" ) );
|
|
alg4.setChildAlgorithm( c10 );
|
|
QVERIFY( !alg4.childAlgorithmsDependOnParameter( "p1" ) );
|
|
c10.addParameterSources( "y", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromModelParameter( "p1" ) );
|
|
alg4.setChildAlgorithm( c10 );
|
|
QVERIFY( alg4.childAlgorithmsDependOnParameter( "p1" ) );
|
|
|
|
QgsProcessingModelParameter vlP;
|
|
alg4.addModelParameter( new QgsProcessingParameterVectorLayer( "layer" ), vlP );
|
|
QgsProcessingModelParameter field;
|
|
alg4.addModelParameter( new QgsProcessingParameterField( "field", QString(), QVariant(), QStringLiteral( "layer" ) ), field );
|
|
QVERIFY( !alg4.otherParametersDependOnParameter( "p1" ) );
|
|
QVERIFY( !alg4.otherParametersDependOnParameter( "field" ) );
|
|
QVERIFY( alg4.otherParametersDependOnParameter( "layer" ) );
|
|
|
|
|
|
|
|
|
|
|
|
// to/from XML
|
|
QgsProcessingModelAlgorithm alg5( "test", "testGroup" );
|
|
alg5.helpContent().insert( "author", "me" );
|
|
alg5.helpContent().insert( "usage", "run" );
|
|
QgsProcessingModelChildAlgorithm alg5c1;
|
|
alg5c1.setChildId( "cx1" );
|
|
alg5c1.setAlgorithmId( "buffer" );
|
|
alg5c1.setConfiguration( myConfig );
|
|
alg5c1.addParameterSources( "x", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromModelParameter( "p1" ) );
|
|
alg5c1.addParameterSources( "y", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromChildOutput( "cx2", "out3" ) );
|
|
alg5c1.addParameterSources( "z", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromStaticValue( 5 ) );
|
|
alg5c1.addParameterSources( "a", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromExpression( "2*2" ) );
|
|
alg5c1.addParameterSources( "zm", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromStaticValue( 6 )
|
|
<< QgsProcessingModelChildParameterSource::fromModelParameter( "p2" )
|
|
<< QgsProcessingModelChildParameterSource::fromChildOutput( "cx2", "out4" )
|
|
<< QgsProcessingModelChildParameterSource::fromExpression( "1+2" ) );
|
|
alg5c1.setActive( true );
|
|
alg5c1.setOutputsCollapsed( true );
|
|
alg5c1.setParametersCollapsed( true );
|
|
alg5c1.setDescription( "child 1" );
|
|
alg5c1.setPosition( QPointF( 1, 2 ) );
|
|
QMap<QString, QgsProcessingModelOutput> alg5c1outputs;
|
|
QgsProcessingModelOutput alg5c1out1;
|
|
alg5c1out1.setDescription( QStringLiteral( "my output" ) );
|
|
alg5c1out1.setPosition( QPointF( 3, 4 ) );
|
|
alg5c1outputs.insert( QStringLiteral( "a" ), alg5c1out1 );
|
|
alg5c1.setModelOutputs( alg5c1outputs );
|
|
alg5.addChildAlgorithm( alg5c1 );
|
|
|
|
QgsProcessingModelChildAlgorithm alg5c2;
|
|
alg5c2.setChildId( "cx2" );
|
|
alg5c2.setActive( false );
|
|
alg5c2.setOutputsCollapsed( false );
|
|
alg5c2.setParametersCollapsed( false );
|
|
alg5c2.setDependencies( QStringList() << "a" << "b" );
|
|
alg5.addChildAlgorithm( alg5c2 );
|
|
|
|
QgsProcessingModelParameter alg5pc1;
|
|
alg5pc1.setParameterName( QStringLiteral( "my_param" ) );
|
|
alg5pc1.setPosition( QPointF( 11, 12 ) );
|
|
alg5.addModelParameter( new QgsProcessingParameterBoolean( QStringLiteral( "my_param" ) ), alg5pc1 );
|
|
|
|
QDomDocument doc = QDomDocument( "model" );
|
|
QDomElement elem = QgsXmlUtils::writeVariant( alg5.toVariant(), doc );
|
|
doc.appendChild( elem );
|
|
|
|
QgsProcessingModelAlgorithm alg6;
|
|
QVERIFY( alg6.loadVariant( QgsXmlUtils::readVariant( doc.firstChildElement() ) ) );
|
|
QCOMPARE( alg6.name(), QStringLiteral( "test" ) );
|
|
QCOMPARE( alg6.group(), QStringLiteral( "testGroup" ) );
|
|
QCOMPARE( alg6.helpContent(), alg5.helpContent() );
|
|
QgsProcessingModelChildAlgorithm alg6c1 = alg6.childAlgorithm( "cx1" );
|
|
QCOMPARE( alg6c1.childId(), QStringLiteral( "cx1" ) );
|
|
QCOMPARE( alg6c1.algorithmId(), QStringLiteral( "buffer" ) );
|
|
QCOMPARE( alg6c1.configuration(), myConfig );
|
|
QVERIFY( alg6c1.isActive() );
|
|
QVERIFY( alg6c1.outputsCollapsed() );
|
|
QVERIFY( alg6c1.parametersCollapsed() );
|
|
QCOMPARE( alg6c1.description(), QStringLiteral( "child 1" ) );
|
|
QCOMPARE( alg6c1.position().x(), 1.0 );
|
|
QCOMPARE( alg6c1.position().y(), 2.0 );
|
|
QCOMPARE( alg6c1.parameterSources().count(), 5 );
|
|
QCOMPARE( alg6c1.parameterSources().value( "x" ).at( 0 ).source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( alg6c1.parameterSources().value( "x" ).at( 0 ).parameterName(), QStringLiteral( "p1" ) );
|
|
QCOMPARE( alg6c1.parameterSources().value( "y" ).at( 0 ).source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( alg6c1.parameterSources().value( "y" ).at( 0 ).outputChildId(), QStringLiteral( "cx2" ) );
|
|
QCOMPARE( alg6c1.parameterSources().value( "y" ).at( 0 ).outputName(), QStringLiteral( "out3" ) );
|
|
QCOMPARE( alg6c1.parameterSources().value( "z" ).at( 0 ).source(), QgsProcessingModelChildParameterSource::StaticValue );
|
|
QCOMPARE( alg6c1.parameterSources().value( "z" ).at( 0 ).staticValue().toInt(), 5 );
|
|
QCOMPARE( alg6c1.parameterSources().value( "a" ).at( 0 ).source(), QgsProcessingModelChildParameterSource::Expression );
|
|
QCOMPARE( alg6c1.parameterSources().value( "a" ).at( 0 ).expression(), QStringLiteral( "2*2" ) );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).count(), 4 );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).at( 0 ).source(), QgsProcessingModelChildParameterSource::StaticValue );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).at( 0 ).staticValue().toInt(), 6 );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).at( 1 ).source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).at( 1 ).parameterName(), QStringLiteral( "p2" ) );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).at( 2 ).source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).at( 2 ).outputChildId(), QStringLiteral( "cx2" ) );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).at( 2 ).outputName(), QStringLiteral( "out4" ) );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).at( 3 ).source(), QgsProcessingModelChildParameterSource::Expression );
|
|
QCOMPARE( alg6c1.parameterSources().value( "zm" ).at( 3 ).expression(), QStringLiteral( "1+2" ) );
|
|
|
|
QCOMPARE( alg6c1.modelOutputs().count(), 1 );
|
|
QCOMPARE( alg6c1.modelOutputs().value( QStringLiteral( "a" ) ).description(), QStringLiteral( "my output" ) );
|
|
QCOMPARE( alg6c1.modelOutput( "a" ).description(), QStringLiteral( "my output" ) );
|
|
QCOMPARE( alg6c1.modelOutput( "a" ).position().x(), 3.0 );
|
|
QCOMPARE( alg6c1.modelOutput( "a" ).position().y(), 4.0 );
|
|
|
|
|
|
QgsProcessingModelChildAlgorithm alg6c2 = alg6.childAlgorithm( "cx2" );
|
|
QCOMPARE( alg6c2.childId(), QStringLiteral( "cx2" ) );
|
|
QVERIFY( !alg6c2.isActive() );
|
|
QVERIFY( !alg6c2.outputsCollapsed() );
|
|
QVERIFY( !alg6c2.parametersCollapsed() );
|
|
QCOMPARE( alg6c2.dependencies(), QStringList() << "a" << "b" );
|
|
|
|
QCOMPARE( alg6.parameterComponents().count(), 1 );
|
|
QCOMPARE( alg6.parameterComponents().value( QStringLiteral( "my_param" ) ).parameterName(), QStringLiteral( "my_param" ) );
|
|
QCOMPARE( alg6.parameterComponent( "my_param" ).parameterName(), QStringLiteral( "my_param" ) );
|
|
QCOMPARE( alg6.parameterComponent( "my_param" ).position().x(), 11.0 );
|
|
QCOMPARE( alg6.parameterComponent( "my_param" ).position().y(), 12.0 );
|
|
QCOMPARE( alg6.parameterDefinitions().count(), 1 );
|
|
QCOMPARE( alg6.parameterDefinitions().at( 0 )->type(), QStringLiteral( "boolean" ) );
|
|
|
|
// destination parameters
|
|
QgsProcessingModelAlgorithm alg7( "test", "testGroup" );
|
|
QgsProcessingModelChildAlgorithm alg7c1;
|
|
alg7c1.setChildId( "cx1" );
|
|
alg7c1.setAlgorithmId( "native:centroids" );
|
|
QMap<QString, QgsProcessingModelOutput> alg7c1outputs;
|
|
QgsProcessingModelOutput alg7c1out1( QStringLiteral( "my_output" ) );
|
|
alg7c1out1.setChildId( "cx1" );
|
|
alg7c1out1.setChildOutputName( "OUTPUT" );
|
|
alg7c1out1.setDescription( QStringLiteral( "my output" ) );
|
|
alg7c1outputs.insert( QStringLiteral( "my_output" ), 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:my_output" ) );
|
|
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->description(), QStringLiteral( "my output" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingDestinationParameter * >( alg7.destinationParameterDefinitions().at( 0 ) )->originalProvider()->id(), QStringLiteral( "native" ) );
|
|
QCOMPARE( alg7.outputDefinitions().count(), 1 );
|
|
QCOMPARE( alg7.outputDefinitions().at( 0 )->name(), QStringLiteral( "cx1:my_output" ) );
|
|
QCOMPARE( alg7.outputDefinitions().at( 0 )->type(), QStringLiteral( "outputVector" ) );
|
|
QCOMPARE( alg7.outputDefinitions().at( 0 )->description(), QStringLiteral( "my output" ) );
|
|
|
|
QgsProcessingModelChildAlgorithm alg7c2;
|
|
alg7c2.setChildId( "cx2" );
|
|
alg7c2.setAlgorithmId( "native:centroids" );
|
|
QMap<QString, QgsProcessingModelOutput> alg7c2outputs;
|
|
QgsProcessingModelOutput alg7c2out1( QStringLiteral( "my_output2" ) );
|
|
alg7c2out1.setChildId( "cx2" );
|
|
alg7c2out1.setChildOutputName( "OUTPUT" );
|
|
alg7c2out1.setDescription( QStringLiteral( "my output2" ) );
|
|
alg7c2out1.setDefaultValue( QStringLiteral( "my value" ) );
|
|
alg7c2out1.setMandatory( true );
|
|
alg7c2outputs.insert( QStringLiteral( "my_output2" ), alg7c2out1 );
|
|
alg7c2.setModelOutputs( alg7c2outputs );
|
|
alg7.addChildAlgorithm( alg7c2 );
|
|
|
|
QCOMPARE( alg7.destinationParameterDefinitions().count(), 2 );
|
|
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->name(), QStringLiteral( "cx1:my_output" ) );
|
|
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->description(), QStringLiteral( "my output" ) );
|
|
QVERIFY( alg7.destinationParameterDefinitions().at( 0 )->defaultValue().isNull() );
|
|
QVERIFY( !( alg7.destinationParameterDefinitions().at( 0 )->flags() & QgsProcessingParameterDefinition::FlagOptional ) );
|
|
QCOMPARE( alg7.destinationParameterDefinitions().at( 1 )->name(), QStringLiteral( "cx2:my_output2" ) );
|
|
QCOMPARE( alg7.destinationParameterDefinitions().at( 1 )->description(), QStringLiteral( "my output2" ) );
|
|
QCOMPARE( alg7.destinationParameterDefinitions().at( 1 )->defaultValue().toString(), QStringLiteral( "my value" ) );
|
|
QVERIFY( !( alg7.destinationParameterDefinitions().at( 1 )->flags() & QgsProcessingParameterDefinition::FlagOptional ) );
|
|
QCOMPARE( alg7.outputDefinitions().count(), 2 );
|
|
QCOMPARE( alg7.outputDefinitions().at( 0 )->name(), QStringLiteral( "cx1:my_output" ) );
|
|
QCOMPARE( alg7.outputDefinitions().at( 0 )->type(), QStringLiteral( "outputVector" ) );
|
|
QCOMPARE( alg7.outputDefinitions().at( 0 )->description(), QStringLiteral( "my output" ) );
|
|
QCOMPARE( alg7.outputDefinitions().at( 1 )->name(), QStringLiteral( "cx2:my_output2" ) );
|
|
QCOMPARE( alg7.outputDefinitions().at( 1 )->type(), QStringLiteral( "outputVector" ) );
|
|
QCOMPARE( alg7.outputDefinitions().at( 1 )->description(), QStringLiteral( "my output2" ) );
|
|
|
|
alg7.removeChildAlgorithm( "cx1" );
|
|
QCOMPARE( alg7.destinationParameterDefinitions().count(), 1 );
|
|
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->name(), QStringLiteral( "cx2:my_output2" ) );
|
|
QCOMPARE( alg7.destinationParameterDefinitions().at( 0 )->description(), QStringLiteral( "my output2" ) );
|
|
QCOMPARE( alg7.outputDefinitions().count(), 1 );
|
|
QCOMPARE( alg7.outputDefinitions().at( 0 )->name(), QStringLiteral( "cx2:my_output2" ) );
|
|
QCOMPARE( alg7.outputDefinitions().at( 0 )->type(), QStringLiteral( "outputVector" ) );
|
|
QCOMPARE( alg7.outputDefinitions().at( 0 )->description(), QStringLiteral( "my output2" ) );
|
|
|
|
// mandatory model output with optional child algorithm parameter
|
|
QgsProcessingModelChildAlgorithm alg7c3;
|
|
alg7c3.setChildId( "cx3" );
|
|
alg7c3.setAlgorithmId( "native:extractbyexpression" );
|
|
QMap<QString, QgsProcessingModelOutput> alg7c3outputs;
|
|
QgsProcessingModelOutput alg7c3out1;
|
|
alg7c3out1.setChildId( "cx3" );
|
|
alg7c3out1.setChildOutputName( "FAIL_OUTPUT" );
|
|
alg7c3out1.setDescription( QStringLiteral( "my_output3" ) );
|
|
alg7c3outputs.insert( QStringLiteral( "my_output3" ), alg7c3out1 );
|
|
alg7c3.setModelOutputs( alg7c3outputs );
|
|
alg7.addChildAlgorithm( alg7c3 );
|
|
QVERIFY( alg7.destinationParameterDefinitions().at( 1 )->flags() & QgsProcessingParameterDefinition::FlagOptional );
|
|
alg7.childAlgorithm( alg7c3.childId() ).modelOutput( QStringLiteral( "my_output3" ) ).setMandatory( true );
|
|
alg7.updateDestinationParameters();
|
|
QVERIFY( !( alg7.destinationParameterDefinitions().at( 1 )->flags() & QgsProcessingParameterDefinition::FlagOptional ) );
|
|
}
|
|
|
|
void TestQgsProcessing::modelExecution()
|
|
{
|
|
// test childOutputIsRequired
|
|
QgsProcessingModelAlgorithm model1;
|
|
QgsProcessingModelChildAlgorithm algc1;
|
|
algc1.setChildId( "cx1" );
|
|
algc1.setAlgorithmId( "native:centroids" );
|
|
model1.addChildAlgorithm( algc1 );
|
|
QgsProcessingModelChildAlgorithm algc2;
|
|
algc2.setChildId( "cx2" );
|
|
algc2.setAlgorithmId( "native:centroids" );
|
|
algc2.addParameterSources( "x", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromChildOutput( "cx1", "p1" ) );
|
|
model1.addChildAlgorithm( algc2 );
|
|
QgsProcessingModelChildAlgorithm algc3;
|
|
algc3.setChildId( "cx3" );
|
|
algc3.setAlgorithmId( "native:centroids" );
|
|
algc3.addParameterSources( "x", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromChildOutput( "cx1", "p2" ) );
|
|
algc3.setActive( false );
|
|
model1.addChildAlgorithm( algc3 );
|
|
|
|
QVERIFY( model1.childOutputIsRequired( "cx1", "p1" ) ); // cx2 depends on p1
|
|
QVERIFY( !model1.childOutputIsRequired( "cx1", "p2" ) ); // cx3 depends on p2, but cx3 is not active
|
|
QVERIFY( !model1.childOutputIsRequired( "cx1", "p3" ) ); // nothing requires p3
|
|
QVERIFY( !model1.childOutputIsRequired( "cx2", "p1" ) );
|
|
QVERIFY( !model1.childOutputIsRequired( "cx3", "p1" ) );
|
|
|
|
// test parametersForChildAlgorithm
|
|
QgsProcessingModelAlgorithm model2;
|
|
model2.addModelParameter( new QgsProcessingParameterFeatureSource( "SOURCE_LAYER" ), QgsProcessingModelParameter( "SOURCE_LAYER" ) );
|
|
model2.addModelParameter( new QgsProcessingParameterNumber( "DIST", QString(), QgsProcessingParameterNumber::Double ), QgsProcessingModelParameter( "DIST" ) );
|
|
QgsProcessingModelChildAlgorithm alg2c1;
|
|
QgsExpressionContext expContext;
|
|
QgsExpressionContextScope *scope = new QgsExpressionContextScope();
|
|
scope->setVariable( "myvar", 8 );
|
|
expContext.appendScope( scope );
|
|
alg2c1.setChildId( "cx1" );
|
|
alg2c1.setAlgorithmId( "native:buffer" );
|
|
alg2c1.addParameterSources( "INPUT", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromModelParameter( "SOURCE_LAYER" ) );
|
|
alg2c1.addParameterSources( "DISTANCE", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromModelParameter( "DIST" ) );
|
|
alg2c1.addParameterSources( "SEGMENTS", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromExpression( QStringLiteral( "@myvar*2" ) ) );
|
|
alg2c1.addParameterSources( "END_CAP_STYLE", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromStaticValue( 1 ) );
|
|
alg2c1.addParameterSources( "JOIN_STYLE", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromStaticValue( 2 ) );
|
|
alg2c1.addParameterSources( "DISSOLVE", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromStaticValue( false ) );
|
|
QMap<QString, QgsProcessingModelOutput> outputs1;
|
|
QgsProcessingModelOutput out1( "MODEL_OUT_LAYER" );
|
|
out1.setChildOutputName( "OUTPUT" );
|
|
outputs1.insert( QStringLiteral( "MODEL_OUT_LAYER" ), out1 );
|
|
alg2c1.setModelOutputs( outputs1 );
|
|
model2.addChildAlgorithm( alg2c1 );
|
|
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString vector = testDataDir + "points.shp";
|
|
|
|
QVariantMap modelInputs;
|
|
modelInputs.insert( "SOURCE_LAYER", vector );
|
|
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 ) );
|
|
QVariantMap childResults;
|
|
QVariantMap params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx1" ), modelInputs, childResults, expContext );
|
|
QCOMPARE( params.value( "DISSOLVE" ).toBool(), false );
|
|
QCOMPARE( params.value( "DISTANCE" ).toInt(), 271 );
|
|
QCOMPARE( params.value( "SEGMENTS" ).toInt(), 16 );
|
|
QCOMPARE( params.value( "END_CAP_STYLE" ).toInt(), 1 );
|
|
QCOMPARE( params.value( "JOIN_STYLE" ).toInt(), 2 );
|
|
QCOMPARE( params.value( "INPUT" ).toString(), vector );
|
|
QCOMPARE( params.value( "OUTPUT" ).toString(), QStringLiteral( "dest.shp" ) );
|
|
QCOMPARE( params.count(), 7 );
|
|
|
|
QgsProcessingContext context;
|
|
|
|
// Check variables for child algorithm
|
|
// without values
|
|
QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = model2.variablesForChildAlgorithm( "cx1", context );
|
|
QCOMPARE( variables.count(), 5 );
|
|
QCOMPARE( variables.value( "DIST" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_minx" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_miny" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_maxx" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_maxy" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
|
|
// with values
|
|
variables = model2.variablesForChildAlgorithm( "cx1", context, modelInputs, childResults );
|
|
QCOMPARE( variables.count(), 5 );
|
|
QCOMPARE( variables.value( "DIST" ).value.toInt(), 271 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_minx" ).value.toDouble(), -118.8888, 0.001 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_miny" ).value.toDouble(), 22.8002, 0.001 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_maxx" ).value.toDouble(), -83.3333, 0.001 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_maxy" ).value.toDouble(), 46.8719, 0.001 );
|
|
|
|
std::unique_ptr< QgsExpressionContextScope > childScope( model2.createExpressionContextScopeForChildAlgorithm( "cx1", context, modelInputs, childResults ) );
|
|
QCOMPARE( childScope->variableCount(), 5 );
|
|
QCOMPARE( childScope->variable( "DIST" ).toInt(), 271 );
|
|
QGSCOMPARENEAR( childScope->variable( "SOURCE_LAYER_minx" ).toDouble(), -118.8888, 0.001 );
|
|
QGSCOMPARENEAR( childScope->variable( "SOURCE_LAYER_miny" ).toDouble(), 22.8002, 0.001 );
|
|
QGSCOMPARENEAR( childScope->variable( "SOURCE_LAYER_maxx" ).toDouble(), -83.3333, 0.001 );
|
|
QGSCOMPARENEAR( childScope->variable( "SOURCE_LAYER_maxy" ).toDouble(), 46.8719, 0.001 );
|
|
|
|
|
|
QVariantMap results;
|
|
results.insert( "OUTPUT", QStringLiteral( "dest.shp" ) );
|
|
childResults.insert( "cx1", results );
|
|
|
|
// a child who uses an output from another alg as a parameter value
|
|
QgsProcessingModelChildAlgorithm alg2c2;
|
|
alg2c2.setChildId( "cx2" );
|
|
alg2c2.setAlgorithmId( "native:centroids" );
|
|
alg2c2.addParameterSources( "INPUT", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromChildOutput( "cx1", "OUTPUT" ) );
|
|
model2.addChildAlgorithm( alg2c2 );
|
|
params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx2" ), modelInputs, childResults, expContext );
|
|
QCOMPARE( params.value( "INPUT" ).toString(), QStringLiteral( "dest.shp" ) );
|
|
QCOMPARE( params.value( "OUTPUT" ).toString(), QStringLiteral( "memory:Centroids" ) );
|
|
QCOMPARE( params.count(), 2 );
|
|
|
|
variables = model2.variablesForChildAlgorithm( "cx2", context );
|
|
QCOMPARE( variables.count(), 9 );
|
|
QCOMPARE( variables.value( "DIST" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_minx" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_miny" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_maxx" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_maxy" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_minx" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_minx" ).source.outputChildId(), QStringLiteral( "cx1" ) );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_miny" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_miny" ).source.outputChildId(), QStringLiteral( "cx1" ) );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_maxx" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_maxx" ).source.outputChildId(), QStringLiteral( "cx1" ) );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_maxy" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_maxy" ).source.outputChildId(), QStringLiteral( "cx1" ) );
|
|
|
|
// with values
|
|
variables = model2.variablesForChildAlgorithm( "cx2", context, modelInputs, childResults );
|
|
QCOMPARE( variables.count(), 9 );
|
|
QCOMPARE( variables.value( "DIST" ).value.toInt(), 271 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_minx" ).value.toDouble(), -118.8888, 0.001 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_miny" ).value.toDouble(), 22.8002, 0.001 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_maxx" ).value.toDouble(), -83.3333, 0.001 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_maxy" ).value.toDouble(), 46.8719, 0.001 );
|
|
|
|
// a child with an optional output
|
|
QgsProcessingModelChildAlgorithm alg2c3;
|
|
alg2c3.setChildId( "cx3" );
|
|
alg2c3.setAlgorithmId( "native:extractbyexpression" );
|
|
alg2c3.addParameterSources( "INPUT", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromChildOutput( "cx1", "OUTPUT" ) );
|
|
alg2c3.addParameterSources( "EXPRESSION", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromStaticValue( "true" ) );
|
|
alg2c3.addParameterSources( "OUTPUT", QgsProcessingModelChildParameterSources() << QgsProcessingModelChildParameterSource::fromModelParameter( "MY_OUT" ) );
|
|
alg2c3.setDependencies( QStringList() << "cx2" );
|
|
QMap<QString, QgsProcessingModelOutput> outputs3;
|
|
QgsProcessingModelOutput 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, expContext );
|
|
QCOMPARE( params.value( "INPUT" ).toString(), QStringLiteral( "dest.shp" ) );
|
|
QCOMPARE( params.value( "EXPRESSION" ).toString(), QStringLiteral( "true" ) );
|
|
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!
|
|
|
|
variables = model2.variablesForChildAlgorithm( "cx3", context );
|
|
QCOMPARE( variables.count(), 13 );
|
|
QCOMPARE( variables.value( "DIST" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_minx" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_miny" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_maxx" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "SOURCE_LAYER_maxy" ).source.source(), QgsProcessingModelChildParameterSource::ModelParameter );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_minx" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_minx" ).source.outputChildId(), QStringLiteral( "cx1" ) );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_miny" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_miny" ).source.outputChildId(), QStringLiteral( "cx1" ) );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_maxx" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_maxx" ).source.outputChildId(), QStringLiteral( "cx1" ) );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_maxy" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx1_OUTPUT_maxy" ).source.outputChildId(), QStringLiteral( "cx1" ) );
|
|
QCOMPARE( variables.value( "cx2_OUTPUT_minx" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx2_OUTPUT_minx" ).source.outputChildId(), QStringLiteral( "cx2" ) );
|
|
QCOMPARE( variables.value( "cx2_OUTPUT_miny" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx2_OUTPUT_miny" ).source.outputChildId(), QStringLiteral( "cx2" ) );
|
|
QCOMPARE( variables.value( "cx2_OUTPUT_maxx" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx2_OUTPUT_maxx" ).source.outputChildId(), QStringLiteral( "cx2" ) );
|
|
QCOMPARE( variables.value( "cx2_OUTPUT_maxy" ).source.source(), QgsProcessingModelChildParameterSource::ChildOutput );
|
|
QCOMPARE( variables.value( "cx2_OUTPUT_maxy" ).source.outputChildId(), QStringLiteral( "cx2" ) );
|
|
// with values
|
|
variables = model2.variablesForChildAlgorithm( "cx3", context, modelInputs, childResults );
|
|
QCOMPARE( variables.count(), 13 );
|
|
QCOMPARE( variables.value( "DIST" ).value.toInt(), 271 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_minx" ).value.toDouble(), -118.8888, 0.001 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_miny" ).value.toDouble(), 22.8002, 0.001 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_maxx" ).value.toDouble(), -83.3333, 0.001 );
|
|
QGSCOMPARENEAR( variables.value( "SOURCE_LAYER_maxy" ).value.toDouble(), 46.8719, 0.001 );
|
|
|
|
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':QgsExpression('@myvar*2').evaluate()}, context=context, feedback=feedback)\n"
|
|
"results['MODEL_OUT_LAYER']=outputs['cx1']['OUTPUT']\n"
|
|
"outputs['cx2']=processing.run('native:centroids', {'INPUT':outputs['cx1']['OUTPUT']}, context=context, feedback=feedback)\n"
|
|
"outputs['cx3']=processing.run('native:extractbyexpression', {'EXPRESSION':true,'INPUT':outputs['cx1']['OUTPUT'],'OUTPUT':parameters['MY_OUT']}, context=context, feedback=feedback)\n"
|
|
"results['MY_OUT']=outputs['cx3']['OUTPUT']\n"
|
|
"return results" ).split( '\n' );
|
|
QCOMPARE( actualParts, expectedParts );
|
|
}
|
|
|
|
void TestQgsProcessing::modelWithProviderWithLimitedTypes()
|
|
{
|
|
QgsApplication::processingRegistry()->addProvider( new DummyProvider4() );
|
|
|
|
QgsProcessingModelAlgorithm alg( "test", "testGroup" );
|
|
QgsProcessingModelChildAlgorithm algc1;
|
|
algc1.setChildId( "cx1" );
|
|
algc1.setAlgorithmId( "dummy4:alg1" );
|
|
QMap<QString, QgsProcessingModelOutput> algc1outputs;
|
|
QgsProcessingModelOutput algc1out1( QStringLiteral( "my_vector_output" ) );
|
|
algc1out1.setChildId( "cx1" );
|
|
algc1out1.setChildOutputName( "vector_dest" );
|
|
algc1out1.setDescription( QStringLiteral( "my output" ) );
|
|
algc1outputs.insert( QStringLiteral( "my_vector_output" ), algc1out1 );
|
|
QgsProcessingModelOutput algc1out2( QStringLiteral( "my_raster_output" ) );
|
|
algc1out2.setChildId( "cx1" );
|
|
algc1out2.setChildOutputName( "raster_dest" );
|
|
algc1out2.setDescription( QStringLiteral( "my output" ) );
|
|
algc1outputs.insert( QStringLiteral( "my_raster_output" ), algc1out2 );
|
|
QgsProcessingModelOutput algc1out3( QStringLiteral( "my_sink_output" ) );
|
|
algc1out3.setChildId( "cx1" );
|
|
algc1out3.setChildOutputName( "sink" );
|
|
algc1out3.setDescription( QStringLiteral( "my output" ) );
|
|
algc1outputs.insert( QStringLiteral( "my_sink_output" ), algc1out3 );
|
|
algc1.setModelOutputs( algc1outputs );
|
|
alg.addChildAlgorithm( algc1 );
|
|
// verify that model has destination parameter created
|
|
QCOMPARE( alg.destinationParameterDefinitions().count(), 3 );
|
|
QCOMPARE( alg.destinationParameterDefinitions().at( 2 )->name(), QStringLiteral( "cx1:my_vector_output" ) );
|
|
QCOMPARE( alg.destinationParameterDefinitions().at( 2 )->description(), QStringLiteral( "my output" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingDestinationParameter * >( alg.destinationParameterDefinitions().at( 2 ) )->originalProvider()->id(), QStringLiteral( "dummy4" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingParameterVectorDestination * >( alg.destinationParameterDefinitions().at( 2 ) )->supportedOutputVectorLayerExtensions(), QStringList() << QStringLiteral( "mif" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingParameterVectorDestination * >( alg.destinationParameterDefinitions().at( 2 ) )->defaultFileExtension(), QStringLiteral( "mif" ) );
|
|
QVERIFY( static_cast< const QgsProcessingParameterVectorDestination * >( alg.destinationParameterDefinitions().at( 2 ) )->generateTemporaryDestination().endsWith( QStringLiteral( ".mif" ) ) );
|
|
QVERIFY( !static_cast< const QgsProcessingDestinationParameter * >( alg.destinationParameterDefinitions().at( 2 ) )->supportsNonFileBasedOutput() );
|
|
|
|
QCOMPARE( alg.destinationParameterDefinitions().at( 0 )->name(), QStringLiteral( "cx1:my_raster_output" ) );
|
|
QCOMPARE( alg.destinationParameterDefinitions().at( 0 )->description(), QStringLiteral( "my output" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingDestinationParameter * >( alg.destinationParameterDefinitions().at( 0 ) )->originalProvider()->id(), QStringLiteral( "dummy4" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingParameterRasterDestination * >( alg.destinationParameterDefinitions().at( 0 ) )->supportedOutputRasterLayerExtensions(), QStringList() << QStringLiteral( "mig" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingParameterRasterDestination * >( alg.destinationParameterDefinitions().at( 0 ) )->defaultFileExtension(), QStringLiteral( "mig" ) );
|
|
QVERIFY( static_cast< const QgsProcessingParameterRasterDestination * >( alg.destinationParameterDefinitions().at( 0 ) )->generateTemporaryDestination().endsWith( QStringLiteral( ".mig" ) ) );
|
|
QVERIFY( !static_cast< const QgsProcessingDestinationParameter * >( alg.destinationParameterDefinitions().at( 0 ) )->supportsNonFileBasedOutput() );
|
|
|
|
QCOMPARE( alg.destinationParameterDefinitions().at( 1 )->name(), QStringLiteral( "cx1:my_sink_output" ) );
|
|
QCOMPARE( alg.destinationParameterDefinitions().at( 1 )->description(), QStringLiteral( "my output" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingDestinationParameter * >( alg.destinationParameterDefinitions().at( 1 ) )->originalProvider()->id(), QStringLiteral( "dummy4" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingParameterFeatureSink * >( alg.destinationParameterDefinitions().at( 1 ) )->supportedOutputVectorLayerExtensions(), QStringList() << QStringLiteral( "mif" ) );
|
|
QCOMPARE( static_cast< const QgsProcessingParameterFeatureSink * >( alg.destinationParameterDefinitions().at( 1 ) )->defaultFileExtension(), QStringLiteral( "mif" ) );
|
|
QVERIFY( static_cast< const QgsProcessingParameterFeatureSink * >( alg.destinationParameterDefinitions().at( 1 ) )->generateTemporaryDestination().endsWith( QStringLiteral( ".mif" ) ) );
|
|
QVERIFY( !static_cast< const QgsProcessingDestinationParameter * >( alg.destinationParameterDefinitions().at( 1 ) )->supportsNonFileBasedOutput() );
|
|
}
|
|
|
|
void TestQgsProcessing::modelVectorOutputIsCompatibleType()
|
|
{
|
|
// IMPORTANT: This method is intended to be "permissive" rather than "restrictive".
|
|
// I.e. we only reject outputs which we know can NEVER be acceptable, but
|
|
// if there's doubt then we default to returning true.
|
|
|
|
// empty acceptable type list = all are compatible
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( QList<int>(), QgsProcessing::TypeVector ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( QList<int>(), QgsProcessing::TypeVectorAnyGeometry ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( QList<int>(), QgsProcessing::TypeVectorPoint ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( QList<int>(), QgsProcessing::TypeVectorLine ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( QList<int>(), QgsProcessing::TypeVectorPolygon ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( QList<int>(), QgsProcessing::TypeMapLayer ) );
|
|
|
|
// accept any vector
|
|
QList< int > dataTypes;
|
|
dataTypes << QgsProcessing::TypeVector;
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVector ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorAnyGeometry ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPoint ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorLine ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPolygon ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeMapLayer ) );
|
|
|
|
// accept any vector with geometry
|
|
dataTypes.clear();
|
|
dataTypes << QgsProcessing::TypeVectorAnyGeometry;
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVector ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorAnyGeometry ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPoint ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorLine ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPolygon ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeMapLayer ) );
|
|
|
|
// accept any point vector
|
|
dataTypes.clear();
|
|
dataTypes << QgsProcessing::TypeVectorPoint;
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVector ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorAnyGeometry ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPoint ) );
|
|
QVERIFY( !QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorLine ) );
|
|
QVERIFY( !QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPolygon ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeMapLayer ) );
|
|
|
|
// accept any line vector
|
|
dataTypes.clear();
|
|
dataTypes << QgsProcessing::TypeVectorLine;
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVector ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorAnyGeometry ) );
|
|
QVERIFY( !QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPoint ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorLine ) );
|
|
QVERIFY( !QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPolygon ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeMapLayer ) );
|
|
|
|
// accept any polygon vector
|
|
dataTypes.clear();
|
|
dataTypes << QgsProcessing::TypeVectorPolygon;
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVector ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorAnyGeometry ) );
|
|
QVERIFY( !QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPoint ) );
|
|
QVERIFY( !QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorLine ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPolygon ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeMapLayer ) );
|
|
|
|
// accept any map layer
|
|
dataTypes.clear();
|
|
dataTypes << QgsProcessing::TypeMapLayer;
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVector ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorAnyGeometry ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPoint ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorLine ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeVectorPolygon ) );
|
|
QVERIFY( QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( dataTypes, QgsProcessing::TypeMapLayer ) );
|
|
}
|
|
|
|
void TestQgsProcessing::modelAcceptableValues()
|
|
{
|
|
QgsProcessingModelAlgorithm m;
|
|
QgsProcessingModelParameter stringParam1( "string" );
|
|
m.addModelParameter( new QgsProcessingParameterString( "string" ), stringParam1 );
|
|
|
|
QgsProcessingModelParameter stringParam2( "string2" );
|
|
m.addModelParameter( new QgsProcessingParameterString( "string2" ), stringParam2 );
|
|
|
|
QgsProcessingModelParameter numParam( "number" );
|
|
m.addModelParameter( new QgsProcessingParameterNumber( "number" ), numParam );
|
|
|
|
QgsProcessingModelParameter tableFieldParam( "field" );
|
|
m.addModelParameter( new QgsProcessingParameterField( "field" ), tableFieldParam );
|
|
|
|
QgsProcessingModelParameter fileParam( "file" );
|
|
m.addModelParameter( new QgsProcessingParameterFile( "file" ), fileParam );
|
|
|
|
// test single types
|
|
QgsProcessingModelChildParameterSources sources = m.availableSourcesForChild( QString(), QStringList() << "number" );
|
|
QCOMPARE( sources.count(), 1 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "number" ) );
|
|
sources = m.availableSourcesForChild( QString(), QStringList() << "field" );
|
|
QCOMPARE( sources.count(), 1 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "field" ) );
|
|
sources = m.availableSourcesForChild( QString(), QStringList() << "file" );
|
|
QCOMPARE( sources.count(), 1 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "file" ) );
|
|
|
|
// test multiple types
|
|
sources = m.availableSourcesForChild( QString(), QStringList() << "string" << "number" << "file" );
|
|
QCOMPARE( sources.count(), 4 );
|
|
QSet< QString > res;
|
|
res << sources.at( 0 ).parameterName();
|
|
res << sources.at( 1 ).parameterName();
|
|
res << sources.at( 2 ).parameterName();
|
|
res << sources.at( 3 ).parameterName();
|
|
|
|
QCOMPARE( res, QSet< QString >() << QStringLiteral( "string" )
|
|
<< QStringLiteral( "string2" )
|
|
<< QStringLiteral( "number" )
|
|
<< QStringLiteral( "file" ) );
|
|
|
|
// check outputs
|
|
QgsProcessingModelChildAlgorithm alg2c1;
|
|
alg2c1.setChildId( "cx1" );
|
|
alg2c1.setAlgorithmId( "native:centroids" );
|
|
m.addChildAlgorithm( alg2c1 );
|
|
|
|
sources = m.availableSourcesForChild( QString(), QStringList(), QStringList() << "string" << "outputVector" );
|
|
QCOMPARE( sources.count(), 1 );
|
|
res.clear();
|
|
res << sources.at( 0 ).outputChildId() + ':' + sources.at( 0 ).outputName();
|
|
QCOMPARE( res, QSet< QString >() << "cx1:OUTPUT" );
|
|
|
|
// with dependencies between child algs
|
|
QgsProcessingModelChildAlgorithm alg2c2;
|
|
alg2c2.setChildId( "cx2" );
|
|
alg2c2.setAlgorithmId( "native:centroids" );
|
|
alg2c2.setDependencies( QStringList() << "cx1" );
|
|
m.addChildAlgorithm( alg2c2 );
|
|
sources = m.availableSourcesForChild( QString(), QStringList(), QStringList() << "string" << "outputVector" );
|
|
QCOMPARE( sources.count(), 2 );
|
|
res.clear();
|
|
res << sources.at( 0 ).outputChildId() + ':' + sources.at( 0 ).outputName();
|
|
res << sources.at( 1 ).outputChildId() + ':' + sources.at( 1 ).outputName();
|
|
QCOMPARE( res, QSet< QString >() << "cx1:OUTPUT" << "cx2:OUTPUT" );
|
|
|
|
sources = m.availableSourcesForChild( QStringLiteral( "cx1" ), QStringList(), QStringList() << "string" << "outputVector" );
|
|
QCOMPARE( sources.count(), 0 );
|
|
|
|
sources = m.availableSourcesForChild( QString( "cx2" ), QStringList(), QStringList() << "string" << "outputVector" );
|
|
QCOMPARE( sources.count(), 1 );
|
|
res.clear();
|
|
res << sources.at( 0 ).outputChildId() + ':' + sources.at( 0 ).outputName();
|
|
QCOMPARE( res, QSet< QString >() << "cx1:OUTPUT" );
|
|
|
|
// test limiting by data types
|
|
QgsProcessingModelAlgorithm m2;
|
|
QgsProcessingModelParameter vlInput( "vl" );
|
|
// with no limit on data types
|
|
m2.addModelParameter( new QgsProcessingParameterVectorLayer( "vl" ), vlInput );
|
|
QgsProcessingModelParameter fsInput( "fs" );
|
|
m2.addModelParameter( new QgsProcessingParameterFeatureSource( "fs" ), fsInput );
|
|
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source" );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorPoint );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVector );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorAnyGeometry );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeMapLayer );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
|
|
// inputs are limited to vector layers
|
|
m2.removeModelParameter( vlInput.parameterName() );
|
|
m2.removeModelParameter( fsInput.parameterName() );
|
|
m2.addModelParameter( new QgsProcessingParameterVectorLayer( "vl", QString(), QList<int>() << QgsProcessing::TypeVector ), vlInput );
|
|
m2.addModelParameter( new QgsProcessingParameterFeatureSource( "fs", QString(), QList<int>() << QgsProcessing::TypeVector ), fsInput );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source" );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorPoint );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVector );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorAnyGeometry );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeMapLayer );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
|
|
// inputs are limited to vector layers with geometries
|
|
m2.removeModelParameter( vlInput.parameterName() );
|
|
m2.removeModelParameter( fsInput.parameterName() );
|
|
m2.addModelParameter( new QgsProcessingParameterVectorLayer( "vl", QString(), QList<int>() << QgsProcessing::TypeVectorAnyGeometry ), vlInput );
|
|
m2.addModelParameter( new QgsProcessingParameterFeatureSource( "fs", QString(), QList<int>() << QgsProcessing::TypeVectorAnyGeometry ), fsInput );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source" );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorPoint );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVector );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorAnyGeometry );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeMapLayer );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
|
|
// inputs are limited to vector layers with lines
|
|
m2.removeModelParameter( vlInput.parameterName() );
|
|
m2.removeModelParameter( fsInput.parameterName() );
|
|
m2.addModelParameter( new QgsProcessingParameterVectorLayer( "vl", QString(), QList<int>() << QgsProcessing::TypeVectorLine ), vlInput );
|
|
m2.addModelParameter( new QgsProcessingParameterFeatureSource( "fs", QString(), QList<int>() << QgsProcessing::TypeVectorLine ), fsInput );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source" );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorPoint );
|
|
QCOMPARE( sources.count(), 0 );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorPolygon );
|
|
QCOMPARE( sources.count(), 0 );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorLine );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVector );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeVectorAnyGeometry );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList<int>() << QgsProcessing::TypeMapLayer );
|
|
QCOMPARE( sources.count(), 2 );
|
|
QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) );
|
|
QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::tempUtils()
|
|
{
|
|
QString tempFolder = QgsProcessingUtils::tempFolder();
|
|
// tempFolder should remain constant for session
|
|
QCOMPARE( QgsProcessingUtils::tempFolder(), tempFolder );
|
|
|
|
QString tempFile1 = QgsProcessingUtils::generateTempFilename( "test.txt" );
|
|
QVERIFY( tempFile1.endsWith( "test.txt" ) );
|
|
QVERIFY( tempFile1.startsWith( tempFolder ) );
|
|
|
|
// expect a different file
|
|
QString tempFile2 = QgsProcessingUtils::generateTempFilename( "test.txt" );
|
|
QVERIFY( tempFile1 != tempFile2 );
|
|
QVERIFY( tempFile2.endsWith( "test.txt" ) );
|
|
QVERIFY( tempFile2.startsWith( tempFolder ) );
|
|
|
|
// invalid characters
|
|
QString tempFile3 = QgsProcessingUtils::generateTempFilename( "mybad:file.txt" );
|
|
QVERIFY( tempFile3.endsWith( "mybad_file.txt" ) );
|
|
QVERIFY( tempFile3.startsWith( tempFolder ) );
|
|
}
|
|
|
|
void TestQgsProcessing::convertCompatible()
|
|
{
|
|
// start with a compatible shapefile
|
|
QString testDataDir = QStringLiteral( TEST_DATA_DIR ) + '/'; //defined in CmakeLists.txt
|
|
QString vector = testDataDir + "points.shp";
|
|
QgsVectorLayer *layer = new QgsVectorLayer( vector, "vl" );
|
|
QgsProject p;
|
|
p.addMapLayer( layer );
|
|
|
|
QgsProcessingContext context;
|
|
context.setProject( &p );
|
|
QgsProcessingFeedback feedback;
|
|
QString out = QgsProcessingUtils::convertToCompatibleFormat( layer, false, QStringLiteral( "test" ), QStringList() << "shp", QString( "shp" ), context, &feedback );
|
|
// layer should be returned unchanged - underlying source is compatible
|
|
QCOMPARE( out, layer->source() );
|
|
|
|
// don't include shp as compatible type
|
|
out = QgsProcessingUtils::convertToCompatibleFormat( layer, false, QStringLiteral( "test" ), QStringList() << "tab", QString( "tab" ), context, &feedback );
|
|
QVERIFY( out != layer->source() );
|
|
QVERIFY( out.endsWith( ".tab" ) );
|
|
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
|
|
// make sure all features are copied
|
|
std::unique_ptr< QgsVectorLayer > t = qgis::make_unique< QgsVectorLayer >( out, "vl2" );
|
|
QCOMPARE( layer->featureCount(), t->featureCount() );
|
|
QCOMPARE( layer->crs(), t->crs() );
|
|
|
|
// use a selection - this will require translation
|
|
QgsFeatureIds ids;
|
|
QgsFeature f;
|
|
QgsFeatureIterator it = layer->getFeatures();
|
|
it.nextFeature( f );
|
|
ids.insert( f.id() );
|
|
it.nextFeature( f );
|
|
ids.insert( f.id() );
|
|
|
|
layer->selectByIds( ids );
|
|
out = QgsProcessingUtils::convertToCompatibleFormat( layer, true, QStringLiteral( "test" ), QStringList() << "tab", QString( "tab" ), context, &feedback );
|
|
QVERIFY( out != layer->source() );
|
|
QVERIFY( out.endsWith( ".tab" ) );
|
|
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
t = qgis::make_unique< QgsVectorLayer >( out, "vl2" );
|
|
QCOMPARE( t->featureCount(), static_cast< long >( ids.count() ) );
|
|
|
|
// using a selection but existing format - will still require translation
|
|
out = QgsProcessingUtils::convertToCompatibleFormat( layer, true, QStringLiteral( "test" ), QStringList() << "shp", QString( "shp" ), context, &feedback );
|
|
QVERIFY( out != layer->source() );
|
|
QVERIFY( out.endsWith( ".shp" ) );
|
|
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
t = qgis::make_unique< QgsVectorLayer >( out, "vl2" );
|
|
QCOMPARE( t->featureCount(), static_cast< long >( ids.count() ) );
|
|
|
|
|
|
// also test evaluating parameter to compatible format
|
|
std::unique_ptr< QgsProcessingParameterDefinition > def( new QgsProcessingParameterFeatureSource( QStringLiteral( "source" ) ) );
|
|
QVariantMap params;
|
|
params.insert( QStringLiteral( "source" ), QgsProcessingFeatureSourceDefinition( layer->id(), false ) );
|
|
out = QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( def.get(), params, context, QStringList() << "shp", QString( "shp" ), &feedback );
|
|
QCOMPARE( out, layer->source() );
|
|
|
|
// incompatible format, will be converted
|
|
out = QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( def.get(), params, context, QStringList() << "tab", QString( "tab" ), &feedback );
|
|
QVERIFY( out != layer->source() );
|
|
QVERIFY( out.endsWith( ".tab" ) );
|
|
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
|
|
// layer as input
|
|
params.insert( QStringLiteral( "source" ), QVariant::fromValue( layer ) );
|
|
out = QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( def.get(), params, context, QStringList() << "shp", QString( "shp" ), &feedback );
|
|
QCOMPARE( out, layer->source() );
|
|
|
|
// incompatible format, will be converted
|
|
out = QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( def.get(), params, context, QStringList() << "tab", QString( "tab" ), &feedback );
|
|
QVERIFY( out != layer->source() );
|
|
QVERIFY( out.endsWith( ".tab" ) );
|
|
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
|
|
// selected only, will force export
|
|
params.insert( QStringLiteral( "source" ), QgsProcessingFeatureSourceDefinition( layer->id(), true ) );
|
|
out = QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( def.get(), params, context, QStringList() << "shp", QString( "shp" ), &feedback );
|
|
QVERIFY( out != layer->source() );
|
|
QVERIFY( out.endsWith( ".shp" ) );
|
|
QVERIFY( out.startsWith( QgsProcessingUtils::tempFolder() ) );
|
|
|
|
// vector layer as default
|
|
def.reset( new QgsProcessingParameterFeatureSource( QStringLiteral( "source" ), QString(), QList<int>(), QVariant::fromValue( layer ) ) );
|
|
params.remove( QStringLiteral( "source" ) );
|
|
out = QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( def.get(), params, context, QStringList() << "shp", QString( "shp" ), &feedback );
|
|
QCOMPARE( out, layer->source() );
|
|
}
|
|
|
|
void TestQgsProcessing::create()
|
|
{
|
|
DummyAlgorithm alg( QStringLiteral( "test" ) );
|
|
DummyProvider p( QStringLiteral( "test_provider" ) );
|
|
alg.setProvider( &p );
|
|
|
|
std::unique_ptr< QgsProcessingAlgorithm > newInstance( alg.create() );
|
|
QVERIFY( newInstance.get() );
|
|
QCOMPARE( newInstance->provider(), &p );
|
|
}
|
|
|
|
void TestQgsProcessing::combineFields()
|
|
{
|
|
QgsFields a;
|
|
QgsFields b;
|
|
// combine empty fields
|
|
QgsFields res = QgsProcessingUtils::combineFields( a, b );
|
|
QVERIFY( res.isEmpty() );
|
|
|
|
// fields in a
|
|
a.append( QgsField( "name" ) );
|
|
res = QgsProcessingUtils::combineFields( a, b );
|
|
QCOMPARE( res.count(), 1 );
|
|
QCOMPARE( res.at( 0 ).name(), QStringLiteral( "name" ) );
|
|
b.append( QgsField( "name" ) );
|
|
res = QgsProcessingUtils::combineFields( a, b );
|
|
QCOMPARE( res.count(), 2 );
|
|
QCOMPARE( res.at( 0 ).name(), QStringLiteral( "name" ) );
|
|
QCOMPARE( res.at( 1 ).name(), QStringLiteral( "name_2" ) );
|
|
|
|
a.append( QgsField( "NEW" ) );
|
|
res = QgsProcessingUtils::combineFields( a, b );
|
|
QCOMPARE( res.count(), 3 );
|
|
QCOMPARE( res.at( 0 ).name(), QStringLiteral( "name" ) );
|
|
QCOMPARE( res.at( 1 ).name(), QStringLiteral( "NEW" ) );
|
|
QCOMPARE( res.at( 2 ).name(), QStringLiteral( "name_2" ) );
|
|
|
|
b.append( QgsField( "new" ) );
|
|
res = QgsProcessingUtils::combineFields( a, b );
|
|
QCOMPARE( res.count(), 4 );
|
|
QCOMPARE( res.at( 0 ).name(), QStringLiteral( "name" ) );
|
|
QCOMPARE( res.at( 1 ).name(), QStringLiteral( "NEW" ) );
|
|
QCOMPARE( res.at( 2 ).name(), QStringLiteral( "name_2" ) );
|
|
QCOMPARE( res.at( 3 ).name(), QStringLiteral( "new_2" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::fieldNamesToIndices()
|
|
{
|
|
QgsFields fields;
|
|
fields.append( QgsField( "name" ) );
|
|
fields.append( QgsField( "address" ) );
|
|
fields.append( QgsField( "age" ) );
|
|
|
|
QList<int> indices1 = QgsProcessingUtils::fieldNamesToIndices( QStringList(), fields );
|
|
QCOMPARE( indices1, QList<int>() << 0 << 1 << 2 );
|
|
|
|
QList<int> indices2 = QgsProcessingUtils::fieldNamesToIndices( QStringList() << "address" << "age", fields );
|
|
QCOMPARE( indices2, QList<int>() << 1 << 2 );
|
|
|
|
QList<int> indices3 = QgsProcessingUtils::fieldNamesToIndices( QStringList() << "address" << "agegege", fields );
|
|
QCOMPARE( indices3, QList<int>() << 1 );
|
|
}
|
|
|
|
void TestQgsProcessing::indicesToFields()
|
|
{
|
|
QgsFields fields;
|
|
fields.append( QgsField( "name" ) );
|
|
fields.append( QgsField( "address" ) );
|
|
fields.append( QgsField( "age" ) );
|
|
|
|
QList<int> indices1 = QList<int>() << 0 << 1 << 2;
|
|
QgsFields fields1 = QgsProcessingUtils::indicesToFields( indices1, fields );
|
|
QCOMPARE( fields1, fields );
|
|
|
|
QList<int> indices2 = QList<int>() << 1;
|
|
QgsFields fields2expected;
|
|
fields2expected.append( QgsField( "address" ) );
|
|
QgsFields fields2 = QgsProcessingUtils::indicesToFields( indices2, fields );
|
|
QCOMPARE( fields2, fields2expected );
|
|
|
|
QList<int> indices3;
|
|
QgsFields fields3 = QgsProcessingUtils::indicesToFields( indices3, fields );
|
|
QCOMPARE( fields3, QgsFields() );
|
|
}
|
|
|
|
void TestQgsProcessing::stringToPythonLiteral()
|
|
{
|
|
QCOMPARE( QgsProcessingUtils::stringToPythonLiteral( QStringLiteral( "a" ) ), QStringLiteral( "'a'" ) );
|
|
QCOMPARE( QgsProcessingUtils::stringToPythonLiteral( QString() ), QStringLiteral( "''" ) );
|
|
QCOMPARE( QgsProcessingUtils::stringToPythonLiteral( QStringLiteral( "a 'string'" ) ), QStringLiteral( "'a \\'string\\''" ) );
|
|
QCOMPARE( QgsProcessingUtils::stringToPythonLiteral( QStringLiteral( "a \"string\"" ) ), QStringLiteral( "'a \\\"string\\\"'" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::defaultExtensionsForProvider()
|
|
{
|
|
DummyProvider3 provider;
|
|
// default implementation should return first supported format for provider
|
|
QCOMPARE( provider.defaultVectorFileExtension( true ), QStringLiteral( "mif" ) );
|
|
QCOMPARE( provider.defaultRasterFileExtension(), QStringLiteral( "mig" ) );
|
|
// unless the user has set a default format, which IS supported by that provider
|
|
QgsSettings settings;
|
|
settings.setValue( QStringLiteral( "Processing/DefaultOutputVectorLayerExt" ), QStringLiteral( "tab" ), QgsSettings::Core );
|
|
settings.setValue( QStringLiteral( "Processing/DefaultOutputRasterLayerExt" ), QStringLiteral( "asc" ), QgsSettings::Core );
|
|
QCOMPARE( provider.defaultVectorFileExtension( true ), QStringLiteral( "tab" ) );
|
|
QCOMPARE( provider.defaultRasterFileExtension(), QStringLiteral( "asc" ) );
|
|
|
|
// but if default is not supported by provider, we use a supported format
|
|
settings.setValue( QStringLiteral( "Processing/DefaultOutputVectorLayerExt" ), QStringLiteral( "gpkg" ), QgsSettings::Core );
|
|
settings.setValue( QStringLiteral( "Processing/DefaultOutputRasterLayerExt" ), QStringLiteral( "ecw" ), QgsSettings::Core );
|
|
QCOMPARE( provider.defaultVectorFileExtension( true ), QStringLiteral( "mif" ) );
|
|
QCOMPARE( provider.defaultRasterFileExtension(), QStringLiteral( "mig" ) );
|
|
}
|
|
|
|
void TestQgsProcessing::supportsNonFileBasedOutput()
|
|
{
|
|
DummyAlgorithm alg( QStringLiteral( "test" ) );
|
|
DummyProvider p( QStringLiteral( "test_provider" ) );
|
|
alg.addDestParams();
|
|
// provider has no support for file based outputs, so both output parameters should deny support
|
|
alg.setProvider( &p );
|
|
QVERIFY( !static_cast< const QgsProcessingDestinationParameter * >( alg.destinationParameterDefinitions().at( 0 ) )->supportsNonFileBasedOutput() );
|
|
QVERIFY( !static_cast< const QgsProcessingDestinationParameter * >( alg.destinationParameterDefinitions().at( 1 ) )->supportsNonFileBasedOutput() );
|
|
|
|
DummyAlgorithm alg2( QStringLiteral( "test" ) );
|
|
DummyProvider p2( QStringLiteral( "test_provider" ) );
|
|
p2.supportsNonFileOutputs = true;
|
|
alg2.addDestParams();
|
|
// provider has support for file based outputs, but only first output parameter should indicate support (since the second has support explicitly denied)
|
|
alg2.setProvider( &p2 );
|
|
QVERIFY( static_cast< const QgsProcessingDestinationParameter * >( alg2.destinationParameterDefinitions().at( 0 ) )->supportsNonFileBasedOutput() );
|
|
QVERIFY( !static_cast< const QgsProcessingDestinationParameter * >( alg2.destinationParameterDefinitions().at( 1 ) )->supportsNonFileBasedOutput() );
|
|
}
|
|
|
|
void TestQgsProcessing::addParameterType()
|
|
{
|
|
QgsProcessingRegistry reg;
|
|
QSignalSpy spy( ®, &QgsProcessingRegistry::parameterTypeAdded );
|
|
DummyParameterType *dpt = new DummyParameterType();
|
|
QVERIFY( reg.addParameterType( dpt ) );
|
|
QCOMPARE( spy.count(), 1 );
|
|
QVERIFY( !reg.addParameterType( dpt ) );
|
|
QCOMPARE( spy.count(), 1 );
|
|
QVERIFY( !reg.addParameterType( new DummyParameterType() ) );
|
|
QCOMPARE( spy.count(), 1 );
|
|
}
|
|
|
|
void TestQgsProcessing::removeParameterType()
|
|
{
|
|
QgsProcessingRegistry reg;
|
|
|
|
auto paramType = new DummyParameterType();
|
|
|
|
reg.addParameterType( paramType );
|
|
QSignalSpy spy( ®, &QgsProcessingRegistry::parameterTypeRemoved );
|
|
reg.removeParameterType( paramType );
|
|
QCOMPARE( spy.count(), 1 );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterTypes()
|
|
{
|
|
QgsProcessingRegistry reg;
|
|
int coreParamCount = reg.parameterTypes().count();
|
|
QVERIFY( coreParamCount > 5 );
|
|
|
|
auto paramType = new DummyParameterType();
|
|
|
|
reg.addParameterType( paramType );
|
|
QCOMPARE( reg.parameterTypes().count(), coreParamCount + 1 );
|
|
QVERIFY( reg.parameterTypes().contains( paramType ) );
|
|
}
|
|
|
|
void TestQgsProcessing::parameterType()
|
|
{
|
|
QgsProcessingRegistry reg;
|
|
|
|
QVERIFY( reg.parameterType( QStringLiteral( "string" ) ) );
|
|
QVERIFY( !reg.parameterType( QStringLiteral( "borken" ) ) );
|
|
|
|
auto paramType = new DummyParameterType();
|
|
|
|
reg.addParameterType( paramType );
|
|
QCOMPARE( reg.parameterType( QStringLiteral( "paramType" ) ), paramType );
|
|
}
|
|
|
|
QGSTEST_MAIN( TestQgsProcessing )
|
|
#include "testqgsprocessing.moc"
|