Skip to content

Commit

Permalink
[expression] Add optional language parameter to format_number() to co…
Browse files Browse the repository at this point in the history
…ntrol locale across different systems

(cherry picked from commit cbd3068)
  • Loading branch information
nirvn authored and nyalldawson committed Jun 19, 2020
1 parent a1342f5 commit 623c263
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 14 deletions.
5 changes: 3 additions & 2 deletions resources/function_help/json/format_number
@@ -1,9 +1,10 @@
{
"name": "format_number",
"type": "function",
"description": "Returns a number formatted with the locale separator for thousands. Also truncates the number to the number of supplied places.",
"description": "Returns a number formatted with the locale separator for thousands. Also truncates the decimal places to the number of supplied places.",
"arguments": [ {"arg":"number","description":"number to be formatted"},
{"arg":"places","description":"integer representing the number of decimal places to truncate the string to."}],
{"arg":"places","description":"integer representing the number of decimal places to truncate the string to."},
{"arg":"language","optional":true,"description":"language (lowercase, two- or three-letter, ISO 639 language code) used to format the number into a string"}],
"examples": [ { "expression":"format_number(10000000.332,2)", "returns":"'10,000,000.33'"}
]
}
22 changes: 10 additions & 12 deletions src/core/expression/qgsexpressionfunction.cpp
Expand Up @@ -3875,29 +3875,27 @@ static QVariant fcnPi( const QVariantList &values, const QgsExpressionContext *,

static QVariant fcnFormatNumber( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
const double value = QgsExpressionUtils::getDoubleValue( values.at( 0 ), parent );
const int places = QgsExpressionUtils::getNativeIntValue( values.at( 1 ), parent );
const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
if ( places < 0 )
{
parent->setEvalErrorString( QObject::tr( "Number of places must be positive" ) );
return QVariant();
}
QLocale locale = QLocale();

QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
locale.setNumberOptions( locale.numberOptions() &= ~QLocale::NumberOption::OmitGroupSeparator );
return locale.toString( value, 'f', places );
}

static QVariant fcnFormatDate( const QVariantList &values, const QgsExpressionContext *, QgsExpression *parent, const QgsExpressionNodeFunction * )
{
QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );
const QDateTime datetime = QgsExpressionUtils::getDateTimeValue( values.at( 0 ), parent );
const QString format = QgsExpressionUtils::getStringValue( values.at( 1 ), parent );
const QString language = QgsExpressionUtils::getStringValue( values.at( 2 ), parent );

QLocale locale = QLocale();
if ( !language.isEmpty() )
{
locale = QLocale( language );
}
QLocale locale = !language.isEmpty() ? QLocale( language ) : QLocale();
return locale.toString( datetime, format );
}

Expand Down Expand Up @@ -5255,7 +5253,7 @@ const QList<QgsExpressionFunction *> &QgsExpression::Functions()
<< new QgsStaticExpressionFunction( QStringLiteral( "rpad" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "width" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "fill" ) ), fcnRPad, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "lpad" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "string" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "width" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "fill" ) ), fcnLPad, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "format" ), -1, fcnFormatString, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "format_number" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "number" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "places" ) ), fcnFormatNumber, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "format_number" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "number" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "places" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "language" ), true, QVariant() ), fcnFormatNumber, QStringLiteral( "String" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "format_date" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "datetime" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "format" ) ) << QgsExpressionFunction::Parameter( QStringLiteral( "language" ), true, QVariant() ), fcnFormatDate, QStringList() << QStringLiteral( "String" ) << QStringLiteral( "Date and Time" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "color_grayscale_average" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "color" ) ), fcnColorGrayscaleAverage, QStringLiteral( "Color" ) )
<< new QgsStaticExpressionFunction( QStringLiteral( "color_mix_rgb" ), QgsExpressionFunction::ParameterList() << QgsExpressionFunction::Parameter( QStringLiteral( "color1" ) )
Expand Down
5 changes: 5 additions & 0 deletions tests/src/core/testqgsexpression.cpp
Expand Up @@ -1153,6 +1153,11 @@ class TestQgsExpression: public QObject
QTest::newRow( "format_number large" ) << "format_number(9000000.0,0)" << false << QVariant( "9,000,000" );
QTest::newRow( "format_number many decimals" ) << "format_number(123.45600,4)" << false << QVariant( "123.4560" );
QTest::newRow( "format_number no decimals" ) << "format_number(1999.567,0)" << false << QVariant( "2,000" );
#if QT_VERSION >= QT_VERSION_CHECK( 5, 12, 0 )
QTest::newRow( "format_number language parameter" ) << "format_number(123457.00,2,'fr')" << false << QVariant( "123\u202F457,00" );
#else
QTest::newRow( "format_number language parameter" ) << "format_number(123457.00,2,'fr')" << false << QVariant( "123\u00A0457,00" );
#endif
QTest::newRow( "lower" ) << "lower('HeLLo')" << false << QVariant( "hello" );
QTest::newRow( "upper" ) << "upper('HeLLo')" << false << QVariant( "HELLO" );
QTest::newRow( "length" ) << "length('HeLLo')" << false << QVariant( 5 );
Expand Down

0 comments on commit 623c263

Please sign in to comment.