Improve the default selection of locale for QCollator

QCollator was using the default-constructed QLocale() as its default;
this locale's default was the system locale; however, that didn't pay
any attention to system settings for collation such as Unix's
environment variable LC_COLLATE or the MS-Win LOCALE_SSORTLOCALE
configuration option.

Teach the system locale back-ends to look up their relevant settings,
add QLocale::collation() as a channel via which to access that and
change no-parameter construction of QCollator to a separate
implementation (rather than the constructor taking QLocale having a
default) using it.

[ChangeLog][QtCore][QLocale] The system locale now knows what to use
for collation, QLocale::system().collation().

[ChangeLog][QtCore][QCollator] The default QCollator now uses the
system's collation locale, rather than the system locale itself.

Fixes: QTBUG-58621
Change-Id: I90f86621541385330315d1f9d6a4b982bdcea9d5
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Edward Welbourne 2018-10-02 17:25:17 +02:00
parent a20da2353c
commit 235ac95520
7 changed files with 55 additions and 6 deletions

View File

@ -46,7 +46,6 @@
QT_BEGIN_NAMESPACE
/*!
\class QCollator
\inmodule QtCore
@ -71,9 +70,20 @@ QT_BEGIN_NAMESPACE
*/
/*!
Constructs a QCollator for \a locale.
\since 5.13
If \a locale is not specified, the system's default locale is used.
Constructs a QCollator using the system's default collation locale.
\sa setLocale(), QLocale::collation()
*/
QCollator::QCollator()
: d(new QCollatorPrivate(QLocale::system().collation()))
{
d->init();
}
/*!
Constructs a QCollator from \a locale.
\sa setLocale()
*/

View File

@ -81,7 +81,8 @@ inline bool operator<(const QCollatorSortKey &lhs, const QCollatorSortKey &rhs)
class Q_CORE_EXPORT QCollator
{
public:
explicit QCollator(const QLocale &locale = QLocale());
QCollator();
explicit QCollator(const QLocale &locale);
QCollator(const QCollator &);
~QCollator();
QCollator &operator=(const QCollator &);

View File

@ -4131,6 +4131,29 @@ QStringList QLocale::uiLanguages() const
return uiLanguages;
}
/*!
\since 5.13
Returns the locale to use for collation.
The result is usually this locale; however, the system locale (which is
commonly the default locale) will return the system collation locale.
The result is suitable for passing to QCollator's constructor.
\sa QCollator
*/
QLocale QLocale::collation() const
{
#ifndef QT_NO_SYSTEMLOCALE
if (d->m_data == systemData()) {
QString res = systemLocale()->query(QSystemLocale::Collation, QVariant()).toString();
if (!res.isEmpty())
return QLocale(res);
}
#endif
return *this;
}
/*!
\since 4.8

View File

@ -1048,7 +1048,7 @@ public:
QString pmText() const;
MeasurementSystem measurementSystem() const;
QLocale collation() const;
Qt::LayoutDirection textDirection() const;
QString toUpper(const QString &str) const;

View File

@ -113,6 +113,7 @@ public:
Weekdays, // QList<Qt::DayOfWeek>
CurrencySymbol, // QString in: CurrencyToStringArgument
CurrencyToString, // QString in: qlonglong, qulonglong or double
Collation, // QString
UILanguages, // QStringList
StringToStandardQuotation, // QString in: QStringRef to quote
StringToAlternateQuotation, // QString in: QStringRef to quote

View File

@ -69,6 +69,7 @@ struct QSystemLocaleData
QLocale lc_messages;
QByteArray lc_messages_var;
QByteArray lc_measurement_var;
QByteArray lc_collate_var;
QStringList uiLanguages;
};
@ -82,6 +83,7 @@ void QSystemLocaleData::readEnvironment()
QByteArray monetary = all.isEmpty() ? qgetenv("LC_MONETARY") : all;
lc_messages_var = all.isEmpty() ? qgetenv("LC_MESSAGES") : all;
lc_measurement_var = all.isEmpty() ? qgetenv("LC_MEASUREMENT") : all;
lc_collate_var = all.isEmpty() ? qgetenv("LC_COLLATE") : all;
QByteArray lang = qgetenv("LANG");
if (lang.isEmpty())
lang = QByteArray("C");
@ -95,6 +97,8 @@ void QSystemLocaleData::readEnvironment()
lc_messages_var = lang;
if (lc_measurement_var.isEmpty())
lc_measurement_var = lang;
if (lc_collate_var.isEmpty())
lc_collate_var = lang;
lc_numeric = QLocale(QString::fromLatin1(numeric));
lc_time = QLocale(QString::fromLatin1(time));
lc_monetary = QLocale(QString::fromLatin1(monetary));
@ -247,13 +251,15 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
return QString();
}
case MeasurementSystem: {
const QString meas_locale = QString::fromLatin1(d->lc_measurement_var.constData(), d->lc_measurement_var.size());
const QString meas_locale = QString::fromLatin1(d->lc_measurement_var);
if (meas_locale.compare(QLatin1String("Metric"), Qt::CaseInsensitive) == 0)
return QLocale::MetricSystem;
if (meas_locale.compare(QLatin1String("Other"), Qt::CaseInsensitive) == 0)
return QLocale::MetricSystem;
return QVariant((int)QLocale(meas_locale).measurementSystem());
}
case Collation:
return QString::fromLatin1(d->lc_collate_var);
case UILanguages: {
if (!d->uiLanguages.isEmpty())
return d->uiLanguages;

View File

@ -120,6 +120,7 @@ struct QSystemLocalePrivate
QVariant toString(const QTime &, QLocale::FormatType);
QVariant toString(const QDateTime &, QLocale::FormatType);
QVariant measurementSystem();
QVariant collation();
QVariant amText();
QVariant pmText();
QVariant firstDayOfWeek();
@ -455,6 +456,11 @@ QVariant QSystemLocalePrivate::measurementSystem()
return QLocale::MetricSystem;
}
QVariant QSystemLocalePrivate::collation()
{
return getLocaleInfo(LOCALE_SSORTLOCALE);
}
QVariant QSystemLocalePrivate::amText()
{
wchar_t output[15]; // maximum length including terminating zero character for Win2003+
@ -808,6 +814,8 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
return QVariant(QLocale::AnyScript);
case MeasurementSystem:
return d->measurementSystem();
case Collation:
return d->collation();
case AMText:
return d->amText();
case PMText: