diff --git a/python/core/processing/qgsprocessingparameters.sip b/python/core/processing/qgsprocessingparameters.sip index 7b2e185b2f7c..66e8ddb7e9b3 100644 --- a/python/core/processing/qgsprocessingparameters.sip +++ b/python/core/processing/qgsprocessingparameters.sip @@ -1420,7 +1420,42 @@ class QgsProcessingParameterExpression : QgsProcessingParameterDefinition }; -class QgsProcessingParameterVectorLayer : QgsProcessingParameterDefinition + +class QgsProcessingParameterLimitedDataTypes +{ +%Docstring + Can be inherited by parameters which require limits to their acceptable data types. +.. versionadded:: 3.0 +%End + +%TypeHeaderCode +#include "qgsprocessingparameters.h" +%End + public: + + QgsProcessingParameterLimitedDataTypes( const QList< int > &types = QList< int >() ); +%Docstring + Constructor for QgsProcessingParameterLimitedDataTypes, with a list of acceptable data ``types``. +%End + + QList< int > dataTypes() const; +%Docstring + Returns the geometry types for sources acceptable by the parameter. +.. seealso:: setDataTypes() + :rtype: list of int +%End + + void setDataTypes( const QList< int > &types ); +%Docstring + Sets the geometry ``types`` for sources acceptable by the parameter. +.. seealso:: dataTypes() +%End + + protected: + +}; + +class QgsProcessingParameterVectorLayer : QgsProcessingParameterDefinition, QgsProcessingParameterLimitedDataTypes { %Docstring A vector layer (with or without geometry) parameter for processing algorithms. Consider using @@ -1455,19 +1490,6 @@ class QgsProcessingParameterVectorLayer : QgsProcessingParameterDefinition virtual QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const; - QList< int > dataTypes() const; -%Docstring - Returns the geometry types for sources acceptable by the parameter. -.. seealso:: setDataTypes() - :rtype: list of int -%End - - void setDataTypes( const QList< int > &types ); -%Docstring - Sets the geometry ``types`` for sources acceptable by the parameter. -.. seealso:: dataTypes() -%End - virtual QVariantMap toVariantMap() const; virtual bool fromVariantMap( const QVariantMap &map ); @@ -1579,7 +1601,8 @@ class QgsProcessingParameterField : QgsProcessingParameterDefinition }; -class QgsProcessingParameterFeatureSource : QgsProcessingParameterDefinition + +class QgsProcessingParameterFeatureSource : QgsProcessingParameterDefinition, QgsProcessingParameterLimitedDataTypes { %Docstring An input feature source (such as vector layers) parameter for processing algorithms. @@ -1613,19 +1636,6 @@ class QgsProcessingParameterFeatureSource : QgsProcessingParameterDefinition virtual QString asScriptCode() const; - QList< int > dataTypes() const; -%Docstring - Returns the geometry types for sources acceptable by the parameter. -.. seealso:: setDataTypes() - :rtype: list of int -%End - - void setDataTypes( const QList< int > &types ); -%Docstring - Sets the geometry ``types`` for sources acceptable by the parameter. -.. seealso:: dataTypes() -%End - virtual QVariantMap toVariantMap() const; virtual bool fromVariantMap( const QVariantMap &map ); diff --git a/python/plugins/processing/gui/wrappers.py b/python/plugins/processing/gui/wrappers.py index e918c0b13cc5..6e4eec128a37 100644 --- a/python/plugins/processing/gui/wrappers.py +++ b/python/plugins/processing/gui/wrappers.py @@ -897,7 +897,7 @@ def createWidget(self): return widget else: self.combo = QComboBox() - layers = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer), QgsProcessingOutputVectorLayer) + layers = self.dialog.getAvailableValuesOfType((QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer), QgsProcessingOutputVectorLayer, self.param.dataTypes()) self.combo.setEditable(True) for layer in layers: self.combo.addItem(self.dialog.resolveValueDescription(layer), layer) diff --git a/src/core/processing/models/qgsprocessingmodelalgorithm.cpp b/src/core/processing/models/qgsprocessingmodelalgorithm.cpp index 76b1b673ae3c..fceaf1d216b8 100644 --- a/src/core/processing/models/qgsprocessingmodelalgorithm.cpp +++ b/src/core/processing/models/qgsprocessingmodelalgorithm.cpp @@ -590,18 +590,24 @@ QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSo continue; } } - else if ( def->type() == QgsProcessingParameterFeatureSource::typeName() ) + else if ( def->type() == QgsProcessingParameterFeatureSource::typeName() || def->type() == QgsProcessingParameterVectorLayer::typeName() ) { - const QgsProcessingParameterFeatureSource *sourceDef = static_cast< const QgsProcessingParameterFeatureSource *>( def ); - bool ok = !sourceDef->dataTypes().isEmpty(); + const QgsProcessingParameterLimitedDataTypes *sourceDef = dynamic_cast< const QgsProcessingParameterLimitedDataTypes *>( def ); + if ( !sourceDef ) + continue; + + bool ok = sourceDef->dataTypes().isEmpty(); Q_FOREACH ( int type, sourceDef->dataTypes() ) { - if ( dataTypes.contains( type ) || type == QgsProcessing::TypeMapLayer ) + if ( dataTypes.contains( type ) || type == QgsProcessing::TypeMapLayer || type == QgsProcessing::TypeVector || type == QgsProcessing::TypeVectorAnyGeometry ) { ok = true; break; } } + if ( dataTypes.contains( QgsProcessing::TypeMapLayer ) || dataTypes.contains( QgsProcessing::TypeVector ) || dataTypes.contains( QgsProcessing::TypeVectorAnyGeometry ) ) + ok = true; + if ( !ok ) continue; } @@ -636,7 +642,9 @@ QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSo if ( out->type() == QgsProcessingOutputVectorLayer::typeName() ) { const QgsProcessingOutputVectorLayer *vectorOut = static_cast< const QgsProcessingOutputVectorLayer *>( out ); - if ( !( dataTypes.contains( vectorOut->dataType() ) || vectorOut->dataType() == QgsProcessing::TypeMapLayer ) ) + + if ( !( dataTypes.contains( vectorOut->dataType() ) || vectorOut->dataType() == QgsProcessing::TypeMapLayer || vectorOut->dataType() == QgsProcessing::TypeVector + || vectorOut->dataType() == QgsProcessing::TypeVectorAnyGeometry ) ) { continue; } diff --git a/src/core/processing/qgsprocessingparameters.cpp b/src/core/processing/qgsprocessingparameters.cpp index 15eac0250bda..c47e0fc6a386 100644 --- a/src/core/processing/qgsprocessingparameters.cpp +++ b/src/core/processing/qgsprocessingparameters.cpp @@ -2184,7 +2184,7 @@ QgsProcessingParameterExpression *QgsProcessingParameterExpression::fromScriptCo QgsProcessingParameterVectorLayer::QgsProcessingParameterVectorLayer( const QString &name, const QString &description, const QList &types, const QVariant &defaultValue, bool optional ) : QgsProcessingParameterDefinition( name, description, defaultValue, optional ) - , mDataTypes( types ) + , QgsProcessingParameterLimitedDataTypes( types ) { } @@ -2234,12 +2234,12 @@ QString QgsProcessingParameterVectorLayer::valueAsPythonString( const QVariant & return layer ? QgsProcessingUtils::normalizeLayerSource( layer->source() ).prepend( '\'' ).append( '\'' ) : QString(); } -QList QgsProcessingParameterVectorLayer::dataTypes() const +QList QgsProcessingParameterLimitedDataTypes::dataTypes() const { return mDataTypes; } -void QgsProcessingParameterVectorLayer::setDataTypes( const QList &types ) +void QgsProcessingParameterLimitedDataTypes::setDataTypes( const QList &types ) { mDataTypes = types; } @@ -2483,7 +2483,7 @@ QgsProcessingParameterField *QgsProcessingParameterField::fromScriptCode( const QgsProcessingParameterFeatureSource::QgsProcessingParameterFeatureSource( const QString &name, const QString &description, const QList &types, const QVariant &defaultValue, bool optional ) : QgsProcessingParameterDefinition( name, description, defaultValue, optional ) - , mDataTypes( types ) + , QgsProcessingParameterLimitedDataTypes( types ) { } @@ -2603,14 +2603,10 @@ QString QgsProcessingParameterFeatureSource::asScriptCode() const return code.trimmed(); } -QList< int > QgsProcessingParameterFeatureSource::dataTypes() const +QgsProcessingParameterLimitedDataTypes::QgsProcessingParameterLimitedDataTypes( const QList &types ) + : mDataTypes( types ) { - return mDataTypes; -} -void QgsProcessingParameterFeatureSource::setDataTypes( const QList &types ) -{ - mDataTypes = types; } QVariantMap QgsProcessingParameterFeatureSource::toVariantMap() const diff --git a/src/core/processing/qgsprocessingparameters.h b/src/core/processing/qgsprocessingparameters.h index 80fed2eee49a..08aa9c8febff 100644 --- a/src/core/processing/qgsprocessingparameters.h +++ b/src/core/processing/qgsprocessingparameters.h @@ -1350,6 +1350,40 @@ class CORE_EXPORT QgsProcessingParameterExpression : public QgsProcessingParamet }; + +/** + * \class QgsProcessingParameterLimitedDataTypes + * \ingroup core + * Can be inherited by parameters which require limits to their acceptable data types. + * \since QGIS 3.0 + */ +class CORE_EXPORT QgsProcessingParameterLimitedDataTypes +{ + public: + + /** + * Constructor for QgsProcessingParameterLimitedDataTypes, with a list of acceptable data \a types. + */ + QgsProcessingParameterLimitedDataTypes( const QList< int > &types = QList< int >() ); + + /** + * Returns the geometry types for sources acceptable by the parameter. + * \see setDataTypes() + */ + QList< int > dataTypes() const; + + /** + * Sets the geometry \a types for sources acceptable by the parameter. + * \see dataTypes() + */ + void setDataTypes( const QList< int > &types ); + + protected: + + //! List of acceptable data types for the parameter + QList< int > mDataTypes; +}; + /** * \class QgsProcessingParameterVectorLayer * \ingroup core @@ -1357,7 +1391,7 @@ class CORE_EXPORT QgsProcessingParameterExpression : public QgsProcessingParamet * the more versatile QgsProcessingParameterFeatureSource wherever possible. * \since QGIS 3.0 */ -class CORE_EXPORT QgsProcessingParameterVectorLayer : public QgsProcessingParameterDefinition +class CORE_EXPORT QgsProcessingParameterVectorLayer : public QgsProcessingParameterDefinition, public QgsProcessingParameterLimitedDataTypes { public: @@ -1379,18 +1413,6 @@ class CORE_EXPORT QgsProcessingParameterVectorLayer : public QgsProcessingParame bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override; QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const override; - /** - * Returns the geometry types for sources acceptable by the parameter. - * \see setDataTypes() - */ - QList< int > dataTypes() const; - - /** - * Sets the geometry \a types for sources acceptable by the parameter. - * \see dataTypes() - */ - void setDataTypes( const QList< int > &types ); - QVariantMap toVariantMap() const override; bool fromVariantMap( const QVariantMap &map ) override; @@ -1399,11 +1421,6 @@ class CORE_EXPORT QgsProcessingParameterVectorLayer : public QgsProcessingParame */ static QgsProcessingParameterVectorLayer *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) SIP_FACTORY; - private: - - QList< int > mDataTypes = QList< int >() << QgsProcessing::TypeVectorAnyGeometry; - - }; /** @@ -1497,13 +1514,14 @@ class CORE_EXPORT QgsProcessingParameterField : public QgsProcessingParameterDef }; + /** * \class QgsProcessingParameterFeatureSource * \ingroup core * An input feature source (such as vector layers) parameter for processing algorithms. * \since QGIS 3.0 */ -class CORE_EXPORT QgsProcessingParameterFeatureSource : public QgsProcessingParameterDefinition +class CORE_EXPORT QgsProcessingParameterFeatureSource : public QgsProcessingParameterDefinition, public QgsProcessingParameterLimitedDataTypes { public: @@ -1524,18 +1542,6 @@ class CORE_EXPORT QgsProcessingParameterFeatureSource : public QgsProcessingPara QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const override; QString asScriptCode() const override; - /** - * Returns the geometry types for sources acceptable by the parameter. - * \see setDataTypes() - */ - QList< int > dataTypes() const; - - /** - * Sets the geometry \a types for sources acceptable by the parameter. - * \see dataTypes() - */ - void setDataTypes( const QList< int > &types ); - QVariantMap toVariantMap() const override; bool fromVariantMap( const QVariantMap &map ) override; @@ -1544,10 +1550,6 @@ class CORE_EXPORT QgsProcessingParameterFeatureSource : public QgsProcessingPara */ static QgsProcessingParameterFeatureSource *fromScriptCode( const QString &name, const QString &description, bool isOptional, const QString &definition ) SIP_FACTORY; - private: - - QList< int > mDataTypes = QList< int >() << QgsProcessing::TypeVectorAnyGeometry; - }; /** diff --git a/tests/src/core/testqgsprocessing.cpp b/tests/src/core/testqgsprocessing.cpp index 5772677c27ea..afd02c8a4494 100644 --- a/tests/src/core/testqgsprocessing.cpp +++ b/tests/src/core/testqgsprocessing.cpp @@ -5154,6 +5154,117 @@ void TestQgsProcessing::modelAcceptableValues() 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() << 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() << 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() << 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() << 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() << QgsProcessing::TypeVector ), vlInput ); + m2.addModelParameter( new QgsProcessingParameterFeatureSource( "fs", QString(), QList() << 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() << 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() << 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() << 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() << 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() << QgsProcessing::TypeVectorAnyGeometry ), vlInput ); + m2.addModelParameter( new QgsProcessingParameterFeatureSource( "fs", QString(), QList() << 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() << 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() << 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() << 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() << 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() << QgsProcessing::TypeVectorLine ), vlInput ); + m2.addModelParameter( new QgsProcessingParameterFeatureSource( "fs", QString(), QList() << 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() << QgsProcessing::TypeVectorPoint ); + QCOMPARE( sources.count(), 0 ); + sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList() << QgsProcessing::TypeVectorPolygon ); + QCOMPARE( sources.count(), 0 ); + sources = m2.availableSourcesForChild( QString(), QStringList() << "vector" << "source", QStringList(), QList() << 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() << 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() << 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() << QgsProcessing::TypeMapLayer ); + QCOMPARE( sources.count(), 2 ); + QCOMPARE( sources.at( 0 ).parameterName(), QStringLiteral( "fs" ) ); + QCOMPARE( sources.at( 1 ).parameterName(), QStringLiteral( "vl" ) ); } void TestQgsProcessing::tempUtils()