forked from qt-creator/qt-creator
QmlJS: Prepare qmldump for multiply exported C++ objects.
In the future, builtin objects are going to be exported in Qt 4.7 and QtQuick 1.0. Reviewed-by: Roberto Raggi
This commit is contained in:
@@ -15,15 +15,15 @@
|
|||||||
#include <QtDeclarative/private/qdeclarativeopenmetaobject_p.h>
|
#include <QtDeclarative/private/qdeclarativeopenmetaobject_p.h>
|
||||||
#include <QtDeclarative/QDeclarativeView>
|
#include <QtDeclarative/QDeclarativeView>
|
||||||
|
|
||||||
static QHash<QByteArray, const QDeclarativeType *> qmlTypeByCppName;
|
static QHash<QByteArray, QList<const QDeclarativeType *> > qmlTypesByCppName;
|
||||||
static QHash<QByteArray, QByteArray> cppToQml;
|
static QHash<QByteArray, QByteArray> cppToId;
|
||||||
|
|
||||||
QByteArray convertToQmlType(const QByteArray &cppName)
|
QByteArray convertToId(const QByteArray &cppName)
|
||||||
{
|
{
|
||||||
QByteArray qmlName = cppToQml.value(cppName, cppName);
|
QByteArray idName = cppToId.value(cppName, cppName);
|
||||||
qmlName.replace("::", ".");
|
idName.replace("::", ".");
|
||||||
qmlName.replace("/", ".");
|
idName.replace("/", ".");
|
||||||
return qmlName;
|
return idName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void erasure(QByteArray *typeName, bool *isList, bool *isPointer)
|
void erasure(QByteArray *typeName, bool *isList, bool *isPointer)
|
||||||
@@ -41,7 +41,7 @@ void erasure(QByteArray *typeName, bool *isList, bool *isPointer)
|
|||||||
erasure(typeName, isList, isPointer);
|
erasure(typeName, isList, isPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
*typeName = convertToQmlType(*typeName);
|
*typeName = convertToId(*typeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void processMetaObject(const QMetaObject *meta, QSet<const QMetaObject *> *metas)
|
void processMetaObject(const QMetaObject *meta, QSet<const QMetaObject *> *metas)
|
||||||
@@ -132,7 +132,7 @@ void dump(const QMetaMethod &meth, QXmlStreamWriter *xml)
|
|||||||
|
|
||||||
attributes.append(QXmlStreamAttribute("name", name));
|
attributes.append(QXmlStreamAttribute("name", name));
|
||||||
|
|
||||||
const QString typeName = convertToQmlType(meth.typeName());
|
const QString typeName = convertToId(meth.typeName());
|
||||||
if (! typeName.isEmpty())
|
if (! typeName.isEmpty())
|
||||||
attributes.append(QXmlStreamAttribute("type", typeName));
|
attributes.append(QXmlStreamAttribute("type", typeName));
|
||||||
|
|
||||||
@@ -187,16 +187,12 @@ public:
|
|||||||
|
|
||||||
void dump(const QMetaObject *meta, QXmlStreamWriter *xml)
|
void dump(const QMetaObject *meta, QXmlStreamWriter *xml)
|
||||||
{
|
{
|
||||||
QByteArray qmlTypeName = convertToQmlType(meta->className());
|
QByteArray id = convertToId(meta->className());
|
||||||
|
|
||||||
xml->writeStartElement("type");
|
xml->writeStartElement("type");
|
||||||
|
|
||||||
QXmlStreamAttributes attributes;
|
QXmlStreamAttributes attributes;
|
||||||
attributes.append(QXmlStreamAttribute("name", qmlTypeName));
|
attributes.append(QXmlStreamAttribute("name", id));
|
||||||
|
|
||||||
if (const QDeclarativeType *qmlTy = qmlTypeByCppName.value(meta->className())) {
|
|
||||||
attributes.append(QXmlStreamAttribute("version", QString("%1.%2").arg(qmlTy->majorVersion()).arg(qmlTy->minorVersion())));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int index = meta->classInfoCount() - 1 ; index >= 0 ; --index) {
|
for (int index = meta->classInfoCount() - 1 ; index >= 0 ; --index) {
|
||||||
QMetaClassInfo classInfo = meta->classInfo(index);
|
QMetaClassInfo classInfo = meta->classInfo(index);
|
||||||
@@ -206,16 +202,31 @@ void dump(const QMetaObject *meta, QXmlStreamWriter *xml)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString version;
|
|
||||||
|
|
||||||
if (meta->superClass())
|
if (meta->superClass())
|
||||||
attributes.append(QXmlStreamAttribute("extends", convertToQmlType(meta->superClass()->className())));
|
attributes.append(QXmlStreamAttribute("extends", convertToId(meta->superClass()->className())));
|
||||||
|
|
||||||
if (! version.isEmpty())
|
|
||||||
attributes.append(QXmlStreamAttribute("version", version));
|
|
||||||
|
|
||||||
xml->writeAttributes(attributes);
|
xml->writeAttributes(attributes);
|
||||||
|
|
||||||
|
QList<const QDeclarativeType *> qmlTypes = qmlTypesByCppName.value(id);
|
||||||
|
if (!qmlTypes.isEmpty()) {
|
||||||
|
xml->writeStartElement("exports");
|
||||||
|
foreach (const QDeclarativeType *qmlTy, qmlTypes) {
|
||||||
|
QXmlStreamAttributes moduleAttributes;
|
||||||
|
const QString qmlTyName = qmlTy->qmlTypeName();
|
||||||
|
int slashIdx = qmlTyName.lastIndexOf(QLatin1Char('/'));
|
||||||
|
if (slashIdx == -1)
|
||||||
|
continue;
|
||||||
|
const QString moduleName = qmlTyName.left(slashIdx);
|
||||||
|
const QString typeName = qmlTyName.mid(slashIdx + 1);
|
||||||
|
moduleAttributes.append(QXmlStreamAttribute("module", moduleName));
|
||||||
|
moduleAttributes.append(QXmlStreamAttribute("version", QString("%1.%2").arg(qmlTy->majorVersion()).arg(qmlTy->minorVersion())));
|
||||||
|
moduleAttributes.append(QXmlStreamAttribute("type", typeName));
|
||||||
|
xml->writeEmptyElement("export");
|
||||||
|
xml->writeAttributes(moduleAttributes);
|
||||||
|
}
|
||||||
|
xml->writeEndElement();
|
||||||
|
}
|
||||||
|
|
||||||
for (int index = meta->enumeratorOffset(); index < meta->enumeratorCount(); ++index)
|
for (int index = meta->enumeratorOffset(); index < meta->enumeratorCount(); ++index)
|
||||||
dump(meta->enumerator(index), xml);
|
dump(meta->enumerator(index), xml);
|
||||||
|
|
||||||
@@ -234,7 +245,7 @@ void writeEasingCurve(QXmlStreamWriter *xml)
|
|||||||
{
|
{
|
||||||
QXmlStreamAttributes attributes;
|
QXmlStreamAttributes attributes;
|
||||||
attributes.append(QXmlStreamAttribute("name", "QEasingCurve"));
|
attributes.append(QXmlStreamAttribute("name", "QEasingCurve"));
|
||||||
attributes.append(QXmlStreamAttribute("extends", "Qt.Easing"));
|
attributes.append(QXmlStreamAttribute("extends", "QDeclarativeEasingValueType"));
|
||||||
xml->writeAttributes(attributes);
|
xml->writeAttributes(attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,8 +273,22 @@ int main(int argc, char *argv[])
|
|||||||
if (!pluginImportPath.isEmpty())
|
if (!pluginImportPath.isEmpty())
|
||||||
engine->addImportPath(pluginImportPath);
|
engine->addImportPath(pluginImportPath);
|
||||||
|
|
||||||
|
bool hasQtQuickModule = false;
|
||||||
|
{
|
||||||
|
QByteArray code = "import QtQuick 1.0; Item {}";
|
||||||
|
QDeclarativeComponent c(engine);
|
||||||
|
c.setData(code, QUrl("xxx"));
|
||||||
|
c.create();
|
||||||
|
if (c.errors().isEmpty()) {
|
||||||
|
hasQtQuickModule = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QByteArray importCode;
|
QByteArray importCode;
|
||||||
importCode += "import Qt 4.7;\n";
|
importCode += "import Qt 4.7;\n";
|
||||||
|
if (hasQtQuickModule) {
|
||||||
|
importCode += "import QtQuick 1.0;\n";
|
||||||
|
}
|
||||||
if (pluginImportName.isEmpty()) {
|
if (pluginImportName.isEmpty()) {
|
||||||
importCode += "import Qt.labs.particles 4.7;\n";
|
importCode += "import Qt.labs.particles 4.7;\n";
|
||||||
importCode += "import Qt.labs.gestures 4.7;\n";
|
importCode += "import Qt.labs.gestures 4.7;\n";
|
||||||
@@ -284,25 +309,25 @@ int main(int argc, char *argv[])
|
|||||||
qDebug() << c.errorString();
|
qDebug() << c.errorString();
|
||||||
}
|
}
|
||||||
|
|
||||||
cppToQml.insert("QString", "string");
|
cppToId.insert("QString", "string");
|
||||||
cppToQml.insert("QDeclarativeEasingValueType::Type", "Type");
|
cppToId.insert("QDeclarativeEasingValueType::Type", "Type");
|
||||||
|
|
||||||
QSet<const QMetaObject *> metas;
|
QSet<const QMetaObject *> metas;
|
||||||
|
|
||||||
metas.insert(FriendlyQObject::qtMeta());
|
metas.insert(FriendlyQObject::qtMeta());
|
||||||
|
|
||||||
QMultiHash<QByteArray, QByteArray> extensions;
|
QHash<QByteArray, QSet<QByteArray> > extensions;
|
||||||
foreach (const QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) {
|
foreach (const QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) {
|
||||||
qmlTypeByCppName.insert(ty->metaObject()->className(), ty);
|
qmlTypesByCppName[ty->metaObject()->className()].append(ty);
|
||||||
if (ty->isExtendedType()) {
|
if (ty->isExtendedType()) {
|
||||||
extensions.insert(ty->typeName(), ty->metaObject()->className());
|
extensions[ty->typeName()].insert(ty->metaObject()->className());
|
||||||
} else {
|
} else {
|
||||||
cppToQml.insert(ty->metaObject()->className(), ty->qmlTypeName());
|
cppToId.insert(ty->metaObject()->className(), ty->metaObject()->className());
|
||||||
}
|
}
|
||||||
processDeclarativeType(ty, &metas);
|
processDeclarativeType(ty, &metas);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust qml names of extended objects.
|
// Adjust ids of extended objects.
|
||||||
// The chain ends up being:
|
// The chain ends up being:
|
||||||
// __extended__.originalname - the base object
|
// __extended__.originalname - the base object
|
||||||
// __extension_0_.originalname - first extension
|
// __extension_0_.originalname - first extension
|
||||||
@@ -310,14 +335,19 @@ int main(int argc, char *argv[])
|
|||||||
// __extension_n-2_.originalname - second to last extension
|
// __extension_n-2_.originalname - second to last extension
|
||||||
// originalname - last extension
|
// originalname - last extension
|
||||||
foreach (const QByteArray &extendedCpp, extensions.keys()) {
|
foreach (const QByteArray &extendedCpp, extensions.keys()) {
|
||||||
const QByteArray extendedQml = cppToQml.value(extendedCpp);
|
const QByteArray extendedId = cppToId.value(extendedCpp);
|
||||||
cppToQml.insert(extendedCpp, "__extended__." + extendedQml);
|
cppToId.insert(extendedCpp, "__extended__." + extendedId);
|
||||||
QList<QByteArray> extensionCppNames = extensions.values(extendedCpp);
|
QSet<QByteArray> extensionCppNames = extensions.value(extendedCpp);
|
||||||
for (int i = 0; i < extensionCppNames.size() - 1; ++i) {
|
int c = 0;
|
||||||
QByteArray adjustedName = QString("__extension__%1.%2").arg(QString::number(i), QString(extendedQml)).toAscii();
|
foreach (const QByteArray &extensionCppName, extensionCppNames) {
|
||||||
cppToQml.insert(extensionCppNames.value(i), adjustedName);
|
if (c != extensionCppNames.size() - 1) {
|
||||||
|
QByteArray adjustedName = QString("__extension__%1.%2").arg(QString::number(c), QString(extendedId)).toAscii();
|
||||||
|
cppToId.insert(extensionCppName, adjustedName);
|
||||||
|
} else {
|
||||||
|
cppToId.insert(extensionCppName, extendedId);
|
||||||
|
}
|
||||||
|
++c;
|
||||||
}
|
}
|
||||||
cppToQml.insert(extensionCppNames.last(), extendedQml);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (const QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) {
|
foreach (const QDeclarativeType *ty, QDeclarativeMetaType::qmlTypes()) {
|
||||||
@@ -350,13 +380,13 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
QMap<QString, const QMetaObject *> nameToMeta;
|
QMap<QString, const QMetaObject *> nameToMeta;
|
||||||
foreach (const QMetaObject *meta, metas) {
|
foreach (const QMetaObject *meta, metas) {
|
||||||
nameToMeta.insert(convertToQmlType(meta->className()), meta);
|
nameToMeta.insert(convertToId(meta->className()), meta);
|
||||||
}
|
}
|
||||||
foreach (const QMetaObject *meta, nameToMeta) {
|
foreach (const QMetaObject *meta, nameToMeta) {
|
||||||
dump(meta, &xml);
|
dump(meta, &xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
// define QEasingCurve as an extension of Qt.Easing
|
// define QEasingCurve as an extension of QDeclarativeEasingValueType
|
||||||
writeEasingCurve(&xml);
|
writeEasingCurve(&xml);
|
||||||
|
|
||||||
xml.writeEndElement();
|
xml.writeEndElement();
|
||||||
|
@@ -199,13 +199,19 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
class FakeMetaObject {
|
class FakeMetaObject {
|
||||||
FakeMetaObject(FakeMetaObject&);
|
Q_DISABLE_COPY(FakeMetaObject)
|
||||||
FakeMetaObject &operator=(const FakeMetaObject&);
|
|
||||||
|
|
||||||
QString m_name;
|
public:
|
||||||
QString m_package;
|
class Export {
|
||||||
QString m_packageNameVersion;
|
public:
|
||||||
ComponentVersion m_version;
|
QString package;
|
||||||
|
QString type;
|
||||||
|
QmlJS::ComponentVersion version;
|
||||||
|
QString packageNameVersion;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
QList<Export> m_exports;
|
||||||
const FakeMetaObject *m_super;
|
const FakeMetaObject *m_super;
|
||||||
QString m_superName;
|
QString m_superName;
|
||||||
QList<FakeMetaEnum> m_enums;
|
QList<FakeMetaEnum> m_enums;
|
||||||
@@ -216,14 +222,26 @@ class FakeMetaObject {
|
|||||||
QString m_defaultPropertyName;
|
QString m_defaultPropertyName;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FakeMetaObject(const QString &name, const QString &package, ComponentVersion version)
|
FakeMetaObject()
|
||||||
: m_name(name), m_package(package), m_version(version), m_super(0)
|
: m_super(0)
|
||||||
{
|
{
|
||||||
m_packageNameVersion = QString::fromLatin1("%1.%2 %3.%4").arg(
|
|
||||||
package, name,
|
|
||||||
QString::number(version.majorVersion()), QString::number(version.minorVersion()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addExport(const QString &name, const QString &package, QmlJS::ComponentVersion version)
|
||||||
|
{
|
||||||
|
Export exp;
|
||||||
|
exp.type = name;
|
||||||
|
exp.package = package;
|
||||||
|
exp.version = version;
|
||||||
|
exp.packageNameVersion = QString::fromLatin1("%1.%2 %3.%4").arg(
|
||||||
|
package, name,
|
||||||
|
QString::number(version.majorVersion()),
|
||||||
|
QString::number(version.minorVersion()));
|
||||||
|
m_exports.append(exp);
|
||||||
|
}
|
||||||
|
QList<Export> exports() const
|
||||||
|
{ return m_exports; }
|
||||||
|
|
||||||
void setSuperclassName(const QString &superclass)
|
void setSuperclassName(const QString &superclass)
|
||||||
{ m_superName = superclass; }
|
{ m_superName = superclass; }
|
||||||
QString superclassName() const
|
QString superclassName() const
|
||||||
@@ -233,12 +251,6 @@ public:
|
|||||||
{ m_super = superClass; }
|
{ m_super = superClass; }
|
||||||
const FakeMetaObject *superClass() const
|
const FakeMetaObject *superClass() const
|
||||||
{ return m_super; }
|
{ return m_super; }
|
||||||
QString className() const
|
|
||||||
{ return m_name; }
|
|
||||||
QString packageName() const
|
|
||||||
{ return m_package; }
|
|
||||||
QString packageClassVersionString() const
|
|
||||||
{ return m_packageNameVersion; }
|
|
||||||
|
|
||||||
void addEnum(const FakeMetaEnum &fakeEnum)
|
void addEnum(const FakeMetaEnum &fakeEnum)
|
||||||
{ m_enumNameToIndex.insert(fakeEnum.name(), m_enums.size()); m_enums.append(fakeEnum); }
|
{ m_enumNameToIndex.insert(fakeEnum.name(), m_enums.size()); m_enums.append(fakeEnum); }
|
||||||
@@ -271,9 +283,6 @@ public:
|
|||||||
FakeMetaMethod method(int index) const
|
FakeMetaMethod method(int index) const
|
||||||
{ return m_methods.at(index); }
|
{ return m_methods.at(index); }
|
||||||
|
|
||||||
ComponentVersion version() const
|
|
||||||
{ return m_version; }
|
|
||||||
|
|
||||||
QString defaultPropertyName() const
|
QString defaultPropertyName() const
|
||||||
{ return m_defaultPropertyName; }
|
{ return m_defaultPropertyName; }
|
||||||
|
|
||||||
@@ -404,38 +413,14 @@ private:
|
|||||||
QString name, defaultPropertyName;
|
QString name, defaultPropertyName;
|
||||||
QmlJS::ComponentVersion version;
|
QmlJS::ComponentVersion version;
|
||||||
QString extends;
|
QString extends;
|
||||||
|
QString id;
|
||||||
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
||||||
if (attr.name() == QLatin1String("name")) {
|
if (attr.name() == QLatin1String("name")) {
|
||||||
name = attr.value().toString();
|
id = attr.value().toString();
|
||||||
if (name.isEmpty()) {
|
if (id.isEmpty()) {
|
||||||
invalidAttr(name, QLatin1String("name"), tag);
|
invalidAttr(name, QLatin1String("name"), tag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else if (attr.name() == QLatin1String("version")) {
|
|
||||||
QString versionStr = attr.value().toString();
|
|
||||||
int dotIdx = versionStr.indexOf('.');
|
|
||||||
if (dotIdx == -1) {
|
|
||||||
bool ok = false;
|
|
||||||
const int major = versionStr.toInt(&ok);
|
|
||||||
if (!ok) {
|
|
||||||
invalidAttr(versionStr, QLatin1String("version"), tag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
version = QmlJS::ComponentVersion(major, QmlJS::ComponentVersion::NoVersion);
|
|
||||||
} else {
|
|
||||||
bool ok = false;
|
|
||||||
const int major = versionStr.left(dotIdx).toInt(&ok);
|
|
||||||
if (!ok) {
|
|
||||||
invalidAttr(versionStr, QLatin1String("version"), tag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const int minor = versionStr.mid(dotIdx + 1).toInt(&ok);
|
|
||||||
if (!ok) {
|
|
||||||
invalidAttr(versionStr, QLatin1String("version"), tag);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
version = QmlJS::ComponentVersion(major, minor);
|
|
||||||
}
|
|
||||||
} else if (attr.name() == QLatin1String("defaultProperty")) {
|
} else if (attr.name() == QLatin1String("defaultProperty")) {
|
||||||
defaultPropertyName = attr.value().toString();
|
defaultPropertyName = attr.value().toString();
|
||||||
} else if (attr.name() == QLatin1String("extends")) {
|
} else if (attr.name() == QLatin1String("extends")) {
|
||||||
@@ -451,9 +436,7 @@ private:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QString className, packageName;
|
FakeMetaObject *metaObject = new FakeMetaObject;
|
||||||
split(name, &packageName, &className);
|
|
||||||
FakeMetaObject *metaObject = new FakeMetaObject(className, packageName, version);
|
|
||||||
if (! extends.isEmpty())
|
if (! extends.isEmpty())
|
||||||
metaObject->setSuperclassName(extends);
|
metaObject->setSuperclassName(extends);
|
||||||
if (! defaultPropertyName.isEmpty())
|
if (! defaultPropertyName.isEmpty())
|
||||||
@@ -468,14 +451,21 @@ private:
|
|||||||
readSignal(metaObject);
|
readSignal(metaObject);
|
||||||
else if (_xml.name() == QLatin1String("method"))
|
else if (_xml.name() == QLatin1String("method"))
|
||||||
readMethod(metaObject);
|
readMethod(metaObject);
|
||||||
|
else if (_xml.name() == QLatin1String("exports"))
|
||||||
|
readExports(metaObject);
|
||||||
else
|
else
|
||||||
unexpectedElement(_xml.name(), tag);
|
unexpectedElement(_xml.name(), tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doInsert)
|
if (metaObject->exports().isEmpty()) {
|
||||||
_objects->insert(name, metaObject);
|
metaObject->addExport(id, QString(), QmlJS::ComponentVersion());
|
||||||
else
|
}
|
||||||
|
|
||||||
|
if (doInsert) {
|
||||||
|
_objects->insert(id, metaObject);
|
||||||
|
} else {
|
||||||
delete metaObject;
|
delete metaObject;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool split(const QString &name, QString *packageName, QString *className) {
|
bool split(const QString &name, QString *packageName, QString *className) {
|
||||||
@@ -706,6 +696,60 @@ private:
|
|||||||
metaObject->addMethod(method);
|
metaObject->addMethod(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void readExports(FakeMetaObject *metaObject)
|
||||||
|
{
|
||||||
|
Q_ASSERT(metaObject);
|
||||||
|
QLatin1String tag("exports");
|
||||||
|
QLatin1String childTag("export");
|
||||||
|
Q_ASSERT(_xml.isStartElement() && _xml.name() == tag);
|
||||||
|
|
||||||
|
while (_xml.readNextStartElement()) {
|
||||||
|
if (_xml.name() == childTag) {
|
||||||
|
QString type;
|
||||||
|
QString package;
|
||||||
|
QmlJS::ComponentVersion version;
|
||||||
|
foreach (const QXmlStreamAttribute &attr, _xml.attributes()) {
|
||||||
|
if (attr.name() == QLatin1String("module")) {
|
||||||
|
package = attr.value().toString();
|
||||||
|
} else if (attr.name() == QLatin1String("type")) {
|
||||||
|
type = attr.value().toString();
|
||||||
|
} else if (attr.name() == QLatin1String("version")) {
|
||||||
|
QString versionStr = attr.value().toString();
|
||||||
|
int dotIdx = versionStr.indexOf('.');
|
||||||
|
if (dotIdx == -1) {
|
||||||
|
bool ok = false;
|
||||||
|
const int major = versionStr.toInt(&ok);
|
||||||
|
if (!ok) {
|
||||||
|
invalidAttr(versionStr, QLatin1String("version"), childTag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
version = QmlJS::ComponentVersion(major, QmlJS::ComponentVersion::NoVersion);
|
||||||
|
} else {
|
||||||
|
bool ok = false;
|
||||||
|
const int major = versionStr.left(dotIdx).toInt(&ok);
|
||||||
|
if (!ok) {
|
||||||
|
invalidAttr(versionStr, QLatin1String("version"), childTag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const int minor = versionStr.mid(dotIdx + 1).toInt(&ok);
|
||||||
|
if (!ok) {
|
||||||
|
invalidAttr(versionStr, QLatin1String("version"), childTag);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
version = QmlJS::ComponentVersion(major, minor);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ignoreAttr(attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metaObject->addExport(type, package, version);
|
||||||
|
} else {
|
||||||
|
unexpectedElement(_xml.name(), childTag);
|
||||||
|
}
|
||||||
|
_xml.skipCurrentElement(); // the <export> tag should be empty anyhow
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QXmlStreamReader _xml;
|
QXmlStreamReader _xml;
|
||||||
QMap<QString, FakeMetaObject *> *_objects;
|
QMap<QString, FakeMetaObject *> *_objects;
|
||||||
@@ -713,11 +757,12 @@ private:
|
|||||||
|
|
||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
|
||||||
QmlObjectValue::QmlObjectValue(const FakeMetaObject *metaObject, Engine *engine)
|
QmlObjectValue::QmlObjectValue(const FakeMetaObject *metaObject, int exportIndex, Engine *engine)
|
||||||
: ObjectValue(engine),
|
: ObjectValue(engine),
|
||||||
_metaObject(metaObject)
|
_metaObject(metaObject),
|
||||||
|
_exportIndex(exportIndex)
|
||||||
{
|
{
|
||||||
setClassName(metaObject->className()); // ### TODO: we probably need to do more than just this...
|
setClassName(metaObject->exports().at(exportIndex).type); // ### TODO: we probably need to do more than just this...
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlObjectValue::~QmlObjectValue()
|
QmlObjectValue::~QmlObjectValue()
|
||||||
@@ -834,10 +879,10 @@ const Value *QmlObjectValue::propertyValue(const FakeMetaProperty &prop) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString QmlObjectValue::packageName() const
|
QString QmlObjectValue::packageName() const
|
||||||
{ return _metaObject->packageName(); }
|
{ return _metaObject->exports().at(_exportIndex).package; }
|
||||||
|
|
||||||
QmlJS::ComponentVersion QmlObjectValue::version() const
|
QmlJS::ComponentVersion QmlObjectValue::version() const
|
||||||
{ return _metaObject->version(); }
|
{ return _metaObject->exports().at(_exportIndex).version; }
|
||||||
|
|
||||||
QString QmlObjectValue::defaultPropertyName() const
|
QString QmlObjectValue::defaultPropertyName() const
|
||||||
{ return _metaObject->defaultPropertyName(); }
|
{ return _metaObject->defaultPropertyName(); }
|
||||||
@@ -890,7 +935,7 @@ bool QmlObjectValue::hasChildInPackage() const
|
|||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
it.next();
|
it.next();
|
||||||
const FakeMetaObject *other = it.value()->_metaObject;
|
const FakeMetaObject *other = it.value()->_metaObject;
|
||||||
if (other->packageName().isEmpty())
|
if (other->exports().isEmpty())
|
||||||
continue;
|
continue;
|
||||||
for (const FakeMetaObject *iter = other; iter; iter = iter->superClass()) {
|
for (const FakeMetaObject *iter = other; iter; iter = iter->superClass()) {
|
||||||
if (iter == _metaObject) // this object is a parent of other
|
if (iter == _metaObject) // this object is a parent of other
|
||||||
@@ -1981,21 +2026,42 @@ void CppQmlTypes::load(Engine *engine, const QList<const FakeMetaObject *> &obje
|
|||||||
{
|
{
|
||||||
// load
|
// load
|
||||||
foreach (const FakeMetaObject *metaObject, objects) {
|
foreach (const FakeMetaObject *metaObject, objects) {
|
||||||
// make sure we're not loading duplicate objects
|
for (int i = 0; i < metaObject->exports().size(); ++i) {
|
||||||
if (_typesByFullyQualifiedName.contains(metaObject->packageClassVersionString()))
|
const FakeMetaObject::Export &exp = metaObject->exports().at(i);
|
||||||
continue;
|
// make sure we're not loading duplicate objects
|
||||||
|
if (_typesByFullyQualifiedName.contains(exp.packageNameVersion))
|
||||||
|
continue;
|
||||||
|
|
||||||
QmlObjectValue *objectValue = new QmlObjectValue(metaObject, engine);
|
QmlObjectValue *objectValue = new QmlObjectValue(metaObject, i, engine);
|
||||||
_typesByPackage[metaObject->packageName()].append(objectValue);
|
_typesByPackage[exp.package].append(objectValue);
|
||||||
_typesByFullyQualifiedName[metaObject->packageClassVersionString()] = objectValue;
|
_typesByFullyQualifiedName[exp.packageNameVersion] = objectValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set prototype correctly
|
// set prototype correctly
|
||||||
foreach (const FakeMetaObject *metaObject, objects) {
|
foreach (const FakeMetaObject *metaObject, objects) {
|
||||||
QmlObjectValue *objectValue = _typesByFullyQualifiedName.value(metaObject->packageClassVersionString());
|
foreach (const FakeMetaObject::Export &exp, metaObject->exports()) {
|
||||||
if (!objectValue || !metaObject->superClass())
|
QmlObjectValue *objectValue = _typesByFullyQualifiedName.value(exp.packageNameVersion);
|
||||||
continue;
|
if (!objectValue || !metaObject->superClass())
|
||||||
objectValue->setPrototype(_typesByFullyQualifiedName.value(metaObject->superClass()->packageClassVersionString()));
|
continue;
|
||||||
|
bool found = false;
|
||||||
|
// try to get a prototype from the library first
|
||||||
|
foreach (const FakeMetaObject::Export &superExports, metaObject->superClass()->exports()) {
|
||||||
|
if (superExports.package == exp.package) {
|
||||||
|
objectValue->setPrototype(_typesByFullyQualifiedName.value(superExports.packageNameVersion));
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
|
continue;
|
||||||
|
// otherwise, just use the first available
|
||||||
|
if (!metaObject->superClass()->exports().isEmpty()) {
|
||||||
|
objectValue->setPrototype(_typesByFullyQualifiedName.value(metaObject->superClass()->exports().first().packageNameVersion));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
//qWarning() << "Could not find super class for " << exp.packageNameVersion;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -383,7 +383,7 @@ private:
|
|||||||
class QMLJS_EXPORT QmlObjectValue: public ObjectValue
|
class QMLJS_EXPORT QmlObjectValue: public ObjectValue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QmlObjectValue(const FakeMetaObject *metaObject, Engine *engine);
|
QmlObjectValue(const FakeMetaObject *metaObject, int exportIndex, Engine *engine);
|
||||||
virtual ~QmlObjectValue();
|
virtual ~QmlObjectValue();
|
||||||
|
|
||||||
virtual void processMembers(MemberProcessor *processor) const;
|
virtual void processMembers(MemberProcessor *processor) const;
|
||||||
@@ -404,6 +404,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const FakeMetaObject *_metaObject;
|
const FakeMetaObject *_metaObject;
|
||||||
|
const int _exportIndex;
|
||||||
mutable QHash<int, const Value *> _metaSignature;
|
mutable QHash<int, const Value *> _metaSignature;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user