summaryrefslogtreecommitdiffstats
path: root/src/tools/moc
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/moc')
-rw-r--r--src/tools/moc/generator.cpp91
-rw-r--r--src/tools/moc/generator.h5
-rw-r--r--src/tools/moc/moc.cpp2
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();
}