From 7b53f64eae84070b705854448949eeded1ec341d 2010-02-21 14:44:57
From: florianlink
Date: 2010-02-21 14:44:57
Subject: [PATCH] added builtin support for variants etc., this will replace the direct includes in PythonQt
git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@129 ea8d5007-eb21-0410-b261-ccb3ea6e24a9
---
diff --git a/generator/classgenerator.cpp b/generator/classgenerator.cpp
deleted file mode 100644
index b0032b0..0000000
--- a/generator/classgenerator.cpp
+++ /dev/null
@@ -1,1842 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt Script Generator project on Qt Labs.
-**
-** $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.
-**
-** 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.
-**
-** 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$
-**
-****************************************************************************/
-
-#include "classgenerator.h"
-#include "fileout.h"
-
-#include
-#include
-
-#include
-
-#define GENERATOR_NO_PROTECTED_FUNCTIONS
-
-ClassGenerator::ClassGenerator(PriGenerator *pri, SetupGenerator *setup) :
- priGenerator(pri),
- setupGenerator(setup)
-{}
-
-QString ClassGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
-{
- return QString("qtscript_%1.cpp").arg(meta_class->name());
-}
-
-bool ClassGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
-{
- return false; // DISABLED!
- uint cg = meta_class->typeEntry()->codeGeneration();
- return (cg & TypeEntry::GenerateCode) != 0;
-}
-
-static QString normalizedType(const AbstractMetaType *type)
-{
- QString str = QString::fromLatin1(QMetaObject::normalizedType(type->cppSignature().toLatin1()));
- if (str.endsWith(QLatin1Char('&')))
- str.chop(1);
- else if (str.startsWith("const ")) {
- if (str.endsWith('*') || type->hasInstantiations() || type->typeEntry()->isValue())
- str.remove(0, 6);
- }
- if (str == QLatin1String("QBool")) // ### hack
- str = QLatin1String("bool");
- return str;
-}
-
-/*!
- Returns true if the class \a meta_class inherits from QObject,
- otherwise returns false.
-*/
-static bool isQObjectBased(const AbstractMetaClass *meta_class)
-{
- while (meta_class) {
- if (meta_class->name() == QLatin1String("QObject"))
- return true;
- meta_class = meta_class->baseClass();
- }
- return false;
-}
-
-/*!
- Returns true if any of the given \a enums has been declared with
- Q_ENUMS.
-*/
-static bool hasQEnums(const AbstractMetaEnumList &enums)
-{
- for (int i = 0; i < enums.size(); ++i) {
- if (enums.at(i)->hasQEnumsDeclaration())
- return true;
- }
- return false;
-}
-
-/*!
- Returns true if any of the given \a enums has a QFlags class
- associated with it.
-*/
-static bool hasFlags(const AbstractMetaEnumList &enums)
-{
- for (int i = 0; i < enums.size(); ++i) {
- FlagsTypeEntry *flags = enums.at(i)->typeEntry()->flags();
- if (flags)
- return true;
- }
- return false;
-}
-
-static bool isSequenceType(const AbstractMetaType *tp)
-{
- return tp->isContainer() && (tp->instantiations().size() == 1);
-}
-
-static AbstractMetaFunction *findDefaultConstructor(const AbstractMetaFunctionList &ctors)
-{
- for (int i = 0; i < ctors.size(); ++i) {
- if (ctors.at(i)->actualMinimumArgumentCount() == 0)
- return ctors.at(i);
- }
- return 0;
-}
-
-static AbstractMetaFunctionList findConstructors(const AbstractMetaClass *meta_class)
-{
- return meta_class->queryFunctions(AbstractMetaClass::Constructors
- | AbstractMetaClass::WasPublic
- | AbstractMetaClass::NotRemovedFromTargetLang);
-}
-
-/*!
- Returns true if \a meta_class has a default constructor, false
- otherwise.
-*/
-bool hasDefaultConstructor(const AbstractMetaClass *meta_class)
-{
- return findDefaultConstructor(findConstructors(meta_class)) != 0;
-}
-
-/*!
- Given the list of \a functions, creates a mapping from # of
- arguments to list of functions.
-*/
-static QMap createArgcToFunctionsMap(
- const AbstractMetaFunctionList &functions)
-{
- QMap result;
- for (int i = 0; i < functions.size(); ++i) {
- AbstractMetaFunction *func = functions.at(i);
- int argc = func->arguments().size();
- for (int k = argc; k > 0; --k) {
- if (func->argumentRemoved(k))
- --argc;
- }
- for (int j = func->actualMinimumArgumentCount(); j <= argc; ++j)
- result[j].append(func);
- }
- return result;
-}
-
-/*!
- Returns the name of the QScriptValue function to use to test if
- a value is of the given \a typeName, or an empty string if there
- is no such function.
-*/
-static QString builtinTypeTesterFunction(const QString &typeName)
-{
- if (typeName == QLatin1String("QString"))
- return QLatin1String("isString");
- else if (typeName == QLatin1String("double"))
- return QLatin1String("isNumber");
- else if (typeName == QLatin1String("float"))
- return QLatin1String("isNumber");
- else if (typeName == QLatin1String("int"))
- return QLatin1String("isNumber");
- else if (typeName == QLatin1String("uint"))
- return QLatin1String("isNumber");
- else if (typeName == QLatin1String("short"))
- return QLatin1String("isNumber");
- else if (typeName == QLatin1String("unsigned short"))
- return QLatin1String("isNumber");
- else if (typeName == QLatin1String("bool"))
- return QLatin1String("isBoolean");
- else if (typeName == QLatin1String("QVariant"))
- return QLatin1String("isVariant");
-// else if (typeName == QLatin1String("QDateTime"))
-// return QLatin1String("isDate");
- else if (typeName == QLatin1String("QRegExp"))
- return QLatin1String("isRegExp");
- else if (typeName == QLatin1String("QObject*"))
- return QLatin1String("isQObject");
- return QString();
-}
-
-/*!
- Writes the code injections for the class \a meta_class that should
- be injected at position \a pos.
-*/
-static void writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class,
- CodeSnip::Position pos)
-{
- CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
- foreach (const CodeSnip &cs, code_snips) {
- if ((cs.language == TypeSystem::NativeCode) && (cs.position == pos)) {
- s << cs.code() << endl;
- }
- }
-}
-
-/*!
- Writes the code injections for the function \a fun of the class \a
- meta_class that should be injected at position \a pos.
-*/
-static void writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class,
- const AbstractMetaFunction *fun, CodeSnip::Position pos)
-{
- FunctionModificationList mods = fun->modifications(meta_class);
- foreach (const FunctionModification &mod, mods) {
- if (!mod.isCodeInjection())
- continue;
- foreach (const CodeSnip &cs, mod.snips) {
- if ((cs.language == TypeSystem::NativeCode) && (cs.position == pos)) {
- s << cs.code() << endl;
- }
- }
- }
-}
-
-/*!
- Writes a boolean expression that checks if the actual arguments are
- compatible with what the function expects. This is used to resolve
- ambiguous calls.
-*/
-static void writeArgumentTypeTests(QTextStream &stream, const AbstractMetaFunction *fun,
- const AbstractMetaArgumentList &arguments, int argc, int indent)
-{
- QString indentStr(indent, QLatin1Char(' '));
- int j = 0;
- for (int i = 0; i < argc; ++j) {
- if (fun->argumentRemoved(j+1))
- continue;
- if (i > 0)
- stream << endl << indentStr << "&& ";
- const AbstractMetaType *argType = 0;
- QString typeName = fun->typeReplaced(j+1);
- if (typeName.isEmpty()) {
- AbstractMetaArgument *arg = arguments.at(j);
- argType = arg->type();
- typeName = normalizedType(argType);
- }
- QString scriptArg = QString::fromLatin1("context->argument(%0)").arg(i);
- if (argType && isSequenceType(argType)) {
- stream << scriptArg << ".isArray()";
- } else if (typeName == "QVariant") {
- stream << "true";
- } else {
- QString tester = builtinTypeTesterFunction(typeName);
- if (!tester.isEmpty()) {
- stream << scriptArg << "." << tester << "()";
- } else if (typeName.endsWith('*')) {
- stream << "qscriptvalue_cast<" << typeName << ">(" << scriptArg << ")";
- } else {
- // typeid-based test
- stream << "(qMetaTypeId<" << typeName;
- if (typeName.endsWith(QLatin1Char('>')))
- stream << " ";
- stream << ">() == " << scriptArg << ".toVariant().userType())";
- }
- }
- ++i;
- }
-}
-
-/*!
- Returns the name of the QScriptValue function to use to convert a
- value is of the given \a typeName, or an empty string if there is no
- such function.
-*/
-static QString builtinConversionFunction(const QString &typeName)
-{
- if (typeName == QLatin1String("QString"))
- return QLatin1String("toString");
- else if (typeName == QLatin1String("double"))
- return QLatin1String("toNumber");
- else if (typeName == QLatin1String("int"))
- return QLatin1String("toInt32");
- else if (typeName == QLatin1String("uint"))
- return QLatin1String("toUInt32");
- else if (typeName == QLatin1String("bool"))
- return QLatin1String("toBoolean");
- else if (typeName == QLatin1String("QVariant"))
- return QLatin1String("toVariant");
- else if (typeName == QLatin1String("QDateTime"))
- return QLatin1String("toDateTime");
- else if (typeName == QLatin1String("QRegExp"))
- return QLatin1String("toRegExp");
- else if (typeName == QLatin1String("QObject*"))
- return QLatin1String("toQObject");
- return QString();
-}
-
-/*!
- Generates script arguments --> C++ types conversion, in preparation
- for calling the native function we are binding.
-*/
-static int writePrepareArguments(QTextStream &stream, const AbstractMetaFunction *fun,
- const AbstractMetaArgumentList &arguments,
- int scriptArgc, int indent)
-{
- if (arguments.size() == 0) {
- Q_ASSERT(scriptArgc == 0);
- return 0; // nothing to do
- }
- QString indentStr(indent, QLatin1Char(' '));
- int j = 0;
- for (int scriptArgIndex = 0; j < arguments.size(); ++j) {
- const AbstractMetaArgument *arg = arguments.at(j);
- bool isOptional = !arg->defaultValueExpression().isEmpty();
- if (isOptional && (scriptArgIndex == scriptArgc))
- break;
- QString conv = fun->conversionRule(TypeSystem::NativeCode, j+1);
- QString actualIn = QString::fromLatin1("context->argument(%0)").arg(scriptArgIndex);
- QString actualOut = QString::fromLatin1("_q_arg%0").arg(j);
- if (!conv.isEmpty()) {
- // custom conversion
- conv.replace(QString::fromLatin1("%in%"), actualIn);
- conv.replace(QString::fromLatin1("%out%"), actualOut);
- conv.replace(QString::fromLatin1("%this%"), QString::fromLatin1("_q_self"));
- stream << conv;
- } else {
- const AbstractMetaType *argType = 0;
- QString typeName = fun->typeReplaced(j+1);
- if (typeName.isEmpty()) {
- argType = arg->type();
- typeName = normalizedType(argType);
- }
- stream << indentStr << typeName << " " << actualOut;
- QString converter;
- // ### generalize the QSet check (we should check if the type has push_back())
- bool useToSequence = argType && isSequenceType(argType) && !argType->name().startsWith("Set");
- if (useToSequence) {
- stream << ";" << endl;
- stream << indentStr << "qScriptValueToSequence(";
- } else {
- stream << " = ";
- converter = builtinConversionFunction(typeName);
- if (converter.isEmpty()) {
- // generic conversion
- stream << "qscriptvalue_cast<" << typeName;
- if (typeName.endsWith(QLatin1Char('>')))
- stream << " ";
- stream << ">(";
- }
- }
- stream << actualIn;
- if (useToSequence) {
- stream << ", " << actualOut << ")";
- } else {
- if (converter.isEmpty()) {
- stream << ")"; // close qscriptvalue_cast
- } else {
- stream << "." << converter << "()";
- }
- }
- stream << ";" << endl;
- }
- if (!fun->argumentRemoved(j+1))
- ++scriptArgIndex;
- }
- return j;
-}
-
-/*!
- Writes the arguments that are passed to the native function we are
- binding. Those arguments must have been prepared already in variables
- _q_arg0, _q_arg1, .. in the generated code.
-*/
-static void writeArguments(QTextStream &stream, int count)
-{
- for (int i = 0; i < count; ++i) {
- if (i > 0)
- stream << ", ";
- stream << "_q_arg" << i;
- }
-}
-
-/*!
- Writes a constructor call.
-*/
-static void writeConstructorCallAndReturn(QTextStream &stream, const AbstractMetaFunction *fun,
- int scriptArgc, const AbstractMetaClass *meta_class,
- int indent)
-{
- QString indentStr(indent, QLatin1Char(' '));
-
- writeInjectedCode(stream, meta_class, fun, CodeSnip::Beginning);
-
- AbstractMetaArgumentList arguments = fun->arguments();
- Q_ASSERT(arguments.size() >= scriptArgc);
- int nativeArgc = writePrepareArguments(stream, fun, arguments, scriptArgc, indent);
- stream << indentStr;
- if (meta_class->generateShellClass()) {
- stream << "QtScriptShell_" << meta_class->name();
- } else {
- stream << meta_class->qualifiedCppName();
- }
- bool useNew = meta_class->typeEntry()->isObject() || !hasDefaultConstructor(meta_class);
- if (useNew)
- stream << "*";
- stream << " _q_cpp_result";
- if (useNew) {
- stream << " = new ";
- if (meta_class->generateShellClass())
- stream << "QtScriptShell_" << meta_class->name();
- else
- stream << meta_class->qualifiedCppName();
- }
- if (useNew || (nativeArgc != 0)) {
- stream << "(";
- writeArguments(stream, nativeArgc);
- stream << ")";
- }
- stream << ";" << endl;
-
- stream << indentStr << "QScriptValue _q_result = context->engine()->new";
- if (isQObjectBased(meta_class))
- stream << "QObject";
- else
- stream << "Variant";
- stream << "(context->thisObject(), ";
- if (!isQObjectBased(meta_class))
- stream << "qVariantFromValue(";
- if (meta_class->generateShellClass()) {
- stream << "(" << meta_class->qualifiedCppName();
- if (useNew)
- stream << "*";
- stream << ")";
- }
- stream << "_q_cpp_result";
- if (isQObjectBased(meta_class))
- stream << ", QScriptEngine::AutoOwnership";
- else
- stream << ")";
- stream << ");" << endl;
- if (meta_class->generateShellClass()) {
- stream << indentStr << "_q_cpp_result";
- if (useNew)
- stream << "->";
- else
- stream << ".";
- stream << "__qtscript_self = _q_result;" << endl;
- }
-
- writeInjectedCode(stream, meta_class, fun, CodeSnip::End);
-
- stream << indentStr << "return _q_result;" << endl;
-}
-
-/*!
- Returns true if the given \a typeName has a QScriptValue constructor
- we can use, false otherwise.
-*/
-static bool hasScriptValueConstructor(const QString &typeName)
-{
- return (typeName == QLatin1String("bool"))
- || (typeName == QLatin1String("int"))
- || (typeName == QLatin1String("uint"))
- || (typeName == QLatin1String("double"))
- || (typeName == QLatin1String("QString"));
-}
-
-/*!
- Writes a function call.
-*/
-static void writeFunctionCallAndReturn(QTextStream &stream, const AbstractMetaFunction *fun,
- int scriptArgc, const AbstractMetaClass *meta_class,
- int indent)
-{
- QString indentStr(indent, QLatin1Char(' '));
- AbstractMetaArgumentList arguments = fun->arguments();
- Q_ASSERT(arguments.size() >= scriptArgc);
-
- writeInjectedCode(stream, meta_class, fun, CodeSnip::Beginning);
-
- int nativeArgc = writePrepareArguments(stream, fun, arguments, scriptArgc, indent);
- bool returnThisObject = fun->shouldReturnThisObject();
- bool ignoreReturnValue = returnThisObject || fun->shouldIgnoreReturnValue();
- stream << indentStr;
- AbstractMetaType *retType = fun->type();
- bool constCastResult = false;
- if (retType && !ignoreReturnValue) {
- QString rsig = retType->cppSignature();
- QString typeName = normalizedType(retType);
- stream << typeName << " _q_result = ";
- constCastResult = rsig.endsWith('*') && rsig.startsWith("const ");
- if (constCastResult)
- stream << "const_cast<" << typeName << ">(";
- }
-
- if (!fun->isStatic()) {
- // ### the friendly check should be enough...
- if (fun->isFriendly()
- || ((fun->name() == QLatin1String("operator_equal"))
- && ((meta_class->name() == QLatin1String("QPoint"))
- || (meta_class->name() == QLatin1String("QPointF"))
- || (meta_class->name() == QLatin1String("QRect"))
- || (meta_class->name() == QLatin1String("QRectF"))
- || (meta_class->name() == QLatin1String("QSize"))
- || (meta_class->name() == QLatin1String("QSizeF"))))) {
- stream << fun->originalName() << "(";
- stream << "*_q_self, ";
- } else {
- stream << "_q_self->";
- stream << fun->originalName() << "(";
- }
- } else {
- stream << meta_class->qualifiedCppName() << "::";
- stream << fun->originalName() << "(";
- }
- writeArguments(stream, nativeArgc);
- if (constCastResult)
- stream << ")";
- stream << ");" << endl;
-
- writeInjectedCode(stream, meta_class, fun, CodeSnip::End);
-
- // write return statement
- stream << indentStr;
- if (returnThisObject) {
- stream << "return context->thisObject();";
- } else {
- QString conv = fun->conversionRule(TypeSystem::NativeCode, 0);
- if (!conv.isEmpty()) {
- // custom conversion
- conv.replace(QString::fromLatin1("%in%"), "_q_result");
- conv.replace(QString::fromLatin1("%out%"), "_q_convertedResult");
- stream << conv;
- stream << "return qScriptValueFromValue(context->engine(), _q_convertedResult);";
- } else {
- stream << "return ";
- if (retType) {
- if (isSequenceType(retType))
- stream << "qScriptValueFromSequence";
- else if (hasScriptValueConstructor(normalizedType(retType)))
- stream << "QScriptValue";
- else
- stream << "qScriptValueFromValue";
- stream << "(context->engine(), _q_result);";
- } else {
- stream << "context->engine()->undefinedValue();";
- }
- }
- }
- stream << endl;
-}
-
-/*!
- Returns true if the given function \a fun is operator>>() or
- operator<<() that streams from/to a Q{Data,Text}Stream, false
- otherwise.
-*/
-bool ClassGenerator::isSpecialStreamingOperator(const AbstractMetaFunction *fun)
-{
- return ((fun->functionType() == AbstractMetaFunction::GlobalScopeFunction)
- && (fun->arguments().size() == 1)
- && (((fun->originalName() == "operator>>") && (fun->modifiedName() == "readFrom"))
- || ((fun->originalName() == "operator<<") && (fun->modifiedName() == "writeTo"))));
-}
-
-/*!
- Generates code that uses Q{Data,Text}Stream operator>>() or
- operator<<() to read/write an instance of meta_class.
-*/
-static void writeStreamingOperatorCall(QTextStream &stream, const AbstractMetaFunction *fun,
- const AbstractMetaClass * /*meta_class*/, int indent)
-{
- QString indentStr(indent, QLatin1Char(' '));
- QString streamClassName = fun->arguments().at(0)->type()->name();
- stream << indentStr << streamClassName << "* _q_arg0 = qscriptvalue_cast<"
- << streamClassName << "*>(context->argument(0));" << endl;
- stream << indentStr << "operator";
- if (fun->modifiedName() == "readFrom")
- stream << ">>";
- else
- stream << "<<";
- stream << "(*_q_arg0, *_q_self);" << endl;
- stream << indentStr << "return context->engine()->undefinedValue();" << endl;
-}
-
-/*!
- Writes the constructor forwarding for \a meta_class.
-*/
-static void writeConstructorForwarding(QTextStream &stream,
- const AbstractMetaFunctionList &functions,
- const AbstractMetaClass *meta_class)
-{
-#if 0
- stream << "/** signatures:" << endl;
- foreach (const AbstractMetaFunction *fun, functions) {
- stream << " * " << fun->signature() << endl;
- }
- stream << " */" << endl;
-#endif
-
- if (/*meta_class->isAbstract() ||*/ (functions.size() == 0)) {
- stream << " return context->throwError(QScriptContext::TypeError," << endl
- << " QString::fromLatin1(\"" << meta_class->name()
- << " cannot be constructed\"));" << endl;
-
- } else {
- stream << " if (context->thisObject().strictlyEquals(context->engine()->globalObject())) {" << endl
- << " return context->throwError(QString::fromLatin1(\""
- << meta_class->name() << "(): Did you forget to construct with 'new'?\"));" << endl
- << " }" << endl;
-
- writeInjectedCode(stream, meta_class, CodeSnip::Constructor);
-
- QMap argcToFunctions;
- argcToFunctions = createArgcToFunctionsMap(functions);
-
- int argcMin = argcToFunctions.keys().first();
- int argcMax = argcToFunctions.keys().last();
- bool needElse = false;
- for (int i = argcMin; i <= argcMax; ++i) {
- AbstractMetaFunctionList funcs = argcToFunctions.value(i);
- if (funcs.isEmpty())
- continue;
- if (needElse)
- stream << " else ";
- else
- stream << " ";
- needElse = true;
- stream << "if (context->argumentCount() == " << i << ") {" << endl;
- if ((funcs.size() == 1) || (i == 0)) {
- AbstractMetaFunction *fun = funcs.at(0);
- const int indent = 8;
- writeConstructorCallAndReturn(stream, fun, i, meta_class, indent);
- } else {
- // handle overloads
- for (int j = 0; j < funcs.size(); ++j) {
- AbstractMetaFunction *fun = funcs.at(j);
- stream << " ";
- if (j > 0)
- stream << "} else ";
- stream << "if (";
- AbstractMetaArgumentList arguments = fun->arguments();
- const int indent = 12;
- writeArgumentTypeTests(stream, fun, arguments, i, indent);
- stream << ") {" << endl;
- writeConstructorCallAndReturn(stream, fun, i, meta_class, indent);
- }
- stream << " }" << endl;
- }
- stream << " }";
- }
- stream << endl;
-// writeThrowAmbiguityError(stream, meta_class, 0, signatures.toList());
- }
-}
-
-/*!
- Returns a list of enum \a values that are actually unique.
- */
-QList uniqueEnumValueIndexes(const AbstractMetaEnumValueList &values)
-{
- QMap map;
- for (int i = 0; i < values.count(); ++i) {
- AbstractMetaEnumValue *val = values.at(i);
- if (!map.contains(val->value()))
- map.insert(val->value(), i);
- }
- return map.values();
-}
-
-/*!
- */
-static bool isContiguousEnum(const QList &indexes, const AbstractMetaEnumValueList &values)
-{
- if (indexes.isEmpty())
- return false;
- int prev = values.at(indexes.at(0))->value();
- for (int i = 1; i < indexes.size(); ++i) {
- int curr = values.at(indexes.at(i))->value();
- if (curr != prev + 1)
- return false;
- prev = curr;
- }
- return true;
-}
-
-static void writeCreateEnumClassHelper(QTextStream &stream)
-{
- stream << "static QScriptValue qtscript_create_enum_class_helper(" << endl
- << " QScriptEngine *engine," << endl
- << " QScriptEngine::FunctionSignature construct," << endl
- << " QScriptEngine::FunctionSignature valueOf," << endl
- << " QScriptEngine::FunctionSignature toString)" << endl
- << "{" << endl
- << " QScriptValue proto = engine->newObject();" << endl
- << " proto.setProperty(QString::fromLatin1(\"valueOf\")," << endl
- << " engine->newFunction(valueOf), QScriptValue::SkipInEnumeration);" << endl
- << " proto.setProperty(QString::fromLatin1(\"toString\")," << endl
- << " engine->newFunction(toString), QScriptValue::SkipInEnumeration);" << endl
- << " return engine->newFunction(construct, proto, 1);" << endl
- << "}" << endl << endl;
-}
-
-static void writeCreateFlagsClassHelper(QTextStream &stream)
-{
- stream << "static QScriptValue qtscript_create_flags_class_helper(" << endl
- << " QScriptEngine *engine," << endl
- << " QScriptEngine::FunctionSignature construct," << endl
- << " QScriptEngine::FunctionSignature valueOf," << endl
- << " QScriptEngine::FunctionSignature toString," << endl
- << " QScriptEngine::FunctionSignature equals)" << endl
- << "{" << endl
- << " QScriptValue proto = engine->newObject();" << endl
- << " proto.setProperty(QString::fromLatin1(\"valueOf\")," << endl
- << " engine->newFunction(valueOf), QScriptValue::SkipInEnumeration);" << endl
- << " proto.setProperty(QString::fromLatin1(\"toString\")," << endl
- << " engine->newFunction(toString), QScriptValue::SkipInEnumeration);" << endl
- << " proto.setProperty(QString::fromLatin1(\"equals\")," << endl
- << " engine->newFunction(equals), QScriptValue::SkipInEnumeration);" << endl
- << " return engine->newFunction(construct, proto);" << endl
- << "}" << endl << endl;
-}
-
-/*!
- Writes the enum \a enom belonging to the class \a meta_class to the
- given \a stream.
- */
-static void writeEnumClass(QTextStream &stream, const AbstractMetaClass *meta_class,
- const AbstractMetaEnum *enom)
-{
- QString qualifiedCppNameColons;
- if (meta_class->name() != "Global")
- qualifiedCppNameColons = meta_class->qualifiedCppName() + "::";
- QString qualifiedEnumName = qualifiedCppNameColons + enom->name();
- QString qtScriptEnumName = meta_class->name() + "_" + enom->name();
-
- stream << "//" << endl;
- stream << "// " << qualifiedEnumName << endl;
- stream << "//" << endl << endl;
-
- // determine unique values (aliases will cause switch statement to not compile)
- AbstractMetaEnumValueList values = enom->values();
- QList uniqueIndexes = uniqueEnumValueIndexes(values);
-
- bool contiguous = isContiguousEnum(uniqueIndexes, values);
-
- // write arrays of values and keys
- stream << "static const " << qualifiedEnumName
- << " qtscript_" << qtScriptEnumName << "_values[] = {" << endl;
- for (int i = 0; i < uniqueIndexes.size(); ++i) {
- stream << " ";
- if (i > 0)
- stream << ", ";
- stream << qualifiedCppNameColons << values.at(uniqueIndexes.at(i))->name() << endl;
- }
- stream << "};" << endl << endl;
- stream << "static const char * const qtscript_" << qtScriptEnumName << "_keys[] = {" << endl;
- for (int i = 0; i < uniqueIndexes.size(); ++i) {
- stream << " ";
- if (i > 0)
- stream << ", ";
- stream << "\"" << values.at(uniqueIndexes.at(i))->name() << "\"" << endl;
- }
- stream << "};" << endl << endl;
-
- // write toString helper
- stream << "static QString qtscript_"
- << qtScriptEnumName << "_toStringHelper"
- << "(" << qualifiedEnumName << " value)" << endl;
- stream << "{" << endl;
- if (enom->hasQEnumsDeclaration() && (meta_class->qualifiedCppName() != "QTransform")) {
- stream << " const QMetaObject *meta = qtscript_" << meta_class->name() << "_metaObject();" << endl;
- stream << " int idx = meta->indexOfEnumerator(\"" << enom->name() << "\");" << endl;
- stream << " Q_ASSERT(idx != -1);" << endl;
- stream << " QMetaEnum menum = meta->enumerator(idx);" << endl;
- stream << " return QString::fromLatin1(menum.valueToKey(value));" << endl;
- } else {
- if (contiguous) {
- stream << " if ((value >= " << qualifiedCppNameColons
- << values.at(uniqueIndexes.first())->name() << ")"
- << " && (value <= " << qualifiedCppNameColons
- << values.at(uniqueIndexes.last())->name() << "))" << endl
- << " return qtscript_" << qtScriptEnumName
- << "_keys[static_cast(value)-static_cast("
- << qualifiedCppNameColons
- << values.at(uniqueIndexes.first())->name() << ")];" << endl;
- } else {
- stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
- << " if (qtscript_" << qtScriptEnumName << "_values[i] == value)" << endl
- << " return QString::fromLatin1(qtscript_" << qtScriptEnumName << "_keys[i]);" << endl
- << " }" << endl;
- }
- stream << " return QString();" << endl;
- }
- stream << "}" << endl << endl;
-
- // write QScriptValue <--> C++ conversion functions
- stream << "static QScriptValue qtscript_"
- << qtScriptEnumName << "_toScriptValue("
- << "QScriptEngine *engine, const " << qualifiedEnumName << " &value)" << endl
- << "{" << endl
- << " QScriptValue clazz = engine->globalObject().property(QString::fromLatin1(\""
- << meta_class->name() << "\"));" << endl
-// << " QScriptValue enumClazz = clazz.property(QString::fromLatin1(\""
-// << enom->name() << "\"));" << endl
- << " return clazz.property(qtscript_" << qtScriptEnumName << "_toStringHelper(value));" << endl
- << "}" << endl << endl;
- stream << "static void qtscript_"
- << qtScriptEnumName << "_fromScriptValue("
- << "const QScriptValue &value, " << qualifiedEnumName << " &out)" << endl
- << "{" << endl
- << " out = qvariant_cast<" << qualifiedEnumName << ">(value.toVariant());" << endl
- << "}" << endl << endl;
-
- // write constructor
- stream << "static QScriptValue qtscript_construct_"
- << qtScriptEnumName
- << "(QScriptContext *context, QScriptEngine *engine)" << endl;
- stream << "{" << endl;
- stream << " int arg = context->argument(0).toInt32();" << endl;
- if (enom->hasQEnumsDeclaration() && (meta_class->qualifiedCppName() != "QTransform")) {
- stream << " const QMetaObject *meta = qtscript_" << meta_class->name() << "_metaObject();" << endl;
- stream << " int idx = meta->indexOfEnumerator(\"" << enom->name() << "\");" << endl;
- stream << " Q_ASSERT(idx != -1);" << endl;
- stream << " QMetaEnum menum = meta->enumerator(idx);" << endl;
- stream << " if (menum.valueToKey(arg) != 0)" << endl;
- stream << " return qScriptValueFromValue(engine, static_cast<"
- << qualifiedEnumName << ">(arg));" << endl;
- } else {
- if (contiguous) {
- stream << " if ((arg >= " << qualifiedCppNameColons
- << values.at(uniqueIndexes.first())->name() << ")"
- << " && (arg <= " << qualifiedCppNameColons
- << values.at(uniqueIndexes.last())->name() << "))" << endl;
- stream << " return qScriptValueFromValue(engine, static_cast<"
- << qualifiedEnumName << ">(arg));" << endl;
- } else {
- stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
- << " if (qtscript_" << qtScriptEnumName << "_values[i] == arg)" << endl;
- stream << " return qScriptValueFromValue(engine, static_cast<"
- << qualifiedEnumName << ">(arg));" << endl;
- stream << " }" << endl;
- }
- }
- stream << " return context->throwError(QString::fromLatin1(\""
- << enom->name() << "(): invalid enum value (%0)\").arg(arg));" << endl;
- stream << "}" << endl;
- stream << endl;
-
- // write prototype.valueOf()
- stream << "static QScriptValue qtscript_" << qtScriptEnumName
- << "_valueOf(QScriptContext *context, QScriptEngine *engine)" << endl;
- stream << "{" << endl;
- stream << " " << qualifiedEnumName << " value = "
- << "qscriptvalue_cast<" << qualifiedEnumName
- << ">(context->thisObject());" << endl;
- stream << " return QScriptValue(engine, static_cast(value));" << endl;
- stream << "}" << endl;
- stream << endl;
-
- // write prototype.toString()
- stream << "static QScriptValue qtscript_" << qtScriptEnumName
- << "_toString(QScriptContext *context, QScriptEngine *engine)" << endl;
- stream << "{" << endl;
- stream << " " << qualifiedEnumName << " value = "
- << "qscriptvalue_cast<" << qualifiedEnumName
- << ">(context->thisObject());" << endl;
- stream << " return QScriptValue(engine, qtscript_" << qtScriptEnumName << "_toStringHelper(value));" << endl;
- stream << "}" << endl;
- stream << endl;
-
- // write class creation function
- stream << "static QScriptValue qtscript_create_"
- << qtScriptEnumName
- << "_class(QScriptEngine *engine, QScriptValue &clazz)" << endl;
- stream << "{" << endl;
-
- stream << " QScriptValue ctor = qtscript_create_enum_class_helper(" << endl
- << " engine, qtscript_construct_" << qtScriptEnumName << "," << endl
- << " qtscript_" << qtScriptEnumName << "_valueOf, qtscript_"
- << qtScriptEnumName << "_toString);" << endl;
-
- stream << " qScriptRegisterMetaType<" << qualifiedEnumName << ">(engine, "
- << "qtscript_" << qtScriptEnumName << "_toScriptValue," << endl
- << " qtscript_" << qtScriptEnumName << "_fromScriptValue,"
- << " ctor.property(QString::fromLatin1(\"prototype\")));" << endl;
-
- // enum values are properties of the constructor
- stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
- << " clazz.setProperty(QString::fromLatin1(qtscript_"
- << qtScriptEnumName << "_keys[i])," << endl
- << " engine->newVariant(qVariantFromValue(qtscript_"
- << qtScriptEnumName << "_values[i]))," << endl
- << " QScriptValue::ReadOnly | QScriptValue::Undeletable);" << endl
- << " }" << endl;
-
- stream << " return ctor;" << endl;
- stream << "}" << endl;
- stream << endl;
-
- // write flags class too, if any
- FlagsTypeEntry *flags = enom->typeEntry()->flags();
- if (!flags)
- return;
-
- QString qualifiedFlagsName = qualifiedCppNameColons + flags->targetLangName();
- QString qtScriptFlagsName = meta_class->name() + "_" + flags->targetLangName();
-
- stream << "//" << endl;
- stream << "// " << qualifiedFlagsName << endl;
- stream << "//" << endl << endl;
-
- // write QScriptValue <--> C++ conversion functions
- stream << "static QScriptValue qtscript_"
- << qtScriptFlagsName << "_toScriptValue("
- << "QScriptEngine *engine, const " << qualifiedFlagsName << " &value)" << endl
- << "{" << endl
- << " return engine->newVariant(qVariantFromValue(value));" << endl
- << "}" << endl << endl;
- stream << "static void qtscript_"
- << qtScriptFlagsName << "_fromScriptValue("
- << "const QScriptValue &value, " << qualifiedFlagsName << " &out)" << endl
- << "{" << endl
- << " QVariant var = value.toVariant();" << endl
- << " if (var.userType() == qMetaTypeId<" << qualifiedFlagsName << ">())" << endl
- << " out = qvariant_cast<" << qualifiedFlagsName << ">(var);" << endl
- << " else if (var.userType() == qMetaTypeId<" << qualifiedEnumName << ">())" << endl
- << " out = qvariant_cast<" << qualifiedEnumName << ">(var);" << endl
- << " else" << endl
- << " out = 0;" << endl
- << "}" << endl << endl;
-
- // write constructor
- stream << "static QScriptValue qtscript_construct_"
- << qtScriptFlagsName
- << "(QScriptContext *context, QScriptEngine *engine)" << endl;
- stream << "{" << endl;
- stream << " " << qualifiedFlagsName << " result = 0;" << endl;
- stream << " if ((context->argumentCount() == 1) && context->argument(0).isNumber()) {" << endl;
- stream << " result = static_cast<" << qualifiedFlagsName << ">(context->argument(0).toInt32());" << endl;
- stream << " } else {" << endl;
- stream << " for (int i = 0; i < context->argumentCount(); ++i) {" << endl;
- stream << " QVariant v = context->argument(i).toVariant();" << endl;
- stream << " if (v.userType() != qMetaTypeId<" << qualifiedEnumName << ">()) {" << endl;
- stream << " return context->throwError(QScriptContext::TypeError," << endl
- << " QString::fromLatin1(\"" << flags->targetLangName()
- << "(): argument %0 is not of type " << enom->name() << "\").arg(i));" << endl;
- stream << " }" << endl;
- stream << " result |= qvariant_cast<" << qualifiedEnumName
- << ">(v);" << endl;
- stream << " }" << endl;
- stream << " }" << endl;
- stream << " return engine->newVariant(qVariantFromValue(result));" << endl;
- stream << "}" << endl;
- stream << endl;
-
- // write prototype.valueOf()
- stream << "static QScriptValue qtscript_" << qtScriptFlagsName
- << "_valueOf(QScriptContext *context, QScriptEngine *engine)" << endl;
- stream << "{" << endl;
- stream << " " << qualifiedFlagsName << " value = "
- << "qscriptvalue_cast<" << qualifiedFlagsName
- << ">(context->thisObject());" << endl;
- stream << " return QScriptValue(engine, static_cast(value));" << endl;
- stream << "}" << endl;
- stream << endl;
-
- // write prototype.toString()
- stream << "static QScriptValue qtscript_" << qtScriptFlagsName
- << "_toString(QScriptContext *context, QScriptEngine *engine)" << endl;
- stream << "{" << endl;
- stream << " " << qualifiedFlagsName << " value = "
- << "qscriptvalue_cast<" << qualifiedFlagsName
- << ">(context->thisObject());" << endl;
- stream << " QString result;" << endl;
- stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
- << " if ((value & qtscript_" << qtScriptEnumName << "_values[i])"
- << " == qtscript_" << qtScriptEnumName << "_values[i]) {" << endl
- << " if (!result.isEmpty())" << endl
- << " result.append(QString::fromLatin1(\",\"));" << endl
- << " result.append(QString::fromLatin1(qtscript_" << qtScriptEnumName << "_keys[i]));" << endl
- << " }" << endl
- << " }" << endl
- << " return QScriptValue(engine, result);" << endl
- << "}" << endl
- << endl;
-
- // write prototype.equals()
- stream << "static QScriptValue qtscript_" << qtScriptFlagsName
- << "_equals(QScriptContext *context, QScriptEngine *engine)" << endl
- << "{" << endl
- << " QVariant thisObj = context->thisObject().toVariant();" << endl
- << " QVariant otherObj = context->argument(0).toVariant();" << endl
-
- << " return QScriptValue(engine, ((thisObj.userType() == otherObj.userType()) &&" << endl
- << " (thisObj.value<" << qualifiedFlagsName << ">() == otherObj.value<" << qualifiedFlagsName << ">())));" << endl
- << "}" << endl << endl;
-
- // write class creation function
- stream << "static QScriptValue qtscript_create_" << qtScriptFlagsName << "_class(QScriptEngine *engine)" << endl;
- stream << "{" << endl;
- stream << " QScriptValue ctor = qtscript_create_flags_class_helper(" << endl
- << " engine, qtscript_construct_" << qtScriptFlagsName
- << ", qtscript_" << qtScriptFlagsName << "_valueOf," << endl
- << " qtscript_" << qtScriptFlagsName << "_toString, qtscript_"
- << qtScriptFlagsName << "_equals);" << endl;
-
- stream << " qScriptRegisterMetaType<" << qualifiedFlagsName << ">(engine, "
- << "qtscript_" << qtScriptFlagsName << "_toScriptValue," << endl
- << " qtscript_" << qtScriptFlagsName << "_fromScriptValue,"
- << " ctor.property(QString::fromLatin1(\"prototype\")));" << endl;
-
- stream << " return ctor;" << endl;
- stream << "}" << endl;
- stream << endl;
-}
-
-/*!
- Declares the given \a typeName if it hasn't been declared already,
- and adds it to the set of registered type names.
-*/
-void maybeDeclareMetaType(QTextStream &stream, const QString &typeName,
- QSet ®isteredTypeNames)
-{
- QString name = typeName;
- if (name.endsWith(QLatin1Char('&')))
- name.chop(1);
- if (registeredTypeNames.contains(name) || (QMetaType::type(typeName.toLatin1()) != 0))
- return;
- if (name.contains(QLatin1Char(','))) {
- // need to expand the Q_DECLARE_METATYPE macro manually,
- // otherwise the compiler will choke
- stream << "template <> \\" << endl
- << "struct QMetaTypeId< " << name << " > \\" << endl
- << "{ \\" << endl
- << " enum { Defined = 1 }; \\" << endl
- << " static int qt_metatype_id() \\" << endl
- << " { \\" << endl
- << " static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \\" << endl
- << " if (!metatype_id) \\" << endl
- << " metatype_id = qRegisterMetaType< " << name << " >(\"" << name << "\"); \\" << endl
- << " return metatype_id; \\" << endl
- << " } \\" << endl
- << "};" << endl;
- } else {
- stream << "Q_DECLARE_METATYPE(" << name << ")" << endl;
- }
- registeredTypeNames << name;
-}
-
-/*!
- Declares the given \a type recursively (i.e. subtypes of a composite
- type are also declared).
-*/
-static void declareTypeRecursive(QTextStream &stream, const AbstractMetaType *type,
- QSet ®isteredTypeNames)
-{
- if (!type)
- return;
- QList subTypes = type->instantiations();
- for (int i = 0; i < subTypes.size(); ++i)
- declareTypeRecursive(stream, subTypes.at(i), registeredTypeNames);
- QString typeName = normalizedType(type);
- if (typeName == QLatin1String("QStringList"))
- return; // ### wtf...
- maybeDeclareMetaType(stream, typeName, registeredTypeNames);
-}
-
-/*!
- Declares the types associated with the given \a functions.
-*/
-void declareFunctionMetaTypes(QTextStream &stream, const AbstractMetaFunctionList &functions,
- QSet ®isteredTypeNames)
-{
- for (int i = 0; i < functions.size(); ++i) {
- AbstractMetaFunction *fun = functions.at(i);
- if (ClassGenerator::isSpecialStreamingOperator(fun)) {
- maybeDeclareMetaType(stream, fun->arguments().at(0)->type()->name() + "*",
- registeredTypeNames);
- continue;
- }
- AbstractMetaArgumentList arguments = fun->arguments();
- for (int j = 0; j < arguments.size(); ++j) {
- if (fun->argumentRemoved(j+1))
- continue;
- QString repl = fun->typeReplaced(j+1);
- if (!repl.isEmpty()) {
- maybeDeclareMetaType(stream, repl, registeredTypeNames);
- } else {
- const AbstractMetaArgument *arg = arguments.at(j);
- declareTypeRecursive(stream, arg->type(), registeredTypeNames);
- }
- }
- QString retRepl = fun->typeReplaced(0);
- if (!retRepl.isEmpty())
- maybeDeclareMetaType(stream, retRepl, registeredTypeNames);
- else
- declareTypeRecursive(stream, fun->type(), registeredTypeNames);
- }
-}
-
-/*!
- Returns true if we don't care about the given enum \a enom,
- false otherwise.
-*/
-static bool shouldIgnoreEnum(const AbstractMetaEnum *enom)
-{
- return !enom->wasPublic() || (enom->name() == "enum_1");
-}
-
-/*!
- Declares the types associated with the enums of the given \a
- meta_class.
-*/
-void declareEnumMetaTypes(QTextStream &stream, const AbstractMetaClass *meta_class,
- QSet ®isteredTypeNames)
-{
- AbstractMetaEnumList enums = meta_class->enums();
- for (int i = 0; i < enums.size(); ++i) {
- const AbstractMetaEnum *enom = enums.at(i);
- if (shouldIgnoreEnum(enom))
- continue;
- if (meta_class->name() == "Global")
- maybeDeclareMetaType(stream, enom->name(), registeredTypeNames);
- else
- maybeDeclareMetaType(stream, QString::fromLatin1("%0::%1")
- .arg(meta_class->qualifiedCppName()).arg(enom->name()),
- registeredTypeNames);
- FlagsTypeEntry *flags = enom->typeEntry()->flags();
- if (flags) {
- maybeDeclareMetaType(stream, QString::fromLatin1("QFlags<%0::%1>")
- .arg(meta_class->qualifiedCppName()).arg(enom->name()),
- registeredTypeNames);
- }
- }
-}
-
-/*!
- Returns the maximum function length among \a functions.
-*/
-static int maxFunctionLength(const AbstractMetaFunctionList &functions)
-{
- int result = 0;
- for (int i = 0; i < functions.size(); ++i)
- result = qMax(result, functions.at(i)->arguments().size());
- return result;
-}
-
-/*!
- Writes a prototype/static function.
-*/
-static void writeFunctionForwarding(QTextStream &stream, const AbstractMetaClass *meta_class,
- const AbstractMetaFunctionList &functions)
-{
-#if 0
- stream << "/** signatures:" << endl;
- foreach (const AbstractMetaFunction *fun, functions) {
- stream << " * " << fun->signature() << endl;
- }
- stream << " */" << endl;
-#endif
- QMap argcToFunctions;
- argcToFunctions = createArgcToFunctionsMap(functions);
- QSet signatures;
- int argcMin = argcToFunctions.keys().first();
- int argcMax = argcToFunctions.keys().last();
- for (int i = argcMin; i <= argcMax; ++i) {
- AbstractMetaFunctionList funcs = argcToFunctions.value(i);
- if (funcs.isEmpty())
- continue;
- stream << " if (context->argumentCount() == " << i << ") {" << endl;
- if (funcs.size() == 1) {
- AbstractMetaFunction *fun = funcs.at(0);
- const int indent = 8;
- // special case for Q{Data,Text}Stream streaming operators
- if (ClassGenerator::isSpecialStreamingOperator(fun))
- writeStreamingOperatorCall(stream, fun, meta_class, indent);
- else
- writeFunctionCallAndReturn(stream, fun, i, meta_class, indent);
- signatures.insert(fun->targetLangSignature());
- } else {
- // handle overloads
- QStringList sigs;
- for (int j = 0; j < funcs.size(); ++j) {
- AbstractMetaFunction *fun = funcs.at(j);
- sigs.append(fun->signature());
- stream << " ";
- if (j > 0)
- stream << "} else ";
- stream << "if (";
- AbstractMetaArgumentList arguments = fun->arguments();
- const int indent = 12;
- writeArgumentTypeTests(stream, fun, arguments, i, indent);
- stream << ") {" << endl;
- writeFunctionCallAndReturn(stream, fun, i, meta_class, indent);
- signatures.insert(fun->targetLangSignature());
- }
- stream << " }" << endl;
- }
- stream << " }" << endl;
- }
-}
-
-static void writePrototypeCall(QTextStream &s, const AbstractMetaClass *meta_class,
- const QMap &nameToFunctions,
- int prototypeFunctionsOffset)
-{
- s << "static QScriptValue qtscript_" << meta_class->name()
- << "_prototype_call(QScriptContext *context, QScriptEngine *)" << endl
- << "{" << endl;
-
- s << "#if QT_VERSION > 0x040400" << endl;
-
- s << " Q_ASSERT(context->callee().isFunction());" << endl
- << " uint _id = context->callee().data().toUInt32();" << endl;
-
- s << "#else" << endl
- << " uint _id;" << endl
- << " if (context->callee().isFunction())" << endl
- << " _id = context->callee().data().toUInt32();" << endl
- << " else" << endl
- << " _id = 0xBABE0000 + " << nameToFunctions.size() << ";" << endl;
-
- s << "#endif" << endl;
-
- s << " Q_ASSERT((_id & 0xFFFF0000) == 0xBABE0000);" << endl
- << " _id &= 0x0000FFFF;" << endl;
-
- // cast the thisObject to C++ type
- s << " ";
-#ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
- if (meta_class->hasProtectedFunctions())
- s << "qtscript_";
-#endif
- s << meta_class->qualifiedCppName() << "* _q_self = ";
-#ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
- if (meta_class->hasProtectedFunctions())
- s << "reinterpret_castname() << "*>(";
-#endif
- s << "qscriptvalue_cast<" << meta_class->qualifiedCppName()
- << "*>(context->thisObject())";
-#ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
- if (meta_class->hasProtectedFunctions())
- s << ")";
-#endif
- s << ";" << endl
- << " if (!_q_self) {" << endl
- << " return context->throwError(QScriptContext::TypeError," << endl
- << " QString::fromLatin1(\"" << meta_class->name()
- << ".%0(): this object is not a " << meta_class->name() << "\")" << endl
- << " .arg(qtscript_" << meta_class->name()
- << "_function_names[_id+" << prototypeFunctionsOffset <<"]));" << endl
- << " }" << endl << endl;
-
- s << " switch (_id) {" << endl;
-
- QMap::const_iterator it;
- int index = 0;
- for (it = nameToFunctions.constBegin(); it != nameToFunctions.constEnd(); ++it) {
- s << " case " << index << ":" << endl;
- writeFunctionForwarding(s, meta_class, it.value());
- s << " break;" << endl << endl;
- ++index;
- }
-
- if (!meta_class->hasDefaultToStringFunction()) {
- s << " case " << index << ": {" << endl;
- s << " QString result";
- FunctionModelItem fun = meta_class->hasToStringCapability();
- if (fun) {
- int indirections = fun->arguments().at(1)->type().indirections();
- QString deref = QLatin1String(indirections == 0 ? "*" : "");
- s << ";" << endl
- << " QDebug d(&result);" << endl
- << " d << " << deref << "_q_self;" << endl;
- } else {
- // ### FIXME: can cause compile error
-// s << "=QString(\"" << meta_class->name() << "(0x%1)\").arg((int)_q_self, 0, 16);" << endl;
- s << " = QString::fromLatin1(\"" << meta_class->name() << "\");" << endl;
- }
- s << " return QScriptValue(context->engine(), result);" << endl
- << " }" << endl << endl;
- }
-
- s << " default:" << endl
- << " Q_ASSERT(false);" << endl
- << " }" << endl;
-
- s << " return qtscript_" << meta_class->name() << "_throw_ambiguity_error_helper(context," << endl
- << " qtscript_" << meta_class->name()
- << "_function_names[_id+" << prototypeFunctionsOffset << "]," << endl
- << " qtscript_" << meta_class->name()
- << "_function_signatures[_id+" << prototypeFunctionsOffset << "]);" << endl;
-
- s << "}" << endl << endl;
-}
-
-static void writeStaticCall(QTextStream &s, const AbstractMetaClass *meta_class,
- const AbstractMetaFunctionList &constructors,
- const QMap &nameToFunctions)
-{
- s << "static QScriptValue qtscript_" << meta_class->name()
- << "_static_call(QScriptContext *context, QScriptEngine *)" << endl
- << "{" << endl;
-
- s << " uint _id = context->callee().data().toUInt32();" << endl
- << " Q_ASSERT((_id & 0xFFFF0000) == 0xBABE0000);" << endl
- << " _id &= 0x0000FFFF;" << endl;
-
- s << " switch (_id) {" << endl;
-
- s << " case 0:" << endl;
- writeConstructorForwarding(s, constructors, meta_class);
- s << " break;" << endl << endl;
-
- QMap::const_iterator it;
- int index = 1;
- for (it = nameToFunctions.constBegin(); it != nameToFunctions.constEnd(); ++it) {
- s << " case " << index << ":" << endl;
- writeFunctionForwarding(s, meta_class, it.value());
- s << " break;" << endl << endl;
- ++index;
- }
-
- s << " default:" << endl
- << " Q_ASSERT(false);" << endl
- << " }" << endl;
-
- s << " return qtscript_" << meta_class->name() << "_throw_ambiguity_error_helper(context," << endl
- << " qtscript_" << meta_class->name() << "_function_names[_id]," << endl
- << " qtscript_" << meta_class->name() << "_function_signatures[_id]);" << endl;
-
- s << "}" << endl << endl;
-}
-
-/*!
- Writes the include defined by \a inc to \a stream.
-*/
-void ClassGenerator::writeInclude(QTextStream &stream, const Include &inc)
-{
- if (inc.name.isEmpty())
- return;
- if (inc.type == Include::TargetLangImport)
- return;
- stream << "#include ";
- if (inc.type == Include::IncludePath)
- stream << "<";
- else
- stream << "\"";
- stream << inc.name;
- if (inc.type == Include::IncludePath)
- stream << ">";
- else
- stream << "\"";
- stream << endl;
-}
-
-static void writeHelperFunctions(QTextStream &stream, const AbstractMetaClass *meta_class)
-{
- stream << "static QScriptValue qtscript_" << meta_class->name() << "_throw_ambiguity_error_helper(" << endl
- << " QScriptContext *context, const char *functionName, const char *signatures)" << endl
- << "{" << endl
- << " QStringList lines = QString::fromLatin1(signatures).split(QLatin1Char('\\n'));" << endl
- << " QStringList fullSignatures;" << endl
- << " for (int i = 0; i < lines.size(); ++i)" << endl
- << " fullSignatures.append(QString::fromLatin1(\"%0(%1)\").arg(functionName).arg(lines.at(i)));" << endl
- << " return context->throwError(QString::fromLatin1(\"" << meta_class->name()
- << "::%0(): could not find a function match; candidates are:\\n%1\")" << endl
- << " .arg(functionName).arg(fullSignatures.join(QLatin1String(\"\\n\"))));" << endl
- << "}" << endl << endl;
-}
-
-
-/*!
- Finds the functions in \a meta_class that we actually want to
- generate bindings for.
-*/
-void findPrototypeAndStaticFunctions(
- const AbstractMetaClass *meta_class,
- QMap &nameToPrototypeFunctions,
- QMap &nameToStaticFunctions)
-{
- AbstractMetaFunctionList functions = meta_class->functionsInTargetLang();
- for (int i = 0; i < functions.size(); ++i) {
- AbstractMetaFunction* func = functions.at(i);
- if (!func->isNormal())
- continue;
-#ifdef GENERATOR_NO_PROTECTED_FUNCTIONS
- if (func->wasProtected())
- continue;
-#endif
- if (func->declaringClass() != meta_class)
- continue; // function inherited through prototype
- if (func->isPropertyReader() || func->isPropertyWriter())
- continue; // no point in including property accessors
- if (func->isSlot() || func->isSignal() || func->isInvokable())
- continue; // no point in including signals and slots
- QMap &map =
- func->isStatic() ? nameToStaticFunctions : nameToPrototypeFunctions;
- map[func->modifiedName()].append(func);
- }
-}
-
-static void writeFunctionSignaturesString(QTextStream &s, const AbstractMetaFunctionList &functions)
-{
- s << "\"";
- for (int i = 0; i < functions.size(); ++i) {
- if (i > 0)
- s << "\\n";
- QString sig = functions.at(i)->targetLangSignature();
- sig = sig.mid(sig.indexOf('(') + 1);
- sig.chop(1);
- s << sig;
- }
- s << "\"";
-}
-
-/*!
- Writes the whole native binding for the class \a meta_class.
-*/
-void ClassGenerator::write(QTextStream &stream, const AbstractMetaClass *meta_class)
-{
- // write common includes
- stream << "#include " << endl;
- stream << "#include " << endl;
- stream << "#include " << endl;
- stream << "#include " << endl;
- stream << "#include " << endl;
- stream << "#include " << endl;
- stream << endl;
-
- // write class-specific includes
- {
- Include inc = meta_class->typeEntry()->include();
- writeInclude(stream, inc);
- }
- {
- IncludeList includes = meta_class->typeEntry()->extraIncludes();
- qSort(includes.begin(), includes.end());
-
- foreach (const Include &i, includes) {
- writeInclude(stream, i);
- }
- }
- stream << endl;
-
- if (meta_class->generateShellClass()) {
- stream << "#include \"qtscriptshell_" << meta_class->name() << ".h\"" << endl;
- stream << endl;
- }
-
- AbstractMetaEnumList enums = meta_class->enums();
- {
- // kill the enums we don't care about
- AbstractMetaEnumList::iterator it;
- for (it = enums.begin(); it != enums.end(); ) {
- if (shouldIgnoreEnum(*it))
- it = enums.erase(it);
- else
- ++it;
- }
- }
-
- if (meta_class->isNamespace() || meta_class->name() == "Global") {
- QMap includes;
- foreach (AbstractMetaEnum *enom, enums) {
- Include include = enom->typeEntry()->include();
- includes.insert(include.toString(), include);
- }
-
- foreach (const Include &i, includes) {
- writeInclude(stream, i);
- }
-
- stream << endl;
- }
-
- if (meta_class->name() == "Global") {
- stream << "class Global {};" << endl;
- stream << endl;
- }
-
- // find constructors
- AbstractMetaFunctionList ctors = findConstructors(meta_class);
- bool hasDefaultCtor = findDefaultConstructor(ctors) != 0;
-
- // find interesting functions
- QMap nameToPrototypeFunctions;
- QMap nameToStaticFunctions;
- findPrototypeAndStaticFunctions(meta_class, nameToPrototypeFunctions, nameToStaticFunctions);
-
- int staticFunctionsOffset = 1;
- int prototypeFunctionsOffset = staticFunctionsOffset + nameToStaticFunctions.size();
-
- // write table of function names
- stream << "static const char * const qtscript_"
- << meta_class->name() << "_function_names[] = {" << endl;
- stream << " \"" << meta_class->name() << "\"" << endl;
- {
- QMap::const_iterator it;
- stream << " // static" << endl;
- for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
- stream << " , ";
- stream << "\"" << it.key() << "\"" << endl;
- }
- stream << " // prototype" << endl;
- for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
- QString functionName = it.key();
- QString scriptName = functionName;
- if (functionName == QLatin1String("operator_equal"))
- scriptName = QLatin1String("equals");
- stream << " , ";
- stream << "\"" << scriptName << "\"" << endl;
- }
- if (!meta_class->hasDefaultToStringFunction())
- stream << " , \"toString\"" << endl;
- }
- stream << "};" << endl << endl;
-
- // write table of function signatures
- stream << "static const char * const qtscript_"
- << meta_class->name() << "_function_signatures[] = {" << endl;
- stream << " ";
- writeFunctionSignaturesString(stream, ctors);
- stream << endl;
- {
- QMap::const_iterator it;
- stream << " // static" << endl;
- for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
- stream << " , ";
- writeFunctionSignaturesString(stream, it.value());
- stream << endl;
- }
- stream << " // prototype" << endl;
- for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
- stream << " , ";
- writeFunctionSignaturesString(stream, it.value());
- stream << endl;
- }
- if (!meta_class->hasDefaultToStringFunction())
- stream << "\"\"" << endl;
- }
- stream << "};" << endl << endl;
-
- // write table of function lengths
- stream << "static const int qtscript_" << meta_class->name() << "_function_lengths[] = {" << endl;
- stream << " " << maxFunctionLength(ctors) << endl;
- {
- QMap::const_iterator it;
- stream << " // static" << endl;
- for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
- stream << " , " << maxFunctionLength(it.value()) << endl;
- }
- stream << " // prototype" << endl;
- for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
- stream << " , " << maxFunctionLength(it.value()) << endl;
- }
- if (!meta_class->hasDefaultToStringFunction())
- stream << " , 0" << endl;
- }
- stream << "};" << endl << endl;
-
-#ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
- if (meta_class->hasProtectedFunctions()) {
- // write a friendly class
- stream << "class qtscript_" << meta_class->name()
- << " : public " << meta_class->qualifiedCppName() << endl;
- stream << "{" << endl;
- for (int x = 0; x < 2; ++x) {
- QMap &map =
- x ? nameToStaticFunctions : nameToPrototypeFunctions;
- QMap::const_iterator it;
- for (it = map.constBegin(); it != map.constEnd(); ++it) {
- AbstractMetaFunctionList functions = it.value();
- for (int i = 0; i < functions.size(); ++i) {
- if (functions.at(i)->isProtected()) {
- stream << " friend QScriptValue qtscript_" << meta_class->name()
- << "_" << it.key();
- if (functions.at(i)->isStatic())
- stream << "_static";
- stream << "(QScriptContext *, QScriptEngine *);" << endl;
- break;
- }
- }
- }
- }
- stream << "};" << endl;
- stream << endl;
- }
-#endif
-
- writeHelperFunctions(stream, meta_class);
-
- // write metaobject getter if we need it
- if (hasQEnums(enums) && (meta_class->qualifiedCppName() != "QTransform")) {
- if (meta_class->qualifiedCppName() == "Qt") {
- stream << "struct qtscript_Qt_metaObject_helper : private QObject" << endl
- << "{" << endl
- << " static const QMetaObject *get()" << endl
- << " { return &static_cast(0)->staticQtMetaObject; }" << endl
- << "};" << endl << endl;
- }
- stream << "static const QMetaObject *qtscript_" << meta_class->name() << "_metaObject()" << endl
- << "{" << endl
- << " return ";
- if (meta_class->qualifiedCppName() == "Qt")
- stream << "qtscript_Qt_metaObject_helper::get()";
- else
- stream << "&" << meta_class->qualifiedCppName() << "::staticMetaObject";
- stream << ";" << endl
- << "}" << endl << endl;
- }
-
- // write metatype declarations
- {
- QSet registeredTypeNames = m_qmetatype_declared_typenames;
-
- if (!meta_class->isNamespace()) {
- if (meta_class->typeEntry()->isValue() && hasDefaultCtor)
- maybeDeclareMetaType(stream, meta_class->qualifiedCppName(), registeredTypeNames);
- else
- registeredTypeNames << meta_class->qualifiedCppName();
- maybeDeclareMetaType(stream, meta_class->qualifiedCppName() + "*", registeredTypeNames);
- }
- if (meta_class->generateShellClass()) {
- if (meta_class->typeEntry()->isValue()) {
- maybeDeclareMetaType(stream, "QtScriptShell_" + meta_class->name(),
- registeredTypeNames);
- }
- maybeDeclareMetaType(stream, "QtScriptShell_" + meta_class->name() + "*",
- registeredTypeNames);
- }
-
- declareEnumMetaTypes(stream, meta_class, registeredTypeNames);
-
- for (int x = 0; x < 2; ++x) {
- QMap &map =
- x ? nameToStaticFunctions : nameToPrototypeFunctions;
- QMap::const_iterator it;
- for (it = map.constBegin(); it != map.constEnd(); ++it) {
- declareFunctionMetaTypes(stream, it.value(), registeredTypeNames);
- }
- }
-
- declareFunctionMetaTypes(stream, ctors, registeredTypeNames);
-
- if (meta_class->baseClass() != 0) {
- maybeDeclareMetaType(stream, meta_class->baseClass()->qualifiedCppName()
- + QLatin1String("*"), registeredTypeNames);
- }
- foreach (AbstractMetaClass *iface, meta_class->interfaces()) {
- AbstractMetaClass *impl = iface->primaryInterfaceImplementor();
- maybeDeclareMetaType(stream, impl->qualifiedCppName() + QLatin1String("*"),
- registeredTypeNames);
- }
-
- // ### hackety hack
- if (meta_class->name().endsWith("Gradient"))
- maybeDeclareMetaType(stream, "QGradient", registeredTypeNames);
-
- stream << endl;
- }
-
- writeInjectedCode(stream, meta_class, CodeSnip::Beginning);
-
- // write enum classes
- if (!enums.isEmpty()) {
- writeCreateEnumClassHelper(stream);
- if (hasFlags(enums))
- writeCreateFlagsClassHelper(stream);
-
- for (int i = 0; i < enums.size(); ++i) {
- const AbstractMetaEnum *enom = enums.at(i);
- writeEnumClass(stream, meta_class, enom);
- }
- }
-
- stream << "//" << endl;
- stream << "// " << meta_class->name() << endl;
- stream << "//" << endl << endl;
-
- if (!meta_class->isNamespace()) {
- if (!nameToPrototypeFunctions.isEmpty() || !meta_class->hasDefaultToStringFunction())
- writePrototypeCall(stream, meta_class, nameToPrototypeFunctions, prototypeFunctionsOffset);
- }
-
- writeStaticCall(stream, meta_class, ctors, nameToStaticFunctions);
-
- if (isQObjectBased(meta_class)) {
- // write C++ <--> script conversion functions
- stream << "static QScriptValue qtscript_" << meta_class->name() << "_toScriptValue(QScriptEngine *engine, "
- << meta_class->qualifiedCppName() << "* const &in)" << endl
- << "{" << endl
- << " return engine->newQObject(in, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);" << endl
- << "}" << endl << endl;
- stream << "static void qtscript_" << meta_class->name() << "_fromScriptValue(const QScriptValue &value, "
- << meta_class->qualifiedCppName() << "* &out)" << endl
- << "{" << endl
- << " out = qobject_cast<" << meta_class->qualifiedCppName() << "*>(value.toQObject());" << endl
- << "}" << endl << endl;
- }
-
- //
- // write exported function that creates the QtScript class
- //
- stream << "QScriptValue qtscript_create_" << meta_class->name()
- << "_class(QScriptEngine *engine)" << endl;
- stream << "{" << endl;
-
- // setup prototype
- if (!meta_class->isNamespace()) {
- stream << " engine->setDefaultPrototype(qMetaTypeId<"
- << meta_class->qualifiedCppName() << "*>(), QScriptValue());" << endl;
- stream << " QScriptValue proto = engine->newVariant(qVariantFromValue(("
- << meta_class->qualifiedCppName() << "*)0));" << endl;
- bool havePrototypePrototype = false;
- if (meta_class->baseClass() != 0) {
- stream << " proto.setPrototype(engine->defaultPrototype(qMetaTypeId<"
- << meta_class->baseClass()->qualifiedCppName() << "*>()));" << endl;
- havePrototypePrototype = true;
- }
- foreach (AbstractMetaClass *iface, meta_class->interfaces()) {
- AbstractMetaClass *impl = iface->primaryInterfaceImplementor();
- if (impl == meta_class)
- continue;
- if (!havePrototypePrototype) {
- stream << " proto.setPrototype(engine->defaultPrototype(qMetaTypeId<"
- << impl->qualifiedCppName() << "*>()));" << endl;
- havePrototypePrototype = true;
- } else {
- // alternative would be to copy the properties from the secondary
- // prototype to the primary prototype.
- stream << " proto.setProperty(QString::fromLatin1(\"__"
- << impl->name() << "__\")," << endl
- << " engine->defaultPrototype(qMetaTypeId<"
- << impl->qualifiedCppName() << "*>())," << endl
- << " QScriptValue::SkipInEnumeration);" << endl;
- }
- }
- if (!nameToPrototypeFunctions.isEmpty()) {
- QMap::const_iterator it;
- int count = nameToPrototypeFunctions.size();
- if (!meta_class->hasDefaultToStringFunction())
- ++count;
- stream << " for (int i = 0; i < " << count << "; ++i) {" << endl
- << " QScriptValue fun = engine->newFunction(qtscript_"
- << meta_class->name() << "_prototype_call, qtscript_"
- << meta_class->name() << "_function_lengths[i+"
- << prototypeFunctionsOffset << "]);" << endl
- << " fun.setData(QScriptValue(engine, uint(0xBABE0000 + i)));" << endl
- << " proto.setProperty(QString::fromLatin1(qtscript_"
- << meta_class->name() << "_function_names[i+" << prototypeFunctionsOffset << "])," << endl
- << " fun, QScriptValue::SkipInEnumeration);" << endl
- << " }" << endl;
- }
- writeInjectedCode(stream, meta_class, CodeSnip::PrototypeInitialization);
- stream << endl;
-
- // register the prototype
-// stream << " qDebug() << \"registering " << meta_class->name() << " prototype\";" << endl;
- if (meta_class->typeEntry()->isValue() && hasDefaultCtor) {
- stream << " engine->setDefaultPrototype(qMetaTypeId<"
- << meta_class->qualifiedCppName() << ">(), proto);" << endl;
- }
- if (isQObjectBased(meta_class)) {
- stream << " qScriptRegisterMetaType<" << meta_class->qualifiedCppName() << "*>(engine, qtscript_"
- << meta_class->name() << "_toScriptValue, " << endl << " qtscript_"
- << meta_class->name() << "_fromScriptValue, proto);" << endl;
- } else {
- stream << " engine->setDefaultPrototype(qMetaTypeId<"
- << meta_class->qualifiedCppName() << "*>(), proto);" << endl;
- }
- stream << endl;
- } else {
- stream << " QScriptValue proto = QScriptValue();" << endl;
- }
-
- // setup constructor
- stream << " QScriptValue ctor = engine->newFunction(qtscript_" << meta_class->name()
- << "_static_call, proto, qtscript_" << meta_class->name() << "_function_lengths[0]);" << endl;
- stream << " ctor.setData(QScriptValue(engine, uint(0xBABE0000 + 0)));" << endl;
- if (!nameToStaticFunctions.isEmpty()) {
- // static functions
- QMap::const_iterator it;
- stream << " for (int i = 0; i < " << nameToStaticFunctions.size() << "; ++i) {" << endl
- << " QScriptValue fun = engine->newFunction(qtscript_" << meta_class->name()
- << "_static_call," << endl
- << " qtscript_" << meta_class->name() << "_function_lengths[i+" << staticFunctionsOffset << "]);" << endl
- << " fun.setData(QScriptValue(engine, uint(0xBABE0000 + i+1)));" << endl
- << " ctor.setProperty(QString::fromLatin1(qtscript_"
- << meta_class->name() << "_function_names[i+" << staticFunctionsOffset << "])," << endl
- << " fun, QScriptValue::SkipInEnumeration);" << endl
- << " }" << endl;
- }
- stream << endl;
- // enums and flags classes
- {
- for (int i = 0; i < enums.size(); ++i) {
- const AbstractMetaEnum *enom = enums.at(i);
- stream << " ctor.setProperty(QString::fromLatin1(\""
- << enom->name() << "\")," << endl
- << " qtscript_create_" << meta_class->name()
- << "_" << enom->name() << "_class(engine, ctor));" << endl;
- FlagsTypeEntry *flags = enom->typeEntry()->flags();
- if (flags) {
- stream << " ctor.setProperty(QString::fromLatin1(\""
- << flags->targetLangName() << "\")," << endl
- << " qtscript_create_" << meta_class->name()
- << "_" << flags->targetLangName() << "_class(engine));" << endl;
- }
- }
- }
-
- writeInjectedCode(stream, meta_class, CodeSnip::ConstructorInitialization);
-
- stream << " return ctor;" << endl;
- stream << "}" << endl;
-
- writeInjectedCode(stream, meta_class, CodeSnip::End);
-
- QString packName = meta_class->package().replace(".", "_");
- priGenerator->addSource(packName, fileNameForClass(meta_class));
- setupGenerator->addClass(meta_class);
-}
diff --git a/generator/classgenerator.h b/generator/classgenerator.h
deleted file mode 100644
index 51bfe78..0000000
--- a/generator/classgenerator.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt Script Generator project on Qt Labs.
-**
-** $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.
-**
-** 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.
-**
-** 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$
-**
-****************************************************************************/
-
-#ifndef CLASS_GENERATOR
-#define CLASS_GENERATOR
-
-#include "generator.h"
-#include "metaqtscript.h"
-#include "prigenerator.h"
-#include "setupgenerator.h"
-
-class ClassGenerator : public Generator
-{
- Q_OBJECT
-
- public:
- ClassGenerator(PriGenerator *pri, SetupGenerator *setup);
-
- virtual QString fileNameForClass(const AbstractMetaClass *meta_class) const;
- virtual QString subDirectoryForClass(const AbstractMetaClass *cls) const
- {
- return "generated_cpp/" + cls->package().replace(".", "_") + "/";
- }
- virtual bool shouldGenerate(const AbstractMetaClass *meta_class) const;
- void write(QTextStream &s, const AbstractMetaClass *meta_class);
-
- static void writeInclude(QTextStream &stream, const Include &inc);
-
- static bool isSpecialStreamingOperator(const AbstractMetaFunction *fun);
-
- private:
- PriGenerator *priGenerator;
- SetupGenerator *setupGenerator;
- QStringList describeFunctons;
-};
-
-#endif // CLASS_GENERATOR
diff --git a/generator/docgenerator.cpp b/generator/docgenerator.cpp
deleted file mode 100644
index aa8b842..0000000
--- a/generator/docgenerator.cpp
+++ /dev/null
@@ -1,347 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt Script Generator project on Qt Labs.
-**
-** $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.
-**
-** 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.
-**
-** 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$
-**
-****************************************************************************/
-
-#include "docgenerator.h"
-#include "fileout.h"
-
-DocGenerator::DocGenerator()
-{
-}
-
-QString DocGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
-{
- return QString::fromLatin1("%0.html").arg(meta_class->name().toLower());
-}
-
-QString DocGenerator::subDirectoryForClass(const AbstractMetaClass *) const
-{
- return QString::fromLatin1("doc");
-}
-
-static void writeDocumentHeader(QTextStream &s, const QString &title)
-{
- s << "" << endl
- << "" << endl
- << "" << endl
- << "" << endl
- << " " << title << " " << endl
- << " " << endl
- << "" << endl
- << "" << endl;
-}
-
-static void writeDocumentFooter(QTextStream &s)
-{
- s << "" << endl
- << "" << endl;
-}
-
-static bool classLessThan(const AbstractMetaClass *c1, const AbstractMetaClass *c2)
-{
- return c1->name() < c2->name();
-}
-
-bool DocGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
-{
- uint cg = meta_class->typeEntry()->codeGeneration();
- return (cg & TypeEntry::GenerateCode) != 0;
-}
-
-void DocGenerator::generate()
-{
- Generator::generate();
-
- QHash > packHash;
- for (int i = 0; i < m_classes.size(); ++i) {
- const AbstractMetaClass *cls = m_classes.at(i);
- packHash[cls->package()].append(cls);
- }
-
- // package pages
- QHash >::const_iterator it;
- for (it = packHash.constBegin(); it != packHash.constEnd(); ++it) {
- QString package = it.key();
- QList classesInPackage = it.value();
- qSort(classesInPackage.begin(), classesInPackage.end(), classLessThan);
-
- FileOut file(m_out_dir + "/doc/" + package.split(".").join("_") + ".html");
-
- writeDocumentHeader(file.stream, package + " Package");
-
- file.stream << "" << package << " Package " << endl;
-
- file.stream << "Classes " << endl
- << "
" << endl;
-
- for (int i = 0; i < classesInPackage.size(); ++i) {
- const AbstractMetaClass *cls = classesInPackage.at(i);
- if (cls->name() == "Global")
- continue; /// ### fixme
- file.stream << "" << cls->name()
- << " " << endl;
- }
-
- file.stream << "
" << endl;
-
- writeDocumentFooter(file.stream);
- }
-
- // all classes page
- {
- FileOut file(m_out_dir + "/doc/classes.html");
-
- writeDocumentHeader(file.stream, "Classes");
-
- file.stream << "Classes " << endl
- << "
" << endl;
-
- AbstractMetaClassList sortedClasses = m_classes;
- qSort(sortedClasses.begin(), sortedClasses.end(), classLessThan);
-
- for (int i = 0; i < sortedClasses.size(); ++i) {
- const AbstractMetaClass *cls = sortedClasses.at(i);
- if (cls->name() == "Global")
- continue; /// ### fixme
- file.stream << "" << cls->name()
- << " " << endl;
- }
-
- file.stream << "
" << endl;
-
- writeDocumentFooter(file.stream);
- }
-
- // index.html
- {
- FileOut file(m_out_dir + "/doc/index.html");
-
- writeDocumentHeader(file.stream, "Qt Bindings Reference Documentation");
-
- file.stream << "Qt Script Qt Bindings Reference Documentation " << endl;
-
- file.stream << "Packages " << endl;
- file.stream << "" << endl;
- QStringList sortedPackages = packHash.keys();
- qSort(sortedPackages.begin(), sortedPackages.end());
- for (int i = 0; i < sortedPackages.size(); ++i) {
- QString pkg = sortedPackages.at(i);
- file.stream << ""
- << pkg << " " << endl;
- }
- file.stream << " " << endl;
-
- file.stream << "" << endl;
-
- file.stream << "" << endl;
-
- file.stream << "Getting Started " << endl
- << "Using the Qt API in Qt Script is very similar to C++." << endl
- << "
var f = new QFile(\"foo.txt\"); " << endl
- << "C++ enum values are mapped to properties of the script constructor function; e.g. " << endl
- << "QIODevice::ReadOnly becomes QIODevice.ReadOnly." << endl
- << "f.open(new QIODevice.OpenMode(QIODevice.ReadOnly)); " << endl
- << "Each C++ flag type is mapped to a property of the script constructor function; e.g. " << endl
- << "QIODevice::OpenMode becomes QIODevice.OpenMode. Such a property is a constructor function " << endl
- << "that takes one or more enum values and constructs a flags instance by OR'ing the arguments " << endl
- << "together.
" << endl
- << "var ts = new QTextStream(f);" << endl
- << "ts.writeString(\"Boo\"); " << endl
- << "C++ streaming operators are normally mapped to readT() and writeT() functions.
" << endl
- << "f.close(); " << endl
- << "In Qt Script, all objects are allocated on the heap; objects that are no longer " << endl
- << "referenced are garbage collected sometime in the future; therefore, make sure to " << endl
- << "explicitly free up resources if you can. (Without the call to close(), the underlying " << endl
- << "file would remain open until the file object is garbage collected.)
" << endl
- ;
-
- file.stream << "" << endl;
-
- writeDocumentFooter(file.stream);
- }
-}
-
-static bool shouldIgnoreEnum(const AbstractMetaEnum *enom)
-{
- return !enom->wasPublic() || (enom->name() == "enum_1");
-}
-
-// in classgenerator.cpp
-void findPrototypeAndStaticFunctions(
- const AbstractMetaClass *meta_class,
- QMap &nameToPrototypeFunctions,
- QMap &nameToStaticFunctions);
-QList uniqueEnumValueIndexes(const AbstractMetaEnumValueList &values);
-
-static void writeFunction(QTextStream &s, const AbstractMetaFunction *fun)
-{
- s << "" << fun->targetLangSignature() << " " << endl;
-}
-
-void DocGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
-{
- QString title = meta_class->name();
- title.append(" ");
- if (meta_class->isNamespace())
- title.append("Namespace");
- else
- title.append("Class");
- title.append(" Reference");
- writeDocumentHeader(s, title);
-
- s << "
" << title << " " << endl;
-
- s << "
" << endl;
-
- if (meta_class->baseClass()) {
- s << "
Inherits baseClass()) << "\">"
- << meta_class->baseClass()->name() << " .
" << endl;
- } else if (!meta_class->interfaces().isEmpty()) {
- AbstractMetaClass *iface = meta_class->interfaces().first();
- AbstractMetaClass *impl = iface->primaryInterfaceImplementor();
- if (impl != meta_class) {
- s << "
Inherits "
- << impl->name() << " .
" << endl;
- }
- }
-
- AbstractMetaFunctionList ctors;
- ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
- | AbstractMetaClass::WasPublic
- | AbstractMetaClass::NotRemovedFromTargetLang);
- QMap
nameToPrototypeFunctions;
- QMap nameToStaticFunctions;
- findPrototypeAndStaticFunctions(meta_class, nameToPrototypeFunctions, nameToStaticFunctions);
-
- s << "Constructor " << endl;
- if (!ctors.isEmpty()) {
- s << "" << endl;
- for (int i = 0; i < ctors.size(); ++i) {
- writeFunction(s, ctors.at(i));
- }
- s << " " << endl;
- } else {
- s << "This class has no public constructors. Calling the constructor function will cause a TypeError.
";
- }
-
- s << "Constructor Properties " << endl;
- s << "" << endl;
- s << "prototype : The " << meta_class->name() << " prototype object " << endl;
- if (!nameToStaticFunctions.isEmpty()) {
- QMap::const_iterator it;
- for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
- writeFunction(s, it.value().first());
- }
- }
- {
- AbstractMetaEnumList enums = meta_class->enums();
- for (int i = 0; i < enums.size(); ++i) {
- const AbstractMetaEnum *enom = enums.at(i);
- if (shouldIgnoreEnum(enom))
- continue;
- AbstractMetaEnumValueList values = enom->values();
- QList indexes = uniqueEnumValueIndexes(values);
- for (int j = 0; j < indexes.size(); ++j) {
- AbstractMetaEnumValue *val = values.at(indexes.at(j));
- s << "" << val->name();
- if (!val->stringValue().isEmpty())
- s << " = " << val->stringValue();
- s << " " << endl;
- }
- s << "" << enom->name() << "( value ) " << endl;
- FlagsTypeEntry *flags = enom->typeEntry()->flags();
- if (flags)
- s << "" << flags->flagsName() << "( value1, value2, ... ) " << endl;
- }
- }
- s << " " << endl;
-
- if (!nameToPrototypeFunctions.isEmpty()) {
- s << "Prototype Object Properties " << endl;
- if (meta_class->baseClass()) {
- s << "The " << meta_class->name() << " prototype object inherits properties from the "
- << "baseClass()) << "\">"
- << meta_class->baseClass()->name() << " prototype object and "
- << "also has the following properties.
" << endl;
- }
- s << "" << endl;
- QMap::const_iterator it;
- for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
- writeFunction(s, it.value().first());
- }
- s << " " << endl;
- }
-
- if (!meta_class->isNamespace()) {
- s << "Instance Properties " << endl;
- {
- QList props = meta_class->propertySpecs();
- if (!props.isEmpty()) {
- s << "" << meta_class->name() << " objects inherit properties from the "
- << meta_class->name() << " prototype object and also have the following properties.
" << endl;
- s << "" << endl;
- for (int i = 0; i < props.size(); ++i) {
- s << "" << props.at(i)->name() << " " << endl;
- }
- s << "" << endl;
- } else {
- s << "
" << meta_class->name() << " objects have no special properties beyond those "
- << "inherited from the " << meta_class->name() << " prototype object.
" << endl;
- }
- }
- }
-
- writeDocumentFooter(s);
-}
diff --git a/generator/docgenerator.h b/generator/docgenerator.h
deleted file mode 100644
index f36ef43..0000000
--- a/generator/docgenerator.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt Script Generator project on Qt Labs.
-**
-** $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.
-**
-** 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.
-**
-** 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$
-**
-****************************************************************************/
-
-#ifndef DOCGENERATOR_H
-#define DOCGENERATOR_H
-
-#include "generator.h"
-
-class DocGenerator : public Generator
-{
-public:
- DocGenerator();
-
- virtual bool shouldGenerate(const AbstractMetaClass *meta_class) const;
- virtual void generate();
- virtual QString fileNameForClass(const AbstractMetaClass *meta_class) const;
- virtual QString subDirectoryForClass(const AbstractMetaClass *cls) const;
- virtual void write(QTextStream &s, const AbstractMetaClass *meta_class);
-};
-
-#endif
diff --git a/generator/generator.pro b/generator/generator.pro
index 0671164..9e2ae50 100644
--- a/generator/generator.pro
+++ b/generator/generator.pro
@@ -11,20 +11,16 @@ HEADERS += \
generatorsetqtscript.h \
metaqtscriptbuilder.h \
metaqtscript.h \
- classgenerator.h \
shellgenerator.h \
shellimplgenerator.h \
shellheadergenerator.h \
- setupgenerator.h \
- docgenerator.h
+ setupgenerator.h
SOURCES += \
generatorsetqtscript.cpp \
metaqtscriptbuilder.cpp \
metaqtscript.cpp \
- classgenerator.cpp \
shellgenerator.cpp \
shellimplgenerator.cpp \
shellheadergenerator.cpp \
- setupgenerator.cpp \
- docgenerator.cpp
+ setupgenerator.cpp
diff --git a/generator/generatorsetqtscript.cpp b/generator/generatorsetqtscript.cpp
index 52b8f2c..abedf34 100644
--- a/generator/generatorsetqtscript.cpp
+++ b/generator/generatorsetqtscript.cpp
@@ -41,10 +41,8 @@
#include "generatorsetqtscript.h"
#include "reporthandler.h"
-#include "classgenerator.h"
#include "shellheadergenerator.h"
#include "shellimplgenerator.h"
-#include "docgenerator.h"
GeneratorSet *GeneratorSet::getInstance() {
return new GeneratorSetQtScript();
@@ -88,13 +86,6 @@ QString GeneratorSetQtScript::generate() {
setupGenerator.setQtMetaTypeDeclaredTypeNames(declaredTypeNames);
setupGenerator.setClasses(classes);
- /*
- ClassGenerator classGenerator(&priGenerator, &setupGenerator);
- classGenerator.setOutputDirectory(outDir);
- classGenerator.setClasses(classes);
- classGenerator.setQtMetaTypeDeclaredTypeNames(declaredTypeNames);
- classGenerator.generate();
-*/
ShellImplGenerator shellImplGenerator(&priGenerator);
shellImplGenerator.setOutputDirectory(outDir);
shellImplGenerator.setClasses(classes);
@@ -106,11 +97,6 @@ QString GeneratorSetQtScript::generate() {
shellHeaderGenerator.setClasses(classes);
shellHeaderGenerator.generate();
- //DocGenerator docGenerator;
- //docGenerator.setOutputDirectory(outDir);
- //docGenerator.setClasses(classes);
- //docGenerator.generate();
-
priGenerator.generate();
setupGenerator.generate();
diff --git a/generator/prigenerator.cpp b/generator/prigenerator.cpp
index a726227..a225602 100644
--- a/generator/prigenerator.cpp
+++ b/generator/prigenerator.cpp
@@ -91,6 +91,10 @@ static QStringList compactFiles(const QStringList& list, const QString& ext, con
QStringList outList;
int count = list.count();
int fileNum = 0;
+ QString srcDir = dir;
+ if (dir.endsWith("_builtin")) {
+ srcDir = dir.left(dir.length()-strlen("_builtin"));
+ }
while (count>0) {
QString outFileName = prefix + QString::number(fileNum) + ext;
FileOut file(dir + "/" + outFileName);
@@ -101,7 +105,7 @@ static QStringList compactFiles(const QStringList& list, const QString& ext, con
QString allText;
QTextStream ts(&allText);
for (int i = 0; i
0; i++) {
- collectAndRemoveFile(ts, dir + "/" + list.at(list.length()-count));
+ collectAndRemoveFile(ts, srcDir + "/" + list.at(list.length()-count));
count--;
}
allText = combineIncludes(allText);
@@ -122,7 +126,8 @@ void PriGenerator::generate()
QString folder = pri.key();
folder.replace('\\','/');
- folder = folder.left(folder.indexOf('/'));
+ int idx = folder.indexOf('/');
+ folder = folder.left(idx);
qSort(list.begin(), list.end());
FileOut file(m_out_dir + "/generated_cpp/" + pri.key());
diff --git a/generator/setupgenerator.cpp b/generator/setupgenerator.cpp
index 49a14f4..875362c 100644
--- a/generator/setupgenerator.cpp
+++ b/generator/setupgenerator.cpp
@@ -46,9 +46,9 @@
//#define Q_SCRIPT_LAZY_GENERATOR
-void SetupGenerator::addClass(const AbstractMetaClass *cls)
+void SetupGenerator::addClass(const QString& package, const AbstractMetaClass *cls)
{
- packHash[cls->package()].append(cls);
+ packHash[package].append(cls);
}
void maybeDeclareMetaType(QTextStream &stream, const QString &typeName,
@@ -80,15 +80,13 @@ void SetupGenerator::generate()
QString packKey = pack.key();
QString packName = pack.key();
- QStringList components = packName.split(".");
+ 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) {
@@ -118,14 +116,21 @@ void SetupGenerator::generate()
}
s << endl;
- QStringList polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id);
- s << endl;
-
+ QStringList polymorphicHandlers;
+ if (!packName.endsWith("_builtin")) {
+ polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id);
+ s << endl;
+ }
+
// declare individual class creation functions
s << "void PythonQt_init_" << shortPackName << "() {" << endl;
+
+ if (shortPackName.endsWith("Builtin")) {
+ shortPackName = shortPackName.mid(shortPackName.length()-strlen("builtin"));
+ }
+
QStringList cppClassNames;
foreach (const AbstractMetaClass *cls, list) {
- if (ShellGenerator::isBuiltIn(cls->name())) { continue; }
QString shellCreator;
if (cls->generateShellClass()) {
diff --git a/generator/setupgenerator.h b/generator/setupgenerator.h
index 7d57e0e..5c7eff2 100644
--- a/generator/setupgenerator.h
+++ b/generator/setupgenerator.h
@@ -52,7 +52,7 @@ class SetupGenerator : public Generator
public:
virtual void generate();
- void addClass(const AbstractMetaClass *cls);
+ void addClass(const QString& package, const AbstractMetaClass *cls);
static void writeInclude(QTextStream &stream, const Include &inc);
diff --git a/generator/shellgenerator.h b/generator/shellgenerator.h
index 2fa67ca..49fa7ee 100644
--- a/generator/shellgenerator.h
+++ b/generator/shellgenerator.h
@@ -46,7 +46,7 @@
#include "metaqtscript.h"
#include "prigenerator.h"
-#define MAX_CLASSES_PER_FILE 20
+#define MAX_CLASSES_PER_FILE 30
class ShellGenerator : public Generator
{
diff --git a/generator/shellheadergenerator.cpp b/generator/shellheadergenerator.cpp
index 3db4f4f..ef1fc5a 100644
--- a/generator/shellheadergenerator.cpp
+++ b/generator/shellheadergenerator.cpp
@@ -53,9 +53,10 @@ QString ShellHeaderGenerator::fileNameForClass(const AbstractMetaClass *meta_cla
void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
{
- if (!ShellGenerator::isBuiltIn(meta_class->name())) {
- setupGenerator->addClass(meta_class);
- }
+ QString builtIn = ShellGenerator::isBuiltIn(meta_class->name())?"_builtin":"";
+ QString pro_file_name = meta_class->package().replace(".", "_") + builtIn + "/" + meta_class->package().replace(".", "_") + builtIn + ".pri";
+ priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
+ setupGenerator->addClass(meta_class->package().replace(".", "_") + builtIn, meta_class);
QString include_block = "PYTHONQTWRAPPER_" + meta_class->name().toUpper() + "_H";
@@ -75,14 +76,6 @@ void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_c
}
s << endl;
- QString pro_file_name = meta_class->package().replace(".", "_") + "/" + meta_class->package().replace(".", "_") + ".pri";
-
- // if (!meta_class->generateShellClass()) {
- // s << "#endif" << endl << endl;
- // priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
- // return ;
- // }
-
AbstractMetaFunctionList ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
| AbstractMetaClass::WasVisible
| AbstractMetaClass::NotRemovedFromTargetLang);
@@ -273,9 +266,6 @@ void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_c
s << "};" << endl << endl
<< "#endif // " << include_block << endl;
- if (!ShellGenerator::isBuiltIn(meta_class->name())) {
- priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
- }
}
void ShellHeaderGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
diff --git a/generator/shellimplgenerator.cpp b/generator/shellimplgenerator.cpp
index 88f71dc..d2d9158 100644
--- a/generator/shellimplgenerator.cpp
+++ b/generator/shellimplgenerator.cpp
@@ -63,12 +63,9 @@ static void writeHelperCode(QTextStream &s, const AbstractMetaClass *)
void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
{
-
- QString pro_file_name = meta_class->package().replace(".", "_") + "/" + meta_class->package().replace(".", "_") + ".pri";
-
- if (!ShellGenerator::isBuiltIn(meta_class->name())) {
- priGenerator->addSource(pro_file_name, fileNameForClass(meta_class));
- }
+ QString builtIn = ShellGenerator::isBuiltIn(meta_class->name())?"_builtin":"";
+ QString pro_file_name = meta_class->package().replace(".", "_") + builtIn + "/" + meta_class->package().replace(".", "_") + builtIn + ".pri";
+ priGenerator->addSource(pro_file_name, fileNameForClass(meta_class));
s << "#include \"PythonQtWrapper_" << meta_class->name() << ".h\"" << endl << endl;