Skip to content
Permalink
Browse files

Convert model child algorithm parameter sources to a list

So that multiple input type parameters are correctly handled,
allowing models with child algorithms like merge to correctly
use any combination of static layers/model inputs/child outputs
as their input parameter
  • Loading branch information
nyalldawson committed Jun 30, 2017
1 parent 8d6d097 commit 77588b9b61f64a0667faf96be97858ee345467be
@@ -161,6 +161,7 @@ class QgsProcessingModelAlgorithm : QgsProcessingAlgorithm

};


class Component
{
%Docstring
@@ -415,30 +416,30 @@ Copies are protected to avoid slicing
:rtype: QgsProcessingAlgorithm
%End

QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSource > parameterSources() const;
QMap< QString, QList< QgsProcessingModelAlgorithm::ChildParameterSource > > parameterSources() const;
%Docstring
Returns a map of parameter sources. The keys are the child algorithm
parameter names, the values are the source for that parameter.
parameter names, the values are the sources for that parameter.
.. seealso:: setParameterSources()
.. seealso:: addParameterSource()
:rtype: QMap< str, QgsProcessingModelAlgorithm.ChildParameterSource >
.. seealso:: addParameterSources()
:rtype: QMap< str, QList< QgsProcessingModelAlgorithm.ChildParameterSource > >
%End

void setParameterSources( const QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSource > &sources );
void setParameterSources( const QMap< QString, QList< QgsProcessingModelAlgorithm::ChildParameterSource > > &sources );
%Docstring
Sets the map of parameter ``sources``. The keys are the child algorithm
parameter names, the values are the source for that parameter.
parameter names, the values are the sources for that parameter.
.. seealso:: parameterSources()
.. seealso:: addParameterSource()
.. seealso:: addParameterSources()
%End

void addParameterSource( const QString &name, const QgsProcessingModelAlgorithm::ChildParameterSource &source );
void addParameterSources( const QString &name, const QList< QgsProcessingModelAlgorithm::ChildParameterSource > &source );
%Docstring
Adds a parameter source. The ``name`` argument should match
one of the child algorithm's parameter names, and the ``source``
argument is used to set the source for that parameter.
one of the child algorithm's parameter names, and the ``sources``
argument is used to set the sources for that parameter.

Any existing parameter source with matching name will be replaced.
Any existing parameter sources with matching name will be replaced.
.. seealso:: parameterSources()
.. seealso:: setParameterSources()
%End
@@ -285,6 +285,8 @@ def setPreviousValues(self):
continue
if param.name() in alg.parameterSources():
value = alg.parameterSources()[param.name()]
if isinstance(value, list) and len(value) == 1:
value = value[0]
else:
value = param.defaultValue()

@@ -325,9 +327,11 @@ def createAlgorithm(self):
if val is None:
continue
elif isinstance(val, QgsProcessingModelAlgorithm.ChildParameterSource):
alg.addParameterSource(param.name(), val)
alg.addParameterSources(param.name(), [val])
elif isinstance(val, list):
alg.addParameterSources(param.name(), val)
else:
alg.addParameterSource(param.name(), QgsProcessingModelAlgorithm.ChildParameterSource.fromStaticValue(val))
alg.addParameterSources(param.name(), [QgsProcessingModelAlgorithm.ChildParameterSource.fromStaticValue(val)])

outputs = {}
for dest in self._alg.destinationParameterDefinitions():
@@ -109,17 +109,18 @@ def paintModel(self, model, controls=True):
for parameter in alg.algorithm().parameterDefinitions():
if not parameter.isDestination() and not parameter.flags() & QgsProcessingParameterDefinition.FlagHidden:
if parameter.name() in alg.parameterSources():
value = alg.parameterSources()[parameter.name()]
sources = alg.parameterSources()[parameter.name()]
else:
value = None
sourceItems = self.getItemsFromParamValue(value)
for sourceItem, sourceIdx in sourceItems:
arrow = ModelerArrowItem(sourceItem, sourceIdx, self.algItems[alg.childId()], idx)
sourceItem.addArrow(arrow)
self.algItems[alg.childId()].addArrow(arrow)
arrow.updatePath()
self.addItem(arrow)
idx += 1
sources = []
for source in sources:
sourceItems = self.getItemsFromParamValue(source)
for sourceItem, sourceIdx in sourceItems:
arrow = ModelerArrowItem(sourceItem, sourceIdx, self.algItems[alg.childId()], idx)
sourceItem.addArrow(arrow)
self.algItems[alg.childId()].addArrow(arrow)
arrow.updatePath()
self.addItem(arrow)
idx += 1
for depend in alg.dependencies():
arrow = ModelerArrowItem(self.algItems[depend], -1,
self.algItems[alg.childId()], -1)
@@ -47,17 +47,17 @@ void QgsProcessingModelAlgorithm::Component::setDescription( const QString &desc
mDescription = description;
}

QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSource> QgsProcessingModelAlgorithm::ChildAlgorithm::parameterSources() const
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSources> QgsProcessingModelAlgorithm::ChildAlgorithm::parameterSources() const
{
return mParams;
}

void QgsProcessingModelAlgorithm::ChildAlgorithm::setParameterSources( const QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSource > &params )
void QgsProcessingModelAlgorithm::ChildAlgorithm::setParameterSources( const QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSources > &params )
{
mParams = params;
}

void QgsProcessingModelAlgorithm::ChildAlgorithm::addParameterSource( const QString &name, const ChildParameterSource &source )
void QgsProcessingModelAlgorithm::ChildAlgorithm::addParameterSources( const QString &name, const ChildParameterSources &source )
{
mParams.insert( name, source );
}
@@ -157,10 +157,15 @@ QVariant QgsProcessingModelAlgorithm::ChildAlgorithm::toVariant() const
saveCommonProperties( map );

QVariantMap paramMap;
QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSource >::const_iterator paramIt = mParams.constBegin();
QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSources >::const_iterator paramIt = mParams.constBegin();
for ( ; paramIt != mParams.constEnd(); ++paramIt )
{
paramMap.insert( paramIt.key(), paramIt.value().toVariant() );
QVariantList sources;
Q_FOREACH ( const ChildParameterSource &source, paramIt.value() )
{
sources << source.toVariant();
}
paramMap.insert( paramIt.key(), sources );
}
map.insert( "params", paramMap );

@@ -193,11 +198,15 @@ bool QgsProcessingModelAlgorithm::ChildAlgorithm::loadVariant( const QVariant &c
QVariantMap::const_iterator paramIt = paramMap.constBegin();
for ( ; paramIt != paramMap.constEnd(); ++paramIt )
{
ChildParameterSource param;
if ( !param.loadVariant( paramIt.value().toMap() ) )
return false;

mParams.insert( paramIt.key(), param );
ChildParameterSources sources;
Q_FOREACH ( const QVariant &sourceVar, paramIt->toList() )
{
ChildParameterSource param;
if ( !param.loadVariant( sourceVar.toMap() ) )
return false;
sources << param;
}
mParams.insert( paramIt.key(), sources );
}

mModelOutputs.clear();
@@ -223,12 +232,20 @@ QString QgsProcessingModelAlgorithm::ChildAlgorithm::asPythonCode() const
return QString();

QStringList paramParts;
QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSource >::const_iterator paramIt = mParams.constBegin();
QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSources >::const_iterator paramIt = mParams.constBegin();
for ( ; paramIt != mParams.constEnd(); ++paramIt )
{
QString part = paramIt->asPythonCode();
if ( !part.isEmpty() )
paramParts << QStringLiteral( "'%1':%2" ).arg( paramIt.key(), part );
QStringList sourceParts;
Q_FOREACH ( const ChildParameterSource &source, paramIt.value() )
{
QString part = source.asPythonCode();
if ( !part.isEmpty() )
sourceParts << QStringLiteral( "'%1':%2" ).arg( paramIt.key(), part );
}
if ( sourceParts.count() == 1 )
paramParts << sourceParts.at( 0 );
else
paramParts << QStringLiteral( "[%1]" ).arg( paramParts.join( ',' ) );
}

lines << QStringLiteral( "outputs['%1']=processing.run('%2', {%3}, context=context, feedback=feedback)" ).arg( mId, mAlgorithmId, paramParts.join( ',' ) );
@@ -347,24 +364,34 @@ QVariantMap QgsProcessingModelAlgorithm::parametersForChildAlgorithm( const Chil
if ( !child.parameterSources().contains( def->name() ) )
continue; // use default value

ChildParameterSource paramSource = child.parameterSources().value( def->name() );
switch ( paramSource.source() )
{
case ChildParameterSource::StaticValue:
childParams.insert( def->name(), paramSource.staticValue() );
break;
ChildParameterSources paramSources = child.parameterSources().value( def->name() );

case ChildParameterSource::ModelParameter:
childParams.insert( def->name(), modelParameters.value( paramSource.parameterName() ) );
break;

case ChildParameterSource::ChildOutput:
QVariantList paramParts;
Q_FOREACH ( const ChildParameterSource &source, paramSources )
{
switch ( source.source() )
{
QVariantMap linkedChildResults = results.value( paramSource.outputChildId() );
childParams.insert( def->name(), linkedChildResults.value( paramSource.outputName() ) );
break;
case ChildParameterSource::StaticValue:
paramParts << source.staticValue();
break;

case ChildParameterSource::ModelParameter:
paramParts << modelParameters.value( source.parameterName() );
break;

case ChildParameterSource::ChildOutput:
{
QVariantMap linkedChildResults = results.value( source.outputChildId() );
paramParts << linkedChildResults.value( source.outputName() );
break;
}
}
}
if ( paramParts.count() == 1 )
childParams.insert( def->name(), paramParts.at( 0 ) );
else
childParams.insert( def->name(), paramParts );

}
else
{
@@ -416,15 +443,18 @@ bool QgsProcessingModelAlgorithm::childOutputIsRequired( const QString &childId,
continue;

// look through all sources for child
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSource> candidateChildParams = childIt->parameterSources();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSource>::const_iterator childParamIt = candidateChildParams.constBegin();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSources> candidateChildParams = childIt->parameterSources();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSources>::const_iterator childParamIt = candidateChildParams.constBegin();
for ( ; childParamIt != candidateChildParams.constEnd(); ++childParamIt )
{
if ( childParamIt->source() == ChildParameterSource::ChildOutput
&& childParamIt->outputChildId() == childId
&& childParamIt->outputName() == outputName )
Q_FOREACH ( const ChildParameterSource &source, childParamIt.value() )
{
return true;
if ( source.source() == ChildParameterSource::ChildOutput
&& source.outputChildId() == childId
&& source.outputName() == outputName )
{
return true;
}
}
}
}
@@ -902,14 +932,17 @@ bool QgsProcessingModelAlgorithm::childAlgorithmsDependOnParameter( const QStrin
for ( ; childIt != mChildAlgorithms.constEnd(); ++childIt )
{
// check whether child requires this parameter
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSource> childParams = childIt->parameterSources();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSource>::const_iterator paramIt = childParams.constBegin();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSources> childParams = childIt->parameterSources();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSources>::const_iterator paramIt = childParams.constBegin();
for ( ; paramIt != childParams.constEnd(); ++paramIt )
{
if ( paramIt->source() == ChildParameterSource::ModelParameter
&& paramIt->parameterName() == name )
Q_FOREACH ( const ChildParameterSource &source, paramIt.value() )
{
return true;
if ( source.source() == ChildParameterSource::ModelParameter
&& source.parameterName() == name )
{
return true;
}
}
}
}
@@ -938,16 +971,19 @@ void QgsProcessingModelAlgorithm::dependentChildAlgorithmsRecursive( const QStri
}

// check whether child requires any outputs from the target alg
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSource> childParams = childIt->parameterSources();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSource>::const_iterator paramIt = childParams.constBegin();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSources> childParams = childIt->parameterSources();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSources>::const_iterator paramIt = childParams.constBegin();
for ( ; paramIt != childParams.constEnd(); ++paramIt )
{
if ( paramIt->source() == ChildParameterSource::ChildOutput
&& paramIt->outputChildId() == childId )
Q_FOREACH ( const ChildParameterSource &source, paramIt.value() )
{
depends.insert( childIt->childId() );
dependsOnChildAlgorithmsRecursive( childIt->childId(), depends );
break;
if ( source.source() == ChildParameterSource::ChildOutput
&& source.outputChildId() == childId )
{
depends.insert( childIt->childId() );
dependsOnChildAlgorithmsRecursive( childIt->childId(), depends );
break;
}
}
}
}
@@ -985,14 +1021,17 @@ void QgsProcessingModelAlgorithm::dependsOnChildAlgorithmsRecursive( const QStri
}

// check through parameter dependencies
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSource> childParams = alg.parameterSources();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSource>::const_iterator paramIt = childParams.constBegin();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSources> childParams = alg.parameterSources();
QMap<QString, QgsProcessingModelAlgorithm::ChildParameterSources>::const_iterator paramIt = childParams.constBegin();
for ( ; paramIt != childParams.constEnd(); ++paramIt )
{
if ( paramIt->source() == ChildParameterSource::ChildOutput && !depends.contains( paramIt->outputChildId() ) )
Q_FOREACH ( const ChildParameterSource &source, paramIt.value() )
{
depends.insert( paramIt->outputChildId() );
dependsOnChildAlgorithmsRecursive( paramIt->outputChildId(), depends );
if ( source.source() == ChildParameterSource::ChildOutput && !depends.contains( source.outputChildId() ) )
{
depends.insert( source.outputChildId() );
dependsOnChildAlgorithmsRecursive( source.outputChildId(), depends );
}
}
}
}
@@ -168,6 +168,11 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm

};

#ifndef SIP_RUN
//! List of child parameter sources
typedef QList< QgsProcessingModelAlgorithm::ChildParameterSource > ChildParameterSources;
#endif

/**
* Represents a component of a model algorithm.
* \since QGIS 3.0
@@ -413,30 +418,30 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm

/**
* Returns a map of parameter sources. The keys are the child algorithm
* parameter names, the values are the source for that parameter.
* parameter names, the values are the sources for that parameter.
* \see setParameterSources()
* \see addParameterSource()
* \see addParameterSources()
*/
QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSource > parameterSources() const;
QMap< QString, QList< QgsProcessingModelAlgorithm::ChildParameterSource > > parameterSources() const;

/**
* Sets the map of parameter \a sources. The keys are the child algorithm
* parameter names, the values are the source for that parameter.
* parameter names, the values are the sources for that parameter.
* \see parameterSources()
* \see addParameterSource()
* \see addParameterSources()
*/
void setParameterSources( const QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSource > &sources );
void setParameterSources( const QMap< QString, QList< QgsProcessingModelAlgorithm::ChildParameterSource > > &sources );

/**
* Adds a parameter source. The \a name argument should match
* one of the child algorithm's parameter names, and the \a source
* argument is used to set the source for that parameter.
* one of the child algorithm's parameter names, and the \a sources
* argument is used to set the sources for that parameter.
*
* Any existing parameter source with matching name will be replaced.
* Any existing parameter sources with matching name will be replaced.
* \see parameterSources()
* \see setParameterSources()
*/
void addParameterSource( const QString &name, const QgsProcessingModelAlgorithm::ChildParameterSource &source );
void addParameterSources( const QString &name, const QList< QgsProcessingModelAlgorithm::ChildParameterSource > &source );

/**
* Returns true if the child algorithm is active.
@@ -554,7 +559,7 @@ class CORE_EXPORT QgsProcessingModelAlgorithm : public QgsProcessingAlgorithm
QString mAlgorithmId;

//! A map of parameter sources. Keys are algorithm parameter names.
QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSource > mParams;
QMap< QString, QgsProcessingModelAlgorithm::ChildParameterSources > mParams;

//! A map of ModelOutput for final model outputs generated by this child algorithm. Keys are output names from the child algorithm.
QMap< QString, QgsProcessingModelAlgorithm::ModelOutput > mModelOutputs;

0 comments on commit 77588b9

Please sign in to comment.
You can’t perform that action at this time.