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