/*************************************************************************** qgsprocessingalgorithm.cpp -------------------------- begin : December 2016 copyright : (C) 2016 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 "qgsprocessingalgorithm.h" #include "qgsapplication.h" #include "qgsprocessingprovider.h" #include "qgsprocessingparameters.h" #include "qgsprocessingoutputs.h" #include "qgsrectangle.h" #include "qgsprocessingcontext.h" #include "qgsprocessingutils.h" QgsProcessingAlgorithm::~QgsProcessingAlgorithm() { qDeleteAll( mParameters ); qDeleteAll( mOutputs ); } QString QgsProcessingAlgorithm::id() const { if ( mProvider ) return QString( "%1:%2" ).arg( mProvider->id(), name() ); else return name(); } QString QgsProcessingAlgorithm::shortHelpString() const { return QString(); } QString QgsProcessingAlgorithm::helpString() const { return QString(); } QString QgsProcessingAlgorithm::helpUrl() const { return QString(); } QIcon QgsProcessingAlgorithm::icon() const { return QgsApplication::getThemeIcon( "/processingAlgorithm.svg" ); } QString QgsProcessingAlgorithm::svgIconPath() const { return QgsApplication::iconPath( "processingAlgorithm.svg" ); } QgsProcessingAlgorithm::Flags QgsProcessingAlgorithm::flags() const { return FlagSupportsBatch | FlagCanCancel; } bool QgsProcessingAlgorithm::canExecute( QString * ) const { return true; } bool QgsProcessingAlgorithm::checkParameterValues( const QVariantMap ¶meters, QgsProcessingContext &context, QString *message ) const { Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters ) { if ( !def->checkValueIsAcceptable( parameters.value( def->name() ), &context ) ) { if ( message ) *message = QObject::tr( "Incorrect parameter value for %1" ).arg( def->name() ); return false; } } return true; } QgsProcessingProvider *QgsProcessingAlgorithm::provider() const { return mProvider; } void QgsProcessingAlgorithm::setProvider( QgsProcessingProvider *provider ) { mProvider = provider; } QWidget *QgsProcessingAlgorithm::createCustomParametersWidget( QWidget * ) const { return nullptr; } QgsExpressionContext QgsProcessingAlgorithm::createExpressionContext( const QVariantMap ¶meters, QgsProcessingContext &context ) const { // start with context's expression context QgsExpressionContext c = context.expressionContext(); if ( c.scopeCount() == 0 ) { //empty scope, populate with initial scopes c << QgsExpressionContextUtils::globalScope() << QgsExpressionContextUtils::projectScope( context.project() ); } c << QgsExpressionContextUtils::processingAlgorithmScope( this, parameters, context ); return c; } bool QgsProcessingAlgorithm::validateInputCrs( const QVariantMap ¶meters, QgsProcessingContext &context ) const { if ( !( flags() & FlagRequiresMatchingCrs ) ) { // I'm a well behaved algorithm - I take work AWAY from users! return true; } bool foundCrs = false; QgsCoordinateReferenceSystem crs; Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters ) { if ( def->type() == QStringLiteral( "layer" ) || def->type() == QStringLiteral( "raster" ) ) { QgsMapLayer *layer = QgsProcessingParameters::parameterAsLayer( def, parameters, context ); if ( layer ) { if ( foundCrs && layer->crs().isValid() && crs != layer->crs() ) { return false; } else if ( !foundCrs && layer->crs().isValid() ) { foundCrs = true; crs = layer->crs(); } } } else if ( def->type() == QStringLiteral( "source" ) ) { QgsFeatureSource *source = QgsProcessingParameters::parameterAsSource( def, parameters, context ); if ( source ) { if ( foundCrs && source->sourceCrs().isValid() && crs != source->sourceCrs() ) { return false; } else if ( !foundCrs && source->sourceCrs().isValid() ) { foundCrs = true; crs = source->sourceCrs(); } } } else if ( def->type() == QStringLiteral( "multilayer" ) ) { QList< QgsMapLayer *> layers = QgsProcessingParameters::parameterAsLayerList( def, parameters, context ); Q_FOREACH ( QgsMapLayer *layer, layers ) { if ( !layer ) continue; if ( foundCrs && layer->crs().isValid() && crs != layer->crs() ) { return false; } else if ( !foundCrs && layer->crs().isValid() ) { foundCrs = true; crs = layer->crs(); } } } } return true; } bool QgsProcessingAlgorithm::addParameter( QgsProcessingParameterDefinition *definition ) { if ( !definition ) return false; // check for duplicate named parameters if ( QgsProcessingAlgorithm::parameterDefinition( definition->name() ) ) return false; mParameters << definition; return true; } bool QgsProcessingAlgorithm::addOutput( QgsProcessingOutputDefinition *definition ) { if ( !definition ) return false; // check for duplicate named outputs if ( QgsProcessingAlgorithm::outputDefinition( definition->name() ) ) return false; mOutputs << definition; return true; } const QgsProcessingParameterDefinition *QgsProcessingAlgorithm::parameterDefinition( const QString &name ) const { Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters ) { if ( def->name().compare( name, Qt::CaseInsensitive ) == 0 ) return def; } return nullptr; } int QgsProcessingAlgorithm::countVisibleParameters() const { int count = 0; Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters ) { if ( !( def->flags() & QgsProcessingParameterDefinition::FlagHidden ) ) count++; } return count; } QgsProcessingParameterDefinitions QgsProcessingAlgorithm::destinationParameterDefinitions() const { QgsProcessingParameterDefinitions result; Q_FOREACH ( const QgsProcessingParameterDefinition *def, mParameters ) { if ( !def->isDestination() ) continue; result << def; } return result; } const QgsProcessingOutputDefinition *QgsProcessingAlgorithm::outputDefinition( const QString &name ) const { Q_FOREACH ( const QgsProcessingOutputDefinition *def, mOutputs ) { if ( def->name().compare( name, Qt::CaseInsensitive ) == 0 ) return def; } return nullptr; } bool QgsProcessingAlgorithm::hasHtmlOutputs() const { Q_FOREACH ( const QgsProcessingOutputDefinition *def, mOutputs ) { if ( def->type() == QStringLiteral( "outputHtml" ) ) return true; } return false; } QVariantMap QgsProcessingAlgorithm::run( const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) const { return processAlgorithm( parameters, context, feedback ); } QString QgsProcessingAlgorithm::parameterAsString( const QVariantMap ¶meters, const QString &name, const QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsString( parameterDefinition( name ), parameters, context ); } QString QgsProcessingAlgorithm::parameterAsExpression( const QVariantMap ¶meters, const QString &name, const QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsExpression( parameterDefinition( name ), parameters, context ); } double QgsProcessingAlgorithm::parameterAsDouble( const QVariantMap ¶meters, const QString &name, const QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsDouble( parameterDefinition( name ), parameters, context ); } int QgsProcessingAlgorithm::parameterAsInt( const QVariantMap ¶meters, const QString &name, const QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsInt( parameterDefinition( name ), parameters, context ); } int QgsProcessingAlgorithm::parameterAsEnum( const QVariantMap ¶meters, const QString &name, const QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsEnum( parameterDefinition( name ), parameters, context ); } QList QgsProcessingAlgorithm::parameterAsEnums( const QVariantMap ¶meters, const QString &name, const QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsEnums( parameterDefinition( name ), parameters, context ); } bool QgsProcessingAlgorithm::parameterAsBool( const QVariantMap ¶meters, const QString &name, const QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsBool( parameterDefinition( name ), parameters, context ); } QgsFeatureSink *QgsProcessingAlgorithm::parameterAsSink( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QString &destinationIdentifier ) const { return QgsProcessingParameters::parameterAsSink( parameterDefinition( name ), parameters, fields, geometryType, crs, context, destinationIdentifier ); } QgsFeatureSource *QgsProcessingAlgorithm::parameterAsSource( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsSource( parameterDefinition( name ), parameters, context ); } QgsMapLayer *QgsProcessingAlgorithm::parameterAsLayer( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsLayer( parameterDefinition( name ), parameters, context ); } QgsRasterLayer *QgsProcessingAlgorithm::parameterAsRasterLayer( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsRasterLayer( parameterDefinition( name ), parameters, context ); } QString QgsProcessingAlgorithm::parameterAsRasterOutputLayer( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsRasterOutputLayer( parameterDefinition( name ), parameters, context ); } QString QgsProcessingAlgorithm::parameterAsFileOutput( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsFileOutput( parameterDefinition( name ), parameters, context ); } QgsVectorLayer *QgsProcessingAlgorithm::parameterAsVectorLayer( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsVectorLayer( parameterDefinition( name ), parameters, context ); } QgsCoordinateReferenceSystem QgsProcessingAlgorithm::parameterAsCrs( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsCrs( parameterDefinition( name ), parameters, context ); } QgsRectangle QgsProcessingAlgorithm::parameterAsExtent( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsExtent( parameterDefinition( name ), parameters, context ); } QgsPointXY QgsProcessingAlgorithm::parameterAsPoint( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsPoint( parameterDefinition( name ), parameters, context ); } QString QgsProcessingAlgorithm::parameterAsFile( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsFile( parameterDefinition( name ), parameters, context ); } QVariantList QgsProcessingAlgorithm::parameterAsMatrix( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsMatrix( parameterDefinition( name ), parameters, context ); } QList QgsProcessingAlgorithm::parameterAsLayerList( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsLayerList( parameterDefinition( name ), parameters, context ); } QList QgsProcessingAlgorithm::parameterAsRange( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsRange( parameterDefinition( name ), parameters, context ); } QStringList QgsProcessingAlgorithm::parameterAsFields( const QVariantMap ¶meters, const QString &name, QgsProcessingContext &context ) const { return QgsProcessingParameters::parameterAsFields( parameterDefinition( name ), parameters, context ); }