Skip to content

Commit

Permalink
[processing] port band parameter definition widget to C++, expose
Browse files Browse the repository at this point in the history
option to define multiple bands parameter in modeler parameter defintion
dialog
  • Loading branch information
alexbruy authored and nyalldawson committed Apr 4, 2020
1 parent 0eaba81 commit a2ed502
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 26 deletions.
Expand Up @@ -75,7 +75,6 @@ class ModelerParameterDefinitionDialog(QDialog):
@staticmethod
def use_legacy_dialog(param=None, paramType=None):
if paramType in (parameters.PARAMETER_TABLE_FIELD,
parameters.PARAMETER_BAND,
parameters.PARAMETER_VECTOR,
parameters.PARAMETER_TABLE,
parameters.PARAMETER_MULTIPLE,
Expand All @@ -85,7 +84,6 @@ def use_legacy_dialog(param=None, paramType=None):
parameters.PARAMETER_MAP_LAYER):
return True
elif isinstance(param, (QgsProcessingParameterField,
QgsProcessingParameterBand,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMultipleLayers,
Expand Down Expand Up @@ -185,21 +183,6 @@ def setupUi(self):
if default is not None:
self.defaultTextBox.setText(str(default))
self.verticalLayout.addWidget(self.defaultTextBox)

elif self.paramType == parameters.PARAMETER_BAND or \
isinstance(self.param, QgsProcessingParameterBand):
self.verticalLayout.addWidget(QLabel(self.tr('Parent layer')))
self.parentCombo = QComboBox()
idx = 0
for param in list(self.alg.parameterComponents().values()):
definition = self.alg.parameterDefinition(param.parameterName())
if isinstance(definition, (QgsProcessingParameterRasterLayer)):
self.parentCombo.addItem(definition.description(), definition.name())
if self.param is not None:
if self.param.parentLayerParameterName() == definition.name():
self.parentCombo.setCurrentIndex(idx)
idx += 1
self.verticalLayout.addWidget(self.parentCombo)
elif (self.paramType in (
parameters.PARAMETER_VECTOR, parameters.PARAMETER_TABLE) or
isinstance(self.param, (QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer))):
Expand Down Expand Up @@ -411,14 +394,6 @@ def accept(self):
self.param = QgsProcessingParameterField(name, description, defaultValue=default,
parentLayerParameterName=parent, type=datatype,
allowMultiple=self.multipleCheck.isChecked())
elif (self.paramType == parameters.PARAMETER_BAND or
isinstance(self.param, QgsProcessingParameterBand)):
if self.parentCombo.currentIndex() < 0:
QMessageBox.warning(self, self.tr('Unable to define parameter'),
self.tr('Wrong or missing parameter values'))
return
parent = self.parentCombo.currentData()
self.param = QgsProcessingParameterBand(name, description, None, parent)
elif (self.paramType == parameters.PARAMETER_MAP_LAYER or
isinstance(self.param, QgsProcessingParameterMapLayer)):
self.param = QgsProcessingParameterMapLayer(
Expand Down
78 changes: 77 additions & 1 deletion src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp
Expand Up @@ -5315,10 +5315,83 @@ void QgsProcessingRasterBandPanelWidget::updateSummaryText()
}



//
// QgsProcessingBandWidgetWrapper
//

QgsProcessingBandParameterDefinitionWidget::QgsProcessingBandParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent )
: QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent )
{
QVBoxLayout *vlayout = new QVBoxLayout();
vlayout->setMargin( 0 );
vlayout->setContentsMargins( 0, 0, 0, 0 );

vlayout->addWidget( new QLabel( tr( "Default value" ) ) );

mDefaultLineEdit = new QLineEdit();
mDefaultLineEdit->setToolTip( tr( "Band number (separate bands with ; for multiple band parameters)" ) );
if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
{
const QList< int > bands = QgsProcessingParameters::parameterAsInts( bandParam, bandParam->defaultValue(), context );
QStringList defVal;
for ( int b : bands )
{
defVal << QString::number( b );
}

mDefaultLineEdit->setText( defVal.join( ';' ) );
}
vlayout->addWidget( mDefaultLineEdit );

vlayout->addWidget( new QLabel( tr( "Parent layer" ) ) );
mParentLayerComboBox = new QComboBox();

QString initialParent;
if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
initialParent = bandParam->parentLayerParameterName();

if ( widgetContext.model() )
{
// populate combo box with other model input choices
const QMap<QString, QgsProcessingModelParameter> components = widgetContext.model()->parameterComponents();
for ( auto it = components.constBegin(); it != components.constEnd(); ++it )
{
if ( const QgsProcessingParameterRasterLayer *definition = dynamic_cast< const QgsProcessingParameterRasterLayer * >( widgetContext.model()->parameterDefinition( it.value().parameterName() ) ) )
{
mParentLayerComboBox-> addItem( definition->description(), definition->name() );
if ( !initialParent.isEmpty() && initialParent == definition->name() )
{
mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
}
}
}
}

if ( mParentLayerComboBox->count() == 0 && !initialParent.isEmpty() )
{
// if no parent candidates found, we just add the existing one as a placeholder
mParentLayerComboBox->addItem( initialParent, initialParent );
mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
}

vlayout->addWidget( mParentLayerComboBox );

mAllowMultipleCheckBox = new QCheckBox( tr( "Allow multiple" ) );
if ( const QgsProcessingParameterBand *bandParam = dynamic_cast<const QgsProcessingParameterBand *>( definition ) )
mAllowMultipleCheckBox->setChecked( bandParam->allowMultiple() );

vlayout->addWidget( mAllowMultipleCheckBox );
setLayout( vlayout );
}

QgsProcessingParameterDefinition *QgsProcessingBandParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
{
auto param = qgis::make_unique< QgsProcessingParameterBand >( name, description, mDefaultLineEdit->text().split( ';' ), mParentLayerComboBox->currentData().toString(), false, mAllowMultipleCheckBox->isChecked() );
param->setFlags( flags );
return param.release();
}

QgsProcessingBandWidgetWrapper::QgsProcessingBandWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
: QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent )
{
Expand Down Expand Up @@ -5579,7 +5652,10 @@ QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingBandWidgetWrapper::cre
return new QgsProcessingBandWidgetWrapper( parameter, type );
}


QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingBandWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm )
{
return new QgsProcessingBandParameterDefinitionWidget( context, widgetContext, definition, algorithm );
}



Expand Down
22 changes: 22 additions & 0 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.h
Expand Up @@ -1663,6 +1663,23 @@ class GUI_EXPORT QgsProcessingRasterBandPanelWidget : public QWidget
friend class TestProcessingGui;
};

class GUI_EXPORT QgsProcessingBandParameterDefinitionWidget : public QgsProcessingAbstractParameterDefinitionWidget
{
Q_OBJECT
public:

QgsProcessingBandParameterDefinitionWidget( QgsProcessingContext &context,
const QgsProcessingParameterWidgetContext &widgetContext,
const QgsProcessingParameterDefinition *definition = nullptr,
const QgsProcessingAlgorithm *algorithm = nullptr, QWidget *parent SIP_TRANSFERTHIS = nullptr );
QgsProcessingParameterDefinition *createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const override;

private:

QComboBox *mParentLayerComboBox = nullptr;
QLineEdit *mDefaultLineEdit = nullptr;
QCheckBox *mAllowMultipleCheckBox = nullptr;
};

class GUI_EXPORT QgsProcessingBandWidgetWrapper : public QgsAbstractProcessingParameterWidgetWrapper, public QgsProcessingParameterWidgetFactoryInterface
{
Expand All @@ -1676,6 +1693,11 @@ class GUI_EXPORT QgsProcessingBandWidgetWrapper : public QgsAbstractProcessingPa
// QgsProcessingParameterWidgetFactoryInterface
QString parameterType() const override;
QgsAbstractProcessingParameterWidgetWrapper *createWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type ) override;
QgsProcessingAbstractParameterDefinitionWidget *createParameterDefinitionWidget(
QgsProcessingContext &context,
const QgsProcessingParameterWidgetContext &widgetContext,
const QgsProcessingParameterDefinition *definition = nullptr,
const QgsProcessingAlgorithm *algorithm = nullptr ) override;

// QgsProcessingParameterWidgetWrapper interface
QWidget *createWidget() override SIP_FACTORY;
Expand Down
34 changes: 34 additions & 0 deletions tests/src/gui/testprocessinggui.cpp
Expand Up @@ -3302,6 +3302,40 @@ void TestProcessingGui::testBandWrapper()

// modeler wrapper
testWrapper( QgsProcessingGui::Modeler );

// config widget
QgsProcessingParameterWidgetContext widgetContext;
QgsProcessingContext context;
std::unique_ptr< QgsProcessingParameterDefinitionWidget > widget = qgis::make_unique< QgsProcessingParameterDefinitionWidget >( QStringLiteral( "band" ), context, widgetContext );
std::unique_ptr< QgsProcessingParameterDefinition > def( widget->createParameter( QStringLiteral( "param_name" ) ) );
QCOMPARE( def->name(), QStringLiteral( "param_name" ) );
QVERIFY( !( def->flags() & QgsProcessingParameterDefinition::FlagOptional ) ); // should default to mandatory
QVERIFY( !( def->flags() & QgsProcessingParameterDefinition::FlagAdvanced ) );

// using a parameter definition as initial values
QgsProcessingParameterBand bandParam( QStringLiteral( "n" ), QStringLiteral( "test desc" ), 1, QStringLiteral( "parent" ) );
widget = qgis::make_unique< QgsProcessingParameterDefinitionWidget >( QStringLiteral( "band" ), context, widgetContext, &bandParam );
def.reset( widget->createParameter( QStringLiteral( "param_name" ) ) );
QCOMPARE( def->name(), QStringLiteral( "param_name" ) );
QCOMPARE( def->description(), QStringLiteral( "test desc" ) );
QVERIFY( !( def->flags() & QgsProcessingParameterDefinition::FlagOptional ) );
QVERIFY( !( def->flags() & QgsProcessingParameterDefinition::FlagAdvanced ) );
QCOMPARE( static_cast< QgsProcessingParameterBand * >( def.get() )->defaultValue().toString(), QStringLiteral( "1" ) );
QCOMPARE( static_cast< QgsProcessingParameterBand * >( def.get() )->allowMultiple(), false );
QCOMPARE( static_cast< QgsProcessingParameterBand * >( def.get() )->parentLayerParameterName(), QStringLiteral( "parent" ) );
bandParam.setFlags( QgsProcessingParameterDefinition::FlagAdvanced | QgsProcessingParameterDefinition::FlagOptional );
bandParam.setParentLayerParameterName( QString() );
bandParam.setAllowMultiple( true );
bandParam.setDefaultValue( QVariantList() << 2 << 3 );
widget = qgis::make_unique< QgsProcessingParameterDefinitionWidget >( QStringLiteral( "band" ), context, widgetContext, &bandParam );
def.reset( widget->createParameter( QStringLiteral( "param_name" ) ) );
QCOMPARE( def->name(), QStringLiteral( "param_name" ) );
QCOMPARE( def->description(), QStringLiteral( "test desc" ) );
QVERIFY( def->flags() & QgsProcessingParameterDefinition::FlagOptional );
QVERIFY( def->flags() & QgsProcessingParameterDefinition::FlagAdvanced );
QCOMPARE( static_cast< QgsProcessingParameterBand * >( def.get() )->defaultValue().toStringList(), QStringList() << "2" << "3" );
QCOMPARE( static_cast< QgsProcessingParameterBand * >( def.get() )->allowMultiple(), true );
QVERIFY( static_cast< QgsProcessingParameterBand * >( def.get() )->parentLayerParameterName().isEmpty() );
}

void TestProcessingGui::testMultipleInputWrapper()
Expand Down

0 comments on commit a2ed502

Please sign in to comment.