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