diff options
-rw-r--r-- | src/qml/qml/v8/qqmlbuiltinfunctions.cpp | 82 | ||||
-rw-r--r-- | src/qml/qml/v8/qqmlbuiltinfunctions_p.h | 14 | ||||
-rw-r--r-- | tests/auto/qml/qqmlqt/data/qtObjectContents.qml | 10 | ||||
-rw-r--r-- | tests/auto/qml/qqmlqt/tst_qqmlqt.cpp | 46 |
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" |