Create specific expression context scope for child algorithms

Contains variables for model parameters, algorithm results for
other child algorithms which are not dependent on the
algorithm.

Allows removal of final pieces of ModelerAlgorithm code
This commit is contained in:
Nyall Dawson 2017-07-03 21:25:04 +10:00
parent d8086e549d
commit 82ef7d2a89
14 changed files with 184 additions and 273 deletions

View File

@ -877,6 +877,13 @@ Copies are protected to avoid slicing
:rtype: list of QgsProcessingModelAlgorithm.ChildParameterSource
%End
QgsExpressionContextScope *createExpressionContextScopeForChildAlgorithm( const QString &childId, QgsProcessingContext &context, const QVariantMap &modelParameters = QVariantMap(),
const QVariantMap &results = QVariantMap() ) const /Factory/;
%Docstring
Creates a new expression context scope for a child algorithm within the model.
:rtype: QgsExpressionContextScope
%End
protected:
virtual QVariantMap processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback );

View File

@ -343,27 +343,6 @@ class ParameterNumber(Parameter):
variables['@%s_max' % name] = stats.maximumValue
return variables
def evaluateForModeler(self, value, model):
if isinstance(value, numbers.Number):
return value
variables = {}
for param in model.parameters:
if isinstance(param, ParameterNumber):
variables["@" + param.name()] = param.value
if isinstance(param, (ParameterRaster, ParameterVector)):
variables.update(self._layerVariables(param))
for alg in list(model.algs.values()):
for out in alg.algorithm.outputs:
if isinstance(out, OutputNumber):
variables["@%s_%s" % (alg.name(), out.name)] = out.value
if isinstance(out, (OutputRaster, OutputVector)):
variables.update(self._layerVariables(out, alg))
for k, v in list(variables.items()):
value = value.replace(k, str(v))
return value
class ParameterRange(Parameter):

View File

@ -34,8 +34,8 @@ from qgis.PyQt.QtWidgets import QDialog, QTreeWidgetItem
from qgis.core import (QgsMessageLog,
QgsProcessingUtils,
QgsProcessingParameterDefinition)
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
QgsProcessingParameterDefinition,
QgsProcessingModelAlgorithm)
pluginPath = os.path.split(os.path.dirname(__file__))[0]
WIDGET, BASE = uic.loadUiType(
@ -55,7 +55,7 @@ class HelpEditionDialog(BASE, WIDGET):
self.alg = alg
self.descriptions = {}
if isinstance(self.alg, ModelerAlgorithm):
if isinstance(self.alg, QgsProcessingModelAlgorithm):
self.descriptions = self.alg.helpContent()
else:
if self.alg.descriptionFile is not None:

View File

@ -36,14 +36,9 @@ from qgis.PyQt.QtWidgets import QDialog
from qgis.core import (QgsExpression,
QgsProcessingParameterNumber,
QgsProcessingOutputNumber,
QgsProcessingOutputVectorLayer,
QgsProcessingOutputRasterLayer,
QgsProcessingParameterFeatureSource,
QgsProcessingModelAlgorithm,
QgsProcessingParameterRasterLayer)
QgsProcessingModelAlgorithm)
from qgis.gui import QgsExpressionBuilderDialog
from processing.modeler.ModelerAlgorithm import ValueFromInput, ValueFromOutput, CompoundValue
from processing.tools.dataobjects import createExpressionContext
from processing.tools.dataobjects import createExpressionContext, createContext
pluginPath = os.path.split(os.path.dirname(__file__))[0]
NUMBER_WIDGET, NUMBER_BASE = uic.loadUiType(
@ -77,47 +72,14 @@ class ModellerNumberInputPanel(BASE, WIDGET):
def showExpressionsBuilder(self):
context = createExpressionContext()
dlg = QgsExpressionBuilderDialog(None, str(self.leText.text()), self, 'generic', context)
processing_context = createContext()
scope = self.modelParametersDialog.model.createExpressionContextScopeForChildAlgorithm(self.modelParametersDialog.childId, processing_context)
context.appendScope(scope)
context.popScope()
values = self.modelParametersDialog.getAvailableValuesOfType(QgsProcessingParameterNumber, QgsProcessingOutputNumber)
variables = {}
for value in values:
if isinstance(value, QgsProcessingModelAlgorithm.ChildParameterSource):
if value.source() == QgsProcessingModelAlgorithm.ChildParameterSource.ModelParameter:
name = value.parameterName()
element = self.modelParametersDialog.model.parameterDefinition(name)
desc = element.description()
elif value.source() == QgsProcessingModelAlgorithm.ChildParameterSource.ChildOutput:
name = "%s_%s" % (value.outputChildId(), value.outputName())
alg = self.modelParametersDialog.model.childAlgorithm(value.outputChildId())
out = alg.algorithm().outputDefinition(value.outputName())
desc = self.tr("Output '{0}' from algorithm '{1}'").format(out.description(), alg.description())
variables[name] = desc
values = self.modelParametersDialog.getAvailableValuesOfType([QgsProcessingParameterFeatureSource, QgsProcessingParameterRasterLayer],
[QgsProcessingOutputVectorLayer, QgsProcessingOutputRasterLayer])
for value in values:
if isinstance(value, QgsProcessingModelAlgorithm.ChildParameterSource):
if value.source() == QgsProcessingModelAlgorithm.ChildParameterSource.ModelParameter:
name = value.parameterName()
element = self.modelParametersDialog.model.parameterDefinition(name)
desc = element.description()
elif value.source() == QgsProcessingModelAlgorithm.ChildParameterSource.ChildOutput:
name = "%s_%s" % (value.outputChildId(), value.outputName())
alg = self.modelParametersDialog.model.childAlgorithm(value.outputChildId())
out = alg.algorithm().outputDefinition(value.outputName())
desc = self.tr("Output '{0}' from algorithm '{1}'").format(out.description(), alg.description())
variables['%s_minx' % name] = self.tr("Minimum X of {0}").format(desc)
variables['%s_miny' % name] = self.tr("Minimum Y of {0}").format(desc)
variables['%s_maxx' % name] = self.tr("Maximum X of {0}").format(desc)
variables['%s_maxy' % name] = self.tr("Maximum Y of {0}").format(desc)
if isinstance(element, (QgsProcessingParameterRasterLayer, QgsProcessingOutputRasterLayer)):
variables['%s_min' % name] = self.tr("Minimum value of {0}").format(desc)
variables['%s_max' % name] = self.tr("Maximum value of {0}").format(desc)
variables['%s_avg' % name] = self.tr("Mean value of {0}").format(desc)
variables['%s_stddev' % name] = self.tr("Standard deviation of {0}").format(desc)
for variable, desc in variables.items():
dlg.expressionBuilder().registerItem("Modeler", variable, "@" + variable, desc, highlightedItem=True)
highlighted = scope.variableNames()
context.setHighlightedVariables(highlighted)
dlg = QgsExpressionBuilderDialog(None, str(self.leText.text()), self, 'generic', context)
dlg.setWindowTitle(self.tr('Expression based input'))
if dlg.exec_() == QDialog.Accepted:

View File

@ -30,10 +30,9 @@ import shutil
from qgis.PyQt.QtWidgets import QFileDialog, QMessageBox
from qgis.PyQt.QtCore import QFileInfo
from qgis.core import QgsApplication, QgsSettings
from qgis.core import QgsApplication, QgsSettings, QgsProcessingModelAlgorithm
from processing.gui.ToolboxAction import ToolboxAction
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
from processing.modeler.WrongModelException import WrongModelException
from processing.modeler.ModelerUtils import ModelerUtils
@ -59,7 +58,7 @@ class AddModelFromFileAction(ToolboxAction):
settings.setValue('Processing/lastModelsDir',
QFileInfo(filename).absoluteDir().absolutePath())
alg = ModelerAlgorithm()
alg = QgsProcessingModelAlgorithm()
if not alg.fromFile(filename):
QMessageBox.warning(
self.toolbox,

View File

@ -26,10 +26,9 @@ __copyright__ = '(C) 2012, Victor Olaya'
__revision__ = '$Format:%H$'
import os
from qgis.core import QgsApplication
from qgis.core import QgsApplication, QgsProcessingModelAlgorithm
from qgis.PyQt.QtWidgets import QMessageBox
from processing.gui.ContextAction import ContextAction
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
class DeleteModelAction(ContextAction):
@ -38,7 +37,7 @@ class DeleteModelAction(ContextAction):
self.name = self.tr('Delete model', 'DeleteModelAction')
def isEnabled(self):
return isinstance(self.itemData, ModelerAlgorithm)
return isinstance(self.itemData, QgsProcessingModelAlgorithm)
def execute(self):
reply = QMessageBox.question(

View File

@ -25,9 +25,8 @@ __copyright__ = '(C) 2012, Victor Olaya'
__revision__ = '$Format:%H$'
from qgis.core import QgsApplication
from qgis.core import QgsApplication, QgsProcessingModelAlgorithm
from processing.gui.ContextAction import ContextAction
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
from processing.modeler.ModelerDialog import ModelerDialog
@ -37,7 +36,7 @@ class EditModelAction(ContextAction):
self.name = self.tr('Edit model', 'EditModelAction')
def isEnabled(self):
return isinstance(self.itemData, ModelerAlgorithm)
return isinstance(self.itemData, QgsProcessingModelAlgorithm)
def execute(self):
alg = self.itemData

View File

@ -1,178 +0,0 @@
# -*- coding: utf-8 -*-
"""
***************************************************************************
ModelerAlgorithm.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
from builtins import str
from builtins import object
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import os.path
import sys
import copy
import time
import json
from qgis.PyQt.QtCore import QPointF
from operator import attrgetter
from qgis.core import (QgsApplication,
QgsProcessingAlgorithm,
QgsProcessingParameterDefinition,
QgsProcessingParameterBoolean,
QgsProcessingParameterCrs,
QgsProcessingParameterMapLayer,
QgsProcessingParameterExtent,
QgsProcessingParameterPoint,
QgsProcessingParameterFile,
QgsProcessingParameterMatrix,
QgsProcessingParameterMultipleLayers,
QgsProcessingParameterNumber,
QgsProcessingParameterRange,
QgsProcessingParameterRasterLayer,
QgsProcessingParameterEnum,
QgsProcessingParameterString,
QgsProcessingParameterExpression,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterField,
QgsProcessingParameterFeatureSource,
QgsProcessingModelAlgorithm)
from qgis.gui import QgsMessageBar
from qgis.utils import iface
from processing.modeler.WrongModelException import WrongModelException
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from processing.gui.Help2Html import getHtmlFromDescriptionsDict
pluginPath = os.path.split(os.path.dirname(__file__))[0]
class ValueFromInput(object):
def __init__(self, name=""):
self.name = name
def todict(self):
return self.__dict__
def __str__(self):
return self.name
def __eq__(self, other):
try:
return self.name == other.name
except:
return False
class ValueFromOutput(object):
def __init__(self, alg="", output=""):
self.alg = alg
self.output = output
def todict(self):
return self.__dict__
def __eq__(self, other):
try:
return self.alg == other.alg and self.output == other.output
except:
return False
def __str__(self):
return self.alg + ":" + self.output
class CompoundValue(object):
def __init__(self, values=[], definition=""):
self.values = values
self.definition = definition
def todict(self):
return self.__dict__
def __eq__(self, other):
try:
return self.values == other.values and self.definition == other.definition
except:
return False
def __str__(self):
return self.definition
def asPythonParameter(self):
return "" # TODO
class ModelerAlgorithm(QgsProcessingModelAlgorithm):
def __init__(self):
super().__init__()
# Geoalgorithms in this model. A dict of Algorithm objects, with names as keys
self.algs = {}
def prepareAlgorithm(self, alg):
algInstance = alg.algorithm()
for param in algInstance.parameterDefinitions():
if not param.flags() & QgsProcessingParameterDefinition.FlagHidden:
if param.name() in alg.params:
value = self.resolveValue(alg.params[param.name()], param)
else:
if iface is not None:
iface.messageBar().pushMessage(self.tr("Warning"),
self.tr("Parameter {0} in algorithm {1} in the model is run with default value! Edit the model to make sure that this is correct.").format(param.name(), alg.displayName()),
QgsMessageBar.WARNING, 4)
value = param.defaultValue()
# note to self - these are parameters, not outputs
for out in algInstance.outputDefinitions():
if not out.flags() & QgsProcessingParameterDefinition.FlagHidden:
if out.name() in alg.outputs:
name = self.getSafeNameForOutput(alg.childId(), out.name())
modelOut = self.getOutputFromName(name)
if modelOut:
out.value = modelOut.value
else:
out.value = None
return algInstance
def getSafeNameForOutput(self, algName, outName):
return outName + '_ALG' + algName
def resolveValue(self, value, param):
if value is None:
v = None
if isinstance(value, list):
v = ";".join([self.resolveValue(v, param) for v in value])
elif isinstance(value, CompoundValue):
v = self.resolveValue(value.definition, param)
elif isinstance(value, ValueFromInput):
v = self.getParameterFromName(value.name).value
elif isinstance(value, ValueFromOutput):
v = self.algs[value.alg].algorithm().outputDefinition(value.output).value
else:
v = value
return param.evaluateForModeler(v, self)

View File

@ -32,12 +32,12 @@ from qgis.PyQt.QtXml import QDomDocument
from qgis.core import (QgsApplication,
QgsProcessingProvider,
QgsMessageLog,
QgsProcessingModelAlgorithm,
QgsProcessingUtils,
QgsXmlUtils)
from processing.core.ProcessingConfig import ProcessingConfig, Setting
from processing.modeler.ModelerUtils import ModelerUtils
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
from processing.modeler.WrongModelException import WrongModelException
from processing.modeler.EditModelAction import EditModelAction
from processing.modeler.CreateNewModelAction import CreateNewModelAction
@ -109,7 +109,7 @@ class ModelerAlgorithmProvider(QgsProcessingProvider):
try:
fullpath = os.path.join(path, descriptionFile)
alg = ModelerAlgorithm()
alg = QgsProcessingModelAlgorithm()
if alg.fromFile(fullpath):
if alg.name():
alg.setSourceFilePath(fullpath)

View File

@ -48,7 +48,6 @@ from qgis.gui import QgsMessageBar
from processing.gui.HelpEditionDialog import HelpEditionDialog
from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog
from processing.modeler.ModelerAlgorithm import ModelerAlgorithm
from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
from processing.modeler.ModelerUtils import ModelerUtils
from processing.modeler.ModelerScene import ModelerScene
@ -244,7 +243,7 @@ class ModelerDialog(BASE, WIDGET):
self.repaintModel()
else:
self.model = ModelerAlgorithm()
self.model = QgsProcessingModelAlgorithm()
self.model.setProvider(QgsApplication.processingRegistry().providerById('model'))
self.fillInputsTree()
@ -475,7 +474,7 @@ class ModelerDialog(BASE, WIDGET):
ModelerUtils.modelsFolders()[0],
self.tr('Processing models (*.model3 *.MODEL3)'))
if filename:
alg = ModelerAlgorithm()
alg = QgsProcessingModelAlgorithm()
if alg.fromFile(filename):
self.model = alg
self.model.setProvider(QgsApplication.processingRegistry().providerById('model'))

View File

@ -32,7 +32,6 @@ from qgis.core import (QgsProcessingParameterDefinition,
QgsProcessingModelAlgorithm)
from processing.modeler.ModelerGraphicItem import ModelerGraphicItem
from processing.modeler.ModelerArrowItem import ModelerArrowItem
from processing.modeler.ModelerAlgorithm import CompoundValue
class ModelerScene(QGraphicsScene):
@ -78,9 +77,6 @@ class ModelerScene(QGraphicsScene):
break
if value.outputChildId() in self.algItems:
items.append((self.algItems[value.outputChildId()], i))
elif isinstance(value, CompoundValue):
for v in value.values:
items.extend(self.getItemsFromParamValue(v))
return items
def paintModel(self, model, controls=True):

View File

@ -351,7 +351,7 @@ QString QgsProcessingModelAlgorithm::helpUrl() const
return QgsProcessingUtils::formatHelpMapAsHtml( mHelpContent, this );
}
QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QMap< QString, QVariantMap > &results, const QgsExpressionContext &expressionContext ) const
QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QVariantMap &results, const QgsExpressionContext &expressionContext ) const
{
QVariantMap childParams;
Q_FOREACH ( const QgsProcessingParameterDefinition *def, child.algorithm()->parameterDefinitions() )
@ -381,7 +381,7 @@ QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( const Chil
case ChildParameterSource::ChildOutput:
{
QVariantMap linkedChildResults = results.value( source.outputChildId() );
QVariantMap linkedChildResults = results.value( source.outputChildId() ).toMap();
paramParts << linkedChildResults.value( source.outputName() );
break;
}
@ -494,7 +494,7 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
QgsExpressionContext baseContext = createExpressionContext( parameters, context );
QMap< QString, QVariantMap > childResults;
QVariantMap childResults;
QVariantMap finalResults;
QSet< QString > executed;
bool executedAlg = true;
@ -525,7 +525,8 @@ QVariantMap QgsProcessingModelAlgorithm::processAlgorithm( const QVariantMap &pa
const ChildAlgorithm &child = mChildAlgorithms[ childId ];
QgsExpressionContext expContext = baseContext;
expContext << QgsExpressionContextUtils::processingAlgorithmScope( child.algorithm(), parameters, context );
expContext << QgsExpressionContextUtils::processingAlgorithmScope( child.algorithm(), parameters, context )
<< createExpressionContextScopeForChildAlgorithm( childId, context, parameters, childResults );
QVariantMap childParams = parametersForChildAlgorithm( child, parameters, childResults, expContext );
feedback->setProgressText( QObject::tr( "Running %1 [%2/%3]" ).arg( child.description() ).arg( executed.count() + 1 ).arg( toExecute.count() ) );
@ -662,6 +663,147 @@ QString QgsProcessingModelAlgorithm::asPythonCode() const
return lines.join( '\n' );
}
QgsExpressionContextScope *QgsProcessingModelAlgorithm::createExpressionContextScopeForChildAlgorithm( const QString &childId, QgsProcessingContext &context, const QVariantMap &modelParameters, const QVariantMap &results ) const
{
QVariantMap variables;
std::unique_ptr< QgsExpressionContextScope > scope( new QgsExpressionContextScope() );
ChildParameterSources sources = availableSourcesForChild( childId, QStringList() << QgsProcessingParameterNumber::typeName(),
QStringList() << QgsProcessingOutputNumber::typeName() );
Q_FOREACH ( const ChildParameterSource &source, sources )
{
QString name;
QVariant value;
switch ( source.source() )
{
case ChildParameterSource::ModelParameter:
{
name = source.parameterName();
value = modelParameters.value( source.parameterName() );
break;
}
case ChildParameterSource::ChildOutput:
{
name = QStringLiteral( "%1_%2" ).arg( mChildAlgorithms.value( source.outputChildId() ).description().isEmpty() ?
source.outputChildId() : mChildAlgorithms.value( source.outputChildId() ).description(), source.outputName() );
value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
break;
}
case ChildParameterSource::Expression:
case ChildParameterSource::StaticValue:
continue;
};
variables.insert( name, value );
}
sources = availableSourcesForChild( childId, QStringList()
<< QgsProcessingParameterVectorLayer::typeName()
<< QgsProcessingParameterRasterLayer::typeName(),
QStringList() << QgsProcessingOutputVectorLayer::typeName()
<< QgsProcessingOutputRasterLayer::typeName() );
Q_FOREACH ( const ChildParameterSource &source, sources )
{
QString name;
QVariant value;
switch ( source.source() )
{
case ChildParameterSource::ModelParameter:
{
name = source.parameterName();
value = modelParameters.value( source.parameterName() );
break;
}
case ChildParameterSource::ChildOutput:
{
name = QStringLiteral( "%1_%2" ).arg( mChildAlgorithms.value( source.outputChildId() ).description().isEmpty() ?
source.outputChildId() : mChildAlgorithms.value( source.outputChildId() ).description(), source.outputName() );
value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
break;
}
case ChildParameterSource::Expression:
case ChildParameterSource::StaticValue:
continue;
};
QgsMapLayer *layer = qobject_cast< QgsMapLayer * >( qvariant_cast<QObject *>( value ) );
if ( !layer )
layer = QgsProcessingUtils::mapLayerFromString( value.toString(), context );
variables.insert( QStringLiteral( "%1_minx" ).arg( name ), layer ? layer->extent().xMinimum() : QVariant() );
variables.insert( QStringLiteral( "%1_miny" ).arg( name ), layer ? layer->extent().yMinimum() : QVariant() );
variables.insert( QStringLiteral( "%1_maxx" ).arg( name ), layer ? layer->extent().xMaximum() : QVariant() );
variables.insert( QStringLiteral( "%1_maxy" ).arg( name ), layer ? layer->extent().yMaximum() : QVariant() );
}
sources = availableSourcesForChild( childId, QStringList()
<< QgsProcessingParameterFeatureSource::typeName() );
Q_FOREACH ( const ChildParameterSource &source, sources )
{
QString name;
QVariant value;
switch ( source.source() )
{
case ChildParameterSource::ModelParameter:
{
name = source.parameterName();
value = modelParameters.value( source.parameterName() );
break;
}
case ChildParameterSource::ChildOutput:
{
name = QStringLiteral( "%1_%2" ).arg( mChildAlgorithms.value( source.outputChildId() ).description().isEmpty() ?
source.outputChildId() : mChildAlgorithms.value( source.outputChildId() ).description(), source.outputName() );
value = results.value( source.outputChildId() ).toMap().value( source.outputName() );
break;
}
case ChildParameterSource::Expression:
case ChildParameterSource::StaticValue:
continue;
};
QgsFeatureSource *featureSource = nullptr;
if ( value.canConvert<QgsProcessingFeatureSourceDefinition>() )
{
QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( value );
value = fromVar.source;
}
if ( QgsVectorLayer *layer = qobject_cast< QgsVectorLayer * >( qvariant_cast<QObject *>( value ) ) )
{
featureSource = layer;
}
if ( !featureSource )
{
if ( QgsVectorLayer *vl = qobject_cast< QgsVectorLayer *>( QgsProcessingUtils::mapLayerFromString( value.toString(), context ) ) )
featureSource = vl;
}
variables.insert( QStringLiteral( "%1_minx" ).arg( name ), featureSource ? featureSource->sourceExtent().xMinimum() : QVariant() );
variables.insert( QStringLiteral( "%1_miny" ).arg( name ), featureSource ? featureSource->sourceExtent().yMinimum() : QVariant() );
variables.insert( QStringLiteral( "%1_maxx" ).arg( name ), featureSource ? featureSource->sourceExtent().xMaximum() : QVariant() );
variables.insert( QStringLiteral( "%1_maxy" ).arg( name ), featureSource ? featureSource->sourceExtent().yMaximum() : QVariant() );
}
QVariantMap::const_iterator varIt = variables.constBegin();
for ( ; varIt != variables.constEnd(); ++varIt )
{
QString name = varIt.key();
name = name.replace( QRegularExpression( "[\\s'\"\\(\\):]" ), QStringLiteral( "_" ) );
scope->addVariable( QgsExpressionContextScope::StaticVariable( name, varIt.value(), true ) );
}
return scope.release();
}
QgsProcessingModelAlgorithm::ChildParameterSources QgsProcessingModelAlgorithm::availableSourcesForChild( const QString &childId, const QStringList &parameterTypes, const QStringList &outputTypes, const QList<int> dataTypes ) const
{
ChildParameterSources sources;

View File

@ -21,6 +21,7 @@
#include "qgis_core.h"
#include "qgis.h"
#include "qgsprocessingalgorithm.h"
#include "qgsprocessingcontext.h"
///@cond NOT_STABLE
@ -866,6 +867,12 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
QList< QgsProcessingModelAlgorithm::ChildParameterSource > availableSourcesForChild( const QString &childId, const QStringList &parameterTypes = QStringList(),
const QStringList &outputTypes = QStringList(), const QList< int > dataTypes = QList< int >() ) const;
/**
* Creates a new expression context scope for a child algorithm within the model.
*/
QgsExpressionContextScope *createExpressionContextScopeForChildAlgorithm( const QString &childId, QgsProcessingContext &context, const QVariantMap &modelParameters = QVariantMap(),
const QVariantMap &results = QVariantMap() ) const SIP_FACTORY;
protected:
QVariantMap processAlgorithm( const QVariantMap &parameters, QgsProcessingContext &context, QgsProcessingFeedback *feedback ) override;
@ -890,7 +897,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
void dependsOnChildAlgorithmsRecursive( const QString &childId, QSet<QString> &depends ) const;
void dependentChildAlgorithmsRecursive( const QString &childId, QSet<QString> &depends ) const;
QVariantMap parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QMap<QString, QVariantMap> &results, const QgsExpressionContext &expressionContext ) const;
QVariantMap parametersForChildAlgorithm( const ChildAlgorithm &child, const QVariantMap &modelParameters, const QVariantMap &results, const QgsExpressionContext &expressionContext ) const;
/**
* Returns true if an output from a child algorithm is required elsewhere in

View File

@ -4788,7 +4788,7 @@ void TestQgsProcessing::modelExecution()
QgsProcessingOutputLayerDefinition layerDef( "memory:" );
layerDef.destinationName = "my_dest";
modelInputs.insert( "cx3:MY_OUT", QVariant::fromValue( layerDef ) );
QMap<QString, QVariantMap> childResults;
QVariantMap childResults;
QVariantMap params = model2.parametersForChildAlgorithm( model2.childAlgorithm( "cx1" ), modelInputs, childResults, expContext );
QCOMPARE( params.value( "DISSOLVE" ).toBool(), false );
QCOMPARE( params.value( "DISTANCE" ).toInt(), 271 );