From 1342f4d9acbeebf559ba7155589b55f8915723d6 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Sun, 16 Jul 2017 18:19:24 +1000 Subject: [PATCH] Add API to set optional destination parameters as not created by default This allows optional outputs (such as null geometry features detected by the Remove Null Geometries algorithm) to be skipped by default when desirable. --- .../models/qgsprocessingmodelalgorithm.sip | 2 +- .../processing/qgsprocessingparameters.sip | 15 +++++++++++++++ .../gui/DestinationSelectionPanel.py | 2 +- .../models/qgsprocessingmodelalgorithm.cpp | 2 +- .../models/qgsprocessingmodelalgorithm.h | 2 +- src/core/processing/qgsnativealgorithms.cpp | 18 ++++++++++++------ .../processing/qgsprocessingparameters.cpp | 12 ++++++++++++ src/core/processing/qgsprocessingparameters.h | 15 +++++++++++++++ tests/src/core/testqgsprocessing.cpp | 3 +++ 9 files changed, 61 insertions(+), 10 deletions(-) diff --git a/python/core/processing/models/qgsprocessingmodelalgorithm.sip b/python/core/processing/models/qgsprocessingmodelalgorithm.sip index ebd3abe8022..c9bc15c4de6 100644 --- a/python/core/processing/models/qgsprocessingmodelalgorithm.sip +++ b/python/core/processing/models/qgsprocessingmodelalgorithm.sip @@ -293,7 +293,7 @@ class QgsProcessingModelAlgorithm : QgsProcessingAlgorithm %End QList< QgsProcessingModelChildParameterSource > availableSourcesForChild( const QString &childId, const QStringList ¶meterTypes = QStringList(), - const QStringList &outputTypes = QStringList(), const QList< int > dataTypes = QList< int >() ) const; + const QStringList &outputTypes = QStringList(), const QList< int > &dataTypes = QList< int >() ) const; %Docstring Returns a list of possible sources which can be used for the parameters for a child algorithm in the model. Returned sources are those which match either one of the diff --git a/python/core/processing/qgsprocessingparameters.sip b/python/core/processing/qgsprocessingparameters.sip index 8a9d5d266f6..f911026d2c6 100644 --- a/python/core/processing/qgsprocessingparameters.sip +++ b/python/core/processing/qgsprocessingparameters.sip @@ -1636,6 +1636,21 @@ class QgsProcessingDestinationParameter : QgsProcessingParameterDefinition :rtype: str %End + bool createByDefault() const; +%Docstring + Returns true if the destination should be created by default. For optional parameters, + a return value of false indicates that the destination should not be created by default. +.. seealso:: setCreateByDefault() + :rtype: bool +%End + + void setCreateByDefault( bool createByDefault ); +%Docstring + Sets whether the destination should be created by default. For optional parameters, + a value of false indicates that the destination should not be created by default. +.. seealso:: createByDefault() +%End + }; diff --git a/python/plugins/processing/gui/DestinationSelectionPanel.py b/python/plugins/processing/gui/DestinationSelectionPanel.py index d8d3f3e654d..e1cf4448fe4 100644 --- a/python/plugins/processing/gui/DestinationSelectionPanel.py +++ b/python/plugins/processing/gui/DestinationSelectionPanel.py @@ -72,7 +72,7 @@ class DestinationSelectionPanel(BASE, WIDGET): self.use_temporary = True if hasattr(self.leText, 'setPlaceholderText'): - if parameter.flags() & QgsProcessingParameterDefinition.FlagOptional and parameter.defaultValue() is None: + if parameter.flags() & QgsProcessingParameterDefinition.FlagOptional and not parameter.createByDefault(): self.leText.setPlaceholderText(self.SKIP_OUTPUT) self.use_temporary = False elif isinstance(self.parameter, QgsProcessingParameterFeatureSink) \ diff --git a/src/core/processing/models/qgsprocessingmodelalgorithm.cpp b/src/core/processing/models/qgsprocessingmodelalgorithm.cpp index 279862965a2..d41c5e8cbd0 100644 --- a/src/core/processing/models/qgsprocessingmodelalgorithm.cpp +++ b/src/core/processing/models/qgsprocessingmodelalgorithm.cpp @@ -566,7 +566,7 @@ QgsExpressionContextScope *QgsProcessingModelAlgorithm::createExpressionContextS return scope.release(); } -QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild( const QString &childId, const QStringList ¶meterTypes, const QStringList &outputTypes, const QList dataTypes ) const +QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild( const QString &childId, const QStringList ¶meterTypes, const QStringList &outputTypes, const QList &dataTypes ) const { QgsProcessingModelChildParameterSources sources; diff --git a/src/core/processing/models/qgsprocessingmodelalgorithm.h b/src/core/processing/models/qgsprocessingmodelalgorithm.h index 81fde0373a6..a792ea52551 100644 --- a/src/core/processing/models/qgsprocessingmodelalgorithm.h +++ b/src/core/processing/models/qgsprocessingmodelalgorithm.h @@ -296,7 +296,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm * sources to those with compatible data types for the parameter/outputs. */ QList< QgsProcessingModelChildParameterSource > availableSourcesForChild( const QString &childId, const QStringList ¶meterTypes = QStringList(), - const QStringList &outputTypes = QStringList(), const QList< int > dataTypes = QList< int >() ) const; + const QStringList &outputTypes = QStringList(), const QList< int > &dataTypes = QList< int >() ) const; /** * Definition of a expression context variable available during model execution. diff --git a/src/core/processing/qgsnativealgorithms.cpp b/src/core/processing/qgsnativealgorithms.cpp index 9a3cf0e2509..138073d95f3 100644 --- a/src/core/processing/qgsnativealgorithms.cpp +++ b/src/core/processing/qgsnativealgorithms.cpp @@ -788,8 +788,10 @@ void QgsExtractByExpressionAlgorithm::initAlgorithm( const QVariantMap & ) addParameter( new QgsProcessingParameterExpression( QStringLiteral( "EXPRESSION" ), QObject::tr( "Expression" ), QVariant(), QStringLiteral( "INPUT" ) ) ); addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Matching features" ) ) ); - addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "FAIL_OUTPUT" ), QObject::tr( "Non-matching" ), - QgsProcessing::TypeVectorAny, QVariant(), true ) ); + QgsProcessingParameterFeatureSink *failOutput = new QgsProcessingParameterFeatureSink( QStringLiteral( "FAIL_OUTPUT" ), QObject::tr( "Non-matching" ), + QgsProcessing::TypeVectorAny, QVariant(), true ); + failOutput->setCreateByDefault( false ); + addParameter( failOutput ); } QString QgsExtractByExpressionAlgorithm::shortHelpString() const @@ -917,8 +919,10 @@ void QgsExtractByAttributeAlgorithm::initAlgorithm( const QVariantMap & ) addParameter( new QgsProcessingParameterString( QStringLiteral( "VALUE" ), QObject::tr( "Value" ), QVariant(), false, true ) ); addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Extracted (attribute)" ) ) ); - addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "FAIL_OUTPUT" ), QObject::tr( "Extracted (non-matching)" ), - QgsProcessing::TypeVectorAny, QVariant(), true ) ); + QgsProcessingParameterFeatureSink *failOutput = new QgsProcessingParameterFeatureSink( QStringLiteral( "FAIL_OUTPUT" ), QObject::tr( "Extracted (non-matching)" ), + QgsProcessing::TypeVectorAny, QVariant(), true ); + failOutput->setCreateByDefault( false ); + addParameter( failOutput ); } QString QgsExtractByAttributeAlgorithm::shortHelpString() const @@ -1101,8 +1105,10 @@ void QgsRemoveNullGeometryAlgorithm::initAlgorithm( const QVariantMap & ) addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), QObject::tr( "Non null geometries" ), QgsProcessing::TypeVectorAny, QVariant(), true ) ); - addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "NULL_OUTPUT" ), QObject::tr( "Null geometries" ), - QgsProcessing::TypeVectorAny, QVariant(), true ) ); + QgsProcessingParameterFeatureSink *nullOutput = new QgsProcessingParameterFeatureSink( QStringLiteral( "NULL_OUTPUT" ), QObject::tr( "Null geometries" ), + QgsProcessing::TypeTable, QVariant(), true ); + nullOutput->setCreateByDefault( false ); + addParameter( nullOutput ); } QString QgsRemoveNullGeometryAlgorithm::shortHelpString() const diff --git a/src/core/processing/qgsprocessingparameters.cpp b/src/core/processing/qgsprocessingparameters.cpp index 6e33948ed8d..c9d49d7e574 100644 --- a/src/core/processing/qgsprocessingparameters.cpp +++ b/src/core/processing/qgsprocessingparameters.cpp @@ -2917,6 +2917,7 @@ QVariantMap QgsProcessingDestinationParameter::toVariantMap() const { QVariantMap map = QgsProcessingParameterDefinition::toVariantMap(); map.insert( QStringLiteral( "supports_non_file_outputs" ), mSupportsNonFileBasedOutputs ); + map.insert( QStringLiteral( "create_by_default" ), mCreateByDefault ); return map; } @@ -2924,6 +2925,7 @@ bool QgsProcessingDestinationParameter::fromVariantMap( const QVariantMap &map ) { QgsProcessingParameterDefinition::fromVariantMap( map ); mSupportsNonFileBasedOutputs = map.value( QStringLiteral( "supports_non_file_outputs" ) ).toBool(); + mCreateByDefault = map.value( QStringLiteral( "create_by_default" ), QStringLiteral( "1" ) ).toBool(); return true; } @@ -2932,6 +2934,16 @@ QString QgsProcessingDestinationParameter::generateTemporaryDestination() const return QgsProcessingUtils::generateTempFilename( name() + '.' + defaultFileExtension() ); } +bool QgsProcessingDestinationParameter::createByDefault() const +{ + return mCreateByDefault; +} + +void QgsProcessingDestinationParameter::setCreateByDefault( bool createByDefault ) +{ + mCreateByDefault = createByDefault; +} + QgsProcessingParameterVectorDestination::QgsProcessingParameterVectorDestination( const QString &name, const QString &description, QgsProcessing::LayerType type, const QVariant &defaultValue, bool optional ) : QgsProcessingDestinationParameter( name, description, defaultValue, optional ) , mDataType( type ) diff --git a/src/core/processing/qgsprocessingparameters.h b/src/core/processing/qgsprocessingparameters.h index 6421b1dc783..f109621ebd7 100644 --- a/src/core/processing/qgsprocessingparameters.h +++ b/src/core/processing/qgsprocessingparameters.h @@ -1555,9 +1555,24 @@ class CORE_EXPORT QgsProcessingDestinationParameter : public QgsProcessingParame */ virtual QString generateTemporaryDestination() const; + /** + * Returns true if the destination should be created by default. For optional parameters, + * a return value of false indicates that the destination should not be created by default. + * \see setCreateByDefault() + */ + bool createByDefault() const; + + /** + * Sets whether the destination should be created by default. For optional parameters, + * a value of false indicates that the destination should not be created by default. + * \see createByDefault() + */ + void setCreateByDefault( bool createByDefault ); + private: bool mSupportsNonFileBasedOutputs = true; + bool mCreateByDefault = true; }; diff --git a/tests/src/core/testqgsprocessing.cpp b/tests/src/core/testqgsprocessing.cpp index d9353d435d7..898e16f9de8 100644 --- a/tests/src/core/testqgsprocessing.cpp +++ b/tests/src/core/testqgsprocessing.cpp @@ -3573,6 +3573,8 @@ void TestQgsProcessing::parameterFeatureSink() 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" ) ); @@ -3582,6 +3584,7 @@ void TestQgsProcessing::parameterFeatureSink() 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::TypeAny ).hasGeometry() );