33 #include <QTextStream>
34 #include <QRegularExpression>
37 QgsProcessingModelAlgorithm::QgsProcessingModelAlgorithm(
const QString &name,
const QString &group,
const QString &groupId )
38 : mModelName( name.isEmpty() ? QObject::tr(
"model" ) : name )
39 , mModelGroup( group )
40 , mModelGroupId( groupId )
43 void QgsProcessingModelAlgorithm::initAlgorithm(
const QVariantMap & )
47 QString QgsProcessingModelAlgorithm::name()
const
52 QString QgsProcessingModelAlgorithm::displayName()
const
57 QString QgsProcessingModelAlgorithm::group()
const
62 QString QgsProcessingModelAlgorithm::groupId()
const
67 QIcon QgsProcessingModelAlgorithm::icon()
const
72 QString QgsProcessingModelAlgorithm::svgIconPath()
const
77 QString QgsProcessingModelAlgorithm::shortHelpString()
const
79 if ( mHelpContent.empty() )
85 QString QgsProcessingModelAlgorithm::shortDescription()
const
87 return mHelpContent.value( QStringLiteral(
"SHORT_DESCRIPTION" ) ).toString();
90 QString QgsProcessingModelAlgorithm::helpUrl()
const
92 return mHelpContent.value( QStringLiteral(
"HELP_URL" ) ).toString();
95 QgsProcessingAlgorithm::Flags QgsProcessingModelAlgorithm::flags()
const
101 QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm(
const QgsProcessingModelChildAlgorithm &child,
const QVariantMap &modelParameters,
const QVariantMap &results,
const QgsExpressionContext &expressionContext, QString &error )
const
106 const QgsProcessingModelChildParameterSources paramSources = child.parameterSources().value( def->name() );
108 QString expressionText;
109 QVariantList paramParts;
110 for (
const QgsProcessingModelChildParameterSource &source : paramSources )
112 switch ( source.source() )
114 case QgsProcessingModelChildParameterSource::StaticValue:
115 paramParts << source.staticValue();
118 case QgsProcessingModelChildParameterSource::ModelParameter:
119 paramParts << modelParameters.value( source.parameterName() );
122 case QgsProcessingModelChildParameterSource::ChildOutput:
124 QVariantMap linkedChildResults = results.value( source.outputChildId() ).toMap();
125 paramParts << linkedChildResults.value( source.outputName() );
129 case QgsProcessingModelChildParameterSource::Expression:
132 paramParts << exp.evaluate( &expressionContext );
133 if ( exp.hasEvalError() )
135 error = QObject::tr(
"Could not evaluate expression for parameter %1 for %2: %3" ).arg( def->name(), child.description(), exp.evalErrorString() );
139 case QgsProcessingModelChildParameterSource::ExpressionText:
145 case QgsProcessingModelChildParameterSource::ModelOutput:
150 if ( ! expressionText.isEmpty() )
152 return expressionText;
154 else if ( paramParts.count() == 1 )
155 return paramParts.at( 0 );
161 QVariantMap childParams;
162 const auto constParameterDefinitions = child.algorithm()->parameterDefinitions();
165 if ( !def->isDestination() )
167 if ( !child.parameterSources().contains( def->name() ) )
170 const QVariant value = evaluateSources( def );
171 childParams.insert( def->name(), value );
178 bool isFinalOutput =
false;
179 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
180 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
181 for ( ; outputIt != outputs.constEnd(); ++outputIt )
183 if ( outputIt->childOutputName() == destParam->
name() )
185 QString paramName = child.childId() +
':' + outputIt.key();
186 if ( modelParameters.contains( paramName ) )
188 QVariant value = modelParameters.value( paramName );
194 value = QVariant::fromValue( fromVar );
197 childParams.insert( destParam->
name(), value );
199 isFinalOutput =
true;
204 bool hasExplicitDefinition =
false;
205 if ( !isFinalOutput && child.parameterSources().contains( def->name() ) )
208 const QVariant value = evaluateSources( def );
209 if ( value.isValid() )
211 childParams.insert( def->name(), value );
212 hasExplicitDefinition =
true;
216 if ( !isFinalOutput && !hasExplicitDefinition )
221 bool required =
true;
224 required = childOutputIsRequired( child.childId(), destParam->
name() );
236 bool QgsProcessingModelAlgorithm::childOutputIsRequired(
const QString &childId,
const QString &outputName )
const
239 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
240 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
242 if ( childIt->childId() == childId || !childIt->isActive() )
246 QMap<QString, QgsProcessingModelChildParameterSources> candidateChildParams = childIt->parameterSources();
247 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator childParamIt = candidateChildParams.constBegin();
248 for ( ; childParamIt != candidateChildParams.constEnd(); ++childParamIt )
250 const auto constValue = childParamIt.value();
251 for (
const QgsProcessingModelChildParameterSource &source : constValue )
253 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput
254 && source.outputChildId() == childId
255 && source.outputName() == outputName )
267 QSet< QString > toExecute;
268 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
269 QSet< QString > broken;
270 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
272 if ( childIt->isActive() )
274 if ( childIt->algorithm() )
275 toExecute.insert( childIt->childId() );
277 broken.insert( childIt->childId() );
281 if ( !broken.empty() )
282 throw QgsProcessingException( QCoreApplication::translate(
"QgsProcessingModelAlgorithm",
"Cannot run model, the following algorithms are not available on this system: %1" ).arg( broken.values().join( QLatin1String(
", " ) ) ) );
284 QElapsedTimer totalTime;
290 QVariantMap childResults;
291 QVariantMap childInputs;
295 QVariantMap finalResults;
296 QSet< QString > executed;
297 bool executedAlg =
true;
298 while ( executedAlg && executed.count() < toExecute.count() )
301 for (
const QString &childId : std::as_const( toExecute ) )
306 if ( executed.contains( childId ) )
309 bool canExecute =
true;
310 const QSet< QString > dependencies = dependsOnChildAlgorithms( childId );
311 for (
const QString &dependency : dependencies )
313 if ( !executed.contains( dependency ) )
325 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
326 std::unique_ptr< QgsProcessingAlgorithm > childAlg( child.algorithm()->create( child.configuration() ) );
329 if ( feedback && !skipGenericLogging )
330 feedback->
pushDebugInfo( QObject::tr(
"Prepare algorithm: %1" ).arg( childId ) );
334 << createExpressionContextScopeForChildAlgorithm( childId, context, parameters, childResults );
338 QVariantMap childParams = parametersForChildAlgorithm( child, parameters, childResults, expContext, error );
339 if ( !error.isEmpty() )
342 if ( feedback && !skipGenericLogging )
343 feedback->
setProgressText( QObject::tr(
"Running %1 [%2/%3]" ).arg( child.description() ).arg( executed.count() + 1 ).arg( toExecute.count() ) );
345 childInputs.insert( childId, childParams );
347 for (
auto childParamIt = childParams.constBegin(); childParamIt != childParams.constEnd(); ++childParamIt )
349 params << QStringLiteral(
"%1: %2" ).arg( childParamIt.key(),
350 child.algorithm()->parameterDefinition( childParamIt.key() )->valueAsPythonString( childParamIt.value(), context ) );
353 if ( feedback && !skipGenericLogging )
355 feedback->
pushInfo( QObject::tr(
"Input Parameters:" ) );
356 feedback->
pushCommandInfo( QStringLiteral(
"{ %1 }" ).arg( params.join( QLatin1String(
", " ) ) ) );
359 QElapsedTimer childTime;
363 QVariantMap results = childAlg->run( childParams, context, &modelFeedback, &ok, child.configuration() );
369 childResults.insert( childId, results );
373 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
374 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
375 for ( ; outputIt != outputs.constEnd(); ++outputIt )
377 finalResults.insert( childId +
':' + outputIt->name(), results.value( outputIt->childOutputName() ) );
380 executed.insert( childId );
382 std::function< void(
const QString &,
const QString & )> pruneAlgorithmBranchRecursive;
383 pruneAlgorithmBranchRecursive = [&](
const QString & id,
const QString &branch = QString() )
385 const QSet<QString> toPrune = dependentChildAlgorithms(
id, branch );
386 for (
const QString &targetId : toPrune )
388 if ( executed.contains( targetId ) )
391 executed.insert( targetId );
392 pruneAlgorithmBranchRecursive( targetId, branch );
402 pruneAlgorithmBranchRecursive( childId, outputDef->name() );
410 for (
const QString &candidateId : std::as_const( toExecute ) )
412 if ( executed.contains( candidateId ) )
417 const QgsProcessingModelChildAlgorithm &candidate = mChildAlgorithms[ candidateId ];
418 const QMap<QString, QgsProcessingModelChildParameterSources> candidateParams = candidate.parameterSources();
419 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = candidateParams.constBegin();
421 for ( ; paramIt != candidateParams.constEnd(); ++paramIt )
423 for (
const QgsProcessingModelChildParameterSource &source : paramIt.value() )
425 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput && source.outputChildId() == childId )
428 if ( !results.contains( source.outputName() ) )
433 executed.insert( candidateId );
435 pruneAlgorithmBranchRecursive( candidateId, QString() );
446 childAlg.reset(
nullptr );
447 modelFeedback.setCurrentStep( executed.count() );
448 if ( feedback && !skipGenericLogging )
449 feedback->
pushInfo( QObject::tr(
"OK. Execution took %1 s (%n output(s)).",
nullptr, results.count() ).arg( childTime.elapsed() / 1000.0 ) );
456 feedback->
pushDebugInfo( QObject::tr(
"Model processed OK. Executed %n algorithm(s) total in %1 s.",
nullptr, executed.count() ).arg( totalTime.elapsed() / 1000.0 ) );
458 mResults = finalResults;
459 mResults.insert( QStringLiteral(
"CHILD_RESULTS" ), childResults );
460 mResults.insert( QStringLiteral(
"CHILD_INPUTS" ), childInputs );
464 QString QgsProcessingModelAlgorithm::sourceFilePath()
const
469 void QgsProcessingModelAlgorithm::setSourceFilePath(
const QString &sourceFile )
471 mSourceFile = sourceFile;
474 bool QgsProcessingModelAlgorithm::modelNameMatchesFilePath()
const
476 if ( mSourceFile.isEmpty() )
479 const QFileInfo fi( mSourceFile );
480 return fi.completeBaseName().compare( mModelName, Qt::CaseInsensitive ) == 0;
485 QStringList fileDocString;
486 fileDocString << QStringLiteral(
"\"\"\"" );
487 fileDocString << QStringLiteral(
"Model exported as python." );
488 fileDocString << QStringLiteral(
"Name : %1" ).arg( displayName() );
489 fileDocString << QStringLiteral(
"Group : %1" ).arg( group() );
490 fileDocString << QStringLiteral(
"With QGIS : %1" ).arg(
Qgis::versionInt() );
491 fileDocString << QStringLiteral(
"\"\"\"" );
492 fileDocString << QString();
495 QString indent = QString(
' ' ).repeated( indentSize );
496 QString currentIndent;
498 QMap< QString, QString> friendlyChildNames;
499 QMap< QString, QString> friendlyOutputNames;
500 auto safeName = [](
const QString & name,
bool capitalize )->QString
502 QString n = name.toLower().trimmed();
503 QRegularExpression rx( QStringLiteral(
"[^\\sa-z_A-Z0-9]" ) );
504 n.replace( rx, QString() );
505 QRegularExpression rx2( QStringLiteral(
"^\\d*" ) );
506 n.replace( rx2, QString() );
508 n = n.replace(
' ',
'_' );
512 auto uniqueSafeName = [ &safeName ](
const QString & name,
bool capitalize,
const QMap< QString, QString > &friendlyNames )->QString
514 const QString base = safeName( name, capitalize );
515 QString candidate = base;
517 while ( friendlyNames.contains( candidate ) )
520 candidate = QStringLiteral(
"%1_%2" ).arg( base ).arg( i );
525 const QString algorithmClassName = safeName( name(),
true );
527 QSet< QString > toExecute;
528 for (
auto childIt = mChildAlgorithms.constBegin(); childIt != mChildAlgorithms.constEnd(); ++childIt )
530 if ( childIt->isActive() && childIt->algorithm() )
532 toExecute.insert( childIt->childId() );
533 friendlyChildNames.insert( childIt->childId(), uniqueSafeName( childIt->description().isEmpty() ? childIt->childId() : childIt->description(), !childIt->description().isEmpty(), friendlyChildNames ) );
536 const int totalSteps = toExecute.count();
538 QStringList importLines;
539 switch ( outputType )
544 const auto params = parameterDefinitions();
545 importLines.reserve( params.count() + 3 );
546 importLines << QStringLiteral(
"from qgis.core import QgsProcessing" );
547 importLines << QStringLiteral(
"from qgis.core import QgsProcessingAlgorithm" );
548 importLines << QStringLiteral(
"from qgis.core import QgsProcessingMultiStepFeedback" );
550 bool hasAdvancedParams =
false;
554 hasAdvancedParams =
true;
557 if ( !importString.isEmpty() && !importLines.contains( importString ) )
558 importLines << importString;
561 if ( hasAdvancedParams )
562 importLines << QStringLiteral(
"from qgis.core import QgsProcessingParameterDefinition" );
564 lines << QStringLiteral(
"import processing" );
565 lines << QString() << QString();
567 lines << QStringLiteral(
"class %1(QgsProcessingAlgorithm):" ).arg( algorithmClassName );
571 lines << indent + QStringLiteral(
"def initAlgorithm(self, config=None):" );
572 if ( params.empty() )
574 lines << indent + indent + QStringLiteral(
"pass" );
578 lines.reserve( lines.size() + params.size() );
581 std::unique_ptr< QgsProcessingParameterDefinition > defClone( def->clone() );
583 if ( defClone->isDestination() )
585 const QString &friendlyName = !defClone->description().isEmpty() ? uniqueSafeName( defClone->description(),
true, friendlyOutputNames ) : defClone->name();
586 friendlyOutputNames.insert( defClone->name(), friendlyName );
587 defClone->setName( friendlyName );
591 if ( !mParameterComponents.value( defClone->name() ).comment()->description().isEmpty() )
592 lines << indent + indent + QStringLiteral(
"# %1" ).arg( mParameterComponents.value( defClone->name() ).comment()->description() );
597 lines << indent + indent + QStringLiteral(
"param = %1" ).arg( defClone->asPythonString() );
598 lines << indent + indent + QStringLiteral(
"param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)" );
599 lines << indent + indent + QStringLiteral(
"self.addParameter(param)" );
603 lines << indent + indent + QStringLiteral(
"self.addParameter(%1)" ).arg( defClone->asPythonString() );
609 lines << indent + QStringLiteral(
"def processAlgorithm(self, parameters, context, model_feedback):" );
610 currentIndent = indent + indent;
612 lines << currentIndent + QStringLiteral(
"# Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the" );
613 lines << currentIndent + QStringLiteral(
"# overall progress through the model" );
614 lines << currentIndent + QStringLiteral(
"feedback = QgsProcessingMultiStepFeedback(%1, model_feedback)" ).arg( totalSteps );
622 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
623 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
625 QString name = paramIt.value().parameterName();
626 if ( parameterDefinition( name ) )
629 params.insert( name, parameterDefinition( name )->valueAsPythonString( parameterDefinition( name )->defaultValue(), context ) );
633 if ( !params.isEmpty() )
635 lines << QStringLiteral(
"parameters = {" );
636 for (
auto it = params.constBegin(); it != params.constEnd(); ++it )
638 lines << QStringLiteral(
" '%1':%2," ).arg( it.key(), it.value() );
640 lines << QStringLiteral(
"}" )
644 lines << QStringLiteral(
"context = QgsProcessingContext()" )
645 << QStringLiteral(
"context.setProject(QgsProject.instance())" )
646 << QStringLiteral(
"feedback = QgsProcessingFeedback()" )
655 lines << currentIndent + QStringLiteral(
"results = {}" );
656 lines << currentIndent + QStringLiteral(
"outputs = {}" );
659 QSet< QString > executed;
660 bool executedAlg =
true;
662 while ( executedAlg && executed.count() < toExecute.count() )
665 const auto constToExecute = toExecute;
666 for (
const QString &childId : constToExecute )
668 if ( executed.contains( childId ) )
671 bool canExecute =
true;
672 const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms( childId );
673 for (
const QString &dependency : constDependsOnChildAlgorithms )
675 if ( !executed.contains( dependency ) )
687 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
694 if ( def->isDestination() )
699 bool isFinalOutput =
false;
700 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
701 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
702 for ( ; outputIt != outputs.constEnd(); ++outputIt )
704 if ( outputIt->childOutputName() == destParam->
name() )
706 QString paramName = child.childId() +
':' + outputIt.key();
707 paramName = friendlyOutputNames.value( paramName, paramName );
708 childParams.insert( destParam->
name(), QStringLiteral(
"parameters['%1']" ).arg( paramName ) );
709 isFinalOutput =
true;
714 if ( !isFinalOutput )
719 bool required =
true;
722 required = childOutputIsRequired( child.childId(), destParam->
name() );
729 childParams.insert( destParam->
name(), QStringLiteral(
"QgsProcessing.TEMPORARY_OUTPUT" ) );
735 lines << child.asPythonCode( outputType, childParams, currentIndent.size(), indentSize, friendlyChildNames, friendlyOutputNames );
737 if ( currentStep < totalSteps )
740 lines << currentIndent + QStringLiteral(
"feedback.setCurrentStep(%1)" ).arg( currentStep );
741 lines << currentIndent + QStringLiteral(
"if feedback.isCanceled():" );
742 lines << currentIndent + indent + QStringLiteral(
"return {}" );
745 executed.insert( childId );
749 switch ( outputType )
752 lines << currentIndent + QStringLiteral(
"return results" );
756 lines << indent + QStringLiteral(
"def name(self):" );
757 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelName );
759 lines << indent + QStringLiteral(
"def displayName(self):" );
760 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelName );
764 lines << indent + QStringLiteral(
"def group(self):" );
765 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelGroup );
767 lines << indent + QStringLiteral(
"def groupId(self):" );
768 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelGroupId );
772 if ( !shortHelpString().isEmpty() )
774 lines << indent + QStringLiteral(
"def shortHelpString(self):" );
775 lines << indent + indent + QStringLiteral(
"return \"\"\"%1\"\"\"" ).arg( shortHelpString() );
778 if ( !helpUrl().isEmpty() )
780 lines << indent + QStringLiteral(
"def helpUrl(self):" );
781 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( helpUrl() );
786 lines << indent + QStringLiteral(
"def createInstance(self):" );
787 lines << indent + indent + QStringLiteral(
"return %1()" ).arg( algorithmClassName );
790 static QMap< QString, QString > sAdditionalImports
792 { QStringLiteral(
"QgsCoordinateReferenceSystem" ), QStringLiteral(
"from qgis.core import QgsCoordinateReferenceSystem" ) },
793 { QStringLiteral(
"QgsExpression" ), QStringLiteral(
"from qgis.core import QgsExpression" ) },
794 { QStringLiteral(
"QgsRectangle" ), QStringLiteral(
"from qgis.core import QgsRectangle" ) },
795 { QStringLiteral(
"QgsReferencedRectangle" ), QStringLiteral(
"from qgis.core import QgsReferencedRectangle" ) },
796 { QStringLiteral(
"QgsPoint" ), QStringLiteral(
"from qgis.core import QgsPoint" ) },
797 { QStringLiteral(
"QgsReferencedPoint" ), QStringLiteral(
"from qgis.core import QgsReferencedPoint" ) },
798 { QStringLiteral(
"QgsProperty" ), QStringLiteral(
"from qgis.core import QgsProperty" ) },
799 { QStringLiteral(
"QgsRasterLayer" ), QStringLiteral(
"from qgis.core import QgsRasterLayer" ) },
800 { QStringLiteral(
"QgsMeshLayer" ), QStringLiteral(
"from qgis.core import QgsMeshLayer" ) },
801 { QStringLiteral(
"QgsVectorLayer" ), QStringLiteral(
"from qgis.core import QgsVectorLayer" ) },
802 { QStringLiteral(
"QgsMapLayer" ), QStringLiteral(
"from qgis.core import QgsMapLayer" ) },
803 { QStringLiteral(
"QgsProcessingFeatureSourceDefinition" ), QStringLiteral(
"from qgis.core import QgsProcessingFeatureSourceDefinition" ) },
804 { QStringLiteral(
"QgsPointXY" ), QStringLiteral(
"from qgis.core import QgsPointXY" ) },
805 { QStringLiteral(
"QgsReferencedPointXY" ), QStringLiteral(
"from qgis.core import QgsReferencedPointXY" ) },
806 { QStringLiteral(
"QgsGeometry" ), QStringLiteral(
"from qgis.core import QgsGeometry" ) },
807 { QStringLiteral(
"QgsProcessingOutputLayerDefinition" ), QStringLiteral(
"from qgis.core import QgsProcessingOutputLayerDefinition" ) },
808 { QStringLiteral(
"QColor" ), QStringLiteral(
"from qgis.PyQt.QtGui import QColor" ) },
809 { QStringLiteral(
"QDateTime" ), QStringLiteral(
"from qgis.PyQt.QtCore import QDateTime" ) },
810 { QStringLiteral(
"QDate" ), QStringLiteral(
"from qgis.PyQt.QtCore import QDate" ) },
811 { QStringLiteral(
"QTime" ), QStringLiteral(
"from qgis.PyQt.QtCore import QTime" ) },
814 for (
auto it = sAdditionalImports.constBegin(); it != sAdditionalImports.constEnd(); ++it )
816 if ( importLines.contains( it.value() ) )
823 for (
const QString &line : std::as_const( lines ) )
825 if ( line.contains( it.key() ) )
833 importLines << it.value();
837 lines = fileDocString + importLines + lines;
846 QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> QgsProcessingModelAlgorithm::variablesForChildAlgorithm(
const QString &childId,
QgsProcessingContext &context,
const QVariantMap &modelParameters,
const QVariantMap &results )
const
848 QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables;
850 auto safeName = [](
const QString & name )->QString
853 return s.replace( QRegularExpression( QStringLiteral(
"[\\s'\"\\(\\):\\.]" ) ), QStringLiteral(
"_" ) );
887 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
892 switch ( source.source() )
894 case QgsProcessingModelChildParameterSource::ModelParameter:
896 name = source.parameterName();
897 value = modelParameters.value( source.parameterName() );
898 description = parameterDefinition( source.parameterName() )->description();
901 case QgsProcessingModelChildParameterSource::ChildOutput:
903 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
904 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
905 source.outputChildId() : child.description(), source.outputName() );
908 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
909 child.description() );
911 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
915 case QgsProcessingModelChildParameterSource::Expression:
916 case QgsProcessingModelChildParameterSource::ExpressionText:
917 case QgsProcessingModelChildParameterSource::StaticValue:
918 case QgsProcessingModelChildParameterSource::ModelOutput:
921 variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
925 sources = availableSourcesForChild( childId, QStringList()
932 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
938 switch ( source.source() )
940 case QgsProcessingModelChildParameterSource::ModelParameter:
942 name = source.parameterName();
943 value = modelParameters.value( source.parameterName() );
944 description = parameterDefinition( source.parameterName() )->description();
947 case QgsProcessingModelChildParameterSource::ChildOutput:
949 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
950 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
951 source.outputChildId() : child.description(), source.outputName() );
952 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
955 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
956 child.description() );
961 case QgsProcessingModelChildParameterSource::Expression:
962 case QgsProcessingModelChildParameterSource::ExpressionText:
963 case QgsProcessingModelChildParameterSource::StaticValue:
964 case QgsProcessingModelChildParameterSource::ModelOutput:
972 value = fromVar.
sink;
978 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( value ) );
982 variables.insert( safeName( name ), VariableDefinition( QVariant::fromValue(
QgsWeakMapLayerPointer( layer ) ), source, description ) );
983 variables.insert( safeName( QStringLiteral(
"%1_minx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMinimum() : QVariant(), source, QObject::tr(
"Minimum X of %1" ).arg( description ) ) );
984 variables.insert( safeName( QStringLiteral(
"%1_miny" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMinimum() : QVariant(), source, QObject::tr(
"Minimum Y of %1" ).arg( description ) ) );
985 variables.insert( safeName( QStringLiteral(
"%1_maxx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMaximum() : QVariant(), source, QObject::tr(
"Maximum X of %1" ).arg( description ) ) );
986 variables.insert( safeName( QStringLiteral(
"%1_maxy" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMaximum() : QVariant(), source, QObject::tr(
"Maximum Y of %1" ).arg( description ) ) );
989 sources = availableSourcesForChild( childId, QStringList()
991 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
997 switch ( source.source() )
999 case QgsProcessingModelChildParameterSource::ModelParameter:
1001 name = source.parameterName();
1002 value = modelParameters.value( source.parameterName() );
1003 description = parameterDefinition( source.parameterName() )->description();
1006 case QgsProcessingModelChildParameterSource::ChildOutput:
1008 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
1009 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
1010 source.outputChildId() : child.description(), source.outputName() );
1011 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
1014 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
1015 child.description() );
1020 case QgsProcessingModelChildParameterSource::Expression:
1021 case QgsProcessingModelChildParameterSource::ExpressionText:
1022 case QgsProcessingModelChildParameterSource::StaticValue:
1023 case QgsProcessingModelChildParameterSource::ModelOutput:
1037 value = fromVar.
sink;
1043 if (
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( value ) ) )
1045 featureSource = layer;
1047 if ( !featureSource )
1053 variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
1054 variables.insert( safeName( QStringLiteral(
"%1_minx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMinimum() : QVariant(), source, QObject::tr(
"Minimum X of %1" ).arg( description ) ) );
1055 variables.insert( safeName( QStringLiteral(
"%1_miny" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMinimum() : QVariant(), source, QObject::tr(
"Minimum Y of %1" ).arg( description ) ) );
1056 variables.insert( safeName( QStringLiteral(
"%1_maxx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMaximum() : QVariant(), source, QObject::tr(
"Maximum X of %1" ).arg( description ) ) );
1057 variables.insert( safeName( QStringLiteral(
"%1_maxy" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMaximum() : QVariant(), source, QObject::tr(
"Maximum Y of %1" ).arg( description ) ) );
1063 QgsExpressionContextScope *QgsProcessingModelAlgorithm::createExpressionContextScopeForChildAlgorithm(
const QString &childId,
QgsProcessingContext &context,
const QVariantMap &modelParameters,
const QVariantMap &results )
const
1065 std::unique_ptr< QgsExpressionContextScope > scope(
new QgsExpressionContextScope( QStringLiteral(
"algorithm_inputs" ) ) );
1066 QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = variablesForChildAlgorithm( childId, context, modelParameters, results );
1067 QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition>::const_iterator varIt = variables.constBegin();
1068 for ( ; varIt != variables.constEnd(); ++varIt )
1072 return scope.release();
1075 QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild(
const QString &childId,
const QStringList ¶meterTypes,
const QStringList &outputTypes,
const QList<int> &dataTypes )
const
1077 QgsProcessingModelChildParameterSources sources;
1080 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
1081 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
1087 if ( parameterTypes.contains( def->
type() ) )
1089 if ( !dataTypes.isEmpty() )
1105 bool ok = sourceDef->
dataTypes().isEmpty();
1106 const auto constDataTypes = sourceDef->
dataTypes();
1107 for (
int type : constDataTypes )
1122 sources << QgsProcessingModelChildParameterSource::fromModelParameter( paramIt->parameterName() );
1126 QSet< QString > dependents;
1127 if ( !childId.isEmpty() )
1129 dependents = dependentChildAlgorithms( childId );
1130 dependents << childId;
1133 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1134 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1136 if ( dependents.contains( childIt->childId() ) )
1146 if ( outputTypes.contains( out->type() ) )
1148 if ( !dataTypes.isEmpty() )
1154 if ( !vectorOutputIsCompatibleType( dataTypes, vectorOut->
dataType() ) )
1161 sources << QgsProcessingModelChildParameterSource::fromChildOutput( childIt->childId(), out->name() );
1169 QVariantMap QgsProcessingModelAlgorithm::helpContent()
const
1171 return mHelpContent;
1174 void QgsProcessingModelAlgorithm::setHelpContent(
const QVariantMap &helpContent )
1176 mHelpContent = helpContent;
1179 void QgsProcessingModelAlgorithm::setName(
const QString &name )
1184 void QgsProcessingModelAlgorithm::setGroup(
const QString &group )
1186 mModelGroup = group;
1189 bool QgsProcessingModelAlgorithm::validate( QStringList &issues )
const
1194 if ( mChildAlgorithms.empty() )
1197 issues << QObject::tr(
"Model does not contain any algorithms" );
1200 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
1202 QStringList childIssues;
1203 res = validateChildAlgorithm( it->childId(), childIssues ) && res;
1205 for (
const QString &issue : std::as_const( childIssues ) )
1207 issues << QStringLiteral(
"<b>%1</b>: %2" ).arg( it->description(), issue );
1213 QMap<QString, QgsProcessingModelChildAlgorithm> QgsProcessingModelAlgorithm::childAlgorithms()
const
1215 return mChildAlgorithms;
1218 void QgsProcessingModelAlgorithm::setParameterComponents(
const QMap<QString, QgsProcessingModelParameter> ¶meterComponents )
1220 mParameterComponents = parameterComponents;
1223 void QgsProcessingModelAlgorithm::setParameterComponent(
const QgsProcessingModelParameter &component )
1225 mParameterComponents.insert( component.parameterName(), component );
1228 QgsProcessingModelParameter &QgsProcessingModelAlgorithm::parameterComponent(
const QString &name )
1230 if ( !mParameterComponents.contains( name ) )
1232 QgsProcessingModelParameter &component = mParameterComponents[ name ];
1233 component.setParameterName( name );
1236 return mParameterComponents[ name ];
1239 QList< QgsProcessingModelParameter > QgsProcessingModelAlgorithm::orderedParameters()
const
1241 QList< QgsProcessingModelParameter > res;
1242 QSet< QString > found;
1243 for (
const QString ¶meter : mParameterOrder )
1245 if ( mParameterComponents.contains( parameter ) )
1247 res << mParameterComponents.value( parameter );
1253 for (
auto it = mParameterComponents.constBegin(); it != mParameterComponents.constEnd(); ++it )
1255 if ( !found.contains( it.key() ) )
1263 void QgsProcessingModelAlgorithm::setParameterOrder(
const QStringList &order )
1265 mParameterOrder = order;
1268 void QgsProcessingModelAlgorithm::updateDestinationParameters()
1271 QMutableListIterator<const QgsProcessingParameterDefinition *> it( mParameters );
1272 while ( it.hasNext() )
1282 qDeleteAll( mOutputs );
1286 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1287 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1289 QMap<QString, QgsProcessingModelOutput> outputs = childIt->modelOutputs();
1290 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
1291 for ( ; outputIt != outputs.constEnd(); ++outputIt )
1293 if ( !childIt->isActive() || !childIt->algorithm() )
1301 std::unique_ptr< QgsProcessingParameterDefinition > param( source->
clone() );
1305 if ( outputIt->isMandatory() )
1307 param->setName( outputIt->childId() +
':' + outputIt->name() );
1308 param->setDescription( outputIt->description() );
1309 param->setDefaultValue( outputIt->defaultValue() );
1312 if ( addParameter( param.release() ) && newDestParam )
1319 newDestParam->mOriginalProvider = provider;
1326 void QgsProcessingModelAlgorithm::addGroupBox(
const QgsProcessingModelGroupBox &groupBox )
1328 mGroupBoxes.insert( groupBox.uuid(), groupBox );
1331 QList<QgsProcessingModelGroupBox> QgsProcessingModelAlgorithm::groupBoxes()
const
1333 return mGroupBoxes.values();
1336 void QgsProcessingModelAlgorithm::removeGroupBox(
const QString &uuid )
1338 mGroupBoxes.remove( uuid );
1341 QVariant QgsProcessingModelAlgorithm::toVariant()
const
1344 map.insert( QStringLiteral(
"model_name" ), mModelName );
1345 map.insert( QStringLiteral(
"model_group" ), mModelGroup );
1346 map.insert( QStringLiteral(
"help" ), mHelpContent );
1348 QVariantMap childMap;
1349 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1350 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1352 childMap.insert( childIt.key(), childIt.value().toVariant() );
1354 map.insert( QStringLiteral(
"children" ), childMap );
1356 QVariantMap paramMap;
1357 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
1358 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
1360 paramMap.insert( paramIt.key(), paramIt.value().toVariant() );
1362 map.insert( QStringLiteral(
"parameters" ), paramMap );
1364 QVariantMap paramDefMap;
1369 map.insert( QStringLiteral(
"parameterDefinitions" ), paramDefMap );
1371 QVariantList groupBoxDefs;
1372 for (
auto it = mGroupBoxes.constBegin(); it != mGroupBoxes.constEnd(); ++it )
1374 groupBoxDefs.append( it.value().toVariant() );
1376 map.insert( QStringLiteral(
"groupBoxes" ), groupBoxDefs );
1378 map.insert( QStringLiteral(
"modelVariables" ), mVariables );
1380 map.insert( QStringLiteral(
"designerParameterValues" ), mDesignerParameterValues );
1382 map.insert( QStringLiteral(
"parameterOrder" ), mParameterOrder );
1387 bool QgsProcessingModelAlgorithm::loadVariant(
const QVariant &model )
1389 QVariantMap map = model.toMap();
1391 mModelName = map.value( QStringLiteral(
"model_name" ) ).toString();
1392 mModelGroup = map.value( QStringLiteral(
"model_group" ) ).toString();
1393 mModelGroupId = map.value( QStringLiteral(
"model_group" ) ).toString();
1394 mHelpContent = map.value( QStringLiteral(
"help" ) ).toMap();
1396 mVariables = map.value( QStringLiteral(
"modelVariables" ) ).toMap();
1397 mDesignerParameterValues = map.value( QStringLiteral(
"designerParameterValues" ) ).toMap();
1399 mParameterOrder = map.value( QStringLiteral(
"parameterOrder" ) ).toStringList();
1401 mChildAlgorithms.clear();
1402 QVariantMap childMap = map.value( QStringLiteral(
"children" ) ).toMap();
1403 QVariantMap::const_iterator childIt = childMap.constBegin();
1404 for ( ; childIt != childMap.constEnd(); ++childIt )
1406 QgsProcessingModelChildAlgorithm child;
1410 if ( !child.loadVariant( childIt.value() ) )
1413 mChildAlgorithms.insert( child.childId(), child );
1416 mParameterComponents.clear();
1417 QVariantMap paramMap = map.value( QStringLiteral(
"parameters" ) ).toMap();
1418 QVariantMap::const_iterator paramIt = paramMap.constBegin();
1419 for ( ; paramIt != paramMap.constEnd(); ++paramIt )
1421 QgsProcessingModelParameter param;
1422 if ( !param.loadVariant( paramIt.value().toMap() ) )
1425 mParameterComponents.insert( param.parameterName(), param );
1428 qDeleteAll( mParameters );
1429 mParameters.clear();
1430 QVariantMap paramDefMap = map.value( QStringLiteral(
"parameterDefinitions" ) ).toMap();
1432 auto addParam = [ = ](
const QVariant & value )
1440 if ( param->name() == QLatin1String(
"VERBOSE_LOG" ) )
1444 param->setHelp( mHelpContent.value( param->name() ).toString() );
1447 addParameter( param.release() );
1451 QVariantMap map = value.toMap();
1452 QString type = map.value( QStringLiteral(
"parameter_type" ) ).toString();
1453 QString name = map.value( QStringLiteral(
"name" ) ).toString();
1455 QgsMessageLog::logMessage( QCoreApplication::translate(
"Processing",
"Could not load parameter %1 of type %2." ).arg( name, type ), QCoreApplication::translate(
"Processing",
"Processing" ) );
1459 QSet< QString > loadedParams;
1461 for (
const QString &name : std::as_const( mParameterOrder ) )
1463 if ( paramDefMap.contains( name ) )
1465 addParam( paramDefMap.value( name ) );
1466 loadedParams << name;
1470 QVariantMap::const_iterator paramDefIt = paramDefMap.constBegin();
1471 for ( ; paramDefIt != paramDefMap.constEnd(); ++paramDefIt )
1473 if ( !loadedParams.contains( paramDefIt.key() ) )
1474 addParam( paramDefIt.value() );
1477 mGroupBoxes.clear();
1478 const QVariantList groupBoxList = map.value( QStringLiteral(
"groupBoxes" ) ).toList();
1479 for (
const QVariant &groupBoxDef : groupBoxList )
1481 QgsProcessingModelGroupBox groupBox;
1482 groupBox.loadVariant( groupBoxDef.toMap() );
1483 mGroupBoxes.insert( groupBox.uuid(), groupBox );
1486 updateDestinationParameters();
1491 bool QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType(
const QList<int> &acceptableDataTypes,
QgsProcessing::SourceType outputType )
1496 return ( acceptableDataTypes.empty()
1497 || acceptableDataTypes.contains( outputType )
1508 void QgsProcessingModelAlgorithm::reattachAlgorithms()
const
1510 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1511 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1513 if ( !childIt->algorithm() )
1514 childIt->reattach();
1518 bool QgsProcessingModelAlgorithm::toFile(
const QString &path )
const
1520 QDomDocument doc = QDomDocument( QStringLiteral(
"model" ) );
1522 doc.appendChild( elem );
1525 if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
1527 QTextStream stream( &file );
1528 doc.save( stream, 2 );
1535 bool QgsProcessingModelAlgorithm::fromFile(
const QString &path )
1540 if ( file.open( QFile::ReadOnly ) )
1542 if ( !doc.setContent( &file ) )
1553 return loadVariant( props );
1556 void QgsProcessingModelAlgorithm::setChildAlgorithms(
const QMap<QString, QgsProcessingModelChildAlgorithm> &childAlgorithms )
1558 mChildAlgorithms = childAlgorithms;
1559 updateDestinationParameters();
1562 void QgsProcessingModelAlgorithm::setChildAlgorithm(
const QgsProcessingModelChildAlgorithm &
algorithm )
1565 updateDestinationParameters();
1568 QString QgsProcessingModelAlgorithm::addChildAlgorithm( QgsProcessingModelChildAlgorithm &
algorithm )
1570 if (
algorithm.childId().isEmpty() || mChildAlgorithms.contains(
algorithm.childId() ) )
1574 updateDestinationParameters();
1578 QgsProcessingModelChildAlgorithm &QgsProcessingModelAlgorithm::childAlgorithm(
const QString &childId )
1580 return mChildAlgorithms[ childId ];
1583 bool QgsProcessingModelAlgorithm::removeChildAlgorithm(
const QString &
id )
1585 if ( !dependentChildAlgorithms(
id ).isEmpty() )
1588 mChildAlgorithms.remove(
id );
1589 updateDestinationParameters();
1593 void QgsProcessingModelAlgorithm::deactivateChildAlgorithm(
const QString &
id )
1595 const auto constDependentChildAlgorithms = dependentChildAlgorithms(
id );
1596 for (
const QString &child : constDependentChildAlgorithms )
1598 childAlgorithm( child ).setActive(
false );
1600 childAlgorithm(
id ).setActive(
false );
1601 updateDestinationParameters();
1604 bool QgsProcessingModelAlgorithm::activateChildAlgorithm(
const QString &
id )
1606 const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms(
id );
1607 for (
const QString &child : constDependsOnChildAlgorithms )
1609 if ( !childAlgorithm( child ).isActive() )
1612 childAlgorithm(
id ).setActive(
true );
1613 updateDestinationParameters();
1619 if ( addParameter( definition ) )
1620 mParameterComponents.insert( definition->
name(), component );
1625 removeParameter( definition->
name() );
1626 addParameter( definition );
1629 void QgsProcessingModelAlgorithm::removeModelParameter(
const QString &name )
1631 removeParameter( name );
1632 mParameterComponents.remove( name );
1635 bool QgsProcessingModelAlgorithm::childAlgorithmsDependOnParameter(
const QString &name )
const
1637 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1638 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1641 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
1642 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
1643 for ( ; paramIt != childParams.constEnd(); ++paramIt )
1645 const auto constValue = paramIt.value();
1646 for (
const QgsProcessingModelChildParameterSource &source : constValue )
1648 if ( source.source() == QgsProcessingModelChildParameterSource::ModelParameter
1649 && source.parameterName() == name )
1659 bool QgsProcessingModelAlgorithm::otherParametersDependOnParameter(
const QString &name )
const
1661 const auto constMParameters = mParameters;
1664 if ( def->
name() == name )
1673 QMap<QString, QgsProcessingModelParameter> QgsProcessingModelAlgorithm::parameterComponents()
const
1675 return mParameterComponents;
1678 void QgsProcessingModelAlgorithm::dependentChildAlgorithmsRecursive(
const QString &childId, QSet<QString> &depends,
const QString &branch )
const
1680 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1681 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1683 if ( depends.contains( childIt->childId() ) )
1687 const QList< QgsProcessingModelChildDependency > constDependencies = childIt->dependencies();
1688 bool hasDependency =
false;
1689 for (
const QgsProcessingModelChildDependency &dep : constDependencies )
1691 if ( dep.childId == childId && ( branch.isEmpty() || dep.conditionalBranch == branch ) )
1693 hasDependency =
true;
1698 if ( hasDependency )
1700 depends.insert( childIt->childId() );
1701 dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
1706 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
1707 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
1708 for ( ; paramIt != childParams.constEnd(); ++paramIt )
1710 const auto constValue = paramIt.value();
1711 for (
const QgsProcessingModelChildParameterSource &source : constValue )
1713 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput
1714 && source.outputChildId() == childId )
1716 depends.insert( childIt->childId() );
1717 dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
1725 QSet<QString> QgsProcessingModelAlgorithm::dependentChildAlgorithms(
const QString &childId,
const QString &conditionalBranch )
const
1727 QSet< QString > algs;
1731 algs.insert( childId );
1733 dependentChildAlgorithmsRecursive( childId, algs, conditionalBranch );
1736 algs.remove( childId );
1742 void QgsProcessingModelAlgorithm::dependsOnChildAlgorithmsRecursive(
const QString &childId, QSet< QString > &depends )
const
1744 const QgsProcessingModelChildAlgorithm &alg = mChildAlgorithms.value( childId );
1747 const QList< QgsProcessingModelChildDependency > constDependencies = alg.dependencies();
1748 for (
const QgsProcessingModelChildDependency &val : constDependencies )
1750 if ( !depends.contains( val.childId ) )
1752 depends.insert( val.childId );
1753 dependsOnChildAlgorithmsRecursive( val.childId, depends );
1758 QMap<QString, QgsProcessingModelChildParameterSources> childParams = alg.parameterSources();
1759 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
1760 for ( ; paramIt != childParams.constEnd(); ++paramIt )
1762 const auto constValue = paramIt.value();
1763 for (
const QgsProcessingModelChildParameterSource &source : constValue )
1765 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput && !depends.contains( source.outputChildId() ) )
1767 depends.insert( source.outputChildId() );
1768 dependsOnChildAlgorithmsRecursive( source.outputChildId(), depends );
1774 QSet< QString > QgsProcessingModelAlgorithm::dependsOnChildAlgorithms(
const QString &childId )
const
1776 QSet< QString > algs;
1780 algs.insert( childId );
1782 dependsOnChildAlgorithmsRecursive( childId, algs );
1785 algs.remove( childId );
1790 QList<QgsProcessingModelChildDependency> QgsProcessingModelAlgorithm::availableDependenciesForChildAlgorithm(
const QString &childId )
const
1792 QSet< QString > dependent;
1793 if ( !childId.isEmpty() )
1795 dependent.unite( dependentChildAlgorithms( childId ) );
1796 dependent.insert( childId );
1799 QList<QgsProcessingModelChildDependency> res;
1800 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
1802 if ( !dependent.contains( it->childId() ) )
1805 bool hasBranches =
false;
1806 if ( it->algorithm() )
1814 QgsProcessingModelChildDependency alg;
1815 alg.childId = it->childId();
1816 alg.conditionalBranch = def->
name();
1824 QgsProcessingModelChildDependency alg;
1825 alg.childId = it->childId();
1833 bool QgsProcessingModelAlgorithm::validateChildAlgorithm(
const QString &childId, QStringList &issues )
const
1836 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constFind( childId );
1837 if ( childIt != mChildAlgorithms.constEnd() )
1839 if ( !childIt->algorithm() )
1841 issues << QObject::tr(
"Algorithm is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
1850 if ( childIt->parameterSources().contains( def->
name() ) )
1853 const QList< QgsProcessingModelChildParameterSource > sources = childIt->parameterSources().value( def->
name() );
1854 for (
const QgsProcessingModelChildParameterSource &source : sources )
1856 switch ( source.source() )
1858 case QgsProcessingModelChildParameterSource::StaticValue:
1862 issues << QObject::tr(
"Value for <i>%1</i> is not acceptable for this parameter" ).arg( def->
name() );
1866 case QgsProcessingModelChildParameterSource::ModelParameter:
1867 if ( !parameterComponents().contains( source.parameterName() ) )
1870 issues << QObject::tr(
"Model input <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.parameterName(), def->
name() );
1874 case QgsProcessingModelChildParameterSource::ChildOutput:
1875 if ( !childAlgorithms().contains( source.outputChildId() ) )
1878 issues << QObject::tr(
"Child algorithm <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.outputChildId(), def->
name() );
1882 case QgsProcessingModelChildParameterSource::Expression:
1883 case QgsProcessingModelChildParameterSource::ExpressionText:
1884 case QgsProcessingModelChildParameterSource::ModelOutput:
1900 issues << QObject::tr(
"Parameter <i>%1</i> is mandatory" ).arg( def->
name() );
1909 issues << QObject::tr(
"Invalid child ID: <i>%1</i>" ).arg( childId );
1914 bool QgsProcessingModelAlgorithm::canExecute( QString *errorMessage )
const
1916 reattachAlgorithms();
1917 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1918 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1920 if ( !childIt->algorithm() )
1924 *errorMessage = QObject::tr(
"The model you are trying to run contains an algorithm that is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
1932 QString QgsProcessingModelAlgorithm::asPythonCommand(
const QVariantMap ¶meters,
QgsProcessingContext &context )
const
1934 if ( mSourceFile.isEmpty() )
1949 QgsProcessingModelAlgorithm *alg =
new QgsProcessingModelAlgorithm();
1950 alg->loadVariant( toVariant() );
1951 alg->setProvider( provider() );
1952 alg->setSourceFilePath( sourceFilePath() );
1956 QVariantMap QgsProcessingModelAlgorithm::variables()
const
1961 void QgsProcessingModelAlgorithm::setVariables(
const QVariantMap &variables )
1963 mVariables = variables;
1966 QVariantMap QgsProcessingModelAlgorithm::designerParameterValues()
const
1968 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.
virtual Flags flags() const
Returns the flags indicating how and when the algorithm operates and should be exposed to users.
@ 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 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.
virtual QgsProcessingParameterDefinition * clone() const =0
Creates a clone of the parameter definition.
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 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 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.
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...
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
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.