34#include <QRegularExpression>
37QgsProcessingModelAlgorithm::QgsProcessingModelAlgorithm(
const QString &name,
const QString &group,
const QString &groupId )
38 : mModelName( name.isEmpty() ? QObject::tr(
"model" ) : name )
39 , mModelGroup( group )
40 , mModelGroupId( groupId )
43void QgsProcessingModelAlgorithm::initAlgorithm(
const QVariantMap & )
47QString QgsProcessingModelAlgorithm::name()
const
52QString QgsProcessingModelAlgorithm::displayName()
const
57QString QgsProcessingModelAlgorithm::group()
const
62QString QgsProcessingModelAlgorithm::groupId()
const
67QIcon QgsProcessingModelAlgorithm::icon()
const
72QString QgsProcessingModelAlgorithm::svgIconPath()
const
77QString QgsProcessingModelAlgorithm::shortHelpString()
const
79 if ( mHelpContent.empty() )
85QString QgsProcessingModelAlgorithm::shortDescription()
const
87 return mHelpContent.value( QStringLiteral(
"SHORT_DESCRIPTION" ) ).toString();
90QString QgsProcessingModelAlgorithm::helpUrl()
const
92 return mHelpContent.value( QStringLiteral(
"HELP_URL" ) ).toString();
95QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm(
const QgsProcessingModelChildAlgorithm &child,
const QVariantMap &modelParameters,
const QVariantMap &results,
const QgsExpressionContext &expressionContext, QString &error )
const
100 const QgsProcessingModelChildParameterSources paramSources = child.parameterSources().value( def->name() );
102 QString expressionText;
103 QVariantList paramParts;
104 for (
const QgsProcessingModelChildParameterSource &source : paramSources )
106 switch ( source.source() )
108 case QgsProcessingModelChildParameterSource::StaticValue:
109 paramParts << source.staticValue();
112 case QgsProcessingModelChildParameterSource::ModelParameter:
113 paramParts << modelParameters.value( source.parameterName() );
116 case QgsProcessingModelChildParameterSource::ChildOutput:
118 QVariantMap linkedChildResults = results.value( source.outputChildId() ).toMap();
119 paramParts << linkedChildResults.value( source.outputName() );
123 case QgsProcessingModelChildParameterSource::Expression:
126 paramParts << exp.evaluate( &expressionContext );
127 if ( exp.hasEvalError() )
129 error = QObject::tr(
"Could not evaluate expression for parameter %1 for %2: %3" ).arg( def->name(), child.description(), exp.evalErrorString() );
133 case QgsProcessingModelChildParameterSource::ExpressionText:
139 case QgsProcessingModelChildParameterSource::ModelOutput:
144 if ( ! expressionText.isEmpty() )
146 return expressionText;
148 else if ( paramParts.count() == 1 )
149 return paramParts.at( 0 );
155 QVariantMap childParams;
156 const QList< const QgsProcessingParameterDefinition * > childParameterDefinitions = child.algorithm()->parameterDefinitions();
159 if ( !def->isDestination() )
161 if ( !child.parameterSources().contains( def->name() ) )
164 const QVariant value = evaluateSources( def );
165 childParams.insert( def->name(), value );
172 bool isFinalOutput =
false;
173 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
174 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
175 for ( ; outputIt != outputs.constEnd(); ++outputIt )
177 if ( outputIt->childOutputName() == destParam->
name() )
179 QString paramName = child.childId() +
':' + outputIt.key();
180 bool foundParam =
false;
184 if ( modelParameters.contains( paramName ) )
186 value = modelParameters.value( paramName );
195 if ( modelParameters.contains( modelParam->name() ) )
197 value = modelParameters.value( modelParam->name() );
205 if ( value.userType() == QMetaType::type(
"QgsProcessingOutputLayerDefinition" ) )
210 value = QVariant::fromValue( fromVar );
213 childParams.insert( destParam->
name(), value );
215 isFinalOutput =
true;
220 bool hasExplicitDefinition =
false;
221 if ( !isFinalOutput && child.parameterSources().contains( def->name() ) )
224 const QVariant value = evaluateSources( def );
225 if ( value.isValid() )
227 childParams.insert( def->name(), value );
228 hasExplicitDefinition =
true;
232 if ( !isFinalOutput && !hasExplicitDefinition )
237 bool required =
true;
240 required = childOutputIsRequired( child.childId(), destParam->
name() );
252const QgsProcessingParameterDefinition *QgsProcessingModelAlgorithm::modelParameterFromChildIdAndOutputName(
const QString &childId,
const QString &childOutputName )
const
256 if ( !definition->isDestination() )
259 const QString modelChildId = definition->
metadata().value( QStringLiteral(
"_modelChildId" ) ).toString();
260 const QString modelOutputName = definition->metadata().value( QStringLiteral(
"_modelChildOutputName" ) ).toString();
262 if ( modelChildId == childId && modelOutputName == childOutputName )
268bool QgsProcessingModelAlgorithm::childOutputIsRequired(
const QString &childId,
const QString &outputName )
const
271 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
272 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
274 if ( childIt->childId() == childId || !childIt->isActive() )
278 QMap<QString, QgsProcessingModelChildParameterSources> candidateChildParams = childIt->parameterSources();
279 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator childParamIt = candidateChildParams.constBegin();
280 for ( ; childParamIt != candidateChildParams.constEnd(); ++childParamIt )
282 const auto constValue = childParamIt.value();
283 for (
const QgsProcessingModelChildParameterSource &source : constValue )
285 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput
286 && source.outputChildId() == childId
287 && source.outputName() == outputName )
299 QSet< QString > toExecute;
300 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
301 QSet< QString > broken;
302 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
304 if ( childIt->isActive() )
306 if ( childIt->algorithm() )
307 toExecute.insert( childIt->childId() );
309 broken.insert( childIt->childId() );
313 if ( !broken.empty() )
314 throw QgsProcessingException( QCoreApplication::translate(
"QgsProcessingModelAlgorithm",
"Cannot run model, the following algorithms are not available on this system: %1" ).arg( broken.values().join( QLatin1String(
", " ) ) ) );
316 QElapsedTimer totalTime;
322 QVariantMap childResults;
323 QVariantMap childInputs;
327 QVariantMap finalResults;
328 QSet< QString > executed;
329 bool executedAlg =
true;
330 while ( executedAlg && executed.count() < toExecute.count() )
333 for (
const QString &childId : std::as_const( toExecute ) )
338 if ( executed.contains( childId ) )
341 bool canExecute =
true;
342 const QSet< QString > dependencies = dependsOnChildAlgorithms( childId );
343 for (
const QString &dependency : dependencies )
345 if ( !executed.contains( dependency ) )
357 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
358 std::unique_ptr< QgsProcessingAlgorithm > childAlg( child.algorithm()->create( child.configuration() ) );
361 if ( feedback && !skipGenericLogging )
362 feedback->
pushDebugInfo( QObject::tr(
"Prepare algorithm: %1" ).arg( childId ) );
366 << createExpressionContextScopeForChildAlgorithm( childId, context, parameters, childResults );
370 QVariantMap childParams = parametersForChildAlgorithm( child, parameters, childResults, expContext, error );
371 if ( !error.isEmpty() )
374 if ( feedback && !skipGenericLogging )
375 feedback->
setProgressText( QObject::tr(
"Running %1 [%2/%3]" ).arg( child.description() ).arg( executed.count() + 1 ).arg( toExecute.count() ) );
379 for (
auto childParamIt = childParams.constBegin(); childParamIt != childParams.constEnd(); ++childParamIt )
381 params << QStringLiteral(
"%1: %2" ).arg( childParamIt.key(),
382 child.algorithm()->parameterDefinition( childParamIt.key() )->valueAsPythonString( childParamIt.value(), context ) );
385 if ( feedback && !skipGenericLogging )
387 feedback->
pushInfo( QObject::tr(
"Input Parameters:" ) );
388 feedback->
pushCommandInfo( QStringLiteral(
"{ %1 }" ).arg( params.join( QLatin1String(
", " ) ) ) );
391 QElapsedTimer childTime;
396 QThread *modelThread = QThread::currentThread();
398 auto prepareOnMainThread = [modelThread, &ok, &childAlg, &childParams, &context, &modelFeedback]
400 Q_ASSERT_X( QThread::currentThread() == qApp->thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"childAlg->prepare() must be run on the main thread" );
401 ok = childAlg->prepare( childParams, context, &modelFeedback );
402 context.pushToThread( modelThread );
406 if ( modelThread == qApp->thread() )
407 ok = childAlg->prepare( childParams, context, &modelFeedback );
410 context.pushToThread( qApp->thread() );
411 QMetaObject::invokeMethod( qApp, prepareOnMainThread, Qt::BlockingQueuedConnection );
414 Q_ASSERT_X( QThread::currentThread() == context.thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"context was not transferred back to model thread" );
428 auto runOnMainThread = [modelThread, &context, &modelFeedback, &results, &childAlg, &childParams]
430 Q_ASSERT_X( QThread::currentThread() == qApp->thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"childAlg->runPrepared() must be run on the main thread" );
431 results = childAlg->runPrepared( childParams, context, &modelFeedback );
432 context.pushToThread( modelThread );
435 if ( feedback && !skipGenericLogging && modelThread != qApp->thread() )
436 feedback->
pushWarning( QObject::tr(
"Algorithm “%1” cannot be run in a background thread, switching to main thread for this step" ).arg( childAlg->displayName() ) );
438 context.pushToThread( qApp->thread() );
439 QMetaObject::invokeMethod( qApp, runOnMainThread, Qt::BlockingQueuedConnection );
444 results = childAlg->runPrepared( childParams, context, &modelFeedback );
453 Q_ASSERT_X( QThread::currentThread() == context.thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"context was not transferred back to model thread" );
456 auto postProcessOnMainThread = [modelThread, &ppRes, &childAlg, &context, &modelFeedback]
458 Q_ASSERT_X( QThread::currentThread() == qApp->thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"childAlg->postProcess() must be run on the main thread" );
459 ppRes = childAlg->postProcess( context, &modelFeedback );
460 context.pushToThread( modelThread );
464 if ( modelThread == qApp->thread() )
465 ppRes = childAlg->postProcess( context, &modelFeedback );
468 context.pushToThread( qApp->thread() );
469 QMetaObject::invokeMethod( qApp, postProcessOnMainThread, Qt::BlockingQueuedConnection );
472 Q_ASSERT_X( QThread::currentThread() == context.thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"context was not transferred back to model thread" );
474 if ( !ppRes.isEmpty() )
477 childResults.insert( childId, results );
481 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
482 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
483 for ( ; outputIt != outputs.constEnd(); ++outputIt )
485 switch ( mInternalVersion )
487 case QgsProcessingModelAlgorithm::InternalVersion::Version1:
488 finalResults.insert( childId +
':' + outputIt->name(), results.value( outputIt->childOutputName() ) );
490 case QgsProcessingModelAlgorithm::InternalVersion::Version2:
493 finalResults.insert( modelParam->name(), results.value( outputIt->childOutputName() ) );
499 executed.insert( childId );
501 std::function< void(
const QString &,
const QString & )> pruneAlgorithmBranchRecursive;
502 pruneAlgorithmBranchRecursive = [&](
const QString & id,
const QString &branch = QString() )
504 const QSet<QString> toPrune = dependentChildAlgorithms(
id, branch );
505 for (
const QString &targetId : toPrune )
507 if ( executed.contains( targetId ) )
510 executed.insert( targetId );
511 pruneAlgorithmBranchRecursive( targetId, branch );
521 pruneAlgorithmBranchRecursive( childId, outputDef->name() );
529 for (
const QString &candidateId : std::as_const( toExecute ) )
531 if ( executed.contains( candidateId ) )
536 const QgsProcessingModelChildAlgorithm &candidate = mChildAlgorithms[ candidateId ];
537 const QMap<QString, QgsProcessingModelChildParameterSources> candidateParams = candidate.parameterSources();
538 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = candidateParams.constBegin();
540 for ( ; paramIt != candidateParams.constEnd(); ++paramIt )
542 for (
const QgsProcessingModelChildParameterSource &source : paramIt.value() )
544 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput && source.outputChildId() == childId )
547 if ( !results.contains( source.outputName() ) )
552 executed.insert( candidateId );
554 pruneAlgorithmBranchRecursive( candidateId, QString() );
565 childAlg.reset(
nullptr );
566 modelFeedback.setCurrentStep( executed.count() );
567 if ( feedback && !skipGenericLogging )
568 feedback->
pushInfo( QObject::tr(
"OK. Execution took %1 s (%n output(s)).",
nullptr, results.count() ).arg( childTime.elapsed() / 1000.0 ) );
575 feedback->
pushDebugInfo( QObject::tr(
"Model processed OK. Executed %n algorithm(s) total in %1 s.",
nullptr, executed.count() ).arg( totalTime.elapsed() / 1000.0 ) );
577 mResults = finalResults;
578 mResults.insert( QStringLiteral(
"CHILD_RESULTS" ), childResults );
579 mResults.insert( QStringLiteral(
"CHILD_INPUTS" ), childInputs );
583QString QgsProcessingModelAlgorithm::sourceFilePath()
const
588void QgsProcessingModelAlgorithm::setSourceFilePath(
const QString &sourceFile )
590 mSourceFile = sourceFile;
593bool QgsProcessingModelAlgorithm::modelNameMatchesFilePath()
const
595 if ( mSourceFile.isEmpty() )
598 const QFileInfo fi( mSourceFile );
599 return fi.completeBaseName().compare( mModelName, Qt::CaseInsensitive ) == 0;
604 QStringList fileDocString;
605 fileDocString << QStringLiteral(
"\"\"\"" );
606 fileDocString << QStringLiteral(
"Model exported as python." );
607 fileDocString << QStringLiteral(
"Name : %1" ).arg( displayName() );
608 fileDocString << QStringLiteral(
"Group : %1" ).arg( group() );
609 fileDocString << QStringLiteral(
"With QGIS : %1" ).arg(
Qgis::versionInt() );
610 fileDocString << QStringLiteral(
"\"\"\"" );
611 fileDocString << QString();
614 QString indent = QString(
' ' ).repeated( indentSize );
615 QString currentIndent;
617 QMap< QString, QString> friendlyChildNames;
618 QMap< QString, QString> friendlyOutputNames;
619 auto uniqueSafeName = [](
const QString & name,
bool capitalize,
const QMap< QString, QString > &friendlyNames )->QString
621 const QString base = safeName( name, capitalize );
622 QString candidate = base;
624 while ( friendlyNames.contains( candidate ) )
627 candidate = QStringLiteral(
"%1_%2" ).arg( base ).arg( i );
632 const QString algorithmClassName = safeName( name(),
true );
634 QSet< QString > toExecute;
635 for (
auto childIt = mChildAlgorithms.constBegin(); childIt != mChildAlgorithms.constEnd(); ++childIt )
637 if ( childIt->isActive() && childIt->algorithm() )
639 toExecute.insert( childIt->childId() );
640 friendlyChildNames.insert( childIt->childId(), uniqueSafeName( childIt->description().isEmpty() ? childIt->childId() : childIt->description(), !childIt->description().isEmpty(), friendlyChildNames ) );
643 const int totalSteps = toExecute.count();
645 QStringList importLines;
646 switch ( outputType )
651 const auto params = parameterDefinitions();
652 importLines.reserve( params.count() + 3 );
653 importLines << QStringLiteral(
"from qgis.core import QgsProcessing" );
654 importLines << QStringLiteral(
"from qgis.core import QgsProcessingAlgorithm" );
655 importLines << QStringLiteral(
"from qgis.core import QgsProcessingMultiStepFeedback" );
657 bool hasAdvancedParams =
false;
661 hasAdvancedParams =
true;
664 if ( !importString.isEmpty() && !importLines.contains( importString ) )
665 importLines << importString;
668 if ( hasAdvancedParams )
669 importLines << QStringLiteral(
"from qgis.core import QgsProcessingParameterDefinition" );
671 lines << QStringLiteral(
"import processing" );
672 lines << QString() << QString();
674 lines << QStringLiteral(
"class %1(QgsProcessingAlgorithm):" ).arg( algorithmClassName );
678 lines << indent + QStringLiteral(
"def initAlgorithm(self, config=None):" );
679 if ( params.empty() )
681 lines << indent + indent + QStringLiteral(
"pass" );
685 lines.reserve( lines.size() + params.size() );
688 std::unique_ptr< QgsProcessingParameterDefinition > defClone( def->clone() );
690 if ( defClone->isDestination() )
692 const QString uniqueChildName = defClone->metadata().value( QStringLiteral(
"_modelChildId" ) ).toString() +
':' + defClone->metadata().value( QStringLiteral(
"_modelChildOutputName" ) ).toString();
693 const QString friendlyName = !defClone->description().isEmpty() ? uniqueSafeName( defClone->description(),
true, friendlyOutputNames ) : defClone->name();
694 friendlyOutputNames.insert( uniqueChildName, friendlyName );
695 defClone->setName( friendlyName );
699 if ( !mParameterComponents.value( defClone->name() ).comment()->description().isEmpty() )
700 lines << indent + indent + QStringLiteral(
"# %1" ).arg( mParameterComponents.value( defClone->name() ).comment()->description() );
705 lines << indent + indent + QStringLiteral(
"param = %1" ).arg( defClone->asPythonString() );
706 lines << indent + indent + QStringLiteral(
"param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)" );
707 lines << indent + indent + QStringLiteral(
"self.addParameter(param)" );
711 lines << indent + indent + QStringLiteral(
"self.addParameter(%1)" ).arg( defClone->asPythonString() );
717 lines << indent + QStringLiteral(
"def processAlgorithm(self, parameters, context, model_feedback):" );
718 currentIndent = indent + indent;
720 lines << currentIndent + QStringLiteral(
"# Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the" );
721 lines << currentIndent + QStringLiteral(
"# overall progress through the model" );
722 lines << currentIndent + QStringLiteral(
"feedback = QgsProcessingMultiStepFeedback(%1, model_feedback)" ).arg( totalSteps );
730 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
731 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
733 QString name = paramIt.value().parameterName();
734 if ( parameterDefinition( name ) )
737 params.insert( name, parameterDefinition( name )->valueAsPythonString( parameterDefinition( name )->defaultValue(), context ) );
741 if ( !params.isEmpty() )
743 lines << QStringLiteral(
"parameters = {" );
744 for (
auto it = params.constBegin(); it != params.constEnd(); ++it )
746 lines << QStringLiteral(
" '%1':%2," ).arg( it.key(), it.value() );
748 lines << QStringLiteral(
"}" )
752 lines << QStringLiteral(
"context = QgsProcessingContext()" )
753 << QStringLiteral(
"context.setProject(QgsProject.instance())" )
754 << QStringLiteral(
"feedback = QgsProcessingFeedback()" )
763 lines << currentIndent + QStringLiteral(
"results = {}" );
764 lines << currentIndent + QStringLiteral(
"outputs = {}" );
767 QSet< QString > executed;
768 bool executedAlg =
true;
770 while ( executedAlg && executed.count() < toExecute.count() )
773 const auto constToExecute = toExecute;
774 for (
const QString &childId : constToExecute )
776 if ( executed.contains( childId ) )
779 bool canExecute =
true;
780 const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms( childId );
781 for (
const QString &dependency : constDependsOnChildAlgorithms )
783 if ( !executed.contains( dependency ) )
795 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
802 if ( def->isDestination() )
807 bool isFinalOutput =
false;
808 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
809 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
810 for ( ; outputIt != outputs.constEnd(); ++outputIt )
812 if ( outputIt->childOutputName() == destParam->
name() )
814 QString paramName = child.childId() +
':' + outputIt.key();
815 paramName = friendlyOutputNames.value( paramName, paramName );
816 childParams.insert( destParam->
name(), QStringLiteral(
"parameters['%1']" ).arg( paramName ) );
817 isFinalOutput =
true;
822 if ( !isFinalOutput )
827 bool required =
true;
830 required = childOutputIsRequired( child.childId(), destParam->
name() );
837 childParams.insert( destParam->
name(), QStringLiteral(
"QgsProcessing.TEMPORARY_OUTPUT" ) );
843 lines << child.asPythonCode( outputType, childParams, currentIndent.size(), indentSize, friendlyChildNames, friendlyOutputNames );
845 if ( currentStep < totalSteps )
848 lines << currentIndent + QStringLiteral(
"feedback.setCurrentStep(%1)" ).arg( currentStep );
849 lines << currentIndent + QStringLiteral(
"if feedback.isCanceled():" );
850 lines << currentIndent + indent + QStringLiteral(
"return {}" );
853 executed.insert( childId );
857 switch ( outputType )
860 lines << currentIndent + QStringLiteral(
"return results" );
864 lines << indent + QStringLiteral(
"def name(self):" );
865 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelName );
867 lines << indent + QStringLiteral(
"def displayName(self):" );
868 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelName );
872 lines << indent + QStringLiteral(
"def group(self):" );
873 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelGroup );
875 lines << indent + QStringLiteral(
"def groupId(self):" );
876 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelGroupId );
880 if ( !shortHelpString().isEmpty() )
882 lines << indent + QStringLiteral(
"def shortHelpString(self):" );
883 lines << indent + indent + QStringLiteral(
"return \"\"\"%1\"\"\"" ).arg( shortHelpString() );
886 if ( !helpUrl().isEmpty() )
888 lines << indent + QStringLiteral(
"def helpUrl(self):" );
889 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( helpUrl() );
894 lines << indent + QStringLiteral(
"def createInstance(self):" );
895 lines << indent + indent + QStringLiteral(
"return %1()" ).arg( algorithmClassName );
898 static QMap< QString, QString > sAdditionalImports
900 { QStringLiteral(
"QgsCoordinateReferenceSystem" ), QStringLiteral(
"from qgis.core import QgsCoordinateReferenceSystem" ) },
901 { QStringLiteral(
"QgsExpression" ), QStringLiteral(
"from qgis.core import QgsExpression" ) },
902 { QStringLiteral(
"QgsRectangle" ), QStringLiteral(
"from qgis.core import QgsRectangle" ) },
903 { QStringLiteral(
"QgsReferencedRectangle" ), QStringLiteral(
"from qgis.core import QgsReferencedRectangle" ) },
904 { QStringLiteral(
"QgsPoint" ), QStringLiteral(
"from qgis.core import QgsPoint" ) },
905 { QStringLiteral(
"QgsReferencedPoint" ), QStringLiteral(
"from qgis.core import QgsReferencedPoint" ) },
906 { QStringLiteral(
"QgsProperty" ), QStringLiteral(
"from qgis.core import QgsProperty" ) },
907 { QStringLiteral(
"QgsRasterLayer" ), QStringLiteral(
"from qgis.core import QgsRasterLayer" ) },
908 { QStringLiteral(
"QgsMeshLayer" ), QStringLiteral(
"from qgis.core import QgsMeshLayer" ) },
909 { QStringLiteral(
"QgsVectorLayer" ), QStringLiteral(
"from qgis.core import QgsVectorLayer" ) },
910 { QStringLiteral(
"QgsMapLayer" ), QStringLiteral(
"from qgis.core import QgsMapLayer" ) },
911 { QStringLiteral(
"QgsProcessingFeatureSourceDefinition" ), QStringLiteral(
"from qgis.core import QgsProcessingFeatureSourceDefinition" ) },
912 { QStringLiteral(
"QgsPointXY" ), QStringLiteral(
"from qgis.core import QgsPointXY" ) },
913 { QStringLiteral(
"QgsReferencedPointXY" ), QStringLiteral(
"from qgis.core import QgsReferencedPointXY" ) },
914 { QStringLiteral(
"QgsGeometry" ), QStringLiteral(
"from qgis.core import QgsGeometry" ) },
915 { QStringLiteral(
"QgsProcessingOutputLayerDefinition" ), QStringLiteral(
"from qgis.core import QgsProcessingOutputLayerDefinition" ) },
916 { QStringLiteral(
"QColor" ), QStringLiteral(
"from qgis.PyQt.QtGui import QColor" ) },
917 { QStringLiteral(
"QDateTime" ), QStringLiteral(
"from qgis.PyQt.QtCore import QDateTime" ) },
918 { QStringLiteral(
"QDate" ), QStringLiteral(
"from qgis.PyQt.QtCore import QDate" ) },
919 { QStringLiteral(
"QTime" ), QStringLiteral(
"from qgis.PyQt.QtCore import QTime" ) },
922 for (
auto it = sAdditionalImports.constBegin(); it != sAdditionalImports.constEnd(); ++it )
924 if ( importLines.contains( it.value() ) )
931 for (
const QString &line : std::as_const( lines ) )
933 if ( line.contains( it.key() ) )
941 importLines << it.value();
945 lines = fileDocString + importLines + lines;
954QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> QgsProcessingModelAlgorithm::variablesForChildAlgorithm(
const QString &childId,
QgsProcessingContext &context,
const QVariantMap &modelParameters,
const QVariantMap &results )
const
956 QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables;
958 auto safeName = [](
const QString & name )->QString
961 return s.replace( QRegularExpression( QStringLiteral(
"[\\s'\"\\(\\):\\.]" ) ), QStringLiteral(
"_" ) );
995 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
1000 switch ( source.source() )
1002 case QgsProcessingModelChildParameterSource::ModelParameter:
1004 name = source.parameterName();
1005 value = modelParameters.value( source.parameterName() );
1006 description = parameterDefinition( source.parameterName() )->description();
1009 case QgsProcessingModelChildParameterSource::ChildOutput:
1011 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
1012 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
1013 source.outputChildId() : child.description(), source.outputName() );
1016 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
1017 child.description() );
1019 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
1023 case QgsProcessingModelChildParameterSource::Expression:
1024 case QgsProcessingModelChildParameterSource::ExpressionText:
1025 case QgsProcessingModelChildParameterSource::StaticValue:
1026 case QgsProcessingModelChildParameterSource::ModelOutput:
1029 variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
1033 sources = availableSourcesForChild( childId, QStringList()
1040 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
1044 QString description;
1046 switch ( source.source() )
1048 case QgsProcessingModelChildParameterSource::ModelParameter:
1050 name = source.parameterName();
1051 value = modelParameters.value( source.parameterName() );
1052 description = parameterDefinition( source.parameterName() )->description();
1055 case QgsProcessingModelChildParameterSource::ChildOutput:
1057 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
1058 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
1059 source.outputChildId() : child.description(), source.outputName() );
1060 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
1063 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
1064 child.description() );
1069 case QgsProcessingModelChildParameterSource::Expression:
1070 case QgsProcessingModelChildParameterSource::ExpressionText:
1071 case QgsProcessingModelChildParameterSource::StaticValue:
1072 case QgsProcessingModelChildParameterSource::ModelOutput:
1077 if ( value.userType() == QMetaType::type(
"QgsProcessingOutputLayerDefinition" ) )
1080 value = fromVar.
sink;
1081 if ( value.userType() == QMetaType::type(
"QgsProperty" ) )
1086 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( value ) );
1090 variables.insert( safeName( name ), VariableDefinition( QVariant::fromValue(
QgsWeakMapLayerPointer( layer ) ), source, description ) );
1091 variables.insert( safeName( QStringLiteral(
"%1_minx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMinimum() : QVariant(), source, QObject::tr(
"Minimum X of %1" ).arg( description ) ) );
1092 variables.insert( safeName( QStringLiteral(
"%1_miny" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMinimum() : QVariant(), source, QObject::tr(
"Minimum Y of %1" ).arg( description ) ) );
1093 variables.insert( safeName( QStringLiteral(
"%1_maxx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMaximum() : QVariant(), source, QObject::tr(
"Maximum X of %1" ).arg( description ) ) );
1094 variables.insert( safeName( QStringLiteral(
"%1_maxy" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMaximum() : QVariant(), source, QObject::tr(
"Maximum Y of %1" ).arg( description ) ) );
1097 sources = availableSourcesForChild( childId, QStringList()
1099 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
1103 QString description;
1105 switch ( source.source() )
1107 case QgsProcessingModelChildParameterSource::ModelParameter:
1109 name = source.parameterName();
1110 value = modelParameters.value( source.parameterName() );
1111 description = parameterDefinition( source.parameterName() )->description();
1114 case QgsProcessingModelChildParameterSource::ChildOutput:
1116 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
1117 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
1118 source.outputChildId() : child.description(), source.outputName() );
1119 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
1122 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
1123 child.description() );
1128 case QgsProcessingModelChildParameterSource::Expression:
1129 case QgsProcessingModelChildParameterSource::ExpressionText:
1130 case QgsProcessingModelChildParameterSource::StaticValue:
1131 case QgsProcessingModelChildParameterSource::ModelOutput:
1137 if ( value.userType() == QMetaType::type(
"QgsProcessingFeatureSourceDefinition" ) )
1142 else if ( value.userType() == QMetaType::type(
"QgsProcessingOutputLayerDefinition" ) )
1145 value = fromVar.
sink;
1146 if ( value.userType() == QMetaType::type(
"QgsProperty" ) )
1151 if (
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( value ) ) )
1153 featureSource = layer;
1155 if ( !featureSource )
1161 variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
1162 variables.insert( safeName( QStringLiteral(
"%1_minx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMinimum() : QVariant(), source, QObject::tr(
"Minimum X of %1" ).arg( description ) ) );
1163 variables.insert( safeName( QStringLiteral(
"%1_miny" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMinimum() : QVariant(), source, QObject::tr(
"Minimum Y of %1" ).arg( description ) ) );
1164 variables.insert( safeName( QStringLiteral(
"%1_maxx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMaximum() : QVariant(), source, QObject::tr(
"Maximum X of %1" ).arg( description ) ) );
1165 variables.insert( safeName( QStringLiteral(
"%1_maxy" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMaximum() : QVariant(), source, QObject::tr(
"Maximum Y of %1" ).arg( description ) ) );
1171QgsExpressionContextScope *QgsProcessingModelAlgorithm::createExpressionContextScopeForChildAlgorithm(
const QString &childId,
QgsProcessingContext &context,
const QVariantMap &modelParameters,
const QVariantMap &results )
const
1173 std::unique_ptr< QgsExpressionContextScope > scope(
new QgsExpressionContextScope( QStringLiteral(
"algorithm_inputs" ) ) );
1174 QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = variablesForChildAlgorithm( childId, context, modelParameters, results );
1175 QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition>::const_iterator varIt = variables.constBegin();
1176 for ( ; varIt != variables.constEnd(); ++varIt )
1180 return scope.release();
1183QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild(
const QString &childId,
const QStringList ¶meterTypes,
const QStringList &outputTypes,
const QList<int> &dataTypes )
const
1185 QgsProcessingModelChildParameterSources sources;
1188 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
1189 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
1195 if ( parameterTypes.contains( def->
type() ) )
1197 if ( !dataTypes.isEmpty() )
1213 bool ok = sourceDef->
dataTypes().isEmpty();
1214 const auto constDataTypes = sourceDef->
dataTypes();
1215 for (
int type : constDataTypes )
1230 sources << QgsProcessingModelChildParameterSource::fromModelParameter( paramIt->parameterName() );
1234 QSet< QString > dependents;
1235 if ( !childId.isEmpty() )
1237 dependents = dependentChildAlgorithms( childId );
1238 dependents << childId;
1241 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1242 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1244 if ( dependents.contains( childIt->childId() ) )
1254 if ( outputTypes.contains( out->type() ) )
1256 if ( !dataTypes.isEmpty() )
1262 if ( !vectorOutputIsCompatibleType( dataTypes, vectorOut->
dataType() ) )
1269 sources << QgsProcessingModelChildParameterSource::fromChildOutput( childIt->childId(), out->name() );
1277QVariantMap QgsProcessingModelAlgorithm::helpContent()
const
1279 return mHelpContent;
1282void QgsProcessingModelAlgorithm::setHelpContent(
const QVariantMap &helpContent )
1284 mHelpContent = helpContent;
1287void QgsProcessingModelAlgorithm::setName(
const QString &name )
1292void QgsProcessingModelAlgorithm::setGroup(
const QString &group )
1294 mModelGroup = group;
1297bool QgsProcessingModelAlgorithm::validate( QStringList &issues )
const
1302 if ( mChildAlgorithms.empty() )
1305 issues << QObject::tr(
"Model does not contain any algorithms" );
1308 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
1310 QStringList childIssues;
1311 res = validateChildAlgorithm( it->childId(), childIssues ) && res;
1313 for (
const QString &issue : std::as_const( childIssues ) )
1315 issues << QStringLiteral(
"<b>%1</b>: %2" ).arg( it->description(), issue );
1321QMap<QString, QgsProcessingModelChildAlgorithm> QgsProcessingModelAlgorithm::childAlgorithms()
const
1323 return mChildAlgorithms;
1326void QgsProcessingModelAlgorithm::setParameterComponents(
const QMap<QString, QgsProcessingModelParameter> ¶meterComponents )
1328 mParameterComponents = parameterComponents;
1331void QgsProcessingModelAlgorithm::setParameterComponent(
const QgsProcessingModelParameter &component )
1333 mParameterComponents.insert( component.parameterName(), component );
1336QgsProcessingModelParameter &QgsProcessingModelAlgorithm::parameterComponent(
const QString &name )
1338 if ( !mParameterComponents.contains( name ) )
1340 QgsProcessingModelParameter &component = mParameterComponents[ name ];
1341 component.setParameterName( name );
1344 return mParameterComponents[ name ];
1347QList< QgsProcessingModelParameter > QgsProcessingModelAlgorithm::orderedParameters()
const
1349 QList< QgsProcessingModelParameter > res;
1350 QSet< QString > found;
1351 for (
const QString ¶meter : mParameterOrder )
1353 if ( mParameterComponents.contains( parameter ) )
1355 res << mParameterComponents.value( parameter );
1361 for (
auto it = mParameterComponents.constBegin(); it != mParameterComponents.constEnd(); ++it )
1363 if ( !found.contains( it.key() ) )
1371void QgsProcessingModelAlgorithm::setParameterOrder(
const QStringList &order )
1373 mParameterOrder = order;
1376void QgsProcessingModelAlgorithm::updateDestinationParameters()
1379 QMutableListIterator<const QgsProcessingParameterDefinition *> it( mParameters );
1380 while ( it.hasNext() )
1390 qDeleteAll( mOutputs );
1394 QSet< QString > usedFriendlyNames;
1395 auto uniqueSafeName = [&usedFriendlyNames ](
const QString & name )->QString
1397 const QString base = safeName( name,
false );
1398 QString candidate = base;
1400 while ( usedFriendlyNames.contains( candidate ) )
1403 candidate = QStringLiteral(
"%1_%2" ).arg( base ).arg( i );
1405 usedFriendlyNames.insert( candidate );
1409 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1410 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1412 QMap<QString, QgsProcessingModelOutput> outputs = childIt->modelOutputs();
1413 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
1414 for ( ; outputIt != outputs.constEnd(); ++outputIt )
1416 if ( !childIt->isActive() || !childIt->algorithm() )
1424 std::unique_ptr< QgsProcessingParameterDefinition > param( source->
clone() );
1428 if ( outputIt->isMandatory() )
1430 if ( mInternalVersion != InternalVersion::Version1 && !outputIt->description().isEmpty() )
1432 QString friendlyName = uniqueSafeName( outputIt->description() );
1433 param->setName( friendlyName );
1437 param->setName( outputIt->childId() +
':' + outputIt->name() );
1440 param->metadata().insert( QStringLiteral(
"_modelChildId" ), outputIt->childId() );
1441 param->metadata().insert( QStringLiteral(
"_modelChildOutputName" ), outputIt->name() );
1442 param->metadata().insert( QStringLiteral(
"_modelChildProvider" ), childIt->algorithm()->provider()->id() );
1444 param->setDescription( outputIt->description() );
1445 param->setDefaultValue( outputIt->defaultValue() );
1448 if ( addParameter( param.release() ) && newDestParam )
1455 newDestParam->mOriginalProvider = provider;
1462void QgsProcessingModelAlgorithm::addGroupBox(
const QgsProcessingModelGroupBox &groupBox )
1464 mGroupBoxes.insert( groupBox.uuid(), groupBox );
1467QList<QgsProcessingModelGroupBox> QgsProcessingModelAlgorithm::groupBoxes()
const
1469 return mGroupBoxes.values();
1472void QgsProcessingModelAlgorithm::removeGroupBox(
const QString &uuid )
1474 mGroupBoxes.remove( uuid );
1477QVariant QgsProcessingModelAlgorithm::toVariant()
const
1480 map.insert( QStringLiteral(
"model_name" ), mModelName );
1481 map.insert( QStringLiteral(
"model_group" ), mModelGroup );
1482 map.insert( QStringLiteral(
"help" ), mHelpContent );
1483 map.insert( QStringLiteral(
"internal_version" ),
qgsEnumValueToKey( mInternalVersion ) );
1485 QVariantMap childMap;
1486 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1487 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1489 childMap.insert( childIt.key(), childIt.value().toVariant() );
1491 map.insert( QStringLiteral(
"children" ), childMap );
1493 QVariantMap paramMap;
1494 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
1495 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
1497 paramMap.insert( paramIt.key(), paramIt.value().toVariant() );
1499 map.insert( QStringLiteral(
"parameters" ), paramMap );
1501 QVariantMap paramDefMap;
1506 map.insert( QStringLiteral(
"parameterDefinitions" ), paramDefMap );
1508 QVariantList groupBoxDefs;
1509 for (
auto it = mGroupBoxes.constBegin(); it != mGroupBoxes.constEnd(); ++it )
1511 groupBoxDefs.append( it.value().toVariant() );
1513 map.insert( QStringLiteral(
"groupBoxes" ), groupBoxDefs );
1515 map.insert( QStringLiteral(
"modelVariables" ), mVariables );
1517 map.insert( QStringLiteral(
"designerParameterValues" ), mDesignerParameterValues );
1519 map.insert( QStringLiteral(
"parameterOrder" ), mParameterOrder );
1524bool QgsProcessingModelAlgorithm::loadVariant(
const QVariant &model )
1526 QVariantMap map = model.toMap();
1528 mModelName = map.value( QStringLiteral(
"model_name" ) ).toString();
1529 mModelGroup = map.value( QStringLiteral(
"model_group" ) ).toString();
1530 mModelGroupId = map.value( QStringLiteral(
"model_group" ) ).toString();
1531 mHelpContent = map.value( QStringLiteral(
"help" ) ).toMap();
1533 mInternalVersion =
qgsEnumKeyToValue( map.value( QStringLiteral(
"internal_version" ) ).toString(), InternalVersion::Version1 );
1535 mVariables = map.value( QStringLiteral(
"modelVariables" ) ).toMap();
1536 mDesignerParameterValues = map.value( QStringLiteral(
"designerParameterValues" ) ).toMap();
1538 mParameterOrder = map.value( QStringLiteral(
"parameterOrder" ) ).toStringList();
1540 mChildAlgorithms.clear();
1541 QVariantMap childMap = map.value( QStringLiteral(
"children" ) ).toMap();
1542 QVariantMap::const_iterator childIt = childMap.constBegin();
1543 for ( ; childIt != childMap.constEnd(); ++childIt )
1545 QgsProcessingModelChildAlgorithm child;
1549 if ( !child.loadVariant( childIt.value() ) )
1552 mChildAlgorithms.insert( child.childId(), child );
1555 mParameterComponents.clear();
1556 QVariantMap paramMap = map.value( QStringLiteral(
"parameters" ) ).toMap();
1557 QVariantMap::const_iterator paramIt = paramMap.constBegin();
1558 for ( ; paramIt != paramMap.constEnd(); ++paramIt )
1560 QgsProcessingModelParameter param;
1561 if ( !param.loadVariant( paramIt.value().toMap() ) )
1564 mParameterComponents.insert( param.parameterName(), param );
1567 qDeleteAll( mParameters );
1568 mParameters.clear();
1569 QVariantMap paramDefMap = map.value( QStringLiteral(
"parameterDefinitions" ) ).toMap();
1571 auto addParam = [ = ](
const QVariant & value )
1579 if ( param->name() == QLatin1String(
"VERBOSE_LOG" ) )
1583 param->setHelp( mHelpContent.value( param->name() ).toString() );
1586 addParameter( param.release() );
1590 QVariantMap map = value.toMap();
1591 QString type = map.value( QStringLiteral(
"parameter_type" ) ).toString();
1592 QString name = map.value( QStringLiteral(
"name" ) ).toString();
1594 QgsMessageLog::logMessage( QCoreApplication::translate(
"Processing",
"Could not load parameter %1 of type %2." ).arg( name, type ), QCoreApplication::translate(
"Processing",
"Processing" ) );
1598 QSet< QString > loadedParams;
1600 for (
const QString &name : std::as_const( mParameterOrder ) )
1602 if ( paramDefMap.contains( name ) )
1604 addParam( paramDefMap.value( name ) );
1605 loadedParams << name;
1609 QVariantMap::const_iterator paramDefIt = paramDefMap.constBegin();
1610 for ( ; paramDefIt != paramDefMap.constEnd(); ++paramDefIt )
1612 if ( !loadedParams.contains( paramDefIt.key() ) )
1613 addParam( paramDefIt.value() );
1616 mGroupBoxes.clear();
1617 const QVariantList groupBoxList = map.value( QStringLiteral(
"groupBoxes" ) ).toList();
1618 for (
const QVariant &groupBoxDef : groupBoxList )
1620 QgsProcessingModelGroupBox groupBox;
1621 groupBox.loadVariant( groupBoxDef.toMap() );
1622 mGroupBoxes.insert( groupBox.uuid(), groupBox );
1625 updateDestinationParameters();
1630bool QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType(
const QList<int> &acceptableDataTypes,
QgsProcessing::SourceType outputType )
1635 return ( acceptableDataTypes.empty()
1636 || acceptableDataTypes.contains( outputType )
1647void QgsProcessingModelAlgorithm::reattachAlgorithms()
const
1649 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1650 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1652 if ( !childIt->algorithm() )
1653 childIt->reattach();
1657bool QgsProcessingModelAlgorithm::toFile(
const QString &path )
const
1659 QDomDocument doc = QDomDocument( QStringLiteral(
"model" ) );
1661 doc.appendChild( elem );
1664 if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
1666 QTextStream stream( &file );
1667 doc.save( stream, 2 );
1674bool QgsProcessingModelAlgorithm::fromFile(
const QString &path )
1679 if ( file.open( QFile::ReadOnly ) )
1681 if ( !doc.setContent( &file ) )
1692 return loadVariant( props );
1695void QgsProcessingModelAlgorithm::setChildAlgorithms(
const QMap<QString, QgsProcessingModelChildAlgorithm> &childAlgorithms )
1697 mChildAlgorithms = childAlgorithms;
1698 updateDestinationParameters();
1701void QgsProcessingModelAlgorithm::setChildAlgorithm(
const QgsProcessingModelChildAlgorithm &
algorithm )
1704 updateDestinationParameters();
1707QString QgsProcessingModelAlgorithm::addChildAlgorithm( QgsProcessingModelChildAlgorithm &
algorithm )
1709 if (
algorithm.childId().isEmpty() || mChildAlgorithms.contains(
algorithm.childId() ) )
1713 updateDestinationParameters();
1717QgsProcessingModelChildAlgorithm &QgsProcessingModelAlgorithm::childAlgorithm(
const QString &childId )
1719 return mChildAlgorithms[ childId ];
1722bool QgsProcessingModelAlgorithm::removeChildAlgorithm(
const QString &
id )
1724 if ( !dependentChildAlgorithms(
id ).isEmpty() )
1727 mChildAlgorithms.remove(
id );
1728 updateDestinationParameters();
1732void QgsProcessingModelAlgorithm::deactivateChildAlgorithm(
const QString &
id )
1734 const auto constDependentChildAlgorithms = dependentChildAlgorithms(
id );
1735 for (
const QString &child : constDependentChildAlgorithms )
1737 childAlgorithm( child ).setActive(
false );
1739 childAlgorithm(
id ).setActive(
false );
1740 updateDestinationParameters();
1743bool QgsProcessingModelAlgorithm::activateChildAlgorithm(
const QString &
id )
1745 const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms(
id );
1746 for (
const QString &child : constDependsOnChildAlgorithms )
1748 if ( !childAlgorithm( child ).isActive() )
1751 childAlgorithm(
id ).setActive(
true );
1752 updateDestinationParameters();
1758 if ( addParameter( definition ) )
1759 mParameterComponents.insert( definition->
name(), component );
1764 removeParameter( definition->
name() );
1765 addParameter( definition );
1768void QgsProcessingModelAlgorithm::removeModelParameter(
const QString &name )
1770 removeParameter( name );
1771 mParameterComponents.remove( name );
1774void QgsProcessingModelAlgorithm::changeParameterName(
const QString &oldName,
const QString &newName )
1779 auto replaceExpressionVariable = [oldName, newName, &expressionContext](
const QString & expressionString ) -> std::tuple< bool, QString >
1782 expression.prepare( &expressionContext );
1783 QSet<QString> variables = expression.referencedVariables();
1784 if ( variables.contains( oldName ) )
1786 QString newExpression = expressionString;
1787 newExpression.replace( QStringLiteral(
"@%1" ).arg( oldName ), QStringLiteral(
"@%2" ).arg( newName ) );
1788 return {
true, newExpression };
1790 return {
false, QString() };
1793 QMap< QString, QgsProcessingModelChildAlgorithm >::iterator childIt = mChildAlgorithms.begin();
1794 for ( ; childIt != mChildAlgorithms.end(); ++childIt )
1796 bool changed =
false;
1797 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
1798 QMap<QString, QgsProcessingModelChildParameterSources>::iterator paramIt = childParams.begin();
1799 for ( ; paramIt != childParams.end(); ++paramIt )
1801 QList< QgsProcessingModelChildParameterSource > &value = paramIt.value();
1802 for (
auto valueIt = value.begin(); valueIt != value.end(); ++valueIt )
1804 switch ( valueIt->source() )
1806 case QgsProcessingModelChildParameterSource::ModelParameter:
1808 if ( valueIt->parameterName() == oldName )
1810 valueIt->setParameterName( newName );
1816 case QgsProcessingModelChildParameterSource::Expression:
1818 bool updatedExpression =
false;
1819 QString newExpression;
1820 std::tie( updatedExpression, newExpression ) = replaceExpressionVariable( valueIt->expression() );
1821 if ( updatedExpression )
1823 valueIt->setExpression( newExpression );
1829 case QgsProcessingModelChildParameterSource::StaticValue:
1831 if ( valueIt->staticValue().userType() == QMetaType::type(
"QgsProperty" ) )
1836 bool updatedExpression =
false;
1837 QString newExpression;
1838 std::tie( updatedExpression, newExpression ) = replaceExpressionVariable( property.expressionString() );
1839 if ( updatedExpression )
1841 property.setExpressionString( newExpression );
1842 valueIt->setStaticValue( property );
1850 case QgsProcessingModelChildParameterSource::ChildOutput:
1851 case QgsProcessingModelChildParameterSource::ExpressionText:
1852 case QgsProcessingModelChildParameterSource::ModelOutput:
1858 childIt->setParameterSources( childParams );
1862bool QgsProcessingModelAlgorithm::childAlgorithmsDependOnParameter(
const QString &name )
const
1864 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1865 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1868 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
1869 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
1870 for ( ; paramIt != childParams.constEnd(); ++paramIt )
1872 const auto constValue = paramIt.value();
1873 for (
const QgsProcessingModelChildParameterSource &source : constValue )
1875 if ( source.source() == QgsProcessingModelChildParameterSource::ModelParameter
1876 && source.parameterName() == name )
1886bool QgsProcessingModelAlgorithm::otherParametersDependOnParameter(
const QString &name )
const
1888 const auto constMParameters = mParameters;
1891 if ( def->
name() == name )
1900QMap<QString, QgsProcessingModelParameter> QgsProcessingModelAlgorithm::parameterComponents()
const
1902 return mParameterComponents;
1905void QgsProcessingModelAlgorithm::dependentChildAlgorithmsRecursive(
const QString &childId, QSet<QString> &depends,
const QString &branch )
const
1907 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1908 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1910 if ( depends.contains( childIt->childId() ) )
1914 const QList< QgsProcessingModelChildDependency > constDependencies = childIt->dependencies();
1915 bool hasDependency =
false;
1916 for (
const QgsProcessingModelChildDependency &dep : constDependencies )
1918 if ( dep.childId == childId && ( branch.isEmpty() || dep.conditionalBranch == branch ) )
1920 hasDependency =
true;
1925 if ( hasDependency )
1927 depends.insert( childIt->childId() );
1928 dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
1933 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
1934 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
1935 for ( ; paramIt != childParams.constEnd(); ++paramIt )
1937 const auto constValue = paramIt.value();
1938 for (
const QgsProcessingModelChildParameterSource &source : constValue )
1940 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput
1941 && source.outputChildId() == childId )
1943 depends.insert( childIt->childId() );
1944 dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
1952QSet<QString> QgsProcessingModelAlgorithm::dependentChildAlgorithms(
const QString &childId,
const QString &conditionalBranch )
const
1954 QSet< QString > algs;
1958 algs.insert( childId );
1960 dependentChildAlgorithmsRecursive( childId, algs, conditionalBranch );
1963 algs.remove( childId );
1969void QgsProcessingModelAlgorithm::dependsOnChildAlgorithmsRecursive(
const QString &childId, QSet< QString > &depends )
const
1971 const QgsProcessingModelChildAlgorithm &alg = mChildAlgorithms.value( childId );
1974 const QList< QgsProcessingModelChildDependency > constDependencies = alg.dependencies();
1975 for (
const QgsProcessingModelChildDependency &val : constDependencies )
1977 if ( !depends.contains( val.childId ) )
1979 depends.insert( val.childId );
1980 dependsOnChildAlgorithmsRecursive( val.childId, depends );
1985 QMap<QString, QgsProcessingModelChildParameterSources> childParams = alg.parameterSources();
1986 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
1987 for ( ; paramIt != childParams.constEnd(); ++paramIt )
1989 const auto constValue = paramIt.value();
1990 for (
const QgsProcessingModelChildParameterSource &source : constValue )
1992 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput && !depends.contains( source.outputChildId() ) )
1994 depends.insert( source.outputChildId() );
1995 dependsOnChildAlgorithmsRecursive( source.outputChildId(), depends );
2001QSet< QString > QgsProcessingModelAlgorithm::dependsOnChildAlgorithms(
const QString &childId )
const
2003 QSet< QString > algs;
2007 algs.insert( childId );
2009 dependsOnChildAlgorithmsRecursive( childId, algs );
2012 algs.remove( childId );
2017QList<QgsProcessingModelChildDependency> QgsProcessingModelAlgorithm::availableDependenciesForChildAlgorithm(
const QString &childId )
const
2019 QSet< QString > dependent;
2020 if ( !childId.isEmpty() )
2022 dependent.unite( dependentChildAlgorithms( childId ) );
2023 dependent.insert( childId );
2026 QList<QgsProcessingModelChildDependency> res;
2027 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
2029 if ( !dependent.contains( it->childId() ) )
2032 bool hasBranches =
false;
2033 if ( it->algorithm() )
2041 QgsProcessingModelChildDependency alg;
2042 alg.childId = it->childId();
2043 alg.conditionalBranch = def->
name();
2051 QgsProcessingModelChildDependency alg;
2052 alg.childId = it->childId();
2060bool QgsProcessingModelAlgorithm::validateChildAlgorithm(
const QString &childId, QStringList &issues )
const
2063 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constFind( childId );
2064 if ( childIt != mChildAlgorithms.constEnd() )
2066 if ( !childIt->algorithm() )
2068 issues << QObject::tr(
"Algorithm is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
2077 if ( childIt->parameterSources().contains( def->
name() ) )
2080 const QList< QgsProcessingModelChildParameterSource > sources = childIt->parameterSources().value( def->
name() );
2081 for (
const QgsProcessingModelChildParameterSource &source : sources )
2083 switch ( source.source() )
2085 case QgsProcessingModelChildParameterSource::StaticValue:
2089 issues << QObject::tr(
"Value for <i>%1</i> is not acceptable for this parameter" ).arg( def->
name() );
2093 case QgsProcessingModelChildParameterSource::ModelParameter:
2094 if ( !parameterComponents().contains( source.parameterName() ) )
2097 issues << QObject::tr(
"Model input <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.parameterName(), def->
name() );
2101 case QgsProcessingModelChildParameterSource::ChildOutput:
2102 if ( !childAlgorithms().contains( source.outputChildId() ) )
2105 issues << QObject::tr(
"Child algorithm <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.outputChildId(), def->
name() );
2109 case QgsProcessingModelChildParameterSource::Expression:
2110 case QgsProcessingModelChildParameterSource::ExpressionText:
2111 case QgsProcessingModelChildParameterSource::ModelOutput:
2127 issues << QObject::tr(
"Parameter <i>%1</i> is mandatory" ).arg( def->
name() );
2136 issues << QObject::tr(
"Invalid child ID: <i>%1</i>" ).arg( childId );
2141bool QgsProcessingModelAlgorithm::canExecute( QString *errorMessage )
const
2143 reattachAlgorithms();
2144 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
2145 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
2147 if ( !childIt->algorithm() )
2151 *errorMessage = QObject::tr(
"The model you are trying to run contains an algorithm that is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
2159QString QgsProcessingModelAlgorithm::asPythonCommand(
const QVariantMap ¶meters,
QgsProcessingContext &context )
const
2161 if ( mSourceFile.isEmpty() )
2176 QgsProcessingModelAlgorithm *alg =
new QgsProcessingModelAlgorithm();
2177 alg->loadVariant( toVariant() );
2178 alg->setProvider( provider() );
2179 alg->setSourceFilePath( sourceFilePath() );
2183QString QgsProcessingModelAlgorithm::safeName(
const QString &name,
bool capitalize )
2185 QString n = name.toLower().trimmed();
2186 const thread_local QRegularExpression rx( QStringLiteral(
"[^\\sa-z_A-Z0-9]" ) );
2187 n.replace( rx, QString() );
2188 const thread_local QRegularExpression rx2( QStringLiteral(
"^\\d*" ) );
2189 n.replace( rx2, QString() );
2191 n = n.replace(
' ',
'_' );
2195QVariantMap QgsProcessingModelAlgorithm::variables()
const
2200void QgsProcessingModelAlgorithm::setVariables(
const QVariantMap &variables )
2202 mVariables = variables;
2205QVariantMap QgsProcessingModelAlgorithm::designerParameterValues()
const
2207 return mDesignerParameterValues;
@ 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.
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 SIP_HOLDGIL
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.
@ FlagNoThreading
Algorithm is not thread safe and cannot be run in a background thread, e.g. for algorithms which mani...
@ FlagCustomException
Algorithm raises custom exception notices, don't use the standard ones.
@ FlagSkipGenericModelLogging
When running as part of a model, the generic algorithm setup and results logging should be skipped.
@ FlagPruneModelBranchesBasedOnAlgorithmResults
Algorithm results will cause remaining model branches to be pruned based on the results of running th...
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.
Contains information about the context in which a processing algorithm is executed.
@ Verbose
Verbose logging.
QgsExpressionContext & expressionContext()
Returns the expression context.
void setExpressionContext(const QgsExpressionContext &context)
Sets the expression context.
LogLevel logLevel() const
Returns the logging level for algorithms to use when pushing feedback messages to users.
Base class for all parameter definitions which represent file or layer destinations,...
virtual QString generateTemporaryDestination() 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 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.
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.
A vector layer output for processing algorithms.
static QString typeName()
Returns the type name for the output class.
QgsProcessing::SourceType dataType() const
Returns the layer type for the output layer.
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.
@ FlagAdvanced
Parameter is an advanced parameter which should be hidden from users by default.
@ FlagOptional
Parameter is optional.
@ FlagHidden
Parameter is hidden and should not be shown to users.
virtual QgsProcessingParameterDefinition * clone() const =0
Creates a clone of the parameter definition.
virtual QString type() const =0
Unique parameter type name.
Flags flags() const
Returns any flags associated with the parameter.
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.
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.
static QString typeName()
Returns the type name for the parameter class.
DataType 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.
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 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)
Interprets a string as a map layer within the supplied context.
PythonOutputType
Available Python output types.
@ PythonQgsProcessingAlgorithmSubclass
Full Python QgsProcessingAlgorithm subclass.
SourceType
Data source types enum.
@ TypeVectorLine
Vector line layers.
@ TypeMapLayer
Any map layer type (raster, vector, mesh, point cloud, annotation or plugin layer)
@ TypeVectorPolygon
Vector polygon layers.
@ TypeVector
Tables (i.e. vector layers with or without geometry). When used for a sink this indicates the sink ha...
@ TypeVectorPoint
Vector point layers.
@ TypeVectorAnyGeometry
Any vector layer with geometry.
A store for object properties.
@ ExpressionBasedProperty
Expression based property (QgsExpressionBasedProperty)
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 yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom 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.
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.