35#include <QRegularExpression> 
   38QgsProcessingModelAlgorithm::QgsProcessingModelAlgorithm( 
const QString &name, 
const QString &group, 
const QString &groupId )
 
   39  : mModelName( name.isEmpty() ? QObject::tr( 
"model" ) : name )
 
   40  , mModelGroup( group )
 
   41  , mModelGroupId( groupId )
 
   44void QgsProcessingModelAlgorithm::initAlgorithm( 
const QVariantMap & )
 
   48QString QgsProcessingModelAlgorithm::name()
 const 
   53QString QgsProcessingModelAlgorithm::displayName()
 const 
   58QString QgsProcessingModelAlgorithm::group()
 const 
   63QString QgsProcessingModelAlgorithm::groupId()
 const 
   68QIcon QgsProcessingModelAlgorithm::icon()
 const 
   73QString QgsProcessingModelAlgorithm::svgIconPath()
 const 
   78QString QgsProcessingModelAlgorithm::shortHelpString()
 const 
   80  if ( mHelpContent.empty() )
 
   86QString QgsProcessingModelAlgorithm::shortDescription()
 const 
   88  return mHelpContent.value( QStringLiteral( 
"SHORT_DESCRIPTION" ) ).toString();
 
   91QString QgsProcessingModelAlgorithm::helpUrl()
 const 
   93  return mHelpContent.value( QStringLiteral( 
"HELP_URL" ) ).toString();
 
   96QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( 
const QgsProcessingModelChildAlgorithm &child, 
const QVariantMap &modelParameters, 
const QVariantMap &results, 
const QgsExpressionContext &expressionContext, QString &error, 
const QgsProcessingContext *context )
 const 
  101    const QgsProcessingModelChildParameterSources paramSources = child.parameterSources().value( def->name() );
 
  103    QString expressionText;
 
  104    QVariantList paramParts;
 
  105    for ( 
const QgsProcessingModelChildParameterSource &source : paramSources )
 
  107      switch ( source.source() )
 
  110          paramParts << source.staticValue();
 
  114          paramParts << modelParameters.value( source.parameterName() );
 
  119          QVariantMap linkedChildResults = results.value( source.outputChildId() ).toMap();
 
  120          paramParts << linkedChildResults.value( source.outputName() );
 
  127          paramParts << exp.evaluate( &expressionContext );
 
  128          if ( exp.hasEvalError() )
 
  130            error = QObject::tr( 
"Could not evaluate expression for parameter %1 for %2: %3" ).arg( def->name(), child.description(), exp.evalErrorString() );
 
  145    if ( ! expressionText.isEmpty() )
 
  147      return expressionText;
 
  149    else if ( paramParts.count() == 1 )
 
  150      return paramParts.at( 0 );
 
  156  QVariantMap childParams;
 
  157  const QList< const QgsProcessingParameterDefinition * > childParameterDefinitions = child.algorithm()->parameterDefinitions();
 
  160    if ( !def->isDestination() )
 
  162      if ( !child.parameterSources().contains( def->name() ) )
 
  165      const QVariant value = evaluateSources( def );
 
  166      childParams.insert( def->name(), value );
 
  173      bool isFinalOutput = 
false;
 
  174      QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
 
  175      QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
 
  176      for ( ; outputIt != outputs.constEnd(); ++outputIt )
 
  178        if ( outputIt->childOutputName() == destParam->
name() )
 
  180          QString paramName = child.childId() + 
':' + outputIt.key();
 
  181          bool foundParam = 
false;
 
  185          if ( modelParameters.contains( paramName ) )
 
  187            value = modelParameters.value( paramName );
 
  196              if ( modelParameters.contains( modelParam->name() ) )
 
  198                value = modelParameters.value( modelParam->name() );
 
  206            if ( value.userType() == QMetaType::type( 
"QgsProcessingOutputLayerDefinition" ) )
 
  211              value = QVariant::fromValue( fromVar );
 
  214            childParams.insert( destParam->
name(), value );
 
  216          isFinalOutput = 
true;
 
  221      bool hasExplicitDefinition = 
false;
 
  222      if ( !isFinalOutput && child.parameterSources().contains( def->name() ) )
 
  225        const QVariant value = evaluateSources( def );
 
  226        if ( value.isValid() )
 
  228          childParams.insert( def->name(), value );
 
  229          hasExplicitDefinition = 
true;
 
  233      if ( !isFinalOutput && !hasExplicitDefinition )
 
  238        bool required = 
true;
 
  241          required = childOutputIsRequired( child.childId(), destParam->
name() );
 
  253const QgsProcessingParameterDefinition *QgsProcessingModelAlgorithm::modelParameterFromChildIdAndOutputName( 
const QString &childId, 
const QString &childOutputName )
 const 
  257    if ( !definition->isDestination() )
 
  260    const QString modelChildId = definition->
metadata().value( QStringLiteral( 
"_modelChildId" ) ).toString();
 
  261    const QString modelOutputName = definition->metadata().value( QStringLiteral( 
"_modelChildOutputName" ) ).toString();
 
  263    if ( modelChildId == childId && modelOutputName == childOutputName )
 
  269bool QgsProcessingModelAlgorithm::childOutputIsRequired( 
const QString &childId, 
const QString &outputName )
 const 
  272  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 
  273  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 
  275    if ( childIt->childId() == childId || !childIt->isActive() )
 
  279    QMap<QString, QgsProcessingModelChildParameterSources> candidateChildParams = childIt->parameterSources();
 
  280    QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator childParamIt = candidateChildParams.constBegin();
 
  281    for ( ; childParamIt != candidateChildParams.constEnd(); ++childParamIt )
 
  283      const auto constValue = childParamIt.value();
 
  284      for ( 
const QgsProcessingModelChildParameterSource &source : constValue )
 
  287             && source.outputChildId() == childId
 
  288             && source.outputName() == outputName )
 
  300  QSet< QString > toExecute;
 
  301  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 
  302  QSet< QString > broken;
 
  304  const bool useSubsetOfChildren = !childSubset.empty();
 
  305  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 
  307    if ( childIt->isActive() && ( !useSubsetOfChildren || childSubset.contains( childIt->childId() ) ) )
 
  309      if ( childIt->algorithm() )
 
  310        toExecute.insert( childIt->childId() );
 
  312        broken.insert( childIt->childId() );
 
  316  if ( !broken.empty() )
 
  317    throw QgsProcessingException( QCoreApplication::translate( 
"QgsProcessingModelAlgorithm", 
"Cannot run model, the following algorithms are not available on this system: %1" ).arg( 
qgsSetJoin( broken, QLatin1String( 
", " ) ) ) );
 
  319  QElapsedTimer totalTime;
 
  333    childInputs = config->initialChildInputs();
 
  334    childResults = config->initialChildOutputs();
 
  335    executed = config->previouslyExecutedChildAlgorithms();
 
  339  if ( useSubsetOfChildren )
 
  341    executed.subtract( childSubset );
 
  344  QVariantMap finalResults;
 
  346  bool executedAlg = 
true;
 
  347  int previousHtmlLogLength = feedback->
htmlLog().length();
 
  348  int countExecuted = 0;
 
  349  while ( executedAlg && countExecuted < toExecute.count() )
 
  352    for ( 
const QString &childId : std::as_const( toExecute ) )
 
  357      if ( executed.contains( childId ) )
 
  360      bool canExecute = 
true;
 
  361      const QSet< QString > dependencies = dependsOnChildAlgorithms( childId );
 
  362      for ( 
const QString &dependency : dependencies )
 
  364        if ( !executed.contains( dependency ) )
 
  376      const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
 
  377      std::unique_ptr< QgsProcessingAlgorithm > childAlg( child.algorithm()->create( child.configuration() ) );
 
  379      bool skipGenericLogging = 
true;
 
  384          skipGenericLogging = 
true;
 
  394          skipGenericLogging = 
false;
 
  398      if ( feedback && !skipGenericLogging )
 
  399        feedback->
pushDebugInfo( QObject::tr( 
"Prepare algorithm: %1" ).arg( childId ) );
 
  403                 << createExpressionContextScopeForChildAlgorithm( childId, context, parameters, childResults );
 
  407      QVariantMap childParams = parametersForChildAlgorithm( child, parameters, childResults, expContext, error, &context );
 
  408      if ( !error.isEmpty() )
 
  411      if ( feedback && !skipGenericLogging )
 
  412        feedback->
setProgressText( QObject::tr( 
"Running %1 [%2/%3]" ).arg( child.description() ).arg( executed.count() + 1 ).arg( toExecute.count() ) );
 
  417      childInputs.insert( childId, thisChildParams );
 
  418      childResult.
setInputs( thisChildParams );
 
  421      for ( 
auto childParamIt = childParams.constBegin(); childParamIt != childParams.constEnd(); ++childParamIt )
 
  423        params << QStringLiteral( 
"%1: %2" ).arg( childParamIt.key(),
 
  424               child.algorithm()->parameterDefinition( childParamIt.key() )->valueAsPythonString( childParamIt.value(), context ) );
 
  427      if ( feedback && !skipGenericLogging )
 
  429        feedback->
pushInfo( QObject::tr( 
"Input Parameters:" ) );
 
  430        feedback->
pushCommandInfo( QStringLiteral( 
"{ %1 }" ).arg( params.join( QLatin1String( 
", " ) ) ) );
 
  433      QElapsedTimer childTime;
 
  438      QThread *modelThread = QThread::currentThread();
 
  440      auto prepareOnMainThread = [modelThread, &ok, &childAlg, &childParams, &context, &modelFeedback]
 
  442        Q_ASSERT_X( QThread::currentThread() == qApp->thread(), 
"QgsProcessingModelAlgorithm::processAlgorithm", 
"childAlg->prepare() must be run on the main thread" );
 
  443        ok = childAlg->prepare( childParams, context, &modelFeedback );
 
  444        context.pushToThread( modelThread );
 
  448      if ( modelThread == qApp->thread() )
 
  449        ok = childAlg->prepare( childParams, context, &modelFeedback );
 
  452        context.pushToThread( qApp->thread() );
 
  454#ifndef __clang_analyzer__ 
  455        QMetaObject::invokeMethod( qApp, prepareOnMainThread, Qt::BlockingQueuedConnection );
 
  459      Q_ASSERT_X( QThread::currentThread() == context.thread(), 
"QgsProcessingModelAlgorithm::processAlgorithm", 
"context was not transferred back to model thread" );
 
  469      bool runResult = 
false;
 
  475          auto runOnMainThread = [modelThread, &context, &modelFeedback, &results, &childAlg, &childParams]
 
  477            Q_ASSERT_X( QThread::currentThread() == qApp->thread(), 
"QgsProcessingModelAlgorithm::processAlgorithm", 
"childAlg->runPrepared() must be run on the main thread" );
 
  478            results = childAlg->runPrepared( childParams, context, &modelFeedback );
 
  479            context.pushToThread( modelThread );
 
  482          if ( feedback && !skipGenericLogging && modelThread != qApp->thread() )
 
  483            feedback->
pushWarning( QObject::tr( 
"Algorithm “%1” cannot be run in a background thread, switching to main thread for this step" ).arg( childAlg->displayName() ) );
 
  485          context.pushToThread( qApp->thread() );
 
  487#ifndef __clang_analyzer__ 
  488          QMetaObject::invokeMethod( qApp, runOnMainThread, Qt::BlockingQueuedConnection );
 
  494          results = childAlg->runPrepared( childParams, context, &modelFeedback );
 
  505      Q_ASSERT_X( QThread::currentThread() == context.thread(), 
"QgsProcessingModelAlgorithm::processAlgorithm", 
"context was not transferred back to model thread" );
 
  508      auto postProcessOnMainThread = [modelThread, &ppRes, &childAlg, &context, &modelFeedback, runResult]
 
  510        Q_ASSERT_X( QThread::currentThread() == qApp->thread(), 
"QgsProcessingModelAlgorithm::processAlgorithm", 
"childAlg->postProcess() must be run on the main thread" );
 
  511        ppRes = childAlg->postProcess( context, &modelFeedback, runResult );
 
  512        context.pushToThread( modelThread );
 
  516      if ( modelThread == qApp->thread() )
 
  517        ppRes = childAlg->postProcess( context, &modelFeedback, runResult );
 
  520        context.pushToThread( qApp->thread() );
 
  522#ifndef __clang_analyzer__ 
  523        QMetaObject::invokeMethod( qApp, postProcessOnMainThread, Qt::BlockingQueuedConnection );
 
  527      Q_ASSERT_X( QThread::currentThread() == context.thread(), 
"QgsProcessingModelAlgorithm::processAlgorithm", 
"context was not transferred back to model thread" );
 
  529      if ( !ppRes.isEmpty() )
 
  532      childResults.insert( childId, results );
 
  537        if ( feedback && !skipGenericLogging )
 
  540          QStringList formattedOutputs;
 
  541          for ( 
auto displayOutputIt = displayOutputs.constBegin(); displayOutputIt != displayOutputs.constEnd(); ++displayOutputIt )
 
  543            formattedOutputs << QStringLiteral( 
"%1: %2" ).arg( displayOutputIt.key(),
 
  546          feedback->
pushInfo( QObject::tr( 
"Results:" ) );
 
  547          feedback->
pushCommandInfo( QStringLiteral( 
"{ %1 }" ).arg( formattedOutputs.join( QLatin1String( 
", " ) ) ) );
 
  552        const QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
 
  553        for ( 
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
 
  555          const int outputSortKey = mOutputOrder.indexOf( QStringLiteral( 
"%1:%2" ).arg( childId, outputIt->childOutputName() ) );
 
  556          switch ( mInternalVersion )
 
  558            case QgsProcessingModelAlgorithm::InternalVersion::Version1:
 
  559              finalResults.insert( childId + 
':' + outputIt->name(), results.value( outputIt->childOutputName() ) );
 
  561            case QgsProcessingModelAlgorithm::InternalVersion::Version2:
 
  564                finalResults.insert( modelParam->name(), results.value( outputIt->childOutputName() ) );
 
  569          const QString outputLayer = results.value( outputIt->childOutputName() ).toString();
 
  570          if ( !outputLayer.isEmpty() && context.willLoadLayerOnCompletion( outputLayer ) )
 
  574            if ( outputSortKey > 0 )
 
  579        executed.insert( childId );
 
  581        std::function< void( 
const QString &, 
const QString & )> pruneAlgorithmBranchRecursive;
 
  582        pruneAlgorithmBranchRecursive = [&]( 
const QString & id, 
const QString &branch = QString() )
 
  584          const QSet<QString> toPrune = dependentChildAlgorithms( 
id, branch );
 
  585          for ( 
const QString &targetId : toPrune )
 
  587            if ( executed.contains( targetId ) )
 
  590            executed.insert( targetId );
 
  591            pruneAlgorithmBranchRecursive( targetId, branch );
 
  601            pruneAlgorithmBranchRecursive( childId, outputDef->name() );
 
  609          for ( 
const QString &candidateId : std::as_const( toExecute ) )
 
  611            if ( executed.contains( candidateId ) )
 
  616            const QgsProcessingModelChildAlgorithm &candidate = mChildAlgorithms[ candidateId ];
 
  617            const QMap<QString, QgsProcessingModelChildParameterSources> candidateParams = candidate.parameterSources();
 
  618            QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = candidateParams.constBegin();
 
  620            for ( ; paramIt != candidateParams.constEnd(); ++paramIt )
 
  622              for ( 
const QgsProcessingModelChildParameterSource &source : paramIt.value() )
 
  627                  if ( !results.contains( source.outputName() ) )
 
  632                    executed.insert( candidateId );
 
  634                    pruneAlgorithmBranchRecursive( candidateId, QString() );
 
  645        childAlg.reset( 
nullptr );
 
  647        modelFeedback.setCurrentStep( countExecuted );
 
  648        if ( feedback && !skipGenericLogging )
 
  650          feedback->
pushInfo( QObject::tr( 
"OK. Execution took %1 s (%n output(s)).", 
nullptr, results.count() ).arg( childTime.elapsed() / 1000.0 ) );
 
  655      const QString thisAlgorithmHtmlLog = feedback->
htmlLog().mid( previousHtmlLogLength );
 
  656      previousHtmlLogLength = feedback->
htmlLog().length();
 
  660        const QString formattedException = QStringLiteral( 
"<span style=\"color:red\">%1</span><br/>" ).arg( error.toHtmlEscaped() ).replace( 
'\n', QLatin1String( 
"<br>" ) );
 
  661        const QString formattedRunTime = QStringLiteral( 
"<span style=\"color:red\">%1</span><br/>" ).arg( QObject::tr( 
"Failed after %1 s." ).arg( childTime.elapsed() / 1000.0 ).toHtmlEscaped() ).replace( 
'\n', QLatin1String( 
"<br>" ) );
 
  663        childResult.
setHtmlLog( thisAlgorithmHtmlLog + formattedException + formattedRunTime );
 
  664        context.modelResult().childResults().insert( childId, childResult );
 
  670        childResult.
setHtmlLog( thisAlgorithmHtmlLog );
 
  671        context.modelResult().childResults().insert( childId, childResult );
 
  679    feedback->
pushDebugInfo( QObject::tr( 
"Model processed OK. Executed %n algorithm(s) total in %1 s.", 
nullptr, countExecuted ).arg( 
static_cast< double >( totalTime.elapsed() ) / 1000.0 ) );
 
  681  mResults = finalResults;
 
  682  mResults.insert( QStringLiteral( 
"CHILD_RESULTS" ), childResults );
 
  683  mResults.insert( QStringLiteral( 
"CHILD_INPUTS" ), childInputs );
 
  687QString QgsProcessingModelAlgorithm::sourceFilePath()
 const 
  692void QgsProcessingModelAlgorithm::setSourceFilePath( 
const QString &sourceFile )
 
  694  mSourceFile = sourceFile;
 
  697bool QgsProcessingModelAlgorithm::modelNameMatchesFilePath()
 const 
  699  if ( mSourceFile.isEmpty() )
 
  702  const QFileInfo fi( mSourceFile );
 
  703  return fi.completeBaseName().compare( mModelName, Qt::CaseInsensitive ) == 0;
 
  708  QStringList fileDocString;
 
  709  fileDocString << QStringLiteral( 
"\"\"\"" );
 
  710  fileDocString << QStringLiteral( 
"Model exported as python." );
 
  711  fileDocString << QStringLiteral( 
"Name : %1" ).arg( displayName() );
 
  712  fileDocString << QStringLiteral( 
"Group : %1" ).arg( group() );
 
  713  fileDocString << QStringLiteral( 
"With QGIS : %1" ).arg( 
Qgis::versionInt() );
 
  714  fileDocString << QStringLiteral( 
"\"\"\"" );
 
  715  fileDocString << QString();
 
  718  QString indent = QString( 
' ' ).repeated( indentSize );
 
  719  QString currentIndent;
 
  721  QMap< QString, QString> friendlyChildNames;
 
  722  QMap< QString, QString> friendlyOutputNames;
 
  723  auto uniqueSafeName = []( 
const QString & name, 
bool capitalize, 
const QMap< QString, QString > &friendlyNames )->QString
 
  725    const QString base = safeName( name, capitalize );
 
  726    QString candidate = base;
 
  728    while ( friendlyNames.contains( candidate ) )
 
  731      candidate = QStringLiteral( 
"%1_%2" ).arg( base ).arg( i );
 
  736  const QString algorithmClassName = safeName( name(), 
true );
 
  738  QSet< QString > toExecute;
 
  739  for ( 
auto childIt = mChildAlgorithms.constBegin(); childIt != mChildAlgorithms.constEnd(); ++childIt )
 
  741    if ( childIt->isActive() && childIt->algorithm() )
 
  743      toExecute.insert( childIt->childId() );
 
  744      friendlyChildNames.insert( childIt->childId(), uniqueSafeName( childIt->description().isEmpty() ? childIt->childId() : childIt->description(), !childIt->description().isEmpty(), friendlyChildNames ) );
 
  747  const int totalSteps = toExecute.count();
 
  749  QStringList importLines; 
 
  750  switch ( outputType )
 
  755      const auto params = parameterDefinitions();
 
  756      importLines.reserve( params.count() + 3 );
 
  757      importLines << QStringLiteral( 
"from qgis.core import QgsProcessing" );
 
  758      importLines << QStringLiteral( 
"from qgis.core import QgsProcessingAlgorithm" );
 
  759      importLines << QStringLiteral( 
"from qgis.core import QgsProcessingMultiStepFeedback" );
 
  761      bool hasAdvancedParams = 
false;
 
  765          hasAdvancedParams = 
true;
 
  768        if ( !importString.isEmpty() && !importLines.contains( importString ) )
 
  769          importLines << importString;
 
  772      if ( hasAdvancedParams )
 
  773        importLines << QStringLiteral( 
"from qgis.core import QgsProcessingParameterDefinition" );
 
  775      lines << QStringLiteral( 
"import processing" );
 
  776      lines << QString() << QString();
 
  778      lines << QStringLiteral( 
"class %1(QgsProcessingAlgorithm):" ).arg( algorithmClassName );
 
  782      lines << indent + QStringLiteral( 
"def initAlgorithm(self, config=None):" );
 
  783      if ( params.empty() )
 
  785        lines << indent + indent + QStringLiteral( 
"pass" );
 
  789        lines.reserve( lines.size() + params.size() );
 
  792          std::unique_ptr< QgsProcessingParameterDefinition > defClone( def->clone() );
 
  794          if ( defClone->isDestination() )
 
  796            const QString uniqueChildName = defClone->metadata().value( QStringLiteral( 
"_modelChildId" ) ).toString() + 
':' + defClone->metadata().value( QStringLiteral( 
"_modelChildOutputName" ) ).toString();
 
  797            const QString friendlyName = !defClone->description().isEmpty() ? uniqueSafeName( defClone->description(), 
true, friendlyOutputNames ) : defClone->name();
 
  798            friendlyOutputNames.insert( uniqueChildName, friendlyName );
 
  799            defClone->setName( friendlyName );
 
  803            if ( !mParameterComponents.value( defClone->name() ).comment()->description().isEmpty() )
 
  805              const QStringList parts = mParameterComponents.value( defClone->name() ).comment()->description().split( QStringLiteral( 
"\n" ) );
 
  806              for ( 
const QString &part : parts )
 
  808                lines << indent + indent + QStringLiteral( 
"# %1" ).arg( part );
 
  815            lines << indent + indent + QStringLiteral( 
"param = %1" ).arg( defClone->asPythonString() );
 
  816            lines << indent + indent + QStringLiteral( 
"param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)" );
 
  817            lines << indent + indent + QStringLiteral( 
"self.addParameter(param)" );
 
  821            lines << indent + indent + QStringLiteral( 
"self.addParameter(%1)" ).arg( defClone->asPythonString() );
 
  827      lines << indent + QStringLiteral( 
"def processAlgorithm(self, parameters, context, model_feedback):" );
 
  828      currentIndent = indent + indent;
 
  830      lines << currentIndent + QStringLiteral( 
"# Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the" );
 
  831      lines << currentIndent + QStringLiteral( 
"# overall progress through the model" );
 
  832      lines << currentIndent + QStringLiteral( 
"feedback = QgsProcessingMultiStepFeedback(%1, model_feedback)" ).arg( totalSteps );
 
  840      QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
 
  841      for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
 
  843        QString name = paramIt.value().parameterName();
 
  844        if ( parameterDefinition( name ) )
 
  847          params.insert( name, parameterDefinition( name )->valueAsPythonString( parameterDefinition( name )->defaultValue(), context ) );
 
  851      if ( !params.isEmpty() )
 
  853        lines << QStringLiteral( 
"parameters = {" );
 
  854        for ( 
auto it = params.constBegin(); it != params.constEnd(); ++it )
 
  856          lines << QStringLiteral( 
"  '%1':%2," ).arg( it.key(), it.value() );
 
  858        lines << QStringLiteral( 
"}" )
 
  862      lines << QStringLiteral( 
"context = QgsProcessingContext()" )
 
  863            << QStringLiteral( 
"context.setProject(QgsProject.instance())" )
 
  864            << QStringLiteral( 
"feedback = QgsProcessingFeedback()" )
 
  873  lines << currentIndent + QStringLiteral( 
"results = {}" );
 
  874  lines << currentIndent + QStringLiteral( 
"outputs = {}" );
 
  877  QSet< QString > executed;
 
  878  bool executedAlg = 
true;
 
  880  while ( executedAlg && executed.count() < toExecute.count() )
 
  883    const auto constToExecute = toExecute;
 
  884    for ( 
const QString &childId : constToExecute )
 
  886      if ( executed.contains( childId ) )
 
  889      bool canExecute = 
true;
 
  890      const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms( childId );
 
  891      for ( 
const QString &dependency : constDependsOnChildAlgorithms )
 
  893        if ( !executed.contains( dependency ) )
 
  905      const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
 
  912        if ( def->isDestination() )
 
  917          bool isFinalOutput = 
false;
 
  918          QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
 
  919          QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
 
  920          for ( ; outputIt != outputs.constEnd(); ++outputIt )
 
  922            if ( outputIt->childOutputName() == destParam->
name() )
 
  924              QString paramName = child.childId() + 
':' + outputIt.key();
 
  925              paramName = friendlyOutputNames.value( paramName, paramName );
 
  926              childParams.insert( destParam->
name(), QStringLiteral( 
"parameters['%1']" ).arg( paramName ) );
 
  927              isFinalOutput = 
true;
 
  932          if ( !isFinalOutput )
 
  937            bool required = 
true;
 
  940              required = childOutputIsRequired( child.childId(), destParam->
name() );
 
  946              childParams.insert( destParam->
name(), QStringLiteral( 
"QgsProcessing.TEMPORARY_OUTPUT" ) );
 
  952      lines << child.asPythonCode( outputType, childParams, currentIndent.size(), indentSize, friendlyChildNames, friendlyOutputNames );
 
  954      if ( currentStep < totalSteps )
 
  957        lines << currentIndent + QStringLiteral( 
"feedback.setCurrentStep(%1)" ).arg( currentStep );
 
  958        lines << currentIndent + QStringLiteral( 
"if feedback.isCanceled():" );
 
  959        lines << currentIndent + indent + QStringLiteral( 
"return {}" );
 
  962      executed.insert( childId );
 
  966  switch ( outputType )
 
  969      lines << currentIndent + QStringLiteral( 
"return results" );
 
  973      lines << indent + QStringLiteral( 
"def name(self):" );
 
  974      lines << indent + indent + QStringLiteral( 
"return '%1'" ).arg( mModelName );
 
  976      lines << indent + QStringLiteral( 
"def displayName(self):" );
 
  977      lines << indent + indent + QStringLiteral( 
"return '%1'" ).arg( mModelName );
 
  981      lines << indent + QStringLiteral( 
"def group(self):" );
 
  982      lines << indent + indent + QStringLiteral( 
"return '%1'" ).arg( mModelGroup );
 
  984      lines << indent + QStringLiteral( 
"def groupId(self):" );
 
  985      lines << indent + indent + QStringLiteral( 
"return '%1'" ).arg( mModelGroupId );
 
  989      if ( !shortHelpString().isEmpty() )
 
  991        lines << indent + QStringLiteral( 
"def shortHelpString(self):" );
 
  992        lines << indent + indent + QStringLiteral( 
"return \"\"\"%1\"\"\"" ).arg( shortHelpString() );
 
  995      if ( !helpUrl().isEmpty() )
 
  997        lines << indent + QStringLiteral( 
"def helpUrl(self):" );
 
  998        lines << indent + indent + QStringLiteral( 
"return '%1'" ).arg( helpUrl() );
 
 1003      lines << indent + QStringLiteral( 
"def createInstance(self):" );
 
 1004      lines << indent + indent + QStringLiteral( 
"return %1()" ).arg( algorithmClassName );
 
 1007      static QMap< QString, QString > sAdditionalImports
 
 1009        { QStringLiteral( 
"QgsCoordinateReferenceSystem" ), QStringLiteral( 
"from qgis.core import QgsCoordinateReferenceSystem" ) },
 
 1010        { QStringLiteral( 
"QgsExpression" ), QStringLiteral( 
"from qgis.core import QgsExpression" ) },
 
 1011        { QStringLiteral( 
"QgsRectangle" ), QStringLiteral( 
"from qgis.core import QgsRectangle" ) },
 
 1012        { QStringLiteral( 
"QgsReferencedRectangle" ), QStringLiteral( 
"from qgis.core import QgsReferencedRectangle" ) },
 
 1013        { QStringLiteral( 
"QgsPoint" ), QStringLiteral( 
"from qgis.core import QgsPoint" ) },
 
 1014        { QStringLiteral( 
"QgsReferencedPoint" ), QStringLiteral( 
"from qgis.core import QgsReferencedPoint" ) },
 
 1015        { QStringLiteral( 
"QgsProperty" ), QStringLiteral( 
"from qgis.core import QgsProperty" ) },
 
 1016        { QStringLiteral( 
"QgsRasterLayer" ), QStringLiteral( 
"from qgis.core import QgsRasterLayer" ) },
 
 1017        { QStringLiteral( 
"QgsMeshLayer" ), QStringLiteral( 
"from qgis.core import QgsMeshLayer" ) },
 
 1018        { QStringLiteral( 
"QgsVectorLayer" ), QStringLiteral( 
"from qgis.core import QgsVectorLayer" ) },
 
 1019        { QStringLiteral( 
"QgsMapLayer" ), QStringLiteral( 
"from qgis.core import QgsMapLayer" ) },
 
 1020        { QStringLiteral( 
"QgsProcessingFeatureSourceDefinition" ), QStringLiteral( 
"from qgis.core import QgsProcessingFeatureSourceDefinition" ) },
 
 1021        { QStringLiteral( 
"QgsPointXY" ), QStringLiteral( 
"from qgis.core import QgsPointXY" ) },
 
 1022        { QStringLiteral( 
"QgsReferencedPointXY" ), QStringLiteral( 
"from qgis.core import QgsReferencedPointXY" ) },
 
 1023        { QStringLiteral( 
"QgsGeometry" ), QStringLiteral( 
"from qgis.core import QgsGeometry" ) },
 
 1024        { QStringLiteral( 
"QgsProcessingOutputLayerDefinition" ), QStringLiteral( 
"from qgis.core import QgsProcessingOutputLayerDefinition" ) },
 
 1025        { QStringLiteral( 
"QColor" ), QStringLiteral( 
"from qgis.PyQt.QtGui import QColor" ) },
 
 1026        { QStringLiteral( 
"QDateTime" ), QStringLiteral( 
"from qgis.PyQt.QtCore import QDateTime" ) },
 
 1027        { QStringLiteral( 
"QDate" ), QStringLiteral( 
"from qgis.PyQt.QtCore import QDate" ) },
 
 1028        { QStringLiteral( 
"QTime" ), QStringLiteral( 
"from qgis.PyQt.QtCore import QTime" ) },
 
 1031      for ( 
auto it = sAdditionalImports.constBegin(); it != sAdditionalImports.constEnd(); ++it )
 
 1033        if ( importLines.contains( it.value() ) )
 
 1040        for ( 
const QString &line : std::as_const( lines ) )
 
 1042          if ( line.contains( it.key() ) )
 
 1050          importLines << it.value();
 
 1054      lines = fileDocString + importLines + lines;
 
 1063QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> QgsProcessingModelAlgorithm::variablesForChildAlgorithm( 
const QString &childId, 
QgsProcessingContext *context, 
const QVariantMap &modelParameters, 
const QVariantMap &results )
 const 
 1065  QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables;
 
 1067  auto safeName = []( 
const QString & name )->QString
 
 1070    const thread_local QRegularExpression safeNameRe( QStringLiteral( 
"[\\s'\"\\(\\):\\.]" ) );
 
 1071    return s.replace( safeNameRe, QStringLiteral( 
"_" ) );
 
 1106  for ( 
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
 
 1110    QString description;
 
 1111    switch ( source.source() )
 
 1115        name = source.parameterName();
 
 1116        value = modelParameters.value( source.parameterName() );
 
 1117        description = parameterDefinition( source.parameterName() )->description();
 
 1122        const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
 
 1123        name = QStringLiteral( 
"%1_%2" ).arg( child.description().isEmpty() ?
 
 1124                                              source.outputChildId() : child.description(), source.outputName() );
 
 1127          description = QObject::tr( 
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
 
 1128                        child.description() );
 
 1130        value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
 
 1140    variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
 
 1144  sources = availableSourcesForChild( childId, QStringList()
 
 1151  for ( 
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
 
 1155    QString description;
 
 1157    switch ( source.source() )
 
 1161        name = source.parameterName();
 
 1162        value = modelParameters.value( source.parameterName() );
 
 1163        description = parameterDefinition( source.parameterName() )->description();
 
 1168        const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
 
 1169        name = QStringLiteral( 
"%1_%2" ).arg( child.description().isEmpty() ?
 
 1170                                              source.outputChildId() : child.description(), source.outputName() );
 
 1171        value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
 
 1174          description = QObject::tr( 
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
 
 1175                        child.description() );
 
 1188    if ( value.userType() == QMetaType::type( 
"QgsProcessingOutputLayerDefinition" ) )
 
 1191      value = fromVar.
sink;
 
 1192      if ( value.userType() == QMetaType::type( 
"QgsProperty" ) && context )
 
 1200      layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( value ) );
 
 1205    variables.insert( safeName( name ), VariableDefinition( layer ? QVariant::fromValue( 
QgsWeakMapLayerPointer( layer ) ) : QVariant(), source, description ) );
 
 1206    variables.insert( safeName( QStringLiteral( 
"%1_minx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMinimum() : QVariant(), source, QObject::tr( 
"Minimum X of %1" ).arg( description ) ) );
 
 1207    variables.insert( safeName( QStringLiteral( 
"%1_miny" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMinimum() : QVariant(), source, QObject::tr( 
"Minimum Y of %1" ).arg( description ) ) );
 
 1208    variables.insert( safeName( QStringLiteral( 
"%1_maxx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMaximum() : QVariant(), source, QObject::tr( 
"Maximum X of %1" ).arg( description ) ) );
 
 1209    variables.insert( safeName( QStringLiteral( 
"%1_maxy" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMaximum() : QVariant(), source, QObject::tr( 
"Maximum Y of %1" ).arg( description ) ) );
 
 1212  sources = availableSourcesForChild( childId, QStringList()
 
 1214  for ( 
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
 
 1218    QString description;
 
 1220    switch ( source.source() )
 
 1224        name = source.parameterName();
 
 1225        value = modelParameters.value( source.parameterName() );
 
 1226        description = parameterDefinition( source.parameterName() )->description();
 
 1231        const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
 
 1232        name = QStringLiteral( 
"%1_%2" ).arg( child.description().isEmpty() ?
 
 1233                                              source.outputChildId() : child.description(), source.outputName() );
 
 1234        value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
 
 1237          description = QObject::tr( 
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
 
 1238                        child.description() );
 
 1252    if ( value.userType() == QMetaType::type( 
"QgsProcessingFeatureSourceDefinition" ) )
 
 1257    else if ( value.userType() == QMetaType::type( 
"QgsProcessingOutputLayerDefinition" ) )
 
 1260      value = fromVar.
sink;
 
 1261      if ( context && value.userType() == QMetaType::type( 
"QgsProperty" ) )
 
 1266    if ( 
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( value ) ) )
 
 1268      featureSource = layer;
 
 1270    if ( context && !featureSource )
 
 1276    variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
 
 1277    variables.insert( safeName( QStringLiteral( 
"%1_minx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMinimum() : QVariant(), source, QObject::tr( 
"Minimum X of %1" ).arg( description ) ) );
 
 1278    variables.insert( safeName( QStringLiteral( 
"%1_miny" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMinimum() : QVariant(), source, QObject::tr( 
"Minimum Y of %1" ).arg( description ) ) );
 
 1279    variables.insert( safeName( QStringLiteral( 
"%1_maxx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMaximum() : QVariant(), source, QObject::tr( 
"Maximum X of %1" ).arg( description ) ) );
 
 1280    variables.insert( safeName( QStringLiteral( 
"%1_maxy" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMaximum() : QVariant(), source, QObject::tr( 
"Maximum Y of %1" ).arg( description ) ) );
 
 1286QgsExpressionContextScope *QgsProcessingModelAlgorithm::createExpressionContextScopeForChildAlgorithm( 
const QString &childId, 
QgsProcessingContext &context, 
const QVariantMap &modelParameters, 
const QVariantMap &results )
 const 
 1288  std::unique_ptr< QgsExpressionContextScope > scope( 
new QgsExpressionContextScope( QStringLiteral( 
"algorithm_inputs" ) ) );
 
 1289  QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = variablesForChildAlgorithm( childId, &context, modelParameters, results );
 
 1290  QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition>::const_iterator varIt = variables.constBegin();
 
 1291  for ( ; varIt != variables.constEnd(); ++varIt )
 
 1295  return scope.release();
 
 1298QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild( 
const QString &childId, 
const QStringList ¶meterTypes, 
const QStringList &outputTypes, 
const QList<int> &dataTypes )
 const 
 1300  QgsProcessingModelChildParameterSources sources;
 
 1303  QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
 
 1304  for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
 
 1310    if ( parameterTypes.contains( def->
type() ) )
 
 1312      if ( !dataTypes.isEmpty() )
 
 1328          bool ok = sourceDef->
dataTypes().isEmpty();
 
 1329          const auto constDataTypes = sourceDef->
dataTypes();
 
 1330          for ( 
int type : constDataTypes )
 
 1345      sources << QgsProcessingModelChildParameterSource::fromModelParameter( paramIt->parameterName() );
 
 1349  QSet< QString > dependents;
 
 1350  if ( !childId.isEmpty() )
 
 1352    dependents = dependentChildAlgorithms( childId );
 
 1353    dependents << childId;
 
 1356  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 
 1357  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 
 1359    if ( dependents.contains( childIt->childId() ) )
 
 1369      if ( outputTypes.contains( out->type() ) )
 
 1371        if ( !dataTypes.isEmpty() )
 
 1377            if ( !vectorOutputIsCompatibleType( dataTypes, vectorOut->
dataType() ) )
 
 1384        sources << QgsProcessingModelChildParameterSource::fromChildOutput( childIt->childId(), out->name() );
 
 1392QVariantMap QgsProcessingModelAlgorithm::helpContent()
 const 
 1394  return mHelpContent;
 
 1397void QgsProcessingModelAlgorithm::setHelpContent( 
const QVariantMap &helpContent )
 
 1399  mHelpContent = helpContent;
 
 1402void QgsProcessingModelAlgorithm::setName( 
const QString &name )
 
 1407void QgsProcessingModelAlgorithm::setGroup( 
const QString &group )
 
 1409  mModelGroup = group;
 
 1412bool QgsProcessingModelAlgorithm::validate( QStringList &issues )
 const 
 1417  if ( mChildAlgorithms.empty() )
 
 1420    issues << QObject::tr( 
"Model does not contain any algorithms" );
 
 1423  for ( 
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
 
 1425    QStringList childIssues;
 
 1426    res = validateChildAlgorithm( it->childId(), childIssues ) && res;
 
 1428    for ( 
const QString &issue : std::as_const( childIssues ) )
 
 1430      issues << QStringLiteral( 
"<b>%1</b>: %2" ).arg( it->description(), issue );
 
 1436QMap<QString, QgsProcessingModelChildAlgorithm> QgsProcessingModelAlgorithm::childAlgorithms()
 const 
 1438  return mChildAlgorithms;
 
 1441void QgsProcessingModelAlgorithm::setParameterComponents( 
const QMap<QString, QgsProcessingModelParameter> ¶meterComponents )
 
 1443  mParameterComponents = parameterComponents;
 
 1446void QgsProcessingModelAlgorithm::setParameterComponent( 
const QgsProcessingModelParameter &component )
 
 1448  mParameterComponents.insert( component.parameterName(), component );
 
 1451QgsProcessingModelParameter &QgsProcessingModelAlgorithm::parameterComponent( 
const QString &name )
 
 1453  if ( !mParameterComponents.contains( name ) )
 
 1455    QgsProcessingModelParameter &component = mParameterComponents[ name ];
 
 1456    component.setParameterName( name );
 
 1459  return mParameterComponents[ name ];
 
 1462QList< QgsProcessingModelParameter > QgsProcessingModelAlgorithm::orderedParameters()
 const 
 1464  QList< QgsProcessingModelParameter > res;
 
 1465  QSet< QString > found;
 
 1466  for ( 
const QString ¶meter : mParameterOrder )
 
 1468    if ( mParameterComponents.contains( parameter ) )
 
 1470      res << mParameterComponents.value( parameter );
 
 1476  for ( 
auto it = mParameterComponents.constBegin(); it != mParameterComponents.constEnd(); ++it )
 
 1478    if ( !found.contains( it.key() ) )
 
 1486void QgsProcessingModelAlgorithm::setParameterOrder( 
const QStringList &order )
 
 1488  mParameterOrder = order;
 
 1491QList<QgsProcessingModelOutput> QgsProcessingModelAlgorithm::orderedOutputs()
 const 
 1493  QList< QgsProcessingModelOutput > res;
 
 1494  QSet< QString > found;
 
 1496  for ( 
const QString &output : mOutputOrder )
 
 1498    bool foundOutput = 
false;
 
 1499    for ( 
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
 
 1501      const QMap<QString, QgsProcessingModelOutput> outputs = it.value().modelOutputs();
 
 1502      for ( 
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
 
 1504        if ( output == QStringLiteral( 
"%1:%2" ).arg( outputIt->childId(), outputIt->childOutputName() ) )
 
 1506          res << outputIt.value();
 
 1508          found.insert( QStringLiteral( 
"%1:%2" ).arg( outputIt->childId(), outputIt->childOutputName() ) );
 
 1517  for ( 
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
 
 1519    const QMap<QString, QgsProcessingModelOutput> outputs = it.value().modelOutputs();
 
 1520    for ( 
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
 
 1522      if ( !found.contains( QStringLiteral( 
"%1:%2" ).arg( outputIt->childId(), outputIt->childOutputName() ) ) )
 
 1524        res << outputIt.value();
 
 1532void QgsProcessingModelAlgorithm::setOutputOrder( 
const QStringList &order )
 
 1534  mOutputOrder = order;
 
 1537QString QgsProcessingModelAlgorithm::outputGroup()
 const 
 1539  return mOutputGroup;
 
 1542void QgsProcessingModelAlgorithm::setOutputGroup( 
const QString &group )
 
 1544  mOutputGroup = group;
 
 1547void QgsProcessingModelAlgorithm::updateDestinationParameters()
 
 1550  QMutableListIterator<const QgsProcessingParameterDefinition *> it( mParameters );
 
 1551  while ( it.hasNext() )
 
 1561  qDeleteAll( mOutputs );
 
 1565  QSet< QString > usedFriendlyNames;
 
 1566  auto uniqueSafeName = [&usedFriendlyNames ]( 
const QString & name )->QString
 
 1568    const QString base = safeName( name, 
false );
 
 1569    QString candidate = base;
 
 1571    while ( usedFriendlyNames.contains( candidate ) )
 
 1574      candidate = QStringLiteral( 
"%1_%2" ).arg( base ).arg( i );
 
 1576    usedFriendlyNames.insert( candidate );
 
 1580  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 
 1581  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 
 1583    QMap<QString, QgsProcessingModelOutput> outputs = childIt->modelOutputs();
 
 1584    QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
 
 1585    for ( ; outputIt != outputs.constEnd(); ++outputIt )
 
 1587      if ( !childIt->isActive() || !childIt->algorithm() )
 
 1595      std::unique_ptr< QgsProcessingParameterDefinition > param( source->
clone() );
 
 1599      if ( outputIt->isMandatory() )
 
 1601      if ( mInternalVersion != InternalVersion::Version1 && !outputIt->description().isEmpty() )
 
 1603        QString friendlyName = uniqueSafeName( outputIt->description() );
 
 1604        param->setName( friendlyName );
 
 1608        param->setName( outputIt->childId() + 
':' + outputIt->name() );
 
 1611      param->metadata().insert( QStringLiteral( 
"_modelChildId" ), outputIt->childId() );
 
 1612      param->metadata().insert( QStringLiteral( 
"_modelChildOutputName" ), outputIt->name() );
 
 1613      param->metadata().insert( QStringLiteral( 
"_modelChildProvider" ), childIt->algorithm()->provider() ? childIt->algorithm()->provider()->id() : QString() );
 
 1615      param->setDescription( outputIt->description() );
 
 1616      param->setDefaultValue( outputIt->defaultValue() );
 
 1619      if ( addParameter( param.release() ) && newDestParam )
 
 1626          newDestParam->mOriginalProvider = provider;
 
 1633void QgsProcessingModelAlgorithm::addGroupBox( 
const QgsProcessingModelGroupBox &groupBox )
 
 1635  mGroupBoxes.insert( groupBox.uuid(), groupBox );
 
 1638QList<QgsProcessingModelGroupBox> QgsProcessingModelAlgorithm::groupBoxes()
 const 
 1640  return mGroupBoxes.values();
 
 1643void QgsProcessingModelAlgorithm::removeGroupBox( 
const QString &uuid )
 
 1645  mGroupBoxes.remove( uuid );
 
 1648QVariant QgsProcessingModelAlgorithm::toVariant()
 const 
 1651  map.insert( QStringLiteral( 
"model_name" ), mModelName );
 
 1652  map.insert( QStringLiteral( 
"model_group" ), mModelGroup );
 
 1653  map.insert( QStringLiteral( 
"help" ), mHelpContent );
 
 1654  map.insert( QStringLiteral( 
"internal_version" ), 
qgsEnumValueToKey( mInternalVersion ) );
 
 1656  QVariantMap childMap;
 
 1657  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 
 1658  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 
 1660    childMap.insert( childIt.key(), childIt.value().toVariant() );
 
 1662  map.insert( QStringLiteral( 
"children" ), childMap );
 
 1664  QVariantMap paramMap;
 
 1665  QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
 
 1666  for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
 
 1668    paramMap.insert( paramIt.key(), paramIt.value().toVariant() );
 
 1670  map.insert( QStringLiteral( 
"parameters" ), paramMap );
 
 1672  QVariantMap paramDefMap;
 
 1677  map.insert( QStringLiteral( 
"parameterDefinitions" ), paramDefMap );
 
 1679  QVariantList groupBoxDefs;
 
 1680  for ( 
auto it = mGroupBoxes.constBegin(); it != mGroupBoxes.constEnd(); ++it )
 
 1682    groupBoxDefs.append( it.value().toVariant() );
 
 1684  map.insert( QStringLiteral( 
"groupBoxes" ), groupBoxDefs );
 
 1686  map.insert( QStringLiteral( 
"modelVariables" ), mVariables );
 
 1688  map.insert( QStringLiteral( 
"designerParameterValues" ), mDesignerParameterValues );
 
 1690  map.insert( QStringLiteral( 
"parameterOrder" ), mParameterOrder );
 
 1691  map.insert( QStringLiteral( 
"outputOrder" ), mOutputOrder );
 
 1692  map.insert( QStringLiteral( 
"outputGroup" ), mOutputGroup );
 
 1697bool QgsProcessingModelAlgorithm::loadVariant( 
const QVariant &model )
 
 1699  QVariantMap map = model.toMap();
 
 1701  mModelName = map.value( QStringLiteral( 
"model_name" ) ).toString();
 
 1702  mModelGroup = map.value( QStringLiteral( 
"model_group" ) ).toString();
 
 1703  mModelGroupId = map.value( QStringLiteral( 
"model_group" ) ).toString();
 
 1704  mHelpContent = map.value( QStringLiteral( 
"help" ) ).toMap();
 
 1706  mInternalVersion = 
qgsEnumKeyToValue( map.value( QStringLiteral( 
"internal_version" ) ).toString(), InternalVersion::Version1 );
 
 1708  mVariables = map.value( QStringLiteral( 
"modelVariables" ) ).toMap();
 
 1709  mDesignerParameterValues = map.value( QStringLiteral( 
"designerParameterValues" ) ).toMap();
 
 1711  mParameterOrder = map.value( QStringLiteral( 
"parameterOrder" ) ).toStringList();
 
 1712  mOutputOrder = map.value( QStringLiteral( 
"outputOrder" ) ).toStringList();
 
 1713  mOutputGroup = map.value( QStringLiteral( 
"outputGroup" ) ).toString();
 
 1715  mChildAlgorithms.clear();
 
 1716  QVariantMap childMap = map.value( QStringLiteral( 
"children" ) ).toMap();
 
 1717  QVariantMap::const_iterator childIt = childMap.constBegin();
 
 1718  for ( ; childIt != childMap.constEnd(); ++childIt )
 
 1720    QgsProcessingModelChildAlgorithm child;
 
 1724    if ( !child.loadVariant( childIt.value() ) )
 
 1727    mChildAlgorithms.insert( child.childId(), child );
 
 1730  mParameterComponents.clear();
 
 1731  QVariantMap paramMap = map.value( QStringLiteral( 
"parameters" ) ).toMap();
 
 1732  QVariantMap::const_iterator paramIt = paramMap.constBegin();
 
 1733  for ( ; paramIt != paramMap.constEnd(); ++paramIt )
 
 1735    QgsProcessingModelParameter param;
 
 1736    if ( !param.loadVariant( paramIt.value().toMap() ) )
 
 1739    mParameterComponents.insert( param.parameterName(), param );
 
 1742  qDeleteAll( mParameters );
 
 1743  mParameters.clear();
 
 1744  QVariantMap paramDefMap = map.value( QStringLiteral( 
"parameterDefinitions" ) ).toMap();
 
 1746  auto addParam = [
this]( 
const QVariant & value )
 
 1754      if ( param->name() == QLatin1String( 
"VERBOSE_LOG" ) )
 
 1758      param->setHelp( mHelpContent.value( param->name() ).toString() );
 
 1761      addParameter( param.release() );
 
 1765      QVariantMap map = value.toMap();
 
 1766      QString type = map.value( QStringLiteral( 
"parameter_type" ) ).toString();
 
 1767      QString name = map.value( QStringLiteral( 
"name" ) ).toString();
 
 1769      QgsMessageLog::logMessage( QCoreApplication::translate( 
"Processing", 
"Could not load parameter %1 of type %2." ).arg( name, type ), QCoreApplication::translate( 
"Processing", 
"Processing" ) );
 
 1773  QSet< QString > loadedParams;
 
 1775  for ( 
const QString &name : std::as_const( mParameterOrder ) )
 
 1777    if ( paramDefMap.contains( name ) )
 
 1779      addParam( paramDefMap.value( name ) );
 
 1780      loadedParams << name;
 
 1784  QVariantMap::const_iterator paramDefIt = paramDefMap.constBegin();
 
 1785  for ( ; paramDefIt != paramDefMap.constEnd(); ++paramDefIt )
 
 1787    if ( !loadedParams.contains( paramDefIt.key() ) )
 
 1788      addParam( paramDefIt.value() );
 
 1791  mGroupBoxes.clear();
 
 1792  const QVariantList groupBoxList = map.value( QStringLiteral( 
"groupBoxes" ) ).toList();
 
 1793  for ( 
const QVariant &groupBoxDef : groupBoxList )
 
 1795    QgsProcessingModelGroupBox groupBox;
 
 1796    groupBox.loadVariant( groupBoxDef.toMap() );
 
 1797    mGroupBoxes.insert( groupBox.uuid(), groupBox );
 
 1800  updateDestinationParameters();
 
 1805bool QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType( 
const QList<int> &acceptableDataTypes, 
Qgis::ProcessingSourceType outputType )
 
 1810  return ( acceptableDataTypes.empty()
 
 1811           || acceptableDataTypes.contains( 
static_cast< int >( outputType ) )
 
 1822void QgsProcessingModelAlgorithm::reattachAlgorithms()
 const 
 1824  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 
 1825  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 
 1827    if ( !childIt->algorithm() )
 
 1828      childIt->reattach();
 
 1832bool QgsProcessingModelAlgorithm::toFile( 
const QString &path )
 const 
 1834  QDomDocument doc = QDomDocument( QStringLiteral( 
"model" ) );
 
 1836  doc.appendChild( elem );
 
 1839  if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
 
 1841    QTextStream stream( &file );
 
 1842    doc.save( stream, 2 );
 
 1849bool QgsProcessingModelAlgorithm::fromFile( 
const QString &path )
 
 1854  if ( file.open( QFile::ReadOnly ) )
 
 1856    if ( !doc.setContent( &file ) )
 
 1867  return loadVariant( props );
 
 1870void QgsProcessingModelAlgorithm::setChildAlgorithms( 
const QMap<QString, QgsProcessingModelChildAlgorithm> &childAlgorithms )
 
 1872  mChildAlgorithms = childAlgorithms;
 
 1873  updateDestinationParameters();
 
 1876void QgsProcessingModelAlgorithm::setChildAlgorithm( 
const QgsProcessingModelChildAlgorithm &
algorithm )
 
 1879  updateDestinationParameters();
 
 1882QString QgsProcessingModelAlgorithm::addChildAlgorithm( QgsProcessingModelChildAlgorithm &
algorithm )
 
 1884  if ( 
algorithm.childId().isEmpty() || mChildAlgorithms.contains( 
algorithm.childId() ) )
 
 1888  updateDestinationParameters();
 
 1892QgsProcessingModelChildAlgorithm &QgsProcessingModelAlgorithm::childAlgorithm( 
const QString &childId )
 
 1894  return mChildAlgorithms[ childId ];
 
 1897bool QgsProcessingModelAlgorithm::removeChildAlgorithm( 
const QString &
id )
 
 1899  if ( !dependentChildAlgorithms( 
id ).isEmpty() )
 
 1902  mChildAlgorithms.remove( 
id );
 
 1903  updateDestinationParameters();
 
 1907void QgsProcessingModelAlgorithm::deactivateChildAlgorithm( 
const QString &
id )
 
 1909  const auto constDependentChildAlgorithms = dependentChildAlgorithms( 
id );
 
 1910  for ( 
const QString &child : constDependentChildAlgorithms )
 
 1912    childAlgorithm( child ).setActive( 
false );
 
 1914  childAlgorithm( 
id ).setActive( 
false );
 
 1915  updateDestinationParameters();
 
 1918bool QgsProcessingModelAlgorithm::activateChildAlgorithm( 
const QString &
id )
 
 1920  const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms( 
id );
 
 1921  for ( 
const QString &child : constDependsOnChildAlgorithms )
 
 1923    if ( !childAlgorithm( child ).isActive() )
 
 1926  childAlgorithm( 
id ).setActive( 
true );
 
 1927  updateDestinationParameters();
 
 1933  if ( addParameter( definition ) )
 
 1934    mParameterComponents.insert( definition->
name(), component );
 
 1939  removeParameter( definition->
name() );
 
 1940  addParameter( definition );
 
 1943void QgsProcessingModelAlgorithm::removeModelParameter( 
const QString &name )
 
 1945  removeParameter( name );
 
 1946  mParameterComponents.remove( name );
 
 1949void QgsProcessingModelAlgorithm::changeParameterName( 
const QString &oldName, 
const QString &newName )
 
 1954  auto replaceExpressionVariable = [oldName, newName, &expressionContext]( 
const QString & expressionString ) -> std::tuple< bool, QString >
 
 1957    expression.prepare( &expressionContext );
 
 1958    QSet<QString> variables = expression.referencedVariables();
 
 1959    if ( variables.contains( oldName ) )
 
 1961      QString newExpression = expressionString;
 
 1962      newExpression.replace( QStringLiteral( 
"@%1" ).arg( oldName ), QStringLiteral( 
"@%2" ).arg( newName ) );
 
 1963      return { 
true, newExpression };
 
 1965    return { 
false, QString() };
 
 1968  QMap< QString, QgsProcessingModelChildAlgorithm >::iterator childIt = mChildAlgorithms.begin();
 
 1969  for ( ; childIt != mChildAlgorithms.end(); ++childIt )
 
 1971    bool changed = 
false;
 
 1972    QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
 
 1973    QMap<QString, QgsProcessingModelChildParameterSources>::iterator paramIt = childParams.begin();
 
 1974    for ( ; paramIt != childParams.end(); ++paramIt )
 
 1976      QList< QgsProcessingModelChildParameterSource > &value = paramIt.value();
 
 1977      for ( 
auto valueIt = value.begin(); valueIt != value.end(); ++valueIt )
 
 1979        switch ( valueIt->source() )
 
 1983            if ( valueIt->parameterName() == oldName )
 
 1985              valueIt->setParameterName( newName );
 
 1993            bool updatedExpression = 
false;
 
 1994            QString newExpression;
 
 1995            std::tie( updatedExpression, newExpression ) = replaceExpressionVariable( valueIt->expression() );
 
 1996            if ( updatedExpression )
 
 1998              valueIt->setExpression( newExpression );
 
 2006            if ( valueIt->staticValue().userType() == QMetaType::type( 
"QgsProperty" ) )
 
 2011                bool updatedExpression = 
false;
 
 2012                QString newExpression;
 
 2013                std::tie( updatedExpression, newExpression ) = replaceExpressionVariable( property.expressionString() );
 
 2014                if ( updatedExpression )
 
 2016                  property.setExpressionString( newExpression );
 
 2017                  valueIt->setStaticValue( property );
 
 2033      childIt->setParameterSources( childParams );
 
 2037bool QgsProcessingModelAlgorithm::childAlgorithmsDependOnParameter( 
const QString &name )
 const 
 2039  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 
 2040  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 
 2043    QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
 
 2044    QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
 
 2045    for ( ; paramIt != childParams.constEnd(); ++paramIt )
 
 2047      const auto constValue = paramIt.value();
 
 2048      for ( 
const QgsProcessingModelChildParameterSource &source : constValue )
 
 2051             && source.parameterName() == name )
 
 2061bool QgsProcessingModelAlgorithm::otherParametersDependOnParameter( 
const QString &name )
 const 
 2063  const auto constMParameters = mParameters;
 
 2066    if ( def->
name() == name )
 
 2075QMap<QString, QgsProcessingModelParameter> QgsProcessingModelAlgorithm::parameterComponents()
 const 
 2077  return mParameterComponents;
 
 2080void QgsProcessingModelAlgorithm::dependentChildAlgorithmsRecursive( 
const QString &childId, QSet<QString> &depends, 
const QString &branch )
 const 
 2082  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 
 2083  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 
 2085    if ( depends.contains( childIt->childId() ) )
 
 2089    const QList< QgsProcessingModelChildDependency > constDependencies = childIt->dependencies();
 
 2090    bool hasDependency = 
false;
 
 2091    for ( 
const QgsProcessingModelChildDependency &dep : constDependencies )
 
 2093      if ( dep.childId == childId && ( branch.isEmpty() || dep.conditionalBranch == branch ) )
 
 2095        hasDependency = 
true;
 
 2100    if ( hasDependency )
 
 2102      depends.insert( childIt->childId() );
 
 2103      dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
 
 2108    QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
 
 2109    QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
 
 2110    for ( ; paramIt != childParams.constEnd(); ++paramIt )
 
 2112      const auto constValue = paramIt.value();
 
 2113      for ( 
const QgsProcessingModelChildParameterSource &source : constValue )
 
 2116             && source.outputChildId() == childId )
 
 2118          depends.insert( childIt->childId() );
 
 2119          dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
 
 2127QSet<QString> QgsProcessingModelAlgorithm::dependentChildAlgorithms( 
const QString &childId, 
const QString &conditionalBranch )
 const 
 2129  QSet< QString > algs;
 
 2133  algs.insert( childId );
 
 2135  dependentChildAlgorithmsRecursive( childId, algs, conditionalBranch );
 
 2138  algs.remove( childId );
 
 2144void QgsProcessingModelAlgorithm::dependsOnChildAlgorithmsRecursive( 
const QString &childId, QSet< QString > &depends )
 const 
 2146  const QgsProcessingModelChildAlgorithm &alg = mChildAlgorithms.value( childId );
 
 2149  const QList< QgsProcessingModelChildDependency > constDependencies = alg.dependencies();
 
 2150  for ( 
const QgsProcessingModelChildDependency &val : constDependencies )
 
 2152    if ( !depends.contains( val.childId ) )
 
 2154      depends.insert( val.childId );
 
 2155      dependsOnChildAlgorithmsRecursive( val.childId, depends );
 
 2160  QMap<QString, QgsProcessingModelChildParameterSources> childParams = alg.parameterSources();
 
 2161  QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
 
 2162  for ( ; paramIt != childParams.constEnd(); ++paramIt )
 
 2164    const auto constValue = paramIt.value();
 
 2165    for ( 
const QgsProcessingModelChildParameterSource &source : constValue )
 
 2167      switch ( source.source() )
 
 2170          if ( !depends.contains( source.outputChildId() ) )
 
 2172            depends.insert( source.outputChildId() );
 
 2173            dependsOnChildAlgorithmsRecursive( source.outputChildId(), depends );
 
 2180          const QSet<QString> vars = exp.referencedVariables();
 
 2185          const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> availableVariables = variablesForChildAlgorithm( childId );
 
 2186          for ( 
auto childVarIt = availableVariables.constBegin(); childVarIt != availableVariables.constEnd(); ++childVarIt )
 
 2192            if ( !vars.contains( childVarIt.key() ) || depends.contains( childVarIt->source.outputChildId() ) )
 
 2196            depends.insert( childVarIt->source.outputChildId() );
 
 2197            dependsOnChildAlgorithmsRecursive( childVarIt->source.outputChildId(), depends );
 
 2212QSet< QString > QgsProcessingModelAlgorithm::dependsOnChildAlgorithms( 
const QString &childId )
 const 
 2214  QSet< QString > algs;
 
 2218  algs.insert( childId );
 
 2220  dependsOnChildAlgorithmsRecursive( childId, algs );
 
 2223  algs.remove( childId );
 
 2228QList<QgsProcessingModelChildDependency> QgsProcessingModelAlgorithm::availableDependenciesForChildAlgorithm( 
const QString &childId )
 const 
 2230  QSet< QString > dependent;
 
 2231  if ( !childId.isEmpty() )
 
 2233    dependent.unite( dependentChildAlgorithms( childId ) );
 
 2234    dependent.insert( childId );
 
 2237  QList<QgsProcessingModelChildDependency> res;
 
 2238  for ( 
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
 
 2240    if ( !dependent.contains( it->childId() ) )
 
 2243      bool hasBranches = 
false;
 
 2244      if ( it->algorithm() )
 
 2252            QgsProcessingModelChildDependency alg;
 
 2253            alg.childId = it->childId();
 
 2254            alg.conditionalBranch = def->
name();
 
 2262        QgsProcessingModelChildDependency alg;
 
 2263        alg.childId = it->childId();
 
 2271bool QgsProcessingModelAlgorithm::validateChildAlgorithm( 
const QString &childId, QStringList &issues )
 const 
 2274  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constFind( childId );
 
 2275  if ( childIt != mChildAlgorithms.constEnd() )
 
 2277    if ( !childIt->algorithm() )
 
 2279      issues << QObject::tr( 
"Algorithm is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
 
 2288      if ( childIt->parameterSources().contains( def->
name() ) )
 
 2291        const QList< QgsProcessingModelChildParameterSource > sources = childIt->parameterSources().value( def->
name() );
 
 2292        for ( 
const QgsProcessingModelChildParameterSource &source : sources )
 
 2294          switch ( source.source() )
 
 2300                issues <<  QObject::tr( 
"Value for <i>%1</i> is not acceptable for this parameter" ).arg( def->
name() );
 
 2305              if ( !parameterComponents().contains( source.parameterName() ) )
 
 2308                issues <<  QObject::tr( 
"Model input <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.parameterName(), def->
name() );
 
 2313              if ( !childAlgorithms().contains( source.outputChildId() ) )
 
 2316                issues <<  QObject::tr( 
"Child algorithm <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.outputChildId(), def->
name() );
 
 2338          issues <<  QObject::tr( 
"Parameter <i>%1</i> is mandatory" ).arg( def->
name() );
 
 2347    issues << QObject::tr( 
"Invalid child ID: <i>%1</i>" ).arg( childId );
 
 2352bool QgsProcessingModelAlgorithm::canExecute( QString *errorMessage )
 const 
 2354  reattachAlgorithms();
 
 2355  QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
 
 2356  for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
 
 2358    if ( !childIt->algorithm() )
 
 2362        *errorMessage = QObject::tr( 
"The model you are trying to run contains an algorithm that is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
 
 2370QString QgsProcessingModelAlgorithm::asPythonCommand( 
const QVariantMap ¶meters, 
QgsProcessingContext &context )
 const 
 2372  if ( mSourceFile.isEmpty() )
 
 2387  QgsProcessingModelAlgorithm *alg = 
new QgsProcessingModelAlgorithm();
 
 2388  alg->loadVariant( toVariant() );
 
 2389  alg->setProvider( provider() );
 
 2390  alg->setSourceFilePath( sourceFilePath() );
 
 2394QString QgsProcessingModelAlgorithm::safeName( 
const QString &name, 
bool capitalize )
 
 2396  QString n = name.toLower().trimmed();
 
 2397  const thread_local QRegularExpression rx( QStringLiteral( 
"[^\\sa-z_A-Z0-9]" ) );
 
 2398  n.replace( rx, QString() );
 
 2399  const thread_local QRegularExpression rx2( QStringLiteral( 
"^\\d*" ) ); 
 
 2400  n.replace( rx2, QString() );
 
 2402    n = n.replace( 
' ', 
'_' );
 
 2406QVariantMap QgsProcessingModelAlgorithm::variables()
 const 
 2411void QgsProcessingModelAlgorithm::setVariables( 
const QVariantMap &variables )
 
 2413  mVariables = variables;
 
 2416QVariantMap QgsProcessingModelAlgorithm::designerParameterValues()
 const 
 2418  return mDesignerParameterValues;
 
ProcessingSourceType
Processing data source types.
 
@ Vector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
 
@ MapLayer
Any map layer type (raster, vector, mesh, point cloud, annotation or plugin layer)
 
@ VectorAnyGeometry
Any vector layer with geometry.
 
@ VectorPoint
Vector point layers.
 
@ VectorPolygon
Vector polygon layers.
 
@ VectorLine
Vector line layers.
 
@ Success
Child was successfully executed.
 
@ Failed
Child encountered an error while executing.
 
@ Expression
Expression based property.
 
@ UpperCamelCase
Convert the string to upper camel case. Note that this method does not unaccent characters.
 
static int versionInt()
Version number used for comparing versions using the "Check QGIS Version" function.
 
@ ExpressionText
Parameter value is taken from a text with expressions, evaluated just before the algorithm runs.
 
@ ModelOutput
Parameter value is linked to an output parameter for the model.
 
@ ChildOutput
Parameter value is taken from an output generated by a child algorithm.
 
@ ModelParameter
Parameter value is taken from a parent model parameter.
 
@ StaticValue
Parameter value is a static value.
 
@ Expression
Parameter value is taken from an expression, evaluated just before the algorithm runs.
 
@ SkipGenericModelLogging
When running as part of a model, the generic algorithm setup and results logging should be skipped.
 
@ CustomException
Algorithm raises custom exception notices, don't use the standard ones.
 
@ NoThreading
Algorithm is not thread safe and cannot be run in a background thread, e.g. for algorithms which mani...
 
@ PruneModelBranchesBasedOnAlgorithmResults
Algorithm results will cause remaining model branches to be pruned based on the results of running th...
 
@ Hidden
Parameter is hidden and should not be shown to users.
 
@ Advanced
Parameter is an advanced parameter which should be hidden from users by default.
 
@ Optional
Parameter is optional.
 
@ DefaultLevel
Default logging level.
 
@ Verbose
Verbose logging.
 
@ ModelDebug
Model debug level logging. Includes verbose logging and other outputs useful for debugging models (si...
 
static QgsProcessingRegistry * processingRegistry()
Returns the application's processing registry, used for managing processing providers,...
 
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
 
static QString iconPath(const QString &iconFile)
Returns path to the desired icon file.
 
Single scope for storing variables and functions for use within a QgsExpressionContext.
 
static QgsExpressionContextScope * processingModelAlgorithmScope(const QgsProcessingModelAlgorithm *model, const QVariantMap ¶meters, QgsProcessingContext &context)
Creates a new scope which contains variables and functions relating to a processing model algorithm,...
 
static QgsExpressionContextScope * processingAlgorithmScope(const QgsProcessingAlgorithm *algorithm, const QVariantMap ¶meters, QgsProcessingContext &context)
Creates a new scope which contains variables and functions relating to a processing algorithm,...
 
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
 
Class for parsing and evaluation of expressions (formerly called "search strings").
 
static QString replaceExpressionText(const QString &action, const QgsExpressionContext *context, const QgsDistanceArea *distanceArea=nullptr)
This function replaces each expression between [% and %] in the string with the result of its evaluat...
 
An interface for objects which provide features via a getFeatures method.
 
virtual QgsRectangle sourceExtent() const
Returns the extent of all geometries from the source.
 
bool isCanceled() const
Tells whether the operation has been canceled already.
 
Base class for all map layer types.
 
virtual QgsRectangle extent() const
Returns the extent of the layer.
 
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
 
Abstract base class for processing algorithms.
 
QgsProcessingOutputDefinitions outputDefinitions() const
Returns an ordered list of output definitions utilized by the algorithm.
 
virtual QgsExpressionContext createExpressionContext(const QVariantMap ¶meters, QgsProcessingContext &context, QgsProcessingFeatureSource *source=nullptr) const
Creates an expression context relating to the algorithm.
 
const QgsProcessingParameterDefinition * parameterDefinition(const QString &name) const
Returns a matching parameter by name.
 
virtual QString asPythonCommand(const QVariantMap ¶meters, QgsProcessingContext &context) const
Returns a Python command string which can be executed to run the algorithm using the specified parame...
 
QgsProcessingProvider * provider() const
Returns the provider to which this algorithm belongs.
 
Details for layers to load into projects.
 
int layerSortKey
Optional sorting key for sorting output layers when loading them into a project.
 
QString groupName
Optional name for a layer tree group under which to place the layer when loading it into a project.
 
Contains information about the context in which a processing algorithm is executed.
 
QgsExpressionContext & expressionContext()
Returns the expression context.
 
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
 
QgsProcessingModelResult modelResult() const
Returns the model results, populated when the context is used to run a model algorithm.
 
QgsProcessingModelInitialRunConfig * modelInitialRunConfig()
Returns a reference to the model initial run configuration, used to run a model algorithm.
 
Qgis::ProcessingLogLevel logLevel() const
Returns the logging level for algorithms to use when pushing feedback messages to users.
 
void setModelInitialRunConfig(std::unique_ptr< QgsProcessingModelInitialRunConfig > config)
Sets the model initial run configuration, used to run a model algorithm.
 
Base class for all parameter definitions which represent file or layer destinations,...
 
virtual QString generateTemporaryDestination(const QgsProcessingContext *context=nullptr) const
Generates a temporary destination value for this parameter.
 
void setSupportsNonFileBasedOutput(bool supportsNonFileBasedOutput)
Sets whether the destination parameter supports non filed-based outputs, such as memory layers or dir...
 
Custom exception class for processing related exceptions.
 
Encapsulates settings relating to a feature source input to a processing algorithm.
 
QgsProperty source
Source definition.
 
QgsFeatureSource subclass which proxies methods to an underlying QgsFeatureSource,...
 
Base class for providing feedback from a processing algorithm.
 
virtual void pushCommandInfo(const QString &info)
Pushes an informational message containing a command from the algorithm.
 
virtual void pushInfo(const QString &info)
Pushes a general informational message from the algorithm.
 
virtual void pushWarning(const QString &warning)
Pushes a warning informational message from the algorithm.
 
virtual QString htmlLog() const
Returns the HTML formatted contents of the log, which contains all messages pushed to the feedback ob...
 
virtual void pushDebugInfo(const QString &info)
Pushes an informational message containing debugging helpers from the algorithm.
 
virtual void setProgressText(const QString &text)
Sets a progress report text string.
 
Encapsulates the results of running a child algorithm within a model.
 
void setOutputs(const QVariantMap &outputs)
Sets the outputs generated by child algorithm.
 
void setExecutionStatus(Qgis::ProcessingModelChildAlgorithmExecutionStatus status)
Sets the status of executing the child algorithm.
 
void setInputs(const QVariantMap &inputs)
Sets the inputs used for the child algorithm.
 
void setHtmlLog(const QString &log)
Sets the HTML formatted contents of logged messages which occurred while running the child.
 
Configuration settings which control how a Processing model is executed.
 
QSet< QString > childAlgorithmSubset() const
Returns the subset of child algorithms to run (by child ID).
 
QVariantMap & rawChildOutputs()
Returns a reference to the map of raw child algorithm outputs.
 
QVariantMap & rawChildInputs()
Returns a reference to the map of raw child algorithm inputs.
 
QSet< QString > & executedChildIds()
Returns a reference to the set of child algorithm IDs which were executed during the model execution.
 
Processing feedback object for multi-step operations.
 
static QString typeName()
Returns the type name for the output class.
 
static QString typeName()
Returns the type name for the output class.
 
Base class for the definition of processing outputs.
 
Encapsulates settings relating to a feature sink or output raster layer for a processing algorithm.
 
QgsProperty sink
Sink/layer definition.
 
QString destinationName
Name to use for sink if it's to be loaded into a destination project.
 
static QString typeName()
Returns the type name for the output class.
 
static QString typeName()
Returns the type name for the output class.
 
static QString typeName()
Returns the type name for the output class.
 
static QString typeName()
Returns the type name for the output class.
 
static QString typeName()
Returns the type name for the output class.
 
A vector layer output for processing algorithms.
 
Qgis::ProcessingSourceType dataType() const
Returns the layer type for the output layer.
 
static QString typeName()
Returns the type name for the output class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
Base class for the definition of processing parameters.
 
QgsProcessingAlgorithm * algorithm() const
Returns a pointer to the algorithm which owns this parameter.
 
QVariantMap metadata() const
Returns the parameter's freeform metadata.
 
virtual bool isDestination() const
Returns true if this parameter represents a file or layer destination, e.g.
 
virtual QgsProcessingParameterDefinition * clone() const =0
Creates a clone of the parameter definition.
 
virtual QString type() const =0
Unique parameter type name.
 
virtual QVariantMap toVariantMap() const
Saves this parameter to a QVariantMap.
 
QString name() const
Returns the name of the parameter.
 
virtual QStringList dependsOnOtherParameters() const
Returns a list of other parameter names on which this parameter is dependent (e.g.
 
Qgis::ProcessingParameterFlags flags() const
Returns any flags associated with the parameter.
 
virtual bool checkValueIsAcceptable(const QVariant &input, QgsProcessingContext *context=nullptr) const
Checks whether the specified input value is acceptable for the parameter.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
A vector layer or feature source field parameter for processing algorithms.
 
Qgis::ProcessingFieldParameterDataType dataType() const
Returns the acceptable data type for the field.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
Can be inherited by parameters which require limits to their acceptable data types.
 
QList< int > dataTypes() const
Returns the geometry types for sources acceptable by the parameter.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
static QString typeName()
Returns the type name for the parameter class.
 
virtual QString pythonImportString() const
Returns a valid Python import string for importing the corresponding parameter type,...
 
static QString typeName()
Returns the type name for the parameter class.
 
static QgsProcessingParameterDefinition * parameterFromVariantMap(const QVariantMap &map)
Creates a new QgsProcessingParameterDefinition using the configuration from a supplied variant map.
 
Abstract base class for processing providers.
 
const QgsProcessingAlgorithm * algorithm(const QString &name) const
Returns the matching algorithm by name, or nullptr if no matching algorithm is contained by this prov...
 
QgsProcessingParameterType * parameterType(const QString &id) const
Returns the parameter type registered for id.
 
static QString formatHelpMapAsHtml(const QVariantMap &map, const QgsProcessingAlgorithm *algorithm)
Returns a HTML formatted version of the help text encoded in a variant map for a specified algorithm.
 
@ Vector
Vector layer type.
 
static QString variantToPythonLiteral(const QVariant &value)
Converts a variant to a Python literal.
 
static QVariantMap removePointerValuesFromMap(const QVariantMap &map)
Removes any raw pointer values from an input map, replacing them with appropriate string values where...
 
static QgsMapLayer * mapLayerFromString(const QString &string, QgsProcessingContext &context, bool allowLoadingNewLayers=true, QgsProcessingUtils::LayerHint typeHint=QgsProcessingUtils::LayerHint::UnknownType, QgsProcessing::LayerOptionsFlags flags=QgsProcessing::LayerOptionsFlags())
Interprets a string as a map layer within the supplied context.
 
PythonOutputType
Available Python output types.
 
@ PythonQgsProcessingAlgorithmSubclass
Full Python QgsProcessingAlgorithm subclass.
 
A store for object properties.
 
QVariant value(const QgsExpressionContext &context, const QVariant &defaultValue=QVariant(), bool *ok=nullptr) const
Calculates the current value of the property, including any transforms which are set for the property...
 
QVariant staticValue() const
Returns the current static value for the property.
 
double xMinimum() const
Returns the x minimum value (left side of rectangle).
 
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
 
double xMaximum() const
Returns the x maximum value (right side of rectangle).
 
double yMaximum() const
Returns the y maximum value (top side of rectangle).
 
static QString capitalize(const QString &string, Qgis::Capitalization capitalization)
Converts a string by applying capitalization rules to the string.
 
Represents a vector layer which manages a vector based data sets.
 
static QDomElement writeVariant(const QVariant &value, QDomDocument &doc)
Write a QVariant to a QDomElement.
 
static QVariant readVariant(const QDomElement &element)
Read a QVariant from a QDomElement.
 
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into allowing algorithms to be written in pure substantial changes are required in order to port existing x Processing algorithms for QGIS x The most significant changes are outlined not GeoAlgorithm For algorithms which operate on features one by consider subclassing the QgsProcessingFeatureBasedAlgorithm class This class allows much of the boilerplate code for looping over features from a vector layer to be bypassed and instead requires implementation of a processFeature method Ensure that your algorithm(or algorithm 's parent class) implements the new pure virtual createInstance(self) call
 
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
 
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
 
QString qgsSetJoin(const QSet< T > &set, const QString &separator)
Joins all the set values into a single string with each element separated by the given separator.
 
QMap< QString, QString > QgsStringMap
 
QPointer< QgsMapLayer > QgsWeakMapLayerPointer
Weak pointer for QgsMapLayer.
 
QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions
List of processing parameters.
 
QList< const QgsProcessingParameterDefinition * > QgsProcessingParameterDefinitions
List of processing parameters.
 
Single variable definition for use within a QgsExpressionContextScope.