From a9788339ea0d0fa04c7e13a9f40900dbc51506d6 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Mon, 1 Jul 2019 10:29:23 +1000 Subject: [PATCH] Port an item type which has a parent parameter choice (layout items) for reference --- .../ModelerParameterDefinitionDialog.py | 27 --------- .../qgsprocessingwidgetwrapperimpl.cpp | 58 +++++++++++++++++++ .../qgsprocessingwidgetwrapperimpl.h | 23 ++++++++ tests/src/gui/testprocessinggui.cpp | 28 +++++++++ 4 files changed, 109 insertions(+), 27 deletions(-) diff --git a/python/plugins/processing/modeler/ModelerParameterDefinitionDialog.py b/python/plugins/processing/modeler/ModelerParameterDefinitionDialog.py index eecf6405d6b..ba779263386 100755 --- a/python/plugins/processing/modeler/ModelerParameterDefinitionDialog.py +++ b/python/plugins/processing/modeler/ModelerParameterDefinitionDialog.py @@ -54,14 +54,11 @@ from qgis.core import (QgsApplication, QgsProcessingParameterRange, QgsProcessingParameterRasterLayer, QgsProcessingParameterEnum, - QgsProcessingParameterString, QgsProcessingParameterExpression, QgsProcessingParameterVectorLayer, QgsProcessingParameterField, QgsProcessingParameterFeatureSource, QgsProcessingParameterBand, - QgsProcessingParameterLayout, - QgsProcessingParameterLayoutItem, QgsProcessingDestinationParameter, QgsProcessingParameterFeatureSink, QgsProcessingParameterFileDestination, @@ -82,7 +79,6 @@ class ModelerParameterDefinitionDialog(QDialog): def use_legacy_dialog(param=None, paramType=None): if paramType in (parameters.PARAMETER_TABLE_FIELD, parameters.PARAMETER_BAND, - parameters.PARAMETER_LAYOUTITEM, parameters.PARAMETER_VECTOR, parameters.PARAMETER_TABLE, parameters.PARAMETER_MULTIPLE, @@ -98,7 +94,6 @@ class ModelerParameterDefinitionDialog(QDialog): return True elif isinstance(param, (QgsProcessingParameterField, QgsProcessingParameterBand, - QgsProcessingParameterLayoutItem, QgsProcessingParameterFeatureSource, QgsProcessingParameterVectorLayer, QgsProcessingParameterMultipleLayers, @@ -209,20 +204,6 @@ class ModelerParameterDefinitionDialog(QDialog): self.parentCombo.setCurrentIndex(idx) idx += 1 self.verticalLayout.addWidget(self.parentCombo) - elif self.paramType == parameters.PARAMETER_LAYOUTITEM or \ - isinstance(self.param, QgsProcessingParameterLayoutItem): - self.verticalLayout.addWidget(QLabel(self.tr('Parent layout'))) - self.parentCombo = QComboBox() - idx = 0 - for param in list(self.alg.parameterComponents().values()): - definition = self.alg.parameterDefinition(param.parameterName()) - if isinstance(definition, (QgsProcessingParameterLayout)): - self.parentCombo.addItem(definition.description(), definition.name()) - if self.param is not None: - if self.param.parentLayoutParameterName() == 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))): @@ -451,14 +432,6 @@ class ModelerParameterDefinitionDialog(QDialog): return parent = self.parentCombo.currentData() self.param = QgsProcessingParameterBand(name, description, None, parent) - elif (self.paramType == parameters.PARAMETER_LAYOUTITEM or - isinstance(self.param, QgsProcessingParameterLayoutItem)): - 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 = QgsProcessingParameterLayoutItem(name, description, None, parent) elif (self.paramType == parameters.PARAMETER_MAP_LAYER or isinstance(self.param, QgsProcessingParameterMapLayer)): self.param = QgsProcessingParameterMapLayer( diff --git a/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp b/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp index d529775236e..13ba5452e39 100644 --- a/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp +++ b/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp @@ -17,6 +17,7 @@ #include "qgsprocessingwidgetwrapperimpl.h" #include "qgsprocessingparameters.h" +#include "processing/models/qgsprocessingmodelalgorithm.h" #include "qgsprocessingoutputs.h" #include "qgsprojectionselectionwidget.h" #include "qgsprocessingmatrixparameterdialog.h" @@ -2009,6 +2010,58 @@ QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutWidgetWrapper::c // QgsProcessingLayoutItemWidgetWrapper // + +QgsProcessingLayoutItemParameterDefinitionWidget::QgsProcessingLayoutItemParameterDefinitionWidget( 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( "Parent layout" ) ) ); + + mParentLayoutComboBox = new QComboBox(); + QString initialParent; + if ( const QgsProcessingParameterLayoutItem *itemParam = dynamic_cast( definition ) ) + initialParent = itemParam->parentLayoutParameterName(); + + bool foundParent = false; + if ( widgetContext.model() ) + { + // populate combo box with other model input choices + const QMap components = widgetContext.model()->parameterComponents(); + for ( auto it = components.constBegin(); it != components.constEnd(); ++it ) + { + if ( const QgsProcessingParameterLayout *definition = dynamic_cast< const QgsProcessingParameterLayout * >( widgetContext.model()->parameterDefinition( it.value().parameterName() ) ) ) + { + mParentLayoutComboBox-> addItem( definition->description(), definition->name() ); + if ( !initialParent.isEmpty() && initialParent == definition->name() ) + { + mParentLayoutComboBox->setCurrentIndex( mParentLayoutComboBox->count() - 1 ); + foundParent = true; + } + } + } + } + + if ( mParentLayoutComboBox->count() == 0 && !initialParent.isEmpty() ) + { + // if no parent candidates found, we just add the existing one as a placeholder + mParentLayoutComboBox->addItem( initialParent, initialParent ); + mParentLayoutComboBox->setCurrentIndex( mParentLayoutComboBox->count() - 1 ); + } + + vlayout->addWidget( mParentLayoutComboBox ); + setLayout( vlayout ); +} +QgsProcessingParameterDefinition *QgsProcessingLayoutItemParameterDefinitionWidget::createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const +{ + auto param = qgis::make_unique< QgsProcessingParameterLayoutItem >( name, description, QVariant(), mParentLayoutComboBox->currentData().toString() ); + param->setFlags( flags ); + return param.release(); +} + + QgsProcessingLayoutItemWidgetWrapper::QgsProcessingLayoutItemWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent ) : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent ) { @@ -2170,6 +2223,11 @@ QgsAbstractProcessingParameterWidgetWrapper *QgsProcessingLayoutItemWidgetWrappe return new QgsProcessingLayoutItemWidgetWrapper( parameter, type ); } +QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingLayoutItemWidgetWrapper::createParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm ) +{ + return new QgsProcessingLayoutItemParameterDefinitionWidget( context, widgetContext, definition, algorithm ); +} + // // QgsProcessingPointMapTool // diff --git a/src/gui/processing/qgsprocessingwidgetwrapperimpl.h b/src/gui/processing/qgsprocessingwidgetwrapperimpl.h index d62457a8584..90c17b6f093 100644 --- a/src/gui/processing/qgsprocessingwidgetwrapperimpl.h +++ b/src/gui/processing/qgsprocessingwidgetwrapperimpl.h @@ -627,6 +627,24 @@ class GUI_EXPORT QgsProcessingLayoutWidgetWrapper : public QgsAbstractProcessing }; + +class GUI_EXPORT QgsProcessingLayoutItemParameterDefinitionWidget : public QgsProcessingAbstractParameterDefinitionWidget +{ + Q_OBJECT + public: + + QgsProcessingLayoutItemParameterDefinitionWidget( 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 *mParentLayoutComboBox = nullptr; + +}; + class GUI_EXPORT QgsProcessingLayoutItemWidgetWrapper : public QgsAbstractProcessingParameterWidgetWrapper, public QgsProcessingParameterWidgetFactoryInterface { Q_OBJECT @@ -639,6 +657,11 @@ class GUI_EXPORT QgsProcessingLayoutItemWidgetWrapper : public QgsAbstractProces // 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; diff --git a/tests/src/gui/testprocessinggui.cpp b/tests/src/gui/testprocessinggui.cpp index 92d10b4040e..1b5f284c39c 100644 --- a/tests/src/gui/testprocessinggui.cpp +++ b/tests/src/gui/testprocessinggui.cpp @@ -2889,6 +2889,34 @@ void TestProcessingGui::testLayoutItemWrapper() // modeler wrapper testWrapper( QgsProcessingGui::Modeler ); + + // config widget + QgsProcessingParameterWidgetContext widgetContext; + QgsProcessingContext context; + std::unique_ptr< QgsProcessingParameterDefinitionWidget > widget = qgis::make_unique< QgsProcessingParameterDefinitionWidget >( QStringLiteral( "layoutitem" ), 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 + QgsProcessingParameterLayoutItem itemParam( QStringLiteral( "n" ), QStringLiteral( "test desc" ), QVariant(), QStringLiteral( "parent" ) ); + widget = qgis::make_unique< QgsProcessingParameterDefinitionWidget >( QStringLiteral( "layoutitem" ), context, widgetContext, &itemParam ); + 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< QgsProcessingParameterLayoutItem * >( def.get() )->parentLayoutParameterName(), QStringLiteral( "parent" ) ); + itemParam.setFlags( QgsProcessingParameterDefinition::FlagAdvanced | QgsProcessingParameterDefinition::FlagOptional ); + itemParam.setParentLayoutParameterName( QString() ); + widget = qgis::make_unique< QgsProcessingParameterDefinitionWidget >( QStringLiteral( "layoutitem" ), context, widgetContext, &itemParam ); + 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 ); + QVERIFY( static_cast< QgsProcessingParameterLayoutItem * >( def.get() )->parentLayoutParameterName().isEmpty() ); } void TestProcessingGui::testPointPanel()