void ShellImplGenerator
::write(QTextStream &s,
const AbstractMetaClass
*meta_class
) {
if (FileOut::license)
writeQtScriptQtBindingsLicense(s);
QString packName
= meta_class
->package
().
replace(".",
"_");
priGenerator->addSource(packName, fileNameForClass(meta_class));
s << "#include \"qtscriptshell_" << meta_class->name() << ".h\"" << endl << endl;
if (!meta_class->generateShellClass())
return;
s << "#include <QtScript/QScriptEngine>" << endl;
IncludeList list = meta_class->typeEntry()->extraIncludes();
qSort(list.begin(), list.end(), include_less_than);
foreach (const Include &inc, list) {
if (inc.type == Include::TargetLangImport)
continue;
s << "#include ";
if (inc.type == Include::LocalPath)
s << "\"";
else
s << "<";
s << inc.name;
if (inc.type == Include::LocalPath)
s << "\"";
else
s << ">";
s << endl;
}
s << endl;
writeHelperCode(s, meta_class);
// find constructors
AbstractMetaFunctionList ctors;
ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
| AbstractMetaClass::WasVisible
| AbstractMetaClass::NotRemovedFromTargetLang);
// find member functions
AbstractMetaFunctionList functions = meta_class->queryFunctions(
AbstractMetaClass:: VirtualFunctions | AbstractMetaClass::WasVisible
| AbstractMetaClass::NotRemovedFromTargetLang
);
// write metatype declarations
{
QSet<QString> registeredTypeNames = m_qmetatype_declared_typenames;
declareFunctionMetaTypes(s, functions, registeredTypeNames);
s << endl;
}
// write constructors
foreach (const AbstractMetaFunction *ctor, ctors) {
s << "QtScriptShell_" << meta_class->name() << "::";
writeFunctionSignature
(s, ctor,
0,
QString(), Option
(OriginalName | ShowStatic
));
s << endl;
s << " : " << meta_class->qualifiedCppName() << "(";
AbstractMetaArgumentList args = ctor->arguments();
for (int i = 0; i < args.size(); ++i) {
if (i > 0)
s << ", ";
s << args.at(i)->argumentName();
}
s << ")" << " {}" << endl << endl;
}
// write destructor
s << "QtScriptShell_" << meta_class->name() << "::"
<< "~QtScriptShell_" << meta_class->name() << "()";
if (!meta_class->destructorException().isEmpty())
s << " " << meta_class->destructorException();
s << " {}" << endl << endl;
// write member functions
for (int i = 0; i < functions.size(); ++i) {
AbstractMetaFunction *fun = functions.at(i);
writeFunctionSignature
(s, fun, meta_class,
QString(),
Option(OriginalName | ShowStatic | UnderscoreSpaces),
"QtScriptShell_");
s << endl << "{" << endl;
QString scriptFunctionName
= fun
->name
();
{
QPropertySpec *read = 0;
for (const AbstractMetaClass *cls = meta_class; !read && cls; cls = cls->baseClass())
read = cls->propertySpecForRead(fun->name());
if (read && (read->name() == fun->name())) {
// use different name to avoid infinite recursion
// ### not sure if this is the best solution though...
scriptFunctionName.prepend("_qs_");
}
}
s << " QScriptValue _q_function = __qtscript_self.property(\""
<< scriptFunctionName << "\");" << endl;
s << " if (!_q_function.isFunction() || QTSCRIPT_IS_GENERATED_FUNCTION(_q_function)" << endl
<< " || (__qtscript_self.propertyFlags(\"" << scriptFunctionName << "\") & QScriptValue::QObjectMember)) {" << endl;
AbstractMetaArgumentList args = fun->arguments();
s << " ";
if (fun->isAbstract()) {
s << "qFatal(\"" << meta_class->name() << "::" << fun->name()
<< "() is abstract!\");" << endl;
} else {
// call the C++ implementation
if (fun->type()) {
s << "return ";
}
s << meta_class->qualifiedCppName() << "::" << fun->originalName() << "(";
for (int i = 0; i < args.size(); ++i) {
if (i > 0)
s << ", ";
s << args.at(i)->argumentName();
}
s << ");" << endl;
}
s << " } else {" << endl;
// call the script function
if (args.size() > 0)
s << " QScriptEngine *_q_engine = __qtscript_self.engine();" << endl;
// NTS Addon
if (!fun->isAbstract()) {
s << " // callmode. first bit: 1:callcpp|0:don't call cpp" << endl;
s << " // 2nd-bit: 1:returncpp|0:returnscript" << endl;
s << " int _callmode = 3;" << endl;
s << " QScriptValue _q_callmode = __qtscript_self.property(\""
<< scriptFunctionName << "_callmode\");" << endl;
s << " if (_q_callmode.isValid()) _callmode = _q_callmode.toInt32();" << endl;
s << " if ((_callmode & 1) > 0) {" << endl;
// First call the c++ implementation
s << " ";
if (fun->type()) {
writeTypeInfo(s, fun->type());
s << "resultcpp = ";
}
s << meta_class->qualifiedCppName() << "::" << fun->originalName() << "(";
for (int i = 0; i < args.size(); ++i) {
if (i > 0)
s << ", ";
s << args.at(i)->argumentName();
}
s << ");" << endl;
// Then call the script implementation
s << " ";
if (fun->type()) {
writeTypeInfo(s, fun->type());
s << "resultscript = qscriptvalue_cast<";
writeTypeInfo(s, fun->type());
s << ">(";
}
s << "_q_function.call(__qtscript_self";
if (args.size() > 0) {
s << "," << endl;
s << " QScriptValueList()";
int i = 0;
for (int j = 0; j < args.size(); ++j) {
if (fun->argumentRemoved(j+1))
continue;
s << endl << " << ";
s << "qScriptValueFromValue(_q_engine, ";
AbstractMetaType *atype = args.at(j)->type();
QString asig
= atype
->cppSignature
();
bool constCastArg = asig.endsWith('*') && asig.startsWith("const ");
if (constCastArg)
s << "const_cast<" << asig.mid(6) << ">(";
s << args.at(i)->argumentName() << ")";
if (constCastArg)
s << ")";
++i;
}
}
s << ")";
if (fun->type())
s << ")";
s << ";" << endl;
if (fun->type()) {
// Decide which value to return
s << " if ((_callmode & 2) > 0) {" << endl;
s << " return resultcpp;" << endl;
s << " } else {" << endl;
s << " return resultscript;" << endl;
s << " }"<< endl;
}
s << " } else {" << endl;
}
// only call the script implementation
s << " ";
if (fun->type()) {
s << "return qscriptvalue_cast<";
writeTypeInfo(s, fun->type());
s << ">(";
}
s << "_q_function.call(__qtscript_self";
if (args.size() > 0) {
s << "," << endl;
s << " QScriptValueList()";
int i = 0;
for (int j = 0; j < args.size(); ++j) {
if (fun->argumentRemoved(j+1))
continue;
s << endl << " << ";
s << "qScriptValueFromValue(_q_engine, ";
AbstractMetaType *atype = args.at(j)->type();
QString asig
= atype
->cppSignature
();
bool constCastArg = asig.endsWith('*') && asig.startsWith("const ");
if (constCastArg)
s << "const_cast<" << asig.mid(6) << ">(";
s << args.at(i)->argumentName() << ")";
if (constCastArg)
s << ")";
++i;
}
}
s << ")";
if (fun->type())
s << ")";
s << ";" << endl;
if (!fun->isAbstract()) {
s << " }" << endl;
}
s << " }" << endl;
s << "}" << endl << endl;
}
}
Bookmarks