diff --git a/python/core/processing/qgsprocessingutils.sip b/python/core/processing/qgsprocessingutils.sip index 6392236ad42..dee3ec21797 100644 --- a/python/core/processing/qgsprocessingutils.sip +++ b/python/core/processing/qgsprocessingutils.sip @@ -79,6 +79,20 @@ class QgsProcessingUtils :rtype: QgsMapLayer %End + static QgsProcessingFeatureSource *variantToSource( const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue = QVariant() ) /Factory/; +%Docstring + Converts a variant ``value`` to a new feature source. + + Sources will either be taken from ``context``'s active project, or loaded from external + sources and stored temporarily in the ``context``. + + The optional ``fallbackValue`` can be used to specify a "default" value which is used + if ``value`` cannot be successfully converted to a source. + + This function creates a new object and the caller takes responsibility for deleting the returned object. + :rtype: QgsProcessingFeatureSource +%End + static QString normalizeLayerSource( const QString &source ); %Docstring Normalizes a layer ``source`` string for safe comparison across different diff --git a/src/core/processing/qgsprocessingparameters.cpp b/src/core/processing/qgsprocessingparameters.cpp index 151a64bad21..6e33948ed8d 100644 --- a/src/core/processing/qgsprocessingparameters.cpp +++ b/src/core/processing/qgsprocessingparameters.cpp @@ -277,55 +277,7 @@ QgsProcessingFeatureSource *QgsProcessingParameters::parameterAsSource( const Qg QVariant val = parameters.value( definition->name() ); - bool selectedFeaturesOnly = false; - if ( val.canConvert() ) - { - // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it - QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast( val ); - selectedFeaturesOnly = fromVar.selectedFeaturesOnly; - val = fromVar.source; - } - - if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast( val ) ) ) - { - return new QgsProcessingFeatureSource( layer, context ); - } - - QString layerRef; - if ( val.canConvert() ) - { - layerRef = val.value< QgsProperty >().valueAsString( context.expressionContext(), definition->defaultValue().toString() ); - } - else if ( !val.isValid() || val.toString().isEmpty() ) - { - // fall back to default - if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast( definition->defaultValue() ) ) ) - { - return new QgsProcessingFeatureSource( layer, context ); - } - - layerRef = definition->defaultValue().toString(); - } - else - { - layerRef = val.toString(); - } - - if ( layerRef.isEmpty() ) - return nullptr; - - QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context ) ); - if ( !vl ) - return nullptr; - - if ( selectedFeaturesOnly ) - { - return new QgsProcessingFeatureSource( new QgsVectorLayerSelectedFeatureSource( vl ), context, true ); - } - else - { - return new QgsProcessingFeatureSource( vl, context ); - } + return QgsProcessingUtils::variantToSource( val, context, definition->defaultValue() ); } QString QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( const QgsProcessingParameterDefinition *definition, const QVariantMap ¶meters, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingFeedback *feedback ) diff --git a/src/core/processing/qgsprocessingutils.cpp b/src/core/processing/qgsprocessingutils.cpp index b7689194652..f4ede6c4fd4 100644 --- a/src/core/processing/qgsprocessingutils.cpp +++ b/src/core/processing/qgsprocessingutils.cpp @@ -25,6 +25,7 @@ #include "qgsmemoryproviderutils.h" #include "qgsprocessingparameters.h" #include "qgsprocessingalgorithm.h" +#include "qgsvectorlayerfeatureiterator.h" QList QgsProcessingUtils::compatibleRasterLayers( QgsProject *project, bool sort ) { @@ -208,6 +209,60 @@ QgsMapLayer *QgsProcessingUtils::mapLayerFromString( const QString &string, QgsP } } +QgsProcessingFeatureSource *QgsProcessingUtils::variantToSource( const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue ) +{ + QVariant val = value; + bool selectedFeaturesOnly = false; + if ( val.canConvert() ) + { + // input is a QgsProcessingFeatureSourceDefinition - get extra properties from it + QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast( val ); + selectedFeaturesOnly = fromVar.selectedFeaturesOnly; + val = fromVar.source; + } + + if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast( val ) ) ) + { + return new QgsProcessingFeatureSource( layer, context ); + } + + QString layerRef; + if ( val.canConvert() ) + { + layerRef = val.value< QgsProperty >().valueAsString( context.expressionContext(), fallbackValue.toString() ); + } + else if ( !val.isValid() || val.toString().isEmpty() ) + { + // fall back to default + if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast( fallbackValue ) ) ) + { + return new QgsProcessingFeatureSource( layer, context ); + } + + layerRef = fallbackValue.toString(); + } + else + { + layerRef = val.toString(); + } + + if ( layerRef.isEmpty() ) + return nullptr; + + QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( layerRef, context ) ); + if ( !vl ) + return nullptr; + + if ( selectedFeaturesOnly ) + { + return new QgsProcessingFeatureSource( new QgsVectorLayerSelectedFeatureSource( vl ), context, true ); + } + else + { + return new QgsProcessingFeatureSource( vl, context ); + } +} + bool QgsProcessingUtils::canUseLayer( const QgsRasterLayer *layer ) { // only gdal file-based layers diff --git a/src/core/processing/qgsprocessingutils.h b/src/core/processing/qgsprocessingutils.h index cf5e08bcfb5..67a6ef9bb33 100644 --- a/src/core/processing/qgsprocessingutils.h +++ b/src/core/processing/qgsprocessingutils.h @@ -29,6 +29,7 @@ class QgsProject; class QgsProcessingContext; class QgsMapLayerStore; class QgsProcessingFeedback; +class QgsProcessingFeatureSource; #include #include @@ -95,6 +96,19 @@ class CORE_EXPORT QgsProcessingUtils */ static QgsMapLayer *mapLayerFromString( const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers = true ); + /** + * Converts a variant \a value to a new feature source. + * + * Sources will either be taken from \a context's active project, or loaded from external + * sources and stored temporarily in the \a context. + * + * The optional \a fallbackValue can be used to specify a "default" value which is used + * if \a value cannot be successfully converted to a source. + * + * This function creates a new object and the caller takes responsibility for deleting the returned object. + */ + static QgsProcessingFeatureSource *variantToSource( const QVariant &value, QgsProcessingContext &context, const QVariant &fallbackValue = QVariant() ) SIP_FACTORY; + /** * Normalizes a layer \a source string for safe comparison across different * operating system environments.