Skip to content
Permalink
Browse files

Automatically handle adding data defined button for dynamic properties

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 70c1680754aa503aea374e042e18d0daed8457d0
@@ -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 );
@@ -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

};
@@ -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):
@@ -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()])
@@ -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)

@@ -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() );
@@ -238,7 +238,7 @@ void QgsProcessingModelerParameterWidget::setSourceType( QgsProcessingModelChild

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

mExpressionWidget->setExpression( mExpression );

@@ -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 )
@@ -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()
@@ -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 )
@@ -30,6 +30,7 @@ class QgsProcessingContext;
class QgsProcessingModelerParameterWidget;
class QgsProcessingModelAlgorithm;
class QLabel;
class QgsPropertyOverrideButton;

/**
* \class QgsAbstractProcessingParameterWidgetWrapper
@@ -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,
@@ -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;

};
@@ -92,7 +92,7 @@ void QgsProcessingBooleanWidgetWrapper::setWidgetValue( const QVariant &value, c
}
}

QVariant QgsProcessingBooleanWidgetWrapper::value() const
QVariant QgsProcessingBooleanWidgetWrapper::widgetValue() const
{
switch ( type() )
{
@@ -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;

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

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

friend class TestProcessingGui;
};

///@endcond PRIVATE
@@ -79,7 +79,7 @@ class TestWidgetWrapper : public QgsAbstractProcessingParameterWidgetWrapper
{
}

QVariant value() const override
QVariant widgetValue() const override
{
return QVariant();
}
@@ -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;
}

@@ -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
@@ -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
@@ -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

0 comments on commit 70c1680

Please sign in to comment.
You can’t perform that action at this time.