Fix display-name calls in QAndroidTimeZonePrivate::init()

Following up on commits 4fa8dfee5d and
c20c7efea9, where I apparently got the
call to Java's getDisplayName() method wrong. Use the same code as our
own displayName() method used for this, pulled out as a function to be
shared by the two callers.

This requires a locale and it's not immediately obvious which to use,
so try the three most plausible candidates: C locale because IANA IDs
are typically in it; default because that's most likely what language
a user-supplied locale name might be in; and system because the name
may have come from the system, not the user.

In the process fixed some loops that didn't visit all the values they
thought they did.

Fixes: QTBUG-81975
Change-Id: I7867ca6f46951315a41c389107439acb439eaf08
Reviewed-by: BogDan Vatra <bogdan@kdab.com>
This commit is contained in:
Edward Welbourne 2020-02-12 11:01:51 +01:00
parent 8138c812cb
commit b34158d7a1

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2014 Drew Parsons <dparsons@emerall.com>
** Contact: https://www.qt.io/licensing/
**
@ -78,6 +78,26 @@ QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate()
{
}
static QJNIObjectPrivate getDisplayName(QJNIObjectPrivate zone, jint style, jboolean dst,
const QLocale &locale)
{
QJNIObjectPrivate jlanguage
= QJNIObjectPrivate::fromString(QLocale::languageToString(locale.language()));
QJNIObjectPrivate jcountry
= QJNIObjectPrivate::fromString(QLocale::countryToString(locale.country()));
QJNIObjectPrivate
jvariant = QJNIObjectPrivate::fromString(QLocale::scriptToString(locale.script()));
QJNIObjectPrivate jlocale("java.util.Locale",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
static_cast<jstring>(jlanguage.object()),
static_cast<jstring>(jcountry.object()),
static_cast<jstring>(jvariant.object()));
return zone.callObjectMethod("getDisplayName",
"(ZILjava/util/Locale;)Ljava/lang/String;",
dst, style, jlocale.object());
}
void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
{
const QString iana = QString::fromUtf8(ianaId);
@ -99,10 +119,13 @@ void QAndroidTimeZonePrivate::init(const QByteArray &ianaId)
// the zone object we got and ignore the zone if not.
// Try checking ianaId against getID(), getDisplayName():
m_id = match(androidTimeZone.callObjectMethod("getID", "()Ljava/lang/String;"));
for (int style = 1; m_id.isEmpty() && style-- > 0;) {
for (int dst = 1; m_id.isEmpty() && dst-- > 0;) {
m_id = match(androidTimeZone.callObjectMethod(
"getDisplayName", "(ZI)Ljava/lang/String;", bool(dst), style));
for (int style = 1; m_id.isEmpty() && style >= 0; --style) {
for (int dst = 1; m_id.isEmpty() && dst >= 0; --dst) {
for (int pick = 2; m_id.isEmpty() && pick >= 0; --pick) {
QLocale locale = (pick == 0 ? QLocale::system()
: pick == 1 ? QLocale() : QLocale::c());
m_id = match(getDisplayName(androidTimeZone, style, jboolean(dst), locale));
}
}
}
}
@ -124,14 +147,7 @@ QString QAndroidTimeZonePrivate::displayName(QTimeZone::TimeType timeType, QTime
// treat all NameTypes as java TimeZone style LONG (value 1), except of course QTimeZone::ShortName which is style SHORT (value 0);
jint style = (nameType == QTimeZone::ShortName ? 0 : 1);
QJNIObjectPrivate jlanguage = QJNIObjectPrivate::fromString(QLocale::languageToString(locale.language()));
QJNIObjectPrivate jcountry = QJNIObjectPrivate::fromString(QLocale::countryToString(locale.country()));
QJNIObjectPrivate jvariant = QJNIObjectPrivate::fromString(QLocale::scriptToString(locale.script()));
QJNIObjectPrivate jlocale("java.util.Locale", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", static_cast<jstring>(jlanguage.object()), static_cast<jstring>(jcountry.object()), static_cast<jstring>(jvariant.object()));
QJNIObjectPrivate jname = androidTimeZone.callObjectMethod("getDisplayName", "(ZILjava/util/Locale;)Ljava/lang/String;", daylightTime, style, jlocale.object());
name = jname.toString();
name = getDisplayName(androidTimeZone, style, daylightTime, locale).toString();
}
return name;