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 QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
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 Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qqmllocale_p.h"
41#include "qqmlengine_p.h"
42#include <private/qqmlcontext_p.h>
43#include <QtCore/qnumeric.h>
44#include <QtCore/qdatetime.h>
45
46#include <private/qlocale_p.h>
47#include <private/qlocale_data_p.h>
48
49#include <private/qv4dateobject_p.h>
50#include <private/qv4numberobject_p.h>
51#include <private/qv4stringobject_p.h>
52
53QT_BEGIN_NAMESPACE
54
55using namespace QV4;
56
57DEFINE_OBJECT_VTABLE(QQmlLocaleData);
58
59#define THROW_ERROR(string) \
60 do { \
61 return scope.engine->throwError(QString::fromUtf8(string)); \
62 } while (false)
63
64
65#define GET_LOCALE_DATA_RESOURCE(OBJECT) \
66 QV4::Scoped<QQmlLocaleData> r(scope, OBJECT.as<QQmlLocaleData>()); \
67 if (!r) \
68 THROW_ERROR("Not a valid Locale object")
69
70static bool isLocaleObject(const QV4::Value &val)
71{
72 return val.as<QQmlLocaleData>();
73}
74
75//--------------
76// Date extension
77
78void QQmlDateExtension::registerExtension(QV4::ExecutionEngine *engine)
79{
80 engine->datePrototype()->defineDefaultProperty(name: engine->id_toLocaleString(), code: method_toLocaleString);
81 engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), code: method_toLocaleTimeString);
82 engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), code: method_toLocaleDateString);
83 engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), code: method_fromLocaleString);
84 engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), code: method_fromLocaleTimeString);
85 engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), code: method_fromLocaleDateString);
86 engine->dateCtor()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), code: method_timeZoneUpdated);
87}
88
89ReturnedValue QQmlDateExtension::method_toLocaleString(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
90{
91 Scope scope(b);
92 if (argc > 2)
93 return QV4::DatePrototype::method_toLocaleString(b, thisObject, argv, argc);
94
95 const QV4::DateObject *date = thisObject->as<DateObject>();
96 if (!date)
97 return QV4::DatePrototype::method_toLocaleString(b, thisObject, argv, argc);
98
99 QDateTime dt = date->toQDateTime();
100
101 if (argc == 0) {
102 // Use QLocale for standard toLocaleString() function
103 QLocale locale;
104 RETURN_RESULT(scope.engine->newString(locale.toString(dt)));
105 }
106
107 if (!isLocaleObject(val: argv[0]))
108 return QV4::DatePrototype::method_toLocaleString(b, thisObject, argv, argc); // Use the default Date toLocaleString()
109
110 GET_LOCALE_DATA_RESOURCE(argv[0]);
111
112 QLocale::FormatType enumFormat = QLocale::LongFormat;
113 QString formattedDt;
114 if (argc == 2) {
115 if (String *s = argv[1].stringValue()) {
116 QString format = s->toQString();
117 formattedDt = r->d()->locale->toString(dateTime: dt, format);
118 } else if (argv[1].isNumber()) {
119 quint32 intFormat = argv[1].toNumber();
120 QLocale::FormatType format = QLocale::FormatType(intFormat);
121 formattedDt = r->d()->locale->toString(dateTime: dt, format);
122 } else {
123 THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
124 }
125 } else {
126 formattedDt = r->d()->locale->toString(dateTime: dt, format: enumFormat);
127 }
128
129 RETURN_RESULT(scope.engine->newString(formattedDt));
130}
131
132ReturnedValue QQmlDateExtension::method_toLocaleTimeString(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
133{
134 Scope scope(b);
135 if (argc > 2)
136 return QV4::DatePrototype::method_toLocaleTimeString(b, thisObject, argv, argc);
137
138 const QV4::DateObject *date = thisObject->as<DateObject>();
139 if (!date)
140 return QV4::DatePrototype::method_toLocaleTimeString(b, thisObject, argv, argc);
141
142 QDateTime dt = date->toQDateTime();
143 QTime time = dt.time();
144
145 if (argc == 0) {
146 // Use QLocale for standard toLocaleString() function
147 QLocale locale;
148 RETURN_RESULT(scope.engine->newString(locale.toString(time)));
149 }
150
151 if (!isLocaleObject(val: argv[0]))
152 return QV4::DatePrototype::method_toLocaleTimeString(b, thisObject, argv, argc); // Use the default Date toLocaleTimeString()
153
154 GET_LOCALE_DATA_RESOURCE(argv[0]);
155
156 QLocale::FormatType enumFormat = QLocale::LongFormat;
157 QString formattedTime;
158 if (argc == 2) {
159 if (String *s = argv[1].stringValue()) {
160 QString format = s->toQString();
161 formattedTime = r->d()->locale->toString(time, formatStr: format);
162 } else if (argv[1].isNumber()) {
163 quint32 intFormat = argv[1].toNumber();
164 QLocale::FormatType format = QLocale::FormatType(intFormat);
165 formattedTime = r->d()->locale->toString(time, format);
166 } else {
167 THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format");
168 }
169 } else {
170 formattedTime = r->d()->locale->toString(time, format: enumFormat);
171 }
172
173 RETURN_RESULT(scope.engine->newString(formattedTime));
174}
175
176ReturnedValue QQmlDateExtension::method_toLocaleDateString(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
177{
178 Scope scope(b);
179 if (argc > 2)
180 return QV4::DatePrototype::method_toLocaleDateString(b, thisObject, argv, argc);
181
182 const QV4::DateObject *dateObj = thisObject->as<DateObject>();
183 if (!dateObj)
184 return QV4::DatePrototype::method_toLocaleDateString(b, thisObject, argv, argc);
185
186 QDateTime dt = dateObj->toQDateTime();
187 QDate date = dt.date();
188
189 if (argc == 0) {
190 // Use QLocale for standard toLocaleString() function
191 QLocale locale;
192 RETURN_RESULT(scope.engine->newString(locale.toString(date)));
193 }
194
195 if (!isLocaleObject(val: argv[0]))
196 return QV4::DatePrototype::method_toLocaleDateString(b, thisObject, argv, argc); // Use the default Date toLocaleDateString()
197
198 GET_LOCALE_DATA_RESOURCE(argv[0]);
199
200 QLocale::FormatType enumFormat = QLocale::LongFormat;
201 QString formattedDate;
202 if (argc == 2) {
203 if (String *s = argv[1].stringValue()) {
204 QString format = s->toQString();
205 formattedDate = r->d()->locale->toString(date, formatStr: format);
206 } else if (argv[1].isNumber()) {
207 quint32 intFormat = argv[1].toNumber();
208 QLocale::FormatType format = QLocale::FormatType(intFormat);
209 formattedDate = r->d()->locale->toString(date, format);
210 } else {
211 THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format");
212 }
213 } else {
214 formattedDate = r->d()->locale->toString(date, format: enumFormat);
215 }
216
217 RETURN_RESULT(scope.engine->newString(formattedDate));
218}
219
220ReturnedValue QQmlDateExtension::method_fromLocaleString(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
221{
222 QV4::Scope scope(b);
223 QV4::ExecutionEngine * const engine = scope.engine;
224 if (argc == 1) {
225 if (String *s = argv[0].stringValue()) {
226 QLocale locale;
227 QString dateString = s->toQString();
228 QDateTime dt = locale.toDateTime(string: dateString);
229 RETURN_RESULT(engine->newDateObject(dt));
230 }
231 }
232
233 if (argc < 1 || argc > 3 || !isLocaleObject(val: argv[0]))
234 THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments");
235
236 GET_LOCALE_DATA_RESOURCE(argv[0]);
237
238 QLocale::FormatType enumFormat = QLocale::LongFormat;
239 QDateTime dt;
240 QString dateString = argv[1].toQStringNoThrow();
241 if (argc == 3) {
242 if (String *s = argv[2].stringValue()) {
243 QString format = s->toQString();
244 dt = r->d()->locale->toDateTime(string: dateString, format);
245 } else if (argv[2].isNumber()) {
246 quint32 intFormat = argv[2].toNumber();
247 QLocale::FormatType format = QLocale::FormatType(intFormat);
248 dt = r->d()->locale->toDateTime(string: dateString, format);
249 } else {
250 THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
251 }
252 } else {
253 dt = r->d()->locale->toDateTime(string: dateString, format: enumFormat);
254 }
255
256 RETURN_RESULT(engine->newDateObject(dt));
257}
258
259ReturnedValue QQmlDateExtension::method_fromLocaleTimeString(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
260{
261 QV4::Scope scope(b);
262 QV4::ExecutionEngine * const engine = scope.engine;
263
264 if (argc == 1) {
265 if (String *s = argv[0].stringValue()) {
266 QLocale locale;
267 QString timeString = s->toQString();
268 QTime time = locale.toTime(string: timeString);
269 QDateTime dt = QDateTime::currentDateTime();
270 dt.setTime(time);
271 RETURN_RESULT(engine->newDateObject(dt));
272 }
273 }
274
275 if (argc < 1 || argc > 3 || !isLocaleObject(val: argv[0]))
276 THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments");
277
278 GET_LOCALE_DATA_RESOURCE(argv[0]);
279
280 QLocale::FormatType enumFormat = QLocale::LongFormat;
281 QTime tm;
282 QString dateString = argv[1].toQStringNoThrow();
283 if (argc == 3) {
284 if (String *s = argv[2].stringValue()) {
285 QString format = s->toQString();
286 tm = r->d()->locale->toTime(string: dateString, format);
287 } else if (argv[2].isNumber()) {
288 quint32 intFormat = argv[2].toNumber();
289 QLocale::FormatType format = QLocale::FormatType(intFormat);
290 tm = r->d()->locale->toTime(string: dateString, format);
291 } else {
292 THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
293 }
294 } else {
295 tm = r->d()->locale->toTime(string: dateString, enumFormat);
296 }
297
298 QDateTime dt;
299 if (tm.isValid()) {
300 dt = QDateTime::currentDateTime();
301 dt.setTime(tm);
302 }
303
304 RETURN_RESULT(engine->newDateObject(dt));
305}
306
307ReturnedValue QQmlDateExtension::method_fromLocaleDateString(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
308{
309 QV4::Scope scope(b);
310 QV4::ExecutionEngine * const engine = scope.engine;
311
312 if (argc == 1) {
313 if (String *s = argv[0].stringValue()) {
314 QLocale locale;
315 QString dateString = s->toQString();
316 QDate date = locale.toDate(string: dateString);
317 RETURN_RESULT(engine->newDateObject(date.startOfDay()));
318 }
319 }
320
321 if (argc < 1 || argc > 3 || !isLocaleObject(val: argv[0]))
322 THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments");
323
324 GET_LOCALE_DATA_RESOURCE(argv[0]);
325
326 QLocale::FormatType enumFormat = QLocale::LongFormat;
327 QDate dt;
328 QString dateString = argv[1].toQStringNoThrow();
329 if (argc == 3) {
330 if (String *s = argv[2].stringValue()) {
331 QString format = s->toQString();
332 dt = r->d()->locale->toDate(string: dateString, format);
333 } else if (argv[2].isNumber()) {
334 quint32 intFormat = argv[2].toNumber();
335 QLocale::FormatType format = QLocale::FormatType(intFormat);
336 dt = r->d()->locale->toDate(string: dateString, format);
337 } else {
338 THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
339 }
340 } else {
341 dt = r->d()->locale->toDate(string: dateString, enumFormat);
342 }
343
344 RETURN_RESULT(engine->newDateObject(dt.startOfDay()));
345}
346
347ReturnedValue QQmlDateExtension::method_timeZoneUpdated(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *, int argc)
348{
349 QV4::Scope scope(b);
350 if (argc != 0)
351 THROW_ERROR("Locale: Date.timeZoneUpdated(): Invalid arguments");
352
353 QV4::DatePrototype::timezoneUpdated(e: scope.engine);
354
355 RETURN_UNDEFINED();
356}
357
358//-----------------
359// Number extension
360
361void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine)
362{
363 engine->numberPrototype()->defineDefaultProperty(name: engine->id_toLocaleString(), code: method_toLocaleString);
364 engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), code: method_toLocaleCurrencyString);
365 engine->numberCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), code: method_fromLocaleString);
366}
367
368QV4::ReturnedValue QQmlNumberExtension::method_toLocaleString(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
369{
370 QV4::Scope scope(b);
371 if (argc > 3)
372 THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
373
374 double number = thisObject->toNumber();
375
376 if (argc == 0) {
377 // Use QLocale for standard toLocaleString() function
378 QLocale locale;
379 RETURN_RESULT(scope.engine->newString(locale.toString(number)));
380 }
381
382 if (!isLocaleObject(val: argv[0]))
383 return QV4::NumberPrototype::method_toLocaleString(b, thisObject, argv, argc); // Use the default Number toLocaleString()
384
385 GET_LOCALE_DATA_RESOURCE(argv[0]);
386
387 quint16 format = 'f';
388 if (argc > 1) {
389 if (!argv[1].isString())
390 THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
391 QString fs = argv[1].toQString();
392 if (fs.length())
393 format = fs.at(i: 0).unicode();
394 }
395 int prec = 2;
396 if (argc > 2) {
397 if (!argv[2].isNumber())
398 THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
399 prec = argv[2].toInt32();
400 }
401
402 RETURN_RESULT(scope.engine->newString(r->d()->locale->toString(number, (char)format, prec)));
403}
404
405ReturnedValue QQmlNumberExtension::method_toLocaleCurrencyString(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
406{
407 QV4::Scope scope(b);
408 if (argc > 2)
409 THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
410
411 double number = thisObject->toNumber();
412
413 if (argc == 0) {
414 // Use QLocale for standard toLocaleString() function
415 QLocale locale;
416 RETURN_RESULT(scope.engine->newString(locale.toString(number)));
417 }
418
419 if (!isLocaleObject(val: argv[0]))
420 THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
421
422 GET_LOCALE_DATA_RESOURCE(argv[0]);
423
424 QString symbol;
425 if (argc > 1) {
426 if (!argv[1].isString())
427 THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
428 symbol = argv[1].toQStringNoThrow();
429 }
430
431 RETURN_RESULT(scope.engine->newString(r->d()->locale->toCurrencyString(number, symbol)));
432}
433
434ReturnedValue QQmlNumberExtension::method_fromLocaleString(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
435{
436 QV4::Scope scope(b);
437 if (argc < 1 || argc > 2)
438 THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
439
440 int numberIdx = 0;
441 QLocale locale;
442
443 if (argc == 2) {
444 if (!isLocaleObject(val: argv[0]))
445 THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
446
447 GET_LOCALE_DATA_RESOURCE(argv[0]);
448 locale = *r->d()->locale;
449
450 numberIdx = 1;
451 }
452
453 QString ns = argv[numberIdx].toQString();
454 if (!ns.length())
455 RETURN_RESULT(QV4::Encode(Q_QNAN));
456
457 bool ok = false;
458 double val = locale.toDouble(s: ns, ok: &ok);
459
460 if (!ok)
461 THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format");
462
463 RETURN_RESULT(QV4::Encode(val));
464}
465
466//--------------
467// Locale object
468
469ReturnedValue QQmlLocaleData::method_get_firstDayOfWeek(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
470{
471 QV4::Scope scope(b);
472 const QLocale *locale = getThisLocale(scope, thisObject);
473 if (!locale)
474 return Encode::undefined();
475 int fdow = int(locale->firstDayOfWeek());
476 if (fdow == 7)
477 fdow = 0; // Qt::Sunday = 7, but Sunday is 0 in JS Date
478 RETURN_RESULT(fdow);
479}
480
481ReturnedValue QQmlLocaleData::method_get_numberOptions(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) {
482 QV4::Scope scope(b);
483 const QLocale *locale = getThisLocale(scope, thisObject);
484 if (!locale)
485 return Encode::undefined();
486 int numberOptions = int(locale->numberOptions());
487 RETURN_RESULT(numberOptions);
488}
489
490ReturnedValue QQmlLocaleData::method_set_numberOptions(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc) {
491 QV4::Scope scope(b);
492 QLocale *locale = getThisLocale(scope, thisObject);
493 int const numberOptions = argc ? int(argv[0].toNumber()) : QLocale::DefaultNumberOptions;
494 locale->setNumberOptions(QLocale::NumberOptions {numberOptions});
495 return Encode::undefined();
496}
497
498ReturnedValue QQmlLocaleData::method_get_measurementSystem(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
499{
500 QV4::Scope scope(b);
501 const QLocale *locale = getThisLocale(scope, thisObject);
502 if (!locale)
503 return Encode::undefined();
504 return QV4::Encode(locale->measurementSystem());
505}
506
507ReturnedValue QQmlLocaleData::method_get_textDirection(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
508{
509 QV4::Scope scope(b);
510 const QLocale *locale = getThisLocale(scope, thisObject);
511 if (!locale)
512 return Encode::undefined();
513
514 return QV4::Encode(locale->textDirection());
515}
516
517ReturnedValue QQmlLocaleData::method_get_weekDays(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
518{
519 QV4::Scope scope(b);
520 const QLocale *locale = getThisLocale(scope, thisObject);
521 if (!locale)
522 return Encode::undefined();
523
524 QList<Qt::DayOfWeek> days = locale->weekdays();
525
526 QV4::ScopedArrayObject result(scope, scope.engine->newArrayObject());
527 result->arrayReserve(n: days.size());
528 for (int i = 0; i < days.size(); ++i) {
529 int day = days.at(i);
530 if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
531 day = 0;
532 result->arrayPut(index: i, value: QV4::Value::fromInt32(i: day));
533 }
534 result->setArrayLengthUnchecked(days.size());
535
536 return result.asReturnedValue();
537}
538
539ReturnedValue QQmlLocaleData::method_get_uiLanguages(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
540{
541 QV4::Scope scope(b);
542 const QLocale *locale = getThisLocale(scope, thisObject);
543 if (!locale)
544 return Encode::undefined();
545
546 QStringList langs = locale->uiLanguages();
547 QV4::ScopedArrayObject result(scope, scope.engine->newArrayObject());
548 result->arrayReserve(n: langs.size());
549 QV4::ScopedValue v(scope);
550 for (int i = 0; i < langs.size(); ++i)
551 result->arrayPut(index: i, value: (v = scope.engine->newString(s: langs.at(i))));
552
553 result->setArrayLengthUnchecked(langs.size());
554
555 return result.asReturnedValue();
556}
557
558ReturnedValue QQmlLocaleData::method_currencySymbol(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
559{
560 QV4::Scope scope(b);
561 const QLocale *locale = getThisLocale(scope, thisObject);
562 if (!locale)
563 return Encode::undefined();
564
565 if (argc > 1)
566 THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
567
568 QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
569 if (argc == 1) {
570 quint32 intFormat = argv[0].toNumber();
571 format = QLocale::CurrencySymbolFormat(intFormat);
572 }
573
574 RETURN_RESULT(scope.engine->newString(locale->currencySymbol(format)));
575}
576
577#define LOCALE_FORMAT(FUNC) \
578ReturnedValue QQmlLocaleData::method_ ##FUNC (const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc) { \
579 QV4::Scope scope(b); \
580 const QLocale *locale = getThisLocale(scope, thisObject); \
581 if (!locale) \
582 return Encode::undefined(); \
583 if (argc > 1) \
584 THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \
585 QLocale::FormatType format = QLocale::LongFormat;\
586 if (argc == 1) { \
587 quint32 intFormat = argv[0].toUInt32(); \
588 format = QLocale::FormatType(intFormat); \
589 } \
590 RETURN_RESULT(scope.engine->newString(locale-> FUNC (format))); \
591}
592
593LOCALE_FORMAT(dateTimeFormat)
594LOCALE_FORMAT(timeFormat)
595LOCALE_FORMAT(dateFormat)
596
597// +1 added to idx because JS is 0-based, whereas QLocale months begin at 1.
598#define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \
599ReturnedValue QQmlLocaleData::method_ ## VARIABLE (const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc) {\
600 Scope scope(b); \
601 const QLocale *locale = getThisLocale(scope, thisObject); \
602 if (!locale) \
603 return Encode::undefined(); \
604 if (argc < 1 || argc > 2) \
605 THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
606 QLocale::FormatType enumFormat = QLocale::LongFormat; \
607 int idx = argv[0].toInt32() + 1; \
608 if (idx < 1 || idx > 12) \
609 THROW_ERROR("Locale: Invalid month"); \
610 QString name; \
611 if (argc == 2) { \
612 if (argv[1].isNumber()) { \
613 quint32 intFormat = argv[1].toUInt32(); \
614 QLocale::FormatType format = QLocale::FormatType(intFormat); \
615 name = locale-> VARIABLE(idx, format); \
616 } else { \
617 THROW_ERROR("Locale: Invalid datetime format"); \
618 } \
619 } else { \
620 name = locale-> VARIABLE(idx, enumFormat); \
621 } \
622 RETURN_RESULT(scope.engine->newString(name)); \
623}
624
625// 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date
626#define LOCALE_FORMATTED_DAYNAME(VARIABLE) \
627ReturnedValue QQmlLocaleData::method_ ## VARIABLE (const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc) {\
628 Scope scope(b); \
629 const QLocale *locale = getThisLocale(scope, thisObject); \
630 if (!locale) \
631 return Encode::undefined(); \
632 if (argc < 1 || argc > 2) \
633 THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
634 QLocale::FormatType enumFormat = QLocale::LongFormat; \
635 int idx = argv[0].toInt32(); \
636 if (idx < 0 || idx > 7) \
637 THROW_ERROR("Locale: Invalid day"); \
638 if (idx == 0) idx = 7; \
639 QString name; \
640 if (argc == 2) { \
641 if (argv[1].isNumber()) { \
642 quint32 intFormat = argv[1].toUInt32(); \
643 QLocale::FormatType format = QLocale::FormatType(intFormat); \
644 name = locale-> VARIABLE(idx, format); \
645 } else { \
646 THROW_ERROR("Locale: Invalid datetime format"); \
647 } \
648 } else { \
649 name = locale-> VARIABLE(idx, enumFormat); \
650 } \
651 RETURN_RESULT(scope.engine->newString(name)); \
652}
653
654LOCALE_FORMATTED_MONTHNAME(monthName)
655LOCALE_FORMATTED_MONTHNAME(standaloneMonthName)
656LOCALE_FORMATTED_DAYNAME(dayName)
657LOCALE_FORMATTED_DAYNAME(standaloneDayName)
658
659#define LOCALE_STRING_PROPERTY(VARIABLE) \
660ReturnedValue QQmlLocaleData::method_get_ ## VARIABLE (const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) \
661{ \
662 Scope scope(b); \
663 const QLocale *locale = getThisLocale(scope, thisObject); \
664 if (!locale) \
665 return Encode::undefined(); \
666 RETURN_RESULT(scope.engine->newString(locale-> VARIABLE()));\
667}
668
669LOCALE_STRING_PROPERTY(name)
670LOCALE_STRING_PROPERTY(nativeLanguageName)
671LOCALE_STRING_PROPERTY(nativeCountryName)
672LOCALE_STRING_PROPERTY(decimalPoint)
673LOCALE_STRING_PROPERTY(groupSeparator)
674LOCALE_STRING_PROPERTY(percent)
675LOCALE_STRING_PROPERTY(zeroDigit)
676LOCALE_STRING_PROPERTY(negativeSign)
677LOCALE_STRING_PROPERTY(positiveSign)
678LOCALE_STRING_PROPERTY(exponential)
679LOCALE_STRING_PROPERTY(amText)
680LOCALE_STRING_PROPERTY(pmText)
681
682class QV4LocaleDataDeletable : public QV4::ExecutionEngine::Deletable
683{
684public:
685 QV4LocaleDataDeletable(QV4::ExecutionEngine *engine);
686 ~QV4LocaleDataDeletable();
687
688 QV4::PersistentValue prototype;
689};
690
691QV4LocaleDataDeletable::QV4LocaleDataDeletable(QV4::ExecutionEngine *engine)
692{
693 QV4::Scope scope(engine);
694 QV4::Scoped<QV4::Object> o(scope, engine->newObject());
695
696 o->defineDefaultProperty(QStringLiteral("dateFormat"), code: QQmlLocaleData::method_dateFormat, argumentCount: 0);
697 o->defineDefaultProperty(QStringLiteral("standaloneDayName"), code: QQmlLocaleData::method_standaloneDayName, argumentCount: 0);
698 o->defineDefaultProperty(QStringLiteral("standaloneMonthName"), code: QQmlLocaleData::method_standaloneMonthName, argumentCount: 0);
699 o->defineDefaultProperty(QStringLiteral("dayName"), code: QQmlLocaleData::method_dayName, argumentCount: 0);
700 o->defineDefaultProperty(QStringLiteral("timeFormat"), code: QQmlLocaleData::method_timeFormat, argumentCount: 0);
701 o->defineDefaultProperty(QStringLiteral("monthName"), code: QQmlLocaleData::method_monthName, argumentCount: 0);
702 o->defineDefaultProperty(QStringLiteral("currencySymbol"), code: QQmlLocaleData::method_currencySymbol, argumentCount: 0);
703 o->defineDefaultProperty(QStringLiteral("dateTimeFormat"), code: QQmlLocaleData::method_dateTimeFormat, argumentCount: 0);
704 o->defineAccessorProperty(QStringLiteral("name"), getter: QQmlLocaleData::method_get_name, setter: nullptr);
705 o->defineAccessorProperty(QStringLiteral("positiveSign"), getter: QQmlLocaleData::method_get_positiveSign, setter: nullptr);
706 o->defineAccessorProperty(QStringLiteral("uiLanguages"), getter: QQmlLocaleData::method_get_uiLanguages, setter: nullptr);
707 o->defineAccessorProperty(QStringLiteral("firstDayOfWeek"), getter: QQmlLocaleData::method_get_firstDayOfWeek, setter: nullptr);
708 o->defineAccessorProperty(QStringLiteral("pmText"), getter: QQmlLocaleData::method_get_pmText, setter: nullptr);
709 o->defineAccessorProperty(QStringLiteral("percent"), getter: QQmlLocaleData::method_get_percent, setter: nullptr);
710 o->defineAccessorProperty(QStringLiteral("textDirection"), getter: QQmlLocaleData::method_get_textDirection, setter: nullptr);
711 o->defineAccessorProperty(QStringLiteral("weekDays"), getter: QQmlLocaleData::method_get_weekDays, setter: nullptr);
712 o->defineAccessorProperty(QStringLiteral("negativeSign"), getter: QQmlLocaleData::method_get_negativeSign, setter: nullptr);
713 o->defineAccessorProperty(QStringLiteral("groupSeparator"), getter: QQmlLocaleData::method_get_groupSeparator, setter: nullptr);
714 o->defineAccessorProperty(QStringLiteral("decimalPoint"), getter: QQmlLocaleData::method_get_decimalPoint, setter: nullptr);
715 o->defineAccessorProperty(QStringLiteral("nativeLanguageName"), getter: QQmlLocaleData::method_get_nativeLanguageName, setter: nullptr);
716 o->defineAccessorProperty(QStringLiteral("nativeCountryName"), getter: QQmlLocaleData::method_get_nativeCountryName, setter: nullptr);
717 o->defineAccessorProperty(QStringLiteral("zeroDigit"), getter: QQmlLocaleData::method_get_zeroDigit, setter: nullptr);
718 o->defineAccessorProperty(QStringLiteral("amText"), getter: QQmlLocaleData::method_get_amText, setter: nullptr);
719 o->defineAccessorProperty(QStringLiteral("measurementSystem"), getter: QQmlLocaleData::method_get_measurementSystem, setter: nullptr);
720 o->defineAccessorProperty(QStringLiteral("exponential"), getter: QQmlLocaleData::method_get_exponential, setter: nullptr);
721 o->defineAccessorProperty(QStringLiteral("numberOptions"), getter: QQmlLocaleData::method_get_numberOptions, setter: QQmlLocaleData::method_set_numberOptions);
722
723 prototype.set(engine, value: o);
724}
725
726QV4LocaleDataDeletable::~QV4LocaleDataDeletable()
727{
728}
729
730V4_DEFINE_EXTENSION(QV4LocaleDataDeletable, localeV4Data);
731
732/*!
733 \qmltype Locale
734 \instantiates QQmlLocale
735 \inqmlmodule QtQml
736 \brief Provides locale specific properties and formatted data.
737
738 The Locale object may only be created via the \l{QtQml::Qt::locale()}{Qt.locale()} function.
739 It cannot be created directly.
740
741 The \l{QtQml::Qt::locale()}{Qt.locale()} function returns a JS Locale object representing the
742 locale with the specified name, which has the format
743 "language[_territory][.codeset][@modifier]" or "C".
744
745 Locale supports the concept of a default locale, which is
746 determined from the system's locale settings at application
747 startup. If no parameter is passed to Qt.locale() the default
748 locale object is returned.
749
750 The Locale object provides a number of functions and properties
751 providing data for the specified locale.
752
753 The Locale object may also be passed to the \l Date and \l Number toLocaleString()
754 and fromLocaleString() methods in order to convert to/from strings using
755 the specified locale.
756
757 This example shows the current date formatted for the German locale:
758
759 \code
760 import QtQuick 2.0
761
762 Text {
763 text: "The date is: " + Date().toLocaleString(Qt.locale("de_DE"))
764 }
765 \endcode
766
767 The following example displays the specified number
768 in the correct format for the default locale:
769
770 \code
771 import QtQuick 2.0
772
773 Text {
774 text: "The value is: " + Number(23443.34).toLocaleString(Qt.locale())
775 }
776 \endcode
777
778 Qt Quick Locale's data is based on Common Locale Data Repository v1.8.1.
779
780
781 \target FormatType
782 \section2 Locale String Format Types
783
784 The monthName(), standaloneMonthName(), dayName() and standaloneDayName()
785 can use the following enumeration values to specify the formatting of
786 the string representation for a Date object.
787
788 \list
789 \li Locale.LongFormat The long version of day and month names; for
790 example, returning "January" as a month name.
791 \li Locale.ShortFormat The short version of day and month names; for
792 example, returning "Jan" as a month name.
793 \li Locale.NarrowFormat A special version of day and month names for
794 use when space is limited; for example, returning "J" as a month
795 name. Note that the narrow format might contain the same text for
796 different months and days or it can even be an empty string if the
797 locale doesn't support narrow names, so you should avoid using it
798 for date formatting. Also, for the system locale this format is
799 the same as ShortFormat.
800 \endlist
801
802
803 Additionally the double-to-string and string-to-double conversion functions are
804 covered by the following licenses:
805
806 \legalese
807 Copyright (c) 1991 by AT&T.
808
809 Permission to use, copy, modify, and distribute this software for any
810 purpose without fee is hereby granted, provided that this entire notice
811 is included in all copies of any software which is or includes a copy
812 or modification of this software and in all copies of the supporting
813 documentation for such software.
814
815 THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
816 WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
817 REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
818 OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
819
820 This product includes software developed by the University of
821 California, Berkeley and its contributors.
822
823 \sa Date, Number
824*/
825
826QQmlLocale::QQmlLocale()
827{
828}
829
830QQmlLocale::~QQmlLocale()
831{
832}
833
834QV4::ReturnedValue QQmlLocale::locale(ExecutionEngine *engine, const QString &localeName)
835{
836 QLocale qlocale;
837 if (!localeName.isEmpty())
838 qlocale = localeName;
839 return wrap(engine, locale: qlocale);
840}
841
842QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
843{
844 QV4::Scope scope(v4);
845 QV4LocaleDataDeletable *d = localeV4Data(engine: scope.engine);
846 QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocate<QQmlLocaleData>());
847 *wrapper->d()->locale = locale;
848 QV4::ScopedObject p(scope, d->prototype.value());
849 wrapper->setPrototypeOf(p);
850 return wrapper.asReturnedValue();
851}
852
853void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
854{
855 engine->stringPrototype()->defineDefaultProperty(QStringLiteral("localeCompare"), code: method_localeCompare);
856}
857
858ReturnedValue QQmlLocale::method_localeCompare(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
859{
860 if (argc != 1 || (!argv[0].isString() && !argv[0].as<StringObject>()))
861 return QV4::StringPrototype::method_localeCompare(b, thisObject, argv, argc);
862
863 if (!thisObject->isString() && !thisObject->as<StringObject>())
864 return QV4::StringPrototype::method_localeCompare(b, thisObject, argv, argc);
865
866 QString thisString = thisObject->toQStringNoThrow();
867 QString thatString = argv[0].toQStringNoThrow();
868
869 return QV4::Encode(QString::localeAwareCompare(s1: thisString, s2: thatString));
870}
871
872/*!
873 \qmlproperty string QtQml::Locale::name
874
875 Holds the language and country of this locale as a
876 string of the form "language_country", where
877 language is a lowercase, two-letter ISO 639 language code,
878 and country is an uppercase, two- or three-letter ISO 3166 country code.
879*/
880
881/*!
882 \qmlproperty string QtQml::Locale::decimalPoint
883
884 Holds the decimal point character of this locale.
885*/
886
887/*!
888 \qmlproperty string QtQml::Locale::groupSeparator
889
890 Holds the group separator character of this locale.
891*/
892
893/*!
894 \qmlproperty enumeration QtQml::Locale::numberOptions
895
896 Holds a set of options for number-to-string and
897 string-to-number conversions.
898
899 \sa Number::toLocaleString()
900 \sa Number::fromLocaleString()
901*/
902
903/*!
904 \qmlproperty string QtQml::Locale::percent
905
906 Holds the percent character of this locale.
907*/
908
909
910/*!
911 \qmlproperty string QtQml::Locale::zeroDigit
912
913 Holds Returns the zero digit character of this locale.
914*/
915
916/*!
917 \qmlproperty string QtQml::Locale::negativeSign
918
919 Holds the negative sign character of this locale.
920*/
921
922/*!
923 \qmlproperty string QtQml::Locale::positiveSign
924
925 Holds the positive sign character of this locale.
926*/
927
928/*!
929 \qmlproperty string QtQml::Locale::exponential
930
931 Holds the exponential character of this locale.
932*/
933
934/*!
935 \qmlmethod string QtQml::Locale::dateTimeFormat(type)
936
937 Returns the date time format used for the current locale.
938 \a type specifies the FormatType to return.
939
940 \sa Date
941*/
942
943/*!
944 \qmlmethod string QtQml::Locale::dateFormat(type)
945
946 Returns the date format used for the current locale.
947 \a type specifies the FormatType to return.
948
949 \sa Date
950*/
951
952/*!
953 \qmlmethod string QtQml::Locale::timeFormat(type)
954
955 Returns the time format used for the current locale.
956 \a type specifies the FormatType to return.
957
958 \sa Date
959*/
960
961/*!
962 \qmlmethod string QtQml::Locale::monthName(month, type)
963
964 Returns the localized name of \a month (0-11), in the optional
965 \l FormatType specified by \a type.
966
967 \note the QLocale C++ API expects a range of (1-12), however Locale.monthName()
968 expects 0-11 as per the JS Date object.
969
970 \sa dayName(), standaloneMonthName()
971*/
972
973/*!
974 \qmlmethod string QtQml::Locale::standaloneMonthName(month, type)
975
976 Returns the localized name of \a month (0-11) that is used as a
977 standalone text, in the optional \l FormatType specified by \a type.
978
979 If the locale information doesn't specify the standalone month
980 name then return value is the same as in monthName().
981
982 \note the QLocale C++ API expects a range of (1-12), however Locale.standaloneMonthName()
983 expects 0-11 as per the JS Date object.
984
985 \sa monthName(), standaloneDayName()
986*/
987
988/*!
989 \qmlmethod string QtQml::Locale::dayName(day, type)
990
991 Returns the localized name of the \a day (where 0 represents
992 Sunday, 1 represents Monday and so on), in the optional
993 \l FormatType specified by \a type.
994
995 \sa monthName(), standaloneDayName()
996*/
997
998/*!
999 \qmlmethod string QtQml::Locale::standaloneDayName(day, type)
1000
1001 Returns the localized name of the \a day (where 0 represents
1002 Sunday, 1 represents Monday and so on) that is used as a
1003 standalone text, in the \l FormatType specified by \a type.
1004
1005 If the locale information does not specify the standalone day
1006 name then return value is the same as in dayName().
1007
1008 \sa dayName(), standaloneMonthName()
1009*/
1010
1011/*!
1012 \qmlproperty enumeration QtQml::Locale::firstDayOfWeek
1013
1014 Holds the first day of the week according to the current locale.
1015
1016 \list
1017 \li Locale.Sunday = 0
1018 \li Locale.Monday = 1
1019 \li Locale.Tuesday = 2
1020 \li Locale.Wednesday = 3
1021 \li Locale.Thursday = 4
1022 \li Locale.Friday = 5
1023 \li Locale.Saturday = 6
1024 \endlist
1025
1026 \note that these values match the JS Date API which is different
1027 from the Qt C++ API where Qt::Sunday = 7.
1028*/
1029
1030/*!
1031 \qmlproperty Array<int> QtQml::Locale::weekDays
1032
1033 Holds an array of days that are considered week days according to the current locale,
1034 where Sunday is 0 and Saturday is 6.
1035
1036 \sa firstDayOfWeek
1037*/
1038
1039/*!
1040 \qmlproperty Array<string> QtQml::Locale::uiLanguages
1041
1042 Returns an ordered list of locale names for translation purposes in
1043 preference order.
1044
1045 The return value represents locale names that the user expects to see the
1046 UI translation in.
1047
1048 The first item in the list is the most preferred one.
1049*/
1050
1051/*!
1052 \qmlproperty enumeration QtQml::Locale::textDirection
1053
1054 Holds the text direction of the language:
1055 \list
1056 \li Qt.LeftToRight
1057 \li Qt.RightToLeft
1058 \endlist
1059*/
1060
1061/*!
1062 \qmlproperty string QtQml::Locale::amText
1063
1064 The localized name of the "AM" suffix for times specified using the conventions of the 12-hour clock.
1065*/
1066
1067/*!
1068 \qmlproperty string QtQml::Locale::pmText
1069
1070 The localized name of the "PM" suffix for times specified using the conventions of the 12-hour clock.
1071*/
1072
1073/*!
1074 \qmlmethod string QtQml::Locale::currencySymbol(format)
1075
1076 Returns the currency symbol for the specified \a format:
1077 \list
1078 \li Locale.CurrencyIsoCode a ISO-4217 code of the currency.
1079 \li Locale.CurrencySymbol a currency symbol.
1080 \li Locale.CurrencyDisplayName a user readable name of the currency.
1081 \endlist
1082 \sa Number::toLocaleCurrencyString()
1083*/
1084
1085/*!
1086 \qmlproperty string QtQml::Locale::nativeLanguageName
1087
1088 Holds a native name of the language for the locale. For example
1089 "Schwiizertüütsch" for Swiss-German locale.
1090
1091 \sa nativeCountryName
1092*/
1093
1094/*!
1095 \qmlproperty string QtQml::Locale::nativeCountryName
1096
1097 Holds a native name of the country for the locale. For example
1098 "España" for Spanish/Spain locale.
1099
1100 \sa nativeLanguageName
1101*/
1102
1103/*!
1104 \qmlproperty enumeration QtQml::Locale::measurementSystem
1105
1106 This property defines which units are used for measurement.
1107
1108 \list
1109 \li Locale.MetricSystem This value indicates metric units, such as meters,
1110 centimeters and millimeters.
1111 \li Locale.ImperialUSSystem This value indicates imperial units, such as
1112 inches and miles as they are used in the United States.
1113 \li Locale.ImperialUKSystem This value indicates imperial units, such as
1114 inches and miles as they are used in the United Kingdom.
1115 \li Locale.ImperialSystem Provided for compatibility. The same as
1116 Locale.ImperialUSSystem.
1117 \endlist
1118*/
1119
1120QT_END_NAMESPACE
1121
1122#include "moc_qqmllocale_p.cpp"
1123

source code of qtdeclarative/src/qml/qml/qqmllocale.cpp