1 /****************************************************************************
3 ** Copyright (C) 1992-2008 Trolltech ASA. All rights reserved.
5 ** This file is part of the Qt Script Generator project on Trolltech Labs.
7 ** This file may be used under the terms of the GNU General Public
8 ** License version 2.0 as published by the Free Software Foundation
9 ** and appearing in the file LICENSE.GPL included in the packaging of
10 ** this file. Please review the following information to ensure GNU
11 ** General Public Licensing requirements will be met:
12 ** http://www.trolltech.com/products/qt/opensource.html
14 ** If you are unsure which license is appropriate for your use, please
15 ** review the following information:
16 ** http://www.trolltech.com/products/qt/licensing.html or contact the
17 ** sales department at sales@trolltech.com.
19 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 ****************************************************************************/
24 #include "setupgenerator.h"
25 #include "reporthandler.h"
28 //#define Q_SCRIPT_LAZY_GENERATOR
30 void SetupGenerator::addClass(const AbstractMetaClass
*cls
)
32 packHash
[cls
->package()].append(cls
);
35 void writeQtScriptQtBindingsLicense(QTextStream
&stream
);
37 static void writeIncludes(QTextStream
&stream
)
39 stream
<< "#include <QtScript/QScriptExtensionPlugin>" << endl
40 << "#include <QtScript/QScriptValue>" << endl
41 << "#include <QtScript/QScriptEngine>" << endl
;
42 #ifdef Q_SCRIPT_LAZY_GENERATOR
43 stream
<< "#include <QtScript/QScriptClass>" << endl
44 << "#include <QtScript/QScriptString>" << endl
;
46 stream
<< "#include <QtCore/QDebug>" << endl
;
49 void writeInclude(QTextStream
&stream
, const Include
&inc
);
50 void maybeDeclareMetaType(QTextStream
&stream
, const QString
&typeName
,
51 QSet
<QString
> ®isteredTypeNames
);
52 bool hasDefaultConstructor(const AbstractMetaClass
*meta_class
);
54 void SetupGenerator::generate()
56 QHashIterator
<QString
, QList
<const AbstractMetaClass
*> > pack(packHash
);
57 while (pack
.hasNext()) {
59 QList
<const AbstractMetaClass
*> list
= pack
.value();
63 QString packName
= pack
.key();
64 QStringList components
= packName
.split(".");
65 if ((components
.size() > 2) && (components
.at(0) == "com")
66 && (components
.at(1) == "trolltech")) {
67 // kill com.trolltech in key
68 components
.removeAt(0);
69 components
.removeAt(0);
71 packName
.replace(".", "_");
72 FileOut
file(m_out_dir
+ "/generated_cpp/" + packName
+ "/main.cpp");
73 QTextStream
&s
= file
.stream
;
76 writeQtScriptQtBindingsLicense(s
);
80 foreach (const AbstractMetaClass
*cls
, list
)
81 writeInclude(s
, cls
->typeEntry()->include());
84 // declare individual class creation functions
85 foreach (const AbstractMetaClass
*cls
, list
) {
86 s
<< "QScriptValue qtscript_create_" << cls
->name() << "_class(QScriptEngine *engine);" << endl
;
90 // write table of class names
92 s
<< "static const char * const qtscript_" << packName
<< "_class_names[] = {" << endl
;
93 bool needComma
= false;
94 foreach (const AbstractMetaClass
*cls
, list
) {
98 s
<< "\"" << cls
->name() << "\"" << endl
;
101 s
<< "};" << endl
<< endl
;
104 // write table of function pointers
106 s
<< "typedef QScriptValue (*QtBindingCreator)(QScriptEngine *engine);" << endl
;
107 s
<< "static const QtBindingCreator qtscript_" << packName
<< "_class_functions[] = {" << endl
;
108 bool needComma
= false;
109 foreach (const AbstractMetaClass
*cls
, list
) {
113 s
<< "qtscript_create_" << cls
->name() << "_class" << endl
;
116 s
<< "};" << endl
<< endl
;
119 #ifdef Q_SCRIPT_LAZY_GENERATOR
121 // declare meta-types
122 QSet
<QString
> registeredTypeNames
= m_qmetatype_declared_typenames
;
123 foreach (const AbstractMetaClass
*cls
, list
) {
124 if (cls
->isNamespace())
126 QString name
= cls
->qualifiedCppName();
127 if (cls
->typeEntry()->isValue() && ::hasDefaultConstructor(cls
))
128 maybeDeclareMetaType(s
, name
, registeredTypeNames
);
129 maybeDeclareMetaType(s
, name
+ "*", registeredTypeNames
);
132 // write table of metatype-ids
133 s
<< "static const int qtscript_" << packName
<< "_metatype_ids[] = {" << endl
;
134 for (int i
= 0; i
< list
.size(); ++i
) {
135 const AbstractMetaClass
*cls
= list
.at(i
);
139 if (cls
->isNamespace()) {
142 QString name
= cls
->qualifiedCppName();
143 if (cls
->typeEntry()->isValue() && ::hasDefaultConstructor(cls
))
144 s
<< "qMetaTypeId<" << name
<< ">()";
147 s
<< ", qMetaTypeId<" << name
<< "*>()";
151 s
<< "};" << endl
<< endl
;
154 // write the fake prototype class
156 s
<< "class qtscript_" << packName
<< "_FakePrototype : public QScriptClass" << endl
159 << " qtscript_" << packName
<< "_FakePrototype(QScriptEngine *engine)" << endl
160 << " : QScriptClass(engine) {}" << endl
<< endl
162 << " QueryFlags queryProperty(const QScriptValue &fake," << endl
163 << " const QScriptString &name, QueryFlags flags, uint *)" << endl
165 << " if (fake.prototype().isValid())" << endl
166 << " return 0;" << endl
167 << " int classIndex = fake.data().toInt32();" << endl
168 << " const char *className = qtscript_" << packName
<< "_class_names[classIndex];" << endl
169 // << " qDebug() << \"faking\" << className;" << endl
170 << " QScriptValue extensionObject = engine()->globalObject();" << endl
171 << " QScriptValue ctor = extensionObject.property(className);" << endl
172 << " QScriptValue genuine = ctor.property(\"prototype\");" << endl
173 << " Q_ASSERT(genuine.isObject());" << endl
174 << " const_cast<QScriptValue&>(fake).setPrototype(genuine);" << endl
175 << " if (!genuine.property(name).isValid())" << endl
176 << " flags &= ~HandlesReadAccess;" << endl
177 << " return flags & ~HandlesWriteAccess;" << endl
178 << " }" << endl
<< endl
180 << " QScriptValue property(const QScriptValue &fake, "
181 << "const QScriptString &name, uint)" << endl
183 << " return fake.prototype().property(name, QScriptValue::ResolveLocal);" << endl
185 << "};" << endl
<< endl
;
188 // write the lazy class loader
190 s
<< "static QScriptValue qtscript_" << packName
<< "_getSetClass("
191 << "QScriptContext *context, QScriptEngine *engine)" << endl
193 << " QScriptValue target = context->thisObject();" << endl
194 << " int classIndex = context->callee().data().toInt32();" << endl
195 << " const char *className = qtscript_" << packName
<< "_class_names[classIndex];" << endl
196 << " qDebug() << \"loading\" << className;" << endl
197 << " target.setProperty(className, QScriptValue(), "
198 << "QScriptValue::PropertyGetter|QScriptValue::PropertySetter);" << endl
199 << " if (context->argumentCount() == 1) {" << endl
200 << " target.setProperty(className, context->argument(0));" << endl
201 << " } else {" << endl
202 << " target.setProperty(className, qtscript_"
203 << packName
<< "_class_functions[classIndex](engine)," << endl
204 << " QScriptValue::SkipInEnumeration);" << endl
206 << " return target.property(className);" << endl
207 << "}" << endl
<< endl
;
211 // plugin class declaration
212 s
<< "class " << packName
<< "_ScriptPlugin : public QScriptExtensionPlugin" << endl
215 << " QStringList keys() const;" << endl
216 << " void initialize(const QString &key, QScriptEngine *engine);" << endl
221 s
<< "QStringList " << packName
<< "_ScriptPlugin::keys() const" << endl
223 << " QStringList list;" << endl
;
226 for (int i
= 0; i
< components
.size(); ++i
) {
229 key
.append(components
.at(i
));
230 s
<< " list << QLatin1String(\"" << key
<< "\");" << endl
;
233 s
<< " return list;" << endl
238 << "void " << packName
<< "_ScriptPlugin::initialize(const QString &key, QScriptEngine *engine)" << endl
242 for (int i
= 0; i
< components
.size(); ++i
) {
248 key
.append(components
.at(i
));
249 s
<< "if (key == QLatin1String(\"" << key
<< "\")) {";
252 s
<< endl
<< " QScriptValue extensionObject = ";
254 if (packName
== "com.trolltech.qt.phonon")
255 s
<< "setupPackage(\"phonon\", engine)";
257 s
<< "engine->globalObject()";
260 #ifdef Q_SCRIPT_LAZY_GENERATOR
261 s
<< " qtscript_" << packName
<< "_FakePrototype *fakeProtoClass;" << endl
262 << " fakeProtoClass = new qtscript_" << packName
<< "_FakePrototype(engine);" << endl
;
264 s
<< " for (int i = 0; i < " << list
.size() << "; ++i) {" << endl
265 #ifndef Q_SCRIPT_LAZY_GENERATOR
266 << " extensionObject.setProperty(qtscript_" << packName
<< "_class_names[i]," << endl
267 << " qtscript_" << packName
<< "_class_functions[i](engine)," << endl
268 << " QScriptValue::SkipInEnumeration);" << endl
270 << " QScriptValue classIndex(engine, i);" << endl
271 << " QScriptValue fakeCtor = engine->newFunction(qtscript_" << packName
<< "_getSetClass);" << endl
272 << " fakeCtor.setData(classIndex);" << endl
273 << " extensionObject.setProperty(qtscript_" << packName
<< "_class_names[i]," << endl
274 << " fakeCtor, QScriptValue::PropertyGetter|QScriptValue::PropertySetter"
275 << "|QScriptValue::SkipInEnumeration);" << endl
276 << " QScriptValue fakeProto = engine->newObject(fakeProtoClass, classIndex);" << endl
277 << " fakeProto.setPrototype(QScriptValue());" << endl
278 << " if (qtscript_" << packName
<< "_metatype_ids[i*2] != -1)" << endl
279 << " engine->setDefaultPrototype(qtscript_"
280 << packName
<< "_metatype_ids[i*2], fakeProto);" << endl
281 << " if (qtscript_" << packName
<< "_metatype_ids[i*2+1] != -1)" << endl
282 << " engine->setDefaultPrototype(qtscript_"
283 << packName
<< "_metatype_ids[i*2+1], fakeProto);" << endl
287 s
<< " } else {" << endl
288 << " Q_ASSERT_X(false, \"" << packName
<< "::initialize\", qPrintable(key));" << endl
292 s
<< "Q_EXPORT_STATIC_PLUGIN(" << packName
<< "_ScriptPlugin)" << endl
293 << "Q_EXPORT_PLUGIN2(qtscript_" << packName
.toLower() << ", " << packName
<< "_ScriptPlugin)" << endl
<< endl
;
296 ++m_num_generated_written
;