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
43class tst_qqmllocale : public QQmlDataTest
44{
45 Q_OBJECT
46public:
47 tst_qqmllocale() { }
48
49private 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();
112private:
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
124void 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
136void 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
170void 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
184void 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
203void 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
216void 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
229void 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
258void 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
271void 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
284void tst_qqmllocale::monthName_data()
285{
286 addStandardFormatData();
287}
288
289void 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
321void tst_qqmllocale::standaloneMonthName_data()
322{
323 addStandardFormatData();
324}
325
326void 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
358void tst_qqmllocale::dayName_data()
359{
360 addStandardFormatData();
361}
362
363void 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
394void tst_qqmllocale::standaloneDayName_data()
395{
396 addStandardFormatData();
397}
398
399void 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
428void 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
440void 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
463void 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
475void 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
505void 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
517void 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
545void tst_qqmllocale::dateTimeFormat_data()
546{
547 addStandardFormatData();
548}
549
550void 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
574void tst_qqmllocale::dateFormat_data()
575{
576 addStandardFormatData();
577}
578
579void 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
603void tst_qqmllocale::timeFormat_data()
604{
605 addStandardFormatData();
606}
607
608void 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
632void tst_qqmllocale::dateToLocaleString_data()
633{
634 addStandardFormatData();
635}
636
637void 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
663void 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
683void 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
696void 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
720void tst_qqmllocale::dateToLocaleDateString_data()
721{
722 addStandardFormatData();
723}
724
725void 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
751void 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
771void 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
784void 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
808void tst_qqmllocale::dateToLocaleTimeString_data()
809{
810 addStandardFormatData();
811}
812
813void 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
839void 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
859void 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
872void 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
896void 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
912void 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
939void 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
955void 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
982void 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
998void 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
1025void 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
1041void 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
1069void 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
1083void 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
1108void 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
1123void 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
1147void 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
1162void 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
1191void 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
1213void 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
1229class Calendar : public QObject
1230{
1231 Q_OBJECT
1232 Q_PROPERTY(QLocale locale READ locale WRITE setLocale)
1233public:
1234 Calendar() {
1235 }
1236
1237 QLocale locale() const {
1238 return mLocale;
1239 }
1240
1241 void setLocale(const QLocale &locale) {
1242 mLocale = locale;
1243 }
1244private:
1245 QLocale mLocale;
1246};
1247
1248void 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
1263class DateFormatter : public QObject
1264{
1265 Q_OBJECT
1266public:
1267 DateFormatter() {}
1268
1269 Q_INVOKABLE QString getLocalizedForm(const QString &isoTimestamp);
1270};
1271
1272QString 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.
1285static 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
1299void 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
1351QTEST_MAIN(tst_qqmllocale)
1352
1353#include "tst_qqmllocale.moc"
1354

source code of qtdeclarative/tests/auto/qml/qqmllocale/tst_qqmllocale.cpp