aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2020-10-29 19:34:24 +0100
committerUlf Hermann <ulf.hermann@qt.io>2020-11-09 18:10:38 +0100
commitcbe1869fbe7048f34513b201a1d9111a0a64257a (patch)
tree5c36cdf60a064f661551c8cf6a11a9716db4aa3f /src/qml/qml
parentd7008c79d4ec023527ebfc118ad47f40075f244d (diff)
QML: Rewrite Qt object in actual C++
Quite obviously, the Qt object is a singleton, extended with a namespace, backed by a member of the JavaScript global object. Defining all the methods as JavaScript functions is unnecessary and duplicates the general type transformation code. Also, it makes it hard to use those same methods from a C++ context as we cannot properly set up the arguments outside the JS engine. Rewriting the Qt object reveals some deficiencies in the old implementation that we need to fix now: 1. The enums of the Qt type were listed as properties of the Qt object, which means you could iterate them with a for..in loop in in JavaScript. This is just wrong. Enums are not properties. This functionality is deleted and the test adapted to check for each enum value separately. The commit message for the change that introduced the iterability already mentioned that the author had failed to find any occurrence of this in the real world. 2. Parsing time objects from strings was done by parsing the string as a date/time and then picking the time from that. We still support that for now, but output a (categorized) warning. Parsing the time directly is preferred where possible. 3. Previously you could create (invalid) dates and times from various kinds of QML types, like int and color. This does not work anymore as we now validate the types before calling the functions. 4. Passing more arguments to a function than the function accepted was unconditionally ignored before. Now, a Q_CLASSINFO on the surrounding class can specify that the arguments should be checked, in which case a JavaScript error is thrown if too many arguments are passed. In order for this to work correctly we also have to ignore JS undefined values as trailing arguments for overload resolution. This way, if a method matching the defined arguments exists, it will be preferred over a method that matches the full argument count, but possibly cannot accept undefined as parameter. Consequently a number of error messages change, which is reflected in the qqmlqt test. [ChangeLog][QtQMl][Important Behavior Changes] You can not iterate the enumerations of the Qt object in JavaScript anymore. This does not work with any other enumeration type either. You can of course still access them by name, for example as Qt.LeftButton or similar. [ChangeLog][QtQMl][Important Behavior Changes] The time formatting functions of the Qt object in QML now allow you to pass an actual time string, rather than a date/time string as argument. Passing a date/time string results in a warning now. [ChangeLog][QtQml][Important Behavior Changes] Functions in the Qt object for formatting date and time will now throw a JavaScript error when presented with a value of an incompatible type, such as int or color. [ChangeLog][QtQml][Important Behavior Changes] The Qt.resolvedUrl() function now returns a URL rather than a string. This follows the documentation. [ChangeLog][QtQml][Important Behavior Changes] The GlobalColor enum of the Qt namespace is not exposed to QML anymore. It did not make any sense before as the enum values could not be used as colors. Change-Id: I7fc2f24377eb2fde8f63a1ffac5548d652de7b12 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmldelayedcallqueue.cpp29
-rw-r--r--src/qml/qml/qqmldelayedcallqueue_p.h4
-rw-r--r--src/qml/qml/qqmlglobal.cpp7
-rw-r--r--src/qml/qml/qqmlglobal_p.h6
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp1050
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h208
6 files changed, 542 insertions, 762 deletions
diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp
index 02fde97b3d..141c55c0ec 100644
--- a/src/qml/qml/qqmldelayedcallqueue.cpp
+++ b/src/qml/qml/qqmldelayedcallqueue.cpp
@@ -108,6 +108,9 @@ void QQmlDelayedCallQueue::init(QV4::ExecutionEngine* engine)
QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(const QV4::FunctionObject *b, const QV4::Value *, const QV4::Value *argv, int argc)
{
+ QV4::ExecutionEngine *engine = b->engine();
+ QQmlDelayedCallQueue *self = engine->delayedCallQueue();
+
QV4::Scope scope(b);
if (argc == 0)
THROW_GENERIC_ERROR("Qt.callLater: no arguments given");
@@ -123,8 +126,8 @@ QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(const QV4::F
QVector<DelayedFunctionCall>::Iterator iter;
if (functionData.second != -1) {
// This is a QObject function wrapper
- iter = m_delayedFunctionCalls.begin();
- while (iter != m_delayedFunctionCalls.end()) {
+ iter = self->m_delayedFunctionCalls.begin();
+ while (iter != self->m_delayedFunctionCalls.end()) {
DelayedFunctionCall& dfc = *iter;
QPair<QObject *, int> storedFunctionData = QV4::QObjectMethod::extractQtMethod(dfc.m_function.as<QV4::FunctionObject>());
if (storedFunctionData == functionData) {
@@ -134,8 +137,8 @@ QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(const QV4::F
}
} else {
// This is a JavaScript function (dynamic slot on VMEMO)
- iter = m_delayedFunctionCalls.begin();
- while (iter != m_delayedFunctionCalls.end()) {
+ iter = self->m_delayedFunctionCalls.begin();
+ while (iter != self->m_delayedFunctionCalls.end()) {
DelayedFunctionCall& dfc = *iter;
if (arg0 == dfc.m_function.value()) {
break; // Already stored!
@@ -144,16 +147,16 @@ QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(const QV4::F
}
}
- const bool functionAlreadyStored = (iter != m_delayedFunctionCalls.end());
+ const bool functionAlreadyStored = (iter != self->m_delayedFunctionCalls.end());
if (functionAlreadyStored) {
DelayedFunctionCall dfc = *iter;
- m_delayedFunctionCalls.erase(iter);
- m_delayedFunctionCalls.append(dfc);
+ self->m_delayedFunctionCalls.erase(iter);
+ self->m_delayedFunctionCalls.append(dfc);
} else {
- m_delayedFunctionCalls.append(QV4::PersistentValue(m_engine, arg0));
+ self->m_delayedFunctionCalls.append(QV4::PersistentValue(engine, arg0));
}
- DelayedFunctionCall& dfc = m_delayedFunctionCalls.last();
+ DelayedFunctionCall& dfc = self->m_delayedFunctionCalls.last();
if (dfc.m_objectGuard.isNull()) {
if (functionData.second != -1) {
// if it's a qobject function wrapper, guard against qobject deletion
@@ -166,11 +169,11 @@ QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(const QV4::F
dfc.m_guarded = true;
}
}
- storeAnyArguments(dfc, argv, argc, 1, m_engine);
+ self->storeAnyArguments(dfc, argv, argc, 1, engine);
- if (!m_callbackOutstanding) {
- m_tickedMethod.invoke(this, Qt::QueuedConnection);
- m_callbackOutstanding = true;
+ if (!self->m_callbackOutstanding) {
+ self->m_tickedMethod.invoke(self, Qt::QueuedConnection);
+ self->m_callbackOutstanding = true;
}
return QV4::Encode::undefined();
}
diff --git a/src/qml/qml/qqmldelayedcallqueue_p.h b/src/qml/qml/qqmldelayedcallqueue_p.h
index 7962318561..48ee38bbb9 100644
--- a/src/qml/qml/qqmldelayedcallqueue_p.h
+++ b/src/qml/qml/qqmldelayedcallqueue_p.h
@@ -69,7 +69,9 @@ public:
void init(QV4::ExecutionEngine *);
- QV4::ReturnedValue addUniquelyAndExecuteLater(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc);
+ static QV4::ReturnedValue addUniquelyAndExecuteLater(
+ const QV4::FunctionObject *, const QV4::Value *thisObject,
+ const QV4::Value *argv, int argc);
public Q_SLOTS:
void ticked();
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp
index e3a5df382e..d4473b7020 100644
--- a/src/qml/qml/qqmlglobal.cpp
+++ b/src/qml/qml/qqmlglobal.cpp
@@ -149,9 +149,12 @@ Q_AUTOTEST_EXPORT QQmlColorProvider *QQml_colorProvider(void)
QQmlGuiProvider::~QQmlGuiProvider() {}
-QObject *QQmlGuiProvider::application(QObject *) { return new QQmlApplication(); }
+QQmlApplication *QQmlGuiProvider::application(QObject *parent)
+{
+ return new QQmlApplication(parent);
+}
QStringList QQmlGuiProvider::fontFamilies() { return QStringList(); }
-bool QQmlGuiProvider::openUrlExternally(QUrl &) { return false; }
+bool QQmlGuiProvider::openUrlExternally(const QUrl &) { return false; }
QObject *QQmlGuiProvider::inputMethod()
{
diff --git a/src/qml/qml/qqmlglobal_p.h b/src/qml/qml/qqmlglobal_p.h
index 5634ada7d1..d32641c10c 100644
--- a/src/qml/qml/qqmlglobal_p.h
+++ b/src/qml/qml/qqmlglobal_p.h
@@ -248,16 +248,16 @@ public:
Q_QML_PRIVATE_EXPORT QQmlColorProvider *QQml_setColorProvider(QQmlColorProvider *);
Q_QML_PRIVATE_EXPORT QQmlColorProvider *QQml_colorProvider();
-
+class QQmlApplication;
class Q_QML_PRIVATE_EXPORT QQmlGuiProvider
{
public:
virtual ~QQmlGuiProvider();
- virtual QObject *application(QObject *parent);
+ virtual QQmlApplication *application(QObject *parent);
virtual QObject *inputMethod();
virtual QObject *styleHints();
virtual QStringList fontFamilies();
- virtual bool openUrlExternally(QUrl &);
+ virtual bool openUrlExternally(const QUrl &);
virtual QString pluginName() const;
};
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index 7061cf1c86..0610bf0ccc 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -84,145 +84,42 @@
QT_BEGIN_NAMESPACE
-using namespace QV4;
+Q_LOGGING_CATEGORY(lcRootProperties, "qml.rootObjectProperties");
-DEFINE_OBJECT_VTABLE(QtObject);
+using namespace QV4;
#define THROW_TYPE_ERROR_WITH_MESSAGE(msg) \
do { \
return scope.engine->throwTypeError(QString::fromUtf8(msg)); \
} while (false)
-void Heap::QtObject::init(QQmlEngine *qmlEngine)
+QtObject::QtObject(ExecutionEngine *engine)
+ : m_engine(engine)
{
- Heap::Object::init();
- enumeratorIterator = 0;
- keyIterator = 0;
- Scope scope(internalClass->engine);
- ScopedObject o(scope, this);
-
- {
- ScopedString str(scope);
- ScopedValue v(scope);
- o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Value::fromInt32(0)));
- o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Value::fromInt32(1)));
- }
-
- o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
- o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject);
- o->defineDefaultProperty(QStringLiteral("color"), QV4::QtObject::method_color);
- o->defineDefaultProperty(QStringLiteral("rgba"), QV4::QtObject::method_rgba);
- o->defineDefaultProperty(QStringLiteral("hsla"), QV4::QtObject::method_hsla);
- o->defineDefaultProperty(QStringLiteral("hsva"), QV4::QtObject::method_hsva);
- o->defineDefaultProperty(QStringLiteral("colorEqual"), QV4::QtObject::method_colorEqual);
- o->defineDefaultProperty(QStringLiteral("rect"), QV4::QtObject::method_rect);
- o->defineDefaultProperty(QStringLiteral("point"), QV4::QtObject::method_point);
- o->defineDefaultProperty(QStringLiteral("size"), QV4::QtObject::method_size);
- o->defineDefaultProperty(QStringLiteral("font"), QV4::QtObject::method_font);
-
- o->defineDefaultProperty(QStringLiteral("vector2d"), QV4::QtObject::method_vector2d);
- o->defineDefaultProperty(QStringLiteral("vector3d"), QV4::QtObject::method_vector3d);
- o->defineDefaultProperty(QStringLiteral("vector4d"), QV4::QtObject::method_vector4d);
- o->defineDefaultProperty(QStringLiteral("quaternion"), QV4::QtObject::method_quaternion);
- o->defineDefaultProperty(QStringLiteral("matrix4x4"), QV4::QtObject::method_matrix4x4);
-
- o->defineDefaultProperty(QStringLiteral("formatDate"), QV4::QtObject::method_formatDate);
- o->defineDefaultProperty(QStringLiteral("formatTime"), QV4::QtObject::method_formatTime);
- o->defineDefaultProperty(QStringLiteral("formatDateTime"), QV4::QtObject::method_formatDateTime);
-
- o->defineDefaultProperty(QStringLiteral("openUrlExternally"), QV4::QtObject::method_openUrlExternally);
- o->defineDefaultProperty(QStringLiteral("fontFamilies"), QV4::QtObject::method_fontFamilies);
- o->defineDefaultProperty(QStringLiteral("md5"), QV4::QtObject::method_md5);
- o->defineDefaultProperty(QStringLiteral("btoa"), QV4::QtObject::method_btoa);
- o->defineDefaultProperty(QStringLiteral("atob"), QV4::QtObject::method_atob);
- o->defineDefaultProperty(QStringLiteral("resolvedUrl"), QV4::QtObject::method_resolvedUrl);
-#if QT_CONFIG(qml_locale)
- o->defineDefaultProperty(QStringLiteral("locale"), QV4::QtObject::method_locale);
-#endif
- o->defineDefaultProperty(QStringLiteral("binding"), QV4::QtObject::method_binding);
-
- if (qmlEngine) {
- o->defineDefaultProperty(QStringLiteral("alpha"), QV4::QtObject::method_alpha);
- o->defineDefaultProperty(QStringLiteral("lighter"), QV4::QtObject::method_lighter);
- o->defineDefaultProperty(QStringLiteral("darker"), QV4::QtObject::method_darker);
- o->defineDefaultProperty(QStringLiteral("tint"), QV4::QtObject::method_tint);
- o->defineDefaultProperty(QStringLiteral("quit"), QV4::QtObject::method_quit);
- o->defineDefaultProperty(QStringLiteral("exit"), QV4::QtObject::method_exit);
- o->defineDefaultProperty(QStringLiteral("createQmlObject"), QV4::QtObject::method_createQmlObject);
- o->defineDefaultProperty(QStringLiteral("createComponent"), QV4::QtObject::method_createComponent);
- }
-
- o->defineAccessorProperty(QStringLiteral("platform"), QV4::QtObject::method_get_platform, nullptr);
- o->defineAccessorProperty(QStringLiteral("application"), QV4::QtObject::method_get_application, nullptr);
- o->defineAccessorProperty(QStringLiteral("inputMethod"), QV4::QtObject::method_get_inputMethod, nullptr);
- o->defineAccessorProperty(QStringLiteral("styleHints"), QV4::QtObject::method_get_styleHints, nullptr);
+ QV4::Scope scope(engine);
+ QV4::ScopedString callLaterName(scope, engine->newIdentifier(QStringLiteral("callLater")));
- o->defineDefaultProperty(QStringLiteral("callLater"), QV4::QtObject::method_callLater);
-}
+ QV4::ScopedFunctionObject function(scope, QV4::FunctionObject::createBuiltinFunction(
+ engine, callLaterName, QQmlDelayedCallQueue::addUniquelyAndExecuteLater, 1));
-void QtObject::addAll()
-{
- bool dummy = false;
- findAndAdd(nullptr, dummy);
+ m_callLater = QJSValuePrivate::fromReturnedValue(function.asReturnedValue());
}
-ReturnedValue QtObject::findAndAdd(const QString *name, bool &foundProperty) const
+QtObject *QtObject::create(QQmlEngine *, QJSEngine *jsEngine)
{
- Scope scope(engine());
- ScopedObject o(scope, this);
- ScopedString key(scope);
- ScopedValue value(scope);
-
- const QMetaObject *qtMetaObject = &Qt::staticMetaObject;
- for (int enumCount = qtMetaObject->enumeratorCount(); d()->enumeratorIterator < enumCount;
- ++d()->enumeratorIterator) {
- QMetaEnum enumerator = qtMetaObject->enumerator(d()->enumeratorIterator);
- for (int keyCount = enumerator.keyCount(); d()->keyIterator < keyCount; ++d()->keyIterator) {
- key = scope.engine->newString(QString::fromUtf8(enumerator.key(d()->keyIterator)));
- value = QV4::Value::fromInt32(enumerator.value(d()->keyIterator));
- o->put(key, value);
- if (name && key->toQString() == *name) {
- ++d()->keyIterator;
- foundProperty = true;
- return value->asReturnedValue();
- }
- }
- d()->keyIterator = 0;
- }
- d()->enumeratorIterator = Heap::QtObject::Finished;
- foundProperty = false;
- return Encode::undefined();
+ QV4::ExecutionEngine *v4 = jsEngine->handle();
+ QV4::Scope scope(v4);
+ ScopedObject globalObject(scope, v4->globalObject);
+ ScopedString qtName(scope, v4->newString(QStringLiteral("Qt")));
+ QV4::ScopedValue result(scope, globalObject->get(qtName->toPropertyKey()));
+ return qobject_cast<QtObject *>(result->as<QV4::QObjectWrapper>()->object());
}
-ReturnedValue QtObject::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
+QJSValue QtObject::include(const QString &url, const QJSValue &callback) const
{
- bool hasProp = false;
- if (hasProperty == nullptr) {
- hasProperty = &hasProp;
- }
-
- ReturnedValue ret = QV4::Object::virtualGet(m, id, receiver, hasProperty);
- if (*hasProperty) {
- return ret;
- }
-
- auto that = static_cast<const QtObject*>(m);
- if (!that->d()->isComplete()) {
- const QString key = id.toQString();
- ret = that->findAndAdd(&key, *hasProperty);
- }
-
- return ret;
+ return QV4Include::method_include(v4Engine(), v4Engine()->resolvedUrl(url), callback);
}
-OwnPropertyKeyIterator *QtObject::virtualOwnPropertyKeys(const Object *m, Value *target)
-{
- auto that = static_cast<const QtObject*>(m);
- if (!that->d()->isComplete())
- const_cast<QtObject *>(that)->addAll();
-
- return Object::virtualOwnPropertyKeys(m, target);
-}
/*!
\qmlmethod bool Qt::isQtObject(object)
@@ -230,12 +127,9 @@ OwnPropertyKeyIterator *QtObject::virtualOwnPropertyKeys(const Object *m, Value
Returns \c true if \a object is a valid reference to a Qt or QML object,
\c false otherwise.
*/
-ReturnedValue QtObject::method_isQtObject(const FunctionObject *, const Value *, const Value *argv, int argc)
+bool QtObject::isQtObject(const QJSValue &value) const
{
- if (argc == 0)
- RETURN_RESULT(QV4::Encode(false));
-
- return QV4::Encode(argv[0].as<QV4::QObjectWrapper>() != nullptr);
+ return qjsvalue_cast<QObject *>(value) != nullptr;
}
/*!
@@ -244,25 +138,15 @@ ReturnedValue QtObject::method_isQtObject(const FunctionObject *, const Value *,
Returns the color corresponding to the given \a name (i.e. red or #ff0000).
If there is no such color, \c null is returned.
*/
-ReturnedValue QtObject::method_color(const FunctionObject *f, const Value *, const Value *argv,
- int argc)
+QVariant QtObject::color(const QString &name) const
{
- QV4::Scope scope(f);
- if (argc != 1)
- THROW_GENERIC_ERROR("Qt.color(): Qt.color takes exactly one argument");
-
- QVariant v = scope.engine->toVariant(argv[0], -1);
- if (v.userType() == QMetaType::QString) {
- bool ok = false;
- v = QQmlStringConverters::colorFromString(v.toString(), &ok);
- if (!ok) {
- return QV4::Encode::null();
- }
- } else {
- THROW_GENERIC_ERROR("Qt.color(): Argument must be a string");
- }
+ bool ok = false;
+ const QVariant v = QQmlStringConverters::colorFromString(name, &ok);
+ if (ok)
+ return v;
- return scope.engine->fromVariant(v);
+ v4Engine()->throwError(QStringLiteral("\"%1\" is not a valid color name").arg(name));
+ return QVariant::fromValue(nullptr);
}
/*!
@@ -271,17 +155,8 @@ ReturnedValue QtObject::method_color(const FunctionObject *f, const Value *, con
Returns a color with the specified \a red, \a green, \a blue, and \a alpha
components. All components should be in the range 0-1 (inclusive).
*/
-ReturnedValue QtObject::method_rgba(const FunctionObject *f, const Value *, const Value *argv, int argc)
+QVariant QtObject::rgba(double r, double g, double b, double a) const
{
- QV4::Scope scope(f);
- if (argc < 3 || argc > 4)
- THROW_GENERIC_ERROR("Qt.rgba(): Invalid arguments");
-
- double r = argv[0].toNumber();
- double g = argv[1].toNumber();
- double b = argv[2].toNumber();
- double a = (argc == 4) ? argv[3].toNumber() : 1;
-
if (r < 0.0) r=0.0;
if (r > 1.0) r=1.0;
if (g < 0.0) g=0.0;
@@ -291,7 +166,7 @@ ReturnedValue QtObject::method_rgba(const FunctionObject *f, const Value *, cons
if (a < 0.0) a=0.0;
if (a > 1.0) a=1.0;
- return scope.engine->fromVariant(QQml_colorProvider()->fromRgbF(r, g, b, a));
+ return QQml_colorProvider()->fromRgbF(r, g, b, a);
}
/*!
@@ -300,18 +175,8 @@ ReturnedValue QtObject::method_rgba(const FunctionObject *f, const Value *, cons
Returns a color with the specified \a hue, \a saturation, \a lightness, and \a alpha
components. All components should be in the range 0-1 (inclusive).
*/
-ReturnedValue QtObject::method_hsla(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::hsla(double h, double s, double l, double a) const
{
- QV4::Scope scope(b);
- int argCount = argc;
- if (argCount < 3 || argCount > 4)
- THROW_GENERIC_ERROR("Qt.hsla(): Invalid arguments");
-
- double h = argv[0].toNumber();
- double s = argv[1].toNumber();
- double l = argv[2].toNumber();
- double a = (argCount == 4) ? argv[3].toNumber() : 1;
-
if (h < 0.0) h=0.0;
if (h > 1.0) h=1.0;
if (s < 0.0) s=0.0;
@@ -321,7 +186,7 @@ ReturnedValue QtObject::method_hsla(const FunctionObject *b, const Value *, cons
if (a < 0.0) a=0.0;
if (a > 1.0) a=1.0;
- return scope.engine->fromVariant(QQml_colorProvider()->fromHslF(h, s, l, a));
+ return QQml_colorProvider()->fromHslF(h, s, l, a);
}
/*!
@@ -332,24 +197,14 @@ ReturnedValue QtObject::method_hsla(const FunctionObject *b, const Value *, cons
components. All components should be in the range 0-1 (inclusive).
*/
-ReturnedValue QtObject::method_hsva(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::hsva(double h, double s, double v, double a) const
{
- QV4::Scope scope(b);
- int argCount = argc;
- if (argCount < 3 || argCount > 4)
- THROW_GENERIC_ERROR("Qt.hsva(): Invalid arguments");
-
- double h = argv[0].toNumber();
- double s = argv[1].toNumber();
- double v = argv[2].toNumber();
- double a = (argCount == 4) ? argv[3].toNumber() : 1;
-
h = qBound(0.0, h, 1.0);
s = qBound(0.0, s, 1.0);
v = qBound(0.0, v, 1.0);
a = qBound(0.0, a, 1.0);
- return scope.engine->fromVariant(QQml_colorProvider()->fromHsvF(h, s, v, a));
+ return QQml_colorProvider()->fromHsvF(h, s, v, a);
}
/*!
@@ -360,36 +215,35 @@ ReturnedValue QtObject::method_hsva(const FunctionObject *b, const Value *, cons
is supplied it must be convertible to a color, as described for the
\l{colorbasictypedocs}{color} basic type.
*/
-ReturnedValue QtObject::method_colorEqual(const FunctionObject *b, const Value *, const Value *argv, int argc)
+bool QtObject::colorEqual(const QVariant &lhs, const QVariant &rhs) const
{
- QV4::Scope scope(b);
- if (argc != 2)
- THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments");
-
bool ok = false;
- QVariant lhs = scope.engine->toVariant(argv[0], -1);
- if (lhs.userType() == QMetaType::QString) {
- lhs = QQmlStringConverters::colorFromString(lhs.toString(), &ok);
+ QVariant color1 = lhs;
+ if (color1.userType() == QMetaType::QString) {
+ color1 = QQmlStringConverters::colorFromString(color1.toString(), &ok);
if (!ok) {
- THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid color name");
+ v4Engine()->throwError(QStringLiteral("Qt.colorEqual(): Invalid color name"));
+ return false;
}
- } else if (lhs.userType() != QMetaType::QColor) {
- THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments");
+ } else if (color1.userType() != QMetaType::QColor) {
+ v4Engine()->throwError(QStringLiteral("Qt.colorEqual(): Invalid arguments"));
+ return false;
}
- QVariant rhs = scope.engine->toVariant(argv[1], -1);
- if (rhs.userType() == QMetaType::QString) {
- rhs = QQmlStringConverters::colorFromString(rhs.toString(), &ok);
+ QVariant color2 = rhs;
+ if (color2.userType() == QMetaType::QString) {
+ color2 = QQmlStringConverters::colorFromString(color2.toString(), &ok);
if (!ok) {
- THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid color name");
+ v4Engine()->throwError(QStringLiteral("Qt.colorEqual(): Invalid color name"));
+ return false;
}
- } else if (rhs.userType() != QMetaType::QColor) {
- THROW_GENERIC_ERROR("Qt.colorEqual(): Invalid arguments");
+ } else if (color2.userType() != QMetaType::QColor) {
+ v4Engine()->throwError(QStringLiteral("Qt.colorEqual(): Invalid arguments"));
+ return false;
}
- bool equal = (lhs == rhs);
- return QV4::Encode(equal);
+ return color1 == color2;
}
/*!
@@ -397,18 +251,9 @@ ReturnedValue QtObject::method_colorEqual(const FunctionObject *b, const Value *
Returns a rect with the top-left corner at \a x, \a y and the specified \a width and \a height.
*/
-ReturnedValue QtObject::method_rect(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QRectF QtObject::rect(double x, double y, double width, double height) const
{
- QV4::Scope scope(b);
- if (argc != 4)
- THROW_GENERIC_ERROR("Qt.rect(): Invalid arguments");
-
- double x = argv[0].toNumber();
- double y = argv[1].toNumber();
- double w = argv[2].toNumber();
- double h = argv[3].toNumber();
-
- return scope.engine->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
+ return QRectF(x, y, width, height);
}
/*!
@@ -416,16 +261,9 @@ ReturnedValue QtObject::method_rect(const FunctionObject *b, const Value *, cons
Returns a point with the specified \a x and \a y coordinates.
*/
-ReturnedValue QtObject::method_point(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QPointF QtObject::point(double x, double y) const
{
- QV4::Scope scope(b);
- if (argc != 2)
- THROW_GENERIC_ERROR("Qt.point(): Invalid arguments");
-
- double x = argv[0].toNumber();
- double y = argv[1].toNumber();
-
- return scope.engine->fromVariant(QVariant::fromValue(QPointF(x, y)));
+ return QPointF(x, y);
}
/*!
@@ -433,16 +271,9 @@ ReturnedValue QtObject::method_point(const FunctionObject *b, const Value *, con
Returns a size with the specified \a width and \a height.
*/
-ReturnedValue QtObject::method_size(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QSizeF QtObject::size(double w, double h) const
{
- QV4::Scope scope(b);
- if (argc != 2)
- THROW_GENERIC_ERROR("Qt.size(): Invalid arguments");
-
- double w = argv[0].toNumber();
- double h = argv[1].toNumber();
-
- return scope.engine->fromVariant(QVariant::fromValue(QSizeF(w, h)));
+ return QSizeF(w, h);
}
/*!
@@ -454,37 +285,53 @@ ReturnedValue QtObject::method_size(const FunctionObject *b, const Value *, cons
subproperty names, and the values are valid values for each subproperty.
Invalid keys will be ignored.
*/
-ReturnedValue QtObject::method_font(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::font(const QJSValue &fontSpecifier) const
{
- QV4::Scope scope(b);
- if (argc != 1 || !argv[0].isObject())
- THROW_GENERIC_ERROR("Qt.font(): Invalid arguments");
+ if (!fontSpecifier.isObject()) {
+ v4Engine()->throwError(QStringLiteral("Qt.font(): Invalid arguments"));
+ return QVariant();
+ }
- QVariant v;
- if (!QQml_valueTypeProvider()->createValueType(
- QMetaType::QFont, QJSValuePrivate::fromReturnedValue(argv[0].asReturnedValue()),
- v)) {
- THROW_GENERIC_ERROR("Qt.font(): Invalid argument: no valid font subproperties specified");
+ {
+ QVariant v;
+ if (QQml_valueTypeProvider()->createValueType(QMetaType::QFont, fontSpecifier, v))
+ return v;
}
- return scope.engine->fromVariant(v);
+
+ v4Engine()->throwError(QStringLiteral("Qt.font(): Invalid argument: "
+ "no valid font subproperties specified"));
+ return QVariant();
}
-static ReturnedValue createValueType(const FunctionObject *b, const Value *argv, int argc,
- int parameters, QMetaType::Type type, const char *method)
+template<typename T>
+void addParameters(QJSEngine *e, QJSValue &result, int i, T parameter)
{
- QV4::Scope scope(b);
- if (argc != parameters) {
- return scope.engine->throwError(QString::fromUtf8("Qt.%1(): Invalid arguments")
- .arg(QString::fromUtf8(method)));
- }
+ result.setProperty(i, e->toScriptValue(parameter));
+}
- QJSValue params = scope.engine->jsEngine()->newArray(parameters);
- for (int i = 0; i < parameters; ++i)
- params.setProperty(i, QJSValuePrivate::fromReturnedValue(argv[i].asReturnedValue()));
+template<>
+void addParameters<double>(QJSEngine *, QJSValue &result, int i, double parameter)
+{
+ result.setProperty(i, QJSValue(parameter));
+}
+
+template<typename T, typename ...Others>
+void addParameters(QJSEngine *e, QJSValue &result, int i, T parameter, Others... others)
+{
+ addParameters<T>(e, result, i, parameter);
+ addParameters<Others...>(e, result, ++i, others...);
+}
+template<typename ...T>
+static QVariant createValueType(QJSEngine *e, QMetaType::Type type, T... parameters)
+{
+ if (!e)
+ return QVariant();
+ QJSValue params = e->newArray(sizeof...(parameters));
+ addParameters(e, params, 0, parameters...);
QVariant variant;
QQml_valueTypeProvider()->createValueType(type, params, variant);
- return scope.engine->fromVariant(variant);
+ return variant;
}
/*!
@@ -492,9 +339,9 @@ static ReturnedValue createValueType(const FunctionObject *b, const Value *argv,
Returns a vector2d with the specified \a x and \a y values.
*/
-ReturnedValue QtObject::method_vector2d(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::vector2d(double x, double y) const
{
- return createValueType(b, argv, argc, 2, QMetaType::QVector2D, "vector2d");
+ return createValueType(jsEngine(), QMetaType::QVector2D, x, y);
}
/*!
@@ -502,9 +349,9 @@ ReturnedValue QtObject::method_vector2d(const FunctionObject *b, const Value *,
Returns a vector3d with the specified \a x, \a y, and \a z values.
*/
-ReturnedValue QtObject::method_vector3d(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::vector3d(double x, double y, double z) const
{
- return createValueType(b, argv, argc, 3, QMetaType::QVector3D, "vector3d");
+ return createValueType(jsEngine(), QMetaType::QVector3D, x, y, z);
}
/*!
@@ -512,9 +359,9 @@ ReturnedValue QtObject::method_vector3d(const FunctionObject *b, const Value *,
Returns a vector4d with the specified \a x, \a y, \a z, and \a w values.
*/
-ReturnedValue QtObject::method_vector4d(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::vector4d(double x, double y, double z, double w) const
{
- return createValueType(b, argv, argc, 4, QMetaType::QVector4D, "vector4d");
+ return createValueType(jsEngine(), QMetaType::QVector4D, x, y, z, w);
}
/*!
@@ -522,9 +369,9 @@ ReturnedValue QtObject::method_vector4d(const FunctionObject *b, const Value *,
Returns a quaternion with the specified \a scalar, \a x, \a y, and \a z values.
*/
-ReturnedValue QtObject::method_quaternion(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::quaternion(double scalar, double x, double y, double z) const
{
- return createValueType(b, argv, argc, 4, QMetaType::QQuaternion, "quaternion");
+ return createValueType(jsEngine(), QMetaType::QQuaternion, scalar, x, y, z);
}
/*!
@@ -548,27 +395,53 @@ ReturnedValue QtObject::method_quaternion(const FunctionObject *b, const Value *
Finally, the function may be called with no arguments and the resulting
matrix will be the identity matrix.
*/
-ReturnedValue QtObject::method_matrix4x4(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::matrix4x4() const
{
- QV4::Scope scope(b);
+ QVariant variant;
+ QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, QJSValue(), variant);
+ return variant;
+}
- if (argc == 0) {
- QVariant variant;
- QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, QJSValue(), variant);
- return scope.engine->fromVariant(variant);
+QVariant QtObject::matrix4x4(const QJSValue &value) const
+{
+ if (value.isObject()) {
+ QVariant v;
+ if (QQml_valueTypeProvider()->createValueType(QMetaType::QMatrix4x4, value, v))
+ return v;
}
- if (argc == 1 && argv[0].isObject()) {
- QVariant v;
- if (!QQml_valueTypeProvider()->createValueType(
- QMetaType::QMatrix4x4,
- QJSValuePrivate::fromReturnedValue(argv[0].asReturnedValue()), v)) {
- THROW_GENERIC_ERROR("Qt.matrix4x4(): Invalid argument: not a valid matrix4x4 values array");
+ v4Engine()->throwError(QStringLiteral("Qt.matrix4x4(): Invalid argument: "
+ "not a valid matrix4x4 values array"));
+ return QVariant();
+}
+
+QVariant QtObject::matrix4x4(double m11, double m12, double m13, double m14,
+ double m21, double m22, double m23, double m24,
+ double m31, double m32, double m33, double m34,
+ double m41, double m42, double m43, double m44) const
+{
+ return createValueType(jsEngine(), QMetaType::QMatrix4x4,
+ m11, m12, m13, m14, m21, m22, m23, m24,
+ m31, m32, m33, m34, m41, m42, m43, m44);
+}
+
+static QVariant colorVariantFromJSValue(const QJSValue &color, bool *ok)
+{
+ QVariant v;
+ if (color.isString()) {
+ v = QQmlStringConverters::colorFromString(color.toString(), ok);
+ if (!(*ok))
+ return QVariant::fromValue(nullptr);
+ } else {
+ v = color.toVariant();
+ if (v.userType() != QMetaType::QColor) {
+ *ok = false;
+ return QVariant::fromValue(nullptr);
}
- return scope.engine->fromVariant(v);
}
- return createValueType(b, argv, argc, 16, QMetaType::QMatrix4x4, "matrix4x4");
+ *ok = true;
+ return v;
}
/*!
@@ -586,28 +459,11 @@ ReturnedValue QtObject::method_matrix4x4(const FunctionObject *b, const Value *,
If \a factor is not supplied, returns a color that is 50% lighter than \a baseColor (factor 1.5).
*/
-ReturnedValue QtObject::method_lighter(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::lighter(const QJSValue &color, double factor) const
{
- QV4::Scope scope(b);
- if (argc != 1 && argc != 2)
- THROW_GENERIC_ERROR("Qt.lighter(): Invalid arguments");
-
- QVariant v = scope.engine->toVariant(argv[0], -1);
- if (v.userType() == QMetaType::QString) {
- bool ok = false;
- v = QQmlStringConverters::colorFromString(v.toString(), &ok);
- if (!ok) {
- return QV4::Encode::null();
- }
- } else if (v.userType() != QMetaType::QColor) {
- return QV4::Encode::null();
- }
-
- qreal factor = 1.5;
- if (argc == 2)
- factor = argv[1].toNumber();
-
- return scope.engine->fromVariant(QQml_colorProvider()->lighter(v, factor));
+ bool ok;
+ const QVariant v = colorVariantFromJSValue(color, &ok);
+ return ok ? QQml_colorProvider()->lighter(v, factor) : v;
}
/*!
@@ -626,28 +482,11 @@ ReturnedValue QtObject::method_lighter(const FunctionObject *b, const Value *, c
If \a factor is not supplied, returns a color that is 50% darker than \a baseColor (factor 2.0).
*/
-ReturnedValue QtObject::method_darker(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::darker(const QJSValue &color, double factor) const
{
- QV4::Scope scope(b);
- if (argc != 1 && argc != 2)
- THROW_GENERIC_ERROR("Qt.darker(): Invalid arguments");
-
- QVariant v = scope.engine->toVariant(argv[0], -1);
- if (v.userType() == QMetaType::QString) {
- bool ok = false;
- v = QQmlStringConverters::colorFromString(v.toString(), &ok);
- if (!ok) {
- return QV4::Encode::null();
- }
- } else if (v.userType() != QMetaType::QColor) {
- return QV4::Encode::null();
- }
-
- qreal factor = 2.0;
- if (argc == 2)
- factor = argv[1].toNumber();
-
- return scope.engine->fromVariant(QQml_colorProvider()->darker(v, factor));
+ bool ok;
+ const QVariant v = colorVariantFromJSValue(color, &ok);
+ return ok ? QQml_colorProvider()->darker(v, factor) : v;
}
/*!
@@ -657,26 +496,11 @@ ReturnedValue QtObject::method_darker(const FunctionObject *b, const Value *, co
\a value is a real ranging from 0 (completely transparent) to 1 (completely opaque).
*/
-ReturnedValue QtObject::method_alpha(const FunctionObject *b, const Value *, const Value *argv,
- int argc)
+QVariant QtObject::alpha(const QJSValue &baseColor, double value) const
{
- QV4::Scope scope(b);
- if (argc != 2)
- THROW_GENERIC_ERROR("Qt.alpha(): Wrong number of arguments provided");
-
- QVariant v = scope.engine->toVariant(argv[0], -1);
- if (v.userType() == QMetaType::QString) {
- bool ok = false;
- v = QQmlStringConverters::colorFromString(v.toString(), &ok);
- if (!ok)
- return QV4::Encode::null();
- } else if (v.userType() != QMetaType::QColor) {
- return QV4::Encode::null();
- }
-
- qreal value = argv[1].toNumber();
-
- return scope.engine->fromVariant(QQml_colorProvider()->alpha(v, value));
+ bool ok;
+ const QVariant v = colorVariantFromJSValue(baseColor, &ok);
+ return ok ? QQml_colorProvider()->alpha(v, value) : v;
}
/*!
@@ -705,37 +529,19 @@ ReturnedValue QtObject::method_alpha(const FunctionObject *b, const Value *, con
Tint is most useful when a subtle change is intended to be conveyed due to some event;
you can then use tinting to more effectively tune the visible color.
*/
-ReturnedValue QtObject::method_tint(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QVariant QtObject::tint(const QJSValue &baseColor, const QJSValue &tintColor) const
{
- QV4::Scope scope(b);
- if (argc != 2)
- THROW_GENERIC_ERROR("Qt.tint(): Invalid arguments");
+ bool ok;
// base color
- QVariant v1 = scope.engine->toVariant(argv[0], -1);
- if (v1.userType() == QMetaType::QString) {
- bool ok = false;
- v1 = QQmlStringConverters::colorFromString(v1.toString(), &ok);
- if (!ok) {
- return QV4::Encode::null();
- }
- } else if (v1.userType() != QMetaType::QColor) {
- return QV4::Encode::null();
- }
+ const QVariant v1 = colorVariantFromJSValue(baseColor, &ok);
+ if (!ok)
+ return v1;
// tint color
- QVariant v2 = scope.engine->toVariant(argv[1], -1);
- if (v2.userType() == QMetaType::QString) {
- bool ok = false;
- v2 = QQmlStringConverters::colorFromString(v2.toString(), &ok);
- if (!ok) {
- return QV4::Encode::null();
- }
- } else if (v2.userType() != QMetaType::QColor) {
- return QV4::Encode::null();
- }
+ const QVariant v2 = colorVariantFromJSValue(tintColor, &ok);
- return scope.engine->fromVariant(QQml_colorProvider()->tint(v1, v2));
+ return ok ? QQml_colorProvider()->tint(v1, v2) : v2;
}
namespace {
@@ -753,46 +559,6 @@ QString formatDateTimeObjectUsingDateFormat(T formatThis, Qt::DateFormat format)
// Q_UNREACHABLE(); // ### Qt 6: restore once the default is gone
return QString();
}
-
-template <typename T>
-ReturnedValue formatDateTimeObject(const T &formatThis, const QV4::Scope &scope, const QString &functionName, int argc, const Value *argv) {
-
- QString formatted;
- if (argc >= 2) {
- QV4::ScopedString s(scope, argv[1]);
- if (s) {
- if (argc == 3)
- scope.engine->throwError(QLatin1String("%1(): Stay argument, third argument can only be used if second argument is a locale").arg(functionName));
- QString format = s->toQString();
- formatted = formatThis.toString(format);
- } else if (argv[1].isNumber()) {
- if (argc == 3)
- scope.engine->throwError(QLatin1String("%1(): Stay argument, third argument can only be used if second argument is a locale").arg(functionName));
- quint32 intFormat = argv[1].asDouble();
- Qt::DateFormat format = Qt::DateFormat(intFormat);
- formatted = formatDateTimeObjectUsingDateFormat(formatThis, format);
- } else {
- QLocale::FormatType formatOptions = QLocale::ShortFormat;
- if (argc == 3) {
- if (argv[2].isNumber())
- formatOptions = QLocale::FormatType(quint32(argv[2].asDouble()));
- else
- scope.engine->throwError(QLatin1String("%1(): Third argument must be a Locale format option").arg(functionName));
- }
- auto enginePriv = QQmlEnginePrivate::get(scope.engine->qmlEngine());
- auto localeMetaTypeId = qMetaTypeId<QLocale>();
- QVariant locale = enginePriv->v4engine()->toVariant(argv[1], localeMetaTypeId);
- if (!locale.canConvert(QMetaType(localeMetaTypeId)))
- scope.engine->throwError(QLatin1String("%1(): Bad second argument (must be either string, number or locale)").arg(functionName));
- formatted = locale.value<QLocale>().toString(formatThis, formatOptions);
- }
- } else {
- formatted = QLocale().toString(formatThis, QLocale::ShortFormat);
- }
-
- return Encode(scope.engine->newString(formatted));
-}
-
}
/*!
@@ -811,17 +577,23 @@ default locale.
\sa Locale
*/
-ReturnedValue QtObject::method_formatDate(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QString QtObject::formatDate(const QDate &date, const QString &format) const
{
- QV4::Scope scope(b);
- if (argc < 1)
- THROW_GENERIC_ERROR("Qt.formatDate(): Missing argument");
- if (argc > 3)
- THROW_GENERIC_ERROR("Qt.formatDate(): Stray arguments; formatDate takes at most 3 arguments.");
+ return date.toString(format);
+}
- QDate date = scope.engine->toVariant(argv[0], -1).toDateTime().date();
- return formatDateTimeObject(date, scope, QLatin1String("Qt.formatDate"), argc, argv);
+QString QtObject::formatDate(const QDate &date, Qt::DateFormat format) const
+{
+ return formatDateTimeObjectUsingDateFormat(date, format);
+}
+
+#if QT_CONFIG(qml_locale)
+QString QtObject::formatDate(const QDate &date, const QLocale &locale,
+ QLocale::FormatType formatType) const
+{
+ return locale.toString(date, formatType);
}
+#endif
/*!
\qmlmethod string Qt::formatTime(datetime time, variant format, variant localeFormatOption)
@@ -839,23 +611,73 @@ If \a format is not specified, \a time is formatted using
\sa Locale
*/
-ReturnedValue QtObject::method_formatTime(const FunctionObject *b, const Value *, const Value *argv, int argc)
+static std::optional<QTime> timeFromString(const QString &string, QV4::ExecutionEngine *engine)
{
- QV4::Scope scope(b);
- if (argc < 1)
- THROW_GENERIC_ERROR("Qt.formatTime(): Missing argument");
- if (argc > 3)
- THROW_GENERIC_ERROR("Qt.formatTime(): Stray arguments; formatTime takes at most 3 arguments.");
+ {
+ const QTime time = QTime::fromString(string, Qt::ISODate);
+ if (time.isValid())
+ return time;
+ }
+
+ {
+ // For historical reasons, the string argument is parsed as datetime, not as only time
+ const QDateTime dateTime = QDateTime::fromString(string, Qt::ISODate);
+ if (dateTime.isValid()) {
+ qCWarning(lcRootProperties())
+ << string << "is a date/time string being passed to formatTime()."
+ << "You should only pass time strings to formatTime().";
+ return dateTime.time();
+ }
+ }
+
+ engine->throwError(QStringLiteral("Invalid argument passed to formatTime(): %1").arg(string));
+ return std::nullopt;
+}
+
+QString QtObject::formatTime(const QTime &time, const QString &format) const
+{
+ return time.toString(format);
+}
+
+QString QtObject::formatTime(const QString &time, const QString &format) const
+{
+
+ if (auto qTime = timeFromString(time, v4Engine()))
+ return formatTime(qTime.value(), format);
+
+ return QString();
+}
+
+QString QtObject::formatTime(const QTime &time, Qt::DateFormat format) const
+{
+ return formatDateTimeObjectUsingDateFormat(time, format);
+}
- QVariant argVariant = scope.engine->toVariant(argv[0], -1);
- QTime time;
- if (argv[0].as<DateObject>() || (argVariant.userType() == QMetaType::QString))
- time = argVariant.toDateTime().time();
- else // if (argVariant.type() == QVariant::Time), or invalid.
- time = argVariant.toTime();
- return formatDateTimeObject(time, scope, QLatin1String("Qt.formatTime"), argc, argv);
+QString QtObject::formatTime(const QString &time, Qt::DateFormat format) const
+{
+ if (auto qTime = timeFromString(time, v4Engine()))
+ return formatTime(qTime.value(), format);
+
+ return QString();
+}
+
+#if QT_CONFIG(qml_locale)
+QString QtObject::formatTime(const QTime &time, const QLocale &locale,
+ QLocale::FormatType formatType) const
+{
+ return locale.toString(time, formatType);
}
+QString QtObject::formatTime(const QString &time, const QLocale &locale,
+ QLocale::FormatType formatType) const
+{
+ if (auto qTime = timeFromString(time, v4Engine()))
+ return locale.toString(qTime.value(), formatType);
+
+ return QString();
+}
+#endif
+
/*!
\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format, variant localeFormatOption)
@@ -954,17 +776,23 @@ with the \a format values below to produce the following results:
\sa Locale
*/
-ReturnedValue QtObject::method_formatDateTime(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QString QtObject::formatDateTime(const QDateTime &dateTime, const QString &format) const
{
- QV4::Scope scope(b);
- if (argc < 1)
- THROW_GENERIC_ERROR("Qt.formatDateTime(): Missing argument");
- if (argc > 3)
- THROW_GENERIC_ERROR("Qt.formatDateTime(): Stray arguments; formatDate takes at most 3 arguments.");
+ return dateTime.toString(format);
+}
- QDateTime dt = scope.engine->toVariant(argv[0], -1).toDateTime();
- return formatDateTimeObject(dt, scope, QLatin1String("Qt.formatDateTime"), argc, argv);
+QString QtObject::formatDateTime(const QDateTime &dateTime, Qt::DateFormat format) const
+{
+ return formatDateTimeObjectUsingDateFormat(dateTime, format);
+}
+
+#if QT_CONFIG(qml_locale)
+QString QtObject::formatDateTime(const QDateTime &dateTime, const QLocale &locale,
+ QLocale::FormatType formatType) const
+{
+ return locale.toString(dateTime, formatType);
}
+#endif
/*!
\qmlmethod bool Qt::openUrlExternally(url target)
@@ -977,15 +805,9 @@ ReturnedValue QtObject::method_formatDateTime(const FunctionObject *b, const Val
still fail to launch or fail to open the requested URL. This result will not be reported back
to the application.
*/
-ReturnedValue QtObject::method_openUrlExternally(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+bool QtObject::openUrlExternally(const QUrl &url) const
{
- QV4::Scope scope(b);
- if (argc != 1)
- return QV4::Encode(false);
-
- ScopedValue result(scope, method_resolvedUrl(b, thisObject, argv, argc));
- QUrl url(result->toQStringNoThrow());
- return scope.engine->fromVariant(QQml_guiProvider()->openUrlExternally(url));
+ return QQml_guiProvider()->openUrlExternally(resolvedUrl(url));
}
/*!
@@ -993,24 +815,13 @@ ReturnedValue QtObject::method_openUrlExternally(const FunctionObject *b, const
Returns \a url resolved relative to the URL of the caller.
*/
-ReturnedValue QtObject::method_resolvedUrl(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QUrl QtObject::resolvedUrl(const QUrl &url) const
{
- QV4::Scope scope(b);
- if (argc != 1)
- return Encode::undefined();
-
- QUrl url = scope.engine->toVariant(argv[0], -1).toUrl();
- QQmlEngine *e = scope.engine->qmlEngine();
- QQmlEnginePrivate *p = nullptr;
- if (e) p = QQmlEnginePrivate::get(e);
- if (p) {
- if (QQmlRefPointer<QQmlContextData> ctxt = scope.engine->callingQmlContext())
- return Encode(scope.engine->newString(ctxt->resolvedUrl(url).toString()));
- else
- return Encode(scope.engine->newString(url.toString()));
- }
-
- return Encode(scope.engine->newString(e->baseUrl().resolved(url).toString()));
+ if (QQmlRefPointer<QQmlContextData> ctxt = v4Engine()->callingQmlContext())
+ return ctxt->resolvedUrl(url);
+ if (QQmlEngine *engine = qmlEngine())
+ return engine->baseUrl().resolved(url);
+ return url;
}
/*!
@@ -1018,58 +829,36 @@ ReturnedValue QtObject::method_resolvedUrl(const FunctionObject *b, const Value
Returns a list of the font families available to the application.
*/
-ReturnedValue QtObject::method_fontFamilies(const FunctionObject *b, const Value *, const Value *, int argc)
+QStringList QtObject::fontFamilies() const
{
- QV4::Scope scope(b);
- if (argc != 0)
- THROW_GENERIC_ERROR("Qt.fontFamilies(): Invalid arguments");
-
- return scope.engine->fromVariant(QVariant(QQml_guiProvider()->fontFamilies()));
+ return QQml_guiProvider()->fontFamilies();
}
/*!
\qmlmethod string Qt::md5(data)
Returns a hex string of the md5 hash of \a data.
*/
-ReturnedValue QtObject::method_md5(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QString QtObject::md5(const QString &data) const
{
- QV4::Scope scope(b);
- if (argc != 1)
- THROW_GENERIC_ERROR("Qt.md5(): Invalid arguments");
-
- QByteArray data = argv[0].toQStringNoThrow().toUtf8();
- QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
- return Encode(scope.engine->newString(QLatin1String(result.toHex())));
+ return QLatin1String(QCryptographicHash::hash(data.toUtf8(), QCryptographicHash::Md5).toHex());
}
/*!
\qmlmethod string Qt::btoa(data)
Binary to ASCII - this function returns a base64 encoding of \a data.
*/
-ReturnedValue QtObject::method_btoa(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QString QtObject::btoa(const QString &data) const
{
- QV4::Scope scope(b);
- if (argc != 1)
- THROW_GENERIC_ERROR("Qt.btoa(): Invalid arguments");
-
- QByteArray data = argv[0].toQStringNoThrow().toUtf8();
-
- return Encode(scope.engine->newString(QLatin1String(data.toBase64())));
+ return QLatin1String(data.toUtf8().toBase64());
}
/*!
\qmlmethod string Qt::atob(data)
ASCII to binary - this function decodes the base64 encoded \a data string and returns it.
*/
-ReturnedValue QtObject::method_atob(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QString QtObject::atob(const QString &data) const
{
- QV4::Scope scope(b);
- if (argc != 1)
- THROW_GENERIC_ERROR("Qt.atob(): Invalid arguments");
-
- QByteArray data = argv[0].toQStringNoThrow().toLatin1();
-
- return Encode(scope.engine->newString(QString::fromUtf8(QByteArray::fromBase64(data))));
+ return QString::fromUtf8(QByteArray::fromBase64(data.toLatin1()));
}
/*!
@@ -1081,10 +870,10 @@ QQmlEngine::quit() signal to the QCoreApplication::quit() slot.
\sa exit()
*/
-ReturnedValue QtObject::method_quit(const FunctionObject *b, const Value *, const Value *, int)
+void QtObject::quit() const
{
- QQmlEnginePrivate::get(b->engine()->qmlEngine())->sendQuit();
- return Encode::undefined();
+ if (QQmlEngine *engine = qmlEngine())
+ QQmlEnginePrivate::get(engine)->sendQuit();
}
/*!
@@ -1098,16 +887,10 @@ ReturnedValue QtObject::method_quit(const FunctionObject *b, const Value *, cons
\sa quit()
*/
-ReturnedValue QtObject::method_exit(const FunctionObject *b, const Value *, const Value *argv, int argc)
+void QtObject::exit(int retCode) const
{
- QV4::Scope scope(b);
- if (argc != 1)
- THROW_GENERIC_ERROR("Qt.exit(): Invalid arguments");
-
- int retCode = argv[0].toNumber();
-
- QQmlEnginePrivate::get(scope.engine->qmlEngine())->sendExit(retCode);
- return QV4::Encode::undefined();
+ if (QQmlEngine *engine = qmlEngine())
+ QQmlEnginePrivate::get(engine)->sendExit(retCode);
}
/*!
@@ -1134,11 +917,14 @@ If this is the case, consider using \l{QtQml::Qt::createComponent()}{Qt.createCo
See \l {Dynamic QML Object Creation from JavaScript} for more information on using this function.
*/
-ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QObject *QtObject::createQmlObject(const QString &qml, QObject *parent, const QUrl &url) const
{
- QV4::Scope scope(b);
- if (argc < 2 || argc > 3)
- THROW_GENERIC_ERROR("Qt.createQmlObject(): Invalid arguments");
+ QQmlEngine *engine = qmlEngine();
+ if (!engine) {
+ v4Engine()->throwError(QStringLiteral("Qt.createQmlObject(): "
+ "Can only be called on a QML engine."));
+ return nullptr;
+ }
struct Error {
static ReturnedValue create(QV4::ExecutionEngine *v4, const QList<QQmlError> &errors) {
@@ -1169,14 +955,10 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
}
};
- QQmlEngine *engine = scope.engine->qmlEngine();
+ QQmlRefPointer<QQmlContextData> context = v4Engine()->callingQmlContext();
+ if (!context)
+ context = QQmlContextData::get(QQmlEnginePrivate::get(engine)->rootContext);
- QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
- if (!context) {
- QQmlEngine *qmlEngine = scope.engine->qmlEngine();
- if (qmlEngine)
- context = QQmlContextData::get(QQmlEnginePrivate::get(qmlEngine)->rootContext);
- }
Q_ASSERT(context);
QQmlContext *effectiveContext = nullptr;
if (context->isPragmaLibraryContext())
@@ -1185,44 +967,42 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
effectiveContext = context->asQQmlContext();
Q_ASSERT(effectiveContext);
- QString qml = argv[0].toQStringNoThrow();
if (qml.isEmpty())
- RETURN_RESULT(Encode::null());
-
- QUrl url;
- if (argc > 2)
- url = QUrl(argv[2].toQStringNoThrow());
- else
- url = QUrl(QLatin1String("inline"));
+ return nullptr;
+ QUrl resolvedUrl = url;
if (url.isValid() && url.isRelative())
- url = context->resolvedUrl(url);
+ resolvedUrl = context->resolvedUrl(url);
- QObject *parentArg = nullptr;
- QV4::Scoped<QV4::QObjectWrapper> qobjectWrapper(scope, argv[1]);
- if (!!qobjectWrapper)
- parentArg = qobjectWrapper->object();
- if (!parentArg)
- THROW_GENERIC_ERROR("Qt.createQmlObject(): Missing parent object");
+ if (!parent) {
+ v4Engine()->throwError(QStringLiteral("Qt.createQmlObject(): Missing parent object"));
+ return nullptr;
+ }
QQmlRefPointer<QQmlTypeData> typeData = QQmlEnginePrivate::get(engine)->typeLoader.getType(
- qml.toUtf8(), url, QQmlTypeLoader::Synchronous);
+ qml.toUtf8(), resolvedUrl, QQmlTypeLoader::Synchronous);
Q_ASSERT(typeData->isCompleteOrError());
QQmlComponent component(engine);
QQmlComponentPrivate *componentPrivate = QQmlComponentPrivate::get(&component);
componentPrivate->fromTypeData(typeData);
componentPrivate->progress = 1.0;
+ Scope scope(v4Engine());
if (component.isError()) {
ScopedValue v(scope, Error::create(scope.engine, component.errors()));
- RETURN_RESULT(scope.engine->throwError(v));
+ scope.engine->throwError(v);
+ return nullptr;
}
- if (!component.isReady())
- THROW_GENERIC_ERROR("Qt.createQmlObject(): Component is not ready");
+ if (!component.isReady()) {
+ v4Engine()->throwError(QStringLiteral("Qt.createQmlObject(): Component is not ready"));
+ return nullptr;
+ }
if (!effectiveContext->isValid()) {
- THROW_GENERIC_ERROR("Qt.createQmlObject(): Cannot create a component in an invalid context");
+ v4Engine()->throwError(QStringLiteral("Qt.createQmlObject(): Cannot create a component "
+ "in an invalid context"));
+ return nullptr;
}
QObject *obj = component.beginCreate(effectiveContext);
@@ -1230,12 +1010,11 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
QQmlData::get(obj, true)->explicitIndestructibleSet = false;
QQmlData::get(obj)->indestructible = false;
-
- obj->setParent(parentArg);
+ obj->setParent(parent);
QList<QQmlPrivate::AutoParentFunction> functions = QQmlMetaType::parentFunctions();
for (int ii = 0; ii < functions.count(); ++ii) {
- if (QQmlPrivate::Parented == functions.at(ii)(obj, parentArg))
+ if (QQmlPrivate::Parented == functions.at(ii)(obj, parent))
break;
}
}
@@ -1243,12 +1022,12 @@ ReturnedValue QtObject::method_createQmlObject(const FunctionObject *b, const Va
if (component.isError()) {
ScopedValue v(scope, Error::create(scope.engine, component.errors()));
- return scope.engine->throwError(v);
+ scope.engine->throwError(v);
+ return nullptr;
}
Q_ASSERT(obj);
-
- return QV4::QObjectWrapper::wrap(scope.engine, obj);
+ return obj;
}
/*!
@@ -1295,101 +1074,59 @@ See \l {Dynamic QML Object Creation from JavaScript} for more information on usi
To create a QML object from an arbitrary string of QML (instead of a file),
use \l{QtQml::Qt::createQmlObject()}{Qt.createQmlObject()}.
*/
-ReturnedValue QtObject::method_createComponent(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QQmlComponent *QtObject::createComponent(const QUrl &url, QObject *parent) const
{
- QV4::Scope scope(b);
- if (argc < 1 || argc > 3)
- THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments");
-
- QQmlEngine *engine = scope.engine->qmlEngine();
+ return createComponent(url, QQmlComponent::PreferSynchronous, parent);
+}
- QQmlRefPointer<QQmlContextData> context = scope.engine->callingQmlContext();
- if (!context) {
- QQmlEngine *qmlEngine = scope.engine->qmlEngine();
- if (qmlEngine)
- context = QQmlContextData::get(QQmlEnginePrivate::get(qmlEngine)->rootContext);
+QQmlComponent *QtObject::createComponent(const QUrl &url, QQmlComponent::CompilationMode mode,
+ QObject *parent) const
+{
+ if (mode != QQmlComponent::Asynchronous && mode != QQmlComponent::PreferSynchronous) {
+ v4Engine()->throwError(QStringLiteral("Invalid compilation mode %1").arg(mode));
+ return nullptr;
}
+
+ if (url.isEmpty())
+ return nullptr;
+
+ QQmlEngine *engine = qmlEngine();
+ if (!engine)
+ return nullptr;
+
+ QQmlRefPointer<QQmlContextData> context = v4Engine()->callingQmlContext();
+ if (!context)
+ context = QQmlContextData::get(QQmlEnginePrivate::get(engine)->rootContext);
+
Q_ASSERT(context);
QQmlRefPointer<QQmlContextData> effectiveContext
= context->isPragmaLibraryContext() ? nullptr : context;
- QString arg = argv[0].toQStringNoThrow();
- if (arg.isEmpty())
- RETURN_RESULT(QV4::Encode::null());
-
- QQmlComponent::CompilationMode compileMode = QQmlComponent::PreferSynchronous;
- QObject *parentArg = nullptr;
-
- int consumedCount = 1;
- if (argc > 1) {
- ScopedValue lastArg(scope, argv[argc-1]);
-
- // The second argument could be the mode enum
- if (argv[1].isInteger()) {
- int mode = argv[1].integerValue();
- if (mode != int(QQmlComponent::PreferSynchronous) && mode != int(QQmlComponent::Asynchronous))
- THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments");
- compileMode = QQmlComponent::CompilationMode(mode);
- consumedCount += 1;
- } else {
- // The second argument could be the parent only if there are exactly two args
- if ((argc != 2) || !(lastArg->isObject() || lastArg->isNull()))
- THROW_GENERIC_ERROR("Qt.createComponent(): Invalid arguments");
- }
-
- if (consumedCount < argc) {
- if (lastArg->isObject()) {
- Scoped<QObjectWrapper> qobjectWrapper(scope, lastArg);
- if (qobjectWrapper)
- parentArg = qobjectWrapper->object();
- if (!parentArg)
- THROW_GENERIC_ERROR("Qt.createComponent(): Invalid parent object");
- } else if (lastArg->isNull()) {
- parentArg = nullptr;
- } else {
- THROW_GENERIC_ERROR("Qt.createComponent(): Invalid parent object");
- }
- }
- }
-
- QUrl url = context->resolvedUrl(QUrl(arg));
- QQmlComponent *c = new QQmlComponent(engine, url, compileMode, parentArg);
+ QQmlComponent *c = new QQmlComponent(engine, context->resolvedUrl(url), mode, parent);
QQmlComponentPrivate::get(c)->creationContext = effectiveContext;
QQmlData::get(c, true)->explicitIndestructibleSet = false;
QQmlData::get(c)->indestructible = false;
-
- return QV4::QObjectWrapper::wrap(scope.engine, c);
+ return c;
}
-ReturnedValue QtObject::method_get_uiLanguage(const FunctionObject *b, const Value * /*thisObject*/, const Value * /*argv*/, int /*argc*/)
+QString QtObject::uiLanguage() const
{
- QV4::Scope scope(b);
- QJSEngine *jsEngine = scope.engine->jsEngine();
- if (!jsEngine)
- return Encode::null();
-
- QQmlEnginePrivate *ep = QQmlEnginePrivate::get(scope.engine);
- if (ep && ep->propertyCapture) {
- static const QMetaProperty metaProperty
- = QQmlEngine::staticMetaObject.property(
- QQmlEngine::staticMetaObject.indexOfProperty("uiLanguage"));
- QQmlEngine *e = QQmlEnginePrivate::get(ep);
- e->captureProperty(e, metaProperty);
- }
+ if (const QJSEngine *e = jsEngine())
+ return e->uiLanguage();
+ return QString();
+}
- return Encode(scope.engine->newString(QJSEnginePrivate::get(jsEngine)->uiLanguage));
+void QtObject::setUiLanguage(const QString &uiLanguage)
+{
+ if (QJSEngine *e = jsEngine())
+ e->setUiLanguage(uiLanguage);
}
-ReturnedValue QtObject::method_set_uiLanguage(const FunctionObject *b, const Value * /*thisObject*/, const Value *argv, int argc)
+QBindable<QString> QtObject::uiLanguageBindable()
{
- Scope scope(b);
- if (!argc)
- THROW_TYPE_ERROR();
- QJSEngine *jsEngine = scope.engine->jsEngine();
- if (!jsEngine)
- THROW_TYPE_ERROR();
- jsEngine->setUiLanguage(argv[0].toQString());
- return Encode::undefined();
+ if (QJSEngine *e = jsEngine())
+ return QBindable<QString>(&QJSEnginePrivate::get(e)->uiLanguage);
+ return QBindable<QString>();
}
#if QT_CONFIG(qml_locale)
@@ -1413,19 +1150,14 @@ ReturnedValue QtObject::method_set_uiLanguage(const FunctionObject *b, const Val
\sa Locale
*/
-ReturnedValue QtObject::method_locale(const FunctionObject *b, const Value *, const Value *argv, int argc)
+QLocale QtObject::locale() const
{
- QV4::Scope scope(b);
- QString code;
- if (argc > 1)
- THROW_GENERIC_ERROR("locale() requires 0 or 1 argument");
- if (argc == 1 && !argv[0].isString())
- THROW_TYPE_ERROR_WITH_MESSAGE("locale(): argument (locale code) must be a string");
-
- if (argc == 1)
- code = argv[0].toQStringNoThrow();
+ return QLocale();
+}
- return QQmlLocale::locale(scope.engine, code);
+QLocale QtObject::locale(const QString &name) const
+{
+ return QLocale(name);
}
#endif
@@ -1489,67 +1221,52 @@ DEFINE_OBJECT_VTABLE(QQmlBindingFunction);
\since 5.0
*/
-ReturnedValue QtObject::method_binding(const FunctionObject *b, const Value *, const Value *argv, int argc)
-{
- QV4::Scope scope(b);
- if (argc != 1)
- THROW_GENERIC_ERROR("binding() requires 1 argument");
- const QV4::FunctionObject *f = argv[0].as<FunctionObject>();
- if (!f)
- THROW_TYPE_ERROR_WITH_MESSAGE("binding(): argument (binding expression) must be a function");
+QJSValue QtObject::binding(const QJSValue &function) const
+{
+ const QV4::FunctionObject *f = QJSValuePrivate::asManagedType<FunctionObject>(&function);
+ QV4::ExecutionEngine *e = v4Engine();
+ if (!f) {
+ return QJSValuePrivate::fromReturnedValue(
+ e->throwError(
+ QStringLiteral(
+ "binding(): argument (binding expression) must be a function")));
+ }
- return Encode(scope.engine->memoryManager->allocate<QQmlBindingFunction>(f));
+ return QJSValuePrivate::fromReturnedValue(
+ Encode(e->memoryManager->allocate<QQmlBindingFunction>(f)));
}
-ReturnedValue QtObject::method_get_platform(const FunctionObject *b, const Value *thisObject, const Value *, int)
+QQmlPlatform *QtObject::platform()
{
- QV4::Scope scope(b);
- // ### inefficient. Should be just a value based getter
- const Object *o = thisObject->as<Object>();
- if (!o)
- THROW_TYPE_ERROR();
- const QtObject *qt = o->as<QtObject>();
- if (!qt)
- THROW_TYPE_ERROR();
-
- if (!qt->d()->platform)
- // Only allocate a platform object once
- qt->d()->platform = new QQmlPlatform(scope.engine->jsEngine());
-
- return QV4::QObjectWrapper::wrap(scope.engine, qt->d()->platform);
+ if (!m_platform)
+ m_platform = new QQmlPlatform(this);
+ return m_platform;
}
-ReturnedValue QtObject::method_get_application(const FunctionObject *b, const Value *thisObject, const Value *, int)
+QQmlApplication *QtObject::application()
{
- QV4::Scope scope(b);
- // ### inefficient. Should be just a value based getter
- const Object *o = thisObject->as<Object>();
- if (!o)
- THROW_TYPE_ERROR();
- const QtObject *qt = o->as<QtObject>();
- if (!qt)
- THROW_TYPE_ERROR();
-
- if (!qt->d()->application)
+ if (!m_application)
// Only allocate an application object once
- qt->d()->application = QQml_guiProvider()->application(scope.engine->jsEngine());
+ m_application = QQml_guiProvider()->application(this);
- return QV4::QObjectWrapper::wrap(scope.engine, qt->d()->application);
+ return m_application;
}
-ReturnedValue QtObject::method_get_inputMethod(const FunctionObject *b, const Value *, const Value *, int)
+QObject *QtObject::inputMethod() const
{
- QObject *o = QQml_guiProvider()->inputMethod();
- return QV4::QObjectWrapper::wrap(b->engine(), o);
+ return QQml_guiProvider()->inputMethod();
}
-ReturnedValue QtObject::method_get_styleHints(const FunctionObject *b, const Value *, const Value *, int)
+QObject *QtObject::styleHints() const
{
- QObject *o = QQml_guiProvider()->styleHints();
- return QV4::QObjectWrapper::wrap(b->engine(), o);
+ return QQml_guiProvider()->styleHints();
}
+QJSValue QtObject::callLater() const
+{
+ return m_callLater;
+}
void QV4::Heap::ConsoleObject::init()
{
@@ -1873,8 +1590,6 @@ ReturnedValue ConsoleObject::method_exception(const FunctionObject *b, const Val
return writeToConsole(b, argv, argc, Error, true);
}
-
-
void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions extensions)
{
ExecutionEngine *v4 = globalObject->engine();
@@ -1889,13 +1604,11 @@ void QV4::GlobalExtensions::init(Object *globalObject, QJSEngine::Extensions ext
globalObject->defineDefaultProperty(QStringLiteral("qsTrId"), QV4::GlobalExtensions::method_qsTrId);
globalObject->defineDefaultProperty(QStringLiteral("QT_TRID_NOOP"), QV4::GlobalExtensions::method_qsTrIdNoOp);
+ // Initialize the Qt global object for the uiLanguage property
ScopedString qtName(scope, v4->newString(QStringLiteral("Qt")));
ScopedObject qt(scope, globalObject->get(qtName));
- if (!qt) {
- qt = v4->newObject();
- globalObject->defineDefaultProperty(qtName, qt);
- }
- qt->defineAccessorProperty(QStringLiteral("uiLanguage"), QV4::QtObject::method_get_uiLanguage, QV4::QtObject::method_set_uiLanguage);
+ if (!qt)
+ v4->createQtObject();
// string prototype extension
scope.engine->stringPrototype()->defineDefaultProperty(QStringLiteral("arg"), QV4::GlobalExtensions::method_string_arg);
@@ -2236,7 +1949,8 @@ be passed on to the function invoked. Note that if redundant calls
are eliminated, then only the last set of arguments will be passed to the
function.
*/
-ReturnedValue QtObject::method_callLater(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
+ReturnedValue QtObject::method_callLater(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int argc)
{
return b->engine()->delayedCallQueue()->addUniquelyAndExecuteLater(b, thisObject, argv, argc);
}
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index 65c68503e3..4ab982d579 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -54,29 +54,21 @@
#include <private/qqmlglobal_p.h>
#include <private/qv4functionobject_p.h>
#include <private/qjsengine_p.h>
+#include <private/qqmlplatform_p.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qsize.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qpoint.h>
+#include <QtQml/qqmlcomponent.h>
+#include <QtQml/qqmlengine.h>
QT_BEGIN_NAMESPACE
-class QQmlEngine;
-
namespace QV4 {
namespace Heap {
-struct QtObject : Object {
- void init(QQmlEngine *qmlEngine);
- QObject *platform;
- QObject *application;
-
- enum { Finished = -1 };
- int enumeratorIterator;
- int keyIterator;
-
- bool isComplete() const
- { return enumeratorIterator == Finished; }
-};
-
struct ConsoleObject : Object {
void init();
};
@@ -90,73 +82,139 @@ DECLARE_HEAP_OBJECT(QQmlBindingFunction, FunctionObject) {
}
-namespace QtInQml {
-Q_NAMESPACE
-QML_FOREIGN_NAMESPACE(Qt)
-QML_NAMED_ELEMENT(Qt)
-QML_ADDED_IN_VERSION(2, 0)
-Q_CLASSINFO("QML.ManualRegistration", "true")
-// should add the functions defined below...
-}
-
-struct QtObject : Object
+class Q_QML_EXPORT QtObject : public QObject
{
- V4_OBJECT2(QtObject, Object)
-
- static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
- static OwnPropertyKeyIterator *virtualOwnPropertyKeys(const Object *m, Value *target);
-
- static ReturnedValue method_isQtObject(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_color(const FunctionObject *b, const Value *thisObject,
- const Value *argv, int argc);
- static ReturnedValue method_rgba(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_hsla(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_hsva(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_colorEqual(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_font(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_rect(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_point(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_size(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_vector2d(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_vector3d(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_vector4d(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_quaternion(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_matrix4x4(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_lighter(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_darker(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_alpha(const FunctionObject *b, const Value *thisObject,
- const Value *argv, int argc);
- static ReturnedValue method_tint(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_formatDate(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_formatTime(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_formatDateTime(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_openUrlExternally(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_fontFamilies(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_md5(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_btoa(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_atob(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_quit(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_exit(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_resolvedUrl(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_createQmlObject(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_createComponent(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_get_uiLanguage(const FunctionObject *b, const Value *, const Value *, int);
- static ReturnedValue method_set_uiLanguage(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+ Q_OBJECT
+ Q_PROPERTY(QQmlApplication *application READ application CONSTANT)
+ Q_PROPERTY(QQmlPlatform *platform READ platform CONSTANT)
+ Q_PROPERTY(QObject *inputMethod READ inputMethod CONSTANT)
+ Q_PROPERTY(QObject *styleHints READ styleHints CONSTANT)
+ Q_PROPERTY(QJSValue callLater READ callLater CONSTANT)
+
+#if QT_CONFIG(translation)
+ Q_PROPERTY(QString uiLanguage READ uiLanguage WRITE setUiLanguage BINDABLE uiLanguageBindable)
+#endif
+
+ QML_NAMED_ELEMENT(Qt)
+ QML_SINGLETON
+ QML_EXTENDED_NAMESPACE(QT_PREPEND_NAMESPACE(Qt))
+ QML_ADDED_IN_VERSION(2, 0)
+
+ Q_CLASSINFO("QML.StrictArguments", "true")
+
+public:
+ enum LoadingMode { Asynchronous = 0, Synchronous = 1 };
+ Q_ENUM(LoadingMode);
+
+ static QtObject *create(QQmlEngine *, QJSEngine *jsEngine);
+
+ Q_INVOKABLE QJSValue include(const QString &url, const QJSValue &callback = QJSValue()) const;
+ Q_INVOKABLE bool isQtObject(const QJSValue &value) const;
+
+ Q_INVOKABLE QVariant color(const QString &name) const;
+ Q_INVOKABLE QVariant rgba(double r, double g, double b, double a = 1) const;
+ Q_INVOKABLE QVariant hsla(double h, double s, double l, double a = 1) const;
+ Q_INVOKABLE QVariant hsva(double h, double s, double v, double a = 1) const;
+ Q_INVOKABLE bool colorEqual(const QVariant &lhs, const QVariant &rhs) const;
+
+ Q_INVOKABLE QRectF rect(double x, double y, double width, double height) const;
+ Q_INVOKABLE QPointF point(double x, double y) const;
+ Q_INVOKABLE QSizeF size(double width, double height) const;
+ Q_INVOKABLE QVariant vector2d(double x, double y) const;
+ Q_INVOKABLE QVariant vector3d(double x, double y, double z) const;
+ Q_INVOKABLE QVariant vector4d(double x, double y, double z, double w) const;
+ Q_INVOKABLE QVariant quaternion(double scalar, double x, double y, double z) const;
+
+ Q_INVOKABLE QVariant matrix4x4() const;
+ Q_INVOKABLE QVariant matrix4x4(double m11, double m12, double m13, double m14,
+ double m21, double m22, double m23, double m24,
+ double m31, double m32, double m33, double m34,
+ double m41, double m42, double m43, double m44) const;
+ Q_INVOKABLE QVariant matrix4x4(const QJSValue &value) const;
+
+ Q_INVOKABLE QVariant lighter(const QJSValue &color, double factor = 1.5) const;
+ Q_INVOKABLE QVariant darker(const QJSValue &color, double factor = 2.0) const;
+ Q_INVOKABLE QVariant alpha(const QJSValue &baseColor, double value) const;
+ Q_INVOKABLE QVariant tint(const QJSValue &baseColor, const QJSValue &tintColor) const;
+
+ Q_INVOKABLE QString formatDate(const QDate &date, const QString &format) const;
+ Q_INVOKABLE QString formatDate(const QDate &date, Qt::DateFormat format) const;
+
+ Q_INVOKABLE QString formatTime(const QTime &time, const QString &format) const;
+ Q_INVOKABLE QString formatTime(const QString &time, const QString &format) const;
+ Q_INVOKABLE QString formatTime(const QTime &time, Qt::DateFormat format) const;
+ Q_INVOKABLE QString formatTime(const QString &time, Qt::DateFormat format) const;
+
+ Q_INVOKABLE QString formatDateTime(const QDateTime &date, const QString &format) const;
+ Q_INVOKABLE QString formatDateTime(const QDateTime &date, Qt::DateFormat format) const;
+
#if QT_CONFIG(qml_locale)
- static ReturnedValue method_locale(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+ Q_INVOKABLE QString formatDate(const QDate &date, const QLocale &locale = QLocale(),
+ QLocale::FormatType formatType = QLocale::ShortFormat) const;
+ Q_INVOKABLE QString formatTime(const QTime &time, const QLocale &locale = QLocale(),
+ QLocale::FormatType formatType = QLocale::ShortFormat) const;
+ Q_INVOKABLE QString formatTime(const QString &time, const QLocale &locale = QLocale(),
+ QLocale::FormatType formatType = QLocale::ShortFormat) const;
+ Q_INVOKABLE QString formatDateTime(const QDateTime &date, const QLocale &locale = QLocale(),
+ QLocale::FormatType formatType = QLocale::ShortFormat) const;
+ Q_INVOKABLE QLocale locale() const;
+ Q_INVOKABLE QLocale locale(const QString &name) const;
+#endif
+
+ Q_INVOKABLE QUrl resolvedUrl(const QUrl &url) const;
+ Q_INVOKABLE bool openUrlExternally(const QUrl &url) const;
+
+ Q_INVOKABLE QVariant font(const QJSValue &fontSpecifier) const;
+ Q_INVOKABLE QStringList fontFamilies() const;
+
+ Q_INVOKABLE QString md5(const QString &data) const;
+ Q_INVOKABLE QString btoa(const QString &data) const;
+ Q_INVOKABLE QString atob(const QString &data) const;
+
+ Q_INVOKABLE void quit() const;
+ Q_INVOKABLE void exit(int retCode) const;
+
+ Q_INVOKABLE QObject *createQmlObject(const QString &qml, QObject *parent,
+ const QUrl &url = QUrl(QStringLiteral("inline"))) const;
+ Q_INVOKABLE QQmlComponent *createComponent(const QUrl &url, QObject *parent) const;
+ Q_INVOKABLE QQmlComponent *createComponent(
+ const QUrl &url, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous,
+ QObject *parent = nullptr) const;
+
+ Q_INVOKABLE QJSValue binding(const QJSValue &function) const;
+
+ // We can't make this invokable as it uses actual varargs
+ static ReturnedValue method_callLater(const FunctionObject *b, const Value *thisObject,
+ const Value *argv, int argc);
+
+#if QT_CONFIG(translation)
+ QString uiLanguage() const;
+ void setUiLanguage(const QString &uiLanguage);
+ QBindable<QString> uiLanguageBindable();
#endif
- static ReturnedValue method_binding(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_get_platform(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_get_application(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_get_inputMethod(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
- static ReturnedValue method_get_styleHints(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
+ // Not const because created on first use, and parented to this.
+ QQmlPlatform *platform();
+ QQmlApplication *application();
- static ReturnedValue method_callLater(const FunctionObject *, const Value *thisObject, const Value *argv, int argc);
+ QObject *inputMethod() const;
+ QObject *styleHints() const;
+ QJSValue callLater() const;
private:
- void addAll();
- ReturnedValue findAndAdd(const QString *name, bool &foundProperty) const;
+ friend struct ExecutionEngine;
+
+ QtObject(QV4::ExecutionEngine *engine);
+
+ QQmlEngine *qmlEngine() const { return m_engine->qmlEngine(); }
+ QJSEngine *jsEngine() const { return m_engine->jsEngine(); }
+ QV4::ExecutionEngine *v4Engine() const { return m_engine; }
+
+ QQmlPlatform *m_platform = nullptr;
+ QQmlApplication *m_application = nullptr;
+
+ QV4::ExecutionEngine *m_engine = nullptr;
+ QJSValue m_callLater;
};
struct ConsoleObject : Object