1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | #include <qtest.h> |
29 | #include <QDebug> |
30 | |
31 | #include <QtQml/qqmlengine.h> |
32 | #include <QtQml/qqmlcomponent.h> |
33 | #include <QtQml/qqmlcontext.h> |
34 | #include <QtCore/QDateTime> |
35 | #include <QtCore/qscopeguard.h> |
36 | #include <QtCore/qscopedpointer.h> |
37 | #include <QtCore/qtimezone.h> |
38 | #include <qcolor.h> |
39 | #include "../../shared/util.h" |
40 | |
41 | #include <time.h> |
42 | |
43 | class tst_qqmllocale : public QQmlDataTest |
44 | { |
45 | Q_OBJECT |
46 | public: |
47 | tst_qqmllocale() { } |
48 | |
49 | private slots: |
50 | void defaultLocale(); |
51 | |
52 | void properties_data(); |
53 | void properties(); |
54 | void currencySymbol_data(); |
55 | void currencySymbol(); |
56 | void monthName_data(); |
57 | void monthName(); |
58 | void standaloneMonthName_data(); |
59 | void standaloneMonthName(); |
60 | void dayName_data(); |
61 | void dayName(); |
62 | void standaloneDayName_data(); |
63 | void standaloneDayName(); |
64 | void firstDayOfWeek_data(); |
65 | void firstDayOfWeek(); |
66 | void weekDays_data(); |
67 | void weekDays(); |
68 | void uiLanguages_data(); |
69 | void uiLanguages(); |
70 | void dateFormat_data(); |
71 | void dateFormat(); |
72 | void dateTimeFormat_data(); |
73 | void dateTimeFormat(); |
74 | void timeFormat_data(); |
75 | void timeFormat(); |
76 | #if defined(Q_OS_UNIX) && QT_CONFIG(timezone) |
77 | void timeZoneUpdated(); |
78 | #endif |
79 | |
80 | void dateToLocaleString_data(); |
81 | void dateToLocaleString(); |
82 | void dateToLocaleStringFormatted_data(); |
83 | void dateToLocaleStringFormatted(); |
84 | void dateToLocaleDateString_data(); |
85 | void dateToLocaleDateString(); |
86 | void dateToLocaleDateStringFormatted_data(); |
87 | void dateToLocaleDateStringFormatted(); |
88 | void dateToLocaleTimeString_data(); |
89 | void dateToLocaleTimeString(); |
90 | void dateToLocaleTimeStringFormatted_data(); |
91 | void dateToLocaleTimeStringFormatted(); |
92 | void dateFromLocaleString_data(); |
93 | void dateFromLocaleString(); |
94 | void dateFromLocaleDateString_data(); |
95 | void dateFromLocaleDateString(); |
96 | void dateFromLocaleTimeString_data(); |
97 | void dateFromLocaleTimeString(); |
98 | |
99 | void numberToLocaleString_data(); |
100 | void numberToLocaleString(); |
101 | void numberToLocaleCurrencyString_data(); |
102 | void numberToLocaleCurrencyString(); |
103 | void numberFromLocaleString_data(); |
104 | void numberFromLocaleString(); |
105 | void numberConstToLocaleString(); |
106 | void numberOptions(); |
107 | |
108 | void stringLocaleCompare_data(); |
109 | void stringLocaleCompare(); |
110 | |
111 | void localeAsCppProperty(); |
112 | private: |
113 | void addPropertyData(const QString &l); |
114 | QVariant getProperty(QObject *obj, const QString &locale, const QString &property); |
115 | void addCurrencySymbolData(const QString &locale); |
116 | void addStandardFormatData(); |
117 | void addFormatNameData(const QString &locale); |
118 | void addDateTimeFormatData(const QString &l); |
119 | void addDateFormatData(const QString &l); |
120 | void addTimeFormatData(const QString &l); |
121 | QQmlEngine engine; |
122 | }; |
123 | |
124 | void tst_qqmllocale::defaultLocale() |
125 | { |
126 | QQmlComponent c(&engine, testFileUrl(fileName: "properties.qml" )); |
127 | |
128 | QObject *obj = c.create(); |
129 | QVERIFY(obj); |
130 | |
131 | QCOMPARE(obj->property("name" ).toString(), QLocale().name()); |
132 | } |
133 | |
134 | #define LOCALE_PROP(type,prop) { #prop, QVariant(type(qlocale.prop())) } |
135 | |
136 | void tst_qqmllocale::addPropertyData(const QString &l) |
137 | { |
138 | QLocale qlocale(l); |
139 | |
140 | struct { |
141 | const char *name; |
142 | QVariant value; |
143 | } |
144 | values[] = { |
145 | LOCALE_PROP(QString,name), |
146 | LOCALE_PROP(QString,amText), |
147 | LOCALE_PROP(QString,pmText), |
148 | LOCALE_PROP(QString,nativeLanguageName), |
149 | LOCALE_PROP(QString,nativeCountryName), |
150 | LOCALE_PROP(QString,decimalPoint), |
151 | LOCALE_PROP(QString,groupSeparator), |
152 | LOCALE_PROP(QString,percent), |
153 | LOCALE_PROP(QString,zeroDigit), |
154 | LOCALE_PROP(QString,negativeSign), |
155 | LOCALE_PROP(QString,positiveSign), |
156 | LOCALE_PROP(QString,exponential), |
157 | LOCALE_PROP(int,measurementSystem), |
158 | LOCALE_PROP(int,textDirection), |
159 | { .name: nullptr, .value: QVariant() } |
160 | }; |
161 | |
162 | int i = 0; |
163 | while (values[i].name) { |
164 | QByteArray n = l.toLatin1() + ':' + values[i].name; |
165 | QTest::newRow(dataTag: n.constData()) << l << QByteArray(values[i].name) << values[i].value; |
166 | ++i; |
167 | } |
168 | } |
169 | |
170 | void tst_qqmllocale::properties_data() |
171 | { |
172 | QTest::addColumn<QString>(name: "locale" ); |
173 | QTest::addColumn<QByteArray>(name: "property" ); |
174 | QTest::addColumn<QVariant>(name: "value" ); |
175 | |
176 | addPropertyData(l: "en_US" ); |
177 | addPropertyData(l: "de_DE" ); |
178 | addPropertyData(l: "ar_SA" ); |
179 | addPropertyData(l: "hi_IN" ); |
180 | addPropertyData(l: "zh_CN" ); |
181 | addPropertyData(l: "th_TH" ); |
182 | } |
183 | |
184 | void tst_qqmllocale::properties() |
185 | { |
186 | QFETCH(QString, locale); |
187 | QFETCH(QByteArray, property); |
188 | QFETCH(QVariant, value); |
189 | |
190 | QQmlComponent c(&engine, testFileUrl(fileName: "properties.qml" )); |
191 | |
192 | QObject *obj = c.create(); |
193 | QVERIFY(obj); |
194 | |
195 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
196 | Q_ARG(QVariant, QVariant(locale))); |
197 | |
198 | QCOMPARE(obj->property(property), value); |
199 | |
200 | delete obj; |
201 | } |
202 | |
203 | void tst_qqmllocale::addCurrencySymbolData(const QString &l) |
204 | { |
205 | QByteArray locale = l.toLatin1(); |
206 | QTest::newRow(dataTag: locale.constData()) << l << -1; |
207 | QByteArray t(locale); |
208 | t += " CurrencyIsoCode" ; |
209 | QTest::newRow(dataTag: t.constData()) << l << (int)QLocale::CurrencyIsoCode; |
210 | t = locale + " CurrencySymbol" ; |
211 | QTest::newRow(dataTag: t.constData()) << l << (int)QLocale::CurrencySymbol; |
212 | t = locale + " CurrencyDisplayName" ; |
213 | QTest::newRow(dataTag: t.constData()) << l << (int)QLocale::CurrencyDisplayName; |
214 | } |
215 | |
216 | void tst_qqmllocale::currencySymbol_data() |
217 | { |
218 | QTest::addColumn<QString>(name: "locale" ); |
219 | QTest::addColumn<int>(name: "param" ); |
220 | |
221 | addCurrencySymbolData(l: "en_US" ); |
222 | addCurrencySymbolData(l: "de_DE" ); |
223 | addCurrencySymbolData(l: "ar_SA" ); |
224 | addCurrencySymbolData(l: "hi_IN" ); |
225 | addCurrencySymbolData(l: "zh_CN" ); |
226 | addCurrencySymbolData(l: "th_TH" ); |
227 | } |
228 | |
229 | void tst_qqmllocale::currencySymbol() |
230 | { |
231 | QFETCH(QString, locale); |
232 | QFETCH(int, param); |
233 | |
234 | QQmlComponent c(&engine, testFileUrl(fileName: "functions.qml" )); |
235 | |
236 | QObject *obj = c.create(); |
237 | QVERIFY(obj); |
238 | |
239 | QLocale l(locale); |
240 | QVariant val; |
241 | QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol; |
242 | |
243 | if (param >= 0) |
244 | format = QLocale::CurrencySymbolFormat(param); |
245 | |
246 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
247 | Q_ARG(QVariant, QVariant(locale))); |
248 | |
249 | QMetaObject::invokeMethod(obj, member: "currencySymbol" , Qt::DirectConnection, |
250 | Q_RETURN_ARG(QVariant, val), |
251 | Q_ARG(QVariant, QVariant(int(format)))); |
252 | |
253 | QCOMPARE(val.toString(), l.currencySymbol(format)); |
254 | |
255 | delete obj; |
256 | } |
257 | |
258 | void tst_qqmllocale::addFormatNameData(const QString &l) |
259 | { |
260 | QByteArray locale = l.toLatin1(); |
261 | QTest::newRow(dataTag: locale.constData()) << l << -1; |
262 | QByteArray t(locale); |
263 | t += " LongFormat" ; |
264 | QTest::newRow(dataTag: t.constData()) << l << (int)QLocale::LongFormat; |
265 | t = locale + " ShortFormat" ; |
266 | QTest::newRow(dataTag: t.constData()) << l << (int)QLocale::ShortFormat; |
267 | t = locale + " NarrowFormat" ; |
268 | QTest::newRow(dataTag: t.constData()) << l << (int)QLocale::NarrowFormat; |
269 | } |
270 | |
271 | void tst_qqmllocale::addStandardFormatData() |
272 | { |
273 | QTest::addColumn<QString>(name: "locale" ); |
274 | QTest::addColumn<int>(name: "param" ); |
275 | |
276 | addFormatNameData(l: "en_US" ); |
277 | addFormatNameData(l: "de_DE" ); |
278 | addFormatNameData(l: "ar_SA" ); |
279 | addFormatNameData(l: "hi_IN" ); |
280 | addFormatNameData(l: "zh_CN" ); |
281 | addFormatNameData(l: "th_TH" ); |
282 | } |
283 | |
284 | void tst_qqmllocale::monthName_data() |
285 | { |
286 | addStandardFormatData(); |
287 | } |
288 | |
289 | void tst_qqmllocale::monthName() |
290 | { |
291 | QFETCH(QString, locale); |
292 | QFETCH(int, param); |
293 | |
294 | QQmlComponent c(&engine, testFileUrl(fileName: "functions.qml" )); |
295 | |
296 | QObject *obj = c.create(); |
297 | QVERIFY(obj); |
298 | |
299 | QLocale l(locale); |
300 | QVariant val; |
301 | QLocale::FormatType format = QLocale::LongFormat; |
302 | if (param >= 0) |
303 | format = QLocale::FormatType(param); |
304 | |
305 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
306 | Q_ARG(QVariant, QVariant(locale))); |
307 | |
308 | for (int i = 0; i <= 11; ++i) { |
309 | QMetaObject::invokeMethod(obj, member: "monthName" , Qt::DirectConnection, |
310 | Q_RETURN_ARG(QVariant, val), |
311 | Q_ARG(QVariant, QVariant(i)), |
312 | Q_ARG(QVariant, QVariant(int(format)))); |
313 | |
314 | // QLocale January == 1, JS Date January == 0 |
315 | QCOMPARE(val.toString(), l.monthName(i+1, format)); |
316 | } |
317 | |
318 | delete obj; |
319 | } |
320 | |
321 | void tst_qqmllocale::standaloneMonthName_data() |
322 | { |
323 | addStandardFormatData(); |
324 | } |
325 | |
326 | void tst_qqmllocale::standaloneMonthName() |
327 | { |
328 | QFETCH(QString, locale); |
329 | QFETCH(int, param); |
330 | |
331 | QQmlComponent c(&engine, testFileUrl(fileName: "functions.qml" )); |
332 | |
333 | QObject *obj = c.create(); |
334 | QVERIFY(obj); |
335 | |
336 | QLocale l(locale); |
337 | QVariant val; |
338 | QLocale::FormatType format = QLocale::LongFormat; |
339 | if (param >= 0) |
340 | format = QLocale::FormatType(param); |
341 | |
342 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
343 | Q_ARG(QVariant, QVariant(locale))); |
344 | |
345 | for (int i = 0; i <= 11; ++i) { |
346 | QMetaObject::invokeMethod(obj, member: "standaloneMonthName" , Qt::DirectConnection, |
347 | Q_RETURN_ARG(QVariant, val), |
348 | Q_ARG(QVariant, QVariant(i)), |
349 | Q_ARG(QVariant, QVariant(int(format)))); |
350 | |
351 | // QLocale January == 1, JS Date January == 0 |
352 | QCOMPARE(val.toString(), l.standaloneMonthName(i+1, format)); |
353 | } |
354 | |
355 | delete obj; |
356 | } |
357 | |
358 | void tst_qqmllocale::dayName_data() |
359 | { |
360 | addStandardFormatData(); |
361 | } |
362 | |
363 | void tst_qqmllocale::dayName() |
364 | { |
365 | QFETCH(QString, locale); |
366 | QFETCH(int, param); |
367 | |
368 | QQmlComponent c(&engine, testFileUrl(fileName: "functions.qml" )); |
369 | |
370 | QObject *obj = c.create(); |
371 | QVERIFY(obj); |
372 | |
373 | QLocale l(locale); |
374 | QVariant val; |
375 | QLocale::FormatType format = QLocale::LongFormat; |
376 | if (param >= 0) |
377 | format = QLocale::FormatType(param); |
378 | |
379 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
380 | Q_ARG(QVariant, QVariant(locale))); |
381 | |
382 | for (int i = 1; i <= 7; ++i) { |
383 | QMetaObject::invokeMethod(obj, member: "dayName" , Qt::DirectConnection, |
384 | Q_RETURN_ARG(QVariant, val), |
385 | Q_ARG(QVariant, QVariant(i)), |
386 | Q_ARG(QVariant, QVariant(int(format)))); |
387 | |
388 | QCOMPARE(val.toString(), l.dayName(i, format)); |
389 | } |
390 | |
391 | delete obj; |
392 | } |
393 | |
394 | void tst_qqmllocale::standaloneDayName_data() |
395 | { |
396 | addStandardFormatData(); |
397 | } |
398 | |
399 | void tst_qqmllocale::standaloneDayName() |
400 | { |
401 | QFETCH(QString, locale); |
402 | QFETCH(int, param); |
403 | |
404 | QQmlComponent c(&engine, testFileUrl(fileName: "functions.qml" )); |
405 | |
406 | QObject *obj = c.create(); |
407 | QVERIFY(obj); |
408 | |
409 | QLocale l(locale); |
410 | QVariant val; |
411 | QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param); |
412 | |
413 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
414 | Q_ARG(QVariant, QVariant(locale))); |
415 | |
416 | for (int i = 1; i <= 7; ++i) { |
417 | QMetaObject::invokeMethod(obj, member: "standaloneDayName" , Qt::DirectConnection, |
418 | Q_RETURN_ARG(QVariant, val), |
419 | Q_ARG(QVariant, QVariant(i)), |
420 | Q_ARG(QVariant, QVariant(int(format)))); |
421 | |
422 | QCOMPARE(val.toString(), l.standaloneDayName(i, format)); |
423 | } |
424 | |
425 | delete obj; |
426 | } |
427 | |
428 | void tst_qqmllocale::firstDayOfWeek_data() |
429 | { |
430 | QTest::addColumn<QString>(name: "locale" ); |
431 | |
432 | QTest::newRow(dataTag: "en_US" ) << "en_US" ; |
433 | QTest::newRow(dataTag: "de_DE" ) << "de_DE" ; |
434 | QTest::newRow(dataTag: "ar_SA" ) << "ar_SA" ; |
435 | QTest::newRow(dataTag: "hi_IN" ) << "hi_IN" ; |
436 | QTest::newRow(dataTag: "zh_CN" ) << "zh_CN" ; |
437 | QTest::newRow(dataTag: "th_TH" ) << "th_TH" ; |
438 | } |
439 | |
440 | void tst_qqmllocale::firstDayOfWeek() |
441 | { |
442 | QFETCH(QString, locale); |
443 | |
444 | QQmlComponent c(&engine, testFileUrl(fileName: "properties.qml" )); |
445 | |
446 | QObject *obj = c.create(); |
447 | QVERIFY(obj); |
448 | |
449 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
450 | Q_ARG(QVariant, QVariant(locale))); |
451 | |
452 | QVariant val = obj->property(name: "firstDayOfWeek" ); |
453 | QCOMPARE(val.userType(), QMetaType::Int); |
454 | |
455 | int day = int(QLocale(locale).firstDayOfWeek()); |
456 | if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday) |
457 | day = 0; |
458 | QCOMPARE(day, val.toInt()); |
459 | |
460 | delete obj; |
461 | } |
462 | |
463 | void tst_qqmllocale::weekDays_data() |
464 | { |
465 | QTest::addColumn<QString>(name: "locale" ); |
466 | |
467 | QTest::newRow(dataTag: "en_US" ) << "en_US" ; |
468 | QTest::newRow(dataTag: "de_DE" ) << "de_DE" ; |
469 | QTest::newRow(dataTag: "ar_SA" ) << "ar_SA" ; |
470 | QTest::newRow(dataTag: "hi_IN" ) << "hi_IN" ; |
471 | QTest::newRow(dataTag: "zh_CN" ) << "zh_CN" ; |
472 | QTest::newRow(dataTag: "th_TH" ) << "th_TH" ; |
473 | } |
474 | |
475 | void tst_qqmllocale::weekDays() |
476 | { |
477 | QFETCH(QString, locale); |
478 | |
479 | QQmlComponent c(&engine, testFileUrl(fileName: "properties.qml" )); |
480 | |
481 | QObject *obj = c.create(); |
482 | QVERIFY(obj); |
483 | |
484 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
485 | Q_ARG(QVariant, QVariant(locale))); |
486 | |
487 | QVariant val = obj->property(name: "weekDays" ); |
488 | QCOMPARE(val.userType(), qMetaTypeId<QJSValue>()); |
489 | |
490 | QList<QVariant> qmlDays = val.toList(); |
491 | QList<Qt::DayOfWeek> days = QLocale(locale).weekdays(); |
492 | |
493 | QCOMPARE(days.count(), qmlDays.count()); |
494 | |
495 | for (int i = 0; i < days.count(); ++i) { |
496 | int day = int(days.at(i)); |
497 | if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday) |
498 | day = 0; |
499 | QCOMPARE(day, qmlDays.at(i).toInt()); |
500 | } |
501 | |
502 | delete obj; |
503 | } |
504 | |
505 | void tst_qqmllocale::uiLanguages_data() |
506 | { |
507 | QTest::addColumn<QString>(name: "locale" ); |
508 | |
509 | QTest::newRow(dataTag: "en_US" ) << "en_US" ; |
510 | QTest::newRow(dataTag: "de_DE" ) << "de_DE" ; |
511 | QTest::newRow(dataTag: "ar_SA" ) << "ar_SA" ; |
512 | QTest::newRow(dataTag: "hi_IN" ) << "hi_IN" ; |
513 | QTest::newRow(dataTag: "zh_CN" ) << "zh_CN" ; |
514 | QTest::newRow(dataTag: "th_TH" ) << "th_TH" ; |
515 | } |
516 | |
517 | void tst_qqmllocale::uiLanguages() |
518 | { |
519 | QFETCH(QString, locale); |
520 | |
521 | QQmlComponent c(&engine, testFileUrl(fileName: "properties.qml" )); |
522 | |
523 | QObject *obj = c.create(); |
524 | QVERIFY(obj); |
525 | |
526 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
527 | Q_ARG(QVariant, QVariant(locale))); |
528 | |
529 | QVariant val = obj->property(name: "uiLanguages" ); |
530 | QCOMPARE(val.userType(), qMetaTypeId<QJSValue>()); |
531 | |
532 | QList<QVariant> qmlLangs = val.toList(); |
533 | QStringList langs = QLocale(locale).uiLanguages(); |
534 | |
535 | QCOMPARE(langs.count(), qmlLangs.count()); |
536 | |
537 | for (int i = 0; i < langs.count(); ++i) { |
538 | QCOMPARE(langs.at(i), qmlLangs.at(i).toString()); |
539 | } |
540 | |
541 | delete obj; |
542 | } |
543 | |
544 | |
545 | void tst_qqmllocale::dateTimeFormat_data() |
546 | { |
547 | addStandardFormatData(); |
548 | } |
549 | |
550 | void tst_qqmllocale::dateTimeFormat() |
551 | { |
552 | QFETCH(QString, locale); |
553 | QFETCH(int, param); |
554 | |
555 | QQmlComponent c(&engine, testFileUrl(fileName: "functions.qml" )); |
556 | |
557 | QObject *obj = c.create(); |
558 | QVERIFY(obj); |
559 | |
560 | QLocale l(locale); |
561 | QVariant val; |
562 | |
563 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
564 | Q_ARG(QVariant, QVariant(locale))); |
565 | |
566 | QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param); |
567 | QMetaObject::invokeMethod(obj, member: "dateTimeFormat" , Qt::DirectConnection, |
568 | Q_RETURN_ARG(QVariant, val), |
569 | Q_ARG(QVariant, QVariant(param))); |
570 | |
571 | QCOMPARE(val.toString(), l.dateTimeFormat(format)); |
572 | } |
573 | |
574 | void tst_qqmllocale::dateFormat_data() |
575 | { |
576 | addStandardFormatData(); |
577 | } |
578 | |
579 | void tst_qqmllocale::dateFormat() |
580 | { |
581 | QFETCH(QString, locale); |
582 | QFETCH(int, param); |
583 | |
584 | QQmlComponent c(&engine, testFileUrl(fileName: "functions.qml" )); |
585 | |
586 | QObject *obj = c.create(); |
587 | QVERIFY(obj); |
588 | |
589 | QLocale l(locale); |
590 | QVariant val; |
591 | |
592 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
593 | Q_ARG(QVariant, QVariant(locale))); |
594 | |
595 | QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param); |
596 | QMetaObject::invokeMethod(obj, member: "dateFormat" , Qt::DirectConnection, |
597 | Q_RETURN_ARG(QVariant, val), |
598 | Q_ARG(QVariant, QVariant(param))); |
599 | |
600 | QCOMPARE(val.toString(), l.dateFormat(format)); |
601 | } |
602 | |
603 | void tst_qqmllocale::timeFormat_data() |
604 | { |
605 | addStandardFormatData(); |
606 | } |
607 | |
608 | void tst_qqmllocale::timeFormat() |
609 | { |
610 | QFETCH(QString, locale); |
611 | QFETCH(int, param); |
612 | |
613 | QQmlComponent c(&engine, testFileUrl(fileName: "functions.qml" )); |
614 | |
615 | QObject *obj = c.create(); |
616 | QVERIFY(obj); |
617 | |
618 | QLocale l(locale); |
619 | QVariant val; |
620 | |
621 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
622 | Q_ARG(QVariant, QVariant(locale))); |
623 | |
624 | QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param); |
625 | QMetaObject::invokeMethod(obj, member: "timeFormat" , Qt::DirectConnection, |
626 | Q_RETURN_ARG(QVariant, val), |
627 | Q_ARG(QVariant, QVariant(param))); |
628 | |
629 | QCOMPARE(val.toString(), l.timeFormat(format)); |
630 | } |
631 | |
632 | void tst_qqmllocale::dateToLocaleString_data() |
633 | { |
634 | addStandardFormatData(); |
635 | } |
636 | |
637 | void tst_qqmllocale::dateToLocaleString() |
638 | { |
639 | QFETCH(QString, locale); |
640 | QFETCH(int, param); |
641 | |
642 | QQmlComponent c(&engine, testFileUrl(fileName: "date.qml" )); |
643 | |
644 | QObject *obj = c.create(); |
645 | QVERIFY(obj); |
646 | |
647 | const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); |
648 | |
649 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
650 | Q_ARG(QVariant, QVariant(locale))); |
651 | |
652 | QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param); |
653 | |
654 | QVariant val; |
655 | QMetaObject::invokeMethod(obj, member: "toLocaleString" , Qt::DirectConnection, |
656 | Q_RETURN_ARG(QVariant, val), |
657 | Q_ARG(QVariant, QVariant(param))); |
658 | |
659 | QLocale l(locale); |
660 | QCOMPARE(val.toString(), l.toString(dt, format)); |
661 | } |
662 | |
663 | void tst_qqmllocale::addDateTimeFormatData(const QString &l) |
664 | { |
665 | const char *formats[] = { |
666 | "hh:mm dd.MM.yyyy" , |
667 | "h:m:sap ddd MMMM d yy" , |
668 | "'The date and time is: 'H:mm:ss:zzz dd/MM/yy" , |
669 | "MMM d yyyy HH:mm t" , |
670 | nullptr |
671 | }; |
672 | QByteArray locale = l.toLatin1(); |
673 | int i = 0; |
674 | while (formats[i]) { |
675 | QByteArray t(locale); |
676 | t += ' '; |
677 | t += formats[i]; |
678 | QTest::newRow(dataTag: t.constData()) << l << QString(formats[i]); |
679 | ++i; |
680 | } |
681 | } |
682 | |
683 | void tst_qqmllocale::dateToLocaleStringFormatted_data() |
684 | { |
685 | QTest::addColumn<QString>(name: "locale" ); |
686 | QTest::addColumn<QString>(name: "format" ); |
687 | |
688 | addDateTimeFormatData(l: "en_US" ); |
689 | addDateTimeFormatData(l: "de_DE" ); |
690 | addDateTimeFormatData(l: "ar_SA" ); |
691 | addDateTimeFormatData(l: "hi_IN" ); |
692 | addDateTimeFormatData(l: "zh_CN" ); |
693 | addDateTimeFormatData(l: "th_TH" ); |
694 | } |
695 | |
696 | void tst_qqmllocale::dateToLocaleStringFormatted() |
697 | { |
698 | QFETCH(QString, locale); |
699 | QFETCH(QString, format); |
700 | |
701 | QQmlComponent c(&engine, testFileUrl(fileName: "date.qml" )); |
702 | |
703 | QObject *obj = c.create(); |
704 | QVERIFY(obj); |
705 | |
706 | const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); |
707 | |
708 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
709 | Q_ARG(QVariant, QVariant(locale))); |
710 | |
711 | QVariant val; |
712 | QMetaObject::invokeMethod(obj, member: "toLocaleString" , Qt::DirectConnection, |
713 | Q_RETURN_ARG(QVariant, val), |
714 | Q_ARG(QVariant, QVariant(format))); |
715 | |
716 | QLocale l(locale); |
717 | QCOMPARE(val.toString(), l.toString(dt, format)); |
718 | } |
719 | |
720 | void tst_qqmllocale::dateToLocaleDateString_data() |
721 | { |
722 | addStandardFormatData(); |
723 | } |
724 | |
725 | void tst_qqmllocale::dateToLocaleDateString() |
726 | { |
727 | QFETCH(QString, locale); |
728 | QFETCH(int, param); |
729 | |
730 | QQmlComponent c(&engine, testFileUrl(fileName: "date.qml" )); |
731 | |
732 | QObject *obj = c.create(); |
733 | QVERIFY(obj); |
734 | |
735 | const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); |
736 | |
737 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
738 | Q_ARG(QVariant, QVariant(locale))); |
739 | |
740 | QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param); |
741 | |
742 | QVariant val; |
743 | QMetaObject::invokeMethod(obj, member: "toLocaleDateString" , Qt::DirectConnection, |
744 | Q_RETURN_ARG(QVariant, val), |
745 | Q_ARG(QVariant, QVariant(param))); |
746 | |
747 | QLocale l(locale); |
748 | QCOMPARE(val.toString(), l.toString(dt.date(), format)); |
749 | } |
750 | |
751 | void tst_qqmllocale::addDateFormatData(const QString &l) |
752 | { |
753 | const char *formats[] = { |
754 | "dd.MM.yyyy" , |
755 | "ddd MMMM d yy" , |
756 | "'The date is: 'dd/MM/yy" , |
757 | "MMM d yyyy" , |
758 | nullptr |
759 | }; |
760 | QByteArray locale = l.toLatin1(); |
761 | int i = 0; |
762 | while (formats[i]) { |
763 | QByteArray t(locale); |
764 | t += ' '; |
765 | t += formats[i]; |
766 | QTest::newRow(dataTag: t.constData()) << l << QString(formats[i]); |
767 | ++i; |
768 | } |
769 | } |
770 | |
771 | void tst_qqmllocale::dateToLocaleDateStringFormatted_data() |
772 | { |
773 | QTest::addColumn<QString>(name: "locale" ); |
774 | QTest::addColumn<QString>(name: "format" ); |
775 | |
776 | addDateFormatData(l: "en_US" ); |
777 | addDateFormatData(l: "de_DE" ); |
778 | addDateFormatData(l: "ar_SA" ); |
779 | addDateFormatData(l: "hi_IN" ); |
780 | addDateFormatData(l: "zh_CN" ); |
781 | addDateFormatData(l: "th_TH" ); |
782 | } |
783 | |
784 | void tst_qqmllocale::dateToLocaleDateStringFormatted() |
785 | { |
786 | QFETCH(QString, locale); |
787 | QFETCH(QString, format); |
788 | |
789 | QQmlComponent c(&engine, testFileUrl(fileName: "date.qml" )); |
790 | |
791 | QObject *obj = c.create(); |
792 | QVERIFY(obj); |
793 | |
794 | const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); |
795 | |
796 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
797 | Q_ARG(QVariant, QVariant(locale))); |
798 | |
799 | QVariant val; |
800 | QMetaObject::invokeMethod(obj, member: "toLocaleString" , Qt::DirectConnection, |
801 | Q_RETURN_ARG(QVariant, val), |
802 | Q_ARG(QVariant, QVariant(format))); |
803 | |
804 | QLocale l(locale); |
805 | QCOMPARE(val.toString(), l.toString(dt.date(), format)); |
806 | } |
807 | |
808 | void tst_qqmllocale::dateToLocaleTimeString_data() |
809 | { |
810 | addStandardFormatData(); |
811 | } |
812 | |
813 | void tst_qqmllocale::dateToLocaleTimeString() |
814 | { |
815 | QFETCH(QString, locale); |
816 | QFETCH(int, param); |
817 | |
818 | QQmlComponent c(&engine, testFileUrl(fileName: "date.qml" )); |
819 | |
820 | QObject *obj = c.create(); |
821 | QVERIFY(obj); |
822 | |
823 | const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); |
824 | |
825 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
826 | Q_ARG(QVariant, QVariant(locale))); |
827 | |
828 | QLocale::FormatType format = param < 0 ? QLocale::LongFormat : QLocale::FormatType(param); |
829 | |
830 | QVariant val; |
831 | QMetaObject::invokeMethod(obj, member: "toLocaleTimeString" , Qt::DirectConnection, |
832 | Q_RETURN_ARG(QVariant, val), |
833 | Q_ARG(QVariant, QVariant(param))); |
834 | |
835 | QLocale l(locale); |
836 | QCOMPARE(val.toString(), l.toString(dt.time(), format)); |
837 | } |
838 | |
839 | void tst_qqmllocale::addTimeFormatData(const QString &l) |
840 | { |
841 | const char *formats[] = { |
842 | "hh:mm" , |
843 | "h:m:sap" , |
844 | "'The time is: 'H:mm:ss:zzz" , |
845 | "HH:mm t" , |
846 | nullptr |
847 | }; |
848 | QByteArray locale = l.toLatin1(); |
849 | int i = 0; |
850 | while (formats[i]) { |
851 | QByteArray t(locale); |
852 | t += ' '; |
853 | t += formats[i]; |
854 | QTest::newRow(dataTag: t.constData()) << l << QString(formats[i]); |
855 | ++i; |
856 | } |
857 | } |
858 | |
859 | void tst_qqmllocale::dateToLocaleTimeStringFormatted_data() |
860 | { |
861 | QTest::addColumn<QString>(name: "locale" ); |
862 | QTest::addColumn<QString>(name: "format" ); |
863 | |
864 | addTimeFormatData(l: "en_US" ); |
865 | addTimeFormatData(l: "de_DE" ); |
866 | addTimeFormatData(l: "ar_SA" ); |
867 | addTimeFormatData(l: "hi_IN" ); |
868 | addTimeFormatData(l: "zh_CN" ); |
869 | addTimeFormatData(l: "th_TH" ); |
870 | } |
871 | |
872 | void tst_qqmllocale::dateToLocaleTimeStringFormatted() |
873 | { |
874 | QFETCH(QString, locale); |
875 | QFETCH(QString, format); |
876 | |
877 | QQmlComponent c(&engine, testFileUrl(fileName: "date.qml" )); |
878 | |
879 | QObject *obj = c.create(); |
880 | QVERIFY(obj); |
881 | |
882 | const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); |
883 | |
884 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
885 | Q_ARG(QVariant, QVariant(locale))); |
886 | |
887 | QVariant val; |
888 | QMetaObject::invokeMethod(obj, member: "toLocaleString" , Qt::DirectConnection, |
889 | Q_RETURN_ARG(QVariant, val), |
890 | Q_ARG(QVariant, QVariant(format))); |
891 | |
892 | QLocale l(locale); |
893 | QCOMPARE(val.toString(), l.toString(dt, format)); |
894 | } |
895 | |
896 | void tst_qqmllocale::dateFromLocaleString_data() |
897 | { |
898 | QTest::addColumn<QString>(name: "locale" ); |
899 | QTest::addColumn<QString>(name: "format" ); |
900 | |
901 | QTest::newRow(dataTag: "en_US 1" ) << "en_US" << "dddd, MMMM d, yyyy h:mm:ss AP" ; |
902 | QTest::newRow(dataTag: "en_US long" ) << "en_US" << QLocale("en_US" ).dateTimeFormat(); |
903 | QTest::newRow(dataTag: "en_US short" ) << "en_US" << QLocale("en_US" ).dateTimeFormat(format: QLocale::ShortFormat); |
904 | QTest::newRow(dataTag: "de_DE long" ) << "de_DE" << QLocale("de_DE" ).dateTimeFormat(); |
905 | QTest::newRow(dataTag: "de_DE short" ) << "de_DE" << QLocale("de_DE" ).dateTimeFormat(format: QLocale::ShortFormat); |
906 | QTest::newRow(dataTag: "ar_SA long" ) << "ar_SA" << QLocale("ar_SA" ).dateTimeFormat(); |
907 | QTest::newRow(dataTag: "ar_SA short" ) << "ar_SA" << QLocale("ar_SA" ).dateTimeFormat(format: QLocale::ShortFormat); |
908 | QTest::newRow(dataTag: "zh_CN long" ) << "zh_CN" << QLocale("zh_CN" ).dateTimeFormat(); |
909 | QTest::newRow(dataTag: "zh_CN short" ) << "zh_CN" << QLocale("zh_CN" ).dateTimeFormat(format: QLocale::ShortFormat); |
910 | } |
911 | |
912 | void tst_qqmllocale::dateFromLocaleString() |
913 | { |
914 | QFETCH(QString, locale); |
915 | QFETCH(QString, format); |
916 | |
917 | QQmlComponent c(&engine, testFileUrl(fileName: "date.qml" )); |
918 | |
919 | QObject *obj = c.create(); |
920 | QVERIFY(obj); |
921 | |
922 | const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); |
923 | |
924 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
925 | Q_ARG(QVariant, QVariant(locale))); |
926 | |
927 | QLocale l(locale); |
928 | const QString localeText(l.toString(dateTime: dt, format)); |
929 | QVariant val; |
930 | QMetaObject::invokeMethod(obj, member: "fromLocaleString" , Qt::DirectConnection, |
931 | Q_RETURN_ARG(QVariant, val), |
932 | Q_ARG(QVariant, QVariant(localeText)), |
933 | Q_ARG(QVariant, QVariant(format))); |
934 | |
935 | QDateTime pd = l.toDateTime(string: localeText, format); |
936 | QCOMPARE(val.toDateTime(), pd); |
937 | } |
938 | |
939 | void tst_qqmllocale::dateFromLocaleDateString_data() |
940 | { |
941 | QTest::addColumn<QString>(name: "locale" ); |
942 | QTest::addColumn<QString>(name: "format" ); |
943 | |
944 | QTest::newRow(dataTag: "en_US 1" ) << "en_US" << "dddd, MMMM d, yyyy h:mm:ss AP" ; |
945 | QTest::newRow(dataTag: "en_US long" ) << "en_US" << QLocale("en_US" ).dateFormat(); |
946 | QTest::newRow(dataTag: "en_US short" ) << "en_US" << QLocale("en_US" ).dateFormat(format: QLocale::ShortFormat); |
947 | QTest::newRow(dataTag: "de_DE long" ) << "de_DE" << QLocale("de_DE" ).dateFormat(); |
948 | QTest::newRow(dataTag: "de_DE short" ) << "de_DE" << QLocale("de_DE" ).dateFormat(format: QLocale::ShortFormat); |
949 | QTest::newRow(dataTag: "ar_SA long" ) << "ar_SA" << QLocale("ar_SA" ).dateFormat(); |
950 | QTest::newRow(dataTag: "ar_SA short" ) << "ar_SA" << QLocale("ar_SA" ).dateFormat(format: QLocale::ShortFormat); |
951 | QTest::newRow(dataTag: "zh_CN long" ) << "zh_CN" << QLocale("zh_CN" ).dateFormat(); |
952 | QTest::newRow(dataTag: "zh_CN short" ) << "zh_CN" << QLocale("zh_CN" ).dateFormat(format: QLocale::ShortFormat); |
953 | } |
954 | |
955 | void tst_qqmllocale::dateFromLocaleDateString() |
956 | { |
957 | QFETCH(QString, locale); |
958 | QFETCH(QString, format); |
959 | |
960 | QQmlComponent c(&engine, testFileUrl(fileName: "date.qml" )); |
961 | |
962 | QObject *obj = c.create(); |
963 | QVERIFY(obj); |
964 | |
965 | const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); |
966 | |
967 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
968 | Q_ARG(QVariant, QVariant(locale))); |
969 | |
970 | QLocale l(locale); |
971 | const QString localeText(l.toString(dateTime: dt, format)); |
972 | QVariant val; |
973 | QMetaObject::invokeMethod(obj, member: "fromLocaleDateString" , Qt::DirectConnection, |
974 | Q_RETURN_ARG(QVariant, val), |
975 | Q_ARG(QVariant, QVariant(localeText)), |
976 | Q_ARG(QVariant, QVariant(format))); |
977 | |
978 | QDate pd = l.toDate(string: localeText, format); |
979 | QCOMPARE(val.toDate(), pd); |
980 | } |
981 | |
982 | void tst_qqmllocale::dateFromLocaleTimeString_data() |
983 | { |
984 | QTest::addColumn<QString>(name: "locale" ); |
985 | QTest::addColumn<QString>(name: "format" ); |
986 | |
987 | QTest::newRow(dataTag: "en_US 1" ) << "en_US" << "dddd, MMMM d, yyyy h:mm:ss AP" ; |
988 | QTest::newRow(dataTag: "en_US long" ) << "en_US" << QLocale("en_US" ).timeFormat(); |
989 | QTest::newRow(dataTag: "en_US short" ) << "en_US" << QLocale("en_US" ).timeFormat(format: QLocale::ShortFormat); |
990 | QTest::newRow(dataTag: "de_DE long" ) << "de_DE" << QLocale("de_DE" ).timeFormat(); |
991 | QTest::newRow(dataTag: "de_DE short" ) << "de_DE" << QLocale("de_DE" ).timeFormat(format: QLocale::ShortFormat); |
992 | QTest::newRow(dataTag: "ar_SA long" ) << "ar_SA" << QLocale("ar_SA" ).timeFormat(); |
993 | QTest::newRow(dataTag: "ar_SA short" ) << "ar_SA" << QLocale("ar_SA" ).timeFormat(format: QLocale::ShortFormat); |
994 | QTest::newRow(dataTag: "zh_CN long" ) << "zh_CN" << QLocale("zh_CN" ).timeFormat(); |
995 | QTest::newRow(dataTag: "zh_CN short" ) << "zh_CN" << QLocale("zh_CN" ).timeFormat(format: QLocale::ShortFormat); |
996 | } |
997 | |
998 | void tst_qqmllocale::dateFromLocaleTimeString() |
999 | { |
1000 | QFETCH(QString, locale); |
1001 | QFETCH(QString, format); |
1002 | |
1003 | QQmlComponent c(&engine, testFileUrl(fileName: "date.qml" )); |
1004 | |
1005 | QObject *obj = c.create(); |
1006 | QVERIFY(obj); |
1007 | |
1008 | const QDateTime dt(QDate(2011, 10, 7), QTime(18, 53, 48, 345)); |
1009 | |
1010 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
1011 | Q_ARG(QVariant, QVariant(locale))); |
1012 | |
1013 | QLocale l(locale); |
1014 | const QString localeText(l.toString(dateTime: dt, format)); |
1015 | QVariant val; |
1016 | QMetaObject::invokeMethod(obj, member: "fromLocaleTimeString" , Qt::DirectConnection, |
1017 | Q_RETURN_ARG(QVariant, val), |
1018 | Q_ARG(QVariant, QVariant(localeText)), |
1019 | Q_ARG(QVariant, QVariant(format))); |
1020 | |
1021 | QTime pd = l.toTime(string: localeText, format); |
1022 | QCOMPARE(val.toTime(), pd); |
1023 | } |
1024 | |
1025 | void tst_qqmllocale::numberToLocaleString_data() |
1026 | { |
1027 | QTest::addColumn<QString>(name: "locale" ); |
1028 | QTest::addColumn<char>(name: "format" ); |
1029 | QTest::addColumn<int>(name: "prec" ); |
1030 | |
1031 | QTest::newRow(dataTag: "en_US 1" ) << "en_US" << 'f' << 2; |
1032 | QTest::newRow(dataTag: "en_US 2" ) << "en_US" << 'g' << 3; |
1033 | QTest::newRow(dataTag: "en_US 3" ) << "en_US" << 'f' << 0; |
1034 | QTest::newRow(dataTag: "en_US 4" ) << "en_US" << 'f' << -1; |
1035 | QTest::newRow(dataTag: "de_DE 1" ) << "de_DE" << 'f' << 2; |
1036 | QTest::newRow(dataTag: "de_DE 2" ) << "de_DE" << 'g' << 3; |
1037 | QTest::newRow(dataTag: "ar_SA 1" ) << "ar_SA" << 'f' << 2; |
1038 | QTest::newRow(dataTag: "ar_SA 2" ) << "ar_SA" << 'g' << 3; |
1039 | } |
1040 | |
1041 | void tst_qqmllocale::numberToLocaleString() |
1042 | { |
1043 | QFETCH(QString, locale); |
1044 | QFETCH(char, format); |
1045 | QFETCH(int, prec); |
1046 | |
1047 | QQmlComponent c(&engine, testFileUrl(fileName: "number.qml" )); |
1048 | |
1049 | QObject *obj = c.create(); |
1050 | QVERIFY(obj); |
1051 | |
1052 | double number = 2344423.3289; |
1053 | |
1054 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
1055 | Q_ARG(QVariant, QVariant(locale))); |
1056 | |
1057 | QLocale l(locale); |
1058 | QVariant val; |
1059 | QMetaObject::invokeMethod(obj, member: "toLocaleString" , Qt::DirectConnection, |
1060 | Q_RETURN_ARG(QVariant, val), |
1061 | Q_ARG(QVariant, QVariant(number)), |
1062 | Q_ARG(QVariant, QVariant(QString(format))), |
1063 | Q_ARG(QVariant, QVariant(prec))); |
1064 | |
1065 | if (prec < 0) prec = 2; |
1066 | QCOMPARE(val.toString(), l.toString(number, format, prec)); |
1067 | } |
1068 | |
1069 | void tst_qqmllocale::numberToLocaleCurrencyString_data() |
1070 | { |
1071 | QTest::addColumn<QString>(name: "locale" ); |
1072 | QTest::addColumn<QString>(name: "symbol" ); |
1073 | |
1074 | QTest::newRow(dataTag: "en_US 1" ) << "en_US" << QString(); |
1075 | QTest::newRow(dataTag: "en_US 2" ) << "en_US" << "USD" ; |
1076 | QTest::newRow(dataTag: "de_DE" ) << "de_DE" << QString(); |
1077 | QTest::newRow(dataTag: "ar_SA" ) << "ar_SA" << QString(); |
1078 | QTest::newRow(dataTag: "hi_IN" ) << "hi_IN" << QString(); |
1079 | QTest::newRow(dataTag: "zh_CN" ) << "zh_CN" << QString(); |
1080 | QTest::newRow(dataTag: "th_TH" ) << "th_TH" << QString(); |
1081 | } |
1082 | |
1083 | void tst_qqmllocale::numberToLocaleCurrencyString() |
1084 | { |
1085 | QFETCH(QString, locale); |
1086 | QFETCH(QString, symbol); |
1087 | |
1088 | QQmlComponent c(&engine, testFileUrl(fileName: "number.qml" )); |
1089 | |
1090 | QObject *obj = c.create(); |
1091 | QVERIFY(obj); |
1092 | |
1093 | double number = 2344423.3289; |
1094 | |
1095 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
1096 | Q_ARG(QVariant, QVariant(locale))); |
1097 | |
1098 | QLocale l(locale); |
1099 | QVariant val; |
1100 | QMetaObject::invokeMethod(obj, member: "toLocaleCurrencyString" , Qt::DirectConnection, |
1101 | Q_RETURN_ARG(QVariant, val), |
1102 | Q_ARG(QVariant, QVariant(number)), |
1103 | Q_ARG(QVariant, QVariant(symbol))); |
1104 | |
1105 | QCOMPARE(val.toString(), l.toCurrencyString(number, symbol)); |
1106 | } |
1107 | |
1108 | void tst_qqmllocale::numberFromLocaleString_data() |
1109 | { |
1110 | QTest::addColumn<QString>(name: "locale" ); |
1111 | QTest::addColumn<double>(name: "number" ); |
1112 | |
1113 | QTest::newRow(dataTag: "en_US 1" ) << "en_US" << 1234567.2345; |
1114 | QTest::newRow(dataTag: "en_US 2" ) << "en_US" << 0.234; |
1115 | QTest::newRow(dataTag: "en_US 3" ) << "en_US" << 234.0; |
1116 | QTest::newRow(dataTag: "de_DE" ) << "de_DE" << 1234567.2345; |
1117 | QTest::newRow(dataTag: "ar_SA" ) << "ar_SA" << 1234567.2345; |
1118 | QTest::newRow(dataTag: "hi_IN" ) << "hi_IN" << 1234567.2345; |
1119 | QTest::newRow(dataTag: "zh_CN" ) << "zh_CN" << 1234567.2345; |
1120 | QTest::newRow(dataTag: "th_TH" ) << "th_TH" << 1234567.2345; |
1121 | } |
1122 | |
1123 | void tst_qqmllocale::numberFromLocaleString() |
1124 | { |
1125 | QFETCH(QString, locale); |
1126 | QFETCH(double, number); |
1127 | |
1128 | QQmlComponent c(&engine, testFileUrl(fileName: "number.qml" )); |
1129 | |
1130 | QObject *obj = c.create(); |
1131 | QVERIFY(obj); |
1132 | |
1133 | QLocale l(locale); |
1134 | QString strNumber = l.toString(i: number, f: 'f'); |
1135 | |
1136 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
1137 | Q_ARG(QVariant, QVariant(locale))); |
1138 | |
1139 | QVariant val; |
1140 | QMetaObject::invokeMethod(obj, member: "fromLocaleString" , Qt::DirectConnection, |
1141 | Q_RETURN_ARG(QVariant, val), |
1142 | Q_ARG(QVariant, QVariant(strNumber))); |
1143 | |
1144 | QCOMPARE(val.toDouble(), l.toDouble(strNumber)); |
1145 | } |
1146 | |
1147 | void tst_qqmllocale::numberConstToLocaleString() |
1148 | { |
1149 | QQmlComponent c(&engine, testFileUrl(fileName: "number.qml" )); |
1150 | |
1151 | QObject *obj = c.create(); |
1152 | QVERIFY(obj); |
1153 | |
1154 | QMetaObject::invokeMethod(obj, member: "setLocale" , type: Qt::DirectConnection, |
1155 | Q_ARG(QVariant, QVariant("en_US" ))); |
1156 | |
1157 | QLocale l("en_US" ); |
1158 | QCOMPARE(obj->property("const1" ).toString(), l.toString(1234.56, 'f', 2)); |
1159 | QCOMPARE(obj->property("const2" ).toString(), l.toString(1234., 'f', 2)); |
1160 | } |
1161 | |
1162 | void tst_qqmllocale::numberOptions() |
1163 | { |
1164 | QQmlEngine engine; |
1165 | QQmlComponent comp(&engine); |
1166 | comp.setData(R"( |
1167 | import QtQml 2.15 |
1168 | QtObject { |
1169 | id: root |
1170 | property string formatted |
1171 | property bool caughtException: false |
1172 | Component.onCompleted: () => { |
1173 | const myLocale = Qt.locale("de_DE") |
1174 | myLocale.numberOptions = Locale.OmitGroupSeparator | Locale.RejectTrailingZeroesAfterDot |
1175 | root.formatted = Number(10000).toLocaleString(myLocale, 'f', 4) |
1176 | try { |
1177 | Number.fromLocaleString(myLocale, "1,10"); |
1178 | } catch (e) {console.warn(e); root.caughtException = true} |
1179 | } |
1180 | } |
1181 | )" , baseUrl: QUrl("testdata" )); |
1182 | QTest::ignoreMessage(type: QtMsgType::QtWarningMsg, message: "Error: Locale: Number.fromLocaleString(): Invalid format" ); |
1183 | QScopedPointer<QObject> root {comp.create()}; |
1184 | qDebug() << comp.errorString(); |
1185 | QVERIFY(root); |
1186 | QCOMPARE(root->property("formatted" ).toString(), QLatin1String("10000,0000" )); |
1187 | QCOMPARE(root->property("caughtException" ).toBool(), true); |
1188 | |
1189 | } |
1190 | |
1191 | void tst_qqmllocale::stringLocaleCompare_data() |
1192 | { |
1193 | QTest::addColumn<QString>(name: "string1" ); |
1194 | QTest::addColumn<QString>(name: "string2" ); |
1195 | |
1196 | QTest::newRow(dataTag: "before" ) << "a" << "b" ; |
1197 | QTest::newRow(dataTag: "equal" ) << "a" << "a" ; |
1198 | QTest::newRow(dataTag: "after" ) << "b" << "a" ; |
1199 | |
1200 | // Copied from QString::localeAwareCompare tests |
1201 | // We don't actually change locale - we just care that String.localeCompare() |
1202 | // matches QString::localeAwareCompare(); |
1203 | QTest::newRow(dataTag: "swedish1" ) << QString::fromLatin1(str: "\xe5" ) << QString::fromLatin1(str: "\xe4" ); |
1204 | QTest::newRow(dataTag: "swedish2" ) << QString::fromLatin1(str: "\xe4" ) << QString::fromLatin1(str: "\xf6" ); |
1205 | QTest::newRow(dataTag: "swedish3" ) << QString::fromLatin1(str: "\xe5" ) << QString::fromLatin1(str: "\xf6" ); |
1206 | QTest::newRow(dataTag: "swedish4" ) << QString::fromLatin1(str: "z" ) << QString::fromLatin1(str: "\xe5" ); |
1207 | |
1208 | QTest::newRow(dataTag: "german1" ) << QString::fromLatin1(str: "z" ) << QString::fromLatin1(str: "\xe4" ); |
1209 | QTest::newRow(dataTag: "german2" ) << QString::fromLatin1(str: "\xe4" ) << QString::fromLatin1(str: "\xf6" ); |
1210 | QTest::newRow(dataTag: "german3" ) << QString::fromLatin1(str: "z" ) << QString::fromLatin1(str: "\xf6" ); |
1211 | } |
1212 | |
1213 | void tst_qqmllocale::stringLocaleCompare() |
1214 | { |
1215 | QFETCH(QString, string1); |
1216 | QFETCH(QString, string2); |
1217 | |
1218 | QQmlComponent c(&engine, testFileUrl(fileName: "localeCompare.qml" )); |
1219 | |
1220 | QObject *obj = c.create(); |
1221 | QVERIFY(obj); |
1222 | |
1223 | obj->setProperty(name: "string1" , value: string1); |
1224 | obj->setProperty(name: "string2" , value: string2); |
1225 | |
1226 | QCOMPARE(obj->property("comparison" ).toInt(), QString::localeAwareCompare(string1, string2)); |
1227 | } |
1228 | |
1229 | class Calendar : public QObject |
1230 | { |
1231 | Q_OBJECT |
1232 | Q_PROPERTY(QLocale locale READ locale WRITE setLocale) |
1233 | public: |
1234 | Calendar() { |
1235 | } |
1236 | |
1237 | QLocale locale() const { |
1238 | return mLocale; |
1239 | } |
1240 | |
1241 | void setLocale(const QLocale &locale) { |
1242 | mLocale = locale; |
1243 | } |
1244 | private: |
1245 | QLocale mLocale; |
1246 | }; |
1247 | |
1248 | void tst_qqmllocale::localeAsCppProperty() |
1249 | { |
1250 | qmlRegisterType<Calendar>(uri: "Test" , versionMajor: 1, versionMinor: 0, qmlName: "Calendar" ); |
1251 | QQmlComponent component(&engine, testFileUrl(fileName: "localeAsCppProperty.qml" )); |
1252 | QVERIFY2(!component.isError(), qPrintable(component.errorString())); |
1253 | QTRY_VERIFY(component.isReady()); |
1254 | |
1255 | Calendar *item = qobject_cast<Calendar*>(object: component.create()); |
1256 | QCOMPARE(item->property("locale" ).toLocale().name(), QLatin1String("en_GB" )); |
1257 | |
1258 | QVariant localeVariant(QLocale("nb_NO" )); |
1259 | item->setProperty(name: "testLocale" , value: localeVariant); |
1260 | QCOMPARE(item->property("testLocale" ).toLocale().name(), QLatin1String("nb_NO" )); |
1261 | } |
1262 | |
1263 | class DateFormatter : public QObject |
1264 | { |
1265 | Q_OBJECT |
1266 | public: |
1267 | DateFormatter() {} |
1268 | |
1269 | Q_INVOKABLE QString getLocalizedForm(const QString &isoTimestamp); |
1270 | }; |
1271 | |
1272 | QString DateFormatter::getLocalizedForm(const QString &isoTimestamp) |
1273 | { |
1274 | QDateTime input = QDateTime::fromString(s: isoTimestamp, f: Qt::ISODate); |
1275 | QLocale locale; |
1276 | return locale.toString(dateTime: input); |
1277 | } |
1278 | |
1279 | #if defined(Q_OS_UNIX) && QT_CONFIG(timezone) |
1280 | // Currently disabled on Windows as adjusting the timezone |
1281 | // requires additional privileges that aren't normally |
1282 | // enabled for a process. This can be achieved by calling |
1283 | // AdjustTokenPrivileges() and then SetTimeZoneInformation(), |
1284 | // which will require linking to a different library to access that API. |
1285 | static void setTimeZone(const QByteArray &tz) |
1286 | { |
1287 | if (tz.isEmpty()) |
1288 | qunsetenv(varName: "TZ" ); |
1289 | else |
1290 | qputenv(varName: "TZ" , value: tz); |
1291 | ::tzset(); |
1292 | |
1293 | // following left for future reference, see comment above |
1294 | // #if defined(Q_OS_WIN32) |
1295 | // ::_tzset(); |
1296 | // #endif |
1297 | } |
1298 | |
1299 | void tst_qqmllocale::timeZoneUpdated() |
1300 | { |
1301 | // Note: This test may not reliably hit the QEXPECT_FAIL clauses below if the initial |
1302 | // system time zone is equivalent to either Australia/Brisbane or Asia/Kalkota. |
1303 | |
1304 | // Initialize the system time zone, so that we actually _change_ something below. |
1305 | QVERIFY2(QTimeZone::systemTimeZone().isValid(), |
1306 | "You know, Toto, I do believe we're not in Kansas any more." ); |
1307 | |
1308 | QByteArray original(qgetenv(varName: "TZ" )); |
1309 | |
1310 | // Set the timezone to Brisbane time, AEST-10:00 |
1311 | setTimeZone(QByteArray("Australia/Brisbane" )); |
1312 | |
1313 | QScopedPointer<QObject> obj; |
1314 | auto cleanup = qScopeGuard(f: [&original, &obj] { |
1315 | // Restore to original time zone |
1316 | setTimeZone(original); |
1317 | QMetaObject::invokeMethod(obj: obj.data(), member: "resetTimeZone" ); |
1318 | }); |
1319 | |
1320 | DateFormatter formatter; |
1321 | |
1322 | QQmlEngine e; |
1323 | e.rootContext()->setContextObject(&formatter); |
1324 | |
1325 | QQmlComponent c(&e, testFileUrl(fileName: "timeZoneUpdated.qml" )); |
1326 | QVERIFY2(!c.isError(), qPrintable(c.errorString())); |
1327 | obj.reset(other: c.create()); |
1328 | QVERIFY(obj); |
1329 | |
1330 | #if !defined(Q_OS_LINUX) || defined(Q_OS_ANDROID) |
1331 | QEXPECT_FAIL("" , |
1332 | "Date.timeZoneUpdated() only works on non-Android Linux with QT_CONFIG(timezone)." , |
1333 | Continue); |
1334 | #endif |
1335 | QVERIFY(obj->property("success" ).toBool()); |
1336 | |
1337 | // Change to Indian time, IST-05:30 |
1338 | setTimeZone(QByteArray("Asia/Kolkata" )); |
1339 | |
1340 | QMetaObject::invokeMethod(obj: obj.data(), member: "check" ); |
1341 | |
1342 | #if !defined(Q_OS_LINUX) || defined(Q_OS_ANDROID) |
1343 | QEXPECT_FAIL("" , |
1344 | "Date.timeZoneUpdated() only works on non-Android Linux with QT_CONFIG(timezone)." , |
1345 | Continue); |
1346 | #endif |
1347 | QVERIFY(obj->property("success" ).toBool()); |
1348 | } |
1349 | #endif // Unix && timezone |
1350 | |
1351 | QTEST_MAIN(tst_qqmllocale) |
1352 | |
1353 | #include "tst_qqmllocale.moc" |
1354 | |