diff options
Diffstat (limited to 'src/tools/moc')
-rw-r--r-- | src/tools/moc/generator.cpp | 91 | ||||
-rw-r--r-- | src/tools/moc/generator.h | 5 | ||||
-rw-r--r-- | src/tools/moc/moc.cpp | 2 |
3 files changed, 93 insertions, 5 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 39bd528008..edf2bf8889 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -86,8 +86,8 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING) return 0; } -Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile) - : out(outfile), cdef(classDef), metaTypes(metaTypes) +Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, const QSet<QByteArray> &knownQObjectClasses, FILE *outfile) + : out(outfile), cdef(classDef), metaTypes(metaTypes), knownQObjectClasses(knownQObjectClasses) { if (cdef->superclassList.size()) purestSuperClass = cdef->superclassList.first().first; @@ -140,6 +140,49 @@ static int aggregateParameterCount(const QList<FunctionDef> &list) return sum; } +bool Generator::registerableMetaType(const QByteArray &propertyType) +{ + if (metaTypes.contains(propertyType)) + return true; + + if (propertyType.endsWith('*')) { + QByteArray objectPointerType = propertyType; + // The objects container stores class names, such as 'QState', 'QLabel' etc, + // not 'QState*', 'QLabel*'. The propertyType does contain the '*', so we need + // to chop it to find the class type in the known QObjects list. + objectPointerType.chop(1); + if (knownQObjectClasses.contains(objectPointerType)) + return true; + } + + static const QVector<QByteArray> smartPointers = QVector<QByteArray>() +#define STREAM_SMART_POINTER(SMART_POINTER) << #SMART_POINTER + QT_FOR_EACH_AUTOMATIC_TEMPLATE_SMART_POINTER(STREAM_SMART_POINTER) +#undef STREAM_SMART_POINTER + ; + + foreach (const QByteArray &smartPointer, smartPointers) + if (propertyType.startsWith(smartPointer + "<")) + return knownQObjectClasses.contains(propertyType.mid(smartPointer.size() + 1, propertyType.size() - smartPointer.size() - 1 - 1)); + + static const QVector<QByteArray> oneArgTemplates = QVector<QByteArray>() +#define STREAM_1ARG_TEMPLATE(TEMPLATENAME) << #TEMPLATENAME + QT_FOR_EACH_AUTOMATIC_TEMPLATE_1ARG(STREAM_1ARG_TEMPLATE) +#undef STREAM_1ARG_TEMPLATE + ; + foreach (const QByteArray &oneArgTemplateType, oneArgTemplates) + if (propertyType.startsWith(oneArgTemplateType + "<")) { + const int argumentSize = propertyType.size() - oneArgTemplateType.size() - 1 + // The closing '>' + - 1 + // templates inside templates have an extra whitespace char to strip. + - (propertyType.at(propertyType.size() - 2) == '>' ? 1 : 0 ); + const QByteArray templateArg = propertyType.mid(oneArgTemplateType.size() + 1, argumentSize); + return isBuiltinType(templateArg) || registerableMetaType(templateArg); + } + return false; +} + void Generator::generateCode() { bool isQt = (cdef->classname == "Qt"); @@ -1034,6 +1077,15 @@ void Generator::generateMetacall() " _id -= %d;\n" " }", cdef->propertyList.count()); + fprintf(out, " else "); + fprintf(out, "if (_c == QMetaObject::RegisterPropertyMetaType) {\n"); + fprintf(out, " if (_id < %d)\n", cdef->propertyList.size()); + + if (automaticPropertyMetaTypesHelper().isEmpty()) + fprintf(out, " *reinterpret_cast<int*>(_a[0]) = -1;\n"); + else + fprintf(out, " qt_static_metacall(this, _c, _id, _a);\n"); + fprintf(out, " _id -= %d;\n }", cdef->propertyList.size()); fprintf(out, "\n#endif // QT_NO_PROPERTIES"); } @@ -1042,6 +1094,18 @@ void Generator::generateMetacall() fprintf(out,"return _id;\n}\n"); } + +QMultiMap<QByteArray, int> Generator::automaticPropertyMetaTypesHelper() +{ + QMultiMap<QByteArray, int> automaticPropertyMetaTypes; + for (int i = 0; i < cdef->propertyList.size(); ++i) { + const QByteArray propertyType = cdef->propertyList.at(i).type; + if (registerableMetaType(propertyType) && !isBuiltinType(propertyType)) + automaticPropertyMetaTypes.insert(propertyType, i); + } + return automaticPropertyMetaTypes; +} + void Generator::generateStaticMetacall() { fprintf(out, "void %s::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)\n{\n", @@ -1175,12 +1239,33 @@ void Generator::generateStaticMetacall() needElse = true; } + QMultiMap<QByteArray, int> automaticPropertyMetaTypes = automaticPropertyMetaTypesHelper(); + + if (!automaticPropertyMetaTypes.isEmpty()) { + if (needElse) + fprintf(out, " else "); + else + fprintf(out, " "); + fprintf(out, "if (_c == QMetaObject::RegisterPropertyMetaType) {\n"); + fprintf(out, " switch (_id) {\n"); + fprintf(out, " default: *reinterpret_cast<int*>(_a[0]) = -1; break;\n"); + foreach (const QByteArray &key, automaticPropertyMetaTypes.uniqueKeys()) { + foreach (int propertyID, automaticPropertyMetaTypes.values(key)) + fprintf(out, " case %d:\n", propertyID); + fprintf(out, " *reinterpret_cast<int*>(_a[0]) = qRegisterMetaType< %s >(); break;\n", key.constData()); + } + fprintf(out, " }\n"); + fprintf(out, " }\n"); + isUsed_a = true; + needElse = true; + } + if (needElse) fprintf(out, "\n"); if (methodList.isEmpty()) { fprintf(out, " Q_UNUSED(_o);\n"); - if (cdef->constructorList.isEmpty()) { + if (cdef->constructorList.isEmpty() && automaticPropertyMetaTypes.isEmpty()) { fprintf(out, " Q_UNUSED(_id);\n"); fprintf(out, " Q_UNUSED(_c);\n"); } diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h index 8ebc00b100..873681ab88 100644 --- a/src/tools/moc/generator.h +++ b/src/tools/moc/generator.h @@ -52,9 +52,10 @@ class Generator ClassDef *cdef; QVector<uint> meta_data; public: - Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile = 0); + Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, const QSet<QByteArray> &knownQObjectClasses, FILE *outfile = 0); void generateCode(); private: + bool registerableMetaType(const QByteArray &propertyType); void registerClassInfoStrings(); void generateClassInfos(); void registerFunctionStrings(const QList<FunctionDef> &list); @@ -70,12 +71,14 @@ private: void generateStaticMetacall(); void generateSignal(FunctionDef *def, int index); void generatePluginMetaData(); + QMultiMap<QByteArray, int> automaticPropertyMetaTypesHelper(); void strreg(const QByteArray &); // registers a string int stridx(const QByteArray &); // returns a string's id QList<QByteArray> strings; QByteArray purestSuperClass; QList<QByteArray> metaTypes; + QSet<QByteArray> knownQObjectClasses; }; QT_END_NAMESPACE diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index a176b87aaa..d7c08b4608 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -849,7 +849,7 @@ void Moc::generate(FILE *out) fprintf(out, "QT_BEGIN_MOC_NAMESPACE\n"); for (i = 0; i < classList.size(); ++i) { - Generator generator(&classList[i], metaTypes, out); + Generator generator(&classList[i], metaTypes, knownQObjectClasses, out); generator.generateCode(); } |