aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorMichael Brasser <mbrasser@ford.com>2017-04-20 15:59:31 +0200
committerMichael Brasser <michael.brasser@live.com>2017-07-13 21:00:55 +0000
commit22a2cc43387ec3b9f74a6c01f8665378a4541147 (patch)
tree33acf5a5367302eb3f488b688aba7c85959035ae /src/qml/qml
parent286f14f1e29e7f4e2db4517d087dd5c92606f971 (diff)
Add support for enum declarations in QML
Enums can be declared with the following syntax: enum MyEnum { Value1, Value2 } Grammar changes done by Simon Hausmann. [ChangeLog][QtQml] Enums can now be declared directly in QML. Task-number: QTBUG-14861 Change-Id: Ic6b6e032651d01ee2ecf9d5ce5734976cb3ad7ab Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlimport.cpp36
-rw-r--r--src/qml/qml/qqmlimport_p.h13
-rw-r--r--src/qml/qml/qqmlmetatype.cpp151
-rw-r--r--src/qml/qml/qqmlmetatype_p.h9
-rw-r--r--src/qml/qml/qqmlpropertycache.cpp21
-rw-r--r--src/qml/qml/qqmlpropertycache_p.h33
-rw-r--r--src/qml/qml/qqmltypeloader.cpp4
-rw-r--r--src/qml/qml/qqmltypenamecache.cpp4
-rw-r--r--src/qml/qml/qqmltypenamecache_p.h2
9 files changed, 154 insertions, 119 deletions
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index ee5b38717b..d2a7970a84 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -295,7 +295,8 @@ public:
QList<QQmlError> *errors);
bool resolveType(const QHashedStringRef &type, int *vmajor, int *vminor,
- QQmlType** type_return, QList<QQmlError> *errors);
+ QQmlType** type_return, QList<QQmlError> *errors,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion);
QUrl baseUrl;
QString base;
@@ -620,7 +621,8 @@ QString QQmlImports::versionString(int vmaj, int vmin, ImportVersion version)
*/
bool QQmlImports::resolveType(const QHashedStringRef &type,
QQmlType** type_return, int *vmaj, int *vmin,
- QQmlImportNamespace** ns_return, QList<QQmlError> *errors) const
+ QQmlImportNamespace** ns_return, QList<QQmlError> *errors,
+ QQmlImport::RecursionRestriction recursionRestriction) const
{
QQmlImportNamespace* ns = d->findQualifiedNamespace(type);
if (ns) {
@@ -629,7 +631,7 @@ bool QQmlImports::resolveType(const QHashedStringRef &type,
return true;
}
if (type_return) {
- if (d->resolveType(type,vmaj,vmin,type_return, errors)) {
+ if (d->resolveType(type,vmaj,vmin,type_return, errors, recursionRestriction)) {
if (qmlImportTrace()) {
#define RESOLVE_TYPE_DEBUG qDebug().nospace() << "QQmlImports(" << qPrintable(baseUrl().toString()) \
<< ')' << "::resolveType: " << type.toString() << " => "
@@ -712,7 +714,8 @@ bool QQmlImports::resolveType(QQmlImportNamespace* ns, const QHashedStringRef &t
bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader,
const QHashedStringRef& type, int *vmajor, int *vminor,
- QQmlType** type_return, QString *base, bool *typeRecursionDetected) const
+ QQmlType** type_return, QString *base, bool *typeRecursionDetected,
+ QQmlImport::RecursionRestriction recursionRestriction) const
{
if (majversion >= 0 && minversion >= 0) {
QQmlType *t = QQmlMetaType::qmlType(type, uri, majversion, minversion);
@@ -747,7 +750,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader,
if (resolveLocalUrl(*base, c.fileName) != componentUrl)
continue; // failed attempt to access an internal type
}
- if (*base == componentUrl) {
+ if (recursionRestriction == QQmlImport::PreventRecursion && *base == componentUrl) {
if (typeRecursionDetected)
*typeRecursionDetected = true;
continue; // no recursion
@@ -790,7 +793,7 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader,
}
if (exists) {
- if (base && (*base == qmlUrl)) { // no recursion
+ if (recursionRestriction == QQmlImport::PreventRecursion && base && (*base == qmlUrl)) { // no recursion
if (typeRecursionDetected)
*typeRecursionDetected = true;
} else {
@@ -806,7 +809,8 @@ bool QQmlImportInstance::resolveType(QQmlTypeLoader *typeLoader,
}
bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor, int *vminor,
- QQmlType** type_return, QList<QQmlError> *errors)
+ QQmlType** type_return, QList<QQmlError> *errors,
+ QQmlImport::RecursionRestriction recursionRestriction)
{
QQmlImportNamespace *s = 0;
int dot = type.indexOf(Dot);
@@ -835,7 +839,7 @@ bool QQmlImportsPrivate::resolveType(const QHashedStringRef& type, int *vmajor,
}
QHashedStringRef unqualifiedtype = dot < 0 ? type : QHashedStringRef(type.constData()+dot+1, type.length()-dot-1);
if (s) {
- if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return, &base, errors))
+ if (s->resolveType(typeLoader,unqualifiedtype,vmajor,vminor,type_return, &base, errors, recursionRestriction))
return true;
if (s->imports.count() == 1 && !s->imports.at(0)->isLibrary && type_return && s != &unqualifiedset) {
// qualified, and only 1 url
@@ -858,13 +862,14 @@ QQmlImportInstance *QQmlImportNamespace::findImport(const QString &uri) const
bool QQmlImportNamespace::resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
int *vmajor, int *vminor, QQmlType** type_return,
- QString *base, QList<QQmlError> *errors)
+ QString *base, QList<QQmlError> *errors,
+ QQmlImport::RecursionRestriction recursionRestriction)
{
bool typeRecursionDetected = false;
for (int i=0; i<imports.count(); ++i) {
const QQmlImportInstance *import = imports.at(i);
if (import->resolveType(typeLoader, type, vmajor, vminor, type_return,
- base, &typeRecursionDetected)) {
+ base, &typeRecursionDetected, recursionRestriction)) {
if (qmlCheckTypes()) {
// check for type clashes
for (int j = i+1; j<imports.count(); ++j) {
@@ -1489,6 +1494,17 @@ bool QQmlImportsPrivate::addFileImport(const QString& uri, const QString &prefix
if (!url.endsWith(Slash) && !url.endsWith(Backslash))
url += Slash;
+ // ### For enum support, we are now adding the implicit import always (and earlier). Bail early
+ // if the implicit import has already been explicitly added, otherwise we can run into issues
+ // with duplicate imports
+ if (isImplicitImport) {
+ for (QList<QQmlImportInstance *>::const_iterator it = nameSpace->imports.constBegin();
+ it != nameSpace->imports.constEnd(); ++it) {
+ if ((*it)->uri == importUri)
+ return true;
+ }
+ }
+
QQmlImportInstance *inserted = addImportToNamespace(nameSpace, importUri, url, vmaj, vmin, QV4::CompiledData::Import::ImportFile, errors, isImplicitImport);
Q_ASSERT(inserted);
diff --git a/src/qml/qml/qqmlimport_p.h b/src/qml/qml/qqmlimport_p.h
index 7c691a468c..1a50d5c16a 100644
--- a/src/qml/qml/qqmlimport_p.h
+++ b/src/qml/qml/qqmlimport_p.h
@@ -70,6 +70,10 @@ class QQmlImportDatabase;
class QQmlTypeLoader;
class QQmlTypeLoaderQmldirContent;
+namespace QQmlImport {
+ enum RecursionRestriction { PreventRecursion, AllowRecursion };
+}
+
struct QQmlImportInstance
{
QString uri; // e.g. QtQuick
@@ -87,7 +91,8 @@ struct QQmlImportInstance
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef &type,
int *vmajor, int *vminor, QQmlType** type_return,
- QString *base = 0, bool *typeRecursionDetected = 0) const;
+ QString *base = 0, bool *typeRecursionDetected = 0,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
};
class QQmlImportNamespace
@@ -102,7 +107,8 @@ public:
bool resolveType(QQmlTypeLoader *typeLoader, const QHashedStringRef& type,
int *vmajor, int *vminor, QQmlType** type_return,
- QString *base = 0, QList<QQmlError> *errors = 0);
+ QString *base = 0, QList<QQmlError> *errors = 0,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion);
// Prefix when used as a qualified import. Otherwise empty.
QHashedString prefix;
@@ -128,7 +134,8 @@ public:
QQmlType** type_return,
int *version_major, int *version_minor,
QQmlImportNamespace** ns_return,
- QList<QQmlError> *errors = 0) const;
+ QList<QQmlError> *errors = 0,
+ QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
bool resolveType(QQmlImportNamespace*,
const QHashedStringRef& type,
QQmlType** type_return, int *version_major, int *version_minor) const;
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 0672618225..b75508e1e5 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -160,8 +160,9 @@ public:
~QQmlTypePrivate();
void init() const;
- void initEnums() const;
+ void initEnums(const QQmlPropertyCache *cache = 0) const;
void insertEnums(const QMetaObject *metaObject) const;
+ void insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const;
QQmlType::RegistrationType regType;
@@ -500,75 +501,17 @@ QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
return QQmlMetaType::qmlType(mo);
}
-int QQmlType::resolveCompositeEnumValue(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
+QQmlPropertyCache *QQmlType::compositePropertyCache(QQmlEnginePrivate *engine) const
{
+ // similar logic to resolveCompositeBaseType
Q_ASSERT(isComposite());
- *ok = false;
- QQmlType *type = resolveCompositeBaseType(engine);
- if (!type)
- return -1;
- 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);
+ if (!engine)
+ return 0;
+ QQmlRefPointer<QQmlTypeData> td(engine->typeLoader.getType(sourceUrl()), QQmlRefPointer<QQmlTypeData>::Adopt);
+ if (td.isNull() || !td->isComplete())
+ return 0;
+ QV4::CompiledData::CompilationUnit *compilationUnit = td->compilationUnit();
+ return compilationUnit->rootPropertyCache();
}
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
@@ -737,7 +680,7 @@ void QQmlTypePrivate::init() const
lock.unlock();
}
-void QQmlTypePrivate::initEnums() const
+void QQmlTypePrivate::initEnums(const QQmlPropertyCache *cache) const
{
if (isEnumSetup) return;
@@ -746,6 +689,8 @@ void QQmlTypePrivate::initEnums() const
QMutexLocker lock(metaTypeDataLock());
if (isEnumSetup) return;
+ if (cache)
+ insertEnumsFromPropertyCache(cache);
if (baseMetaObject) // could be singleton type without metaobject
insertEnums(baseMetaObject);
@@ -784,6 +729,31 @@ void QQmlTypePrivate::insertEnums(const QMetaObject *metaObject) const
}
}
+void QQmlTypePrivate::insertEnumsFromPropertyCache(const QQmlPropertyCache *cache) const
+{
+ const QMetaObject *cppMetaObject = cache->firstCppMetaObject();
+
+ while (cache && cache->metaObject() != cppMetaObject) {
+ QStringHash<int> *scoped = new QStringHash<int>();
+
+ int count = cache->qmlEnumCount();
+ for (int ii = 0; ii < count; ++ii) {
+ QQmlEnumData *enumData = cache->qmlEnum(ii);
+
+ for (int jj = 0; jj < enumData->values.count(); ++jj) {
+ const QQmlEnumValue &value = enumData->values.at(jj);
+ enums.insert(value.namedValue, value.value);
+ scoped->insert(value.namedValue, value.value);
+ }
+ scopedEnums << scoped;
+ scopedEnumIndex.insert(enumData->name, scopedEnums.count()-1);
+ }
+ cache = cache->parent();
+ }
+ insertEnums(cppMetaObject);
+}
+
+
QByteArray QQmlType::typeName() const
{
if (d->regType == SingletonType || d->regType == CompositeSingletonType)
@@ -1033,11 +1003,11 @@ QUrl QQmlType::sourceUrl() const
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name, bool *ok) const
{
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeEnumValue(engine, name.toString(), ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->enums.value(name);
if (rv)
@@ -1050,11 +1020,11 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedStringRef &name,
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name, bool *ok) const
{
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeEnumValue(engine, name.toUtf16(), ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
+
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->enums.value(name);
if (rv)
@@ -1067,11 +1037,10 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QHashedCStringRef &name
int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
{
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeEnumValue(engine, name->toQString(), ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->enums.value(name);
if (rv)
@@ -1084,11 +1053,10 @@ int QQmlType::enumValue(QQmlEnginePrivate *engine, const QV4::String *name, bool
int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name, bool *ok) const
{
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeScopedEnumIndex(engine, name, ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->scopedEnumIndex.value(name);
if (rv)
@@ -1101,11 +1069,10 @@ int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QV4::String *name
int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bool *ok) const
{
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeScopedEnumIndex(engine, name, ok);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->scopedEnumIndex.value(name);
if (rv)
@@ -1117,9 +1084,8 @@ int QQmlType::scopedEnumIndex(QQmlEnginePrivate *engine, const QString &name, bo
int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::String *name, bool *ok) const
{
+ Q_UNUSED(engine)
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeScopedEnumValue(engine, index, name, ok);
*ok = true;
Q_ASSERT(index > -1 && index < d->scopedEnums.count());
@@ -1133,9 +1099,8 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QV4::S
int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QString &name, bool *ok) const
{
+ Q_UNUSED(engine)
Q_ASSERT(ok);
- if (isComposite())
- return resolveCompositeScopedEnumValue(engine, index, name, ok);
*ok = true;
Q_ASSERT(index > -1 && index < d->scopedEnums.count());
@@ -1150,11 +1115,10 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, int index, const QStrin
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);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->scopedEnumIndex.value(QHashedCStringRef(scopedEnumName.constData(), scopedEnumName.length()));
if (rv) {
@@ -1172,11 +1136,10 @@ int QQmlType::scopedEnumValue(QQmlEnginePrivate *engine, const QByteArray &scope
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);
+ const QQmlPropertyCache *cache = isComposite() ? compositePropertyCache(engine) : 0;
*ok = true;
- d->initEnums();
+ d->initEnums(cache);
int *rv = d->scopedEnumIndex.value(QHashedStringRef(scopedEnumName));
if (rv) {
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 4dd28bbd36..ead4f130ec 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -135,6 +135,7 @@ public:
struct QQmlMetaTypeData;
class QHashedCStringRef;
+class QQmlPropertyCache;
class Q_QML_PRIVATE_EXPORT QQmlType
{
public:
@@ -227,13 +228,7 @@ public:
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;
+ QQmlPropertyCache *compositePropertyCache(QQmlEnginePrivate *engine) const;
friend class QQmlTypePrivate;
friend struct QQmlMetaTypeData;
diff --git a/src/qml/qml/qqmlpropertycache.cpp b/src/qml/qml/qqmlpropertycache.cpp
index d18159841c..15b9fe8312 100644
--- a/src/qml/qml/qqmlpropertycache.cpp
+++ b/src/qml/qml/qqmlpropertycache.cpp
@@ -321,12 +321,13 @@ QQmlPropertyCache *QQmlPropertyCache::copy()
}
QQmlPropertyCache *QQmlPropertyCache::copyAndReserve(int propertyCount, int methodCount,
- int signalCount)
+ int signalCount, int enumCount)
{
QQmlPropertyCache *rv = copy(propertyCount + methodCount + signalCount);
rv->propertyIndexCache.reserve(propertyCount);
rv->methodIndexCache.reserve(methodCount);
rv->signalHandlerIndexCache.reserve(signalCount);
+ rv->enumCache.reserve(enumCount);
rv->_metaObject = 0;
return rv;
@@ -421,6 +422,14 @@ void QQmlPropertyCache::appendMethod(const QString &name, QQmlPropertyData::Flag
setNamedProperty(name, methodIndex + methodOffset(), methodIndexCache.data() + methodIndex, (old != 0));
}
+void QQmlPropertyCache::appendEnum(const QString &name, const QVector<QQmlEnumValue> &values)
+{
+ QQmlEnumData data;
+ data.name = name;
+ data.values = values;
+ enumCache.append(data);
+}
+
// Returns this property cache's metaObject, creating it if necessary.
const QMetaObject *QQmlPropertyCache::createMetaObject()
{
@@ -1245,6 +1254,16 @@ void QQmlPropertyCache::toMetaObjectBuilder(QMetaObjectBuilder &builder)
method.setReturnType(returnType);
}
+ for (int ii = 0; ii < enumCache.count(); ++ii) {
+ const QQmlEnumData &enumData = enumCache.at(ii);
+ QMetaEnumBuilder enumeration = builder.addEnumerator(enumData.name.toUtf8());
+ enumeration.setIsScoped(true);
+ for (int jj = 0; jj < enumData.values.count(); ++jj) {
+ const QQmlEnumValue &value = enumData.values.at(jj);
+ enumeration.addKey(value.namedValue.toUtf8(), value.value);
+ }
+ }
+
if (!_defaultPropertyName.isEmpty()) {
QQmlPropertyData *dp = property(_defaultPropertyName, 0, 0);
if (dp && dp->coreIndex() >= propertyIndexCacheStart) {
diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h
index 64be1cb206..392768c1b1 100644
--- a/src/qml/qml/qqmlpropertycache_p.h
+++ b/src/qml/qml/qqmlpropertycache_p.h
@@ -349,6 +349,20 @@ private:
bool notFullyResolved() const { return _flags.notFullyResolved; }
};
+struct QQmlEnumValue
+{
+ QQmlEnumValue() : value(-1) {}
+ QQmlEnumValue(const QString &n, int v) : namedValue(n), value(v) {}
+ QString namedValue;
+ int value;
+};
+
+struct QQmlEnumData
+{
+ QString name;
+ QVector<QQmlEnumValue> values;
+};
+
class QQmlPropertyCacheMethodArguments;
class Q_QML_PRIVATE_EXPORT QQmlPropertyCache : public QQmlRefCount, public QQmlCleanup
{
@@ -374,13 +388,14 @@ public:
QQmlPropertyRawData::Flags signalFlags = QQmlPropertyData::Flags());
QQmlPropertyCache *copyAndReserve(int propertyCount,
- int methodCount, int signalCount);
+ int methodCount, int signalCount, int enumCount);
void appendProperty(const QString &, QQmlPropertyRawData::Flags flags, int coreIndex,
int propType, int notifyIndex);
void appendSignal(const QString &, QQmlPropertyRawData::Flags, int coreIndex,
const int *types = 0, const QList<QByteArray> &names = QList<QByteArray>());
void appendMethod(const QString &, QQmlPropertyData::Flags flags, int coreIndex,
const QList<QByteArray> &names = QList<QByteArray>());
+ void appendEnum(const QString &, const QVector<QQmlEnumValue> &);
const QMetaObject *metaObject() const;
const QMetaObject *createMetaObject();
@@ -395,6 +410,7 @@ public:
QQmlPropertyData *property(int) const;
QQmlPropertyData *method(int) const;
QQmlPropertyData *signal(int index) const;
+ QQmlEnumData *qmlEnum(int) const;
int methodIndexToSignalIndex(int) const;
QString defaultPropertyName() const;
@@ -434,6 +450,7 @@ public:
inline int methodOffset() const;
inline int signalCount() const;
inline int signalOffset() const;
+ inline int qmlEnumCount() const;
static bool isDynamicMetaObject(const QMetaObject *);
@@ -507,6 +524,7 @@ private:
IndexCache signalHandlerIndexCache;
StringCache stringCache;
AllowedRevisionCache allowedRevisionCache;
+ QVector<QQmlEnumData> enumCache;
bool _hasPropertyOverrides : 1;
bool _ownMetaObject : 1;
@@ -747,6 +765,14 @@ inline QQmlPropertyData *QQmlPropertyCache::signal(int index) const
return ensureResolved(rv);
}
+inline QQmlEnumData *QQmlPropertyCache::qmlEnum(int index) const
+{
+ if (index < 0 || index >= enumCache.count())
+ return 0;
+
+ return const_cast<QQmlEnumData *>(&enumCache.at(index));
+}
+
inline int QQmlPropertyCache::methodIndexToSignalIndex(int index) const
{
if (index < 0 || index >= (methodIndexCacheStart + methodIndexCache.count()))
@@ -817,6 +843,11 @@ int QQmlPropertyCache::signalOffset() const
return signalHandlerIndexCacheStart;
}
+int QQmlPropertyCache::qmlEnumCount() const
+{
+ return enumCache.count();
+}
+
bool QQmlPropertyCache::callJSFactoryMethod(QObject *object, void **args) const
{
if (_jsFactoryMethodIndex != -1) {
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index e4293596d8..151a7cd883 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2651,6 +2651,10 @@ void QQmlTypeData::resolveTypes()
m_resolvedTypes.insert(unresolvedRef.key(), ref);
}
+
+ // ### this allows enums to work without explicit import or instantiation of the type
+ if (!m_implicitImportLoaded)
+ loadImplicitImport();
}
QQmlCompileError QQmlTypeData::buildTypeResolutionCaches(
diff --git a/src/qml/qml/qqmltypenamecache.cpp b/src/qml/qml/qqmltypenamecache.cpp
index c8e2b92c29..35ef8ada57 100644
--- a/src/qml/qml/qqmltypenamecache.cpp
+++ b/src/qml/qml/qqmltypenamecache.cpp
@@ -140,7 +140,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QHashedStringRef &name,
return result;
}
-QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name) const
+QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name, QQmlImport::RecursionRestriction recursionRestriction) const
{
Result result = query(m_namedImports, name);
@@ -156,7 +156,7 @@ QQmlTypeNameCache::Result QQmlTypeNameCache::query(const QV4::String *name) cons
QQmlImportNamespace *typeNamespace = 0;
QList<QQmlError> errors;
QQmlType *t = 0;
- bool typeFound = m_imports.resolveType(typeName, &t, 0, 0, &typeNamespace, &errors);
+ bool typeFound = m_imports.resolveType(typeName, &t, 0, 0, &typeNamespace, &errors, recursionRestriction);
if (typeFound) {
return Result(t);
}
diff --git a/src/qml/qml/qqmltypenamecache_p.h b/src/qml/qml/qqmltypenamecache_p.h
index 7cdcbe91b6..f7ba2a91b7 100644
--- a/src/qml/qml/qqmltypenamecache_p.h
+++ b/src/qml/qml/qqmltypenamecache_p.h
@@ -90,7 +90,7 @@ public:
};
Result query(const QHashedStringRef &) const;
Result query(const QHashedStringRef &, const void *importNamespace) const;
- Result query(const QV4::String *) const;
+ Result query(const QV4::String *, QQmlImport::RecursionRestriction recursionRestriction = QQmlImport::PreventRecursion) const;
Result query(const QV4::String *, const void *importNamespace) const;
private: