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