LCOV - code coverage report
Current view: top level - core/processing - qgsprocessingalgorithm.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 591 0.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                          qgsprocessingalgorithm.cpp
       3                 :            :                          --------------------------
       4                 :            :     begin                : December 2016
       5                 :            :     copyright            : (C) 2016 by Nyall Dawson
       6                 :            :     email                : nyall dot dawson at gmail dot com
       7                 :            :  ***************************************************************************/
       8                 :            : 
       9                 :            : /***************************************************************************
      10                 :            :  *                                                                         *
      11                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      12                 :            :  *   it under the terms of the GNU General Public License as published by  *
      13                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      14                 :            :  *   (at your option) any later version.                                   *
      15                 :            :  *                                                                         *
      16                 :            :  ***************************************************************************/
      17                 :            : 
      18                 :            : #include "qgsprocessingalgorithm.h"
      19                 :            : #include "qgsapplication.h"
      20                 :            : #include "qgsprocessingprovider.h"
      21                 :            : #include "qgsprocessingparameters.h"
      22                 :            : #include "qgsprocessingoutputs.h"
      23                 :            : #include "qgsrectangle.h"
      24                 :            : #include "qgsprocessingcontext.h"
      25                 :            : #include "qgsprocessingutils.h"
      26                 :            : #include "qgsexception.h"
      27                 :            : #include "qgsmessagelog.h"
      28                 :            : #include "qgsvectorlayer.h"
      29                 :            : #include "qgsprocessingfeedback.h"
      30                 :            : #include "qgsmeshlayer.h"
      31                 :            : #include "qgsexpressioncontextutils.h"
      32                 :            : 
      33                 :            : 
      34                 :          0 : QgsProcessingAlgorithm::~QgsProcessingAlgorithm()
      35                 :          0 : {
      36                 :          0 :   qDeleteAll( mParameters );
      37                 :          0 :   qDeleteAll( mOutputs );
      38                 :          0 : }
      39                 :            : 
      40                 :          0 : QgsProcessingAlgorithm *QgsProcessingAlgorithm::create( const QVariantMap &configuration ) const
      41                 :            : {
      42                 :          0 :   std::unique_ptr< QgsProcessingAlgorithm > creation( createInstance() );
      43                 :          0 :   if ( ! creation )
      44                 :          0 :     throw QgsProcessingException( QObject::tr( "Error creating algorithm from createInstance()" ) );
      45                 :          0 :   creation->setProvider( provider() );
      46                 :          0 :   creation->initAlgorithm( configuration );
      47                 :          0 :   return creation.release();
      48                 :          0 : }
      49                 :            : 
      50                 :          0 : QString QgsProcessingAlgorithm::id() const
      51                 :            : {
      52                 :          0 :   if ( mProvider )
      53                 :          0 :     return QStringLiteral( "%1:%2" ).arg( mProvider->id(), name() );
      54                 :            :   else
      55                 :          0 :     return name();
      56                 :          0 : }
      57                 :            : 
      58                 :          0 : QString QgsProcessingAlgorithm::shortDescription() const
      59                 :            : {
      60                 :          0 :   return QString();
      61                 :            : }
      62                 :            : 
      63                 :          0 : QString QgsProcessingAlgorithm::shortHelpString() const
      64                 :            : {
      65                 :          0 :   return QString();
      66                 :            : }
      67                 :            : 
      68                 :          0 : QString QgsProcessingAlgorithm::helpString() const
      69                 :            : {
      70                 :          0 :   return QString();
      71                 :            : }
      72                 :            : 
      73                 :          0 : QString QgsProcessingAlgorithm::helpUrl() const
      74                 :            : {
      75                 :          0 :   return QString();
      76                 :            : }
      77                 :            : 
      78                 :          0 : QIcon QgsProcessingAlgorithm::icon() const
      79                 :            : {
      80                 :          0 :   return QgsApplication::getThemeIcon( "/processingAlgorithm.svg" );
      81                 :          0 : }
      82                 :            : 
      83                 :          0 : QString QgsProcessingAlgorithm::svgIconPath() const
      84                 :            : {
      85                 :          0 :   return QgsApplication::iconPath( QStringLiteral( "processingAlgorithm.svg" ) );
      86                 :          0 : }
      87                 :            : 
      88                 :          0 : QgsProcessingAlgorithm::Flags QgsProcessingAlgorithm::flags() const
      89                 :            : {
      90                 :          0 :   return FlagSupportsBatch | FlagCanCancel;
      91                 :            : }
      92                 :            : 
      93                 :          0 : bool QgsProcessingAlgorithm::canExecute( QString * ) const
      94                 :            : {
      95                 :          0 :   return true;
      96                 :            : }
      97                 :            : 
      98                 :          0 : bool QgsProcessingAlgorithm::checkParameterValues( const QVariantMap &parameters, QgsProcessingContext &context, QString *message ) const
      99                 :            : {
     100                 :          0 :   for ( const QgsProcessingParameterDefinition *def : mParameters )
     101                 :            :   {
     102                 :          0 :     if ( !def->checkValueIsAcceptable( parameters.value( def->name() ), &context ) )
     103                 :            :     {
     104                 :          0 :       if ( message )
     105                 :            :       {
     106                 :            :         // TODO QGIS 4 - move the message handling to the parameter subclasses (but this
     107                 :            :         // requires a change in signature for the virtual checkValueIsAcceptable method)
     108                 :          0 :         if ( def->type() == QgsProcessingParameterFeatureSource::typeName() )
     109                 :          0 :           *message = invalidSourceError( parameters, def->name() );
     110                 :          0 :         else if ( def->type() == QgsProcessingParameterFeatureSink::typeName() )
     111                 :          0 :           *message = invalidSinkError( parameters, def->name() );
     112                 :          0 :         else if ( def->type() == QgsProcessingParameterRasterLayer::typeName() )
     113                 :          0 :           *message = invalidRasterError( parameters, def->name() );
     114                 :            :         else
     115                 :          0 :           *message = QObject::tr( "Incorrect parameter value for %1" ).arg( def->name() );
     116                 :          0 :       }
     117                 :          0 :       return false;
     118                 :            :     }
     119                 :            :   }
     120                 :          0 :   return true;
     121                 :          0 : }
     122                 :            : 
     123                 :          0 : QVariantMap QgsProcessingAlgorithm::preprocessParameters( const QVariantMap &parameters )
     124                 :            : {
     125                 :          0 :   return parameters;
     126                 :            : }
     127                 :            : 
     128                 :          0 : QgsProcessingProvider *QgsProcessingAlgorithm::provider() const
     129                 :            : {
     130                 :          0 :   return mProvider;
     131                 :            : }
     132                 :            : 
     133                 :          0 : void QgsProcessingAlgorithm::setProvider( QgsProcessingProvider *provider )
     134                 :            : {
     135                 :          0 :   mProvider = provider;
     136                 :            : 
     137                 :          0 :   if ( mProvider && !mProvider->supportsNonFileBasedOutput() )
     138                 :            :   {
     139                 :            :     // need to update all destination parameters to turn off non file based outputs
     140                 :          0 :     for ( const QgsProcessingParameterDefinition *definition : std::as_const( mParameters ) )
     141                 :            :     {
     142                 :          0 :       if ( definition->isDestination() )
     143                 :            :       {
     144                 :          0 :         const QgsProcessingDestinationParameter *destParam = static_cast< const QgsProcessingDestinationParameter *>( definition );
     145                 :          0 :         const_cast< QgsProcessingDestinationParameter *>( destParam )->setSupportsNonFileBasedOutput( false );
     146                 :          0 :       }
     147                 :            :     }
     148                 :          0 :   }
     149                 :          0 : }
     150                 :            : 
     151                 :          0 : QWidget *QgsProcessingAlgorithm::createCustomParametersWidget( QWidget * ) const
     152                 :            : {
     153                 :          0 :   return nullptr;
     154                 :            : }
     155                 :            : 
     156                 :          0 : QgsExpressionContext QgsProcessingAlgorithm::createExpressionContext( const QVariantMap &parameters,
     157                 :            :     QgsProcessingContext &context, QgsProcessingFeatureSource *source ) const
     158                 :            : {
     159                 :            :   // start with context's expression context
     160                 :          0 :   QgsExpressionContext c = context.expressionContext();
     161                 :            : 
     162                 :            :   // If there's a source capable of generating a context scope, use it
     163                 :          0 :   if ( source )
     164                 :            :   {
     165                 :          0 :     QgsExpressionContextScope *scope = source->createExpressionContextScope();
     166                 :          0 :     if ( scope )
     167                 :          0 :       c << scope;
     168                 :          0 :   }
     169                 :          0 :   else if ( c.scopeCount() == 0 )
     170                 :            :   {
     171                 :            :     //empty scope, populate with initial scopes
     172                 :          0 :     c << QgsExpressionContextUtils::globalScope()
     173                 :          0 :       << QgsExpressionContextUtils::projectScope( context.project() );
     174                 :          0 :   }
     175                 :            : 
     176                 :          0 :   c << QgsExpressionContextUtils::processingAlgorithmScope( this, parameters, context );
     177                 :          0 :   return c;
     178                 :          0 : }
     179                 :            : 
     180                 :          0 : bool QgsProcessingAlgorithm::validateInputCrs( const QVariantMap &parameters, QgsProcessingContext &context ) const
     181                 :            : {
     182                 :          0 :   if ( !( flags() & FlagRequiresMatchingCrs ) )
     183                 :            :   {
     184                 :            :     // I'm a well behaved algorithm - I take work AWAY from users!
     185                 :          0 :     return true;
     186                 :            :   }
     187                 :            : 
     188                 :          0 :   bool foundCrs = false;
     189                 :          0 :   QgsCoordinateReferenceSystem crs;
     190                 :          0 :   for ( const QgsProcessingParameterDefinition *def : mParameters )
     191                 :            :   {
     192                 :          0 :     if ( def->type() == QgsProcessingParameterMapLayer::typeName() || def->type() == QgsProcessingParameterRasterLayer::typeName() )
     193                 :            :     {
     194                 :          0 :       QgsMapLayer *layer = QgsProcessingParameters::parameterAsLayer( def, parameters, context );
     195                 :          0 :       if ( layer )
     196                 :            :       {
     197                 :          0 :         if ( foundCrs && layer->crs().isValid() && crs != layer->crs() )
     198                 :            :         {
     199                 :          0 :           return false;
     200                 :            :         }
     201                 :          0 :         else if ( !foundCrs && layer->crs().isValid() )
     202                 :            :         {
     203                 :          0 :           foundCrs = true;
     204                 :          0 :           crs = layer->crs();
     205                 :          0 :         }
     206                 :          0 :       }
     207                 :          0 :     }
     208                 :          0 :     else if ( def->type() == QgsProcessingParameterFeatureSource::typeName() )
     209                 :            :     {
     210                 :          0 :       std::unique_ptr< QgsFeatureSource  > source( QgsProcessingParameters::parameterAsSource( def, parameters, context ) );
     211                 :          0 :       if ( source )
     212                 :            :       {
     213                 :          0 :         if ( foundCrs && source->sourceCrs().isValid() && crs != source->sourceCrs() )
     214                 :            :         {
     215                 :          0 :           return false;
     216                 :            :         }
     217                 :          0 :         else if ( !foundCrs && source->sourceCrs().isValid() )
     218                 :            :         {
     219                 :          0 :           foundCrs = true;
     220                 :          0 :           crs = source->sourceCrs();
     221                 :          0 :         }
     222                 :          0 :       }
     223                 :          0 :     }
     224                 :          0 :     else if ( def->type() == QgsProcessingParameterMultipleLayers::typeName() )
     225                 :            :     {
     226                 :          0 :       QList< QgsMapLayer *> layers = QgsProcessingParameters::parameterAsLayerList( def, parameters, context );
     227                 :          0 :       const auto constLayers = layers;
     228                 :          0 :       for ( QgsMapLayer *layer : constLayers )
     229                 :            :       {
     230                 :          0 :         if ( !layer )
     231                 :          0 :           continue;
     232                 :            : 
     233                 :          0 :         if ( foundCrs && layer->crs().isValid() && crs != layer->crs() )
     234                 :            :         {
     235                 :          0 :           return false;
     236                 :            :         }
     237                 :          0 :         else if ( !foundCrs && layer->crs().isValid() )
     238                 :            :         {
     239                 :          0 :           foundCrs = true;
     240                 :          0 :           crs = layer->crs();
     241                 :          0 :         }
     242                 :            :       }
     243                 :          0 :     }
     244                 :          0 :     else if ( def->type() == QgsProcessingParameterExtent::typeName() )
     245                 :            :     {
     246                 :          0 :       QgsCoordinateReferenceSystem extentCrs = QgsProcessingParameters::parameterAsExtentCrs( def, parameters, context );
     247                 :          0 :       if ( foundCrs && extentCrs.isValid() && crs != extentCrs )
     248                 :            :       {
     249                 :          0 :         return false;
     250                 :            :       }
     251                 :          0 :       else if ( !foundCrs && extentCrs.isValid() )
     252                 :            :       {
     253                 :          0 :         foundCrs = true;
     254                 :          0 :         crs = extentCrs;
     255                 :          0 :       }
     256                 :          0 :     }
     257                 :          0 :     else if ( def->type() == QgsProcessingParameterPoint::typeName() )
     258                 :            :     {
     259                 :          0 :       QgsCoordinateReferenceSystem pointCrs = QgsProcessingParameters::parameterAsPointCrs( def, parameters, context );
     260                 :          0 :       if ( foundCrs && pointCrs.isValid() && crs != pointCrs )
     261                 :            :       {
     262                 :          0 :         return false;
     263                 :            :       }
     264                 :          0 :       else if ( !foundCrs && pointCrs.isValid() )
     265                 :            :       {
     266                 :          0 :         foundCrs = true;
     267                 :          0 :         crs = pointCrs;
     268                 :          0 :       }
     269                 :          0 :     }
     270                 :          0 :     else if ( def->type() == QgsProcessingParameterGeometry::typeName() )
     271                 :            :     {
     272                 :          0 :       QgsCoordinateReferenceSystem geomCrs = QgsProcessingParameters::parameterAsGeometryCrs( def, parameters, context );
     273                 :          0 :       if ( foundCrs && geomCrs.isValid() && crs != geomCrs )
     274                 :            :       {
     275                 :          0 :         return false;
     276                 :            :       }
     277                 :          0 :       else if ( !foundCrs && geomCrs.isValid() )
     278                 :            :       {
     279                 :          0 :         foundCrs = true;
     280                 :          0 :         crs = geomCrs;
     281                 :          0 :       }
     282                 :          0 :     }
     283                 :            : 
     284                 :            :   }
     285                 :          0 :   return true;
     286                 :          0 : }
     287                 :            : 
     288                 :          0 : QString QgsProcessingAlgorithm::asPythonCommand( const QVariantMap &parameters, QgsProcessingContext &context ) const
     289                 :            : {
     290                 :          0 :   QString s = QStringLiteral( "processing.run(\"%1\"," ).arg( id() );
     291                 :            : 
     292                 :          0 :   QStringList parts;
     293                 :          0 :   for ( const QgsProcessingParameterDefinition *def : mParameters )
     294                 :            :   {
     295                 :          0 :     if ( def->flags() & QgsProcessingParameterDefinition::FlagHidden )
     296                 :          0 :       continue;
     297                 :            : 
     298                 :          0 :     if ( !parameters.contains( def->name() ) )
     299                 :          0 :       continue;
     300                 :            : 
     301                 :          0 :     parts << QStringLiteral( "'%1':%2" ).arg( def->name(), def->valueAsPythonString( parameters.value( def->name() ), context ) );
     302                 :            :   }
     303                 :            : 
     304                 :          0 :   s += QStringLiteral( " {%1})" ).arg( parts.join( ',' ) );
     305                 :          0 :   return s;
     306                 :          0 : }
     307                 :            : 
     308                 :          0 : bool QgsProcessingAlgorithm::addParameter( QgsProcessingParameterDefinition *definition, bool createOutput )
     309                 :            : {
     310                 :          0 :   if ( !definition )
     311                 :          0 :     return false;
     312                 :            : 
     313                 :            :   // check for duplicate named parameters
     314                 :          0 :   const QgsProcessingParameterDefinition *existingDef = QgsProcessingAlgorithm::parameterDefinition( definition->name() );
     315                 :          0 :   if ( existingDef && existingDef->name() == definition->name() ) // parameterDefinition is case-insensitive, but we DO allow case-different duplicate names
     316                 :            :   {
     317                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Duplicate parameter %1 registered for alg %2" ).arg( definition->name(), id() ), QObject::tr( "Processing" ) );
     318                 :          0 :     delete definition;
     319                 :          0 :     return false;
     320                 :            :   }
     321                 :            : 
     322                 :          0 :   if ( definition->isDestination() && mProvider )
     323                 :            :   {
     324                 :          0 :     QgsProcessingDestinationParameter *destParam = static_cast< QgsProcessingDestinationParameter *>( definition );
     325                 :          0 :     if ( !mProvider->supportsNonFileBasedOutput() )
     326                 :          0 :       destParam->setSupportsNonFileBasedOutput( false );
     327                 :          0 :   }
     328                 :            : 
     329                 :          0 :   mParameters << definition;
     330                 :          0 :   definition->mAlgorithm = this;
     331                 :            : 
     332                 :          0 :   if ( createOutput )
     333                 :          0 :     return createAutoOutputForParameter( definition );
     334                 :            :   else
     335                 :          0 :     return true;
     336                 :          0 : }
     337                 :            : 
     338                 :          0 : void QgsProcessingAlgorithm::removeParameter( const QString &name )
     339                 :            : {
     340                 :          0 :   const QgsProcessingParameterDefinition *def = parameterDefinition( name );
     341                 :          0 :   if ( def )
     342                 :            :   {
     343                 :          0 :     delete def;
     344                 :          0 :     mParameters.removeAll( def );
     345                 :            : 
     346                 :            :     // remove output automatically created when adding parameter
     347                 :          0 :     const QgsProcessingOutputDefinition *outputDef = QgsProcessingAlgorithm::outputDefinition( name );
     348                 :          0 :     if ( outputDef && outputDef->autoCreated() )
     349                 :            :     {
     350                 :          0 :       delete outputDef;
     351                 :          0 :       mOutputs.removeAll( outputDef );
     352                 :          0 :     }
     353                 :          0 :   }
     354                 :          0 : }
     355                 :            : 
     356                 :          0 : bool QgsProcessingAlgorithm::addOutput( QgsProcessingOutputDefinition *definition )
     357                 :            : {
     358                 :          0 :   if ( !definition )
     359                 :          0 :     return false;
     360                 :            : 
     361                 :            :   // check for duplicate named outputs
     362                 :          0 :   if ( QgsProcessingAlgorithm::outputDefinition( definition->name() ) )
     363                 :            :   {
     364                 :          0 :     QgsMessageLog::logMessage( QObject::tr( "Duplicate output %1 registered for alg %2" ).arg( definition->name(), id() ), QObject::tr( "Processing" ) );
     365                 :          0 :     delete definition;
     366                 :          0 :     return false;
     367                 :            :   }
     368                 :            : 
     369                 :          0 :   mOutputs << definition;
     370                 :          0 :   return true;
     371                 :          0 : }
     372                 :            : 
     373                 :          0 : bool QgsProcessingAlgorithm::prepareAlgorithm( const QVariantMap &, QgsProcessingContext &, QgsProcessingFeedback * )
     374                 :            : {
     375                 :          0 :   return true;
     376                 :            : }
     377                 :            : 
     378                 :          0 : QVariantMap QgsProcessingAlgorithm::postProcessAlgorithm( QgsProcessingContext &, QgsProcessingFeedback * )
     379                 :            : {
     380                 :          0 :   return QVariantMap();
     381                 :            : }
     382                 :            : 
     383                 :          0 : const QgsProcessingParameterDefinition *QgsProcessingAlgorithm::parameterDefinition( const QString &name ) const
     384                 :            : {
     385                 :            :   // first pass - case sensitive match
     386                 :          0 :   for ( const QgsProcessingParameterDefinition *def : mParameters )
     387                 :            :   {
     388                 :          0 :     if ( def->name() == name )
     389                 :          0 :       return def;
     390                 :            :   }
     391                 :            : 
     392                 :            :   // second pass - case insensitive
     393                 :          0 :   for ( const QgsProcessingParameterDefinition *def : mParameters )
     394                 :            :   {
     395                 :          0 :     if ( def->name().compare( name, Qt::CaseInsensitive ) == 0 )
     396                 :          0 :       return def;
     397                 :            :   }
     398                 :          0 :   return nullptr;
     399                 :          0 : }
     400                 :            : 
     401                 :          0 : int QgsProcessingAlgorithm::countVisibleParameters() const
     402                 :            : {
     403                 :          0 :   int count = 0;
     404                 :          0 :   for ( const QgsProcessingParameterDefinition *def : mParameters )
     405                 :            :   {
     406                 :          0 :     if ( !( def->flags() & QgsProcessingParameterDefinition::FlagHidden ) )
     407                 :          0 :       count++;
     408                 :            :   }
     409                 :          0 :   return count;
     410                 :            : }
     411                 :            : 
     412                 :          0 : QgsProcessingParameterDefinitions QgsProcessingAlgorithm::destinationParameterDefinitions() const
     413                 :            : {
     414                 :          0 :   QgsProcessingParameterDefinitions result;
     415                 :          0 :   for ( const QgsProcessingParameterDefinition *def : mParameters )
     416                 :            :   {
     417                 :          0 :     if ( def->isDestination() )
     418                 :          0 :       result << def;
     419                 :            :   }
     420                 :          0 :   return result;
     421                 :          0 : }
     422                 :            : 
     423                 :          0 : const QgsProcessingOutputDefinition *QgsProcessingAlgorithm::outputDefinition( const QString &name ) const
     424                 :            : {
     425                 :          0 :   for ( const QgsProcessingOutputDefinition *def : mOutputs )
     426                 :            :   {
     427                 :          0 :     if ( def->name().compare( name, Qt::CaseInsensitive ) == 0 )
     428                 :          0 :       return def;
     429                 :            :   }
     430                 :          0 :   return nullptr;
     431                 :          0 : }
     432                 :            : 
     433                 :          0 : bool QgsProcessingAlgorithm::hasHtmlOutputs() const
     434                 :            : {
     435                 :          0 :   for ( const QgsProcessingOutputDefinition *def : mOutputs )
     436                 :            :   {
     437                 :          0 :     if ( def->type() == QLatin1String( "outputHtml" ) )
     438                 :          0 :       return true;
     439                 :            :   }
     440                 :          0 :   return false;
     441                 :          0 : }
     442                 :            : 
     443                 :          0 : QgsProcessingAlgorithm::VectorProperties QgsProcessingAlgorithm::sinkProperties( const QString &, const QVariantMap &, QgsProcessingContext &, const QMap<QString, QgsProcessingAlgorithm::VectorProperties> & ) const
     444                 :            : {
     445                 :          0 :   return VectorProperties();
     446                 :            : }
     447                 :            : 
     448                 :          0 : QVariantMap QgsProcessingAlgorithm::run( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback, bool *ok, const QVariantMap &configuration, bool catchExceptions ) const
     449                 :            : {
     450                 :          0 :   std::unique_ptr< QgsProcessingAlgorithm > alg( create( configuration ) );
     451                 :          0 :   if ( ok )
     452                 :          0 :     *ok = false;
     453                 :            : 
     454                 :          0 :   bool res = alg->prepare( parameters, context, feedback );
     455                 :          0 :   if ( !res )
     456                 :          0 :     return QVariantMap();
     457                 :            : 
     458                 :          0 :   QVariantMap runRes;
     459                 :            :   try
     460                 :            :   {
     461                 :          0 :     runRes = alg->runPrepared( parameters, context, feedback );
     462                 :          0 :   }
     463                 :            :   catch ( QgsProcessingException &e )
     464                 :            :   {
     465                 :          0 :     if ( !catchExceptions )
     466                 :          0 :       throw e;
     467                 :            : 
     468                 :          0 :     QgsMessageLog::logMessage( e.what(), QObject::tr( "Processing" ), Qgis::Critical );
     469                 :          0 :     feedback->reportError( e.what() );
     470                 :          0 :     return QVariantMap();
     471                 :          0 :   }
     472                 :            : 
     473                 :          0 :   if ( ok )
     474                 :          0 :     *ok = true;
     475                 :            : 
     476                 :          0 :   QVariantMap ppRes = alg->postProcess( context, feedback );
     477                 :          0 :   if ( !ppRes.isEmpty() )
     478                 :          0 :     return ppRes;
     479                 :            :   else
     480                 :          0 :     return runRes;
     481                 :          0 : }
     482                 :            : 
     483                 :          0 : bool QgsProcessingAlgorithm::prepare( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
     484                 :            : {
     485                 :            :   Q_ASSERT_X( QThread::currentThread() == context.temporaryLayerStore()->thread(), "QgsProcessingAlgorithm::prepare", "prepare() must be called from the same thread as context was created in" );
     486                 :            :   Q_ASSERT_X( !mHasPrepared, "QgsProcessingAlgorithm::prepare", "prepare() has already been called for the algorithm instance" );
     487                 :            :   try
     488                 :            :   {
     489                 :          0 :     mHasPrepared = prepareAlgorithm( parameters, context, feedback );
     490                 :          0 :     return mHasPrepared;
     491                 :          0 :   }
     492                 :            :   catch ( QgsProcessingException &e )
     493                 :            :   {
     494                 :          0 :     QgsMessageLog::logMessage( e.what(), QObject::tr( "Processing" ), Qgis::Critical );
     495                 :          0 :     feedback->reportError( e.what() );
     496                 :          0 :     return false;
     497                 :          0 :   }
     498                 :          0 : }
     499                 :            : 
     500                 :          0 : QVariantMap QgsProcessingAlgorithm::runPrepared( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
     501                 :            : {
     502                 :            :   Q_ASSERT_X( mHasPrepared, "QgsProcessingAlgorithm::runPrepared", QStringLiteral( "prepare() was not called for the algorithm instance %1" ).arg( name() ).toLatin1() );
     503                 :            :   Q_ASSERT_X( !mHasExecuted, "QgsProcessingAlgorithm::runPrepared", "runPrepared() was already called for this algorithm instance" );
     504                 :            : 
     505                 :            :   // Hey kids, let's all be thread safe! It's the fun thing to do!
     506                 :            :   //
     507                 :            :   // First, let's see if we're going to run into issues.
     508                 :          0 :   QgsProcessingContext *runContext = nullptr;
     509                 :          0 :   if ( context.thread() == QThread::currentThread() )
     510                 :            :   {
     511                 :            :     // OH. No issues. Seems you're running everything in the same thread, so go about your business. Sorry about
     512                 :            :     // the intrusion, we're just making sure everything's nice and safe here. We like to keep a clean and tidy neighbourhood,
     513                 :            :     // you know, for the kids and dogs and all.
     514                 :          0 :     runContext = &context;
     515                 :          0 :   }
     516                 :            :   else
     517                 :            :   {
     518                 :            :     // HA! I knew things looked a bit suspicious - seems you're running this algorithm in a different thread
     519                 :            :     // from that which the passed context has an affinity for. That's fine and all, but we need to make sure
     520                 :            :     // we proceed safely...
     521                 :            : 
     522                 :            :     // So first we create a temporary local context with affinity for the current thread
     523                 :          0 :     mLocalContext.reset( new QgsProcessingContext() );
     524                 :            :     // copy across everything we can safely do from the passed context
     525                 :          0 :     mLocalContext->copyThreadSafeSettings( context );
     526                 :            :     // and we'll run the actual algorithm processing using the local thread safe context
     527                 :          0 :     runContext = mLocalContext.get();
     528                 :            :   }
     529                 :            : 
     530                 :            :   try
     531                 :            :   {
     532                 :          0 :     QVariantMap runResults = processAlgorithm( parameters, *runContext, feedback );
     533                 :            : 
     534                 :          0 :     mHasExecuted = true;
     535                 :          0 :     if ( mLocalContext )
     536                 :            :     {
     537                 :            :       // ok, time to clean things up. We need to push the temporary context back into
     538                 :            :       // the thread that the passed context is associated with (we can only push from the
     539                 :            :       // current thread, so we HAVE to do this here)
     540                 :          0 :       mLocalContext->pushToThread( context.thread() );
     541                 :          0 :     }
     542                 :          0 :     return runResults;
     543                 :          0 :   }
     544                 :            :   catch ( QgsProcessingException & )
     545                 :            :   {
     546                 :          0 :     if ( mLocalContext )
     547                 :            :     {
     548                 :            :       // see above!
     549                 :          0 :       mLocalContext->pushToThread( context.thread() );
     550                 :          0 :     }
     551                 :            :     //rethrow
     552                 :          0 :     throw;
     553                 :          0 :   }
     554                 :          0 : }
     555                 :            : 
     556                 :          0 : QVariantMap QgsProcessingAlgorithm::postProcess( QgsProcessingContext &context, QgsProcessingFeedback *feedback )
     557                 :            : {
     558                 :            :   Q_ASSERT_X( QThread::currentThread() == context.temporaryLayerStore()->thread(), "QgsProcessingAlgorithm::postProcess", "postProcess() must be called from the same thread the context was created in" );
     559                 :            :   Q_ASSERT_X( mHasExecuted, "QgsProcessingAlgorithm::postProcess", QStringLiteral( "algorithm instance %1 was not executed" ).arg( name() ).toLatin1() );
     560                 :            :   Q_ASSERT_X( !mHasPostProcessed, "QgsProcessingAlgorithm::postProcess", "postProcess() was already called for this algorithm instance" );
     561                 :            : 
     562                 :          0 :   if ( mLocalContext )
     563                 :            :   {
     564                 :            :     // algorithm was processed using a temporary thread safe context. So now we need
     565                 :            :     // to take the results from that temporary context, and smash them into the passed
     566                 :            :     // context
     567                 :          0 :     context.takeResultsFrom( *mLocalContext );
     568                 :            :     // now get lost, we don't need you anymore
     569                 :          0 :     mLocalContext.reset();
     570                 :          0 :   }
     571                 :            : 
     572                 :          0 :   mHasPostProcessed = true;
     573                 :            :   try
     574                 :            :   {
     575                 :          0 :     return postProcessAlgorithm( context, feedback );
     576                 :          0 :   }
     577                 :            :   catch ( QgsProcessingException &e )
     578                 :            :   {
     579                 :          0 :     QgsMessageLog::logMessage( e.what(), QObject::tr( "Processing" ), Qgis::Critical );
     580                 :          0 :     feedback->reportError( e.what() );
     581                 :          0 :     return QVariantMap();
     582                 :          0 :   }
     583                 :          0 : }
     584                 :            : 
     585                 :          0 : QString QgsProcessingAlgorithm::parameterAsString( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     586                 :            : {
     587                 :          0 :   return QgsProcessingParameters::parameterAsString( parameterDefinition( name ), parameters, context );
     588                 :            : }
     589                 :            : 
     590                 :          0 : QString QgsProcessingAlgorithm::parameterAsExpression( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     591                 :            : {
     592                 :          0 :   return QgsProcessingParameters::parameterAsExpression( parameterDefinition( name ), parameters, context );
     593                 :            : }
     594                 :            : 
     595                 :          0 : double QgsProcessingAlgorithm::parameterAsDouble( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     596                 :            : {
     597                 :          0 :   return QgsProcessingParameters::parameterAsDouble( parameterDefinition( name ), parameters, context );
     598                 :            : }
     599                 :            : 
     600                 :          0 : int QgsProcessingAlgorithm::parameterAsInt( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     601                 :            : {
     602                 :          0 :   return QgsProcessingParameters::parameterAsInt( parameterDefinition( name ), parameters, context );
     603                 :            : }
     604                 :            : 
     605                 :          0 : QList<int> QgsProcessingAlgorithm::parameterAsInts( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     606                 :            : {
     607                 :          0 :   return QgsProcessingParameters::parameterAsInts( parameterDefinition( name ), parameters, context );
     608                 :            : }
     609                 :            : 
     610                 :          0 : int QgsProcessingAlgorithm::parameterAsEnum( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     611                 :            : {
     612                 :          0 :   return QgsProcessingParameters::parameterAsEnum( parameterDefinition( name ), parameters, context );
     613                 :            : }
     614                 :            : 
     615                 :          0 : QList<int> QgsProcessingAlgorithm::parameterAsEnums( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     616                 :            : {
     617                 :          0 :   return QgsProcessingParameters::parameterAsEnums( parameterDefinition( name ), parameters, context );
     618                 :            : }
     619                 :            : 
     620                 :          0 : QString QgsProcessingAlgorithm::parameterAsEnumString( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     621                 :            : {
     622                 :          0 :   return QgsProcessingParameters::parameterAsEnumString( parameterDefinition( name ), parameters, context );
     623                 :            : }
     624                 :            : 
     625                 :          0 : QStringList QgsProcessingAlgorithm::parameterAsEnumStrings( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     626                 :            : {
     627                 :          0 :   return QgsProcessingParameters::parameterAsEnumStrings( parameterDefinition( name ), parameters, context );
     628                 :            : }
     629                 :            : 
     630                 :          0 : bool QgsProcessingAlgorithm::parameterAsBool( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     631                 :            : {
     632                 :          0 :   return QgsProcessingParameters::parameterAsBool( parameterDefinition( name ), parameters, context );
     633                 :            : }
     634                 :            : 
     635                 :          0 : bool QgsProcessingAlgorithm::parameterAsBoolean( const QVariantMap &parameters, const QString &name, const QgsProcessingContext &context ) const
     636                 :            : {
     637                 :          0 :   return QgsProcessingParameters::parameterAsBool( parameterDefinition( name ), parameters, context );
     638                 :            : }
     639                 :            : 
     640                 :          0 : QgsFeatureSink *QgsProcessingAlgorithm::parameterAsSink( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, QString &destinationIdentifier, const QgsFields &fields, QgsWkbTypes::Type geometryType, const QgsCoordinateReferenceSystem &crs, QgsFeatureSink::SinkFlags sinkFlags, const QVariantMap &createOptions, const QStringList &datasourceOptions, const QStringList &layerOptions ) const
     641                 :            : {
     642                 :          0 :   if ( !parameterDefinition( name ) )
     643                 :          0 :     throw QgsProcessingException( QObject::tr( "No parameter definition for the sink '%1'" ).arg( name ) );
     644                 :            : 
     645                 :          0 :   return QgsProcessingParameters::parameterAsSink( parameterDefinition( name ), parameters, fields, geometryType, crs, context, destinationIdentifier, sinkFlags, createOptions, datasourceOptions, layerOptions );
     646                 :          0 : }
     647                 :            : 
     648                 :          0 : QgsProcessingFeatureSource *QgsProcessingAlgorithm::parameterAsSource( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     649                 :            : {
     650                 :          0 :   return QgsProcessingParameters::parameterAsSource( parameterDefinition( name ), parameters, context );
     651                 :            : }
     652                 :            : 
     653                 :          0 : QString QgsProcessingAlgorithm::parameterAsCompatibleSourceLayerPath( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingFeedback *feedback )
     654                 :            : {
     655                 :          0 :   return QgsProcessingParameters::parameterAsCompatibleSourceLayerPath( parameterDefinition( name ), parameters, context, compatibleFormats, preferredFormat, feedback );
     656                 :            : }
     657                 :            : 
     658                 :          0 : QString QgsProcessingAlgorithm::parameterAsCompatibleSourceLayerPathAndLayerName( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QStringList &compatibleFormats, const QString &preferredFormat, QgsProcessingFeedback *feedback, QString *layerName )
     659                 :            : {
     660                 :          0 :   return QgsProcessingParameters::parameterAsCompatibleSourceLayerPathAndLayerName( parameterDefinition( name ), parameters, context, compatibleFormats, preferredFormat, feedback, layerName );
     661                 :            : }
     662                 :            : 
     663                 :          0 : QgsMapLayer *QgsProcessingAlgorithm::parameterAsLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     664                 :            : {
     665                 :          0 :   return QgsProcessingParameters::parameterAsLayer( parameterDefinition( name ), parameters, context );
     666                 :            : }
     667                 :            : 
     668                 :          0 : QgsRasterLayer *QgsProcessingAlgorithm::parameterAsRasterLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     669                 :            : {
     670                 :          0 :   return QgsProcessingParameters::parameterAsRasterLayer( parameterDefinition( name ), parameters, context );
     671                 :            : }
     672                 :            : 
     673                 :          0 : QgsMeshLayer *QgsProcessingAlgorithm::parameterAsMeshLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     674                 :            : {
     675                 :          0 :   return QgsProcessingParameters::parameterAsMeshLayer( parameterDefinition( name ), parameters, context );
     676                 :            : }
     677                 :            : 
     678                 :          0 : QString QgsProcessingAlgorithm::parameterAsOutputLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     679                 :            : {
     680                 :          0 :   return QgsProcessingParameters::parameterAsOutputLayer( parameterDefinition( name ), parameters, context );
     681                 :            : }
     682                 :            : 
     683                 :          0 : QString QgsProcessingAlgorithm::parameterAsFileOutput( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     684                 :            : {
     685                 :          0 :   return QgsProcessingParameters::parameterAsFileOutput( parameterDefinition( name ), parameters, context );
     686                 :            : }
     687                 :            : 
     688                 :          0 : QgsVectorLayer *QgsProcessingAlgorithm::parameterAsVectorLayer( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     689                 :            : {
     690                 :          0 :   return QgsProcessingParameters::parameterAsVectorLayer( parameterDefinition( name ), parameters, context );
     691                 :            : }
     692                 :            : 
     693                 :          0 : QgsCoordinateReferenceSystem QgsProcessingAlgorithm::parameterAsCrs( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     694                 :            : {
     695                 :          0 :   return QgsProcessingParameters::parameterAsCrs( parameterDefinition( name ), parameters, context );
     696                 :            : }
     697                 :            : 
     698                 :          0 : QgsCoordinateReferenceSystem QgsProcessingAlgorithm::parameterAsExtentCrs( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
     699                 :            : {
     700                 :          0 :   return QgsProcessingParameters::parameterAsExtentCrs( parameterDefinition( name ), parameters, context );
     701                 :            : }
     702                 :            : 
     703                 :          0 : QgsRectangle QgsProcessingAlgorithm::parameterAsExtent( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs ) const
     704                 :            : {
     705                 :          0 :   return QgsProcessingParameters::parameterAsExtent( parameterDefinition( name ), parameters, context, crs );
     706                 :            : }
     707                 :            : 
     708                 :          0 : QgsGeometry QgsProcessingAlgorithm::parameterAsExtentGeometry( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs )
     709                 :            : {
     710                 :          0 :   return QgsProcessingParameters::parameterAsExtentGeometry( parameterDefinition( name ), parameters, context, crs );
     711                 :            : }
     712                 :            : 
     713                 :          0 : QgsPointXY QgsProcessingAlgorithm::parameterAsPoint( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs ) const
     714                 :            : {
     715                 :          0 :   return QgsProcessingParameters::parameterAsPoint( parameterDefinition( name ), parameters, context, crs );
     716                 :            : }
     717                 :            : 
     718                 :          0 : QgsCoordinateReferenceSystem QgsProcessingAlgorithm::parameterAsPointCrs( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
     719                 :            : {
     720                 :          0 :   return QgsProcessingParameters::parameterAsPointCrs( parameterDefinition( name ), parameters, context );
     721                 :            : }
     722                 :            : 
     723                 :          0 : QgsGeometry QgsProcessingAlgorithm::parameterAsGeometry( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, const QgsCoordinateReferenceSystem &crs ) const
     724                 :            : {
     725                 :          0 :   return QgsProcessingParameters::parameterAsGeometry( parameterDefinition( name ), parameters, context, crs );
     726                 :            : }
     727                 :            : 
     728                 :          0 : QgsCoordinateReferenceSystem QgsProcessingAlgorithm::parameterAsGeometryCrs( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
     729                 :            : {
     730                 :          0 :   return QgsProcessingParameters::parameterAsGeometryCrs( parameterDefinition( name ), parameters, context );
     731                 :            : }
     732                 :            : 
     733                 :          0 : QString QgsProcessingAlgorithm::parameterAsFile( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     734                 :            : {
     735                 :          0 :   return QgsProcessingParameters::parameterAsFile( parameterDefinition( name ), parameters, context );
     736                 :            : }
     737                 :            : 
     738                 :          0 : QVariantList QgsProcessingAlgorithm::parameterAsMatrix( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     739                 :            : {
     740                 :          0 :   return QgsProcessingParameters::parameterAsMatrix( parameterDefinition( name ), parameters, context );
     741                 :            : }
     742                 :            : 
     743                 :          0 : QList<QgsMapLayer *> QgsProcessingAlgorithm::parameterAsLayerList( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     744                 :            : {
     745                 :          0 :   return QgsProcessingParameters::parameterAsLayerList( parameterDefinition( name ), parameters, context );
     746                 :            : }
     747                 :            : 
     748                 :          0 : QStringList QgsProcessingAlgorithm::parameterAsFileList( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     749                 :            : {
     750                 :          0 :   return QgsProcessingParameters::parameterAsFileList( parameterDefinition( name ), parameters, context );
     751                 :            : }
     752                 :            : 
     753                 :          0 : QList<double> QgsProcessingAlgorithm::parameterAsRange( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     754                 :            : {
     755                 :          0 :   return QgsProcessingParameters::parameterAsRange( parameterDefinition( name ), parameters, context );
     756                 :            : }
     757                 :            : 
     758                 :          0 : QStringList QgsProcessingAlgorithm::parameterAsFields( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context ) const
     759                 :            : {
     760                 :          0 :   return QgsProcessingParameters::parameterAsFields( parameterDefinition( name ), parameters, context );
     761                 :            : }
     762                 :            : 
     763                 :          0 : QgsPrintLayout *QgsProcessingAlgorithm::parameterAsLayout( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
     764                 :            : {
     765                 :          0 :   return QgsProcessingParameters::parameterAsLayout( parameterDefinition( name ), parameters, context );
     766                 :            : }
     767                 :            : 
     768                 :          0 : QgsLayoutItem *QgsProcessingAlgorithm::parameterAsLayoutItem( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context, QgsPrintLayout *layout )
     769                 :            : {
     770                 :          0 :   return QgsProcessingParameters::parameterAsLayoutItem( parameterDefinition( name ), parameters, context, layout );
     771                 :            : }
     772                 :            : 
     773                 :          0 : QColor QgsProcessingAlgorithm::parameterAsColor( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
     774                 :            : {
     775                 :          0 :   return QgsProcessingParameters::parameterAsColor( parameterDefinition( name ), parameters, context );
     776                 :            : }
     777                 :            : 
     778                 :          0 : QString QgsProcessingAlgorithm::parameterAsConnectionName( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
     779                 :            : {
     780                 :          0 :   return QgsProcessingParameters::parameterAsConnectionName( parameterDefinition( name ), parameters, context );
     781                 :            : }
     782                 :            : 
     783                 :          0 : QDateTime QgsProcessingAlgorithm::parameterAsDateTime( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
     784                 :            : {
     785                 :          0 :   return QgsProcessingParameters::parameterAsDateTime( parameterDefinition( name ), parameters, context );
     786                 :            : }
     787                 :            : 
     788                 :          0 : QString QgsProcessingAlgorithm::parameterAsSchema( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
     789                 :            : {
     790                 :          0 :   return QgsProcessingParameters::parameterAsSchema( parameterDefinition( name ), parameters, context );
     791                 :            : }
     792                 :            : 
     793                 :          0 : QString QgsProcessingAlgorithm::parameterAsDatabaseTableName( const QVariantMap &parameters, const QString &name, QgsProcessingContext &context )
     794                 :            : {
     795                 :          0 :   return QgsProcessingParameters::parameterAsDatabaseTableName( parameterDefinition( name ), parameters, context );
     796                 :            : }
     797                 :            : 
     798                 :          0 : QString QgsProcessingAlgorithm::invalidSourceError( const QVariantMap &parameters, const QString &name )
     799                 :            : {
     800                 :          0 :   if ( !parameters.contains( name ) )
     801                 :          0 :     return QObject::tr( "Could not load source layer for %1: no value specified for parameter" ).arg( name );
     802                 :            :   else
     803                 :            :   {
     804                 :          0 :     QVariant var = parameters.value( name );
     805                 :          0 :     if ( var.canConvert<QgsProcessingFeatureSourceDefinition>() )
     806                 :            :     {
     807                 :          0 :       QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( var );
     808                 :          0 :       var = fromVar.source;
     809                 :          0 :     }
     810                 :          0 :     else if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
     811                 :            :     {
     812                 :          0 :       QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
     813                 :          0 :       var = fromVar.sink;
     814                 :          0 :     }
     815                 :          0 :     if ( var.canConvert<QgsProperty>() )
     816                 :            :     {
     817                 :          0 :       QgsProperty p = var.value< QgsProperty >();
     818                 :          0 :       if ( p.propertyType() == QgsProperty::StaticProperty )
     819                 :            :       {
     820                 :          0 :         var = p.staticValue();
     821                 :          0 :       }
     822                 :          0 :     }
     823                 :          0 :     if ( !var.toString().isEmpty() )
     824                 :          0 :       return QObject::tr( "Could not load source layer for %1: %2 not found" ).arg( name, var.toString() );
     825                 :            :     else
     826                 :          0 :       return QObject::tr( "Could not load source layer for %1: invalid value" ).arg( name );
     827                 :          0 :   }
     828                 :          0 : }
     829                 :            : 
     830                 :          0 : QString QgsProcessingAlgorithm::invalidRasterError( const QVariantMap &parameters, const QString &name )
     831                 :            : {
     832                 :          0 :   if ( !parameters.contains( name ) )
     833                 :          0 :     return QObject::tr( "Could not load source layer for %1: no value specified for parameter" ).arg( name );
     834                 :            :   else
     835                 :            :   {
     836                 :          0 :     QVariant var = parameters.value( name );
     837                 :          0 :     if ( var.canConvert<QgsProperty>() )
     838                 :            :     {
     839                 :          0 :       QgsProperty p = var.value< QgsProperty >();
     840                 :          0 :       if ( p.propertyType() == QgsProperty::StaticProperty )
     841                 :            :       {
     842                 :          0 :         var = p.staticValue();
     843                 :          0 :       }
     844                 :          0 :     }
     845                 :          0 :     if ( !var.toString().isEmpty() )
     846                 :          0 :       return QObject::tr( "Could not load source layer for %1: %2 not found" ).arg( name, var.toString() );
     847                 :            :     else
     848                 :          0 :       return QObject::tr( "Could not load source layer for %1: invalid value" ).arg( name );
     849                 :          0 :   }
     850                 :          0 : }
     851                 :            : 
     852                 :          0 : QString QgsProcessingAlgorithm::invalidSinkError( const QVariantMap &parameters, const QString &name )
     853                 :            : {
     854                 :          0 :   if ( !parameters.contains( name ) )
     855                 :          0 :     return QObject::tr( "Could not create destination layer for %1: no value specified for parameter" ).arg( name );
     856                 :            :   else
     857                 :            :   {
     858                 :          0 :     QVariant var = parameters.value( name );
     859                 :          0 :     if ( var.canConvert<QgsProcessingOutputLayerDefinition>() )
     860                 :            :     {
     861                 :          0 :       QgsProcessingOutputLayerDefinition fromVar = qvariant_cast<QgsProcessingOutputLayerDefinition>( var );
     862                 :          0 :       var = fromVar.sink;
     863                 :          0 :     }
     864                 :          0 :     if ( var.canConvert<QgsProperty>() )
     865                 :            :     {
     866                 :          0 :       QgsProperty p = var.value< QgsProperty >();
     867                 :          0 :       if ( p.propertyType() == QgsProperty::StaticProperty )
     868                 :            :       {
     869                 :          0 :         var = p.staticValue();
     870                 :          0 :       }
     871                 :          0 :     }
     872                 :          0 :     if ( !var.toString().isEmpty() )
     873                 :          0 :       return QObject::tr( "Could not create destination layer for %1: %2" ).arg( name, var.toString() );
     874                 :            :     else
     875                 :          0 :       return QObject::tr( "Could not create destination layer for %1: invalid value" ).arg( name );
     876                 :          0 :   }
     877                 :          0 : }
     878                 :            : 
     879                 :          0 : bool QgsProcessingAlgorithm::supportInPlaceEdit( const QgsMapLayer *layer ) const
     880                 :            : {
     881                 :            :   Q_UNUSED( layer )
     882                 :          0 :   return false;
     883                 :            : }
     884                 :            : 
     885                 :            : 
     886                 :          0 : bool QgsProcessingAlgorithm::createAutoOutputForParameter( QgsProcessingParameterDefinition *parameter )
     887                 :            : {
     888                 :          0 :   if ( !parameter->isDestination() )
     889                 :          0 :     return true; // nothing created, but nothing went wrong - so return true
     890                 :            : 
     891                 :          0 :   QgsProcessingDestinationParameter *dest = static_cast< QgsProcessingDestinationParameter * >( parameter );
     892                 :          0 :   QgsProcessingOutputDefinition *output( dest->toOutputDefinition() );
     893                 :          0 :   if ( !output )
     894                 :          0 :     return true; // nothing created - but nothing went wrong - so return true
     895                 :          0 :   output->setAutoCreated( true );
     896                 :            : 
     897                 :          0 :   if ( !addOutput( output ) )
     898                 :            :   {
     899                 :            :     // couldn't add output - probably a duplicate name
     900                 :          0 :     return false;
     901                 :            :   }
     902                 :            :   else
     903                 :            :   {
     904                 :          0 :     return true;
     905                 :            :   }
     906                 :          0 : }
     907                 :            : 
     908                 :            : 
     909                 :            : //
     910                 :            : // QgsProcessingFeatureBasedAlgorithm
     911                 :            : //
     912                 :            : 
     913                 :          0 : QgsProcessingAlgorithm::Flags QgsProcessingFeatureBasedAlgorithm::flags() const
     914                 :            : {
     915                 :          0 :   Flags f = QgsProcessingAlgorithm::flags();
     916                 :          0 :   f |= QgsProcessingAlgorithm::FlagSupportsInPlaceEdits;
     917                 :          0 :   return f;
     918                 :            : }
     919                 :            : 
     920                 :          0 : void QgsProcessingFeatureBasedAlgorithm::initAlgorithm( const QVariantMap &config )
     921                 :            : {
     922                 :          0 :   addParameter( new QgsProcessingParameterFeatureSource( inputParameterName(), inputParameterDescription(), inputLayerTypes() ) );
     923                 :          0 :   initParameters( config );
     924                 :          0 :   addParameter( new QgsProcessingParameterFeatureSink( QStringLiteral( "OUTPUT" ), outputName(), outputLayerType(), QVariant(), false, true, true ) );
     925                 :          0 : }
     926                 :            : 
     927                 :          0 : QString QgsProcessingFeatureBasedAlgorithm::inputParameterName() const
     928                 :            : {
     929                 :          0 :   return QStringLiteral( "INPUT" );
     930                 :            : }
     931                 :            : 
     932                 :          0 : QString QgsProcessingFeatureBasedAlgorithm::inputParameterDescription() const
     933                 :            : {
     934                 :          0 :   return QObject::tr( "Input layer" );
     935                 :            : }
     936                 :            : 
     937                 :          0 : QList<int> QgsProcessingFeatureBasedAlgorithm::inputLayerTypes() const
     938                 :            : {
     939                 :          0 :   return QList<int>();
     940                 :            : }
     941                 :            : 
     942                 :          0 : QgsProcessing::SourceType QgsProcessingFeatureBasedAlgorithm::outputLayerType() const
     943                 :            : {
     944                 :          0 :   return QgsProcessing::TypeVectorAnyGeometry;
     945                 :            : }
     946                 :            : 
     947                 :          0 : QgsProcessingFeatureSource::Flag QgsProcessingFeatureBasedAlgorithm::sourceFlags() const
     948                 :            : {
     949                 :          0 :   return static_cast<QgsProcessingFeatureSource::Flag>( 0 );
     950                 :            : }
     951                 :            : 
     952                 :          0 : QgsFeatureSink::SinkFlags QgsProcessingFeatureBasedAlgorithm::sinkFlags() const
     953                 :            : {
     954                 :          0 :   return QgsFeatureSink::SinkFlags();
     955                 :            : }
     956                 :            : 
     957                 :          0 : QgsWkbTypes::Type QgsProcessingFeatureBasedAlgorithm::outputWkbType( QgsWkbTypes::Type inputWkbType ) const
     958                 :            : {
     959                 :          0 :   return inputWkbType;
     960                 :            : }
     961                 :            : 
     962                 :          0 : QgsFields QgsProcessingFeatureBasedAlgorithm::outputFields( const QgsFields &inputFields ) const
     963                 :            : {
     964                 :          0 :   return inputFields;
     965                 :            : }
     966                 :            : 
     967                 :          0 : QgsCoordinateReferenceSystem QgsProcessingFeatureBasedAlgorithm::outputCrs( const QgsCoordinateReferenceSystem &inputCrs ) const
     968                 :            : {
     969                 :          0 :   return inputCrs;
     970                 :            : }
     971                 :            : 
     972                 :          0 : void QgsProcessingFeatureBasedAlgorithm::initParameters( const QVariantMap & )
     973                 :            : {
     974                 :          0 : }
     975                 :            : 
     976                 :          0 : QgsCoordinateReferenceSystem QgsProcessingFeatureBasedAlgorithm::sourceCrs() const
     977                 :            : {
     978                 :          0 :   if ( mSource )
     979                 :          0 :     return mSource->sourceCrs();
     980                 :            :   else
     981                 :          0 :     return QgsCoordinateReferenceSystem();
     982                 :          0 : }
     983                 :            : 
     984                 :          0 : QVariantMap QgsProcessingFeatureBasedAlgorithm::processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback )
     985                 :            : {
     986                 :          0 :   prepareSource( parameters, context );
     987                 :          0 :   QString dest;
     988                 :          0 :   std::unique_ptr< QgsFeatureSink > sink( parameterAsSink( parameters, QStringLiteral( "OUTPUT" ), context, dest,
     989                 :          0 :                                           outputFields( mSource->fields() ),
     990                 :          0 :                                           outputWkbType( mSource->wkbType() ),
     991                 :          0 :                                           outputCrs( mSource->sourceCrs() ),
     992                 :          0 :                                           sinkFlags() ) );
     993                 :          0 :   if ( !sink )
     994                 :          0 :     throw QgsProcessingException( invalidSinkError( parameters, QStringLiteral( "OUTPUT" ) ) );
     995                 :            : 
     996                 :            :   // prepare expression context for feature iteration
     997                 :          0 :   QgsExpressionContext prevContext = context.expressionContext();
     998                 :          0 :   QgsExpressionContext algContext = prevContext;
     999                 :            : 
    1000                 :          0 :   algContext.appendScopes( createExpressionContext( parameters, context, mSource.get() ).takeScopes() );
    1001                 :          0 :   context.setExpressionContext( algContext );
    1002                 :            : 
    1003                 :          0 :   long count = mSource->featureCount();
    1004                 :            : 
    1005                 :          0 :   QgsFeature f;
    1006                 :          0 :   QgsFeatureIterator it = mSource->getFeatures( request(), sourceFlags() );
    1007                 :            : 
    1008                 :          0 :   double step = count > 0 ? 100.0 / count : 1;
    1009                 :          0 :   int current = 0;
    1010                 :          0 :   while ( it.nextFeature( f ) )
    1011                 :            :   {
    1012                 :          0 :     if ( feedback->isCanceled() )
    1013                 :            :     {
    1014                 :          0 :       break;
    1015                 :            :     }
    1016                 :            : 
    1017                 :          0 :     context.expressionContext().setFeature( f );
    1018                 :          0 :     const QgsFeatureList transformed = processFeature( f, context, feedback );
    1019                 :          0 :     for ( QgsFeature transformedFeature : transformed )
    1020                 :          0 :       sink->addFeature( transformedFeature, QgsFeatureSink::FastInsert );
    1021                 :            : 
    1022                 :          0 :     feedback->setProgress( current * step );
    1023                 :          0 :     current++;
    1024                 :          0 :   }
    1025                 :            : 
    1026                 :          0 :   mSource.reset();
    1027                 :            : 
    1028                 :            :   // probably not necessary - context's aren't usually recycled, but can't hurt
    1029                 :          0 :   context.setExpressionContext( prevContext );
    1030                 :            : 
    1031                 :          0 :   QVariantMap outputs;
    1032                 :          0 :   outputs.insert( QStringLiteral( "OUTPUT" ), dest );
    1033                 :          0 :   return outputs;
    1034                 :          0 : }
    1035                 :            : 
    1036                 :          0 : QgsFeatureRequest QgsProcessingFeatureBasedAlgorithm::request() const
    1037                 :            : {
    1038                 :          0 :   return QgsFeatureRequest();
    1039                 :            : }
    1040                 :            : 
    1041                 :          0 : bool QgsProcessingFeatureBasedAlgorithm::supportInPlaceEdit( const QgsMapLayer *l ) const
    1042                 :            : {
    1043                 :          0 :   const QgsVectorLayer *layer = qobject_cast< const QgsVectorLayer * >( l );
    1044                 :          0 :   if ( !layer )
    1045                 :          0 :     return false;
    1046                 :            : 
    1047                 :          0 :   QgsWkbTypes::GeometryType inPlaceGeometryType = layer->geometryType();
    1048                 :          0 :   if ( !inputLayerTypes().empty() &&
    1049                 :          0 :        !inputLayerTypes().contains( QgsProcessing::TypeVector ) &&
    1050                 :          0 :        !inputLayerTypes().contains( QgsProcessing::TypeVectorAnyGeometry ) &&
    1051                 :          0 :        ( ( inPlaceGeometryType == QgsWkbTypes::PolygonGeometry && !inputLayerTypes().contains( QgsProcessing::TypeVectorPolygon ) ) ||
    1052                 :          0 :          ( inPlaceGeometryType == QgsWkbTypes::LineGeometry && !inputLayerTypes().contains( QgsProcessing::TypeVectorLine ) ) ||
    1053                 :          0 :          ( inPlaceGeometryType == QgsWkbTypes::PointGeometry && !inputLayerTypes().contains( QgsProcessing::TypeVectorPoint ) ) ) )
    1054                 :          0 :     return false;
    1055                 :            : 
    1056                 :          0 :   QgsWkbTypes::Type type = QgsWkbTypes::Unknown;
    1057                 :          0 :   if ( inPlaceGeometryType == QgsWkbTypes::PointGeometry )
    1058                 :          0 :     type = QgsWkbTypes::Point;
    1059                 :          0 :   else if ( inPlaceGeometryType == QgsWkbTypes::LineGeometry )
    1060                 :          0 :     type = QgsWkbTypes::LineString;
    1061                 :          0 :   else if ( inPlaceGeometryType == QgsWkbTypes::PolygonGeometry )
    1062                 :          0 :     type = QgsWkbTypes::Polygon;
    1063                 :            : 
    1064                 :          0 :   if ( QgsWkbTypes::geometryType( outputWkbType( type ) ) != inPlaceGeometryType )
    1065                 :          0 :     return false;
    1066                 :            : 
    1067                 :          0 :   return true;
    1068                 :          0 : }
    1069                 :            : 
    1070                 :          0 : void QgsProcessingFeatureBasedAlgorithm::prepareSource( const QVariantMap &parameters, QgsProcessingContext &context )
    1071                 :            : {
    1072                 :          0 :   if ( ! mSource )
    1073                 :            :   {
    1074                 :          0 :     mSource.reset( parameterAsSource( parameters, inputParameterName(), context ) );
    1075                 :          0 :     if ( !mSource )
    1076                 :          0 :       throw QgsProcessingException( invalidSourceError( parameters, inputParameterName() ) );
    1077                 :          0 :   }
    1078                 :          0 : }
    1079                 :            : 
    1080                 :            : 
    1081                 :          0 : QgsProcessingAlgorithm::VectorProperties QgsProcessingFeatureBasedAlgorithm::sinkProperties( const QString &sink, const QVariantMap &parameters, QgsProcessingContext &context, const QMap<QString, QgsProcessingAlgorithm::VectorProperties> &sourceProperties ) const
    1082                 :            : {
    1083                 :          0 :   QgsProcessingAlgorithm::VectorProperties result;
    1084                 :          0 :   if ( sink == QLatin1String( "OUTPUT" ) )
    1085                 :            :   {
    1086                 :          0 :     if ( sourceProperties.value( QStringLiteral( "INPUT" ) ).availability == QgsProcessingAlgorithm::Available )
    1087                 :            :     {
    1088                 :          0 :       const VectorProperties inputProps = sourceProperties.value( QStringLiteral( "INPUT" ) );
    1089                 :          0 :       result.fields = outputFields( inputProps.fields );
    1090                 :          0 :       result.crs = outputCrs( inputProps.crs );
    1091                 :          0 :       result.wkbType = outputWkbType( inputProps.wkbType );
    1092                 :          0 :       result.availability = Available;
    1093                 :          0 :       return result;
    1094                 :          0 :     }
    1095                 :            :     else
    1096                 :            :     {
    1097                 :          0 :       std::unique_ptr< QgsProcessingFeatureSource > source( parameterAsSource( parameters, QStringLiteral( "INPUT" ), context ) );
    1098                 :          0 :       if ( source )
    1099                 :            :       {
    1100                 :          0 :         result.fields = outputFields( source->fields() );
    1101                 :          0 :         result.crs = outputCrs( source->sourceCrs() );
    1102                 :          0 :         result.wkbType = outputWkbType( source->wkbType() );
    1103                 :          0 :         result.availability = Available;
    1104                 :          0 :         return result;
    1105                 :            :       }
    1106                 :          0 :     }
    1107                 :          0 :   }
    1108                 :          0 :   return result;
    1109                 :          0 : }
    1110                 :            : 

Generated by: LCOV version 1.14