##// END OF EJS Templates
added experimental compacting to avoid generation of hundreds of files that all include the same stuff...
florianlink -
r92:f97ec94c87a9
parent child
Show More
@@ -1,1872 +1,1842
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "classgenerator.h"
42 #include "classgenerator.h"
43 #include "fileout.h"
43 #include "fileout.h"
44
44
45 #include <QtCore/QDir>
45 #include <QtCore/QDir>
46 #include <QtCore/QMetaType>
46 #include <QtCore/QMetaType>
47
47
48 #include <qdebug.h>
48 #include <qdebug.h>
49
49
50 #define GENERATOR_NO_PROTECTED_FUNCTIONS
50 #define GENERATOR_NO_PROTECTED_FUNCTIONS
51
51
52 ClassGenerator::ClassGenerator(PriGenerator *pri, SetupGenerator *setup) :
52 ClassGenerator::ClassGenerator(PriGenerator *pri, SetupGenerator *setup) :
53 priGenerator(pri),
53 priGenerator(pri),
54 setupGenerator(setup)
54 setupGenerator(setup)
55 {}
55 {}
56
56
57 QString ClassGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
57 QString ClassGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
58 {
58 {
59 return QString("qtscript_%1.cpp").arg(meta_class->name());
59 return QString("qtscript_%1.cpp").arg(meta_class->name());
60 }
60 }
61
61
62 bool ClassGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
62 bool ClassGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
63 {
63 {
64 return false; // DISABLED!
64 return false; // DISABLED!
65 uint cg = meta_class->typeEntry()->codeGeneration();
65 uint cg = meta_class->typeEntry()->codeGeneration();
66 return (cg & TypeEntry::GenerateCode) != 0;
66 return (cg & TypeEntry::GenerateCode) != 0;
67 }
67 }
68
68
69 static QString normalizedType(const AbstractMetaType *type)
69 static QString normalizedType(const AbstractMetaType *type)
70 {
70 {
71 QString str = QString::fromLatin1(QMetaObject::normalizedType(type->cppSignature().toLatin1()));
71 QString str = QString::fromLatin1(QMetaObject::normalizedType(type->cppSignature().toLatin1()));
72 if (str.endsWith(QLatin1Char('&')))
72 if (str.endsWith(QLatin1Char('&')))
73 str.chop(1);
73 str.chop(1);
74 else if (str.startsWith("const ")) {
74 else if (str.startsWith("const ")) {
75 if (str.endsWith('*') || type->hasInstantiations() || type->typeEntry()->isValue())
75 if (str.endsWith('*') || type->hasInstantiations() || type->typeEntry()->isValue())
76 str.remove(0, 6);
76 str.remove(0, 6);
77 }
77 }
78 if (str == QLatin1String("QBool")) // ### hack
78 if (str == QLatin1String("QBool")) // ### hack
79 str = QLatin1String("bool");
79 str = QLatin1String("bool");
80 return str;
80 return str;
81 }
81 }
82
82
83 /*!
83 /*!
84 Returns true if the class \a meta_class inherits from QObject,
84 Returns true if the class \a meta_class inherits from QObject,
85 otherwise returns false.
85 otherwise returns false.
86 */
86 */
87 static bool isQObjectBased(const AbstractMetaClass *meta_class)
87 static bool isQObjectBased(const AbstractMetaClass *meta_class)
88 {
88 {
89 while (meta_class) {
89 while (meta_class) {
90 if (meta_class->name() == QLatin1String("QObject"))
90 if (meta_class->name() == QLatin1String("QObject"))
91 return true;
91 return true;
92 meta_class = meta_class->baseClass();
92 meta_class = meta_class->baseClass();
93 }
93 }
94 return false;
94 return false;
95 }
95 }
96
96
97 /*!
97 /*!
98 Returns true if any of the given \a enums has been declared with
98 Returns true if any of the given \a enums has been declared with
99 Q_ENUMS.
99 Q_ENUMS.
100 */
100 */
101 static bool hasQEnums(const AbstractMetaEnumList &enums)
101 static bool hasQEnums(const AbstractMetaEnumList &enums)
102 {
102 {
103 for (int i = 0; i < enums.size(); ++i) {
103 for (int i = 0; i < enums.size(); ++i) {
104 if (enums.at(i)->hasQEnumsDeclaration())
104 if (enums.at(i)->hasQEnumsDeclaration())
105 return true;
105 return true;
106 }
106 }
107 return false;
107 return false;
108 }
108 }
109
109
110 /*!
110 /*!
111 Returns true if any of the given \a enums has a QFlags class
111 Returns true if any of the given \a enums has a QFlags class
112 associated with it.
112 associated with it.
113 */
113 */
114 static bool hasFlags(const AbstractMetaEnumList &enums)
114 static bool hasFlags(const AbstractMetaEnumList &enums)
115 {
115 {
116 for (int i = 0; i < enums.size(); ++i) {
116 for (int i = 0; i < enums.size(); ++i) {
117 FlagsTypeEntry *flags = enums.at(i)->typeEntry()->flags();
117 FlagsTypeEntry *flags = enums.at(i)->typeEntry()->flags();
118 if (flags)
118 if (flags)
119 return true;
119 return true;
120 }
120 }
121 return false;
121 return false;
122 }
122 }
123
123
124 static bool isSequenceType(const AbstractMetaType *tp)
124 static bool isSequenceType(const AbstractMetaType *tp)
125 {
125 {
126 return tp->isContainer() && (tp->instantiations().size() == 1);
126 return tp->isContainer() && (tp->instantiations().size() == 1);
127 }
127 }
128
128
129 static AbstractMetaFunction *findDefaultConstructor(const AbstractMetaFunctionList &ctors)
129 static AbstractMetaFunction *findDefaultConstructor(const AbstractMetaFunctionList &ctors)
130 {
130 {
131 for (int i = 0; i < ctors.size(); ++i) {
131 for (int i = 0; i < ctors.size(); ++i) {
132 if (ctors.at(i)->actualMinimumArgumentCount() == 0)
132 if (ctors.at(i)->actualMinimumArgumentCount() == 0)
133 return ctors.at(i);
133 return ctors.at(i);
134 }
134 }
135 return 0;
135 return 0;
136 }
136 }
137
137
138 static AbstractMetaFunctionList findConstructors(const AbstractMetaClass *meta_class)
138 static AbstractMetaFunctionList findConstructors(const AbstractMetaClass *meta_class)
139 {
139 {
140 return meta_class->queryFunctions(AbstractMetaClass::Constructors
140 return meta_class->queryFunctions(AbstractMetaClass::Constructors
141 | AbstractMetaClass::WasPublic
141 | AbstractMetaClass::WasPublic
142 | AbstractMetaClass::NotRemovedFromTargetLang);
142 | AbstractMetaClass::NotRemovedFromTargetLang);
143 }
143 }
144
144
145 /*!
145 /*!
146 Returns true if \a meta_class has a default constructor, false
146 Returns true if \a meta_class has a default constructor, false
147 otherwise.
147 otherwise.
148 */
148 */
149 bool hasDefaultConstructor(const AbstractMetaClass *meta_class)
149 bool hasDefaultConstructor(const AbstractMetaClass *meta_class)
150 {
150 {
151 return findDefaultConstructor(findConstructors(meta_class)) != 0;
151 return findDefaultConstructor(findConstructors(meta_class)) != 0;
152 }
152 }
153
153
154 /*!
154 /*!
155 Given the list of \a functions, creates a mapping from # of
155 Given the list of \a functions, creates a mapping from # of
156 arguments to list of functions.
156 arguments to list of functions.
157 */
157 */
158 static QMap<int, AbstractMetaFunctionList> createArgcToFunctionsMap(
158 static QMap<int, AbstractMetaFunctionList> createArgcToFunctionsMap(
159 const AbstractMetaFunctionList &functions)
159 const AbstractMetaFunctionList &functions)
160 {
160 {
161 QMap<int, AbstractMetaFunctionList> result;
161 QMap<int, AbstractMetaFunctionList> result;
162 for (int i = 0; i < functions.size(); ++i) {
162 for (int i = 0; i < functions.size(); ++i) {
163 AbstractMetaFunction *func = functions.at(i);
163 AbstractMetaFunction *func = functions.at(i);
164 int argc = func->arguments().size();
164 int argc = func->arguments().size();
165 for (int k = argc; k > 0; --k) {
165 for (int k = argc; k > 0; --k) {
166 if (func->argumentRemoved(k))
166 if (func->argumentRemoved(k))
167 --argc;
167 --argc;
168 }
168 }
169 for (int j = func->actualMinimumArgumentCount(); j <= argc; ++j)
169 for (int j = func->actualMinimumArgumentCount(); j <= argc; ++j)
170 result[j].append(func);
170 result[j].append(func);
171 }
171 }
172 return result;
172 return result;
173 }
173 }
174
174
175 /*!
175 /*!
176 Returns the name of the QScriptValue function to use to test if
176 Returns the name of the QScriptValue function to use to test if
177 a value is of the given \a typeName, or an empty string if there
177 a value is of the given \a typeName, or an empty string if there
178 is no such function.
178 is no such function.
179 */
179 */
180 static QString builtinTypeTesterFunction(const QString &typeName)
180 static QString builtinTypeTesterFunction(const QString &typeName)
181 {
181 {
182 if (typeName == QLatin1String("QString"))
182 if (typeName == QLatin1String("QString"))
183 return QLatin1String("isString");
183 return QLatin1String("isString");
184 else if (typeName == QLatin1String("double"))
184 else if (typeName == QLatin1String("double"))
185 return QLatin1String("isNumber");
185 return QLatin1String("isNumber");
186 else if (typeName == QLatin1String("float"))
186 else if (typeName == QLatin1String("float"))
187 return QLatin1String("isNumber");
187 return QLatin1String("isNumber");
188 else if (typeName == QLatin1String("int"))
188 else if (typeName == QLatin1String("int"))
189 return QLatin1String("isNumber");
189 return QLatin1String("isNumber");
190 else if (typeName == QLatin1String("uint"))
190 else if (typeName == QLatin1String("uint"))
191 return QLatin1String("isNumber");
191 return QLatin1String("isNumber");
192 else if (typeName == QLatin1String("short"))
192 else if (typeName == QLatin1String("short"))
193 return QLatin1String("isNumber");
193 return QLatin1String("isNumber");
194 else if (typeName == QLatin1String("unsigned short"))
194 else if (typeName == QLatin1String("unsigned short"))
195 return QLatin1String("isNumber");
195 return QLatin1String("isNumber");
196 else if (typeName == QLatin1String("bool"))
196 else if (typeName == QLatin1String("bool"))
197 return QLatin1String("isBoolean");
197 return QLatin1String("isBoolean");
198 else if (typeName == QLatin1String("QVariant"))
198 else if (typeName == QLatin1String("QVariant"))
199 return QLatin1String("isVariant");
199 return QLatin1String("isVariant");
200 // else if (typeName == QLatin1String("QDateTime"))
200 // else if (typeName == QLatin1String("QDateTime"))
201 // return QLatin1String("isDate");
201 // return QLatin1String("isDate");
202 else if (typeName == QLatin1String("QRegExp"))
202 else if (typeName == QLatin1String("QRegExp"))
203 return QLatin1String("isRegExp");
203 return QLatin1String("isRegExp");
204 else if (typeName == QLatin1String("QObject*"))
204 else if (typeName == QLatin1String("QObject*"))
205 return QLatin1String("isQObject");
205 return QLatin1String("isQObject");
206 return QString();
206 return QString();
207 }
207 }
208
208
209 /*!
209 /*!
210 Writes the code injections for the class \a meta_class that should
210 Writes the code injections for the class \a meta_class that should
211 be injected at position \a pos.
211 be injected at position \a pos.
212 */
212 */
213 static void writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class,
213 static void writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class,
214 CodeSnip::Position pos)
214 CodeSnip::Position pos)
215 {
215 {
216 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
216 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
217 foreach (const CodeSnip &cs, code_snips) {
217 foreach (const CodeSnip &cs, code_snips) {
218 if ((cs.language == TypeSystem::NativeCode) && (cs.position == pos)) {
218 if ((cs.language == TypeSystem::NativeCode) && (cs.position == pos)) {
219 s << cs.code() << endl;
219 s << cs.code() << endl;
220 }
220 }
221 }
221 }
222 }
222 }
223
223
224 /*!
224 /*!
225 Writes the code injections for the function \a fun of the class \a
225 Writes the code injections for the function \a fun of the class \a
226 meta_class that should be injected at position \a pos.
226 meta_class that should be injected at position \a pos.
227 */
227 */
228 static void writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class,
228 static void writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class,
229 const AbstractMetaFunction *fun, CodeSnip::Position pos)
229 const AbstractMetaFunction *fun, CodeSnip::Position pos)
230 {
230 {
231 FunctionModificationList mods = fun->modifications(meta_class);
231 FunctionModificationList mods = fun->modifications(meta_class);
232 foreach (const FunctionModification &mod, mods) {
232 foreach (const FunctionModification &mod, mods) {
233 if (!mod.isCodeInjection())
233 if (!mod.isCodeInjection())
234 continue;
234 continue;
235 foreach (const CodeSnip &cs, mod.snips) {
235 foreach (const CodeSnip &cs, mod.snips) {
236 if ((cs.language == TypeSystem::NativeCode) && (cs.position == pos)) {
236 if ((cs.language == TypeSystem::NativeCode) && (cs.position == pos)) {
237 s << cs.code() << endl;
237 s << cs.code() << endl;
238 }
238 }
239 }
239 }
240 }
240 }
241 }
241 }
242
242
243 /*!
243 /*!
244 Writes a boolean expression that checks if the actual arguments are
244 Writes a boolean expression that checks if the actual arguments are
245 compatible with what the function expects. This is used to resolve
245 compatible with what the function expects. This is used to resolve
246 ambiguous calls.
246 ambiguous calls.
247 */
247 */
248 static void writeArgumentTypeTests(QTextStream &stream, const AbstractMetaFunction *fun,
248 static void writeArgumentTypeTests(QTextStream &stream, const AbstractMetaFunction *fun,
249 const AbstractMetaArgumentList &arguments, int argc, int indent)
249 const AbstractMetaArgumentList &arguments, int argc, int indent)
250 {
250 {
251 QString indentStr(indent, QLatin1Char(' '));
251 QString indentStr(indent, QLatin1Char(' '));
252 int j = 0;
252 int j = 0;
253 for (int i = 0; i < argc; ++j) {
253 for (int i = 0; i < argc; ++j) {
254 if (fun->argumentRemoved(j+1))
254 if (fun->argumentRemoved(j+1))
255 continue;
255 continue;
256 if (i > 0)
256 if (i > 0)
257 stream << endl << indentStr << "&& ";
257 stream << endl << indentStr << "&& ";
258 const AbstractMetaType *argType = 0;
258 const AbstractMetaType *argType = 0;
259 QString typeName = fun->typeReplaced(j+1);
259 QString typeName = fun->typeReplaced(j+1);
260 if (typeName.isEmpty()) {
260 if (typeName.isEmpty()) {
261 AbstractMetaArgument *arg = arguments.at(j);
261 AbstractMetaArgument *arg = arguments.at(j);
262 argType = arg->type();
262 argType = arg->type();
263 typeName = normalizedType(argType);
263 typeName = normalizedType(argType);
264 }
264 }
265 QString scriptArg = QString::fromLatin1("context->argument(%0)").arg(i);
265 QString scriptArg = QString::fromLatin1("context->argument(%0)").arg(i);
266 if (argType && isSequenceType(argType)) {
266 if (argType && isSequenceType(argType)) {
267 stream << scriptArg << ".isArray()";
267 stream << scriptArg << ".isArray()";
268 } else if (typeName == "QVariant") {
268 } else if (typeName == "QVariant") {
269 stream << "true";
269 stream << "true";
270 } else {
270 } else {
271 QString tester = builtinTypeTesterFunction(typeName);
271 QString tester = builtinTypeTesterFunction(typeName);
272 if (!tester.isEmpty()) {
272 if (!tester.isEmpty()) {
273 stream << scriptArg << "." << tester << "()";
273 stream << scriptArg << "." << tester << "()";
274 } else if (typeName.endsWith('*')) {
274 } else if (typeName.endsWith('*')) {
275 stream << "qscriptvalue_cast<" << typeName << ">(" << scriptArg << ")";
275 stream << "qscriptvalue_cast<" << typeName << ">(" << scriptArg << ")";
276 } else {
276 } else {
277 // typeid-based test
277 // typeid-based test
278 stream << "(qMetaTypeId<" << typeName;
278 stream << "(qMetaTypeId<" << typeName;
279 if (typeName.endsWith(QLatin1Char('>')))
279 if (typeName.endsWith(QLatin1Char('>')))
280 stream << " ";
280 stream << " ";
281 stream << ">() == " << scriptArg << ".toVariant().userType())";
281 stream << ">() == " << scriptArg << ".toVariant().userType())";
282 }
282 }
283 }
283 }
284 ++i;
284 ++i;
285 }
285 }
286 }
286 }
287
287
288 /*!
288 /*!
289 Returns the name of the QScriptValue function to use to convert a
289 Returns the name of the QScriptValue function to use to convert a
290 value is of the given \a typeName, or an empty string if there is no
290 value is of the given \a typeName, or an empty string if there is no
291 such function.
291 such function.
292 */
292 */
293 static QString builtinConversionFunction(const QString &typeName)
293 static QString builtinConversionFunction(const QString &typeName)
294 {
294 {
295 if (typeName == QLatin1String("QString"))
295 if (typeName == QLatin1String("QString"))
296 return QLatin1String("toString");
296 return QLatin1String("toString");
297 else if (typeName == QLatin1String("double"))
297 else if (typeName == QLatin1String("double"))
298 return QLatin1String("toNumber");
298 return QLatin1String("toNumber");
299 else if (typeName == QLatin1String("int"))
299 else if (typeName == QLatin1String("int"))
300 return QLatin1String("toInt32");
300 return QLatin1String("toInt32");
301 else if (typeName == QLatin1String("uint"))
301 else if (typeName == QLatin1String("uint"))
302 return QLatin1String("toUInt32");
302 return QLatin1String("toUInt32");
303 else if (typeName == QLatin1String("bool"))
303 else if (typeName == QLatin1String("bool"))
304 return QLatin1String("toBoolean");
304 return QLatin1String("toBoolean");
305 else if (typeName == QLatin1String("QVariant"))
305 else if (typeName == QLatin1String("QVariant"))
306 return QLatin1String("toVariant");
306 return QLatin1String("toVariant");
307 else if (typeName == QLatin1String("QDateTime"))
307 else if (typeName == QLatin1String("QDateTime"))
308 return QLatin1String("toDateTime");
308 return QLatin1String("toDateTime");
309 else if (typeName == QLatin1String("QRegExp"))
309 else if (typeName == QLatin1String("QRegExp"))
310 return QLatin1String("toRegExp");
310 return QLatin1String("toRegExp");
311 else if (typeName == QLatin1String("QObject*"))
311 else if (typeName == QLatin1String("QObject*"))
312 return QLatin1String("toQObject");
312 return QLatin1String("toQObject");
313 return QString();
313 return QString();
314 }
314 }
315
315
316 /*!
316 /*!
317 Generates script arguments --> C++ types conversion, in preparation
317 Generates script arguments --> C++ types conversion, in preparation
318 for calling the native function we are binding.
318 for calling the native function we are binding.
319 */
319 */
320 static int writePrepareArguments(QTextStream &stream, const AbstractMetaFunction *fun,
320 static int writePrepareArguments(QTextStream &stream, const AbstractMetaFunction *fun,
321 const AbstractMetaArgumentList &arguments,
321 const AbstractMetaArgumentList &arguments,
322 int scriptArgc, int indent)
322 int scriptArgc, int indent)
323 {
323 {
324 if (arguments.size() == 0) {
324 if (arguments.size() == 0) {
325 Q_ASSERT(scriptArgc == 0);
325 Q_ASSERT(scriptArgc == 0);
326 return 0; // nothing to do
326 return 0; // nothing to do
327 }
327 }
328 QString indentStr(indent, QLatin1Char(' '));
328 QString indentStr(indent, QLatin1Char(' '));
329 int j = 0;
329 int j = 0;
330 for (int scriptArgIndex = 0; j < arguments.size(); ++j) {
330 for (int scriptArgIndex = 0; j < arguments.size(); ++j) {
331 const AbstractMetaArgument *arg = arguments.at(j);
331 const AbstractMetaArgument *arg = arguments.at(j);
332 bool isOptional = !arg->defaultValueExpression().isEmpty();
332 bool isOptional = !arg->defaultValueExpression().isEmpty();
333 if (isOptional && (scriptArgIndex == scriptArgc))
333 if (isOptional && (scriptArgIndex == scriptArgc))
334 break;
334 break;
335 QString conv = fun->conversionRule(TypeSystem::NativeCode, j+1);
335 QString conv = fun->conversionRule(TypeSystem::NativeCode, j+1);
336 QString actualIn = QString::fromLatin1("context->argument(%0)").arg(scriptArgIndex);
336 QString actualIn = QString::fromLatin1("context->argument(%0)").arg(scriptArgIndex);
337 QString actualOut = QString::fromLatin1("_q_arg%0").arg(j);
337 QString actualOut = QString::fromLatin1("_q_arg%0").arg(j);
338 if (!conv.isEmpty()) {
338 if (!conv.isEmpty()) {
339 // custom conversion
339 // custom conversion
340 conv.replace(QString::fromLatin1("%in%"), actualIn);
340 conv.replace(QString::fromLatin1("%in%"), actualIn);
341 conv.replace(QString::fromLatin1("%out%"), actualOut);
341 conv.replace(QString::fromLatin1("%out%"), actualOut);
342 conv.replace(QString::fromLatin1("%this%"), QString::fromLatin1("_q_self"));
342 conv.replace(QString::fromLatin1("%this%"), QString::fromLatin1("_q_self"));
343 stream << conv;
343 stream << conv;
344 } else {
344 } else {
345 const AbstractMetaType *argType = 0;
345 const AbstractMetaType *argType = 0;
346 QString typeName = fun->typeReplaced(j+1);
346 QString typeName = fun->typeReplaced(j+1);
347 if (typeName.isEmpty()) {
347 if (typeName.isEmpty()) {
348 argType = arg->type();
348 argType = arg->type();
349 typeName = normalizedType(argType);
349 typeName = normalizedType(argType);
350 }
350 }
351 stream << indentStr << typeName << " " << actualOut;
351 stream << indentStr << typeName << " " << actualOut;
352 QString converter;
352 QString converter;
353 // ### generalize the QSet check (we should check if the type has push_back())
353 // ### generalize the QSet check (we should check if the type has push_back())
354 bool useToSequence = argType && isSequenceType(argType) && !argType->name().startsWith("Set");
354 bool useToSequence = argType && isSequenceType(argType) && !argType->name().startsWith("Set");
355 if (useToSequence) {
355 if (useToSequence) {
356 stream << ";" << endl;
356 stream << ";" << endl;
357 stream << indentStr << "qScriptValueToSequence(";
357 stream << indentStr << "qScriptValueToSequence(";
358 } else {
358 } else {
359 stream << " = ";
359 stream << " = ";
360 converter = builtinConversionFunction(typeName);
360 converter = builtinConversionFunction(typeName);
361 if (converter.isEmpty()) {
361 if (converter.isEmpty()) {
362 // generic conversion
362 // generic conversion
363 stream << "qscriptvalue_cast<" << typeName;
363 stream << "qscriptvalue_cast<" << typeName;
364 if (typeName.endsWith(QLatin1Char('>')))
364 if (typeName.endsWith(QLatin1Char('>')))
365 stream << " ";
365 stream << " ";
366 stream << ">(";
366 stream << ">(";
367 }
367 }
368 }
368 }
369 stream << actualIn;
369 stream << actualIn;
370 if (useToSequence) {
370 if (useToSequence) {
371 stream << ", " << actualOut << ")";
371 stream << ", " << actualOut << ")";
372 } else {
372 } else {
373 if (converter.isEmpty()) {
373 if (converter.isEmpty()) {
374 stream << ")"; // close qscriptvalue_cast
374 stream << ")"; // close qscriptvalue_cast
375 } else {
375 } else {
376 stream << "." << converter << "()";
376 stream << "." << converter << "()";
377 }
377 }
378 }
378 }
379 stream << ";" << endl;
379 stream << ";" << endl;
380 }
380 }
381 if (!fun->argumentRemoved(j+1))
381 if (!fun->argumentRemoved(j+1))
382 ++scriptArgIndex;
382 ++scriptArgIndex;
383 }
383 }
384 return j;
384 return j;
385 }
385 }
386
386
387 /*!
387 /*!
388 Writes the arguments that are passed to the native function we are
388 Writes the arguments that are passed to the native function we are
389 binding. Those arguments must have been prepared already in variables
389 binding. Those arguments must have been prepared already in variables
390 _q_arg0, _q_arg1, .. in the generated code.
390 _q_arg0, _q_arg1, .. in the generated code.
391 */
391 */
392 static void writeArguments(QTextStream &stream, int count)
392 static void writeArguments(QTextStream &stream, int count)
393 {
393 {
394 for (int i = 0; i < count; ++i) {
394 for (int i = 0; i < count; ++i) {
395 if (i > 0)
395 if (i > 0)
396 stream << ", ";
396 stream << ", ";
397 stream << "_q_arg" << i;
397 stream << "_q_arg" << i;
398 }
398 }
399 }
399 }
400
400
401 /*!
401 /*!
402 Writes a constructor call.
402 Writes a constructor call.
403 */
403 */
404 static void writeConstructorCallAndReturn(QTextStream &stream, const AbstractMetaFunction *fun,
404 static void writeConstructorCallAndReturn(QTextStream &stream, const AbstractMetaFunction *fun,
405 int scriptArgc, const AbstractMetaClass *meta_class,
405 int scriptArgc, const AbstractMetaClass *meta_class,
406 int indent)
406 int indent)
407 {
407 {
408 QString indentStr(indent, QLatin1Char(' '));
408 QString indentStr(indent, QLatin1Char(' '));
409
409
410 writeInjectedCode(stream, meta_class, fun, CodeSnip::Beginning);
410 writeInjectedCode(stream, meta_class, fun, CodeSnip::Beginning);
411
411
412 AbstractMetaArgumentList arguments = fun->arguments();
412 AbstractMetaArgumentList arguments = fun->arguments();
413 Q_ASSERT(arguments.size() >= scriptArgc);
413 Q_ASSERT(arguments.size() >= scriptArgc);
414 int nativeArgc = writePrepareArguments(stream, fun, arguments, scriptArgc, indent);
414 int nativeArgc = writePrepareArguments(stream, fun, arguments, scriptArgc, indent);
415 stream << indentStr;
415 stream << indentStr;
416 if (meta_class->generateShellClass()) {
416 if (meta_class->generateShellClass()) {
417 stream << "QtScriptShell_" << meta_class->name();
417 stream << "QtScriptShell_" << meta_class->name();
418 } else {
418 } else {
419 stream << meta_class->qualifiedCppName();
419 stream << meta_class->qualifiedCppName();
420 }
420 }
421 bool useNew = meta_class->typeEntry()->isObject() || !hasDefaultConstructor(meta_class);
421 bool useNew = meta_class->typeEntry()->isObject() || !hasDefaultConstructor(meta_class);
422 if (useNew)
422 if (useNew)
423 stream << "*";
423 stream << "*";
424 stream << " _q_cpp_result";
424 stream << " _q_cpp_result";
425 if (useNew) {
425 if (useNew) {
426 stream << " = new ";
426 stream << " = new ";
427 if (meta_class->generateShellClass())
427 if (meta_class->generateShellClass())
428 stream << "QtScriptShell_" << meta_class->name();
428 stream << "QtScriptShell_" << meta_class->name();
429 else
429 else
430 stream << meta_class->qualifiedCppName();
430 stream << meta_class->qualifiedCppName();
431 }
431 }
432 if (useNew || (nativeArgc != 0)) {
432 if (useNew || (nativeArgc != 0)) {
433 stream << "(";
433 stream << "(";
434 writeArguments(stream, nativeArgc);
434 writeArguments(stream, nativeArgc);
435 stream << ")";
435 stream << ")";
436 }
436 }
437 stream << ";" << endl;
437 stream << ";" << endl;
438
438
439 stream << indentStr << "QScriptValue _q_result = context->engine()->new";
439 stream << indentStr << "QScriptValue _q_result = context->engine()->new";
440 if (isQObjectBased(meta_class))
440 if (isQObjectBased(meta_class))
441 stream << "QObject";
441 stream << "QObject";
442 else
442 else
443 stream << "Variant";
443 stream << "Variant";
444 stream << "(context->thisObject(), ";
444 stream << "(context->thisObject(), ";
445 if (!isQObjectBased(meta_class))
445 if (!isQObjectBased(meta_class))
446 stream << "qVariantFromValue(";
446 stream << "qVariantFromValue(";
447 if (meta_class->generateShellClass()) {
447 if (meta_class->generateShellClass()) {
448 stream << "(" << meta_class->qualifiedCppName();
448 stream << "(" << meta_class->qualifiedCppName();
449 if (useNew)
449 if (useNew)
450 stream << "*";
450 stream << "*";
451 stream << ")";
451 stream << ")";
452 }
452 }
453 stream << "_q_cpp_result";
453 stream << "_q_cpp_result";
454 if (isQObjectBased(meta_class))
454 if (isQObjectBased(meta_class))
455 stream << ", QScriptEngine::AutoOwnership";
455 stream << ", QScriptEngine::AutoOwnership";
456 else
456 else
457 stream << ")";
457 stream << ")";
458 stream << ");" << endl;
458 stream << ");" << endl;
459 if (meta_class->generateShellClass()) {
459 if (meta_class->generateShellClass()) {
460 stream << indentStr << "_q_cpp_result";
460 stream << indentStr << "_q_cpp_result";
461 if (useNew)
461 if (useNew)
462 stream << "->";
462 stream << "->";
463 else
463 else
464 stream << ".";
464 stream << ".";
465 stream << "__qtscript_self = _q_result;" << endl;
465 stream << "__qtscript_self = _q_result;" << endl;
466 }
466 }
467
467
468 writeInjectedCode(stream, meta_class, fun, CodeSnip::End);
468 writeInjectedCode(stream, meta_class, fun, CodeSnip::End);
469
469
470 stream << indentStr << "return _q_result;" << endl;
470 stream << indentStr << "return _q_result;" << endl;
471 }
471 }
472
472
473 /*!
473 /*!
474 Returns true if the given \a typeName has a QScriptValue constructor
474 Returns true if the given \a typeName has a QScriptValue constructor
475 we can use, false otherwise.
475 we can use, false otherwise.
476 */
476 */
477 static bool hasScriptValueConstructor(const QString &typeName)
477 static bool hasScriptValueConstructor(const QString &typeName)
478 {
478 {
479 return (typeName == QLatin1String("bool"))
479 return (typeName == QLatin1String("bool"))
480 || (typeName == QLatin1String("int"))
480 || (typeName == QLatin1String("int"))
481 || (typeName == QLatin1String("uint"))
481 || (typeName == QLatin1String("uint"))
482 || (typeName == QLatin1String("double"))
482 || (typeName == QLatin1String("double"))
483 || (typeName == QLatin1String("QString"));
483 || (typeName == QLatin1String("QString"));
484 }
484 }
485
485
486 /*!
486 /*!
487 Writes a function call.
487 Writes a function call.
488 */
488 */
489 static void writeFunctionCallAndReturn(QTextStream &stream, const AbstractMetaFunction *fun,
489 static void writeFunctionCallAndReturn(QTextStream &stream, const AbstractMetaFunction *fun,
490 int scriptArgc, const AbstractMetaClass *meta_class,
490 int scriptArgc, const AbstractMetaClass *meta_class,
491 int indent)
491 int indent)
492 {
492 {
493 QString indentStr(indent, QLatin1Char(' '));
493 QString indentStr(indent, QLatin1Char(' '));
494 AbstractMetaArgumentList arguments = fun->arguments();
494 AbstractMetaArgumentList arguments = fun->arguments();
495 Q_ASSERT(arguments.size() >= scriptArgc);
495 Q_ASSERT(arguments.size() >= scriptArgc);
496
496
497 writeInjectedCode(stream, meta_class, fun, CodeSnip::Beginning);
497 writeInjectedCode(stream, meta_class, fun, CodeSnip::Beginning);
498
498
499 int nativeArgc = writePrepareArguments(stream, fun, arguments, scriptArgc, indent);
499 int nativeArgc = writePrepareArguments(stream, fun, arguments, scriptArgc, indent);
500 bool returnThisObject = fun->shouldReturnThisObject();
500 bool returnThisObject = fun->shouldReturnThisObject();
501 bool ignoreReturnValue = returnThisObject || fun->shouldIgnoreReturnValue();
501 bool ignoreReturnValue = returnThisObject || fun->shouldIgnoreReturnValue();
502 stream << indentStr;
502 stream << indentStr;
503 AbstractMetaType *retType = fun->type();
503 AbstractMetaType *retType = fun->type();
504 bool constCastResult = false;
504 bool constCastResult = false;
505 if (retType && !ignoreReturnValue) {
505 if (retType && !ignoreReturnValue) {
506 QString rsig = retType->cppSignature();
506 QString rsig = retType->cppSignature();
507 QString typeName = normalizedType(retType);
507 QString typeName = normalizedType(retType);
508 stream << typeName << " _q_result = ";
508 stream << typeName << " _q_result = ";
509 constCastResult = rsig.endsWith('*') && rsig.startsWith("const ");
509 constCastResult = rsig.endsWith('*') && rsig.startsWith("const ");
510 if (constCastResult)
510 if (constCastResult)
511 stream << "const_cast<" << typeName << ">(";
511 stream << "const_cast<" << typeName << ">(";
512 }
512 }
513
513
514 if (!fun->isStatic()) {
514 if (!fun->isStatic()) {
515 // ### the friendly check should be enough...
515 // ### the friendly check should be enough...
516 if (fun->isFriendly()
516 if (fun->isFriendly()
517 || ((fun->name() == QLatin1String("operator_equal"))
517 || ((fun->name() == QLatin1String("operator_equal"))
518 && ((meta_class->name() == QLatin1String("QPoint"))
518 && ((meta_class->name() == QLatin1String("QPoint"))
519 || (meta_class->name() == QLatin1String("QPointF"))
519 || (meta_class->name() == QLatin1String("QPointF"))
520 || (meta_class->name() == QLatin1String("QRect"))
520 || (meta_class->name() == QLatin1String("QRect"))
521 || (meta_class->name() == QLatin1String("QRectF"))
521 || (meta_class->name() == QLatin1String("QRectF"))
522 || (meta_class->name() == QLatin1String("QSize"))
522 || (meta_class->name() == QLatin1String("QSize"))
523 || (meta_class->name() == QLatin1String("QSizeF"))))) {
523 || (meta_class->name() == QLatin1String("QSizeF"))))) {
524 stream << fun->originalName() << "(";
524 stream << fun->originalName() << "(";
525 stream << "*_q_self, ";
525 stream << "*_q_self, ";
526 } else {
526 } else {
527 stream << "_q_self->";
527 stream << "_q_self->";
528 stream << fun->originalName() << "(";
528 stream << fun->originalName() << "(";
529 }
529 }
530 } else {
530 } else {
531 stream << meta_class->qualifiedCppName() << "::";
531 stream << meta_class->qualifiedCppName() << "::";
532 stream << fun->originalName() << "(";
532 stream << fun->originalName() << "(";
533 }
533 }
534 writeArguments(stream, nativeArgc);
534 writeArguments(stream, nativeArgc);
535 if (constCastResult)
535 if (constCastResult)
536 stream << ")";
536 stream << ")";
537 stream << ");" << endl;
537 stream << ");" << endl;
538
538
539 writeInjectedCode(stream, meta_class, fun, CodeSnip::End);
539 writeInjectedCode(stream, meta_class, fun, CodeSnip::End);
540
540
541 // write return statement
541 // write return statement
542 stream << indentStr;
542 stream << indentStr;
543 if (returnThisObject) {
543 if (returnThisObject) {
544 stream << "return context->thisObject();";
544 stream << "return context->thisObject();";
545 } else {
545 } else {
546 QString conv = fun->conversionRule(TypeSystem::NativeCode, 0);
546 QString conv = fun->conversionRule(TypeSystem::NativeCode, 0);
547 if (!conv.isEmpty()) {
547 if (!conv.isEmpty()) {
548 // custom conversion
548 // custom conversion
549 conv.replace(QString::fromLatin1("%in%"), "_q_result");
549 conv.replace(QString::fromLatin1("%in%"), "_q_result");
550 conv.replace(QString::fromLatin1("%out%"), "_q_convertedResult");
550 conv.replace(QString::fromLatin1("%out%"), "_q_convertedResult");
551 stream << conv;
551 stream << conv;
552 stream << "return qScriptValueFromValue(context->engine(), _q_convertedResult);";
552 stream << "return qScriptValueFromValue(context->engine(), _q_convertedResult);";
553 } else {
553 } else {
554 stream << "return ";
554 stream << "return ";
555 if (retType) {
555 if (retType) {
556 if (isSequenceType(retType))
556 if (isSequenceType(retType))
557 stream << "qScriptValueFromSequence";
557 stream << "qScriptValueFromSequence";
558 else if (hasScriptValueConstructor(normalizedType(retType)))
558 else if (hasScriptValueConstructor(normalizedType(retType)))
559 stream << "QScriptValue";
559 stream << "QScriptValue";
560 else
560 else
561 stream << "qScriptValueFromValue";
561 stream << "qScriptValueFromValue";
562 stream << "(context->engine(), _q_result);";
562 stream << "(context->engine(), _q_result);";
563 } else {
563 } else {
564 stream << "context->engine()->undefinedValue();";
564 stream << "context->engine()->undefinedValue();";
565 }
565 }
566 }
566 }
567 }
567 }
568 stream << endl;
568 stream << endl;
569 }
569 }
570
570
571 /*!
571 /*!
572 Returns true if the given function \a fun is operator>>() or
572 Returns true if the given function \a fun is operator>>() or
573 operator<<() that streams from/to a Q{Data,Text}Stream, false
573 operator<<() that streams from/to a Q{Data,Text}Stream, false
574 otherwise.
574 otherwise.
575 */
575 */
576 bool ClassGenerator::isSpecialStreamingOperator(const AbstractMetaFunction *fun)
576 bool ClassGenerator::isSpecialStreamingOperator(const AbstractMetaFunction *fun)
577 {
577 {
578 return ((fun->functionType() == AbstractMetaFunction::GlobalScopeFunction)
578 return ((fun->functionType() == AbstractMetaFunction::GlobalScopeFunction)
579 && (fun->arguments().size() == 1)
579 && (fun->arguments().size() == 1)
580 && (((fun->originalName() == "operator>>") && (fun->modifiedName() == "readFrom"))
580 && (((fun->originalName() == "operator>>") && (fun->modifiedName() == "readFrom"))
581 || ((fun->originalName() == "operator<<") && (fun->modifiedName() == "writeTo"))));
581 || ((fun->originalName() == "operator<<") && (fun->modifiedName() == "writeTo"))));
582 }
582 }
583
583
584 /*!
584 /*!
585 Generates code that uses Q{Data,Text}Stream operator>>() or
585 Generates code that uses Q{Data,Text}Stream operator>>() or
586 operator<<() to read/write an instance of meta_class.
586 operator<<() to read/write an instance of meta_class.
587 */
587 */
588 static void writeStreamingOperatorCall(QTextStream &stream, const AbstractMetaFunction *fun,
588 static void writeStreamingOperatorCall(QTextStream &stream, const AbstractMetaFunction *fun,
589 const AbstractMetaClass * /*meta_class*/, int indent)
589 const AbstractMetaClass * /*meta_class*/, int indent)
590 {
590 {
591 QString indentStr(indent, QLatin1Char(' '));
591 QString indentStr(indent, QLatin1Char(' '));
592 QString streamClassName = fun->arguments().at(0)->type()->name();
592 QString streamClassName = fun->arguments().at(0)->type()->name();
593 stream << indentStr << streamClassName << "* _q_arg0 = qscriptvalue_cast<"
593 stream << indentStr << streamClassName << "* _q_arg0 = qscriptvalue_cast<"
594 << streamClassName << "*>(context->argument(0));" << endl;
594 << streamClassName << "*>(context->argument(0));" << endl;
595 stream << indentStr << "operator";
595 stream << indentStr << "operator";
596 if (fun->modifiedName() == "readFrom")
596 if (fun->modifiedName() == "readFrom")
597 stream << ">>";
597 stream << ">>";
598 else
598 else
599 stream << "<<";
599 stream << "<<";
600 stream << "(*_q_arg0, *_q_self);" << endl;
600 stream << "(*_q_arg0, *_q_self);" << endl;
601 stream << indentStr << "return context->engine()->undefinedValue();" << endl;
601 stream << indentStr << "return context->engine()->undefinedValue();" << endl;
602 }
602 }
603
603
604 /*!
604 /*!
605 Writes the constructor forwarding for \a meta_class.
605 Writes the constructor forwarding for \a meta_class.
606 */
606 */
607 static void writeConstructorForwarding(QTextStream &stream,
607 static void writeConstructorForwarding(QTextStream &stream,
608 const AbstractMetaFunctionList &functions,
608 const AbstractMetaFunctionList &functions,
609 const AbstractMetaClass *meta_class)
609 const AbstractMetaClass *meta_class)
610 {
610 {
611 #if 0
611 #if 0
612 stream << "/** signatures:" << endl;
612 stream << "/** signatures:" << endl;
613 foreach (const AbstractMetaFunction *fun, functions) {
613 foreach (const AbstractMetaFunction *fun, functions) {
614 stream << " * " << fun->signature() << endl;
614 stream << " * " << fun->signature() << endl;
615 }
615 }
616 stream << " */" << endl;
616 stream << " */" << endl;
617 #endif
617 #endif
618
618
619 if (/*meta_class->isAbstract() ||*/ (functions.size() == 0)) {
619 if (/*meta_class->isAbstract() ||*/ (functions.size() == 0)) {
620 stream << " return context->throwError(QScriptContext::TypeError," << endl
620 stream << " return context->throwError(QScriptContext::TypeError," << endl
621 << " QString::fromLatin1(\"" << meta_class->name()
621 << " QString::fromLatin1(\"" << meta_class->name()
622 << " cannot be constructed\"));" << endl;
622 << " cannot be constructed\"));" << endl;
623
623
624 } else {
624 } else {
625 stream << " if (context->thisObject().strictlyEquals(context->engine()->globalObject())) {" << endl
625 stream << " if (context->thisObject().strictlyEquals(context->engine()->globalObject())) {" << endl
626 << " return context->throwError(QString::fromLatin1(\""
626 << " return context->throwError(QString::fromLatin1(\""
627 << meta_class->name() << "(): Did you forget to construct with 'new'?\"));" << endl
627 << meta_class->name() << "(): Did you forget to construct with 'new'?\"));" << endl
628 << " }" << endl;
628 << " }" << endl;
629
629
630 writeInjectedCode(stream, meta_class, CodeSnip::Constructor);
630 writeInjectedCode(stream, meta_class, CodeSnip::Constructor);
631
631
632 QMap<int, AbstractMetaFunctionList> argcToFunctions;
632 QMap<int, AbstractMetaFunctionList> argcToFunctions;
633 argcToFunctions = createArgcToFunctionsMap(functions);
633 argcToFunctions = createArgcToFunctionsMap(functions);
634
634
635 int argcMin = argcToFunctions.keys().first();
635 int argcMin = argcToFunctions.keys().first();
636 int argcMax = argcToFunctions.keys().last();
636 int argcMax = argcToFunctions.keys().last();
637 bool needElse = false;
637 bool needElse = false;
638 for (int i = argcMin; i <= argcMax; ++i) {
638 for (int i = argcMin; i <= argcMax; ++i) {
639 AbstractMetaFunctionList funcs = argcToFunctions.value(i);
639 AbstractMetaFunctionList funcs = argcToFunctions.value(i);
640 if (funcs.isEmpty())
640 if (funcs.isEmpty())
641 continue;
641 continue;
642 if (needElse)
642 if (needElse)
643 stream << " else ";
643 stream << " else ";
644 else
644 else
645 stream << " ";
645 stream << " ";
646 needElse = true;
646 needElse = true;
647 stream << "if (context->argumentCount() == " << i << ") {" << endl;
647 stream << "if (context->argumentCount() == " << i << ") {" << endl;
648 if ((funcs.size() == 1) || (i == 0)) {
648 if ((funcs.size() == 1) || (i == 0)) {
649 AbstractMetaFunction *fun = funcs.at(0);
649 AbstractMetaFunction *fun = funcs.at(0);
650 const int indent = 8;
650 const int indent = 8;
651 writeConstructorCallAndReturn(stream, fun, i, meta_class, indent);
651 writeConstructorCallAndReturn(stream, fun, i, meta_class, indent);
652 } else {
652 } else {
653 // handle overloads
653 // handle overloads
654 for (int j = 0; j < funcs.size(); ++j) {
654 for (int j = 0; j < funcs.size(); ++j) {
655 AbstractMetaFunction *fun = funcs.at(j);
655 AbstractMetaFunction *fun = funcs.at(j);
656 stream << " ";
656 stream << " ";
657 if (j > 0)
657 if (j > 0)
658 stream << "} else ";
658 stream << "} else ";
659 stream << "if (";
659 stream << "if (";
660 AbstractMetaArgumentList arguments = fun->arguments();
660 AbstractMetaArgumentList arguments = fun->arguments();
661 const int indent = 12;
661 const int indent = 12;
662 writeArgumentTypeTests(stream, fun, arguments, i, indent);
662 writeArgumentTypeTests(stream, fun, arguments, i, indent);
663 stream << ") {" << endl;
663 stream << ") {" << endl;
664 writeConstructorCallAndReturn(stream, fun, i, meta_class, indent);
664 writeConstructorCallAndReturn(stream, fun, i, meta_class, indent);
665 }
665 }
666 stream << " }" << endl;
666 stream << " }" << endl;
667 }
667 }
668 stream << " }";
668 stream << " }";
669 }
669 }
670 stream << endl;
670 stream << endl;
671 // writeThrowAmbiguityError(stream, meta_class, 0, signatures.toList());
671 // writeThrowAmbiguityError(stream, meta_class, 0, signatures.toList());
672 }
672 }
673 }
673 }
674
674
675 /*!
675 /*!
676 Returns a list of enum \a values that are actually unique.
676 Returns a list of enum \a values that are actually unique.
677 */
677 */
678 QList<int> uniqueEnumValueIndexes(const AbstractMetaEnumValueList &values)
678 QList<int> uniqueEnumValueIndexes(const AbstractMetaEnumValueList &values)
679 {
679 {
680 QMap<int, int> map;
680 QMap<int, int> map;
681 for (int i = 0; i < values.count(); ++i) {
681 for (int i = 0; i < values.count(); ++i) {
682 AbstractMetaEnumValue *val = values.at(i);
682 AbstractMetaEnumValue *val = values.at(i);
683 if (!map.contains(val->value()))
683 if (!map.contains(val->value()))
684 map.insert(val->value(), i);
684 map.insert(val->value(), i);
685 }
685 }
686 return map.values();
686 return map.values();
687 }
687 }
688
688
689 /*!
689 /*!
690 */
690 */
691 static bool isContiguousEnum(const QList<int> &indexes, const AbstractMetaEnumValueList &values)
691 static bool isContiguousEnum(const QList<int> &indexes, const AbstractMetaEnumValueList &values)
692 {
692 {
693 if (indexes.isEmpty())
693 if (indexes.isEmpty())
694 return false;
694 return false;
695 int prev = values.at(indexes.at(0))->value();
695 int prev = values.at(indexes.at(0))->value();
696 for (int i = 1; i < indexes.size(); ++i) {
696 for (int i = 1; i < indexes.size(); ++i) {
697 int curr = values.at(indexes.at(i))->value();
697 int curr = values.at(indexes.at(i))->value();
698 if (curr != prev + 1)
698 if (curr != prev + 1)
699 return false;
699 return false;
700 prev = curr;
700 prev = curr;
701 }
701 }
702 return true;
702 return true;
703 }
703 }
704
704
705 static void writeCreateEnumClassHelper(QTextStream &stream)
705 static void writeCreateEnumClassHelper(QTextStream &stream)
706 {
706 {
707 stream << "static QScriptValue qtscript_create_enum_class_helper(" << endl
707 stream << "static QScriptValue qtscript_create_enum_class_helper(" << endl
708 << " QScriptEngine *engine," << endl
708 << " QScriptEngine *engine," << endl
709 << " QScriptEngine::FunctionSignature construct," << endl
709 << " QScriptEngine::FunctionSignature construct," << endl
710 << " QScriptEngine::FunctionSignature valueOf," << endl
710 << " QScriptEngine::FunctionSignature valueOf," << endl
711 << " QScriptEngine::FunctionSignature toString)" << endl
711 << " QScriptEngine::FunctionSignature toString)" << endl
712 << "{" << endl
712 << "{" << endl
713 << " QScriptValue proto = engine->newObject();" << endl
713 << " QScriptValue proto = engine->newObject();" << endl
714 << " proto.setProperty(QString::fromLatin1(\"valueOf\")," << endl
714 << " proto.setProperty(QString::fromLatin1(\"valueOf\")," << endl
715 << " engine->newFunction(valueOf), QScriptValue::SkipInEnumeration);" << endl
715 << " engine->newFunction(valueOf), QScriptValue::SkipInEnumeration);" << endl
716 << " proto.setProperty(QString::fromLatin1(\"toString\")," << endl
716 << " proto.setProperty(QString::fromLatin1(\"toString\")," << endl
717 << " engine->newFunction(toString), QScriptValue::SkipInEnumeration);" << endl
717 << " engine->newFunction(toString), QScriptValue::SkipInEnumeration);" << endl
718 << " return engine->newFunction(construct, proto, 1);" << endl
718 << " return engine->newFunction(construct, proto, 1);" << endl
719 << "}" << endl << endl;
719 << "}" << endl << endl;
720 }
720 }
721
721
722 static void writeCreateFlagsClassHelper(QTextStream &stream)
722 static void writeCreateFlagsClassHelper(QTextStream &stream)
723 {
723 {
724 stream << "static QScriptValue qtscript_create_flags_class_helper(" << endl
724 stream << "static QScriptValue qtscript_create_flags_class_helper(" << endl
725 << " QScriptEngine *engine," << endl
725 << " QScriptEngine *engine," << endl
726 << " QScriptEngine::FunctionSignature construct," << endl
726 << " QScriptEngine::FunctionSignature construct," << endl
727 << " QScriptEngine::FunctionSignature valueOf," << endl
727 << " QScriptEngine::FunctionSignature valueOf," << endl
728 << " QScriptEngine::FunctionSignature toString," << endl
728 << " QScriptEngine::FunctionSignature toString," << endl
729 << " QScriptEngine::FunctionSignature equals)" << endl
729 << " QScriptEngine::FunctionSignature equals)" << endl
730 << "{" << endl
730 << "{" << endl
731 << " QScriptValue proto = engine->newObject();" << endl
731 << " QScriptValue proto = engine->newObject();" << endl
732 << " proto.setProperty(QString::fromLatin1(\"valueOf\")," << endl
732 << " proto.setProperty(QString::fromLatin1(\"valueOf\")," << endl
733 << " engine->newFunction(valueOf), QScriptValue::SkipInEnumeration);" << endl
733 << " engine->newFunction(valueOf), QScriptValue::SkipInEnumeration);" << endl
734 << " proto.setProperty(QString::fromLatin1(\"toString\")," << endl
734 << " proto.setProperty(QString::fromLatin1(\"toString\")," << endl
735 << " engine->newFunction(toString), QScriptValue::SkipInEnumeration);" << endl
735 << " engine->newFunction(toString), QScriptValue::SkipInEnumeration);" << endl
736 << " proto.setProperty(QString::fromLatin1(\"equals\")," << endl
736 << " proto.setProperty(QString::fromLatin1(\"equals\")," << endl
737 << " engine->newFunction(equals), QScriptValue::SkipInEnumeration);" << endl
737 << " engine->newFunction(equals), QScriptValue::SkipInEnumeration);" << endl
738 << " return engine->newFunction(construct, proto);" << endl
738 << " return engine->newFunction(construct, proto);" << endl
739 << "}" << endl << endl;
739 << "}" << endl << endl;
740 }
740 }
741
741
742 /*!
742 /*!
743 Writes the enum \a enom belonging to the class \a meta_class to the
743 Writes the enum \a enom belonging to the class \a meta_class to the
744 given \a stream.
744 given \a stream.
745 */
745 */
746 static void writeEnumClass(QTextStream &stream, const AbstractMetaClass *meta_class,
746 static void writeEnumClass(QTextStream &stream, const AbstractMetaClass *meta_class,
747 const AbstractMetaEnum *enom)
747 const AbstractMetaEnum *enom)
748 {
748 {
749 QString qualifiedCppNameColons;
749 QString qualifiedCppNameColons;
750 if (meta_class->name() != "Global")
750 if (meta_class->name() != "Global")
751 qualifiedCppNameColons = meta_class->qualifiedCppName() + "::";
751 qualifiedCppNameColons = meta_class->qualifiedCppName() + "::";
752 QString qualifiedEnumName = qualifiedCppNameColons + enom->name();
752 QString qualifiedEnumName = qualifiedCppNameColons + enom->name();
753 QString qtScriptEnumName = meta_class->name() + "_" + enom->name();
753 QString qtScriptEnumName = meta_class->name() + "_" + enom->name();
754
754
755 stream << "//" << endl;
755 stream << "//" << endl;
756 stream << "// " << qualifiedEnumName << endl;
756 stream << "// " << qualifiedEnumName << endl;
757 stream << "//" << endl << endl;
757 stream << "//" << endl << endl;
758
758
759 // determine unique values (aliases will cause switch statement to not compile)
759 // determine unique values (aliases will cause switch statement to not compile)
760 AbstractMetaEnumValueList values = enom->values();
760 AbstractMetaEnumValueList values = enom->values();
761 QList<int> uniqueIndexes = uniqueEnumValueIndexes(values);
761 QList<int> uniqueIndexes = uniqueEnumValueIndexes(values);
762
762
763 bool contiguous = isContiguousEnum(uniqueIndexes, values);
763 bool contiguous = isContiguousEnum(uniqueIndexes, values);
764
764
765 // write arrays of values and keys
765 // write arrays of values and keys
766 stream << "static const " << qualifiedEnumName
766 stream << "static const " << qualifiedEnumName
767 << " qtscript_" << qtScriptEnumName << "_values[] = {" << endl;
767 << " qtscript_" << qtScriptEnumName << "_values[] = {" << endl;
768 for (int i = 0; i < uniqueIndexes.size(); ++i) {
768 for (int i = 0; i < uniqueIndexes.size(); ++i) {
769 stream << " ";
769 stream << " ";
770 if (i > 0)
770 if (i > 0)
771 stream << ", ";
771 stream << ", ";
772 stream << qualifiedCppNameColons << values.at(uniqueIndexes.at(i))->name() << endl;
772 stream << qualifiedCppNameColons << values.at(uniqueIndexes.at(i))->name() << endl;
773 }
773 }
774 stream << "};" << endl << endl;
774 stream << "};" << endl << endl;
775 stream << "static const char * const qtscript_" << qtScriptEnumName << "_keys[] = {" << endl;
775 stream << "static const char * const qtscript_" << qtScriptEnumName << "_keys[] = {" << endl;
776 for (int i = 0; i < uniqueIndexes.size(); ++i) {
776 for (int i = 0; i < uniqueIndexes.size(); ++i) {
777 stream << " ";
777 stream << " ";
778 if (i > 0)
778 if (i > 0)
779 stream << ", ";
779 stream << ", ";
780 stream << "\"" << values.at(uniqueIndexes.at(i))->name() << "\"" << endl;
780 stream << "\"" << values.at(uniqueIndexes.at(i))->name() << "\"" << endl;
781 }
781 }
782 stream << "};" << endl << endl;
782 stream << "};" << endl << endl;
783
783
784 // write toString helper
784 // write toString helper
785 stream << "static QString qtscript_"
785 stream << "static QString qtscript_"
786 << qtScriptEnumName << "_toStringHelper"
786 << qtScriptEnumName << "_toStringHelper"
787 << "(" << qualifiedEnumName << " value)" << endl;
787 << "(" << qualifiedEnumName << " value)" << endl;
788 stream << "{" << endl;
788 stream << "{" << endl;
789 if (enom->hasQEnumsDeclaration() && (meta_class->qualifiedCppName() != "QTransform")) {
789 if (enom->hasQEnumsDeclaration() && (meta_class->qualifiedCppName() != "QTransform")) {
790 stream << " const QMetaObject *meta = qtscript_" << meta_class->name() << "_metaObject();" << endl;
790 stream << " const QMetaObject *meta = qtscript_" << meta_class->name() << "_metaObject();" << endl;
791 stream << " int idx = meta->indexOfEnumerator(\"" << enom->name() << "\");" << endl;
791 stream << " int idx = meta->indexOfEnumerator(\"" << enom->name() << "\");" << endl;
792 stream << " Q_ASSERT(idx != -1);" << endl;
792 stream << " Q_ASSERT(idx != -1);" << endl;
793 stream << " QMetaEnum menum = meta->enumerator(idx);" << endl;
793 stream << " QMetaEnum menum = meta->enumerator(idx);" << endl;
794 stream << " return QString::fromLatin1(menum.valueToKey(value));" << endl;
794 stream << " return QString::fromLatin1(menum.valueToKey(value));" << endl;
795 } else {
795 } else {
796 if (contiguous) {
796 if (contiguous) {
797 stream << " if ((value >= " << qualifiedCppNameColons
797 stream << " if ((value >= " << qualifiedCppNameColons
798 << values.at(uniqueIndexes.first())->name() << ")"
798 << values.at(uniqueIndexes.first())->name() << ")"
799 << " && (value <= " << qualifiedCppNameColons
799 << " && (value <= " << qualifiedCppNameColons
800 << values.at(uniqueIndexes.last())->name() << "))" << endl
800 << values.at(uniqueIndexes.last())->name() << "))" << endl
801 << " return qtscript_" << qtScriptEnumName
801 << " return qtscript_" << qtScriptEnumName
802 << "_keys[static_cast<int>(value)-static_cast<int>("
802 << "_keys[static_cast<int>(value)-static_cast<int>("
803 << qualifiedCppNameColons
803 << qualifiedCppNameColons
804 << values.at(uniqueIndexes.first())->name() << ")];" << endl;
804 << values.at(uniqueIndexes.first())->name() << ")];" << endl;
805 } else {
805 } else {
806 stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
806 stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
807 << " if (qtscript_" << qtScriptEnumName << "_values[i] == value)" << endl
807 << " if (qtscript_" << qtScriptEnumName << "_values[i] == value)" << endl
808 << " return QString::fromLatin1(qtscript_" << qtScriptEnumName << "_keys[i]);" << endl
808 << " return QString::fromLatin1(qtscript_" << qtScriptEnumName << "_keys[i]);" << endl
809 << " }" << endl;
809 << " }" << endl;
810 }
810 }
811 stream << " return QString();" << endl;
811 stream << " return QString();" << endl;
812 }
812 }
813 stream << "}" << endl << endl;
813 stream << "}" << endl << endl;
814
814
815 // write QScriptValue <--> C++ conversion functions
815 // write QScriptValue <--> C++ conversion functions
816 stream << "static QScriptValue qtscript_"
816 stream << "static QScriptValue qtscript_"
817 << qtScriptEnumName << "_toScriptValue("
817 << qtScriptEnumName << "_toScriptValue("
818 << "QScriptEngine *engine, const " << qualifiedEnumName << " &value)" << endl
818 << "QScriptEngine *engine, const " << qualifiedEnumName << " &value)" << endl
819 << "{" << endl
819 << "{" << endl
820 << " QScriptValue clazz = engine->globalObject().property(QString::fromLatin1(\""
820 << " QScriptValue clazz = engine->globalObject().property(QString::fromLatin1(\""
821 << meta_class->name() << "\"));" << endl
821 << meta_class->name() << "\"));" << endl
822 // << " QScriptValue enumClazz = clazz.property(QString::fromLatin1(\""
822 // << " QScriptValue enumClazz = clazz.property(QString::fromLatin1(\""
823 // << enom->name() << "\"));" << endl
823 // << enom->name() << "\"));" << endl
824 << " return clazz.property(qtscript_" << qtScriptEnumName << "_toStringHelper(value));" << endl
824 << " return clazz.property(qtscript_" << qtScriptEnumName << "_toStringHelper(value));" << endl
825 << "}" << endl << endl;
825 << "}" << endl << endl;
826 stream << "static void qtscript_"
826 stream << "static void qtscript_"
827 << qtScriptEnumName << "_fromScriptValue("
827 << qtScriptEnumName << "_fromScriptValue("
828 << "const QScriptValue &value, " << qualifiedEnumName << " &out)" << endl
828 << "const QScriptValue &value, " << qualifiedEnumName << " &out)" << endl
829 << "{" << endl
829 << "{" << endl
830 << " out = qvariant_cast<" << qualifiedEnumName << ">(value.toVariant());" << endl
830 << " out = qvariant_cast<" << qualifiedEnumName << ">(value.toVariant());" << endl
831 << "}" << endl << endl;
831 << "}" << endl << endl;
832
832
833 // write constructor
833 // write constructor
834 stream << "static QScriptValue qtscript_construct_"
834 stream << "static QScriptValue qtscript_construct_"
835 << qtScriptEnumName
835 << qtScriptEnumName
836 << "(QScriptContext *context, QScriptEngine *engine)" << endl;
836 << "(QScriptContext *context, QScriptEngine *engine)" << endl;
837 stream << "{" << endl;
837 stream << "{" << endl;
838 stream << " int arg = context->argument(0).toInt32();" << endl;
838 stream << " int arg = context->argument(0).toInt32();" << endl;
839 if (enom->hasQEnumsDeclaration() && (meta_class->qualifiedCppName() != "QTransform")) {
839 if (enom->hasQEnumsDeclaration() && (meta_class->qualifiedCppName() != "QTransform")) {
840 stream << " const QMetaObject *meta = qtscript_" << meta_class->name() << "_metaObject();" << endl;
840 stream << " const QMetaObject *meta = qtscript_" << meta_class->name() << "_metaObject();" << endl;
841 stream << " int idx = meta->indexOfEnumerator(\"" << enom->name() << "\");" << endl;
841 stream << " int idx = meta->indexOfEnumerator(\"" << enom->name() << "\");" << endl;
842 stream << " Q_ASSERT(idx != -1);" << endl;
842 stream << " Q_ASSERT(idx != -1);" << endl;
843 stream << " QMetaEnum menum = meta->enumerator(idx);" << endl;
843 stream << " QMetaEnum menum = meta->enumerator(idx);" << endl;
844 stream << " if (menum.valueToKey(arg) != 0)" << endl;
844 stream << " if (menum.valueToKey(arg) != 0)" << endl;
845 stream << " return qScriptValueFromValue(engine, static_cast<"
845 stream << " return qScriptValueFromValue(engine, static_cast<"
846 << qualifiedEnumName << ">(arg));" << endl;
846 << qualifiedEnumName << ">(arg));" << endl;
847 } else {
847 } else {
848 if (contiguous) {
848 if (contiguous) {
849 stream << " if ((arg >= " << qualifiedCppNameColons
849 stream << " if ((arg >= " << qualifiedCppNameColons
850 << values.at(uniqueIndexes.first())->name() << ")"
850 << values.at(uniqueIndexes.first())->name() << ")"
851 << " && (arg <= " << qualifiedCppNameColons
851 << " && (arg <= " << qualifiedCppNameColons
852 << values.at(uniqueIndexes.last())->name() << "))" << endl;
852 << values.at(uniqueIndexes.last())->name() << "))" << endl;
853 stream << " return qScriptValueFromValue(engine, static_cast<"
853 stream << " return qScriptValueFromValue(engine, static_cast<"
854 << qualifiedEnumName << ">(arg));" << endl;
854 << qualifiedEnumName << ">(arg));" << endl;
855 } else {
855 } else {
856 stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
856 stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
857 << " if (qtscript_" << qtScriptEnumName << "_values[i] == arg)" << endl;
857 << " if (qtscript_" << qtScriptEnumName << "_values[i] == arg)" << endl;
858 stream << " return qScriptValueFromValue(engine, static_cast<"
858 stream << " return qScriptValueFromValue(engine, static_cast<"
859 << qualifiedEnumName << ">(arg));" << endl;
859 << qualifiedEnumName << ">(arg));" << endl;
860 stream << " }" << endl;
860 stream << " }" << endl;
861 }
861 }
862 }
862 }
863 stream << " return context->throwError(QString::fromLatin1(\""
863 stream << " return context->throwError(QString::fromLatin1(\""
864 << enom->name() << "(): invalid enum value (%0)\").arg(arg));" << endl;
864 << enom->name() << "(): invalid enum value (%0)\").arg(arg));" << endl;
865 stream << "}" << endl;
865 stream << "}" << endl;
866 stream << endl;
866 stream << endl;
867
867
868 // write prototype.valueOf()
868 // write prototype.valueOf()
869 stream << "static QScriptValue qtscript_" << qtScriptEnumName
869 stream << "static QScriptValue qtscript_" << qtScriptEnumName
870 << "_valueOf(QScriptContext *context, QScriptEngine *engine)" << endl;
870 << "_valueOf(QScriptContext *context, QScriptEngine *engine)" << endl;
871 stream << "{" << endl;
871 stream << "{" << endl;
872 stream << " " << qualifiedEnumName << " value = "
872 stream << " " << qualifiedEnumName << " value = "
873 << "qscriptvalue_cast<" << qualifiedEnumName
873 << "qscriptvalue_cast<" << qualifiedEnumName
874 << ">(context->thisObject());" << endl;
874 << ">(context->thisObject());" << endl;
875 stream << " return QScriptValue(engine, static_cast<int>(value));" << endl;
875 stream << " return QScriptValue(engine, static_cast<int>(value));" << endl;
876 stream << "}" << endl;
876 stream << "}" << endl;
877 stream << endl;
877 stream << endl;
878
878
879 // write prototype.toString()
879 // write prototype.toString()
880 stream << "static QScriptValue qtscript_" << qtScriptEnumName
880 stream << "static QScriptValue qtscript_" << qtScriptEnumName
881 << "_toString(QScriptContext *context, QScriptEngine *engine)" << endl;
881 << "_toString(QScriptContext *context, QScriptEngine *engine)" << endl;
882 stream << "{" << endl;
882 stream << "{" << endl;
883 stream << " " << qualifiedEnumName << " value = "
883 stream << " " << qualifiedEnumName << " value = "
884 << "qscriptvalue_cast<" << qualifiedEnumName
884 << "qscriptvalue_cast<" << qualifiedEnumName
885 << ">(context->thisObject());" << endl;
885 << ">(context->thisObject());" << endl;
886 stream << " return QScriptValue(engine, qtscript_" << qtScriptEnumName << "_toStringHelper(value));" << endl;
886 stream << " return QScriptValue(engine, qtscript_" << qtScriptEnumName << "_toStringHelper(value));" << endl;
887 stream << "}" << endl;
887 stream << "}" << endl;
888 stream << endl;
888 stream << endl;
889
889
890 // write class creation function
890 // write class creation function
891 stream << "static QScriptValue qtscript_create_"
891 stream << "static QScriptValue qtscript_create_"
892 << qtScriptEnumName
892 << qtScriptEnumName
893 << "_class(QScriptEngine *engine, QScriptValue &clazz)" << endl;
893 << "_class(QScriptEngine *engine, QScriptValue &clazz)" << endl;
894 stream << "{" << endl;
894 stream << "{" << endl;
895
895
896 stream << " QScriptValue ctor = qtscript_create_enum_class_helper(" << endl
896 stream << " QScriptValue ctor = qtscript_create_enum_class_helper(" << endl
897 << " engine, qtscript_construct_" << qtScriptEnumName << "," << endl
897 << " engine, qtscript_construct_" << qtScriptEnumName << "," << endl
898 << " qtscript_" << qtScriptEnumName << "_valueOf, qtscript_"
898 << " qtscript_" << qtScriptEnumName << "_valueOf, qtscript_"
899 << qtScriptEnumName << "_toString);" << endl;
899 << qtScriptEnumName << "_toString);" << endl;
900
900
901 stream << " qScriptRegisterMetaType<" << qualifiedEnumName << ">(engine, "
901 stream << " qScriptRegisterMetaType<" << qualifiedEnumName << ">(engine, "
902 << "qtscript_" << qtScriptEnumName << "_toScriptValue," << endl
902 << "qtscript_" << qtScriptEnumName << "_toScriptValue," << endl
903 << " qtscript_" << qtScriptEnumName << "_fromScriptValue,"
903 << " qtscript_" << qtScriptEnumName << "_fromScriptValue,"
904 << " ctor.property(QString::fromLatin1(\"prototype\")));" << endl;
904 << " ctor.property(QString::fromLatin1(\"prototype\")));" << endl;
905
905
906 // enum values are properties of the constructor
906 // enum values are properties of the constructor
907 stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
907 stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
908 << " clazz.setProperty(QString::fromLatin1(qtscript_"
908 << " clazz.setProperty(QString::fromLatin1(qtscript_"
909 << qtScriptEnumName << "_keys[i])," << endl
909 << qtScriptEnumName << "_keys[i])," << endl
910 << " engine->newVariant(qVariantFromValue(qtscript_"
910 << " engine->newVariant(qVariantFromValue(qtscript_"
911 << qtScriptEnumName << "_values[i]))," << endl
911 << qtScriptEnumName << "_values[i]))," << endl
912 << " QScriptValue::ReadOnly | QScriptValue::Undeletable);" << endl
912 << " QScriptValue::ReadOnly | QScriptValue::Undeletable);" << endl
913 << " }" << endl;
913 << " }" << endl;
914
914
915 stream << " return ctor;" << endl;
915 stream << " return ctor;" << endl;
916 stream << "}" << endl;
916 stream << "}" << endl;
917 stream << endl;
917 stream << endl;
918
918
919 // write flags class too, if any
919 // write flags class too, if any
920 FlagsTypeEntry *flags = enom->typeEntry()->flags();
920 FlagsTypeEntry *flags = enom->typeEntry()->flags();
921 if (!flags)
921 if (!flags)
922 return;
922 return;
923
923
924 QString qualifiedFlagsName = qualifiedCppNameColons + flags->targetLangName();
924 QString qualifiedFlagsName = qualifiedCppNameColons + flags->targetLangName();
925 QString qtScriptFlagsName = meta_class->name() + "_" + flags->targetLangName();
925 QString qtScriptFlagsName = meta_class->name() + "_" + flags->targetLangName();
926
926
927 stream << "//" << endl;
927 stream << "//" << endl;
928 stream << "// " << qualifiedFlagsName << endl;
928 stream << "// " << qualifiedFlagsName << endl;
929 stream << "//" << endl << endl;
929 stream << "//" << endl << endl;
930
930
931 // write QScriptValue <--> C++ conversion functions
931 // write QScriptValue <--> C++ conversion functions
932 stream << "static QScriptValue qtscript_"
932 stream << "static QScriptValue qtscript_"
933 << qtScriptFlagsName << "_toScriptValue("
933 << qtScriptFlagsName << "_toScriptValue("
934 << "QScriptEngine *engine, const " << qualifiedFlagsName << " &value)" << endl
934 << "QScriptEngine *engine, const " << qualifiedFlagsName << " &value)" << endl
935 << "{" << endl
935 << "{" << endl
936 << " return engine->newVariant(qVariantFromValue(value));" << endl
936 << " return engine->newVariant(qVariantFromValue(value));" << endl
937 << "}" << endl << endl;
937 << "}" << endl << endl;
938 stream << "static void qtscript_"
938 stream << "static void qtscript_"
939 << qtScriptFlagsName << "_fromScriptValue("
939 << qtScriptFlagsName << "_fromScriptValue("
940 << "const QScriptValue &value, " << qualifiedFlagsName << " &out)" << endl
940 << "const QScriptValue &value, " << qualifiedFlagsName << " &out)" << endl
941 << "{" << endl
941 << "{" << endl
942 << " QVariant var = value.toVariant();" << endl
942 << " QVariant var = value.toVariant();" << endl
943 << " if (var.userType() == qMetaTypeId<" << qualifiedFlagsName << ">())" << endl
943 << " if (var.userType() == qMetaTypeId<" << qualifiedFlagsName << ">())" << endl
944 << " out = qvariant_cast<" << qualifiedFlagsName << ">(var);" << endl
944 << " out = qvariant_cast<" << qualifiedFlagsName << ">(var);" << endl
945 << " else if (var.userType() == qMetaTypeId<" << qualifiedEnumName << ">())" << endl
945 << " else if (var.userType() == qMetaTypeId<" << qualifiedEnumName << ">())" << endl
946 << " out = qvariant_cast<" << qualifiedEnumName << ">(var);" << endl
946 << " out = qvariant_cast<" << qualifiedEnumName << ">(var);" << endl
947 << " else" << endl
947 << " else" << endl
948 << " out = 0;" << endl
948 << " out = 0;" << endl
949 << "}" << endl << endl;
949 << "}" << endl << endl;
950
950
951 // write constructor
951 // write constructor
952 stream << "static QScriptValue qtscript_construct_"
952 stream << "static QScriptValue qtscript_construct_"
953 << qtScriptFlagsName
953 << qtScriptFlagsName
954 << "(QScriptContext *context, QScriptEngine *engine)" << endl;
954 << "(QScriptContext *context, QScriptEngine *engine)" << endl;
955 stream << "{" << endl;
955 stream << "{" << endl;
956 stream << " " << qualifiedFlagsName << " result = 0;" << endl;
956 stream << " " << qualifiedFlagsName << " result = 0;" << endl;
957 stream << " if ((context->argumentCount() == 1) && context->argument(0).isNumber()) {" << endl;
957 stream << " if ((context->argumentCount() == 1) && context->argument(0).isNumber()) {" << endl;
958 stream << " result = static_cast<" << qualifiedFlagsName << ">(context->argument(0).toInt32());" << endl;
958 stream << " result = static_cast<" << qualifiedFlagsName << ">(context->argument(0).toInt32());" << endl;
959 stream << " } else {" << endl;
959 stream << " } else {" << endl;
960 stream << " for (int i = 0; i < context->argumentCount(); ++i) {" << endl;
960 stream << " for (int i = 0; i < context->argumentCount(); ++i) {" << endl;
961 stream << " QVariant v = context->argument(i).toVariant();" << endl;
961 stream << " QVariant v = context->argument(i).toVariant();" << endl;
962 stream << " if (v.userType() != qMetaTypeId<" << qualifiedEnumName << ">()) {" << endl;
962 stream << " if (v.userType() != qMetaTypeId<" << qualifiedEnumName << ">()) {" << endl;
963 stream << " return context->throwError(QScriptContext::TypeError," << endl
963 stream << " return context->throwError(QScriptContext::TypeError," << endl
964 << " QString::fromLatin1(\"" << flags->targetLangName()
964 << " QString::fromLatin1(\"" << flags->targetLangName()
965 << "(): argument %0 is not of type " << enom->name() << "\").arg(i));" << endl;
965 << "(): argument %0 is not of type " << enom->name() << "\").arg(i));" << endl;
966 stream << " }" << endl;
966 stream << " }" << endl;
967 stream << " result |= qvariant_cast<" << qualifiedEnumName
967 stream << " result |= qvariant_cast<" << qualifiedEnumName
968 << ">(v);" << endl;
968 << ">(v);" << endl;
969 stream << " }" << endl;
969 stream << " }" << endl;
970 stream << " }" << endl;
970 stream << " }" << endl;
971 stream << " return engine->newVariant(qVariantFromValue(result));" << endl;
971 stream << " return engine->newVariant(qVariantFromValue(result));" << endl;
972 stream << "}" << endl;
972 stream << "}" << endl;
973 stream << endl;
973 stream << endl;
974
974
975 // write prototype.valueOf()
975 // write prototype.valueOf()
976 stream << "static QScriptValue qtscript_" << qtScriptFlagsName
976 stream << "static QScriptValue qtscript_" << qtScriptFlagsName
977 << "_valueOf(QScriptContext *context, QScriptEngine *engine)" << endl;
977 << "_valueOf(QScriptContext *context, QScriptEngine *engine)" << endl;
978 stream << "{" << endl;
978 stream << "{" << endl;
979 stream << " " << qualifiedFlagsName << " value = "
979 stream << " " << qualifiedFlagsName << " value = "
980 << "qscriptvalue_cast<" << qualifiedFlagsName
980 << "qscriptvalue_cast<" << qualifiedFlagsName
981 << ">(context->thisObject());" << endl;
981 << ">(context->thisObject());" << endl;
982 stream << " return QScriptValue(engine, static_cast<int>(value));" << endl;
982 stream << " return QScriptValue(engine, static_cast<int>(value));" << endl;
983 stream << "}" << endl;
983 stream << "}" << endl;
984 stream << endl;
984 stream << endl;
985
985
986 // write prototype.toString()
986 // write prototype.toString()
987 stream << "static QScriptValue qtscript_" << qtScriptFlagsName
987 stream << "static QScriptValue qtscript_" << qtScriptFlagsName
988 << "_toString(QScriptContext *context, QScriptEngine *engine)" << endl;
988 << "_toString(QScriptContext *context, QScriptEngine *engine)" << endl;
989 stream << "{" << endl;
989 stream << "{" << endl;
990 stream << " " << qualifiedFlagsName << " value = "
990 stream << " " << qualifiedFlagsName << " value = "
991 << "qscriptvalue_cast<" << qualifiedFlagsName
991 << "qscriptvalue_cast<" << qualifiedFlagsName
992 << ">(context->thisObject());" << endl;
992 << ">(context->thisObject());" << endl;
993 stream << " QString result;" << endl;
993 stream << " QString result;" << endl;
994 stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
994 stream << " for (int i = 0; i < " << uniqueIndexes.size() << "; ++i) {" << endl
995 << " if ((value & qtscript_" << qtScriptEnumName << "_values[i])"
995 << " if ((value & qtscript_" << qtScriptEnumName << "_values[i])"
996 << " == qtscript_" << qtScriptEnumName << "_values[i]) {" << endl
996 << " == qtscript_" << qtScriptEnumName << "_values[i]) {" << endl
997 << " if (!result.isEmpty())" << endl
997 << " if (!result.isEmpty())" << endl
998 << " result.append(QString::fromLatin1(\",\"));" << endl
998 << " result.append(QString::fromLatin1(\",\"));" << endl
999 << " result.append(QString::fromLatin1(qtscript_" << qtScriptEnumName << "_keys[i]));" << endl
999 << " result.append(QString::fromLatin1(qtscript_" << qtScriptEnumName << "_keys[i]));" << endl
1000 << " }" << endl
1000 << " }" << endl
1001 << " }" << endl
1001 << " }" << endl
1002 << " return QScriptValue(engine, result);" << endl
1002 << " return QScriptValue(engine, result);" << endl
1003 << "}" << endl
1003 << "}" << endl
1004 << endl;
1004 << endl;
1005
1005
1006 // write prototype.equals()
1006 // write prototype.equals()
1007 stream << "static QScriptValue qtscript_" << qtScriptFlagsName
1007 stream << "static QScriptValue qtscript_" << qtScriptFlagsName
1008 << "_equals(QScriptContext *context, QScriptEngine *engine)" << endl
1008 << "_equals(QScriptContext *context, QScriptEngine *engine)" << endl
1009 << "{" << endl
1009 << "{" << endl
1010 << " QVariant thisObj = context->thisObject().toVariant();" << endl
1010 << " QVariant thisObj = context->thisObject().toVariant();" << endl
1011 << " QVariant otherObj = context->argument(0).toVariant();" << endl
1011 << " QVariant otherObj = context->argument(0).toVariant();" << endl
1012
1012
1013 << " return QScriptValue(engine, ((thisObj.userType() == otherObj.userType()) &&" << endl
1013 << " return QScriptValue(engine, ((thisObj.userType() == otherObj.userType()) &&" << endl
1014 << " (thisObj.value<" << qualifiedFlagsName << ">() == otherObj.value<" << qualifiedFlagsName << ">())));" << endl
1014 << " (thisObj.value<" << qualifiedFlagsName << ">() == otherObj.value<" << qualifiedFlagsName << ">())));" << endl
1015 << "}" << endl << endl;
1015 << "}" << endl << endl;
1016
1016
1017 // write class creation function
1017 // write class creation function
1018 stream << "static QScriptValue qtscript_create_" << qtScriptFlagsName << "_class(QScriptEngine *engine)" << endl;
1018 stream << "static QScriptValue qtscript_create_" << qtScriptFlagsName << "_class(QScriptEngine *engine)" << endl;
1019 stream << "{" << endl;
1019 stream << "{" << endl;
1020 stream << " QScriptValue ctor = qtscript_create_flags_class_helper(" << endl
1020 stream << " QScriptValue ctor = qtscript_create_flags_class_helper(" << endl
1021 << " engine, qtscript_construct_" << qtScriptFlagsName
1021 << " engine, qtscript_construct_" << qtScriptFlagsName
1022 << ", qtscript_" << qtScriptFlagsName << "_valueOf," << endl
1022 << ", qtscript_" << qtScriptFlagsName << "_valueOf," << endl
1023 << " qtscript_" << qtScriptFlagsName << "_toString, qtscript_"
1023 << " qtscript_" << qtScriptFlagsName << "_toString, qtscript_"
1024 << qtScriptFlagsName << "_equals);" << endl;
1024 << qtScriptFlagsName << "_equals);" << endl;
1025
1025
1026 stream << " qScriptRegisterMetaType<" << qualifiedFlagsName << ">(engine, "
1026 stream << " qScriptRegisterMetaType<" << qualifiedFlagsName << ">(engine, "
1027 << "qtscript_" << qtScriptFlagsName << "_toScriptValue," << endl
1027 << "qtscript_" << qtScriptFlagsName << "_toScriptValue," << endl
1028 << " qtscript_" << qtScriptFlagsName << "_fromScriptValue,"
1028 << " qtscript_" << qtScriptFlagsName << "_fromScriptValue,"
1029 << " ctor.property(QString::fromLatin1(\"prototype\")));" << endl;
1029 << " ctor.property(QString::fromLatin1(\"prototype\")));" << endl;
1030
1030
1031 stream << " return ctor;" << endl;
1031 stream << " return ctor;" << endl;
1032 stream << "}" << endl;
1032 stream << "}" << endl;
1033 stream << endl;
1033 stream << endl;
1034 }
1034 }
1035
1035
1036 /*!
1036 /*!
1037 Declares the given \a typeName if it hasn't been declared already,
1037 Declares the given \a typeName if it hasn't been declared already,
1038 and adds it to the set of registered type names.
1038 and adds it to the set of registered type names.
1039 */
1039 */
1040 void maybeDeclareMetaType(QTextStream &stream, const QString &typeName,
1040 void maybeDeclareMetaType(QTextStream &stream, const QString &typeName,
1041 QSet<QString> &registeredTypeNames)
1041 QSet<QString> &registeredTypeNames)
1042 {
1042 {
1043 QString name = typeName;
1043 QString name = typeName;
1044 if (name.endsWith(QLatin1Char('&')))
1044 if (name.endsWith(QLatin1Char('&')))
1045 name.chop(1);
1045 name.chop(1);
1046 if (registeredTypeNames.contains(name) || (QMetaType::type(typeName.toLatin1()) != 0))
1046 if (registeredTypeNames.contains(name) || (QMetaType::type(typeName.toLatin1()) != 0))
1047 return;
1047 return;
1048 if (name.contains(QLatin1Char(','))) {
1048 if (name.contains(QLatin1Char(','))) {
1049 // need to expand the Q_DECLARE_METATYPE macro manually,
1049 // need to expand the Q_DECLARE_METATYPE macro manually,
1050 // otherwise the compiler will choke
1050 // otherwise the compiler will choke
1051 stream << "template <> \\" << endl
1051 stream << "template <> \\" << endl
1052 << "struct QMetaTypeId< " << name << " > \\" << endl
1052 << "struct QMetaTypeId< " << name << " > \\" << endl
1053 << "{ \\" << endl
1053 << "{ \\" << endl
1054 << " enum { Defined = 1 }; \\" << endl
1054 << " enum { Defined = 1 }; \\" << endl
1055 << " static int qt_metatype_id() \\" << endl
1055 << " static int qt_metatype_id() \\" << endl
1056 << " { \\" << endl
1056 << " { \\" << endl
1057 << " static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \\" << endl
1057 << " static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0); \\" << endl
1058 << " if (!metatype_id) \\" << endl
1058 << " if (!metatype_id) \\" << endl
1059 << " metatype_id = qRegisterMetaType< " << name << " >(\"" << name << "\"); \\" << endl
1059 << " metatype_id = qRegisterMetaType< " << name << " >(\"" << name << "\"); \\" << endl
1060 << " return metatype_id; \\" << endl
1060 << " return metatype_id; \\" << endl
1061 << " } \\" << endl
1061 << " } \\" << endl
1062 << "};" << endl;
1062 << "};" << endl;
1063 } else {
1063 } else {
1064 stream << "Q_DECLARE_METATYPE(" << name << ")" << endl;
1064 stream << "Q_DECLARE_METATYPE(" << name << ")" << endl;
1065 }
1065 }
1066 registeredTypeNames << name;
1066 registeredTypeNames << name;
1067 }
1067 }
1068
1068
1069 /*!
1069 /*!
1070 Declares the given \a type recursively (i.e. subtypes of a composite
1070 Declares the given \a type recursively (i.e. subtypes of a composite
1071 type are also declared).
1071 type are also declared).
1072 */
1072 */
1073 static void declareTypeRecursive(QTextStream &stream, const AbstractMetaType *type,
1073 static void declareTypeRecursive(QTextStream &stream, const AbstractMetaType *type,
1074 QSet<QString> &registeredTypeNames)
1074 QSet<QString> &registeredTypeNames)
1075 {
1075 {
1076 if (!type)
1076 if (!type)
1077 return;
1077 return;
1078 QList<AbstractMetaType *> subTypes = type->instantiations();
1078 QList<AbstractMetaType *> subTypes = type->instantiations();
1079 for (int i = 0; i < subTypes.size(); ++i)
1079 for (int i = 0; i < subTypes.size(); ++i)
1080 declareTypeRecursive(stream, subTypes.at(i), registeredTypeNames);
1080 declareTypeRecursive(stream, subTypes.at(i), registeredTypeNames);
1081 QString typeName = normalizedType(type);
1081 QString typeName = normalizedType(type);
1082 if (typeName == QLatin1String("QStringList<QString>"))
1082 if (typeName == QLatin1String("QStringList<QString>"))
1083 return; // ### wtf...
1083 return; // ### wtf...
1084 maybeDeclareMetaType(stream, typeName, registeredTypeNames);
1084 maybeDeclareMetaType(stream, typeName, registeredTypeNames);
1085 }
1085 }
1086
1086
1087 /*!
1087 /*!
1088 Declares the types associated with the given \a functions.
1088 Declares the types associated with the given \a functions.
1089 */
1089 */
1090 void declareFunctionMetaTypes(QTextStream &stream, const AbstractMetaFunctionList &functions,
1090 void declareFunctionMetaTypes(QTextStream &stream, const AbstractMetaFunctionList &functions,
1091 QSet<QString> &registeredTypeNames)
1091 QSet<QString> &registeredTypeNames)
1092 {
1092 {
1093 for (int i = 0; i < functions.size(); ++i) {
1093 for (int i = 0; i < functions.size(); ++i) {
1094 AbstractMetaFunction *fun = functions.at(i);
1094 AbstractMetaFunction *fun = functions.at(i);
1095 if (ClassGenerator::isSpecialStreamingOperator(fun)) {
1095 if (ClassGenerator::isSpecialStreamingOperator(fun)) {
1096 maybeDeclareMetaType(stream, fun->arguments().at(0)->type()->name() + "*",
1096 maybeDeclareMetaType(stream, fun->arguments().at(0)->type()->name() + "*",
1097 registeredTypeNames);
1097 registeredTypeNames);
1098 continue;
1098 continue;
1099 }
1099 }
1100 AbstractMetaArgumentList arguments = fun->arguments();
1100 AbstractMetaArgumentList arguments = fun->arguments();
1101 for (int j = 0; j < arguments.size(); ++j) {
1101 for (int j = 0; j < arguments.size(); ++j) {
1102 if (fun->argumentRemoved(j+1))
1102 if (fun->argumentRemoved(j+1))
1103 continue;
1103 continue;
1104 QString repl = fun->typeReplaced(j+1);
1104 QString repl = fun->typeReplaced(j+1);
1105 if (!repl.isEmpty()) {
1105 if (!repl.isEmpty()) {
1106 maybeDeclareMetaType(stream, repl, registeredTypeNames);
1106 maybeDeclareMetaType(stream, repl, registeredTypeNames);
1107 } else {
1107 } else {
1108 const AbstractMetaArgument *arg = arguments.at(j);
1108 const AbstractMetaArgument *arg = arguments.at(j);
1109 declareTypeRecursive(stream, arg->type(), registeredTypeNames);
1109 declareTypeRecursive(stream, arg->type(), registeredTypeNames);
1110 }
1110 }
1111 }
1111 }
1112 QString retRepl = fun->typeReplaced(0);
1112 QString retRepl = fun->typeReplaced(0);
1113 if (!retRepl.isEmpty())
1113 if (!retRepl.isEmpty())
1114 maybeDeclareMetaType(stream, retRepl, registeredTypeNames);
1114 maybeDeclareMetaType(stream, retRepl, registeredTypeNames);
1115 else
1115 else
1116 declareTypeRecursive(stream, fun->type(), registeredTypeNames);
1116 declareTypeRecursive(stream, fun->type(), registeredTypeNames);
1117 }
1117 }
1118 }
1118 }
1119
1119
1120 /*!
1120 /*!
1121 Returns true if we don't care about the given enum \a enom,
1121 Returns true if we don't care about the given enum \a enom,
1122 false otherwise.
1122 false otherwise.
1123 */
1123 */
1124 static bool shouldIgnoreEnum(const AbstractMetaEnum *enom)
1124 static bool shouldIgnoreEnum(const AbstractMetaEnum *enom)
1125 {
1125 {
1126 return !enom->wasPublic() || (enom->name() == "enum_1");
1126 return !enom->wasPublic() || (enom->name() == "enum_1");
1127 }
1127 }
1128
1128
1129 /*!
1129 /*!
1130 Declares the types associated with the enums of the given \a
1130 Declares the types associated with the enums of the given \a
1131 meta_class.
1131 meta_class.
1132 */
1132 */
1133 void declareEnumMetaTypes(QTextStream &stream, const AbstractMetaClass *meta_class,
1133 void declareEnumMetaTypes(QTextStream &stream, const AbstractMetaClass *meta_class,
1134 QSet<QString> &registeredTypeNames)
1134 QSet<QString> &registeredTypeNames)
1135 {
1135 {
1136 AbstractMetaEnumList enums = meta_class->enums();
1136 AbstractMetaEnumList enums = meta_class->enums();
1137 for (int i = 0; i < enums.size(); ++i) {
1137 for (int i = 0; i < enums.size(); ++i) {
1138 const AbstractMetaEnum *enom = enums.at(i);
1138 const AbstractMetaEnum *enom = enums.at(i);
1139 if (shouldIgnoreEnum(enom))
1139 if (shouldIgnoreEnum(enom))
1140 continue;
1140 continue;
1141 if (meta_class->name() == "Global")
1141 if (meta_class->name() == "Global")
1142 maybeDeclareMetaType(stream, enom->name(), registeredTypeNames);
1142 maybeDeclareMetaType(stream, enom->name(), registeredTypeNames);
1143 else
1143 else
1144 maybeDeclareMetaType(stream, QString::fromLatin1("%0::%1")
1144 maybeDeclareMetaType(stream, QString::fromLatin1("%0::%1")
1145 .arg(meta_class->qualifiedCppName()).arg(enom->name()),
1145 .arg(meta_class->qualifiedCppName()).arg(enom->name()),
1146 registeredTypeNames);
1146 registeredTypeNames);
1147 FlagsTypeEntry *flags = enom->typeEntry()->flags();
1147 FlagsTypeEntry *flags = enom->typeEntry()->flags();
1148 if (flags) {
1148 if (flags) {
1149 maybeDeclareMetaType(stream, QString::fromLatin1("QFlags<%0::%1>")
1149 maybeDeclareMetaType(stream, QString::fromLatin1("QFlags<%0::%1>")
1150 .arg(meta_class->qualifiedCppName()).arg(enom->name()),
1150 .arg(meta_class->qualifiedCppName()).arg(enom->name()),
1151 registeredTypeNames);
1151 registeredTypeNames);
1152 }
1152 }
1153 }
1153 }
1154 }
1154 }
1155
1155
1156 /*!
1156 /*!
1157 Returns the maximum function length among \a functions.
1157 Returns the maximum function length among \a functions.
1158 */
1158 */
1159 static int maxFunctionLength(const AbstractMetaFunctionList &functions)
1159 static int maxFunctionLength(const AbstractMetaFunctionList &functions)
1160 {
1160 {
1161 int result = 0;
1161 int result = 0;
1162 for (int i = 0; i < functions.size(); ++i)
1162 for (int i = 0; i < functions.size(); ++i)
1163 result = qMax(result, functions.at(i)->arguments().size());
1163 result = qMax(result, functions.at(i)->arguments().size());
1164 return result;
1164 return result;
1165 }
1165 }
1166
1166
1167 /*!
1167 /*!
1168 Writes a prototype/static function.
1168 Writes a prototype/static function.
1169 */
1169 */
1170 static void writeFunctionForwarding(QTextStream &stream, const AbstractMetaClass *meta_class,
1170 static void writeFunctionForwarding(QTextStream &stream, const AbstractMetaClass *meta_class,
1171 const AbstractMetaFunctionList &functions)
1171 const AbstractMetaFunctionList &functions)
1172 {
1172 {
1173 #if 0
1173 #if 0
1174 stream << "/** signatures:" << endl;
1174 stream << "/** signatures:" << endl;
1175 foreach (const AbstractMetaFunction *fun, functions) {
1175 foreach (const AbstractMetaFunction *fun, functions) {
1176 stream << " * " << fun->signature() << endl;
1176 stream << " * " << fun->signature() << endl;
1177 }
1177 }
1178 stream << " */" << endl;
1178 stream << " */" << endl;
1179 #endif
1179 #endif
1180 QMap<int, AbstractMetaFunctionList> argcToFunctions;
1180 QMap<int, AbstractMetaFunctionList> argcToFunctions;
1181 argcToFunctions = createArgcToFunctionsMap(functions);
1181 argcToFunctions = createArgcToFunctionsMap(functions);
1182 QSet<QString> signatures;
1182 QSet<QString> signatures;
1183 int argcMin = argcToFunctions.keys().first();
1183 int argcMin = argcToFunctions.keys().first();
1184 int argcMax = argcToFunctions.keys().last();
1184 int argcMax = argcToFunctions.keys().last();
1185 for (int i = argcMin; i <= argcMax; ++i) {
1185 for (int i = argcMin; i <= argcMax; ++i) {
1186 AbstractMetaFunctionList funcs = argcToFunctions.value(i);
1186 AbstractMetaFunctionList funcs = argcToFunctions.value(i);
1187 if (funcs.isEmpty())
1187 if (funcs.isEmpty())
1188 continue;
1188 continue;
1189 stream << " if (context->argumentCount() == " << i << ") {" << endl;
1189 stream << " if (context->argumentCount() == " << i << ") {" << endl;
1190 if (funcs.size() == 1) {
1190 if (funcs.size() == 1) {
1191 AbstractMetaFunction *fun = funcs.at(0);
1191 AbstractMetaFunction *fun = funcs.at(0);
1192 const int indent = 8;
1192 const int indent = 8;
1193 // special case for Q{Data,Text}Stream streaming operators
1193 // special case for Q{Data,Text}Stream streaming operators
1194 if (ClassGenerator::isSpecialStreamingOperator(fun))
1194 if (ClassGenerator::isSpecialStreamingOperator(fun))
1195 writeStreamingOperatorCall(stream, fun, meta_class, indent);
1195 writeStreamingOperatorCall(stream, fun, meta_class, indent);
1196 else
1196 else
1197 writeFunctionCallAndReturn(stream, fun, i, meta_class, indent);
1197 writeFunctionCallAndReturn(stream, fun, i, meta_class, indent);
1198 signatures.insert(fun->targetLangSignature());
1198 signatures.insert(fun->targetLangSignature());
1199 } else {
1199 } else {
1200 // handle overloads
1200 // handle overloads
1201 QStringList sigs;
1201 QStringList sigs;
1202 for (int j = 0; j < funcs.size(); ++j) {
1202 for (int j = 0; j < funcs.size(); ++j) {
1203 AbstractMetaFunction *fun = funcs.at(j);
1203 AbstractMetaFunction *fun = funcs.at(j);
1204 sigs.append(fun->signature());
1204 sigs.append(fun->signature());
1205 stream << " ";
1205 stream << " ";
1206 if (j > 0)
1206 if (j > 0)
1207 stream << "} else ";
1207 stream << "} else ";
1208 stream << "if (";
1208 stream << "if (";
1209 AbstractMetaArgumentList arguments = fun->arguments();
1209 AbstractMetaArgumentList arguments = fun->arguments();
1210 const int indent = 12;
1210 const int indent = 12;
1211 writeArgumentTypeTests(stream, fun, arguments, i, indent);
1211 writeArgumentTypeTests(stream, fun, arguments, i, indent);
1212 stream << ") {" << endl;
1212 stream << ") {" << endl;
1213 writeFunctionCallAndReturn(stream, fun, i, meta_class, indent);
1213 writeFunctionCallAndReturn(stream, fun, i, meta_class, indent);
1214 signatures.insert(fun->targetLangSignature());
1214 signatures.insert(fun->targetLangSignature());
1215 }
1215 }
1216 stream << " }" << endl;
1216 stream << " }" << endl;
1217 }
1217 }
1218 stream << " }" << endl;
1218 stream << " }" << endl;
1219 }
1219 }
1220 }
1220 }
1221
1221
1222 static void writePrototypeCall(QTextStream &s, const AbstractMetaClass *meta_class,
1222 static void writePrototypeCall(QTextStream &s, const AbstractMetaClass *meta_class,
1223 const QMap<QString, AbstractMetaFunctionList> &nameToFunctions,
1223 const QMap<QString, AbstractMetaFunctionList> &nameToFunctions,
1224 int prototypeFunctionsOffset)
1224 int prototypeFunctionsOffset)
1225 {
1225 {
1226 s << "static QScriptValue qtscript_" << meta_class->name()
1226 s << "static QScriptValue qtscript_" << meta_class->name()
1227 << "_prototype_call(QScriptContext *context, QScriptEngine *)" << endl
1227 << "_prototype_call(QScriptContext *context, QScriptEngine *)" << endl
1228 << "{" << endl;
1228 << "{" << endl;
1229
1229
1230 s << "#if QT_VERSION > 0x040400" << endl;
1230 s << "#if QT_VERSION > 0x040400" << endl;
1231
1231
1232 s << " Q_ASSERT(context->callee().isFunction());" << endl
1232 s << " Q_ASSERT(context->callee().isFunction());" << endl
1233 << " uint _id = context->callee().data().toUInt32();" << endl;
1233 << " uint _id = context->callee().data().toUInt32();" << endl;
1234
1234
1235 s << "#else" << endl
1235 s << "#else" << endl
1236 << " uint _id;" << endl
1236 << " uint _id;" << endl
1237 << " if (context->callee().isFunction())" << endl
1237 << " if (context->callee().isFunction())" << endl
1238 << " _id = context->callee().data().toUInt32();" << endl
1238 << " _id = context->callee().data().toUInt32();" << endl
1239 << " else" << endl
1239 << " else" << endl
1240 << " _id = 0xBABE0000 + " << nameToFunctions.size() << ";" << endl;
1240 << " _id = 0xBABE0000 + " << nameToFunctions.size() << ";" << endl;
1241
1241
1242 s << "#endif" << endl;
1242 s << "#endif" << endl;
1243
1243
1244 s << " Q_ASSERT((_id & 0xFFFF0000) == 0xBABE0000);" << endl
1244 s << " Q_ASSERT((_id & 0xFFFF0000) == 0xBABE0000);" << endl
1245 << " _id &= 0x0000FFFF;" << endl;
1245 << " _id &= 0x0000FFFF;" << endl;
1246
1246
1247 // cast the thisObject to C++ type
1247 // cast the thisObject to C++ type
1248 s << " ";
1248 s << " ";
1249 #ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
1249 #ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
1250 if (meta_class->hasProtectedFunctions())
1250 if (meta_class->hasProtectedFunctions())
1251 s << "qtscript_";
1251 s << "qtscript_";
1252 #endif
1252 #endif
1253 s << meta_class->qualifiedCppName() << "* _q_self = ";
1253 s << meta_class->qualifiedCppName() << "* _q_self = ";
1254 #ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
1254 #ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
1255 if (meta_class->hasProtectedFunctions())
1255 if (meta_class->hasProtectedFunctions())
1256 s << "reinterpret_cast<qtscript_" << meta_class->name() << "*>(";
1256 s << "reinterpret_cast<qtscript_" << meta_class->name() << "*>(";
1257 #endif
1257 #endif
1258 s << "qscriptvalue_cast<" << meta_class->qualifiedCppName()
1258 s << "qscriptvalue_cast<" << meta_class->qualifiedCppName()
1259 << "*>(context->thisObject())";
1259 << "*>(context->thisObject())";
1260 #ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
1260 #ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
1261 if (meta_class->hasProtectedFunctions())
1261 if (meta_class->hasProtectedFunctions())
1262 s << ")";
1262 s << ")";
1263 #endif
1263 #endif
1264 s << ";" << endl
1264 s << ";" << endl
1265 << " if (!_q_self) {" << endl
1265 << " if (!_q_self) {" << endl
1266 << " return context->throwError(QScriptContext::TypeError," << endl
1266 << " return context->throwError(QScriptContext::TypeError," << endl
1267 << " QString::fromLatin1(\"" << meta_class->name()
1267 << " QString::fromLatin1(\"" << meta_class->name()
1268 << ".%0(): this object is not a " << meta_class->name() << "\")" << endl
1268 << ".%0(): this object is not a " << meta_class->name() << "\")" << endl
1269 << " .arg(qtscript_" << meta_class->name()
1269 << " .arg(qtscript_" << meta_class->name()
1270 << "_function_names[_id+" << prototypeFunctionsOffset <<"]));" << endl
1270 << "_function_names[_id+" << prototypeFunctionsOffset <<"]));" << endl
1271 << " }" << endl << endl;
1271 << " }" << endl << endl;
1272
1272
1273 s << " switch (_id) {" << endl;
1273 s << " switch (_id) {" << endl;
1274
1274
1275 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1275 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1276 int index = 0;
1276 int index = 0;
1277 for (it = nameToFunctions.constBegin(); it != nameToFunctions.constEnd(); ++it) {
1277 for (it = nameToFunctions.constBegin(); it != nameToFunctions.constEnd(); ++it) {
1278 s << " case " << index << ":" << endl;
1278 s << " case " << index << ":" << endl;
1279 writeFunctionForwarding(s, meta_class, it.value());
1279 writeFunctionForwarding(s, meta_class, it.value());
1280 s << " break;" << endl << endl;
1280 s << " break;" << endl << endl;
1281 ++index;
1281 ++index;
1282 }
1282 }
1283
1283
1284 if (!meta_class->hasDefaultToStringFunction()) {
1284 if (!meta_class->hasDefaultToStringFunction()) {
1285 s << " case " << index << ": {" << endl;
1285 s << " case " << index << ": {" << endl;
1286 s << " QString result";
1286 s << " QString result";
1287 FunctionModelItem fun = meta_class->hasToStringCapability();
1287 FunctionModelItem fun = meta_class->hasToStringCapability();
1288 if (fun) {
1288 if (fun) {
1289 int indirections = fun->arguments().at(1)->type().indirections();
1289 int indirections = fun->arguments().at(1)->type().indirections();
1290 QString deref = QLatin1String(indirections == 0 ? "*" : "");
1290 QString deref = QLatin1String(indirections == 0 ? "*" : "");
1291 s << ";" << endl
1291 s << ";" << endl
1292 << " QDebug d(&result);" << endl
1292 << " QDebug d(&result);" << endl
1293 << " d << " << deref << "_q_self;" << endl;
1293 << " d << " << deref << "_q_self;" << endl;
1294 } else {
1294 } else {
1295 // ### FIXME: can cause compile error
1295 // ### FIXME: can cause compile error
1296 // s << "=QString(\"" << meta_class->name() << "(0x%1)\").arg((int)_q_self, 0, 16);" << endl;
1296 // s << "=QString(\"" << meta_class->name() << "(0x%1)\").arg((int)_q_self, 0, 16);" << endl;
1297 s << " = QString::fromLatin1(\"" << meta_class->name() << "\");" << endl;
1297 s << " = QString::fromLatin1(\"" << meta_class->name() << "\");" << endl;
1298 }
1298 }
1299 s << " return QScriptValue(context->engine(), result);" << endl
1299 s << " return QScriptValue(context->engine(), result);" << endl
1300 << " }" << endl << endl;
1300 << " }" << endl << endl;
1301 }
1301 }
1302
1302
1303 s << " default:" << endl
1303 s << " default:" << endl
1304 << " Q_ASSERT(false);" << endl
1304 << " Q_ASSERT(false);" << endl
1305 << " }" << endl;
1305 << " }" << endl;
1306
1306
1307 s << " return qtscript_" << meta_class->name() << "_throw_ambiguity_error_helper(context," << endl
1307 s << " return qtscript_" << meta_class->name() << "_throw_ambiguity_error_helper(context," << endl
1308 << " qtscript_" << meta_class->name()
1308 << " qtscript_" << meta_class->name()
1309 << "_function_names[_id+" << prototypeFunctionsOffset << "]," << endl
1309 << "_function_names[_id+" << prototypeFunctionsOffset << "]," << endl
1310 << " qtscript_" << meta_class->name()
1310 << " qtscript_" << meta_class->name()
1311 << "_function_signatures[_id+" << prototypeFunctionsOffset << "]);" << endl;
1311 << "_function_signatures[_id+" << prototypeFunctionsOffset << "]);" << endl;
1312
1312
1313 s << "}" << endl << endl;
1313 s << "}" << endl << endl;
1314 }
1314 }
1315
1315
1316 static void writeStaticCall(QTextStream &s, const AbstractMetaClass *meta_class,
1316 static void writeStaticCall(QTextStream &s, const AbstractMetaClass *meta_class,
1317 const AbstractMetaFunctionList &constructors,
1317 const AbstractMetaFunctionList &constructors,
1318 const QMap<QString, AbstractMetaFunctionList> &nameToFunctions)
1318 const QMap<QString, AbstractMetaFunctionList> &nameToFunctions)
1319 {
1319 {
1320 s << "static QScriptValue qtscript_" << meta_class->name()
1320 s << "static QScriptValue qtscript_" << meta_class->name()
1321 << "_static_call(QScriptContext *context, QScriptEngine *)" << endl
1321 << "_static_call(QScriptContext *context, QScriptEngine *)" << endl
1322 << "{" << endl;
1322 << "{" << endl;
1323
1323
1324 s << " uint _id = context->callee().data().toUInt32();" << endl
1324 s << " uint _id = context->callee().data().toUInt32();" << endl
1325 << " Q_ASSERT((_id & 0xFFFF0000) == 0xBABE0000);" << endl
1325 << " Q_ASSERT((_id & 0xFFFF0000) == 0xBABE0000);" << endl
1326 << " _id &= 0x0000FFFF;" << endl;
1326 << " _id &= 0x0000FFFF;" << endl;
1327
1327
1328 s << " switch (_id) {" << endl;
1328 s << " switch (_id) {" << endl;
1329
1329
1330 s << " case 0:" << endl;
1330 s << " case 0:" << endl;
1331 writeConstructorForwarding(s, constructors, meta_class);
1331 writeConstructorForwarding(s, constructors, meta_class);
1332 s << " break;" << endl << endl;
1332 s << " break;" << endl << endl;
1333
1333
1334 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1334 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1335 int index = 1;
1335 int index = 1;
1336 for (it = nameToFunctions.constBegin(); it != nameToFunctions.constEnd(); ++it) {
1336 for (it = nameToFunctions.constBegin(); it != nameToFunctions.constEnd(); ++it) {
1337 s << " case " << index << ":" << endl;
1337 s << " case " << index << ":" << endl;
1338 writeFunctionForwarding(s, meta_class, it.value());
1338 writeFunctionForwarding(s, meta_class, it.value());
1339 s << " break;" << endl << endl;
1339 s << " break;" << endl << endl;
1340 ++index;
1340 ++index;
1341 }
1341 }
1342
1342
1343 s << " default:" << endl
1343 s << " default:" << endl
1344 << " Q_ASSERT(false);" << endl
1344 << " Q_ASSERT(false);" << endl
1345 << " }" << endl;
1345 << " }" << endl;
1346
1346
1347 s << " return qtscript_" << meta_class->name() << "_throw_ambiguity_error_helper(context," << endl
1347 s << " return qtscript_" << meta_class->name() << "_throw_ambiguity_error_helper(context," << endl
1348 << " qtscript_" << meta_class->name() << "_function_names[_id]," << endl
1348 << " qtscript_" << meta_class->name() << "_function_names[_id]," << endl
1349 << " qtscript_" << meta_class->name() << "_function_signatures[_id]);" << endl;
1349 << " qtscript_" << meta_class->name() << "_function_signatures[_id]);" << endl;
1350
1350
1351 s << "}" << endl << endl;
1351 s << "}" << endl << endl;
1352 }
1352 }
1353
1353
1354 /*!
1354 /*!
1355 Writes the include defined by \a inc to \a stream.
1355 Writes the include defined by \a inc to \a stream.
1356 */
1356 */
1357 void ClassGenerator::writeInclude(QTextStream &stream, const Include &inc)
1357 void ClassGenerator::writeInclude(QTextStream &stream, const Include &inc)
1358 {
1358 {
1359 if (inc.name.isEmpty())
1359 if (inc.name.isEmpty())
1360 return;
1360 return;
1361 if (inc.type == Include::TargetLangImport)
1361 if (inc.type == Include::TargetLangImport)
1362 return;
1362 return;
1363 stream << "#include ";
1363 stream << "#include ";
1364 if (inc.type == Include::IncludePath)
1364 if (inc.type == Include::IncludePath)
1365 stream << "<";
1365 stream << "<";
1366 else
1366 else
1367 stream << "\"";
1367 stream << "\"";
1368 stream << inc.name;
1368 stream << inc.name;
1369 if (inc.type == Include::IncludePath)
1369 if (inc.type == Include::IncludePath)
1370 stream << ">";
1370 stream << ">";
1371 else
1371 else
1372 stream << "\"";
1372 stream << "\"";
1373 stream << endl;
1373 stream << endl;
1374 }
1374 }
1375
1375
1376 static void writeHelperFunctions(QTextStream &stream, const AbstractMetaClass *meta_class)
1376 static void writeHelperFunctions(QTextStream &stream, const AbstractMetaClass *meta_class)
1377 {
1377 {
1378 stream << "static QScriptValue qtscript_" << meta_class->name() << "_throw_ambiguity_error_helper(" << endl
1378 stream << "static QScriptValue qtscript_" << meta_class->name() << "_throw_ambiguity_error_helper(" << endl
1379 << " QScriptContext *context, const char *functionName, const char *signatures)" << endl
1379 << " QScriptContext *context, const char *functionName, const char *signatures)" << endl
1380 << "{" << endl
1380 << "{" << endl
1381 << " QStringList lines = QString::fromLatin1(signatures).split(QLatin1Char('\\n'));" << endl
1381 << " QStringList lines = QString::fromLatin1(signatures).split(QLatin1Char('\\n'));" << endl
1382 << " QStringList fullSignatures;" << endl
1382 << " QStringList fullSignatures;" << endl
1383 << " for (int i = 0; i < lines.size(); ++i)" << endl
1383 << " for (int i = 0; i < lines.size(); ++i)" << endl
1384 << " fullSignatures.append(QString::fromLatin1(\"%0(%1)\").arg(functionName).arg(lines.at(i)));" << endl
1384 << " fullSignatures.append(QString::fromLatin1(\"%0(%1)\").arg(functionName).arg(lines.at(i)));" << endl
1385 << " return context->throwError(QString::fromLatin1(\"" << meta_class->name()
1385 << " return context->throwError(QString::fromLatin1(\"" << meta_class->name()
1386 << "::%0(): could not find a function match; candidates are:\\n%1\")" << endl
1386 << "::%0(): could not find a function match; candidates are:\\n%1\")" << endl
1387 << " .arg(functionName).arg(fullSignatures.join(QLatin1String(\"\\n\"))));" << endl
1387 << " .arg(functionName).arg(fullSignatures.join(QLatin1String(\"\\n\"))));" << endl
1388 << "}" << endl << endl;
1388 << "}" << endl << endl;
1389 }
1389 }
1390
1390
1391 void writeQtScriptQtBindingsLicense(QTextStream &stream)
1392 {
1393 stream
1394 << "/****************************************************************************" << endl
1395 << "**" << endl
1396 << "** Copyright (C) 2008 Trolltech ASA. All rights reserved." << endl
1397 << "**" << endl
1398 << "** This file is part of the Qt Script Qt Bindings project on Trolltech Labs." << endl
1399 << "**" << endl
1400 << "** This file may be used under the terms of the GNU General Public" << endl
1401 << "** License version 2.0 as published by the Free Software Foundation" << endl
1402 << "** and appearing in the file LICENSE.GPL included in the packaging of" << endl
1403 << "** this file. Please review the following information to ensure GNU" << endl
1404 << "** General Public Licensing requirements will be met:" << endl
1405 << "** http://www.trolltech.com/products/qt/opensource.html" << endl
1406 << "**" << endl
1407 << "** If you are unsure which license is appropriate for your use, please" << endl
1408 << "** review the following information:" << endl
1409 << "** http://www.trolltech.com/products/qt/licensing.html or contact the" << endl
1410 << "** sales department at sales@trolltech.com." << endl
1411 << "**" << endl
1412 << "** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE" << endl
1413 << "** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE." << endl
1414 << "**" << endl
1415 << "****************************************************************************/" << endl
1416 << endl;
1417 }
1418
1391
1419 /*!
1392 /*!
1420 Finds the functions in \a meta_class that we actually want to
1393 Finds the functions in \a meta_class that we actually want to
1421 generate bindings for.
1394 generate bindings for.
1422 */
1395 */
1423 void findPrototypeAndStaticFunctions(
1396 void findPrototypeAndStaticFunctions(
1424 const AbstractMetaClass *meta_class,
1397 const AbstractMetaClass *meta_class,
1425 QMap<QString, AbstractMetaFunctionList> &nameToPrototypeFunctions,
1398 QMap<QString, AbstractMetaFunctionList> &nameToPrototypeFunctions,
1426 QMap<QString, AbstractMetaFunctionList> &nameToStaticFunctions)
1399 QMap<QString, AbstractMetaFunctionList> &nameToStaticFunctions)
1427 {
1400 {
1428 AbstractMetaFunctionList functions = meta_class->functionsInTargetLang();
1401 AbstractMetaFunctionList functions = meta_class->functionsInTargetLang();
1429 for (int i = 0; i < functions.size(); ++i) {
1402 for (int i = 0; i < functions.size(); ++i) {
1430 AbstractMetaFunction* func = functions.at(i);
1403 AbstractMetaFunction* func = functions.at(i);
1431 if (!func->isNormal())
1404 if (!func->isNormal())
1432 continue;
1405 continue;
1433 #ifdef GENERATOR_NO_PROTECTED_FUNCTIONS
1406 #ifdef GENERATOR_NO_PROTECTED_FUNCTIONS
1434 if (func->wasProtected())
1407 if (func->wasProtected())
1435 continue;
1408 continue;
1436 #endif
1409 #endif
1437 if (func->declaringClass() != meta_class)
1410 if (func->declaringClass() != meta_class)
1438 continue; // function inherited through prototype
1411 continue; // function inherited through prototype
1439 if (func->isPropertyReader() || func->isPropertyWriter())
1412 if (func->isPropertyReader() || func->isPropertyWriter())
1440 continue; // no point in including property accessors
1413 continue; // no point in including property accessors
1441 if (func->isSlot() || func->isSignal() || func->isInvokable())
1414 if (func->isSlot() || func->isSignal() || func->isInvokable())
1442 continue; // no point in including signals and slots
1415 continue; // no point in including signals and slots
1443 QMap<QString, AbstractMetaFunctionList> &map =
1416 QMap<QString, AbstractMetaFunctionList> &map =
1444 func->isStatic() ? nameToStaticFunctions : nameToPrototypeFunctions;
1417 func->isStatic() ? nameToStaticFunctions : nameToPrototypeFunctions;
1445 map[func->modifiedName()].append(func);
1418 map[func->modifiedName()].append(func);
1446 }
1419 }
1447 }
1420 }
1448
1421
1449 static void writeFunctionSignaturesString(QTextStream &s, const AbstractMetaFunctionList &functions)
1422 static void writeFunctionSignaturesString(QTextStream &s, const AbstractMetaFunctionList &functions)
1450 {
1423 {
1451 s << "\"";
1424 s << "\"";
1452 for (int i = 0; i < functions.size(); ++i) {
1425 for (int i = 0; i < functions.size(); ++i) {
1453 if (i > 0)
1426 if (i > 0)
1454 s << "\\n";
1427 s << "\\n";
1455 QString sig = functions.at(i)->targetLangSignature();
1428 QString sig = functions.at(i)->targetLangSignature();
1456 sig = sig.mid(sig.indexOf('(') + 1);
1429 sig = sig.mid(sig.indexOf('(') + 1);
1457 sig.chop(1);
1430 sig.chop(1);
1458 s << sig;
1431 s << sig;
1459 }
1432 }
1460 s << "\"";
1433 s << "\"";
1461 }
1434 }
1462
1435
1463 /*!
1436 /*!
1464 Writes the whole native binding for the class \a meta_class.
1437 Writes the whole native binding for the class \a meta_class.
1465 */
1438 */
1466 void ClassGenerator::write(QTextStream &stream, const AbstractMetaClass *meta_class)
1439 void ClassGenerator::write(QTextStream &stream, const AbstractMetaClass *meta_class)
1467 {
1440 {
1468 if (FileOut::license)
1469 writeQtScriptQtBindingsLicense(stream);
1470
1471 // write common includes
1441 // write common includes
1472 stream << "#include <QtScript/QScriptEngine>" << endl;
1442 stream << "#include <QtScript/QScriptEngine>" << endl;
1473 stream << "#include <QtScript/QScriptContext>" << endl;
1443 stream << "#include <QtScript/QScriptContext>" << endl;
1474 stream << "#include <QtScript/QScriptValue>" << endl;
1444 stream << "#include <QtScript/QScriptValue>" << endl;
1475 stream << "#include <QtCore/QStringList>" << endl;
1445 stream << "#include <QtCore/QStringList>" << endl;
1476 stream << "#include <QtCore/QDebug>" << endl;
1446 stream << "#include <QtCore/QDebug>" << endl;
1477 stream << "#include <qmetaobject.h>" << endl;
1447 stream << "#include <qmetaobject.h>" << endl;
1478 stream << endl;
1448 stream << endl;
1479
1449
1480 // write class-specific includes
1450 // write class-specific includes
1481 {
1451 {
1482 Include inc = meta_class->typeEntry()->include();
1452 Include inc = meta_class->typeEntry()->include();
1483 writeInclude(stream, inc);
1453 writeInclude(stream, inc);
1484 }
1454 }
1485 {
1455 {
1486 IncludeList includes = meta_class->typeEntry()->extraIncludes();
1456 IncludeList includes = meta_class->typeEntry()->extraIncludes();
1487 qSort(includes.begin(), includes.end());
1457 qSort(includes.begin(), includes.end());
1488
1458
1489 foreach (const Include &i, includes) {
1459 foreach (const Include &i, includes) {
1490 writeInclude(stream, i);
1460 writeInclude(stream, i);
1491 }
1461 }
1492 }
1462 }
1493 stream << endl;
1463 stream << endl;
1494
1464
1495 if (meta_class->generateShellClass()) {
1465 if (meta_class->generateShellClass()) {
1496 stream << "#include \"qtscriptshell_" << meta_class->name() << ".h\"" << endl;
1466 stream << "#include \"qtscriptshell_" << meta_class->name() << ".h\"" << endl;
1497 stream << endl;
1467 stream << endl;
1498 }
1468 }
1499
1469
1500 AbstractMetaEnumList enums = meta_class->enums();
1470 AbstractMetaEnumList enums = meta_class->enums();
1501 {
1471 {
1502 // kill the enums we don't care about
1472 // kill the enums we don't care about
1503 AbstractMetaEnumList::iterator it;
1473 AbstractMetaEnumList::iterator it;
1504 for (it = enums.begin(); it != enums.end(); ) {
1474 for (it = enums.begin(); it != enums.end(); ) {
1505 if (shouldIgnoreEnum(*it))
1475 if (shouldIgnoreEnum(*it))
1506 it = enums.erase(it);
1476 it = enums.erase(it);
1507 else
1477 else
1508 ++it;
1478 ++it;
1509 }
1479 }
1510 }
1480 }
1511
1481
1512 if (meta_class->isNamespace() || meta_class->name() == "Global") {
1482 if (meta_class->isNamespace() || meta_class->name() == "Global") {
1513 QMap<QString, Include> includes;
1483 QMap<QString, Include> includes;
1514 foreach (AbstractMetaEnum *enom, enums) {
1484 foreach (AbstractMetaEnum *enom, enums) {
1515 Include include = enom->typeEntry()->include();
1485 Include include = enom->typeEntry()->include();
1516 includes.insert(include.toString(), include);
1486 includes.insert(include.toString(), include);
1517 }
1487 }
1518
1488
1519 foreach (const Include &i, includes) {
1489 foreach (const Include &i, includes) {
1520 writeInclude(stream, i);
1490 writeInclude(stream, i);
1521 }
1491 }
1522
1492
1523 stream << endl;
1493 stream << endl;
1524 }
1494 }
1525
1495
1526 if (meta_class->name() == "Global") {
1496 if (meta_class->name() == "Global") {
1527 stream << "class Global {};" << endl;
1497 stream << "class Global {};" << endl;
1528 stream << endl;
1498 stream << endl;
1529 }
1499 }
1530
1500
1531 // find constructors
1501 // find constructors
1532 AbstractMetaFunctionList ctors = findConstructors(meta_class);
1502 AbstractMetaFunctionList ctors = findConstructors(meta_class);
1533 bool hasDefaultCtor = findDefaultConstructor(ctors) != 0;
1503 bool hasDefaultCtor = findDefaultConstructor(ctors) != 0;
1534
1504
1535 // find interesting functions
1505 // find interesting functions
1536 QMap<QString, AbstractMetaFunctionList> nameToPrototypeFunctions;
1506 QMap<QString, AbstractMetaFunctionList> nameToPrototypeFunctions;
1537 QMap<QString, AbstractMetaFunctionList> nameToStaticFunctions;
1507 QMap<QString, AbstractMetaFunctionList> nameToStaticFunctions;
1538 findPrototypeAndStaticFunctions(meta_class, nameToPrototypeFunctions, nameToStaticFunctions);
1508 findPrototypeAndStaticFunctions(meta_class, nameToPrototypeFunctions, nameToStaticFunctions);
1539
1509
1540 int staticFunctionsOffset = 1;
1510 int staticFunctionsOffset = 1;
1541 int prototypeFunctionsOffset = staticFunctionsOffset + nameToStaticFunctions.size();
1511 int prototypeFunctionsOffset = staticFunctionsOffset + nameToStaticFunctions.size();
1542
1512
1543 // write table of function names
1513 // write table of function names
1544 stream << "static const char * const qtscript_"
1514 stream << "static const char * const qtscript_"
1545 << meta_class->name() << "_function_names[] = {" << endl;
1515 << meta_class->name() << "_function_names[] = {" << endl;
1546 stream << " \"" << meta_class->name() << "\"" << endl;
1516 stream << " \"" << meta_class->name() << "\"" << endl;
1547 {
1517 {
1548 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1518 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1549 stream << " // static" << endl;
1519 stream << " // static" << endl;
1550 for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
1520 for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
1551 stream << " , ";
1521 stream << " , ";
1552 stream << "\"" << it.key() << "\"" << endl;
1522 stream << "\"" << it.key() << "\"" << endl;
1553 }
1523 }
1554 stream << " // prototype" << endl;
1524 stream << " // prototype" << endl;
1555 for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
1525 for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
1556 QString functionName = it.key();
1526 QString functionName = it.key();
1557 QString scriptName = functionName;
1527 QString scriptName = functionName;
1558 if (functionName == QLatin1String("operator_equal"))
1528 if (functionName == QLatin1String("operator_equal"))
1559 scriptName = QLatin1String("equals");
1529 scriptName = QLatin1String("equals");
1560 stream << " , ";
1530 stream << " , ";
1561 stream << "\"" << scriptName << "\"" << endl;
1531 stream << "\"" << scriptName << "\"" << endl;
1562 }
1532 }
1563 if (!meta_class->hasDefaultToStringFunction())
1533 if (!meta_class->hasDefaultToStringFunction())
1564 stream << " , \"toString\"" << endl;
1534 stream << " , \"toString\"" << endl;
1565 }
1535 }
1566 stream << "};" << endl << endl;
1536 stream << "};" << endl << endl;
1567
1537
1568 // write table of function signatures
1538 // write table of function signatures
1569 stream << "static const char * const qtscript_"
1539 stream << "static const char * const qtscript_"
1570 << meta_class->name() << "_function_signatures[] = {" << endl;
1540 << meta_class->name() << "_function_signatures[] = {" << endl;
1571 stream << " ";
1541 stream << " ";
1572 writeFunctionSignaturesString(stream, ctors);
1542 writeFunctionSignaturesString(stream, ctors);
1573 stream << endl;
1543 stream << endl;
1574 {
1544 {
1575 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1545 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1576 stream << " // static" << endl;
1546 stream << " // static" << endl;
1577 for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
1547 for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
1578 stream << " , ";
1548 stream << " , ";
1579 writeFunctionSignaturesString(stream, it.value());
1549 writeFunctionSignaturesString(stream, it.value());
1580 stream << endl;
1550 stream << endl;
1581 }
1551 }
1582 stream << " // prototype" << endl;
1552 stream << " // prototype" << endl;
1583 for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
1553 for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
1584 stream << " , ";
1554 stream << " , ";
1585 writeFunctionSignaturesString(stream, it.value());
1555 writeFunctionSignaturesString(stream, it.value());
1586 stream << endl;
1556 stream << endl;
1587 }
1557 }
1588 if (!meta_class->hasDefaultToStringFunction())
1558 if (!meta_class->hasDefaultToStringFunction())
1589 stream << "\"\"" << endl;
1559 stream << "\"\"" << endl;
1590 }
1560 }
1591 stream << "};" << endl << endl;
1561 stream << "};" << endl << endl;
1592
1562
1593 // write table of function lengths
1563 // write table of function lengths
1594 stream << "static const int qtscript_" << meta_class->name() << "_function_lengths[] = {" << endl;
1564 stream << "static const int qtscript_" << meta_class->name() << "_function_lengths[] = {" << endl;
1595 stream << " " << maxFunctionLength(ctors) << endl;
1565 stream << " " << maxFunctionLength(ctors) << endl;
1596 {
1566 {
1597 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1567 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1598 stream << " // static" << endl;
1568 stream << " // static" << endl;
1599 for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
1569 for (it = nameToStaticFunctions.constBegin(); it != nameToStaticFunctions.constEnd(); ++it) {
1600 stream << " , " << maxFunctionLength(it.value()) << endl;
1570 stream << " , " << maxFunctionLength(it.value()) << endl;
1601 }
1571 }
1602 stream << " // prototype" << endl;
1572 stream << " // prototype" << endl;
1603 for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
1573 for (it = nameToPrototypeFunctions.constBegin(); it != nameToPrototypeFunctions.constEnd(); ++it) {
1604 stream << " , " << maxFunctionLength(it.value()) << endl;
1574 stream << " , " << maxFunctionLength(it.value()) << endl;
1605 }
1575 }
1606 if (!meta_class->hasDefaultToStringFunction())
1576 if (!meta_class->hasDefaultToStringFunction())
1607 stream << " , 0" << endl;
1577 stream << " , 0" << endl;
1608 }
1578 }
1609 stream << "};" << endl << endl;
1579 stream << "};" << endl << endl;
1610
1580
1611 #ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
1581 #ifndef GENERATOR_NO_PROTECTED_FUNCTIONS
1612 if (meta_class->hasProtectedFunctions()) {
1582 if (meta_class->hasProtectedFunctions()) {
1613 // write a friendly class
1583 // write a friendly class
1614 stream << "class qtscript_" << meta_class->name()
1584 stream << "class qtscript_" << meta_class->name()
1615 << " : public " << meta_class->qualifiedCppName() << endl;
1585 << " : public " << meta_class->qualifiedCppName() << endl;
1616 stream << "{" << endl;
1586 stream << "{" << endl;
1617 for (int x = 0; x < 2; ++x) {
1587 for (int x = 0; x < 2; ++x) {
1618 QMap<QString, AbstractMetaFunctionList> &map =
1588 QMap<QString, AbstractMetaFunctionList> &map =
1619 x ? nameToStaticFunctions : nameToPrototypeFunctions;
1589 x ? nameToStaticFunctions : nameToPrototypeFunctions;
1620 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1590 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1621 for (it = map.constBegin(); it != map.constEnd(); ++it) {
1591 for (it = map.constBegin(); it != map.constEnd(); ++it) {
1622 AbstractMetaFunctionList functions = it.value();
1592 AbstractMetaFunctionList functions = it.value();
1623 for (int i = 0; i < functions.size(); ++i) {
1593 for (int i = 0; i < functions.size(); ++i) {
1624 if (functions.at(i)->isProtected()) {
1594 if (functions.at(i)->isProtected()) {
1625 stream << " friend QScriptValue qtscript_" << meta_class->name()
1595 stream << " friend QScriptValue qtscript_" << meta_class->name()
1626 << "_" << it.key();
1596 << "_" << it.key();
1627 if (functions.at(i)->isStatic())
1597 if (functions.at(i)->isStatic())
1628 stream << "_static";
1598 stream << "_static";
1629 stream << "(QScriptContext *, QScriptEngine *);" << endl;
1599 stream << "(QScriptContext *, QScriptEngine *);" << endl;
1630 break;
1600 break;
1631 }
1601 }
1632 }
1602 }
1633 }
1603 }
1634 }
1604 }
1635 stream << "};" << endl;
1605 stream << "};" << endl;
1636 stream << endl;
1606 stream << endl;
1637 }
1607 }
1638 #endif
1608 #endif
1639
1609
1640 writeHelperFunctions(stream, meta_class);
1610 writeHelperFunctions(stream, meta_class);
1641
1611
1642 // write metaobject getter if we need it
1612 // write metaobject getter if we need it
1643 if (hasQEnums(enums) && (meta_class->qualifiedCppName() != "QTransform")) {
1613 if (hasQEnums(enums) && (meta_class->qualifiedCppName() != "QTransform")) {
1644 if (meta_class->qualifiedCppName() == "Qt") {
1614 if (meta_class->qualifiedCppName() == "Qt") {
1645 stream << "struct qtscript_Qt_metaObject_helper : private QObject" << endl
1615 stream << "struct qtscript_Qt_metaObject_helper : private QObject" << endl
1646 << "{" << endl
1616 << "{" << endl
1647 << " static const QMetaObject *get()" << endl
1617 << " static const QMetaObject *get()" << endl
1648 << " { return &static_cast<qtscript_Qt_metaObject_helper*>(0)->staticQtMetaObject; }" << endl
1618 << " { return &static_cast<qtscript_Qt_metaObject_helper*>(0)->staticQtMetaObject; }" << endl
1649 << "};" << endl << endl;
1619 << "};" << endl << endl;
1650 }
1620 }
1651 stream << "static const QMetaObject *qtscript_" << meta_class->name() << "_metaObject()" << endl
1621 stream << "static const QMetaObject *qtscript_" << meta_class->name() << "_metaObject()" << endl
1652 << "{" << endl
1622 << "{" << endl
1653 << " return ";
1623 << " return ";
1654 if (meta_class->qualifiedCppName() == "Qt")
1624 if (meta_class->qualifiedCppName() == "Qt")
1655 stream << "qtscript_Qt_metaObject_helper::get()";
1625 stream << "qtscript_Qt_metaObject_helper::get()";
1656 else
1626 else
1657 stream << "&" << meta_class->qualifiedCppName() << "::staticMetaObject";
1627 stream << "&" << meta_class->qualifiedCppName() << "::staticMetaObject";
1658 stream << ";" << endl
1628 stream << ";" << endl
1659 << "}" << endl << endl;
1629 << "}" << endl << endl;
1660 }
1630 }
1661
1631
1662 // write metatype declarations
1632 // write metatype declarations
1663 {
1633 {
1664 QSet<QString> registeredTypeNames = m_qmetatype_declared_typenames;
1634 QSet<QString> registeredTypeNames = m_qmetatype_declared_typenames;
1665
1635
1666 if (!meta_class->isNamespace()) {
1636 if (!meta_class->isNamespace()) {
1667 if (meta_class->typeEntry()->isValue() && hasDefaultCtor)
1637 if (meta_class->typeEntry()->isValue() && hasDefaultCtor)
1668 maybeDeclareMetaType(stream, meta_class->qualifiedCppName(), registeredTypeNames);
1638 maybeDeclareMetaType(stream, meta_class->qualifiedCppName(), registeredTypeNames);
1669 else
1639 else
1670 registeredTypeNames << meta_class->qualifiedCppName();
1640 registeredTypeNames << meta_class->qualifiedCppName();
1671 maybeDeclareMetaType(stream, meta_class->qualifiedCppName() + "*", registeredTypeNames);
1641 maybeDeclareMetaType(stream, meta_class->qualifiedCppName() + "*", registeredTypeNames);
1672 }
1642 }
1673 if (meta_class->generateShellClass()) {
1643 if (meta_class->generateShellClass()) {
1674 if (meta_class->typeEntry()->isValue()) {
1644 if (meta_class->typeEntry()->isValue()) {
1675 maybeDeclareMetaType(stream, "QtScriptShell_" + meta_class->name(),
1645 maybeDeclareMetaType(stream, "QtScriptShell_" + meta_class->name(),
1676 registeredTypeNames);
1646 registeredTypeNames);
1677 }
1647 }
1678 maybeDeclareMetaType(stream, "QtScriptShell_" + meta_class->name() + "*",
1648 maybeDeclareMetaType(stream, "QtScriptShell_" + meta_class->name() + "*",
1679 registeredTypeNames);
1649 registeredTypeNames);
1680 }
1650 }
1681
1651
1682 declareEnumMetaTypes(stream, meta_class, registeredTypeNames);
1652 declareEnumMetaTypes(stream, meta_class, registeredTypeNames);
1683
1653
1684 for (int x = 0; x < 2; ++x) {
1654 for (int x = 0; x < 2; ++x) {
1685 QMap<QString, AbstractMetaFunctionList> &map =
1655 QMap<QString, AbstractMetaFunctionList> &map =
1686 x ? nameToStaticFunctions : nameToPrototypeFunctions;
1656 x ? nameToStaticFunctions : nameToPrototypeFunctions;
1687 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1657 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1688 for (it = map.constBegin(); it != map.constEnd(); ++it) {
1658 for (it = map.constBegin(); it != map.constEnd(); ++it) {
1689 declareFunctionMetaTypes(stream, it.value(), registeredTypeNames);
1659 declareFunctionMetaTypes(stream, it.value(), registeredTypeNames);
1690 }
1660 }
1691 }
1661 }
1692
1662
1693 declareFunctionMetaTypes(stream, ctors, registeredTypeNames);
1663 declareFunctionMetaTypes(stream, ctors, registeredTypeNames);
1694
1664
1695 if (meta_class->baseClass() != 0) {
1665 if (meta_class->baseClass() != 0) {
1696 maybeDeclareMetaType(stream, meta_class->baseClass()->qualifiedCppName()
1666 maybeDeclareMetaType(stream, meta_class->baseClass()->qualifiedCppName()
1697 + QLatin1String("*"), registeredTypeNames);
1667 + QLatin1String("*"), registeredTypeNames);
1698 }
1668 }
1699 foreach (AbstractMetaClass *iface, meta_class->interfaces()) {
1669 foreach (AbstractMetaClass *iface, meta_class->interfaces()) {
1700 AbstractMetaClass *impl = iface->primaryInterfaceImplementor();
1670 AbstractMetaClass *impl = iface->primaryInterfaceImplementor();
1701 maybeDeclareMetaType(stream, impl->qualifiedCppName() + QLatin1String("*"),
1671 maybeDeclareMetaType(stream, impl->qualifiedCppName() + QLatin1String("*"),
1702 registeredTypeNames);
1672 registeredTypeNames);
1703 }
1673 }
1704
1674
1705 // ### hackety hack
1675 // ### hackety hack
1706 if (meta_class->name().endsWith("Gradient"))
1676 if (meta_class->name().endsWith("Gradient"))
1707 maybeDeclareMetaType(stream, "QGradient", registeredTypeNames);
1677 maybeDeclareMetaType(stream, "QGradient", registeredTypeNames);
1708
1678
1709 stream << endl;
1679 stream << endl;
1710 }
1680 }
1711
1681
1712 writeInjectedCode(stream, meta_class, CodeSnip::Beginning);
1682 writeInjectedCode(stream, meta_class, CodeSnip::Beginning);
1713
1683
1714 // write enum classes
1684 // write enum classes
1715 if (!enums.isEmpty()) {
1685 if (!enums.isEmpty()) {
1716 writeCreateEnumClassHelper(stream);
1686 writeCreateEnumClassHelper(stream);
1717 if (hasFlags(enums))
1687 if (hasFlags(enums))
1718 writeCreateFlagsClassHelper(stream);
1688 writeCreateFlagsClassHelper(stream);
1719
1689
1720 for (int i = 0; i < enums.size(); ++i) {
1690 for (int i = 0; i < enums.size(); ++i) {
1721 const AbstractMetaEnum *enom = enums.at(i);
1691 const AbstractMetaEnum *enom = enums.at(i);
1722 writeEnumClass(stream, meta_class, enom);
1692 writeEnumClass(stream, meta_class, enom);
1723 }
1693 }
1724 }
1694 }
1725
1695
1726 stream << "//" << endl;
1696 stream << "//" << endl;
1727 stream << "// " << meta_class->name() << endl;
1697 stream << "// " << meta_class->name() << endl;
1728 stream << "//" << endl << endl;
1698 stream << "//" << endl << endl;
1729
1699
1730 if (!meta_class->isNamespace()) {
1700 if (!meta_class->isNamespace()) {
1731 if (!nameToPrototypeFunctions.isEmpty() || !meta_class->hasDefaultToStringFunction())
1701 if (!nameToPrototypeFunctions.isEmpty() || !meta_class->hasDefaultToStringFunction())
1732 writePrototypeCall(stream, meta_class, nameToPrototypeFunctions, prototypeFunctionsOffset);
1702 writePrototypeCall(stream, meta_class, nameToPrototypeFunctions, prototypeFunctionsOffset);
1733 }
1703 }
1734
1704
1735 writeStaticCall(stream, meta_class, ctors, nameToStaticFunctions);
1705 writeStaticCall(stream, meta_class, ctors, nameToStaticFunctions);
1736
1706
1737 if (isQObjectBased(meta_class)) {
1707 if (isQObjectBased(meta_class)) {
1738 // write C++ <--> script conversion functions
1708 // write C++ <--> script conversion functions
1739 stream << "static QScriptValue qtscript_" << meta_class->name() << "_toScriptValue(QScriptEngine *engine, "
1709 stream << "static QScriptValue qtscript_" << meta_class->name() << "_toScriptValue(QScriptEngine *engine, "
1740 << meta_class->qualifiedCppName() << "* const &in)" << endl
1710 << meta_class->qualifiedCppName() << "* const &in)" << endl
1741 << "{" << endl
1711 << "{" << endl
1742 << " return engine->newQObject(in, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);" << endl
1712 << " return engine->newQObject(in, QScriptEngine::QtOwnership, QScriptEngine::PreferExistingWrapperObject);" << endl
1743 << "}" << endl << endl;
1713 << "}" << endl << endl;
1744 stream << "static void qtscript_" << meta_class->name() << "_fromScriptValue(const QScriptValue &value, "
1714 stream << "static void qtscript_" << meta_class->name() << "_fromScriptValue(const QScriptValue &value, "
1745 << meta_class->qualifiedCppName() << "* &out)" << endl
1715 << meta_class->qualifiedCppName() << "* &out)" << endl
1746 << "{" << endl
1716 << "{" << endl
1747 << " out = qobject_cast<" << meta_class->qualifiedCppName() << "*>(value.toQObject());" << endl
1717 << " out = qobject_cast<" << meta_class->qualifiedCppName() << "*>(value.toQObject());" << endl
1748 << "}" << endl << endl;
1718 << "}" << endl << endl;
1749 }
1719 }
1750
1720
1751 //
1721 //
1752 // write exported function that creates the QtScript class
1722 // write exported function that creates the QtScript class
1753 //
1723 //
1754 stream << "QScriptValue qtscript_create_" << meta_class->name()
1724 stream << "QScriptValue qtscript_create_" << meta_class->name()
1755 << "_class(QScriptEngine *engine)" << endl;
1725 << "_class(QScriptEngine *engine)" << endl;
1756 stream << "{" << endl;
1726 stream << "{" << endl;
1757
1727
1758 // setup prototype
1728 // setup prototype
1759 if (!meta_class->isNamespace()) {
1729 if (!meta_class->isNamespace()) {
1760 stream << " engine->setDefaultPrototype(qMetaTypeId<"
1730 stream << " engine->setDefaultPrototype(qMetaTypeId<"
1761 << meta_class->qualifiedCppName() << "*>(), QScriptValue());" << endl;
1731 << meta_class->qualifiedCppName() << "*>(), QScriptValue());" << endl;
1762 stream << " QScriptValue proto = engine->newVariant(qVariantFromValue(("
1732 stream << " QScriptValue proto = engine->newVariant(qVariantFromValue(("
1763 << meta_class->qualifiedCppName() << "*)0));" << endl;
1733 << meta_class->qualifiedCppName() << "*)0));" << endl;
1764 bool havePrototypePrototype = false;
1734 bool havePrototypePrototype = false;
1765 if (meta_class->baseClass() != 0) {
1735 if (meta_class->baseClass() != 0) {
1766 stream << " proto.setPrototype(engine->defaultPrototype(qMetaTypeId<"
1736 stream << " proto.setPrototype(engine->defaultPrototype(qMetaTypeId<"
1767 << meta_class->baseClass()->qualifiedCppName() << "*>()));" << endl;
1737 << meta_class->baseClass()->qualifiedCppName() << "*>()));" << endl;
1768 havePrototypePrototype = true;
1738 havePrototypePrototype = true;
1769 }
1739 }
1770 foreach (AbstractMetaClass *iface, meta_class->interfaces()) {
1740 foreach (AbstractMetaClass *iface, meta_class->interfaces()) {
1771 AbstractMetaClass *impl = iface->primaryInterfaceImplementor();
1741 AbstractMetaClass *impl = iface->primaryInterfaceImplementor();
1772 if (impl == meta_class)
1742 if (impl == meta_class)
1773 continue;
1743 continue;
1774 if (!havePrototypePrototype) {
1744 if (!havePrototypePrototype) {
1775 stream << " proto.setPrototype(engine->defaultPrototype(qMetaTypeId<"
1745 stream << " proto.setPrototype(engine->defaultPrototype(qMetaTypeId<"
1776 << impl->qualifiedCppName() << "*>()));" << endl;
1746 << impl->qualifiedCppName() << "*>()));" << endl;
1777 havePrototypePrototype = true;
1747 havePrototypePrototype = true;
1778 } else {
1748 } else {
1779 // alternative would be to copy the properties from the secondary
1749 // alternative would be to copy the properties from the secondary
1780 // prototype to the primary prototype.
1750 // prototype to the primary prototype.
1781 stream << " proto.setProperty(QString::fromLatin1(\"__"
1751 stream << " proto.setProperty(QString::fromLatin1(\"__"
1782 << impl->name() << "__\")," << endl
1752 << impl->name() << "__\")," << endl
1783 << " engine->defaultPrototype(qMetaTypeId<"
1753 << " engine->defaultPrototype(qMetaTypeId<"
1784 << impl->qualifiedCppName() << "*>())," << endl
1754 << impl->qualifiedCppName() << "*>())," << endl
1785 << " QScriptValue::SkipInEnumeration);" << endl;
1755 << " QScriptValue::SkipInEnumeration);" << endl;
1786 }
1756 }
1787 }
1757 }
1788 if (!nameToPrototypeFunctions.isEmpty()) {
1758 if (!nameToPrototypeFunctions.isEmpty()) {
1789 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1759 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1790 int count = nameToPrototypeFunctions.size();
1760 int count = nameToPrototypeFunctions.size();
1791 if (!meta_class->hasDefaultToStringFunction())
1761 if (!meta_class->hasDefaultToStringFunction())
1792 ++count;
1762 ++count;
1793 stream << " for (int i = 0; i < " << count << "; ++i) {" << endl
1763 stream << " for (int i = 0; i < " << count << "; ++i) {" << endl
1794 << " QScriptValue fun = engine->newFunction(qtscript_"
1764 << " QScriptValue fun = engine->newFunction(qtscript_"
1795 << meta_class->name() << "_prototype_call, qtscript_"
1765 << meta_class->name() << "_prototype_call, qtscript_"
1796 << meta_class->name() << "_function_lengths[i+"
1766 << meta_class->name() << "_function_lengths[i+"
1797 << prototypeFunctionsOffset << "]);" << endl
1767 << prototypeFunctionsOffset << "]);" << endl
1798 << " fun.setData(QScriptValue(engine, uint(0xBABE0000 + i)));" << endl
1768 << " fun.setData(QScriptValue(engine, uint(0xBABE0000 + i)));" << endl
1799 << " proto.setProperty(QString::fromLatin1(qtscript_"
1769 << " proto.setProperty(QString::fromLatin1(qtscript_"
1800 << meta_class->name() << "_function_names[i+" << prototypeFunctionsOffset << "])," << endl
1770 << meta_class->name() << "_function_names[i+" << prototypeFunctionsOffset << "])," << endl
1801 << " fun, QScriptValue::SkipInEnumeration);" << endl
1771 << " fun, QScriptValue::SkipInEnumeration);" << endl
1802 << " }" << endl;
1772 << " }" << endl;
1803 }
1773 }
1804 writeInjectedCode(stream, meta_class, CodeSnip::PrototypeInitialization);
1774 writeInjectedCode(stream, meta_class, CodeSnip::PrototypeInitialization);
1805 stream << endl;
1775 stream << endl;
1806
1776
1807 // register the prototype
1777 // register the prototype
1808 // stream << " qDebug() << \"registering " << meta_class->name() << " prototype\";" << endl;
1778 // stream << " qDebug() << \"registering " << meta_class->name() << " prototype\";" << endl;
1809 if (meta_class->typeEntry()->isValue() && hasDefaultCtor) {
1779 if (meta_class->typeEntry()->isValue() && hasDefaultCtor) {
1810 stream << " engine->setDefaultPrototype(qMetaTypeId<"
1780 stream << " engine->setDefaultPrototype(qMetaTypeId<"
1811 << meta_class->qualifiedCppName() << ">(), proto);" << endl;
1781 << meta_class->qualifiedCppName() << ">(), proto);" << endl;
1812 }
1782 }
1813 if (isQObjectBased(meta_class)) {
1783 if (isQObjectBased(meta_class)) {
1814 stream << " qScriptRegisterMetaType<" << meta_class->qualifiedCppName() << "*>(engine, qtscript_"
1784 stream << " qScriptRegisterMetaType<" << meta_class->qualifiedCppName() << "*>(engine, qtscript_"
1815 << meta_class->name() << "_toScriptValue, " << endl << " qtscript_"
1785 << meta_class->name() << "_toScriptValue, " << endl << " qtscript_"
1816 << meta_class->name() << "_fromScriptValue, proto);" << endl;
1786 << meta_class->name() << "_fromScriptValue, proto);" << endl;
1817 } else {
1787 } else {
1818 stream << " engine->setDefaultPrototype(qMetaTypeId<"
1788 stream << " engine->setDefaultPrototype(qMetaTypeId<"
1819 << meta_class->qualifiedCppName() << "*>(), proto);" << endl;
1789 << meta_class->qualifiedCppName() << "*>(), proto);" << endl;
1820 }
1790 }
1821 stream << endl;
1791 stream << endl;
1822 } else {
1792 } else {
1823 stream << " QScriptValue proto = QScriptValue();" << endl;
1793 stream << " QScriptValue proto = QScriptValue();" << endl;
1824 }
1794 }
1825
1795
1826 // setup constructor
1796 // setup constructor
1827 stream << " QScriptValue ctor = engine->newFunction(qtscript_" << meta_class->name()
1797 stream << " QScriptValue ctor = engine->newFunction(qtscript_" << meta_class->name()
1828 << "_static_call, proto, qtscript_" << meta_class->name() << "_function_lengths[0]);" << endl;
1798 << "_static_call, proto, qtscript_" << meta_class->name() << "_function_lengths[0]);" << endl;
1829 stream << " ctor.setData(QScriptValue(engine, uint(0xBABE0000 + 0)));" << endl;
1799 stream << " ctor.setData(QScriptValue(engine, uint(0xBABE0000 + 0)));" << endl;
1830 if (!nameToStaticFunctions.isEmpty()) {
1800 if (!nameToStaticFunctions.isEmpty()) {
1831 // static functions
1801 // static functions
1832 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1802 QMap<QString, AbstractMetaFunctionList>::const_iterator it;
1833 stream << " for (int i = 0; i < " << nameToStaticFunctions.size() << "; ++i) {" << endl
1803 stream << " for (int i = 0; i < " << nameToStaticFunctions.size() << "; ++i) {" << endl
1834 << " QScriptValue fun = engine->newFunction(qtscript_" << meta_class->name()
1804 << " QScriptValue fun = engine->newFunction(qtscript_" << meta_class->name()
1835 << "_static_call," << endl
1805 << "_static_call," << endl
1836 << " qtscript_" << meta_class->name() << "_function_lengths[i+" << staticFunctionsOffset << "]);" << endl
1806 << " qtscript_" << meta_class->name() << "_function_lengths[i+" << staticFunctionsOffset << "]);" << endl
1837 << " fun.setData(QScriptValue(engine, uint(0xBABE0000 + i+1)));" << endl
1807 << " fun.setData(QScriptValue(engine, uint(0xBABE0000 + i+1)));" << endl
1838 << " ctor.setProperty(QString::fromLatin1(qtscript_"
1808 << " ctor.setProperty(QString::fromLatin1(qtscript_"
1839 << meta_class->name() << "_function_names[i+" << staticFunctionsOffset << "])," << endl
1809 << meta_class->name() << "_function_names[i+" << staticFunctionsOffset << "])," << endl
1840 << " fun, QScriptValue::SkipInEnumeration);" << endl
1810 << " fun, QScriptValue::SkipInEnumeration);" << endl
1841 << " }" << endl;
1811 << " }" << endl;
1842 }
1812 }
1843 stream << endl;
1813 stream << endl;
1844 // enums and flags classes
1814 // enums and flags classes
1845 {
1815 {
1846 for (int i = 0; i < enums.size(); ++i) {
1816 for (int i = 0; i < enums.size(); ++i) {
1847 const AbstractMetaEnum *enom = enums.at(i);
1817 const AbstractMetaEnum *enom = enums.at(i);
1848 stream << " ctor.setProperty(QString::fromLatin1(\""
1818 stream << " ctor.setProperty(QString::fromLatin1(\""
1849 << enom->name() << "\")," << endl
1819 << enom->name() << "\")," << endl
1850 << " qtscript_create_" << meta_class->name()
1820 << " qtscript_create_" << meta_class->name()
1851 << "_" << enom->name() << "_class(engine, ctor));" << endl;
1821 << "_" << enom->name() << "_class(engine, ctor));" << endl;
1852 FlagsTypeEntry *flags = enom->typeEntry()->flags();
1822 FlagsTypeEntry *flags = enom->typeEntry()->flags();
1853 if (flags) {
1823 if (flags) {
1854 stream << " ctor.setProperty(QString::fromLatin1(\""
1824 stream << " ctor.setProperty(QString::fromLatin1(\""
1855 << flags->targetLangName() << "\")," << endl
1825 << flags->targetLangName() << "\")," << endl
1856 << " qtscript_create_" << meta_class->name()
1826 << " qtscript_create_" << meta_class->name()
1857 << "_" << flags->targetLangName() << "_class(engine));" << endl;
1827 << "_" << flags->targetLangName() << "_class(engine));" << endl;
1858 }
1828 }
1859 }
1829 }
1860 }
1830 }
1861
1831
1862 writeInjectedCode(stream, meta_class, CodeSnip::ConstructorInitialization);
1832 writeInjectedCode(stream, meta_class, CodeSnip::ConstructorInitialization);
1863
1833
1864 stream << " return ctor;" << endl;
1834 stream << " return ctor;" << endl;
1865 stream << "}" << endl;
1835 stream << "}" << endl;
1866
1836
1867 writeInjectedCode(stream, meta_class, CodeSnip::End);
1837 writeInjectedCode(stream, meta_class, CodeSnip::End);
1868
1838
1869 QString packName = meta_class->package().replace(".", "_");
1839 QString packName = meta_class->package().replace(".", "_");
1870 priGenerator->addSource(packName, fileNameForClass(meta_class));
1840 priGenerator->addSource(packName, fileNameForClass(meta_class));
1871 setupGenerator->addClass(meta_class);
1841 setupGenerator->addClass(meta_class);
1872 }
1842 }
@@ -1,86 +1,157
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "prigenerator.h"
42 #include "prigenerator.h"
43 #include "shellgenerator.h"
43 #include "reporthandler.h"
44 #include "reporthandler.h"
44 #include "fileout.h"
45 #include "fileout.h"
45
46
46 void PriGenerator::addHeader(const QString &folder, const QString &header)
47 void PriGenerator::addHeader(const QString &folder, const QString &header)
47 {
48 {
48 priHash[folder].headers << header;
49 priHash[folder].headers << header;
49 }
50 }
50
51
51 void PriGenerator::addSource(const QString &folder, const QString &source)
52 void PriGenerator::addSource(const QString &folder, const QString &source)
52 {
53 {
53 priHash[folder].sources << source;
54 priHash[folder].sources << source;
54 }
55 }
55
56
57 static void collectAndRemoveFile(QTextStream& stream, const QString& file) {
58 QFile f(file);
59 if (f.open(QIODevice::ReadOnly | QIODevice::Text)) {
60 QString s = QString::fromLatin1(f.readAll());
61 if (file.endsWith(".cpp")) {
62 // remove first line include
63 s = s.mid(s.indexOf('\n')+1);
64 }
65 stream << s;
66 f.close();
67 QFile::remove(file);
68 }
69 }
70
71 static QString combineIncludes(const QString& text) {
72 QStringList lines = text.split('\n');
73 QSet<QString> includes;
74 QString result;
75 foreach(QString line, lines) {
76 if (line.startsWith("#include")) {
77 includes.insert(line);
78 } else if (line.startsWith("#")) {
79 // skip preprocessor stuff
80 } else {
81 result += line + "\n";
82 }
83 }
84 QStringList includeList = includes.toList();
85 qSort(includeList);
86 result = includeList.join("\n") + result;
87 return result;
88 }
89
90 static QStringList compactFiles(const QStringList& list, const QString& ext, const QString& dir, const QString& prefix) {
91 QStringList outList;
92 int count = list.count();
93 int fileNum = 0;
94 while (count>0) {
95 QString outFileName = prefix + QString::number(fileNum) + ext;
96 FileOut file(dir + "/" + outFileName);
97 if (ext == ".cpp") {
98 file.stream << "#include \"" + prefix + QString::number(fileNum) + ".h\"\n";
99 }
100 outList << outFileName;
101 QString allText;
102 QTextStream ts(&allText);
103 for (int i = 0; i<MAX_CLASSES_PER_FILE && count>0; i++) {
104 collectAndRemoveFile(ts, dir + "/" + list.at(list.length()-count));
105 count--;
106 }
107 allText = combineIncludes(allText);
108 file.stream << allText;
109 fileNum++;
110 }
111 return outList;
112 }
113
56 void PriGenerator::generate()
114 void PriGenerator::generate()
57 {
115 {
58 QHashIterator<QString, Pri> pri(priHash);
116 QHashIterator<QString, Pri> pri(priHash);
59 while (pri.hasNext()) {
117 while (pri.hasNext()) {
60 pri.next();
118 pri.next();
61 QStringList list = pri.value().headers;
119 QStringList list = pri.value().headers;
62 if (list.isEmpty())
120 if (list.isEmpty())
63 continue;
121 continue;
64
122
65 QString folder = pri.key();
123 QString folder = pri.key();
66 FileOut file(m_out_dir + "/generated_cpp/" + folder + "/" + folder + ".pri");
124 folder.replace('\\','/');
67 file.stream << "HEADERS += \\\n";
125 folder = folder.left(folder.indexOf('/'));
126
68 qSort(list.begin(), list.end());
127 qSort(list.begin(), list.end());
128 FileOut file(m_out_dir + "/generated_cpp/" + pri.key());
129
130 // strange idea to do the file compacting so late, but it is the most effective way without patching the generator a lot
131 bool compact = true;
132 if (compact) {
133 list = compactFiles(list, ".h", m_out_dir + "/generated_cpp/" + folder, folder);
134 }
135
136 file.stream << "HEADERS += \\\n";
69 foreach (const QString &entry, list) {
137 foreach (const QString &entry, list) {
70 file.stream << " $$PWD/" << entry << " \\\n";
138 file.stream << " $$PWD/" << entry << " \\\n";
71 }
139 }
72
140
73 file.stream << "\n";
141 file.stream << "\n";
74 file.stream << "SOURCES += \\\n";
142 file.stream << "SOURCES += \\\n";
75 list = pri.value().sources;
143 list = pri.value().sources;
76 qSort(list.begin(), list.end());
144 qSort(list.begin(), list.end());
145 if (compact) {
146 list = compactFiles(list, ".cpp", m_out_dir + "/generated_cpp/" + folder, folder);
147 }
77 foreach (const QString &entry, list) {
148 foreach (const QString &entry, list) {
78 file.stream << " $$PWD/" << entry << " \\\n";
149 file.stream << " $$PWD/" << entry << " \\\n";
79 }
150 }
80 file.stream << " $$PWD/" << folder << "_init.cpp\n";
151 file.stream << " $$PWD/" << folder << "_init.cpp\n";
81
152
82 if (file.done())
153 if (file.done())
83 ++m_num_generated_written;
154 ++m_num_generated_written;
84 ++m_num_generated;
155 ++m_num_generated;
85 }
156 }
86 }
157 }
@@ -1,233 +1,228
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "setupgenerator.h"
42 #include "setupgenerator.h"
43 #include "shellgenerator.h"
43 #include "shellgenerator.h"
44 #include "reporthandler.h"
44 #include "reporthandler.h"
45 #include "fileout.h"
45 #include "fileout.h"
46
46
47 //#define Q_SCRIPT_LAZY_GENERATOR
47 //#define Q_SCRIPT_LAZY_GENERATOR
48
48
49 void SetupGenerator::addClass(const AbstractMetaClass *cls)
49 void SetupGenerator::addClass(const AbstractMetaClass *cls)
50 {
50 {
51 packHash[cls->package()].append(cls);
51 packHash[cls->package()].append(cls);
52 }
52 }
53
53
54 void writeQtScriptQtBindingsLicense(QTextStream &stream);
55
56 void maybeDeclareMetaType(QTextStream &stream, const QString &typeName,
54 void maybeDeclareMetaType(QTextStream &stream, const QString &typeName,
57 QSet<QString> &registeredTypeNames);
55 QSet<QString> &registeredTypeNames);
58 bool hasDefaultConstructor(const AbstractMetaClass *meta_class);
56 bool hasDefaultConstructor(const AbstractMetaClass *meta_class);
59
57
60 void SetupGenerator::generate()
58 void SetupGenerator::generate()
61 {
59 {
62 AbstractMetaClassList classes_with_polymorphic_id;
60 AbstractMetaClassList classes_with_polymorphic_id;
63 {
61 {
64 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
62 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
65 while (pack.hasNext()) {
63 while (pack.hasNext()) {
66 pack.next();
64 pack.next();
67 QList<const AbstractMetaClass*> list = pack.value();
65 QList<const AbstractMetaClass*> list = pack.value();
68 foreach (const AbstractMetaClass *cls, list) {
66 foreach (const AbstractMetaClass *cls, list) {
69 if (cls->typeEntry()->isPolymorphicBase()) {
67 if (cls->typeEntry()->isPolymorphicBase()) {
70 classes_with_polymorphic_id.append((AbstractMetaClass*)cls);
68 classes_with_polymorphic_id.append((AbstractMetaClass*)cls);
71 }
69 }
72 }
70 }
73 }
71 }
74 }
72 }
75
73
76 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
74 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
77 while (pack.hasNext()) {
75 while (pack.hasNext()) {
78 pack.next();
76 pack.next();
79 QList<const AbstractMetaClass*> list = pack.value();
77 QList<const AbstractMetaClass*> list = pack.value();
80 if (list.isEmpty())
78 if (list.isEmpty())
81 continue;
79 continue;
82
80
83 QString packKey = pack.key();
81 QString packKey = pack.key();
84 QString packName = pack.key();
82 QString packName = pack.key();
85 QStringList components = packName.split(".");
83 QStringList components = packName.split(".");
86 if ((components.size() > 2) && (components.at(0) == "com")
84 if ((components.size() > 2) && (components.at(0) == "com")
87 && (components.at(1) == "trolltech")) {
85 && (components.at(1) == "trolltech")) {
88 // kill com.trolltech in key
86 // kill com.trolltech in key
89 components.removeAt(0);
87 components.removeAt(0);
90 components.removeAt(0);
88 components.removeAt(0);
91 }
89 }
92 packName.replace(".", "_");
90 packName.replace(".", "_");
93 packKey.replace(".", "_");
91 packKey.replace(".", "_");
94
92
95 QString shortPackName;
93 QString shortPackName;
96 foreach (QString comp, components) {
94 foreach (QString comp, components) {
97 comp[0] = comp[0].toUpper();
95 comp[0] = comp[0].toUpper();
98 shortPackName += comp;
96 shortPackName += comp;
99 }
97 }
100 // add missing camel case (workaround..)
98 // add missing camel case (workaround..)
101 if (shortPackName == "QtWebkit") {
99 if (shortPackName == "QtWebkit") {
102 shortPackName = "QtWebKit";
100 shortPackName = "QtWebKit";
103 } else if (shortPackName == "QtXmlpatterns") {
101 } else if (shortPackName == "QtXmlpatterns") {
104 shortPackName = "QtXmlPatterns";
102 shortPackName = "QtXmlPatterns";
105 } else if (shortPackName == "QtOpengl") {
103 } else if (shortPackName == "QtOpengl") {
106 shortPackName = "QtOpenGL";
104 shortPackName = "QtOpenGL";
107 } else if (shortPackName == "QtUitools") {
105 } else if (shortPackName == "QtUitools") {
108 shortPackName = "QtUiTools";
106 shortPackName = "QtUiTools";
109 }
107 }
110
108
111
109
112 {
110 {
113 FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp");
111 FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp");
114 QTextStream &s = initFile.stream;
112 QTextStream &s = initFile.stream;
115
113
116 if (FileOut::license)
117 writeQtScriptQtBindingsLicense(s);
118
119 s << "#include <PythonQt.h>" << endl;
114 s << "#include <PythonQt.h>" << endl;
120
115
121 foreach (const AbstractMetaClass *cls, list) {
116 for (int i=0; i<(list.count()+MAX_CLASSES_PER_FILE-1) / MAX_CLASSES_PER_FILE; i++) {
122 s << "#include \"" << ShellGenerator::wrapperClassName(cls) << ".h\"" << endl;
117 s << "#include \"" << packKey << QString::number(i) << ".h\"" << endl;
123 }
118 }
124 s << endl;
119 s << endl;
125
120
126 QStringList polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id);
121 QStringList polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id);
127 s << endl;
122 s << endl;
128
123
129 // declare individual class creation functions
124 // declare individual class creation functions
130 s << "void PythonQt_init_" << shortPackName << "() {" << endl;
125 s << "void PythonQt_init_" << shortPackName << "() {" << endl;
131 QStringList cppClassNames;
126 QStringList cppClassNames;
132 foreach (const AbstractMetaClass *cls, list) {
127 foreach (const AbstractMetaClass *cls, list) {
133 if (ShellGenerator::isBuiltIn(cls->name())) { continue; }
128 if (ShellGenerator::isBuiltIn(cls->name())) { continue; }
134
129
135 QString shellCreator;
130 QString shellCreator;
136 if (cls->generateShellClass()) {
131 if (cls->generateShellClass()) {
137 shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">";
132 shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">";
138 }
133 }
139 if (cls->isQObject()) {
134 if (cls->isQObject()) {
140 s << "PythonQt::self()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ");" << endl;
135 s << "PythonQt::self()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ");" << endl;
141 } else {
136 } else {
142 QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():"";
137 QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():"";
143 s << "PythonQt::self()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ");" << endl;
138 s << "PythonQt::self()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ");" << endl;
144 }
139 }
145 foreach(AbstractMetaClass* interface, cls->interfaces()) {
140 foreach(AbstractMetaClass* interface, cls->interfaces()) {
146 // the interface might be our own class... (e.g. QPaintDevice)
141 // the interface might be our own class... (e.g. QPaintDevice)
147 if (interface->qualifiedCppName() != cls->qualifiedCppName()) {
142 if (interface->qualifiedCppName() != cls->qualifiedCppName()) {
148 s << "PythonQt::self()->addParentClass(\""<< cls->qualifiedCppName() << "\", \"" << interface->qualifiedCppName() << "\",PythonQtUpcastingOffset<" << cls->qualifiedCppName() <<","<<interface->qualifiedCppName()<<">());" << endl;
143 s << "PythonQt::self()->addParentClass(\""<< cls->qualifiedCppName() << "\", \"" << interface->qualifiedCppName() << "\",PythonQtUpcastingOffset<" << cls->qualifiedCppName() <<","<<interface->qualifiedCppName()<<">());" << endl;
149 }
144 }
150 }
145 }
151 }
146 }
152 s << endl;
147 s << endl;
153 foreach (QString handler, polymorphicHandlers) {
148 foreach (QString handler, polymorphicHandlers) {
154 s << "PythonQt::self()->addPolymorphicHandler(\""<< handler << "\", polymorphichandler_" << handler << ");" << endl;
149 s << "PythonQt::self()->addPolymorphicHandler(\""<< handler << "\", polymorphichandler_" << handler << ");" << endl;
155 }
150 }
156
151
157 s << "}";
152 s << "}";
158 s << endl;
153 s << endl;
159 }
154 }
160 }
155 }
161 }
156 }
162
157
163 QStringList SetupGenerator::writePolymorphicHandler(QTextStream &s, const QString &package,
158 QStringList SetupGenerator::writePolymorphicHandler(QTextStream &s, const QString &package,
164 const AbstractMetaClassList &classes)
159 const AbstractMetaClassList &classes)
165 {
160 {
166 QStringList handlers;
161 QStringList handlers;
167 foreach (AbstractMetaClass *cls, classes) {
162 foreach (AbstractMetaClass *cls, classes) {
168 const ComplexTypeEntry *centry = cls->typeEntry();
163 const ComplexTypeEntry *centry = cls->typeEntry();
169 if (!centry->isPolymorphicBase())
164 if (!centry->isPolymorphicBase())
170 continue;
165 continue;
171 bool isGraphicsItem = (cls->qualifiedCppName()=="QGraphicsItem");
166 bool isGraphicsItem = (cls->qualifiedCppName()=="QGraphicsItem");
172
167
173 AbstractMetaClassList classList = this->classes();
168 AbstractMetaClassList classList = this->classes();
174 bool first = true;
169 bool first = true;
175 foreach (AbstractMetaClass *clazz, classList) {
170 foreach (AbstractMetaClass *clazz, classList) {
176 bool inherits = false;
171 bool inherits = false;
177 if (isGraphicsItem) {
172 if (isGraphicsItem) {
178 foreach(AbstractMetaClass* interfaze, clazz->interfaces()) {
173 foreach(AbstractMetaClass* interfaze, clazz->interfaces()) {
179 if (interfaze->qualifiedCppName()=="QGraphicsItem") {
174 if (interfaze->qualifiedCppName()=="QGraphicsItem") {
180 inherits = true;
175 inherits = true;
181 break;
176 break;
182 }
177 }
183 }
178 }
184 } else {
179 } else {
185 inherits = clazz->inheritsFrom(cls);
180 inherits = clazz->inheritsFrom(cls);
186 }
181 }
187 if (clazz->package() == package && inherits) {
182 if (clazz->package() == package && inherits) {
188 if (!clazz->typeEntry()->polymorphicIdValue().isEmpty() || isGraphicsItem) {
183 if (!clazz->typeEntry()->polymorphicIdValue().isEmpty() || isGraphicsItem) {
189 // On first find, open the function
184 // On first find, open the function
190 if (first) {
185 if (first) {
191 first = false;
186 first = false;
192
187
193 QString handler = cls->name();
188 QString handler = cls->name();
194 handlers.append(handler);
189 handlers.append(handler);
195
190
196 s << "static void* polymorphichandler_" << handler
191 s << "static void* polymorphichandler_" << handler
197 << "(const void *ptr, char **class_name)" << endl
192 << "(const void *ptr, char **class_name)" << endl
198 << "{" << endl
193 << "{" << endl
199 << " Q_ASSERT(ptr != 0);" << endl
194 << " Q_ASSERT(ptr != 0);" << endl
200 << " " << cls->qualifiedCppName() << " *object = ("
195 << " " << cls->qualifiedCppName() << " *object = ("
201 << cls->qualifiedCppName() << " *)ptr;" << endl;
196 << cls->qualifiedCppName() << " *)ptr;" << endl;
202 }
197 }
203
198
204 // For each, add case label
199 // For each, add case label
205 QString polyId = clazz->typeEntry()->polymorphicIdValue();
200 QString polyId = clazz->typeEntry()->polymorphicIdValue();
206 if (isGraphicsItem) {
201 if (isGraphicsItem) {
207 polyId = "%1->type() == " + clazz->qualifiedCppName() + "::Type";
202 polyId = "%1->type() == " + clazz->qualifiedCppName() + "::Type";
208 }
203 }
209 s << " if ("
204 s << " if ("
210 << polyId.replace("%1", "object")
205 << polyId.replace("%1", "object")
211 << ") {" << endl
206 << ") {" << endl
212 << " *class_name = \"" << clazz->name() << "\";" << endl
207 << " *class_name = \"" << clazz->name() << "\";" << endl
213 << " return (" << clazz->qualifiedCppName() << "*)object;" << endl
208 << " return (" << clazz->qualifiedCppName() << "*)object;" << endl
214 << " }" << endl;
209 << " }" << endl;
215 } else {
210 } else {
216 QString warning = QString("class '%1' inherits from polymorphic class '%2', but has no polymorphic id set")
211 QString warning = QString("class '%1' inherits from polymorphic class '%2', but has no polymorphic id set")
217 .arg(clazz->name())
212 .arg(clazz->name())
218 .arg(cls->name());
213 .arg(cls->name());
219
214
220 ReportHandler::warning(warning);
215 ReportHandler::warning(warning);
221 }
216 }
222 }
217 }
223 }
218 }
224
219
225 // Close the function if it has been opened
220 // Close the function if it has been opened
226 if (!first) {
221 if (!first) {
227 s << " return NULL;" << endl
222 s << " return NULL;" << endl
228 << "}" << endl;
223 << "}" << endl;
229 }
224 }
230 }
225 }
231
226
232 return handlers;
227 return handlers;
233 }
228 }
@@ -1,64 +1,68
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #ifndef SETUPGENERATOR_H
42 #ifndef SETUPGENERATOR_H
43 #define SETUPGENERATOR_H
43 #define SETUPGENERATOR_H
44
44
45 #include "generator.h"
45 #include "generator.h"
46 #include "metaqtscript.h"
46 #include "metaqtscript.h"
47
47
48 class SetupGenerator : public Generator
48 class SetupGenerator : public Generator
49 {
49 {
50 Q_OBJECT
50 Q_OBJECT
51
51
52 public:
52 public:
53 virtual void generate();
53 virtual void generate();
54
54
55 void addClass(const AbstractMetaClass *cls);
55 void addClass(const AbstractMetaClass *cls);
56
56
57 static void writeInclude(QTextStream &stream, const Include &inc);
58
59 static bool isSpecialStreamingOperator(const AbstractMetaFunction *fun);
60
57 private:
61 private:
58 QStringList writePolymorphicHandler(QTextStream &s, const QString &package,
62 QStringList writePolymorphicHandler(QTextStream &s, const QString &package,
59 const AbstractMetaClassList &classes);
63 const AbstractMetaClassList &classes);
60
64
61 QHash<QString, QList<const AbstractMetaClass*> > packHash;
65 QHash<QString, QList<const AbstractMetaClass*> > packHash;
62 };
66 };
63 #endif // SETUPGENERATOR_H
67 #endif // SETUPGENERATOR_H
64
68
@@ -1,374 +1,377
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "shellgenerator.h"
42 #include "shellgenerator.h"
43 #include "reporthandler.h"
43 #include "reporthandler.h"
44
44
45 #include "metaqtscript.h"
45 #include "metaqtscript.h"
46
46
47 bool ShellGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
47 bool ShellGenerator::shouldGenerate(const AbstractMetaClass *meta_class) const
48 {
48 {
49 uint cg = meta_class->typeEntry()->codeGeneration();
49 uint cg = meta_class->typeEntry()->codeGeneration();
50 if (meta_class->name().startsWith("QtScript")) return false;
50 if (meta_class->name().startsWith("QtScript")) return false;
51 if (meta_class->name().startsWith("QFuture")) return false;
51 if (meta_class->name().startsWith("QFuture")) return false;
52 if (meta_class->name().startsWith("Global")) return false;
52 if (meta_class->name().startsWith("Global")) return false;
53 if (meta_class->name().startsWith("QStyleOptionComplex")) return false;
53 if (meta_class->name().startsWith("QStyleOptionComplex")) return false;
54 if (meta_class->name().startsWith("QTextLayout")) return false;
54 if (meta_class->name().startsWith("QTextLayout")) return false;
55 //if (meta_class->name().startsWith("QTextStream")) return false; // because of >> operators
55 //if (meta_class->name().startsWith("QTextStream")) return false; // because of >> operators
56 //if (meta_class->name().startsWith("QDataStream")) return false; // "
56 //if (meta_class->name().startsWith("QDataStream")) return false; // "
57 return ((cg & TypeEntry::GenerateCode) != 0);
57 return ((cg & TypeEntry::GenerateCode) != 0);
58 }
58 }
59
59
60 void ShellGenerator::writeTypeInfo(QTextStream &s, const AbstractMetaType *type, Option options)
60 void ShellGenerator::writeTypeInfo(QTextStream &s, const AbstractMetaType *type, Option options)
61 {
61 {
62 if ((options & OriginalTypeDescription) && !type->originalTypeDescription().isEmpty()) {
62 if ((options & OriginalTypeDescription) && !type->originalTypeDescription().isEmpty()) {
63 s << type->originalTypeDescription();
63 s << type->originalTypeDescription();
64 return;
64 return;
65 }
65 }
66
66
67 if (type->isArray()) {
67 if (type->isArray()) {
68 writeTypeInfo(s, type->arrayElementType(), options);
68 writeTypeInfo(s, type->arrayElementType(), options);
69 if (options & ArrayAsPointer) {
69 if (options & ArrayAsPointer) {
70 s << "*";
70 s << "*";
71 } else {
71 } else {
72 s << "[" << type->arrayElementCount() << "]";
72 s << "[" << type->arrayElementCount() << "]";
73 }
73 }
74 return;
74 return;
75 }
75 }
76
76
77 const TypeEntry *te = type->typeEntry();
77 const TypeEntry *te = type->typeEntry();
78
78
79 if (type->isConstant() && !(options & ExcludeConst))
79 if (type->isConstant() && !(options & ExcludeConst))
80 s << "const ";
80 s << "const ";
81
81
82 if ((options & EnumAsInts) && (te->isEnum() || te->isFlags())) {
82 if ((options & EnumAsInts) && (te->isEnum() || te->isFlags())) {
83 s << "int";
83 s << "int";
84 } else if (te->isFlags()) {
84 } else if (te->isFlags()) {
85 s << ((FlagsTypeEntry *) te)->originalName();
85 s << ((FlagsTypeEntry *) te)->originalName();
86 } else {
86 } else {
87 s << fixCppTypeName(te->qualifiedCppName());
87 s << fixCppTypeName(te->qualifiedCppName());
88 }
88 }
89
89
90 if (type->instantiations().size() > 0
90 if (type->instantiations().size() > 0
91 && (!type->isContainer()
91 && (!type->isContainer()
92 || (static_cast<const ContainerTypeEntry *>(te))->type() != ContainerTypeEntry::StringListContainer)) {
92 || (static_cast<const ContainerTypeEntry *>(te))->type() != ContainerTypeEntry::StringListContainer)) {
93 s << '<';
93 s << '<';
94 QList<AbstractMetaType *> args = type->instantiations();
94 QList<AbstractMetaType *> args = type->instantiations();
95 bool nested_template = false;
95 bool nested_template = false;
96 for (int i=0; i<args.size(); ++i) {
96 for (int i=0; i<args.size(); ++i) {
97 if (i != 0)
97 if (i != 0)
98 s << ", ";
98 s << ", ";
99 nested_template |= args.at(i)->isContainer();
99 nested_template |= args.at(i)->isContainer();
100 writeTypeInfo(s, args.at(i));
100 writeTypeInfo(s, args.at(i));
101 }
101 }
102 if (nested_template)
102 if (nested_template)
103 s << ' ';
103 s << ' ';
104 s << '>';
104 s << '>';
105 }
105 }
106
106
107 s << QString(type->indirections(), '*');
107 s << QString(type->indirections(), '*');
108
108
109 if (type->isReference() && !(options & ExcludeReference) && !(options & ConvertReferenceToPtr))
109 if (type->isReference() && !(options & ExcludeReference) && !(options & ConvertReferenceToPtr))
110 s << "&";
110 s << "&";
111
111
112 if (type->isReference() && (options & ConvertReferenceToPtr)) {
112 if (type->isReference() && (options & ConvertReferenceToPtr)) {
113 s << "*";
113 s << "*";
114 }
114 }
115
115
116
116
117 if (!(options & SkipName))
117 if (!(options & SkipName))
118 s << ' ';
118 s << ' ';
119 }
119 }
120
120
121
121
122 void ShellGenerator::writeFunctionArguments(QTextStream &s, const AbstractMetaClass* owner,
122 void ShellGenerator::writeFunctionArguments(QTextStream &s, const AbstractMetaClass* owner,
123 const AbstractMetaArgumentList &arguments,
123 const AbstractMetaArgumentList &arguments,
124 Option option,
124 Option option,
125 int numArguments)
125 int numArguments)
126 {
126 {
127 if (numArguments < 0) numArguments = arguments.size();
127 if (numArguments < 0) numArguments = arguments.size();
128
128
129 for (int i=0; i<numArguments; ++i) {
129 for (int i=0; i<numArguments; ++i) {
130 if (i != 0)
130 if (i != 0)
131 s << ", ";
131 s << ", ";
132 AbstractMetaArgument *arg = arguments.at(i);
132 AbstractMetaArgument *arg = arguments.at(i);
133 writeTypeInfo(s, arg->type(), option);
133 writeTypeInfo(s, arg->type(), option);
134 if (!(option & SkipName))
134 if (!(option & SkipName))
135 s << " " << arg->argumentName();
135 s << " " << arg->argumentName();
136 if ((option & IncludeDefaultExpression) && !arg->originalDefaultValueExpression().isEmpty()) {
136 if ((option & IncludeDefaultExpression) && !arg->originalDefaultValueExpression().isEmpty()) {
137 s << " = ";
137 s << " = ";
138
138
139 QString expr = arg->originalDefaultValueExpression();
139 QString expr = arg->originalDefaultValueExpression();
140 if (expr != "0") {
140 if (expr != "0") {
141 QString qualifier;
141 QString qualifier;
142 if (arg->type()->typeEntry()->isEnum() && expr.indexOf("::") < 0) {
142 if (arg->type()->typeEntry()->isEnum() && expr.indexOf("::") < 0) {
143 qualifier = ((EnumTypeEntry *)arg->type()->typeEntry())->qualifier();
143 qualifier = ((EnumTypeEntry *)arg->type()->typeEntry())->qualifier();
144 } else if (arg->type()->typeEntry()->isFlags() && expr.indexOf("::") < 0) {
144 } else if (arg->type()->typeEntry()->isFlags() && expr.indexOf("::") < 0) {
145 qualifier = ((FlagsTypeEntry *)arg->type()->typeEntry())->originator()->qualifier();
145 qualifier = ((FlagsTypeEntry *)arg->type()->typeEntry())->originator()->qualifier();
146 }
146 }
147 if (!qualifier.isEmpty()) {
147 if (!qualifier.isEmpty()) {
148 s << qualifier << "::";
148 s << qualifier << "::";
149 }
149 }
150 }
150 }
151 if (expr.contains("defaultConnection")) {
151 if (expr.contains("defaultConnection")) {
152 expr.replace("defaultConnection","QSqlDatabase::defaultConnection");
152 expr.replace("defaultConnection","QSqlDatabase::defaultConnection");
153 }
153 }
154 if (expr == "MediaSource()") {
154 if (expr == "MediaSource()") {
155 expr = "Phonon::MediaSource()";
155 expr = "Phonon::MediaSource()";
156 }
156 }
157 s << expr;
157 s << expr;
158 }
158 }
159 }
159 }
160 }
160 }
161
161
162 /*!
162 /*!
163 * Writes the function \a meta_function signature to the textstream \a s.
163 * Writes the function \a meta_function signature to the textstream \a s.
164 *
164 *
165 * The \a name_prefix can be used to give the function name a prefix,
165 * The \a name_prefix can be used to give the function name a prefix,
166 * like "__public_" or "__override_" and \a classname_prefix can
166 * like "__public_" or "__override_" and \a classname_prefix can
167 * be used to give the class name a prefix.
167 * be used to give the class name a prefix.
168 *
168 *
169 * The \a option flags can be used to tweak various parameters, such as
169 * The \a option flags can be used to tweak various parameters, such as
170 * showing static, original vs renamed name, underscores for space etc.
170 * showing static, original vs renamed name, underscores for space etc.
171 *
171 *
172 * The \a extra_arguments list is a list of extra arguments on the
172 * The \a extra_arguments list is a list of extra arguments on the
173 * form "bool static_call".
173 * form "bool static_call".
174 */
174 */
175
175
176 void ShellGenerator::writeFunctionSignature(QTextStream &s,
176 void ShellGenerator::writeFunctionSignature(QTextStream &s,
177 const AbstractMetaFunction *meta_function,
177 const AbstractMetaFunction *meta_function,
178 const AbstractMetaClass *implementor,
178 const AbstractMetaClass *implementor,
179 const QString &name_prefix,
179 const QString &name_prefix,
180 Option option,
180 Option option,
181 const QString &classname_prefix,
181 const QString &classname_prefix,
182 const QStringList &extra_arguments,
182 const QStringList &extra_arguments,
183 int numArguments)
183 int numArguments)
184 {
184 {
185 // ### remove the implementor
185 // ### remove the implementor
186 AbstractMetaType *function_type = meta_function->type();
186 AbstractMetaType *function_type = meta_function->type();
187
187
188
188
189 if ((option & SkipReturnType) == 0) {
189 if ((option & SkipReturnType) == 0) {
190 if (function_type) {
190 if (function_type) {
191 writeTypeInfo(s, function_type, option);
191 writeTypeInfo(s, function_type, option);
192 s << " ";
192 s << " ";
193 } else if (!meta_function->isConstructor()) {
193 } else if (!meta_function->isConstructor()) {
194 s << "void ";
194 s << "void ";
195 }
195 }
196 }
196 }
197
197
198 if (implementor) {
198 if (implementor) {
199 if (classname_prefix.isEmpty())
199 if (classname_prefix.isEmpty())
200 s << wrapperClassName(implementor) << "::";
200 s << wrapperClassName(implementor) << "::";
201 else
201 else
202 s << classname_prefix << implementor->name() << "::";
202 s << classname_prefix << implementor->name() << "::";
203 }
203 }
204
204
205
205
206 QString function_name;
206 QString function_name;
207 if (option & OriginalName)
207 if (option & OriginalName)
208 function_name = meta_function->originalName();
208 function_name = meta_function->originalName();
209 else
209 else
210 function_name = meta_function->name();
210 function_name = meta_function->name();
211
211
212 if (option & UnderscoreSpaces)
212 if (option & UnderscoreSpaces)
213 function_name = function_name.replace(' ', '_');
213 function_name = function_name.replace(' ', '_');
214
214
215 if (meta_function->isConstructor())
215 if (meta_function->isConstructor())
216 function_name = meta_function->ownerClass()->name();
216 function_name = meta_function->ownerClass()->name();
217
217
218 if (meta_function->isStatic() && (option & ShowStatic)) {
218 if (meta_function->isStatic() && (option & ShowStatic)) {
219 function_name = "static_" + meta_function->ownerClass()->name() + "_" + function_name;
219 function_name = "static_" + meta_function->ownerClass()->name() + "_" + function_name;
220 }
220 }
221
221
222 if (function_name.startsWith("operator")) {
222 if (function_name.startsWith("operator")) {
223 function_name = meta_function->name();
223 function_name = meta_function->name();
224 }
224 }
225
225
226 s << name_prefix << function_name;
226 s << name_prefix << function_name;
227
227
228 if (meta_function->attributes() & AbstractMetaAttributes::SetterFunction)
228 if (meta_function->attributes() & AbstractMetaAttributes::SetterFunction)
229 s << "_setter";
229 s << "_setter";
230 else if (meta_function->attributes() & AbstractMetaAttributes::GetterFunction)
230 else if (meta_function->attributes() & AbstractMetaAttributes::GetterFunction)
231 s << "_getter";
231 s << "_getter";
232
232
233 s << "(";
233 s << "(";
234
234
235 if ((option & FirstArgIsWrappedObject) && meta_function->ownerClass() && !meta_function->isConstructor() && !meta_function->isStatic()) {
235 if ((option & FirstArgIsWrappedObject) && meta_function->ownerClass() && !meta_function->isConstructor() && !meta_function->isStatic()) {
236 s << meta_function->ownerClass()->qualifiedCppName() << "* theWrappedObject";
236 s << meta_function->ownerClass()->qualifiedCppName() << "* theWrappedObject";
237 if (meta_function->arguments().size() != 0) {
237 if (meta_function->arguments().size() != 0) {
238 s << ", ";
238 s << ", ";
239 }
239 }
240 }
240 }
241
241
242 writeFunctionArguments(s, meta_function->ownerClass(), meta_function->arguments(), Option(option & Option(~ConvertReferenceToPtr)), numArguments);
242 writeFunctionArguments(s, meta_function->ownerClass(), meta_function->arguments(), Option(option & Option(~ConvertReferenceToPtr)), numArguments);
243
243
244 // The extra arguments...
244 // The extra arguments...
245 for (int i=0; i<extra_arguments.size(); ++i) {
245 for (int i=0; i<extra_arguments.size(); ++i) {
246 if (i > 0 || meta_function->arguments().size() != 0)
246 if (i > 0 || meta_function->arguments().size() != 0)
247 s << ", ";
247 s << ", ";
248 s << extra_arguments.at(i);
248 s << extra_arguments.at(i);
249 }
249 }
250
250
251 s << ")";
251 s << ")";
252 if (meta_function->isConstant())
252 if (meta_function->isConstant())
253 s << " const";
253 s << " const";
254 }
254 }
255
255
256 AbstractMetaFunctionList ShellGenerator::getFunctionsToWrap(const AbstractMetaClass* meta_class)
256 AbstractMetaFunctionList ShellGenerator::getFunctionsToWrap(const AbstractMetaClass* meta_class)
257 {
257 {
258 AbstractMetaFunctionList functions = meta_class->queryFunctions(
258 AbstractMetaFunctionList functions = meta_class->queryFunctions(
259 AbstractMetaClass::NormalFunctions | AbstractMetaClass::WasPublic
259 AbstractMetaClass::NormalFunctions | AbstractMetaClass::WasPublic
260 | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
260 | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
261 );
261 );
262 AbstractMetaFunctionList functions2 = meta_class->queryFunctions(
262 AbstractMetaFunctionList functions2 = meta_class->queryFunctions(
263 AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
263 AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
264 | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
264 | AbstractMetaClass::NotRemovedFromTargetLang | AbstractMetaClass::ClassImplements
265 );
265 );
266 QSet<AbstractMetaFunction*> set1 = QSet<AbstractMetaFunction*>::fromList(functions);
266 QSet<AbstractMetaFunction*> set1 = QSet<AbstractMetaFunction*>::fromList(functions);
267 foreach(AbstractMetaFunction* func, functions2) {
267 foreach(AbstractMetaFunction* func, functions2) {
268 set1.insert(func);
268 set1.insert(func);
269 }
269 }
270
270
271 AbstractMetaFunctionList resultFunctions;
271 AbstractMetaFunctionList resultFunctions;
272
272
273 foreach(AbstractMetaFunction* func, set1.toList()) {
273 foreach(AbstractMetaFunction* func, set1.toList()) {
274 if (!func->isAbstract() && func->implementingClass()==meta_class) {
274 if (!func->isAbstract() && func->implementingClass()==meta_class) {
275 resultFunctions << func;
275 resultFunctions << func;
276 }
276 }
277 }
277 }
278 return resultFunctions;
278 return resultFunctions;
279 }
279 }
280
280
281 AbstractMetaFunctionList ShellGenerator::getVirtualFunctionsForShell(const AbstractMetaClass* meta_class)
281 AbstractMetaFunctionList ShellGenerator::getVirtualFunctionsForShell(const AbstractMetaClass* meta_class)
282 {
282 {
283 AbstractMetaFunctionList functions = meta_class->queryFunctions(
283 AbstractMetaFunctionList functions = meta_class->queryFunctions(
284 AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
284 AbstractMetaClass::VirtualFunctions | AbstractMetaClass::WasVisible
285 // | AbstractMetaClass::NotRemovedFromTargetLang
285 // | AbstractMetaClass::NotRemovedFromTargetLang
286 );
286 );
287 return functions;
287 return functions;
288 }
288 }
289
289
290 AbstractMetaFunctionList ShellGenerator::getProtectedFunctionsThatNeedPromotion(const AbstractMetaClass* meta_class)
290 AbstractMetaFunctionList ShellGenerator::getProtectedFunctionsThatNeedPromotion(const AbstractMetaClass* meta_class)
291 {
291 {
292 AbstractMetaFunctionList functions;
292 AbstractMetaFunctionList functions;
293 AbstractMetaFunctionList functions1 = getFunctionsToWrap(meta_class);
293 AbstractMetaFunctionList functions1 = getFunctionsToWrap(meta_class);
294 foreach(AbstractMetaFunction* func, functions1) {
294 foreach(AbstractMetaFunction* func, functions1) {
295 if (!func->isPublic() || func->isVirtual()) {
295 if (!func->isPublic() || func->isVirtual()) {
296 functions << func;
296 functions << func;
297 }
297 }
298 }
298 }
299 return functions;
299 return functions;
300 }
300 }
301
301
302 /*!
302 /*!
303 Writes the include defined by \a inc to \a stream.
303 Writes the include defined by \a inc to \a stream.
304 */
304 */
305 void ShellGenerator::writeInclude(QTextStream &stream, const Include &inc)
305 void ShellGenerator::writeInclude(QTextStream &stream, const Include &inc)
306 {
306 {
307 if (inc.name.isEmpty())
307 if (inc.name.isEmpty())
308 return;
308 return;
309 if (inc.type == Include::TargetLangImport)
309 if (inc.type == Include::TargetLangImport)
310 return;
310 return;
311 stream << "#include ";
311 stream << "#include ";
312 if (inc.type == Include::IncludePath)
312 if (inc.type == Include::IncludePath)
313 stream << "<";
313 stream << "<";
314 else
314 else
315 stream << "\"";
315 stream << "\"";
316 stream << inc.name;
316 stream << inc.name;
317 if (inc.type == Include::IncludePath)
317 if (inc.type == Include::IncludePath)
318 stream << ">";
318 stream << ">";
319 else
319 else
320 stream << "\"";
320 stream << "\"";
321 stream << endl;
321 stream << endl;
322 }
322 }
323
323
324 /*!
324 /*!
325 Returns true if the given function \a fun is operator>>() or
325 Returns true if the given function \a fun is operator>>() or
326 operator<<() that streams from/to a Q{Data,Text}Stream, false
326 operator<<() that streams from/to a Q{Data,Text}Stream, false
327 otherwise.
327 otherwise.
328 */
328 */
329 bool ShellGenerator::isSpecialStreamingOperator(const AbstractMetaFunction *fun)
329 bool ShellGenerator::isSpecialStreamingOperator(const AbstractMetaFunction *fun)
330 {
330 {
331 return ((fun->functionType() == AbstractMetaFunction::GlobalScopeFunction)
331 return ((fun->functionType() == AbstractMetaFunction::GlobalScopeFunction)
332 && (fun->arguments().size() == 1)
332 && (fun->arguments().size() == 1)
333 && (((fun->originalName() == "operator>>") && (fun->modifiedName() == "readFrom"))
333 && (((fun->originalName() == "operator>>") && (fun->modifiedName() == "readFrom"))
334 || ((fun->originalName() == "operator<<") && (fun->modifiedName() == "writeTo"))));
334 || ((fun->originalName() == "operator<<") && (fun->modifiedName() == "writeTo"))));
335 }
335 }
336
336
337 bool ShellGenerator::isBuiltIn(const QString& name) {
337 bool ShellGenerator::isBuiltIn(const QString& name) {
338
338
339 static QSet<QString> builtIn;
339 static QSet<QString> builtIn;
340 if (builtIn.isEmpty()) {
340 if (builtIn.isEmpty()) {
341 builtIn.insert("Qt");
341 builtIn.insert("Qt");
342 builtIn.insert("QFont");
342 builtIn.insert("QFont");
343 builtIn.insert("QPixmap");
343 builtIn.insert("QPixmap");
344 builtIn.insert("QBrush");
344 builtIn.insert("QBrush");
345 builtIn.insert("QBitArray");
345 builtIn.insert("QPalette");
346 builtIn.insert("QPalette");
347 builtIn.insert("QPen");
346 builtIn.insert("QIcon");
348 builtIn.insert("QIcon");
347 builtIn.insert("QImage");
349 builtIn.insert("QImage");
348 builtIn.insert("QPolygon");
350 builtIn.insert("QPolygon");
349 builtIn.insert("QRegion");
351 builtIn.insert("QRegion");
350 builtIn.insert("QBitmap");
352 builtIn.insert("QBitmap");
351 builtIn.insert("QCursor");
353 builtIn.insert("QCursor");
352 builtIn.insert("QColor");
354 builtIn.insert("QColor");
353 builtIn.insert("QSizePolicy");
355 builtIn.insert("QSizePolicy");
354 builtIn.insert("QKeySequence");
356 builtIn.insert("QKeySequence");
355 builtIn.insert("QTextLength");
357 builtIn.insert("QTextLength");
356 builtIn.insert("QTextFormat");
358 builtIn.insert("QTextFormat");
357 builtIn.insert("QMatrix");
359 builtIn.insert("QMatrix");
358 builtIn.insert("QDate");
360 builtIn.insert("QDate");
359 builtIn.insert("QTime");
361 builtIn.insert("QTime");
360 builtIn.insert("QDateTime");
362 builtIn.insert("QDateTime");
361 builtIn.insert("QUrl");
363 builtIn.insert("QUrl");
362 builtIn.insert("QLocale");
364 builtIn.insert("QLocale");
363 builtIn.insert("QRect");
365 builtIn.insert("QRect");
364 builtIn.insert("QRectF");
366 builtIn.insert("QRectF");
365 builtIn.insert("QSize");
367 builtIn.insert("QSize");
366 builtIn.insert("QSizeF");
368 builtIn.insert("QSizeF");
367 builtIn.insert("QLine");
369 builtIn.insert("QLine");
368 builtIn.insert("QLineF");
370 builtIn.insert("QLineF");
369 builtIn.insert("QPoint");
371 builtIn.insert("QPoint");
370 builtIn.insert("QPointF");
372 builtIn.insert("QPointF");
371 builtIn.insert("QRegExp");
373 builtIn.insert("QRegExp");
372 }
374 }
373 return builtIn.contains(name);
375 return builtIn.contains(name);
374 }
376 }
377
@@ -1,100 +1,102
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #ifndef SHELLGENERATOR_H
42 #ifndef SHELLGENERATOR_H
43 #define SHELLGENERATOR_H
43 #define SHELLGENERATOR_H
44
44
45 #include "generator.h"
45 #include "generator.h"
46 #include "metaqtscript.h"
46 #include "metaqtscript.h"
47 #include "prigenerator.h"
47 #include "prigenerator.h"
48
48
49 #define MAX_CLASSES_PER_FILE 20
50
49 class ShellGenerator : public Generator
51 class ShellGenerator : public Generator
50 {
52 {
51 Q_OBJECT
53 Q_OBJECT
52
54
53 public:
55 public:
54 virtual QString subDirectoryForClass(const AbstractMetaClass *cls) const
56 virtual QString subDirectoryForClass(const AbstractMetaClass *cls) const
55 {
57 {
56 return "generated_cpp/" + cls->package().replace(".", "_") + "/";
58 return "generated_cpp/" + cls->package().replace(".", "_") + "/";
57 }
59 }
58
60
59 static void writeTypeInfo(QTextStream &s, const AbstractMetaType *type, Option option = NoOption);
61 static void writeTypeInfo(QTextStream &s, const AbstractMetaType *type, Option option = NoOption);
60 static void writeFunctionSignature(QTextStream &s, const AbstractMetaFunction *meta_function,
62 static void writeFunctionSignature(QTextStream &s, const AbstractMetaFunction *meta_function,
61 const AbstractMetaClass *implementor = 0,
63 const AbstractMetaClass *implementor = 0,
62 const QString &name_prefix = QString(),
64 const QString &name_prefix = QString(),
63 Option option = NoOption,
65 Option option = NoOption,
64 const QString &classname_prefix = QString(),
66 const QString &classname_prefix = QString(),
65 const QStringList &extra_arguments = QStringList(),
67 const QStringList &extra_arguments = QStringList(),
66 int numArguments = -1);
68 int numArguments = -1);
67 static void writeFunctionArguments(QTextStream &s, const AbstractMetaClass* owner, const AbstractMetaArgumentList &arguments,
69 static void writeFunctionArguments(QTextStream &s, const AbstractMetaClass* owner, const AbstractMetaArgumentList &arguments,
68 Option option = NoOption,
70 Option option = NoOption,
69 int numArguments = -1);
71 int numArguments = -1);
70
72
71 bool shouldGenerate(const AbstractMetaClass *meta_class) const;
73 bool shouldGenerate(const AbstractMetaClass *meta_class) const;
72
74
73 static QString shellClassName(const AbstractMetaClass *meta_class) {
75 static QString shellClassName(const AbstractMetaClass *meta_class) {
74 return "PythonQtShell_" + meta_class->name();
76 return "PythonQtShell_" + meta_class->name();
75 }
77 }
76 static QString wrapperClassName(const AbstractMetaClass *meta_class) {
78 static QString wrapperClassName(const AbstractMetaClass *meta_class) {
77 return "PythonQtWrapper_" + meta_class->name();
79 return "PythonQtWrapper_" + meta_class->name();
78 }
80 }
79 static QString promoterClassName(const AbstractMetaClass *meta_class) {
81 static QString promoterClassName(const AbstractMetaClass *meta_class) {
80 return "PythonQtPublicPromoter_" + meta_class->name();
82 return "PythonQtPublicPromoter_" + meta_class->name();
81 }
83 }
82
84
83 static AbstractMetaFunctionList getFunctionsToWrap(const AbstractMetaClass* cls);
85 static AbstractMetaFunctionList getFunctionsToWrap(const AbstractMetaClass* cls);
84 static AbstractMetaFunctionList getVirtualFunctionsForShell(const AbstractMetaClass* cls);
86 static AbstractMetaFunctionList getVirtualFunctionsForShell(const AbstractMetaClass* cls);
85 static AbstractMetaFunctionList getProtectedFunctionsThatNeedPromotion(const AbstractMetaClass* cls);
87 static AbstractMetaFunctionList getProtectedFunctionsThatNeedPromotion(const AbstractMetaClass* cls);
86
88
87 // PythonQt builtins..., dont put them in pri files and dont register them, but generate the code
89 // PythonQt builtins..., dont put them in pri files and dont register them, but generate the code
88 static bool isBuiltIn(const QString& name);
90 static bool isBuiltIn(const QString& name);
89
91
90 static bool isSpecialStreamingOperator(const AbstractMetaFunction *fun);
92 static bool isSpecialStreamingOperator(const AbstractMetaFunction *fun);
91
93
92 static void writeInclude(QTextStream &stream, const Include &inc);
94 static void writeInclude(QTextStream &stream, const Include &inc);
93
95
94 protected:
96 protected:
95 PriGenerator *priGenerator;
97 PriGenerator *priGenerator;
96
98
97 };
99 };
98
100
99
101
100 #endif // SHELLGENERATOR_H
102 #endif // SHELLGENERATOR_H
@@ -1,293 +1,289
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "shellheadergenerator.h"
42 #include "shellheadergenerator.h"
43 #include "fileout.h"
43 #include "fileout.h"
44
44
45 #include <QtCore/QDir>
45 #include <QtCore/QDir>
46
46
47 #include <qdebug.h>
47 #include <qdebug.h>
48
48
49 QString ShellHeaderGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
49 QString ShellHeaderGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
50 {
50 {
51 return QString("PythonQtWrapper_%1.h").arg(meta_class->name());
51 return QString("PythonQtWrapper_%1.h").arg(meta_class->name());
52 }
52 }
53
53
54 void writeQtScriptQtBindingsLicense(QTextStream &stream);
55
56 void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
54 void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
57 {
55 {
58
56 if (!ShellGenerator::isBuiltIn(meta_class->name())) {
59 setupGenerator->addClass(meta_class);
57 setupGenerator->addClass(meta_class);
60
58 }
61 if (FileOut::license)
62 writeQtScriptQtBindingsLicense(s);
63
59
64 QString include_block = "PYTHONQTWRAPPER_" + meta_class->name().toUpper() + "_H";
60 QString include_block = "PYTHONQTWRAPPER_" + meta_class->name().toUpper() + "_H";
65
61
66 s << "#ifndef " << include_block << endl
62 s << "#ifndef " << include_block << endl
67 << "#define " << include_block << endl << endl;
63 << "#define " << include_block << endl << endl;
68
64
69 Include inc = meta_class->typeEntry()->include();
65 Include inc = meta_class->typeEntry()->include();
70 ShellGenerator::writeInclude(s, inc);
66 ShellGenerator::writeInclude(s, inc);
71
67
72 s << "#include <QObject>" << endl << endl;
68 s << "#include <QObject>" << endl << endl;
73 s << "#include <PythonQt.h>" << endl << endl;
69 s << "#include <PythonQt.h>" << endl << endl;
74
70
75 IncludeList list = meta_class->typeEntry()->extraIncludes();
71 IncludeList list = meta_class->typeEntry()->extraIncludes();
76 qSort(list.begin(), list.end());
72 qSort(list.begin(), list.end());
77 foreach (const Include &inc, list) {
73 foreach (const Include &inc, list) {
78 ShellGenerator::writeInclude(s, inc);
74 ShellGenerator::writeInclude(s, inc);
79 }
75 }
80 s << endl;
76 s << endl;
81
77
82 QString pro_file_name = meta_class->package().replace(".", "_") + "/" + meta_class->package().replace(".", "_") + ".pri";
78 QString pro_file_name = meta_class->package().replace(".", "_") + "/" + meta_class->package().replace(".", "_") + ".pri";
83
79
84 // if (!meta_class->generateShellClass()) {
80 // if (!meta_class->generateShellClass()) {
85 // s << "#endif" << endl << endl;
81 // s << "#endif" << endl << endl;
86 // priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
82 // priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
87 // return ;
83 // return ;
88 // }
84 // }
89
85
90 AbstractMetaFunctionList ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
86 AbstractMetaFunctionList ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
91 | AbstractMetaClass::WasVisible
87 | AbstractMetaClass::WasVisible
92 | AbstractMetaClass::NotRemovedFromTargetLang);
88 | AbstractMetaClass::NotRemovedFromTargetLang);
93
89
94 // Shell-------------------------------------------------------------------
90 // Shell-------------------------------------------------------------------
95 if (meta_class->generateShellClass()) {
91 if (meta_class->generateShellClass()) {
96
92
97 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
93 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
98
94
99 s << "class " << shellClassName(meta_class)
95 s << "class " << shellClassName(meta_class)
100 << " : public " << meta_class->qualifiedCppName() << endl << "{" << endl;
96 << " : public " << meta_class->qualifiedCppName() << endl << "{" << endl;
101 s << "public:" << endl;
97 s << "public:" << endl;
102 foreach(AbstractMetaFunction* fun, ctors) {
98 foreach(AbstractMetaFunction* fun, ctors) {
103 s << " ";
99 s << " ";
104 writeFunctionSignature(s, fun, 0,"PythonQtShell_",
100 writeFunctionSignature(s, fun, 0,"PythonQtShell_",
105 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
101 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
106 s << ":" << meta_class->qualifiedCppName() << "(";
102 s << ":" << meta_class->qualifiedCppName() << "(";
107 QString scriptFunctionName = fun->originalName();
103 QString scriptFunctionName = fun->originalName();
108 AbstractMetaArgumentList args = fun->arguments();
104 AbstractMetaArgumentList args = fun->arguments();
109 for (int i = 0; i < args.size(); ++i) {
105 for (int i = 0; i < args.size(); ++i) {
110 if (i > 0)
106 if (i > 0)
111 s << ", ";
107 s << ", ";
112 s << args.at(i)->argumentName();
108 s << args.at(i)->argumentName();
113 }
109 }
114 s << "),_wrapper(NULL) {};" << endl;
110 s << "),_wrapper(NULL) {};" << endl;
115 }
111 }
116 s << endl;
112 s << endl;
117
113
118 foreach(AbstractMetaFunction* fun, virtualsForShell) {
114 foreach(AbstractMetaFunction* fun, virtualsForShell) {
119 s << "virtual ";
115 s << "virtual ";
120 writeFunctionSignature(s, fun, 0, QString(),
116 writeFunctionSignature(s, fun, 0, QString(),
121 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
117 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
122 s << ";" << endl;
118 s << ";" << endl;
123 }
119 }
124 s << endl;
120 s << endl;
125 s << " PythonQtInstanceWrapper* _wrapper; " << endl;
121 s << " PythonQtInstanceWrapper* _wrapper; " << endl;
126
122
127 s << "};" << endl << endl;
123 s << "};" << endl << endl;
128 }
124 }
129
125
130 // Promoter-------------------------------------------------------------------
126 // Promoter-------------------------------------------------------------------
131 AbstractMetaFunctionList promoteFunctions = getProtectedFunctionsThatNeedPromotion(meta_class);
127 AbstractMetaFunctionList promoteFunctions = getProtectedFunctionsThatNeedPromotion(meta_class);
132 if (!promoteFunctions.isEmpty()) {
128 if (!promoteFunctions.isEmpty()) {
133 s << "class " << promoterClassName(meta_class)
129 s << "class " << promoterClassName(meta_class)
134 << " : public " << meta_class->qualifiedCppName() << endl << "{ public:" << endl;
130 << " : public " << meta_class->qualifiedCppName() << endl << "{ public:" << endl;
135
131
136 foreach(AbstractMetaFunction* fun, promoteFunctions) {
132 foreach(AbstractMetaFunction* fun, promoteFunctions) {
137 s << "inline ";
133 s << "inline ";
138 writeFunctionSignature(s, fun, 0, "promoted_",
134 writeFunctionSignature(s, fun, 0, "promoted_",
139 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
135 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
140 s << " { ";
136 s << " { ";
141 QString scriptFunctionName = fun->originalName();
137 QString scriptFunctionName = fun->originalName();
142 AbstractMetaArgumentList args = fun->arguments();
138 AbstractMetaArgumentList args = fun->arguments();
143 if (fun->type())
139 if (fun->type())
144 s << "return ";
140 s << "return ";
145 s << meta_class->qualifiedCppName() << "::";
141 s << meta_class->qualifiedCppName() << "::";
146 s << fun->originalName() << "(";
142 s << fun->originalName() << "(";
147 for (int i = 0; i < args.size(); ++i) {
143 for (int i = 0; i < args.size(); ++i) {
148 if (i > 0)
144 if (i > 0)
149 s << ", ";
145 s << ", ";
150 s << args.at(i)->argumentName();
146 s << args.at(i)->argumentName();
151 }
147 }
152 s << "); }" << endl;
148 s << "); }" << endl;
153 }
149 }
154
150
155 s << "};" << endl << endl;
151 s << "};" << endl << endl;
156 }
152 }
157
153
158 // Wrapper-------------------------------------------------------------------
154 // Wrapper-------------------------------------------------------------------
159
155
160 s << "class " << wrapperClassName(meta_class)
156 s << "class " << wrapperClassName(meta_class)
161 << " : public QObject" << endl
157 << " : public QObject" << endl
162 << "{ Q_OBJECT" << endl;
158 << "{ Q_OBJECT" << endl;
163
159
164 s << "public:" << endl;
160 s << "public:" << endl;
165
161
166 AbstractMetaEnumList enums1 = meta_class->enums();
162 AbstractMetaEnumList enums1 = meta_class->enums();
167 AbstractMetaEnumList enums;
163 AbstractMetaEnumList enums;
168 QList<FlagsTypeEntry*> flags;
164 QList<FlagsTypeEntry*> flags;
169 foreach(AbstractMetaEnum* enum1, enums1) {
165 foreach(AbstractMetaEnum* enum1, enums1) {
170 // catch gadgets and enums that are not exported on QObjects...
166 // catch gadgets and enums that are not exported on QObjects...
171 if (enum1->wasPublic() && (!meta_class->isQObject() || !enum1->hasQEnumsDeclaration())) {
167 if (enum1->wasPublic() && (!meta_class->isQObject() || !enum1->hasQEnumsDeclaration())) {
172 enums << enum1;
168 enums << enum1;
173 if (enum1->typeEntry()->flags()) {
169 if (enum1->typeEntry()->flags()) {
174 flags << enum1->typeEntry()->flags();
170 flags << enum1->typeEntry()->flags();
175 }
171 }
176 }
172 }
177 }
173 }
178 if (enums.count()) {
174 if (enums.count()) {
179 s << "Q_ENUMS(";
175 s << "Q_ENUMS(";
180 foreach(AbstractMetaEnum* enum1, enums) {
176 foreach(AbstractMetaEnum* enum1, enums) {
181 s << enum1->name() << " ";
177 s << enum1->name() << " ";
182 }
178 }
183 s << ")" << endl;
179 s << ")" << endl;
184
180
185 if (flags.count()) {
181 if (flags.count()) {
186 s << "Q_FLAGS(";
182 s << "Q_FLAGS(";
187 foreach(FlagsTypeEntry* flag1, flags) {
183 foreach(FlagsTypeEntry* flag1, flags) {
188 QString origName = flag1->originalName();
184 QString origName = flag1->originalName();
189 int idx = origName.lastIndexOf("::");
185 int idx = origName.lastIndexOf("::");
190 if (idx!= -1) {
186 if (idx!= -1) {
191 origName = origName.mid(idx+2);
187 origName = origName.mid(idx+2);
192 }
188 }
193 s << origName << " ";
189 s << origName << " ";
194 }
190 }
195 s << ")" << endl;
191 s << ")" << endl;
196 }
192 }
197
193
198 foreach(AbstractMetaEnum* enum1, enums) {
194 foreach(AbstractMetaEnum* enum1, enums) {
199 s << "enum " << enum1->name() << "{" << endl;
195 s << "enum " << enum1->name() << "{" << endl;
200 bool first = true;
196 bool first = true;
201 foreach(AbstractMetaEnumValue* value, enum1->values()) {
197 foreach(AbstractMetaEnumValue* value, enum1->values()) {
202 if (first) { first = false; }
198 if (first) { first = false; }
203 else { s << ", "; }
199 else { s << ", "; }
204 s << " " << value->name() << " = " << meta_class->qualifiedCppName() << "::" << value->name();
200 s << " " << value->name() << " = " << meta_class->qualifiedCppName() << "::" << value->name();
205 }
201 }
206 s << "};" << endl;
202 s << "};" << endl;
207 }
203 }
208 if (flags.count()) {
204 if (flags.count()) {
209 foreach(AbstractMetaEnum* enum1, enums) {
205 foreach(AbstractMetaEnum* enum1, enums) {
210 if (enum1->typeEntry()->flags()) {
206 if (enum1->typeEntry()->flags()) {
211 QString origName = enum1->typeEntry()->flags()->originalName();
207 QString origName = enum1->typeEntry()->flags()->originalName();
212 int idx = origName.lastIndexOf("::");
208 int idx = origName.lastIndexOf("::");
213 if (idx!= -1) {
209 if (idx!= -1) {
214 origName = origName.mid(idx+2);
210 origName = origName.mid(idx+2);
215 }
211 }
216 s << "Q_DECLARE_FLAGS("<< origName << ", " << enum1->name() <<")"<<endl;
212 s << "Q_DECLARE_FLAGS("<< origName << ", " << enum1->name() <<")"<<endl;
217 }
213 }
218 }
214 }
219 }
215 }
220 }
216 }
221 s << "public slots:" << endl;
217 s << "public slots:" << endl;
222 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
218 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
223
219
224 bool copyConstructorSeen = false;
220 bool copyConstructorSeen = false;
225 bool defaultConstructorSeen = false;
221 bool defaultConstructorSeen = false;
226 foreach (const AbstractMetaFunction *fun, ctors) {
222 foreach (const AbstractMetaFunction *fun, ctors) {
227 if (!fun->isPublic() || fun->isAbstract()) { continue; }
223 if (!fun->isPublic() || fun->isAbstract()) { continue; }
228 s << meta_class->qualifiedCppName() << "* ";
224 s << meta_class->qualifiedCppName() << "* ";
229 writeFunctionSignature(s, fun, 0, "new_",
225 writeFunctionSignature(s, fun, 0, "new_",
230 Option(IncludeDefaultExpression | OriginalName | ShowStatic));
226 Option(IncludeDefaultExpression | OriginalName | ShowStatic));
231 s << ";" << endl;
227 s << ";" << endl;
232 if (fun->arguments().size()==1 && meta_class->qualifiedCppName() == fun->arguments().at(0)->type()->typeEntry()->qualifiedCppName()) {
228 if (fun->arguments().size()==1 && meta_class->qualifiedCppName() == fun->arguments().at(0)->type()->typeEntry()->qualifiedCppName()) {
233 copyConstructorSeen = true;
229 copyConstructorSeen = true;
234 }
230 }
235 if (fun->arguments().size()==0) {
231 if (fun->arguments().size()==0) {
236 defaultConstructorSeen = true;
232 defaultConstructorSeen = true;
237 }
233 }
238 }
234 }
239
235
240 if (meta_class->typeEntry()->isValue()
236 if (meta_class->typeEntry()->isValue()
241 && !copyConstructorSeen && defaultConstructorSeen) {
237 && !copyConstructorSeen && defaultConstructorSeen) {
242 QString className = meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName();
238 QString className = meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName();
243 s << meta_class->qualifiedCppName() << "* new_" << meta_class->name() << "(const " << meta_class->qualifiedCppName() << "& other) {" << endl;
239 s << meta_class->qualifiedCppName() << "* new_" << meta_class->name() << "(const " << meta_class->qualifiedCppName() << "& other) {" << endl;
244 s << className << "* a = new " << className << "();" << endl;
240 s << className << "* a = new " << className << "();" << endl;
245 s << "*((" << meta_class->qualifiedCppName() << "*)a) = other;" << endl;
241 s << "*((" << meta_class->qualifiedCppName() << "*)a) = other;" << endl;
246 s << "return a; }" << endl;
242 s << "return a; }" << endl;
247 }
243 }
248 }
244 }
249 if (meta_class->hasPublicDestructor() && !meta_class->isNamespace()) {
245 if (meta_class->hasPublicDestructor() && !meta_class->isNamespace()) {
250 s << "void delete_" << meta_class->name() << "(" << meta_class->qualifiedCppName() << "* obj) { delete obj; } ";
246 s << "void delete_" << meta_class->name() << "(" << meta_class->qualifiedCppName() << "* obj) { delete obj; } ";
251 s << endl;
247 s << endl;
252 }
248 }
253 if (meta_class->name()=="QTreeWidgetItem") {
249 if (meta_class->name()=="QTreeWidgetItem") {
254 s << "bool hasOwner(QTreeWidgetItem* theWrappedObject) { return theWrappedObject->treeWidget()!=NULL || theWrappedObject->parent()!=NULL; }" << endl;
250 s << "bool hasOwner(QTreeWidgetItem* theWrappedObject) { return theWrappedObject->treeWidget()!=NULL || theWrappedObject->parent()!=NULL; }" << endl;
255 } else if (meta_class->name()=="QGraphicsItem") {
251 } else if (meta_class->name()=="QGraphicsItem") {
256 s << "bool hasOwner(QGraphicsItem* theWrappedObject) { return theWrappedObject->scene()!=NULL || theWrappedObject->parentItem()!=NULL; }" << endl;
252 s << "bool hasOwner(QGraphicsItem* theWrappedObject) { return theWrappedObject->scene()!=NULL || theWrappedObject->parentItem()!=NULL; }" << endl;
257 }
253 }
258
254
259 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
255 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
260
256
261 foreach (const AbstractMetaFunction *function, functions) {
257 foreach (const AbstractMetaFunction *function, functions) {
262 if (!function->isSlot()) {
258 if (!function->isSlot()) {
263 s << " ";
259 s << " ";
264 writeFunctionSignature(s, function, 0, QString(),
260 writeFunctionSignature(s, function, 0, QString(),
265 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
261 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
266 s << ";" << endl;
262 s << ";" << endl;
267 }
263 }
268 }
264 }
269 if (!meta_class->hasDefaultToStringFunction() && meta_class->hasToStringCapability()) {
265 if (!meta_class->hasDefaultToStringFunction() && meta_class->hasToStringCapability()) {
270 s << " QString toString(" << meta_class->qualifiedCppName() << "*);" << endl;
266 s << " QString toString(" << meta_class->qualifiedCppName() << "*);" << endl;
271 }
267 }
272
268
273 // writeInjectedCode(s, meta_class);
269 // writeInjectedCode(s, meta_class);
274
270
275 // s << endl << " QScriptValue __qtscript_self;" << endl;
271 // s << endl << " QScriptValue __qtscript_self;" << endl;
276
272
277 s << "};" << endl << endl
273 s << "};" << endl << endl
278 << "#endif // " << include_block << endl;
274 << "#endif // " << include_block << endl;
279
275
280 if (!ShellGenerator::isBuiltIn(meta_class->name())) {
276 if (!ShellGenerator::isBuiltIn(meta_class->name())) {
281 priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
277 priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
282 }
278 }
283 }
279 }
284
280
285 void ShellHeaderGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
281 void ShellHeaderGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
286 {
282 {
287 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
283 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
288 foreach (const CodeSnip &cs, code_snips) {
284 foreach (const CodeSnip &cs, code_snips) {
289 if (cs.language == TypeSystem::ShellDeclaration) {
285 if (cs.language == TypeSystem::ShellDeclaration) {
290 s << cs.code() << endl;
286 s << cs.code() << endl;
291 }
287 }
292 }
288 }
293 }
289 }
@@ -1,313 +1,309
1 /****************************************************************************
1 /****************************************************************************
2 **
2 **
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
3 ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
6 **
6 **
7 ** This file is part of the Qt Script Generator project on Qt Labs.
7 ** This file is part of the Qt Script Generator project on Qt Labs.
8 **
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
14 ** this package.
15 **
15 **
16 ** GNU Lesser General Public License Usage
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23 **
23 **
24 ** In addition, as a special exception, Nokia gives you certain additional
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27 **
27 **
28 ** If you have questions regarding the use of this file, please contact
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
29 ** Nokia at qt-info@nokia.com.
30 **
30 **
31 **
31 **
32 **
32 **
33 **
33 **
34 **
34 **
35 **
35 **
36 **
36 **
37 **
37 **
38 ** $QT_END_LICENSE$
38 ** $QT_END_LICENSE$
39 **
39 **
40 ****************************************************************************/
40 ****************************************************************************/
41
41
42 #include "shellimplgenerator.h"
42 #include "shellimplgenerator.h"
43 #include "reporthandler.h"
43 #include "reporthandler.h"
44 #include "fileout.h"
44 #include "fileout.h"
45
45
46 extern void declareFunctionMetaTypes(QTextStream &stream,
46 extern void declareFunctionMetaTypes(QTextStream &stream,
47 const AbstractMetaFunctionList &functions,
47 const AbstractMetaFunctionList &functions,
48 QSet<QString> &registeredTypeNames);
48 QSet<QString> &registeredTypeNames);
49
49
50 QString ShellImplGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
50 QString ShellImplGenerator::fileNameForClass(const AbstractMetaClass *meta_class) const
51 {
51 {
52 return QString("PythonQtWrapper_%1.cpp").arg(meta_class->name());
52 return QString("PythonQtWrapper_%1.cpp").arg(meta_class->name());
53 }
53 }
54
54
55 static bool include_less_than(const Include &a, const Include &b)
55 static bool include_less_than(const Include &a, const Include &b)
56 {
56 {
57 return a.name < b.name;
57 return a.name < b.name;
58 }
58 }
59
59
60 static void writeHelperCode(QTextStream &s, const AbstractMetaClass *)
60 static void writeHelperCode(QTextStream &s, const AbstractMetaClass *)
61 {
61 {
62 }
62 }
63
63
64 void writeQtScriptQtBindingsLicense(QTextStream &stream);
65
66 void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
64 void ShellImplGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
67 {
65 {
68 if (FileOut::license)
69 writeQtScriptQtBindingsLicense(s);
70
66
71 QString pro_file_name = meta_class->package().replace(".", "_") + "/" + meta_class->package().replace(".", "_") + ".pri";
67 QString pro_file_name = meta_class->package().replace(".", "_") + "/" + meta_class->package().replace(".", "_") + ".pri";
72
68
73 if (!ShellGenerator::isBuiltIn(meta_class->name())) {
69 if (!ShellGenerator::isBuiltIn(meta_class->name())) {
74 priGenerator->addSource(pro_file_name, fileNameForClass(meta_class));
70 priGenerator->addSource(pro_file_name, fileNameForClass(meta_class));
75 }
71 }
76
72
77 s << "#include \"PythonQtWrapper_" << meta_class->name() << ".h\"" << endl << endl;
73 s << "#include \"PythonQtWrapper_" << meta_class->name() << ".h\"" << endl << endl;
78
74
79 s << "#include <PythonQtSignalReceiver.h>" << endl;
75 s << "#include <PythonQtSignalReceiver.h>" << endl;
80 s << "#include <PythonQtMethodInfo.h>" << endl;
76 s << "#include <PythonQtMethodInfo.h>" << endl;
81 s << "#include <PythonQtConversion.h>" << endl;
77 s << "#include <PythonQtConversion.h>" << endl;
82
78
83 //if (!meta_class->generateShellClass())
79 //if (!meta_class->generateShellClass())
84 // return;
80 // return;
85
81
86 IncludeList list = meta_class->typeEntry()->extraIncludes();
82 IncludeList list = meta_class->typeEntry()->extraIncludes();
87 qSort(list.begin(), list.end());
83 qSort(list.begin(), list.end());
88 foreach (const Include &inc, list) {
84 foreach (const Include &inc, list) {
89 ShellGenerator::writeInclude(s, inc);
85 ShellGenerator::writeInclude(s, inc);
90 }
86 }
91 s << endl;
87 s << endl;
92
88
93 writeHelperCode(s, meta_class);
89 writeHelperCode(s, meta_class);
94
90
95 // find constructors
91 // find constructors
96 AbstractMetaFunctionList ctors;
92 AbstractMetaFunctionList ctors;
97 ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
93 ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
98 | AbstractMetaClass::WasVisible
94 | AbstractMetaClass::WasVisible
99 | AbstractMetaClass::NotRemovedFromTargetLang);
95 | AbstractMetaClass::NotRemovedFromTargetLang);
100 // find member functions
96 // find member functions
101 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
97 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
102
98
103 // write metatype declarations
99 // write metatype declarations
104 {
100 {
105 // QSet<QString> registeredTypeNames = m_qmetatype_declared_typenames;
101 // QSet<QString> registeredTypeNames = m_qmetatype_declared_typenames;
106 // declareFunctionMetaTypes(s, functions, registeredTypeNames);
102 // declareFunctionMetaTypes(s, functions, registeredTypeNames);
107 // s << endl;
103 // s << endl;
108 }
104 }
109
105
110 if (meta_class->generateShellClass()) {
106 if (meta_class->generateShellClass()) {
111 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
107 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
112 foreach (const AbstractMetaFunction *fun, virtualsForShell) {
108 foreach (const AbstractMetaFunction *fun, virtualsForShell) {
113 bool hasReturnValue = (fun->type());
109 bool hasReturnValue = (fun->type());
114 writeFunctionSignature(s, fun, meta_class, QString(),
110 writeFunctionSignature(s, fun, meta_class, QString(),
115 Option(OriginalName | ShowStatic | UnderscoreSpaces),
111 Option(OriginalName | ShowStatic | UnderscoreSpaces),
116 "PythonQtShell_");
112 "PythonQtShell_");
117 s << endl << "{" << endl;
113 s << endl << "{" << endl;
118
114
119 Option typeOptions = Option(OriginalName | UnderscoreSpaces | SkipName);
115 Option typeOptions = Option(OriginalName | UnderscoreSpaces | SkipName);
120 AbstractMetaArgumentList args = fun->arguments();
116 AbstractMetaArgumentList args = fun->arguments();
121
117
122 s << "if (_wrapper) {" << endl;
118 s << "if (_wrapper) {" << endl;
123 s << " PyObject* obj = PyObject_GetAttrString((PyObject*)_wrapper, \"" << fun->name() << "\");" << endl;
119 s << " PyObject* obj = PyObject_GetAttrString((PyObject*)_wrapper, \"" << fun->name() << "\");" << endl;
124 s << " PyErr_Clear();" << endl;
120 s << " PyErr_Clear();" << endl;
125 s << " if (obj && !PythonQtSlotFunction_Check(obj)) {" << endl;
121 s << " if (obj && !PythonQtSlotFunction_Check(obj)) {" << endl;
126 s << " static const char* argumentList[] ={\"";
122 s << " static const char* argumentList[] ={\"";
127 if (hasReturnValue) {
123 if (hasReturnValue) {
128 // write the arguments, return type first
124 // write the arguments, return type first
129 writeTypeInfo(s, fun->type(), typeOptions);
125 writeTypeInfo(s, fun->type(), typeOptions);
130 }
126 }
131 s << "\"";
127 s << "\"";
132 for (int i = 0; i < args.size(); ++i) {
128 for (int i = 0; i < args.size(); ++i) {
133 s << " , \"";
129 s << " , \"";
134 writeTypeInfo(s, args.at(i)->type(), typeOptions);
130 writeTypeInfo(s, args.at(i)->type(), typeOptions);
135 s << "\"";
131 s << "\"";
136 }
132 }
137 s << "};" << endl;
133 s << "};" << endl;
138 s << " static const PythonQtMethodInfo* methodInfo = PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(" << QString::number(args.size()+1) << ", argumentList);" << endl;
134 s << " static const PythonQtMethodInfo* methodInfo = PythonQtMethodInfo::getCachedMethodInfoFromArgumentList(" << QString::number(args.size()+1) << ", argumentList);" << endl;
139
135
140 if (hasReturnValue) {
136 if (hasReturnValue) {
141 s << " ";
137 s << " ";
142 writeTypeInfo(s, fun->type(), typeOptions);
138 writeTypeInfo(s, fun->type(), typeOptions);
143 s << " returnValue;" << endl;
139 s << " returnValue;" << endl;
144 // TODO: POD init to default is missing...
140 // TODO: POD init to default is missing...
145 }
141 }
146 s << " void* args[" << QString::number(args.size()+1) << "] = {NULL";
142 s << " void* args[" << QString::number(args.size()+1) << "] = {NULL";
147 for (int i = 0; i < args.size(); ++i) {
143 for (int i = 0; i < args.size(); ++i) {
148 s << ", (void*)&" << args.at(i)->argumentName();
144 s << ", (void*)&" << args.at(i)->argumentName();
149 }
145 }
150 s << "};" << endl;
146 s << "};" << endl;
151
147
152 s << " PyObject* result = PythonQtSignalTarget::call(obj, methodInfo, args, true);" << endl;
148 s << " PyObject* result = PythonQtSignalTarget::call(obj, methodInfo, args, true);" << endl;
153 if (hasReturnValue) {
149 if (hasReturnValue) {
154 s << " if (result) {" << endl;
150 s << " if (result) {" << endl;
155 s << " args[0] = PythonQtConv::ConvertPythonToQt(methodInfo->parameters().at(0), result, false, NULL, &returnValue);" << endl;
151 s << " args[0] = PythonQtConv::ConvertPythonToQt(methodInfo->parameters().at(0), result, false, NULL, &returnValue);" << endl;
156 s << " if (args[0]!=&returnValue) {" << endl;
152 s << " if (args[0]!=&returnValue) {" << endl;
157 s << " if (args[0]==NULL) {" << endl;
153 s << " if (args[0]==NULL) {" << endl;
158 s << " PythonQt::priv()->handleVirtualOverloadReturnError(\"" << fun->name() << "\", methodInfo, result);" << endl;
154 s << " PythonQt::priv()->handleVirtualOverloadReturnError(\"" << fun->name() << "\", methodInfo, result);" << endl;
159 s << " } else {" << endl;
155 s << " } else {" << endl;
160 s << " returnValue = *((";
156 s << " returnValue = *((";
161 writeTypeInfo(s, fun->type(), typeOptions);
157 writeTypeInfo(s, fun->type(), typeOptions);
162 s << "*)args[0]);" << endl;
158 s << "*)args[0]);" << endl;
163 s << " }" << endl;
159 s << " }" << endl;
164 s << " }" << endl;
160 s << " }" << endl;
165 s << " }" << endl;
161 s << " }" << endl;
166 }
162 }
167 s << " if (result) { Py_DECREF(result); } " << endl;
163 s << " if (result) { Py_DECREF(result); } " << endl;
168 s << " Py_DECREF(obj);" << endl;
164 s << " Py_DECREF(obj);" << endl;
169 if (hasReturnValue) {
165 if (hasReturnValue) {
170 s << " return returnValue;" << endl;
166 s << " return returnValue;" << endl;
171 } else {
167 } else {
172 s << " return;" << endl;
168 s << " return;" << endl;
173 }
169 }
174 s << " }" << endl;
170 s << " }" << endl;
175 s << "}" << endl;
171 s << "}" << endl;
176
172
177 s << " ";
173 s << " ";
178 if (fun->isAbstract()) {
174 if (fun->isAbstract()) {
179 if (fun->type()) {
175 if (fun->type()) {
180 // return empty default object
176 // return empty default object
181 writeTypeInfo(s, fun->type(), typeOptions);
177 writeTypeInfo(s, fun->type(), typeOptions);
182 s << " result;" << endl;
178 s << " result;" << endl;
183 s << "return result";
179 s << "return result";
184 s << ";";
180 s << ";";
185 }
181 }
186 } else {
182 } else {
187 if (fun->type()) {
183 if (fun->type()) {
188 s << "return ";
184 s << "return ";
189 }
185 }
190 s << meta_class->qualifiedCppName() << "::";
186 s << meta_class->qualifiedCppName() << "::";
191 s << fun->originalName() << "(";
187 s << fun->originalName() << "(";
192 for (int i = 0; i < args.size(); ++i) {
188 for (int i = 0; i < args.size(); ++i) {
193 if (i > 0)
189 if (i > 0)
194 s << ", ";
190 s << ", ";
195 s << args.at(i)->argumentName();
191 s << args.at(i)->argumentName();
196 }
192 }
197 s << ");";
193 s << ");";
198 }
194 }
199 s << endl << "}" << endl;
195 s << endl << "}" << endl;
200 }
196 }
201 }
197 }
202
198
203 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
199 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
204
200
205 // write constructors
201 // write constructors
206 foreach (const AbstractMetaFunction *ctor, ctors) {
202 foreach (const AbstractMetaFunction *ctor, ctors) {
207 if (!ctor->isPublic() || ctor->isAbstract()) { continue; }
203 if (!ctor->isPublic() || ctor->isAbstract()) { continue; }
208
204
209 s << meta_class->qualifiedCppName() << "* ";
205 s << meta_class->qualifiedCppName() << "* ";
210 s << "PythonQtWrapper_" << meta_class->name() << "::";
206 s << "PythonQtWrapper_" << meta_class->name() << "::";
211 writeFunctionSignature(s, ctor, 0, "new_", Option(OriginalName | ShowStatic));
207 writeFunctionSignature(s, ctor, 0, "new_", Option(OriginalName | ShowStatic));
212 s << endl;
208 s << endl;
213 s << "{ " << endl;
209 s << "{ " << endl;
214 s << "return new " << (meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName()) << "(";
210 s << "return new " << (meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName()) << "(";
215 AbstractMetaArgumentList args = ctor->arguments();
211 AbstractMetaArgumentList args = ctor->arguments();
216 for (int i = 0; i < args.size(); ++i) {
212 for (int i = 0; i < args.size(); ++i) {
217 if (i > 0)
213 if (i > 0)
218 s << ", ";
214 s << ", ";
219 s << args.at(i)->argumentName();
215 s << args.at(i)->argumentName();
220 }
216 }
221 s << ");" << " }" << endl << endl;
217 s << ");" << " }" << endl << endl;
222 }
218 }
223 }
219 }
224
220
225 QString wrappedObject = " (*theWrappedObject)";
221 QString wrappedObject = " (*theWrappedObject)";
226
222
227 // write member functions
223 // write member functions
228 for (int i = 0; i < functions.size(); ++i) {
224 for (int i = 0; i < functions.size(); ++i) {
229 AbstractMetaFunction *fun = functions.at(i);
225 AbstractMetaFunction *fun = functions.at(i);
230 if (fun->isSlot()) continue;
226 if (fun->isSlot()) continue;
231
227
232 writeFunctionSignature(s, fun, meta_class, QString(),
228 writeFunctionSignature(s, fun, meta_class, QString(),
233 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject | OriginalName | ShowStatic | UnderscoreSpaces),
229 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject | OriginalName | ShowStatic | UnderscoreSpaces),
234 "PythonQtWrapper_");
230 "PythonQtWrapper_");
235 s << endl << "{" << endl;
231 s << endl << "{" << endl;
236 s << " ";
232 s << " ";
237 if (ShellGenerator::isSpecialStreamingOperator(fun)) {
233 if (ShellGenerator::isSpecialStreamingOperator(fun)) {
238 s << fun->arguments().at(0)->argumentName();
234 s << fun->arguments().at(0)->argumentName();
239 if (fun->originalName().startsWith("operator>>")) {
235 if (fun->originalName().startsWith("operator>>")) {
240 s << " >> ";
236 s << " >> ";
241 } else {
237 } else {
242 s << " << ";
238 s << " << ";
243 }
239 }
244 s << wrappedObject;
240 s << wrappedObject;
245 } else {
241 } else {
246 QString scriptFunctionName = fun->originalName();
242 QString scriptFunctionName = fun->originalName();
247 AbstractMetaArgumentList args = fun->arguments();
243 AbstractMetaArgumentList args = fun->arguments();
248 // call the C++ implementation
244 // call the C++ implementation
249 if (fun->type()) {
245 if (fun->type()) {
250 s << "return ";
246 s << "return ";
251 // call the C++ implementation
247 // call the C++ implementation
252 if (fun->type()->isReference()) {
248 if (fun->type()->isReference()) {
253 s << "&";
249 s << "&";
254 }
250 }
255 }
251 }
256 s << "(";
252 s << "(";
257 if (scriptFunctionName.startsWith("operator>>")) {
253 if (scriptFunctionName.startsWith("operator>>")) {
258 s << wrappedObject << " >>" << args.at(0)->argumentName();
254 s << wrappedObject << " >>" << args.at(0)->argumentName();
259 } else if (scriptFunctionName.startsWith("operator<<")) {
255 } else if (scriptFunctionName.startsWith("operator<<")) {
260 s << wrappedObject << " <<" << args.at(0)->argumentName();
256 s << wrappedObject << " <<" << args.at(0)->argumentName();
261 } else if (scriptFunctionName.startsWith("operator[]")) {
257 } else if (scriptFunctionName.startsWith("operator[]")) {
262 s << wrappedObject << "[" << args.at(0)->argumentName() << "]";
258 s << wrappedObject << "[" << args.at(0)->argumentName() << "]";
263 } else if (scriptFunctionName.startsWith("operator") && args.size()==1) {
259 } else if (scriptFunctionName.startsWith("operator") && args.size()==1) {
264 QString op = scriptFunctionName.mid(8);
260 QString op = scriptFunctionName.mid(8);
265 s << wrappedObject << op << " " << args.at(0)->argumentName();
261 s << wrappedObject << op << " " << args.at(0)->argumentName();
266 } else {
262 } else {
267 if (fun->isStatic()) {
263 if (fun->isStatic()) {
268 s << meta_class->qualifiedCppName() << "::";
264 s << meta_class->qualifiedCppName() << "::";
269 } else {
265 } else {
270 if (!fun->isPublic() || fun->isVirtual()) {
266 if (!fun->isPublic() || fun->isVirtual()) {
271 s << " ((" << promoterClassName(meta_class) << "*)theWrappedObject)->promoted_";
267 s << " ((" << promoterClassName(meta_class) << "*)theWrappedObject)->promoted_";
272 } else {
268 } else {
273 s << " theWrappedObject->";
269 s << " theWrappedObject->";
274 }
270 }
275 }
271 }
276 s << fun->originalName() << "(";
272 s << fun->originalName() << "(";
277 for (int i = 0; i < args.size(); ++i) {
273 for (int i = 0; i < args.size(); ++i) {
278 if (i > 0)
274 if (i > 0)
279 s << ", ";
275 s << ", ";
280 s << args.at(i)->argumentName();
276 s << args.at(i)->argumentName();
281 }
277 }
282 s << ")";
278 s << ")";
283 }
279 }
284 s << ")";
280 s << ")";
285 }
281 }
286 s << ";" << endl;
282 s << ";" << endl;
287
283
288 s << "}" << endl << endl;
284 s << "}" << endl << endl;
289 }
285 }
290
286
291 if (!meta_class->hasDefaultToStringFunction() && meta_class->hasToStringCapability()) {
287 if (!meta_class->hasDefaultToStringFunction() && meta_class->hasToStringCapability()) {
292 FunctionModelItem fun = meta_class->hasToStringCapability();
288 FunctionModelItem fun = meta_class->hasToStringCapability();
293 int indirections = fun->arguments().at(1)->type().indirections();
289 int indirections = fun->arguments().at(1)->type().indirections();
294 QString deref = QLatin1String(indirections == 0 ? "*" : "");
290 QString deref = QLatin1String(indirections == 0 ? "*" : "");
295 s << "QString PythonQtWrapper_" << meta_class->name() << "::toString(" << meta_class->qualifiedCppName() << "* obj) {" << endl;
291 s << "QString PythonQtWrapper_" << meta_class->name() << "::toString(" << meta_class->qualifiedCppName() << "* obj) {" << endl;
296 s << " QString result;" << endl;
292 s << " QString result;" << endl;
297 s << " QDebug d(&result);" << endl;
293 s << " QDebug d(&result);" << endl;
298 s << " d << " << deref << "obj;" << endl;
294 s << " d << " << deref << "obj;" << endl;
299 s << " return result;" << endl;
295 s << " return result;" << endl;
300 s << "}" << endl << endl;
296 s << "}" << endl << endl;
301 }
297 }
302
298
303 }
299 }
304
300
305 void ShellImplGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
301 void ShellImplGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
306 {
302 {
307 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
303 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
308 foreach (const CodeSnip &cs, code_snips) {
304 foreach (const CodeSnip &cs, code_snips) {
309 if (cs.language == TypeSystem::ShellCode) {
305 if (cs.language == TypeSystem::ShellCode) {
310 s << cs.code() << endl;
306 s << cs.code() << endl;
311 }
307 }
312 }
308 }
313 }
309 }
General Comments 0
You need to be logged in to leave comments. Login now