Skip to content

Commit

Permalink
[FEATURE][processing] Port multi-layer input parameter widget to new API
Browse files Browse the repository at this point in the history
Allows
- expression based inputs
- rearrangement of inputs for multi-layer parameters in models, to set
specific layer orders
  • Loading branch information
nyalldawson committed Mar 30, 2020
1 parent a682405 commit e386573
Show file tree
Hide file tree
Showing 16 changed files with 464 additions and 102 deletions.
Expand Up @@ -120,6 +120,13 @@ algorithms already executed by the model.
Source source() const;
%Docstring
Returns the parameter value's source.
%End

void setSource( Source source );
%Docstring
Sets the parameter's source.

.. versionadded:: 3.14
%End

QVariant staticValue() const;
Expand Down Expand Up @@ -245,6 +252,13 @@ Loads this source from a QVariantMap.
Attempts to convert the source to executable Python code.

The ``friendlyChildNames`` argument gives a map of child id to a friendly algorithm name, to be used in the code to identify that algorithm instead of the raw child id.
%End

QString friendlyIdentifier( QgsProcessingModelAlgorithm *model ) const;
%Docstring
Returns a user-friendly identifier for this source, given the context of the specified ``model``.

.. versionadded:: 3.14
%End

};
Expand Down
Expand Up @@ -114,7 +114,16 @@ Sets the current ``value`` for the parameter.
.. seealso:: :py:func:`value`
%End

virtual QgsProcessingModelChildParameterSource value() const;
void setWidgetValue( const QList< QgsProcessingModelChildParameterSource > &values );
%Docstring
Sets the current ``values`` for the parameter.

.. seealso:: :py:func:`value`

.. versionadded:: 3.14
%End

virtual QVariant value() const;
%Docstring
Returns the current value of the parameter.

Expand Down
Expand Up @@ -98,7 +98,6 @@ Emitted when the selection changes in the widget.
Adds a new option to the widget.
%End


};


Expand Down Expand Up @@ -188,7 +187,9 @@ A panel widget for selection of multiple inputs from a fixed list of options.
public:

QgsProcessingMultipleInputPanelWidget( const QgsProcessingParameterMultipleLayers *parameter,
const QVariantList &selectedOptions = QVariantList(),
const QVariantList &selectedOptions,
const QList< QgsProcessingModelChildParameterSource > &modelSources,
QgsProcessingModelAlgorithm *model = 0,
QWidget *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsProcessingMultipleInputPanelWidget.
Expand Down Expand Up @@ -220,7 +221,9 @@ A dialog for selection of multiple layer inputs.
public:

QgsProcessingMultipleInputDialog( const QgsProcessingParameterMultipleLayers *parameter,
const QVariantList &selectedOptions = QVariantList(),
const QVariantList &selectedOptions,
const QList< QgsProcessingModelChildParameterSource > &modelSources,
QgsProcessingModelAlgorithm *model = 0,
QWidget *parent /TransferThis/ = 0, Qt::WindowFlags flags = 0 );
%Docstring
Constructor for QgsProcessingMultipleInputDialog.
Expand Down
5 changes: 3 additions & 2 deletions python/plugins/processing/gui/BatchPanel.py
Expand Up @@ -144,7 +144,8 @@ def createMenu(self):
QgsProcessingParameterRasterLayer,
QgsProcessingParameterMeshLayer,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterFeatureSource)):
QgsProcessingParameterFeatureSource,
QgsProcessingParameterMultipleLayers)):
self.menu.addSeparator()
find_by_pattern_action = QAction(QCoreApplication.translate('BatchPanel', 'Add Files by Pattern…'),
self.menu)
Expand Down Expand Up @@ -277,7 +278,7 @@ def showLayerSelectionDialog(self):
if isinstance(self.parameterDefinition, QgsProcessingParameterRasterLayer):
layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance())
elif isinstance(self.parameterDefinition,
QgsProcessingParameterMultipleLayers) and self.param.layerType() == QgsProcessing.TypeRaster:
QgsProcessingParameterMultipleLayers) and self.parameterDefinition.layerType() == QgsProcessing.TypeRaster:
layers = QgsProcessingUtils.compatibleRasterLayers(QgsProject.instance())
elif isinstance(self.parameterDefinition, QgsProcessingParameterVectorLayer):
layers = QgsProcessingUtils.compatibleVectorLayers(QgsProject.instance())
Expand Down
Expand Up @@ -18,6 +18,7 @@
#include "qgsprocessingmodelchildparametersource.h"
#include "qgsprocessingparameters.h"
#include "qgsprocessingcontext.h"
#include "qgsprocessingmodelalgorithm.h"

///@cond NOT_STABLE

Expand Down Expand Up @@ -88,6 +89,11 @@ QgsProcessingModelChildParameterSource::Source QgsProcessingModelChildParameterS
return mSource;
}

void QgsProcessingModelChildParameterSource::setSource( QgsProcessingModelChildParameterSource::Source source )
{
mSource = source;
}

QVariant QgsProcessingModelChildParameterSource::toVariant() const
{
QVariantMap map;
Expand Down Expand Up @@ -177,4 +183,81 @@ QString QgsProcessingModelChildParameterSource::asPythonCode( const QgsProcessin
return QString();
}

QString QgsProcessingModelChildParameterSource::friendlyIdentifier( QgsProcessingModelAlgorithm *model ) const
{
switch ( mSource )
{
case ModelParameter:
return model ? model->parameterDefinition( mParameterName )->description() : mParameterName;

case ChildOutput:
{
if ( model )
{
const QgsProcessingModelChildAlgorithm &alg = model->childAlgorithm( mChildId );
QString outputName = alg.algorithm() && alg.algorithm()->outputDefinition( mOutputName ) ? alg.algorithm()->outputDefinition( mOutputName )->description() : mOutputName;
// see if this output has been named by the model designer -- if so, we use that friendly name
const QMap<QString, QgsProcessingModelOutput> outputs = alg.modelOutputs();
for ( auto it = outputs.constBegin(); it != outputs.constEnd(); ++it )
{
if ( it.value().childOutputName() == mOutputName )
{
outputName = it.key();
break;
}
}
return QObject::tr( "'%1' from algorithm '%2'" ).arg( outputName, alg.description() );
}
else
{
return QObject::tr( "'%1' from algorithm '%2'" ).arg( mOutputName, mChildId );
}
}

case StaticValue:
return mStaticValue.toString();

case Expression:
return mExpression;

case ExpressionText:
return mExpressionText;
}
return QString();
}

QDataStream &operator<<( QDataStream &out, const QgsProcessingModelChildParameterSource &source )
{
out << source.source();
out << source.staticValue();
out << source.parameterName();
out << source.outputChildId();
out << source.outputName();
out << source.expression();
out << source.expressionText();
return out;
}

QDataStream &operator>>( QDataStream &in, QgsProcessingModelChildParameterSource &source )
{
int sourceType;
QVariant staticValue;
QString parameterName;
QString outputChildId;
QString outputName;
QString expression;
QString expressionText;

in >> sourceType >> staticValue >> parameterName >> outputChildId >> outputName >> expression >> expressionText;

source.setStaticValue( staticValue );
source.setParameterName( parameterName );
source.setOutputChildId( outputChildId );
source.setOutputName( outputName );
source.setExpression( expression );
source.setExpressionText( expressionText );
source.setSource( static_cast<QgsProcessingModelChildParameterSource::Source>( sourceType ) );
return in;
}

///@endcond
Expand Up @@ -22,6 +22,7 @@
#include "qgis.h"
#include "qgsprocessing.h"
class QgsProcessingParameterDefinition;
class QgsProcessingModelAlgorithm;

///@cond NOT_STABLE

Expand Down Expand Up @@ -115,6 +116,13 @@ class CORE_EXPORT QgsProcessingModelChildParameterSource
*/
Source source() const;

/**
* Sets the parameter's source.
*
* \since QGIS 3.14
*/
void setSource( Source source );

/**
* Returns the source's static value. This is only used when the source() is StaticValue.
* \see setStaticValue()
Expand Down Expand Up @@ -220,6 +228,12 @@ class CORE_EXPORT QgsProcessingModelChildParameterSource
*/
QString asPythonCode( QgsProcessing::PythonOutputType outputType, const QgsProcessingParameterDefinition *definition, const QMap< QString, QString > &friendlydChildNames ) const;

/**
* Returns a user-friendly identifier for this source, given the context of the specified \a model.
* \since QGIS 3.14
*/
QString friendlyIdentifier( QgsProcessingModelAlgorithm *model ) const;

private:

Source mSource = StaticValue;
Expand All @@ -233,6 +247,8 @@ class CORE_EXPORT QgsProcessingModelChildParameterSource
};

Q_DECLARE_METATYPE( QgsProcessingModelChildParameterSource );
CORE_EXPORT QDataStream &operator<<( QDataStream &out, const QgsProcessingModelChildParameterSource &source );
CORE_EXPORT QDataStream &operator>>( QDataStream &in, QgsProcessingModelChildParameterSource &source );

#ifndef SIP_RUN
//! List of child parameter sources
Expand Down
3 changes: 3 additions & 0 deletions src/core/qgsapplication.cpp
Expand Up @@ -64,6 +64,7 @@

#include "gps/qgsgpsconnectionregistry.h"
#include "processing/qgsprocessingregistry.h"
#include "processing/models/qgsprocessingmodelchildparametersource.h"

#include "layout/qgspagesizeregistry.h"

Expand Down Expand Up @@ -227,6 +228,8 @@ void QgsApplication::init( QString profileFolder )
qRegisterMetaType<QgsDatumTransform::TransformDetails>( "QgsDatumTransform::TransformDetails" );
qRegisterMetaType<QgsNewsFeedParser::Entry>( "QgsNewsFeedParser::Entry" );
qRegisterMetaType<QgsRectangle>( "QgsRectangle" );
qRegisterMetaType<QgsProcessingModelChildParameterSource>( "QgsProcessingModelChildParameterSource" );
qRegisterMetaTypeStreamOperators<QgsProcessingModelChildParameterSource>( "QgsProcessingModelChildParameterSource" );

( void ) resolvePkgPath();

Expand Down
2 changes: 1 addition & 1 deletion src/gui/processing/models/qgsmodelgraphicsscene.cpp
Expand Up @@ -138,9 +138,9 @@ void QgsModelGraphicsScene::createItems( QgsProcessingModelAlgorithm *model, Qgs
arrow = new QgsModelArrowItem( link.item, link.edge, link.linkIndex, mChildAlgorithmItems.value( it.value().childId() ), Qt::TopEdge, idx );
addItem( arrow );
}
idx += 1;
}
}
idx += 1;
}
const QStringList dependencies = it.value().dependencies();
for ( const QString &depend : dependencies )
Expand Down
42 changes: 36 additions & 6 deletions src/gui/processing/qgsprocessingmodelerparameterwidget.cpp
Expand Up @@ -157,27 +157,57 @@ void QgsProcessingModelerParameterWidget::setWidgetValue( const QgsProcessingMod
setSourceType( value.source() );
}

QgsProcessingModelChildParameterSource QgsProcessingModelerParameterWidget::value() const
void QgsProcessingModelerParameterWidget::setWidgetValue( const QList<QgsProcessingModelChildParameterSource> &values )
{
if ( values.size() == 1 )
setWidgetValue( values.at( 0 ) );
else
{
QVariantList r;
for ( const QgsProcessingModelChildParameterSource &v : values )
r << QVariant::fromValue( v );
mStaticValue = r;
updateUi();
setSourceType( QgsProcessingModelChildParameterSource::StaticValue );
}
}

QVariant QgsProcessingModelerParameterWidget::value() const
{
switch ( currentSourceType() )
{
case StaticValue:
return QgsProcessingModelChildParameterSource::fromStaticValue( mStaticWidgetWrapper->parameterValue() );
{
const QVariant v = mStaticWidgetWrapper->parameterValue();

if ( v.type() == QVariant::List )
{
const QVariantList vList = v.toList();
if ( std::all_of( vList.begin(), vList.end(), []( const QVariant & val )
{
return val.canConvert< QgsProcessingModelChildParameterSource >();
} ) )
{
return v;
}
}
return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromStaticValue( v ) );
}

case Expression:
return QgsProcessingModelChildParameterSource::fromExpression( mExpressionWidget->expression() );
return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromExpression( mExpressionWidget->expression() ) );

case ModelParameter:
return QgsProcessingModelChildParameterSource::fromModelParameter( mModelInputCombo->currentData().toString() );
return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromModelParameter( mModelInputCombo->currentData().toString() ) );

case ChildOutput:
{
const QStringList parts = mChildOutputCombo->currentData().toStringList();
return QgsProcessingModelChildParameterSource::fromChildOutput( parts.value( 0, QString() ), parts.value( 1, QString() ) );
return QVariant::fromValue( QgsProcessingModelChildParameterSource::fromChildOutput( parts.value( 0, QString() ), parts.value( 1, QString() ) ) );
}
}

return QgsProcessingModelChildParameterSource();
return QVariant::fromValue( QgsProcessingModelChildParameterSource() );
}

void QgsProcessingModelerParameterWidget::setDialog( QDialog *dialog )
Expand Down
10 changes: 9 additions & 1 deletion src/gui/processing/qgsprocessingmodelerparameterwidget.h
Expand Up @@ -141,12 +141,20 @@ class GUI_EXPORT QgsProcessingModelerParameterWidget : public QWidget, public Qg
*/
virtual void setWidgetValue( const QgsProcessingModelChildParameterSource &value );

/**
* Sets the current \a values for the parameter.
*
* \see value()
* \since QGIS 3.14
*/
void setWidgetValue( const QList< QgsProcessingModelChildParameterSource > &values );

/**
* Returns the current value of the parameter.
*
* \see setWidgetValue()
*/
virtual QgsProcessingModelChildParameterSource value() const;
virtual QVariant value() const;

/**
* Sets the parent \a dialog in which the widget is shown.
Expand Down

0 comments on commit e386573

Please sign in to comment.