Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativelocale.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativelocale_p.h"
43 #include "qdeclarativeengine_p.h"
44 #include <private/qdeclarativecontext_p.h>
45 #include <private/qjsconverter_impl_p.h>
46 #include <QtCore/qnumeric.h>
47 #include <QtCore/qdatetime.h>
48
49 #include <private/qlocale_p.h>
50 #include <private/qlocale_data_p.h>
51
52 QT_BEGIN_NAMESPACE
53
54 class QV8LocaleDataResource : public QV8ObjectResource
55 {
56     V8_RESOURCE_TYPE(LocaleDataType)
57 public:
58     QV8LocaleDataResource(QV8Engine *e) : QV8ObjectResource(e) {}
59     QLocale locale;
60 };
61
62 #define GET_LOCALE_DATA_RESOURCE(OBJECT) \
63 QV8LocaleDataResource *r = v8_resource_cast<QV8LocaleDataResource>(OBJECT); \
64 if (!r) \
65     V8THROW_ERROR("Not a valid Locale object")
66
67 static bool isLocaleObject(v8::Handle<v8::Value> val)
68 {
69     if (!val->IsObject())
70         return false;
71
72     v8::Handle<v8::Object> localeObj = val->ToObject();
73     return localeObj->Has(v8::String::New("nativeLanguageName")); //XXX detect locale object properly
74 }
75
76 //--------------
77 // Date extension
78
79 static const char *dateToLocaleStringFunction =
80         "(function(toLocaleStringFunc) { "
81         "  var orig_toLocaleString;"
82         "  orig_toLocaleString = Date.prototype.toLocaleString;"
83         "  Date.prototype.toLocaleString = (function() {"
84         "    var val = toLocaleStringFunc.apply(this, arguments);"
85         "    if (val == undefined) val = orig_toLocaleString.call(this);"
86         "    return val;"
87         "  })"
88         "})";
89
90 static const char *dateToLocaleTimeStringFunction =
91         "(function(toLocaleTimeStringFunc) { "
92         "  var orig_toLocaleTimeString;"
93         "  orig_toLocaleTimeString = Date.prototype.toLocaleTimeString;"
94         "  Date.prototype.toLocaleTimeString = (function() {"
95         "    var val = toLocaleTimeStringFunc.apply(this, arguments);"
96         "    if (val == undefined) val = orig_toLocaleTimeString.call(this);"
97         "    return val;"
98         "  })"
99         "})";
100
101 static const char *dateToLocaleDateStringFunction =
102         "(function(toLocaleDateStringFunc) { "
103         "  var orig_toLocaleDateString;"
104         "  orig_toLocaleDateString = Date.prototype.toLocaleDateString;"
105         "  Date.prototype.toLocaleDateString = (function() {"
106         "    var val = toLocaleDateStringFunc.apply(this, arguments);"
107         "    if (val == undefined) val = orig_toLocaleDateString.call(this);"
108         "    return val;"
109         "  })"
110         "})";
111
112
113 static const char *dateFromLocaleStringFunction =
114         "(function(fromLocaleStringFunc) { "
115         "  Date.fromLocaleString = (function() {"
116         "    return fromLocaleStringFunc.apply(null, arguments);"
117         "  })"
118         "})";
119
120 static const char *dateFromLocaleTimeStringFunction =
121         "(function(fromLocaleTimeStringFunc) { "
122         "  Date.fromLocaleTimeString = (function() {"
123         "    return fromLocaleTimeStringFunc.apply(null, arguments);"
124         "  })"
125         "})";
126
127 static const char *dateFromLocaleDateStringFunction =
128         "(function(fromLocaleDateStringFunc) { "
129         "  Date.fromLocaleDateString = (function() {"
130         "    return fromLocaleDateStringFunc.apply(null, arguments);"
131         "  })"
132         "})";
133
134
135 static void registerFunction(QV8Engine *engine, const char *script, v8::InvocationCallback func)
136 {
137     v8::Local<v8::Script> registerScript = v8::Script::New(v8::String::New(script), 0, 0, v8::Handle<v8::String>(), v8::Script::NativeMode);
138     v8::Local<v8::Value> result = registerScript->Run();
139     Q_ASSERT(result->IsFunction());
140     v8::Local<v8::Function> registerFunc = v8::Local<v8::Function>::Cast(result);
141     v8::Handle<v8::Value> args = V8FUNCTION(func, engine);
142     registerFunc->Call(v8::Local<v8::Object>::Cast(registerFunc), 1, &args);
143 }
144
145 void QDeclarativeDateExtension::registerExtension(QV8Engine *engine)
146 {
147     registerFunction(engine, dateToLocaleStringFunction, toLocaleString);
148     registerFunction(engine, dateToLocaleTimeStringFunction, toLocaleTimeString);
149     registerFunction(engine, dateToLocaleDateStringFunction, toLocaleDateString);
150     registerFunction(engine, dateFromLocaleStringFunction, fromLocaleString);
151     registerFunction(engine, dateFromLocaleTimeStringFunction, fromLocaleTimeString);
152     registerFunction(engine, dateFromLocaleDateStringFunction, fromLocaleDateString);
153 }
154
155 v8::Handle<v8::Value> QDeclarativeDateExtension::toLocaleString(const v8::Arguments& args)
156 {
157     if (args.Length() > 2)
158         return v8::Undefined();
159
160     if (!args.This()->IsDate())
161         return v8::Undefined();
162
163     QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
164
165     if (args.Length() == 0) {
166         // Use QLocale for standard toLocaleString() function
167         QLocale locale;
168         return QJSConverter::toString(locale.toString(dt));
169     }
170
171     if (!isLocaleObject(args[0]))
172         return v8::Undefined(); // Use the default Date toLocaleString()
173
174     GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
175
176     QLocale::FormatType enumFormat = QLocale::LongFormat;
177     QString formattedDt;
178     if (args.Length() == 2) {
179         if (args[1]->IsString()) {
180             QString format = r->engine->toVariant(args[1], -1).toString();
181             formattedDt = r->locale.toString(dt, format);
182         } else if (args[1]->IsNumber()) {
183             quint32 intFormat = args[1]->ToNumber()->Value();
184             QLocale::FormatType format = QLocale::FormatType(intFormat);
185             formattedDt = r->locale.toString(dt, format);
186         } else {
187             V8THROW_ERROR("Locale: Date.toLocaleString(): Invalid datetime format");
188         }
189     } else {
190          formattedDt = r->locale.toString(dt, enumFormat);
191     }
192
193     return r->engine->toString(formattedDt);
194 }
195
196 v8::Handle<v8::Value> QDeclarativeDateExtension::toLocaleTimeString(const v8::Arguments& args)
197 {
198     if (args.Length() > 2)
199         return v8::Undefined();
200
201     if (!args.This()->IsDate())
202         return v8::Undefined();
203
204     QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
205     QTime time = dt.time();
206
207     if (args.Length() == 0) {
208         // Use QLocale for standard toLocaleString() function
209         QLocale locale;
210         return QJSConverter::toString(locale.toString(time));
211     }
212
213     if (!isLocaleObject(args[0]))
214         return v8::Undefined(); // Use the default Date toLocaleTimeString()
215
216     GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
217
218     QLocale::FormatType enumFormat = QLocale::LongFormat;
219     QString formattedTime;
220     if (args.Length() == 2) {
221         if (args[1]->IsString()) {
222             QString format = r->engine->toVariant(args[1], -1).toString();
223             formattedTime = r->locale.toString(time, format);
224         } else if (args[1]->IsNumber()) {
225             quint32 intFormat = args[1]->ToNumber()->Value();
226             QLocale::FormatType format = QLocale::FormatType(intFormat);
227             formattedTime = r->locale.toString(time, format);
228         } else {
229             V8THROW_ERROR("Locale: Date.toLocaleTimeString(): Invalid time format");
230         }
231     } else {
232          formattedTime = r->locale.toString(time, enumFormat);
233     }
234
235     return r->engine->toString(formattedTime);
236 }
237
238 v8::Handle<v8::Value> QDeclarativeDateExtension::toLocaleDateString(const v8::Arguments& args)
239 {
240     if (args.Length() > 2)
241         return v8::Undefined();
242
243     if (!args.This()->IsDate())
244         return v8::Undefined();
245
246     QDateTime dt = QV8Engine::qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(args.This())->NumberValue());
247     QDate date = dt.date();
248
249     if (args.Length() == 0) {
250         // Use QLocale for standard toLocaleString() function
251         QLocale locale;
252         return QJSConverter::toString(locale.toString(date));
253     }
254
255     if (!isLocaleObject(args[0]))
256         return v8::Undefined(); // Use the default Date toLocaleDateString()
257
258     GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
259
260     QLocale::FormatType enumFormat = QLocale::LongFormat;
261     QString formattedDate;
262     if (args.Length() == 2) {
263         if (args[1]->IsString()) {
264             QString format = r->engine->toVariant(args[1], -1).toString();
265             formattedDate = r->locale.toString(date, format);
266         } else if (args[1]->IsNumber()) {
267             quint32 intFormat = args[1]->ToNumber()->Value();
268             QLocale::FormatType format = QLocale::FormatType(intFormat);
269             formattedDate = r->locale.toString(date, format);
270         } else {
271             V8THROW_ERROR("Locale: Date.loLocaleDateString(): Invalid date format");
272         }
273     } else {
274          formattedDate = r->locale.toString(date, enumFormat);
275     }
276
277     return r->engine->toString(formattedDate);
278 }
279
280 v8::Handle<v8::Value> QDeclarativeDateExtension::fromLocaleString(const v8::Arguments& args)
281 {
282     if (args.Length() == 1 && args[0]->IsString()) {
283         QLocale locale;
284         QString dateString = QJSConverter::toString(args[0]->ToString());
285         QDateTime dt = locale.toDateTime(dateString);
286         return QJSConverter::toDateTime(dt);
287     }
288
289     if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
290         V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid arguments");
291
292     GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
293
294     QLocale::FormatType enumFormat = QLocale::LongFormat;
295     QDateTime dt;
296     QString dateString = r->engine->toString(args[1]->ToString());
297     if (args.Length() == 3) {
298         if (args[2]->IsString()) {
299             QString format = r->engine->toString(args[2]->ToString());
300             dt = r->locale.toDateTime(dateString, format);
301         } else if (args[2]->IsNumber()) {
302             quint32 intFormat = args[2]->ToNumber()->Value();
303             QLocale::FormatType format = QLocale::FormatType(intFormat);
304             dt = r->locale.toDateTime(dateString, format);
305         } else {
306             V8THROW_ERROR("Locale: Date.fromLocaleString(): Invalid datetime format");
307         }
308     } else {
309         dt = r->locale.toDateTime(dateString, enumFormat);
310     }
311
312     return QJSConverter::toDateTime(dt);
313 }
314
315 v8::Handle<v8::Value> QDeclarativeDateExtension::fromLocaleTimeString(const v8::Arguments& args)
316 {
317     if (args.Length() == 1 && args[0]->IsString()) {
318         QLocale locale;
319         QString timeString = QJSConverter::toString(args[0]->ToString());
320         QTime time = locale.toTime(timeString);
321         QDateTime dt = QDateTime::currentDateTime();
322         dt.setTime(time);
323         return QJSConverter::toDateTime(dt);
324     }
325
326     if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
327         V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid arguments");
328
329     GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
330
331     QLocale::FormatType enumFormat = QLocale::LongFormat;
332     QTime tm;
333     QString dateString = r->engine->toString(args[1]->ToString());
334     if (args.Length() == 3) {
335         if (args[2]->IsString()) {
336             QString format = r->engine->toString(args[2]->ToString());
337             tm = r->locale.toTime(dateString, format);
338         } else if (args[2]->IsNumber()) {
339             quint32 intFormat = args[2]->ToNumber()->Value();
340             QLocale::FormatType format = QLocale::FormatType(intFormat);
341             tm = r->locale.toTime(dateString, format);
342         } else {
343             V8THROW_ERROR("Locale: Date.fromLocaleTimeString(): Invalid datetime format");
344         }
345     } else {
346         tm = r->locale.toTime(dateString, enumFormat);
347     }
348
349     QDateTime dt = QDateTime::currentDateTime();
350     dt.setTime(tm);
351
352     return QJSConverter::toDateTime(dt);
353 }
354
355 v8::Handle<v8::Value> QDeclarativeDateExtension::fromLocaleDateString(const v8::Arguments& args)
356 {
357     if (args.Length() == 1 && args[0]->IsString()) {
358         QLocale locale;
359         QString dateString = QJSConverter::toString(args[0]->ToString());
360         QDate date = locale.toDate(dateString);
361         return QJSConverter::toDateTime(QDateTime(date));
362     }
363
364     if (args.Length() < 1 || args.Length() > 3 || !isLocaleObject(args[0]))
365         V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid arguments");
366
367     GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
368
369     QLocale::FormatType enumFormat = QLocale::LongFormat;
370     QDate dt;
371     QString dateString = r->engine->toString(args[1]->ToString());
372     if (args.Length() == 3) {
373         if (args[2]->IsString()) {
374             QString format = r->engine->toString(args[2]->ToString());
375             dt = r->locale.toDate(dateString, format);
376         } else if (args[2]->IsNumber()) {
377             quint32 intFormat = args[2]->ToNumber()->Value();
378             QLocale::FormatType format = QLocale::FormatType(intFormat);
379             dt = r->locale.toDate(dateString, format);
380         } else {
381             V8THROW_ERROR("Locale: Date.fromLocaleDateString(): Invalid datetime format");
382         }
383     } else {
384         dt = r->locale.toDate(dateString, enumFormat);
385     }
386
387     return QJSConverter::toDateTime(QDateTime(dt));
388 }
389
390 //-----------------
391 // Number extension
392
393 static const char *numberToLocaleStringFunction =
394         "(function(toLocaleStringFunc) { "
395         "  var orig_toLocaleString;"
396         "  orig_toLocaleString = Number.prototype.toLocaleString;"
397         "  Number.prototype.toLocaleString = (function() {"
398         "    var val = toLocaleStringFunc.apply(this, arguments);"
399         "    if (val == undefined) val = orig_toLocaleString.call(this);"
400         "    return val;"
401         "  })"
402         "})";
403
404 static const char *numberToLocaleCurrencyStringFunction =
405         "(function(toLocaleCurrencyStringFunc) { "
406         "  Number.prototype.toLocaleCurrencyString = (function() {"
407         "    return toLocaleCurrencyStringFunc.apply(this, arguments);"
408         "  })"
409         "})";
410
411 static const char *numberFromLocaleStringFunction =
412         "(function(fromLocaleStringFunc) { "
413         "  Number.fromLocaleString = (function() {"
414         "    return fromLocaleStringFunc.apply(null, arguments);"
415         "  })"
416         "})";
417
418
419 void QDeclarativeNumberExtension::registerExtension(QV8Engine *engine)
420 {
421     registerFunction(engine, numberToLocaleStringFunction, toLocaleString);
422     registerFunction(engine, numberToLocaleCurrencyStringFunction, toLocaleCurrencyString);
423     registerFunction(engine, numberFromLocaleStringFunction, fromLocaleString);
424 }
425
426 v8::Handle<v8::Value> QDeclarativeNumberExtension::toLocaleString(const v8::Arguments& args)
427 {
428     if (args.Length() > 3)
429         V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
430
431     double number = args.This()->ToNumber()->Value();
432
433     if (args.Length() == 0) {
434         // Use QLocale for standard toLocaleString() function
435         QLocale locale;
436         return QJSConverter::toString(locale.toString(number));
437     }
438
439     if (!isLocaleObject(args[0]))
440         return v8::Undefined(); // Use the default Number toLocaleString()
441
442     GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
443
444     uint16_t format = 'f';
445     if (args.Length() > 1) {
446         if (!args[1]->IsString())
447             V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
448         v8::Local<v8::String> fs = args[1]->ToString();
449         if (!fs.IsEmpty() && fs->Length())
450             format = fs->GetCharacter(0);
451     }
452     int prec = 2;
453     if (args.Length() > 2) {
454         if (!args[2]->IsNumber())
455             V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
456          prec = args[2]->IntegerValue();
457     }
458
459     return r->engine->toString(r->locale.toString(number, (char)format, prec));
460 }
461
462 v8::Handle<v8::Value> QDeclarativeNumberExtension::toLocaleCurrencyString(const v8::Arguments& args)
463 {
464     if (args.Length() > 2)
465         V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
466
467     double number = args.This()->ToNumber()->Value();
468
469     if (args.Length() == 0) {
470         // Use QLocale for standard toLocaleString() function
471         QLocale locale;
472         return QJSConverter::toString(locale.toString(number));
473     }
474
475     if (!isLocaleObject(args[0]))
476         V8THROW_ERROR("Locale: Number.toLocaleCurrencyString(): Invalid arguments");
477
478     GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
479
480     QString symbol;
481     if (args.Length() > 1) {
482         if (!args[1]->IsString())
483             V8THROW_ERROR("Locale: Number.toLocaleString(): Invalid arguments");
484         symbol = r->engine->toString(args[1]->ToString());
485     }
486
487     return r->engine->toString(r->locale.toCurrencyString(number, symbol));
488 }
489
490 v8::Handle<v8::Value> QDeclarativeNumberExtension::fromLocaleString(const v8::Arguments& args)
491 {
492     if (args.Length() < 1 || args.Length() > 2)
493         V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
494
495     int numberIdx = 0;
496     QLocale locale;
497
498     if (args.Length() == 2) {
499         if (!isLocaleObject(args[0]))
500             V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid arguments");
501
502         GET_LOCALE_DATA_RESOURCE(args[0]->ToObject());
503         locale = r->locale;
504
505         numberIdx = 1;
506     }
507
508     v8::Local<v8::String> ns = args[numberIdx]->ToString();
509     if (ns.IsEmpty() || ns->Length() == 0)
510         return v8::Number::New(Q_QNAN);
511
512     bool ok = false;
513     double val = locale.toDouble(QJSConverter::toString(ns), &ok);
514
515     if (!ok)
516         V8THROW_ERROR("Locale: Number.fromLocaleString(): Invalid format")
517
518     return v8::Number::New(val);
519 }
520
521 //--------------
522 // Locale object
523
524 static v8::Handle<v8::Value> locale_get_firstDayOfWeek(v8::Local<v8::String>, const v8::AccessorInfo &info)
525 {
526     GET_LOCALE_DATA_RESOURCE(info.This());
527     return v8::Integer::New(r->locale.firstDayOfWeek());
528 }
529
530 static v8::Handle<v8::Value> locale_get_measurementSystem(v8::Local<v8::String>, const v8::AccessorInfo &info)
531 {
532     GET_LOCALE_DATA_RESOURCE(info.This());
533     return v8::Integer::New(r->locale.measurementSystem());
534 }
535
536 static v8::Handle<v8::Value> locale_get_textDirection(v8::Local<v8::String>, const v8::AccessorInfo &info)
537 {
538     GET_LOCALE_DATA_RESOURCE(info.This());
539     return v8::Integer::New(r->locale.textDirection());
540 }
541
542 static v8::Handle<v8::Value> locale_get_weekDays(v8::Local<v8::String>, const v8::AccessorInfo &info)
543 {
544     GET_LOCALE_DATA_RESOURCE(info.This());
545
546     QList<Qt::DayOfWeek> days = r->locale.weekdays();
547
548     v8::Handle<v8::Array> result = v8::Array::New(days.size());
549     for (int i = 0; i < days.size(); ++i) {
550         int day = days.at(i);
551         if (day == 7) // JS Date days in range 0(Sunday) to 6(Saturday)
552             day = 0;
553         result->Set(i, v8::Integer::New(day));
554     }
555
556     return result;
557 }
558
559 static v8::Handle<v8::Value> locale_currencySymbol(const v8::Arguments &args)
560 {
561     GET_LOCALE_DATA_RESOURCE(args.This());
562
563     if (args.Length() > 1)
564         V8THROW_ERROR("Locale: currencySymbol(): Invalid arguments");
565
566     QLocale::CurrencySymbolFormat format = QLocale::CurrencySymbol;
567     if (args.Length() == 1) {
568         quint32 intFormat = args[0]->ToNumber()->Value();
569         format = QLocale::CurrencySymbolFormat(intFormat);
570     }
571
572     return r->engine->toString(r->locale.currencySymbol(format));
573 }
574
575 #define LOCALE_FORMAT(FUNC) \
576 static v8::Handle<v8::Value> locale_ ##FUNC (const v8::Arguments &args) { \
577     GET_LOCALE_DATA_RESOURCE(args.This());\
578     if (args.Length() > 1) \
579         V8THROW_ERROR("Locale: " #FUNC "(): Invalid arguments"); \
580     QLocale::FormatType format = QLocale::LongFormat;\
581     if (args.Length() == 1) { \
582         quint32 intFormat = args[0]->Uint32Value(); \
583         format = QLocale::FormatType(intFormat); \
584     } \
585     return r->engine->toString(r->locale. FUNC (format)); \
586 }
587
588 LOCALE_FORMAT(dateTimeFormat)
589 LOCALE_FORMAT(timeFormat)
590 LOCALE_FORMAT(dateFormat)
591
592 // +1 added to idx because JS is 0-based, whereas QLocale months begin at 1.
593 #define LOCALE_FORMATTED_MONTHNAME(VARIABLE) \
594 static v8::Handle<v8::Value> locale_ ## VARIABLE (const v8::Arguments &args) {\
595     GET_LOCALE_DATA_RESOURCE(args.This()); \
596     if (args.Length() < 1 || args.Length() > 2) \
597         V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
598     QLocale::FormatType enumFormat = QLocale::LongFormat; \
599     int idx = args[0]->IntegerValue() + 1; \
600     if (idx < 1 || idx > 12) \
601         V8THROW_ERROR("Locale: Invalid month"); \
602     QString name; \
603     if (args.Length() == 2) { \
604         if (args[1]->IsNumber()) { \
605             quint32 intFormat = args[1]->IntegerValue(); \
606             QLocale::FormatType format = QLocale::FormatType(intFormat); \
607             name = r->locale. VARIABLE(idx, format); \
608         } else { \
609             V8THROW_ERROR("Locale: Invalid datetime format"); \
610         } \
611     } else { \
612         name = r->locale. VARIABLE(idx, enumFormat); \
613     } \
614     return r->engine->toString(name); \
615 }
616
617 // 0 -> 7 as Qt::Sunday is 7, but Sunday is 0 in JS Date
618 #define LOCALE_FORMATTED_DAYNAME(VARIABLE) \
619 static v8::Handle<v8::Value> locale_ ## VARIABLE (const v8::Arguments &args) {\
620     GET_LOCALE_DATA_RESOURCE(args.This()); \
621     if (args.Length() < 1 || args.Length() > 2) \
622         V8THROW_ERROR("Locale: " #VARIABLE "(): Invalid arguments"); \
623     QLocale::FormatType enumFormat = QLocale::LongFormat; \
624     int idx = args[0]->IntegerValue(); \
625     if (idx < 0 || idx > 7) \
626         V8THROW_ERROR("Locale: Invalid day"); \
627     if (idx == 0) idx = 7; \
628     QString name; \
629     if (args.Length() == 2) { \
630         if (args[1]->IsNumber()) { \
631             quint32 intFormat = args[1]->ToNumber()->Value(); \
632             QLocale::FormatType format = QLocale::FormatType(intFormat); \
633             name = r->locale. VARIABLE(idx, format); \
634         } else { \
635             V8THROW_ERROR("Locale: Invalid datetime format"); \
636         } \
637     } else { \
638         name = r->locale. VARIABLE(idx, enumFormat); \
639     } \
640     return r->engine->toString(name); \
641 }
642
643
644 #define LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(FT, VARIABLE, ENGINE) \
645     FT->PrototypeTemplate()->Set(v8::String::New( #VARIABLE ), V8FUNCTION(locale_ ## VARIABLE, ENGINE));
646
647 LOCALE_FORMATTED_MONTHNAME(monthName)
648 LOCALE_FORMATTED_MONTHNAME(standaloneMonthName)
649 LOCALE_FORMATTED_DAYNAME(dayName)
650 LOCALE_FORMATTED_DAYNAME(standaloneDayName)
651
652 #define LOCALE_STRING_PROPERTY(VARIABLE) static v8::Handle<v8::Value> locale_get_ ## VARIABLE (v8::Local<v8::String>, const v8::AccessorInfo &info) \
653 { \
654     GET_LOCALE_DATA_RESOURCE(info.This()); \
655     return r->engine->toString(r->locale. VARIABLE());\
656 }
657
658 #define LOCALE_REGISTER_STRING_ACCESSOR(FT, VARIABLE) \
659     FT ->PrototypeTemplate()->SetAccessor( v8::String::New( #VARIABLE ), locale_get_ ## VARIABLE )
660
661
662 LOCALE_STRING_PROPERTY(name)
663 LOCALE_STRING_PROPERTY(nativeLanguageName)
664 LOCALE_STRING_PROPERTY(nativeCountryName)
665 LOCALE_STRING_PROPERTY(decimalPoint)
666 LOCALE_STRING_PROPERTY(groupSeparator)
667 LOCALE_STRING_PROPERTY(percent)
668 LOCALE_STRING_PROPERTY(zeroDigit)
669 LOCALE_STRING_PROPERTY(negativeSign)
670 LOCALE_STRING_PROPERTY(positiveSign)
671 LOCALE_STRING_PROPERTY(exponential)
672 LOCALE_STRING_PROPERTY(amText)
673 LOCALE_STRING_PROPERTY(pmText)
674
675 class QV8LocaleDataDeletable : public QV8Engine::Deletable
676 {
677 public:
678     QV8LocaleDataDeletable(QV8Engine *engine);
679     ~QV8LocaleDataDeletable();
680
681     v8::Persistent<v8::Function> constructor;
682 };
683
684 QV8LocaleDataDeletable::QV8LocaleDataDeletable(QV8Engine *engine)
685 {
686     v8::HandleScope handle_scope;
687     v8::Context::Scope scope(engine->context());
688
689     v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
690     ft->InstanceTemplate()->SetHasExternalResource(true);
691
692     LOCALE_REGISTER_STRING_ACCESSOR(ft, name);
693     LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeLanguageName);
694     LOCALE_REGISTER_STRING_ACCESSOR(ft, nativeCountryName);
695     LOCALE_REGISTER_STRING_ACCESSOR(ft, decimalPoint);
696     LOCALE_REGISTER_STRING_ACCESSOR(ft, groupSeparator);
697     LOCALE_REGISTER_STRING_ACCESSOR(ft, percent);
698     LOCALE_REGISTER_STRING_ACCESSOR(ft, zeroDigit);
699     LOCALE_REGISTER_STRING_ACCESSOR(ft, negativeSign);
700     LOCALE_REGISTER_STRING_ACCESSOR(ft, positiveSign);
701     LOCALE_REGISTER_STRING_ACCESSOR(ft, exponential);
702     LOCALE_REGISTER_STRING_ACCESSOR(ft, amText);
703     LOCALE_REGISTER_STRING_ACCESSOR(ft, pmText);
704
705     ft->PrototypeTemplate()->Set(v8::String::New("currencySymbol"), V8FUNCTION(locale_currencySymbol, engine));
706
707     ft->PrototypeTemplate()->Set(v8::String::New("dateTimeFormat"), V8FUNCTION(locale_dateTimeFormat, engine));
708     ft->PrototypeTemplate()->Set(v8::String::New("dateFormat"), V8FUNCTION(locale_dateFormat, engine));
709     ft->PrototypeTemplate()->Set(v8::String::New("timeFormat"), V8FUNCTION(locale_timeFormat, engine));
710
711     LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, monthName, engine);
712     LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneMonthName, engine);
713     LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, dayName, engine);
714     LOCALE_REGISTER_FORMATTED_NAME_FUNCTION(ft, standaloneDayName, engine);
715
716     ft->PrototypeTemplate()->SetAccessor(v8::String::New("firstDayOfWeek"), locale_get_firstDayOfWeek);
717     ft->PrototypeTemplate()->SetAccessor(v8::String::New("weekDays"), locale_get_weekDays);
718     ft->PrototypeTemplate()->SetAccessor(v8::String::New("measurementSystem"), locale_get_measurementSystem);
719     ft->PrototypeTemplate()->SetAccessor(v8::String::New("textDirection"), locale_get_textDirection);
720
721     constructor = qPersistentNew(ft->GetFunction());
722 }
723
724 QV8LocaleDataDeletable::~QV8LocaleDataDeletable()
725 {
726     qPersistentDispose(constructor);
727 }
728
729 V8_DEFINE_EXTENSION(QV8LocaleDataDeletable, localeV8Data);
730
731 /*!
732     \qmlclass Locale QDeclarativeLocale
733     \inqmlmodule QtQuick 2
734     \brief The Locale object provides locale specific properties and formatted data.
735
736     The Locale object is created via the \l{QML:Qt::locale()}{Qt.locale()} function.  It cannot be created
737     directly.
738
739     The \l{QML:Qt::locale()}{Qt.locale()} function returns a JS Locale object representing the
740     locale with the specified name, which has the format
741     "language[_territory][.codeset][@modifier]" or "C".
742
743     Locale supports the concept of a default locale, which is
744     determined from the system's locale settings at application
745     startup.  If no parameter is passed to Qt.locale() the default
746     locale object is returned.
747
748     The Locale object provides a number of functions and properties
749     providing data for the specified locale.
750
751     The Locale object may also be passed to the \l Date and \l Number toLocaleString()
752     and fromLocaleString() methods in order to convert to/from strings using
753     the specified locale.
754
755     This example shows the current date formatted for the German locale:
756
757     \code
758     import QtQuick 2.0
759
760     Text {
761         text: "The date is: " + Date().toLocaleString(Qt.locale("de_DE"))
762     }
763     \endcode
764
765     The following example displays the specified number
766     in the correct format for the default locale:
767
768     \code
769     import QtQuick 2.0
770
771     Text {
772         text: "The value is: " + Number(23443.34).toLocaleString(Qt.locale())
773     }
774     \endcode
775
776     QtQuick Locale's data is based on Common Locale Data Repository v1.8.1.
777
778     The double-to-string and string-to-double conversion functions are
779     covered by the following licenses:
780
781     \legalese
782     Copyright (c) 1991 by AT&T.
783
784     Permission to use, copy, modify, and distribute this software for any
785     purpose without fee is hereby granted, provided that this entire notice
786     is included in all copies of any software which is or includes a copy
787     or modification of this software and in all copies of the supporting
788     documentation for such software.
789
790     THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
791     WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR AT&T MAKES ANY
792     REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
793     OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
794
795     This product includes software developed by the University of
796     California, Berkeley and its contributors.
797
798     \sa {QtQuick2::Date}{Date} {QtQuick2::Number}{Number}
799 */
800
801 QDeclarativeLocale::QDeclarativeLocale()
802 {
803 }
804
805 QDeclarativeLocale::~QDeclarativeLocale()
806 {
807 }
808
809 v8::Handle<v8::Value> QDeclarativeLocale::locale(QV8Engine *v8engine, const QString &locale)
810 {
811     QV8LocaleDataDeletable *d = localeV8Data(v8engine);
812     v8::Local<v8::Object> v8Value = d->constructor->NewInstance();
813     QV8LocaleDataResource *r = new QV8LocaleDataResource(v8engine);
814     if (locale.isEmpty())
815         r->locale = QLocale();
816     else
817         r->locale = QLocale(locale);
818     v8Value->SetExternalResource(r);
819
820     return v8Value;
821 }
822
823 /*!
824     \enum QtQuick2::Locale::FormatType
825
826     This enumeration describes the types of format that can be used when
827     converting Date objects to strings.
828
829     \value LongFormat The long version of day and month names; for
830     example, returning "January" as a month name.
831
832     \value ShortFormat The short version of day and month names; for
833     example, returning "Jan" as a month name.
834
835     \value NarrowFormat A special version of day and month names for
836     use when space is limited; for example, returning "J" as a month
837     name. Note that the narrow format might contain the same text for
838     different months and days or it can even be an empty string if the
839     locale doesn't support narrow names, so you should avoid using it
840     for date formatting. Also, for the system locale this format is
841     the same as ShortFormat.
842 */
843
844 /*!
845     \qmlproperty string QtQuick2::Locale::name
846
847     Holds the language and country of this locale as a
848     string of the form "language_country", where
849     language is a lowercase, two-letter ISO 639 language code,
850     and country is an uppercase, two- or three-letter ISO 3166 country code.
851 */
852
853 /*!
854     \qmlproperty string QtQuick2::Locale::decimalPoint
855
856     Holds the decimal point character of this locale.
857 */
858
859 /*!
860     \qmlproperty string QtQuick2::Locale::groupSeparator
861
862     Holds the group separator character of this locale.
863 */
864
865 /*!
866     \qmlproperty string QtQuick2::Locale::percent
867
868     Holds the percent character of this locale.
869 */
870
871
872 /*!
873     \qmlproperty string QtQuick2::Locale::zeroDigit
874
875     Holds Returns the zero digit character of this locale.
876 */
877
878 /*!
879     \qmlproperty string QtQuick2::Locale::negativeSign
880
881     Holds the negative sign character of this locale.
882 */
883
884 /*!
885     \qmlproperty string QtQuick2::Locale::positiveSign
886
887     Holds the positive sign character of this locale.
888 */
889
890 /*!
891     \qmlproperty string QtQuick2::Locale::exponential
892
893     Holds the exponential character of this locale.
894 */
895
896 /*!
897     \qmlmethod string QtQuick2::Locale::dateTimeFormat(type)
898
899     Returns the date time format used for the current locale.
900     \a type specifies the FormatType to return.
901
902     \sa {QtQuick2::Date}{Date}
903 */
904
905 /*!
906     \qmlmethod string QtQuick2::Locale::dateFormat(type)
907
908     Returns the date format used for the current locale.
909     \a type specifies the FormatType to return.
910
911     \sa {QtQuick2::Date}{Date}
912 */
913
914 /*!
915     \qmlmethod string QtQuick2::Locale::timeFormat(type)
916
917     Returns the time format used for the current locale.
918     \a type specifies the FormatType to return.
919
920     \sa {QtQuick2::Date}{Date}
921 */
922
923 /*!
924     \qmlmethod string QtQuick2::Locale::monthName(month, type)
925
926     Returns the localized name of \a month (0-11), in the optional
927     \l FortmatType specified by \a type.
928
929     \note the QLocale C++ API expects a range of (1-12), however Locale.monthName()
930     expects 0-11 as per the JS Date object.
931
932     \sa dayName(), standaloneMonthName()
933 */
934
935 /*!
936     \qmlmethod string QtQuick2::Locale::standaloneMonthName(month, type)
937
938     Returns the localized name of \a month (0-11) that is used as a
939     standalone text, in the optional \l FormatType specified by \a type.
940
941     If the locale information doesn't specify the standalone month
942     name then return value is the same as in monthName().
943
944     \note the QLocale C++ API expects a range of (1-12), however Locale.standaloneMonthName()
945     expects 0-11 as per the JS Date object.
946
947     \sa monthName(), standaloneDayName()
948 */
949
950 /*!
951     \qmlmethod string QtQuick2::Locale::dayName(day, type)
952
953     Returns the localized name of the \a day (where 0 represents
954     Sunday, 1 represents Monday and so on), in the optional
955     \l FormatType specified by \a type.
956
957     \sa monthName(), standaloneDayName()
958 */
959
960 /*!
961     \qmlmethod string QtQuick2::Locale::standaloneDayName(day, type)
962
963     Returns the localized name of the \a day (where 0 represents
964     Sunday, 1 represents Monday and so on) that is used as a
965     standalone text, in the \l FormatType specified by \a type.
966
967     If the locale information does not specify the standalone day
968     name then return value is the same as in dayName().
969
970     \sa dayName(), standaloneMonthName()
971 */
972
973 /*!
974     \qmlproperty enumeration QtQuick2::Locale::firstDayOfWeek
975
976     Holds the first day of the week according to the current locale.
977
978     \list
979     \o Locale.Sunday = 0
980     \o Locale.Monday = 1
981     \o Locale.Tuesday = 2
982     \o Locale.Wednesday = 3
983     \o Locale.Thursday = 4
984     \o Locale.Friday = 5
985     \o Locale.Saturday = 6
986     \endlist
987
988     \note that these values match the JS Date API which is different
989     from the Qt C++ API where Qt::Sunday = 7.
990 */
991
992 /*!
993     \qmlproperty Array<int> QtQuick2::Locale::weekDays
994
995     Holds an array of days that are considered week days according to the current locale,
996     where Sunday is 0 and Saturday is 6.
997
998     \sa firstDayOfWeek
999 */
1000
1001
1002 /*!
1003     \qmlproperty enumeration QtQuick2::Locale::textDirection
1004
1005     Holds the text direction of the language:
1006     \list
1007     \o Qt.LeftToRight
1008     \o Qt.RightToLeft
1009     \endlist
1010 */
1011
1012 /*!
1013     \qmlproperty string QtQuick2::Locale::amText
1014
1015     The localized name of the "AM" suffix for times specified using the conventions of the 12-hour clock.
1016 */
1017
1018 /*!
1019     \qmlproperty string QtQuick2::Locale::pmText
1020
1021     The localized name of the "PM" suffix for times specified using the conventions of the 12-hour clock.
1022 */
1023
1024 /*!
1025     \qmlmethod string QtQuick2::Locale::currencySymbol(format)
1026
1027     Returns the currency symbol for the specified \a format:
1028     \list
1029     \o Locale.CurrencyIsoCode a ISO-4217 code of the currency.
1030     \o Locale.CurrencySymbol a currency symbol.
1031     \o Locale.CurrencyDisplayName a user readable name of the currency.
1032     \endlist
1033     \sa Number::toLocaleCurrencyString()
1034 */
1035
1036 /*!
1037     \qmlproperty string QtQuick2::Locale::nativeLanguageName
1038
1039     Holds a native name of the language for the locale. For example
1040     "Schwiizertüütsch" for Swiss-German locale.
1041
1042     \sa nativeCountryName
1043 */
1044
1045 /*!
1046     \qmlproperty string QtQuick2::Locale::nativeCountryName
1047
1048     Holds a native name of the country for the locale. For example
1049     "España" for Spanish/Spain locale.
1050
1051     \sa nativeLanguageName
1052 */
1053
1054 /*!
1055     \qmlproperty enumeration QtQuick2::Locale::measurementSystem
1056
1057     This property defines which units are used for measurement.
1058
1059     \list
1060     \o Locale.MetricSystem This value indicates metric units, such as meters,
1061         centimeters and millimeters.
1062     \o Locale.ImperialSystem This value indicates imperial units, such as inches and
1063         miles. There are several distinct imperial systems in the world; this
1064         value stands for the official United States imperial units.
1065     \endlist
1066 */
1067
1068 QT_END_NAMESPACE