From d72c4d001f34835916ca85d693185f1e7cf20c1b Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Tue, 27 Nov 2018 20:22:50 +1000 Subject: [PATCH] [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 } }) --- .../processing/qgsprocessingparameters.sip.in | 22 +++++++++++++++ src/core/processing/qgsprocessingparameters.h | 28 +++++++++++++++++-- .../qgsprocessingwidgetwrapperimpl.cpp | 7 +++-- tests/src/gui/testprocessinggui.cpp | 26 +++++++++++++++++ 4 files changed, 79 insertions(+), 4 deletions(-) diff --git a/python/core/auto_generated/processing/qgsprocessingparameters.sip.in b/python/core/auto_generated/processing/qgsprocessingparameters.sip.in index d39a5fa82929..e4a906063344 100644 --- a/python/core/auto_generated/processing/qgsprocessingparameters.sip.in +++ b/python/core/auto_generated/processing/qgsprocessingparameters.sip.in @@ -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 diff --git a/src/core/processing/qgsprocessingparameters.h b/src/core/processing/qgsprocessingparameters.h index d2b5aaddb92a..aeca44224ddf 100644 --- a/src/core/processing/qgsprocessingparameters.h +++ b/src/core/processing/qgsprocessingparameters.h @@ -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 { diff --git a/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp b/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp index 1bce7f50ca4d..26b37475455a 100644 --- a/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp +++ b/src/gui/processing/qgsprocessingwidgetwrapperimpl.cpp @@ -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::max() ) && !qgsDoubleNear( numberDef->minimum(), std::numeric_limits::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 ); } diff --git a/tests/src/gui/testprocessinggui.cpp b/tests/src/gui/testprocessinggui.cpp index 13841a24c4d4..8b6f89258c4b 100644 --- a/tests/src/gui/testprocessinggui.cpp +++ b/tests/src/gui/testprocessinggui.cpp @@ -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( ¶mDecimals, 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( ¶mDecimals, 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( ¶m, QgsProcessingGui::Batch );