Speed up view flick tests.
[profile/ivi/qtdeclarative.git] / src / qml / qml / v8 / qqmlbuiltinfunctions.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 QtQml 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 "qqmlbuiltinfunctions_p.h"
43
44 #include <QtQml/qqmlcomponent.h>
45 #include <private/qqmlengine_p.h>
46 #include <private/qqmlcomponent_p.h>
47 #include <private/qqmlstringconverters_p.h>
48 #include <private/qqmllocale_p.h>
49 #include <private/qv8engine_p.h>
50 #include <private/qjsconverter_impl_p.h>
51
52 #include <private/qv8profilerservice_p.h>
53 #include <private/qqmlprofilerservice_p.h>
54
55 #include <QtCore/qstring.h>
56 #include <QtCore/qdatetime.h>
57 #include <QtCore/qcryptographichash.h>
58 #include <QtCore/qrect.h>
59 #include <QtCore/qsize.h>
60 #include <QtCore/qpoint.h>
61 #include <QtCore/qurl.h>
62 #include <QtCore/qfile.h>
63 #include <QtCore/qcoreapplication.h>
64
65 #include <QtGui/qcolor.h>
66 #include <QtGui/qvector3d.h>
67 #include <QtGui/qvector4d.h>
68 #include <QtGui/qdesktopservices.h>
69 #include <QtGui/qfontdatabase.h>
70
71 QT_BEGIN_NAMESPACE
72
73 namespace QQmlBuiltinFunctions {
74
75 enum ConsoleLogTypes {
76     Log,
77     Warn,
78     Error
79 };
80
81 static void jsContext(v8::Handle<v8::Value> *file, int *line, v8::Handle<v8::Value> *function) {
82     v8::Local<v8::StackTrace> stackTrace = v8::StackTrace::CurrentStackTrace(1);
83     if (stackTrace->GetFrameCount()) {
84         v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(0);
85         *file = frame->GetScriptName();
86         *line = frame->GetLineNumber();
87         *function = frame->GetFunctionName();
88     }
89 }
90
91 static QString jsStack() {
92     QStringList stackFrames;
93
94     //The v8 default is currently 10 stack frames.
95     v8::Handle<v8::StackTrace> stackTrace =
96         v8::StackTrace::CurrentStackTrace(10, v8::StackTrace::kOverview);
97     int stackCount = stackTrace->GetFrameCount();
98
99     for (int i = 0; i < stackCount; i++) {
100         v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(i);
101         v8::Handle<v8::String> function(frame->GetFunctionName());
102         v8::Handle<v8::String> script(frame->GetScriptName());
103         int lineNumber = frame->GetLineNumber();
104         int columnNumber = frame->GetColumn();
105
106         QString stackFrame =
107                 QString::fromLatin1("%1 (%2:%3:%4)").arg(QJSConverter::toString(function),
108                                                          QJSConverter::toString(script),
109                                                          QString::number(lineNumber),
110                                                          QString::number(columnNumber));
111         stackFrames.append(stackFrame);
112     }
113     return stackFrames.join(QLatin1String("\n"));
114 }
115
116 v8::Handle<v8::Value> console(ConsoleLogTypes logType, const v8::Arguments &args,
117                               bool printStack = false)
118 {
119     v8::HandleScope handleScope;
120
121     QString result;
122     for (int i = 0; i < args.Length(); ++i) {
123         if (i != 0)
124             result.append(QLatin1Char(' '));
125
126         v8::Local<v8::Value> value = args[i];
127         //Check for Object Type
128         if (value->IsObject() && !value->IsFunction()
129                 && !value->IsArray() && !value->IsDate()
130                 && !value->IsRegExp()) {
131             result.append(QLatin1String("Object"));
132         } else {
133             v8::Local<v8::String> jsstr = value->ToString();
134             QString tmp = V8ENGINE()->toString(jsstr);
135             if (value->IsArray())
136                 result.append(QString::fromLatin1("[%1]").arg(tmp));
137             else
138                 result.append(tmp);
139         }
140     }
141
142     if (printStack) {
143         result.append(QLatin1String("\n"));
144         result.append(jsStack());
145     }
146
147     v8::Handle<v8::Value> fileHandle;
148     v8::Handle<v8::Value> functionHandle;
149     int line;
150
151     jsContext(&fileHandle, &line, &functionHandle);
152
153     switch (logType) {
154     case Log:
155         QMessageLogger(*v8::String::AsciiValue(fileHandle), line,
156                        *v8::String::AsciiValue(functionHandle)).debug("%s", qPrintable(result));
157         break;
158     case Warn:
159         QMessageLogger(*v8::String::AsciiValue(fileHandle), line,
160                        *v8::String::AsciiValue(functionHandle)).warning("%s", qPrintable(result));
161         break;
162     case Error:
163         QMessageLogger(*v8::String::AsciiValue(fileHandle), line,
164                        *v8::String::AsciiValue(functionHandle)).critical("%s", qPrintable(result));
165         break;
166     default:
167         break;
168     }
169
170     return v8::Undefined();
171 }
172
173 v8::Handle<v8::Value> gc(const v8::Arguments &args)
174 {
175     Q_UNUSED(args);
176     QV8Engine::gc();
177     return v8::Undefined();
178 }
179
180 v8::Handle<v8::Value> consoleError(const v8::Arguments &args)
181 {
182     return console(Error, args);
183 }
184
185 v8::Handle<v8::Value> consoleLog(const v8::Arguments &args)
186 {
187     //console.log
188     //console.debug
189     //console.info
190     //print
191     return console(Log, args);
192 }
193
194 v8::Handle<v8::Value> consoleProfile(const v8::Arguments &args)
195 {
196     //DeclarativeDebugTrace cannot handle nested profiling
197     //although v8 can handle several profiling at once,
198     //we do not allow that. Hence, we pass an empty(default) title
199     Q_UNUSED(args);
200     QString title;
201
202
203
204     v8::Handle<v8::Value> file;
205     v8::Handle<v8::Value> function;
206     int line;
207     jsContext(&file, &line, &function);
208
209     if (QQmlProfilerService::startProfiling()) {
210         QV8ProfilerService::instance()->startProfiling(title);
211
212         QMessageLogger(*v8::String::AsciiValue(file), line,
213                        *v8::String::AsciiValue(function)).debug("Profiling started.");
214     } else {
215         QMessageLogger(*v8::String::AsciiValue(file), line,
216                        *v8::String::AsciiValue(function)).warning(
217                     "Profiling is already in progress. First, end current profiling session.");
218     }
219
220     return v8::Undefined();
221 }
222
223 v8::Handle<v8::Value> consoleProfileEnd(const v8::Arguments &args)
224 {
225     //DeclarativeDebugTrace cannot handle nested profiling
226     //although v8 can handle several profiling at once,
227     //we do not allow that. Hence, we pass an empty(default) title
228     Q_UNUSED(args);
229     QString title;
230
231     v8::Handle<v8::Value> file;
232     v8::Handle<v8::Value> function;
233     int line;
234     jsContext(&file, &line, &function);
235
236     if (QQmlProfilerService::stopProfiling()) {
237         QV8ProfilerService *profiler = QV8ProfilerService::instance();
238         profiler->stopProfiling(title);
239         QQmlProfilerService::sendProfilingData();
240         profiler->sendProfilingData();
241
242         QMessageLogger(*v8::String::AsciiValue(file), line,
243                        *v8::String::AsciiValue(function)).debug("Profiling ended.");
244     } else {
245         QMessageLogger(*v8::String::AsciiValue(file), line,
246                        *v8::String::AsciiValue(function)).warning("Profiling was not started.");
247     }
248
249     return v8::Undefined();
250 }
251
252 v8::Handle<v8::Value> consoleTime(const v8::Arguments &args)
253 {
254     if (args.Length() != 1)
255         V8THROW_ERROR("console.time(): Invalid arguments");
256     QString name = V8ENGINE()->toString(args[0]);
257     V8ENGINE()->startTimer(name);
258     return v8::Undefined();
259 }
260
261 v8::Handle<v8::Value> consoleTimeEnd(const v8::Arguments &args)
262 {
263     if (args.Length() != 1)
264         V8THROW_ERROR("console.time(): Invalid arguments");
265     QString name = V8ENGINE()->toString(args[0]);
266     bool wasRunning;
267     qint64 elapsed = V8ENGINE()->stopTimer(name, &wasRunning);
268     if (wasRunning) {
269         qDebug("%s: %llims", qPrintable(name), elapsed);
270     }
271     return v8::Undefined();
272 }
273
274 v8::Handle<v8::Value> consoleCount(const v8::Arguments &args)
275 {
276     // first argument: name to print. Ignore any additional arguments
277     QString name;
278     if (args.Length() > 0)
279         name = V8ENGINE()->toString(args[0]);
280
281     v8::Handle<v8::StackTrace> stackTrace =
282         v8::StackTrace::CurrentStackTrace(1, v8::StackTrace::kOverview);
283
284     if (stackTrace->GetFrameCount()) {
285         v8::Local<v8::StackFrame> frame = stackTrace->GetFrame(0);
286
287         QString scriptName = V8ENGINE()->toString(frame->GetScriptName());
288         QString functionName = V8ENGINE()->toString(frame->GetFunctionName());
289         int line = frame->GetLineNumber();
290         int column = frame->GetColumn();
291
292         int value = V8ENGINE()->consoleCountHelper(scriptName, line, column);
293         QString message = name + QLatin1String(": ") + QString::number(value);
294
295         QMessageLogger(qPrintable(scriptName), line,
296                        qPrintable(functionName)).debug("%s", qPrintable(message));
297     }
298
299     return v8::Undefined();
300 }
301
302 v8::Handle<v8::Value> consoleTrace(const v8::Arguments &args)
303 {
304     if (args.Length() != 0)
305         V8THROW_ERROR("console.trace(): Invalid arguments");
306
307     QString stack = jsStack();
308
309     v8::Handle<v8::Value> file;
310     v8::Handle<v8::Value> function;
311     int line;
312     jsContext(&file, &line, &function);
313
314     QMessageLogger(*v8::String::AsciiValue(file), line, *v8::String::AsciiValue(function)).debug(
315                 "%s", qPrintable(stack));
316     return v8::Undefined();
317 }
318
319 v8::Handle<v8::Value> consoleWarn(const v8::Arguments &args)
320 {
321     return console(Warn, args);
322 }
323
324 v8::Handle<v8::Value> consoleAssert(const v8::Arguments &args)
325 {
326     if (args.Length() == 0)
327         V8THROW_ERROR("console.assert(): Missing argument");
328
329     if (!args[0]->ToBoolean()->Value()) {
330         QString message;
331         for (int i = 1; i < args.Length(); ++i) {
332             if (i != 1)
333                 message.append(QLatin1Char(' '));
334
335             v8::Local<v8::Value> value = args[i];
336             message.append(V8ENGINE()->toString(value->ToString()));
337         }
338
339         QString stack = jsStack();
340
341         v8::Handle<v8::Value> file;
342         v8::Handle<v8::Value> function;
343         int line;
344         jsContext(&file, &line, &function);
345
346         QMessageLogger(*v8::String::AsciiValue(file), line, *v8::String::AsciiValue(function)).critical(
347                     "%s\n%s", qPrintable(message), qPrintable(stack));
348
349     }
350     return v8::Undefined();
351 }
352
353 v8::Handle<v8::Value> consoleException(const v8::Arguments &args)
354 {
355     if (args.Length() == 0)
356         V8THROW_ERROR("console.exception(): Missing argument");
357
358     console(Error, args, true);
359
360     return v8::Undefined();
361 }
362
363 v8::Handle<v8::Value> stringArg(const v8::Arguments &args)
364 {
365     QString value = V8ENGINE()->toString(args.This()->ToString());
366     if (args.Length() != 1)
367         V8THROW_ERROR("String.arg(): Invalid arguments");
368
369     v8::Handle<v8::Value> arg = args[0];
370     if (arg->IsUint32())
371         return V8ENGINE()->toString(value.arg(arg->Uint32Value()));
372     else if (arg->IsInt32())
373         return V8ENGINE()->toString(value.arg(arg->Int32Value()));
374     else if (arg->IsNumber())
375         return V8ENGINE()->toString(value.arg(arg->NumberValue()));
376     else if (arg->IsBoolean())
377         return V8ENGINE()->toString(value.arg(arg->BooleanValue()));
378
379     return V8ENGINE()->toString(value.arg(V8ENGINE()->toString(arg)));
380 }
381
382 /*!
383 \qmlmethod bool Qt::isQtObject(object)
384 Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
385 */
386 v8::Handle<v8::Value> isQtObject(const v8::Arguments &args)
387 {
388     if (args.Length() == 0)
389         return v8::Boolean::New(false);
390
391     return v8::Boolean::New(0 != V8ENGINE()->toQObject(args[0]));
392 }
393
394 /*!
395 \qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
396
397 Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
398 All components should be in the range 0-1 inclusive.
399 */
400 v8::Handle<v8::Value> rgba(const v8::Arguments &args)
401 {
402     int argCount = args.Length();
403     if (argCount < 3 || argCount > 4)
404         V8THROW_ERROR("Qt.rgba(): Invalid arguments");
405
406     double r = args[0]->NumberValue();
407     double g = args[1]->NumberValue();
408     double b = args[2]->NumberValue();
409     double a = (argCount == 4) ? args[3]->NumberValue() : 1;
410
411     if (r < 0.0) r=0.0;
412     if (r > 1.0) r=1.0;
413     if (g < 0.0) g=0.0;
414     if (g > 1.0) g=1.0;
415     if (b < 0.0) b=0.0;
416     if (b > 1.0) b=1.0;
417     if (a < 0.0) a=0.0;
418     if (a > 1.0) a=1.0;
419
420     return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromRgbF(r, g, b, a)));
421 }
422
423 /*!
424 \qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
425
426 Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
427 All components should be in the range 0-1 inclusive.
428 */
429 v8::Handle<v8::Value> hsla(const v8::Arguments &args)
430 {
431     int argCount = args.Length();
432     if (argCount < 3 || argCount > 4)
433         V8THROW_ERROR("Qt.hsla(): Invalid arguments");
434
435     double h = args[0]->NumberValue();
436     double s = args[1]->NumberValue();
437     double l = args[2]->NumberValue();
438     double a = (argCount == 4) ? args[3]->NumberValue() : 1;
439
440     if (h < 0.0) h=0.0;
441     if (h > 1.0) h=1.0;
442     if (s < 0.0) s=0.0;
443     if (s > 1.0) s=1.0;
444     if (l < 0.0) l=0.0;
445     if (l > 1.0) l=1.0;
446     if (a < 0.0) a=0.0;
447     if (a > 1.0) a=1.0;
448
449     return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromHslF(h, s, l, a)));
450 }
451
452 /*!
453 \qmlmethod rect Qt::rect(int x, int y, int width, int height)
454
455 Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
456
457 The returned object has \c x, \c y, \c width and \c height attributes with the given values.
458 */
459 v8::Handle<v8::Value> rect(const v8::Arguments &args)
460 {
461     if (args.Length() != 4)
462         V8THROW_ERROR("Qt.rect(): Invalid arguments");
463
464     double x = args[0]->NumberValue();
465     double y = args[1]->NumberValue();
466     double w = args[2]->NumberValue();
467     double h = args[3]->NumberValue();
468
469     return V8ENGINE()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
470 }
471
472 /*!
473 \qmlmethod point Qt::point(int x, int y)
474 Returns a Point with the specified \c x and \c y coordinates.
475 */
476 v8::Handle<v8::Value> point(const v8::Arguments &args)
477 {
478     if (args.Length() != 2)
479         V8THROW_ERROR("Qt.point(): Invalid arguments");
480
481     double x = args[0]->ToNumber()->Value();
482     double y = args[1]->ToNumber()->Value();
483
484     return V8ENGINE()->fromVariant(QVariant::fromValue(QPointF(x, y)));
485 }
486
487 /*!
488 \qmlmethod Qt::size(int width, int height)
489 Returns a Size with the specified \c width and \c height.
490 */
491 v8::Handle<v8::Value> size(const v8::Arguments &args)
492 {
493     if (args.Length() != 2)
494         V8THROW_ERROR("Qt.size(): Invalid arguments");
495
496     double w = args[0]->ToNumber()->Value();
497     double h = args[1]->ToNumber()->Value();
498
499     return V8ENGINE()->fromVariant(QVariant::fromValue(QSizeF(w, h)));
500 }
501
502 /*!
503 \qmlmethod Qt::vector3d(real x, real y, real z)
504 Returns a Vector3D with the specified \c x, \c y and \c z.
505 */
506 v8::Handle<v8::Value> vector3d(const v8::Arguments &args)
507 {
508     if (args.Length() != 3)
509         V8THROW_ERROR("Qt.vector(): Invalid arguments");
510
511     double x = args[0]->ToNumber()->Value();
512     double y = args[1]->ToNumber()->Value();
513     double z = args[2]->ToNumber()->Value();
514
515     return V8ENGINE()->fromVariant(QVariant::fromValue(QVector3D(x, y, z)));
516 }
517
518 /*!
519 \qmlmethod Qt::vector4d(real x, real y, real z, real w)
520 Returns a Vector4D with the specified \c x, \c y, \c z and \c w.
521 */
522 v8::Handle<v8::Value> vector4d(const v8::Arguments &args)
523 {
524     if (args.Length() != 4)
525         V8THROW_ERROR("Qt.vector4d(): Invalid arguments");
526
527     double x = args[0]->NumberValue();
528     double y = args[1]->NumberValue();
529     double z = args[2]->NumberValue();
530     double w = args[3]->NumberValue();
531
532     return V8ENGINE()->fromVariant(QVariant::fromValue(QVector4D(x, y, z, w)));
533 }
534
535 /*!
536 \qmlmethod color Qt::lighter(color baseColor, real factor)
537 Returns a color lighter than \c baseColor by the \c factor provided.
538
539 If the factor is greater than 1.0, this functions returns a lighter color.
540 Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
541 the return color is darker, but we recommend using the Qt.darker() function for this purpose.
542 If the factor is 0 or negative, the return value is unspecified.
543
544 The function converts the current RGB color to HSV, multiplies the value (V) component
545 by factor and converts the color back to RGB.
546
547 If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
548 */
549 v8::Handle<v8::Value> lighter(const v8::Arguments &args)
550 {
551     if (args.Length() != 1 && args.Length() != 2)
552         V8THROW_ERROR("Qt.lighter(): Invalid arguments");
553
554     QColor color;
555     QVariant v = V8ENGINE()->toVariant(args[0], -1);
556     if (v.userType() == QVariant::Color) {
557         color = v.value<QColor>();
558     } else if (v.userType() == QVariant::String) {
559         bool ok = false;
560         color = QQmlStringConverters::colorFromString(v.toString(), &ok);
561         if (!ok) {
562             return v8::Null();
563         }
564     } else {
565         return v8::Null();
566     }
567
568     qreal factor = 1.5;
569     if (args.Length() == 2)
570         factor = args[1]->ToNumber()->Value();
571
572     color = color.lighter(int(qRound(factor*100.)));
573     return V8ENGINE()->fromVariant(QVariant::fromValue(color));
574 }
575
576 /*!
577 \qmlmethod color Qt::darker(color baseColor, real factor)
578 Returns a color darker than \c baseColor by the \c factor provided.
579
580 If the factor is greater than 1.0, this function returns a darker color.
581 Setting factor to 3.0 returns a color that has one-third the brightness.
582 If the factor is less than 1.0, the return color is lighter, but we recommend using
583 the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
584 value is unspecified.
585
586 The function converts the current RGB color to HSV, divides the value (V) component
587 by factor and converts the color back to RGB.
588
589 If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
590 */
591 v8::Handle<v8::Value> darker(const v8::Arguments &args)
592 {
593     if (args.Length() != 1 && args.Length() != 2)
594         V8THROW_ERROR("Qt.darker(): Invalid arguments");
595
596     QColor color;
597     QVariant v = V8ENGINE()->toVariant(args[0], -1);
598     if (v.userType() == QVariant::Color) {
599         color = v.value<QColor>();
600     } else if (v.userType() == QVariant::String) {
601         bool ok = false;
602         color = QQmlStringConverters::colorFromString(v.toString(), &ok);
603         if (!ok) {
604             return v8::Null();
605         }
606     } else {
607         return v8::Null();
608     }
609
610     qreal factor = 2.0;
611     if (args.Length() == 2)
612         factor = args[1]->ToNumber()->Value();
613
614     color = color.darker(int(qRound(factor*100.)));
615     return V8ENGINE()->fromVariant(QVariant::fromValue(color));
616 }
617
618 /*!
619     \qmlmethod color Qt::tint(color baseColor, color tintColor)
620     This function allows tinting one color with another.
621
622     The tint color should usually be mostly transparent, or you will not be
623     able to see the underlying color. The below example provides a slight red
624     tint by having the tint color be pure red which is only 1/16th opaque.
625
626     \qml
627     Item {
628         Rectangle {
629             x: 0; width: 80; height: 80
630             color: "lightsteelblue"
631         }
632         Rectangle {
633             x: 100; width: 80; height: 80
634             color: Qt.tint("lightsteelblue", "#10FF0000")
635         }
636     }
637     \endqml
638     \image declarative-rect_tint.png
639
640     Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
641 */
642 v8::Handle<v8::Value> tint(const v8::Arguments &args)
643 {
644     if (args.Length() != 2)
645         V8THROW_ERROR("Qt.tint(): Invalid arguments");
646
647     // base color
648     QColor color;
649     QVariant v = V8ENGINE()->toVariant(args[0], -1);
650     if (v.userType() == QVariant::Color) {
651         color = v.value<QColor>();
652     } else if (v.userType() == QVariant::String) {
653         bool ok = false;
654         color = QQmlStringConverters::colorFromString(v.toString(), &ok);
655         if (!ok) {
656             return v8::Null();
657         }
658     } else {
659         return v8::Null();
660     }
661
662     // tint color
663     QColor tintColor;
664     v = V8ENGINE()->toVariant(args[1], -1);
665     if (v.userType() == QVariant::Color) {
666         tintColor = v.value<QColor>();
667     } else if (v.userType() == QVariant::String) {
668         bool ok = false;
669         tintColor = QQmlStringConverters::colorFromString(v.toString(), &ok);
670         if (!ok) {
671             return v8::Null();
672         }
673     } else {
674         return v8::Null();
675     }
676
677     // tint the base color and return the final color
678     QColor finalColor;
679     int a = tintColor.alpha();
680     if (a == 0xFF)
681         finalColor = tintColor;
682     else if (a == 0x00)
683         finalColor = color;
684     else {
685         qreal a = tintColor.alphaF();
686         qreal inv_a = 1.0 - a;
687
688         finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
689                            tintColor.greenF() * a + color.greenF() * inv_a,
690                            tintColor.blueF() * a + color.blueF() * inv_a,
691                            a + inv_a * color.alphaF());
692     }
693
694     return V8ENGINE()->fromVariant(QVariant::fromValue(finalColor));
695 }
696
697 /*!
698 \qmlmethod string Qt::formatDate(datetime date, variant format)
699
700 Returns a string representation of \c date, optionally formatted according
701 to \c format.
702
703 The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
704 property, a QDate, or QDateTime value. The \a format parameter may be any of
705 the possible format values as described for
706 \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
707
708 If \a format is not specified, \a date is formatted using
709 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
710
711 \sa Locale
712 */
713 v8::Handle<v8::Value> formatDate(const v8::Arguments &args)
714 {
715     if (args.Length() < 1 || args.Length() > 2)
716         V8THROW_ERROR("Qt.formatDate(): Invalid arguments");
717
718     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
719     QDate date = V8ENGINE()->toVariant(args[0], -1).toDateTime().date();
720     QString formattedDate;
721     if (args.Length() == 2) {
722         if (args[1]->IsString()) {
723             QString format = V8ENGINE()->toVariant(args[1], -1).toString();
724             formattedDate = date.toString(format);
725         } else if (args[1]->IsNumber()) {
726             quint32 intFormat = args[1]->ToNumber()->Value();
727             Qt::DateFormat format = Qt::DateFormat(intFormat);
728             formattedDate = date.toString(format);
729         } else {
730             V8THROW_ERROR("Qt.formatDate(): Invalid date format");
731         }
732     } else {
733          formattedDate = date.toString(enumFormat);
734     }
735
736     return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDate));
737 }
738
739 /*!
740 \qmlmethod string Qt::formatTime(datetime time, variant format)
741
742 Returns a string representation of \c time, optionally formatted according to
743 \c format.
744
745 The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
746 value. The \a format parameter may be any of the possible format values as
747 described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
748
749 If \a format is not specified, \a time is formatted using
750 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
751
752 \sa Locale
753 */
754 v8::Handle<v8::Value> formatTime(const v8::Arguments &args)
755 {
756     if (args.Length() < 1 || args.Length() > 2)
757         V8THROW_ERROR("Qt.formatTime(): Invalid arguments");
758
759     QVariant argVariant = V8ENGINE()->toVariant(args[0], -1);
760     QTime time;
761     if (args[0]->IsDate() || (argVariant.type() == QVariant::String))
762         time = argVariant.toDateTime().time();
763     else // if (argVariant.type() == QVariant::Time), or invalid.
764         time = argVariant.toTime();
765
766     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
767     QString formattedTime;
768     if (args.Length() == 2) {
769         if (args[1]->IsString()) {
770             QString format = V8ENGINE()->toVariant(args[1], -1).toString();
771             formattedTime = time.toString(format);
772         } else if (args[1]->IsNumber()) {
773             quint32 intFormat = args[1]->ToNumber()->Value();
774             Qt::DateFormat format = Qt::DateFormat(intFormat);
775             formattedTime = time.toString(format);
776         } else {
777             V8THROW_ERROR("Qt.formatTime(): Invalid time format");
778         }
779     } else {
780          formattedTime = time.toString(enumFormat);
781     }
782
783     return V8ENGINE()->fromVariant(QVariant::fromValue(formattedTime));
784 }
785
786 /*!
787 \qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
788
789 Returns a string representation of \c datetime, optionally formatted according to
790 \c format.
791
792 The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
793 property, a QDate, QTime, or QDateTime value.
794
795 If \a format is not provided, \a dateTime is formatted using
796 \l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
797 \a format should be either:
798
799 \list
800 \o One of the Qt::DateFormat enumeration values, such as
801    \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
802 \o A string that specifies the format of the returned string, as detailed below.
803 \endlist
804
805 If \a format specifies a format string, it should use the following expressions
806 to specify the date:
807
808     \table
809     \header \i Expression \i Output
810     \row \i d \i the day as number without a leading zero (1 to 31)
811     \row \i dd \i the day as number with a leading zero (01 to 31)
812     \row \i ddd
813             \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
814             Uses QDate::shortDayName().
815     \row \i dddd
816             \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
817             Uses QDate::longDayName().
818     \row \i M \i the month as number without a leading zero (1-12)
819     \row \i MM \i the month as number with a leading zero (01-12)
820     \row \i MMM
821             \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
822             Uses QDate::shortMonthName().
823     \row \i MMMM
824             \i the long localized month name (e.g. 'January' to 'December').
825             Uses QDate::longMonthName().
826     \row \i yy \i the year as two digit number (00-99)
827     \row \i yyyy \i the year as four digit number
828     \endtable
829
830 In addition the following expressions can be used to specify the time:
831
832     \table
833     \header \i Expression \i Output
834     \row \i h
835          \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
836     \row \i hh
837          \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
838     \row \i m \i the minute without a leading zero (0 to 59)
839     \row \i mm \i the minute with a leading zero (00 to 59)
840     \row \i s \i the second without a leading zero (0 to 59)
841     \row \i ss \i the second with a leading zero (00 to 59)
842     \row \i z \i the milliseconds without leading zeroes (0 to 999)
843     \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
844     \row \i AP
845             \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
846     \row \i ap
847             \i use am/pm display. \e ap will be replaced by either "am" or "pm".
848     \endtable
849
850     All other input characters will be ignored. Any sequence of characters that
851     are enclosed in single quotes will be treated as text and not be used as an
852     expression. Two consecutive single quotes ("''") are replaced by a single quote
853     in the output.
854
855 For example, if the following date/time value was specified:
856
857     \code
858     // 21 May 2001 14:13:09
859     var dateTime = new Date(2001, 5, 21, 14, 13, 09)
860     \endcode
861
862 This \a dateTime value could be passed to \c Qt.formatDateTime(),
863 \l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()}
864 with the \a format values below to produce the following results:
865
866     \table
867     \header \i Format \i Result
868     \row \i "dd.MM.yyyy"      \i 21.05.2001
869     \row \i "ddd MMMM d yy"   \i Tue May 21 01
870     \row \i "hh:mm:ss.zzz"    \i 14:13:09.042
871     \row \i "h:m:s ap"        \i 2:13:9 pm
872     \endtable
873
874     \sa Locale
875 */
876 v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args)
877 {
878     if (args.Length() < 1 || args.Length() > 2)
879         V8THROW_ERROR("Qt.formatDateTime(): Invalid arguments");
880
881     Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
882     QDateTime dt = V8ENGINE()->toVariant(args[0], -1).toDateTime();
883     QString formattedDt;
884     if (args.Length() == 2) {
885         if (args[1]->IsString()) {
886             QString format = V8ENGINE()->toVariant(args[1], -1).toString();
887             formattedDt = dt.toString(format);
888         } else if (args[1]->IsNumber()) {
889             quint32 intFormat = args[1]->ToNumber()->Value();
890             Qt::DateFormat format = Qt::DateFormat(intFormat);
891             formattedDt = dt.toString(format);
892         } else {
893             V8THROW_ERROR("Qt.formatDateTime(): Invalid datetime format");
894         }
895     } else {
896          formattedDt = dt.toString(enumFormat);
897     }
898
899     return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDt));
900 }
901
902 /*!
903 \qmlmethod bool Qt::openUrlExternally(url target)
904 Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise.
905 */
906 v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args)
907 {
908     if (args.Length() != 1)
909         return V8ENGINE()->fromVariant(false);
910
911     bool ret = false;
912 #ifndef QT_NO_DESKTOPSERVICES
913     ret = QDesktopServices::openUrl(V8ENGINE()->toVariant(resolvedUrl(args), -1).toUrl());
914 #endif
915     return V8ENGINE()->fromVariant(ret);
916 }
917
918 /*!
919   \qmlmethod url Qt::resolvedUrl(url url)
920   Returns \a url resolved relative to the URL of the caller.
921 */
922 v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args)
923 {
924     QUrl url = V8ENGINE()->toVariant(args[0], -1).toUrl();
925     QQmlEngine *e = V8ENGINE()->engine();
926     QQmlEnginePrivate *p = 0;
927     if (e) p = QQmlEnginePrivate::get(e);
928     if (p) {
929         QQmlContextData *ctxt = V8ENGINE()->callingContext();
930         if (ctxt)
931             return V8ENGINE()->toString(ctxt->resolvedUrl(url).toString());
932         else
933             return V8ENGINE()->toString(url.toString());
934     }
935
936     return V8ENGINE()->toString(e->baseUrl().resolved(url).toString());
937 }
938
939 /*!
940 \qmlmethod list<string> Qt::fontFamilies()
941 Returns a list of the font families available to the application.
942 */
943 v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args)
944 {
945     if (args.Length() != 0)
946         V8THROW_ERROR("Qt.fontFamilies(): Invalid arguments");
947
948     QFontDatabase database;
949     return V8ENGINE()->fromVariant(database.families());
950 }
951
952 /*!
953 \qmlmethod string Qt::md5(data)
954 Returns a hex string of the md5 hash of \c data.
955 */
956 v8::Handle<v8::Value> md5(const v8::Arguments &args)
957 {
958     if (args.Length() != 1)
959         V8THROW_ERROR("Qt.md5(): Invalid arguments");
960
961     QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
962     QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
963     return V8ENGINE()->toString(QLatin1String(result.toHex()));
964 }
965
966 /*!
967 \qmlmethod string Qt::btoa(data)
968 Binary to ASCII - this function returns a base64 encoding of \c data.
969 */
970 v8::Handle<v8::Value> btoa(const v8::Arguments &args)
971 {
972     if (args.Length() != 1)
973         V8THROW_ERROR("Qt.btoa(): Invalid arguments");
974
975     QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
976
977     return V8ENGINE()->toString(QLatin1String(data.toBase64()));
978 }
979
980 /*!
981 \qmlmethod string Qt::atob(data)
982 ASCII to binary - this function returns a base64 decoding of \c data.
983 */
984 v8::Handle<v8::Value> atob(const v8::Arguments &args)
985 {
986     if (args.Length() != 1)
987         V8THROW_ERROR("Qt.atob(): Invalid arguments");
988
989     QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
990
991     return V8ENGINE()->toString(QLatin1String(QByteArray::fromBase64(data)));
992 }
993
994 /*!
995 \qmlmethod Qt::quit()
996 This function causes the QQmlEngine::quit() signal to be emitted.
997 Within the \l {QML Viewer}, this causes the launcher application to exit;
998 to quit a C++ application when this method is called, connect the
999 QQmlEngine::quit() signal to the QCoreApplication::quit() slot.
1000 */
1001 v8::Handle<v8::Value> quit(const v8::Arguments &args)
1002 {
1003     QQmlEnginePrivate::get(V8ENGINE()->engine())->sendQuit();
1004     return v8::Undefined();
1005 }
1006
1007 /*!
1008 \qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
1009
1010 Returns a new object created from the given \a string of QML which will have the specified \a parent,
1011 or \c null if there was an error in creating the object.
1012
1013 If \a filepath is specified, it will be used for error reporting for the created object.
1014
1015 Example (where \c parentItem is the id of an existing QML item):
1016
1017 \snippet doc/src/snippets/qml/createQmlObject.qml 0
1018
1019 In the case of an error, a QtScript Error object is thrown. This object has an additional property,
1020 \c qmlErrors, which is an array of the errors encountered.
1021 Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
1022 For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
1023 { "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
1024
1025 Note that this function returns immediately, and therefore may not work if
1026 the \a qml string loads new components (that is, external QML files that have not yet been loaded).
1027 If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
1028
1029 See \l {Dynamic Object Management in QML} for more information on using this function.
1030 */
1031 v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args)
1032 {
1033     if (args.Length() < 2 || args.Length() > 3)
1034         V8THROW_ERROR("Qt.createQmlObject(): Invalid arguments");
1035
1036     struct Error {
1037         static v8::Local<v8::Value> create(QV8Engine *engine, const QList<QQmlError> &errors) {
1038             QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: ");
1039
1040             v8::Local<v8::Array> qmlerrors = v8::Array::New(errors.count());
1041             for (int ii = 0; ii < errors.count(); ++ii) {
1042                 const QQmlError &error = errors.at(ii);
1043                 errorstr += QLatin1String("\n    ") + error.toString();
1044                 v8::Local<v8::Object> qmlerror = v8::Object::New();
1045                 qmlerror->Set(v8::String::New("lineNumber"), v8::Integer::New(error.line()));
1046                 qmlerror->Set(v8::String::New("columnNumber"), v8::Integer::New(error.column()));
1047                 qmlerror->Set(v8::String::New("fileName"), engine->toString(error.url().toString()));
1048                 qmlerror->Set(v8::String::New("message"), engine->toString(error.description()));
1049                 qmlerrors->Set(ii, qmlerror);
1050             }
1051
1052             v8::Local<v8::Value> error = v8::Exception::Error(engine->toString(errorstr));
1053             v8::Local<v8::Object> errorObject = error->ToObject();
1054             errorObject->Set(v8::String::New("qmlErrors"), qmlerrors);
1055             return error;
1056         }
1057     };
1058
1059     QV8Engine *v8engine = V8ENGINE();
1060     QQmlEngine *engine = v8engine->engine();
1061
1062     QQmlContextData *context = v8engine->callingContext();
1063     QQmlContext *effectiveContext = 0;
1064     if (context->isPragmaLibraryContext)
1065         effectiveContext = engine->rootContext();
1066     else
1067         effectiveContext = context->asQQmlContext();
1068     Q_ASSERT(context && effectiveContext);
1069
1070     QString qml = v8engine->toString(args[0]->ToString());
1071     if (qml.isEmpty())
1072         return v8::Null();
1073
1074     QUrl url;
1075     if (args.Length() > 2)
1076         url = QUrl(v8engine->toString(args[2]->ToString()));
1077     else
1078         url = QUrl(QLatin1String("inline"));
1079
1080     if (url.isValid() && url.isRelative())
1081         url = context->resolvedUrl(url);
1082
1083     QObject *parentArg = v8engine->toQObject(args[1]);
1084     if (!parentArg)
1085         V8THROW_ERROR("Qt.createQmlObject(): Missing parent object");
1086
1087     QQmlComponent component(engine);
1088     component.setData(qml.toUtf8(), url);
1089
1090     if (component.isError()) {
1091         v8::ThrowException(Error::create(v8engine, component.errors()));
1092         return v8::Undefined();
1093     }
1094
1095     if (!component.isReady())
1096         V8THROW_ERROR("Qt.createQmlObject(): Component is not ready");
1097
1098     QObject *obj = component.beginCreate(effectiveContext);
1099     if (obj) {
1100         QQmlData::get(obj, true)->setImplicitDestructible();
1101
1102         obj->setParent(parentArg);
1103
1104         QList<QQmlPrivate::AutoParentFunction> functions = QQmlMetaType::parentFunctions();
1105         for (int ii = 0; ii < functions.count(); ++ii) {
1106             if (QQmlPrivate::Parented == functions.at(ii)(obj, parentArg))
1107                 break;
1108         }
1109     }
1110     component.completeCreate();
1111
1112     if (component.isError()) {
1113         v8::ThrowException(Error::create(v8engine, component.errors()));
1114         return v8::Undefined();
1115     }
1116
1117     Q_ASSERT(obj);
1118
1119     return v8engine->newQObject(obj);
1120 }
1121
1122 /*!
1123 \qmlmethod object Qt::createComponent(url)
1124
1125 Returns a \l Component object created using the QML file at the specified \a url,
1126 or \c null if an empty string was given.
1127
1128 The returned component's \l Component::status property indicates whether the
1129 component was successfully created. If the status is \c Component.Error,
1130 see \l Component::errorString() for an error description.
1131
1132 Call \l {Component::createObject()}{Component.createObject()} on the returned
1133 component to create an object instance of the component.
1134
1135 For example:
1136
1137 \snippet doc/src/snippets/qml/createComponent-simple.qml 0
1138
1139 See \l {Dynamic Object Management in QML} for more information on using this function.
1140
1141 To create a QML object from an arbitrary string of QML (instead of a file),
1142 use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
1143 */
1144 v8::Handle<v8::Value> createComponent(const v8::Arguments &args)
1145 {
1146     if (args.Length() != 1)
1147         V8THROW_ERROR("Qt.createComponent(): Invalid arguments");
1148
1149     QV8Engine *v8engine = V8ENGINE();
1150     QQmlEngine *engine = v8engine->engine();
1151
1152     QQmlContextData *context = v8engine->callingContext();
1153     QQmlContextData *effectiveContext = context;
1154     if (context->isPragmaLibraryContext)
1155         effectiveContext = 0;
1156     Q_ASSERT(context);
1157
1158     QString arg = v8engine->toString(args[0]->ToString());
1159     if (arg.isEmpty())
1160         return v8::Null();
1161
1162     QUrl url = context->resolvedUrl(QUrl(arg));
1163     QQmlComponent *c = new QQmlComponent(engine, url, engine);
1164     QQmlComponentPrivate::get(c)->creationContext = effectiveContext;
1165     QQmlData::get(c, true)->setImplicitDestructible();
1166     return v8engine->newQObject(c);
1167 }
1168
1169 v8::Handle<v8::Value> qsTranslate(const v8::Arguments &args)
1170 {
1171     if (args.Length() < 2)
1172         V8THROW_ERROR("qsTranslate() requires at least two arguments");
1173     if (!args[0]->IsString())
1174         V8THROW_ERROR("qsTranslate(): first argument (context) must be a string");
1175     if (!args[1]->IsString())
1176         V8THROW_ERROR("qsTranslate(): second argument (text) must be a string");
1177     if ((args.Length() > 2) && !args[2]->IsString())
1178         V8THROW_ERROR("qsTranslate(): third argument (comment) must be a string");
1179     if ((args.Length() > 3) && !args[3]->IsString())
1180         V8THROW_ERROR("qsTranslate(): fourth argument (encoding) must be a string");
1181
1182     QV8Engine *v8engine = V8ENGINE();
1183     QString context = v8engine->toString(args[0]);
1184     QString text = v8engine->toString(args[1]);
1185     QString comment;
1186     if (args.Length() > 2) comment = v8engine->toString(args[2]);
1187
1188     QCoreApplication::Encoding encoding = QCoreApplication::UnicodeUTF8;
1189     if (args.Length() > 3) {
1190         QString encStr = v8engine->toString(args[3]);
1191         if (encStr == QLatin1String("UnicodeUTF8")) {
1192             encoding = QCoreApplication::UnicodeUTF8;
1193         } else {
1194             QString msg = QString::fromLatin1("qsTranslate(): invalid encoding '%0'").arg(encStr);
1195             V8THROW_ERROR((uint16_t *)msg.constData());
1196         }
1197     }
1198
1199     int n = -1;
1200     if (args.Length() > 4)
1201         n = args[4]->Int32Value();
1202
1203     QString result = QCoreApplication::translate(context.toUtf8().constData(),
1204                                                  text.toUtf8().constData(),
1205                                                  comment.toUtf8().constData(),
1206                                                  encoding, n);
1207
1208     return v8engine->toString(result);
1209 }
1210
1211 v8::Handle<v8::Value> qsTranslateNoOp(const v8::Arguments &args)
1212 {
1213     if (args.Length() < 2)
1214         return v8::Undefined();
1215     return args[1];
1216 }
1217
1218 v8::Handle<v8::Value> qsTr(const v8::Arguments &args)
1219 {
1220     if (args.Length() < 1)
1221         V8THROW_ERROR("qsTr() requires at least one argument");
1222     if (!args[0]->IsString())
1223         V8THROW_ERROR("qsTr(): first argument (text) must be a string");
1224     if ((args.Length() > 1) && !args[1]->IsString())
1225         V8THROW_ERROR("qsTr(): second argument (comment) must be a string");
1226     if ((args.Length() > 2) && !args[2]->IsNumber())
1227         V8THROW_ERROR("qsTr(): third argument (n) must be a number");
1228
1229     QV8Engine *v8engine = V8ENGINE();
1230     QQmlContextData *ctxt = v8engine->callingContext();
1231
1232     QString path = ctxt->url.toString();
1233     int lastSlash = path.lastIndexOf(QLatin1Char('/'));
1234     QString context = (lastSlash > -1) ? path.mid(lastSlash + 1, path.length()-lastSlash-5) : QString();
1235
1236     QString text = v8engine->toString(args[0]);
1237     QString comment;
1238     if (args.Length() > 1)
1239         comment = v8engine->toString(args[1]);
1240     int n = -1;
1241     if (args.Length() > 2)
1242         n = args[2]->Int32Value();
1243
1244     QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(),
1245                                                  comment.toUtf8().constData(), QCoreApplication::UnicodeUTF8, n);
1246
1247     return v8engine->toString(result);
1248 }
1249
1250 v8::Handle<v8::Value> qsTrNoOp(const v8::Arguments &args)
1251 {
1252     if (args.Length() < 1)
1253         return v8::Undefined();
1254     return args[0];
1255 }
1256
1257 v8::Handle<v8::Value> qsTrId(const v8::Arguments &args)
1258 {
1259     if (args.Length() < 1)
1260         V8THROW_ERROR("qsTrId() requires at least one argument");
1261     if (!args[0]->IsString())
1262         V8THROW_TYPE("qsTrId(): first argument (id) must be a string");
1263     if (args.Length() > 1 && !args[1]->IsNumber())
1264         V8THROW_TYPE("qsTrId(): second argument (n) must be a number");
1265
1266     int n = -1;
1267     if (args.Length() > 1)
1268         n = args[1]->Int32Value();
1269
1270     QV8Engine *v8engine = V8ENGINE();
1271     return v8engine->toString(qtTrId(v8engine->toString(args[0]).toUtf8().constData(), n));
1272 }
1273
1274 v8::Handle<v8::Value> qsTrIdNoOp(const v8::Arguments &args)
1275 {
1276     if (args.Length() < 1)
1277         return v8::Undefined();
1278     return args[0];
1279 }
1280
1281
1282 /*!
1283     \qmlmethod Qt::locale(name)
1284
1285     Returns a JS object representing the locale with the specified
1286     name, which has the format "language[_territory][.codeset][@modifier]"
1287     or "C", where:
1288
1289     \list
1290     \o language is a lowercase, two-letter, ISO 639 language code,
1291     \o territory is an uppercase, two-letter, ISO 3166 country code,
1292     \o and codeset and modifier are ignored.
1293     \endlist
1294
1295     If the string violates the locale format, or language is not a
1296     valid ISO 369 code, the "C" locale is used instead. If country
1297     is not present, or is not a valid ISO 3166 code, the most
1298     appropriate country is chosen for the specified language.
1299
1300     \sa QtQuick2::Locale
1301 */
1302 v8::Handle<v8::Value> locale(const v8::Arguments &args)
1303 {
1304     QString code;
1305     if (args.Length() > 1)
1306         V8THROW_ERROR("locale() requires 0 or 1 argument");
1307     if (args.Length() == 1 && !args[0]->IsString())
1308         V8THROW_TYPE("locale(): argument (locale code) must be a string");
1309
1310     QV8Engine *v8engine = V8ENGINE();
1311     if (args.Length() == 1)
1312         code = v8engine->toString(args[0]);
1313
1314     return QQmlLocale::locale(v8engine, code);
1315 }
1316
1317 } // namespace QQmlBuiltinFunctions
1318
1319 QT_END_NAMESPACE