[processing] Allow parameter metadata to set the number of decimal places

to show in numeric/distance widgets

E.g. to only show 2 decimal places:

  # only show two decimal places in parameter's widgets, not 6:
  param.setMetadata( {'widget_wrapper':
    { 'decimals': 2 }
  })
This commit is contained in:
Nyall Dawson 2018-11-27 20:22:50 +10:00
parent b03d8a7f0e
commit d72c4d001f
4 changed files with 79 additions and 4 deletions

View File

@ -1364,6 +1364,17 @@ class QgsProcessingParameterNumber : QgsProcessingParameterDefinition
%Docstring
A numeric parameter for processing algorithms.
For numeric parameters with a dataType() of Double, the number of decimals places
shown in the parameter's widget can be specified by setting the parameter's metadata. For example:
.. code-block:: python
param = QgsProcessingParameterNumber( 'VAL', 'Threshold', type=QgsProcessingParameter.Double)
# only show two decimal places in parameter's widgets, not 6:
param.setMetadata( {'widget_wrapper':
{ 'decimals': 2 }
})
.. versionadded:: 3.0
%End
@ -1463,6 +1474,17 @@ class QgsProcessingParameterDistance : QgsProcessingParameterNumber
A double numeric parameter for distance values. Linked to a source layer or CRS parameter
to determine what units the distance values are in.
The number of decimals places shown in a distance parameter's widget can be specified by
setting the parameter's metadata. For example:
.. code-block:: python
param = QgsProcessingParameterDistance( 'VAL', 'Threshold')
# only show two decimal places in parameter's widgets, not 6:
param.setMetadata( {'widget_wrapper':
{ 'decimals': 2 }
})
.. versionadded:: 3.2
%End

View File

@ -1359,7 +1359,19 @@ class CORE_EXPORT QgsProcessingParameterMultipleLayers : public QgsProcessingPar
* \class QgsProcessingParameterNumber
* \ingroup core
* A numeric parameter for processing algorithms.
* \since QGIS 3.0
*
* For numeric parameters with a dataType() of Double, the number of decimals places
* shown in the parameter's widget can be specified by setting the parameter's metadata. For example:
*
* * \code{.py}
* param = QgsProcessingParameterNumber( 'VAL', 'Threshold', type=QgsProcessingParameter.Double)
* # only show two decimal places in parameter's widgets, not 6:
* param.setMetadata( {'widget_wrapper':
* { 'decimals': 2 }
* })
* \endcode
*
* \since QGIS 3.0
*/
class CORE_EXPORT QgsProcessingParameterNumber : public QgsProcessingParameterDefinition
{
@ -1449,7 +1461,19 @@ class CORE_EXPORT QgsProcessingParameterNumber : public QgsProcessingParameterDe
* \ingroup core
* A double numeric parameter for distance values. Linked to a source layer or CRS parameter
* to determine what units the distance values are in.
* \since QGIS 3.2
*
* The number of decimals places shown in a distance parameter's widget can be specified by
* setting the parameter's metadata. For example:
*
* * \code{.py}
* param = QgsProcessingParameterDistance( 'VAL', 'Threshold')
* # only show two decimal places in parameter's widgets, not 6:
* param.setMetadata( {'widget_wrapper':
* { 'decimals': 2 }
* })
* \endcode
*
* \since QGIS 3.2
*/
class CORE_EXPORT QgsProcessingParameterDistance : public QgsProcessingParameterNumber
{

View File

@ -420,6 +420,8 @@ QgsProcessingNumericWidgetWrapper::QgsProcessingNumericWidgetWrapper( const QgsP
QWidget *QgsProcessingNumericWidgetWrapper::createWidget()
{
const QgsProcessingParameterNumber *numberDef = static_cast< const QgsProcessingParameterNumber * >( parameterDefinition() );
const QVariantMap metadata = numberDef->metadata();
const int decimals = metadata.value( QStringLiteral( "widget_wrapper" ) ).toMap().value( QStringLiteral( "decimals" ), 6 ).toInt();
switch ( type() )
{
case QgsProcessingGui::Standard:
@ -433,13 +435,14 @@ QWidget *QgsProcessingNumericWidgetWrapper::createWidget()
case QgsProcessingParameterNumber::Double:
mDoubleSpinBox = new QgsDoubleSpinBox();
mDoubleSpinBox->setExpressionsEnabled( true );
mDoubleSpinBox->setDecimals( 6 );
mDoubleSpinBox->setDecimals( decimals );
// guess reasonable step value for double spin boxes
if ( !qgsDoubleNear( numberDef->maximum(), std::numeric_limits<double>::max() ) &&
!qgsDoubleNear( numberDef->minimum(), std::numeric_limits<double>::lowest() + 1 ) )
{
const double singleStep = calculateStep( numberDef->minimum(), numberDef->maximum() );
double singleStep = calculateStep( numberDef->minimum(), numberDef->maximum() );
singleStep = std::max( singleStep, std::pow( 10, -decimals ) );
mDoubleSpinBox->setSingleStep( singleStep );
}

View File

@ -1005,6 +1005,19 @@ void TestProcessingGui::testNumericWrapperDouble()
QCOMPARE( wrapperOptionalDefault.parameterValue().toDouble(), 5.0 );
delete w;
// with decimals
QgsProcessingParameterNumber paramDecimals( QStringLiteral( "num" ), QStringLiteral( "num" ), QgsProcessingParameterNumber::Double, QVariant(), true, 1, 1.02 );
QVariantMap metadata;
QVariantMap wrapperMetadata;
wrapperMetadata.insert( QStringLiteral( "decimals" ), 2 );
metadata.insert( QStringLiteral( "widget_wrapper" ), wrapperMetadata );
paramDecimals.setMetadata( metadata );
QgsProcessingNumericWidgetWrapper wrapperDecimals( &paramDecimals, type );
w = wrapperDecimals.createWrappedWidget( context );
QCOMPARE( static_cast< QgsDoubleSpinBox * >( wrapperDecimals.wrappedWidget() )->decimals(), 2 );
QCOMPARE( static_cast< QgsDoubleSpinBox * >( wrapperDecimals.wrappedWidget() )->singleStep(), 0.01 ); // single step should never be less than set number of decimals
delete w;
};
// standard wrapper
@ -1280,6 +1293,19 @@ void TestProcessingGui::testDistanceWrapper()
delete w;
// with decimals
QgsProcessingParameterDistance paramDecimals( QStringLiteral( "num" ), QStringLiteral( "num" ), QVariant(), QString(), true, 1, 1.02 );
QVariantMap metadata;
QVariantMap wrapperMetadata;
wrapperMetadata.insert( QStringLiteral( "decimals" ), 2 );
metadata.insert( QStringLiteral( "widget_wrapper" ), wrapperMetadata );
paramDecimals.setMetadata( metadata );
QgsProcessingDistanceWidgetWrapper wrapperDecimals( &paramDecimals, QgsProcessingGui::Standard );
w = wrapperDecimals.createWrappedWidget( context );
QCOMPARE( wrapperDecimals.mDoubleSpinBox->decimals(), 2 );
QCOMPARE( wrapperDecimals.mDoubleSpinBox->singleStep(), 0.01 ); // single step should never be less than set number of decimals
delete w;
// batch wrapper
QgsProcessingDistanceWidgetWrapper wrapperB( &param, QgsProcessingGui::Batch );