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 QT_BEGIN_NAMESPACE
/*! /*!
\class QCollator \class QCollator
\inmodule QtCore \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() \sa setLocale()
*/ */

View File

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

View File

@ -4131,6 +4131,29 @@ QStringList QLocale::uiLanguages() const
return uiLanguages; 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 \since 4.8

View File

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

View File

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

View File

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

View File

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