aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions.cpp82
-rw-r--r--src/qml/qml/v8/qqmlbuiltinfunctions_p.h14
-rw-r--r--tests/auto/qml/qqmlqt/data/qtObjectContents.qml10
-rw-r--r--tests/auto/qml/qqmlqt/tst_qqmlqt.cpp46
4 files changed, 141 insertions, 11 deletions
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
index ed478fa17f..ecfc817d3b 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp
@@ -87,22 +87,18 @@ struct StaticQtMetaObject : public QObject
};
Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
+ : enumeratorIterator(0)
+ , keyIterator(0)
{
Scope scope(internalClass->engine);
ScopedObject o(scope, this);
- // Set all the enums from the "Qt" namespace
- const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
- ScopedString str(scope);
- ScopedValue v(scope);
- for (int ii = 0, eii = qtMetaObject->enumeratorCount(); ii < eii; ++ii) {
- QMetaEnum enumerator = qtMetaObject->enumerator(ii);
- for (int jj = 0, ejj = enumerator.keyCount(); jj < ejj; ++jj) {
- o->put((str = scope.engine->newString(QString::fromUtf8(enumerator.key(jj)))), (v = QV4::Primitive::fromInt32(enumerator.value(jj))));
- }
+ {
+ ScopedString str(scope);
+ ScopedValue v(scope);
+ o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
+ o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
}
- o->put((str = scope.engine->newString(QStringLiteral("Asynchronous"))), (v = QV4::Primitive::fromInt32(0)));
- o->put((str = scope.engine->newString(QStringLiteral("Synchronous"))), (v = QV4::Primitive::fromInt32(1)));
o->defineDefaultProperty(QStringLiteral("include"), QV4Include::method_include);
o->defineDefaultProperty(QStringLiteral("isQtObject"), QV4::QtObject::method_isQtObject);
@@ -151,6 +147,70 @@ Heap::QtObject::QtObject(QQmlEngine *qmlEngine)
o->defineAccessorProperty(QStringLiteral("styleHints"), QV4::QtObject::method_get_styleHints, 0);
}
+void QtObject::addAll()
+{
+ bool dummy = false;
+ findAndAdd(nullptr, dummy);
+}
+
+ReturnedValue QtObject::findAndAdd(const QString *name, bool &foundProperty) const
+{
+ Scope scope(engine());
+ ScopedObject o(scope, this);
+ ScopedString key(scope);
+ ScopedValue value(scope);
+
+ const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
+ 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::Primitive::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();
+}
+
+ReturnedValue QtObject::get(const Managed *m, String *name, bool *hasProperty)
+{
+ bool hasProp = false;
+ if (hasProperty == nullptr) {
+ hasProperty = &hasProp;
+ }
+
+ ReturnedValue ret = QV4::Object::get(m, name, hasProperty);
+ if (*hasProperty) {
+ return ret;
+ }
+
+ auto that = static_cast<const QtObject*>(m);
+ if (!that->d()->isComplete()) {
+ const QString key = name->toQString();
+ ret = that->findAndAdd(&key, *hasProperty);
+ }
+
+ return ret;
+}
+
+void QtObject::advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes)
+{
+ auto that = static_cast<QtObject*>(m);
+ if (!that->d()->isComplete()) {
+ that->addAll();
+ }
+
+ QV4::Object::advanceIterator(m, it, name, index, p, attributes);
+}
/*!
\qmlmethod bool Qt::isQtObject(object)
diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
index 53468f062b..dc806c6031 100644
--- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
+++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h
@@ -67,6 +67,13 @@ struct QtObject : Object {
QtObject(QQmlEngine *qmlEngine);
QObject *platform;
QObject *application;
+
+ enum { Finished = -1 };
+ int enumeratorIterator;
+ int keyIterator;
+
+ bool isComplete() const
+ { return enumeratorIterator == Finished; }
};
struct ConsoleObject : Object {
@@ -86,6 +93,9 @@ struct QtObject : Object
{
V4_OBJECT2(QtObject, Object)
+ static ReturnedValue get(const Managed *m, String *name, bool *hasProperty);
+ static void advanceIterator(Managed *m, ObjectIterator *it, Value *name, uint *index, Property *p, PropertyAttributes *attributes);
+
static ReturnedValue method_isQtObject(CallContext *ctx);
static ReturnedValue method_rgba(CallContext *ctx);
static ReturnedValue method_hsla(CallContext *ctx);
@@ -124,6 +134,10 @@ struct QtObject : Object
static ReturnedValue method_get_inputMethod(CallContext *ctx);
#endif
static ReturnedValue method_get_styleHints(CallContext *ctx);
+
+private:
+ void addAll();
+ ReturnedValue findAndAdd(const QString *name, bool &foundProperty) const;
};
struct ConsoleObject : Object
diff --git a/tests/auto/qml/qqmlqt/data/qtObjectContents.qml b/tests/auto/qml/qqmlqt/data/qtObjectContents.qml
new file mode 100644
index 0000000000..c85e7986e9
--- /dev/null
+++ b/tests/auto/qml/qqmlqt/data/qtObjectContents.qml
@@ -0,0 +1,10 @@
+import QtQuick 2.0
+
+QtObject {
+ property var values: Object()
+ Component.onCompleted: {
+ for (var key in Qt) {
+ values[key] = Qt[key]
+ }
+ }
+}
diff --git a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
index 01283dd587..2f44c34bc2 100644
--- a/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
+++ b/tests/auto/qml/qqmlqt/tst_qqmlqt.cpp
@@ -87,6 +87,7 @@ private slots:
void fontFamilies();
void quit();
void resolvedUrl();
+ void qtObjectContents();
private:
QQmlEngine engine;
@@ -934,6 +935,51 @@ void tst_qqmlqt::resolvedUrl()
delete object;
}
+void tst_qqmlqt::qtObjectContents()
+{
+ struct StaticQtMetaObject : public QObject
+ {
+ static const QMetaObject *get()
+ { return &staticQtMetaObject; }
+ };
+
+ QQmlComponent component(&engine, testFileUrl("qtObjectContents.qml"));
+
+ QObject *object = component.create();
+ QVERIFY(object != 0);
+
+ QVERIFY(object->property("values").canConvert<QJSValue>());
+ QVariantMap values = object->property("values").value<QJSValue>().toVariant().toMap();
+
+ QSet<const char *> keys;
+ int uniqueKeys = 0;
+ const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
+ for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
+ QMetaEnum enumerator = qtMetaObject->enumerator(ii);
+ for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
+ auto key = enumerator.key(jj);
+// qDebug() << "key:" << key;
+ if (!keys.contains(key)) {
+ ++uniqueKeys;
+ keys.insert(key);
+ }
+ QVERIFY(values.contains(key));
+ QVariant value = values.value(key);
+ QVERIFY(value.canConvert<int>());
+ QCOMPARE(value.toInt(), enumerator.value(jj));
+ }
+ }
+ QVERIFY(values.contains("Asynchronous"));
+ QCOMPARE(values.value("Asynchronous").toInt(), 0);
+ ++uniqueKeys;
+ QVERIFY(values.contains("Synchronous"));
+ QCOMPARE(values.value("Synchronous").toInt(), 1);
+ ++uniqueKeys;
+ QCOMPARE(values.count(), uniqueKeys);
+
+ delete object;
+}
+
QTEST_MAIN(tst_qqmlqt)
#include "tst_qqmlqt.moc"