setupgenerator.cpp
235 lines
| 8.4 KiB
| text/x-c
|
CppLexer
/ generator / setupgenerator.cpp
florianlink
|
r10 | /**************************************************************************** | ||
** | ||||
florianlink
|
r87 | ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). | ||
** All rights reserved. | ||||
** Contact: Nokia Corporation (qt-info@nokia.com) | ||||
florianlink
|
r10 | ** | ||
florianlink
|
r87 | ** This file is part of the Qt Script Generator project on Qt Labs. | ||
florianlink
|
r10 | ** | ||
florianlink
|
r87 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
** No Commercial Usage | ||||
** This file contains pre-release code and may not be distributed. | ||||
** You may use this file in accordance with the terms and conditions | ||||
** contained in the Technology Preview License Agreement accompanying | ||||
** this package. | ||||
florianlink
|
r10 | ** | ||
florianlink
|
r87 | ** GNU Lesser General Public License Usage | ||
** Alternatively, this file may be used under the terms of the GNU Lesser | ||||
** General Public License version 2.1 as published by the Free Software | ||||
** Foundation and appearing in the file LICENSE.LGPL included in the | ||||
** packaging of this file. Please review the following information to | ||||
** ensure the GNU Lesser General Public License version 2.1 requirements | ||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||||
florianlink
|
r10 | ** | ||
florianlink
|
r87 | ** In addition, as a special exception, Nokia gives you certain additional | ||
** rights. These rights are described in the Nokia Qt LGPL Exception | ||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||||
** | ||||
** If you have questions regarding the use of this file, please contact | ||||
** Nokia at qt-info@nokia.com. | ||||
** | ||||
** | ||||
** | ||||
** | ||||
** | ||||
** | ||||
** | ||||
** | ||||
** $QT_END_LICENSE$ | ||||
florianlink
|
r10 | ** | ||
****************************************************************************/ | ||||
#include "setupgenerator.h" | ||||
florianlink
|
r24 | #include "shellgenerator.h" | ||
florianlink
|
r10 | #include "reporthandler.h" | ||
#include "fileout.h" | ||||
//#define Q_SCRIPT_LAZY_GENERATOR | ||||
florianlink
|
r93 | void SetupGenerator::addClass(const QString& package, const AbstractMetaClass *cls) | ||
florianlink
|
r10 | { | ||
florianlink
|
r93 | packHash[package].append(cls); | ||
florianlink
|
r10 | } | ||
void maybeDeclareMetaType(QTextStream &stream, const QString &typeName, | ||||
QSet<QString> ®isteredTypeNames); | ||||
bool hasDefaultConstructor(const AbstractMetaClass *meta_class); | ||||
void SetupGenerator::generate() | ||||
{ | ||||
florianlink
|
r29 | AbstractMetaClassList classes_with_polymorphic_id; | ||
{ | ||||
florianlink
|
r10 | QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash); | ||
while (pack.hasNext()) { | ||||
florianlink
|
r29 | pack.next(); | ||
QList<const AbstractMetaClass*> list = pack.value(); | ||||
foreach (const AbstractMetaClass *cls, list) { | ||||
if (cls->typeEntry()->isPolymorphicBase()) { | ||||
classes_with_polymorphic_id.append((AbstractMetaClass*)cls); | ||||
florianlink
|
r10 | } | ||
florianlink
|
r29 | } | ||
} | ||||
} | ||||
QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash); | ||||
while (pack.hasNext()) { | ||||
pack.next(); | ||||
QList<const AbstractMetaClass*> list = pack.value(); | ||||
if (list.isEmpty()) | ||||
continue; | ||||
QString packKey = pack.key(); | ||||
QString packName = pack.key(); | ||||
florianlink
|
r93 | QStringList components = packName.split("_"); | ||
florianlink
|
r29 | if ((components.size() > 2) && (components.at(0) == "com") | ||
&& (components.at(1) == "trolltech")) { | ||||
// kill com.trolltech in key | ||||
components.removeAt(0); | ||||
components.removeAt(0); | ||||
} | ||||
florianlink
|
r12 | |||
florianlink
|
r29 | 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"; | ||||
} | ||||
florianlink
|
r12 | |||
florianlink
|
r29 | { | ||
FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp"); | ||||
QTextStream &s = initFile.stream; | ||||
florianlink
|
r10 | |||
florianlink
|
r29 | s << "#include <PythonQt.h>" << endl; | ||
florianlink
|
r92 | for (int i=0; i<(list.count()+MAX_CLASSES_PER_FILE-1) / MAX_CLASSES_PER_FILE; i++) { | ||
s << "#include \"" << packKey << QString::number(i) << ".h\"" << endl; | ||||
florianlink
|
r29 | } | ||
s << endl; | ||||
florianlink
|
r93 | QStringList polymorphicHandlers; | ||
if (!packName.endsWith("_builtin")) { | ||||
polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id); | ||||
s << endl; | ||||
} | ||||
florianlink
|
r29 | // declare individual class creation functions | ||
florianlink
|
r108 | s << "void PythonQt_init_" << shortPackName << "(PyObject* module) {" << endl; | ||
florianlink
|
r93 | |||
if (shortPackName.endsWith("Builtin")) { | ||||
florianlink
|
r94 | shortPackName = shortPackName.mid(0, shortPackName.length()-strlen("builtin")); | ||
florianlink
|
r93 | } | ||
florianlink
|
r29 | QStringList cppClassNames; | ||
foreach (const AbstractMetaClass *cls, list) { | ||||
QString shellCreator; | ||||
if (cls->generateShellClass()) { | ||||
shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">"; | ||||
florianlink
|
r108 | } else { | ||
shellCreator = ", NULL"; | ||||
florianlink
|
r29 | } | ||
if (cls->isQObject()) { | ||||
florianlink
|
r108 | s << "PythonQt::priv()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module);" << endl; | ||
florianlink
|
r29 | } else { | ||
QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():""; | ||||
florianlink
|
r108 | s << "PythonQt::priv()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module);" << endl; | ||
florianlink
|
r29 | } | ||
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() <<","<<interface->qualifiedCppName()<<">());" << endl; | ||||
} | ||||
} | ||||
} | ||||
s << endl; | ||||
foreach (QString handler, polymorphicHandlers) { | ||||
s << "PythonQt::self()->addPolymorphicHandler(\""<< handler << "\", polymorphichandler_" << handler << ");" << endl; | ||||
} | ||||
s << "}"; | ||||
s << endl; | ||||
} | ||||
} | ||||
} | ||||
florianlink
|
r10 | |||
florianlink
|
r29 | 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; | ||||
florianlink
|
r10 | } | ||
florianlink
|
r29 | } | ||
} 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; | ||||
florianlink
|
r10 | } | ||
florianlink
|
r12 | |||
florianlink
|
r29 | // 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); | ||||
florianlink
|
r10 | } | ||
florianlink
|
r29 | } | ||
florianlink
|
r10 | } | ||
florianlink
|
r29 | |||
// Close the function if it has been opened | ||||
if (!first) { | ||||
s << " return NULL;" << endl | ||||
<< "}" << endl; | ||||
} | ||||
} | ||||
return handlers; | ||||
florianlink
|
r10 | } | ||