Skip to content

Commit

Permalink
[processing] port distance parameter definition widget to C++
Browse files Browse the repository at this point in the history
  • Loading branch information
alexbruy authored and nyalldawson committed Apr 4, 2020
1 parent ffd21f3 commit abe12c4
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 69 deletions.
Expand Up @@ -73,11 +73,9 @@ class ModelerParameterDefinitionDialog(QDialog):

@staticmethod
def use_legacy_dialog(param=None, paramType=None):
if paramType in (parameters.PARAMETER_DISTANCE,
parameters.PARAMETER_MAP_LAYER):
if paramType in (parameters.PARAMETER_MAP_LAYER):
return True
elif isinstance(param, (QgsProcessingParameterDistance,
QgsProcessingParameterMapLayer,
elif isinstance(param, (QgsProcessingParameterMapLayer,
QgsProcessingDestinationParameter)):
return True

Expand Down Expand Up @@ -138,48 +136,6 @@ def setupUi(self):
if self.param is not None:
self.datatypeCombo.setCurrentIndex(self.datatypeCombo.findData(self.param.dataTypes()[0]))
self.verticalLayout.addWidget(self.datatypeCombo)
elif (self.paramType in (parameters.PARAMETER_DISTANCE) or
isinstance(self.param, (QgsProcessingParameterDistance))):

if (self.paramType == parameters.PARAMETER_DISTANCE or
isinstance(self.param, QgsProcessingParameterDistance)):
self.verticalLayout.addWidget(QLabel(self.tr('Linked input')))
self.parentCombo = QComboBox()
self.parentCombo.addItem('', '')
idx = 1
for param in list(self.alg.parameterComponents().values()):
definition = self.alg.parameterDefinition(param.parameterName())
if isinstance(definition, (QgsProcessingParameterFeatureSource,
QgsProcessingParameterVectorLayer,
QgsProcessingParameterMapLayer,
QgsProcessingParameterCrs)):
self.parentCombo.addItem(definition.description(), definition.name())
if self.param is not None:
if self.param.parentParameterName() == definition.name():
self.parentCombo.setCurrentIndex(idx)
idx += 1
self.verticalLayout.addWidget(self.parentCombo)

self.verticalLayout.addWidget(QLabel(self.tr('Min value')))
self.minTextBox = QLineEdit()
self.verticalLayout.addWidget(self.minTextBox)
self.verticalLayout.addWidget(QLabel(self.tr('Max value')))
self.maxTextBox = QLineEdit()
self.verticalLayout.addWidget(self.maxTextBox)
if self.param is not None:
self.minTextBox.setText(str(self.param.minimum()))
self.maxTextBox.setText(str(self.param.maximum()))
self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
self.defaultTextBox = QLineEdit()
self.defaultTextBox.setText(self.tr('0'))
if self.param is not None:
default = self.param.defaultValue()
if self.param.dataType() == QgsProcessingParameterNumber.Integer:
default = int(math.floor(float(default)))
if default:
self.defaultTextBox.setText(str(default))
self.verticalLayout.addWidget(self.defaultTextBox)

elif isinstance(self.param, QgsProcessingDestinationParameter):
self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
self.defaultWidget = QgsProcessingLayerOutputDestinationWidget(self.param, defaultSelection=True)
Expand Down Expand Up @@ -291,29 +247,6 @@ def accept(self):
isinstance(self.param, QgsProcessingParameterRasterLayer)):
self.param = QgsProcessingParameterRasterLayer(
name, description)
elif (self.paramType == parameters.PARAMETER_DISTANCE or
isinstance(self.param, QgsProcessingParameterDistance)):
self.param = QgsProcessingParameterDistance(name, description,
self.defaultTextBox.text())
try:
vmin = self.minTextBox.text().strip()
if not vmin == '':
self.param.setMinimum(float(vmin))
vmax = self.maxTextBox.text().strip()
if not vmax == '':
self.param.setMaximum(float(vmax))
except:
QMessageBox.warning(self, self.tr('Unable to define parameter'),
self.tr('Wrong or missing parameter values'))
return

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()
if parent:
self.param.setParentParameterName(parent)

# Destination parameter
elif (isinstance(self.param, QgsProcessingParameterFeatureSink)):
Expand Down
113 changes: 113 additions & 0 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp
Expand Up @@ -905,6 +905,114 @@ QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingNumericWidgetWrappe
// QgsProcessingDistanceWidgetWrapper
//

QgsProcessingDistanceParameterDefinitionWidget::QgsProcessingDistanceParameterDefinitionWidget( 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( "Linked input" ) ) );

mParentLayerComboBox = new QComboBox();

QString initialParent;
if ( const QgsProcessingParameterDistance *distParam = dynamic_cast<const QgsProcessingParameterDistance *>( definition ) )
initialParent = distParam->parentParameterName();

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 QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( widgetContext.model()->parameterDefinition( it.value().parameterName() ) ) )
{
mParentLayerComboBox-> addItem( definition->description(), definition->name() );
if ( !initialParent.isEmpty() && initialParent == definition->name() )
{
mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
}
}
else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( widgetContext.model()->parameterDefinition( it.value().parameterName() ) ) )
{
mParentLayerComboBox-> addItem( definition->description(), definition->name() );
if ( !initialParent.isEmpty() && initialParent == definition->name() )
{
mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
}
}
else if ( const QgsProcessingParameterMapLayer *definition = dynamic_cast< const QgsProcessingParameterMapLayer * >( widgetContext.model()->parameterDefinition( it.value().parameterName() ) ) )
{
mParentLayerComboBox-> addItem( definition->description(), definition->name() );
if ( !initialParent.isEmpty() && initialParent == definition->name() )
{
mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 );
}
}
else if ( const QgsProcessingParameterCrs *definition = dynamic_cast< const QgsProcessingParameterCrs * >( 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 );

vlayout->addWidget( new QLabel( tr( "Minimum value" ) ) );
mMinLineEdit = new QLineEdit();
vlayout->addWidget( mMinLineEdit );

vlayout->addWidget( new QLabel( tr( "Maximum value" ) ) );
mMaxLineEdit = new QLineEdit();
vlayout->addWidget( mMaxLineEdit );

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

if ( const QgsProcessingParameterDistance *distParam = dynamic_cast<const QgsProcessingParameterDistance *>( definition ) )
{
mMinLineEdit->setText( QString::number( distParam->minimum() ) );
mMaxLineEdit->setText( QString::number( distParam->maximum() ) );
mDefaultLineEdit->setText( distParam->defaultValue().toString() );
}

setLayout( vlayout );
}

QgsProcessingParameterDefinition *QgsProcessingDistanceParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const
{
auto param = qgis::make_unique< QgsProcessingParameterDistance >( name, description, mDefaultLineEdit->text(), mParentLayerComboBox->currentData().toString() );

bool ok;
float val = mMinLineEdit->text().toFloat( &ok );
if ( ok )
{
param->setMinimum( val );
}

val = mMaxLineEdit->text().toFloat( &ok );
if ( ok )
{
param->setMaximum( val );
}

param->setFlags( flags );
return param.release();
}

QgsProcessingDistanceWidgetWrapper::QgsProcessingDistanceWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent )
: QgsProcessingNumericWidgetWrapper( parameter, type, parent )
{
Expand Down Expand Up @@ -1070,6 +1178,11 @@ QVariant QgsProcessingDistanceWidgetWrapper::widgetValue() const
}
}

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

//
// QgsProcessingScaleWidgetWrapper
//
Expand Down
25 changes: 25 additions & 0 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.h
Expand Up @@ -335,6 +335,26 @@ class GUI_EXPORT QgsProcessingNumericWidgetWrapper : public QgsAbstractProcessin
};


class GUI_EXPORT QgsProcessingDistanceParameterDefinitionWidget : public QgsProcessingAbstractParameterDefinitionWidget
{
Q_OBJECT
public:

QgsProcessingDistanceParameterDefinitionWidget( 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 *mMinLineEdit = nullptr;
QLineEdit *mMaxLineEdit = nullptr;
QLineEdit *mDefaultLineEdit = nullptr;

};

class GUI_EXPORT QgsProcessingDistanceWidgetWrapper : public QgsProcessingNumericWidgetWrapper
{
Q_OBJECT
Expand All @@ -347,6 +367,11 @@ class GUI_EXPORT QgsProcessingDistanceWidgetWrapper : public QgsProcessingNumeri
// 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
38 changes: 38 additions & 0 deletions tests/src/gui/testprocessinggui.cpp
Expand Up @@ -2029,6 +2029,44 @@ void TestProcessingGui::testDistanceWrapper()
QCOMPARE( l->toolTip(), param.toolTip() );
delete w;
delete l;

// config widget
QgsProcessingParameterWidgetContext widgetContext;
std::unique_ptr< QgsProcessingParameterDefinitionWidget > widget = qgis::make_unique< QgsProcessingParameterDefinitionWidget >( QStringLiteral( "distance" ), 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
QgsProcessingParameterDistance distParam( QStringLiteral( "n" ), QStringLiteral( "test desc" ), 1, QStringLiteral( "parent" ) );
distParam.setMinimum( 1 );
distParam.setMaximum( 100 );
widget = qgis::make_unique< QgsProcessingParameterDefinitionWidget >( QStringLiteral( "distance" ), context, widgetContext, &distParam );
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< QgsProcessingParameterDistance * >( def.get() )->defaultValue().toDouble(), 1.0 );
QCOMPARE( static_cast< QgsProcessingParameterDistance * >( def.get() )->minimum(), 1.0 );
QCOMPARE( static_cast< QgsProcessingParameterDistance * >( def.get() )->maximum(), 100.0 );
QCOMPARE( static_cast< QgsProcessingParameterDistance * >( def.get() )->parentParameterName(), QStringLiteral( "parent" ) );
distParam.setFlags( QgsProcessingParameterDefinition::FlagAdvanced | QgsProcessingParameterDefinition::FlagOptional );
distParam.setParentParameterName( QString() );
distParam.setMinimum( 10 );
distParam.setMaximum( 12 );
distParam.setDefaultValue( 11.5 );
widget = qgis::make_unique< QgsProcessingParameterDefinitionWidget >( QStringLiteral( "distance" ), context, widgetContext, &distParam );
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< QgsProcessingParameterDistance * >( def.get() )->defaultValue().toDouble(), 11.5 );
QCOMPARE( static_cast< QgsProcessingParameterDistance * >( def.get() )->minimum(), 10.0 );
QCOMPARE( static_cast< QgsProcessingParameterDistance * >( def.get() )->maximum(), 12.0 );
QVERIFY( static_cast< QgsProcessingParameterDistance * >( def.get() )->parentParameterName().isEmpty() );
}

void TestProcessingGui::testScaleWrapper()
Expand Down

0 comments on commit abe12c4

Please sign in to comment.