diff --git a/python/core/processing/qgsprocessingparameters.sip b/python/core/processing/qgsprocessingparameters.sip index 36c98991b2c..3f094cf8e09 100644 --- a/python/core/processing/qgsprocessingparameters.sip +++ b/python/core/processing/qgsprocessingparameters.sip @@ -175,6 +175,8 @@ class QgsProcessingParameterDefinition sipType = sipType_QgsProcessingParameterRasterOutput; else if ( sipCpp->type() == "fileOut" ) sipType = sipType_QgsProcessingParameterFileOutput; + else if ( sipCpp->type() == "folderOut" ) + sipType = sipType_QgsProcessingParameterFolderOutput; %End public: @@ -1344,6 +1346,32 @@ class QgsProcessingParameterFileOutput : QgsProcessingParameterDefinition }; +class QgsProcessingParameterFolderOutput : QgsProcessingParameterDefinition +{ +%Docstring + A folder output parameter. +.. versionadded:: 3.0 +%End + +%TypeHeaderCode +#include "qgsprocessingparameters.h" +%End + public: + + QgsProcessingParameterFolderOutput( const QString &name, const QString &description = QString(), + const QVariant &defaultValue = QVariant(), + bool optional = false ); +%Docstring + Constructor for QgsProcessingParameterFolderOutput. +%End + + virtual QString type() const; + virtual bool isDestination() const; + virtual bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = 0 ) const; + + +}; + /************************************************************************ diff --git a/src/core/processing/qgsprocessingparameters.cpp b/src/core/processing/qgsprocessingparameters.cpp index 972b147ca75..12f0475e700 100644 --- a/src/core/processing/qgsprocessingparameters.cpp +++ b/src/core/processing/qgsprocessingparameters.cpp @@ -1912,3 +1912,27 @@ void QgsProcessingParameterFileOutput::setFileFilter( const QString &fileFilter { mFileFilter = fileFilter; } + +QgsProcessingParameterFolderOutput::QgsProcessingParameterFolderOutput( const QString &name, const QString &description, const QVariant &defaultValue, bool optional ) + : QgsProcessingParameterDefinition( name, description, defaultValue, optional ) +{} + +bool QgsProcessingParameterFolderOutput::checkValueIsAcceptable( const QVariant &input, QgsProcessingContext * ) const +{ + QVariant var = input; + if ( !var.isValid() ) + return mFlags & FlagOptional; + + if ( var.canConvert() ) + { + return true; + } + + if ( var.type() != QVariant::String ) + return false; + + if ( var.toString().isEmpty() ) + return mFlags & FlagOptional; + + return true; +} diff --git a/src/core/processing/qgsprocessingparameters.h b/src/core/processing/qgsprocessingparameters.h index 7d52b742dd0..227dfd09d97 100644 --- a/src/core/processing/qgsprocessingparameters.h +++ b/src/core/processing/qgsprocessingparameters.h @@ -210,6 +210,8 @@ class CORE_EXPORT QgsProcessingParameterDefinition sipType = sipType_QgsProcessingParameterRasterOutput; else if ( sipCpp->type() == "fileOut" ) sipType = sipType_QgsProcessingParameterFileOutput; + else if ( sipCpp->type() == "folderOut" ) + sipType = sipType_QgsProcessingParameterFolderOutput; SIP_END #endif @@ -1318,6 +1320,29 @@ class CORE_EXPORT QgsProcessingParameterFileOutput : public QgsProcessingParamet QString mFileFilter; }; +/** + * \class QgsProcessingParameterFolderOutput + * \ingroup core + * A folder output parameter. + * \since QGIS 3.0 + */ +class CORE_EXPORT QgsProcessingParameterFolderOutput : public QgsProcessingParameterDefinition +{ + public: + + /** + * Constructor for QgsProcessingParameterFolderOutput. + */ + QgsProcessingParameterFolderOutput( const QString &name, const QString &description = QString(), + const QVariant &defaultValue = QVariant(), + bool optional = false ); + + QString type() const override { return QStringLiteral( "folderOut" ); } + bool isDestination() const override { return true; } + bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override; + +}; + #endif // QGSPROCESSINGPARAMETERS_H diff --git a/tests/src/core/testqgsprocessing.cpp b/tests/src/core/testqgsprocessing.cpp index 094c18702df..0dce634a200 100644 --- a/tests/src/core/testqgsprocessing.cpp +++ b/tests/src/core/testqgsprocessing.cpp @@ -309,6 +309,7 @@ class TestQgsProcessing: public QObject void parameterFeatureSink(); void parameterRasterOut(); void parameterFileOut(); + void parameterFolderOut(); void checkParamValues(); void combineLayerExtent(); void processingFeatureSource(); @@ -2651,6 +2652,48 @@ void TestQgsProcessing::parameterFileOut() QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "default.txt" ) ); } +void TestQgsProcessing::parameterFolderOut() +{ + // setup a context + QgsProject p; + QgsProcessingContext context; + context.setProject( &p ); + + // not optional! + std::unique_ptr< QgsProcessingParameterFolderOutput > def( new QgsProcessingParameterFolderOutput( "non_optional", QString(), QString(), false ) ); + + QVERIFY( !def->checkValueIsAcceptable( false ) ); + QVERIFY( !def->checkValueIsAcceptable( true ) ); + QVERIFY( !def->checkValueIsAcceptable( 5 ) ); + QVERIFY( def->checkValueIsAcceptable( "asdasd" ) ); + QVERIFY( !def->checkValueIsAcceptable( "" ) ); + QVERIFY( !def->checkValueIsAcceptable( QVariant() ) ); + + // 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 ) ); + + QVariantMap params; + params.insert( "non_optional", "c:/mine" ); + QCOMPARE( QgsProcessingParameters::parameterAsFileOutput( def.get(), params, context ), QStringLiteral( "c:/mine" ) ); + + QCOMPARE( def->valueAsPythonString( QStringLiteral( "abc" ), context ), QStringLiteral( "'abc'" ) ); + QCOMPARE( def->valueAsPythonString( QVariant::fromValue( QgsProperty::fromExpression( "\"a\"=1" ) ), context ), QStringLiteral( "QgsProperty.fromExpression('\"a\"=1')" ) ); + + // optional + def.reset( new QgsProcessingParameterFolderOutput( "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" ) ); +} + void TestQgsProcessing::checkParamValues() { DummyAlgorithm a( "asd" );