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(engine->id_toLocaleString(), method_toLocaleString);
81 engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleTimeString"), method_toLocaleTimeString);
82 engine->datePrototype()->defineDefaultProperty(QStringLiteral("toLocaleDateString"), method_toLocaleDateString);
83 engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), method_fromLocaleString);
84 engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleTimeString"), method_fromLocaleTimeString);
85 engine->dateCtor()->defineDefaultProperty(QStringLiteral("fromLocaleDateString"), method_fromLocaleDateString);
86 engine->dateCtor()->defineDefaultProperty(QStringLiteral("timeZoneUpdated"), 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(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(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(dt, format);
122 } else {
123 THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
124 }
125 } else {
126 formattedDt = r->d()->locale->toString(dt, 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(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, 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, 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(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, 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, 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(dateString);
229 RETURN_RESULT(engine->newDateObject(dt));
230 }
231 }
232
233 if (argc < 1 || argc > 3 || !isLocaleObject(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(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(dateString, format);
249 } else {
250 THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
251 }
252 } else {
253 dt = r->d()->locale->toDateTime(dateString, 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(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(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(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(dateString, format);
291 } else {
292 THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
293 }
294 } else {
295 tm = r->d()->locale->toTime(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(dateString);
317 RETURN_RESULT(engine->newDateObject(QDateTime(date)));
318 }
319 }
320
321 if (argc < 1 || argc > 3 || !isLocaleObject(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(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(dateString, format);
337 } else {
338 THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
339 }
340 } else {
341 dt = r->d()->locale->toDate(dateString, enumFormat);
342 }
343
344 RETURN_RESULT(engine->newDateObject(QDateTime(dt)));
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(scope.engine);
354
355 RETURN_UNDEFINED();
356}
357
358//-----------------
359// Number extension
360
361void QQmlNumberExtension::registerExtension(QV4::ExecutionEngine *engine)
362{
363 engine->numberPrototype()->defineDefaultProperty(engine->id_toLocaleString(), method_toLocaleString);
364 engine->numberPrototype()->defineDefaultProperty(QStringLiteral("toLocaleCurrencyString"), method_toLocaleCurrencyString);
365 engine->numberCtor()->defineDefaultProperty(QStringLiteral("fromLocaleString"), 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(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(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(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(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(ns, &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_measurementSystem(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
482{
483 QV4::Scope scope(b);
484 const QLocale *locale = getThisLocale(scope, thisObject);
485 if (!locale)
486 return Encode::undefined();
487 return QV4::Encode(locale->measurementSystem());
488}
489
490ReturnedValue QQmlLocaleData::method_get_textDirection(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
491{
492 QV4::Scope scope(b);
493 const QLocale *locale = getThisLocale(scope, thisObject);
494 if (!locale)
495 return Encode::undefined();
496
497 return QV4::Encode(locale->textDirection());
498}
499
500ReturnedValue QQmlLocaleData::method_get_weekDays(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
501{
502 QV4::Scope scope(b);
503 const QLocale *locale = getThisLocale(scope, thisObject);
504 if (!locale)
505 return Encode::undefined();
506
507 QList<Qt::DayOfWeek> days = locale->weekdays();
508
509 QV4::ScopedArrayObject result(scope, scope.engine->newArrayObject());
510 result->arrayReserve(days.size());
511 for (int i = 0; i < days.size(); ++i) {
512 int day = days.at(i);
513 if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
514 day = 0;
515 result->arrayPut(i, QV4::Value::fromInt32(day));
516 }
517 result->setArrayLengthUnchecked(days.size());
518
519 return result.asReturnedValue();
520}
521
522ReturnedValue QQmlLocaleData::method_get_uiLanguages(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int)
523{
524 QV4::Scope scope(b);
525 const QLocale *locale = getThisLocale(scope, thisObject);
526 if (!locale)
527 return Encode::undefined();
528
529 QStringList langs = locale->uiLanguages();
530 QV4::ScopedArrayObject result(scope, scope.engine->newArrayObject());
531 result->arrayReserve(langs.size());
532 QV4::ScopedValue v(scope);
533 for (int i = 0; i < langs.size(); ++i)
534 result->arrayPut(i, (v = scope.engine->newString(langs.at(i))));
535
536 result->setArrayLengthUnchecked(langs.size());
537
538 return result.asReturnedValue();
539}
540
541ReturnedValue QQmlLocaleData::method_currencySymbol(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
542{
543 QV4::Scope scope(b);
544 const QLocale *locale = getThisLocale(scope, thisObject);
545 if (!locale)
546 return Encode::undefined();
547
548 if (argc > 1)
549 THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
550
551 QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
552 if (argc == 1) {
553 quint32 intFormat = argv[0].toNumber();
554 format = QLocale::CurrencySymbolFormat(intFormat);
555 }
556
557 RETURN_RESULT(scope.engine->newString(locale->currencySymbol(format)));
558}
559
560#define LOCALE_FORMAT(FUNC) \
561ReturnedValue QQmlLocaleData::method_ ##FUNC (const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc) { \
562 QV4::Scope scope(b); \
563 const QLocale *locale = getThisLocale(scope, thisObject); \
564 if (!locale) \
565 return Encode::undefined(); \
566 if (argc > 1) \
567 THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \
568 QLocale::FormatType format = QLocale::LongFormat;\
569 if (argc == 1) { \
570 quint32 intFormat = argv[0].toUInt32(); \
571 format = QLocale::FormatType(intFormat); \
572 } \
573 RETURN_RESULT(scope.engine->newString(locale-> FUNC (format))); \
574}
575
576LOCALE_FORMAT(dateTimeFormat)
577LOCALE_FORMAT(timeFormat)
578LOCALE_FORMAT(dateFormat)
579
580// +1 added to idx because JS is 0-based, whereas QLocale months begin at 1.
581#define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \
582ReturnedValue QQmlLocaleData::method_ ## VARIABLE (const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc) {\
583 Scope scope(b); \
584 const QLocale *locale = getThisLocale(scope, thisObject); \
585 if (!locale) \
586 return Encode::undefined(); \
587 if (argc < 1 || argc > 2) \
588 THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
589 QLocale::FormatType enumFormat = QLocale::LongFormat; \
590 int idx = argv[0].toInt32() + 1; \
591 if (idx < 1 || idx > 12) \
592 THROW_ERROR("Locale: Invalid month"); \
593 QString name; \
594 if (argc == 2) { \
595 if (argv[1].isNumber()) { \
596 quint32 intFormat = argv[1].toUInt32(); \
597 QLocale::FormatType format = QLocale::FormatType(intFormat); \
598 name = locale-> VARIABLE(idx, format); \
599 } else { \
600 THROW_ERROR("Locale: Invalid datetime format"); \
601 } \
602 } else { \
603 name = locale-> VARIABLE(idx, enumFormat); \
604 } \
605 RETURN_RESULT(scope.engine->newString(name)); \
606}
607
608// 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date
609#define LOCALE_FORMATTED_DAYNAME(VARIABLE) \
610ReturnedValue QQmlLocaleData::method_ ## VARIABLE (const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc) {\
611 Scope scope(b); \
612 const QLocale *locale = getThisLocale(scope, thisObject); \
613 if (!locale) \
614 return Encode::undefined(); \
615 if (argc < 1 || argc > 2) \
616 THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
617 QLocale::FormatType enumFormat = QLocale::LongFormat; \
618 int idx = argv[0].toInt32(); \
619 if (idx < 0 || idx > 7) \
620 THROW_ERROR("Locale: Invalid day"); \
621 if (idx == 0) idx = 7; \
622 QString name; \
623 if (argc == 2) { \
624 if (argv[1].isNumber()) { \
625 quint32 intFormat = argv[1].toUInt32(); \
626 QLocale::FormatType format = QLocale::FormatType(intFormat); \
627 name = locale-> VARIABLE(idx, format); \
628 } else { \
629 THROW_ERROR("Locale: Invalid datetime format"); \
630 } \
631 } else { \
632 name = locale-> VARIABLE(idx, enumFormat); \
633 } \
634 RETURN_RESULT(scope.engine->newString(name)); \
635}
636
637LOCALE_FORMATTED_MONTHNAME(monthName)
638LOCALE_FORMATTED_MONTHNAME(standaloneMonthName)
639LOCALE_FORMATTED_DAYNAME(dayName)
640LOCALE_FORMATTED_DAYNAME(standaloneDayName)
641
642#define LOCALE_STRING_PROPERTY(VARIABLE) \
643ReturnedValue QQmlLocaleData::method_get_ ## VARIABLE (const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *, int) \
644{ \
645 Scope scope(b); \
646 const QLocale *locale = getThisLocale(scope, thisObject); \
647 if (!locale) \
648 return Encode::undefined(); \
649 RETURN_RESULT(scope.engine->newString(locale-> VARIABLE()));\
650}
651
652LOCALE_STRING_PROPERTY(name)
653LOCALE_STRING_PROPERTY(nativeLanguageName)
654LOCALE_STRING_PROPERTY(nativeCountryName)
655LOCALE_STRING_PROPERTY(decimalPoint)
656LOCALE_STRING_PROPERTY(groupSeparator)
657LOCALE_STRING_PROPERTY(percent)
658LOCALE_STRING_PROPERTY(zeroDigit)
659LOCALE_STRING_PROPERTY(negativeSign)
660LOCALE_STRING_PROPERTY(positiveSign)
661LOCALE_STRING_PROPERTY(exponential)
662LOCALE_STRING_PROPERTY(amText)
663LOCALE_STRING_PROPERTY(pmText)
664
665class QV4LocaleDataDeletable : public QV4::ExecutionEngine::Deletable
666{
667public:
668 QV4LocaleDataDeletable(QV4::ExecutionEngine *engine);
669 ~QV4LocaleDataDeletable();
670
671 QV4::PersistentValue prototype;
672};
673
674QV4LocaleDataDeletable::QV4LocaleDataDeletable(QV4::ExecutionEngine *engine)
675{
676 QV4::Scope scope(engine);
677 QV4::Scoped<QV4::Object> o(scope, engine->newObject());
678
679 o->defineDefaultProperty(QStringLiteral("dateFormat"), QQmlLocaleData::method_dateFormat, 0);
680 o->defineDefaultProperty(QStringLiteral("standaloneDayName"), QQmlLocaleData::method_standaloneDayName, 0);
681 o->defineDefaultProperty(QStringLiteral("standaloneMonthName"), QQmlLocaleData::method_standaloneMonthName, 0);
682 o->defineDefaultProperty(QStringLiteral("dayName"), QQmlLocaleData::method_dayName, 0);
683 o->defineDefaultProperty(QStringLiteral("timeFormat"), QQmlLocaleData::method_timeFormat, 0);
684 o->defineDefaultProperty(QStringLiteral("monthName"), QQmlLocaleData::method_monthName, 0);
685 o->defineDefaultProperty(QStringLiteral("currencySymbol"), QQmlLocaleData::method_currencySymbol, 0);
686 o->defineDefaultProperty(QStringLiteral("dateTimeFormat"), QQmlLocaleData::method_dateTimeFormat, 0);
687 o->defineAccessorProperty(QStringLiteral("name"), QQmlLocaleData::method_get_name, nullptr);
688 o->defineAccessorProperty(QStringLiteral("positiveSign"), QQmlLocaleData::method_get_positiveSign, nullptr);
689 o->defineAccessorProperty(QStringLiteral("uiLanguages"), QQmlLocaleData::method_get_uiLanguages, nullptr);
690 o->defineAccessorProperty(QStringLiteral("firstDayOfWeek"), QQmlLocaleData::method_get_firstDayOfWeek, nullptr);
691 o->defineAccessorProperty(QStringLiteral("pmText"), QQmlLocaleData::method_get_pmText, nullptr);
692 o->defineAccessorProperty(QStringLiteral("percent"), QQmlLocaleData::method_get_percent, nullptr);
693 o->defineAccessorProperty(QStringLiteral("textDirection"), QQmlLocaleData::method_get_textDirection, nullptr);
694 o->defineAccessorProperty(QStringLiteral("weekDays"), QQmlLocaleData::method_get_weekDays, nullptr);
695 o->defineAccessorProperty(QStringLiteral("negativeSign"), QQmlLocaleData::method_get_negativeSign, nullptr);
696 o->defineAccessorProperty(QStringLiteral("groupSeparator"), QQmlLocaleData::method_get_groupSeparator, nullptr);
697 o->defineAccessorProperty(QStringLiteral("decimalPoint"), QQmlLocaleData::method_get_decimalPoint, nullptr);
698 o->defineAccessorProperty(QStringLiteral("nativeLanguageName"), QQmlLocaleData::method_get_nativeLanguageName, nullptr);
699 o->defineAccessorProperty(QStringLiteral("nativeCountryName"), QQmlLocaleData::method_get_nativeCountryName, nullptr);
700 o->defineAccessorProperty(QStringLiteral("zeroDigit"), QQmlLocaleData::method_get_zeroDigit, nullptr);
701 o->defineAccessorProperty(QStringLiteral("amText"), QQmlLocaleData::method_get_amText, nullptr);
702 o->defineAccessorProperty(QStringLiteral("measurementSystem"), QQmlLocaleData::method_get_measurementSystem, nullptr);
703 o->defineAccessorProperty(QStringLiteral("exponential"), QQmlLocaleData::method_get_exponential, nullptr);
704
705 prototype.set(engine, o);
706}
707
708QV4LocaleDataDeletable::~QV4LocaleDataDeletable()
709{
710}
711
712V4_DEFINE_EXTENSION(QV4LocaleDataDeletable, localeV4Data);
713
714/*!
715 \qmltype Locale
716 \instantiates QQmlLocale
717 \inqmlmodule QtQml
718 \brief Provides locale specific properties and formatted data.
719
720 The Locale object may only be created via the \l{QtQml::Qt::locale()}{Qt.locale()} function.
721 It cannot be created directly.
722
723 The \l{QtQml::Qt::locale()}{Qt.locale()} function returns a JS Locale object representing the
724 locale with the specified name, which has the format
725 "language[_territory][.codeset][@modifier]" or "C".
726
727 Locale supports the concept of a default locale, which is
728 determined from the system's locale settings at application
729 startup. If no parameter is passed to Qt.locale() the default
730 locale object is returned.
731
732 The Locale object provides a number of functions and properties
733 providing data for the specified locale.
734
735 The Locale object may also be passed to the \l Date and \l Number toLocaleString()
736 and fromLocaleString() methods in order to convert to/from strings using
737 the specified locale.
738
739 This example shows the current date formatted for the German locale:
740
741 \code
742 import QtQuick 2.0
743
744 Text {
745 text: "The date is: " + Date().toLocaleString(Qt.locale("de_DE"))
746 }
747 \endcode
748
749 The following example displays the specified number
750 in the correct format for the default locale:
751
752 \code
753 import QtQuick 2.0
754
755 Text {
756 text: "The value is: " + Number(23443.34).toLocaleString(Qt.locale())
757 }
758 \endcode
759
760 Qt Quick Locale's data is based on Common Locale Data Repository v1.8.1.
761
762
763 \target FormatType
764 \section2 Locale String Format Types
765
766 The monthName(), standaloneMonthName(), dayName() and standaloneDayName()
767 can use the following enumeration values to specify the formatting of
768 the string representation for a Date object.
769
770 \list
771 \li Locale.LongFormat The long version of day and month names; for
772 example, returning "January" as a month name.
773 \li Locale.ShortFormat The short version of day and month names; for
774 example, returning "Jan" as a month name.
775 \li Locale.NarrowFormat A special version of day and month names for
776 use when space is limited; for example, returning "J" as a month
777 name. Note that the narrow format might contain the same text for
778 different months and days or it can even be an empty string if the
779 locale doesn't support narrow names, so you should avoid using it
780 for date formatting. Also, for the system locale this format is
781 the same as ShortFormat.
782 \endlist
783
784
785 Additionally the double-to-string and string-to-double conversion functions are
786 covered by the following licenses:
787
788 \legalese
789 Copyright (c) 1991 by AT&T.
790
791 Permission to use, copy, modify, and distribute this software for any
792 purpose without fee is hereby granted, provided that this entire notice
793 is included in all copies of any software which is or includes a copy
794 or modification of this software and in all copies of the supporting
795 documentation for such software.
796
797 THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
798 WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
799 REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
800 OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
801
802 This product includes software developed by the University of
803 California, Berkeley and its contributors.
804
805 \sa Date, Number
806*/
807
808QQmlLocale::QQmlLocale()
809{
810}
811
812QQmlLocale::~QQmlLocale()
813{
814}
815
816QV4::ReturnedValue QQmlLocale::locale(ExecutionEngine *engine, const QString &localeName)
817{
818 QLocale qlocale;
819 if (!localeName.isEmpty())
820 qlocale = localeName;
821 return wrap(engine, qlocale);
822}
823
824QV4::ReturnedValue QQmlLocale::wrap(ExecutionEngine *v4, const QLocale &locale)
825{
826 QV4::Scope scope(v4);
827 QV4LocaleDataDeletable *d = localeV4Data(scope.engine);
828 QV4::Scoped<QQmlLocaleData> wrapper(scope, v4->memoryManager->allocate<QQmlLocaleData>());
829 *wrapper->d()->locale = locale;
830 QV4::ScopedObject p(scope, d->prototype.value());
831 wrapper->setPrototypeOf(p);
832 return wrapper.asReturnedValue();
833}
834
835void QQmlLocale::registerStringLocaleCompare(QV4::ExecutionEngine *engine)
836{
837 engine->stringPrototype()->defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare);
838}
839
840ReturnedValue QQmlLocale::method_localeCompare(const QV4::FunctionObject *b, const QV4::Value *thisObject, const QV4::Value *argv, int argc)
841{
842 if (argc != 1 || (!argv[0].isString() && !argv[0].as<StringObject>()))
843 return QV4::StringPrototype::method_localeCompare(b, thisObject, argv, argc);
844
845 if (!thisObject->isString() && !thisObject->as<StringObject>())
846 return QV4::StringPrototype::method_localeCompare(b, thisObject, argv, argc);
847
848 QString thisString = thisObject->toQStringNoThrow();
849 QString thatString = argv[0].toQStringNoThrow();
850
851 return QV4::Encode(QString::localeAwareCompare(thisString, thatString));
852}
853
854/*!
855 \qmlproperty string QtQml::Locale::name
856
857 Holds the language and country of this locale as a
858 string of the form "language_country", where
859 language is a lowercase, two-letter ISO 639 language code,
860 and country is an uppercase, two- or three-letter ISO 3166 country code.
861*/
862
863/*!
864 \qmlproperty string QtQml::Locale::decimalPoint
865
866 Holds the decimal point character of this locale.
867*/
868
869/*!
870 \qmlproperty string QtQml::Locale::groupSeparator
871
872 Holds the group separator character of this locale.
873*/
874
875/*!
876 \qmlproperty string QtQml::Locale::percent
877
878 Holds the percent character of this locale.
879*/
880
881
882/*!
883 \qmlproperty string QtQml::Locale::zeroDigit
884
885 Holds Returns the zero digit character of this locale.
886*/
887
888/*!
889 \qmlproperty string QtQml::Locale::negativeSign
890
891 Holds the negative sign character of this locale.
892*/
893
894/*!
895 \qmlproperty string QtQml::Locale::positiveSign
896
897 Holds the positive sign character of this locale.
898*/
899
900/*!
901 \qmlproperty string QtQml::Locale::exponential
902
903 Holds the exponential character of this locale.
904*/
905
906/*!
907 \qmlmethod string QtQml::Locale::dateTimeFormat(type)
908
909 Returns the date time format used for the current locale.
910 \a type specifies the FormatType to return.
911
912 \sa Date
913*/
914
915/*!
916 \qmlmethod string QtQml::Locale::dateFormat(type)
917
918 Returns the date format used for the current locale.
919 \a type specifies the FormatType to return.
920
921 \sa Date
922*/
923
924/*!
925 \qmlmethod string QtQml::Locale::timeFormat(type)
926
927 Returns the time format used for the current locale.
928 \a type specifies the FormatType to return.
929
930 \sa Date
931*/
932
933/*!
934 \qmlmethod string QtQml::Locale::monthName(month, type)
935
936 Returns the localized name of \a month (0-11), in the optional
937 \l FormatType specified by \a type.
938
939 \note the QLocale C++ API expects a range of (1-12), however Locale.monthName()
940 expects 0-11 as per the JS Date object.
941
942 \sa dayName(), standaloneMonthName()
943*/
944
945/*!
946 \qmlmethod string QtQml::Locale::standaloneMonthName(month, type)
947
948 Returns the localized name of \a month (0-11) that is used as a
949 standalone text, in the optional \l FormatType specified by \a type.
950
951 If the locale information doesn't specify the standalone month
952 name then return value is the same as in monthName().
953
954 \note the QLocale C++ API expects a range of (1-12), however Locale.standaloneMonthName()
955 expects 0-11 as per the JS Date object.
956
957 \sa monthName(), standaloneDayName()
958*/
959
960/*!
961 \qmlmethod string QtQml::Locale::dayName(day, type)
962
963 Returns the localized name of the \a day (where 0 represents
964 Sunday, 1 represents Monday and so on), in the optional
965 \l FormatType specified by \a type.
966
967 \sa monthName(), standaloneDayName()
968*/
969
970/*!
971 \qmlmethod string QtQml::Locale::standaloneDayName(day, type)
972
973 Returns the localized name of the \a day (where 0 represents
974 Sunday, 1 represents Monday and so on) that is used as a
975 standalone text, in the \l FormatType specified by \a type.
976
977 If the locale information does not specify the standalone day
978 name then return value is the same as in dayName().
979
980 \sa dayName(), standaloneMonthName()
981*/
982
983/*!
984 \qmlproperty enumeration QtQml::Locale::firstDayOfWeek
985
986 Holds the first day of the week according to the current locale.
987
988 \list
989 \li Locale.Sunday = 0
990 \li Locale.Monday = 1
991 \li Locale.Tuesday = 2
992 \li Locale.Wednesday = 3
993 \li Locale.Thursday = 4
994 \li Locale.Friday = 5
995 \li Locale.Saturday = 6
996 \endlist
997
998 \note that these values match the JS Date API which is different
999 from the Qt C++ API where Qt::Sunday = 7.
1000*/
1001
1002/*!
1003 \qmlproperty Array<int> QtQml::Locale::weekDays
1004
1005 Holds an array of days that are considered week days according to the current locale,
1006 where Sunday is 0 and Saturday is 6.
1007
1008 \sa firstDayOfWeek
1009*/
1010
1011/*!
1012 \qmlproperty Array<string> QtQml::Locale::uiLanguages
1013
1014 Returns an ordered list of locale names for translation purposes in
1015 preference order.
1016
1017 The return value represents locale names that the user expects to see the
1018 UI translation in.
1019
1020 The first item in the list is the most preferred one.
1021*/
1022
1023/*!
1024 \qmlproperty enumeration QtQml::Locale::textDirection
1025
1026 Holds the text direction of the language:
1027 \list
1028 \li Qt.LeftToRight
1029 \li Qt.RightToLeft
1030 \endlist
1031*/
1032
1033/*!
1034 \qmlproperty string QtQml::Locale::amText
1035
1036 The localized name of the "AM" suffix for times specified using the conventions of the 12-hour clock.
1037*/
1038
1039/*!
1040 \qmlproperty string QtQml::Locale::pmText
1041
1042 The localized name of the "PM" suffix for times specified using the conventions of the 12-hour clock.
1043*/
1044
1045/*!
1046 \qmlmethod string QtQml::Locale::currencySymbol(format)
1047
1048 Returns the currency symbol for the specified \a format:
1049 \list
1050 \li Locale.CurrencyIsoCode a ISO-4217 code of the currency.
1051 \li Locale.CurrencySymbol a currency symbol.
1052 \li Locale.CurrencyDisplayName a user readable name of the currency.
1053 \endlist
1054 \sa Number::toLocaleCurrencyString()
1055*/
1056
1057/*!
1058 \qmlproperty string QtQml::Locale::nativeLanguageName
1059
1060 Holds a native name of the language for the locale. For example
1061 "Schwiizertüütsch" for Swiss-German locale.
1062
1063 \sa nativeCountryName
1064*/
1065
1066/*!
1067 \qmlproperty string QtQml::Locale::nativeCountryName
1068
1069 Holds a native name of the country for the locale. For example
1070 "España" for Spanish/Spain locale.
1071
1072 \sa nativeLanguageName
1073*/
1074
1075/*!
1076 \qmlproperty enumeration QtQml::Locale::measurementSystem
1077
1078 This property defines which units are used for measurement.
1079
1080 \list
1081 \li Locale.MetricSystem This value indicates metric units, such as meters,
1082 centimeters and millimeters.
1083 \li Locale.ImperialUSSystem This value indicates imperial units, such as
1084 inches and miles as they are used in the United States.
1085 \li Locale.ImperialUKSystem This value indicates imperial units, such as
1086 inches and miles as they are used in the United Kingdom.
1087 \li Locale.ImperialSystem Provided for compatibility. The same as
1088 Locale.ImperialUSSystem.
1089 \endlist
1090*/
1091
1092QT_END_NAMESPACE
1093
1094#include "moc_qqmllocale_p.cpp"
1095