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