6#include <private/qqmlcontext_p.h>
7#include <QtCore/qnumeric.h>
8#include <QtCore/qdatetime.h>
9#include <QtCore/qtimezone.h>
11#include <private/qlocale_p.h>
13#include <private/qv4dateobject_p.h>
14#include <private/qv4numberobject_p.h>
15#include <private/qv4stringobject_p.h>
16#include <private/qqmlvaluetypewrapper_p.h>
22#define THROW_ERROR(string)
24 return scope.engine->throwError(QString::fromUtf8(string));
28#define GET_LOCALE_DATA_RESOURCE(OBJECT)
30 QV4::Scoped<QQmlValueTypeWrapper> r(scope, OBJECT.as<QQmlValueTypeWrapper>());
31 return r ? r->cast<QLocale>() : nullptr;
38 if (
const QV4::QQmlValueTypeWrapper *wrapper = val.as<QQmlValueTypeWrapper>())
39 return wrapper->type() == QMetaType::fromType<QLocale>();
46void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine)
48 engine->datePrototype()->defineDefaultProperty(engine->id_toLocaleString(), method_toLocaleString);
49 engine->datePrototype()->defineDefaultProperty(QStringLiteral(
"toLocaleTimeString"), method_toLocaleTimeString);
50 engine->datePrototype()->defineDefaultProperty(QStringLiteral(
"toLocaleDateString"), method_toLocaleDateString);
51 engine->dateCtor()->defineDefaultProperty(QStringLiteral(
"fromLocaleString"), method_fromLocaleString);
52 engine->dateCtor()->defineDefaultProperty(QStringLiteral(
"fromLocaleTimeString"), method_fromLocaleTimeString);
53 engine->dateCtor()->defineDefaultProperty(QStringLiteral(
"fromLocaleDateString"), method_fromLocaleDateString);
54 engine->dateCtor()->defineDefaultProperty(QStringLiteral(
"timeZoneUpdated"), method_timeZoneUpdated);
57ReturnedValue QQmlDateExtension::method_toLocaleString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
61 return QV4::DatePrototype::method_toLocaleString(b, thisObject, argv, argc);
63 const QV4::DateObject *date = thisObject->as<DateObject>();
65 return QV4::DatePrototype::method_toLocaleString(b, thisObject, argv, argc);
67 QDateTime dt = date->toQDateTime();
72 RETURN_RESULT(scope.engine->newString(locale.toString(dt)));
75 if (!isLocaleObject(argv[0]))
76 return QV4::DatePrototype::method_toLocaleString(b, thisObject, argv, argc);
80 QLocale::FormatType enumFormat = QLocale::LongFormat;
83 if (String *s = argv[1].stringValue()) {
84 QString format = s->toQString();
85 formattedDt = r->toString(dt, format);
86 }
else if (argv[1].isNumber()) {
87 quint32 intFormat = argv[1].toNumber();
88 QLocale::FormatType format = QLocale::FormatType(intFormat);
89 formattedDt = r->toString(dt, format);
91 THROW_ERROR(
"Locale: Date.toLocaleString(): Invalid datetime format");
94 formattedDt = r->toString(dt, enumFormat);
97 RETURN_RESULT(scope.engine->newString(formattedDt));
100ReturnedValue QQmlDateExtension::method_toLocaleTimeString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
104 return QV4::DatePrototype::method_toLocaleTimeString(b, thisObject, argv, argc);
106 const QV4::DateObject *date = thisObject->as<DateObject>();
108 return QV4::DatePrototype::method_toLocaleTimeString(b, thisObject, argv, argc);
110 QDateTime dt = date->toQDateTime();
111 QTime time = dt.time();
116 RETURN_RESULT(scope.engine->newString(locale.toString(time)));
119 if (!isLocaleObject(argv[0]))
120 return QV4::DatePrototype::method_toLocaleTimeString(b, thisObject, argv, argc);
124 QLocale::FormatType enumFormat = QLocale::LongFormat;
125 QString formattedTime;
127 if (String *s = argv[1].stringValue()) {
128 QString format = s->toQString();
129 formattedTime = r->toString(time, format);
130 }
else if (argv[1].isNumber()) {
131 quint32 intFormat = argv[1].toNumber();
132 QLocale::FormatType format = QLocale::FormatType(intFormat);
133 formattedTime = r->toString(time, format);
135 THROW_ERROR(
"Locale: Date.toLocaleTimeString(): Invalid time format");
138 formattedTime = r->toString(time, enumFormat);
141 RETURN_RESULT(scope.engine->newString(formattedTime));
144ReturnedValue QQmlDateExtension::method_toLocaleDateString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
148 return QV4::DatePrototype::method_toLocaleDateString(b, thisObject, argv, argc);
150 const QV4::DateObject *dateObj = thisObject->as<DateObject>();
152 return QV4::DatePrototype::method_toLocaleDateString(b, thisObject, argv, argc);
154 QDateTime dt = dateObj->toQDateTime();
155 QDate date = dt.date();
160 RETURN_RESULT(scope.engine->newString(locale.toString(date)));
163 if (!isLocaleObject(argv[0]))
164 return QV4::DatePrototype::method_toLocaleDateString(b, thisObject, argv, argc);
168 QLocale::FormatType enumFormat = QLocale::LongFormat;
169 QString formattedDate;
171 if (String *s = argv[1].stringValue()) {
172 QString format = s->toQString();
173 formattedDate = r->toString(date, format);
174 }
else if (argv[1].isNumber()) {
175 quint32 intFormat = argv[1].toNumber();
176 QLocale::FormatType format = QLocale::FormatType(intFormat);
177 formattedDate = r->toString(date, format);
179 THROW_ERROR(
"Locale: Date.loLocaleDateString(): Invalid date format");
182 formattedDate = r->toString(date, enumFormat);
185 RETURN_RESULT(scope.engine->newString(formattedDate));
188ReturnedValue QQmlDateExtension::method_fromLocaleString(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *argv,
int argc)
191 QV4::ExecutionEngine *
const engine = scope.engine;
193 if (String *s = argv[0].stringValue()) {
195 QString dateString = s->toQString();
196 QDateTime dt = locale.toDateTime(dateString);
197 RETURN_RESULT(engine->newDateObject(dt));
201 if (argc < 1 || argc > 3 || !isLocaleObject(argv[0]))
202 THROW_ERROR(
"Locale: Date.fromLocaleString(): Invalid arguments");
206 QLocale::FormatType enumFormat = QLocale::LongFormat;
208 QString dateString = argv[1].toQStringNoThrow();
210 if (String *s = argv[2].stringValue()) {
211 QString format = s->toQString();
212 dt = r->toDateTime(dateString, format);
213 }
else if (argv[2].isNumber()) {
214 quint32 intFormat = argv[2].toNumber();
215 QLocale::FormatType format = QLocale::FormatType(intFormat);
216 dt = r->toDateTime(dateString, format);
218 THROW_ERROR(
"Locale: Date.fromLocaleString(): Invalid datetime format");
221 dt = r->toDateTime(dateString, enumFormat);
224 RETURN_RESULT(engine->newDateObject(dt));
227ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *argv,
int argc)
230 QV4::ExecutionEngine *
const engine = scope.engine;
233 if (String *s = argv[0].stringValue()) {
235 QString timeString = s->toQString();
236 QTime time = locale.toTime(timeString);
237 QDateTime dt = QDateTime::currentDateTime();
239 RETURN_RESULT(engine->newDateObject(dt));
243 if (argc < 1 || argc > 3 || !isLocaleObject(argv[0]))
244 THROW_ERROR(
"Locale: Date.fromLocaleTimeString(): Invalid arguments");
248 QLocale::FormatType enumFormat = QLocale::LongFormat;
250 QString dateString = argv[1].toQStringNoThrow();
252 if (String *s = argv[2].stringValue()) {
253 QString format = s->toQString();
254 tm = r->toTime(dateString, format);
255 }
else if (argv[2].isNumber()) {
256 quint32 intFormat = argv[2].toNumber();
257 QLocale::FormatType format = QLocale::FormatType(intFormat);
258 tm = r->toTime(dateString, format);
260 THROW_ERROR(
"Locale: Date.fromLocaleTimeString(): Invalid datetime format");
263 tm = r->toTime(dateString, enumFormat);
268 dt = QDateTime::currentDateTime();
272 RETURN_RESULT(engine->newDateObject(dt));
275ReturnedValue QQmlDateExtension::method_fromLocaleDateString(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *argv,
int argc)
278 QV4::ExecutionEngine *
const engine = scope.engine;
281 if (String *s = argv[0].stringValue()) {
283 QString dateString = s->toQString();
284 QDate date = locale.toDate(dateString);
285 RETURN_RESULT(engine->newDateObject(date.startOfDay(QTimeZone::UTC)));
289 if (argc < 1 || argc > 3 || !isLocaleObject(argv[0]))
290 THROW_ERROR(
"Locale: Date.fromLocaleDateString(): Invalid arguments");
294 QLocale::FormatType enumFormat = QLocale::LongFormat;
296 QString dateString = argv[1].toQStringNoThrow();
298 if (String *s = argv[2].stringValue()) {
299 QString format = s->toQString();
300 dt = r->toDate(dateString, format);
301 }
else if (argv[2].isNumber()) {
302 quint32 intFormat = argv[2].toNumber();
303 QLocale::FormatType format = QLocale::FormatType(intFormat);
304 dt = r->toDate(dateString, format);
306 THROW_ERROR(
"Locale: Date.fromLocaleDateString(): Invalid datetime format");
309 dt = r->toDate(dateString, enumFormat);
312 RETURN_RESULT(engine->newDateObject(dt.startOfDay(QTimeZone::UTC)));
315ReturnedValue QQmlDateExtension::method_timeZoneUpdated(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *,
int argc)
319 THROW_ERROR(
"Locale: Date.timeZoneUpdated(): Invalid arguments");
321 QV4::DatePrototype::timezoneUpdated(scope.engine);
331 engine->numberPrototype()->defineDefaultProperty(engine->id_toLocaleString(), method_toLocaleString);
332 engine->numberPrototype()->defineDefaultProperty(QStringLiteral(
"toLocaleCurrencyString"), method_toLocaleCurrencyString);
333 engine->numberCtor()->defineDefaultProperty(QStringLiteral(
"fromLocaleString"), method_fromLocaleString);
336QV4::ReturnedValue
QQmlNumberExtension::method_toLocaleString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
340 THROW_ERROR(
"Locale: Number.toLocaleString(): Invalid arguments");
342 double number = thisObject->toNumber();
347 RETURN_RESULT(scope.engine->newString(locale.toString(number)));
350 if (!isLocaleObject(argv[0]))
351 return QV4::NumberPrototype::method_toLocaleString(b, thisObject, argv, argc);
355 quint16 format =
'f';
357 if (!argv[1].isString())
358 THROW_ERROR(
"Locale: Number.toLocaleString(): Invalid arguments");
359 QString fs = argv[1].toQString();
361 format = fs.at(0).unicode();
365 if (!argv[2].isNumber())
366 THROW_ERROR(
"Locale: Number.toLocaleString(): Invalid arguments");
367 prec = argv[2].toInt32();
370 RETURN_RESULT(scope.engine->newString(r->toString(number, (
char)format, prec)));
373ReturnedValue
QQmlNumberExtension::method_toLocaleCurrencyString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
377 THROW_ERROR(
"Locale: Number.toLocaleCurrencyString(): Invalid arguments");
379 double number = thisObject->toNumber();
384 RETURN_RESULT(scope.engine->newString(locale.toString(number)));
387 if (!isLocaleObject(argv[0]))
388 THROW_ERROR(
"Locale: Number.toLocaleCurrencyString(): Invalid arguments");
394 if (!argv[1].isString())
395 THROW_ERROR(
"Locale: Number.toLocaleString(): Invalid arguments");
396 symbol = argv[1].toQStringNoThrow();
399 RETURN_RESULT(scope.engine->newString(r->toCurrencyString(number, symbol)));
402ReturnedValue
QQmlNumberExtension::method_fromLocaleString(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *argv,
int argc)
405 if (argc < 1 || argc > 2)
406 THROW_ERROR(
"Locale: Number.fromLocaleString(): Invalid arguments");
412 if (!isLocaleObject(argv[0]))
413 THROW_ERROR(
"Locale: Number.fromLocaleString(): Invalid arguments");
421 QString ns = argv[numberIdx].toQString();
423 RETURN_RESULT(QV4::Encode(Q_QNAN));
426 double val = locale.toDouble(ns, &ok);
429 THROW_ERROR(
"Locale: Number.fromLocaleString(): Invalid format");
431 RETURN_RESULT(QV4::Encode(val));
439 QV4::Scope scope(args->v4engine());
440 const auto doThrow = [&](
const QString &message) {
441 args->setReturnValue(scope.engine->throwError(message));
444 const int argc = args->length();
446 if (argc < 1 || argc > 3) {
447 doThrow(QString::fromLatin1(
448 "Locale: formattedDataSize(): Expected 1-3 arguments, but received %1")
453 QV4::ScopedValue arg0(scope, (*args)[0]);
454 bool mismatched0 =
false;
455 if (!arg0->isNumber()) {
457 qWarning() <<
"Locale: formattedDataSize(): Invalid argument ('bytes' should be a number)";
459 args->setReturnValue(
460 scope.engine->newString(locale.formattedDataSize(qint64(arg0->toInteger())))
461 ->asReturnedValue());
471 QV4::ScopedValue arg1(scope, (*args)[1]);
472 if (!arg1->isInteger()) {
473 doThrow(QLatin1String(
474 "Locale: formattedDataSize(): Invalid argument ('precision' must be an int)"));
480 const QString result = locale.formattedDataSize(
481 qint64(arg0->toInteger()), arg1->integerValue());
482 args->setReturnValue(scope.engine->newString(result)->asReturnedValue());
486 QV4::ScopedValue arg2(scope, (*args)[2]);
487 if (arg2->isNumber()) {
488 const QString result = locale.formattedDataSize(
489 qint64(arg0->toInteger()), arg1->integerValue(),
490 QLocale::DataSizeFormats(arg2->integerValue()));
491 args->setReturnValue(scope.engine->newString(result)->asReturnedValue());
497 Q_ASSERT(!QV4::ScopedValue(scope, (*args)[2])->isNumber());
499 doThrow(QLatin1String(
500 "Locale: formattedDataSize(): Invalid argument ('format' must be DataSizeFormat)"));
505 return day == Qt::Sunday ? QQmlLocale::DayOfWeek::Sunday : QQmlLocale::DayOfWeek(day);
510 return qtDayToQmlDay(locale.firstDayOfWeek());
515 const QList<Qt::DayOfWeek> days = locale.weekdays();
516 QList<QQmlLocale::DayOfWeek> result;
517 result.reserve(days.size());
518 for (Qt::DayOfWeek day : days)
519 result.append(qtDayToQmlDay(day));
525 Scope scope(args->v4engine());
526 const auto doThrow = [&](
const QString &message) {
527 args->setReturnValue(scope.engine->throwError(message));
530 const int argc = args->length();
536 doThrow(QString::fromLatin1(
"Locale: toString(): Expected 1-3 arguments, but received %1")
541 QV4::ScopedValue arg0(scope, (*args)[0]);
542 if (arg0->isNumber()) {
548 QV4::ScopedValue arg1(scope, (*args)[1]);
549 if (!arg1->isString()) {
550 doThrow(QLatin1String(
"Locale: the second argument to the toString overload "
551 "whose first argument is a double should be a char"));
558 Q_ASSERT(!QV4::ScopedValue(scope, (*args)[2])->isInteger());
560 doThrow(QLatin1String(
"Locale: the third argument to the toString overload "
561 "whose first argument is a double should be an int"));
565 if (arg0->as<DateObject>()) {
567 doThrow(QString::fromLatin1(
568 "Locale: the toString() overload that takes a Date as its first "
569 "argument expects 1 or 2 arguments, but received %1").arg(argc));
575 QV4::ScopedValue arg1(scope, (*args)[1]);
578 Q_ASSERT(!arg1->isString());
581 Q_ASSERT(!arg1->isNumber());
583 doThrow(QLatin1String(
"Locale: the second argument to the toString overloads whose "
584 "first argument is a Date should be a string or FormatType"));
588 doThrow(QLatin1String(
"Locale: toString() expects either an int, double, "
589 "or Date as its first argument"));
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
684QV4::ReturnedValue QQmlLocale::locale(ExecutionEngine *engine,
const QString &localeName)
686 if (localeName.isEmpty()) {
687 return QQmlValueTypeWrapper::create(
688 engine,
nullptr, &QQmlLocaleValueType::staticMetaObject,
689 QMetaType::fromType<QLocale>());
692 QLocale qlocale(localeName);
693 return QQmlValueTypeWrapper::create(
694 engine, &qlocale, &QQmlLocaleValueType::staticMetaObject,
695 QMetaType::fromType<QLocale>());
698void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
700 engine->stringPrototype()->defineDefaultProperty(QStringLiteral(
"localeCompare"), method_localeCompare);
703ReturnedValue QQmlLocale::method_localeCompare(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
705 if (argc != 1 || (!argv[0].isString() && !argv[0].as<StringObject>()))
706 return QV4::StringPrototype::method_localeCompare(b, thisObject, argv, argc);
708 if (!thisObject->isString() && !thisObject->as<StringObject>())
709 return QV4::StringPrototype::method_localeCompare(b, thisObject, argv, argc);
711 QString thisString = thisObject->toQStringNoThrow();
712 QString thatString = argv[0].toQStringNoThrow();
714 return QV4::Encode(QString::localeAwareCompare(thisString, thatString));
718
719
720
721
722
723
724
727
728
729
730
733
734
735
736
739
740
741
742
743
744
745
746
749
750
751
752
756
757
758
759
762
763
764
765
768
769
770
771
774
775
776
777
780
781
782
783
784
785
786
789
790
791
792
793
794
795
798
799
800
801
802
803
804
807
808
809
810
811
812
813
814
815
816
817
818
821
822
823
824
825
826
827
828
829
830
833
834
835
836
837
838
839
840
841
842
843
844
845
848
849
850
851
852
853
854
855
858
859
860
861
862
863
864
865
866
867
868
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
888
889
890
891
892
893
894
897
898
899
900
901
902
903
906
907
908
909
910
911
912
913
914
915
916
919
920
921
922
923
924
925
926
927
928
931
932
933
934
935
936
937
938
939
942
943
944
945
946
947
948
949
952
953
954
955
956
957
958
959
960
961
964
965
966
967
968
969
970
973
974
975
976
979
980
981
982
985
986
987
988
989
990
991
992
993
994
997
998
999
1000
1001
1002
1003
1006
1007
1008
1009
1010
1011
1012
1013
1016
1017
1018
1019
1020
1021
1022
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1040#include "moc_qqmllocale_p.cpp"
QList< QQmlLocale::DayOfWeek > weekDays() const
Combined button and popup list for selecting options.
#define GET_LOCALE_DATA_RESOURCE(OBJECT)
static bool isLocaleObject(const QV4::Value &val)
#define THROW_ERROR(string)
static QQmlLocale::DayOfWeek qtDayToQmlDay(Qt::DayOfWeek day)