5#include <private/qqmlcontext_p.h>
6#include <QtCore/qnumeric.h>
7#include <QtCore/qdatetime.h>
8#include <QtCore/qtimezone.h>
10#include <private/qlocale_p.h>
12#include <private/qv4dateobject_p.h>
13#include <private/qv4numberobject_p.h>
14#include <private/qv4stringobject_p.h>
15#include <private/qqmlvaluetypewrapper_p.h>
21#define THROW_ERROR(string)
23 return scope.engine->throwError(QString::fromUtf8(string));
27#define GET_LOCALE_DATA_RESOURCE(OBJECT)
29 QV4::Scoped<QQmlValueTypeWrapper> r(scope, OBJECT.as<QQmlValueTypeWrapper>());
30 return r ? r->cast<QLocale>() : nullptr;
37 if (
const QV4::QQmlValueTypeWrapper *wrapper = val.as<QQmlValueTypeWrapper>())
38 return wrapper->type() == QMetaType::fromType<QLocale>();
45void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine)
47 engine->datePrototype()->defineDefaultProperty(engine->id_toLocaleString(), method_toLocaleString);
48 engine->datePrototype()->defineDefaultProperty(QStringLiteral(
"toLocaleTimeString"), method_toLocaleTimeString);
49 engine->datePrototype()->defineDefaultProperty(QStringLiteral(
"toLocaleDateString"), method_toLocaleDateString);
50 engine->dateCtor()->defineDefaultProperty(QStringLiteral(
"fromLocaleString"), method_fromLocaleString);
51 engine->dateCtor()->defineDefaultProperty(QStringLiteral(
"fromLocaleTimeString"), method_fromLocaleTimeString);
52 engine->dateCtor()->defineDefaultProperty(QStringLiteral(
"fromLocaleDateString"), method_fromLocaleDateString);
53 engine->dateCtor()->defineDefaultProperty(QStringLiteral(
"timeZoneUpdated"), method_timeZoneUpdated);
56ReturnedValue QQmlDateExtension::method_toLocaleString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
60 return QV4::DatePrototype::method_toLocaleString(b, thisObject, argv, argc);
62 const QV4::DateObject *date = thisObject->as<DateObject>();
64 return QV4::DatePrototype::method_toLocaleString(b, thisObject, argv, argc);
66 QDateTime dt = date->toQDateTime();
71 RETURN_RESULT(scope.engine->newString(locale.toString(dt)));
74 if (!isLocaleObject(argv[0]))
75 return QV4::DatePrototype::method_toLocaleString(b, thisObject, argv, argc);
79 QLocale::FormatType enumFormat = QLocale::LongFormat;
82 if (String *s = argv[1].stringValue()) {
83 QString format = s->toQString();
84 formattedDt = r->toString(dt, format);
85 }
else if (argv[1].isNumber()) {
86 quint32 intFormat = argv[1].toNumber();
87 QLocale::FormatType format = QLocale::FormatType(intFormat);
88 formattedDt = r->toString(dt, format);
90 THROW_ERROR(
"Locale: Date.toLocaleString(): Invalid datetime format");
93 formattedDt = r->toString(dt, enumFormat);
96 RETURN_RESULT(scope.engine->newString(formattedDt));
99ReturnedValue QQmlDateExtension::method_toLocaleTimeString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
103 return QV4::DatePrototype::method_toLocaleTimeString(b, thisObject, argv, argc);
105 const QV4::DateObject *date = thisObject->as<DateObject>();
107 return QV4::DatePrototype::method_toLocaleTimeString(b, thisObject, argv, argc);
109 QDateTime dt = date->toQDateTime();
110 QTime time = dt.time();
115 RETURN_RESULT(scope.engine->newString(locale.toString(time)));
118 if (!isLocaleObject(argv[0]))
119 return QV4::DatePrototype::method_toLocaleTimeString(b, thisObject, argv, argc);
123 QLocale::FormatType enumFormat = QLocale::LongFormat;
124 QString formattedTime;
126 if (String *s = argv[1].stringValue()) {
127 QString format = s->toQString();
128 formattedTime = r->toString(time, format);
129 }
else if (argv[1].isNumber()) {
130 quint32 intFormat = argv[1].toNumber();
131 QLocale::FormatType format = QLocale::FormatType(intFormat);
132 formattedTime = r->toString(time, format);
134 THROW_ERROR(
"Locale: Date.toLocaleTimeString(): Invalid time format");
137 formattedTime = r->toString(time, enumFormat);
140 RETURN_RESULT(scope.engine->newString(formattedTime));
143ReturnedValue QQmlDateExtension::method_toLocaleDateString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
147 return QV4::DatePrototype::method_toLocaleDateString(b, thisObject, argv, argc);
149 const QV4::DateObject *dateObj = thisObject->as<DateObject>();
151 return QV4::DatePrototype::method_toLocaleDateString(b, thisObject, argv, argc);
153 QDateTime dt = dateObj->toQDateTime();
154 QDate date = dt.date();
159 RETURN_RESULT(scope.engine->newString(locale.toString(date)));
162 if (!isLocaleObject(argv[0]))
163 return QV4::DatePrototype::method_toLocaleDateString(b, thisObject, argv, argc);
167 QLocale::FormatType enumFormat = QLocale::LongFormat;
168 QString formattedDate;
170 if (String *s = argv[1].stringValue()) {
171 QString format = s->toQString();
172 formattedDate = r->toString(date, format);
173 }
else if (argv[1].isNumber()) {
174 quint32 intFormat = argv[1].toNumber();
175 QLocale::FormatType format = QLocale::FormatType(intFormat);
176 formattedDate = r->toString(date, format);
178 THROW_ERROR(
"Locale: Date.loLocaleDateString(): Invalid date format");
181 formattedDate = r->toString(date, enumFormat);
184 RETURN_RESULT(scope.engine->newString(formattedDate));
187ReturnedValue QQmlDateExtension::method_fromLocaleString(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *argv,
int argc)
190 QV4::ExecutionEngine *
const engine = scope.engine;
192 if (String *s = argv[0].stringValue()) {
194 QString dateString = s->toQString();
195 QDateTime dt = locale.toDateTime(dateString);
196 RETURN_RESULT(engine->newDateObject(dt));
200 if (argc < 1 || argc > 3 || !isLocaleObject(argv[0]))
201 THROW_ERROR(
"Locale: Date.fromLocaleString(): Invalid arguments");
205 QLocale::FormatType enumFormat = QLocale::LongFormat;
207 QString dateString = argv[1].toQStringNoThrow();
209 if (String *s = argv[2].stringValue()) {
210 QString format = s->toQString();
211 dt = r->toDateTime(dateString, format);
212 }
else if (argv[2].isNumber()) {
213 quint32 intFormat = argv[2].toNumber();
214 QLocale::FormatType format = QLocale::FormatType(intFormat);
215 dt = r->toDateTime(dateString, format);
217 THROW_ERROR(
"Locale: Date.fromLocaleString(): Invalid datetime format");
220 dt = r->toDateTime(dateString, enumFormat);
223 RETURN_RESULT(engine->newDateObject(dt));
226ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *argv,
int argc)
229 QV4::ExecutionEngine *
const engine = scope.engine;
232 if (String *s = argv[0].stringValue()) {
234 QString timeString = s->toQString();
235 QTime time = locale.toTime(timeString);
236 QDateTime dt = QDateTime::currentDateTime();
238 RETURN_RESULT(engine->newDateObject(dt));
242 if (argc < 1 || argc > 3 || !isLocaleObject(argv[0]))
243 THROW_ERROR(
"Locale: Date.fromLocaleTimeString(): Invalid arguments");
247 QLocale::FormatType enumFormat = QLocale::LongFormat;
249 QString dateString = argv[1].toQStringNoThrow();
251 if (String *s = argv[2].stringValue()) {
252 QString format = s->toQString();
253 tm = r->toTime(dateString, format);
254 }
else if (argv[2].isNumber()) {
255 quint32 intFormat = argv[2].toNumber();
256 QLocale::FormatType format = QLocale::FormatType(intFormat);
257 tm = r->toTime(dateString, format);
259 THROW_ERROR(
"Locale: Date.fromLocaleTimeString(): Invalid datetime format");
262 tm = r->toTime(dateString, enumFormat);
267 dt = QDateTime::currentDateTime();
271 RETURN_RESULT(engine->newDateObject(dt));
274ReturnedValue QQmlDateExtension::method_fromLocaleDateString(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *argv,
int argc)
277 QV4::ExecutionEngine *
const engine = scope.engine;
280 if (String *s = argv[0].stringValue()) {
282 QString dateString = s->toQString();
283 QDate date = locale.toDate(dateString);
284 RETURN_RESULT(engine->newDateObject(date.startOfDay(QTimeZone::UTC)));
288 if (argc < 1 || argc > 3 || !isLocaleObject(argv[0]))
289 THROW_ERROR(
"Locale: Date.fromLocaleDateString(): Invalid arguments");
293 QLocale::FormatType enumFormat = QLocale::LongFormat;
295 QString dateString = argv[1].toQStringNoThrow();
297 if (String *s = argv[2].stringValue()) {
298 QString format = s->toQString();
299 dt = r->toDate(dateString, format);
300 }
else if (argv[2].isNumber()) {
301 quint32 intFormat = argv[2].toNumber();
302 QLocale::FormatType format = QLocale::FormatType(intFormat);
303 dt = r->toDate(dateString, format);
305 THROW_ERROR(
"Locale: Date.fromLocaleDateString(): Invalid datetime format");
308 dt = r->toDate(dateString, enumFormat);
311 RETURN_RESULT(engine->newDateObject(dt.startOfDay(QTimeZone::UTC)));
314ReturnedValue QQmlDateExtension::method_timeZoneUpdated(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *,
int argc)
318 THROW_ERROR(
"Locale: Date.timeZoneUpdated(): Invalid arguments");
320 QV4::DatePrototype::timezoneUpdated(scope.engine);
330 engine->numberPrototype()->defineDefaultProperty(engine->id_toLocaleString(), method_toLocaleString);
331 engine->numberPrototype()->defineDefaultProperty(QStringLiteral(
"toLocaleCurrencyString"), method_toLocaleCurrencyString);
332 engine->numberCtor()->defineDefaultProperty(QStringLiteral(
"fromLocaleString"), method_fromLocaleString);
335QV4::ReturnedValue
QQmlNumberExtension::method_toLocaleString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
339 THROW_ERROR(
"Locale: Number.toLocaleString(): Invalid arguments");
341 double number = thisObject->toNumber();
346 RETURN_RESULT(scope.engine->newString(locale.toString(number)));
349 if (!isLocaleObject(argv[0]))
350 return QV4::NumberPrototype::method_toLocaleString(b, thisObject, argv, argc);
354 quint16 format =
'f';
356 if (!argv[1].isString())
357 THROW_ERROR(
"Locale: Number.toLocaleString(): Invalid arguments");
358 QString fs = argv[1].toQString();
360 format = fs.at(0).unicode();
364 if (!argv[2].isNumber())
365 THROW_ERROR(
"Locale: Number.toLocaleString(): Invalid arguments");
366 prec = argv[2].toInt32();
369 RETURN_RESULT(scope.engine->newString(r->toString(number, (
char)format, prec)));
372ReturnedValue
QQmlNumberExtension::method_toLocaleCurrencyString(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
376 THROW_ERROR(
"Locale: Number.toLocaleCurrencyString(): Invalid arguments");
378 double number = thisObject->toNumber();
383 RETURN_RESULT(scope.engine->newString(locale.toString(number)));
386 if (!isLocaleObject(argv[0]))
387 THROW_ERROR(
"Locale: Number.toLocaleCurrencyString(): Invalid arguments");
393 if (!argv[1].isString())
394 THROW_ERROR(
"Locale: Number.toLocaleString(): Invalid arguments");
395 symbol = argv[1].toQStringNoThrow();
398 RETURN_RESULT(scope.engine->newString(r->toCurrencyString(number, symbol)));
401ReturnedValue
QQmlNumberExtension::method_fromLocaleString(
const QV4::FunctionObject *b,
const QV4::Value *,
const QV4::Value *argv,
int argc)
404 if (argc < 1 || argc > 2)
405 THROW_ERROR(
"Locale: Number.fromLocaleString(): Invalid arguments");
411 if (!isLocaleObject(argv[0]))
412 THROW_ERROR(
"Locale: Number.fromLocaleString(): Invalid arguments");
420 QString ns = argv[numberIdx].toQString();
422 RETURN_RESULT(QV4::Encode(Q_QNAN));
425 double val = locale.toDouble(ns, &ok);
428 THROW_ERROR(
"Locale: Number.fromLocaleString(): Invalid format");
430 RETURN_RESULT(QV4::Encode(val));
438 QV4::Scope scope(args->v4engine());
439 const auto doThrow = [&](
const QString &message) {
440 args->setReturnValue(scope.engine->throwError(message));
443 const int argc = args->length();
445 if (argc < 1 || argc > 3) {
446 doThrow(QString::fromLatin1(
447 "Locale: formattedDataSize(): Expected 1-3 arguments, but received %1")
452 QV4::ScopedValue arg0(scope, (*args)[0]);
453 bool mismatched0 =
false;
454 if (!arg0->isNumber()) {
456 qWarning() <<
"Locale: formattedDataSize(): Invalid argument ('bytes' should be a number)";
458 args->setReturnValue(
459 scope.engine->newString(locale.formattedDataSize(qint64(arg0->toInteger())))
460 ->asReturnedValue());
470 QV4::ScopedValue arg1(scope, (*args)[1]);
471 if (!arg1->isInteger()) {
472 doThrow(QLatin1String(
473 "Locale: formattedDataSize(): Invalid argument ('precision' must be an int)"));
479 const QString result = locale.formattedDataSize(
480 qint64(arg0->toInteger()), arg1->integerValue());
481 args->setReturnValue(scope.engine->newString(result)->asReturnedValue());
485 QV4::ScopedValue arg2(scope, (*args)[2]);
486 if (arg2->isNumber()) {
487 const QString result = locale.formattedDataSize(
488 qint64(arg0->toInteger()), arg1->integerValue(),
489 QLocale::DataSizeFormats(arg2->integerValue()));
490 args->setReturnValue(scope.engine->newString(result)->asReturnedValue());
496 Q_ASSERT(!QV4::ScopedValue(scope, (*args)[2])->isNumber());
498 doThrow(QLatin1String(
499 "Locale: formattedDataSize(): Invalid argument ('format' must be DataSizeFormat)"));
504 return day == Qt::Sunday ? QQmlLocale::DayOfWeek::Sunday : QQmlLocale::DayOfWeek(day);
509 return qtDayToQmlDay(locale.firstDayOfWeek());
514 const QList<Qt::DayOfWeek> days = locale.weekdays();
515 QList<QQmlLocale::DayOfWeek> result;
516 result.reserve(days.size());
517 for (Qt::DayOfWeek day : days)
518 result.append(qtDayToQmlDay(day));
524 Scope scope(args->v4engine());
525 const auto doThrow = [&](
const QString &message) {
526 args->setReturnValue(scope.engine->throwError(message));
529 const int argc = args->length();
535 doThrow(QString::fromLatin1(
"Locale: toString(): Expected 1-3 arguments, but received %1")
540 QV4::ScopedValue arg0(scope, (*args)[0]);
541 if (arg0->isNumber()) {
547 QV4::ScopedValue arg1(scope, (*args)[1]);
548 if (!arg1->isString()) {
549 doThrow(QLatin1String(
"Locale: the second argument to the toString overload "
550 "whose first argument is a double should be a char"));
557 Q_ASSERT(!QV4::ScopedValue(scope, (*args)[2])->isInteger());
559 doThrow(QLatin1String(
"Locale: the third argument to the toString overload "
560 "whose first argument is a double should be an int"));
564 if (arg0->as<DateObject>()) {
566 doThrow(QString::fromLatin1(
567 "Locale: the toString() overload that takes a Date as its first "
568 "argument expects 1 or 2 arguments, but received %1").arg(argc));
574 QV4::ScopedValue arg1(scope, (*args)[1]);
577 Q_ASSERT(!arg1->isString());
580 Q_ASSERT(!arg1->isNumber());
582 doThrow(QLatin1String(
"Locale: the second argument to the toString overloads whose "
583 "first argument is a Date should be a string or FormatType"));
587 doThrow(QLatin1String(
"Locale: toString() expects either an int, double, "
588 "or Date as its first argument"));
592
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
683QV4::ReturnedValue QQmlLocale::locale(ExecutionEngine *engine,
const QString &localeName)
685 if (localeName.isEmpty()) {
686 return QQmlValueTypeWrapper::create(
687 engine,
nullptr, &QQmlLocaleValueType::staticMetaObject,
688 QMetaType::fromType<QLocale>());
691 QLocale qlocale(localeName);
692 return QQmlValueTypeWrapper::create(
693 engine, &qlocale, &QQmlLocaleValueType::staticMetaObject,
694 QMetaType::fromType<QLocale>());
697void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
699 engine->stringPrototype()->defineDefaultProperty(QStringLiteral(
"localeCompare"), method_localeCompare);
702ReturnedValue QQmlLocale::method_localeCompare(
const QV4::FunctionObject *b,
const QV4::Value *thisObject,
const QV4::Value *argv,
int argc)
704 if (argc != 1 || (!argv[0].isString() && !argv[0].as<StringObject>()))
705 return QV4::StringPrototype::method_localeCompare(b, thisObject, argv, argc);
707 if (!thisObject->isString() && !thisObject->as<StringObject>())
708 return QV4::StringPrototype::method_localeCompare(b, thisObject, argv, argc);
710 QString thisString = thisObject->toQStringNoThrow();
711 QString thatString = argv[0].toQStringNoThrow();
713 return QV4::Encode(QString::localeAwareCompare(thisString, thatString));
717
718
719
720
721
722
723
726
727
728
729
732
733
734
735
738
739
740
741
742
743
744
745
748
749
750
751
755
756
757
758
761
762
763
764
767
768
769
770
773
774
775
776
779
780
781
782
783
784
785
788
789
790
791
792
793
794
797
798
799
800
801
802
803
806
807
808
809
810
811
812
813
814
815
816
817
820
821
822
823
824
825
826
827
828
829
832
833
834
835
836
837
838
839
840
841
842
843
844
847
848
849
850
851
852
853
854
857
858
859
860
861
862
863
864
865
866
867
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
887
888
889
890
891
892
893
896
897
898
899
900
901
902
905
906
907
908
909
910
911
912
913
914
915
918
919
920
921
922
923
924
925
926
927
930
931
932
933
934
935
936
937
938
941
942
943
944
945
946
947
948
951
952
953
954
955
956
957
958
959
960
963
964
965
966
967
968
969
972
973
974
975
978
979
980
981
984
985
986
987
988
989
990
991
992
993
996
997
998
999
1000
1001
1002
1005
1006
1007
1008
1009
1010
1011
1012
1015
1016
1017
1018
1019
1020
1021
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1039#include "moc_qqmllocale_p.cpp"
QList< QQmlLocale::DayOfWeek > weekDays() const
#define GET_LOCALE_DATA_RESOURCE(OBJECT)
static bool isLocaleObject(const QV4::Value &val)
#define THROW_ERROR(string)
static QQmlLocale::DayOfWeek qtDayToQmlDay(Qt::DayOfWeek day)