return d->base;
}
-static QDeclarativeTypeNameCache *
-cacheForNamespace(QDeclarativeEngine *engine, const QDeclarativeImportedNamespace &set,
- QDeclarativeTypeNameCache *cache, bool importWasQualified)
+void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const
{
- if (!cache)
- cache = new QDeclarativeTypeNameCache(engine);
-
- QList<QDeclarativeType *> types = QDeclarativeMetaType::qmlTypes();
+ const QDeclarativeImportedNamespace &set = d->unqualifiedset;
- for (int ii = 0; ii < set.uris.count(); ++ii) {
- QByteArray uri = set.uris.at(ii).toUtf8();
- int major = set.majversions.at(ii);
- int minor = set.minversions.at(ii);
+ for (int ii = set.uris.count() - 1; ii >= 0; --ii) {
+ const QByteArray uri = set.uris.at(ii).toUtf8(); // XXX sigh
+ int majversion = set.majversions.at(ii);
+ int minversion = set.minversions.at(ii);
+ QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(uri, majversion);
+ if (module) cache->m_anonymousImports.append(QDeclarativeTypeModuleVersion(module, minversion));
+ }
- if (importWasQualified) {
- QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(uri, major, minor);
+ for (QHash<QString,QDeclarativeImportedNamespace* >::ConstIterator iter = d->set.begin();
+ iter != d->set.end();
+ ++iter) {
+
+ const QDeclarativeImportedNamespace &set = *iter.value();
+ QDeclarativeTypeNameCache::Import &import = cache->m_namedImports[iter.key()];
+ for (int ii = set.uris.count() - 1; ii >= 0; --ii) {
+ const QByteArray uri = set.uris.at(ii).toUtf8(); // XXX sigh
+ int majversion = set.majversions.at(ii);
+ int minversion = set.minversions.at(ii);
+ QDeclarativeTypeModule *module = QDeclarativeMetaType::typeModule(uri, majversion);
+ if (module) import.modules.append(QDeclarativeTypeModuleVersion(module, minversion));
+
+ QDeclarativeMetaType::ModuleApi moduleApi = QDeclarativeMetaType::moduleApi(uri, majversion, minversion);
if (moduleApi.script || moduleApi.qobject) {
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
QDeclarativeMetaType::ModuleApiInstance *a = ep->moduleApiInstances.value(moduleApi);
a->qobjectCallback = moduleApi.qobject;
ep->moduleApiInstances.insert(moduleApi, a);
}
- cache->setModuleApi(a);
- }
- }
-
- QByteArray base = uri + '/';
-
- foreach (QDeclarativeType *type, types) {
- if (type->qmlTypeName().startsWith(base) &&
- type->qmlTypeName().lastIndexOf('/') == (base.length() - 1) &&
- (major < 0 || type->availableInVersion(major,minor)))
- {
- QString name = QString::fromUtf8(type->qmlTypeName().mid(base.length()));
-
- cache->add(name, type);
+ import.moduleApi = a;
}
}
}
- return cache;
-}
-
-void QDeclarativeImports::populateCache(QDeclarativeTypeNameCache *cache, QDeclarativeEngine *engine) const
-{
- const QDeclarativeImportedNamespace &set = d->unqualifiedset;
-
- for (QHash<QString,QDeclarativeImportedNamespace* >::ConstIterator iter = d->set.begin();
- iter != d->set.end(); ++iter) {
-
- QDeclarativeTypeNameCache::Data *d = cache->data(iter.key());
- if (d) {
- if (!d->typeNamespace)
- cacheForNamespace(engine, *(*iter), d->typeNamespace, true);
- } else {
- QDeclarativeTypeNameCache *nc = cacheForNamespace(engine, *(*iter), 0, true);
- cache->add(iter.key(), nc);
- nc->release();
- }
- }
- cacheForNamespace(engine, set, cache, false);
}
/*!
bool found = false;
QString dir;
-
// step 1: search for extension with fully encoded version number
- foreach (const QString &p, database->fileImportPath) {
- dir = p+QLatin1Char('/')+url;
+ if (!found) {
+ foreach (const QString &p, database->fileImportPath) {
+ dir = p+QLatin1Char('/')+url;
QFileInfo fi(dir+QString(QLatin1String(".%1.%2")).arg(vmaj).arg(vmin)+QLatin1String("/qmldir"));
const QString absoluteFilePath = fi.absoluteFilePath();
}
// step 2: search for extension with encoded version major
- foreach (const QString &p, database->fileImportPath) {
- dir = p+QLatin1Char('/')+url;
+ if (!found) {
+ foreach (const QString &p, database->fileImportPath) {
+ dir = p+QLatin1Char('/')+url;
QFileInfo fi(dir+QString(QLatin1String(".%1")).arg(vmaj)+QLatin1String("/qmldir"));
const QString absoluteFilePath = fi.absoluteFilePath();
if (!versionFound && qmldircomponents.isEmpty()) {
if (errors) {
- bool anyversion = QDeclarativeMetaType::isAnyModule(uri.toUtf8());
QDeclarativeError error; // we don't set the url or line or column as these will be set by the loader.
- if (anyversion)
+ if (QDeclarativeMetaType::isAnyModule(uri.toUtf8()))
error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" version %2.%3 is not installed").arg(uri_arg).arg(vmaj).arg(vmin));
else
error.setDescription(QDeclarativeImportDatabase::tr("module \"%1\" is not installed").arg(uri_arg));
#include <QtDeclarative/qdeclarativeprivate.h>
#include "private/qdeclarativemetatype_p.h"
-#include "private/qdeclarativeproxymetaobject_p.h"
-#include "private/qdeclarativecustomparser_p.h"
-#include "private/qdeclarativeguard_p.h"
+#include <private/qdeclarativeproxymetaobject_p.h>
+#include <private/qdeclarativecustomparser_p.h>
+#include <private/qdeclarativeguard_p.h>
+#include <private/qhashedstring_p.h>
#include <QtCore/qdebug.h>
#include <QtCore/qstringlist.h>
MetaObjects metaObjectToType;
typedef QHash<int, QDeclarativeMetaType::StringConverter> StringConverters;
StringConverters stringConverters;
+
+ struct VersionedUri {
+ VersionedUri()
+ : majorVersion(0) {}
+ VersionedUri(const QByteArray &uri, int majorVersion)
+ : uri(uri), majorVersion(majorVersion) {}
+ bool operator==(const VersionedUri &other) const {
+ return other.majorVersion == majorVersion && other.uri == uri;
+ }
+ QByteArray uri;
+ int majorVersion;
+ };
+ typedef QHash<VersionedUri, QDeclarativeTypeModule *> TypeModules;
+ TypeModules uriToModule;
+
struct ModuleApiList {
ModuleApiList() : sorted(true) {}
QList<QDeclarativeMetaType::ModuleApi> moduleApis;
ModuleApis moduleApis;
int moduleApiCount;
- struct ModuleInfo {
- ModuleInfo(int major, int minor)
- : vmajor(major), vminor_min(minor), vminor_max(minor) {}
- ModuleInfo(int major, int minor_min, int minor_max)
- : vmajor(major), vminor_min(minor_min), vminor_max(minor_max) {}
- int vmajor;
- int vminor_min, vminor_max;
- };
- typedef QHash<QPair<QByteArray,int>, ModuleInfo> ModuleInfoHash;
- ModuleInfoHash modules;
-
QBitArray objects;
QBitArray interfaces;
QBitArray lists;
QList<QDeclarativePrivate::AutoParentFunction> parentFunctions;
};
+
+class QDeclarativeTypeModulePrivate
+{
+public:
+ QDeclarativeTypeModulePrivate()
+ : minMinorVersion(INT_MAX), maxMinorVersion(0) {}
+
+ QDeclarativeMetaTypeData::VersionedUri uri;
+
+ int minMinorVersion;
+ int maxMinorVersion;
+
+ void add(QDeclarativeType *);
+
+ QStringHash<QList<QDeclarativeType *> > typeHash;
+ QList<QDeclarativeType *> types;
+};
+
Q_GLOBAL_STATIC(QDeclarativeMetaTypeData, metaTypeData)
Q_GLOBAL_STATIC(QReadWriteLock, metaTypeDataLock)
+static uint qHash(const QDeclarativeMetaTypeData::VersionedUri &v)
+{
+ return qHash(v.uri) ^ qHash(v.majorVersion);
+}
+
QDeclarativeMetaTypeData::QDeclarativeMetaTypeData()
: moduleApiCount(0)
{
QDeclarativeTypePrivate();
void init() const;
+ void initEnums() const;
bool m_isInterface : 1;
const char *m_iid;
QByteArray m_module;
QByteArray m_name;
+ QString m_elementName;
int m_version_maj;
int m_version_min;
int m_typeId; int m_listId;
int m_index;
QDeclarativeCustomParser *m_customParser;
mutable volatile bool m_isSetup:1;
- mutable bool m_haveSuperType : 1;
+ mutable volatile bool m_isEnumSetup:1;
+ mutable bool m_haveSuperType:1;
mutable QList<QDeclarativeProxyMetaObject::ProxyData> m_metaObjects;
+ mutable QStringHash<int> m_enums;
static QHash<const QMetaObject *, int> m_attachedPropertyIds;
};
m_superType(0), m_allocationSize(0), m_newFunc(0), m_baseMetaObject(0), m_attachedPropertiesFunc(0),
m_attachedPropertiesType(0), m_parserStatusCast(-1), m_propertyValueSourceCast(-1),
m_propertyValueInterceptorCast(-1), m_extFunc(0), m_extMetaObject(0), m_index(-1), m_customParser(0),
- m_isSetup(false), m_haveSuperType(false)
+ m_isSetup(false), m_isEnumSetup(false), m_haveSuperType(false)
{
}
bool QDeclarativeType::availableInVersion(int vmajor, int vminor) const
{
+ Q_ASSERT(vmajor >= 0 && vminor >= 0);
return vmajor == d->m_version_maj && vminor >= d->m_version_min;
}
bool QDeclarativeType::availableInVersion(const QByteArray &module, int vmajor, int vminor) const
{
+ Q_ASSERT(vmajor >= 0 && vminor >= 0);
return module == d->m_module && vmajor == d->m_version_maj && vminor >= d->m_version_min;
}
lock.unlock();
}
+void QDeclarativeTypePrivate::initEnums() const
+{
+ if (m_isEnumSetup) return;
+
+ init();
+
+ QWriteLocker lock(metaTypeDataLock());
+ if (m_isEnumSetup) return;
+
+ const QMetaObject *metaObject = m_baseMetaObject;
+ for (int ii = 0; ii < metaObject->enumeratorCount(); ++ii) {
+
+ QMetaEnum e = metaObject->enumerator(ii);
+
+ for (int jj = 0; jj < e.keyCount(); ++jj)
+ m_enums.insert(QString::fromUtf8(e.key(jj)), e.value(jj));
+ }
+
+ m_isEnumSetup = true;
+}
+
QByteArray QDeclarativeType::typeName() const
{
if (d->m_baseMetaObject)
return QByteArray();
}
+const QString &QDeclarativeType::elementName() const
+{
+ if (d->m_elementName.isEmpty()) {
+ QByteArray n = qmlTypeName();
+ int idx = n.lastIndexOf('/');
+ d->m_elementName = QString::fromUtf8(n.mid(idx + 1));
+ }
+ return d->m_elementName;
+}
+
QByteArray QDeclarativeType::qmlTypeName() const
{
return d->m_name;
return d->m_index;
}
+int QDeclarativeType::enumValue(const QHashedStringRef &name) const
+{
+ d->initEnums();
+
+ int *rv = d->m_enums.value(name);
+ return rv?*rv:-1;
+}
+
+int QDeclarativeType::enumValue(const QHashedV8String &name) const
+{
+ d->initEnums();
+
+ int *rv = d->m_enums.value(name);
+ return rv?*rv:-1;
+}
+
+QDeclarativeTypeModule::QDeclarativeTypeModule()
+: d(new QDeclarativeTypeModulePrivate)
+{
+}
+
+QDeclarativeTypeModule::~QDeclarativeTypeModule()
+{
+ delete d; d = 0;
+}
+
+QByteArray QDeclarativeTypeModule::module() const
+{
+ return d->uri.uri;
+}
+
+int QDeclarativeTypeModule::majorVersion() const
+{
+ return d->uri.majorVersion;
+}
+
+int QDeclarativeTypeModule::minimumMinorVersion() const
+{
+ return d->minMinorVersion;
+}
+
+int QDeclarativeTypeModule::maximumMinorVersion() const
+{
+ return d->maxMinorVersion;
+}
+
+void QDeclarativeTypeModulePrivate::add(QDeclarativeType *type)
+{
+ types << type;
+
+ minMinorVersion = qMin(minMinorVersion, type->minorVersion());
+ maxMinorVersion = qMax(maxMinorVersion, type->minorVersion());
+
+ QList<QDeclarativeType *> &list = typeHash[type->elementName()];
+ for (int ii = 0; ii < list.count(); ++ii) {
+ if (list.at(ii)->minorVersion() < type->minorVersion()) {
+ list.insert(ii, type);
+ return;
+ }
+ }
+ list.append(type);
+}
+
+QList<QDeclarativeType *> QDeclarativeTypeModule::types()
+{
+ QList<QDeclarativeType *> rv;
+ QReadLocker lock(metaTypeDataLock());
+ rv = d->types;
+ return rv;
+}
+
+QList<QDeclarativeType *> QDeclarativeTypeModule::type(const QString &name)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QList<QDeclarativeType *> rv;
+ for (int ii = 0; ii < d->types.count(); ++ii) {
+ if (d->types.at(ii)->elementName() == name)
+ rv << d->types.at(ii);
+ }
+ return rv;
+}
+
+QDeclarativeType *QDeclarativeTypeModule::type(const QHashedStringRef &name, int minor)
+{
+ QReadLocker lock(metaTypeDataLock());
+
+ QList<QDeclarativeType *> *types = d->typeHash.value(name);
+ if (!types) return 0;
+
+ for (int ii = 0; ii < types->count(); ++ii)
+ if (types->at(ii)->minorVersion() <= minor)
+ return types->at(ii);
+
+ return 0;
+}
+
+QDeclarativeType *QDeclarativeTypeModule::type(const QHashedV8String &name, int minor)
+{
+ QReadLocker lock(metaTypeDataLock());
+
+ QList<QDeclarativeType *> *types = d->typeHash.value(name);
+ if (!types) return 0;
+
+ for (int ii = 0; ii < types->count(); ++ii)
+ if (types->at(ii)->minorVersion() <= minor)
+ return types->at(ii);
+
+ return 0;
+}
+
+
+QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion()
+: m_module(0), m_minor(0)
+{
+}
+
+QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(QDeclarativeTypeModule *module, int minor)
+: m_module(module), m_minor(minor)
+{
+ Q_ASSERT(m_module);
+ Q_ASSERT(m_minor >= 0);
+}
+
+QDeclarativeTypeModuleVersion::QDeclarativeTypeModuleVersion(const QDeclarativeTypeModuleVersion &o)
+: m_module(o.m_module), m_minor(o.m_minor)
+{
+}
+
+QDeclarativeTypeModuleVersion &QDeclarativeTypeModuleVersion::operator=(const QDeclarativeTypeModuleVersion &o)
+{
+ m_module = o.m_module;
+ m_minor = o.m_minor;
+ return *this;
+}
+
+QDeclarativeTypeModule *QDeclarativeTypeModuleVersion::module() const
+{
+ return m_module;
+}
+
+int QDeclarativeTypeModuleVersion::minorVersion() const
+{
+ return m_minor;
+}
+
+QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedStringRef &name) const
+{
+ if (m_module) return m_module->type(name, m_minor);
+ else return 0;
+}
+
+QDeclarativeType *QDeclarativeTypeModuleVersion::type(const QHashedV8String &name) const
+{
+ if (m_module) return m_module->type(name, m_minor);
+ else return 0;
+}
+
+
int registerAutoParentFunction(QDeclarativePrivate::RegisterAutoParent &autoparent)
{
QWriteLocker lock(metaTypeDataLock());
if (type.uri) {
QByteArray mod(type.uri);
- QPair<QByteArray,int> key(mod,type.versionMajor);
- QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(key);
- if (it == data->modules.end()) {
- // New module
- data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo(type.versionMajor,type.versionMinor));
- } else {
- if ((*it).vminor_max < type.versionMinor) {
- // Newer module
- data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo((*it).vmajor, (*it).vminor_min, type.versionMinor));
- } else if ((*it).vminor_min > type.versionMinor) {
- // Older module
- data->modules.insert(key, QDeclarativeMetaTypeData::ModuleInfo((*it).vmajor, type.versionMinor, (*it).vminor_min));
- }
+
+ QDeclarativeMetaTypeData::VersionedUri versionedUri(mod, type.versionMajor);
+ QDeclarativeTypeModule *module = data->uriToModule.value(versionedUri);
+ if (!module) {
+ module = new QDeclarativeTypeModule;
+ module->d->uri = versionedUri;
+ data->uriToModule.insert(versionedUri, module);
}
+ module->d->add(dtype);
}
return index;
}
/*
+ Returns true if a module \a uri of any version is installed.
+*/
+bool QDeclarativeMetaType::isAnyModule(const QByteArray &uri)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QDeclarativeMetaTypeData *data = metaTypeData();
+
+ for (QDeclarativeMetaTypeData::TypeModules::ConstIterator iter = data->uriToModule.begin();
+ iter != data->uriToModule.end(); ++iter) {
+ if ((*iter)->module() == uri)
+ return true;
+ }
+
+ return false;
+}
+
+/*
Returns true if any type or API has been registered for the given \a module with at least
versionMajor.versionMinor, or if types have been registered for \a module with at most
versionMajor.versionMinor.
*/
bool QDeclarativeMetaType::isModule(const QByteArray &module, int versionMajor, int versionMinor)
{
+ Q_ASSERT(versionMajor >= 0 && versionMinor >= 0);
+ QReadLocker lock(metaTypeDataLock());
+
QDeclarativeMetaTypeData *data = metaTypeData();
// first, check Types
- QDeclarativeMetaTypeData::ModuleInfoHash::Iterator it = data->modules.find(QPair<QByteArray,int>(module,versionMajor));
- if (it != data->modules.end()) {
- if (((*it).vminor_max >= versionMinor && (*it).vminor_min <= versionMinor))
- return true;
- }
+ QDeclarativeTypeModule *tm =
+ data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(module, versionMajor));
+ if (tm && tm->minimumMinorVersion() <= versionMinor && tm->maximumMinorVersion() >= versionMinor)
+ return true;
// then, check ModuleApis
foreach (const QDeclarativeMetaType::ModuleApi &mApi, data->moduleApis.value(module).moduleApis) {
- if (mApi.major == versionMajor && mApi.minor == versionMinor) {
+ if (mApi.major == versionMajor && mApi.minor == versionMinor) // XXX is this correct?
return true;
- }
}
return false;
}
+QDeclarativeTypeModule *QDeclarativeMetaType::typeModule(const QByteArray &uri, int majorVersion)
+{
+ QReadLocker lock(metaTypeDataLock());
+ QDeclarativeMetaTypeData *data = metaTypeData();
+ return data->uriToModule.value(QDeclarativeMetaTypeData::VersionedUri(uri, majorVersion));
+}
+
QList<QDeclarativePrivate::AutoParentFunction> QDeclarativeMetaType::parentFunctions()
{
QReadLocker lock(metaTypeDataLock());
*/
QDeclarativeType *QDeclarativeMetaType::qmlType(const QByteArray &name, int version_major, int version_minor)
{
+ Q_ASSERT(version_major >= 0 && version_minor >= 0);
QReadLocker lock(metaTypeDataLock());
QDeclarativeMetaTypeData *data = metaTypeData();
*/
QDeclarativeType *QDeclarativeMetaType::qmlType(const QMetaObject *metaObject, const QByteArray &module, int version_major, int version_minor)
{
+ Q_ASSERT(version_major >= 0 && version_minor >= 0);
QReadLocker lock(metaTypeDataLock());
QDeclarativeMetaTypeData *data = metaTypeData();
class QDeclarativeType;
class QDeclarativeCustomParser;
class QDeclarativeTypePrivate;
+class QDeclarativeTypeModule;
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeMetaType
{
static void registerCustomStringConverter(int, StringConverter);
static StringConverter customStringConverter(int);
- static bool isAnyModule(const QByteArray &module);
+ static bool isAnyModule(const QByteArray &uri);
static bool isModule(const QByteArray &module, int versionMajor, int versionMinor);
+ static QDeclarativeTypeModule *typeModule(const QByteArray &uri, int majorVersion);
static QList<QDeclarativePrivate::AutoParentFunction> parentFunctions();
static ModuleApi moduleApi(const QByteArray &, int, int);
};
+class QHashedStringRef;
+class QHashedV8String;
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeType
{
public:
QByteArray typeName() const;
QByteArray qmlTypeName() const;
+ const QString &elementName() const;
QByteArray module() const;
int majorVersion() const;
int index() const;
+ int enumValue(const QHashedStringRef &) const;
+ int enumValue(const QHashedV8String &) const;
private:
QDeclarativeType *superType() const;
friend class QDeclarativeTypePrivate;
QDeclarativeTypePrivate *d;
};
+class QDeclarativeTypeModulePrivate;
+class QDeclarativeTypeModule
+{
+public:
+ QByteArray module() const;
+ int majorVersion() const;
+
+ int minimumMinorVersion() const;
+ int maximumMinorVersion() const;
+
+ QList<QDeclarativeType *> types();
+ QList<QDeclarativeType *> type(const QString &);
+
+ QDeclarativeType *type(const QHashedStringRef &, int);
+ QDeclarativeType *type(const QHashedV8String &, int);
+
+private:
+ friend int registerType(const QDeclarativePrivate::RegisterType &);
+ QDeclarativeTypeModule();
+ ~QDeclarativeTypeModule();
+ QDeclarativeTypeModulePrivate *d;
+};
+
+class QDeclarativeTypeModuleVersion
+{
+public:
+ QDeclarativeTypeModuleVersion();
+ QDeclarativeTypeModuleVersion(QDeclarativeTypeModule *, int);
+ QDeclarativeTypeModuleVersion(const QDeclarativeTypeModuleVersion &);
+ QDeclarativeTypeModuleVersion &operator=(const QDeclarativeTypeModuleVersion &);
+
+ QDeclarativeTypeModule *module() const;
+ int minorVersion() const;
+
+ QDeclarativeType *type(const QHashedStringRef &) const;
+ QDeclarativeType *type(const QHashedV8String &) const;
+
+private:
+ QDeclarativeTypeModule *m_module;
+ int m_minor;
+};
+
QDeclarativeMetaType::ModuleApi::ModuleApi()
-// : major(0), minor(0), script(0), qobject(0)
{
major = 0;
minor = 0;
for (int ii = 0; ii < path.count() - 1; ++ii) {
const QString &pathName = path.at(ii);
- if (QDeclarativeTypeNameCache::Data *data = typeNameCache?typeNameCache->data(pathName):0) {
- if (data->type) {
- QDeclarativeAttachedPropertiesFunc func = data->type->attachedPropertiesFunction();
- if (!func) return; // Not an attachable type
-
- currentObject = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), currentObject);
- if (!currentObject) return; // Something is broken with the attachable type
- } else {
- Q_ASSERT(data->typeNamespace);
- if ((ii + 1) == path.count()) return; // No type following the namespace
+ if (typeNameCache) {
+ QDeclarativeTypeNameCache::Result r = typeNameCache->query(pathName);
+ if (r.isValid()) {
+ if (r.type) {
+ QDeclarativeAttachedPropertiesFunc func = r.type->attachedPropertiesFunction();
+ if (!func) return; // Not an attachable type
+
+ currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject);
+ if (!currentObject) return; // Something is broken with the attachable type
+ } else if (r.importNamespace) {
+ if ((ii + 1) == path.count()) return; // No type following the namespace
+
+ ++ii; r = typeNameCache->query(path.at(ii), r.importNamespace);
+ if (!r.type) return; // Invalid type in namespace
- ++ii; data = data->typeNamespace->data(path.at(ii));
- if (!data || !data->type) return; // Invalid type in namespace
+ QDeclarativeAttachedPropertiesFunc func = r.type->attachedPropertiesFunction();
+ if (!func) return; // Not an attachable type
- QDeclarativeAttachedPropertiesFunc func = data->type->attachedPropertiesFunction();
- if (!func) return; // Not an attachable type
+ currentObject = qmlAttachedPropertiesObjectById(r.type->attachedPropertiesId(), currentObject);
+ if (!currentObject) return; // Something is broken with the attachable type
- currentObject = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), currentObject);
- if (!currentObject) return; // Something is broken with the attachable type
+ } else if (r.scriptIndex != -1) {
+ return; // Not a type
+ } else {
+ Q_ASSERT(!"Unreachable");
+ }
+ continue;
}
- } else {
- QDeclarativePropertyCache::Data local;
- QDeclarativePropertyCache::Data *property =
- QDeclarativePropertyCache::property(engine, obj, pathName, local);
+ }
- if (!property) return; // Not a property
- if (property->isFunction())
- return; // Not an object property
+ QDeclarativePropertyCache::Data local;
+ QDeclarativePropertyCache::Data *property =
+ QDeclarativePropertyCache::property(engine, obj, pathName, local);
- if (ii == (path.count() - 2) && QDeclarativeValueTypeFactory::isValueType(property->propType)) {
- // We're now at a value type property. We can use a global valuetypes array as we
- // never actually use the objects, just look up their properties.
- QObject *typeObject = (*qmlValueTypes())[property->propType];
- if (!typeObject) return; // Not a value type
+ if (!property) return; // Not a property
+ if (property->isFunction())
+ return; // Not an object property
- int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData());
- if (idx == -1) return; // Value type property does not exist
+ if (ii == (path.count() - 2) && QDeclarativeValueTypeFactory::isValueType(property->propType)) {
+ // We're now at a value type property. We can use a global valuetypes array as we
+ // never actually use the objects, just look up their properties.
+ QObject *typeObject = (*qmlValueTypes())[property->propType];
+ if (!typeObject) return; // Not a value type
- QMetaProperty vtProp = typeObject->metaObject()->property(idx);
+ int idx = typeObject->metaObject()->indexOfProperty(path.last().toUtf8().constData());
+ if (idx == -1) return; // Value type property does not exist
- object = currentObject;
- core = *property;
- valueType.flags = QDeclarativePropertyCache::Data::flagsForProperty(vtProp);
- valueType.valueTypeCoreIdx = idx;
- valueType.valueTypePropType = vtProp.userType();
+ QMetaProperty vtProp = typeObject->metaObject()->property(idx);
- return;
- } else {
- if (!property->isQObject())
- return; // Not an object property
+ object = currentObject;
+ core = *property;
+ valueType.flags = QDeclarativePropertyCache::Data::flagsForProperty(vtProp);
+ valueType.valueTypeCoreIdx = idx;
+ valueType.valueTypePropType = vtProp.userType();
- void *args[] = { ¤tObject, 0 };
- QMetaObject::metacall(currentObject, QMetaObject::ReadProperty, property->coreIndex, args);
- if (!currentObject) return; // No value
+ return;
+ } else {
+ if (!property->isQObject())
+ return; // Not an object property
+
+ void *args[] = { ¤tObject, 0 };
+ QMetaObject::metacall(currentObject, QMetaObject::ReadProperty, property->coreIndex, args);
+ if (!currentObject) return; // No value
- }
}
}
QT_BEGIN_NAMESPACE
QDeclarativeTypeNameCache::QDeclarativeTypeNameCache(QDeclarativeEngine *e)
-: QDeclarativeCleanup(e), engine(e), m_moduleApi(0)
+: QDeclarativeCleanup(e), engine(e)
{
}
void QDeclarativeTypeNameCache::clear()
{
- stringCache.clear();
- m_moduleApi = 0;
+ m_namedImports.clear();
+ m_anonymousImports.clear();
engine = 0;
}
-void QDeclarativeTypeNameCache::add(const QString &name, int importedScriptIndex)
+void QDeclarativeTypeNameCache::add(const QHashedString &name, int importedScriptIndex)
{
- if (stringCache.contains(name))
+ if (m_namedImports.contains(name))
return;
- Data data;
- data.importedScriptIndex = importedScriptIndex;
- stringCache.insert(name, data);
+ Import import;
+ import.scriptIndex = importedScriptIndex;
+ m_namedImports.insert(name, import);
}
-void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeType *type)
+QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedStringRef &name)
{
- if (stringCache.contains(name))
- return;
-
- Data data;
- data.type = type;
- stringCache.insert(name, data);
+ Import *i = m_namedImports.value(name);
+ if (i) {
+ if (i->scriptIndex != -1)
+ return Result(i->scriptIndex);
+ else
+ return Result((const void *)i);
+ }
+
+ for (int ii = 0; ii < m_anonymousImports.count(); ++ii) {
+ if (QDeclarativeType *type = m_anonymousImports.at(ii).type(name))
+ return Result(type);
+ }
+
+ return Result();
}
-void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeTypeNameCache *typeNamespace)
+QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedStringRef &name,
+ const void *importNamespace)
{
- if (stringCache.contains(name))
- return;
-
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ Q_ASSERT(importNamespace);
+ Import *i = (Import *)importNamespace;
+ Q_ASSERT(i->scriptIndex == -1);
+
+ for (int ii = 0; ii < i->modules.count(); ++ii) {
+ if (QDeclarativeType *type = i->modules.at(ii).type(name))
+ return Result(type);
+ }
+
+ return Result();
+}
- Data data;
- typeNamespace->addref();
- data.typeNamespace = typeNamespace;
- stringCache.insert(name, data);
+QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedV8String &name)
+{
+ Import *i = m_namedImports.value(name);
+ if (i) {
+ if (i->scriptIndex != -1)
+ return Result(i->scriptIndex);
+ else
+ return Result((const void *)i);
+ }
+
+ for (int ii = 0; ii < m_anonymousImports.count(); ++ii) {
+ if (QDeclarativeType *type = m_anonymousImports.at(ii).type(name))
+ return Result(type);
+ }
+
+ return Result();
}
-QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QString &id) const
+QDeclarativeTypeNameCache::Result QDeclarativeTypeNameCache::query(const QHashedV8String &name, const void *importNamespace)
{
- return stringCache.value(id);
+ Q_ASSERT(importNamespace);
+ Import *i = (Import *)importNamespace;
+ Q_ASSERT(i->scriptIndex == -1);
+
+ for (int ii = 0; ii < i->modules.count(); ++ii) {
+ if (QDeclarativeType *type = i->modules.at(ii).type(name))
+ return Result(type);
+ }
+
+ return Result();
}
-void QDeclarativeTypeNameCache::setModuleApi(QDeclarativeMetaType::ModuleApiInstance *api)
+QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi(const void *importNamespace)
{
- m_moduleApi = api;
+ Q_ASSERT(importNamespace);
+ Import *i = (Import *)importNamespace;
+ Q_ASSERT(i->scriptIndex == -1);
+
+ return i->moduleApi;
}
QT_END_NAMESPACE
#include <private/qhashedstring_p.h>
+#include <QtCore/qvector.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeType;
QDeclarativeTypeNameCache(QDeclarativeEngine *);
virtual ~QDeclarativeTypeNameCache();
- struct Data {
- inline Data();
- inline Data(const Data &);
- inline ~Data();
- inline Data &operator=(const Data &);
- QDeclarativeType *type;
- QDeclarativeTypeNameCache *typeNamespace;
- int importedScriptIndex;
- };
+ inline bool isEmpty() const;
- void add(const QString &, int);
- void add(const QString &, QDeclarativeType *);
- void add(const QString &, QDeclarativeTypeNameCache *);
+ void add(const QHashedString &, int);
- Data *data(const QString &) const;
- inline Data *data(const QHashedV8String &) const;
- inline bool isEmpty() const;
+ struct Result {
+ inline Result();
+ inline Result(const void *importNamespace);
+ inline Result(QDeclarativeType *type);
+ inline Result(int scriptIndex);
+ inline Result(const Result &);
+
+ inline bool isValid() const;
- inline QDeclarativeMetaType::ModuleApiInstance *moduleApi() const;
- void setModuleApi(QDeclarativeMetaType::ModuleApiInstance *);
+ QDeclarativeType *type;
+ const void *importNamespace;
+ int scriptIndex;
+ };
+ Result query(const QHashedStringRef &);
+ Result query(const QHashedStringRef &, const void *importNamespace);
+ Result query(const QHashedV8String &);
+ Result query(const QHashedV8String &, const void *importNamespace);
+ QDeclarativeMetaType::ModuleApiInstance *moduleApi(const void *importNamespace);
protected:
virtual void clear();
private:
- typedef QStringHash<Data> StringCache;
+ friend class QDeclarativeImports;
- StringCache stringCache;
+ struct Import {
+ inline Import();
+ // Imported module
+ QDeclarativeMetaType::ModuleApiInstance *moduleApi;
+ QVector<QDeclarativeTypeModuleVersion> modules;
+
+ // Or, imported script
+ int scriptIndex;
+ };
+
+ QStringHash<Import> m_namedImports;
+ QVector<QDeclarativeTypeModuleVersion> m_anonymousImports;
QDeclarativeEngine *engine;
- QDeclarativeMetaType::ModuleApiInstance *m_moduleApi;
};
-QDeclarativeTypeNameCache::Data::Data()
-: type(0), typeNamespace(0), importedScriptIndex(-1)
+QDeclarativeTypeNameCache::Result::Result()
+: type(0), importNamespace(0), scriptIndex(-1)
{
}
-QDeclarativeTypeNameCache::Data::~Data()
+QDeclarativeTypeNameCache::Result::Result(const void *importNamespace)
+: type(0), importNamespace(importNamespace), scriptIndex(-1)
{
- if (typeNamespace) typeNamespace->release();
}
-bool QDeclarativeTypeNameCache::isEmpty() const
+QDeclarativeTypeNameCache::Result::Result(QDeclarativeType *type)
+: type(type), importNamespace(0), scriptIndex(-1)
{
- return stringCache.isEmpty();
}
-QDeclarativeTypeNameCache::Data::Data(const QDeclarativeTypeNameCache::Data &o)
-: type(o.type), typeNamespace(o.typeNamespace), importedScriptIndex(o.importedScriptIndex)
+QDeclarativeTypeNameCache::Result::Result(int scriptIndex)
+: type(0), importNamespace(0), scriptIndex(scriptIndex)
{
- if (typeNamespace) typeNamespace->addref();
}
-QDeclarativeTypeNameCache::Data &QDeclarativeTypeNameCache::Data::operator=(const QDeclarativeTypeNameCache::Data &o)
+QDeclarativeTypeNameCache::Result::Result(const Result &o)
+: type(o.type), importNamespace(o.importNamespace), scriptIndex(o.scriptIndex)
{
- if (o.typeNamespace) o.typeNamespace->addref();
- if (typeNamespace) typeNamespace->release();
- type = o.type;
- typeNamespace = o.typeNamespace;
- importedScriptIndex = o.importedScriptIndex;
- return *this;
}
-QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi() const
+bool QDeclarativeTypeNameCache::Result::isValid() const
{
- return m_moduleApi;
+ return type || importNamespace || scriptIndex != -1;
}
-QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QHashedV8String &name) const
+QDeclarativeTypeNameCache::Import::Import()
+: scriptIndex(-1)
+{
+}
+
+bool QDeclarativeTypeNameCache::isEmpty() const
{
- return stringCache.value(name);
+ return m_namedImports.isEmpty() && m_anonymousImports.isEmpty();
}
QT_END_NAMESPACE
if (obj == m_expression->component)
code->storage = IR::Name::RootStorage;
_expr.code = code;
- } else if (QDeclarativeTypeNameCache::Data *typeNameData = m_expression->importCache->data(name)) {
- if (typeNameData->importedScriptIndex != -1) {
- // We don't support invoking imported scripts
- } else if (typeNameData->type) {
- _expr.code = _block->ATTACH_TYPE(name, typeNameData->type, IR::Name::ScopeStorage, line, column);
- } else if (typeNameData->typeNamespace) {
- // We don't support namespaces
- } else {
- Q_ASSERT(!"Unreachable");
- }
} else {
- bool found = false;
- if (m_expression->context != m_expression->component) {
- // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
- QDeclarativePropertyCache *cache = m_expression->context->synthCache;
- const QMetaObject *metaObject = m_expression->context->metaObject();
- if (!cache) cache = m_engine->cache(metaObject);
+ QDeclarativeTypeNameCache::Result r = m_expression->importCache->query(name);
+ if (r.isValid()) {
+ if (r.type) {
+ _expr.code = _block->ATTACH_TYPE(name, r.type, IR::Name::ScopeStorage, line, column);
+ }
+ // We don't support anything else
+ } else {
+ bool found = false;
+
+ if (m_expression->context != m_expression->component) {
+ // RootStorage is more efficient than ScopeStorage, so prefer that if they are the same
+ QDeclarativePropertyCache *cache = m_expression->context->synthCache;
+ const QMetaObject *metaObject = m_expression->context->metaObject();
+ if (!cache) cache = m_engine->cache(metaObject);
- QDeclarativePropertyCache::Data *data = cache->property(name);
+ QDeclarativePropertyCache::Data *data = cache->property(name);
+
+ if (data && data->revision != 0) {
+ if (qmlVerboseCompiler())
+ qWarning() << "*** versioned symbol:" << name;
+ discard();
+ return false;
+ }
- if (data && data->revision != 0) {
- if (qmlVerboseCompiler())
- qWarning() << "*** versioned symbol:" << name;
- discard();
- return false;
+ if (data && !data->isFunction()) {
+ IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
+ _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column);
+ found = true;
+ }
}
- if (data && !data->isFunction()) {
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
- _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::ScopeStorage, line, column);
- found = true;
- }
- }
+ if (!found) {
+ QDeclarativePropertyCache *cache = m_expression->component->synthCache;
+ const QMetaObject *metaObject = m_expression->component->metaObject();
+ if (!cache) cache = m_engine->cache(metaObject);
- if (!found) {
- QDeclarativePropertyCache *cache = m_expression->component->synthCache;
- const QMetaObject *metaObject = m_expression->component->metaObject();
- if (!cache) cache = m_engine->cache(metaObject);
+ QDeclarativePropertyCache::Data *data = cache->property(name);
- QDeclarativePropertyCache::Data *data = cache->property(name);
+ if (data && data->revision != 0) {
+ if (qmlVerboseCompiler())
+ qWarning() << "*** versioned symbol:" << name;
+ discard();
+ return false;
+ }
- if (data && data->revision != 0) {
- if (qmlVerboseCompiler())
- qWarning() << "*** versioned symbol:" << name;
- discard();
- return false;
+ if (data && !data->isFunction()) {
+ IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
+ _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column);
+ found = true;
+ }
}
- if (data && !data->isFunction()) {
- IR::Type irType = irTypeFromVariantType(data->propType, m_engine, metaObject);
- _expr.code = _block->SYMBOL(irType, name, metaObject, data->coreIndex, IR::Name::RootStorage, line, column);
- found = true;
- }
+ if (!found && qmlVerboseCompiler())
+ qWarning() << "*** unknown symbol:" << name;
}
-
- if (!found && qmlVerboseCompiler())
- qWarning() << "*** unknown symbol:" << name;
}
if (_expr.code && _expr.hint == ExprResult::cx) {
if (context->imports && QV8Engine::startsWithUpper(property)) {
// Search for attached properties, enums and imported scripts
- QDeclarativeTypeNameCache::Data *data = context->imports->data(propertystring);
-
- if (data) {
- if (data->importedScriptIndex != -1) {
- int index = data->importedScriptIndex;
+ QDeclarativeTypeNameCache::Result r = context->imports->query(propertystring);
+
+ if (r.isValid()) {
+ if (r.scriptIndex != -1) {
+ int index = r.scriptIndex;
if (index < context->importedScripts.count())
return context->importedScripts.at(index);
else
return v8::Undefined();
- } else if (data->type) {
- return engine->typeWrapper()->newObject(scopeObject, data->type);
- } else if (data->typeNamespace) {
- return engine->typeWrapper()->newObject(scopeObject, data->typeNamespace);
+ } else if (r.type) {
+ return engine->typeWrapper()->newObject(scopeObject, r.type);
+ } else if (r.importNamespace) {
+ return engine->typeWrapper()->newObject(scopeObject, context->imports, r.importNamespace);
}
Q_ASSERT(!"Unreachable");
}
if (QV8Engine::startsWithUpper(property)) {
// Check for attached properties
QDeclarativeContextData *context = v8engine->callingContext();
- QDeclarativeTypeNameCache::Data *data =
- context && (context->imports)?context->imports->data(propertystring):0;
-
- if (data) {
- if (data->type) {
- return v8engine->typeWrapper()->newObject(object, data->type, QV8TypeWrapper::ExcludeEnums);
- } else if (data->typeNamespace) {
- return v8engine->typeWrapper()->newObject(object, data->typeNamespace, QV8TypeWrapper::ExcludeEnums);
+
+ if (context && context->imports) {
+ QDeclarativeTypeNameCache::Result r = context->imports->query(propertystring);
+
+ if (r.isValid()) {
+ if (r.scriptIndex != -1) {
+ return v8::Undefined();
+ } else if (r.type) {
+ return v8engine->typeWrapper()->newObject(object, r.type, QV8TypeWrapper::ExcludeEnums);
+ } else if (r.importNamespace) {
+ return v8engine->typeWrapper()->newObject(object, context->imports, r.importNamespace,
+ QV8TypeWrapper::ExcludeEnums);
+ }
+ Q_ASSERT(!"Unreachable");
}
}
}
QV8TypeWrapper::TypeNameMode mode;
QDeclarativeGuard<QObject> object;
+
QDeclarativeType *type;
QDeclarativeTypeNameCache *typeNamespace;
+ const void *importNamespace;
};
QV8TypeResource::QV8TypeResource(QV8Engine *engine)
-: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0)
+: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0), importNamespace(0)
{
}
m_constructor = qPersistentNew<v8::Function>(ft->GetFunction());
}
+// Returns a type wrapper for type t on o. This allows access of enums, and attached properties.
v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode)
{
Q_ASSERT(t);
return rv;
}
-v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, TypeNameMode mode)
+// Returns a type wrapper for importNamespace (of t) on o. This allows nested resolution of a type in a
+// namespace.
+v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t,
+ const void *importNamespace, TypeNameMode mode)
{
Q_ASSERT(t);
+ Q_ASSERT(importNamespace);
// XXX NewInstance() should be optimized
v8::Local<v8::Object> rv = m_constructor->NewInstance();
QV8TypeResource *r = new QV8TypeResource(m_engine);
t->addref();
- r->mode = mode; r->object = o; r->typeNamespace = t;
+ r->mode = mode; r->object = o; r->typeNamespace = t; r->importNamespace = importNamespace;
rv->SetExternalResource(r);
return rv;
}
QDeclarativeType *type = resource->type;
if (QV8Engine::startsWithUpper(property)) {
- if (resource->mode == IncludeEnums) {
- QString name = v8engine->toString(property);
-
- // ### Optimize
- QByteArray enumName = name.toUtf8();
- const QMetaObject *metaObject = type->baseMetaObject();
- for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
- QMetaEnum e = metaObject->enumerator(ii);
- int value = e.keyToValue(enumName.constData());
- if (value != -1)
- return v8::Integer::New(value);
- }
- }
+ int value = type->enumValue(propertystring);
+ if (-1 != value)
+ return v8::Integer::New(value);
// Fall through to return empty handle
// Fall through to return empty handle
} else if (resource->typeNamespace) {
+ Q_ASSERT(resource->importNamespace);
+ QDeclarativeTypeNameCache::Result r = resource->typeNamespace->query(propertystring,
+ resource->importNamespace);
- QDeclarativeTypeNameCache *typeNamespace = resource->typeNamespace;
- QDeclarativeTypeNameCache::Data *d = typeNamespace->data(propertystring);
- Q_ASSERT(!d || !d->typeNamespace); // Nested namespaces not supported
+ if (r.isValid()) {
+ Q_ASSERT(r.type);
- if (d && d->type) {
- return v8engine->typeWrapper()->newObject(object, d->type, resource->mode);
- } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = typeNamespace->moduleApi()) {
+ return v8engine->typeWrapper()->newObject(object, r.type, resource->mode);
+ } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = resource->typeNamespace->moduleApi(resource->importNamespace)) {
if (moduleApi->scriptCallback) {
moduleApi->scriptApi = moduleApi->scriptCallback(v8engine->engine(), v8engine->engine());
enum TypeNameMode { IncludeEnums, ExcludeEnums };
v8::Local<v8::Object> newObject(QObject *, QDeclarativeType *, TypeNameMode = IncludeEnums);
- v8::Local<v8::Object> newObject(QObject *, QDeclarativeTypeNameCache *, TypeNameMode = IncludeEnums);
+ v8::Local<v8::Object> newObject(QObject *, QDeclarativeTypeNameCache *, const void *,
+ TypeNameMode = IncludeEnums);
private:
static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
}
QRegExp quick1("^\\s*import +QtQuick +1\\.");
+ QRegExp quick2("^\\s*import +QtQuick +2\\.");
QRegExp qt47("^\\s*import +Qt +4\\.7");
QString envToWrite;
QTextStream stream(&f);
bool codeFound= false;
- while (!codeFound && envToWrite.isEmpty()) {
+ while (!codeFound) {
QString line = stream.readLine();
if (line.contains("{"))
codeFound = true;
- if (quick1.indexIn(line) >= 0) {
+ if (envToWrite.isEmpty() && quick1.indexIn(line) >= 0) {
envToWrite = QLatin1String("quick1");
compat = QLatin1String("QtQuick 1.0");
- } else if (qt47.indexIn(line) >= 0) {
+ } else if (envToWrite.isEmpty() && qt47.indexIn(line) >= 0) {
envToWrite = QLatin1String("qt");
compat = QLatin1String("Qt 4.7");
+ } else if (quick2.indexIn(line) >= 0) {
+ envToWrite.clear();
+ compat.clear();
+ break;
}
}