diff options
Diffstat (limited to 'src/qml/qml')
-rw-r--r-- | src/qml/qml/qqmlapplicationengine.cpp | 11 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 31 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent_p.h | 7 | ||||
-rw-r--r-- | src/qml/qml/qqmlcontext.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcustomparser.cpp | 22 | ||||
-rw-r--r-- | src/qml/qml/qqmldelayedcallqueue.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 8 | ||||
-rw-r--r-- | src/qml/qml/qqmlextensionplugin.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlfileselector.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlglobal.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmllocale.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlloggingcategory.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 191 | ||||
-rw-r--r-- | src/qml/qml/qqmlmetatype_p.h | 14 | ||||
-rw-r--r-- | src/qml/qml/qqmlplatform.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmltypenotavailable.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper.cpp | 85 | ||||
-rw-r--r-- | src/qml/qml/qqmltypewrapper_p.h | 25 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetype.cpp | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlvaluetypewrapper.cpp | 26 |
20 files changed, 392 insertions, 48 deletions
diff --git a/src/qml/qml/qqmlapplicationengine.cpp b/src/qml/qml/qqmlapplicationengine.cpp index a10dda166c..faab8bf926 100644 --- a/src/qml/qml/qqmlapplicationengine.cpp +++ b/src/qml/qml/qqmlapplicationengine.cpp @@ -57,6 +57,10 @@ QQmlApplicationEnginePrivate::~QQmlApplicationEnginePrivate() void QQmlApplicationEnginePrivate::cleanUp() { + Q_Q(QQmlApplicationEngine); + for (auto obj : qAsConst(objects)) + obj->disconnect(q); + qDeleteAll(objects); #if QT_CONFIG(translation) qDeleteAll(translators); @@ -126,9 +130,12 @@ void QQmlApplicationEnginePrivate::finishLoad(QQmlComponent *c) qWarning() << qPrintable(c->errorString()); q->objectCreated(0, c->url()); break; - case QQmlComponent::Ready: - objects << c->create(); + case QQmlComponent::Ready: { + auto newObj = c->create(); + objects << newObj; + QObject::connect(newObj, &QObject::destroyed, q, [&](QObject *obj) { objects.removeAll(obj); }); q->objectCreated(objects.constLast(), c->url()); + } break; case QQmlComponent::Loading: case QQmlComponent::Null: diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 75968ffc43..e7a45482e6 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1040,6 +1040,35 @@ void QQmlComponent::create(QQmlIncubator &incubator, QQmlContext *context, enginePriv->incubate(incubator, forContextData); } +/* + This is essentially a copy of QQmlComponent::create(); except it takes the QQmlContextData + arguments instead of QQmlContext which means we don't have to construct the rather weighty + wrapper class for every delegate item. + + This is used by QQmlDelegateModel. +*/ +void QQmlComponentPrivate::incubateObject( + QQmlIncubator *incubationTask, + QQmlComponent *component, + QQmlEngine *engine, + QQmlContextData *context, + QQmlContextData *forContext) +{ + QQmlIncubatorPrivate *incubatorPriv = QQmlIncubatorPrivate::get(incubationTask); + QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine); + QQmlComponentPrivate *componentPriv = QQmlComponentPrivate::get(component); + + incubatorPriv->compilationUnit = componentPriv->compilationUnit; + incubatorPriv->compilationUnit->addref(); + incubatorPriv->enginePriv = enginePriv; + incubatorPriv->creator.reset(new QQmlObjectCreator(context, componentPriv->compilationUnit, componentPriv->creationContext)); + incubatorPriv->subComponentToCreate = componentPriv->start; + + enginePriv->incubate(*incubationTask, forContext); +} + + + class QQmlComponentIncubator; namespace QV4 { @@ -1527,3 +1556,5 @@ void QV4::QmlIncubatorObject::statusChanged(QQmlIncubator::Status s) #undef INITIALPROPERTIES_SOURCE QT_END_NAMESPACE + +#include "moc_qqmlcomponent.cpp" diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h index d01a987acc..6414025574 100644 --- a/src/qml/qml/qqmlcomponent_p.h +++ b/src/qml/qml/qqmlcomponent_p.h @@ -88,6 +88,13 @@ public: void initializeObjectWithInitialProperties(QV4::QmlContext *qmlContext, const QV4::Value &valuemap, QObject *toCreate); static void setInitialProperties(QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &o, const QV4::Value &v); + void incubateObject( + QQmlIncubator *incubationTask, + QQmlComponent *component, + QQmlEngine *engine, + QQmlContextData *context, + QQmlContextData *forContext); + QQmlTypeData *typeData; void typeDataReady(QQmlTypeData *) override; void typeDataProgress(QQmlTypeData *, qreal) override; diff --git a/src/qml/qml/qqmlcontext.cpp b/src/qml/qml/qqmlcontext.cpp index 018841b9b1..1476c276f4 100644 --- a/src/qml/qml/qqmlcontext.cpp +++ b/src/qml/qml/qqmlcontext.cpp @@ -834,3 +834,5 @@ QString QQmlContextData::urlString() const } QT_END_NAMESPACE + +#include "moc_qqmlcontext.cpp" diff --git a/src/qml/qml/qqmlcustomparser.cpp b/src/qml/qml/qqmlcustomparser.cpp index 0b0bbef795..6ad641b8b1 100644 --- a/src/qml/qml/qqmlcustomparser.cpp +++ b/src/qml/qml/qqmlcustomparser.cpp @@ -121,13 +121,16 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const { Q_ASSERT_X(ok, "QQmlCustomParser::evaluateEnum", "ok must not be a null pointer"); *ok = false; + + // we support one or two '.' in the enum phrase: + // * <TypeName>.<EnumValue> + // * <TypeName>.<ScopedEnumName>.<EnumValue> + int dot = script.indexOf('.'); - if (dot == -1) + if (dot == -1 || dot == script.length()-1) return -1; - QString scope = QString::fromUtf8(script.left(dot)); - QByteArray enumValue = script.mid(dot+1); if (scope != QLatin1String("Qt")) { if (imports.isNull()) @@ -142,9 +145,20 @@ int QQmlCustomParser::evaluateEnum(const QByteArray& script, bool *ok) const type = result.type; } - return type ? type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok) : -1; + if (!type) + return -1; + + int dot2 = script.indexOf('.', dot+1); + const bool dot2Valid = dot2 != -1 && dot2 != script.length()-1; + QByteArray enumValue = script.mid(dot2Valid ? dot2 + 1 : dot + 1); + QByteArray scopedEnumName = (dot2Valid ? script.mid(dot + 1, dot2 - dot - 1) : QByteArray()); + if (!scopedEnumName.isEmpty()) + return type->scopedEnumValue(engine, scopedEnumName, enumValue, ok); + else + return type->enumValue(engine, QHashedCStringRef(enumValue.constData(), enumValue.length()), ok); } + QByteArray enumValue = script.mid(dot + 1); const QMetaObject *mo = StaticQtMetaObject::get(); int i = mo->enumeratorCount(); while (i--) { diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp index d5d2c9a28d..13e62ec696 100644 --- a/src/qml/qml/qqmldelayedcallqueue.cpp +++ b/src/qml/qml/qqmldelayedcallqueue.cpp @@ -210,3 +210,5 @@ void QQmlDelayedCallQueue::ticked() } QT_END_NAMESPACE + +#include "moc_qqmldelayedcallqueue_p.cpp" diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 9ff76d7b24..4a21acb050 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1492,9 +1492,9 @@ QQmlEngine *qmlEngine(const QObject *obj) QObject *qmlAttachedPropertiesObjectById(int id, const QObject *object, bool create) { - QQmlData *data = QQmlData::get(object); + QQmlData *data = QQmlData::get(object, create); if (!data) - return 0; // Attached properties are only on objects created by QML + return 0; // Attached properties are only on objects created by QML, unless explicitly requested (create==true) QObject *rv = data->hasExtendedData()?data->attachedProperties()->value(id):0; if (rv || !create) @@ -2177,7 +2177,7 @@ QString QQmlEngine::offlineStoragePath() const Returns the file path where a \l{QtQuick.LocalStorage}{Local Storage} database with the identifier \a databaseName is (or would be) located. - \sa LocalStorage.openDatabaseSync() + \sa {openDatabaseSync}{LocalStorage.openDatabaseSync()} \since 5.9 */ QString QQmlEngine::offlineStorageDatabaseFilePath(const QString &databaseName) const @@ -2553,3 +2553,5 @@ bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn /* = -1 */) */ QT_END_NAMESPACE + +#include "moc_qqmlengine.cpp" diff --git a/src/qml/qml/qqmlextensionplugin.cpp b/src/qml/qml/qqmlextensionplugin.cpp index 097fa71200..b0e6a24616 100644 --- a/src/qml/qml/qqmlextensionplugin.cpp +++ b/src/qml/qml/qqmlextensionplugin.cpp @@ -128,3 +128,5 @@ void QQmlExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri) */ QT_END_NAMESPACE + +#include "moc_qqmlextensionplugin.cpp" diff --git a/src/qml/qml/qqmlfileselector.cpp b/src/qml/qml/qqmlfileselector.cpp index 461ca33b3e..be6216d3ff 100644 --- a/src/qml/qml/qqmlfileselector.cpp +++ b/src/qml/qml/qqmlfileselector.cpp @@ -222,3 +222,5 @@ QUrl QQmlFileSelectorInterceptor::intercept(const QUrl &path, DataType type) } QT_END_NAMESPACE + +#include "moc_qqmlfileselector.cpp" diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp index f967dacd34..7939656107 100644 --- a/src/qml/qml/qqmlglobal.cpp +++ b/src/qml/qml/qqmlglobal.cpp @@ -450,3 +450,5 @@ void QQmlApplication::setDomain(const QString &arg) } QT_END_NAMESPACE + +#include "moc_qqmlglobal_p.cpp" diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 712da78807..326b36c5cd 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -1090,3 +1090,5 @@ void QQmlLocale::method_localeCompare(const BuiltinFunction *b, Scope &scope, Ca */ QT_END_NAMESPACE + +#include "moc_qqmllocale_p.cpp" diff --git a/src/qml/qml/qqmlloggingcategory.cpp b/src/qml/qml/qqmlloggingcategory.cpp index 764b874131..08f8552ab6 100644 --- a/src/qml/qml/qqmlloggingcategory.cpp +++ b/src/qml/qml/qqmlloggingcategory.cpp @@ -126,3 +126,5 @@ void QQmlLoggingCategory::setName(const QString &name) QScopedPointer<QLoggingCategory> category(new QLoggingCategory(m_name.constData())); m_category.swap(category); } + +#include "moc_qqmlloggingcategory_p.cpp" diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index bb9b69c479..0672618225 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -216,6 +216,8 @@ public: mutable bool haveSuperType:1; mutable QList<QQmlProxyMetaObject::ProxyData> metaObjects; mutable QStringHash<int> enums; + mutable QStringHash<int> scopedEnumIndex; // maps from enum name to index in scopedEnums + mutable QList<QStringHash<int>*> scopedEnums; static QHash<const QMetaObject *, int> attachedPropertyIds; }; @@ -313,6 +315,7 @@ QQmlTypePrivate::QQmlTypePrivate(QQmlType::RegistrationType type) QQmlTypePrivate::~QQmlTypePrivate() { + qDeleteAll(scopedEnums); switch (regType) { case QQmlType::CppType: delete extraData.cd->customParser; @@ -507,6 +510,67 @@ int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString return type->enumValue(engine, name, ok); } +int QQmlType::resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumIndex(engine, name, ok); +} + +int QQmlType::resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumIndex(engine, name, ok); +} + + +int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumValue(engine, index, name, ok); +} + +int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumValue(engine, index, name, ok); +} + +int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedName, const QByteArray &name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumValue(engine, scopedName, name, ok); +} + +int QQmlType::resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedName, const QStringRef &name, bool *ok) const +{ + Q_ASSERT(isComposite()); + *ok = false; + QQmlType *type = resolveCompositeBaseType(engine); + if (!type) + return -1; + return type->scopedEnumValue(engine, scopedName, name, ok); +} + static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo, const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd) { @@ -702,8 +766,21 @@ void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const // Add any enum values defined by this class, overwriting any inherited values for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) { QMetaEnum e = metaObject->enumerator(ii); - for (int jj = 0; jj < e.keyCount(); ++jj) - enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj)); + const bool isScoped = e.isScoped(); + QStringHash<int> *scoped = isScoped ? new QStringHash<int>() : 0; + + for (int jj = 0; jj < e.keyCount(); ++jj) { + const QString key = QString::fromUtf8(e.key(jj)); + const int value = e.value(jj); + enums.insert(key, value); + if (isScoped) + scoped->insert(key, value); + } + + if (isScoped) { + scopedEnums << scoped; + scopedEnumIndex.insert(QString::fromUtf8(e.name()), scopedEnums.count()-1); + } } } @@ -1004,6 +1081,116 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool return -1; } +int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const +{ + Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeScopedEnumIndex(engine, name, ok); + *ok = true; + + d->initEnums(); + + int *rv = d->scopedEnumIndex.value(name); + if (rv) + return *rv; + + *ok = false; + return -1; +} + +int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const +{ + Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeScopedEnumIndex(engine, name, ok); + *ok = true; + + d->initEnums(); + + int *rv = d->scopedEnumIndex.value(name); + if (rv) + return *rv; + + *ok = false; + return -1; +} + +int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const +{ + Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeScopedEnumValue(engine, index, name, ok); + *ok = true; + + Q_ASSERT(index > -1 && index < d->scopedEnums.count()); + int *rv = d->scopedEnums.at(index)->value(name); + if (rv) + return *rv; + + *ok = false; + return -1; +} + +int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const +{ + Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeScopedEnumValue(engine, index, name, ok); + *ok = true; + + Q_ASSERT(index > -1 && index < d->scopedEnums.count()); + int *rv = d->scopedEnums.at(index)->value(name); + if (rv) + return *rv; + + *ok = false; + return -1; +} + +int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedEnumName, const QByteArray &name, bool *ok) const +{ + Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeScopedEnumValue(engine, scopedEnumName, name, ok); + *ok = true; + + d->initEnums(); + + int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length())); + if (rv) { + int index = *rv; + Q_ASSERT(index > -1 && index < d->scopedEnums.count()); + rv = d->scopedEnums.at(index)->value(QHashedCStringRef(name.constData(), name.length())); + if (rv) + return *rv; + } + + *ok = false; + return -1; +} + +int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedEnumName, const QStringRef &name, bool *ok) const +{ + Q_ASSERT(ok); + if (isComposite()) + return resolveCompositeScopedEnumValue(engine, scopedEnumName, name, ok); + *ok = true; + + d->initEnums(); + + int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName)); + if (rv) { + int index = *rv; + Q_ASSERT(index > -1 && index < d->scopedEnums.count()); + rv = d->scopedEnums.at(index)->value(QHashedStringRef(name)); + if (rv) + return *rv; + } + + *ok = false; + return -1; +} + QQmlTypeModule::QQmlTypeModule() : d(new QQmlTypeModulePrivate) { diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h index 2b615e645a..4dd28bbd36 100644 --- a/src/qml/qml/qqmlmetatype_p.h +++ b/src/qml/qml/qqmlmetatype_p.h @@ -216,10 +216,24 @@ public: int enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &, bool *ok) const; int enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &, bool *ok) const; int enumValue(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const; + + int scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const; + int scopedEnumIndex(QQmlEnginePrivate *engine, const QString &, bool *ok) const; + int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *, bool *ok) const; + int scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &, bool *ok) const; + int scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &, const QByteArray &, bool *ok) const; + int scopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &, const QStringRef &, bool *ok) const; + private: QQmlType *superType() const; QQmlType *resolveCompositeBaseType(QQmlEnginePrivate *engine) const; int resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const; + int resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *, bool *ok) const; + int resolveCompositeScopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const; + int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *, bool *ok) const; + int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const; + int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scopedName, const QByteArray &name, bool *ok) const; + int resolveCompositeScopedEnumValue(QQmlEnginePrivate *engine, const QStringRef &scopedName, const QStringRef &name, bool *ok) const; friend class QQmlTypePrivate; friend struct QQmlMetaTypeData; diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp index 64ca208f1b..165cde5eb3 100644 --- a/src/qml/qml/qqmlplatform.cpp +++ b/src/qml/qml/qqmlplatform.cpp @@ -79,3 +79,5 @@ QString QQmlPlatform::os() } QT_END_NAMESPACE + +#include "moc_qqmlplatform_p.cpp" diff --git a/src/qml/qml/qqmltypenotavailable.cpp b/src/qml/qml/qqmltypenotavailable.cpp index b10a7c62b9..ffa4472e4b 100644 --- a/src/qml/qml/qqmltypenotavailable.cpp +++ b/src/qml/qml/qqmltypenotavailable.cpp @@ -49,3 +49,5 @@ int qmlRegisterTypeNotAvailable(const char *uri, int versionMajor, int versionMi QQmlTypeNotAvailable::QQmlTypeNotAvailable() { } QT_END_NAMESPACE + +#include "moc_qqmltypenotavailable_p.cpp" diff --git a/src/qml/qml/qqmltypewrapper.cpp b/src/qml/qml/qqmltypewrapper.cpp index 7b98096a7f..7a06077c11 100644 --- a/src/qml/qml/qqmltypewrapper.cpp +++ b/src/qml/qml/qqmltypewrapper.cpp @@ -52,16 +52,17 @@ QT_BEGIN_NAMESPACE using namespace QV4; -DEFINE_OBJECT_VTABLE(QmlTypeWrapper); +DEFINE_OBJECT_VTABLE(QQmlTypeWrapper); +DEFINE_OBJECT_VTABLE(QQmlScopedEnumWrapper); -void Heap::QmlTypeWrapper::init() +void Heap::QQmlTypeWrapper::init() { Object::init(); mode = IncludeEnums; object.init(); } -void Heap::QmlTypeWrapper::destroy() +void Heap::QQmlTypeWrapper::destroy() { if (typeNamespace) typeNamespace->release(); @@ -69,12 +70,12 @@ void Heap::QmlTypeWrapper::destroy() Object::destroy(); } -bool QmlTypeWrapper::isSingleton() const +bool QQmlTypeWrapper::isSingleton() const { return d()->type && d()->type->isSingleton(); } -QObject* QmlTypeWrapper::singletonObject() const +QObject* QQmlTypeWrapper::singletonObject() const { if (!isSingleton()) return 0; @@ -85,7 +86,7 @@ QObject* QmlTypeWrapper::singletonObject() const return siinfo->qobjectApi(e); } -QVariant QmlTypeWrapper::toVariant() const +QVariant QQmlTypeWrapper::toVariant() const { if (d()->type && d()->type->isSingleton()) { QQmlEngine *e = engine()->qmlEngine(); @@ -103,27 +104,27 @@ QVariant QmlTypeWrapper::toVariant() const // Returns a type wrapper for type t on o. This allows access of enums, and attached properties. -ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlType *t, - Heap::QmlTypeWrapper::TypeNameMode mode) +ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlType *t, + Heap::QQmlTypeWrapper::TypeNameMode mode) { Q_ASSERT(t); Scope scope(engine); - Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>()); + Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->type = t; return w.asReturnedValue(); } // Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a // namespace. -ReturnedValue QmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const void *importNamespace, - Heap::QmlTypeWrapper::TypeNameMode mode) +ReturnedValue QQmlTypeWrapper::create(QV4::ExecutionEngine *engine, QObject *o, QQmlTypeNameCache *t, const void *importNamespace, + Heap::QQmlTypeWrapper::TypeNameMode mode) { Q_ASSERT(t); Q_ASSERT(importNamespace); Scope scope(engine); - Scoped<QmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QmlTypeWrapper>()); + Scoped<QQmlTypeWrapper> w(scope, engine->memoryManager->allocObject<QQmlTypeWrapper>()); w->d()->mode = mode; w->d()->object = o; w->d()->typeNamespace = t; w->d()->importNamespace = importNamespace; t->addref(); return w.asReturnedValue(); @@ -157,14 +158,14 @@ static ReturnedValue throwLowercaseEnumError(QV4::ExecutionEngine *v4, String *n return v4->throwTypeError(message); } -ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) +ReturnedValue QQmlTypeWrapper::get(const Managed *m, String *name, bool *hasProperty) { - Q_ASSERT(m->as<QmlTypeWrapper>()); + Q_ASSERT(m->as<QQmlTypeWrapper>()); - QV4::ExecutionEngine *v4 = static_cast<const QmlTypeWrapper *>(m)->engine(); + QV4::ExecutionEngine *v4 = static_cast<const QQmlTypeWrapper *>(m)->engine(); QV4::Scope scope(v4); - Scoped<QmlTypeWrapper> w(scope, static_cast<const QmlTypeWrapper *>(m)); + Scoped<QQmlTypeWrapper> w(scope, static_cast<const QQmlTypeWrapper *>(m)); if (hasProperty) *hasProperty = true; @@ -186,7 +187,7 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope if (qobjectSingleton) { // check for enum value - const bool includeEnums = w->d()->mode == Heap::QmlTypeWrapper::IncludeEnums; + const bool includeEnums = w->d()->mode == Heap::QQmlTypeWrapper::IncludeEnums; if (includeEnums && name->startsWithUpper()) { const int value = enumForSingleton(v4, name, qobjectSingleton, type); if (value != -1) @@ -224,6 +225,14 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope if (ok) return QV4::Primitive::fromInt32(value).asReturnedValue(); + value = type->scopedEnumIndex(QQmlEnginePrivate::get(v4->qmlEngine()), name, &ok); + if (ok) { + Scoped<QQmlScopedEnumWrapper> enumWrapper(scope, v4->memoryManager->allocObject<QQmlScopedEnumWrapper>()); + enumWrapper->d()->type = type; + enumWrapper->d()->scopeEnumIndex = value; + return enumWrapper.asReturnedValue(); + } + // Fall through to base implementation } else if (w->d()->object) { @@ -280,10 +289,10 @@ ReturnedValue QmlTypeWrapper::get(const Managed *m, String *name, bool *hasPrope } -bool QmlTypeWrapper::put(Managed *m, String *name, const Value &value) +bool QQmlTypeWrapper::put(Managed *m, String *name, const Value &value) { - Q_ASSERT(m->as<QmlTypeWrapper>()); - QmlTypeWrapper *w = static_cast<QmlTypeWrapper *>(m); + Q_ASSERT(m->as<QQmlTypeWrapper>()); + QQmlTypeWrapper *w = static_cast<QQmlTypeWrapper *>(m); QV4::ExecutionEngine *v4 = w->engine(); if (v4->hasException) return false; @@ -322,7 +331,7 @@ bool QmlTypeWrapper::put(Managed *m, String *name, const Value &value) return false; } -PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name) +PropertyAttributes QQmlTypeWrapper::query(const Managed *m, String *name) { // ### Implement more efficiently. bool hasProperty = false; @@ -330,11 +339,11 @@ PropertyAttributes QmlTypeWrapper::query(const Managed *m, String *name) return hasProperty ? Attr_Data : Attr_Invalid; } -bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b) +bool QQmlTypeWrapper::isEqualTo(Managed *a, Managed *b) { - Q_ASSERT(a->as<QV4::QmlTypeWrapper>()); - QV4::QmlTypeWrapper *qmlTypeWrapperA = static_cast<QV4::QmlTypeWrapper *>(a); - if (QV4::QmlTypeWrapper *qmlTypeWrapperB = b->as<QV4::QmlTypeWrapper>()) + Q_ASSERT(a->as<QV4::QQmlTypeWrapper>()); + QV4::QQmlTypeWrapper *qmlTypeWrapperA = static_cast<QV4::QQmlTypeWrapper *>(a); + if (QV4::QQmlTypeWrapper *qmlTypeWrapperB = b->as<QV4::QQmlTypeWrapper>()) return qmlTypeWrapperA->toVariant() == qmlTypeWrapperB->toVariant(); else if (QV4::QObjectWrapper *qobjectWrapper = b->as<QV4::QObjectWrapper>()) return qmlTypeWrapperA->toVariant().value<QObject*>() == qobjectWrapper->object(); @@ -342,10 +351,10 @@ bool QmlTypeWrapper::isEqualTo(Managed *a, Managed *b) return false; } -ReturnedValue QmlTypeWrapper::instanceOf(const Object *typeObject, const Value &var) +ReturnedValue QQmlTypeWrapper::instanceOf(const Object *typeObject, const Value &var) { - Q_ASSERT(typeObject->as<QV4::QmlTypeWrapper>()); - const QV4::QmlTypeWrapper *typeWrapper = static_cast<const QV4::QmlTypeWrapper *>(typeObject); + Q_ASSERT(typeObject->as<QV4::QQmlTypeWrapper>()); + const QV4::QQmlTypeWrapper *typeWrapper = static_cast<const QV4::QQmlTypeWrapper *>(typeObject); QV4::ExecutionEngine *engine = typeObject->internalClass()->engine; QQmlEnginePrivate *qenginepriv = QQmlEnginePrivate::get(engine->qmlEngine()); @@ -382,4 +391,24 @@ ReturnedValue QmlTypeWrapper::instanceOf(const Object *typeObject, const Value & return QV4::Encode(QQmlMetaObject::canConvert(theirType, myQmlType)); } +ReturnedValue QQmlScopedEnumWrapper::get(const Managed *m, String *name, bool *hasProperty) +{ + Q_ASSERT(m->as<QQmlScopedEnumWrapper>()); + const QQmlScopedEnumWrapper *resource = static_cast<const QQmlScopedEnumWrapper *>(m); + QV4::ExecutionEngine *v4 = resource->engine(); + QV4::Scope scope(v4); + + QQmlType *type = resource->d()->type; + int index = resource->d()->scopeEnumIndex; + + bool ok = false; + int value = type->scopedEnumValue(QQmlEnginePrivate::get(v4->qmlEngine()), index, name, &ok); + if (hasProperty) + *hasProperty = ok; + if (ok) + return QV4::Primitive::fromInt32(value).asReturnedValue(); + + return Encode::undefined(); +} + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmltypewrapper_p.h b/src/qml/qml/qqmltypewrapper_p.h index c584458ed4..730bfd6d12 100644 --- a/src/qml/qml/qqmltypewrapper_p.h +++ b/src/qml/qml/qqmltypewrapper_p.h @@ -65,7 +65,7 @@ namespace QV4 { namespace Heap { -struct QmlTypeWrapper : Object { +struct QQmlTypeWrapper : Object { enum TypeNameMode { IncludeEnums, ExcludeEnums @@ -81,11 +81,18 @@ struct QmlTypeWrapper : Object { const void *importNamespace; }; +struct QQmlScopedEnumWrapper : Object { + void init() { Object::init(); } + void destroy() { Object::destroy(); } + int scopeEnumIndex; + QQmlType *type; +}; + } -struct Q_QML_EXPORT QmlTypeWrapper : Object +struct Q_QML_EXPORT QQmlTypeWrapper : Object { - V4_OBJECT2(QmlTypeWrapper, Object) + V4_OBJECT2(QQmlTypeWrapper, Object) V4_NEEDS_DESTROY bool isSingleton() const; @@ -94,9 +101,9 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object QVariant toVariant() const; static ReturnedValue create(ExecutionEngine *, QObject *, QQmlType *, - Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums); + Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums); static ReturnedValue create(ExecutionEngine *, QObject *, QQmlTypeNameCache *, const void *, - Heap::QmlTypeWrapper::TypeNameMode = Heap::QmlTypeWrapper::IncludeEnums); + Heap::QQmlTypeWrapper::TypeNameMode = Heap::QQmlTypeWrapper::IncludeEnums); static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); @@ -106,6 +113,14 @@ struct Q_QML_EXPORT QmlTypeWrapper : Object static ReturnedValue instanceOf(const Object *typeObject, const Value &var); }; +struct Q_QML_EXPORT QQmlScopedEnumWrapper : Object +{ + V4_OBJECT2(QQmlScopedEnumWrapper, Object) + V4_NEEDS_DESTROY + + static ReturnedValue get(const Managed *m, String *name, bool *hasProperty); +}; + } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlvaluetype.cpp b/src/qml/qml/qqmlvaluetype.cpp index bcefad0ee3..520f512b1a 100644 --- a/src/qml/qml/qqmlvaluetype.cpp +++ b/src/qml/qml/qqmlvaluetype.cpp @@ -566,3 +566,5 @@ QVariantList QQmlEasingValueType::bezierCurve() const } QT_END_NAMESPACE + +#include "moc_qqmlvaluetype_p.cpp" diff --git a/src/qml/qml/qqmlvaluetypewrapper.cpp b/src/qml/qml/qqmlvaluetypewrapper.cpp index d262b230e2..ce47ab9fa9 100644 --- a/src/qml/qml/qqmlvaluetypewrapper.cpp +++ b/src/qml/qml/qqmlvaluetypewrapper.cpp @@ -51,9 +51,11 @@ #include <private/qv4alloca_p.h> #include <private/qv4objectiterator_p.h> #include <private/qv4qobjectwrapper_p.h> +#include <QtCore/qloggingcategory.h> QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcBindingRemoval) DEFINE_OBJECT_VTABLE(QV4::QQmlValueTypeWrapper); @@ -438,6 +440,9 @@ bool QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) if (reference) { QV4::ScopedFunctionObject f(scope, value); + const QQmlQPointer<QObject> &referenceObject = reference->d()->object; + const int referencePropertyIndex = reference->d()->property; + if (f) { if (!f->isBinding()) { // assigning a JS function to a non-var-property is not allowed. @@ -452,18 +457,31 @@ bool QQmlValueTypeWrapper::put(Managed *m, String *name, const Value &value) QQmlPropertyData cacheData; cacheData.setWritable(true); cacheData.setPropType(writeBackPropertyType); - cacheData.setCoreIndex(reference->d()->property); + cacheData.setCoreIndex(referencePropertyIndex); QV4::Scoped<QQmlBindingFunction> bindingFunction(scope, (const Value &)f); QV4::ScopedContext ctx(scope, bindingFunction->scope()); - QQmlBinding *newBinding = QQmlBinding::create(&cacheData, bindingFunction->function(), reference->d()->object, context, ctx); + QQmlBinding *newBinding = QQmlBinding::create(&cacheData, bindingFunction->function(), referenceObject, context, ctx); newBinding->setSourceLocation(bindingFunction->currentLocation()); - newBinding->setTarget(reference->d()->object, cacheData, pd); + newBinding->setTarget(referenceObject, cacheData, pd); QQmlPropertyPrivate::setBinding(newBinding); return true; } else { - QQmlPropertyPrivate::removeBinding(reference->d()->object, QQmlPropertyIndex(reference->d()->property, pd->coreIndex())); + if (Q_UNLIKELY(lcBindingRemoval().isInfoEnabled())) { + if (auto binding = QQmlPropertyPrivate::binding(referenceObject, QQmlPropertyIndex(referencePropertyIndex, pd->coreIndex()))) { + Q_ASSERT(!binding->isValueTypeProxy()); + const auto qmlBinding = static_cast<const QQmlBinding*>(binding); + const auto stackFrame = v4->currentStackFrame(); + qCInfo(lcBindingRemoval, + "Overwriting binding on %s::%s which was initially bound at %s by setting \"%s\" at %s:%d", + referenceObject->metaObject()->className(), referenceObject->metaObject()->property(referencePropertyIndex).name(), + qPrintable(qmlBinding->expressionIdentifier()), + metaObject->property(pd->coreIndex()).name(), + qPrintable(stackFrame.source), stackFrame.line); + } + } + QQmlPropertyPrivate::removeBinding(referenceObject, QQmlPropertyIndex(referencePropertyIndex, pd->coreIndex())); } } |