diff --git a/python/gui/auto_generated/processing/qgsprocessingparameterdefinitionwidget.sip.in b/python/gui/auto_generated/processing/qgsprocessingparameterdefinitionwidget.sip.in index 8fb9dad414a..8c94e47ba72 100644 --- a/python/gui/auto_generated/processing/qgsprocessingparameterdefinitionwidget.sip.in +++ b/python/gui/auto_generated/processing/qgsprocessingparameterdefinitionwidget.sip.in @@ -12,7 +12,8 @@ -class QgsProcessingAbstractParameterDefinitionWidget : QWidget + +class QgsProcessingAbstractParameterDefinitionWidget : QWidget, QgsExpressionContextGenerator { %Docstring Abstract base class for widgets which allow users to specify the properties of a @@ -53,6 +54,42 @@ Common properties for parameters, including the ``name``, ``description``, and p method. Subclass implementations must use these properties when crafting a parameter definition which also respects the additional properties specific to the parameter type handled by the widget subclass. %End + + virtual void setWidgetContext( const QgsProcessingParameterWidgetContext &context ); +%Docstring +Sets the ``context`` in which the Processing definition widget is shown, e.g., the +parent model algorithm, a linked map canvas, and other relevant information which allows the widget +to fine-tune its behavior. + +Subclasses should take care to call the base class method when reimplementing this method. + +.. seealso:: :py:func:`widgetContext` + +.. versionadded:: 3.18 +%End + + const QgsProcessingParameterWidgetContext &widgetContext() const; +%Docstring +Returns the context in which the Processing definition widget is shown, e.g., the +parent model algorithm, a linked map canvas, and other relevant information which allows the widget +to fine-tune its behavior. + +.. seealso:: :py:func:`setWidgetContext` + +.. versionadded:: 3.18 +%End + + void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator ); +%Docstring +Registers a Processing context ``generator`` class that will be used to retrieve +a Processing context for the widget when required. + +.. versionadded:: 3.18 +%End + + virtual QgsExpressionContext createExpressionContext() const; + + }; @@ -96,6 +133,14 @@ associated with the parameter. Returns a new instance of a parameter definition, using the current settings defined in the dialog. The ``name`` parameter specifies the name for the newly created parameter. +%End + + void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator ); +%Docstring +Registers a Processing context ``generator`` class that will be used to retrieve +a Processing context for the widget when required. + +.. versionadded:: 3.18 %End }; @@ -181,6 +226,14 @@ Returns the color for the comments for the parameter. void switchToCommentTab(); %Docstring Switches the dialog to the comments tab. +%End + + void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator ); +%Docstring +Registers a Processing context ``generator`` class that will be used to retrieve +a Processing context for the widget when required. + +.. versionadded:: 3.18 %End public slots: diff --git a/python/gui/auto_generated/qgsexpressionlineedit.sip.in b/python/gui/auto_generated/qgsexpressionlineedit.sip.in index f03a66d7862..f08e480a858 100644 --- a/python/gui/auto_generated/qgsexpressionlineedit.sip.in +++ b/python/gui/auto_generated/qgsexpressionlineedit.sip.in @@ -127,15 +127,6 @@ an expression context for the widget. create an expression context when required. %End - void setExpressionContext( QgsExpressionContext &context ); -%Docstring -Set a default expression context. Will be used if no QgsEcpressionContextGenerator or layer is set. - -:param context: The QgsExpressionContext to use. - -.. versionadded:: 3.18 -%End - signals: void expressionChanged( const QString &expression ); diff --git a/python/plugins/processing/modeler/ModelerDialog.py b/python/plugins/processing/modeler/ModelerDialog.py index fe827008778..0fc584cb64a 100644 --- a/python/plugins/processing/modeler/ModelerDialog.py +++ b/python/plugins/processing/modeler/ModelerDialog.py @@ -40,12 +40,13 @@ from qgis.core import (Qgis, QgsProcessing, QgsProject, QgsProcessingModelParameter, - QgsSettings + QgsSettings, ) from qgis.gui import (QgsProcessingParameterDefinitionDialog, QgsProcessingParameterWidgetContext, QgsModelGraphicsScene, - QgsModelDesignerDialog) + QgsModelDesignerDialog, + QgsProcessingContextGenerator) from processing.gui.HelpEditionDialog import HelpEditionDialog from processing.gui.AlgorithmDialog import AlgorithmDialog from processing.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog @@ -105,6 +106,19 @@ class ModelerDialog(QgsModelDesignerDialog): self.view().centerOn(0, 0) + self.processing_context = createContext() + + class ContextGenerator(QgsProcessingContextGenerator): + + def __init__(self, context): + super().__init__() + self.processing_context = context + + def processingContext(self): + return self.processing_context + + self.context_generator = ContextGenerator(self.processing_context) + def editHelp(self): alg = self.model() dlg = HelpEditionDialog(alg) @@ -270,6 +284,7 @@ class ModelerDialog(QgsModelDesignerDialog): context=context, widgetContext=widget_context, algorithm=self.model()) + dlg.registerProcessingContextGenerator(self.context_generator) if dlg.exec_(): new_param = dlg.createParameter() self.autogenerate_parameter_name(new_param) diff --git a/python/plugins/processing/modeler/ModelerGraphicItem.py b/python/plugins/processing/modeler/ModelerGraphicItem.py index 09b0ef24fe0..eda1d02f52b 100644 --- a/python/plugins/processing/modeler/ModelerGraphicItem.py +++ b/python/plugins/processing/modeler/ModelerGraphicItem.py @@ -31,7 +31,8 @@ from qgis.gui import ( QgsProcessingParameterWidgetContext, QgsModelParameterGraphicItem, QgsModelChildAlgorithmGraphicItem, - QgsModelOutputGraphicItem + QgsModelOutputGraphicItem, + QgsProcessingContextGenerator ) from processing.modeler.ModelerParameterDefinitionDialog import ModelerParameterDefinitionDialog from processing.modeler.ModelerParametersDialog import ModelerParametersDialog @@ -50,6 +51,19 @@ class ModelerInputGraphicItem(QgsModelParameterGraphicItem): def __init__(self, element, model): super().__init__(element, model, None) + self.processing_context = createContext() + + class ContextGenerator(QgsProcessingContextGenerator): + + def __init__(self, context): + super().__init__() + self.processing_context = context + + def processingContext(self): + return self.processing_context + + self.context_generator = ContextGenerator(self.processing_context) + def create_widget_context(self): """ Returns a new widget context for use in the model editor @@ -91,6 +105,8 @@ class ModelerInputGraphicItem(QgsModelParameterGraphicItem): algorithm=self.model()) dlg.setComments(comment) dlg.setCommentColor(comment_color) + dlg.registerProcessingContextGenerator(self.context_generator) + if edit_comment: dlg.switchToCommentTab() diff --git a/src/gui/processing/qgsprocessingparameterdefinitionwidget.cpp b/src/gui/processing/qgsprocessingparameterdefinitionwidget.cpp index 8771e36eab3..c5801fc1bf0 100644 --- a/src/gui/processing/qgsprocessingparameterdefinitionwidget.cpp +++ b/src/gui/processing/qgsprocessingparameterdefinitionwidget.cpp @@ -34,14 +34,35 @@ #include QgsProcessingAbstractParameterDefinitionWidget::QgsProcessingAbstractParameterDefinitionWidget( QgsProcessingContext &, - const QgsProcessingParameterWidgetContext &, + const QgsProcessingParameterWidgetContext &context, const QgsProcessingParameterDefinition *, const QgsProcessingAlgorithm *, QWidget *parent ) : QWidget( parent ) + , mWidgetContext( context ) { } +void QgsProcessingAbstractParameterDefinitionWidget::setWidgetContext( const QgsProcessingParameterWidgetContext &context ) +{ + mWidgetContext = context; +} + +const QgsProcessingParameterWidgetContext &QgsProcessingAbstractParameterDefinitionWidget::widgetContext() const +{ + return mWidgetContext; +} + +void QgsProcessingAbstractParameterDefinitionWidget::registerProcessingContextGenerator( QgsProcessingContextGenerator *generator ) +{ + mContextGenerator = generator; +} + +QgsExpressionContext QgsProcessingAbstractParameterDefinitionWidget::createExpressionContext() const +{ + return QgsProcessingGuiUtils::createExpressionContext( mContextGenerator, mWidgetContext, nullptr, nullptr ); +} + // // QgsProcessingParameterDefinitionWidget // @@ -120,6 +141,14 @@ QgsProcessingParameterDefinition *QgsProcessingParameterDefinitionWidget::create return param.release(); } +void QgsProcessingParameterDefinitionWidget::registerProcessingContextGenerator( QgsProcessingContextGenerator *generator ) +{ + if ( mDefinitionWidget ) + { + mDefinitionWidget->registerProcessingContextGenerator( generator ); + } +} + // // QgsProcessingParameterDefinitionDialog // @@ -210,6 +239,14 @@ void QgsProcessingParameterDefinitionDialog::switchToCommentTab() mCommentEdit->selectAll(); } +void QgsProcessingParameterDefinitionDialog::registerProcessingContextGenerator( QgsProcessingContextGenerator *generator ) +{ + if ( mWidget ) + { + mWidget->registerProcessingContextGenerator( generator ); + } +} + void QgsProcessingParameterDefinitionDialog::accept() { if ( mWidget->mDescriptionLineEdit->text().isEmpty() ) diff --git a/src/gui/processing/qgsprocessingparameterdefinitionwidget.h b/src/gui/processing/qgsprocessingparameterdefinitionwidget.h index c47cef60cc8..585f6133905 100644 --- a/src/gui/processing/qgsprocessingparameterdefinitionwidget.h +++ b/src/gui/processing/qgsprocessingparameterdefinitionwidget.h @@ -25,8 +25,11 @@ #include "qgis_gui.h" #include "qgis_sip.h" #include "qgsprocessingparameters.h" +#include "qgsexpressioncontextgenerator.h" +#include "qgsprocessingwidgetwrapper.h" + +class QgsProcessingContextGenerator; -class QgsProcessingParameterWidgetContext; class QLineEdit; class QCheckBox; class QTabWidget; @@ -40,7 +43,7 @@ class QgsColorButton; * \ingroup gui * \since QGIS 3.10 */ -class GUI_EXPORT QgsProcessingAbstractParameterDefinitionWidget : public QWidget +class GUI_EXPORT QgsProcessingAbstractParameterDefinitionWidget : public QWidget, public QgsExpressionContextGenerator { Q_OBJECT @@ -73,6 +76,43 @@ class GUI_EXPORT QgsProcessingAbstractParameterDefinitionWidget : public QWidget * also respects the additional properties specific to the parameter type handled by the widget subclass. */ virtual QgsProcessingParameterDefinition *createParameter( const QString &name, const QString &description, QgsProcessingParameterDefinition::Flags flags ) const = 0 SIP_FACTORY; + + /** + * Sets the \a context in which the Processing definition widget is shown, e.g., the + * parent model algorithm, a linked map canvas, and other relevant information which allows the widget + * to fine-tune its behavior. + * + * Subclasses should take care to call the base class method when reimplementing this method. + * + * \see widgetContext() + * \since QGIS 3.18 + */ + virtual void setWidgetContext( const QgsProcessingParameterWidgetContext &context ); + + /** + * Returns the context in which the Processing definition widget is shown, e.g., the + * parent model algorithm, a linked map canvas, and other relevant information which allows the widget + * to fine-tune its behavior. + * + * \see setWidgetContext() + * \since QGIS 3.18 + */ + const QgsProcessingParameterWidgetContext &widgetContext() const; + + /** + * Registers a Processing context \a generator class that will be used to retrieve + * a Processing context for the widget when required. + * + * \since QGIS 3.18 + */ + void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator ); + + QgsExpressionContext createExpressionContext() const override; + + private: + + QgsProcessingContextGenerator *mContextGenerator = nullptr; + QgsProcessingParameterWidgetContext mWidgetContext; }; @@ -117,6 +157,14 @@ class GUI_EXPORT QgsProcessingParameterDefinitionWidget: public QWidget */ QgsProcessingParameterDefinition *createParameter( const QString &name = QString() ) const SIP_FACTORY; + /** + * Registers a Processing context \a generator class that will be used to retrieve + * a Processing context for the widget when required. + * + * \since QGIS 3.18 + */ + void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator ); + private: QString mType; @@ -203,6 +251,14 @@ class GUI_EXPORT QgsProcessingParameterDefinitionDialog: public QDialog */ void switchToCommentTab(); + /** + * Registers a Processing context \a generator class that will be used to retrieve + * a Processing context for the widget when required. + * + * \since QGIS 3.18 + */ + void registerProcessingContextGenerator( QgsProcessingContextGenerator *generator ); + public slots: void accept() override; diff --git a/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp b/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp index 1503ab806f6..ebe3aa3c077 100644 --- a/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp +++ b/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp @@ -1841,18 +1841,13 @@ QgsProcessingAbstractParameterDefinitionWidget *QgsProcessingFileWidgetWrapper:: QgsProcessingExpressionParameterDefinitionWidget::QgsProcessingExpressionParameterDefinitionWidget( QgsProcessingContext &context, const QgsProcessingParameterWidgetContext &widgetContext, const QgsProcessingParameterDefinition *definition, const QgsProcessingAlgorithm *algorithm, QWidget *parent ) : QgsProcessingAbstractParameterDefinitionWidget( context, widgetContext, definition, algorithm, parent ) { - mModel = widgetContext.model(); - QVBoxLayout *vlayout = new QVBoxLayout(); vlayout->setContentsMargins( 0, 0, 0, 0 ); vlayout->addWidget( new QLabel( tr( "Default value" ) ) ); mDefaultLineEdit = new QgsExpressionLineEdit(); - if ( mModel ) - { - QgsExpressionContext expressionContext = createExpressionContext( context, algorithm ); - mDefaultLineEdit->setExpressionContext( expressionContext ); - } + mDefaultLineEdit->registerExpressionContextGenerator( this ); + if ( const QgsProcessingParameterExpression *expParam = dynamic_cast( definition ) ) mDefaultLineEdit->setExpression( QgsProcessingParameters::parameterAsExpression( expParam, expParam->defaultValueForGui(), context ) ); vlayout->addWidget( mDefaultLineEdit ); @@ -1866,14 +1861,13 @@ QgsProcessingExpressionParameterDefinitionWidget::QgsProcessingExpressionParamet if ( const QgsProcessingParameterExpression *expParam = dynamic_cast( definition ) ) initialParent = expParam->parentLayerParameterName(); - - if ( mModel ) + if ( QgsProcessingModelAlgorithm *model = widgetContext.model() ) { // populate combo box with other model input choices - const QMap components = mModel->parameterComponents(); + const QMap components = model->parameterComponents(); for ( auto it = components.constBegin(); it != components.constEnd(); ++it ) { - if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( mModel->parameterDefinition( it.value().parameterName() ) ) ) + if ( const QgsProcessingParameterFeatureSource *definition = dynamic_cast< const QgsProcessingParameterFeatureSource * >( model->parameterDefinition( it.value().parameterName() ) ) ) { mParentLayerComboBox-> addItem( definition->description(), definition->name() ); if ( !initialParent.isEmpty() && initialParent == definition->name() ) @@ -1881,7 +1875,7 @@ QgsProcessingExpressionParameterDefinitionWidget::QgsProcessingExpressionParamet mParentLayerComboBox->setCurrentIndex( mParentLayerComboBox->count() - 1 ); } } - else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( mModel->parameterDefinition( it.value().parameterName() ) ) ) + else if ( const QgsProcessingParameterVectorLayer *definition = dynamic_cast< const QgsProcessingParameterVectorLayer * >( model->parameterDefinition( it.value().parameterName() ) ) ) { mParentLayerComboBox-> addItem( definition->description(), definition->name() ); if ( !initialParent.isEmpty() && initialParent == definition->name() ) @@ -1907,46 +1901,9 @@ QgsProcessingParameterDefinition *QgsProcessingExpressionParameterDefinitionWidg { auto param = qgis::make_unique< QgsProcessingParameterExpression >( name, description, mDefaultLineEdit->expression(), mParentLayerComboBox->currentData().toString() ); param->setFlags( flags ); - if ( mModel ) - { - QStringList extraVars = mModel->variables().keys(); - param->setAdditionalExpressionContextVariables( extraVars ); - } return param.release(); } -QgsExpressionContext QgsProcessingExpressionParameterDefinitionWidget::createExpressionContext( QgsProcessingContext &context, const QgsProcessingAlgorithm *algorithm ) const -{ - QgsExpressionContext finalContext = context.expressionContext(); - QString childId; - - QgsExpressionContextScope *algScope = QgsExpressionContextUtils::processingAlgorithmScope( algorithm, QVariantMap(), context ); - finalContext.appendScope( algScope ); - - QgsExpressionContextScope *modelScope = QgsExpressionContextUtils::processingModelAlgorithmScope( mModel, QVariantMap(), context ); - finalContext << modelScope; - const QgsProcessingAlgorithm *childAlg = nullptr; - if ( mModel->childAlgorithms().contains( childId ) ) - childAlg = mModel->childAlgorithm( childId ).algorithm(); - QgsExpressionContextScope *algorithmScope = QgsExpressionContextUtils::processingAlgorithmScope( childAlg, QVariantMap(), context ); - finalContext << algorithmScope; - - QgsExpressionContextScope *childScope = mModel->createExpressionContextScopeForChildAlgorithm( childId, context, QVariantMap(), QVariantMap() ); - finalContext << childScope; - - QStringList highlightedVariables = childScope->variableNames(); - QStringList highlightedFunctions = childScope->functionNames(); - highlightedVariables += algorithmScope->variableNames(); - highlightedVariables += algScope->variableNames(); - highlightedVariables += mModel->variables().keys(); - highlightedFunctions += algScope->functionNames(); - highlightedFunctions += algorithmScope->functionNames(); - finalContext.setHighlightedVariables( highlightedVariables ); - finalContext.setHighlightedFunctions( highlightedFunctions ); - - return finalContext; -} - QgsProcessingExpressionWidgetWrapper::QgsProcessingExpressionWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QWidget *parent ) : QgsAbstractProcessingParameterWidgetWrapper( parameter, type, parent ) { diff --git a/src/gui/processing/qgsprocessingwidgetwrapperimpl.h b/src/gui/processing/qgsprocessingwidgetwrapperimpl.h index 5040a3996d0..d7775225ea9 100644 --- a/src/gui/processing/qgsprocessingwidgetwrapperimpl.h +++ b/src/gui/processing/qgsprocessingwidgetwrapperimpl.h @@ -66,8 +66,6 @@ class QgsProcessingMapLayerComboBox; class QgsRasterBandComboBox; class QgsProcessingLayerOutputDestinationWidget; class QgsCheckableComboBox; -class QgsProcessingModelAlgorithm; -class QgsExpressionContext; ///@cond PRIVATE @@ -635,13 +633,11 @@ class GUI_EXPORT QgsProcessingExpressionParameterDefinitionWidget : public QgsPr 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; - QgsExpressionContext createExpressionContext( QgsProcessingContext &context, const QgsProcessingAlgorithm *algorithm ) const; private: QComboBox *mParentLayerComboBox = nullptr; QgsExpressionLineEdit *mDefaultLineEdit = nullptr; - QgsProcessingModelAlgorithm *mModel = nullptr; }; diff --git a/src/gui/qgsexpressionlineedit.h b/src/gui/qgsexpressionlineedit.h index 07e4a8393bf..c4cf7b8f1d5 100644 --- a/src/gui/qgsexpressionlineedit.h +++ b/src/gui/qgsexpressionlineedit.h @@ -132,13 +132,6 @@ class GUI_EXPORT QgsExpressionLineEdit : public QWidget */ void registerExpressionContextGenerator( const QgsExpressionContextGenerator *generator ); - /** - * Set a default expression context. Will be used if no QgsEcpressionContextGenerator or layer is set. - * \param context The QgsExpressionContext to use. - * \since QGIS 3.18 - */ - void setExpressionContext( QgsExpressionContext &context ) { mExpressionContext = context; } - signals: /**