Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlbuiltinfunctions.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <private/qqmlcomponent_p.h>
7#include <private/qqmldebugconnector_p.h>
8#include <private/qqmldebugserviceinterfaces_p.h>
9#include <private/qqmldelayedcallqueue_p.h>
10#include <private/qqmlengine_p.h>
11#include <private/qqmlloggingcategorybase_p.h>
12#include <private/qqmlplatform_p.h>
13#include <private/qqmlstringconverters_p.h>
14
15#include <private/qv4dateobject_p.h>
16#include <private/qv4domerrors_p.h>
17#include <private/qv4engine_p.h>
18#include <private/qv4functionobject_p.h>
19#include <private/qv4include_p.h>
20#include <private/qv4mm_p.h>
21#include <private/qv4qobjectwrapper_p.h>
22#include <private/qv4sequenceobject_p.h>
23#include <private/qv4stackframe_p.h>
24
25#include <QtQml/qqmlfile.h>
26
27#include <QtCore/qcoreapplication.h>
28#include <QtCore/qcryptographichash.h>
29#include <QtCore/qdatetime.h>
30#include <QtCore/qfileinfo.h>
31#include <QtCore/qloggingcategory.h>
32#include <QtCore/qpoint.h>
33#include <QtCore/qrect.h>
34#include <QtCore/qsize.h>
35#include <QtCore/qstring.h>
36#include <QtCore/qurl.h>
37
39
40Q_STATIC_LOGGING_CATEGORY(lcRootProperties, "qt.qml.rootObjectProperties");
43
44using namespace QV4;
45
46#define THROW_TYPE_ERROR_WITH_MESSAGE(msg)
47 do {
48 return scope.engine->throwTypeError(QString::fromUtf8(msg));
49 } while (false)
50
51/*!
52\qmltype Qt
53\inqmlmodule QtQml
54//! \nativetype QQmlEnginePrivate
55\ingroup qml-utility-elements
56\keyword QmlGlobalQtObject
57\brief Provides a global object with useful enums and functions from Qt.
58
59\c Qt is a singleton type that provides utility functions, properties, and
60enums. Here is an example showing how to use this type:
61
62\qml
63import QtQuick 2.0
64
65Text {
66 color: Qt.rgba(1, 0, 0, 1)
67 text: Qt.md5("hello, world")
68}
69\endqml
70
71
72\section1 Enums
73
74The Qt object contains the enums available in the \l [QtCore]{Qt}{Qt Namespace}. For example, you can access
75the \l Qt::LeftButton and \l Qt::RightButton enumeration values as \c Qt.LeftButton and \c Qt.RightButton.
76
77
78\section1 Types
79\target globalqtobjecttypes
80
81The Qt object also contains helper functions for creating objects of specific
82data types. This is primarily useful when setting the properties of an item
83when the property has one of the following types:
84\list
85\li \c rect - use \l{Qt::rect()}{Qt.rect()}
86\li \c point - use \l{Qt::point()}{Qt.point()}
87\li \c size - use \l{Qt::size()}{Qt.size()}
88\endlist
89
90If the \c QtQuick module has been imported, the following helper functions for
91creating objects of specific data types are also available for clients to use:
92\list
93\li \c color - use \l{Qt::rgba()}{Qt.rgba()}, \l{Qt::hsla()}{Qt.hsla()}, \l{Qt::darker()}{Qt.darker()}, \l{Qt::lighter()}{Qt.lighter()} or \l{Qt::tint()}{Qt.tint()}
94\li \c font - use \l{Qt::font()}{Qt.font()}
95\li \c vector2d - use \l{Qt::vector2d()}{Qt.vector2d()}
96\li \c vector3d - use \l{Qt::vector3d()}{Qt.vector3d()}
97\li \c vector4d - use \l{Qt::vector4d()}{Qt.vector4d()}
98\li \c quaternion - use \l{Qt::quaternion()}{Qt.quaternion()}
99\li \c matrix4x4 - use \l{Qt::matrix4x4()}{Qt.matrix4x4()}
100\endlist
101
102\section1 Date/Time Formatters
103
104The Qt object contains several functions for formatting QDateTime, QDate and QTime values.
105
106\list
107 \li \l{Qt::formatDateTime}{string Qt.formatDateTime(datetime date, variant format)}
108 \li \l{Qt::formatDate}{string Qt.formatDate(datetime date, variant format)}
109 \li \l{Qt::formatTime}{string Qt.formatTime(datetime date, variant format)}
110\endlist
111
112The format specification is described at \l{Qt::formatDateTime}{Qt.formatDateTime}.
113
114
115\section1 Dynamic Object Creation
116The following functions on the global object allow you to dynamically create QML
117items from files or strings. See \l{Dynamic QML Object Creation from JavaScript} for an overview
118of their use.
119
120\list
121 \li \l{Qt::createComponent()}{object Qt.createComponent(url)}
122 \li \l{Qt::createQmlObject()}{object Qt.createQmlObject(string qml, object parent, url url)}
123\endlist
124
125
126\section1 Other Functions
127
128The following functions are also on the Qt object.
129
130\list
131 \li \l{Qt::quit()}{Qt.quit()}
132 \li \l{Qt::md5()}{Qt.md5(string)}
133 \li \l{Qt::btoa()}{string Qt.btoa(string)}
134 \li \l{Qt::atob()}{string Qt.atob(string)}
135 \li \l{Qt::binding()}{object Qt.binding(function)}
136 \li \l{Qt::locale()}{object Qt.locale()}
137 \li \l{Qt::resolvedUrl()}{string Qt.resolvedUrl(string)}
138 \li \l{Qt::openUrlExternally()}{Qt.openUrlExternally(string)}
139 \li \l{Qt::fontFamilies()}{list<string> Qt.fontFamilies()}
140\endlist
141*/
142
143/*!
144 \qmlproperty object Qt::platform
145 \since 5.1
146
147 The \c platform object provides info about the underlying platform.
148
149 Its properties are:
150
151 \table
152 \row
153 \li \c platform.os
154 \li
155
156 This read-only property contains the name of the operating system.
157
158 Possible values are:
159
160 \list
161 \li \c "android" - Android
162 \li \c "ios" - iOS
163 \li \c "tvos" - tvOS
164 \li \c "visionos" - visionOS
165 \li \c "linux" - Linux
166 \li \c "osx" - \macos
167 \li \c "qnx" - QNX (since Qt 5.9.3)
168 \li \c "unix" - Other Unix-based OS
169 \li \c "windows" - Windows
170 \li \c "wasm" - WebAssembly
171 \endlist
172
173 \note The property's value on \macos is "osx", regardless of Apple naming convention.
174 The returned value will be updated to "macos" for Qt 7.
175
176 \row
177 \li \c platform.pluginName
178 \li This is the name of the platform set on the QGuiApplication instance
179 as returned by \l QGuiApplication::platformName()
180
181 \endtable
182*/
183
184/*!
185 \qmlproperty Application Qt::application
186 \since 5.1
187
188 The \c application object provides access to global application state
189 properties shared by many QML components.
190
191 It is the same as the \l Application singleton.
192
193 The following example uses the \c application object to indicate
194 whether the application is currently active:
195
196 \snippet qml/application.qml document
197
198 \note When using QML without a QGuiApplication, the following properties will be undefined:
199 \list
200 \li application.active
201 \li application.state
202 \li application.layoutDirection
203 \li application.font
204 \endlist
205*/
206
207/*!
208 \qmlproperty InputMethod Qt::inputMethod
209 \since 5.0
210
211 It is the same as the \l InputMethod singleton.
212
213 The \c inputMethod object allows access to application's QInputMethod object
214 and all its properties and slots. See the QInputMethod documentation for
215 further details.
216*/
217
218/*!
219 \qmlproperty object Qt::styleHints
220 \since 5.5
221
222 The \c styleHints object provides platform-specific style hints and settings.
223 See the \l QStyleHints documentation for further details.
224
225 You should access StyleHints via \l Application::styleHints instead, as
226 this provides better type information for tooling such as the
227 \l {Qt Quick Compiler}.
228
229 \note The \c styleHints object is only available when using the Qt Quick module.
230*/
231
232/*!
233\qmlmethod object Qt::include(string url, jsobject callback)
234\deprecated
235
236This method should not be used. Use ECMAScript modules, and the native
237JavaScript \c import and \c export statements instead.
238
239Includes another JavaScript file. This method can only be used from within JavaScript files,
240and not regular QML files.
241
242This imports all functions from \a url into the current script's namespace.
243
244Qt.include() returns an object that describes the status of the operation. The object has
245a single property, \c {status}, that is set to one of the following values:
246
247\table
248\header \li Symbol \li Value \li Description
249\row \li result.OK \li 0 \li The include completed successfully.
250\row \li result.LOADING \li 1 \li Data is being loaded from the network.
251\row \li result.NETWORK_ERROR \li 2 \li A network error occurred while fetching the url.
252\row \li result.EXCEPTION \li 3 \li A JavaScript exception occurred while executing the included code.
253An additional \c exception property will be set in this case.
254\endtable
255
256The \c status property will be updated as the operation progresses.
257
258If provided, \a callback is invoked when the operation completes. The callback is passed
259the same object as is returned from the Qt.include() call.
260
261\warning Using this function is strict mode does not actually put identifier into the
262current context.
263*/
264// Qt.include() is implemented in qv4include.cpp
265
266QtObject::QtObject(ExecutionEngine *engine)
267 : m_engine(engine)
268{
269#if QT_CONFIG(translation)
270 connect(m_engine->jsEngine(), &QJSEngine::uiLanguageChanged,
271 this, &QtObject::uiLanguageChanged);
272#endif
273}
274
275QtObject::Contexts QtObject::getContexts() const
276{
277 QQmlEngine *engine = qmlEngine();
278 if (!engine)
279 return {};
280
281 QQmlRefPointer<QQmlContextData> context = v4Engine()->callingQmlContext();
282 if (!context)
283 context = QQmlContextData::get(QQmlEnginePrivate::get(engine)->rootContext);
284
285 Q_ASSERT(context);
286 QQmlRefPointer<QQmlContextData> effectiveContext
287 = context->isPragmaLibraryContext() ? nullptr : context;
288 return {context, effectiveContext};
289}
290
291QtObject *QtObject::create(QQmlEngine *, QJSEngine *jsEngine)
292{
293 QV4::ExecutionEngine *v4 = jsEngine->handle();
294 QV4::Scope scope(v4);
295 ScopedObject globalObject(scope, v4->globalObject);
296 ScopedString qtName(scope, v4->newString(QStringLiteral("Qt")));
297 QV4::ScopedValue result(scope, globalObject->get(qtName->toPropertyKey()));
298 return qobject_cast<QtObject *>(result->as<QV4::QObjectWrapper>()->object());
299}
300
301QJSValue QtObject::include(const QString &url, const QJSValue &callback) const
302{
303 return QV4Include::method_include(v4Engine(), v4Engine()->resolvedUrl(url), callback);
304}
305
306
307/*!
308 \qmlmethod bool Qt::isQtObject(object)
309
310 Returns \c true if \a object is a valid reference to a Qt or QML object,
311 \c false otherwise.
312*/
313bool QtObject::isQtObject(const QJSValue &value) const
314{
315 return qjsvalue_cast<QObject *>(value) != nullptr;
316}
317
318/*!
319 \qmlmethod color Qt::color(string name)
320
321 Returns the color corresponding to the given \a name (i.e. red or #ff0000).
322 If there is no such color, \c null is returned.
323*/
324QVariant QtObject::color(const QString &name) const
325{
326 bool ok = false;
327 const QVariant v = QQmlStringConverters::colorFromString(name, &ok);
328 if (ok)
329 return v;
330
331 v4Engine()->throwError(QStringLiteral("\"%1\" is not a valid color name").arg(name));
332 return QVariant::fromValue(nullptr);
333}
334
335/*!
336 \qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
337
338 Returns a color with the specified \a red, \a green, \a blue, and \a alpha
339 components. All components should be in the range 0-1 (inclusive).
340*/
341QVariant QtObject::rgba(double r, double g, double b, double a) const
342{
343 if (r < 0.0) r=0.0;
344 if (r > 1.0) r=1.0;
345 if (g < 0.0) g=0.0;
346 if (g > 1.0) g=1.0;
347 if (b < 0.0) b=0.0;
348 if (b > 1.0) b=1.0;
349 if (a < 0.0) a=0.0;
350 if (a > 1.0) a=1.0;
351
352 return QQml_colorProvider()->fromRgbF(r, g, b, a);
353}
354
355/*!
356 \qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
357
358 Returns a color with the specified \a hue, \a saturation, \a lightness, and \a alpha
359 components. All components should be in the range 0-1 (inclusive).
360*/
361QVariant QtObject::hsla(double h, double s, double l, double a) const
362{
363 if (h != -1)
364 h = qBound(0.0, h, 1.0);
365 s = qBound(0.0, s, 1.0);
366 l = qBound(0.0, l, 1.0);
367 a = qBound(0.0, a, 1.0);
368
369 return QQml_colorProvider()->fromHslF(h, s, l, a);
370}
371
372/*!
373 \since 5.5
374 \qmlmethod color Qt::hsva(real hue, real saturation, real value, real alpha)
375
376 Returns a color with the specified \a hue, \a saturation, \a value and \a alpha
377 components. All components should be in the range 0-1 (inclusive).
378
379*/
380QVariant QtObject::hsva(double h, double s, double v, double a) const
381{
382 if (h != -1)
383 h = qBound(0.0, h, 1.0);
384 s = qBound(0.0, s, 1.0);
385 v = qBound(0.0, v, 1.0);
386 a = qBound(0.0, a, 1.0);
387
388 return QQml_colorProvider()->fromHsvF(h, s, v, a);
389}
390
391/*!
392 \qmlmethod color Qt::colorEqual(color lhs, string rhs)
393
394 Returns \c true if both \a lhs and \a rhs yield equal color values. Both
395 arguments may be either color values or string values. If a string value
396 is supplied it must be convertible to a color, as described for the
397 \l{colorvaluetypedocs}{color} value type.
398*/
399bool QtObject::colorEqual(const QVariant &lhs, const QVariant &rhs) const
400{
401 bool ok = false;
402
403 QVariant color1 = lhs;
404 if (color1.userType() == QMetaType::QString) {
405 color1 = QQmlStringConverters::colorFromString(color1.toString(), &ok);
406 if (!ok) {
407 v4Engine()->throwError(QStringLiteral("Qt.colorEqual(): Invalid color name"));
408 return false;
409 }
410 } else if (color1.userType() != QMetaType::QColor) {
411 v4Engine()->throwError(QStringLiteral("Qt.colorEqual(): Invalid arguments"));
412 return false;
413 }
414
415 QVariant color2 = rhs;
416 if (color2.userType() == QMetaType::QString) {
417 color2 = QQmlStringConverters::colorFromString(color2.toString(), &ok);
418 if (!ok) {
419 v4Engine()->throwError(QStringLiteral("Qt.colorEqual(): Invalid color name"));
420 return false;
421 }
422 } else if (color2.userType() != QMetaType::QColor) {
423 v4Engine()->throwError(QStringLiteral("Qt.colorEqual(): Invalid arguments"));
424 return false;
425 }
426
427 return color1 == color2;
428}
429
430/*!
431 \qmlmethod rect Qt::rect(real x, real y, real width, real height)
432
433 Returns a rect with the top-left corner at \a x, \a y and the specified \a width and \a height.
434*/
435QRectF QtObject::rect(double x, double y, double width, double height) const
436{
437 return QRectF(x, y, width, height);
438}
439
440/*!
441 \qmlmethod point Qt::point(real x, real y)
442
443 Returns a point with the specified \a x and \a y coordinates.
444*/
445QPointF QtObject::point(double x, double y) const
446{
447 return QPointF(x, y);
448}
449
450/*!
451 \qmlmethod size Qt::size(real width, real height)
452
453 Returns a size with the specified \a width and \a height.
454*/
455QSizeF QtObject::size(double w, double h) const
456{
457 return QSizeF(w, h);
458}
459
460/*!
461 \qmlmethod font Qt::font(object fontSpecifier)
462
463 Returns a font with the properties specified in the \a fontSpecifier object
464 or the nearest matching font. The \a fontSpecifier object should contain
465 key-value pairs where valid keys are the \l{fontvaluetypedocs}{font} type's
466 subproperty names, and the values are valid values for each subproperty.
467 Invalid keys will be ignored.
468*/
469QVariant QtObject::font(const QJSValue &fontSpecifier) const
470{
471 if (!fontSpecifier.isObject()) {
472 v4Engine()->throwError(QStringLiteral("Qt.font(): Invalid arguments"));
473 return QVariant();
474 }
475
476 {
477 const QVariant v = QQmlValueTypeProvider::createValueType(
478 fontSpecifier, QMetaType(QMetaType::QFont));
479 if (v.isValid())
480 return v;
481 }
482
483 v4Engine()->throwError(QStringLiteral("Qt.font(): Invalid argument: "
484 "no valid font subproperties specified"));
485 return QVariant();
486}
487
488template<typename T>
489void addParameters(QJSEngine *e, QJSValue &result, int i, T parameter)
490{
491 result.setProperty(i, e->toScriptValue(parameter));
492}
493
494template<>
495void addParameters<double>(QJSEngine *, QJSValue &result, int i, double parameter)
496{
497 result.setProperty(i, QJSValue(parameter));
498}
499
500template<typename T, typename ...Others>
501void addParameters(QJSEngine *e, QJSValue &result, int i, T parameter, Others... others)
502{
503 addParameters<T>(e, result, i, parameter);
504 addParameters<Others...>(e, result, ++i, others...);
505}
506
507template<typename ...T>
508static QVariant constructFromJSValue(QJSEngine *e, QMetaType type, T... parameters)
509{
510 if (!e)
511 return QVariant();
512 QJSValue params = e->newArray(sizeof...(parameters));
513 addParameters(e, params, 0, parameters...);
514 const QVariant variant = QQmlValueTypeProvider::createValueType(params, type);
515 return variant.isValid() ? variant : QVariant(type);
516}
517
518/*!
519 \qmlmethod vector2d Qt::vector2d(real x, real y)
520
521 Returns a vector2d with the specified \a x and \a y values.
522*/
523QVariant QtObject::vector2d(double x, double y) const
524{
525 return constructFromJSValue(jsEngine(), QMetaType(QMetaType::QVector2D), x, y);
526}
527
528/*!
529 \qmlmethod vector3d Qt::vector3d(real x, real y, real z)
530
531 Returns a vector3d with the specified \a x, \a y, and \a z values.
532*/
533QVariant QtObject::vector3d(double x, double y, double z) const
534{
535 return constructFromJSValue(jsEngine(), QMetaType(QMetaType::QVector3D), x, y, z);
536}
537
538/*!
539 \qmlmethod vector4d Qt::vector4d(real x, real y, real z, real w)
540
541 Returns a vector4d with the specified \a x, \a y, \a z, and \a w values.
542*/
543QVariant QtObject::vector4d(double x, double y, double z, double w) const
544{
545 return constructFromJSValue(jsEngine(), QMetaType(QMetaType::QVector4D), x, y, z, w);
546}
547
548/*!
549 \qmlmethod quaternion Qt::quaternion(real scalar, real x, real y, real z)
550
551 Returns a quaternion with the specified \a scalar, \a x, \a y, and \a z values.
552*/
553QVariant QtObject::quaternion(double scalar, double x, double y, double z) const
554{
555 return constructFromJSValue(jsEngine(), QMetaType(QMetaType::QQuaternion), scalar, x, y, z);
556}
557
558/*!
559 \qmlmethod matrix4x4 Qt::matrix4x4()
560
561 Returns an identity matrix4x4.
562 */
563QVariant QtObject::matrix4x4() const
564{
565 const QMetaType metaType(QMetaType::QMatrix4x4);
566 const QVariant variant = QQmlValueTypeProvider::createValueType(QJSValue(), metaType);
567 return variant.isValid() ? variant : QVariant(metaType);
568}
569
570/*!
571 \qmlmethod matrix4x4 Qt::matrix4x4(var values)
572
573 Returns a matrix4x4 with the specified \a values. \a values is expected to
574 be a JavaScript array with 16 entries.
575
576 The array indices correspond to positions in the matrix as follows:
577
578 \table
579 \row \li 0 \li 1 \li 2 \li 3
580 \row \li 4 \li 5 \li 6 \li 7
581 \row \li 8 \li 9 \li 10 \li 11
582 \row \li 12 \li 13 \li 14 \li 15
583 \endtable
584*/
585QVariant QtObject::matrix4x4(const QJSValue &value) const
586{
587 if (value.isObject()) {
588 QVariant v = QQmlValueTypeProvider::createValueType(
589 value, QMetaType(QMetaType::QMatrix4x4));
590 if (v.isValid())
591 return v;
592 }
593
594 v4Engine()->throwError(QStringLiteral("Qt.matrix4x4(): Invalid argument: "
595 "not a valid matrix4x4 values array"));
596 return QVariant();
597}
598
599/*!
600 \qmlmethod matrix4x4 Qt::matrix4x4(real m11, real m12, real m13, real m14, real m21, real m22, real m23, real m24, real m31, real m32, real m33, real m34, real m41, real m42, real m43, real m44)
601
602 Returns a matrix4x4 with the specified values.
603
604 The arguments correspond to their positions in the matrix:
605
606 \table
607 \row \li \a m11 \li \a m12 \li \a m13 \li \a m14
608 \row \li \a m21 \li \a m22 \li \a m23 \li \a m24
609 \row \li \a m31 \li \a m32 \li \a m33 \li \a m34
610 \row \li \a m41 \li \a m42 \li \a m43 \li \a m44
611 \endtable
612*/
613QVariant QtObject::matrix4x4(double m11, double m12, double m13, double m14,
614 double m21, double m22, double m23, double m24,
615 double m31, double m32, double m33, double m34,
616 double m41, double m42, double m43, double m44) const
617{
618 return constructFromJSValue(jsEngine(), QMetaType(QMetaType::QMatrix4x4),
619 m11, m12, m13, m14, m21, m22, m23, m24,
620 m31, m32, m33, m34, m41, m42, m43, m44);
621}
622
623static QVariant colorVariantFromJSValue(const QJSValue &color, bool *ok)
624{
625 QVariant v;
626 if (color.isString()) {
627 v = QQmlStringConverters::colorFromString(color.toString(), ok);
628 if (!(*ok))
629 return QVariant::fromValue(nullptr);
630 } else {
631 v = color.toVariant();
632 if (v.userType() != QMetaType::QColor) {
633 *ok = false;
634 return QVariant::fromValue(nullptr);
635 }
636 }
637
638 *ok = true;
639 return v;
640}
641
642/*!
643 \qmlmethod color Qt::lighter(color baseColor, real factor)
644
645 Returns a color lighter than \a baseColor by the \a factor provided.
646
647 If the factor is greater than 1.0, this functions returns a lighter color.
648 Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
649 the return color is darker, but we recommend using the Qt.darker() function for this purpose.
650 If the factor is 0 or negative, the return value is unspecified.
651
652 The function converts the current RGB color to HSV, multiplies the value (V) component
653 by factor and converts the color back to RGB.
654
655 If \a factor is not supplied, returns a color that is 50% lighter than \a baseColor (factor 1.5).
656*/
657QVariant QtObject::lighter(const QJSValue &color, double factor) const
658{
659 bool ok;
660 const QVariant v = colorVariantFromJSValue(color, &ok);
661 return ok ? QQml_colorProvider()->lighter(v, factor) : v;
662}
663
664/*!
665 \qmlmethod color Qt::darker(color baseColor, real factor)
666
667 Returns a color darker than \a baseColor by the \a factor provided.
668
669 If the factor is greater than 1.0, this function returns a darker color.
670 Setting factor to 3.0 returns a color that has one-third the brightness.
671 If the factor is less than 1.0, the return color is lighter, but we recommend using
672 the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
673 value is unspecified.
674
675 The function converts the current RGB color to HSV, divides the value (V) component
676 by factor and converts the color back to RGB.
677
678 If \a factor is not supplied, returns a color that is 50% darker than \a baseColor (factor 2.0).
679*/
680QVariant QtObject::darker(const QJSValue &color, double factor) const
681{
682 bool ok;
683 const QVariant v = colorVariantFromJSValue(color, &ok);
684 return ok ? QQml_colorProvider()->darker(v, factor) : v;
685}
686
687/*!
688 \qmlmethod color Qt::alpha(color baseColor, real value)
689
690 Returns \a baseColor with an alpha value of \a value.
691
692 \a value is a real ranging from 0 (completely transparent) to 1 (completely opaque).
693*/
694QVariant QtObject::alpha(const QJSValue &baseColor, double value) const
695{
696 bool ok;
697 const QVariant v = colorVariantFromJSValue(baseColor, &ok);
698 return ok ? QQml_colorProvider()->alpha(v, value) : v;
699}
700
701/*!
702 \qmlmethod color Qt::tint(color baseColor, color tintColor)
703
704 This function allows tinting one color (\a baseColor) with another (\a tintColor).
705
706 The tint color should usually be mostly transparent, or you will not be
707 able to see the underlying color. The below example provides a slight red
708 tint by having the tint color be pure red which is only 1/16th opaque.
709
710 \qml
711 Item {
712 Rectangle {
713 x: 0; width: 80; height: 80
714 color: "lightsteelblue"
715 }
716 Rectangle {
717 x: 100; width: 80; height: 80
718 color: Qt.tint("lightsteelblue", "#10FF0000")
719 }
720 }
721 \endqml
722 \image declarative-rect_tint.png {Side-by-side representation of a light
723 steel blue square and a light steel blue square with a tint applied}
724
725 Tint is most useful when a subtle change is intended to be conveyed due to some event;
726 you can then use tinting to more effectively tune the visible color.
727*/
728QVariant QtObject::tint(const QJSValue &baseColor, const QJSValue &tintColor) const
729{
730 bool ok;
731
732 // base color
733 const QVariant v1 = colorVariantFromJSValue(baseColor, &ok);
734 if (!ok)
735 return v1;
736
737 // tint color
738 const QVariant v2 = colorVariantFromJSValue(tintColor, &ok);
739
740 return ok ? QQml_colorProvider()->tint(v1, v2) : v2;
741}
742
743namespace {
744template <typename T>
745QString formatDateTimeObjectUsingDateFormat(T formatThis, Qt::DateFormat format) {
746 switch (format) {
747 case Qt::TextDate:
748 case Qt::ISODate:
749 case Qt::RFC2822Date:
750 case Qt::ISODateWithMs:
751 return formatThis.toString(format);
752 default: // ### Qt 6: remove once qtbase has removed the rest of the enum !
753 break;
754 }
755 // Q_UNREACHABLE(); // ### Qt 6: restore once the default is gone
756 return QString();
757}
758}
759
760static QTime dateTimeToTime(const QDateTime &dateTime)
761{
762 return dateTime.toLocalTime().time();
763}
764
765/*!
766\qmlmethod string Qt::formatDate(datetime date, variant format, variant localeFormatOption)
767
768Returns a string representation of \a date, optionally formatted using \a format.
769
770The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
771property, a QDate, or QDateTime value. The \a format and \a localeFormatOption
772parameter may be any of the possible format values as described for
773\l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}.
774
775If \a format is not specified, \a date is formatted using
776\l {QLocale::FormatType}{Locale.ShortFormat} using the
777default locale.
778
779\sa Locale
780*/
781static std::optional<QDate> dateFromString(const QString &string, QV4::ExecutionEngine *engine)
782{
783 {
784 const QDate date = QDate::fromString(string, Qt::ISODate);
785 if (date.isValid())
786 return date;
787 }
788
789 {
790 // For historical reasons, the string argument is parsed as datetime, not as only date
791 const QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
792 if (dateTime.isValid()) {
793 qCWarning(lcRootProperties())
794 << string << "is a date/time string being passed to formatDate()."
795 << "You should only pass date strings to formatDate().";
796 return dateTime.date();
797 }
798 }
799
800 {
801 // Since we can coerce QDate to QString, allow the resulting string format here.
802 const QDateTime dateTime = DateObject::stringToDateTime(string, engine);
803 if (dateTime.isValid())
804 return DateObject::dateTimeToDate(dateTime);
805 }
806
807 engine->throwError(QStringLiteral("Invalid argument passed to formatDate(): %1").arg(string));
808 return std::nullopt;
809}
810
811QString QtObject::formatDate(QDate date, const QString &format) const
812{
813 return date.toString(format);
814}
815
816QString QtObject::formatDate(QDate date, Qt::DateFormat format) const
817{
818 return formatDateTimeObjectUsingDateFormat(date, format);
819}
820
821QString QtObject::formatDate(const QDateTime &dateTime, const QString &format) const
822{
823 return DateObject::dateTimeToDate(dateTime).toString(format);
824}
825
826QString QtObject::formatDate(const QString &string, const QString &format) const
827{
828 if (const auto qDate = dateFromString(string, v4Engine()))
829 return formatDate(qDate.value(), format);
830
831 return QString();
832}
833
834QString QtObject::formatDate(const QDateTime &dateTime, Qt::DateFormat format) const
835{
836 return formatDateTimeObjectUsingDateFormat(DateObject::dateTimeToDate(dateTime), format);
837}
838
839QString QtObject::formatDate(const QString &string, Qt::DateFormat format) const
840{
841 if (const auto qDate = dateFromString(string, v4Engine()))
842 return formatDate(qDate.value(), format);
843
844 return QString();
845}
846
847#if QT_CONFIG(qml_locale)
848QString QtObject::formatDate(QDate date, const QLocale &locale,
849 QLocale::FormatType formatType) const
850{
851 return locale.toString(date, formatType);
852}
853
854QString QtObject::formatDate(const QDateTime &dateTime, const QLocale &locale,
855 QLocale::FormatType formatType) const
856{
857 return locale.toString(DateObject::dateTimeToDate(dateTime), formatType);
858}
859
860QString QtObject::formatDate(const QString &string, const QLocale &locale,
861 QLocale::FormatType formatType) const
862{
863 if (const auto qDate = dateFromString(string, v4Engine()))
864 return locale.toString(qDate.value(), formatType);
865
866 return QString();
867}
868#endif
869
870/*!
871\qmlmethod string Qt::formatTime(datetime time, variant format, variant localeFormatOption)
872
873Returns a string representation of \a time, optionally formatted using
874\a format, and, if provided, \a localeFormatOption.
875
876The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
877value. The \a format and \a localeFormatOption parameter may be any of the
878possible format values as described for
879\l{QtQml::Qt::formatDateTime()}{Qt.formatDateTime()}.
880
881If \a format is not specified, \a time is formatted using
882\l {QLocale::FormatType}{Locale.ShortFormat} using the default locale.
883
884\sa Locale
885*/
886static std::optional<QTime> timeFromString(const QString &string, QV4::ExecutionEngine *engine)
887{
888 {
889 const QTime time = QTime::fromString(string, Qt::ISODate);
890 if (time.isValid())
891 return time;
892 }
893
894 {
895 // For historical reasons, the string argument is parsed as datetime, not as only time
896 const QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
897 if (dateTime.isValid()) {
898 qCWarning(lcRootProperties())
899 << string << "is a date/time string being passed to formatTime()."
900 << "You should only pass time strings to formatTime().";
901 return dateTime.time();
902 }
903 }
904
905 {
906 // Since we can coerce QTime to QString, allow the resulting string format here.
907 const QDateTime dateTime = DateObject::stringToDateTime(string, engine);
908 if (dateTime.isValid())
909 return dateTimeToTime(dateTime);
910 }
911
912 engine->throwError(QStringLiteral("Invalid argument passed to formatTime(): %1").arg(string));
913 return std::nullopt;
914}
915
916QString QtObject::formatTime(QTime time, const QString &format) const
917{
918 return time.toString(format);
919}
920
921QString QtObject::formatTime(const QDateTime &dateTime, const QString &format) const
922{
923 return dateTimeToTime(dateTime).toString(format);
924}
925
926QString QtObject::formatTime(const QString &time, const QString &format) const
927{
928
929 if (auto qTime = timeFromString(time, v4Engine()))
930 return formatTime(qTime.value(), format);
931
932 return QString();
933}
934
935QString QtObject::formatTime(QTime time, Qt::DateFormat format) const
936{
937 return formatDateTimeObjectUsingDateFormat(time, format);
938}
939
940QString QtObject::formatTime(const QDateTime &dateTime, Qt::DateFormat format) const
941{
942 return formatDateTimeObjectUsingDateFormat(dateTimeToTime(dateTime), format);
943}
944
945QString QtObject::formatTime(const QString &time, Qt::DateFormat format) const
946{
947 if (auto qTime = timeFromString(time, v4Engine()))
948 return formatTime(qTime.value(), format);
949
950 return QString();
951}
952
953#if QT_CONFIG(qml_locale)
954QString QtObject::formatTime(QTime time, const QLocale &locale,
955 QLocale::FormatType formatType) const
956{
957 return locale.toString(time, formatType);
958}
959
960QString QtObject::formatTime(const QDateTime &dateTime, const QLocale &locale,
961 QLocale::FormatType formatType) const
962{
963 return locale.toString(dateTimeToTime(dateTime), formatType);
964}
965
966QString QtObject::formatTime(const QString &time, const QLocale &locale,
967 QLocale::FormatType formatType) const
968{
969 if (auto qTime = timeFromString(time, v4Engine()))
970 return locale.toString(qTime.value(), formatType);
971
972 return QString();
973}
974#endif
975
976/*!
977\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format, variant localeFormatOption)
978
979Returns a string representation of \a dateTime, optionally formatted using
980\a format and \a localeFormatOption.
981
982The \a dateTime parameter may be a JavaScript \c Date object, a \l{date}{date}
983property, a QDate, QTime, or QDateTime value.
984
985If \a format is not provided, \a dateTime is formatted using
986\l {QLocale::FormatType}{Locale.ShortFormat} using the
987default locale. Otherwise, \a format should be either:
988
989\list
990\li One of the Qt::DateFormat enumeration values, such as
991 \c Qt.RFC2822Date or \c Qt.ISODate.
992\li A string that specifies the format of the returned string, as detailed below.
993\li A \c locale object.
994\endlist
995
996If \a format specifies a locale object, \dateTime is formatted
997with \l{QLocale::toString}. In this case, \a localeFormatOption can hold a value
998of type \l {QLocale::FormatType} to further tune the formatting. If none is
999provided, \l {QLocale::FormatType}{Locale.ShortFormat} is used.
1000
1001If \a format specifies a format string, it should use the following expressions
1002to specify the date:
1003
1004 \table
1005 \header \li Expression \li Output
1006 \row \li d \li the day as number without a leading zero (1 to 31)
1007 \row \li dd \li the day as number with a leading zero (01 to 31)
1008 \row \li ddd
1009 \li the abbreviated localized day name (e.g. 'Mon' to 'Sun').
1010 Uses QDate::shortDayName().
1011 \row \li dddd
1012 \li the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
1013 Uses QDate::longDayName().
1014 \row \li M \li the month as number without a leading zero (1-12)
1015 \row \li MM \li the month as number with a leading zero (01-12)
1016 \row \li MMM
1017 \li the abbreviated localized month name (e.g. 'Jan' to 'Dec').
1018 Uses QDate::shortMonthName().
1019 \row \li MMMM
1020 \li the long localized month name (e.g. 'January' to 'December').
1021 Uses QDate::longMonthName().
1022 \row \li yy \li the year as two digit number (00-99)
1023 \row \li yyyy \li the year as four digit number
1024 \endtable
1025
1026In addition the following expressions can be used to specify the time:
1027
1028 \table
1029 \header \li Expression \li Output
1030 \row \li h
1031 \li the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
1032 \row \li hh
1033 \li the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
1034 \row \li m \li the minute without a leading zero (0 to 59)
1035 \row \li mm \li the minute with a leading zero (00 to 59)
1036 \row \li s \li the second without a leading zero (0 to 59)
1037 \row \li ss \li the second with a leading zero (00 to 59)
1038 \row \li z \li the milliseconds without leading zeroes (0 to 999)
1039 \row \li zzz \li the milliseconds with leading zeroes (000 to 999)
1040 \row \li AP
1041 \li use AM/PM display. \e AP will be replaced by either "AM" or "PM".
1042 \row \li ap
1043 \li use am/pm display. \e ap will be replaced by either "am" or "pm".
1044 \row \li t
1045 \li include a time-zone indicator.
1046 \endtable
1047
1048 All other input characters will be ignored. Any sequence of characters that
1049 are enclosed in single quotes will be treated as text and not be used as an
1050 expression. Two consecutive single quotes ("''") are replaced by a single quote
1051 in the output.
1052
1053For example, if the following date/time value was specified:
1054
1055 \code
1056 // 21 May 2001 14:13:09
1057 var dateTime = new Date(2001, 5, 21, 14, 13, 09)
1058 \endcode
1059
1060This \a dateTime value could be passed to \c Qt.formatDateTime(),
1061\l {QtQml::Qt::formatDate()}{Qt.formatDate()} or \l {QtQml::Qt::formatTime()}{Qt.formatTime()}
1062with the \a format values below to produce the following results:
1063
1064 \table
1065 \header \li Format \li Result
1066 \row \li "dd.MM.yyyy" \li 21.05.2001
1067 \row \li "ddd MMMM d yy" \li Tue May 21 01
1068 \row \li "hh:mm:ss.zzz" \li 14:13:09.042
1069 \row \li "h:m:s ap" \li 2:13:9 pm
1070 \endtable
1071
1072 \sa Locale
1073*/
1074static std::optional<QDateTime> dateTimeFromString(const QString &string, QV4::ExecutionEngine *engine)
1075{
1076 {
1077 const QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
1078 if (dateTime.isValid())
1079 return dateTime;
1080 }
1081
1082 {
1083 // Since we can coerce QDateTime to QString, allow the resulting string format here.
1084 const QDateTime dateTime = DateObject::stringToDateTime(string, engine);
1085 if (dateTime.isValid())
1086 return dateTime;
1087 }
1088
1089 engine->throwError(QStringLiteral("Invalid argument passed to formatDateTime(): %1").arg(string));
1090 return std::nullopt;
1091}
1092
1093QString QtObject::formatDateTime(const QDateTime &dateTime, const QString &format) const
1094{
1095 return dateTime.toString(format);
1096}
1097
1098QString QtObject::formatDateTime(const QString &string, const QString &format) const
1099{
1100
1101 if (const auto qDateTime = dateTimeFromString(string, v4Engine()))
1102 return formatDateTime(qDateTime.value(), format);
1103
1104 return QString();
1105}
1106
1107QString QtObject::formatDateTime(const QDateTime &dateTime, Qt::DateFormat format) const
1108{
1109 return formatDateTimeObjectUsingDateFormat(dateTime, format);
1110}
1111
1112QString QtObject::formatDateTime(const QString &string, Qt::DateFormat format) const
1113{
1114
1115 if (const auto qDateTime = dateTimeFromString(string, v4Engine()))
1116 return formatDateTime(qDateTime.value(), format);
1117
1118 return QString();
1119}
1120
1121#if QT_CONFIG(qml_locale)
1122QString QtObject::formatDateTime(const QDateTime &dateTime, const QLocale &locale,
1123 QLocale::FormatType formatType) const
1124{
1125 return locale.toString(dateTime, formatType);
1126}
1127
1128QString QtObject::formatDateTime(const QString &string, const QLocale &locale,
1129 QLocale::FormatType formatType) const
1130{
1131
1132 if (const auto qDateTime = dateTimeFromString(string, v4Engine()))
1133 return formatDateTime(qDateTime.value(), locale, formatType);
1134
1135 return QString();
1136}
1137#endif
1138
1139/*!
1140 \qmlmethod bool Qt::openUrlExternally(url target)
1141
1142 Attempts to open the specified \a target url in an external application, based on the user's
1143 desktop preferences. Returns \c true if it succeeds, \c false otherwise.
1144
1145 \warning A return value of \c true indicates that the application has successfully requested
1146 the operating system to open the URL in an external application. The external application may
1147 still fail to launch or fail to open the requested URL. This result will not be reported back
1148 to the application.
1149*/
1150bool QtObject::openUrlExternally(const QUrl &url) const
1151{
1152 return QQml_guiProvider()->openUrlExternally(resolvedUrl(url));
1153}
1154
1155/*!
1156 \qmlmethod url Qt::url(url url)
1157
1158 Returns \a url verbatim. This can be used to force a type coercion to \c url.
1159 In contrast to Qt.resolvedUrl() this retains any relative URLs. As strings
1160 are implicitly converted to urls, the function can be called with a string
1161 as argument, and will then return a url.
1162
1163 \sa resolvedUrl()
1164*/
1165QUrl QtObject::url(const QUrl &url) const
1166{
1167 return url;
1168}
1169
1170/*!
1171 \qmlmethod url Qt::resolvedUrl(url url)
1172
1173 Returns \a url resolved relative to the URL of the caller.
1174
1175 If there is no caller or the caller is not associated with a QML context,
1176 returns \a url resolved relative to the QML engine's base URL. If the QML
1177 engine has no base URL, just returns \a url.
1178
1179 \sa url()
1180*/
1181QUrl QtObject::resolvedUrl(const QUrl &url) const
1182{
1183 if (QQmlRefPointer<QQmlContextData> ctxt = v4Engine()->callingQmlContext())
1184 return ctxt->resolvedUrl(url);
1185 if (QQmlEngine *engine = qmlEngine())
1186 return engine->baseUrl().resolved(url);
1187 return url;
1188}
1189
1190/*!
1191 \qmlmethod url Qt::resolvedUrl(url url, object context)
1192
1193 Returns \a url resolved relative to the URL of the QML context of
1194 \a context. If \a context is not associated with a QML context,
1195 returns \a url resolved relative to the QML engine's base URL. If
1196 the QML engine has no base URL, just returns \a url.
1197
1198 \sa url()
1199*/
1200QUrl QtObject::resolvedUrl(const QUrl &url, QObject *context) const
1201{
1202 if (context) {
1203 QQmlData *data = QQmlData::get(context);
1204 if (data && data->outerContext)
1205 return data->outerContext->resolvedUrl(url);
1206 }
1207
1208 if (QQmlEngine *engine = qmlEngine())
1209 return engine->baseUrl().resolved(url);
1210 return url;
1211}
1212
1213/*!
1214\qmlmethod list<string> Qt::fontFamilies()
1215
1216Returns a list of the font families available to the application.
1217*/
1218QStringList QtObject::fontFamilies() const
1219{
1220 return QQml_guiProvider()->fontFamilies();
1221}
1222
1223/*!
1224\qmlmethod string Qt::md5(data)
1225Returns a hex string of the md5 hash of \a data.
1226*/
1227QString QtObject::md5(const QString &data) const
1228{
1229 return QLatin1String(QCryptographicHash::hash(data.toUtf8(), QCryptographicHash::Md5).toHex());
1230}
1231
1232/*!
1233\qmlmethod string Qt::btoa(string data)
1234\deprecated [6.11] This method performs a UTF-8 conversion of the string before encoding it.
1235
1236Binary to ASCII --- this function returns a base64 encoding of \a data.
1237*/
1238QString QtObject::btoa(const QString &data) const
1239{
1240 qWarning("Qt.btoa(string): This method is deprecated. "
1241 "Its output differs from the common Web API. "
1242 "Use the overloads that take array-likes.");
1243 return QLatin1String(data.toUtf8().toBase64());
1244}
1245
1246/*!
1247\qmlmethod string Qt::atob(string data)
1248\deprecated [6.11] This method performs a Latin-1 conversion of the string before decoding it
1249 and then interprets the result as UTF-8.
1250
1251ASCII to binary --- this function decodes the base64 encoded \a data string and returns it.
1252*/
1253QString QtObject::atob(const QString &data) const
1254{
1255 qWarning("Qt.atob(string): This method is deprecated. "
1256 "Its output differs from the common Web API. "
1257 "Use the overloads that take array-likes.");
1258 return QString::fromUtf8(QByteArray::fromBase64(data.toLatin1()));
1259}
1260
1261/*!
1262\qmlmethod ArrayBuffer Qt::btoa(ArrayBuffer data)
1263\since 6.11
1264
1265Binary to ASCII --- this function returns a base64 encoding of \a data.
1266
1267You can pass any array-like as \a data, and it will try to convert
1268it into a byte array. In particular this works with a list of numbers
1269and a list of one-character strings. The most efficient way to do this,
1270however, is passing either a QByteArray or a JavaScript ArrayBuffer
1271object.
1272
1273If the conversion fails and it turns out that the \a data is not of
1274the expected form, an \c{Invalid Character} exception is thrown and an
1275empty array is returned.
1276
1277*/
1278QByteArray QtObject::btoa(const QByteArray &data) const
1279{
1280 return data.toBase64();
1281}
1282
1283static QV4::ReturnedValue throwInvalidCharacter(QV4::ExecutionEngine *engine)
1284{
1285 QV4::Scope scope(engine);
1286 THROW_DOM(DOMEXCEPTION_INVALID_CHARACTER_ERR, "Invalid character");
1287}
1288
1289/*!
1290\qmlmethod ArrayBuffer Qt::atob(ArrayBuffer data)
1291\since 6.11
1292
1293ASCII to binary --- this function decodes the base64 encoded \a data and returns it.
1294
1295You can pass any array-like as \a data, and it will try to convert
1296it into a byte array. In particular this works with a list of numbers
1297and a list of one-character strings. The most efficient way to do this,
1298however, is passing either a QByteArray or a JavaScript ArrayBuffer
1299object.
1300
1301If the conversion fails and it turns out that the \a data is not of
1302the expected form, an \c{Invalid Character} exception is thrown and an
1303empty array is returned.
1304
1305*/
1306QByteArray QtObject::atob(const QByteArray &data) const
1307{
1308 const auto result
1309 = QByteArray::fromBase64Encoding(data, QByteArray::AbortOnBase64DecodingErrors);
1310 if (result.decodingStatus == QByteArray::Base64DecodingStatus::Ok)
1311 return result.decoded;
1312
1313 throwInvalidCharacter(v4Engine());
1314 return QByteArray();
1315}
1316
1317static QByteArray convertVariantList(const QVariantList &data, QV4::ExecutionEngine *engine)
1318{
1319 const auto fail = [&]() {
1320 throwInvalidCharacter(engine);
1321 return QByteArray();
1322 };
1323
1324 QByteArray result;
1325
1326 const auto append = [&](auto value) {
1327 if (value < 0 || value >= 256)
1328 return false;
1329 result.append(char(value));
1330 return true;
1331 };
1332
1333 for (const QVariant &entry : data) {
1334 switch (entry.typeId()) {
1335 case QMetaType::Char:
1336 result.append(*static_cast<const char *>(entry.constData()));
1337 break;
1338 case QMetaType::Int: {
1339 if (!append(*static_cast<const int *>(entry.constData())))
1340 return fail();
1341 break;
1342 }
1343 case QMetaType::Double: {
1344 if (!append(*static_cast<const double *>(entry.constData())))
1345 return fail();
1346 break;
1347 }
1348 case QMetaType::QString: {
1349 const QString *string = static_cast<const QString *>(entry.constData());
1350 if (string->length() != 1)
1351 return fail();
1352 if (!append(string->at(0).unicode()))
1353 return fail();
1354 break;
1355 }
1356 default:
1357 return fail();
1358 }
1359 }
1360
1361 return result;
1362}
1363
1364/*!
1365\qmlmethod var Qt::btoa(var data)
1366\overload
1367\since 6.11
1368
1369Binary to ASCII --- this function returns a base64 encoding of \a data.
1370*/
1371QByteArray QtObject::btoa(const QVariantList &data) const
1372{
1373 return btoa(convertVariantList(data, v4Engine()));
1374}
1375
1376/*!
1377\qmlmethod var Qt::atob(var data)
1378\overload
1379\since 6.11
1380
1381ASCII to binary --- this function decodes the base64 encoded \a data and returns it.
1382*/
1383QByteArray QtObject::atob(const QVariantList &data) const
1384{
1385 return atob(convertVariantList(data, v4Engine()));
1386}
1387
1388/*!
1389 \qmlmethod Qt::quit()
1390
1391 This function causes the QQmlEngine::quit() signal to be emitted.
1392 Within the \l {Prototyping with the QML Runtime Tool}{qml tool},
1393 this causes the launcher application to exit; to quit a C++ application
1394 when this method is called, connect the QQmlEngine::quit() signal to the
1395 QCoreApplication::quit() slot.
1396
1397 \sa exit()
1398*/
1399void QtObject::quit() const
1400{
1401 if (QQmlEngine *engine = qmlEngine())
1402 QQmlEnginePrivate::get(engine)->sendQuit();
1403}
1404
1405/*!
1406 \qmlmethod Qt::exit(int retCode)
1407
1408 This function causes the QQmlEngine::exit(int) signal to be emitted.
1409 Within the \l {Prototyping with the QML Runtime Tool}{qml tool},
1410 this causes the launcher application to exit with
1411 the specified return code (\a retCode). To exit from the event loop with a specified
1412 return code when this method is called, a C++ application can connect the
1413 QQmlEngine::exit(int) signal to the QCoreApplication::exit(int) slot.
1414
1415 \sa quit()
1416*/
1417void QtObject::exit(int retCode) const
1418{
1419 if (QQmlEngine *engine = qmlEngine())
1420 QQmlEnginePrivate::get(engine)->sendExit(retCode);
1421}
1422
1423/*!
1424\qmlmethod object Qt::createQmlObject(string qml, object parent, url url)
1425
1426Compiles the given \a qml string into a component and then returns a new object created from
1427that component. The new object will have the specified \a parent. Returns \c null if there was
1428an error in creating the component or the object.
1429
1430If \a url is specified, it will be used as URL of the component. This is useful for error
1431reporting.
1432
1433\warning The new component will shadow any existing component of the same URL. You should not
1434pass a URL of an existing component. In particular, by passing the URL of the surrounding QML
1435file, you prevent access to the surrounding component from the new one.
1436
1437Example (where \c parentItem is the id of an existing QML item):
1438
1439\snippet qml/createQmlObject.qml 0
1440
1441In the case of an error, a QQmlError object is thrown. This object has an additional property,
1442\c qmlErrors, which is an array of the errors encountered.
1443Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
1444For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
1445{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
1446
1447\note This function returns immediately, and therefore may not work if
1448the \a qml string loads new components (that is, external QML files that have not yet been loaded).
1449If this is the case, consider using \l{QtQml::Qt::createComponent()}{Qt.createComponent()} instead.
1450
1451\warning This function is extremely slow since it has to compile the passed QML string every time
1452it is invoked. Furthermore, it's very easy to produce invalid QML when programmatically constructing
1453QML code. It's much better to keep your QML components as separate files and add properties and
1454methods to customize their behavior than to produce new components by string manipulation.
1455
1456See \l {Dynamic QML Object Creation from JavaScript} for more information on using this function.
1457*/
1458QObject *QtObject::createQmlObject(const QString &qml, QObject *parent, const QUrl &url) const
1459{
1460 QQmlEngine *engine = qmlEngine();
1461 if (!engine) {
1462 v4Engine()->throwError(QStringLiteral("Qt.createQmlObject(): "
1463 "Can only be called on a QML engine."));
1464 return nullptr;
1465 }
1466
1467 struct Error {
1468 static ReturnedValue create(QV4::ExecutionEngine *v4, const QList<QQmlError> &errors) {
1469 Scope scope(v4);
1470 QString errorstr;
1471 // '+=' reserves extra capacity. Follow-up appending will be probably free.
1472 errorstr += QLatin1String("Qt.createQmlObject(): failed to create object: ");
1473
1474 QV4::ScopedArrayObject qmlerrors(scope, v4->newArrayObject());
1475 QV4::ScopedObject qmlerror(scope);
1476 QV4::ScopedString s(scope);
1477 QV4::ScopedValue v(scope);
1478 for (int ii = 0; ii < errors.size(); ++ii) {
1479 const QQmlError &error = errors.at(ii);
1480 errorstr += QLatin1String("\n ") + error.toString();
1481 qmlerror = v4->newObject();
1482 qmlerror->put((s = v4->newString(QStringLiteral("lineNumber"))), (v = QV4::Value::fromInt32(error.line())));
1483 qmlerror->put((s = v4->newString(QStringLiteral("columnNumber"))), (v = QV4::Value::fromInt32(error.column())));
1484 qmlerror->put((s = v4->newString(QStringLiteral("fileName"))), (v = v4->newString(error.url().toString())));
1485 qmlerror->put((s = v4->newString(QStringLiteral("message"))), (v = v4->newString(error.description())));
1486 qmlerrors->put(ii, qmlerror);
1487 }
1488
1489 v = v4->newString(errorstr);
1490 ScopedObject errorObject(scope, v4->newErrorObject(v));
1491 errorObject->put((s = v4->newString(QStringLiteral("qmlErrors"))), qmlerrors);
1492 return errorObject.asReturnedValue();
1493 }
1494 };
1495
1496 QQmlRefPointer<QQmlContextData> context = v4Engine()->callingQmlContext();
1497 if (!context)
1498 context = QQmlContextData::get(QQmlEnginePrivate::get(engine)->rootContext);
1499
1500 Q_ASSERT(context);
1501 QQmlContext *effectiveContext = nullptr;
1502 if (context->isPragmaLibraryContext())
1503 effectiveContext = engine->rootContext();
1504 else
1505 effectiveContext = context->asQQmlContext();
1506 Q_ASSERT(effectiveContext);
1507
1508 if (qml.isEmpty())
1509 return nullptr;
1510
1511 QUrl resolvedUrl = url;
1512 if (url.isValid() && url.isRelative())
1513 resolvedUrl = context->resolvedUrl(url);
1514
1515 if (!parent) {
1516 v4Engine()->throwError(QStringLiteral("Qt.createQmlObject(): Missing parent object"));
1517 return nullptr;
1518 }
1519
1520 QQmlRefPointer<QQmlTypeData> typeData = v4Engine()->typeLoader()->getType(
1521 qml.toUtf8(), resolvedUrl, QQmlTypeLoader::Synchronous);
1522
1523 if (!typeData->isCompleteOrError()) {
1524 v4Engine()->throwError(
1525 QStringLiteral("Qt.createQmlObject(): Failed to force synchronous loading "
1526 "of asynchronous URL '%1'").arg(resolvedUrl.toString()));
1527 return nullptr;
1528 }
1529
1530 QQmlComponent component(engine);
1531 QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component);
1532 componentPrivate->fromTypeData(typeData);
1533 componentPrivate->setProgress(1.0);
1534
1535 Scope scope(v4Engine());
1536 if (component.isError()) {
1537 ScopedValue v(scope, Error::create(scope.engine, component.errors()));
1538 scope.engine->throwError(v);
1539 return nullptr;
1540 }
1541
1542 if (!component.isReady()) {
1543 v4Engine()->throwError(QStringLiteral("Qt.createQmlObject(): Component is not ready"));
1544 return nullptr;
1545 }
1546
1547 if (!effectiveContext->isValid()) {
1548 v4Engine()->throwError(QStringLiteral("Qt.createQmlObject(): Cannot create a component "
1549 "in an invalid context"));
1550 return nullptr;
1551 }
1552
1553 QObject *obj = component.beginCreate(effectiveContext);
1554 if (obj) {
1555 QQmlData::get(obj, true)->explicitIndestructibleSet = false;
1556 QQmlData::get(obj)->indestructible = false;
1557
1558 obj->setParent(parent);
1559
1560 QList<QQmlPrivate::AutoParentFunction> functions = QQmlMetaType::parentFunctions();
1561 for (int ii = 0; ii < functions.size(); ++ii) {
1562 if (QQmlPrivate::Parented == functions.at(ii)(obj, parent))
1563 break;
1564 }
1565 }
1566 component.completeCreate();
1567
1568 if (component.isError()) {
1569 ScopedValue v(scope, Error::create(scope.engine, component.errors()));
1570 scope.engine->throwError(v);
1571 return nullptr;
1572 }
1573
1574 Q_ASSERT(obj);
1575 return obj;
1576}
1577
1578/*!
1579\qmlmethod Component Qt::createComponent(url url, enumeration mode, QtObject parent)
1580
1581Returns a \l Component object created using the QML file at the specified \a url,
1582or \c null if an empty string was given.
1583
1584The returned component's \l Component::status property indicates whether the
1585component was successfully created. If the status is \c Component.Error,
1586see \l Component::errorString() for an error description.
1587
1588If the optional \a mode parameter is set to \c Component.Asynchronous, the
1589component will be loaded in a background thread. The Component::status property
1590will be \c Component.Loading while it is loading. The status will change to
1591\c Component.Ready if the component loads successfully, or \c Component.Error
1592if loading fails. This parameter defaults to \c Component.PreferSynchronous
1593if omitted.
1594
1595If \a mode is set to \c Component.PreferSynchronous, Qt will attempt to load
1596the component synchronously, but may end up loading it asynchronously if
1597necessary. Scenarios that may cause asynchronous loading include, but are not
1598limited to, the following:
1599
1600\list
1601\li The URL refers to a network resource
1602\li The component is being created as a result of another component that is
1603being loaded asynchronously
1604\endlist
1605
1606If the optional \a parent parameter is given, it should refer to the object
1607that will become the parent for the created \l Component object. If no mode
1608was passed, this can be the second argument.
1609
1610Call \l {Component::createObject()}{Component.createObject()} on the returned
1611component to create an object instance of the component.
1612
1613For example:
1614
1615\snippet qml/createComponent-simple.qml 0
1616
1617See \l {Dynamic QML Object Creation from JavaScript} for more information on using this function.
1618
1619To create a QML object from an arbitrary string of QML (instead of a file),
1620use \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}.
1621*/
1622
1623/*!
1624\since 6.5
1625\qmlmethod Component Qt::createComponent(string moduleUri, string typeName, enumeration mode, QtObject parent)
1626\overload
1627Returns a \l Component object created for the type specified by \a moduleUri and \a typeName.
1628\qml
1629import QtQml
1630QtObject {
1631 id: root
1632 property Component myComponent: Qt.createComponent("QtQuick", "Rectangle", Component.Asynchronous, root)
1633}
1634\endqml
1635This overload mostly behaves as the \c url based version, but can be used
1636to instantiate types which do not have an URL (e.g. C++ types registered
1637via \l {QML_ELEMENT}).
1638\note In some cases, passing \c Component.Asynchronous won't have any
1639effect:
1640\list
1641\li The type is implemented in C++
1642\li The type is an inline component.
1643\endlist
1644If the optional \a parent parameter is given, it should refer to the object
1645that will become the parent for the created \l Component object. If no mode
1646was passed, this can be the second argument.
1647*/
1648
1649QQmlComponent *QtObject::createComponent(const QUrl &url, QObject *parent) const
1650{
1651 return createComponent(url, QQmlComponent::PreferSynchronous, parent);
1652}
1653
1655static void throw_invalid_compilation_mode(QV4::ExecutionEngine *engine, QQmlComponent::CompilationMode mode)
1656{
1657 engine->throwError(QStringLiteral("Invalid compilation mode %1").arg(int(mode)));
1658 // ^ QTBUG-131906
1659}
1660
1661QQmlComponent *QtObject::createComponent(const QUrl &url, QQmlComponent::CompilationMode mode,
1662 QObject *parent) const
1663{
1664 if (mode != QQmlComponent::Asynchronous && mode != QQmlComponent::PreferSynchronous) {
1665 throw_invalid_compilation_mode(v4Engine(), mode);
1666 return nullptr;
1667 }
1668
1669 if (url.isEmpty())
1670 return nullptr;
1671
1672 QQmlEngine *engine = qmlEngine();
1673 if (!engine)
1674 return nullptr;
1675
1676 auto [context, effectiveContext] = getContexts();
1677 if (!context)
1678 return nullptr;
1679
1680 QQmlComponent *c = new QQmlComponent(engine, context->resolvedUrl(url), mode, parent);
1681 QQmlComponentPrivate::get(c)->setCreationContext(std::move(effectiveContext));
1682 QQmlData::get(c, true)->explicitIndestructibleSet = false;
1683 QQmlData::get(c)->indestructible = false;
1684 return c;
1685}
1686
1687QQmlComponent *QtObject::createComponent(const QString &moduleUri, const QString &typeName,
1688 QObject *parent) const
1689{
1690 return createComponent(moduleUri, typeName, QQmlComponent::PreferSynchronous, parent);
1691}
1692
1693QQmlComponent *QtObject::createComponent(const QString &moduleUri, const QString &typeName, QQmlComponent::CompilationMode mode, QObject *parent) const
1694{
1695 if (mode != QQmlComponent::Asynchronous && mode != QQmlComponent::PreferSynchronous) {
1696 throw_invalid_compilation_mode(v4Engine(), mode);
1697 return nullptr;
1698 }
1699
1700 QQmlEngine *engine = qmlEngine();
1701 if (!engine)
1702 return nullptr;
1703
1704 if (moduleUri.isEmpty() || typeName.isEmpty())
1705 return nullptr;
1706
1707 auto [context, effectiveContext] = getContexts();
1708 if (!context)
1709 return nullptr;
1710
1711 QQmlComponent *c = new QQmlComponent(engine, moduleUri, typeName, mode, parent);
1712 if (c->isError() && !parent && moduleUri.endsWith(u".qml")) {
1713 v4Engine()->throwTypeError(
1714 QStringLiteral("Invalid arguments; did you swap mode and parent"));
1715 }
1716 QQmlComponentPrivate::get(c)->setCreationContext(std::move(effectiveContext));
1717 QQmlData::get(c, true)->explicitIndestructibleSet = false;
1718 QQmlData::get(c)->indestructible = false;
1719 return c;
1720}
1721
1722#if QT_CONFIG(translation)
1723QString QtObject::uiLanguage() const
1724{
1725 if (const QJSEngine *e = jsEngine())
1726 return e->uiLanguage();
1727 return QString();
1728}
1729
1730void QtObject::setUiLanguage(const QString &uiLanguage)
1731{
1732 if (QJSEngine *e = jsEngine())
1733 e->setUiLanguage(uiLanguage);
1734}
1735
1736QBindable<QString> QtObject::uiLanguageBindable()
1737{
1738 if (QJSEngine *e = jsEngine())
1739 return QBindable<QString>(&QJSEnginePrivate::get(e)->uiLanguage);
1740 return QBindable<QString>();
1741}
1742#endif
1743
1744#if QT_CONFIG(qml_locale)
1745/*!
1746 \qmlmethod Qt::locale(name)
1747
1748 Returns a JS object representing the locale with the specified
1749 \a name, which has the format "language[_territory][.codeset][@modifier]"
1750 or "C", where:
1751
1752 \list
1753 \li \c language is a lowercase, two-letter, ISO 639 language code,
1754 \li \c territory is an uppercase, two-letter, ISO 3166 country code, and
1755 \li \c codeset and \c modifier are ignored.
1756 \endlist
1757
1758 If the string violates the locale format, or language is not a
1759 valid ISO 369 code, the "C" locale is used instead. If country
1760 is not present, or is not a valid ISO 3166 code, the most
1761 appropriate country is chosen for the specified language.
1762
1763 \sa Locale
1764*/
1765QLocale QtObject::locale() const
1766{
1767 return QLocale();
1768}
1769
1770QLocale QtObject::locale(const QString &name) const
1771{
1772 return QLocale(name);
1773}
1774#endif
1775
1776void Heap::QQmlBindingFunction::init(const QV4::JavaScriptFunctionObject *bindingFunction)
1777{
1778 Scope scope(bindingFunction->engine());
1779 ScopedContext context(scope, bindingFunction->scope());
1780 JavaScriptFunctionObject::init(context, bindingFunction->function());
1781 this->bindingFunction.set(internalClass->engine, bindingFunction->d());
1782}
1783
1784ReturnedValue QQmlBindingFunction::virtualCall(
1785 const FunctionObject *f, const Value *, const Value *, int)
1786{
1787 // Mark this as a callable object, so that we can perform the binding magic on it.
1788 return f->engine()->throwTypeError(QStringLiteral("Bindings must not be called directly."));
1789}
1790
1792{
1793 QV4::CppStackFrame *frame = engine()->currentStackFrame;
1794 if (frame->v4Function) // synchronous loading:
1795 return QQmlSourceLocation(frame->source(), frame->lineNumber(), 0);
1796 else // async loading:
1797 return bindingFunction()->function->sourceLocation();
1798}
1799
1801
1802/*!
1803 \qmlmethod Qt::binding(function)
1804
1805 Returns a JavaScript object representing a \l{Property Binding}{property binding},
1806 with a \a function that evaluates the binding.
1807
1808 There are two main use-cases for the function: firstly, to apply a
1809 property binding imperatively from JavaScript code:
1810
1811 \snippet qml/qtBinding.1.qml 0
1812
1813 and secondly, to apply a property binding when initializing property values
1814 of dynamically constructed objects (via \l{Component::createObject()}
1815 {Component.createObject()} or \l{Loader::setSource()}{Loader.setSource()}).
1816
1817 For example, assuming the existence of a DynamicText component:
1818 \snippet qml/DynamicText.qml 0
1819
1820 the output from:
1821 \snippet qml/qtBinding.2.qml 0
1822
1823 and from:
1824 \snippet qml/qtBinding.3.qml 0
1825
1826 should both be:
1827 \code
1828 Root text extra text
1829 Modified root text extra text
1830 Dynamic text extra text
1831 Modified dynamic text extra text
1832 \endcode
1833
1834 This function cannot be used in property binding declarations
1835 (see the documentation on \l{qml-javascript-assignment}{binding
1836 declarations and binding assignments}) except when the result is
1837 stored in an array bound to a var property.
1838
1839 \snippet qml/qtBinding.4.qml 0
1840
1841 \since 5.0
1842*/
1843QJSValue QtObject::binding(const QJSValue &function) const
1844{
1845 const QV4::JavaScriptFunctionObject *f
1846 = QJSValuePrivate::asManagedType<JavaScriptFunctionObject>(&function);
1847 QV4::ExecutionEngine *e = v4Engine();
1848 if (!f) {
1849 return QJSValuePrivate::fromReturnedValue(
1850 e->throwError(
1851 QStringLiteral(
1852 "binding(): argument (binding expression) must be a function")));
1853 }
1854
1855 return QJSValuePrivate::fromReturnedValue(
1856 Encode(e->memoryManager->allocate<QQmlBindingFunction>(f)));
1857}
1858
1859void QtObject::callLater(QQmlV4FunctionPtr args)
1860{
1861 m_engine->delayedCallQueue()->addUniquelyAndExecuteLater(m_engine, args);
1862}
1863
1864/*!
1865 \qmlmethod Qt::enumStringToValue(enumType, keyName)
1866
1867 Returns the numeric value of key \a keyName in enum \a enumType. If the
1868 enum could not be found, a \c TypeError is thrown. If the key is not an
1869 entry of the enum, a \c ReferenceError is thrown.
1870 */
1871double QtObject::enumStringToValue(const QJSManagedValue &enumType, const QString &string)
1872{
1873 return retrieveFromEnum<double>(
1874 enumType,
1875 [&](const QQmlType &type, QQmlTypeLoader *typeLoader, int enumIndex, bool *ok) {
1876 return type.scopedEnumValue(typeLoader, enumIndex, string, ok);
1877 }, [&](const QQmlType &type, QQmlTypeLoader *typeLoader, int enumIndex, bool *ok) {
1878 return type.unscopedEnumValue(typeLoader, enumIndex, string, ok);
1879 }, m_engine);
1880}
1881
1882/*!
1883 \qmlmethod Qt::enumValueToString(enumType, keyValue)
1884
1885 Returns the string representation of a key of enum \a enumType that has the
1886 value \a keyValue. If the enum could not be found, a \c TypeError is
1887 thrown. If the value does not match any key of the enum, a
1888 \c ReferenceError is thrown.
1889
1890 \note If multiple keys match the value of \a keyValue, which of the
1891 matching keys will be returned is unspecified. Use enumValueToStrings in
1892 that case.
1893 */
1894QString QtObject::enumValueToString(const QJSManagedValue &enumType, double value)
1895{
1896 // Undefined -> double = NaN
1897 if (std::isnan(value)) {
1898 m_engine->throwReferenceError("Invalid second argument, entry"_L1);
1899 return {};
1900 }
1901
1902 return retrieveFromEnum<QString>(
1903 enumType,
1904 [&](const QQmlType &type, QQmlTypeLoader *typeLoader, int enumIndex, bool *ok) {
1905 return type.scopedEnumKey(typeLoader, enumIndex, QtPrivate::qSaturateRound(value), ok);
1906 }, [&](const QQmlType &type, QQmlTypeLoader *typeLoader, int enumIndex, bool *ok) {
1907 return type.unscopedEnumKey(typeLoader, enumIndex, QtPrivate::qSaturateRound(value), ok);
1908 }, m_engine);
1909}
1910
1911/*!
1912 \qmlmethod Qt::enumValueToStrings(enumType, keyValue)
1913
1914 Returns a list of the string representation of all the keys of enum
1915 \a enumType that have the value \a keyValue. If the enum could not be
1916 found, a \c TypeError is thrown. If no key in the enum has value
1917 \a keyValue, a \c ReferenceError is thrown.
1918 */
1919QStringList QtObject::enumValueToStrings(const QJSManagedValue &enumType, double value)
1920{
1921 // Undefined -> double = NaN
1922 if (std::isnan(value)) {
1923 m_engine->throwReferenceError("Invalid second argument, entry"_L1);
1924 return {};
1925 }
1926
1927 return retrieveFromEnum<QStringList>(
1928 enumType,
1929 [&](const QQmlType &type, QQmlTypeLoader *typeLoader, int enumIndex, bool *ok) {
1930 return type.scopedEnumKeys(typeLoader, enumIndex, QtPrivate::qSaturateRound(value), ok);
1931 }, [&](const QQmlType &type, QQmlTypeLoader *typeLoader, int enumIndex, bool *ok) {
1932 return type.unscopedEnumKeys(typeLoader, enumIndex, QtPrivate::qSaturateRound(value), ok);
1933 }, m_engine);
1934}
1935
1936QQmlPlatform *QtObject::platform()
1937{
1938 if (!m_platform)
1939 m_platform = new QQmlPlatform(this);
1940 return m_platform;
1941}
1942
1943QQmlApplication *QtObject::application()
1944{
1945 if (!m_application)
1946 // Only allocate an application object once
1947 m_application = QQml_guiProvider()->application(this);
1948
1949 return m_application;
1950}
1951
1952QObject *QtObject::inputMethod() const
1953{
1954 return QQml_guiProvider()->inputMethod();
1955}
1956
1957QObject *QtObject::styleHints() const
1958{
1959 return QQml_guiProvider()->styleHints();
1960}
1961
1963{
1964 Object::init();
1965 QV4::Scope scope(internalClass->engine);
1966 QV4::ScopedObject o(scope, this);
1967
1968 o->defineDefaultProperty(QStringLiteral("debug"), QV4::ConsoleObject::method_log);
1969 o->defineDefaultProperty(QStringLiteral("log"), QV4::ConsoleObject::method_log);
1970 o->defineDefaultProperty(QStringLiteral("info"), QV4::ConsoleObject::method_info);
1971 o->defineDefaultProperty(QStringLiteral("warn"), QV4::ConsoleObject::method_warn);
1972 o->defineDefaultProperty(QStringLiteral("error"), QV4::ConsoleObject::method_error);
1973 o->defineDefaultProperty(QStringLiteral("assert"), QV4::ConsoleObject::method_assert);
1974
1975 o->defineDefaultProperty(QStringLiteral("count"), QV4::ConsoleObject::method_count);
1976 o->defineDefaultProperty(QStringLiteral("profile"), QV4::ConsoleObject::method_profile);
1977 o->defineDefaultProperty(QStringLiteral("profileEnd"), QV4::ConsoleObject::method_profileEnd);
1978 o->defineDefaultProperty(QStringLiteral("time"), QV4::ConsoleObject::method_time);
1979 o->defineDefaultProperty(QStringLiteral("timeEnd"), QV4::ConsoleObject::method_timeEnd);
1980 o->defineDefaultProperty(QStringLiteral("trace"), QV4::ConsoleObject::method_trace);
1981 o->defineDefaultProperty(QStringLiteral("exception"), QV4::ConsoleObject::method_exception);
1982}
1983
1984
1991
1992static QString jsStack(QV4::ExecutionEngine *engine) {
1993 QString stack;
1994
1995 int i = 0;
1996 for (CppStackFrame *f = engine->currentStackFrame; f && i < 10; f = f->parentFrame(), ++i) {
1997 QString stackFrame;
1998
1999 if (f->isJSTypesFrame() && static_cast<JSTypesStackFrame *>(f)->isTailCalling()) {
2000 stackFrame = QStringLiteral("[elided tail calls]");
2001 } else {
2002 const int line = f->lineNumber();
2003 if (line != f->missingLineNumber()) {
2004 stackFrame = QStringLiteral("%1 (%2:%3)").arg(
2005 f->function(), f->source(), QString::number(qAbs(line)));
2006 } else {
2007 stackFrame = QStringLiteral("%1 (%2)").arg(
2008 f->function(), f->source());
2009 }
2010 }
2011
2012 if (i)
2013 stack += QLatin1Char('\n');
2014 stack += stackFrame;
2015 }
2016 return stack;
2017}
2018
2019static QString serializeArray(Object *array, ExecutionEngine *v4, QSet<QV4::Heap::Object *> &alreadySeen) {
2020 Scope scope(v4);
2021 ScopedValue val(scope);
2022 QString result;
2023 alreadySeen.insert(array->d());
2024
2025 ScopedObject detached(scope);
2026 if (Sequence *reference = array->as<Sequence>())
2027 detached = ReferenceObject::detached(reference->d());
2028 else
2029 detached = array;
2030
2031 result += QLatin1Char('[');
2032 const uint length = detached->getLength();
2033 for (uint i = 0; i < length; ++i) {
2034 if (i != 0)
2035 result += QLatin1Char(',');
2036 val = detached->get(i);
2037 if (val->isManaged() && val->managed()->isArrayLike())
2038 if (!alreadySeen.contains(val->objectValue()->d()))
2039 result += serializeArray(val->objectValue(), v4, alreadySeen);
2040 else
2041 result += QLatin1String("[Circular]");
2042 else
2043 result += val->toQStringNoThrow();
2044 }
2045 result += QLatin1Char(']');
2046
2047 alreadySeen.remove(array->d());
2048 return result;
2049};
2050
2051static ReturnedValue writeToConsole(const FunctionObject *b, const Value *argv, int argc,
2052 ConsoleLogTypes logType, bool printStack = false)
2053{
2054 const QLoggingCategory *loggingCategory = nullptr;
2055 QString result;
2056 QV4::Scope scope(b);
2057 QV4::ExecutionEngine *v4 = scope.engine;
2058
2059 int start = 0;
2060 if (argc > 0) {
2061 if (const QObjectWrapper* wrapper = argv[0].as<QObjectWrapper>()) {
2062 if (QQmlLoggingCategoryBase *category
2063 = qobject_cast<QQmlLoggingCategoryBase *>(wrapper->object())) {
2064 if (category->category())
2065 loggingCategory = category->category();
2066 else
2067 THROW_GENERIC_ERROR("A QmlLoggingCatgory was provided without a valid name");
2068 start = 1;
2069 }
2070 }
2071 }
2072
2073
2074 for (int i = start, ei = argc; i < ei; ++i) {
2075 if (i != start)
2076 result.append(QLatin1Char(' '));
2077
2078 QSet<QV4::Heap::Object *> alreadySeenElements;
2079 if (argv[i].isManaged() && argv[i].managed()->isArrayLike())
2080 result.append(serializeArray(argv[i].objectValue(), v4, alreadySeenElements));
2081 else
2082 result.append(argv[i].toQStringNoThrow());
2083 }
2084
2085 if (printStack)
2086 result += QLatin1Char('\n') + jsStack(v4);
2087
2088 if (!loggingCategory)
2089 loggingCategory = v4->qmlEngine() ? &lcQml() : &lcJs();
2090 QV4::CppStackFrame *frame = v4->currentStackFrame;
2091 const QByteArray baSource = frame ? frame->source().toUtf8() : QByteArray();
2092 const QByteArray baFunction = frame ? frame->function().toUtf8() : QByteArray();
2093 QMessageLogger logger(baSource.constData(), frame ? frame->lineNumber() : 0,
2094 baFunction.constData(), loggingCategory->categoryName());
2095
2096 switch (logType) {
2097 case Log:
2098 if (loggingCategory->isDebugEnabled())
2099 logger.debug("%s", result.toUtf8().constData());
2100 break;
2101 case Info:
2102 if (loggingCategory->isInfoEnabled())
2103 logger.info("%s", result.toUtf8().constData());
2104 break;
2105 case Warn:
2106 if (loggingCategory->isWarningEnabled())
2107 logger.warning("%s", result.toUtf8().constData());
2108 break;
2109 case Error:
2110 if (loggingCategory->isCriticalEnabled())
2111 logger.critical("%s", result.toUtf8().constData());
2112 break;
2113 default:
2114 break;
2115 }
2116
2117 return Encode::undefined();
2118}
2119
2121
2122ReturnedValue ConsoleObject::method_error(const FunctionObject *b, const Value *, const Value *argv, int argc)
2123{
2124 return writeToConsole(b, argv, argc, Error);
2125}
2126
2127ReturnedValue ConsoleObject::method_log(const FunctionObject *b, const Value *, const Value *argv, int argc)
2128{
2129 //console.log
2130 //console.debug
2131 //print
2132 return writeToConsole(b, argv, argc, Log);
2133}
2134
2135ReturnedValue ConsoleObject::method_info(const FunctionObject *b, const Value *, const Value *argv, int argc)
2136{
2137 return writeToConsole(b, argv, argc, Info);
2138}
2139
2140ReturnedValue ConsoleObject::method_profile(const FunctionObject *b, const Value *, const Value *, int)
2141{
2142 QV4::Scope scope(b);
2143 QV4::ExecutionEngine *v4 = scope.engine;
2144
2145 QV4::CppStackFrame *frame = v4->currentStackFrame;
2146 const QByteArray baSource = frame->source().toUtf8();
2147 const QByteArray baFunction = frame->function().toUtf8();
2148 QMessageLogger logger(baSource.constData(), frame->lineNumber(), baFunction.constData());
2149 QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
2150 if (!service) {
2151 logger.warning("Cannot start profiling because debug service is disabled. Start with -qmljsdebugger=port:XXXXX.");
2152 } else {
2153 service->startProfiling(v4->jsEngine());
2154 logger.debug("Profiling started.");
2155 }
2156
2157 return QV4::Encode::undefined();
2158}
2159
2160ReturnedValue ConsoleObject::method_profileEnd(const FunctionObject *b, const Value *, const Value *, int)
2161{
2162 QV4::Scope scope(b);
2163 QV4::ExecutionEngine *v4 = scope.engine;
2164
2165 QV4::CppStackFrame *frame = v4->currentStackFrame;
2166 const QByteArray baSource = frame->source().toUtf8();
2167 const QByteArray baFunction = frame->function().toUtf8();
2168 QMessageLogger logger(baSource.constData(), frame->lineNumber(), baFunction.constData());
2169
2170 QQmlProfilerService *service = QQmlDebugConnector::service<QQmlProfilerService>();
2171 if (!service) {
2172 logger.warning("Ignoring console.profileEnd(): the debug service is disabled.");
2173 } else {
2174 service->stopProfiling(v4->jsEngine());
2175 logger.debug("Profiling ended.");
2176 }
2177
2178 return QV4::Encode::undefined();
2179}
2180
2181ReturnedValue ConsoleObject::method_time(const FunctionObject *b, const Value *, const Value *argv, int argc)
2182{
2183 QV4::Scope scope(b);
2184 if (argc != 1)
2185 THROW_GENERIC_ERROR("console.time(): Invalid arguments");
2186
2187 QString name = argv[0].toQStringNoThrow();
2188 scope.engine->startTimer(name);
2189 return QV4::Encode::undefined();
2190}
2191
2192ReturnedValue ConsoleObject::method_timeEnd(const FunctionObject *b, const Value *, const Value *argv, int argc)
2193{
2194 QV4::Scope scope(b);
2195 if (argc != 1)
2196 THROW_GENERIC_ERROR("console.timeEnd(): Invalid arguments");
2197
2198 QString name = argv[0].toQStringNoThrow();
2199 bool wasRunning;
2200 qint64 elapsed = scope.engine->stopTimer(name, &wasRunning);
2201 if (wasRunning) {
2202 qDebug("%s: %llims", qPrintable(name), elapsed);
2203 }
2204 return QV4::Encode::undefined();
2205}
2206
2207ReturnedValue ConsoleObject::method_count(const FunctionObject *b, const Value *, const Value *argv, int argc)
2208{
2209 // first argument: name to print. Ignore any additional arguments
2210 QString name;
2211 if (argc > 0)
2212 name = argv[0].toQStringNoThrow();
2213
2214 Scope scope(b);
2215 QV4::ExecutionEngine *v4 = scope.engine;
2216
2217 QV4::CppStackFrame *frame = v4->currentStackFrame;
2218
2219 QString scriptName = frame->source();
2220
2221 int value = v4->consoleCountHelper(scriptName, frame->lineNumber(), 0);
2222 QString message = name + QLatin1String(": ") + QString::number(value);
2223
2224 QMessageLogger(qPrintable(scriptName), frame->lineNumber(),
2225 qPrintable(frame->function()))
2226 .debug("%s", qPrintable(message));
2227
2228 return QV4::Encode::undefined();
2229}
2230
2231ReturnedValue ConsoleObject::method_trace(const FunctionObject *b, const Value *, const Value *, int argc)
2232{
2233 QV4::Scope scope(b);
2234 if (argc != 0)
2235 THROW_GENERIC_ERROR("console.trace(): Invalid arguments");
2236
2237 QV4::ExecutionEngine *v4 = scope.engine;
2238
2239 QString stack = jsStack(v4);
2240
2241 QV4::CppStackFrame *frame = v4->currentStackFrame;
2242 QMessageLogger(frame->source().toUtf8().constData(), frame->lineNumber(),
2243 frame->function().toUtf8().constData())
2244 .debug(v4->qmlEngine() ? lcQml() : lcJs(), "%s", qPrintable(stack));
2245
2246 return QV4::Encode::undefined();
2247}
2248
2249ReturnedValue ConsoleObject::method_warn(const FunctionObject *b, const Value *, const Value *argv, int argc)
2250{
2251 return writeToConsole(b, argv, argc, Warn);
2252}
2253
2254ReturnedValue ConsoleObject::method_assert(const FunctionObject *b, const Value *, const Value *argv, int argc)
2255{
2256 QV4::Scope scope(b);
2257 if (argc == 0)
2258 THROW_GENERIC_ERROR("console.assert(): Missing argument");
2259
2260 QV4::ExecutionEngine *v4 = scope.engine;
2261
2262 if (!argv[0].toBoolean()) {
2263 QString message;
2264 for (int i = 1, ei = argc; i < ei; ++i) {
2265 if (i != 1)
2266 message.append(QLatin1Char(' '));
2267
2268 message.append(argv[i].toQStringNoThrow());
2269 }
2270
2271 QString stack = jsStack(v4);
2272
2273 QV4::CppStackFrame *frame = v4->currentStackFrame;
2274 QMessageLogger(frame->source().toUtf8().constData(), frame->lineNumber(),
2275 frame->function().toUtf8().constData())
2276 .critical("%s\n%s",qPrintable(message), qPrintable(stack));
2277
2278 }
2279 return QV4::Encode::undefined();
2280}
2281
2282ReturnedValue ConsoleObject::method_exception(const FunctionObject *b, const Value *, const Value *argv, int argc)
2283{
2284 QV4::Scope scope(b);
2285 if (argc == 0)
2286 THROW_GENERIC_ERROR("console.exception(): Missing argument");
2287
2288 return writeToConsole(b, argv, argc, Error, true);
2289}
2290
2291void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions extensions)
2292{
2293 ExecutionEngine *v4 = globalObject->engine();
2294 Scope scope(v4);
2295
2296 if (extensions.testFlag(QJSEngine::TranslationExtension)) {
2297 #if QT_CONFIG(translation)
2298 globalObject->defineDefaultProperty(QStringLiteral("qsTranslate"), QV4::GlobalExtensions::method_qsTranslate);
2299 globalObject->defineDefaultProperty(QStringLiteral("QT_TRANSLATE_NOOP"), QV4::GlobalExtensions::method_qsTranslateNoOp);
2300 globalObject->defineDefaultProperty(QStringLiteral("qsTr"), QV4::GlobalExtensions::method_qsTr);
2301 globalObject->defineDefaultProperty(QStringLiteral("QT_TR_NOOP"), QV4::GlobalExtensions::method_qsTrNoOp);
2302 globalObject->defineDefaultProperty(QStringLiteral("qsTrId"), QV4::GlobalExtensions::method_qsTrId);
2303 globalObject->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp);
2304
2305 // Initialize the Qt global object for the uiLanguage property
2306 ScopedString qtName(scope, v4->newString(QStringLiteral("Qt")));
2307 ScopedObject qt(scope, globalObject->get(qtName));
2308 if (!qt)
2309 v4->createQtObject();
2310
2311 // string prototype extension
2312 scope.engine->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"), QV4::GlobalExtensions::method_string_arg);
2313 #endif
2314 }
2315
2316 if (extensions.testFlag(QJSEngine::ConsoleExtension)) {
2317 globalObject->defineDefaultProperty(QStringLiteral("print"), QV4::ConsoleObject::method_log);
2318
2319
2320 QV4::ScopedObject console(scope, globalObject->engine()->memoryManager->allocate<QV4::ConsoleObject>());
2321 globalObject->defineDefaultProperty(QStringLiteral("console"), console);
2322 }
2323
2324 if (extensions.testFlag(QJSEngine::GarbageCollectionExtension)) {
2325 globalObject->defineDefaultProperty(QStringLiteral("gc"), QV4::GlobalExtensions::method_gc);
2326 }
2327}
2328
2329
2330#if QT_CONFIG(translation)
2331/*!
2332 \qmlmethod string Qt::qsTranslate(string context, string sourceText, string disambiguation, int n)
2333
2334 Returns a translated version of \a sourceText within the given \a context, optionally based on a
2335 \a disambiguation string and value of \a n for strings containing plurals;
2336 otherwise returns \a sourceText itself if no appropriate translated string
2337 is available.
2338
2339 If the same \a sourceText is used in different roles within the
2340 same translation \a context, an additional identifying string may be passed in
2341 for \a disambiguation.
2342
2343 Example:
2344 \snippet qml/qsTranslate.qml 0
2345
2346 Use if you have a translation \a context that differs from the file \a context.
2347
2348 \sa {Internationalization with Qt}
2349 \sa qsTr()
2350*/
2351ReturnedValue GlobalExtensions::method_qsTranslate(const FunctionObject *b, const Value *, const Value *argv, int argc)
2352{
2353 QV4::Scope scope(b);
2354 if (argc < 2)
2355 THROW_GENERIC_ERROR("qsTranslate() requires at least two arguments");
2356 if (!argv[0].isString())
2357 THROW_GENERIC_ERROR("qsTranslate(): first argument (context) must be a string");
2358 if (!argv[1].isString())
2359 THROW_GENERIC_ERROR("qsTranslate(): second argument (sourceText) must be a string");
2360 if ((argc > 2) && !argv[2].isString())
2361 THROW_GENERIC_ERROR("qsTranslate(): third argument (disambiguation) must be a string");
2362
2363 QString context = argv[0].toQStringNoThrow();
2364 QString text = argv[1].toQStringNoThrow();
2365 QString comment;
2366 if (argc > 2) comment = argv[2].toQStringNoThrow();
2367
2368 int i = 3;
2369 if (argc > i && argv[i].isString()) {
2370 qWarning("qsTranslate(): specifying the encoding as fourth argument is deprecated");
2371 ++i;
2372 }
2373
2374 int n = -1;
2375 if (argc > i)
2376 n = argv[i].toInt32();
2377
2378 if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr))
2379 if (ep->propertyCapture)
2380 ep->propertyCapture->captureTranslation();
2381
2382 QString result = QCoreApplication::translate(context.toUtf8().constData(),
2383 text.toUtf8().constData(),
2384 comment.toUtf8().constData(),
2385 n);
2386
2387 return Encode(scope.engine->newString(result));
2388}
2389
2390/*!
2391 \qmlmethod string Qt::QT_TRANSLATE_NOOP(string context, string sourceText, string disambiguation)
2392
2393 Marks \a sourceText for dynamic translation in the given \a context; i.e, the stored \a sourceText
2394 will not be altered.
2395
2396 If the same \a sourceText is used in different roles within the
2397 same translation context, an additional identifying string may be passed in
2398 for \a disambiguation.
2399
2400 Returns the \a sourceText.
2401
2402 QT_TRANSLATE_NOOP is used in conjunction with the dynamic translation functions
2403 qsTr() and qsTranslate(). It identifies a string as requiring
2404 translation (so it can be identified by \c lupdate), but leaves the actual
2405 translation to the dynamic functions.
2406
2407 Example:
2408 \snippet qml/qtTranslateNoOp.qml 0
2409
2410 \sa {Internationalization with Qt}
2411*/
2412ReturnedValue GlobalExtensions::method_qsTranslateNoOp(const FunctionObject *b, const Value *, const Value *argv, int argc)
2413{
2414 QV4::Scope scope(b);
2415 if (argc < 2)
2416 return QV4::Encode::undefined();
2417 else
2418 return argv[1].asReturnedValue();
2419}
2420
2421QString GlobalExtensions::currentTranslationContext(ExecutionEngine *engine)
2422{
2423 QString context;
2424 CppStackFrame *frame = engine->currentStackFrame;
2425
2426 // The first non-empty source URL in the call stack determines the translation context.
2427 while (frame && context.isEmpty()) {
2428 if (ExecutableCompilationUnit *unit = frame->v4Function->executableCompilationUnit()) {
2429 auto translationContextIndex = unit->unitData()->translationContextIndex();
2430 if (translationContextIndex)
2431 context = unit->stringAt(*translationContextIndex);
2432 if (!context.isEmpty())
2433 break;
2434 QString fileName = unit->fileName();
2435 QUrl url(unit->fileName());
2436 if (url.isValid() && url.isRelative()) {
2437 context = url.fileName();
2438 } else {
2439 context = QQmlFile::urlToLocalFileOrQrc(fileName);
2440 if (context.isEmpty() && fileName.startsWith(QLatin1String(":/")))
2441 context = fileName;
2442 }
2443 context = QFileInfo(context).completeBaseName();
2444 }
2445 frame = frame->parentFrame();
2446 }
2447
2448 if (context.isEmpty()) {
2449 if (QQmlRefPointer<QQmlContextData> ctxt = engine->callingQmlContext()) {
2450 QString path = ctxt->urlString();
2451 int lastSlash = path.lastIndexOf(QLatin1Char('/'));
2452 int lastDot = path.lastIndexOf(QLatin1Char('.'));
2453 int length = lastDot - (lastSlash + 1);
2454 context = (lastSlash > -1) ? path.mid(lastSlash + 1, (length > -1) ? length : -1) : QString();
2455 }
2456 }
2457
2458 return context;
2459}
2460
2461/*!
2462 \qmlmethod string Qt::qsTr(string sourceText, string disambiguation, int n)
2463
2464 Returns a translated version of \a sourceText, optionally based on a
2465 \a disambiguation string and value of \a n for strings containing plurals;
2466 otherwise returns \a sourceText itself if no appropriate translated string
2467 is available.
2468
2469 Examples with \a sourceText and \a {n}:
2470
2471 \if defined(onlinedocs)
2472 \tab {qstr}{qstr-1}{sourceText}{checked}
2473 \tab {qstr}{qstr-2}{sourceText and n}{}
2474 \tabcontent {qstr-1}
2475 \else
2476 \section1 Only sourceText
2477 \endif
2478 \snippet qml/qsTr.qml 0
2479 \if defined(onlinedocs)
2480 \endtabcontent
2481 \tabcontent {qstr-2}
2482 \else
2483 \section1 SourceText and n
2484 \endif
2485 \snippet qml/qsTr.qml 1
2486 \if defined(onlinedocs)
2487 \endtabcontent
2488 \endif
2489
2490 If the same \a sourceText is used in different roles within the
2491 same translation context, an additional identifying string may be passed in
2492 for \a disambiguation. For more information and examples, refer to
2493 \l{Disambiguate Identical Text}.
2494
2495 \sa qsTranslate()
2496 \sa {Internationalization with Qt},{Writing Source Code for Translation}
2497*/
2498ReturnedValue GlobalExtensions::method_qsTr(const FunctionObject *b, const Value *, const Value *argv, int argc)
2499{
2500 QV4::Scope scope(b);
2501 if (argc < 1)
2502 THROW_GENERIC_ERROR("qsTr() requires at least one argument");
2503 if (!argv[0].isString())
2504 THROW_GENERIC_ERROR("qsTr(): first argument (sourceText) must be a string");
2505 if ((argc > 1) && !argv[1].isString())
2506 THROW_GENERIC_ERROR("qsTr(): second argument (disambiguation) must be a string");
2507 if ((argc > 2) && !argv[2].isNumber())
2508 THROW_GENERIC_ERROR("qsTr(): third argument (n) must be a number");
2509
2510 const QString context = currentTranslationContext(scope.engine);
2511 const QString text = argv[0].toQStringNoThrow();
2512 const QString comment = argc > 1 ? argv[1].toQStringNoThrow() : QString();
2513 const int n = argc > 2 ? argv[2].toInt32() : -1;
2514
2515 if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr))
2516 if (ep->propertyCapture)
2517 ep->propertyCapture->captureTranslation();
2518
2519 QString result = QCoreApplication::translate(context.toUtf8().constData(), text.toUtf8().constData(),
2520 comment.toUtf8().constData(), n);
2521
2522 return Encode(scope.engine->newString(result));
2523}
2524
2525/*!
2526 \qmlmethod string Qt::QT_TR_NOOP(string sourceText, string disambiguation)
2527
2528 Marks \a sourceText for dynamic translation; i.e, the stored \a sourceText
2529 will not be altered.
2530
2531 If the same \a sourceText is used in different roles within the
2532 same translation context, an additional identifying string may be passed in
2533 for \a disambiguation.
2534
2535 Returns the \a sourceText.
2536
2537 QT_TR_NOOP is used in conjunction with the dynamic translation functions
2538 qsTr() and qsTranslate(). It identifies a string as requiring
2539 translation (so it can be identified by \c lupdate), but leaves the actual
2540 translation to the dynamic functions.
2541
2542 Example:
2543 \snippet qml/qtTrNoOp.qml 0
2544
2545 \sa {Internationalization with Qt}
2546*/
2547ReturnedValue GlobalExtensions::method_qsTrNoOp(const FunctionObject *, const Value *, const Value *argv, int argc)
2548{
2549 if (argc < 1)
2550 return QV4::Encode::undefined();
2551 else
2552 return argv[0].asReturnedValue();
2553}
2554
2555/*!
2556 \qmlmethod string Qt::qsTrId(string id, int n)
2557
2558 Returns a translated string identified by \a id.
2559 If no matching string is found, the id itself is returned. This
2560 should not happen under normal conditions.
2561
2562 If \a n >= 0, all occurrences of \c %n in the resulting string
2563 are replaced with a decimal representation of \a n. In addition,
2564 depending on \a n's value, the translation text may vary.
2565
2566 Example:
2567 \snippet qml/qsTrId.qml 0
2568
2569 It is possible to supply a source string template like:
2570
2571 \tt{//% <string>}
2572
2573 \snippet qml/qsTrId.1.qml 0
2574
2575 or
2576
2577 \tt{\begincomment% <string> \endcomment}
2578
2579 \snippet qml/qsTrId.1.qml 1
2580
2581 Creating binary translation (QM) files suitable for use with this function requires passing
2582 the \c -idbased option to the \c lrelease tool.
2583
2584 \sa QT_TRID_NOOP(), {Internationalization with Qt}
2585*/
2586ReturnedValue GlobalExtensions::method_qsTrId(const FunctionObject *b, const Value *, const Value *argv, int argc)
2587{
2588 QV4::Scope scope(b);
2589 if (argc < 1)
2590 THROW_GENERIC_ERROR("qsTrId() requires at least one argument");
2591 if (!argv[0].isString())
2592 THROW_TYPE_ERROR_WITH_MESSAGE("qsTrId(): first argument (id) must be a string");
2593 if (argc > 1 && !argv[1].isNumber())
2594 THROW_TYPE_ERROR_WITH_MESSAGE("qsTrId(): second argument (n) must be a number");
2595
2596 int n = -1;
2597 if (argc > 1)
2598 n = argv[1].toInt32();
2599
2600 if (QQmlEnginePrivate *ep = (scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr))
2601 if (ep->propertyCapture)
2602 ep->propertyCapture->captureTranslation();
2603
2604 return Encode(scope.engine->newString(qtTrId(argv[0].toQStringNoThrow().toUtf8().constData(), n)));
2605}
2606
2607/*!
2608 \qmlmethod string Qt::QT_TRID_NOOP(string id)
2609
2610 Marks \a id for dynamic translation.
2611
2612 Returns the \a id.
2613
2614 QT_TRID_NOOP is used in conjunction with the dynamic translation function
2615 qsTrId(). It identifies a string as requiring translation (so it can be identified
2616 by \c lupdate), but leaves the actual translation to qsTrId().
2617
2618 Example:
2619 \snippet qml/qtTrIdNoOp.qml 0
2620
2621 \sa qsTrId(), {Internationalization with Qt}
2622*/
2623ReturnedValue GlobalExtensions::method_qsTrIdNoOp(const FunctionObject *, const Value *, const Value *argv, int argc)
2624{
2625 if (argc < 1)
2626 return QV4::Encode::undefined();
2627 else
2628 return argv[0].asReturnedValue();
2629}
2630#endif // translation
2631
2632/*!
2633 \qmlmethod void Qt::gc()
2634
2635 Runs the garbage collector.
2636
2637 This is equivalent to calling QJSEngine::collectGarbage().
2638
2639 \sa {Garbage Collection}
2640*/
2641ReturnedValue GlobalExtensions::method_gc(const FunctionObject *b, const Value *, const Value *, int)
2642{
2643 auto mm = b->engine()->memoryManager;
2644 mm->runFullGC();
2645
2646 return QV4::Encode::undefined();
2647}
2648
2649ReturnedValue GlobalExtensions::method_string_arg(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
2650{
2651 QV4::Scope scope(b);
2652 if (argc != 1)
2653 THROW_GENERIC_ERROR("String.arg(): Invalid arguments");
2654
2655 QString value = thisObject->toQString();
2656
2657 QV4::ScopedValue arg(scope, argv[0]);
2658 if (arg->isInteger())
2659 RETURN_RESULT(scope.engine->newString(value.arg(arg->integerValue())));
2660 else if (arg->isDouble())
2661 RETURN_RESULT(scope.engine->newString(value.arg(arg->doubleValue())));
2662 else if (arg->isBoolean())
2663 RETURN_RESULT(scope.engine->newString(value.arg(arg->booleanValue())));
2664
2665 RETURN_RESULT(scope.engine->newString(value.arg(arg->toQString())));
2666}
2667
2668/*!
2669\qmlmethod Qt::callLater(function)
2670\qmlmethod Qt::callLater(function, argument1, argument2, ...)
2671\since 5.8
2672Use this function to eliminate redundant calls to a function or signal.
2673
2674The function passed as the first argument to Qt.callLater()
2675will be called later, once the QML engine returns to the event loop.
2676
2677When this function is called multiple times in quick succession with the
2678same function as its first argument, that function will be called only once.
2679
2680For example:
2681\snippet qml/qtLater.qml 0
2682
2683Any additional arguments passed to Qt.callLater() will
2684be passed on to the function invoked. Note that if redundant calls
2685are eliminated, then only the last set of arguments will be passed to the
2686function.
2687*/
2688
2689QT_END_NAMESPACE
2690
2691#include "moc_qqmlbuiltinfunctions_p.cpp"
Definition qjsvalue.h:23
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
DEFINE_OBJECT_VTABLE(QQmlBindingFunction)
static QByteArray convertVariantList(const QVariantList &data, QV4::ExecutionEngine *engine)
static QTime dateTimeToTime(const QDateTime &dateTime)
static QString serializeArray(Object *array, ExecutionEngine *v4, QSet< QV4::Heap::Object * > &alreadySeen)
void addParameters(QJSEngine *e, QJSValue &result, int i, T parameter, Others... others)
static QVariant constructFromJSValue(QJSEngine *e, QMetaType type, T... parameters)
void addParameters< double >(QJSEngine *, QJSValue &result, int i, double parameter)
static std::optional< QDate > dateFromString(const QString &string, QV4::ExecutionEngine *engine)
\qmlmethod string Qt::formatDate(datetime date, variant format, variant localeFormatOption)
static QV4::ReturnedValue throwInvalidCharacter(QV4::ExecutionEngine *engine)
DEFINE_OBJECT_VTABLE(ConsoleObject)
static ReturnedValue writeToConsole(const FunctionObject *b, const Value *argv, int argc, ConsoleLogTypes logType, bool printStack=false)
void addParameters(QJSEngine *e, QJSValue &result, int i, T parameter)
static QString jsStack(QV4::ExecutionEngine *engine)
static std::optional< QTime > timeFromString(const QString &string, QV4::ExecutionEngine *engine)
\qmlmethod string Qt::formatTime(datetime time, variant format, variant localeFormatOption)
static std::optional< QDateTime > dateTimeFromString(const QString &string, QV4::ExecutionEngine *engine)
\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format, variant localeFormatOption)
static Q_DECL_COLD_FUNCTION void throw_invalid_compilation_mode(QV4::ExecutionEngine *engine, QQmlComponent::CompilationMode mode)
static QVariant colorVariantFromJSValue(const QJSValue &color, bool *ok)
Q_DECLARE_LOGGING_CATEGORY(lcQml)
Q_DECLARE_LOGGING_CATEGORY(lcJs)
QQmlSourceLocation currentLocation() const