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 )
const
105 const QgsProcessingModelChildParameterSources paramSources = child.parameterSources().value( def->name() );
107 QString expressionText;
108 QVariantList paramParts;
109 for (
const QgsProcessingModelChildParameterSource &source : paramSources )
111 switch ( source.source() )
113 case QgsProcessingModelChildParameterSource::StaticValue:
114 paramParts << source.staticValue();
117 case QgsProcessingModelChildParameterSource::ModelParameter:
118 paramParts << modelParameters.value( source.parameterName() );
121 case QgsProcessingModelChildParameterSource::ChildOutput:
123 QVariantMap linkedChildResults = results.value( source.outputChildId() ).toMap();
124 paramParts << linkedChildResults.value( source.outputName() );
128 case QgsProcessingModelChildParameterSource::Expression:
131 paramParts << exp.evaluate( &expressionContext );
134 case QgsProcessingModelChildParameterSource::ExpressionText:
140 case QgsProcessingModelChildParameterSource::ModelOutput:
145 if ( ! expressionText.isEmpty() )
147 return expressionText;
149 else if ( paramParts.count() == 1 )
150 return paramParts.at( 0 );
156 QVariantMap childParams;
157 const auto constParameterDefinitions = child.algorithm()->parameterDefinitions();
160 if ( !def->isDestination() )
162 if ( !child.parameterSources().contains( def->name() ) )
165 const QVariant value = evaluateSources( def );
166 childParams.insert( def->name(), value );
173 bool isFinalOutput =
false;
174 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
175 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
176 for ( ; outputIt != outputs.constEnd(); ++outputIt )
178 if ( outputIt->childOutputName() == destParam->
name() )
180 QString paramName = child.childId() +
':' + outputIt.key();
181 if ( modelParameters.contains( paramName ) )
183 QVariant value = modelParameters.value( paramName );
189 value = QVariant::fromValue( fromVar );
192 childParams.insert( destParam->
name(), value );
194 isFinalOutput =
true;
199 bool hasExplicitDefinition =
false;
200 if ( !isFinalOutput && child.parameterSources().contains( def->name() ) )
203 const QVariant value = evaluateSources( def );
204 if ( value.isValid() )
206 childParams.insert( def->name(), value );
207 hasExplicitDefinition =
true;
211 if ( !isFinalOutput && !hasExplicitDefinition )
216 bool required =
true;
219 required = childOutputIsRequired( child.childId(), destParam->
name() );
231 bool QgsProcessingModelAlgorithm::childOutputIsRequired(
const QString &childId,
const QString &outputName )
const
234 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
235 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
237 if ( childIt->childId() == childId || !childIt->isActive() )
241 QMap<QString, QgsProcessingModelChildParameterSources> candidateChildParams = childIt->parameterSources();
242 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator childParamIt = candidateChildParams.constBegin();
243 for ( ; childParamIt != candidateChildParams.constEnd(); ++childParamIt )
245 const auto constValue = childParamIt.value();
246 for (
const QgsProcessingModelChildParameterSource &source : constValue )
248 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput
249 && source.outputChildId() == childId
250 && source.outputName() == outputName )
262 QSet< QString > toExecute;
263 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
264 QSet< QString > broken;
265 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
267 if ( childIt->isActive() )
269 if ( childIt->algorithm() )
270 toExecute.insert( childIt->childId() );
272 broken.insert( childIt->childId() );
276 if ( !broken.empty() )
277 throw QgsProcessingException( QCoreApplication::translate(
"QgsProcessingModelAlgorithm",
"Cannot run model, the following algorithms are not available on this system: %1" ).arg( broken.values().join( QLatin1String(
", " ) ) ) );
279 QElapsedTimer totalTime;
285 QVariantMap childResults;
286 QVariantMap childInputs;
290 QVariantMap finalResults;
291 QSet< QString > executed;
292 bool executedAlg =
true;
293 while ( executedAlg && executed.count() < toExecute.count() )
296 for (
const QString &childId : std::as_const( toExecute ) )
301 if ( executed.contains( childId ) )
304 bool canExecute =
true;
305 const QSet< QString > dependencies = dependsOnChildAlgorithms( childId );
306 for (
const QString &dependency : dependencies )
308 if ( !executed.contains( dependency ) )
320 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
321 std::unique_ptr< QgsProcessingAlgorithm > childAlg( child.algorithm()->create( child.configuration() ) );
324 if ( feedback && !skipGenericLogging )
325 feedback->
pushDebugInfo( QObject::tr(
"Prepare algorithm: %1" ).arg( childId ) );
329 << createExpressionContextScopeForChildAlgorithm( childId, context, parameters, childResults );
332 QVariantMap childParams = parametersForChildAlgorithm( child, parameters, childResults, expContext );
333 if ( feedback && !skipGenericLogging )
334 feedback->
setProgressText( QObject::tr(
"Running %1 [%2/%3]" ).arg( child.description() ).arg( executed.count() + 1 ).arg( toExecute.count() ) );
336 childInputs.insert( childId, childParams );
338 for (
auto childParamIt = childParams.constBegin(); childParamIt != childParams.constEnd(); ++childParamIt )
340 params << QStringLiteral(
"%1: %2" ).arg( childParamIt.key(),
341 child.algorithm()->parameterDefinition( childParamIt.key() )->valueAsPythonString( childParamIt.value(), context ) );
344 if ( feedback && !skipGenericLogging )
346 feedback->
pushInfo( QObject::tr(
"Input Parameters:" ) );
347 feedback->
pushCommandInfo( QStringLiteral(
"{ %1 }" ).arg( params.join( QLatin1String(
", " ) ) ) );
350 QElapsedTimer childTime;
354 QVariantMap results = childAlg->run( childParams, context, &modelFeedback, &ok, child.configuration() );
360 childResults.insert( childId, results );
364 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
365 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
366 for ( ; outputIt != outputs.constEnd(); ++outputIt )
368 finalResults.insert( childId +
':' + outputIt->name(), results.value( outputIt->childOutputName() ) );
371 executed.insert( childId );
373 std::function< void(
const QString &,
const QString & )> pruneAlgorithmBranchRecursive;
374 pruneAlgorithmBranchRecursive = [&](
const QString & id,
const QString &branch = QString() )
376 const QSet<QString> toPrune = dependentChildAlgorithms(
id, branch );
377 for (
const QString &targetId : toPrune )
379 if ( executed.contains( targetId ) )
382 executed.insert( targetId );
383 pruneAlgorithmBranchRecursive( targetId, branch );
393 pruneAlgorithmBranchRecursive( childId, outputDef->name() );
401 for (
const QString &candidateId : std::as_const( toExecute ) )
403 if ( executed.contains( candidateId ) )
408 const QgsProcessingModelChildAlgorithm &candidate = mChildAlgorithms[ candidateId ];
409 const QMap<QString, QgsProcessingModelChildParameterSources> candidateParams = candidate.parameterSources();
410 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = candidateParams.constBegin();
412 for ( ; paramIt != candidateParams.constEnd(); ++paramIt )
414 for (
const QgsProcessingModelChildParameterSource &source : paramIt.value() )
416 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput && source.outputChildId() == childId )
419 if ( !results.contains( source.outputName() ) )
424 executed.insert( candidateId );
426 pruneAlgorithmBranchRecursive( candidateId, QString() );
437 childAlg.reset(
nullptr );
438 modelFeedback.setCurrentStep( executed.count() );
439 if ( feedback && !skipGenericLogging )
440 feedback->
pushInfo( QObject::tr(
"OK. Execution took %1 s (%2 outputs)." ).arg( childTime.elapsed() / 1000.0 ).arg( results.count() ) );
447 feedback->
pushDebugInfo( QObject::tr(
"Model processed OK. Executed %1 algorithms total in %2 s." ).arg( executed.count() ).arg( totalTime.elapsed() / 1000.0 ) );
449 mResults = finalResults;
450 mResults.insert( QStringLiteral(
"CHILD_RESULTS" ), childResults );
451 mResults.insert( QStringLiteral(
"CHILD_INPUTS" ), childInputs );
455 QString QgsProcessingModelAlgorithm::sourceFilePath()
const
460 void QgsProcessingModelAlgorithm::setSourceFilePath(
const QString &sourceFile )
462 mSourceFile = sourceFile;
467 QStringList fileDocString;
468 fileDocString << QStringLiteral(
"\"\"\"" );
469 fileDocString << QStringLiteral(
"Model exported as python." );
470 fileDocString << QStringLiteral(
"Name : %1" ).arg( displayName() );
471 fileDocString << QStringLiteral(
"Group : %1" ).arg( group() );
472 fileDocString << QStringLiteral(
"With QGIS : %1" ).arg(
Qgis::versionInt() );
473 fileDocString << QStringLiteral(
"\"\"\"" );
474 fileDocString << QString();
477 QString indent = QString(
' ' ).repeated( indentSize );
478 QString currentIndent;
480 QMap< QString, QString> friendlyChildNames;
481 QMap< QString, QString> friendlyOutputNames;
482 auto safeName = [](
const QString & name,
bool capitalize )->QString
484 QString n = name.toLower().trimmed();
485 QRegularExpression rx( QStringLiteral(
"[^\\sa-z_A-Z0-9]" ) );
486 n.replace( rx, QString() );
487 QRegularExpression rx2( QStringLiteral(
"^\\d*" ) );
488 n.replace( rx2, QString() );
490 n = n.replace(
' ',
'_' );
494 auto uniqueSafeName = [ &safeName ](
const QString & name,
bool capitalize,
const QMap< QString, QString > &friendlyNames )->QString
496 const QString base = safeName( name, capitalize );
497 QString candidate = base;
499 while ( friendlyNames.contains( candidate ) )
502 candidate = QStringLiteral(
"%1_%2" ).arg( base ).arg( i );
507 const QString algorithmClassName = safeName( name(),
true );
509 QSet< QString > toExecute;
510 for (
auto childIt = mChildAlgorithms.constBegin(); childIt != mChildAlgorithms.constEnd(); ++childIt )
512 if ( childIt->isActive() && childIt->algorithm() )
514 toExecute.insert( childIt->childId() );
515 friendlyChildNames.insert( childIt->childId(), uniqueSafeName( childIt->description().isEmpty() ? childIt->childId() : childIt->description(), !childIt->description().isEmpty(), friendlyChildNames ) );
518 const int totalSteps = toExecute.count();
520 QStringList importLines;
521 switch ( outputType )
526 const auto params = parameterDefinitions();
527 importLines.reserve( params.count() + 3 );
528 importLines << QStringLiteral(
"from qgis.core import QgsProcessing" );
529 importLines << QStringLiteral(
"from qgis.core import QgsProcessingAlgorithm" );
530 importLines << QStringLiteral(
"from qgis.core import QgsProcessingMultiStepFeedback" );
532 bool hasAdvancedParams =
false;
536 hasAdvancedParams =
true;
539 if ( !importString.isEmpty() && !importLines.contains( importString ) )
540 importLines << importString;
543 if ( hasAdvancedParams )
544 importLines << QStringLiteral(
"from qgis.core import QgsProcessingParameterDefinition" );
546 lines << QStringLiteral(
"import processing" );
547 lines << QString() << QString();
549 lines << QStringLiteral(
"class %1(QgsProcessingAlgorithm):" ).arg( algorithmClassName );
553 lines << indent + QStringLiteral(
"def initAlgorithm(self, config=None):" );
554 if ( params.empty() )
556 lines << indent + indent + QStringLiteral(
"pass" );
560 lines.reserve( lines.size() + params.size() );
563 std::unique_ptr< QgsProcessingParameterDefinition > defClone( def->clone() );
565 if ( defClone->isDestination() )
567 const QString &friendlyName = !defClone->description().isEmpty() ? uniqueSafeName( defClone->description(),
true, friendlyOutputNames ) : defClone->name();
568 friendlyOutputNames.insert( defClone->name(), friendlyName );
569 defClone->setName( friendlyName );
573 if ( !mParameterComponents.value( defClone->name() ).comment()->description().isEmpty() )
574 lines << indent + indent + QStringLiteral(
"# %1" ).arg( mParameterComponents.value( defClone->name() ).comment()->description() );
579 lines << indent + indent + QStringLiteral(
"param = %1" ).arg( defClone->asPythonString() );
580 lines << indent + indent + QStringLiteral(
"param.setFlags(param.flags() | QgsProcessingParameterDefinition.FlagAdvanced)" );
581 lines << indent + indent + QStringLiteral(
"self.addParameter(param)" );
585 lines << indent + indent + QStringLiteral(
"self.addParameter(%1)" ).arg( defClone->asPythonString() );
591 lines << indent + QStringLiteral(
"def processAlgorithm(self, parameters, context, model_feedback):" );
592 currentIndent = indent + indent;
594 lines << currentIndent + QStringLiteral(
"# Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the" );
595 lines << currentIndent + QStringLiteral(
"# overall progress through the model" );
596 lines << currentIndent + QStringLiteral(
"feedback = QgsProcessingMultiStepFeedback(%1, model_feedback)" ).arg( totalSteps );
604 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
605 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
607 QString name = paramIt.value().parameterName();
608 if ( parameterDefinition( name ) )
611 params.insert( name, parameterDefinition( name )->valueAsPythonString( parameterDefinition( name )->defaultValue(), context ) );
615 if ( !params.isEmpty() )
617 lines << QStringLiteral(
"parameters = {" );
618 for (
auto it = params.constBegin(); it != params.constEnd(); ++it )
620 lines << QStringLiteral(
" '%1':%2," ).arg( it.key(), it.value() );
622 lines << QStringLiteral(
"}" )
626 lines << QStringLiteral(
"context = QgsProcessingContext()" )
627 << QStringLiteral(
"context.setProject(QgsProject.instance())" )
628 << QStringLiteral(
"feedback = QgsProcessingFeedback()" )
637 lines << currentIndent + QStringLiteral(
"results = {}" );
638 lines << currentIndent + QStringLiteral(
"outputs = {}" );
641 QSet< QString > executed;
642 bool executedAlg =
true;
644 while ( executedAlg && executed.count() < toExecute.count() )
647 const auto constToExecute = toExecute;
648 for (
const QString &childId : constToExecute )
650 if ( executed.contains( childId ) )
653 bool canExecute =
true;
654 const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms( childId );
655 for (
const QString &dependency : constDependsOnChildAlgorithms )
657 if ( !executed.contains( dependency ) )
669 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms[ childId ];
676 if ( def->isDestination() )
681 bool isFinalOutput =
false;
682 QMap<QString, QgsProcessingModelOutput> outputs = child.modelOutputs();
683 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
684 for ( ; outputIt != outputs.constEnd(); ++outputIt )
686 if ( outputIt->childOutputName() == destParam->
name() )
688 QString paramName = child.childId() +
':' + outputIt.key();
689 paramName = friendlyOutputNames.value( paramName, paramName );
690 childParams.insert( destParam->
name(), QStringLiteral(
"parameters['%1']" ).arg( paramName ) );
691 isFinalOutput =
true;
696 if ( !isFinalOutput )
701 bool required =
true;
704 required = childOutputIsRequired( child.childId(), destParam->
name() );
711 childParams.insert( destParam->
name(), QStringLiteral(
"QgsProcessing.TEMPORARY_OUTPUT" ) );
717 lines << child.asPythonCode( outputType, childParams, currentIndent.size(), indentSize, friendlyChildNames, friendlyOutputNames );
719 if ( currentStep < totalSteps )
722 lines << currentIndent + QStringLiteral(
"feedback.setCurrentStep(%1)" ).arg( currentStep );
723 lines << currentIndent + QStringLiteral(
"if feedback.isCanceled():" );
724 lines << currentIndent + indent + QStringLiteral(
"return {}" );
727 executed.insert( childId );
731 switch ( outputType )
734 lines << currentIndent + QStringLiteral(
"return results" );
738 lines << indent + QStringLiteral(
"def name(self):" );
739 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelName );
741 lines << indent + QStringLiteral(
"def displayName(self):" );
742 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelName );
746 lines << indent + QStringLiteral(
"def group(self):" );
747 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelGroup );
749 lines << indent + QStringLiteral(
"def groupId(self):" );
750 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( mModelGroupId );
754 if ( !shortHelpString().isEmpty() )
756 lines << indent + QStringLiteral(
"def shortHelpString(self):" );
757 lines << indent + indent + QStringLiteral(
"return \"\"\"%1\"\"\"" ).arg( shortHelpString() );
760 if ( !helpUrl().isEmpty() )
762 lines << indent + QStringLiteral(
"def helpUrl(self):" );
763 lines << indent + indent + QStringLiteral(
"return '%1'" ).arg( helpUrl() );
768 lines << indent + QStringLiteral(
"def createInstance(self):" );
769 lines << indent + indent + QStringLiteral(
"return %1()" ).arg( algorithmClassName );
772 static QMap< QString, QString > sAdditionalImports
774 { QStringLiteral(
"QgsCoordinateReferenceSystem" ), QStringLiteral(
"from qgis.core import QgsCoordinateReferenceSystem" ) },
775 { QStringLiteral(
"QgsExpression" ), QStringLiteral(
"from qgis.core import QgsExpression" ) },
776 { QStringLiteral(
"QgsRectangle" ), QStringLiteral(
"from qgis.core import QgsRectangle" ) },
777 { QStringLiteral(
"QgsReferencedRectangle" ), QStringLiteral(
"from qgis.core import QgsReferencedRectangle" ) },
778 { QStringLiteral(
"QgsPoint" ), QStringLiteral(
"from qgis.core import QgsPoint" ) },
779 { QStringLiteral(
"QgsReferencedPoint" ), QStringLiteral(
"from qgis.core import QgsReferencedPoint" ) },
780 { QStringLiteral(
"QgsProperty" ), QStringLiteral(
"from qgis.core import QgsProperty" ) },
781 { QStringLiteral(
"QgsRasterLayer" ), QStringLiteral(
"from qgis.core import QgsRasterLayer" ) },
782 { QStringLiteral(
"QgsMeshLayer" ), QStringLiteral(
"from qgis.core import QgsMeshLayer" ) },
783 { QStringLiteral(
"QgsVectorLayer" ), QStringLiteral(
"from qgis.core import QgsVectorLayer" ) },
784 { QStringLiteral(
"QgsMapLayer" ), QStringLiteral(
"from qgis.core import QgsMapLayer" ) },
785 { QStringLiteral(
"QgsProcessingFeatureSourceDefinition" ), QStringLiteral(
"from qgis.core import QgsProcessingFeatureSourceDefinition" ) },
786 { QStringLiteral(
"QgsPointXY" ), QStringLiteral(
"from qgis.core import QgsPointXY" ) },
787 { QStringLiteral(
"QgsReferencedPointXY" ), QStringLiteral(
"from qgis.core import QgsReferencedPointXY" ) },
788 { QStringLiteral(
"QgsGeometry" ), QStringLiteral(
"from qgis.core import QgsGeometry" ) },
789 { QStringLiteral(
"QgsProcessingOutputLayerDefinition" ), QStringLiteral(
"from qgis.core import QgsProcessingOutputLayerDefinition" ) },
790 { QStringLiteral(
"QColor" ), QStringLiteral(
"from qgis.PyQt.QtGui import QColor" ) },
791 { QStringLiteral(
"QDateTime" ), QStringLiteral(
"from qgis.PyQt.QtCore import QDateTime" ) },
792 { QStringLiteral(
"QDate" ), QStringLiteral(
"from qgis.PyQt.QtCore import QDate" ) },
793 { QStringLiteral(
"QTime" ), QStringLiteral(
"from qgis.PyQt.QtCore import QTime" ) },
796 for (
auto it = sAdditionalImports.constBegin(); it != sAdditionalImports.constEnd(); ++it )
798 if ( importLines.contains( it.value() ) )
805 for (
const QString &line : std::as_const( lines ) )
807 if ( line.contains( it.key() ) )
815 importLines << it.value();
819 lines = fileDocString + importLines + lines;
828 QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> QgsProcessingModelAlgorithm::variablesForChildAlgorithm(
const QString &childId,
QgsProcessingContext &context,
const QVariantMap &modelParameters,
const QVariantMap &results )
const
830 QMap<QString, QgsProcessingModelAlgorithm::VariableDefinition> variables;
832 auto safeName = [](
const QString & name )->QString
835 return s.replace( QRegularExpression( QStringLiteral(
"[\\s'\"\\(\\):\\.]" ) ), QStringLiteral(
"_" ) );
869 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
874 switch ( source.source() )
876 case QgsProcessingModelChildParameterSource::ModelParameter:
878 name = source.parameterName();
879 value = modelParameters.value( source.parameterName() );
880 description = parameterDefinition( source.parameterName() )->description();
883 case QgsProcessingModelChildParameterSource::ChildOutput:
885 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
886 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
887 source.outputChildId() : child.description(), source.outputName() );
890 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
891 child.description() );
893 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
897 case QgsProcessingModelChildParameterSource::Expression:
898 case QgsProcessingModelChildParameterSource::ExpressionText:
899 case QgsProcessingModelChildParameterSource::StaticValue:
900 case QgsProcessingModelChildParameterSource::ModelOutput:
903 variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
907 sources = availableSourcesForChild( childId, QStringList()
914 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
920 switch ( source.source() )
922 case QgsProcessingModelChildParameterSource::ModelParameter:
924 name = source.parameterName();
925 value = modelParameters.value( source.parameterName() );
926 description = parameterDefinition( source.parameterName() )->description();
929 case QgsProcessingModelChildParameterSource::ChildOutput:
931 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
932 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
933 source.outputChildId() : child.description(), source.outputName() );
934 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
937 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
938 child.description() );
943 case QgsProcessingModelChildParameterSource::Expression:
944 case QgsProcessingModelChildParameterSource::ExpressionText:
945 case QgsProcessingModelChildParameterSource::StaticValue:
946 case QgsProcessingModelChildParameterSource::ModelOutput:
954 value = fromVar.
sink;
960 QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( value ) );
964 variables.insert( safeName( name ), VariableDefinition( QVariant::fromValue( layer ), source, description ) );
965 variables.insert( safeName( QStringLiteral(
"%1_minx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMinimum() : QVariant(), source, QObject::tr(
"Minimum X of %1" ).arg( description ) ) );
966 variables.insert( safeName( QStringLiteral(
"%1_miny" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMinimum() : QVariant(), source, QObject::tr(
"Minimum Y of %1" ).arg( description ) ) );
967 variables.insert( safeName( QStringLiteral(
"%1_maxx" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
xMaximum() : QVariant(), source, QObject::tr(
"Maximum X of %1" ).arg( description ) ) );
968 variables.insert( safeName( QStringLiteral(
"%1_maxy" ).arg( name ) ), VariableDefinition( layer ? layer->
extent().
yMaximum() : QVariant(), source, QObject::tr(
"Maximum Y of %1" ).arg( description ) ) );
971 sources = availableSourcesForChild( childId, QStringList()
973 for (
const QgsProcessingModelChildParameterSource &source : std::as_const( sources ) )
979 switch ( source.source() )
981 case QgsProcessingModelChildParameterSource::ModelParameter:
983 name = source.parameterName();
984 value = modelParameters.value( source.parameterName() );
985 description = parameterDefinition( source.parameterName() )->description();
988 case QgsProcessingModelChildParameterSource::ChildOutput:
990 const QgsProcessingModelChildAlgorithm &child = mChildAlgorithms.value( source.outputChildId() );
991 name = QStringLiteral(
"%1_%2" ).arg( child.description().isEmpty() ?
992 source.outputChildId() : child.description(), source.outputName() );
993 value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
996 description = QObject::tr(
"Output '%1' from algorithm '%2'" ).arg( alg->outputDefinition( source.outputName() )->description(),
997 child.description() );
1002 case QgsProcessingModelChildParameterSource::Expression:
1003 case QgsProcessingModelChildParameterSource::ExpressionText:
1004 case QgsProcessingModelChildParameterSource::StaticValue:
1005 case QgsProcessingModelChildParameterSource::ModelOutput:
1019 value = fromVar.
sink;
1025 if (
QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( value ) ) )
1027 featureSource = layer;
1029 if ( !featureSource )
1035 variables.insert( safeName( name ), VariableDefinition( value, source, description ) );
1036 variables.insert( safeName( QStringLiteral(
"%1_minx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMinimum() : QVariant(), source, QObject::tr(
"Minimum X of %1" ).arg( description ) ) );
1037 variables.insert( safeName( QStringLiteral(
"%1_miny" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMinimum() : QVariant(), source, QObject::tr(
"Minimum Y of %1" ).arg( description ) ) );
1038 variables.insert( safeName( QStringLiteral(
"%1_maxx" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
xMaximum() : QVariant(), source, QObject::tr(
"Maximum X of %1" ).arg( description ) ) );
1039 variables.insert( safeName( QStringLiteral(
"%1_maxy" ).arg( name ) ), VariableDefinition( featureSource ? featureSource->
sourceExtent().
yMaximum() : QVariant(), source, QObject::tr(
"Maximum Y of %1" ).arg( description ) ) );
1045 QgsExpressionContextScope *QgsProcessingModelAlgorithm::createExpressionContextScopeForChildAlgorithm(
const QString &childId,
QgsProcessingContext &context,
const QVariantMap &modelParameters,
const QVariantMap &results )
const
1047 std::unique_ptr< QgsExpressionContextScope > scope(
new QgsExpressionContextScope( QStringLiteral(
"algorithm_inputs" ) ) );
1048 QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition> variables = variablesForChildAlgorithm( childId, context, modelParameters, results );
1049 QMap< QString, QgsProcessingModelAlgorithm::VariableDefinition>::const_iterator varIt = variables.constBegin();
1050 for ( ; varIt != variables.constEnd(); ++varIt )
1054 return scope.release();
1057 QgsProcessingModelChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild(
const QString &childId,
const QStringList ¶meterTypes,
const QStringList &outputTypes,
const QList<int> &dataTypes )
const
1059 QgsProcessingModelChildParameterSources sources;
1062 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
1063 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
1069 if ( parameterTypes.contains( def->
type() ) )
1071 if ( !dataTypes.isEmpty() )
1087 bool ok = sourceDef->
dataTypes().isEmpty();
1088 const auto constDataTypes = sourceDef->
dataTypes();
1089 for (
int type : constDataTypes )
1104 sources << QgsProcessingModelChildParameterSource::fromModelParameter( paramIt->parameterName() );
1108 QSet< QString > dependents;
1109 if ( !childId.isEmpty() )
1111 dependents = dependentChildAlgorithms( childId );
1112 dependents << childId;
1115 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1116 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1118 if ( dependents.contains( childIt->childId() ) )
1128 if ( outputTypes.contains( out->type() ) )
1130 if ( !dataTypes.isEmpty() )
1136 if ( !vectorOutputIsCompatibleType( dataTypes, vectorOut->
dataType() ) )
1143 sources << QgsProcessingModelChildParameterSource::fromChildOutput( childIt->childId(), out->name() );
1151 QVariantMap QgsProcessingModelAlgorithm::helpContent()
const
1153 return mHelpContent;
1156 void QgsProcessingModelAlgorithm::setHelpContent(
const QVariantMap &helpContent )
1158 mHelpContent = helpContent;
1161 void QgsProcessingModelAlgorithm::setName(
const QString &name )
1166 void QgsProcessingModelAlgorithm::setGroup(
const QString &group )
1168 mModelGroup = group;
1171 bool QgsProcessingModelAlgorithm::validate( QStringList &issues )
const
1176 if ( mChildAlgorithms.empty() )
1179 issues << QObject::tr(
"Model does not contain any algorithms" );
1182 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
1184 QStringList childIssues;
1185 res = validateChildAlgorithm( it->childId(), childIssues ) && res;
1187 for (
const QString &issue : std::as_const( childIssues ) )
1189 issues << QStringLiteral(
"<b>%1</b>: %2" ).arg( it->description(), issue );
1195 QMap<QString, QgsProcessingModelChildAlgorithm> QgsProcessingModelAlgorithm::childAlgorithms()
const
1197 return mChildAlgorithms;
1200 void QgsProcessingModelAlgorithm::setParameterComponents(
const QMap<QString, QgsProcessingModelParameter> ¶meterComponents )
1202 mParameterComponents = parameterComponents;
1205 void QgsProcessingModelAlgorithm::setParameterComponent(
const QgsProcessingModelParameter &component )
1207 mParameterComponents.insert( component.parameterName(), component );
1210 QgsProcessingModelParameter &QgsProcessingModelAlgorithm::parameterComponent(
const QString &name )
1212 if ( !mParameterComponents.contains( name ) )
1214 QgsProcessingModelParameter &component = mParameterComponents[ name ];
1215 component.setParameterName( name );
1218 return mParameterComponents[ name ];
1221 QList< QgsProcessingModelParameter > QgsProcessingModelAlgorithm::orderedParameters()
const
1223 QList< QgsProcessingModelParameter > res;
1224 QSet< QString > found;
1225 for (
const QString ¶meter : mParameterOrder )
1227 if ( mParameterComponents.contains( parameter ) )
1229 res << mParameterComponents.value( parameter );
1235 for (
auto it = mParameterComponents.constBegin(); it != mParameterComponents.constEnd(); ++it )
1237 if ( !found.contains( it.key() ) )
1245 void QgsProcessingModelAlgorithm::setParameterOrder(
const QStringList &order )
1247 mParameterOrder = order;
1250 void QgsProcessingModelAlgorithm::updateDestinationParameters()
1253 QMutableListIterator<const QgsProcessingParameterDefinition *> it( mParameters );
1254 while ( it.hasNext() )
1264 qDeleteAll( mOutputs );
1268 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1269 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1271 QMap<QString, QgsProcessingModelOutput> outputs = childIt->modelOutputs();
1272 QMap<QString, QgsProcessingModelOutput>::const_iterator outputIt = outputs.constBegin();
1273 for ( ; outputIt != outputs.constEnd(); ++outputIt )
1275 if ( !childIt->isActive() || !childIt->algorithm() )
1283 std::unique_ptr< QgsProcessingParameterDefinition > param( source->
clone() );
1287 if ( outputIt->isMandatory() )
1289 param->setName( outputIt->childId() +
':' + outputIt->name() );
1290 param->setDescription( outputIt->description() );
1291 param->setDefaultValue( outputIt->defaultValue() );
1294 if ( addParameter( param.release() ) && newDestParam )
1301 newDestParam->mOriginalProvider = provider;
1308 void QgsProcessingModelAlgorithm::addGroupBox(
const QgsProcessingModelGroupBox &groupBox )
1310 mGroupBoxes.insert( groupBox.uuid(), groupBox );
1313 QList<QgsProcessingModelGroupBox> QgsProcessingModelAlgorithm::groupBoxes()
const
1315 return mGroupBoxes.values();
1318 void QgsProcessingModelAlgorithm::removeGroupBox(
const QString &uuid )
1320 mGroupBoxes.remove( uuid );
1323 QVariant QgsProcessingModelAlgorithm::toVariant()
const
1326 map.insert( QStringLiteral(
"model_name" ), mModelName );
1327 map.insert( QStringLiteral(
"model_group" ), mModelGroup );
1328 map.insert( QStringLiteral(
"help" ), mHelpContent );
1330 QVariantMap childMap;
1331 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1332 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1334 childMap.insert( childIt.key(), childIt.value().toVariant() );
1336 map.insert( QStringLiteral(
"children" ), childMap );
1338 QVariantMap paramMap;
1339 QMap< QString, QgsProcessingModelParameter >::const_iterator paramIt = mParameterComponents.constBegin();
1340 for ( ; paramIt != mParameterComponents.constEnd(); ++paramIt )
1342 paramMap.insert( paramIt.key(), paramIt.value().toVariant() );
1344 map.insert( QStringLiteral(
"parameters" ), paramMap );
1346 QVariantMap paramDefMap;
1351 map.insert( QStringLiteral(
"parameterDefinitions" ), paramDefMap );
1353 QVariantList groupBoxDefs;
1354 for (
auto it = mGroupBoxes.constBegin(); it != mGroupBoxes.constEnd(); ++it )
1356 groupBoxDefs.append( it.value().toVariant() );
1358 map.insert( QStringLiteral(
"groupBoxes" ), groupBoxDefs );
1360 map.insert( QStringLiteral(
"modelVariables" ), mVariables );
1362 map.insert( QStringLiteral(
"designerParameterValues" ), mDesignerParameterValues );
1364 map.insert( QStringLiteral(
"parameterOrder" ), mParameterOrder );
1369 bool QgsProcessingModelAlgorithm::loadVariant(
const QVariant &model )
1371 QVariantMap map = model.toMap();
1373 mModelName = map.value( QStringLiteral(
"model_name" ) ).toString();
1374 mModelGroup = map.value( QStringLiteral(
"model_group" ) ).toString();
1375 mModelGroupId = map.value( QStringLiteral(
"model_group" ) ).toString();
1376 mHelpContent = map.value( QStringLiteral(
"help" ) ).toMap();
1378 mVariables = map.value( QStringLiteral(
"modelVariables" ) ).toMap();
1379 mDesignerParameterValues = map.value( QStringLiteral(
"designerParameterValues" ) ).toMap();
1381 mParameterOrder = map.value( QStringLiteral(
"parameterOrder" ) ).toStringList();
1383 mChildAlgorithms.clear();
1384 QVariantMap childMap = map.value( QStringLiteral(
"children" ) ).toMap();
1385 QVariantMap::const_iterator childIt = childMap.constBegin();
1386 for ( ; childIt != childMap.constEnd(); ++childIt )
1388 QgsProcessingModelChildAlgorithm child;
1392 if ( !child.loadVariant( childIt.value() ) )
1395 mChildAlgorithms.insert( child.childId(), child );
1398 mParameterComponents.clear();
1399 QVariantMap paramMap = map.value( QStringLiteral(
"parameters" ) ).toMap();
1400 QVariantMap::const_iterator paramIt = paramMap.constBegin();
1401 for ( ; paramIt != paramMap.constEnd(); ++paramIt )
1403 QgsProcessingModelParameter param;
1404 if ( !param.loadVariant( paramIt.value().toMap() ) )
1407 mParameterComponents.insert( param.parameterName(), param );
1410 qDeleteAll( mParameters );
1411 mParameters.clear();
1412 QVariantMap paramDefMap = map.value( QStringLiteral(
"parameterDefinitions" ) ).toMap();
1414 auto addParam = [ = ](
const QVariant & value )
1422 if ( param->name() == QLatin1String(
"VERBOSE_LOG" ) )
1426 param->setHelp( mHelpContent.value( param->name() ).toString() );
1429 addParameter( param.release() );
1433 QVariantMap map = value.toMap();
1434 QString type = map.value( QStringLiteral(
"parameter_type" ) ).toString();
1435 QString name = map.value( QStringLiteral(
"name" ) ).toString();
1437 QgsMessageLog::logMessage( QCoreApplication::translate(
"Processing",
"Could not load parameter %1 of type %2." ).arg( name, type ), QCoreApplication::translate(
"Processing",
"Processing" ) );
1441 QSet< QString > loadedParams;
1443 for (
const QString &name : std::as_const( mParameterOrder ) )
1445 if ( paramDefMap.contains( name ) )
1447 addParam( paramDefMap.value( name ) );
1448 loadedParams << name;
1452 QVariantMap::const_iterator paramDefIt = paramDefMap.constBegin();
1453 for ( ; paramDefIt != paramDefMap.constEnd(); ++paramDefIt )
1455 if ( !loadedParams.contains( paramDefIt.key() ) )
1456 addParam( paramDefIt.value() );
1459 mGroupBoxes.clear();
1460 const QVariantList groupBoxList = map.value( QStringLiteral(
"groupBoxes" ) ).toList();
1461 for (
const QVariant &groupBoxDef : groupBoxList )
1463 QgsProcessingModelGroupBox groupBox;
1464 groupBox.loadVariant( groupBoxDef.toMap() );
1465 mGroupBoxes.insert( groupBox.uuid(), groupBox );
1468 updateDestinationParameters();
1473 bool QgsProcessingModelAlgorithm::vectorOutputIsCompatibleType(
const QList<int> &acceptableDataTypes,
QgsProcessing::SourceType outputType )
1478 return ( acceptableDataTypes.empty()
1479 || acceptableDataTypes.contains( outputType )
1490 void QgsProcessingModelAlgorithm::reattachAlgorithms()
const
1492 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1493 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1495 if ( !childIt->algorithm() )
1496 childIt->reattach();
1500 bool QgsProcessingModelAlgorithm::toFile(
const QString &path )
const
1502 QDomDocument doc = QDomDocument( QStringLiteral(
"model" ) );
1504 doc.appendChild( elem );
1507 if ( file.open( QFile::WriteOnly | QFile::Truncate ) )
1509 QTextStream stream( &file );
1510 doc.save( stream, 2 );
1517 bool QgsProcessingModelAlgorithm::fromFile(
const QString &path )
1522 if ( file.open( QFile::ReadOnly ) )
1524 if ( !doc.setContent( &file ) )
1535 return loadVariant( props );
1538 void QgsProcessingModelAlgorithm::setChildAlgorithms(
const QMap<QString, QgsProcessingModelChildAlgorithm> &childAlgorithms )
1540 mChildAlgorithms = childAlgorithms;
1541 updateDestinationParameters();
1544 void QgsProcessingModelAlgorithm::setChildAlgorithm(
const QgsProcessingModelChildAlgorithm &
algorithm )
1547 updateDestinationParameters();
1550 QString QgsProcessingModelAlgorithm::addChildAlgorithm( QgsProcessingModelChildAlgorithm &
algorithm )
1552 if (
algorithm.childId().isEmpty() || mChildAlgorithms.contains(
algorithm.childId() ) )
1556 updateDestinationParameters();
1560 QgsProcessingModelChildAlgorithm &QgsProcessingModelAlgorithm::childAlgorithm(
const QString &childId )
1562 return mChildAlgorithms[ childId ];
1565 bool QgsProcessingModelAlgorithm::removeChildAlgorithm(
const QString &
id )
1567 if ( !dependentChildAlgorithms(
id ).isEmpty() )
1570 mChildAlgorithms.remove(
id );
1571 updateDestinationParameters();
1575 void QgsProcessingModelAlgorithm::deactivateChildAlgorithm(
const QString &
id )
1577 const auto constDependentChildAlgorithms = dependentChildAlgorithms(
id );
1578 for (
const QString &child : constDependentChildAlgorithms )
1580 childAlgorithm( child ).setActive(
false );
1582 childAlgorithm(
id ).setActive(
false );
1583 updateDestinationParameters();
1586 bool QgsProcessingModelAlgorithm::activateChildAlgorithm(
const QString &
id )
1588 const auto constDependsOnChildAlgorithms = dependsOnChildAlgorithms(
id );
1589 for (
const QString &child : constDependsOnChildAlgorithms )
1591 if ( !childAlgorithm( child ).isActive() )
1594 childAlgorithm(
id ).setActive(
true );
1595 updateDestinationParameters();
1601 if ( addParameter( definition ) )
1602 mParameterComponents.insert( definition->
name(), component );
1607 removeParameter( definition->
name() );
1608 addParameter( definition );
1611 void QgsProcessingModelAlgorithm::removeModelParameter(
const QString &name )
1613 removeParameter( name );
1614 mParameterComponents.remove( name );
1617 bool QgsProcessingModelAlgorithm::childAlgorithmsDependOnParameter(
const QString &name )
const
1619 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1620 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1623 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
1624 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
1625 for ( ; paramIt != childParams.constEnd(); ++paramIt )
1627 const auto constValue = paramIt.value();
1628 for (
const QgsProcessingModelChildParameterSource &source : constValue )
1630 if ( source.source() == QgsProcessingModelChildParameterSource::ModelParameter
1631 && source.parameterName() == name )
1641 bool QgsProcessingModelAlgorithm::otherParametersDependOnParameter(
const QString &name )
const
1643 const auto constMParameters = mParameters;
1646 if ( def->
name() == name )
1655 QMap<QString, QgsProcessingModelParameter> QgsProcessingModelAlgorithm::parameterComponents()
const
1657 return mParameterComponents;
1660 void QgsProcessingModelAlgorithm::dependentChildAlgorithmsRecursive(
const QString &childId, QSet<QString> &depends,
const QString &branch )
const
1662 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1663 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1665 if ( depends.contains( childIt->childId() ) )
1669 const QList< QgsProcessingModelChildDependency > constDependencies = childIt->dependencies();
1670 bool hasDependency =
false;
1671 for (
const QgsProcessingModelChildDependency &dep : constDependencies )
1673 if ( dep.childId == childId && ( branch.isEmpty() || dep.conditionalBranch == branch ) )
1675 hasDependency =
true;
1680 if ( hasDependency )
1682 depends.insert( childIt->childId() );
1683 dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
1688 QMap<QString, QgsProcessingModelChildParameterSources> childParams = childIt->parameterSources();
1689 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
1690 for ( ; paramIt != childParams.constEnd(); ++paramIt )
1692 const auto constValue = paramIt.value();
1693 for (
const QgsProcessingModelChildParameterSource &source : constValue )
1695 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput
1696 && source.outputChildId() == childId )
1698 depends.insert( childIt->childId() );
1699 dependentChildAlgorithmsRecursive( childIt->childId(), depends, branch );
1707 QSet<QString> QgsProcessingModelAlgorithm::dependentChildAlgorithms(
const QString &childId,
const QString &conditionalBranch )
const
1709 QSet< QString > algs;
1713 algs.insert( childId );
1715 dependentChildAlgorithmsRecursive( childId, algs, conditionalBranch );
1718 algs.remove( childId );
1724 void QgsProcessingModelAlgorithm::dependsOnChildAlgorithmsRecursive(
const QString &childId, QSet< QString > &depends )
const
1726 const QgsProcessingModelChildAlgorithm &alg = mChildAlgorithms.value( childId );
1729 const QList< QgsProcessingModelChildDependency > constDependencies = alg.dependencies();
1730 for (
const QgsProcessingModelChildDependency &val : constDependencies )
1732 if ( !depends.contains( val.childId ) )
1734 depends.insert( val.childId );
1735 dependsOnChildAlgorithmsRecursive( val.childId, depends );
1740 QMap<QString, QgsProcessingModelChildParameterSources> childParams = alg.parameterSources();
1741 QMap<QString, QgsProcessingModelChildParameterSources>::const_iterator paramIt = childParams.constBegin();
1742 for ( ; paramIt != childParams.constEnd(); ++paramIt )
1744 const auto constValue = paramIt.value();
1745 for (
const QgsProcessingModelChildParameterSource &source : constValue )
1747 if ( source.source() == QgsProcessingModelChildParameterSource::ChildOutput && !depends.contains( source.outputChildId() ) )
1749 depends.insert( source.outputChildId() );
1750 dependsOnChildAlgorithmsRecursive( source.outputChildId(), depends );
1756 QSet< QString > QgsProcessingModelAlgorithm::dependsOnChildAlgorithms(
const QString &childId )
const
1758 QSet< QString > algs;
1762 algs.insert( childId );
1764 dependsOnChildAlgorithmsRecursive( childId, algs );
1767 algs.remove( childId );
1772 QList<QgsProcessingModelChildDependency> QgsProcessingModelAlgorithm::availableDependenciesForChildAlgorithm(
const QString &childId )
const
1774 QSet< QString > dependent;
1775 if ( !childId.isEmpty() )
1777 dependent.unite( dependentChildAlgorithms( childId ) );
1778 dependent.insert( childId );
1781 QList<QgsProcessingModelChildDependency> res;
1782 for (
auto it = mChildAlgorithms.constBegin(); it != mChildAlgorithms.constEnd(); ++it )
1784 if ( !dependent.contains( it->childId() ) )
1787 bool hasBranches =
false;
1788 if ( it->algorithm() )
1796 QgsProcessingModelChildDependency alg;
1797 alg.childId = it->childId();
1798 alg.conditionalBranch = def->
name();
1806 QgsProcessingModelChildDependency alg;
1807 alg.childId = it->childId();
1815 bool QgsProcessingModelAlgorithm::validateChildAlgorithm(
const QString &childId, QStringList &issues )
const
1818 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constFind( childId );
1819 if ( childIt != mChildAlgorithms.constEnd() )
1821 if ( !childIt->algorithm() )
1823 issues << QObject::tr(
"Algorithm is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
1832 if ( childIt->parameterSources().contains( def->
name() ) )
1835 const QList< QgsProcessingModelChildParameterSource > sources = childIt->parameterSources().value( def->
name() );
1836 for (
const QgsProcessingModelChildParameterSource &source : sources )
1838 switch ( source.source() )
1840 case QgsProcessingModelChildParameterSource::StaticValue:
1844 issues << QObject::tr(
"Value for <i>%1</i> is not acceptable for this parameter" ).arg( def->
name() );
1848 case QgsProcessingModelChildParameterSource::ModelParameter:
1849 if ( !parameterComponents().contains( source.parameterName() ) )
1852 issues << QObject::tr(
"Model input <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.parameterName(), def->
name() );
1856 case QgsProcessingModelChildParameterSource::ChildOutput:
1857 if ( !childAlgorithms().contains( source.outputChildId() ) )
1860 issues << QObject::tr(
"Child algorithm <i>%1</i> used for parameter <i>%2</i> does not exist" ).arg( source.outputChildId(), def->
name() );
1864 case QgsProcessingModelChildParameterSource::Expression:
1865 case QgsProcessingModelChildParameterSource::ExpressionText:
1866 case QgsProcessingModelChildParameterSource::ModelOutput:
1882 issues << QObject::tr(
"Parameter <i>%1</i> is mandatory" ).arg( def->
name() );
1891 issues << QObject::tr(
"Invalid child ID: <i>%1</i>" ).arg( childId );
1896 bool QgsProcessingModelAlgorithm::canExecute( QString *errorMessage )
const
1898 reattachAlgorithms();
1899 QMap< QString, QgsProcessingModelChildAlgorithm >::const_iterator childIt = mChildAlgorithms.constBegin();
1900 for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
1902 if ( !childIt->algorithm() )
1906 *errorMessage = QObject::tr(
"The model you are trying to run contains an algorithm that is not available: <i>%1</i>" ).arg( childIt->algorithmId() );
1914 QString QgsProcessingModelAlgorithm::asPythonCommand(
const QVariantMap ¶meters,
QgsProcessingContext &context )
const
1916 if ( mSourceFile.isEmpty() )
1931 QgsProcessingModelAlgorithm *alg =
new QgsProcessingModelAlgorithm();
1932 alg->loadVariant( toVariant() );
1933 alg->setProvider( provider() );
1934 alg->setSourceFilePath( sourceFilePath() );
1938 QVariantMap QgsProcessingModelAlgorithm::variables()
const
1943 void QgsProcessingModelAlgorithm::setVariables(
const QVariantMap &variables )
1945 mVariables = variables;
1948 QVariantMap QgsProcessingModelAlgorithm::designerParameterValues()
const
1950 return mDesignerParameterValues;
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, Capitalization capitalization)
Converts a string by applying capitalization rules to the string.
@ UpperCamelCase
Convert the string to upper camel case. Note that this method does not unaccent characters.
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
QList< const QgsProcessingOutputDefinition * > QgsProcessingOutputDefinitions
List of processing parameters.
QList< const QgsProcessingParameterDefinition * > QgsProcessingParameterDefinitions
List of processing parameters.
Single variable definition for use within a QgsExpressionContextScope.