From fa33440a60c5becac3ae7e0b28c6a258b01a8fa0 2009-04-21 14:47:59 From: florianlink Date: 2009-04-21 14:47:59 Subject: [PATCH] - upgraded generator to generate polymorphic handlers for downcasting - fixed virtual function promotion/forwarding git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@65 ea8d5007-eb21-0410-b261-ccb3ea6e24a9 --- diff --git a/generator/abstractmetalang.h b/generator/abstractmetalang.h index a69b406..471b855 100644 --- a/generator/abstractmetalang.h +++ b/generator/abstractmetalang.h @@ -471,6 +471,8 @@ public: FunctionType functionType() const { return m_function_type; } void setFunctionType(FunctionType type) { m_function_type = type; } + bool isVirtual() { return !(isFinal() || isSignal() || isStatic()); } + QStringList introspectionCompatibleSignatures(const QStringList &resolvedArguments = QStringList()) const; QString signature() const; QString targetLangSignature(bool minimal = false) const; diff --git a/generator/generatorsetqtscript.cpp b/generator/generatorsetqtscript.cpp index 19dfadf..0a73231 100644 --- a/generator/generatorsetqtscript.cpp +++ b/generator/generatorsetqtscript.cpp @@ -68,6 +68,7 @@ QString GeneratorSetQtScript::generate() { SetupGenerator setupGenerator; setupGenerator.setOutputDirectory(outDir); setupGenerator.setQtMetaTypeDeclaredTypeNames(declaredTypeNames); + setupGenerator.setClasses(classes); /* ClassGenerator classGenerator(&priGenerator, &setupGenerator); diff --git a/generator/setupgenerator.cpp b/generator/setupgenerator.cpp index ce79f3b..ccdbe8d 100644 --- a/generator/setupgenerator.cpp +++ b/generator/setupgenerator.cpp @@ -30,7 +30,7 @@ void SetupGenerator::addClass(const AbstractMetaClass *cls) { - packHash[cls->package()].append(cls); + packHash[cls->package()].append(cls); } void writeQtScriptQtBindingsLicense(QTextStream &stream); @@ -41,83 +41,175 @@ bool hasDefaultConstructor(const AbstractMetaClass *meta_class); void SetupGenerator::generate() { + AbstractMetaClassList classes_with_polymorphic_id; + { QHashIterator > pack(packHash); while (pack.hasNext()) { - pack.next(); - QList list = pack.value(); - if (list.isEmpty()) - continue; - - QString packKey = pack.key(); - QString packName = pack.key(); - QStringList components = packName.split("."); - if ((components.size() > 2) && (components.at(0) == "com") - && (components.at(1) == "trolltech")) { - // kill com.trolltech in key - components.removeAt(0); - components.removeAt(0); + pack.next(); + QList list = pack.value(); + foreach (const AbstractMetaClass *cls, list) { + if (cls->typeEntry()->isPolymorphicBase()) { + classes_with_polymorphic_id.append((AbstractMetaClass*)cls); } - packName.replace(".", "_"); - packKey.replace(".", "_"); + } + } + } + + QHashIterator > pack(packHash); + while (pack.hasNext()) { + pack.next(); + QList list = pack.value(); + if (list.isEmpty()) + continue; + + QString packKey = pack.key(); + QString packName = pack.key(); + QStringList components = packName.split("."); + if ((components.size() > 2) && (components.at(0) == "com") + && (components.at(1) == "trolltech")) { + // kill com.trolltech in key + components.removeAt(0); + components.removeAt(0); + } + packName.replace(".", "_"); + packKey.replace(".", "_"); - QString shortPackName; - foreach (QString comp, components) { - comp[0] = comp[0].toUpper(); - shortPackName += comp; - } - // add missing camel case (workaround..) - if (shortPackName == "QtWebkit") { - shortPackName = "QtWebKit"; - } else if (shortPackName == "QtXmlpatterns") { - shortPackName = "QtXmlPatterns"; - } else if (shortPackName == "QtOpengl") { - shortPackName = "QtOpenGL"; - } else if (shortPackName == "QtUitools") { - shortPackName = "QtUiTools"; - } + QString shortPackName; + foreach (QString comp, components) { + comp[0] = comp[0].toUpper(); + shortPackName += comp; + } + // add missing camel case (workaround..) + if (shortPackName == "QtWebkit") { + shortPackName = "QtWebKit"; + } else if (shortPackName == "QtXmlpatterns") { + shortPackName = "QtXmlPatterns"; + } else if (shortPackName == "QtOpengl") { + shortPackName = "QtOpenGL"; + } else if (shortPackName == "QtUitools") { + shortPackName = "QtUiTools"; + } - { - FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp"); - QTextStream &s = initFile.stream; + { + FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp"); + QTextStream &s = initFile.stream; - if (FileOut::license) - writeQtScriptQtBindingsLicense(s); + if (FileOut::license) + writeQtScriptQtBindingsLicense(s); - s << "#include " << endl; + s << "#include " << endl; + + foreach (const AbstractMetaClass *cls, list) { + s << "#include \"" << ShellGenerator::wrapperClassName(cls) << ".h\"" << endl; + } + s << endl; + + QStringList polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id); + s << endl; + + // declare individual class creation functions + s << "void PythonQt_init_" << shortPackName << "() {" << endl; + QStringList cppClassNames; + foreach (const AbstractMetaClass *cls, list) { + if (ShellGenerator::isBuiltIn(cls->name())) { continue; } + + QString shellCreator; + if (cls->generateShellClass()) { + shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">"; + } + if (cls->isQObject()) { + s << "PythonQt::self()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObjectname() << ">" << shellCreator << ");" << endl; + } else { + QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():""; + s << "PythonQt::self()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObjectname() << ">" << shellCreator << ");" << endl; + } + foreach(AbstractMetaClass* interface, cls->interfaces()) { + // the interface might be our own class... (e.g. QPaintDevice) + if (interface->qualifiedCppName() != cls->qualifiedCppName()) { + s << "PythonQt::self()->addParentClass(\""<< cls->qualifiedCppName() << "\", \"" << interface->qualifiedCppName() << "\",PythonQtUpcastingOffset<" << cls->qualifiedCppName() <<","<qualifiedCppName()<<">());" << endl; + } + } + } + s << endl; + foreach (QString handler, polymorphicHandlers) { + s << "PythonQt::self()->addPolymorphicHandler(\""<< handler << "\", polymorphichandler_" << handler << ");" << endl; + } + + s << "}"; + s << endl; + } + } +} - foreach (const AbstractMetaClass *cls, list) { - s << "#include \"" << ShellGenerator::wrapperClassName(cls) << ".h\"" << endl; +QStringList SetupGenerator::writePolymorphicHandler(QTextStream &s, const QString &package, + const AbstractMetaClassList &classes) +{ + QStringList handlers; + foreach (AbstractMetaClass *cls, classes) { + const ComplexTypeEntry *centry = cls->typeEntry(); + if (!centry->isPolymorphicBase()) + continue; + bool isGraphicsItem = (cls->qualifiedCppName()=="QGraphicsItem"); + + AbstractMetaClassList classList = this->classes(); + bool first = true; + foreach (AbstractMetaClass *clazz, classList) { + bool inherits = false; + if (isGraphicsItem) { + foreach(AbstractMetaClass* interfaze, clazz->interfaces()) { + if (interfaze->qualifiedCppName()=="QGraphicsItem") { + inherits = true; + break; } - s << endl; - - // declare individual class creation functions - s << "void PythonQt_init_" << shortPackName << "() {" << endl; - QStringList cppClassNames; - foreach (const AbstractMetaClass *cls, list) { - if (ShellGenerator::isBuiltIn(cls->name())) { continue; } - - QString shellCreator; - if (cls->generateShellClass()) { - shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">"; - } - if (cls->isQObject()) { - s << "PythonQt::self()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObjectname() << ">" << shellCreator << ");" << endl; - } else { - QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():""; - s << "PythonQt::self()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObjectname() << ">" << shellCreator << ");" << endl; - } - foreach(AbstractMetaClass* interface, cls->interfaces()) { - // the interface might be our own class... (e.g. QPaintDevice) - if (interface->qualifiedCppName() != cls->qualifiedCppName()) { - s << "PythonQt::self()->addParentClass(\""<< cls->qualifiedCppName() << "\", \"" << interface->qualifiedCppName() << "\",PythonQtUpcastingOffset<" << cls->qualifiedCppName() <<","<qualifiedCppName()<<">());" << endl; - } - } + } + } else { + inherits = clazz->inheritsFrom(cls); + } + if (clazz->package() == package && inherits) { + if (!clazz->typeEntry()->polymorphicIdValue().isEmpty() || isGraphicsItem) { + // On first find, open the function + if (first) { + first = false; + + QString handler = cls->name(); + handlers.append(handler); + + s << "static void* polymorphichandler_" << handler + << "(const void *ptr, char **class_name)" << endl + << "{" << endl + << " Q_ASSERT(ptr != 0);" << endl + << " " << cls->qualifiedCppName() << " *object = (" + << cls->qualifiedCppName() << " *)ptr;" << endl; } - s << endl; - s << "}"; - s << endl; + // For each, add case label + QString polyId = clazz->typeEntry()->polymorphicIdValue(); + if (isGraphicsItem) { + polyId = "%1->type() == " + clazz->qualifiedCppName() + "::Type"; + } + s << " if (" + << polyId.replace("%1", "object") + << ") {" << endl + << " *class_name = \"" << clazz->name() << "\";" << endl + << " return (" << clazz->qualifiedCppName() << "*)object;" << endl + << " }" << endl; + } else { + QString warning = QString("class '%1' inherits from polymorphic class '%2', but has no polymorphic id set") + .arg(clazz->name()) + .arg(cls->name()); + + ReportHandler::warning(warning); } + } } + + // Close the function if it has been opened + if (!first) { + s << " return NULL;" << endl + << "}" << endl; + } + } + + return handlers; } diff --git a/generator/setupgenerator.h b/generator/setupgenerator.h index b7ef9e6..73f3b7f 100644 --- a/generator/setupgenerator.h +++ b/generator/setupgenerator.h @@ -37,7 +37,10 @@ class SetupGenerator : public Generator void addClass(const AbstractMetaClass *cls); private: - QHash > packHash; + QStringList writePolymorphicHandler(QTextStream &s, const QString &package, + const AbstractMetaClassList &classes); + + QHash > packHash; }; #endif // SETUPGENERATOR_H diff --git a/generator/shellgenerator.cpp b/generator/shellgenerator.cpp index 99445a8..bb4e120 100644 --- a/generator/shellgenerator.cpp +++ b/generator/shellgenerator.cpp @@ -269,7 +269,7 @@ AbstractMetaFunctionList ShellGenerator::getProtectedFunctionsThatNeedPromotion( AbstractMetaFunctionList functions; AbstractMetaFunctionList functions1 = getFunctionsToWrap(meta_class); foreach(AbstractMetaFunction* func, functions1) { - if (!func->wasPublic()) { + if (!func->isPublic() || func->isVirtual()) { functions << func; } } diff --git a/generator/shellheadergenerator.cpp b/generator/shellheadergenerator.cpp index 1aa19c6..21e3fd7 100644 --- a/generator/shellheadergenerator.cpp +++ b/generator/shellheadergenerator.cpp @@ -117,7 +117,7 @@ void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_c foreach(AbstractMetaFunction* fun, promoteFunctions) { s << "inline "; - writeFunctionSignature(s, fun, 0, QString(), + writeFunctionSignature(s, fun, 0, "promoted_", Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces)); s << " { "; QString scriptFunctionName = fun->originalName(); diff --git a/generator/shellimplgenerator.cpp b/generator/shellimplgenerator.cpp index 1d2a3c2..7001328 100644 --- a/generator/shellimplgenerator.cpp +++ b/generator/shellimplgenerator.cpp @@ -199,6 +199,8 @@ void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_cla } } + QString wrappedObject = " (*theWrappedObject)"; + // write member functions for (int i = 0; i < functions.size(); ++i) { AbstractMetaFunction *fun = functions.at(i); @@ -208,12 +210,7 @@ void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_cla Option(FirstArgIsWrappedObject | OriginalName | ShowStatic | UnderscoreSpaces), "PythonQtWrapper_"); s << endl << "{" << endl; - QString wrappedObject; - if (fun->wasPublic()) { - wrappedObject = " (*theWrappedObject)"; - } else { - wrappedObject = " (*((" + promoterClassName(meta_class) + "*)theWrappedObject))"; - } + s << " "; if (ShellGenerator::isSpecialStreamingOperator(fun)) { s << fun->arguments().at(0)->argumentName(); if (fun->originalName().startsWith("operator>>")) { @@ -241,9 +238,13 @@ void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_cla if (fun->isStatic()) { s << meta_class->qualifiedCppName() << "::"; } else { - s << wrappedObject << "."; + if (!fun->isPublic() || fun->isVirtual()) { + s << " ((" << promoterClassName(meta_class) << "*)theWrappedObject)->promoted_"; + } else { + s << " theWrappedObject->"; + } } - s << fun->originalName() << "("; + s << fun->originalName() << "("; for (int i = 0; i < args.size(); ++i) { if (i > 0) s << ", "; diff --git a/generator/typesystem_gui.xml b/generator/typesystem_gui.xml index 7ed7f4e..094d281 100644 --- a/generator/typesystem_gui.xml +++ b/generator/typesystem_gui.xml @@ -1025,7 +1025,7 @@ - + @@ -1401,7 +1401,7 @@ - + @@ -1476,7 +1476,7 @@ - + @@ -5045,10 +5045,10 @@ - + - +