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