@@ -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> ®isteredTypeNames) |
|
1041 | QSet<QString> ®isteredTypeNames) | |
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> ®isteredTypeNames) |
|
1074 | QSet<QString> ®isteredTypeNames) | |
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> ®isteredTypeNames) |
|
1091 | QSet<QString> ®isteredTypeNames) | |
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> ®isteredTypeNames) |
|
1134 | QSet<QString> ®isteredTypeNames) | |
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 |
|
|
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> ®isteredTypeNames); |
|
55 | QSet<QString> ®isteredTypeNames); | |
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 \"" << |
|
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 |
|
|
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 |
|
|
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> ®isteredTypeNames); |
|
48 | QSet<QString> ®isteredTypeNames); | |
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