Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qandroidsystemlocale.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6#include "qdatetime.h"
7#include "qstringlist.h"
8#include "qvariant.h"
9
10#include <QtCore/private/qjnihelpers_p.h>
11#include <QtCore/QJniObject>
12
14
15Q_DECLARE_JNI_CLASS(Locale, "java/util/Locale")
16Q_DECLARE_JNI_CLASS(Resources, "android/content/res/Resources")
17Q_DECLARE_JNI_CLASS(Configuration, "android/content/res/Configuration")
18Q_DECLARE_JNI_CLASS(LocaleList, "android/os/LocaleList")
19Q_DECLARE_JNI_CLASS(DateFormat, "android/text/format/DateFormat")
20
21using namespace QtJniTypes;
22
23QAndroidSystemLocale::QAndroidSystemLocale() : m_locale(QLocale::C)
24{
25}
26
27void QAndroidSystemLocale::getLocaleFromJava() const
28{
29 const Locale javaLocaleObject = []{
30 const QJniObject javaContext = QtAndroidPrivate::context();
31 if (javaContext.isValid()) {
32 const QJniObject resources = javaContext.callMethod<Resources>("getResources");
33 const QJniObject configuration = resources.callMethod<Configuration>("getConfiguration");
34 return configuration.getField<Locale>("locale");
35 } else {
36 return Locale::callStaticMethod<Locale>("getDefault");
37 }
38 }();
39
40 const QString languageCode = javaLocaleObject.callMethod<QString>("getLanguage");
41 const QString extraCodes[3] = {
42 javaLocaleObject.callMethod<QString>("getScript"),
43 javaLocaleObject.callMethod<QString>("getCountry"),
44 javaLocaleObject.callMethod<QString>("getVariant"),
45 };
46 QString fullName = languageCode;
47 for (const QString &code : extraCodes) {
48 if (code.isEmpty())
49 continue;
50 if (!fullName.isEmpty())
51 fullName += u'_';
52 fullName += code;
53 }
54
55 const bool is24HourFormat = DateFormat::callStaticMethod<bool>("is24HourFormat",
56 QNativeInterface::QAndroidApplication::context());
57
58 QWriteLocker locker(&m_lock);
59 m_locale = QLocale(fullName);
60 m_24hFormat = is24HourFormat;
61}
62
63QString QAndroidSystemLocale::convertTo24hFormat(const QString &format) const
64{
65 if (!m_24hFormat)
66 return format;
67
68 QString format24(format);
69 bool inQuoted = false;
70 for (qsizetype i = 0; i < format24.size(); ++i) {
71 if (format24[i] == QLatin1Char('\'')) {
72 inQuoted = !inQuoted;
73 continue;
74 }
75 if (inQuoted)
76 continue;
77
78 // remove AM/PM markerg from format string
79 const auto c = format24[i].toUpper();
80 if (c == QLatin1Char('A') || c == QLatin1Char('P'))
81 format24.remove(i--, 1);
82 }
83
84 return format24.trimmed();
85}
86
87QString QAndroidSystemLocale::timeToString(const QTime &time, QLocale::FormatType type) const
88{
89 if (m_24hFormat)
90 return m_locale.toString(time, convertTo24hFormat(m_locale.timeFormat(type)));
91 return m_locale.toString(time, type);
92}
93
94QString QAndroidSystemLocale::dateTimeToString(const QDateTime &dt, QLocale::FormatType type) const
95{
96 if (m_24hFormat)
97 return m_locale.toString(dt, convertTo24hFormat(m_locale.dateTimeFormat(type)));
98 return m_locale.toString(dt, type);
99}
100
101QVariant QAndroidSystemLocale::query(QueryType type, QVariant &&in) const
102{
103 if (type == LocaleChanged) {
104 getLocaleFromJava();
105 return QVariant();
106 }
107
108 QReadLocker locker(&m_lock);
109
110 switch (type) {
111 case DecimalPoint:
112 return m_locale.decimalPoint();
113 case Grouping:
114 return QVariant::fromValue(localeData(m_locale)->m_data->groupSizes());
115 case GroupSeparator:
116 return m_locale.groupSeparator();
117 case ZeroDigit:
118 return m_locale.zeroDigit();
119 case NegativeSign:
120 return m_locale.negativeSign();
121 case DateFormatLong:
122 return m_locale.dateFormat(QLocale::LongFormat);
123 case DateFormatShort:
124 return m_locale.dateFormat(QLocale::ShortFormat);
125 case TimeFormatLong:
126 return convertTo24hFormat(m_locale.timeFormat(QLocale::LongFormat));
127 case TimeFormatShort:
128 return convertTo24hFormat(m_locale.timeFormat(QLocale::ShortFormat));
129 case DayNameLong:
130 return m_locale.dayName(in.toInt(), QLocale::LongFormat);
131 case DayNameShort:
132 return m_locale.dayName(in.toInt(), QLocale::ShortFormat);
133 case DayNameNarrow:
134 return m_locale.dayName(in.toInt(), QLocale::NarrowFormat);
135 case StandaloneDayNameLong:
136 return m_locale.standaloneDayName(in.toInt(), QLocale::LongFormat);
137 case StandaloneDayNameShort:
138 return m_locale.standaloneDayName(in.toInt(), QLocale::ShortFormat);
139 case StandaloneDayNameNarrow:
140 return m_locale.standaloneDayName(in.toInt(), QLocale::NarrowFormat);
141 case MonthNameLong:
142 return m_locale.monthName(in.toInt(), QLocale::LongFormat);
143 case MonthNameShort:
144 return m_locale.monthName(in.toInt(), QLocale::ShortFormat);
145 case MonthNameNarrow:
146 return m_locale.monthName(in.toInt(), QLocale::NarrowFormat);
147 case StandaloneMonthNameLong:
148 return m_locale.standaloneMonthName(in.toInt(), QLocale::LongFormat);
149 case StandaloneMonthNameShort:
150 return m_locale.standaloneMonthName(in.toInt(), QLocale::ShortFormat);
151 case StandaloneMonthNameNarrow:
152 return m_locale.standaloneMonthName(in.toInt(), QLocale::NarrowFormat);
153 case DateToStringLong:
154 return m_locale.toString(in.toDate(), QLocale::LongFormat);
155 case DateToStringShort:
156 return m_locale.toString(in.toDate(), QLocale::ShortFormat);
157 case TimeToStringLong:
158 return timeToString(in.toTime(), QLocale::LongFormat);
159 case TimeToStringShort:
160 return timeToString(in.toTime(), QLocale::ShortFormat);
161 case DateTimeFormatLong:
162 return convertTo24hFormat(m_locale.dateTimeFormat(QLocale::LongFormat));
163 case DateTimeFormatShort:
164 return convertTo24hFormat(m_locale.dateTimeFormat(QLocale::ShortFormat));
165 case DateTimeToStringLong:
166 return dateTimeToString(in.toDateTime(), QLocale::LongFormat);
167 case DateTimeToStringShort:
168 return dateTimeToString(in.toDateTime(), QLocale::ShortFormat);
169 case PositiveSign:
170 return m_locale.positiveSign();
171 case AMText:
172 return m_locale.amText();
173 case PMText:
174 return m_locale.pmText();
175 case FirstDayOfWeek:
176 return m_locale.firstDayOfWeek();
177 case CurrencySymbol:
178 return m_locale .currencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()));
179 case CurrencyToString: {
180 switch (in.metaType().id()) {
181 case QMetaType::Int:
182 return m_locale .toCurrencyString(in.toInt());
183 case QMetaType::UInt:
184 return m_locale .toCurrencyString(in.toUInt());
185 case QMetaType::Double:
186 return m_locale .toCurrencyString(in.toDouble());
187 case QMetaType::LongLong:
188 return m_locale .toCurrencyString(in.toLongLong());
189 case QMetaType::ULongLong:
190 return m_locale .toCurrencyString(in.toULongLong());
191 default:
192 break;
193 }
194 return QString();
195 }
196 case StringToStandardQuotation:
197 return m_locale.quoteString(in.value<QStringView>());
198 case StringToAlternateQuotation:
199 return m_locale.quoteString(in.value<QStringView>(), QLocale::AlternateQuotation);
200 case ListToSeparatedString:
201 return m_locale.createSeparatedList(in.value<QStringList>());
202 case LocaleChanged:
203 Q_ASSERT_X(false, Q_FUNC_INFO, "This can't happen.");
204 case UILanguages: {
205 if (QtAndroidPrivate::androidSdkVersion() >= 24) {
206 LocaleList localeListObject = LocaleList::callStaticMethod<LocaleList>("getDefault");
207 if (localeListObject.isValid()) {
208 QString lang = localeListObject.callMethod<QString>("toLanguageTags");
209 // Some devices return with it enclosed in []'s so check if both exists before
210 // removing to ensure it is formatted correctly
211 if (lang.startsWith(QChar('[')) && lang.endsWith(QChar(']')))
212 lang = lang.mid(1, lang.length() - 2);
213 return lang.split(QChar(','));
214 }
215 }
216 return QVariant();
217 }
218 default:
219 break;
220 }
221 return QVariant();
222}
223
225{
226 QReadLocker locker(&m_lock);
227 return m_locale;
228}
229
230QT_END_NAMESPACE
QVariant query(QueryType type, QVariant &&in) const override
QLocale fallbackLocale() const override