QLocale: Support Indian number formatting

When QLocale::Country is set to QLocale::India numbers are written so that
after first three from the right and then after every second will be comma.
E.g. 10000000 is written as 1,00,00,000

Task-number: QTBUG-24301
Change-Id: Ic06241c127b0af1824104f94f7e2ce6e2058a070
Reviewed-by: Venugopal Shivashankar <Venugopal.Shivashankar@qt.io>
Reviewed-by: Teemu Holappa <teemu.holappa@qt.io>
This commit is contained in:
Tuomas Heimonen 2019-11-29 09:27:35 +02:00
parent 411c2e3e4f
commit 27d1391280
3 changed files with 89 additions and 12 deletions

View File

@ -1969,7 +1969,8 @@ QString QLocale::toString(qlonglong i) const
{
int flags = d->m_numberOptions & OmitGroupSeparator
? 0
: QLocaleData::ThousandsGroup;
: (d->m_data->m_country_id == Country::India)
? QLocaleData::IndianNumberGrouping : QLocaleData::ThousandsGroup;
return d->m_data->longLongToString(i, -1, 10, -1, flags);
}
@ -1984,7 +1985,8 @@ QString QLocale::toString(qulonglong i) const
{
int flags = d->m_numberOptions & OmitGroupSeparator
? 0
: QLocaleData::ThousandsGroup;
: (d->m_data->m_country_id == Country::India)
? QLocaleData::IndianNumberGrouping : QLocaleData::ThousandsGroup;
return d->m_data->unsLongLongToString(i, -1, 10, -1, flags);
}
@ -3626,10 +3628,19 @@ QT_WARNING_DISABLE_MSVC(4146)
QT_WARNING_POP
uint cnt_thousand_sep = 0;
if (flags & ThousandsGroup && base == 10) {
for (int i = num_str.length() - 3; i > 0; i -= 3) {
num_str.insert(i, group);
++cnt_thousand_sep;
if (base == 10){
if (flags & ThousandsGroup) {
for (int i = num_str.length() - 3; i > 0; i -= 3) {
num_str.insert(i, group);
++cnt_thousand_sep;
}
} else if (flags & IndianNumberGrouping) {
if (num_str.length() > 3)
num_str.insert(num_str.length() - 3 , group);
for (int i = num_str.length() - 6; i > 0; i -= 2) {
num_str.insert(i, group);
++cnt_thousand_sep;
}
}
}
@ -3713,10 +3724,19 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
}
uint cnt_thousand_sep = 0;
if (flags & ThousandsGroup && base == 10) {
for (int i = num_str.length() - 3; i > 0; i -=3) {
num_str.insert(i, group);
++cnt_thousand_sep;
if (base == 10) {
if (flags & ThousandsGroup) {
for (int i = num_str.length() - 3; i > 0; i -=3) {
num_str.insert(i, group);
++cnt_thousand_sep;
}
} else if (flags & IndianNumberGrouping) {
if (num_str.length() > 3)
num_str.insert(num_str.length() - 3 , group);
for (int i = num_str.length() - 6; i > 0; i -= 2) {
num_str.insert(i, group);
++cnt_thousand_sep;
}
}
}
@ -3851,7 +3871,10 @@ bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_o
// check distance from the last separator or from the beginning of the digits
// ### FIXME: Some locales allow other groupings!
// See https://en.wikipedia.org/wiki/Thousands_separator
if (last_separator_idx != -1 && idx - last_separator_idx != 4)
if (m_country_id == QLocale::India) {
if (last_separator_idx != -1 && idx - last_separator_idx != 3)
return false;
} else if (last_separator_idx != -1 && idx - last_separator_idx != 4)
return false;
if (last_separator_idx == -1
&& (start_of_digits_idx == -1 || idx - start_of_digits_idx > 3)) {

View File

@ -213,7 +213,8 @@ public:
ShowBase = 0x80,
UppercaseBase = 0x100,
ZeroPadExponent = 0x200,
ForcePoint = 0x400
ForcePoint = 0x400,
IndianNumberGrouping= 0x800
};
enum NumberMode { IntegerMode, DoubleStandardMode, DoubleScientificMode };

View File

@ -147,6 +147,8 @@ private slots:
void systemLocale_data();
void systemLocale();
void IndianNumberGrouping();
// *** ORDER-DEPENDENCY *** (This Is Bad.)
// Test order is determined by order of declaration here: *all* tests that
// QLocale::setDefault() *must* appear *after* all other tests !
@ -2991,5 +2993,56 @@ void tst_QLocale::systemLocale()
QCOMPARE(QLocale::system(), originalSystemLocale);
}
void tst_QLocale::IndianNumberGrouping()
{
QLocale indian(QLocale::Hindi, QLocale::India);
qint8 int8 = 100;
QString strResult8("100");
QCOMPARE(indian.toString(int8), strResult8);
QCOMPARE(indian.toShort(strResult8), short(int8));
quint8 uint8 = 100;
QCOMPARE(indian.toString(uint8), strResult8);
QCOMPARE(indian.toShort(strResult8), short(uint8));
// Boundary case 1000 for short and ushort
short shortInt = 1000;
QString strResult16("1,000");
QCOMPARE(indian.toString(shortInt), strResult16);
QCOMPARE(indian.toShort(strResult16), shortInt);
ushort uShortInt = 1000;
QCOMPARE(indian.toString(uShortInt), strResult16);
QCOMPARE(indian.toUShort(strResult16), uShortInt);
shortInt = 10000;
strResult16 = "10,000";
QCOMPARE(indian.toString(shortInt), strResult16);
QCOMPARE(indian.toShort(strResult16), shortInt);
uShortInt = 10000;
QCOMPARE(indian.toString(uShortInt), strResult16);
QCOMPARE(indian.toUShort(strResult16), uShortInt);
int intInt = 1000000000;
QString strResult32("1,00,00,00,000");
QCOMPARE(indian.toString(intInt), strResult32);
QCOMPARE(indian.toInt(strResult32), intInt);
uint uIntInt = 1000000000;
QCOMPARE(indian.toString(uIntInt), strResult32);
QCOMPARE(indian.toUInt(strResult32), uIntInt);
QString strResult64("10,00,00,00,00,00,00,00,000");
qint64 int64 = Q_INT64_C(1000000000000000000);
QCOMPARE(indian.toString(int64), strResult64);
QCOMPARE(indian.toLongLong(strResult64), int64);
quint64 uint64 = Q_UINT64_C(1000000000000000000);
QCOMPARE(indian.toString(uint64), strResult64);
QCOMPARE(indian.toULongLong(strResult64), uint64);
}
QTEST_MAIN(tst_QLocale)
#include "tst_qlocale.moc"