[expression] Add optional language parameter to format_number() to control locale across different systems

This commit is contained in:
nirvn 2020-06-05 09:41:42 +07:00 committed by Mathieu Pellerin
parent 4fe0651f51
commit cbd3068443
3 changed files with 18 additions and 14 deletions

View File

@ -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'"}
]
}

View File

@ -4364,29 +4364,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 );
}
@ -5879,7 +5877,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" ) )

View File

@ -1246,6 +1246,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 );