Skip to content

Commit

Permalink
Automatically handle adding data defined button for dynamic properties
Browse files Browse the repository at this point in the history
Also exposes this capability to modeler - so that model algorithms
can use data defined parameters within their child algorithms.

TODO:
- tests
- setting the associated vector layer
  • Loading branch information
nyalldawson committed Sep 4, 2018
1 parent a717b85 commit 70c1680
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 30 deletions.
Expand Up @@ -92,22 +92,21 @@ Returns the current wrapped label, if any.
Returns the parameter definition associated with this wrapper.
%End


virtual void setWidgetValue( const QVariant &value, const QgsProcessingContext &context ) = 0;
void setParameterValue( const QVariant &value, const QgsProcessingContext &context );
%Docstring
Sets the current ``value`` for the parameter.

The ``context`` argument is used to specify the wider Processing context which the
current value is associated with.

.. seealso:: :py:func:`value`
.. seealso:: :py:func:`parameterValue`
%End

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

.. seealso:: :py:func:`setWidgetValue`
.. seealso:: :py:func:`setParameterValue`
%End

virtual void postInitialize( const QList< QgsAbstractProcessingParameterWidgetWrapper * > &wrappers );
Expand Down Expand Up @@ -137,6 +136,23 @@ label should be shown for the parameter's widget (i.e. the label is embedded ins
widget itself).

.. seealso:: :py:func:`createWidget`
%End

virtual void setWidgetValue( const QVariant &value, const QgsProcessingContext &context ) = 0;
%Docstring
Sets the current ``value`` for the parameter to show in the widget.

The ``context`` argument is used to specify the wider Processing context which the
current value is associated with.

.. seealso:: :py:func:`widgetValue`
%End

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

.. seealso:: :py:func:`setWidgetValue`
%End

};
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/gui/AlgorithmDialog.py
Expand Up @@ -110,7 +110,7 @@ def getParameterValues(self):
if widget is None:
continue

value = wrapper.value()
value = wrapper.parameterValue()
parameters[param.name()] = value

if not param.checkValueIsAcceptable(value):
Expand Down
2 changes: 1 addition & 1 deletion python/plugins/processing/gui/ParametersPanel.py
Expand Up @@ -219,7 +219,7 @@ def setParameters(self, parameters):
value = parameters[param.name()]

wrapper = self.wrappers[param.name()]
wrapper.setWidgetValue(value, context)
wrapper.setParameterValue(value, context)
else:
dest_widget = self.outputWidgets[param.name()]
dest_widget.setValue(parameters[param.name()])
Expand Down
6 changes: 6 additions & 0 deletions python/plugins/processing/gui/wrappers.py
Expand Up @@ -202,6 +202,12 @@ def createLabel(self):
def setValue(self, value):
pass

def value(self):
return None

def widgetValue(self):
return self.value()

def setWidgetValue(self, value, context):
self.setValue(value)

Expand Down
4 changes: 2 additions & 2 deletions src/gui/processing/qgsprocessingmodelerwidget.cpp
Expand Up @@ -145,7 +145,7 @@ QgsProcessingModelChildParameterSource QgsProcessingModelerParameterWidget::valu
switch ( mStackedWidget->currentIndex() )
{
case 0:
return QgsProcessingModelChildParameterSource::fromStaticValue( mStaticWidgetWrapper->value() );
return QgsProcessingModelChildParameterSource::fromStaticValue( mStaticWidgetWrapper->parameterValue() );

case 1:
return QgsProcessingModelChildParameterSource::fromExpression( mExpressionWidget->expression() );
Expand Down Expand Up @@ -238,7 +238,7 @@ void QgsProcessingModelerParameterWidget::setSourceType( QgsProcessingModelChild

void QgsProcessingModelerParameterWidget::updateUi()
{
mStaticWidgetWrapper->setWidgetValue( mStaticValue, mContext );
mStaticWidgetWrapper->setParameterValue( mStaticValue, mContext );

mExpressionWidget->setExpression( mExpression );

Expand Down
41 changes: 39 additions & 2 deletions src/gui/processing/qgsprocessingwidgetwrapper.cpp
Expand Up @@ -19,8 +19,9 @@
#include "qgsprocessingwidgetwrapper.h"
#include "qgsprocessingparameters.h"
#include "qgsprocessingmodelerwidget.h"
#include "qgspropertyoverridebutton.h"
#include <QLabel>

#include <QHBoxLayout>

QgsAbstractProcessingParameterWidgetWrapper::QgsAbstractProcessingParameterWidgetWrapper( const QgsProcessingParameterDefinition *parameter, QgsProcessingGui::WidgetType type, QObject *parent )
: QObject( parent )
Expand All @@ -40,9 +41,25 @@ QWidget *QgsAbstractProcessingParameterWidgetWrapper::createWrappedWidget( const
return mWidget;

mWidget = createWidget();
QWidget *wrappedWidget = mWidget;
if ( mType != QgsProcessingGui::Batch && mParameterDefinition->isDynamic() )
{
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->setMargin( 0 );
hLayout->setContentsMargins( 0, 0, 0, 0 );
hLayout->addWidget( mWidget, 1 );
mPropertyButton = new QgsPropertyOverrideButton();
hLayout->addWidget( mPropertyButton );
mPropertyButton->init( 0, QgsProperty(), mParameterDefinition->dynamicPropertyDefinition() );
mPropertyButton->registerEnabledWidget( mWidget, false );

wrappedWidget = new QWidget();
wrappedWidget->setLayout( hLayout );
}

setWidgetValue( mParameterDefinition->defaultValue(), context );

return mWidget;
return wrappedWidget;
}

QLabel *QgsAbstractProcessingParameterWidgetWrapper::createWrappedLabel()
Expand All @@ -69,6 +86,26 @@ const QgsProcessingParameterDefinition *QgsAbstractProcessingParameterWidgetWrap
return mParameterDefinition;
}

void QgsAbstractProcessingParameterWidgetWrapper::setParameterValue( const QVariant &value, const QgsProcessingContext &context )
{
if ( mPropertyButton && value.canConvert< QgsProperty >() )
{
mPropertyButton->setToProperty( value.value< QgsProperty >() );
}
else
{
setWidgetValue( value, context );
}
}

QVariant QgsAbstractProcessingParameterWidgetWrapper::parameterValue() const
{
if ( mPropertyButton && mPropertyButton->isActive() )
return mPropertyButton->toProperty();
else
return widgetValue();
}

QLabel *QgsAbstractProcessingParameterWidgetWrapper::createLabel()
{
switch ( mType )
Expand Down
29 changes: 23 additions & 6 deletions src/gui/processing/qgsprocessingwidgetwrapper.h
Expand Up @@ -30,6 +30,7 @@ class QgsProcessingContext;
class QgsProcessingModelerParameterWidget;
class QgsProcessingModelAlgorithm;
class QLabel;
class QgsPropertyOverrideButton;

/**
* \class QgsAbstractProcessingParameterWidgetWrapper
Expand Down Expand Up @@ -111,24 +112,22 @@ class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject
*/
const QgsProcessingParameterDefinition *parameterDefinition() const;

// TODO QGIS 4.0 - rename to setValue, avoid conflict with Python WidgetWrapper method

/**
* Sets the current \a value for the parameter.
*
* The \a context argument is used to specify the wider Processing context which the
* current value is associated with.
*
* \see value()
* \see parameterValue()
*/
virtual void setWidgetValue( const QVariant &value, const QgsProcessingContext &context ) = 0;
void setParameterValue( const QVariant &value, const QgsProcessingContext &context );

/**
* Returns the current value of the parameter.
*
* \see setWidgetValue()
* \see setParameterValue()
*/
virtual QVariant value() const = 0;
QVariant parameterValue() const;

/**
* Called after all wrappers have been created within a particular dialog or context,
Expand Down Expand Up @@ -159,12 +158,30 @@ class GUI_EXPORT QgsAbstractProcessingParameterWidgetWrapper : public QObject
*/
virtual QLabel *createLabel() SIP_FACTORY;

/**
* Sets the current \a value for the parameter to show in the widget.
*
* The \a context argument is used to specify the wider Processing context which the
* current value is associated with.
*
* \see widgetValue()
*/
virtual void setWidgetValue( const QVariant &value, const QgsProcessingContext &context ) = 0;

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

private:

QgsProcessingGui::WidgetType mType = QgsProcessingGui::Standard;
const QgsProcessingParameterDefinition *mParameterDefinition = nullptr;

QPointer< QWidget > mWidget;
QPointer< QgsPropertyOverrideButton > mPropertyButton;
QPointer< QLabel > mLabel;

};
Expand Down
2 changes: 1 addition & 1 deletion src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp
Expand Up @@ -92,7 +92,7 @@ void QgsProcessingBooleanWidgetWrapper::setWidgetValue( const QVariant &value, c
}
}

QVariant QgsProcessingBooleanWidgetWrapper::value() const
QVariant QgsProcessingBooleanWidgetWrapper::widgetValue() const
{
switch ( type() )
{
Expand Down
7 changes: 4 additions & 3 deletions src/gui/processing/qgsprocessingwidgetwrapperimpl.h
Expand Up @@ -41,12 +41,11 @@ class GUI_EXPORT QgsProcessingBooleanWidgetWrapper : public QgsAbstractProcessin
// QgsProcessingParameterWidgetWrapper interface
QWidget *createWidget() override SIP_FACTORY;
QLabel *createLabel() override SIP_FACTORY;
void setWidgetValue( const QVariant &value, const QgsProcessingContext &context ) override;
QVariant value() const override;

protected:

protected:
void setWidgetValue( const QVariant &value, const QgsProcessingContext &context ) override;
QVariant widgetValue() const override;

QStringList compatibleParameterTypes() const override;

Expand All @@ -58,6 +57,8 @@ class GUI_EXPORT QgsProcessingBooleanWidgetWrapper : public QgsAbstractProcessin

QCheckBox *mCheckBox = nullptr;
QComboBox *mComboBox = nullptr;

friend class TestProcessingGui;
};

///@endcond PRIVATE
Expand Down
18 changes: 9 additions & 9 deletions tests/src/gui/testprocessinggui.cpp
Expand Up @@ -79,7 +79,7 @@ class TestWidgetWrapper : public QgsAbstractProcessingParameterWidgetWrapper
{
}

QVariant value() const override
QVariant widgetValue() const override
{
return QVariant();
}
Expand Down Expand Up @@ -286,12 +286,12 @@ void TestProcessingGui::testWrapperGeneral()
param = TestParamType( QStringLiteral( "boolean" ), QStringLiteral( "bool" ), true );
QgsProcessingBooleanWidgetWrapper trueDefault( &param );
w = trueDefault.createWrappedWidget( context );
QVERIFY( trueDefault.value().toBool() );
QVERIFY( trueDefault.widgetValue().toBool() );
delete w;
param = TestParamType( QStringLiteral( "boolean" ), QStringLiteral( "bool" ), false );
QgsProcessingBooleanWidgetWrapper falseDefault( &param );
w = falseDefault.createWrappedWidget( context );
QVERIFY( !falseDefault.value().toBool() );
QVERIFY( !falseDefault.widgetValue().toBool() );
delete w;
}

Expand Down Expand Up @@ -406,10 +406,10 @@ void TestProcessingGui::testBooleanWrapper()
QgsProcessingContext context;
QWidget *w = wrapper.createWrappedWidget( context );
wrapper.setWidgetValue( true, context );
QVERIFY( wrapper.value().toBool() );
QVERIFY( wrapper.widgetValue().toBool() );
QVERIFY( static_cast< QCheckBox * >( wrapper.wrappedWidget() )->isChecked() );
wrapper.setWidgetValue( false, context );
QVERIFY( !wrapper.value().toBool() );
QVERIFY( !wrapper.widgetValue().toBool() );
QVERIFY( !static_cast< QCheckBox * >( wrapper.wrappedWidget() )->isChecked() );

// should be no label in standard mode
Expand All @@ -422,10 +422,10 @@ void TestProcessingGui::testBooleanWrapper()

w = wrapperB.createWrappedWidget( context );
wrapperB.setWidgetValue( true, context );
QVERIFY( wrapperB.value().toBool() );
QVERIFY( wrapperB.widgetValue().toBool() );
QVERIFY( static_cast< QComboBox * >( wrapperB.wrappedWidget() )->currentData().toBool() );
wrapperB.setWidgetValue( false, context );
QVERIFY( !wrapperB.value().toBool() );
QVERIFY( !wrapperB.widgetValue().toBool() );
QVERIFY( !static_cast< QComboBox * >( wrapperB.wrappedWidget() )->currentData().toBool() );

// should be no label in batch mode
Expand All @@ -437,10 +437,10 @@ void TestProcessingGui::testBooleanWrapper()

w = wrapperM.createWrappedWidget( context );
wrapperM.setWidgetValue( true, context );
QVERIFY( wrapperM.value().toBool() );
QVERIFY( wrapperM.widgetValue().toBool() );
QVERIFY( static_cast< QComboBox * >( wrapperM.wrappedWidget() )->currentData().toBool() );
wrapperM.setWidgetValue( false, context );
QVERIFY( !wrapperM.value().toBool() );
QVERIFY( !wrapperM.widgetValue().toBool() );
QVERIFY( !static_cast< QComboBox * >( wrapperM.wrappedWidget() )->currentData().toBool() );

// should be a label in modeler mode
Expand Down

0 comments on commit 70c1680

Please sign in to comment.