35#include <QRegularExpression>
38#include "moc_qgsprocessingmodelalgorithm.cpp"
42QgsProcessingModelAlgorithm::QgsProcessingModelAlgorithm(
const QString &name,
const QString &group,
const QString &groupId )
43 : mModelName( name.isEmpty() ? QObject::tr(
"model" ) : name )
44 , mModelGroup( group )
45 , mModelGroupId( groupId )
48void QgsProcessingModelAlgorithm::initAlgorithm(
const QVariantMap & )
57 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
58 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
69QString QgsProcessingModelAlgorithm::name()
const
74QString QgsProcessingModelAlgorithm::displayName()
const
79QString QgsProcessingModelAlgorithm::group()
const
84QString QgsProcessingModelAlgorithm::groupId()
const
89QIcon QgsProcessingModelAlgorithm::icon()
const
94QString QgsProcessingModelAlgorithm::svgIconPath()
const
99QString QgsProcessingModelAlgorithm::shortHelpString()
const
101 if ( mHelpContent.empty() )
107QString QgsProcessingModelAlgorithm::shortDescription()
const
109 return mHelpContent.value( QStringLiteral(
"SHORT_DESCRIPTION" ) ).toString();
112QString QgsProcessingModelAlgorithm::helpUrl()
const
114 return mHelpContent.value( QStringLiteral(
"HELP_URL" ) ).toString();
117QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm(
const QgsProcessingModelChildAlgorithm &child,
const QVariantMap &modelParameters,
const QVariantMap &results,
const QgsExpressionContext &expressionContext, QString &error,
const QgsProcessingContext *context )
const
122 const QgsProcessingModelChildParameterSources paramSources = child.parameterSources().value( def->name() );
124 QString expressionText;
125 QVariantList paramParts;
126 for (
const QgsProcessingModelChildParameterSource &source : paramSources )
128 switch ( source.source() )
131 paramParts << source.staticValue();
135 paramParts << modelParameters.value( source.parameterName() );
140 QVariantMap linkedChildResults = results.value( source.outputChildId() ).toMap();
141 paramParts << linkedChildResults.value( source.outputName() );
148 paramParts << exp.evaluate( &expressionContext );
149 if ( exp.hasEvalError() )
151 error = QObject::tr(
"Could not evaluate expression for parameter %1 for %2: %3" ).arg( def->name(), child.description(), exp.evalErrorString() );
166 if ( ! expressionText.isEmpty() )
168 return expressionText;
170 else if ( paramParts.count() == 1 )
171 return paramParts.at( 0 );
177 QVariantMap childParams;
178 const QList< const QgsProcessingParameterDefinition * > childParameterDefinitions = child.algorithm()->parameterDefinitions();
181 if ( !def->isDestination() )
183 if ( !child.parameterSources().contains( def->name() ) )
186 const QVariant value = evaluateSources( def );
187 childParams.insert( def->name(), value );
194 bool isFinalOutput =
false;
195 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
196 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
197 for ( ; outputIt != outputs.constEnd(); ++outputIt )
199 if ( outputIt->childOutputName() == destParam->
name() )
201 QString paramName = child.childId() +
':' + outputIt.key();
202 bool foundParam =
false;
206 if ( modelParameters.contains( paramName ) )
208 value = modelParameters.value( paramName );
217 if ( modelParameters.contains( modelParam->name() ) )
219 value = modelParameters.value( modelParam->name() );
227 if ( value.userType() == qMetaTypeId<QgsProcessingOutputLayerDefinition>() )
232 value = QVariant::fromValue( fromVar );
235 childParams.insert( destParam->
name(), value );
237 isFinalOutput =
true;
242 bool hasExplicitDefinition =
false;
243 if ( !isFinalOutput && child.parameterSources().contains( def->name() ) )
246 const QVariant value = evaluateSources( def );
247 if ( value.isValid() )
249 childParams.insert( def->name(), value );
250 hasExplicitDefinition =
true;
254 if ( !isFinalOutput && !hasExplicitDefinition )
259 bool required =
true;
262 required = childOutputIsRequired( child.childId(), destParam->
name() );
274const QgsProcessingParameterDefinition *QgsProcessingModelAlgorithm::modelParameterFromChildIdAndOutputName(
const QString &childId,
const QString &childOutputName )
const
278 if ( !definition->isDestination() )
281 const QString modelChildId = definition->metadata().value( QStringLiteral(
"_modelChildId" ) ).toString();
282 const QString modelOutputName = definition->metadata().value( QStringLiteral(
"_modelChildOutputName" ) ).toString();
284 if ( modelChildId == childId && modelOutputName == childOutputName )
290bool QgsProcessingModelAlgorithm::childOutputIsRequired(
const QString &childId,
const QString &outputName )
const
293 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
294 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
296 if ( childIt->childId() == childId || !childIt->isActive() )
300 QMap<QString, QgsProcessingModelChildParameterSources> candidateChildParams = childIt->parameterSources();
301 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator childParamIt = candidateChildParams.constBegin();
302 for ( ; childParamIt != candidateChildParams.constEnd(); ++childParamIt )
304 const auto constValue = childParamIt.value();
305 for (
const QgsProcessingModelChildParameterSource &source : constValue )
308 && source.outputChildId() == childId
309 && source.outputName() == outputName )
321 QSet< QString > toExecute;
322 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
323 QSet< QString > broken;
325 const bool useSubsetOfChildren = !childSubset.empty();
326 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
328 if ( childIt->isActive() && ( !useSubsetOfChildren || childSubset.contains( childIt->childId() ) ) )
330 if ( childIt->algorithm() )
331 toExecute.insert( childIt->childId() );
333 broken.insert( childIt->childId() );
337 if ( !broken.empty() )
338 throw QgsProcessingException( QCoreApplication::translate(
"QgsProcessingModelAlgorithm",
"Cannot run model, the following algorithms are not available on this system: %1" ).arg(
qgsSetJoin( broken, QLatin1String(
", " ) ) ) );
340 QElapsedTimer totalTime;
349 QMap< QString, QgsProcessingModelChildAlgorithmResult > &contextChildResults = context.
modelResult().
childResults();
355 childInputs = config->initialChildInputs();
356 childResults = config->initialChildOutputs();
357 executed = config->previouslyExecutedChildAlgorithms();
361 if ( useSubsetOfChildren )
363 executed.subtract( childSubset );
366 QVariantMap finalResults;
368 bool executedAlg =
true;
369 int previousHtmlLogLength = feedback ? feedback->
htmlLog().length() : 0;
370 int countExecuted = 0;
371 while ( executedAlg && countExecuted < toExecute.count() )
374 for (
const QString &childId : std::as_const( toExecute ) )
379 if ( executed.contains( childId ) )
384 bool canExecute =
true;
385 const QSet< QString > dependencies = dependsOnChildAlgorithms( childId );
386 for (
const QString &dependency : dependencies )
388 if ( !executed.contains( dependency ) )
402 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
403 std::unique_ptr< QgsProcessingAlgorithm > childAlg( child.algorithm()->create( child.configuration() ) );
405 bool skipGenericLogging =
true;
410 skipGenericLogging =
true;
420 skipGenericLogging =
false;
424 if ( feedback && !skipGenericLogging )
425 feedback->
pushDebugInfo( QObject::tr(
"Prepare algorithm: %1" ).arg( childId ) );
429 << createExpressionContextScopeForChildAlgorithm( childId, context, parameters, childResults );
433 QVariantMap childParams = parametersForChildAlgorithm( child, parameters, childResults, expContext, error, &context );
434 if ( !error.isEmpty() )
437 if ( feedback && !skipGenericLogging )
438 feedback->
setProgressText( QObject::tr(
"Running %1 [%2/%3]" ).arg( child.description() ).arg( executed.count() + 1 ).arg( toExecute.count() ) );
443 childInputs.insert( childId, thisChildParams );
444 childResult.
setInputs( thisChildParams );
447 for (
auto childParamIt = childParams.constBegin(); childParamIt != childParams.constEnd(); ++childParamIt )
449 params << QStringLiteral(
"%1: %2" ).arg( childParamIt.key(),
450 child.algorithm()->parameterDefinition( childParamIt.key() )->valueAsPythonString( childParamIt.value(), context ) );
453 if ( feedback && !skipGenericLogging )
455 feedback->
pushInfo( QObject::tr(
"Input Parameters:" ) );
456 feedback->
pushCommandInfo( QStringLiteral(
"{ %1 }" ).arg( params.join( QLatin1String(
", " ) ) ) );
459 QElapsedTimer childTime;
462 QVariantMap outerScopeChildInputs = childInputs;
463 QVariantMap outerScopePrevChildResults = childResults;
464 QSet< QString > outerScopeExecuted = executed;
465 QMap< QString, QgsProcessingModelChildAlgorithmResult > outerScopeContextChildResult = contextChildResults;
466 if (
dynamic_cast< QgsProcessingModelAlgorithm *
>( childAlg.get() ) )
470 childResults.clear();
472 contextChildResults.clear();
477 QThread *modelThread = QThread::currentThread();
479 auto prepareOnMainThread = [modelThread, &ok, &childAlg, &childParams, &context, &modelFeedback]
481 Q_ASSERT_X( QThread::currentThread() == qApp->thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"childAlg->prepare() must be run on the main thread" );
482 ok = childAlg->prepare( childParams, context, &modelFeedback );
483 context.pushToThread( modelThread );
487 if ( modelThread == qApp->thread() )
488 ok = childAlg->prepare( childParams, context, &modelFeedback );
491 context.pushToThread( qApp->thread() );
493#ifndef __clang_analyzer__
494 QMetaObject::invokeMethod( qApp, prepareOnMainThread, Qt::BlockingQueuedConnection );
498 Q_ASSERT_X( QThread::currentThread() == context.thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"context was not transferred back to model thread" );
508 bool runResult =
false;
514 auto runOnMainThread = [modelThread, &context, &modelFeedback, &results, &childAlg, &childParams]
516 Q_ASSERT_X( QThread::currentThread() == qApp->thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"childAlg->runPrepared() must be run on the main thread" );
517 results = childAlg->runPrepared( childParams, context, &modelFeedback );
518 context.pushToThread( modelThread );
521 if ( feedback && !skipGenericLogging && modelThread != qApp->thread() )
522 feedback->
pushWarning( QObject::tr(
"Algorithm “%1” cannot be run in a background thread, switching to main thread for this step" ).arg( childAlg->displayName() ) );
524 context.pushToThread( qApp->thread() );
526#ifndef __clang_analyzer__
527 QMetaObject::invokeMethod( qApp, runOnMainThread, Qt::BlockingQueuedConnection );
533 results = childAlg->runPrepared( childParams, context, &modelFeedback );
544 Q_ASSERT_X( QThread::currentThread() == context.thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"context was not transferred back to model thread" );
547 auto postProcessOnMainThread = [modelThread, &ppRes, &childAlg, &context, &modelFeedback, runResult]
549 Q_ASSERT_X( QThread::currentThread() == qApp->thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"childAlg->postProcess() must be run on the main thread" );
550 ppRes = childAlg->postProcess( context, &modelFeedback, runResult );
551 context.pushToThread( modelThread );
555 if ( modelThread == qApp->thread() )
556 ppRes = childAlg->postProcess( context, &modelFeedback, runResult );
559 context.pushToThread( qApp->thread() );
561#ifndef __clang_analyzer__
562 QMetaObject::invokeMethod( qApp, postProcessOnMainThread, Qt::BlockingQueuedConnection );
566 Q_ASSERT_X( QThread::currentThread() == context.thread(),
"QgsProcessingModelAlgorithm::processAlgorithm",
"context was not transferred back to model thread" );
568 if ( !ppRes.isEmpty() )
571 if (
dynamic_cast< QgsProcessingModelAlgorithm *
>( childAlg.get() ) )
573 childInputs = outerScopeChildInputs;
574 childResults = outerScopePrevChildResults;
575 executed = outerScopeExecuted;
576 contextChildResults = outerScopeContextChildResult;
579 childResults.insert( childId, results );
584 if ( feedback && !skipGenericLogging )
587 QStringList formattedOutputs;
588 for (
auto displayOutputIt = displayOutputs.constBegin(); displayOutputIt != displayOutputs.constEnd(); ++displayOutputIt )
590 formattedOutputs << QStringLiteral(
"%1: %2" ).arg( displayOutputIt.key(),
593 feedback->
pushInfo( QObject::tr(
"Results:" ) );
594 feedback->
pushCommandInfo( QStringLiteral(
"{ %1 }" ).arg( formattedOutputs.join( QLatin1String(
", " ) ) ) );
599 const QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
600 for (
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
602 const int outputSortKey = mOutputOrder.indexOf( QStringLiteral(
"%1:%2" ).arg( childId, outputIt->childOutputName() ) );
603 switch ( mInternalVersion )
605 case QgsProcessingModelAlgorithm::InternalVersion::Version1:
606 finalResults.insert( childId +
':' + outputIt->name(), results.value( outputIt->childOutputName() ) );
608 case QgsProcessingModelAlgorithm::InternalVersion::Version2:
611 finalResults.insert( modelParam->name(), results.value( outputIt->childOutputName() ) );
616 const QString outputLayer = results.value( outputIt->childOutputName() ).toString();
617 if ( !outputLayer.isEmpty() && context.willLoadLayerOnCompletion( outputLayer ) )
621 if ( outputSortKey > 0 )
626 executed.insert( childId );
628 std::function< void(
const QString &,
const QString & )> pruneAlgorithmBranchRecursive;
629 pruneAlgorithmBranchRecursive = [&](
const QString & id,
const QString &branch = QString() )
631 const QSet<QString> toPrune = dependentChildAlgorithms(
id, branch );
632 for (
const QString &targetId : toPrune )
634 if ( executed.contains( targetId ) )
637 executed.insert( targetId );
638 pruneAlgorithmBranchRecursive( targetId, branch );
648 pruneAlgorithmBranchRecursive( childId, outputDef->name() );
656 for (
const QString &candidateId : std::as_const( toExecute ) )
658 if ( executed.contains( candidateId ) )
663 const QgsProcessingModelChildAlgorithm &candidate = mChildAlgorithms[ candidateId ];
664 const QMap<QString, QgsProcessingModelChildParameterSources> candidateParams = candidate.parameterSources();
665 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = candidateParams.constBegin();
667 for ( ; paramIt != candidateParams.constEnd(); ++paramIt )
669 for (
const QgsProcessingModelChildParameterSource &source : paramIt.value() )
674 if ( !results.contains( source.outputName() ) )
679 executed.insert( candidateId );
681 pruneAlgorithmBranchRecursive( candidateId, QString() );
692 childAlg.reset(
nullptr );
694 modelFeedback.setCurrentStep( countExecuted );
695 if ( feedback && !skipGenericLogging )
697 feedback->
pushInfo( QObject::tr(
"OK. Execution took %1 s (%n output(s)).",
nullptr, results.count() ).arg( childTime.elapsed() / 1000.0 ) );
702 const QString thisAlgorithmHtmlLog = feedback ? feedback->
htmlLog().mid( previousHtmlLogLength ) : QString();
703 previousHtmlLogLength = feedback ? feedback->
htmlLog().length() : 0;
707 const QString formattedException = QStringLiteral(
"<span style=\"color:red\">%1</span><br/>" ).arg( error.toHtmlEscaped() ).replace(
'\n', QLatin1String(
"<br>" ) );
708 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>" ) );
710 childResult.
setHtmlLog( thisAlgorithmHtmlLog + formattedException + formattedRunTime );
711 context.modelResult().childResults().insert( childId, childResult );
717 childResult.
setHtmlLog( thisAlgorithmHtmlLog );
718 context.modelResult().childResults().insert( childId, childResult );
726 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 ) );
728 mResults = finalResults;
729 mResults.insert( QStringLiteral(
"CHILD_RESULTS" ), childResults );
730 mResults.insert( QStringLiteral(
"CHILD_INPUTS" ), childInputs );
734QString QgsProcessingModelAlgorithm::sourceFilePath()
const
739void QgsProcessingModelAlgorithm::setSourceFilePath(
const QString &sourceFile )
741 mSourceFile = sourceFile;
744bool QgsProcessingModelAlgorithm::modelNameMatchesFilePath()
const
746 if ( mSourceFile.isEmpty() )
749 const QFileInfo fi( mSourceFile );
750 return fi.completeBaseName().compare( mModelName, Qt::CaseInsensitive ) == 0;
755 QStringList fileDocString;
756 fileDocString << QStringLiteral(
"\"\"\"" );
757 fileDocString << QStringLiteral(
"Model exported as python." );
758 fileDocString << QStringLiteral(
"Name : %1" ).arg( displayName() );
759 fileDocString << QStringLiteral(
"Group : %1" ).arg( group() );
760 fileDocString << QStringLiteral(
"With QGIS : %1" ).arg(
Qgis::versionInt() );
761 fileDocString << QStringLiteral(
"\"\"\"" );
762 fileDocString << QString();
765 QString indent = QString(
' ' ).repeated( indentSize );
766 QString currentIndent;
768 QMap< QString, QString> friendlyChildNames;
769 QMap< QString, QString> friendlyOutputNames;
770 auto uniqueSafeName = [](
const QString & name,
bool capitalize,
const QMap< QString, QString > &friendlyNames )->QString
772 const QString base = safeName( name, capitalize );
773 QString candidate = base;
776 while ( std::find( friendlyNames.cbegin(), friendlyNames.cend(), candidate ) != friendlyNames.cend() )
779 candidate = QStringLiteral(
"%1_%2" ).arg( base ).arg( i );
784 const QString algorithmClassName = safeName( name(),
true );
786 QSet< QString > toExecute;
787 for (
auto childIt = mChildAlgorithms.constBegin(); childIt != mChildAlgorithms.constEnd(); ++childIt )
789 if ( childIt->isActive() && childIt->algorithm() )
791 toExecute.insert( childIt->childId() );
792 friendlyChildNames.insert( childIt->childId(), uniqueSafeName( childIt->description().isEmpty() ? childIt->childId() : childIt->description(), !childIt->description().isEmpty(), friendlyChildNames ) );
795 const int totalSteps = toExecute.count();
797 QStringList importLines;
798 switch ( outputType )
803 const auto params = parameterDefinitions();
804 importLines.reserve( params.count() + 6 );
805 importLines << QStringLiteral(
"from typing import Any, Optional" );
806 importLines << QString();
807 importLines << QStringLiteral(
"from qgis.core import QgsProcessing" );
808 importLines << QStringLiteral(
"from qgis.core import QgsProcessingAlgorithm" );
809 importLines << QStringLiteral(
"from qgis.core import QgsProcessingContext" );
810 importLines << QStringLiteral(
"from qgis.core import QgsProcessingFeedback, QgsProcessingMultiStepFeedback" );
812 bool hasAdvancedParams =
false;
816 hasAdvancedParams =
true;
820 const QString importString = type->pythonImportString();
821 if ( !importString.isEmpty() && !importLines.contains( importString ) )
822 importLines << importString;
826 if ( hasAdvancedParams )
827 importLines << QStringLiteral(
"from qgis.core import QgsProcessingParameterDefinition" );
829 lines << QStringLiteral(
"from qgis import processing" );
830 lines << QString() << QString();
832 lines << QStringLiteral(
"class %1(QgsProcessingAlgorithm):" ).arg( algorithmClassName );
836 lines << indent + QStringLiteral(
"def initAlgorithm(self, config: Optional[dict[str, Any]] = None):" );
837 if ( params.empty() )
839 lines << indent + indent + QStringLiteral(
"pass" );
843 lines.reserve( lines.size() + params.size() );
846 std::unique_ptr< QgsProcessingParameterDefinition > defClone( def->clone() );
848 if ( defClone->isDestination() )
850 const QString uniqueChildName = defClone->metadata().value( QStringLiteral(
"_modelChildId" ) ).toString() +
':' + defClone->metadata().value( QStringLiteral(
"_modelChildOutputName" ) ).toString();
851 const QString friendlyName = !defClone->description().isEmpty() ? uniqueSafeName( defClone->description(),
true, friendlyOutputNames ) : defClone->name();
852 friendlyOutputNames.insert( uniqueChildName, friendlyName );
853 defClone->setName( friendlyName );
857 if ( !mParameterComponents.value( defClone->name() ).comment()->description().isEmpty() )
859 const QStringList parts = mParameterComponents.value( defClone->name() ).comment()->description().split( QStringLiteral(
"\n" ) );
860 for (
const QString &part : parts )
862 lines << indent + indent + QStringLiteral(
"# %1" ).arg( part );
869 lines << indent + indent + QStringLiteral(
"param = %1" ).arg( defClone->asPythonString() );
870 lines << indent + indent + QStringLiteral(
"param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)" );
871 lines << indent + indent + QStringLiteral(
"self.addParameter(param)" );
875 lines << indent + indent + QStringLiteral(
"self.addParameter(%1)" ).arg( defClone->asPythonString() );
881 lines << indent + QStringLiteral(
"def processAlgorithm(self, parameters: dict[str, Any], context: QgsProcessingContext, model_feedback: QgsProcessingFeedback) -> dict[str, Any]:" );
882 currentIndent = indent + indent;
884 lines << currentIndent + QStringLiteral(
"# Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the" );
885 lines << currentIndent + QStringLiteral(
"# overall progress through the model" );
886 lines << currentIndent + QStringLiteral(
"feedback = QgsProcessingMultiStepFeedback(%1, model_feedback)" ).arg( totalSteps );
894 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
895 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
897 QString name = paramIt.value().parameterName();
898 if ( parameterDefinition( name ) )
901 params.insert( name, parameterDefinition( name )->valueAsPythonString( parameterDefinition( name )->defaultValue(), context ) );
905 if ( !params.isEmpty() )
907 lines << QStringLiteral(
"parameters = {" );
908 for (
auto it = params.constBegin(); it != params.constEnd(); ++it )
910 lines << QStringLiteral(
" '%1':%2," ).arg( it.key(), it.value() );
912 lines << QStringLiteral(
"}" )
916 lines << QStringLiteral(
"context = QgsProcessingContext()" )
917 << QStringLiteral(
"context.setProject(QgsProject.instance())" )
918 << QStringLiteral(
"feedback = QgsProcessingFeedback()" )
927 lines << currentIndent + QStringLiteral(
"results = {}" );
928 lines << currentIndent + QStringLiteral(
"outputs = {}" );
931 QSet< QString > executed;
932 bool executedAlg =
true;
934 while ( executedAlg && executed.count() < toExecute.count() )
937 const auto constToExecute = toExecute;
938 for (
const QString &childId : constToExecute )
940 if ( executed.contains( childId ) )
943 bool canExecute =
true;
944 const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms( childId );
945 for (
const QString &dependency : constDependsOnChildAlgorithms )
947 if ( !executed.contains( dependency ) )
959 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
966 if ( def->isDestination() )
971 bool isFinalOutput =
false;
972 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
973 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
974 for ( ; outputIt != outputs.constEnd(); ++outputIt )
976 if ( outputIt->childOutputName() == destParam->
name() )
978 QString paramName = child.childId() +
':' + outputIt.key();
979 paramName = friendlyOutputNames.value( paramName, paramName );
980 childParams.insert( destParam->
name(), QStringLiteral(
"parameters['%1']" ).arg( paramName ) );
981 isFinalOutput =
true;
986 if ( !isFinalOutput )
991 bool required =
true;
994 required = childOutputIsRequired( child.childId(), destParam->
name() );
1000 childParams.insert( destParam->
name(), QStringLiteral(
"QgsProcessing.TEMPORARY_OUTPUT" ) );
1006 lines << child.asPythonCode( outputType, childParams, currentIndent.size(), indentSize, friendlyChildNames, friendlyOutputNames );
1008 if ( currentStep < totalSteps )
1011 lines << currentIndent + QStringLiteral(
"feedback.setCurrentStep(%1)" ).arg( currentStep );
1012 lines << currentIndent + QStringLiteral(
"if feedback.isCanceled():" );
1013 lines << currentIndent + indent + QStringLiteral(
"return {}" );
1016 executed.insert( childId );
1020 switch ( outputType )
1023 lines << currentIndent + QStringLiteral(
"return results" );
1027 lines << indent + QStringLiteral(
"def name(self) -> str:" );
1028 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelName );
1030 lines << indent + QStringLiteral(
"def displayName(self) -> str:" );
1031 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelName );
1035 lines << indent + QStringLiteral(
"def group(self) -> str:" );
1036 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelGroup );
1038 lines << indent + QStringLiteral(
"def groupId(self) -> str:" );
1039 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelGroupId );
1043 if ( !shortHelpString().isEmpty() )
1045 lines << indent + QStringLiteral(
"def shortHelpString(self) -> str:" );
1046 lines << indent + indent + QStringLiteral(
"return \"\"\"%1\"\"\"" ).arg( shortHelpString() );
1049 if ( !helpUrl().isEmpty() )
1051 lines << indent + QStringLiteral(
"def helpUrl(self) -> str:" );
1052 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( helpUrl() );
1057 lines << indent + QStringLiteral(
"def createInstance(self):" );
1058 lines << indent + indent + QStringLiteral(
"return self.__class__()" );
1061 static QMap< QString, QString > sAdditionalImports
1063 { QStringLiteral(
"QgsCoordinateReferenceSystem" ), QStringLiteral(
"from qgis.core import QgsCoordinateReferenceSystem" ) },
1064 { QStringLiteral(
"QgsExpression" ), QStringLiteral(
"from qgis.core import QgsExpression" ) },
1065 { QStringLiteral(
"QgsRectangle" ), QStringLiteral(
"from qgis.core import QgsRectangle" ) },
1066 { QStringLiteral(
"QgsReferencedRectangle" ), QStringLiteral(
"from qgis.core import QgsReferencedRectangle" ) },
1067 { QStringLiteral(
"QgsPoint" ), QStringLiteral(
"from qgis.core import QgsPoint" ) },
1068 { QStringLiteral(
"QgsReferencedPoint" ), QStringLiteral(
"from qgis.core import QgsReferencedPoint" ) },
1069 { QStringLiteral(
"QgsProperty" ), QStringLiteral(
"from qgis.core import QgsProperty" ) },
1070 { QStringLiteral(
"QgsRasterLayer" ), QStringLiteral(
"from qgis.core import QgsRasterLayer" ) },
1071 { QStringLiteral(
"QgsMeshLayer" ), QStringLiteral(
"from qgis.core import QgsMeshLayer" ) },
1072 { QStringLiteral(
"QgsVectorLayer" ), QStringLiteral(
"from qgis.core import QgsVectorLayer" ) },
1073 { QStringLiteral(
"QgsMapLayer" ), QStringLiteral(
"from qgis.core import QgsMapLayer" ) },
1074 { QStringLiteral(
"QgsProcessingFeatureSourceDefinition" ), QStringLiteral(
"from qgis.core import QgsProcessingFeatureSourceDefinition" ) },
1075 { QStringLiteral(
"QgsPointXY" ), QStringLiteral(
"from qgis.core import QgsPointXY" ) },
1076 { QStringLiteral(
"QgsReferencedPointXY" ), QStringLiteral(
"from qgis.core import QgsReferencedPointXY" ) },
1077 { QStringLiteral(
"QgsGeometry" ), QStringLiteral(
"from qgis.core import QgsGeometry" ) },
1078 { QStringLiteral(
"QgsProcessingOutputLayerDefinition" ), QStringLiteral(
"from qgis.core import QgsProcessingOutputLayerDefinition" ) },
1079 { QStringLiteral(
"QColor" ), QStringLiteral(
"from qgis.PyQt.QtGui import QColor" ) },
1080 { QStringLiteral(
"QDateTime" ), QStringLiteral(
"from qgis.PyQt.QtCore import QDateTime" ) },
1081 { QStringLiteral(
"QDate" ), QStringLiteral(
"from qgis.PyQt.QtCore import QDate" ) },
1082 { QStringLiteral(
"QTime" ), QStringLiteral(
"from qgis.PyQt.QtCore import QTime" ) },
1085 for (
auto it = sAdditionalImports.constBegin(); it != sAdditionalImports.constEnd(); ++it )
1087 if ( importLines.contains( it.value() ) )
1094 for (
const QString &line : std::as_const( lines ) )
1096 if ( line.contains( it.key() ) )
1104 importLines << it.value();
1108 lines = fileDocString + importLines + lines;
1117QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> QgsProcessingModelAlgorithm::variablesForChildAlgorithm(
const QString &childId,
QgsProcessingContext *context,
const QVariantMap &modelParameters,
const QVariantMap &results )
const
1119 QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables;
1121 auto safeName = [](
const QString & name )->QString
1124 const thread_local QRegularExpression safeNameRe( QStringLiteral(
"[\\s'\"\\(\\):\\.]" ) );
1125 return s.replace( safeNameRe, QStringLiteral(
"_" ) );
1162 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
1166 QString description;
1167 switch ( source.source() )
1171 name = source.parameterName();
1172 value = modelParameters.value( source.parameterName() );
1173 description = parameterDefinition( source.parameterName() )->description();
1178 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
1179 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
1180 source.outputChildId() : child.description(), source.outputName() );
1183 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
1184 child.description() );
1186 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
1196 variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
1200 sources = availableSourcesForChild( childId, QStringList()
1207 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
1211 QString description;
1213 switch ( source.source() )
1217 name = source.parameterName();
1218 value = modelParameters.value( source.parameterName() );
1219 description = parameterDefinition( source.parameterName() )->description();
1224 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
1225 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
1226 source.outputChildId() : child.description(), source.outputName() );
1227 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
1230 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
1231 child.description() );
1244 if ( value.userType() == qMetaTypeId<QgsProcessingOutputLayerDefinition>() )
1247 value = fromVar.
sink;
1248 if ( value.userType() == qMetaTypeId<QgsProperty>() && context )
1256 layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( value ) );
1261 variables.insert( safeName( name ), VariableDefinition( layer ? QVariant::fromValue(
QgsWeakMapLayerPointer( layer ) ) : QVariant(), source, description ) );
1262 variables.insert( safeName( QStringLiteral(
"%1_minx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMinimum() : QVariant(), source, QObject::tr(
"Minimum X of %1" ).arg( description ) ) );
1263 variables.insert( safeName( QStringLiteral(
"%1_miny" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMinimum() : QVariant(), source, QObject::tr(
"Minimum Y of %1" ).arg( description ) ) );
1264 variables.insert( safeName( QStringLiteral(
"%1_maxx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMaximum() : QVariant(), source, QObject::tr(
"Maximum X of %1" ).arg( description ) ) );
1265 variables.insert( safeName( QStringLiteral(
"%1_maxy" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMaximum() : QVariant(), source, QObject::tr(
"Maximum Y of %1" ).arg( description ) ) );
1268 sources = availableSourcesForChild( childId, QStringList()
1270 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
1274 QString description;
1276 switch ( source.source() )
1280 name = source.parameterName();
1281 value = modelParameters.value( source.parameterName() );
1282 description = parameterDefinition( source.parameterName() )->description();
1287 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
1288 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
1289 source.outputChildId() : child.description(), source.outputName() );
1290 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
1293 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
1294 child.description() );
1308 if ( value.userType() == qMetaTypeId<QgsProcessingFeatureSourceDefinition>() )
1313 else if ( value.userType() == qMetaTypeId<QgsProcessingOutputLayerDefinition>() )
1316 value = fromVar.
sink;
1317 if ( context && value.userType() == qMetaTypeId<QgsProperty>() )
1322 if (
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( value ) ) )
1324 featureSource = layer;
1326 if ( context && !featureSource )
1332 variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
1333 variables.insert( safeName( QStringLiteral(
"%1_minx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMinimum() : QVariant(), source, QObject::tr(
"Minimum X of %1" ).arg( description ) ) );
1334 variables.insert( safeName( QStringLiteral(
"%1_miny" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMinimum() : QVariant(), source, QObject::tr(
"Minimum Y of %1" ).arg( description ) ) );
1335 variables.insert( safeName( QStringLiteral(
"%1_maxx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMaximum() : QVariant(), source, QObject::tr(
"Maximum X of %1" ).arg( description ) ) );
1336 variables.insert( safeName( QStringLiteral(
"%1_maxy" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMaximum() : QVariant(), source, QObject::tr(
"Maximum Y of %1" ).arg( description ) ) );
1342QgsExpressionContextScope *QgsProcessingModelAlgorithm::createExpressionContextScopeForChildAlgorithm(
const QString &childId,
QgsProcessingContext &context,
const QVariantMap &modelParameters,
const QVariantMap &results )
const
1344 auto scope = std::make_unique<QgsExpressionContextScope>( QStringLiteral(
"algorithm_inputs" ) );
1345 QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = variablesForChildAlgorithm( childId, &context, modelParameters, results );
1346 QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition>::const_iterator varIt = variables.constBegin();
1347 for ( ; varIt != variables.constEnd(); ++varIt )
1351 return scope.release();
1354QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild(
const QString &childId,
const QgsProcessingParameterDefinition *param )
const
1358 return QgsProcessingModelChildParameterSources();
1362QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild(
const QString &childId,
const QStringList ¶meterTypes,
const QStringList &outputTypes,
const QList<int> &dataTypes )
const
1364 QgsProcessingModelChildParameterSources sources;
1367 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
1368 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
1374 if ( parameterTypes.contains( def->
type() ) )
1376 if ( !dataTypes.isEmpty() )
1392 bool ok = sourceDef->
dataTypes().isEmpty();
1393 const auto constDataTypes = sourceDef->
dataTypes();
1394 for (
int type : constDataTypes )
1409 sources << QgsProcessingModelChildParameterSource::fromModelParameter( paramIt->parameterName() );
1413 QSet< QString > dependents;
1414 if ( !childId.isEmpty() )
1416 dependents = dependentChildAlgorithms( childId );
1417 dependents << childId;
1420 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1421 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1423 if ( dependents.contains( childIt->childId() ) )
1433 if ( outputTypes.contains( out->type() ) )
1435 if ( !dataTypes.isEmpty() )
1441 if ( !vectorOutputIsCompatibleType( dataTypes, vectorOut->
dataType() ) )
1448 sources << QgsProcessingModelChildParameterSource::fromChildOutput( childIt->childId(), out->name() );
1456QVariantMap QgsProcessingModelAlgorithm::helpContent()
const
1458 return mHelpContent;
1461void QgsProcessingModelAlgorithm::setHelpContent(
const QVariantMap &helpContent )
1463 mHelpContent = helpContent;
1466void QgsProcessingModelAlgorithm::setName(
const QString &name )
1471void QgsProcessingModelAlgorithm::setGroup(
const QString &group )
1473 mModelGroup = group;
1476bool QgsProcessingModelAlgorithm::validate( QStringList &issues )
const
1481 if ( mChildAlgorithms.empty() )
1484 issues << QObject::tr(
"Model does not contain any algorithms" );
1487 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
1489 QStringList childIssues;
1490 res = validateChildAlgorithm( it->childId(), childIssues ) && res;
1492 for (
const QString &issue : std::as_const( childIssues ) )
1494 issues << QStringLiteral(
"<b>%1</b>: %2" ).arg( it->description(), issue );
1500QMap<QString, QgsProcessingModelChildAlgorithm> QgsProcessingModelAlgorithm::childAlgorithms()
const
1502 return mChildAlgorithms;
1505void QgsProcessingModelAlgorithm::setParameterComponents(
const QMap<QString, QgsProcessingModelParameter> ¶meterComponents )
1507 mParameterComponents = parameterComponents;
1510void QgsProcessingModelAlgorithm::setParameterComponent(
const QgsProcessingModelParameter &component )
1512 mParameterComponents.insert( component.parameterName(), component );
1515QgsProcessingModelParameter &QgsProcessingModelAlgorithm::parameterComponent(
const QString &name )
1517 if ( !mParameterComponents.contains( name ) )
1519 QgsProcessingModelParameter &component = mParameterComponents[ name ];
1520 component.setParameterName( name );
1523 return mParameterComponents[ name ];
1526QList< QgsProcessingModelParameter > QgsProcessingModelAlgorithm::orderedParameters()
const
1528 QList< QgsProcessingModelParameter > res;
1529 QSet< QString > found;
1530 for (
const QString ¶meter : mParameterOrder )
1532 if ( mParameterComponents.contains( parameter ) )
1534 res << mParameterComponents.value( parameter );
1540 for (
auto it = mParameterComponents.constBegin(); it != mParameterComponents.constEnd(); ++it )
1542 if ( !found.contains( it.key() ) )
1550void QgsProcessingModelAlgorithm::setParameterOrder(
const QStringList &order )
1552 mParameterOrder = order;
1555QList<QgsProcessingModelOutput> QgsProcessingModelAlgorithm::orderedOutputs()
const
1557 QList< QgsProcessingModelOutput > res;
1558 QSet< QString > found;
1560 for (
const QString &output : mOutputOrder )
1562 bool foundOutput =
false;
1563 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
1565 const QMap<QString, QgsProcessingModelOutput> outputs = it.value().modelOutputs();
1566 for (
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
1568 if ( output == QStringLiteral(
"%1:%2" ).arg( outputIt->childId(), outputIt->childOutputName() ) )
1570 res << outputIt.value();
1572 found.insert( QStringLiteral(
"%1:%2" ).arg( outputIt->childId(), outputIt->childOutputName() ) );
1581 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
1583 const QMap<QString, QgsProcessingModelOutput> outputs = it.value().modelOutputs();
1584 for (
auto outputIt = outputs.constBegin(); outputIt != outputs.constEnd(); ++outputIt )
1586 if ( !found.contains( QStringLiteral(
"%1:%2" ).arg( outputIt->childId(), outputIt->childOutputName() ) ) )
1588 res << outputIt.value();
1596void QgsProcessingModelAlgorithm::setOutputOrder(
const QStringList &order )
1598 mOutputOrder = order;
1601QString QgsProcessingModelAlgorithm::outputGroup()
const
1603 return mOutputGroup;
1606void QgsProcessingModelAlgorithm::setOutputGroup(
const QString &group )
1608 mOutputGroup = group;
1611void QgsProcessingModelAlgorithm::updateDestinationParameters()
1614 QMutableListIterator<const QgsProcessingParameterDefinition *> it( mParameters );
1615 while ( it.hasNext() )
1625 qDeleteAll( mOutputs );
1629 QSet< QString > usedFriendlyNames;
1630 auto uniqueSafeName = [&usedFriendlyNames ](
const QString & name )->QString
1632 const QString base = safeName( name,
false );
1633 QString candidate = base;
1635 while ( usedFriendlyNames.contains( candidate ) )
1638 candidate = QStringLiteral(
"%1_%2" ).arg( base ).arg( i );
1640 usedFriendlyNames.insert( candidate );
1644 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1645 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1647 QMap<QString, QgsProcessingModelOutput> outputs = childIt->modelOutputs();
1648 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
1649 for ( ; outputIt != outputs.constEnd(); ++outputIt )
1651 if ( !childIt->isActive() || !childIt->algorithm() )
1659 std::unique_ptr< QgsProcessingParameterDefinition > param( source->
clone() );
1663 if ( outputIt->isMandatory() )
1665 if ( mInternalVersion != InternalVersion::Version1 && !outputIt->description().isEmpty() )
1667 QString friendlyName = uniqueSafeName( outputIt->description() );
1668 param->
setName( friendlyName );
1672 param->
setName( outputIt->childId() +
':' + outputIt->name() );
1675 param->
metadata().insert( QStringLiteral(
"_modelChildId" ), outputIt->childId() );
1676 param->
metadata().insert( QStringLiteral(
"_modelChildOutputName" ), outputIt->name() );
1677 param->
metadata().insert( QStringLiteral(
"_modelChildProvider" ), childIt->algorithm()->provider() ? childIt->algorithm()->provider()->id() : QString() );
1683 if ( addParameter( param.release() ) && newDestParam )
1690 newDestParam->mOriginalProvider = provider;
1697void QgsProcessingModelAlgorithm::addGroupBox(
const QgsProcessingModelGroupBox &groupBox )
1699 mGroupBoxes.insert( groupBox.uuid(), groupBox );
1702QList<QgsProcessingModelGroupBox> QgsProcessingModelAlgorithm::groupBoxes()
const
1704 return mGroupBoxes.values();
1707void QgsProcessingModelAlgorithm::removeGroupBox(
const QString &uuid )
1709 mGroupBoxes.remove( uuid );
1712QVariant QgsProcessingModelAlgorithm::toVariant()
const
1715 map.insert( QStringLiteral(
"model_name" ), mModelName );
1716 map.insert( QStringLiteral(
"model_group" ), mModelGroup );
1717 map.insert( QStringLiteral(
"help" ), mHelpContent );
1718 map.insert( QStringLiteral(
"internal_version" ),
qgsEnumValueToKey( mInternalVersion ) );
1720 QVariantMap childMap;
1721 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1722 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1724 childMap.insert( childIt.key(), childIt.value().toVariant() );
1726 map.insert( QStringLiteral(
"children" ), childMap );
1728 QVariantMap paramMap;
1729 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
1730 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
1732 paramMap.insert( paramIt.key(), paramIt.value().toVariant() );
1734 map.insert( QStringLiteral(
"parameters" ), paramMap );
1736 QVariantMap paramDefMap;
1741 map.insert( QStringLiteral(
"parameterDefinitions" ), paramDefMap );
1743 QVariantList groupBoxDefs;
1744 for (
auto it = mGroupBoxes.constBegin(); it != mGroupBoxes.constEnd(); ++it )
1746 groupBoxDefs.append( it.value().toVariant() );
1748 map.insert( QStringLiteral(
"groupBoxes" ), groupBoxDefs );
1750 map.insert( QStringLiteral(
"modelVariables" ), mVariables );
1752 map.insert( QStringLiteral(
"designerParameterValues" ), mDesignerParameterValues );
1754 map.insert( QStringLiteral(
"parameterOrder" ), mParameterOrder );
1755 map.insert( QStringLiteral(
"outputOrder" ), mOutputOrder );
1756 map.insert( QStringLiteral(
"outputGroup" ), mOutputGroup );
1761bool QgsProcessingModelAlgorithm::loadVariant(
const QVariant &model )
1763 QVariantMap map = model.toMap();
1765 mModelName = map.value( QStringLiteral(
"model_name" ) ).toString();
1766 mModelGroup = map.value( QStringLiteral(
"model_group" ) ).toString();
1767 mModelGroupId = map.value( QStringLiteral(
"model_group" ) ).toString();
1768 mHelpContent = map.value( QStringLiteral(
"help" ) ).toMap();
1770 mInternalVersion =
qgsEnumKeyToValue( map.value( QStringLiteral(
"internal_version" ) ).toString(), InternalVersion::Version1 );
1772 mVariables = map.value( QStringLiteral(
"modelVariables" ) ).toMap();
1773 mDesignerParameterValues = map.value( QStringLiteral(
"designerParameterValues" ) ).toMap();
1775 mParameterOrder = map.value( QStringLiteral(
"parameterOrder" ) ).toStringList();
1776 mOutputOrder = map.value( QStringLiteral(
"outputOrder" ) ).toStringList();
1777 mOutputGroup = map.value( QStringLiteral(
"outputGroup" ) ).toString();
1779 mChildAlgorithms.clear();
1780 QVariantMap childMap = map.value( QStringLiteral(
"children" ) ).toMap();
1781 QVariantMap::const_iterator childIt = childMap.constBegin();
1782 for ( ; childIt != childMap.constEnd(); ++childIt )
1784 QgsProcessingModelChildAlgorithm child;
1788 if ( !child.loadVariant( childIt.value() ) )
1791 mChildAlgorithms.insert( child.childId(), child );
1794 mParameterComponents.clear();
1795 QVariantMap paramMap = map.value( QStringLiteral(
"parameters" ) ).toMap();
1796 QVariantMap::const_iterator paramIt = paramMap.constBegin();
1797 for ( ; paramIt != paramMap.constEnd(); ++paramIt )
1799 QgsProcessingModelParameter param;
1800 if ( !param.loadVariant( paramIt.value().toMap() ) )
1803 mParameterComponents.insert( param.parameterName(), param );
1806 qDeleteAll( mParameters );
1807 mParameters.clear();
1808 QVariantMap paramDefMap = map.value( QStringLiteral(
"parameterDefinitions" ) ).toMap();
1810 auto addParam = [
this](
const QVariant & value )
1818 if ( param->name() == QLatin1String(
"VERBOSE_LOG" ) )
1822 param->setHelp( mHelpContent.value( param->name() ).toString() );
1825 addParameter( param.release() );
1829 QVariantMap map = value.toMap();
1830 QString type = map.value( QStringLiteral(
"parameter_type" ) ).toString();
1831 QString name = map.value( QStringLiteral(
"name" ) ).toString();
1833 QgsMessageLog::logMessage( QCoreApplication::translate(
"Processing",
"Could not load parameter %1 of type %2." ).arg( name, type ), QCoreApplication::translate(
"Processing",
"Processing" ) );
1837 QSet< QString > loadedParams;
1839 for (
const QString &name : std::as_const( mParameterOrder ) )
1841 if ( paramDefMap.contains( name ) )
1843 addParam( paramDefMap.value( name ) );
1844 loadedParams << name;
1848 QVariantMap::const_iterator paramDefIt = paramDefMap.constBegin();
1849 for ( ; paramDefIt != paramDefMap.constEnd(); ++paramDefIt )
1851 if ( !loadedParams.contains( paramDefIt.key() ) )
1852 addParam( paramDefIt.value() );
1855 mGroupBoxes.clear();
1856 const QVariantList groupBoxList = map.value( QStringLiteral(
"groupBoxes" ) ).toList();
1857 for (
const QVariant &groupBoxDef : groupBoxList )
1859 QgsProcessingModelGroupBox groupBox;
1860 groupBox.loadVariant( groupBoxDef.toMap() );
1861 mGroupBoxes.insert( groupBox.uuid(), groupBox );
1864 updateDestinationParameters();
1869bool QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType(
const QList<int> &acceptableDataTypes,
Qgis::ProcessingSourceType outputType )
1874 return ( acceptableDataTypes.empty()
1875 || acceptableDataTypes.contains(
static_cast< int >( outputType ) )
1886void QgsProcessingModelAlgorithm::reattachAlgorithms()
const
1888 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1889 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1891 if ( !childIt->algorithm() )
1892 childIt->reattach();
1896bool QgsProcessingModelAlgorithm::toFile(
const QString &path )
const
1898 QDomDocument doc = QDomDocument( QStringLiteral(
"model" ) );
1900 doc.appendChild( elem );
1903 if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
1905 QTextStream stream( &file );
1906 doc.save( stream, 2 );
1913bool QgsProcessingModelAlgorithm::fromFile(
const QString &path )
1918 if ( file.open( QFile::ReadOnly ) )
1920 if ( !doc.setContent( &file ) )
1931 return loadVariant( props );
1934void QgsProcessingModelAlgorithm::setChildAlgorithms(
const QMap<QString, QgsProcessingModelChildAlgorithm> &childAlgorithms )
1936 mChildAlgorithms = childAlgorithms;
1937 updateDestinationParameters();
1940void QgsProcessingModelAlgorithm::setChildAlgorithm(
const QgsProcessingModelChildAlgorithm &
algorithm )
1943 updateDestinationParameters();
1946QString QgsProcessingModelAlgorithm::addChildAlgorithm( QgsProcessingModelChildAlgorithm &
algorithm )
1948 if (
algorithm.childId().isEmpty() || mChildAlgorithms.contains(
algorithm.childId() ) )
1952 updateDestinationParameters();
1956QgsProcessingModelChildAlgorithm &QgsProcessingModelAlgorithm::childAlgorithm(
const QString &childId )
1958 return mChildAlgorithms[ childId ];
1961bool QgsProcessingModelAlgorithm::removeChildAlgorithm(
const QString &
id )
1963 if ( !dependentChildAlgorithms(
id ).isEmpty() )
1966 mChildAlgorithms.remove(
id );
1967 updateDestinationParameters();
1971void QgsProcessingModelAlgorithm::deactivateChildAlgorithm(
const QString &
id )
1973 const auto constDependentChildAlgorithms = dependentChildAlgorithms(
id );
1974 for (
const QString &child : constDependentChildAlgorithms )
1976 childAlgorithm( child ).setActive(
false );
1978 childAlgorithm(
id ).setActive(
false );
1979 updateDestinationParameters();
1982bool QgsProcessingModelAlgorithm::activateChildAlgorithm(
const QString &
id )
1984 const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms(
id );
1985 for (
const QString &child : constDependsOnChildAlgorithms )
1987 if ( !childAlgorithm( child ).isActive() )
1990 childAlgorithm(
id ).setActive(
true );
1991 updateDestinationParameters();
1997 if ( addParameter( definition ) )
1998 mParameterComponents.insert( definition->
name(), component );
2003 removeParameter( definition->
name() );
2004 addParameter( definition );
2007void QgsProcessingModelAlgorithm::removeModelParameter(
const QString &name )
2009 removeParameter( name );
2010 mParameterComponents.remove( name );
2013void QgsProcessingModelAlgorithm::changeParameterName(
const QString &oldName,
const QString &newName )
2018 auto replaceExpressionVariable = [oldName, newName, &expressionContext](
const QString & expressionString ) -> std::tuple< bool, QString >
2021 expression.prepare( &expressionContext );
2022 QSet<QString> variables = expression.referencedVariables();
2023 if ( variables.contains( oldName ) )
2025 QString newExpression = expressionString;
2026 newExpression.replace( QStringLiteral(
"@%1" ).arg( oldName ), QStringLiteral(
"@%2" ).arg( newName ) );
2027 return {
true, newExpression };
2029 return {
false, QString() };
2032 QMap< QString, QgsProcessingModelChildAlgorithm >::iterator childIt = mChildAlgorithms.begin();
2033 for ( ; childIt != mChildAlgorithms.end(); ++childIt )
2035 bool changed =
false;
2036 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
2037 QMap<QString, QgsProcessingModelChildParameterSources>::iterator paramIt = childParams.begin();
2038 for ( ; paramIt != childParams.end(); ++paramIt )
2040 QList< QgsProcessingModelChildParameterSource > &value = paramIt.value();
2041 for (
auto valueIt = value.begin(); valueIt != value.end(); ++valueIt )
2043 switch ( valueIt->source() )
2047 if ( valueIt->parameterName() == oldName )
2049 valueIt->setParameterName( newName );
2057 bool updatedExpression =
false;
2058 QString newExpression;
2059 std::tie( updatedExpression, newExpression ) = replaceExpressionVariable( valueIt->expression() );
2060 if ( updatedExpression )
2062 valueIt->setExpression( newExpression );
2070 if ( valueIt->staticValue().userType() == qMetaTypeId<QgsProperty>() )
2075 bool updatedExpression =
false;
2076 QString newExpression;
2077 std::tie( updatedExpression, newExpression ) = replaceExpressionVariable( property.expressionString() );
2078 if ( updatedExpression )
2080 property.setExpressionString( newExpression );
2081 valueIt->setStaticValue( property );
2097 childIt->setParameterSources( childParams );
2101bool QgsProcessingModelAlgorithm::childAlgorithmsDependOnParameter(
const QString &name )
const
2103 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
2104 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
2107 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
2108 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
2109 for ( ; paramIt != childParams.constEnd(); ++paramIt )
2111 const auto constValue = paramIt.value();
2112 for (
const QgsProcessingModelChildParameterSource &source : constValue )
2115 && source.parameterName() == name )
2125bool QgsProcessingModelAlgorithm::otherParametersDependOnParameter(
const QString &name )
const
2127 const auto constMParameters = mParameters;
2130 if ( def->
name() == name )
2139QMap<QString, QgsProcessingModelParameter> QgsProcessingModelAlgorithm::parameterComponents()
const
2141 return mParameterComponents;
2144void QgsProcessingModelAlgorithm::dependentChildAlgorithmsRecursive(
const QString &childId, QSet<QString> &depends,
const QString &branch )
const
2146 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
2147 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
2149 if ( depends.contains( childIt->childId() ) )
2153 const QList< QgsProcessingModelChildDependency > constDependencies = childIt->dependencies();
2154 bool hasDependency =
false;
2155 for (
const QgsProcessingModelChildDependency &dep : constDependencies )
2157 if ( dep.childId == childId && ( branch.isEmpty() || dep.conditionalBranch == branch ) )
2159 hasDependency =
true;
2164 if ( hasDependency )
2166 depends.insert( childIt->childId() );
2167 dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
2172 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
2173 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
2174 for ( ; paramIt != childParams.constEnd(); ++paramIt )
2176 const auto constValue = paramIt.value();
2177 for (
const QgsProcessingModelChildParameterSource &source : constValue )
2180 && source.outputChildId() == childId )
2182 depends.insert( childIt->childId() );
2183 dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
2191QSet<QString> QgsProcessingModelAlgorithm::dependentChildAlgorithms(
const QString &childId,
const QString &conditionalBranch )
const
2193 QSet< QString > algs;
2197 algs.insert( childId );
2199 dependentChildAlgorithmsRecursive( childId, algs, conditionalBranch );
2202 algs.remove( childId );
2208void QgsProcessingModelAlgorithm::dependsOnChildAlgorithmsRecursive(
const QString &childId, QSet< QString > &depends )
const
2210 const QgsProcessingModelChildAlgorithm &alg = mChildAlgorithms.value( childId );
2213 const QList< QgsProcessingModelChildDependency > constDependencies = alg.dependencies();
2214 for (
const QgsProcessingModelChildDependency &val : constDependencies )
2216 if ( !depends.contains( val.childId ) )
2218 depends.insert( val.childId );
2219 dependsOnChildAlgorithmsRecursive( val.childId, depends );
2224 QMap<QString, QgsProcessingModelChildParameterSources> childParams = alg.parameterSources();
2225 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
2226 for ( ; paramIt != childParams.constEnd(); ++paramIt )
2228 const auto constValue = paramIt.value();
2229 for (
const QgsProcessingModelChildParameterSource &source : constValue )
2231 switch ( source.source() )
2234 if ( !depends.contains( source.outputChildId() ) )
2236 depends.insert( source.outputChildId() );
2237 dependsOnChildAlgorithmsRecursive( source.outputChildId(), depends );
2244 const QSet<QString> vars = exp.referencedVariables();
2249 const QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> availableVariables = variablesForChildAlgorithm( childId );
2250 for (
auto childVarIt = availableVariables.constBegin(); childVarIt != availableVariables.constEnd(); ++childVarIt )
2256 if ( !vars.contains( childVarIt.key() ) || depends.contains( childVarIt->source.outputChildId() ) )
2260 depends.insert( childVarIt->source.outputChildId() );
2261 dependsOnChildAlgorithmsRecursive( childVarIt->source.outputChildId(), depends );
2276QSet< QString > QgsProcessingModelAlgorithm::dependsOnChildAlgorithms(
const QString &childId )
const
2278 QSet< QString > algs;
2282 algs.insert( childId );
2284 dependsOnChildAlgorithmsRecursive( childId, algs );
2287 algs.remove( childId );
2292QList<QgsProcessingModelChildDependency> QgsProcessingModelAlgorithm::availableDependenciesForChildAlgorithm(
const QString &childId )
const
2294 QSet< QString > dependent;
2295 if ( !childId.isEmpty() )
2297 dependent.unite( dependentChildAlgorithms( childId ) );
2298 dependent.insert( childId );
2301 QList<QgsProcessingModelChildDependency> res;
2302 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
2304 if ( !dependent.contains( it->childId() ) )
2307 bool hasBranches =
false;
2308 if ( it->algorithm() )
2316 QgsProcessingModelChildDependency alg;
2317 alg.childId = it->childId();
2318 alg.conditionalBranch = def->
name();
2326 QgsProcessingModelChildDependency alg;
2327 alg.childId = it->childId();
2335bool QgsProcessingModelAlgorithm::validateChildAlgorithm(
const QString &childId, QStringList &issues )
const
2338 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constFind( childId );
2339 if ( childIt != mChildAlgorithms.constEnd() )
2341 if ( !childIt->algorithm() )
2343 issues << QObject::tr(
"Algorithm is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
2352 if ( childIt->parameterSources().contains( def->
name() ) )
2355 const QList< QgsProcessingModelChildParameterSource > sources = childIt->parameterSources().value( def->
name() );
2356 for (
const QgsProcessingModelChildParameterSource &source : sources )
2358 switch ( source.source() )
2364 issues << QObject::tr(
"Value for <i>%1</i> is not acceptable for this parameter" ).arg( def->
name() );
2369 if ( !parameterComponents().contains( source.parameterName() ) )
2372 issues << QObject::tr(
"Model input <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.parameterName(), def->
name() );
2377 if ( !childAlgorithms().contains( source.outputChildId() ) )
2380 issues << QObject::tr(
"Child algorithm <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.outputChildId(), def->
name() );
2402 issues << QObject::tr(
"Parameter <i>%1</i> is mandatory" ).arg( def->
name() );
2411 issues << QObject::tr(
"Invalid child ID: <i>%1</i>" ).arg( childId );
2416bool QgsProcessingModelAlgorithm::canExecute( QString *errorMessage )
const
2418 reattachAlgorithms();
2419 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
2420 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
2422 if ( !childIt->algorithm() )
2426 *errorMessage = QObject::tr(
"The model you are trying to run contains an algorithm that is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
2434QString QgsProcessingModelAlgorithm::asPythonCommand(
const QVariantMap ¶meters,
QgsProcessingContext &context )
const
2436 if ( mSourceFile.isEmpty() )
2451 QgsProcessingModelAlgorithm *alg =
new QgsProcessingModelAlgorithm();
2452 alg->loadVariant( toVariant() );
2453 alg->setProvider( provider() );
2454 alg->setSourceFilePath( sourceFilePath() );
2458QString QgsProcessingModelAlgorithm::safeName(
const QString &name,
bool capitalize )
2460 QString n = name.toLower().trimmed();
2461 const thread_local QRegularExpression rx( QStringLiteral(
"[^\\sa-z_A-Z0-9]" ) );
2462 n.replace( rx, QString() );
2463 const thread_local QRegularExpression rx2( QStringLiteral(
"^\\d*" ) );
2464 n.replace( rx2, QString() );
2466 n = n.replace(
' ',
'_' );
2470QVariantMap QgsProcessingModelAlgorithm::variables()
const
2475void QgsProcessingModelAlgorithm::setVariables(
const QVariantMap &variables )
2477 mVariables = variables;
2480QVariantMap QgsProcessingModelAlgorithm::designerParameterValues()
const
2482 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.
QFlags< ProcessingAlgorithmFlag > ProcessingAlgorithmFlags
Flags indicating how and when an algorithm operates and should be exposed to users.
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...
@ SecurityRisk
The algorithm represents a potential security risk if executed with untrusted inputs.
@ 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.
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...
Handles 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, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE())
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 Qgis::ProcessingAlgorithmFlags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
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.
QMap< QString, QgsProcessingModelChildAlgorithmResult > childResults() const
Returns the map of child algorithm results.
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.
static QString typeName()
Returns the type name for the parameter class.
Base class for the definition of processing parameters.
void setDefaultValue(const QVariant &value)
Sets the default value for the parameter.
QgsProcessingAlgorithm * algorithm() const
Returns a pointer to the algorithm which owns this parameter.
void setFlags(Qgis::ProcessingParameterFlags flags)
Sets the flags associated with the 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.
void setDescription(const QString &description)
Sets the description for the parameter.
void setName(const QString &name)
Sets the name of the parameter.
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.
Makes metadata of processing parameters available.
virtual QStringList acceptedOutputTypes() const =0
Returns a list of compatible Processing output types for inputs for this parameter type.
virtual QList< int > acceptedDataTypes(const QgsProcessingParameterDefinition *parameter) const
Returns a list of compatible Processing data types for inputs for this parameter type for the specifi...
virtual QStringList acceptedParameterTypes() const =0
Returns a list of compatible Processing parameter types for inputs for this parameter type.
static QString typeName()
Returns the type name for the parameter class.
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 staticValue() const
Returns the current static value for the property.
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 dataset.
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.