##// END OF EJS Templates
added support for operators and rich compare...
florianlink -
r119:609e1e5898f0
parent child
Show More
@@ -1,2634 +1,2634
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 "abstractmetabuilder.h"
42 #include "abstractmetabuilder.h"
43 #include "reporthandler.h"
43 #include "reporthandler.h"
44
44
45 #include "ast.h"
45 #include "ast.h"
46 #include "binder.h"
46 #include "binder.h"
47 #include "control.h"
47 #include "control.h"
48 #include "default_visitor.h"
48 #include "default_visitor.h"
49 #include "dumptree.h"
49 #include "dumptree.h"
50 #include "lexer.h"
50 #include "lexer.h"
51 #include "parser.h"
51 #include "parser.h"
52 #include "tokens.h"
52 #include "tokens.h"
53
53
54 #include <QtCore/QDebug>
54 #include <QtCore/QDebug>
55 #include <QtCore/QFile>
55 #include <QtCore/QFile>
56 #include <QtCore/QFileInfo>
56 #include <QtCore/QFileInfo>
57 #include <QtCore/QTextCodec>
57 #include <QtCore/QTextCodec>
58 #include <QtCore/QTextStream>
58 #include <QtCore/QTextStream>
59 #include <QtCore/QVariant>
59 #include <QtCore/QVariant>
60
60
61 static QString strip_template_args(const QString &name)
61 static QString strip_template_args(const QString &name)
62 {
62 {
63 int pos = name.indexOf('<');
63 int pos = name.indexOf('<');
64 return pos < 0 ? name : name.left(pos);
64 return pos < 0 ? name : name.left(pos);
65 }
65 }
66
66
67 static QHash<QString, QString> *operator_names;
67 static QHash<QString, QString> *operator_names;
68 QString rename_operator(const QString &oper)
68 QString rename_operator(const QString &oper)
69 {
69 {
70 QString op = oper.trimmed();
70 QString op = oper.trimmed();
71 if (!operator_names) {
71 if (!operator_names) {
72 operator_names = new QHash<QString, QString>;
72 operator_names = new QHash<QString, QString>;
73
73
74 operator_names->insert("+", "__add__");
74 operator_names->insert("+", "__add__");
75 operator_names->insert("-", "__sub__");
75 operator_names->insert("-", "__sub__");
76 operator_names->insert("*", "__mul__");
76 operator_names->insert("*", "__mul__");
77 operator_names->insert("/", "__div__");
77 operator_names->insert("/", "__div__");
78 operator_names->insert("%", "__mod__");
78 operator_names->insert("%", "__mod__");
79 operator_names->insert("&", "__and__");
79 operator_names->insert("&", "__and__");
80 operator_names->insert("|", "__or__");
80 operator_names->insert("|", "__or__");
81 operator_names->insert("^", "__xor__");
81 operator_names->insert("^", "__xor__");
82 operator_names->insert("~", "__negate__");
82 operator_names->insert("~", "__invert__");
83 operator_names->insert("<<", "__lshift__");
83 operator_names->insert("<<", "__lshift__");
84 operator_names->insert(">>", "__rshift__");
84 operator_names->insert(">>", "__rshift__");
85
85
86 // assigments
86 // assigments
87 operator_names->insert("=", "assign");
87 operator_names->insert("=", "assign");
88 operator_names->insert("+=", "__iadd__");
88 operator_names->insert("+=", "__iadd__");
89 operator_names->insert("-=", "__isub__");
89 operator_names->insert("-=", "__isub__");
90 operator_names->insert("*=", "__imul__");
90 operator_names->insert("*=", "__imul__");
91 operator_names->insert("/=", "__idiv__");
91 operator_names->insert("/=", "__idiv__");
92 operator_names->insert("%=", "__imod__");
92 operator_names->insert("%=", "__imod__");
93 operator_names->insert("&=", "__iand__");
93 operator_names->insert("&=", "__iand__");
94 operator_names->insert("|=", "__ior__");
94 operator_names->insert("|=", "__ior__");
95 operator_names->insert("^=", "__ixor__");
95 operator_names->insert("^=", "__ixor__");
96 operator_names->insert("<<=", "__ilshift__");
96 operator_names->insert("<<=", "__ilshift__");
97 operator_names->insert(">>=", "__irshift__");
97 operator_names->insert(">>=", "__irshift__");
98
98
99 // Logical
99 // Logical
100 operator_names->insert("&&", "logical_and");
100 operator_names->insert("&&", "logical_and");
101 operator_names->insert("||", "logical_or");
101 operator_names->insert("||", "logical_or");
102 operator_names->insert("!", "not");
102 operator_names->insert("!", "not");
103
103
104 // incr/decr
104 // incr/decr
105 operator_names->insert("++", "increment");
105 operator_names->insert("++", "increment");
106 operator_names->insert("--", "decrement");
106 operator_names->insert("--", "decrement");
107
107
108 // compare
108 // compare
109 operator_names->insert("<", "less");
109 operator_names->insert("<", "__lt__");
110 operator_names->insert(">", "greater");
110 operator_names->insert(">", "__gt__");
111 operator_names->insert("<=", "less_or_equal");
111 operator_names->insert("<=", "__le__");
112 operator_names->insert(">=", "greater_or_equal");
112 operator_names->insert(">=", "__ge__");
113 operator_names->insert("!=", "not_equal");
113 operator_names->insert("!=", "__ne__");
114 operator_names->insert("==", "equal");
114 operator_names->insert("==", "__eq__");
115
115
116 // other
116 // other
117 operator_names->insert("[]", "subscript");
117 operator_names->insert("[]", "subscript");
118 operator_names->insert("->", "pointer");
118 operator_names->insert("->", "pointer");
119 }
119 }
120
120
121 if (!operator_names->contains(op)) {
121 if (!operator_names->contains(op)) {
122 TypeDatabase *tb = TypeDatabase::instance();
122 TypeDatabase *tb = TypeDatabase::instance();
123
123
124 TypeParser::Info typeInfo = TypeParser::parse(op);
124 TypeParser::Info typeInfo = TypeParser::parse(op);
125 QString cast_to_name = typeInfo.qualified_name.join("::");
125 QString cast_to_name = typeInfo.qualified_name.join("::");
126 TypeEntry *te = tb->findType(cast_to_name);
126 TypeEntry *te = tb->findType(cast_to_name);
127 if ((te && te->codeGeneration() == TypeEntry::GenerateNothing)
127 if ((te && te->codeGeneration() == TypeEntry::GenerateNothing)
128 || tb->isClassRejected(cast_to_name)) {
128 || tb->isClassRejected(cast_to_name)) {
129 return QString();
129 return QString();
130 } else if (te) {
130 } else if (te) {
131 return "operator_cast_" + typeInfo.qualified_name.join("_");
131 return "operator_cast_" + typeInfo.qualified_name.join("_");
132 } else {
132 } else {
133 ReportHandler::warning(QString("unknown operator '%1'").arg(op));
133 ReportHandler::warning(QString("unknown operator '%1'").arg(op));
134 return "operator " + op;
134 return "operator " + op;
135 }
135 }
136 }
136 }
137
137
138 QString r = operator_names->value(op);
138 QString r = operator_names->value(op);
139 if (r.startsWith("__")) {
139 if (r.startsWith("__")) {
140 return r;
140 return r;
141 } else {
141 } else {
142 return "operator_" + r;
142 return "operator_" + r;
143 }
143 }
144 }
144 }
145
145
146 AbstractMetaBuilder::AbstractMetaBuilder()
146 AbstractMetaBuilder::AbstractMetaBuilder()
147 : m_current_class(0)
147 : m_current_class(0)
148 {
148 {
149 }
149 }
150
150
151 void AbstractMetaBuilder::checkFunctionModifications()
151 void AbstractMetaBuilder::checkFunctionModifications()
152 {
152 {
153 TypeDatabase *types = TypeDatabase::instance();
153 TypeDatabase *types = TypeDatabase::instance();
154 SingleTypeEntryHash entryHash = types->entries();
154 SingleTypeEntryHash entryHash = types->entries();
155 QList<TypeEntry *> entries = entryHash.values();
155 QList<TypeEntry *> entries = entryHash.values();
156 foreach (TypeEntry *entry, entries) {
156 foreach (TypeEntry *entry, entries) {
157 if (entry == 0)
157 if (entry == 0)
158 continue;
158 continue;
159 if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
159 if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
160 continue;
160 continue;
161
161
162 ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(entry);
162 ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(entry);
163 FunctionModificationList modifications = centry->functionModifications();
163 FunctionModificationList modifications = centry->functionModifications();
164
164
165 foreach (FunctionModification modification, modifications) {
165 foreach (FunctionModification modification, modifications) {
166 QString signature = modification.signature;
166 QString signature = modification.signature;
167
167
168 QString name = signature.trimmed();
168 QString name = signature.trimmed();
169 name = name.mid(0, signature.indexOf("("));
169 name = name.mid(0, signature.indexOf("("));
170
170
171 AbstractMetaClass *clazz = m_meta_classes.findClass(centry->qualifiedCppName());
171 AbstractMetaClass *clazz = m_meta_classes.findClass(centry->qualifiedCppName());
172 if (clazz == 0)
172 if (clazz == 0)
173 continue;
173 continue;
174
174
175 AbstractMetaFunctionList functions = clazz->functions();
175 AbstractMetaFunctionList functions = clazz->functions();
176 bool found = false;
176 bool found = false;
177 QStringList possibleSignatures;
177 QStringList possibleSignatures;
178 foreach (AbstractMetaFunction *function, functions) {
178 foreach (AbstractMetaFunction *function, functions) {
179 if (function->minimalSignature() == signature && function->implementingClass() == clazz) {
179 if (function->minimalSignature() == signature && function->implementingClass() == clazz) {
180 found = true;
180 found = true;
181 break;
181 break;
182 }
182 }
183
183
184 if (function->originalName() == name)
184 if (function->originalName() == name)
185 possibleSignatures.append(function->minimalSignature() + " in " + function->implementingClass()->name());
185 possibleSignatures.append(function->minimalSignature() + " in " + function->implementingClass()->name());
186 }
186 }
187
187
188 if (!found) {
188 if (!found) {
189 QString warning
189 QString warning
190 = QString("signature '%1' for function modification in '%2' not found. Possible candidates: %3")
190 = QString("signature '%1' for function modification in '%2' not found. Possible candidates: %3")
191 .arg(signature)
191 .arg(signature)
192 .arg(clazz->qualifiedCppName())
192 .arg(clazz->qualifiedCppName())
193 .arg(possibleSignatures.join(", "));
193 .arg(possibleSignatures.join(", "));
194
194
195 ReportHandler::warning(warning);
195 ReportHandler::warning(warning);
196 }
196 }
197 }
197 }
198 }
198 }
199 }
199 }
200
200
201 AbstractMetaClass *AbstractMetaBuilder::argumentToClass(ArgumentModelItem argument)
201 AbstractMetaClass *AbstractMetaBuilder::argumentToClass(ArgumentModelItem argument)
202 {
202 {
203 AbstractMetaClass *returned = 0;
203 AbstractMetaClass *returned = 0;
204 bool ok = false;
204 bool ok = false;
205 AbstractMetaType *type = translateType(argument->type(), &ok);
205 AbstractMetaType *type = translateType(argument->type(), &ok);
206 if (ok && type != 0 && type->typeEntry() != 0 && type->typeEntry()->isComplex()) {
206 if (ok && type != 0 && type->typeEntry() != 0 && type->typeEntry()->isComplex()) {
207 const TypeEntry *entry = type->typeEntry();
207 const TypeEntry *entry = type->typeEntry();
208 returned = m_meta_classes.findClass(entry->name());
208 returned = m_meta_classes.findClass(entry->name());
209 }
209 }
210 delete type;
210 delete type;
211 return returned;
211 return returned;
212 }
212 }
213
213
214 /**
214 /**
215 * Checks the argument of a hash function and flags the type if it is a complex type
215 * Checks the argument of a hash function and flags the type if it is a complex type
216 */
216 */
217 void AbstractMetaBuilder::registerHashFunction(FunctionModelItem function_item)
217 void AbstractMetaBuilder::registerHashFunction(FunctionModelItem function_item)
218 {
218 {
219 ArgumentList arguments = function_item->arguments();
219 ArgumentList arguments = function_item->arguments();
220 if (arguments.size() == 1) {
220 if (arguments.size() == 1) {
221 if (AbstractMetaClass *cls = argumentToClass(arguments.at(0)))
221 if (AbstractMetaClass *cls = argumentToClass(arguments.at(0)))
222 cls->setHasHashFunction(true);
222 cls->setHasHashFunction(true);
223 }
223 }
224 }
224 }
225
225
226 /**
226 /**
227 * Check if a class has a debug stream operator that can be used as toString
227 * Check if a class has a debug stream operator that can be used as toString
228 */
228 */
229
229
230 void AbstractMetaBuilder::registerToStringCapability(FunctionModelItem function_item)
230 void AbstractMetaBuilder::registerToStringCapability(FunctionModelItem function_item)
231 {
231 {
232 ArgumentList arguments = function_item->arguments();
232 ArgumentList arguments = function_item->arguments();
233 if (arguments.size() == 2) {
233 if (arguments.size() == 2) {
234 if (arguments.at(0)->type().toString() == "QDebug"){
234 if (arguments.at(0)->type().toString() == "QDebug"){
235 ArgumentModelItem arg = arguments.at(1);
235 ArgumentModelItem arg = arguments.at(1);
236 if (AbstractMetaClass *cls = argumentToClass(arg)) {
236 if (AbstractMetaClass *cls = argumentToClass(arg)) {
237 if (arg->type().indirections() < 2 && cls->name()!="QObject") {
237 if (arg->type().indirections() < 2 && cls->name()!="QObject") {
238 cls->setToStringCapability(function_item);
238 cls->setToStringCapability(function_item);
239 }
239 }
240 }
240 }
241 }
241 }
242 }
242 }
243 }
243 }
244
244
245 void AbstractMetaBuilder::traverseCompareOperator(FunctionModelItem item) {
245 void AbstractMetaBuilder::traverseCompareOperator(FunctionModelItem item) {
246 ArgumentList arguments = item->arguments();
246 ArgumentList arguments = item->arguments();
247 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
247 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
248 AbstractMetaClass *comparer_class = argumentToClass(arguments.at(0));
248 AbstractMetaClass *comparer_class = argumentToClass(arguments.at(0));
249 AbstractMetaClass *compared_class = argumentToClass(arguments.at(1));
249 AbstractMetaClass *compared_class = argumentToClass(arguments.at(1));
250 if (comparer_class != 0 && compared_class != 0) {
250 if (comparer_class != 0 && compared_class != 0) {
251 AbstractMetaClass *old_current_class = m_current_class;
251 AbstractMetaClass *old_current_class = m_current_class;
252 m_current_class = comparer_class;
252 m_current_class = comparer_class;
253
253
254 AbstractMetaFunction *meta_function = traverseFunction(item);
254 AbstractMetaFunction *meta_function = traverseFunction(item);
255 if (meta_function != 0 && !meta_function->isInvalid()) {
255 if (meta_function != 0 && !meta_function->isInvalid()) {
256 // Strip away first argument, since that is the containing object
256 // Strip away first argument, since that is the containing object
257 AbstractMetaArgumentList arguments = meta_function->arguments();
257 AbstractMetaArgumentList arguments = meta_function->arguments();
258 arguments.pop_front();
258 arguments.pop_front();
259 meta_function->setArguments(arguments);
259 meta_function->setArguments(arguments);
260
260
261 meta_function->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
261 meta_function->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
262
262
263 meta_function->setOriginalAttributes(meta_function->attributes());
263 meta_function->setOriginalAttributes(meta_function->attributes());
264 setupFunctionDefaults(meta_function, comparer_class);
264 setupFunctionDefaults(meta_function, comparer_class);
265
265
266 comparer_class->addFunction(meta_function);
266 comparer_class->addFunction(meta_function);
267 } else if (meta_function != 0) {
267 } else if (meta_function != 0) {
268 delete meta_function;
268 delete meta_function;
269 }
269 }
270
270
271 m_current_class = old_current_class;
271 m_current_class = old_current_class;
272 }
272 }
273 }
273 }
274 }
274 }
275
275
276 void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item)
276 void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item)
277 {
277 {
278 ArgumentList arguments = item->arguments();
278 ArgumentList arguments = item->arguments();
279 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
279 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
280 AbstractMetaClass *streamClass = argumentToClass(arguments.at(0));
280 AbstractMetaClass *streamClass = argumentToClass(arguments.at(0));
281 AbstractMetaClass *streamedClass = argumentToClass(arguments.at(1));
281 AbstractMetaClass *streamedClass = argumentToClass(arguments.at(1));
282
282
283 if (streamClass != 0 && streamedClass != 0
283 if (streamClass != 0 && streamedClass != 0
284 && (streamClass->name() == "QDataStream" || streamClass->name() == "QTextStream")) {
284 && (streamClass->name() == "QDataStream" || streamClass->name() == "QTextStream")) {
285 AbstractMetaClass *old_current_class = m_current_class;
285 AbstractMetaClass *old_current_class = m_current_class;
286 m_current_class = streamedClass;
286 m_current_class = streamedClass;
287 AbstractMetaFunction *streamFunction = traverseFunction(item);
287 AbstractMetaFunction *streamFunction = traverseFunction(item);
288
288
289 if (streamFunction != 0 && !streamFunction->isInvalid()) {
289 if (streamFunction != 0 && !streamFunction->isInvalid()) {
290 QString name = item->name();
290 QString name = item->name();
291 streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
291 streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
292
292
293 if (name.endsWith("<<"))
293 if (name.endsWith("<<"))
294 streamFunction->setName("writeTo");
294 streamFunction->setName("writeTo");
295 else
295 else
296 streamFunction->setName("readFrom");
296 streamFunction->setName("readFrom");
297
297
298 // Strip away last argument, since that is the containing object
298 // Strip away last argument, since that is the containing object
299 AbstractMetaArgumentList arguments = streamFunction->arguments();
299 AbstractMetaArgumentList arguments = streamFunction->arguments();
300 arguments.pop_back();
300 arguments.pop_back();
301 streamFunction->setArguments(arguments);
301 streamFunction->setArguments(arguments);
302
302
303 *streamFunction += AbstractMetaAttributes::Final;
303 *streamFunction += AbstractMetaAttributes::Final;
304 *streamFunction += AbstractMetaAttributes::Public;
304 *streamFunction += AbstractMetaAttributes::Public;
305 streamFunction->setOriginalAttributes(streamFunction->attributes());
305 streamFunction->setOriginalAttributes(streamFunction->attributes());
306
306
307 streamFunction->setType(0);
307 streamFunction->setType(0);
308
308
309 setupFunctionDefaults(streamFunction, streamedClass);
309 setupFunctionDefaults(streamFunction, streamedClass);
310
310
311 streamedClass->addFunction(streamFunction);
311 streamedClass->addFunction(streamFunction);
312 streamedClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
312 streamedClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
313
313
314 m_current_class = old_current_class;
314 m_current_class = old_current_class;
315 }
315 }
316 }
316 }
317 }
317 }
318 }
318 }
319
319
320 void AbstractMetaBuilder::traverseBinaryArithmeticOperator(FunctionModelItem item)
320 void AbstractMetaBuilder::traverseBinaryArithmeticOperator(FunctionModelItem item)
321 {
321 {
322 ArgumentList arguments = item->arguments();
322 ArgumentList arguments = item->arguments();
323 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
323 if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
324 AbstractMetaClass *aClass = argumentToClass(arguments.at(0));
324 AbstractMetaClass *aClass = argumentToClass(arguments.at(0));
325 AbstractMetaClass *bClass = argumentToClass(arguments.at(1));
325 AbstractMetaClass *bClass = argumentToClass(arguments.at(1));
326
326
327 if (!aClass) return;
327 if (!aClass) return;
328
328
329 AbstractMetaClass *old_current_class = m_current_class;
329 AbstractMetaClass *old_current_class = m_current_class;
330 m_current_class = aClass;
330 m_current_class = aClass;
331 AbstractMetaFunction *streamFunction = traverseFunction(item);
331 AbstractMetaFunction *streamFunction = traverseFunction(item);
332 if (streamFunction != 0 && !streamFunction->isInvalid()) {
332 if (streamFunction != 0 && !streamFunction->isInvalid()) {
333 QString name = rename_operator(item->name().mid(8));
333 QString name = rename_operator(item->name().mid(8));
334 if (name.isEmpty()) return;
334 if (name.isEmpty()) return;
335
335
336 streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
336 streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
337 streamFunction->setName(name);
337 streamFunction->setName(name);
338
338
339 // Strip away the first argument, since that is the operator object
339 // Strip away the first argument, since that is the operator object
340 AbstractMetaArgumentList arguments = streamFunction->arguments();
340 AbstractMetaArgumentList arguments = streamFunction->arguments();
341 arguments.removeFirst();
341 arguments.removeFirst();
342 streamFunction->setArguments(arguments);
342 streamFunction->setArguments(arguments);
343
343
344 *streamFunction += AbstractMetaAttributes::Final;
344 *streamFunction += AbstractMetaAttributes::Final;
345 *streamFunction += AbstractMetaAttributes::Public;
345 *streamFunction += AbstractMetaAttributes::Public;
346 streamFunction->setOriginalAttributes(streamFunction->attributes());
346 streamFunction->setOriginalAttributes(streamFunction->attributes());
347
347
348 setupFunctionDefaults(streamFunction, aClass);
348 setupFunctionDefaults(streamFunction, aClass);
349
349
350 aClass->addFunction(streamFunction);
350 aClass->addFunction(streamFunction);
351 if (bClass) {
351 if (bClass) {
352 aClass->typeEntry()->addExtraInclude(bClass->typeEntry()->include());
352 aClass->typeEntry()->addExtraInclude(bClass->typeEntry()->include());
353 }
353 }
354
354
355 m_current_class = old_current_class;
355 m_current_class = old_current_class;
356 }
356 }
357 }
357 }
358 }
358 }
359
359
360 void AbstractMetaBuilder::fixQObjectForScope(TypeDatabase *types,
360 void AbstractMetaBuilder::fixQObjectForScope(TypeDatabase *types,
361 NamespaceModelItem scope)
361 NamespaceModelItem scope)
362 {
362 {
363 foreach (ClassModelItem item, scope->classes()) {
363 foreach (ClassModelItem item, scope->classes()) {
364 QString qualified_name = item->qualifiedName().join("::");
364 QString qualified_name = item->qualifiedName().join("::");
365 TypeEntry *entry = types->findType(qualified_name);
365 TypeEntry *entry = types->findType(qualified_name);
366 if (entry) {
366 if (entry) {
367 if (isQObject(qualified_name) && entry->isComplex()) {
367 if (isQObject(qualified_name) && entry->isComplex()) {
368 ((ComplexTypeEntry *) entry)->setQObject(true);
368 ((ComplexTypeEntry *) entry)->setQObject(true);
369 }
369 }
370 }
370 }
371 }
371 }
372
372
373 foreach (NamespaceModelItem item, scope->namespaceMap().values()) {
373 foreach (NamespaceModelItem item, scope->namespaceMap().values()) {
374 if (scope != item)
374 if (scope != item)
375 fixQObjectForScope(types, item);
375 fixQObjectForScope(types, item);
376 }
376 }
377 }
377 }
378
378
379 static bool class_less_than(AbstractMetaClass *a, AbstractMetaClass *b)
379 static bool class_less_than(AbstractMetaClass *a, AbstractMetaClass *b)
380 {
380 {
381 return a->name() < b->name();
381 return a->name() < b->name();
382 }
382 }
383
383
384
384
385 void AbstractMetaBuilder::sortLists()
385 void AbstractMetaBuilder::sortLists()
386 {
386 {
387 qSort(m_meta_classes.begin(), m_meta_classes.end(), class_less_than);
387 qSort(m_meta_classes.begin(), m_meta_classes.end(), class_less_than);
388 foreach (AbstractMetaClass *cls, m_meta_classes) {
388 foreach (AbstractMetaClass *cls, m_meta_classes) {
389 cls->sortFunctions();
389 cls->sortFunctions();
390 }
390 }
391 }
391 }
392
392
393 bool AbstractMetaBuilder::build()
393 bool AbstractMetaBuilder::build()
394 {
394 {
395 Q_ASSERT(!m_file_name.isEmpty());
395 Q_ASSERT(!m_file_name.isEmpty());
396
396
397 QFile file(m_file_name);
397 QFile file(m_file_name);
398
398
399 if (!file.open(QFile::ReadOnly))
399 if (!file.open(QFile::ReadOnly))
400 return false;
400 return false;
401
401
402 QTextStream stream(&file);
402 QTextStream stream(&file);
403 stream.setCodec(QTextCodec::codecForName("UTF-8"));
403 stream.setCodec(QTextCodec::codecForName("UTF-8"));
404 QByteArray contents = stream.readAll().toUtf8();
404 QByteArray contents = stream.readAll().toUtf8();
405 file.close();
405 file.close();
406
406
407 Control control;
407 Control control;
408 Parser p(&control);
408 Parser p(&control);
409 pool __pool;
409 pool __pool;
410
410
411 TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool);
411 TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool);
412
412
413 CodeModel model;
413 CodeModel model;
414 Binder binder(&model, p.location());
414 Binder binder(&model, p.location());
415 m_dom = binder.run(ast);
415 m_dom = binder.run(ast);
416
416
417 pushScope(model_dynamic_cast<ScopeModelItem>(m_dom));
417 pushScope(model_dynamic_cast<ScopeModelItem>(m_dom));
418
418
419 QHash<QString, ClassModelItem> typeMap = m_dom->classMap();
419 QHash<QString, ClassModelItem> typeMap = m_dom->classMap();
420
420
421
421
422 // fix up QObject's in the type system..
422 // fix up QObject's in the type system..
423 TypeDatabase *types = TypeDatabase::instance();
423 TypeDatabase *types = TypeDatabase::instance();
424 fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom));
424 fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom));
425
425
426
426
427 // Start the generation...
427 // Start the generation...
428 foreach (ClassModelItem item, typeMap.values()) {
428 foreach (ClassModelItem item, typeMap.values()) {
429 AbstractMetaClass *cls = traverseClass(item);
429 AbstractMetaClass *cls = traverseClass(item);
430 addAbstractMetaClass(cls);
430 addAbstractMetaClass(cls);
431 }
431 }
432
432
433
433
434 QHash<QString, NamespaceModelItem> namespaceMap = m_dom->namespaceMap();
434 QHash<QString, NamespaceModelItem> namespaceMap = m_dom->namespaceMap();
435 foreach (NamespaceModelItem item, namespaceMap.values()) {
435 foreach (NamespaceModelItem item, namespaceMap.values()) {
436 AbstractMetaClass *meta_class = traverseNamespace(item);
436 AbstractMetaClass *meta_class = traverseNamespace(item);
437 if (meta_class)
437 if (meta_class)
438 m_meta_classes << meta_class;
438 m_meta_classes << meta_class;
439 }
439 }
440
440
441
441
442 // Some trickery to support global-namespace enums...
442 // Some trickery to support global-namespace enums...
443 QHash<QString, EnumModelItem> enumMap = m_dom->enumMap();
443 QHash<QString, EnumModelItem> enumMap = m_dom->enumMap();
444 m_current_class = 0;
444 m_current_class = 0;
445 foreach (EnumModelItem item, enumMap) {
445 foreach (EnumModelItem item, enumMap) {
446 AbstractMetaEnum *meta_enum = traverseEnum(item, 0, QSet<QString>());
446 AbstractMetaEnum *meta_enum = traverseEnum(item, 0, QSet<QString>());
447
447
448 if (meta_enum) {
448 if (meta_enum) {
449 QString package = meta_enum->typeEntry()->javaPackage();
449 QString package = meta_enum->typeEntry()->javaPackage();
450 QString globalName = TypeDatabase::globalNamespaceClassName(meta_enum->typeEntry());
450 QString globalName = TypeDatabase::globalNamespaceClassName(meta_enum->typeEntry());
451
451
452 AbstractMetaClass *global = m_meta_classes.findClass(package + "." + globalName);
452 AbstractMetaClass *global = m_meta_classes.findClass(package + "." + globalName);
453 if (!global) {
453 if (!global) {
454 ComplexTypeEntry *gte = new ObjectTypeEntry(globalName);
454 ComplexTypeEntry *gte = new ObjectTypeEntry(globalName);
455 gte->setTargetLangPackage(meta_enum->typeEntry()->javaPackage());
455 gte->setTargetLangPackage(meta_enum->typeEntry()->javaPackage());
456 gte->setCodeGeneration(meta_enum->typeEntry()->codeGeneration());
456 gte->setCodeGeneration(meta_enum->typeEntry()->codeGeneration());
457 global = createMetaClass();
457 global = createMetaClass();
458 global->setTypeEntry(gte);
458 global->setTypeEntry(gte);
459 *global += AbstractMetaAttributes::Final;
459 *global += AbstractMetaAttributes::Final;
460 *global += AbstractMetaAttributes::Public;
460 *global += AbstractMetaAttributes::Public;
461 *global += AbstractMetaAttributes::Fake;
461 *global += AbstractMetaAttributes::Fake;
462
462
463 m_meta_classes << global;
463 m_meta_classes << global;
464 }
464 }
465
465
466 global->addEnum(meta_enum);
466 global->addEnum(meta_enum);
467 meta_enum->setEnclosingClass(global);
467 meta_enum->setEnclosingClass(global);
468 meta_enum->typeEntry()->setQualifier(globalName);
468 meta_enum->typeEntry()->setQualifier(globalName);
469
469
470 // Global enums should be public despite not having public
470 // Global enums should be public despite not having public
471 // identifiers so we'll fix the original attributes here.
471 // identifiers so we'll fix the original attributes here.
472 meta_enum->setOriginalAttributes(meta_enum->attributes());
472 meta_enum->setOriginalAttributes(meta_enum->attributes());
473 }
473 }
474
474
475
475
476 }
476 }
477
477
478
478
479 // Go through all typedefs to see if we have defined any
479 // Go through all typedefs to see if we have defined any
480 // specific typedefs to be used as classes.
480 // specific typedefs to be used as classes.
481 TypeAliasList typeAliases = m_dom->typeAliases();
481 TypeAliasList typeAliases = m_dom->typeAliases();
482 foreach (TypeAliasModelItem typeAlias, typeAliases) {
482 foreach (TypeAliasModelItem typeAlias, typeAliases) {
483 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
483 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
484 addAbstractMetaClass(cls);
484 addAbstractMetaClass(cls);
485 }
485 }
486
486
487
487
488
488
489
489
490 foreach (AbstractMetaClass *cls, m_meta_classes) {
490 foreach (AbstractMetaClass *cls, m_meta_classes) {
491 if (!cls->isInterface() && !cls->isNamespace()) {
491 if (!cls->isInterface() && !cls->isNamespace()) {
492 setupInheritance(cls);
492 setupInheritance(cls);
493 }
493 }
494 }
494 }
495
495
496
496
497 foreach (AbstractMetaClass *cls, m_meta_classes) {
497 foreach (AbstractMetaClass *cls, m_meta_classes) {
498 cls->fixFunctions();
498 cls->fixFunctions();
499
499
500 if (cls->typeEntry() == 0) {
500 if (cls->typeEntry() == 0) {
501 ReportHandler::warning(QString("class '%1' does not have an entry in the type system")
501 ReportHandler::warning(QString("class '%1' does not have an entry in the type system")
502 .arg(cls->name()));
502 .arg(cls->name()));
503 } else {
503 } else {
504 if (!cls->hasConstructors() && !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace())
504 if (!cls->hasConstructors() && !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace())
505 cls->addDefaultConstructor();
505 cls->addDefaultConstructor();
506 }
506 }
507
507
508 if (cls->isAbstract() && !cls->isInterface()) {
508 if (cls->isAbstract() && !cls->isInterface()) {
509 cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + "$ConcreteWrapper");
509 cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + "$ConcreteWrapper");
510 }
510 }
511 }
511 }
512
512
513 QList<TypeEntry *> entries = TypeDatabase::instance()->entries().values();
513 QList<TypeEntry *> entries = TypeDatabase::instance()->entries().values();
514 foreach (const TypeEntry *entry, entries) {
514 foreach (const TypeEntry *entry, entries) {
515 if (entry->isPrimitive())
515 if (entry->isPrimitive())
516 continue;
516 continue;
517
517
518 if ((entry->isValue() || entry->isObject())
518 if ((entry->isValue() || entry->isObject())
519 && !entry->isString()
519 && !entry->isString()
520 && !entry->isChar()
520 && !entry->isChar()
521 && !entry->isContainer()
521 && !entry->isContainer()
522 && !entry->isCustom()
522 && !entry->isCustom()
523 && !entry->isVariant()
523 && !entry->isVariant()
524 && !m_meta_classes.findClass(entry->qualifiedCppName())) {
524 && !m_meta_classes.findClass(entry->qualifiedCppName())) {
525 ReportHandler::warning(QString("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
525 ReportHandler::warning(QString("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
526 .arg(entry->qualifiedCppName()));
526 .arg(entry->qualifiedCppName()));
527 }
527 }
528
528
529 if (entry->isEnum()) {
529 if (entry->isEnum()) {
530 QString pkg = entry->javaPackage();
530 QString pkg = entry->javaPackage();
531 QString name = (pkg.isEmpty() ? QString() : pkg + ".")
531 QString name = (pkg.isEmpty() ? QString() : pkg + ".")
532 + ((EnumTypeEntry *) entry)->javaQualifier();
532 + ((EnumTypeEntry *) entry)->javaQualifier();
533 AbstractMetaClass *cls = m_meta_classes.findClass(name);
533 AbstractMetaClass *cls = m_meta_classes.findClass(name);
534
534
535 if (!cls) {
535 if (!cls) {
536 ReportHandler::warning(QString("namespace '%1' for enum '%2' is not declared")
536 ReportHandler::warning(QString("namespace '%1' for enum '%2' is not declared")
537 .arg(name).arg(entry->targetLangName()));
537 .arg(name).arg(entry->targetLangName()));
538 } else {
538 } else {
539 AbstractMetaEnum *e = cls->findEnum(entry->targetLangName());
539 AbstractMetaEnum *e = cls->findEnum(entry->targetLangName());
540 if (!e)
540 if (!e)
541 ReportHandler::warning(QString("enum '%1' is specified in typesystem, "
541 ReportHandler::warning(QString("enum '%1' is specified in typesystem, "
542 "but not declared")
542 "but not declared")
543 .arg(entry->qualifiedCppName()));
543 .arg(entry->qualifiedCppName()));
544 }
544 }
545 }
545 }
546 }
546 }
547
547
548 {
548 {
549 FunctionList hash_functions = m_dom->findFunctions("qHash");
549 FunctionList hash_functions = m_dom->findFunctions("qHash");
550 foreach (FunctionModelItem item, hash_functions) {
550 foreach (FunctionModelItem item, hash_functions) {
551 registerHashFunction(item);
551 registerHashFunction(item);
552 }
552 }
553 }
553 }
554
554
555 {
555 {
556 FunctionList hash_functions = m_dom->findFunctions("operator<<");
556 FunctionList hash_functions = m_dom->findFunctions("operator<<");
557 foreach (FunctionModelItem item, hash_functions) {
557 foreach (FunctionModelItem item, hash_functions) {
558 registerToStringCapability(item);
558 registerToStringCapability(item);
559 }
559 }
560 }
560 }
561
561
562 {
562 {
563 FunctionList compare_operators = m_dom->findFunctions("operator==")
563 FunctionList compare_operators = m_dom->findFunctions("operator==")
564 + m_dom->findFunctions("operator<=")
564 + m_dom->findFunctions("operator<=")
565 + m_dom->findFunctions("operator>=")
565 + m_dom->findFunctions("operator>=")
566 + m_dom->findFunctions("operator<")
566 + m_dom->findFunctions("operator<")
567 + m_dom->findFunctions("operator>");
567 + m_dom->findFunctions("operator>");
568 foreach (FunctionModelItem item, compare_operators) {
568 foreach (FunctionModelItem item, compare_operators) {
569 traverseCompareOperator(item);
569 traverseCompareOperator(item);
570 }
570 }
571 }
571 }
572
572
573 {
573 {
574 FunctionList stream_operators =
574 FunctionList stream_operators =
575 m_dom->findFunctions("operator+") + m_dom->findFunctions("operator-")
575 m_dom->findFunctions("operator+") + m_dom->findFunctions("operator-")
576 + m_dom->findFunctions("operator/") + m_dom->findFunctions("operator*")
576 + m_dom->findFunctions("operator/") + m_dom->findFunctions("operator*")
577 + m_dom->findFunctions("operator&") + m_dom->findFunctions("operator|")
577 + m_dom->findFunctions("operator&") + m_dom->findFunctions("operator|")
578 + m_dom->findFunctions("operator%") + m_dom->findFunctions("operator^");
578 + m_dom->findFunctions("operator%") + m_dom->findFunctions("operator^");
579 foreach (FunctionModelItem item, stream_operators) {
579 foreach (FunctionModelItem item, stream_operators) {
580 traverseBinaryArithmeticOperator(item);
580 traverseBinaryArithmeticOperator(item);
581 }
581 }
582 }
582 }
583 {
583 {
584 FunctionList stream_operators = m_dom->findFunctions("operator<<") + m_dom->findFunctions("operator>>");
584 FunctionList stream_operators = m_dom->findFunctions("operator<<") + m_dom->findFunctions("operator>>");
585 foreach (FunctionModelItem item, stream_operators) {
585 foreach (FunctionModelItem item, stream_operators) {
586 traverseStreamOperator(item);
586 traverseStreamOperator(item);
587 }
587 }
588 }
588 }
589
589
590 figureOutEnumValues();
590 figureOutEnumValues();
591 figureOutDefaultEnumArguments();
591 figureOutDefaultEnumArguments();
592 checkFunctionModifications();
592 checkFunctionModifications();
593
593
594 foreach (AbstractMetaClass *cls, m_meta_classes) {
594 foreach (AbstractMetaClass *cls, m_meta_classes) {
595 setupEquals(cls);
595 setupEquals(cls);
596 setupComparable(cls);
596 setupComparable(cls);
597 setupClonable(cls);
597 setupClonable(cls);
598 }
598 }
599
599
600 dumpLog();
600 dumpLog();
601
601
602 sortLists();
602 sortLists();
603
603
604 return true;
604 return true;
605 }
605 }
606
606
607
607
608 void AbstractMetaBuilder::addAbstractMetaClass(AbstractMetaClass *cls)
608 void AbstractMetaBuilder::addAbstractMetaClass(AbstractMetaClass *cls)
609 {
609 {
610 if (!cls)
610 if (!cls)
611 return;
611 return;
612
612
613 cls->setOriginalAttributes(cls->attributes());
613 cls->setOriginalAttributes(cls->attributes());
614 if (cls->typeEntry()->isContainer()) {
614 if (cls->typeEntry()->isContainer()) {
615 m_templates << cls;
615 m_templates << cls;
616 } else {
616 } else {
617 m_meta_classes << cls;
617 m_meta_classes << cls;
618 if (cls->typeEntry()->designatedInterface()) {
618 if (cls->typeEntry()->designatedInterface()) {
619 AbstractMetaClass *interface = cls->extractInterface();
619 AbstractMetaClass *interface = cls->extractInterface();
620 m_meta_classes << interface;
620 m_meta_classes << interface;
621 ReportHandler::debugSparse(QString(" -> interface '%1'").arg(interface->name()));
621 ReportHandler::debugSparse(QString(" -> interface '%1'").arg(interface->name()));
622 }
622 }
623 }
623 }
624 }
624 }
625
625
626
626
627 AbstractMetaClass *AbstractMetaBuilder::traverseNamespace(NamespaceModelItem namespace_item)
627 AbstractMetaClass *AbstractMetaBuilder::traverseNamespace(NamespaceModelItem namespace_item)
628 {
628 {
629 QString namespace_name = (!m_namespace_prefix.isEmpty() ? m_namespace_prefix + "::" : QString()) + namespace_item->name();
629 QString namespace_name = (!m_namespace_prefix.isEmpty() ? m_namespace_prefix + "::" : QString()) + namespace_item->name();
630 NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespace_name);
630 NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespace_name);
631
631
632 if (TypeDatabase::instance()->isClassRejected(namespace_name)) {
632 if (TypeDatabase::instance()->isClassRejected(namespace_name)) {
633 m_rejected_classes.insert(namespace_name, GenerationDisabled);
633 m_rejected_classes.insert(namespace_name, GenerationDisabled);
634 return 0;
634 return 0;
635 }
635 }
636
636
637 if (!type) {
637 if (!type) {
638 ReportHandler::warning(QString("namespace '%1' does not have a type entry")
638 ReportHandler::warning(QString("namespace '%1' does not have a type entry")
639 .arg(namespace_name));
639 .arg(namespace_name));
640 return 0;
640 return 0;
641 }
641 }
642
642
643 AbstractMetaClass *meta_class = createMetaClass();
643 AbstractMetaClass *meta_class = createMetaClass();
644 meta_class->setTypeEntry(type);
644 meta_class->setTypeEntry(type);
645
645
646 *meta_class += AbstractMetaAttributes::Public;
646 *meta_class += AbstractMetaAttributes::Public;
647
647
648 m_current_class = meta_class;
648 m_current_class = meta_class;
649
649
650 ReportHandler::debugSparse(QString("namespace '%1.%2'")
650 ReportHandler::debugSparse(QString("namespace '%1.%2'")
651 .arg(meta_class->package())
651 .arg(meta_class->package())
652 .arg(namespace_item->name()));
652 .arg(namespace_item->name()));
653
653
654 traverseEnums(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class, namespace_item->enumsDeclarations());
654 traverseEnums(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class, namespace_item->enumsDeclarations());
655 traverseFunctions(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class);
655 traverseFunctions(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class);
656 // traverseClasses(model_dynamic_cast<ScopeModelItem>(namespace_item));
656 // traverseClasses(model_dynamic_cast<ScopeModelItem>(namespace_item));
657
657
658 pushScope(model_dynamic_cast<ScopeModelItem>(namespace_item));
658 pushScope(model_dynamic_cast<ScopeModelItem>(namespace_item));
659 m_namespace_prefix = currentScope()->qualifiedName().join("::");
659 m_namespace_prefix = currentScope()->qualifiedName().join("::");
660
660
661
661
662 ClassList classes = namespace_item->classes();
662 ClassList classes = namespace_item->classes();
663 foreach (ClassModelItem cls, classes) {
663 foreach (ClassModelItem cls, classes) {
664 AbstractMetaClass *mjc = traverseClass(cls);
664 AbstractMetaClass *mjc = traverseClass(cls);
665 addAbstractMetaClass(mjc);
665 addAbstractMetaClass(mjc);
666 }
666 }
667
667
668 // Go through all typedefs to see if we have defined any
668 // Go through all typedefs to see if we have defined any
669 // specific typedefs to be used as classes.
669 // specific typedefs to be used as classes.
670 TypeAliasList typeAliases = namespace_item->typeAliases();
670 TypeAliasList typeAliases = namespace_item->typeAliases();
671 foreach (TypeAliasModelItem typeAlias, typeAliases) {
671 foreach (TypeAliasModelItem typeAlias, typeAliases) {
672 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
672 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
673 addAbstractMetaClass(cls);
673 addAbstractMetaClass(cls);
674 }
674 }
675
675
676
676
677
677
678 // Traverse namespaces recursively
678 // Traverse namespaces recursively
679 QList<NamespaceModelItem> inner_namespaces = namespace_item->namespaceMap().values();
679 QList<NamespaceModelItem> inner_namespaces = namespace_item->namespaceMap().values();
680 foreach (const NamespaceModelItem &ni, inner_namespaces) {
680 foreach (const NamespaceModelItem &ni, inner_namespaces) {
681 AbstractMetaClass *mjc = traverseNamespace(ni);
681 AbstractMetaClass *mjc = traverseNamespace(ni);
682 addAbstractMetaClass(mjc);
682 addAbstractMetaClass(mjc);
683 }
683 }
684
684
685 m_current_class = 0;
685 m_current_class = 0;
686
686
687
687
688 popScope();
688 popScope();
689 m_namespace_prefix = currentScope()->qualifiedName().join("::");
689 m_namespace_prefix = currentScope()->qualifiedName().join("::");
690
690
691 if (!type->include().isValid()) {
691 if (!type->include().isValid()) {
692 QFileInfo info(namespace_item->fileName());
692 QFileInfo info(namespace_item->fileName());
693 type->setInclude(Include(Include::IncludePath, info.fileName()));
693 type->setInclude(Include(Include::IncludePath, info.fileName()));
694 }
694 }
695
695
696 return meta_class;
696 return meta_class;
697 }
697 }
698
698
699 struct Operator
699 struct Operator
700 {
700 {
701 enum Type { Plus, ShiftLeft, None };
701 enum Type { Plus, ShiftLeft, None };
702
702
703 Operator() : type(None) { }
703 Operator() : type(None) { }
704
704
705 int calculate(int x) {
705 int calculate(int x) {
706 switch (type) {
706 switch (type) {
707 case Plus: return x + value;
707 case Plus: return x + value;
708 case ShiftLeft: return x << value;
708 case ShiftLeft: return x << value;
709 case None: return x;
709 case None: return x;
710 }
710 }
711 return x;
711 return x;
712 }
712 }
713
713
714 Type type;
714 Type type;
715 int value;
715 int value;
716 };
716 };
717
717
718
718
719
719
720 Operator findOperator(QString *s) {
720 Operator findOperator(QString *s) {
721 const char *names[] = {
721 const char *names[] = {
722 "+",
722 "+",
723 "<<"
723 "<<"
724 };
724 };
725
725
726 for (int i=0; i<Operator::None; ++i) {
726 for (int i=0; i<Operator::None; ++i) {
727 QString name = QLatin1String(names[i]);
727 QString name = QLatin1String(names[i]);
728 QString str = *s;
728 QString str = *s;
729 int splitPoint = str.indexOf(name);
729 int splitPoint = str.indexOf(name);
730 if (splitPoint > 0) {
730 if (splitPoint > 0) {
731 bool ok;
731 bool ok;
732 QString right = str.mid(splitPoint + name.length());
732 QString right = str.mid(splitPoint + name.length());
733 Operator op;
733 Operator op;
734 op.value = right.toInt(&ok);
734 op.value = right.toInt(&ok);
735 if (ok) {
735 if (ok) {
736 op.type = Operator::Type(i);
736 op.type = Operator::Type(i);
737 *s = str.left(splitPoint).trimmed();
737 *s = str.left(splitPoint).trimmed();
738 return op;
738 return op;
739 }
739 }
740 }
740 }
741 }
741 }
742 return Operator();
742 return Operator();
743 }
743 }
744
744
745 int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
745 int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
746 int oldValuevalue,
746 int oldValuevalue,
747 AbstractMetaEnum *meta_enum,
747 AbstractMetaEnum *meta_enum,
748 AbstractMetaFunction *meta_function)
748 AbstractMetaFunction *meta_function)
749 {
749 {
750 if (stringValue.isEmpty())
750 if (stringValue.isEmpty())
751 return oldValuevalue;
751 return oldValuevalue;
752
752
753 QStringList stringValues = stringValue.split("|");
753 QStringList stringValues = stringValue.split("|");
754
754
755 int returnValue = 0;
755 int returnValue = 0;
756
756
757 bool matched = false;
757 bool matched = false;
758
758
759 for (int i=0; i<stringValues.size(); ++i) {
759 for (int i=0; i<stringValues.size(); ++i) {
760 QString s = stringValues.at(i).trimmed();
760 QString s = stringValues.at(i).trimmed();
761
761
762 bool ok;
762 bool ok;
763 int v;
763 int v;
764
764
765 Operator op = findOperator(&s);
765 Operator op = findOperator(&s);
766
766
767 if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
767 if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
768 v = s.toUInt(&ok, 0);
768 v = s.toUInt(&ok, 0);
769 else
769 else
770 v = s.toInt(&ok);
770 v = s.toInt(&ok);
771
771
772 if (ok) {
772 if (ok) {
773 matched = true;
773 matched = true;
774
774
775 } else if (m_enum_values.contains(s)) {
775 } else if (m_enum_values.contains(s)) {
776 v = m_enum_values[s]->value();
776 v = m_enum_values[s]->value();
777 matched = true;
777 matched = true;
778
778
779 } else {
779 } else {
780 AbstractMetaEnumValue *ev = 0;
780 AbstractMetaEnumValue *ev = 0;
781
781
782 if (meta_enum && (ev = meta_enum->values().find(s))) {
782 if (meta_enum && (ev = meta_enum->values().find(s))) {
783 v = ev->value();
783 v = ev->value();
784 matched = true;
784 matched = true;
785
785
786 } else if (meta_enum && (ev = meta_enum->enclosingClass()->findEnumValue(s, meta_enum))) {
786 } else if (meta_enum && (ev = meta_enum->enclosingClass()->findEnumValue(s, meta_enum))) {
787 v = ev->value();
787 v = ev->value();
788 matched = true;
788 matched = true;
789
789
790 } else {
790 } else {
791 if (meta_enum)
791 if (meta_enum)
792 ReportHandler::warning("unhandled enum value: " + s + " in "
792 ReportHandler::warning("unhandled enum value: " + s + " in "
793 + meta_enum->enclosingClass()->name() + "::"
793 + meta_enum->enclosingClass()->name() + "::"
794 + meta_enum->name());
794 + meta_enum->name());
795 else
795 else
796 ReportHandler::warning("unhandled enum value: Unknown enum");
796 ReportHandler::warning("unhandled enum value: Unknown enum");
797 }
797 }
798 }
798 }
799
799
800 if (matched)
800 if (matched)
801 returnValue |= op.calculate(v);
801 returnValue |= op.calculate(v);
802 }
802 }
803
803
804 if (!matched) {
804 if (!matched) {
805 QString warn = QString("unmatched enum %1").arg(stringValue);
805 QString warn = QString("unmatched enum %1").arg(stringValue);
806
806
807 if (meta_function != 0) {
807 if (meta_function != 0) {
808 warn += QString(" when parsing default value of '%1' in class '%2'")
808 warn += QString(" when parsing default value of '%1' in class '%2'")
809 .arg(meta_function->name())
809 .arg(meta_function->name())
810 .arg(meta_function->implementingClass()->name());
810 .arg(meta_function->implementingClass()->name());
811 }
811 }
812
812
813 ReportHandler::warning(warn);
813 ReportHandler::warning(warn);
814 returnValue = oldValuevalue;
814 returnValue = oldValuevalue;
815 }
815 }
816
816
817 return returnValue;
817 return returnValue;
818 }
818 }
819
819
820 void AbstractMetaBuilder::figureOutEnumValuesForClass(AbstractMetaClass *meta_class,
820 void AbstractMetaBuilder::figureOutEnumValuesForClass(AbstractMetaClass *meta_class,
821 QSet<AbstractMetaClass *> *classes)
821 QSet<AbstractMetaClass *> *classes)
822 {
822 {
823 AbstractMetaClass *base = meta_class->baseClass();
823 AbstractMetaClass *base = meta_class->baseClass();
824
824
825 if (base != 0 && !classes->contains(base))
825 if (base != 0 && !classes->contains(base))
826 figureOutEnumValuesForClass(base, classes);
826 figureOutEnumValuesForClass(base, classes);
827
827
828 if (classes->contains(meta_class))
828 if (classes->contains(meta_class))
829 return;
829 return;
830
830
831 AbstractMetaEnumList enums = meta_class->enums();
831 AbstractMetaEnumList enums = meta_class->enums();
832 foreach (AbstractMetaEnum *e, enums) {
832 foreach (AbstractMetaEnum *e, enums) {
833 if (!e) {
833 if (!e) {
834 ReportHandler::warning("bad enum in class " + meta_class->name());
834 ReportHandler::warning("bad enum in class " + meta_class->name());
835 continue;
835 continue;
836 }
836 }
837 AbstractMetaEnumValueList lst = e->values();
837 AbstractMetaEnumValueList lst = e->values();
838 int value = 0;
838 int value = 0;
839 for (int i=0; i<lst.size(); ++i) {
839 for (int i=0; i<lst.size(); ++i) {
840 value = figureOutEnumValue(lst.at(i)->stringValue(), value, e);
840 value = figureOutEnumValue(lst.at(i)->stringValue(), value, e);
841 lst.at(i)->setValue(value);
841 lst.at(i)->setValue(value);
842 value++;
842 value++;
843 }
843 }
844
844
845 // Check for duplicate values...
845 // Check for duplicate values...
846 EnumTypeEntry *ete = e->typeEntry();
846 EnumTypeEntry *ete = e->typeEntry();
847 if (!ete->forceInteger()) {
847 if (!ete->forceInteger()) {
848 QHash<int, AbstractMetaEnumValue *> entries;
848 QHash<int, AbstractMetaEnumValue *> entries;
849 foreach (AbstractMetaEnumValue *v, lst) {
849 foreach (AbstractMetaEnumValue *v, lst) {
850
850
851 bool vRejected = ete->isEnumValueRejected(v->name());
851 bool vRejected = ete->isEnumValueRejected(v->name());
852
852
853 AbstractMetaEnumValue *current = entries.value(v->value());
853 AbstractMetaEnumValue *current = entries.value(v->value());
854 if (current) {
854 if (current) {
855 bool currentRejected = ete->isEnumValueRejected(current->name());
855 bool currentRejected = ete->isEnumValueRejected(current->name());
856 if (!currentRejected && !vRejected) {
856 if (!currentRejected && !vRejected) {
857 ReportHandler::warning(
857 ReportHandler::warning(
858 QString("duplicate enum values: %1::%2, %3 and %4 are %5, already rejected: (%6)")
858 QString("duplicate enum values: %1::%2, %3 and %4 are %5, already rejected: (%6)")
859 .arg(meta_class->name())
859 .arg(meta_class->name())
860 .arg(e->name())
860 .arg(e->name())
861 .arg(v->name())
861 .arg(v->name())
862 .arg(entries[v->value()]->name())
862 .arg(entries[v->value()]->name())
863 .arg(v->value())
863 .arg(v->value())
864 .arg(ete->enumValueRejections().join(", ")));
864 .arg(ete->enumValueRejections().join(", ")));
865 continue;
865 continue;
866 }
866 }
867 }
867 }
868
868
869 if (!vRejected)
869 if (!vRejected)
870 entries[v->value()] = v;
870 entries[v->value()] = v;
871 }
871 }
872
872
873 // Entries now contain all the original entries, no
873 // Entries now contain all the original entries, no
874 // rejected ones... Use this to generate the enumValueRedirection table.
874 // rejected ones... Use this to generate the enumValueRedirection table.
875 foreach (AbstractMetaEnumValue *reject, lst) {
875 foreach (AbstractMetaEnumValue *reject, lst) {
876 if (!ete->isEnumValueRejected(reject->name()))
876 if (!ete->isEnumValueRejected(reject->name()))
877 continue;
877 continue;
878
878
879 AbstractMetaEnumValue *used = entries.value(reject->value());
879 AbstractMetaEnumValue *used = entries.value(reject->value());
880 if (!used) {
880 if (!used) {
881 ReportHandler::warning(
881 ReportHandler::warning(
882 QString::fromLatin1("Rejected enum has no alternative...: %1::%2")
882 QString::fromLatin1("Rejected enum has no alternative...: %1::%2")
883 .arg(meta_class->name())
883 .arg(meta_class->name())
884 .arg(reject->name()));
884 .arg(reject->name()));
885 continue;
885 continue;
886 }
886 }
887 ete->addEnumValueRedirection(reject->name(), used->name());
887 ete->addEnumValueRedirection(reject->name(), used->name());
888 }
888 }
889
889
890 }
890 }
891 }
891 }
892
892
893
893
894
894
895 *classes += meta_class;
895 *classes += meta_class;
896 }
896 }
897
897
898
898
899 void AbstractMetaBuilder::figureOutEnumValues()
899 void AbstractMetaBuilder::figureOutEnumValues()
900 {
900 {
901 // Keep a set of classes that we already traversed. We use this to
901 // Keep a set of classes that we already traversed. We use this to
902 // enforce that we traverse base classes prior to subclasses.
902 // enforce that we traverse base classes prior to subclasses.
903 QSet<AbstractMetaClass *> classes;
903 QSet<AbstractMetaClass *> classes;
904 foreach (AbstractMetaClass *c, m_meta_classes) {
904 foreach (AbstractMetaClass *c, m_meta_classes) {
905 figureOutEnumValuesForClass(c, &classes);
905 figureOutEnumValuesForClass(c, &classes);
906 }
906 }
907 }
907 }
908
908
909 void AbstractMetaBuilder::figureOutDefaultEnumArguments()
909 void AbstractMetaBuilder::figureOutDefaultEnumArguments()
910 {
910 {
911 foreach (AbstractMetaClass *meta_class, m_meta_classes) {
911 foreach (AbstractMetaClass *meta_class, m_meta_classes) {
912 foreach (AbstractMetaFunction *meta_function, meta_class->functions()) {
912 foreach (AbstractMetaFunction *meta_function, meta_class->functions()) {
913 foreach (AbstractMetaArgument *arg, meta_function->arguments()) {
913 foreach (AbstractMetaArgument *arg, meta_function->arguments()) {
914
914
915 QString expr = arg->defaultValueExpression();
915 QString expr = arg->defaultValueExpression();
916 if (expr.isEmpty())
916 if (expr.isEmpty())
917 continue;
917 continue;
918
918
919 if (!meta_function->replacedDefaultExpression(meta_function->implementingClass(),
919 if (!meta_function->replacedDefaultExpression(meta_function->implementingClass(),
920 arg->argumentIndex()+1).isEmpty()) {
920 arg->argumentIndex()+1).isEmpty()) {
921 continue;
921 continue;
922 }
922 }
923
923
924 QString new_expr = expr;
924 QString new_expr = expr;
925 if (arg->type()->isEnum()) {
925 if (arg->type()->isEnum()) {
926 QStringList lst = expr.split(QLatin1String("::"));
926 QStringList lst = expr.split(QLatin1String("::"));
927 if (lst.size() == 1) {
927 if (lst.size() == 1) {
928 QVector<AbstractMetaClass *> classes(1, meta_class);
928 QVector<AbstractMetaClass *> classes(1, meta_class);
929 AbstractMetaEnum *e = 0;
929 AbstractMetaEnum *e = 0;
930 while (!classes.isEmpty() && e == 0) {
930 while (!classes.isEmpty() && e == 0) {
931 if (classes.front() != 0) {
931 if (classes.front() != 0) {
932 classes << classes.front()->baseClass();
932 classes << classes.front()->baseClass();
933
933
934 AbstractMetaClassList interfaces = classes.front()->interfaces();
934 AbstractMetaClassList interfaces = classes.front()->interfaces();
935 foreach (AbstractMetaClass *interface, interfaces)
935 foreach (AbstractMetaClass *interface, interfaces)
936 classes << interface->primaryInterfaceImplementor();
936 classes << interface->primaryInterfaceImplementor();
937
937
938 e = classes.front()->findEnumForValue(expr);
938 e = classes.front()->findEnumForValue(expr);
939 }
939 }
940
940
941 classes.pop_front();
941 classes.pop_front();
942 }
942 }
943
943
944 if (e != 0) {
944 if (e != 0) {
945 new_expr = QString("%1.%2")
945 new_expr = QString("%1.%2")
946 .arg(e->typeEntry()->qualifiedTargetLangName())
946 .arg(e->typeEntry()->qualifiedTargetLangName())
947 .arg(expr);
947 .arg(expr);
948 } else {
948 } else {
949 ReportHandler::warning("Cannot find enum constant for value '" + expr + "' in '" + meta_class->name() + "' or any of its super classes");
949 ReportHandler::warning("Cannot find enum constant for value '" + expr + "' in '" + meta_class->name() + "' or any of its super classes");
950 }
950 }
951 } else if (lst.size() == 2) {
951 } else if (lst.size() == 2) {
952 AbstractMetaClass *cl = m_meta_classes.findClass(lst.at(0));
952 AbstractMetaClass *cl = m_meta_classes.findClass(lst.at(0));
953 if (!cl) {
953 if (!cl) {
954 ReportHandler::warning("missing required class for enums: " + lst.at(0));
954 ReportHandler::warning("missing required class for enums: " + lst.at(0));
955 continue;
955 continue;
956 }
956 }
957 new_expr = QString("%1.%2.%3")
957 new_expr = QString("%1.%2.%3")
958 .arg(cl->typeEntry()->qualifiedTargetLangName())
958 .arg(cl->typeEntry()->qualifiedTargetLangName())
959 .arg(arg->type()->name())
959 .arg(arg->type()->name())
960 .arg(lst.at(1));
960 .arg(lst.at(1));
961 } else {
961 } else {
962 ReportHandler::warning("bad default value passed to enum " + expr);
962 ReportHandler::warning("bad default value passed to enum " + expr);
963 }
963 }
964
964
965 } else if(arg->type()->isFlags()) {
965 } else if(arg->type()->isFlags()) {
966 const FlagsTypeEntry *flagsEntry =
966 const FlagsTypeEntry *flagsEntry =
967 static_cast<const FlagsTypeEntry *>(arg->type()->typeEntry());
967 static_cast<const FlagsTypeEntry *>(arg->type()->typeEntry());
968 EnumTypeEntry *enumEntry = flagsEntry->originator();
968 EnumTypeEntry *enumEntry = flagsEntry->originator();
969 AbstractMetaEnum *meta_enum = m_meta_classes.findEnum(enumEntry);
969 AbstractMetaEnum *meta_enum = m_meta_classes.findEnum(enumEntry);
970 if (!meta_enum) {
970 if (!meta_enum) {
971 ReportHandler::warning("unknown required enum " + enumEntry->qualifiedCppName());
971 ReportHandler::warning("unknown required enum " + enumEntry->qualifiedCppName());
972 continue;
972 continue;
973 }
973 }
974
974
975 int value = figureOutEnumValue(expr, 0, meta_enum, meta_function);
975 int value = figureOutEnumValue(expr, 0, meta_enum, meta_function);
976 new_expr = QString::number(value);
976 new_expr = QString::number(value);
977
977
978 } else if (arg->type()->isPrimitive()) {
978 } else if (arg->type()->isPrimitive()) {
979 AbstractMetaEnumValue *value = 0;
979 AbstractMetaEnumValue *value = 0;
980 if (expr.contains("::"))
980 if (expr.contains("::"))
981 value = m_meta_classes.findEnumValue(expr);
981 value = m_meta_classes.findEnumValue(expr);
982 if (!value)
982 if (!value)
983 value = meta_class->findEnumValue(expr, 0);
983 value = meta_class->findEnumValue(expr, 0);
984
984
985 if (value) {
985 if (value) {
986 new_expr = QString::number(value->value());
986 new_expr = QString::number(value->value());
987 } else if (expr.contains(QLatin1Char('+'))) {
987 } else if (expr.contains(QLatin1Char('+'))) {
988 new_expr = QString::number(figureOutEnumValue(expr, 0, 0));
988 new_expr = QString::number(figureOutEnumValue(expr, 0, 0));
989
989
990 }
990 }
991
991
992
992
993
993
994 }
994 }
995
995
996 arg->setDefaultValueExpression(new_expr);
996 arg->setDefaultValueExpression(new_expr);
997 }
997 }
998 }
998 }
999 }
999 }
1000 }
1000 }
1001
1001
1002
1002
1003 AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enum_item, AbstractMetaClass *enclosing, const QSet<QString> &enumsDeclarations)
1003 AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enum_item, AbstractMetaClass *enclosing, const QSet<QString> &enumsDeclarations)
1004 {
1004 {
1005 // Skipping private enums.
1005 // Skipping private enums.
1006 if (enum_item->accessPolicy() == CodeModel::Private) {
1006 if (enum_item->accessPolicy() == CodeModel::Private) {
1007 return 0;
1007 return 0;
1008 }
1008 }
1009
1009
1010 QString qualified_name = enum_item->qualifiedName().join("::");
1010 QString qualified_name = enum_item->qualifiedName().join("::");
1011
1011
1012 TypeEntry *type_entry = TypeDatabase::instance()->findType(qualified_name);
1012 TypeEntry *type_entry = TypeDatabase::instance()->findType(qualified_name);
1013 QString enum_name = enum_item->name();
1013 QString enum_name = enum_item->name();
1014
1014
1015 QString class_name;
1015 QString class_name;
1016 if (m_current_class)
1016 if (m_current_class)
1017 class_name = m_current_class->typeEntry()->qualifiedCppName();
1017 class_name = m_current_class->typeEntry()->qualifiedCppName();
1018
1018
1019 if (TypeDatabase::instance()->isEnumRejected(class_name, enum_name)) {
1019 if (TypeDatabase::instance()->isEnumRejected(class_name, enum_name)) {
1020 m_rejected_enums.insert(qualified_name, GenerationDisabled);
1020 m_rejected_enums.insert(qualified_name, GenerationDisabled);
1021 return 0;
1021 return 0;
1022 }
1022 }
1023
1023
1024 if (!type_entry || !type_entry->isEnum()) {
1024 if (!type_entry || !type_entry->isEnum()) {
1025 QString context = m_current_class ? m_current_class->name() : QLatin1String("");
1025 QString context = m_current_class ? m_current_class->name() : QLatin1String("");
1026 ReportHandler::warning(QString("enum '%1' does not have a type entry or is not an enum")
1026 ReportHandler::warning(QString("enum '%1' does not have a type entry or is not an enum")
1027 .arg(qualified_name));
1027 .arg(qualified_name));
1028 m_rejected_enums.insert(qualified_name, NotInTypeSystem);
1028 m_rejected_enums.insert(qualified_name, NotInTypeSystem);
1029 return 0;
1029 return 0;
1030 }
1030 }
1031
1031
1032 AbstractMetaEnum *meta_enum = createMetaEnum();
1032 AbstractMetaEnum *meta_enum = createMetaEnum();
1033 if ( enumsDeclarations.contains(qualified_name)
1033 if ( enumsDeclarations.contains(qualified_name)
1034 || enumsDeclarations.contains(enum_name)) {
1034 || enumsDeclarations.contains(enum_name)) {
1035 meta_enum->setHasQEnumsDeclaration(true);
1035 meta_enum->setHasQEnumsDeclaration(true);
1036 }
1036 }
1037
1037
1038 meta_enum->setTypeEntry((EnumTypeEntry *) type_entry);
1038 meta_enum->setTypeEntry((EnumTypeEntry *) type_entry);
1039 switch (enum_item->accessPolicy()) {
1039 switch (enum_item->accessPolicy()) {
1040 case CodeModel::Public: *meta_enum += AbstractMetaAttributes::Public; break;
1040 case CodeModel::Public: *meta_enum += AbstractMetaAttributes::Public; break;
1041 case CodeModel::Protected: *meta_enum += AbstractMetaAttributes::Protected; break;
1041 case CodeModel::Protected: *meta_enum += AbstractMetaAttributes::Protected; break;
1042 // case CodeModel::Private: *meta_enum += AbstractMetaAttributes::Private; break;
1042 // case CodeModel::Private: *meta_enum += AbstractMetaAttributes::Private; break;
1043 default: break;
1043 default: break;
1044 }
1044 }
1045
1045
1046 ReportHandler::debugMedium(QString(" - traversing enum %1").arg(meta_enum->fullName()));
1046 ReportHandler::debugMedium(QString(" - traversing enum %1").arg(meta_enum->fullName()));
1047
1047
1048 foreach (EnumeratorModelItem value, enum_item->enumerators()) {
1048 foreach (EnumeratorModelItem value, enum_item->enumerators()) {
1049
1049
1050 AbstractMetaEnumValue *meta_enum_value = createMetaEnumValue();
1050 AbstractMetaEnumValue *meta_enum_value = createMetaEnumValue();
1051 meta_enum_value->setName(value->name());
1051 meta_enum_value->setName(value->name());
1052 // Deciding the enum value...
1052 // Deciding the enum value...
1053
1053
1054 meta_enum_value->setStringValue(value->value());
1054 meta_enum_value->setStringValue(value->value());
1055 meta_enum->addEnumValue(meta_enum_value);
1055 meta_enum->addEnumValue(meta_enum_value);
1056
1056
1057 ReportHandler::debugFull(" - " + meta_enum_value->name() + " = "
1057 ReportHandler::debugFull(" - " + meta_enum_value->name() + " = "
1058 + meta_enum_value->value());
1058 + meta_enum_value->value());
1059
1059
1060 // Add into global register...
1060 // Add into global register...
1061 if (enclosing)
1061 if (enclosing)
1062 m_enum_values[enclosing->name() + "::" + meta_enum_value->name()] = meta_enum_value;
1062 m_enum_values[enclosing->name() + "::" + meta_enum_value->name()] = meta_enum_value;
1063 else
1063 else
1064 m_enum_values[meta_enum_value->name()] = meta_enum_value;
1064 m_enum_values[meta_enum_value->name()] = meta_enum_value;
1065 }
1065 }
1066
1066
1067 QFileInfo info(enum_item->fileName());
1067 QFileInfo info(enum_item->fileName());
1068 meta_enum->typeEntry()->setInclude(Include(Include::IncludePath, info.fileName()));
1068 meta_enum->typeEntry()->setInclude(Include(Include::IncludePath, info.fileName()));
1069
1069
1070 m_enums << meta_enum;
1070 m_enums << meta_enum;
1071
1071
1072 return meta_enum;
1072 return meta_enum;
1073 }
1073 }
1074
1074
1075 AbstractMetaClass *AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typeAlias)
1075 AbstractMetaClass *AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typeAlias)
1076 {
1076 {
1077 QString class_name = strip_template_args(typeAlias->name());
1077 QString class_name = strip_template_args(typeAlias->name());
1078
1078
1079 QString full_class_name = class_name;
1079 QString full_class_name = class_name;
1080 // we have an inner class
1080 // we have an inner class
1081 if (m_current_class) {
1081 if (m_current_class) {
1082 full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
1082 full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
1083 + "::" + full_class_name;
1083 + "::" + full_class_name;
1084 }
1084 }
1085
1085
1086 // If we haven't specified anything for the typedef, then we don't care
1086 // If we haven't specified anything for the typedef, then we don't care
1087 ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
1087 ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
1088 if (type == 0)
1088 if (type == 0)
1089 return 0;
1089 return 0;
1090
1090
1091 if (type->isObject())
1091 if (type->isObject())
1092 static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(strip_template_args(typeAlias->type().qualifiedName().join("::"))));
1092 static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(strip_template_args(typeAlias->type().qualifiedName().join("::"))));
1093
1093
1094 AbstractMetaClass *meta_class = createMetaClass();
1094 AbstractMetaClass *meta_class = createMetaClass();
1095 meta_class->setTypeAlias(true);
1095 meta_class->setTypeAlias(true);
1096 meta_class->setTypeEntry(type);
1096 meta_class->setTypeEntry(type);
1097 meta_class->setBaseClassNames(QStringList() << typeAlias->type().qualifiedName().join("::"));
1097 meta_class->setBaseClassNames(QStringList() << typeAlias->type().qualifiedName().join("::"));
1098 *meta_class += AbstractMetaAttributes::Public;
1098 *meta_class += AbstractMetaAttributes::Public;
1099
1099
1100 // Set the default include file name
1100 // Set the default include file name
1101 if (!type->include().isValid()) {
1101 if (!type->include().isValid()) {
1102 QFileInfo info(typeAlias->fileName());
1102 QFileInfo info(typeAlias->fileName());
1103 type->setInclude(Include(Include::IncludePath, info.fileName()));
1103 type->setInclude(Include(Include::IncludePath, info.fileName()));
1104 }
1104 }
1105
1105
1106 return meta_class;
1106 return meta_class;
1107 }
1107 }
1108
1108
1109 AbstractMetaClass *AbstractMetaBuilder::traverseClass(ClassModelItem class_item)
1109 AbstractMetaClass *AbstractMetaBuilder::traverseClass(ClassModelItem class_item)
1110 {
1110 {
1111 QString class_name = strip_template_args(class_item->name());
1111 QString class_name = strip_template_args(class_item->name());
1112 QString full_class_name = class_name;
1112 QString full_class_name = class_name;
1113
1113
1114 // we have inner an class
1114 // we have inner an class
1115 if (m_current_class) {
1115 if (m_current_class) {
1116 full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
1116 full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
1117 + "::" + full_class_name;
1117 + "::" + full_class_name;
1118 }
1118 }
1119
1119
1120 ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
1120 ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
1121 RejectReason reason = NoReason;
1121 RejectReason reason = NoReason;
1122
1122
1123 if (full_class_name == "QMetaTypeId") {
1123 if (full_class_name == "QMetaTypeId") {
1124 // QtScript: record which types have been declared
1124 // QtScript: record which types have been declared
1125 int lpos = class_item->name().indexOf('<');
1125 int lpos = class_item->name().indexOf('<');
1126 int rpos = class_item->name().lastIndexOf('>');
1126 int rpos = class_item->name().lastIndexOf('>');
1127 if ((lpos != -1) && (rpos != -1)) {
1127 if ((lpos != -1) && (rpos != -1)) {
1128 QString declared_typename = class_item->name().mid(lpos+1, rpos - lpos-1);
1128 QString declared_typename = class_item->name().mid(lpos+1, rpos - lpos-1);
1129 m_qmetatype_declared_typenames.insert(declared_typename);
1129 m_qmetatype_declared_typenames.insert(declared_typename);
1130 }
1130 }
1131 }
1131 }
1132
1132
1133 if (TypeDatabase::instance()->isClassRejected(full_class_name)) {
1133 if (TypeDatabase::instance()->isClassRejected(full_class_name)) {
1134 reason = GenerationDisabled;
1134 reason = GenerationDisabled;
1135 } else if (!type) {
1135 } else if (!type) {
1136 TypeEntry *te = TypeDatabase::instance()->findType(full_class_name);
1136 TypeEntry *te = TypeDatabase::instance()->findType(full_class_name);
1137 if (te && !te->isComplex())
1137 if (te && !te->isComplex())
1138 reason = RedefinedToNotClass;
1138 reason = RedefinedToNotClass;
1139 else
1139 else
1140 reason = NotInTypeSystem;
1140 reason = NotInTypeSystem;
1141 } else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
1141 } else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
1142 reason = GenerationDisabled;
1142 reason = GenerationDisabled;
1143 }
1143 }
1144
1144
1145 if (reason != NoReason) {
1145 if (reason != NoReason) {
1146 m_rejected_classes.insert(full_class_name, reason);
1146 m_rejected_classes.insert(full_class_name, reason);
1147 return 0;
1147 return 0;
1148 }
1148 }
1149
1149
1150 if (type->isObject()) {
1150 if (type->isObject()) {
1151 ((ObjectTypeEntry *)type)->setQObject(isQObject(full_class_name));
1151 ((ObjectTypeEntry *)type)->setQObject(isQObject(full_class_name));
1152 }
1152 }
1153
1153
1154 AbstractMetaClass *meta_class = createMetaClass();
1154 AbstractMetaClass *meta_class = createMetaClass();
1155 meta_class->setTypeEntry(type);
1155 meta_class->setTypeEntry(type);
1156 meta_class->setBaseClassNames(class_item->baseClasses());
1156 meta_class->setBaseClassNames(class_item->baseClasses());
1157 *meta_class += AbstractMetaAttributes::Public;
1157 *meta_class += AbstractMetaAttributes::Public;
1158
1158
1159 AbstractMetaClass *old_current_class = m_current_class;
1159 AbstractMetaClass *old_current_class = m_current_class;
1160 m_current_class = meta_class;
1160 m_current_class = meta_class;
1161
1161
1162 if (type->isContainer()) {
1162 if (type->isContainer()) {
1163 ReportHandler::debugSparse(QString("container: '%1'").arg(full_class_name));
1163 ReportHandler::debugSparse(QString("container: '%1'").arg(full_class_name));
1164 } else {
1164 } else {
1165 ReportHandler::debugSparse(QString("class: '%1'").arg(meta_class->fullName()));
1165 ReportHandler::debugSparse(QString("class: '%1'").arg(meta_class->fullName()));
1166 }
1166 }
1167
1167
1168 TemplateParameterList template_parameters = class_item->templateParameters();
1168 TemplateParameterList template_parameters = class_item->templateParameters();
1169 QList<TypeEntry *> template_args;
1169 QList<TypeEntry *> template_args;
1170 template_args.clear();
1170 template_args.clear();
1171 for (int i=0; i<template_parameters.size(); ++i) {
1171 for (int i=0; i<template_parameters.size(); ++i) {
1172 const TemplateParameterModelItem &param = template_parameters.at(i);
1172 const TemplateParameterModelItem &param = template_parameters.at(i);
1173 TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name());
1173 TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name());
1174 param_type->setOrdinal(i);
1174 param_type->setOrdinal(i);
1175 template_args.append(param_type);
1175 template_args.append(param_type);
1176 }
1176 }
1177 meta_class->setTemplateArguments(template_args);
1177 meta_class->setTemplateArguments(template_args);
1178
1178
1179 parseQ_Property(meta_class, class_item->propertyDeclarations());
1179 parseQ_Property(meta_class, class_item->propertyDeclarations());
1180
1180
1181 traverseFunctions(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
1181 traverseFunctions(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
1182 traverseEnums(model_dynamic_cast<ScopeModelItem>(class_item), meta_class, class_item->enumsDeclarations());
1182 traverseEnums(model_dynamic_cast<ScopeModelItem>(class_item), meta_class, class_item->enumsDeclarations());
1183 traverseFields(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
1183 traverseFields(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
1184
1184
1185 // Inner classes
1185 // Inner classes
1186 {
1186 {
1187 QList<ClassModelItem> inner_classes = class_item->classMap().values();
1187 QList<ClassModelItem> inner_classes = class_item->classMap().values();
1188 foreach (const ClassModelItem &ci, inner_classes) {
1188 foreach (const ClassModelItem &ci, inner_classes) {
1189 AbstractMetaClass *cl = traverseClass(ci);
1189 AbstractMetaClass *cl = traverseClass(ci);
1190 if (cl) {
1190 if (cl) {
1191 cl->setEnclosingClass(meta_class);
1191 cl->setEnclosingClass(meta_class);
1192 m_meta_classes << cl;
1192 m_meta_classes << cl;
1193 }
1193 }
1194 }
1194 }
1195
1195
1196 }
1196 }
1197
1197
1198 // Go through all typedefs to see if we have defined any
1198 // Go through all typedefs to see if we have defined any
1199 // specific typedefs to be used as classes.
1199 // specific typedefs to be used as classes.
1200 TypeAliasList typeAliases = class_item->typeAliases();
1200 TypeAliasList typeAliases = class_item->typeAliases();
1201 foreach (TypeAliasModelItem typeAlias, typeAliases) {
1201 foreach (TypeAliasModelItem typeAlias, typeAliases) {
1202 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
1202 AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
1203 if (cls != 0) {
1203 if (cls != 0) {
1204 cls->setEnclosingClass(meta_class);
1204 cls->setEnclosingClass(meta_class);
1205 addAbstractMetaClass(cls);
1205 addAbstractMetaClass(cls);
1206 }
1206 }
1207 }
1207 }
1208
1208
1209
1209
1210 m_current_class = old_current_class;
1210 m_current_class = old_current_class;
1211
1211
1212 // Set the default include file name
1212 // Set the default include file name
1213 if (!type->include().isValid()) {
1213 if (!type->include().isValid()) {
1214 QFileInfo info(class_item->fileName());
1214 QFileInfo info(class_item->fileName());
1215 type->setInclude(Include(Include::IncludePath, info.fileName()));
1215 type->setInclude(Include(Include::IncludePath, info.fileName()));
1216 }
1216 }
1217
1217
1218 return meta_class;
1218 return meta_class;
1219 }
1219 }
1220
1220
1221 AbstractMetaField *AbstractMetaBuilder::traverseField(VariableModelItem field, const AbstractMetaClass *cls)
1221 AbstractMetaField *AbstractMetaBuilder::traverseField(VariableModelItem field, const AbstractMetaClass *cls)
1222 {
1222 {
1223 QString field_name = field->name();
1223 QString field_name = field->name();
1224 QString class_name = m_current_class->typeEntry()->qualifiedCppName();
1224 QString class_name = m_current_class->typeEntry()->qualifiedCppName();
1225
1225
1226 // Ignore friend decl.
1226 // Ignore friend decl.
1227 if (field->isFriend())
1227 if (field->isFriend())
1228 return 0;
1228 return 0;
1229
1229
1230 if (field->accessPolicy() == CodeModel::Private)
1230 if (field->accessPolicy() == CodeModel::Private)
1231 return 0;
1231 return 0;
1232
1232
1233 if (TypeDatabase::instance()->isFieldRejected(class_name, field_name)) {
1233 if (TypeDatabase::instance()->isFieldRejected(class_name, field_name)) {
1234 m_rejected_fields.insert(class_name + "::" + field_name, GenerationDisabled);
1234 m_rejected_fields.insert(class_name + "::" + field_name, GenerationDisabled);
1235 return 0;
1235 return 0;
1236 }
1236 }
1237
1237
1238
1238
1239 AbstractMetaField *meta_field = createMetaField();
1239 AbstractMetaField *meta_field = createMetaField();
1240 meta_field->setName(field_name);
1240 meta_field->setName(field_name);
1241 meta_field->setEnclosingClass(cls);
1241 meta_field->setEnclosingClass(cls);
1242
1242
1243 bool ok;
1243 bool ok;
1244 TypeInfo field_type = field->type();
1244 TypeInfo field_type = field->type();
1245 AbstractMetaType *meta_type = translateType(field_type, &ok);
1245 AbstractMetaType *meta_type = translateType(field_type, &ok);
1246
1246
1247 if (!meta_type || !ok) {
1247 if (!meta_type || !ok) {
1248 ReportHandler::warning(QString("skipping field '%1::%2' with unmatched type '%3'")
1248 ReportHandler::warning(QString("skipping field '%1::%2' with unmatched type '%3'")
1249 .arg(m_current_class->name())
1249 .arg(m_current_class->name())
1250 .arg(field_name)
1250 .arg(field_name)
1251 .arg(TypeInfo::resolveType(field_type, currentScope()->toItem()).qualifiedName().join("::")));
1251 .arg(TypeInfo::resolveType(field_type, currentScope()->toItem()).qualifiedName().join("::")));
1252 delete meta_field;
1252 delete meta_field;
1253 return 0;
1253 return 0;
1254 }
1254 }
1255
1255
1256 meta_field->setType(meta_type);
1256 meta_field->setType(meta_type);
1257
1257
1258 uint attr = 0;
1258 uint attr = 0;
1259 if (field->isStatic())
1259 if (field->isStatic())
1260 attr |= AbstractMetaAttributes::Static;
1260 attr |= AbstractMetaAttributes::Static;
1261
1261
1262 CodeModel::AccessPolicy policy = field->accessPolicy();
1262 CodeModel::AccessPolicy policy = field->accessPolicy();
1263 if (policy == CodeModel::Public)
1263 if (policy == CodeModel::Public)
1264 attr |= AbstractMetaAttributes::Public;
1264 attr |= AbstractMetaAttributes::Public;
1265 else if (policy == CodeModel::Protected)
1265 else if (policy == CodeModel::Protected)
1266 attr |= AbstractMetaAttributes::Protected;
1266 attr |= AbstractMetaAttributes::Protected;
1267 else
1267 else
1268 attr |= AbstractMetaAttributes::Private;
1268 attr |= AbstractMetaAttributes::Private;
1269 meta_field->setAttributes(attr);
1269 meta_field->setAttributes(attr);
1270
1270
1271 return meta_field;
1271 return meta_field;
1272 }
1272 }
1273
1273
1274 void AbstractMetaBuilder::traverseFields(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
1274 void AbstractMetaBuilder::traverseFields(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
1275 {
1275 {
1276 foreach (VariableModelItem field, scope_item->variables()) {
1276 foreach (VariableModelItem field, scope_item->variables()) {
1277 AbstractMetaField *meta_field = traverseField(field, meta_class);
1277 AbstractMetaField *meta_field = traverseField(field, meta_class);
1278
1278
1279 if (meta_field) {
1279 if (meta_field) {
1280 meta_field->setOriginalAttributes(meta_field->attributes());
1280 meta_field->setOriginalAttributes(meta_field->attributes());
1281 meta_class->addField(meta_field);
1281 meta_class->addField(meta_field);
1282 }
1282 }
1283 }
1283 }
1284 }
1284 }
1285
1285
1286 void AbstractMetaBuilder::setupFunctionDefaults(AbstractMetaFunction *meta_function, AbstractMetaClass *meta_class)
1286 void AbstractMetaBuilder::setupFunctionDefaults(AbstractMetaFunction *meta_function, AbstractMetaClass *meta_class)
1287 {
1287 {
1288 // Set the default value of the declaring class. This may be changed
1288 // Set the default value of the declaring class. This may be changed
1289 // in fixFunctions later on
1289 // in fixFunctions later on
1290 meta_function->setDeclaringClass(meta_class);
1290 meta_function->setDeclaringClass(meta_class);
1291
1291
1292 // Some of the queries below depend on the implementing class being set
1292 // Some of the queries below depend on the implementing class being set
1293 // to function properly. Such as function modifications
1293 // to function properly. Such as function modifications
1294 meta_function->setImplementingClass(meta_class);
1294 meta_function->setImplementingClass(meta_class);
1295
1295
1296 if (meta_function->name() == "operator_equal")
1296 if (meta_function->name() == "operator_equal")
1297 meta_class->setHasEqualsOperator(true);
1297 meta_class->setHasEqualsOperator(true);
1298
1298
1299 if (!meta_function->isFinalInTargetLang()
1299 if (!meta_function->isFinalInTargetLang()
1300 && meta_function->isRemovedFrom(meta_class, TypeSystem::TargetLangCode)) {
1300 && meta_function->isRemovedFrom(meta_class, TypeSystem::TargetLangCode)) {
1301 *meta_function += AbstractMetaAttributes::FinalInCpp;
1301 *meta_function += AbstractMetaAttributes::FinalInCpp;
1302 }
1302 }
1303 }
1303 }
1304
1304
1305 void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
1305 void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
1306 {
1306 {
1307 foreach (FunctionModelItem function, scope_item->functions()) {
1307 foreach (FunctionModelItem function, scope_item->functions()) {
1308 AbstractMetaFunction *meta_function = traverseFunction(function);
1308 AbstractMetaFunction *meta_function = traverseFunction(function);
1309
1309
1310 if (meta_function) {
1310 if (meta_function) {
1311 meta_function->setOriginalAttributes(meta_function->attributes());
1311 meta_function->setOriginalAttributes(meta_function->attributes());
1312 if (meta_class->isNamespace())
1312 if (meta_class->isNamespace())
1313 *meta_function += AbstractMetaAttributes::Static;
1313 *meta_function += AbstractMetaAttributes::Static;
1314
1314
1315 if (QPropertySpec *read = meta_class->propertySpecForRead(meta_function->name())) {
1315 if (QPropertySpec *read = meta_class->propertySpecForRead(meta_function->name())) {
1316 if (read->type() == meta_function->type()->typeEntry()) {
1316 if (read->type() == meta_function->type()->typeEntry()) {
1317 *meta_function += AbstractMetaAttributes::PropertyReader;
1317 *meta_function += AbstractMetaAttributes::PropertyReader;
1318 meta_function->setPropertySpec(read);
1318 meta_function->setPropertySpec(read);
1319 // printf("%s is reader for %s\n",
1319 // printf("%s is reader for %s\n",
1320 // qPrintable(meta_function->name()),
1320 // qPrintable(meta_function->name()),
1321 // qPrintable(read->name()));
1321 // qPrintable(read->name()));
1322 }
1322 }
1323 } else if (QPropertySpec *write =
1323 } else if (QPropertySpec *write =
1324 meta_class->propertySpecForWrite(meta_function->name())) {
1324 meta_class->propertySpecForWrite(meta_function->name())) {
1325 if (write->type() == meta_function->arguments().at(0)->type()->typeEntry()) {
1325 if (write->type() == meta_function->arguments().at(0)->type()->typeEntry()) {
1326 *meta_function += AbstractMetaAttributes::PropertyWriter;
1326 *meta_function += AbstractMetaAttributes::PropertyWriter;
1327 meta_function->setPropertySpec(write);
1327 meta_function->setPropertySpec(write);
1328 // printf("%s is writer for %s\n",
1328 // printf("%s is writer for %s\n",
1329 // qPrintable(meta_function->name()),
1329 // qPrintable(meta_function->name()),
1330 // qPrintable(write->name()));
1330 // qPrintable(write->name()));
1331 }
1331 }
1332 } else if (QPropertySpec *reset =
1332 } else if (QPropertySpec *reset =
1333 meta_class->propertySpecForReset(meta_function->name())) {
1333 meta_class->propertySpecForReset(meta_function->name())) {
1334 *meta_function += AbstractMetaAttributes::PropertyResetter;
1334 *meta_function += AbstractMetaAttributes::PropertyResetter;
1335 meta_function->setPropertySpec(reset);
1335 meta_function->setPropertySpec(reset);
1336 // printf("%s is resetter for %s\n",
1336 // printf("%s is resetter for %s\n",
1337 // qPrintable(meta_function->name()),
1337 // qPrintable(meta_function->name()),
1338 // qPrintable(reset->name()));
1338 // qPrintable(reset->name()));
1339 }
1339 }
1340
1340
1341
1341
1342 bool isInvalidDestructor = meta_function->isDestructor() && meta_function->isPrivate();
1342 bool isInvalidDestructor = meta_function->isDestructor() && meta_function->isPrivate();
1343 bool isInvalidConstructor = meta_function->isConstructor()
1343 bool isInvalidConstructor = meta_function->isConstructor()
1344 && (meta_function->isPrivate() || meta_function->isInvalid());
1344 && (meta_function->isPrivate() || meta_function->isInvalid());
1345 if ((isInvalidDestructor || isInvalidConstructor)
1345 if ((isInvalidDestructor || isInvalidConstructor)
1346 && !meta_class->hasNonPrivateConstructor()) {
1346 && !meta_class->hasNonPrivateConstructor()) {
1347 *meta_class += AbstractMetaAttributes::Final;
1347 *meta_class += AbstractMetaAttributes::Final;
1348 } else if (meta_function->isConstructor() && !meta_function->isPrivate()) {
1348 } else if (meta_function->isConstructor() && !meta_function->isPrivate()) {
1349 *meta_class -= AbstractMetaAttributes::Final;
1349 *meta_class -= AbstractMetaAttributes::Final;
1350 meta_class->setHasNonPrivateConstructor(true);
1350 meta_class->setHasNonPrivateConstructor(true);
1351 }
1351 }
1352
1352
1353 // Classes with virtual destructors should always have a shell class
1353 // Classes with virtual destructors should always have a shell class
1354 // (since we aren't registering the destructors, we need this extra check)
1354 // (since we aren't registering the destructors, we need this extra check)
1355 if (meta_function->isDestructor() && !meta_function->isFinal())
1355 if (meta_function->isDestructor() && !meta_function->isFinal())
1356 meta_class->setForceShellClass(true);
1356 meta_class->setForceShellClass(true);
1357
1357
1358 if (!meta_function->isDestructor()
1358 if (!meta_function->isDestructor()
1359 && !meta_function->isInvalid()
1359 && !meta_function->isInvalid()
1360 && (!meta_function->isConstructor() || !meta_function->isPrivate())) {
1360 && (!meta_function->isConstructor() || !meta_function->isPrivate())) {
1361
1361
1362 if (meta_class->typeEntry()->designatedInterface() && !meta_function->isPublic()
1362 if (meta_class->typeEntry()->designatedInterface() && !meta_function->isPublic()
1363 && !meta_function->isPrivate()) {
1363 && !meta_function->isPrivate()) {
1364 QString warn = QString("non-public function '%1' in interface '%2'")
1364 QString warn = QString("non-public function '%1' in interface '%2'")
1365 .arg(meta_function->name()).arg(meta_class->name());
1365 .arg(meta_function->name()).arg(meta_class->name());
1366 ReportHandler::warning(warn);
1366 ReportHandler::warning(warn);
1367
1367
1368 meta_function->setVisibility(AbstractMetaClass::Public);
1368 meta_function->setVisibility(AbstractMetaClass::Public);
1369 }
1369 }
1370
1370
1371 setupFunctionDefaults(meta_function, meta_class);
1371 setupFunctionDefaults(meta_function, meta_class);
1372
1372
1373 if (meta_function->isSignal() && meta_class->hasSignal(meta_function)) {
1373 if (meta_function->isSignal() && meta_class->hasSignal(meta_function)) {
1374 QString warn = QString("signal '%1' in class '%2' is overloaded.")
1374 QString warn = QString("signal '%1' in class '%2' is overloaded.")
1375 .arg(meta_function->name()).arg(meta_class->name());
1375 .arg(meta_function->name()).arg(meta_class->name());
1376 ReportHandler::warning(warn);
1376 ReportHandler::warning(warn);
1377 }
1377 }
1378
1378
1379 if (meta_function->isSignal() && !meta_class->isQObject()) {
1379 if (meta_function->isSignal() && !meta_class->isQObject()) {
1380 QString warn = QString("signal '%1' in non-QObject class '%2'")
1380 QString warn = QString("signal '%1' in non-QObject class '%2'")
1381 .arg(meta_function->name()).arg(meta_class->name());
1381 .arg(meta_function->name()).arg(meta_class->name());
1382 ReportHandler::warning(warn);
1382 ReportHandler::warning(warn);
1383 }
1383 }
1384
1384
1385 meta_class->addFunction(meta_function);
1385 meta_class->addFunction(meta_function);
1386 } else if (meta_function->isDestructor() && !meta_function->isPublic()) {
1386 } else if (meta_function->isDestructor() && !meta_function->isPublic()) {
1387 meta_class->setHasPublicDestructor(false);
1387 meta_class->setHasPublicDestructor(false);
1388 }
1388 }
1389 }
1389 }
1390 }
1390 }
1391 }
1391 }
1392
1392
1393 bool AbstractMetaBuilder::setupInheritance(AbstractMetaClass *meta_class)
1393 bool AbstractMetaBuilder::setupInheritance(AbstractMetaClass *meta_class)
1394 {
1394 {
1395 Q_ASSERT(!meta_class->isInterface());
1395 Q_ASSERT(!meta_class->isInterface());
1396
1396
1397 if (m_setup_inheritance_done.contains(meta_class))
1397 if (m_setup_inheritance_done.contains(meta_class))
1398 return true;
1398 return true;
1399 m_setup_inheritance_done.insert(meta_class);
1399 m_setup_inheritance_done.insert(meta_class);
1400
1400
1401 QStringList base_classes = meta_class->baseClassNames();
1401 QStringList base_classes = meta_class->baseClassNames();
1402
1402
1403 TypeDatabase *types = TypeDatabase::instance();
1403 TypeDatabase *types = TypeDatabase::instance();
1404
1404
1405 // we only support our own containers and ONLY if there is only one baseclass
1405 // we only support our own containers and ONLY if there is only one baseclass
1406 if (base_classes.size() == 1 && base_classes.first().count('<') == 1) {
1406 if (base_classes.size() == 1 && base_classes.first().count('<') == 1) {
1407 QStringList scope = meta_class->typeEntry()->qualifiedCppName().split("::");
1407 QStringList scope = meta_class->typeEntry()->qualifiedCppName().split("::");
1408 scope.removeLast();
1408 scope.removeLast();
1409 for (int i=scope.size(); i>=0; --i) {
1409 for (int i=scope.size(); i>=0; --i) {
1410 QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join("::") + "::" : QString();
1410 QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join("::") + "::" : QString();
1411 QString complete_name = prefix + base_classes.first();
1411 QString complete_name = prefix + base_classes.first();
1412 TypeParser::Info info = TypeParser::parse(complete_name);
1412 TypeParser::Info info = TypeParser::parse(complete_name);
1413 QString base_name = info.qualified_name.join("::");
1413 QString base_name = info.qualified_name.join("::");
1414
1414
1415 AbstractMetaClass *templ = 0;
1415 AbstractMetaClass *templ = 0;
1416 foreach (AbstractMetaClass *c, m_templates) {
1416 foreach (AbstractMetaClass *c, m_templates) {
1417 if (c->typeEntry()->name() == base_name) {
1417 if (c->typeEntry()->name() == base_name) {
1418 templ = c;
1418 templ = c;
1419 break;
1419 break;
1420 }
1420 }
1421 }
1421 }
1422
1422
1423 if (templ == 0)
1423 if (templ == 0)
1424 templ = m_meta_classes.findClass(base_name);
1424 templ = m_meta_classes.findClass(base_name);
1425
1425
1426 if (templ) {
1426 if (templ) {
1427 setupInheritance(templ);
1427 setupInheritance(templ);
1428 inheritTemplate(meta_class, templ, info);
1428 inheritTemplate(meta_class, templ, info);
1429 return true;
1429 return true;
1430 }
1430 }
1431 }
1431 }
1432
1432
1433 ReportHandler::warning(QString("template baseclass '%1' of '%2' is not known")
1433 ReportHandler::warning(QString("template baseclass '%1' of '%2' is not known")
1434 .arg(base_classes.first())
1434 .arg(base_classes.first())
1435 .arg(meta_class->name()));
1435 .arg(meta_class->name()));
1436 return false;
1436 return false;
1437 }
1437 }
1438
1438
1439 int primary = -1;
1439 int primary = -1;
1440 int primaries = 0;
1440 int primaries = 0;
1441 for (int i=0; i<base_classes.size(); ++i) {
1441 for (int i=0; i<base_classes.size(); ++i) {
1442
1442
1443 if (types->isClassRejected(base_classes.at(i)))
1443 if (types->isClassRejected(base_classes.at(i)))
1444 continue;
1444 continue;
1445
1445
1446 TypeEntry *base_class_entry = types->findType(base_classes.at(i));
1446 TypeEntry *base_class_entry = types->findType(base_classes.at(i));
1447 if (!base_class_entry) {
1447 if (!base_class_entry) {
1448 ReportHandler::warning(QString("class '%1' inherits from unknown base class '%2'")
1448 ReportHandler::warning(QString("class '%1' inherits from unknown base class '%2'")
1449 .arg(meta_class->name()).arg(base_classes.at(i)));
1449 .arg(meta_class->name()).arg(base_classes.at(i)));
1450 }
1450 }
1451
1451
1452 // true for primary base class
1452 // true for primary base class
1453 else if (!base_class_entry->designatedInterface()) {
1453 else if (!base_class_entry->designatedInterface()) {
1454 if (primaries > 0) {
1454 if (primaries > 0) {
1455 ReportHandler::warning(QString("class '%1' has multiple primary base classes"
1455 ReportHandler::warning(QString("class '%1' has multiple primary base classes"
1456 " '%2' and '%3'")
1456 " '%2' and '%3'")
1457 .arg(meta_class->name())
1457 .arg(meta_class->name())
1458 .arg(base_classes.at(primary))
1458 .arg(base_classes.at(primary))
1459 .arg(base_class_entry->name()));
1459 .arg(base_class_entry->name()));
1460 return false;
1460 return false;
1461 }
1461 }
1462 primaries++;
1462 primaries++;
1463 primary = i;
1463 primary = i;
1464 }
1464 }
1465 }
1465 }
1466
1466
1467 if (primary >= 0) {
1467 if (primary >= 0) {
1468 AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(primary));
1468 AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(primary));
1469 if (!base_class) {
1469 if (!base_class) {
1470 ReportHandler::warning(QString("unknown baseclass for '%1': '%2'")
1470 ReportHandler::warning(QString("unknown baseclass for '%1': '%2'")
1471 .arg(meta_class->name())
1471 .arg(meta_class->name())
1472 .arg(base_classes.at(primary)));
1472 .arg(base_classes.at(primary)));
1473 return false;
1473 return false;
1474 }
1474 }
1475 meta_class->setBaseClass(base_class);
1475 meta_class->setBaseClass(base_class);
1476
1476
1477 if (meta_class->typeEntry()->designatedInterface() != 0 && meta_class->isQObject()) {
1477 if (meta_class->typeEntry()->designatedInterface() != 0 && meta_class->isQObject()) {
1478 ReportHandler::warning(QString("QObject extended by interface type '%1'. This is not supported and the generated Java code will not compile.")
1478 ReportHandler::warning(QString("QObject extended by interface type '%1'. This is not supported and the generated Java code will not compile.")
1479 .arg(meta_class->name()));
1479 .arg(meta_class->name()));
1480 } else if (meta_class->typeEntry()->designatedInterface() != 0 && base_class != 0 && !base_class->isInterface()) {
1480 } else if (meta_class->typeEntry()->designatedInterface() != 0 && base_class != 0 && !base_class->isInterface()) {
1481 ReportHandler::warning(QString("object type '%1' extended by interface type '%2'. The resulting API will be less expressive than the original.")
1481 ReportHandler::warning(QString("object type '%1' extended by interface type '%2'. The resulting API will be less expressive than the original.")
1482 .arg(base_class->name())
1482 .arg(base_class->name())
1483 .arg(meta_class->name()));
1483 .arg(meta_class->name()));
1484 }
1484 }
1485
1485
1486 }
1486 }
1487
1487
1488 for (int i=0; i<base_classes.size(); ++i) {
1488 for (int i=0; i<base_classes.size(); ++i) {
1489 if (types->isClassRejected(base_classes.at(i)))
1489 if (types->isClassRejected(base_classes.at(i)))
1490 continue;
1490 continue;
1491
1491
1492 if (i != primary) {
1492 if (i != primary) {
1493 AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(i));
1493 AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(i));
1494 if (base_class == 0) {
1494 if (base_class == 0) {
1495 ReportHandler::warning(QString("class not found for setup inheritance '%1'").arg(base_classes.at(i)));
1495 ReportHandler::warning(QString("class not found for setup inheritance '%1'").arg(base_classes.at(i)));
1496 return false;
1496 return false;
1497 }
1497 }
1498
1498
1499 setupInheritance(base_class);
1499 setupInheritance(base_class);
1500
1500
1501 QString interface_name = InterfaceTypeEntry::interfaceName(base_class->name());
1501 QString interface_name = InterfaceTypeEntry::interfaceName(base_class->name());
1502 AbstractMetaClass *iface = m_meta_classes.findClass(interface_name);
1502 AbstractMetaClass *iface = m_meta_classes.findClass(interface_name);
1503 if (!iface) {
1503 if (!iface) {
1504 ReportHandler::warning(QString("unknown interface for '%1': '%2'")
1504 ReportHandler::warning(QString("unknown interface for '%1': '%2'")
1505 .arg(meta_class->name())
1505 .arg(meta_class->name())
1506 .arg(interface_name));
1506 .arg(interface_name));
1507 return false;
1507 return false;
1508 }
1508 }
1509 meta_class->addInterface(iface);
1509 meta_class->addInterface(iface);
1510
1510
1511 AbstractMetaClassList interfaces = iface->interfaces();
1511 AbstractMetaClassList interfaces = iface->interfaces();
1512 foreach (AbstractMetaClass *iface, interfaces)
1512 foreach (AbstractMetaClass *iface, interfaces)
1513 meta_class->addInterface(iface);
1513 meta_class->addInterface(iface);
1514 }
1514 }
1515 }
1515 }
1516
1516
1517 return true;
1517 return true;
1518 }
1518 }
1519
1519
1520 void AbstractMetaBuilder::traverseEnums(ScopeModelItem scope_item, AbstractMetaClass *meta_class, const QStringList &enumsDeclarations)
1520 void AbstractMetaBuilder::traverseEnums(ScopeModelItem scope_item, AbstractMetaClass *meta_class, const QStringList &enumsDeclarations)
1521 {
1521 {
1522 EnumList enums = scope_item->enums();
1522 EnumList enums = scope_item->enums();
1523 foreach (EnumModelItem enum_item, enums) {
1523 foreach (EnumModelItem enum_item, enums) {
1524 AbstractMetaEnum *meta_enum = traverseEnum(enum_item, meta_class, QSet<QString>::fromList(enumsDeclarations));
1524 AbstractMetaEnum *meta_enum = traverseEnum(enum_item, meta_class, QSet<QString>::fromList(enumsDeclarations));
1525 if (meta_enum) {
1525 if (meta_enum) {
1526 meta_enum->setOriginalAttributes(meta_enum->attributes());
1526 meta_enum->setOriginalAttributes(meta_enum->attributes());
1527 meta_class->addEnum(meta_enum);
1527 meta_class->addEnum(meta_enum);
1528 meta_enum->setEnclosingClass(meta_class);
1528 meta_enum->setEnclosingClass(meta_class);
1529 }
1529 }
1530 }
1530 }
1531 }
1531 }
1532
1532
1533 AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem function_item)
1533 AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem function_item)
1534 {
1534 {
1535 QString function_name = function_item->name();
1535 QString function_name = function_item->name();
1536 QString class_name = m_current_class->typeEntry()->qualifiedCppName();
1536 QString class_name = m_current_class->typeEntry()->qualifiedCppName();
1537
1537
1538 if (TypeDatabase::instance()->isFunctionRejected(class_name, function_name)) {
1538 if (TypeDatabase::instance()->isFunctionRejected(class_name, function_name)) {
1539 m_rejected_functions.insert(class_name + "::" + function_name, GenerationDisabled);
1539 m_rejected_functions.insert(class_name + "::" + function_name, GenerationDisabled);
1540 return 0;
1540 return 0;
1541 }
1541 }
1542
1542
1543
1543
1544 Q_ASSERT(function_item->functionType() == CodeModel::Normal
1544 Q_ASSERT(function_item->functionType() == CodeModel::Normal
1545 || function_item->functionType() == CodeModel::Signal
1545 || function_item->functionType() == CodeModel::Signal
1546 || function_item->functionType() == CodeModel::Slot);
1546 || function_item->functionType() == CodeModel::Slot);
1547
1547
1548 if (function_item->isFriend())
1548 if (function_item->isFriend())
1549 return 0;
1549 return 0;
1550
1550
1551
1551
1552 QString cast_type;
1552 QString cast_type;
1553
1553
1554 if (function_name.startsWith("operator")) {
1554 if (function_name.startsWith("operator")) {
1555 function_name = rename_operator(function_name.mid(8));
1555 function_name = rename_operator(function_name.mid(8));
1556 if (function_name.isEmpty()) {
1556 if (function_name.isEmpty()) {
1557 m_rejected_functions.insert(class_name + "::" + function_name,
1557 m_rejected_functions.insert(class_name + "::" + function_name,
1558 GenerationDisabled);
1558 GenerationDisabled);
1559 return 0;
1559 return 0;
1560 }
1560 }
1561 if (function_name.contains("_cast_"))
1561 if (function_name.contains("_cast_"))
1562 cast_type = function_name.mid(14).trimmed();
1562 cast_type = function_name.mid(14).trimmed();
1563 }
1563 }
1564
1564
1565 AbstractMetaFunction *meta_function = createMetaFunction();
1565 AbstractMetaFunction *meta_function = createMetaFunction();
1566 meta_function->setConstant(function_item->isConstant());
1566 meta_function->setConstant(function_item->isConstant());
1567
1567
1568 ReportHandler::debugMedium(QString(" - %2()").arg(function_name));
1568 ReportHandler::debugMedium(QString(" - %2()").arg(function_name));
1569
1569
1570 meta_function->setName(function_name);
1570 meta_function->setName(function_name);
1571 meta_function->setOriginalName(function_item->name());
1571 meta_function->setOriginalName(function_item->name());
1572
1572
1573 if (function_item->isAbstract())
1573 if (function_item->isAbstract())
1574 *meta_function += AbstractMetaAttributes::Abstract;
1574 *meta_function += AbstractMetaAttributes::Abstract;
1575
1575
1576 if (!meta_function->isAbstract())
1576 if (!meta_function->isAbstract())
1577 *meta_function += AbstractMetaAttributes::Native;
1577 *meta_function += AbstractMetaAttributes::Native;
1578
1578
1579 if (!function_item->isVirtual())
1579 if (!function_item->isVirtual())
1580 *meta_function += AbstractMetaAttributes::Final;
1580 *meta_function += AbstractMetaAttributes::Final;
1581
1581
1582 if (function_item->isInvokable())
1582 if (function_item->isInvokable())
1583 *meta_function += AbstractMetaAttributes::Invokable;
1583 *meta_function += AbstractMetaAttributes::Invokable;
1584
1584
1585 if (function_item->isStatic()) {
1585 if (function_item->isStatic()) {
1586 *meta_function += AbstractMetaAttributes::Static;
1586 *meta_function += AbstractMetaAttributes::Static;
1587 *meta_function += AbstractMetaAttributes::Final;
1587 *meta_function += AbstractMetaAttributes::Final;
1588 }
1588 }
1589
1589
1590 // Access rights
1590 // Access rights
1591 if (function_item->accessPolicy() == CodeModel::Public)
1591 if (function_item->accessPolicy() == CodeModel::Public)
1592 *meta_function += AbstractMetaAttributes::Public;
1592 *meta_function += AbstractMetaAttributes::Public;
1593 else if (function_item->accessPolicy() == CodeModel::Private)
1593 else if (function_item->accessPolicy() == CodeModel::Private)
1594 *meta_function += AbstractMetaAttributes::Private;
1594 *meta_function += AbstractMetaAttributes::Private;
1595 else
1595 else
1596 *meta_function += AbstractMetaAttributes::Protected;
1596 *meta_function += AbstractMetaAttributes::Protected;
1597
1597
1598
1598
1599 QString stripped_class_name = class_name;
1599 QString stripped_class_name = class_name;
1600 int cc_pos = stripped_class_name.lastIndexOf("::");
1600 int cc_pos = stripped_class_name.lastIndexOf("::");
1601 if (cc_pos > 0)
1601 if (cc_pos > 0)
1602 stripped_class_name = stripped_class_name.mid(cc_pos + 2);
1602 stripped_class_name = stripped_class_name.mid(cc_pos + 2);
1603
1603
1604 TypeInfo function_type = function_item->type();
1604 TypeInfo function_type = function_item->type();
1605 if (function_name.startsWith('~')) {
1605 if (function_name.startsWith('~')) {
1606 meta_function->setFunctionType(AbstractMetaFunction::DestructorFunction);
1606 meta_function->setFunctionType(AbstractMetaFunction::DestructorFunction);
1607 meta_function->setInvalid(true);
1607 meta_function->setInvalid(true);
1608 } else if (strip_template_args(function_name) == stripped_class_name) {
1608 } else if (strip_template_args(function_name) == stripped_class_name) {
1609 meta_function->setFunctionType(AbstractMetaFunction::ConstructorFunction);
1609 meta_function->setFunctionType(AbstractMetaFunction::ConstructorFunction);
1610 meta_function->setName(m_current_class->name());
1610 meta_function->setName(m_current_class->name());
1611 } else {
1611 } else {
1612 bool ok;
1612 bool ok;
1613 AbstractMetaType *type = 0;
1613 AbstractMetaType *type = 0;
1614
1614
1615 if (!cast_type.isEmpty()) {
1615 if (!cast_type.isEmpty()) {
1616 TypeInfo info;
1616 TypeInfo info;
1617 info.setQualifiedName(QStringList(cast_type));
1617 info.setQualifiedName(QStringList(cast_type));
1618 type = translateType(info, &ok);
1618 type = translateType(info, &ok);
1619 } else {
1619 } else {
1620 type = translateType(function_type, &ok);
1620 type = translateType(function_type, &ok);
1621 }
1621 }
1622
1622
1623 if (!ok) {
1623 if (!ok) {
1624 ReportHandler::warning(QString("skipping function '%1::%2', unmatched return type '%3'")
1624 ReportHandler::warning(QString("skipping function '%1::%2', unmatched return type '%3'")
1625 .arg(class_name)
1625 .arg(class_name)
1626 .arg(function_item->name())
1626 .arg(function_item->name())
1627 .arg(function_item->type().toString()));
1627 .arg(function_item->type().toString()));
1628 m_rejected_functions[class_name + "::" + function_name] =
1628 m_rejected_functions[class_name + "::" + function_name] =
1629 UnmatchedReturnType;
1629 UnmatchedReturnType;
1630 meta_function->setInvalid(true);
1630 meta_function->setInvalid(true);
1631 return meta_function;
1631 return meta_function;
1632 }
1632 }
1633 meta_function->setType(type);
1633 meta_function->setType(type);
1634
1634
1635 if (function_item->functionType() == CodeModel::Signal)
1635 if (function_item->functionType() == CodeModel::Signal)
1636 meta_function->setFunctionType(AbstractMetaFunction::SignalFunction);
1636 meta_function->setFunctionType(AbstractMetaFunction::SignalFunction);
1637 else if (function_item->functionType() == CodeModel::Slot)
1637 else if (function_item->functionType() == CodeModel::Slot)
1638 meta_function->setFunctionType(AbstractMetaFunction::SlotFunction);
1638 meta_function->setFunctionType(AbstractMetaFunction::SlotFunction);
1639 }
1639 }
1640
1640
1641 ArgumentList arguments = function_item->arguments();
1641 ArgumentList arguments = function_item->arguments();
1642 AbstractMetaArgumentList meta_arguments;
1642 AbstractMetaArgumentList meta_arguments;
1643
1643
1644 int first_default_argument = 0;
1644 int first_default_argument = 0;
1645 for (int i=0; i<arguments.size(); ++i) {
1645 for (int i=0; i<arguments.size(); ++i) {
1646 ArgumentModelItem arg = arguments.at(i);
1646 ArgumentModelItem arg = arguments.at(i);
1647
1647
1648 bool ok;
1648 bool ok;
1649 AbstractMetaType *meta_type = translateType(arg->type(), &ok);
1649 AbstractMetaType *meta_type = translateType(arg->type(), &ok);
1650 if (!meta_type || !ok) {
1650 if (!meta_type || !ok) {
1651 ReportHandler::warning(QString("skipping function '%1::%2', "
1651 ReportHandler::warning(QString("skipping function '%1::%2', "
1652 "unmatched parameter type '%3'")
1652 "unmatched parameter type '%3'")
1653 .arg(class_name)
1653 .arg(class_name)
1654 .arg(function_item->name())
1654 .arg(function_item->name())
1655 .arg(arg->type().toString()));
1655 .arg(arg->type().toString()));
1656 m_rejected_functions[class_name + "::" + function_name] =
1656 m_rejected_functions[class_name + "::" + function_name] =
1657 UnmatchedArgumentType;
1657 UnmatchedArgumentType;
1658 meta_function->setInvalid(true);
1658 meta_function->setInvalid(true);
1659 return meta_function;
1659 return meta_function;
1660 }
1660 }
1661 AbstractMetaArgument *meta_argument = createMetaArgument();
1661 AbstractMetaArgument *meta_argument = createMetaArgument();
1662 meta_argument->setType(meta_type);
1662 meta_argument->setType(meta_type);
1663 meta_argument->setName(arg->name());
1663 meta_argument->setName(arg->name());
1664 meta_argument->setArgumentIndex(i);
1664 meta_argument->setArgumentIndex(i);
1665 meta_arguments << meta_argument;
1665 meta_arguments << meta_argument;
1666 }
1666 }
1667
1667
1668 meta_function->setArguments(meta_arguments);
1668 meta_function->setArguments(meta_arguments);
1669
1669
1670 // Find the correct default values
1670 // Find the correct default values
1671 for (int i=0; i<arguments.size(); ++i) {
1671 for (int i=0; i<arguments.size(); ++i) {
1672 ArgumentModelItem arg = arguments.at(i);
1672 ArgumentModelItem arg = arguments.at(i);
1673 AbstractMetaArgument *meta_arg = meta_arguments.at(i);
1673 AbstractMetaArgument *meta_arg = meta_arguments.at(i);
1674 if (arg->defaultValue()) {
1674 if (arg->defaultValue()) {
1675 QString expr = arg->defaultValueExpression();
1675 QString expr = arg->defaultValueExpression();
1676 if (!expr.isEmpty())
1676 if (!expr.isEmpty())
1677 meta_arg->setOriginalDefaultValueExpression(expr);
1677 meta_arg->setOriginalDefaultValueExpression(expr);
1678
1678
1679 expr = translateDefaultValue(arg, meta_arg->type(), meta_function, m_current_class, i);
1679 expr = translateDefaultValue(arg, meta_arg->type(), meta_function, m_current_class, i);
1680 if (expr.isEmpty()) {
1680 if (expr.isEmpty()) {
1681 first_default_argument = i;
1681 first_default_argument = i;
1682 } else {
1682 } else {
1683 meta_arg->setDefaultValueExpression(expr);
1683 meta_arg->setDefaultValueExpression(expr);
1684 }
1684 }
1685
1685
1686 if (meta_arg->type()->isEnum() || meta_arg->type()->isFlags()) {
1686 if (meta_arg->type()->isEnum() || meta_arg->type()->isFlags()) {
1687 m_enum_default_arguments
1687 m_enum_default_arguments
1688 << QPair<AbstractMetaArgument *, AbstractMetaFunction *>(meta_arg, meta_function);
1688 << QPair<AbstractMetaArgument *, AbstractMetaFunction *>(meta_arg, meta_function);
1689 }
1689 }
1690
1690
1691 }
1691 }
1692 }
1692 }
1693
1693
1694 // If we where not able to translate the default argument make it
1694 // If we where not able to translate the default argument make it
1695 // reset all default arguments before this one too.
1695 // reset all default arguments before this one too.
1696 for (int i=0; i<first_default_argument; ++i)
1696 for (int i=0; i<first_default_argument; ++i)
1697 meta_arguments[i]->setDefaultValueExpression(QString());
1697 meta_arguments[i]->setDefaultValueExpression(QString());
1698
1698
1699 if (ReportHandler::debugLevel() == ReportHandler::FullDebug)
1699 if (ReportHandler::debugLevel() == ReportHandler::FullDebug)
1700 foreach(AbstractMetaArgument *arg, meta_arguments)
1700 foreach(AbstractMetaArgument *arg, meta_arguments)
1701 ReportHandler::debugFull(" - " + arg->toString());
1701 ReportHandler::debugFull(" - " + arg->toString());
1702
1702
1703 return meta_function;
1703 return meta_function;
1704 }
1704 }
1705
1705
1706
1706
1707 AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, bool *ok, bool resolveType, bool resolveScope)
1707 AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, bool *ok, bool resolveType, bool resolveScope)
1708 {
1708 {
1709 Q_ASSERT(ok);
1709 Q_ASSERT(ok);
1710 *ok = true;
1710 *ok = true;
1711
1711
1712 // 1. Test the type info without resolving typedefs in case this is present in the
1712 // 1. Test the type info without resolving typedefs in case this is present in the
1713 // type system
1713 // type system
1714 TypeInfo typei;
1714 TypeInfo typei;
1715 if (resolveType) {
1715 if (resolveType) {
1716 bool isok;
1716 bool isok;
1717 AbstractMetaType *t = translateType(_typei, &isok, false, resolveScope);
1717 AbstractMetaType *t = translateType(_typei, &isok, false, resolveScope);
1718 if (t != 0 && isok)
1718 if (t != 0 && isok)
1719 return t;
1719 return t;
1720 }
1720 }
1721
1721
1722 if (!resolveType)
1722 if (!resolveType)
1723 typei = _typei;
1723 typei = _typei;
1724 else {
1724 else {
1725 // Go through all parts of the current scope (including global namespace)
1725 // Go through all parts of the current scope (including global namespace)
1726 // to resolve typedefs. The parser does not properly resolve typedefs in
1726 // to resolve typedefs. The parser does not properly resolve typedefs in
1727 // the global scope when they are referenced from inside a namespace.
1727 // the global scope when they are referenced from inside a namespace.
1728 // This is a work around to fix this bug since fixing it in resolveType
1728 // This is a work around to fix this bug since fixing it in resolveType
1729 // seemed non-trivial
1729 // seemed non-trivial
1730 int i = m_scopes.size() - 1;
1730 int i = m_scopes.size() - 1;
1731 while (i >= 0) {
1731 while (i >= 0) {
1732 typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)->toItem());
1732 typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)->toItem());
1733 if (typei.qualifiedName().join("::") != _typei.qualifiedName().join("::"))
1733 if (typei.qualifiedName().join("::") != _typei.qualifiedName().join("::"))
1734 break;
1734 break;
1735 }
1735 }
1736
1736
1737 }
1737 }
1738
1738
1739 if (typei.isFunctionPointer()) {
1739 if (typei.isFunctionPointer()) {
1740 *ok = false;
1740 *ok = false;
1741 return 0;
1741 return 0;
1742 }
1742 }
1743
1743
1744 TypeParser::Info typeInfo = TypeParser::parse(typei.toString());
1744 TypeParser::Info typeInfo = TypeParser::parse(typei.toString());
1745 if (typeInfo.is_busted) {
1745 if (typeInfo.is_busted) {
1746 *ok = false;
1746 *ok = false;
1747 return 0;
1747 return 0;
1748 }
1748 }
1749
1749
1750 // 2. Handle pointers specified as arrays with unspecified size
1750 // 2. Handle pointers specified as arrays with unspecified size
1751 bool array_of_unspecified_size = false;
1751 bool array_of_unspecified_size = false;
1752 if (typeInfo.arrays.size() > 0) {
1752 if (typeInfo.arrays.size() > 0) {
1753 array_of_unspecified_size = true;
1753 array_of_unspecified_size = true;
1754 for (int i=0; i<typeInfo.arrays.size(); ++i)
1754 for (int i=0; i<typeInfo.arrays.size(); ++i)
1755 array_of_unspecified_size = array_of_unspecified_size && typeInfo.arrays.at(i).isEmpty();
1755 array_of_unspecified_size = array_of_unspecified_size && typeInfo.arrays.at(i).isEmpty();
1756
1756
1757 if (!array_of_unspecified_size) {
1757 if (!array_of_unspecified_size) {
1758 TypeInfo newInfo;
1758 TypeInfo newInfo;
1759 //newInfo.setArguments(typei.arguments());
1759 //newInfo.setArguments(typei.arguments());
1760 newInfo.setIndirections(typei.indirections());
1760 newInfo.setIndirections(typei.indirections());
1761 newInfo.setConstant(typei.isConstant());
1761 newInfo.setConstant(typei.isConstant());
1762 newInfo.setFunctionPointer(typei.isFunctionPointer());
1762 newInfo.setFunctionPointer(typei.isFunctionPointer());
1763 newInfo.setQualifiedName(typei.qualifiedName());
1763 newInfo.setQualifiedName(typei.qualifiedName());
1764 newInfo.setReference(typei.isReference());
1764 newInfo.setReference(typei.isReference());
1765 newInfo.setVolatile(typei.isVolatile());
1765 newInfo.setVolatile(typei.isVolatile());
1766
1766
1767 AbstractMetaType *elementType = translateType(newInfo, ok);
1767 AbstractMetaType *elementType = translateType(newInfo, ok);
1768 if (!(*ok))
1768 if (!(*ok))
1769 return 0;
1769 return 0;
1770
1770
1771 for (int i=typeInfo.arrays.size()-1; i>=0; --i) {
1771 for (int i=typeInfo.arrays.size()-1; i>=0; --i) {
1772 QString s = typeInfo.arrays.at(i);
1772 QString s = typeInfo.arrays.at(i);
1773 bool isok;
1773 bool isok;
1774
1774
1775 int elems = s.toInt(&isok);
1775 int elems = s.toInt(&isok);
1776 if (!isok)
1776 if (!isok)
1777 return 0;
1777 return 0;
1778
1778
1779 AbstractMetaType *arrayType = createMetaType();
1779 AbstractMetaType *arrayType = createMetaType();
1780 arrayType->setArrayElementCount(elems);
1780 arrayType->setArrayElementCount(elems);
1781 arrayType->setArrayElementType(elementType);
1781 arrayType->setArrayElementType(elementType);
1782 arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry()));
1782 arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry()));
1783 decideUsagePattern(arrayType);
1783 decideUsagePattern(arrayType);
1784
1784
1785 elementType = arrayType;
1785 elementType = arrayType;
1786 }
1786 }
1787
1787
1788 return elementType;
1788 return elementType;
1789 } else {
1789 } else {
1790 typeInfo.indirections += typeInfo.arrays.size();
1790 typeInfo.indirections += typeInfo.arrays.size();
1791 }
1791 }
1792 }
1792 }
1793
1793
1794 QStringList qualifier_list = typeInfo.qualified_name;
1794 QStringList qualifier_list = typeInfo.qualified_name;
1795 if (qualifier_list.isEmpty()) {
1795 if (qualifier_list.isEmpty()) {
1796 ReportHandler::warning(QString("horribly broken type '%1'").arg(_typei.toString()));
1796 ReportHandler::warning(QString("horribly broken type '%1'").arg(_typei.toString()));
1797 *ok = false;
1797 *ok = false;
1798 return 0;
1798 return 0;
1799 }
1799 }
1800
1800
1801 QString qualified_name = qualifier_list.join("::");
1801 QString qualified_name = qualifier_list.join("::");
1802 QString name = qualifier_list.takeLast();
1802 QString name = qualifier_list.takeLast();
1803
1803
1804 // 3. Special case 'void' type
1804 // 3. Special case 'void' type
1805 if (name == "void" && typeInfo.indirections == 0) {
1805 if (name == "void" && typeInfo.indirections == 0) {
1806 return 0;
1806 return 0;
1807 }
1807 }
1808
1808
1809 // 4. Special case QFlags (include instantiation in name)
1809 // 4. Special case QFlags (include instantiation in name)
1810 if (qualified_name == "QFlags")
1810 if (qualified_name == "QFlags")
1811 qualified_name = typeInfo.toString();
1811 qualified_name = typeInfo.toString();
1812
1812
1813 // 5. Try to find the type
1813 // 5. Try to find the type
1814 const TypeEntry *type = TypeDatabase::instance()->findType(qualified_name);
1814 const TypeEntry *type = TypeDatabase::instance()->findType(qualified_name);
1815
1815
1816 // 6. No? Try looking it up as a flags type
1816 // 6. No? Try looking it up as a flags type
1817 if (!type)
1817 if (!type)
1818 type = TypeDatabase::instance()->findFlagsType(qualified_name);
1818 type = TypeDatabase::instance()->findFlagsType(qualified_name);
1819
1819
1820 // 7. No? Try looking it up as a container type
1820 // 7. No? Try looking it up as a container type
1821 if (!type)
1821 if (!type)
1822 type = TypeDatabase::instance()->findContainerType(name);
1822 type = TypeDatabase::instance()->findContainerType(name);
1823
1823
1824 // 8. No? Check if the current class is a template and this type is one
1824 // 8. No? Check if the current class is a template and this type is one
1825 // of the parameters.
1825 // of the parameters.
1826 if (type == 0 && m_current_class != 0) {
1826 if (type == 0 && m_current_class != 0) {
1827 QList<TypeEntry *> template_args = m_current_class->templateArguments();
1827 QList<TypeEntry *> template_args = m_current_class->templateArguments();
1828 foreach (TypeEntry *te, template_args) {
1828 foreach (TypeEntry *te, template_args) {
1829 if (te->name() == qualified_name)
1829 if (te->name() == qualified_name)
1830 type = te;
1830 type = te;
1831 }
1831 }
1832 }
1832 }
1833
1833
1834 // 9. Try finding the type by prefixing it with the current
1834 // 9. Try finding the type by prefixing it with the current
1835 // context and all baseclasses of the current context
1835 // context and all baseclasses of the current context
1836 if (!type && !TypeDatabase::instance()->isClassRejected(qualified_name) && m_current_class != 0 && resolveScope) {
1836 if (!type && !TypeDatabase::instance()->isClassRejected(qualified_name) && m_current_class != 0 && resolveScope) {
1837 QStringList contexts;
1837 QStringList contexts;
1838 contexts.append(m_current_class->qualifiedCppName());
1838 contexts.append(m_current_class->qualifiedCppName());
1839 contexts.append(currentScope()->qualifiedName().join("::"));
1839 contexts.append(currentScope()->qualifiedName().join("::"));
1840
1840
1841
1841
1842 TypeInfo info = typei;
1842 TypeInfo info = typei;
1843 bool subclasses_done = false;
1843 bool subclasses_done = false;
1844 while (!contexts.isEmpty() && type == 0) {
1844 while (!contexts.isEmpty() && type == 0) {
1845 //type = TypeDatabase::instance()->findType(contexts.at(0) + "::" + qualified_name);
1845 //type = TypeDatabase::instance()->findType(contexts.at(0) + "::" + qualified_name);
1846
1846
1847 bool isok;
1847 bool isok;
1848 info.setQualifiedName(QStringList() << contexts.at(0) << qualified_name);
1848 info.setQualifiedName(QStringList() << contexts.at(0) << qualified_name);
1849 AbstractMetaType *t = translateType(info, &isok, true, false);
1849 AbstractMetaType *t = translateType(info, &isok, true, false);
1850 if (t != 0 && isok)
1850 if (t != 0 && isok)
1851 return t;
1851 return t;
1852
1852
1853 ClassModelItem item = m_dom->findClass(contexts.at(0));
1853 ClassModelItem item = m_dom->findClass(contexts.at(0));
1854 if (item != 0)
1854 if (item != 0)
1855 contexts += item->baseClasses();
1855 contexts += item->baseClasses();
1856 contexts.pop_front();
1856 contexts.pop_front();
1857
1857
1858 // 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so
1858 // 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so
1859 // enum types from there may be addressed without any scope resolution in properties.
1859 // enum types from there may be addressed without any scope resolution in properties.
1860 if (contexts.size() == 0 && !subclasses_done) {
1860 if (contexts.size() == 0 && !subclasses_done) {
1861 contexts << "Qt";
1861 contexts << "Qt";
1862 subclasses_done = true;
1862 subclasses_done = true;
1863 }
1863 }
1864 }
1864 }
1865
1865
1866 }
1866 }
1867
1867
1868 if (!type) {
1868 if (!type) {
1869 *ok = false;
1869 *ok = false;
1870 return 0;
1870 return 0;
1871 }
1871 }
1872
1872
1873 // Used to for diagnostics later...
1873 // Used to for diagnostics later...
1874 m_used_types << type;
1874 m_used_types << type;
1875
1875
1876 // These are only implicit and should not appear in code...
1876 // These are only implicit and should not appear in code...
1877 Q_ASSERT(!type->isInterface());
1877 Q_ASSERT(!type->isInterface());
1878
1878
1879 AbstractMetaType *meta_type = createMetaType();
1879 AbstractMetaType *meta_type = createMetaType();
1880 meta_type->setTypeEntry(type);
1880 meta_type->setTypeEntry(type);
1881 meta_type->setIndirections(typeInfo.indirections);
1881 meta_type->setIndirections(typeInfo.indirections);
1882 meta_type->setReference(typeInfo.is_reference);
1882 meta_type->setReference(typeInfo.is_reference);
1883 meta_type->setConstant(typeInfo.is_constant);
1883 meta_type->setConstant(typeInfo.is_constant);
1884 meta_type->setOriginalTypeDescription(_typei.toString());
1884 meta_type->setOriginalTypeDescription(_typei.toString());
1885 decideUsagePattern(meta_type);
1885 decideUsagePattern(meta_type);
1886
1886
1887 if (meta_type->typeEntry()->isContainer()) {
1887 if (meta_type->typeEntry()->isContainer()) {
1888 ContainerTypeEntry::Type container_type = static_cast<const ContainerTypeEntry *>(type)->type();
1888 ContainerTypeEntry::Type container_type = static_cast<const ContainerTypeEntry *>(type)->type();
1889
1889
1890 if (container_type == ContainerTypeEntry::StringListContainer) {
1890 if (container_type == ContainerTypeEntry::StringListContainer) {
1891 TypeInfo info;
1891 TypeInfo info;
1892 info.setQualifiedName(QStringList() << "QString");
1892 info.setQualifiedName(QStringList() << "QString");
1893 AbstractMetaType *targ_type = translateType(info, ok);
1893 AbstractMetaType *targ_type = translateType(info, ok);
1894
1894
1895 Q_ASSERT(*ok);
1895 Q_ASSERT(*ok);
1896 Q_ASSERT(targ_type);
1896 Q_ASSERT(targ_type);
1897
1897
1898 meta_type->addInstantiation(targ_type);
1898 meta_type->addInstantiation(targ_type);
1899 meta_type->setInstantiationInCpp(false);
1899 meta_type->setInstantiationInCpp(false);
1900
1900
1901 } else {
1901 } else {
1902 foreach (const TypeParser::Info &ta, typeInfo.template_instantiations) {
1902 foreach (const TypeParser::Info &ta, typeInfo.template_instantiations) {
1903 TypeInfo info;
1903 TypeInfo info;
1904 info.setConstant(ta.is_constant);
1904 info.setConstant(ta.is_constant);
1905 info.setReference(ta.is_reference);
1905 info.setReference(ta.is_reference);
1906 info.setIndirections(ta.indirections);
1906 info.setIndirections(ta.indirections);
1907
1907
1908 info.setFunctionPointer(false);
1908 info.setFunctionPointer(false);
1909 info.setQualifiedName(ta.instantiationName().split("::"));
1909 info.setQualifiedName(ta.instantiationName().split("::"));
1910
1910
1911 AbstractMetaType *targ_type = translateType(info, ok);
1911 AbstractMetaType *targ_type = translateType(info, ok);
1912 if (!(*ok)) {
1912 if (!(*ok)) {
1913 delete meta_type;
1913 delete meta_type;
1914 return 0;
1914 return 0;
1915 }
1915 }
1916
1916
1917 meta_type->addInstantiation(targ_type);
1917 meta_type->addInstantiation(targ_type);
1918 }
1918 }
1919 }
1919 }
1920
1920
1921 if (container_type == ContainerTypeEntry::ListContainer
1921 if (container_type == ContainerTypeEntry::ListContainer
1922 || container_type == ContainerTypeEntry::VectorContainer
1922 || container_type == ContainerTypeEntry::VectorContainer
1923 || container_type == ContainerTypeEntry::StringListContainer) {
1923 || container_type == ContainerTypeEntry::StringListContainer) {
1924 Q_ASSERT(meta_type->instantiations().size() == 1);
1924 Q_ASSERT(meta_type->instantiations().size() == 1);
1925 }
1925 }
1926 }
1926 }
1927
1927
1928 return meta_type;
1928 return meta_type;
1929 }
1929 }
1930
1930
1931 void AbstractMetaBuilder::decideUsagePattern(AbstractMetaType *meta_type)
1931 void AbstractMetaBuilder::decideUsagePattern(AbstractMetaType *meta_type)
1932 {
1932 {
1933 const TypeEntry *type = meta_type->typeEntry();
1933 const TypeEntry *type = meta_type->typeEntry();
1934
1934
1935 if (type->isPrimitive() && (meta_type->actualIndirections() == 0
1935 if (type->isPrimitive() && (meta_type->actualIndirections() == 0
1936 || (meta_type->isConstant() && meta_type->isReference() && meta_type->indirections() == 0))) {
1936 || (meta_type->isConstant() && meta_type->isReference() && meta_type->indirections() == 0))) {
1937 meta_type->setTypeUsagePattern(AbstractMetaType::PrimitivePattern);
1937 meta_type->setTypeUsagePattern(AbstractMetaType::PrimitivePattern);
1938
1938
1939 } else if (type->isVoid()) {
1939 } else if (type->isVoid()) {
1940 meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
1940 meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
1941
1941
1942 } else if (type->isString()
1942 } else if (type->isString()
1943 && meta_type->indirections() == 0
1943 && meta_type->indirections() == 0
1944 && (meta_type->isConstant() == meta_type->isReference()
1944 && (meta_type->isConstant() == meta_type->isReference()
1945 || meta_type->isConstant())) {
1945 || meta_type->isConstant())) {
1946 meta_type->setTypeUsagePattern(AbstractMetaType::StringPattern);
1946 meta_type->setTypeUsagePattern(AbstractMetaType::StringPattern);
1947
1947
1948 } else if (type->isChar()
1948 } else if (type->isChar()
1949 && meta_type->indirections() == 0
1949 && meta_type->indirections() == 0
1950 && meta_type->isConstant() == meta_type->isReference()) {
1950 && meta_type->isConstant() == meta_type->isReference()) {
1951 meta_type->setTypeUsagePattern(AbstractMetaType::CharPattern);
1951 meta_type->setTypeUsagePattern(AbstractMetaType::CharPattern);
1952
1952
1953 } else if (type->isJObjectWrapper()
1953 } else if (type->isJObjectWrapper()
1954 && meta_type->indirections() == 0
1954 && meta_type->indirections() == 0
1955 && meta_type->isConstant() == meta_type->isReference()) {
1955 && meta_type->isConstant() == meta_type->isReference()) {
1956 meta_type->setTypeUsagePattern(AbstractMetaType::JObjectWrapperPattern);
1956 meta_type->setTypeUsagePattern(AbstractMetaType::JObjectWrapperPattern);
1957
1957
1958 } else if (type->isVariant()
1958 } else if (type->isVariant()
1959 && meta_type->indirections() == 0
1959 && meta_type->indirections() == 0
1960 && meta_type->isConstant() == meta_type->isReference()) {
1960 && meta_type->isConstant() == meta_type->isReference()) {
1961 meta_type->setTypeUsagePattern(AbstractMetaType::VariantPattern);
1961 meta_type->setTypeUsagePattern(AbstractMetaType::VariantPattern);
1962
1962
1963 } else if (type->isEnum() && meta_type->actualIndirections() == 0) {
1963 } else if (type->isEnum() && meta_type->actualIndirections() == 0) {
1964 meta_type->setTypeUsagePattern(AbstractMetaType::EnumPattern);
1964 meta_type->setTypeUsagePattern(AbstractMetaType::EnumPattern);
1965
1965
1966 } else if (type->isObject()
1966 } else if (type->isObject()
1967 && meta_type->indirections() == 0
1967 && meta_type->indirections() == 0
1968 && meta_type->isReference()) {
1968 && meta_type->isReference()) {
1969 if (((ComplexTypeEntry *) type)->isQObject())
1969 if (((ComplexTypeEntry *) type)->isQObject())
1970 meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
1970 meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
1971 else
1971 else
1972 meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
1972 meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
1973
1973
1974 } else if (type->isObject()
1974 } else if (type->isObject()
1975 && meta_type->indirections() == 1) {
1975 && meta_type->indirections() == 1) {
1976 if (((ComplexTypeEntry *) type)->isQObject())
1976 if (((ComplexTypeEntry *) type)->isQObject())
1977 meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
1977 meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
1978 else
1978 else
1979 meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
1979 meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
1980
1980
1981 // const-references to pointers can be passed as pointers
1981 // const-references to pointers can be passed as pointers
1982 if (meta_type->isReference() && meta_type->isConstant()) {
1982 if (meta_type->isReference() && meta_type->isConstant()) {
1983 meta_type->setReference(false);
1983 meta_type->setReference(false);
1984 meta_type->setConstant(false);
1984 meta_type->setConstant(false);
1985 }
1985 }
1986
1986
1987 } else if (type->isContainer() && meta_type->indirections() == 0) {
1987 } else if (type->isContainer() && meta_type->indirections() == 0) {
1988 meta_type->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
1988 meta_type->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
1989
1989
1990 } else if (type->isTemplateArgument()) {
1990 } else if (type->isTemplateArgument()) {
1991
1991
1992 } else if (type->isFlags()
1992 } else if (type->isFlags()
1993 && meta_type->indirections() == 0
1993 && meta_type->indirections() == 0
1994 && (meta_type->isConstant() == meta_type->isReference())) {
1994 && (meta_type->isConstant() == meta_type->isReference())) {
1995 meta_type->setTypeUsagePattern(AbstractMetaType::FlagsPattern);
1995 meta_type->setTypeUsagePattern(AbstractMetaType::FlagsPattern);
1996
1996
1997 } else if (type->isArray()) {
1997 } else if (type->isArray()) {
1998 meta_type->setTypeUsagePattern(AbstractMetaType::ArrayPattern);
1998 meta_type->setTypeUsagePattern(AbstractMetaType::ArrayPattern);
1999
1999
2000 } else if (type->isThread()) {
2000 } else if (type->isThread()) {
2001 Q_ASSERT(meta_type->indirections() == 1);
2001 Q_ASSERT(meta_type->indirections() == 1);
2002 meta_type->setTypeUsagePattern(AbstractMetaType::ThreadPattern);
2002 meta_type->setTypeUsagePattern(AbstractMetaType::ThreadPattern);
2003
2003
2004 } else if (type->isValue()
2004 } else if (type->isValue()
2005 && meta_type->indirections() == 0
2005 && meta_type->indirections() == 0
2006 && (meta_type->isConstant() == meta_type->isReference()
2006 && (meta_type->isConstant() == meta_type->isReference()
2007 || !meta_type->isReference())) {
2007 || !meta_type->isReference())) {
2008 meta_type->setTypeUsagePattern(AbstractMetaType::ValuePattern);
2008 meta_type->setTypeUsagePattern(AbstractMetaType::ValuePattern);
2009
2009
2010 } else {
2010 } else {
2011 meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
2011 meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
2012 ReportHandler::debugFull(QString("native pointer pattern for '%1'")
2012 ReportHandler::debugFull(QString("native pointer pattern for '%1'")
2013 .arg(meta_type->cppSignature()));
2013 .arg(meta_type->cppSignature()));
2014 }
2014 }
2015 }
2015 }
2016
2016
2017 QString AbstractMetaBuilder::translateDefaultValue(ArgumentModelItem item, AbstractMetaType *type,
2017 QString AbstractMetaBuilder::translateDefaultValue(ArgumentModelItem item, AbstractMetaType *type,
2018 AbstractMetaFunction *fnc, AbstractMetaClass *implementing_class,
2018 AbstractMetaFunction *fnc, AbstractMetaClass *implementing_class,
2019 int argument_index)
2019 int argument_index)
2020 {
2020 {
2021 QString function_name = fnc->name();
2021 QString function_name = fnc->name();
2022 QString class_name = implementing_class->name();
2022 QString class_name = implementing_class->name();
2023
2023
2024 QString replaced_expression = fnc->replacedDefaultExpression(implementing_class, argument_index + 1);
2024 QString replaced_expression = fnc->replacedDefaultExpression(implementing_class, argument_index + 1);
2025 if (fnc->removedDefaultExpression(implementing_class, argument_index +1))
2025 if (fnc->removedDefaultExpression(implementing_class, argument_index +1))
2026 return "";
2026 return "";
2027 if (!replaced_expression.isEmpty())
2027 if (!replaced_expression.isEmpty())
2028 return replaced_expression;
2028 return replaced_expression;
2029
2029
2030 QString expr = item->defaultValueExpression();
2030 QString expr = item->defaultValueExpression();
2031 if (type != 0 && type->isPrimitive()) {
2031 if (type != 0 && type->isPrimitive()) {
2032 if (type->name() == "boolean") {
2032 if (type->name() == "boolean") {
2033 if (expr == "false" || expr=="true") {
2033 if (expr == "false" || expr=="true") {
2034 return expr;
2034 return expr;
2035 } else {
2035 } else {
2036 bool ok = false;
2036 bool ok = false;
2037 int number = expr.toInt(&ok);
2037 int number = expr.toInt(&ok);
2038 if (ok && number)
2038 if (ok && number)
2039 return "true";
2039 return "true";
2040 else
2040 else
2041 return "false";
2041 return "false";
2042 }
2042 }
2043 } else if (expr == "ULONG_MAX") {
2043 } else if (expr == "ULONG_MAX") {
2044 return "Long.MAX_VALUE";
2044 return "Long.MAX_VALUE";
2045 } else if (expr == "QVariant::Invalid") {
2045 } else if (expr == "QVariant::Invalid") {
2046 return QString::number(QVariant::Invalid);
2046 return QString::number(QVariant::Invalid);
2047 } else {
2047 } else {
2048 // This can be an enum or flag so I need to delay the
2048 // This can be an enum or flag so I need to delay the
2049 // translation untill all namespaces are completly
2049 // translation untill all namespaces are completly
2050 // processed. This is done in figureOutEnumValues()
2050 // processed. This is done in figureOutEnumValues()
2051 return expr;
2051 return expr;
2052 }
2052 }
2053 } else if (type != 0 && (type->isFlags() || type->isEnum())) {
2053 } else if (type != 0 && (type->isFlags() || type->isEnum())) {
2054 // Same as with enum explanation above...
2054 // Same as with enum explanation above...
2055 return expr;
2055 return expr;
2056
2056
2057 } else {
2057 } else {
2058
2058
2059 // constructor or functioncall can be a bit tricky...
2059 // constructor or functioncall can be a bit tricky...
2060 if (expr == "QVariant()" || expr == "QModelIndex()") {
2060 if (expr == "QVariant()" || expr == "QModelIndex()") {
2061 return "null";
2061 return "null";
2062 } else if (expr == "QString()") {
2062 } else if (expr == "QString()") {
2063 return "null";
2063 return "null";
2064 } else if (expr.endsWith(")") && expr.contains("::")) {
2064 } else if (expr.endsWith(")") && expr.contains("::")) {
2065 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
2065 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
2066 if (typeEntry)
2066 if (typeEntry)
2067 return typeEntry->qualifiedTargetLangName() + "." + expr.right(expr.length() - expr.indexOf("::") - 2);
2067 return typeEntry->qualifiedTargetLangName() + "." + expr.right(expr.length() - expr.indexOf("::") - 2);
2068 } else if (expr.endsWith(")") && type != 0 && type->isValue()) {
2068 } else if (expr.endsWith(")") && type != 0 && type->isValue()) {
2069 int pos = expr.indexOf("(");
2069 int pos = expr.indexOf("(");
2070
2070
2071 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(pos));
2071 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(pos));
2072 if (typeEntry)
2072 if (typeEntry)
2073 return "new " + typeEntry->qualifiedTargetLangName() + expr.right(expr.length() - pos);
2073 return "new " + typeEntry->qualifiedTargetLangName() + expr.right(expr.length() - pos);
2074 else
2074 else
2075 return expr;
2075 return expr;
2076 } else if (expr == "0") {
2076 } else if (expr == "0") {
2077 return "null";
2077 return "null";
2078 } else if (type != 0 && (type->isObject() || type->isValue() || expr.contains("::"))) { // like Qt::black passed to a QColor
2078 } else if (type != 0 && (type->isObject() || type->isValue() || expr.contains("::"))) { // like Qt::black passed to a QColor
2079 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
2079 TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
2080
2080
2081 expr = expr.right(expr.length() - expr.indexOf("::") - 2);
2081 expr = expr.right(expr.length() - expr.indexOf("::") - 2);
2082 if (typeEntry) {
2082 if (typeEntry) {
2083 return "new " + type->typeEntry()->qualifiedTargetLangName() +
2083 return "new " + type->typeEntry()->qualifiedTargetLangName() +
2084 "(" + typeEntry->qualifiedTargetLangName() + "." + expr + ")";
2084 "(" + typeEntry->qualifiedTargetLangName() + "." + expr + ")";
2085 }
2085 }
2086 }
2086 }
2087 }
2087 }
2088
2088
2089 QString warn = QString("unsupported default value '%3' of argument in function '%1', class '%2'")
2089 QString warn = QString("unsupported default value '%3' of argument in function '%1', class '%2'")
2090 .arg(function_name).arg(class_name).arg(item->defaultValueExpression());
2090 .arg(function_name).arg(class_name).arg(item->defaultValueExpression());
2091 ReportHandler::warning(warn);
2091 ReportHandler::warning(warn);
2092
2092
2093 return QString();
2093 return QString();
2094 }
2094 }
2095
2095
2096
2096
2097 bool AbstractMetaBuilder::isQObject(const QString &qualified_name)
2097 bool AbstractMetaBuilder::isQObject(const QString &qualified_name)
2098 {
2098 {
2099 if (qualified_name == "QObject")
2099 if (qualified_name == "QObject")
2100 return true;
2100 return true;
2101
2101
2102 ClassModelItem class_item = m_dom->findClass(qualified_name);
2102 ClassModelItem class_item = m_dom->findClass(qualified_name);
2103
2103
2104 if (!class_item) {
2104 if (!class_item) {
2105 QStringList names = qualified_name.split(QLatin1String("::"));
2105 QStringList names = qualified_name.split(QLatin1String("::"));
2106 NamespaceModelItem ns = model_dynamic_cast<NamespaceModelItem>(m_dom);
2106 NamespaceModelItem ns = model_dynamic_cast<NamespaceModelItem>(m_dom);
2107 for (int i=0; i<names.size() - 1 && ns; ++i)
2107 for (int i=0; i<names.size() - 1 && ns; ++i)
2108 ns = ns->namespaceMap().value(names.at(i));
2108 ns = ns->namespaceMap().value(names.at(i));
2109 if (ns && names.size() >= 2)
2109 if (ns && names.size() >= 2)
2110 class_item = ns->findClass(names.at(names.size() - 1));
2110 class_item = ns->findClass(names.at(names.size() - 1));
2111 }
2111 }
2112
2112
2113 bool isqobject = class_item && class_item->extendsClass("QObject");
2113 bool isqobject = class_item && class_item->extendsClass("QObject");
2114
2114
2115 if (class_item && !isqobject) {
2115 if (class_item && !isqobject) {
2116 QStringList baseClasses = class_item->baseClasses();
2116 QStringList baseClasses = class_item->baseClasses();
2117 for (int i=0; i<baseClasses.count(); ++i) {
2117 for (int i=0; i<baseClasses.count(); ++i) {
2118
2118
2119 isqobject = isQObject(baseClasses.at(i));
2119 isqobject = isQObject(baseClasses.at(i));
2120 if (isqobject)
2120 if (isqobject)
2121 break;
2121 break;
2122 }
2122 }
2123 }
2123 }
2124
2124
2125 return isqobject;
2125 return isqobject;
2126 }
2126 }
2127
2127
2128
2128
2129 bool AbstractMetaBuilder::isEnum(const QStringList &qualified_name)
2129 bool AbstractMetaBuilder::isEnum(const QStringList &qualified_name)
2130 {
2130 {
2131 CodeModelItem item = m_dom->model()->findItem(qualified_name, m_dom->toItem());
2131 CodeModelItem item = m_dom->model()->findItem(qualified_name, m_dom->toItem());
2132 return item && item->kind() == _EnumModelItem::__node_kind;
2132 return item && item->kind() == _EnumModelItem::__node_kind;
2133 }
2133 }
2134
2134
2135 AbstractMetaType *AbstractMetaBuilder::inheritTemplateType(const QList<AbstractMetaType *> &template_types,
2135 AbstractMetaType *AbstractMetaBuilder::inheritTemplateType(const QList<AbstractMetaType *> &template_types,
2136 AbstractMetaType *meta_type, bool *ok)
2136 AbstractMetaType *meta_type, bool *ok)
2137 {
2137 {
2138 if (ok != 0)
2138 if (ok != 0)
2139 *ok = true;
2139 *ok = true;
2140 if (!meta_type || (!meta_type->typeEntry()->isTemplateArgument() && !meta_type->hasInstantiations()))
2140 if (!meta_type || (!meta_type->typeEntry()->isTemplateArgument() && !meta_type->hasInstantiations()))
2141 return meta_type ? meta_type->copy() : 0;
2141 return meta_type ? meta_type->copy() : 0;
2142
2142
2143 AbstractMetaType *returned = meta_type->copy();
2143 AbstractMetaType *returned = meta_type->copy();
2144 returned->setOriginalTemplateType(meta_type->copy());
2144 returned->setOriginalTemplateType(meta_type->copy());
2145
2145
2146 if (returned->typeEntry()->isTemplateArgument()) {
2146 if (returned->typeEntry()->isTemplateArgument()) {
2147 const TemplateArgumentEntry *tae = static_cast<const TemplateArgumentEntry *>(returned->typeEntry());
2147 const TemplateArgumentEntry *tae = static_cast<const TemplateArgumentEntry *>(returned->typeEntry());
2148
2148
2149 // If the template is intantiated with void we special case this as rejecting the functions that use this
2149 // If the template is intantiated with void we special case this as rejecting the functions that use this
2150 // parameter from the instantiation.
2150 // parameter from the instantiation.
2151 if (template_types.size() <= tae->ordinal() || template_types.at(tae->ordinal())->typeEntry()->name() == "void") {
2151 if (template_types.size() <= tae->ordinal() || template_types.at(tae->ordinal())->typeEntry()->name() == "void") {
2152 if (ok != 0)
2152 if (ok != 0)
2153 *ok = false;
2153 *ok = false;
2154 return 0;
2154 return 0;
2155 }
2155 }
2156
2156
2157 AbstractMetaType *t = returned->copy();
2157 AbstractMetaType *t = returned->copy();
2158 t->setTypeEntry(template_types.at(tae->ordinal())->typeEntry());
2158 t->setTypeEntry(template_types.at(tae->ordinal())->typeEntry());
2159 t->setIndirections(template_types.at(tae->ordinal())->indirections() + t->indirections()
2159 t->setIndirections(template_types.at(tae->ordinal())->indirections() + t->indirections()
2160 ? 1
2160 ? 1
2161 : 0);
2161 : 0);
2162 decideUsagePattern(t);
2162 decideUsagePattern(t);
2163
2163
2164 delete returned;
2164 delete returned;
2165 returned = inheritTemplateType(template_types, t, ok);
2165 returned = inheritTemplateType(template_types, t, ok);
2166 if (ok != 0 && !(*ok))
2166 if (ok != 0 && !(*ok))
2167 return 0;
2167 return 0;
2168 }
2168 }
2169
2169
2170 if (returned->hasInstantiations()) {
2170 if (returned->hasInstantiations()) {
2171 QList<AbstractMetaType *> instantiations = returned->instantiations();
2171 QList<AbstractMetaType *> instantiations = returned->instantiations();
2172 for (int i=0; i<instantiations.count(); ++i) {
2172 for (int i=0; i<instantiations.count(); ++i) {
2173 instantiations[i] = inheritTemplateType(template_types, instantiations.at(i), ok);
2173 instantiations[i] = inheritTemplateType(template_types, instantiations.at(i), ok);
2174 if (ok != 0 && !(*ok))
2174 if (ok != 0 && !(*ok))
2175 return 0;
2175 return 0;
2176 }
2176 }
2177 returned->setInstantiations(instantiations);
2177 returned->setInstantiations(instantiations);
2178 }
2178 }
2179
2179
2180 return returned;
2180 return returned;
2181 }
2181 }
2182
2182
2183 bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass *subclass,
2183 bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass *subclass,
2184 const AbstractMetaClass *template_class,
2184 const AbstractMetaClass *template_class,
2185 const TypeParser::Info &info)
2185 const TypeParser::Info &info)
2186 {
2186 {
2187 QList<TypeParser::Info> targs = info.template_instantiations;
2187 QList<TypeParser::Info> targs = info.template_instantiations;
2188
2188
2189 QList<AbstractMetaType *> template_types;
2189 QList<AbstractMetaType *> template_types;
2190 foreach (const TypeParser::Info &i, targs) {
2190 foreach (const TypeParser::Info &i, targs) {
2191 TypeEntry *t = TypeDatabase::instance()->findType(i.qualified_name.join("::"));
2191 TypeEntry *t = TypeDatabase::instance()->findType(i.qualified_name.join("::"));
2192
2192
2193 if (t != 0) {
2193 if (t != 0) {
2194 AbstractMetaType *temporary_type = createMetaType();
2194 AbstractMetaType *temporary_type = createMetaType();
2195 temporary_type->setTypeEntry(t);
2195 temporary_type->setTypeEntry(t);
2196 temporary_type->setConstant(i.is_constant);
2196 temporary_type->setConstant(i.is_constant);
2197 temporary_type->setReference(i.is_reference);
2197 temporary_type->setReference(i.is_reference);
2198 temporary_type->setIndirections(i.indirections);
2198 temporary_type->setIndirections(i.indirections);
2199 template_types << temporary_type;
2199 template_types << temporary_type;
2200 }
2200 }
2201 }
2201 }
2202
2202
2203 AbstractMetaFunctionList funcs = subclass->functions();
2203 AbstractMetaFunctionList funcs = subclass->functions();
2204 foreach (const AbstractMetaFunction *function, template_class->functions()) {
2204 foreach (const AbstractMetaFunction *function, template_class->functions()) {
2205
2205
2206 if (function->isModifiedRemoved(TypeSystem::All))
2206 if (function->isModifiedRemoved(TypeSystem::All))
2207 continue;
2207 continue;
2208
2208
2209 AbstractMetaFunction *f = function->copy();
2209 AbstractMetaFunction *f = function->copy();
2210 f->setArguments(AbstractMetaArgumentList());
2210 f->setArguments(AbstractMetaArgumentList());
2211
2211
2212 bool ok = true;
2212 bool ok = true;
2213 AbstractMetaType *ftype = function->type();
2213 AbstractMetaType *ftype = function->type();
2214 f->setType(inheritTemplateType(template_types, ftype, &ok));
2214 f->setType(inheritTemplateType(template_types, ftype, &ok));
2215 if (!ok) {
2215 if (!ok) {
2216 delete f;
2216 delete f;
2217 continue;
2217 continue;
2218 }
2218 }
2219
2219
2220 foreach (AbstractMetaArgument *argument, function->arguments()) {
2220 foreach (AbstractMetaArgument *argument, function->arguments()) {
2221 AbstractMetaType *atype = argument->type();
2221 AbstractMetaType *atype = argument->type();
2222
2222
2223 AbstractMetaArgument *arg = argument->copy();
2223 AbstractMetaArgument *arg = argument->copy();
2224 arg->setType(inheritTemplateType(template_types, atype, &ok));
2224 arg->setType(inheritTemplateType(template_types, atype, &ok));
2225 if (!ok)
2225 if (!ok)
2226 break;
2226 break;
2227 f->addArgument(arg);
2227 f->addArgument(arg);
2228 }
2228 }
2229
2229
2230 if (!ok) {
2230 if (!ok) {
2231 delete f;
2231 delete f;
2232 continue ;
2232 continue ;
2233 }
2233 }
2234
2234
2235 // There is no base class in java to inherit from here, so the
2235 // There is no base class in java to inherit from here, so the
2236 // template instantiation is the class that implements the function..
2236 // template instantiation is the class that implements the function..
2237 f->setImplementingClass(subclass);
2237 f->setImplementingClass(subclass);
2238
2238
2239 // We also set it as the declaring class, since the superclass is
2239 // We also set it as the declaring class, since the superclass is
2240 // supposed to disappear. This allows us to make certain function modifications
2240 // supposed to disappear. This allows us to make certain function modifications
2241 // on the inherited functions.
2241 // on the inherited functions.
2242 f->setDeclaringClass(subclass);
2242 f->setDeclaringClass(subclass);
2243
2243
2244
2244
2245 if (f->isConstructor() && subclass->isTypeAlias()) {
2245 if (f->isConstructor() && subclass->isTypeAlias()) {
2246 f->setName(subclass->name());
2246 f->setName(subclass->name());
2247 } else if (f->isConstructor()) {
2247 } else if (f->isConstructor()) {
2248 delete f;
2248 delete f;
2249 continue;
2249 continue;
2250 }
2250 }
2251
2251
2252 // if the instantiation has a function named the same as an existing
2252 // if the instantiation has a function named the same as an existing
2253 // function we have shadowing so we need to skip it.
2253 // function we have shadowing so we need to skip it.
2254 bool found = false;
2254 bool found = false;
2255 for (int i=0; i<funcs.size(); ++i) {
2255 for (int i=0; i<funcs.size(); ++i) {
2256 if (funcs.at(i)->name() == f->name()) {
2256 if (funcs.at(i)->name() == f->name()) {
2257 found = true;
2257 found = true;
2258 continue;
2258 continue;
2259 }
2259 }
2260 }
2260 }
2261 if (found) {
2261 if (found) {
2262 delete f;
2262 delete f;
2263 continue;
2263 continue;
2264 }
2264 }
2265
2265
2266 ComplexTypeEntry *te = subclass->typeEntry();
2266 ComplexTypeEntry *te = subclass->typeEntry();
2267 FunctionModificationList mods = function->modifications(template_class);
2267 FunctionModificationList mods = function->modifications(template_class);
2268 for (int i=0; i<mods.size(); ++i) {
2268 for (int i=0; i<mods.size(); ++i) {
2269 FunctionModification mod = mods.at(i);
2269 FunctionModification mod = mods.at(i);
2270 mod.signature = f->minimalSignature();
2270 mod.signature = f->minimalSignature();
2271
2271
2272 // If we ever need it... Below is the code to do
2272 // If we ever need it... Below is the code to do
2273 // substitution of the template instantation type inside
2273 // substitution of the template instantation type inside
2274 // injected code..
2274 // injected code..
2275 #if 0
2275 #if 0
2276 if (mod.modifiers & Modification::CodeInjection) {
2276 if (mod.modifiers & Modification::CodeInjection) {
2277 for (int j=0; j<template_types.size(); ++j) {
2277 for (int j=0; j<template_types.size(); ++j) {
2278 CodeSnip &snip = mod.snips.last();
2278 CodeSnip &snip = mod.snips.last();
2279 QString code = snip.code();
2279 QString code = snip.code();
2280 code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
2280 code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
2281 template_types.at(j)->typeEntry()->qualifiedCppName());
2281 template_types.at(j)->typeEntry()->qualifiedCppName());
2282 snip.codeList.clear();
2282 snip.codeList.clear();
2283 snip.addCode(code);
2283 snip.addCode(code);
2284 }
2284 }
2285 }
2285 }
2286 #endif
2286 #endif
2287 te->addFunctionModification(mod);
2287 te->addFunctionModification(mod);
2288 }
2288 }
2289
2289
2290 subclass->addFunction(f);
2290 subclass->addFunction(f);
2291 }
2291 }
2292
2292
2293 // Clean up
2293 // Clean up
2294 foreach (AbstractMetaType *type, template_types) {
2294 foreach (AbstractMetaType *type, template_types) {
2295 delete type;
2295 delete type;
2296 }
2296 }
2297
2297
2298
2298
2299 {
2299 {
2300 subclass->setTemplateBaseClass(template_class);
2300 subclass->setTemplateBaseClass(template_class);
2301
2301
2302 subclass->setInterfaces(template_class->interfaces());
2302 subclass->setInterfaces(template_class->interfaces());
2303 subclass->setBaseClass(template_class->baseClass());
2303 subclass->setBaseClass(template_class->baseClass());
2304 }
2304 }
2305
2305
2306 return true;
2306 return true;
2307 }
2307 }
2308
2308
2309 void AbstractMetaBuilder::parseQ_Property(AbstractMetaClass *meta_class, const QStringList &declarations)
2309 void AbstractMetaBuilder::parseQ_Property(AbstractMetaClass *meta_class, const QStringList &declarations)
2310 {
2310 {
2311 for (int i=0; i<declarations.size(); ++i) {
2311 for (int i=0; i<declarations.size(); ++i) {
2312 QString p = declarations.at(i);
2312 QString p = declarations.at(i);
2313
2313
2314 QStringList l = p.split(QLatin1String(" "));
2314 QStringList l = p.split(QLatin1String(" "));
2315
2315
2316
2316
2317 QStringList qualifiedScopeName = currentScope()->qualifiedName();
2317 QStringList qualifiedScopeName = currentScope()->qualifiedName();
2318 bool ok = false;
2318 bool ok = false;
2319 AbstractMetaType *type = 0;
2319 AbstractMetaType *type = 0;
2320 QString scope;
2320 QString scope;
2321 for (int j=qualifiedScopeName.size(); j>=0; --j) {
2321 for (int j=qualifiedScopeName.size(); j>=0; --j) {
2322 scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join("::") + "::" : QString();
2322 scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join("::") + "::" : QString();
2323 TypeInfo info;
2323 TypeInfo info;
2324 info.setQualifiedName((scope + l.at(0)).split("::"));
2324 info.setQualifiedName((scope + l.at(0)).split("::"));
2325
2325
2326 type = translateType(info, &ok);
2326 type = translateType(info, &ok);
2327 if (type != 0 && ok) {
2327 if (type != 0 && ok) {
2328 break;
2328 break;
2329 }
2329 }
2330 }
2330 }
2331
2331
2332 if (type == 0 || !ok) {
2332 if (type == 0 || !ok) {
2333 ReportHandler::warning(QString("Unable to decide type of property: '%1' in class '%2'")
2333 ReportHandler::warning(QString("Unable to decide type of property: '%1' in class '%2'")
2334 .arg(l.at(0)).arg(meta_class->name()));
2334 .arg(l.at(0)).arg(meta_class->name()));
2335 continue;
2335 continue;
2336 }
2336 }
2337
2337
2338 QString typeName = scope + l.at(0);
2338 QString typeName = scope + l.at(0);
2339
2339
2340 QPropertySpec *spec = new QPropertySpec(type->typeEntry());
2340 QPropertySpec *spec = new QPropertySpec(type->typeEntry());
2341 spec->setName(l.at(1));
2341 spec->setName(l.at(1));
2342 spec->setIndex(i);
2342 spec->setIndex(i);
2343
2343
2344 for (int pos=2; pos+1<l.size(); pos+=2) {
2344 for (int pos=2; pos+1<l.size(); pos+=2) {
2345 if (l.at(pos) == QLatin1String("READ"))
2345 if (l.at(pos) == QLatin1String("READ"))
2346 spec->setRead(l.at(pos+1));
2346 spec->setRead(l.at(pos+1));
2347 else if (l.at(pos) == QLatin1String("WRITE"))
2347 else if (l.at(pos) == QLatin1String("WRITE"))
2348 spec->setWrite(l.at(pos+1));
2348 spec->setWrite(l.at(pos+1));
2349 else if (l.at(pos) == QLatin1String("DESIGNABLE"))
2349 else if (l.at(pos) == QLatin1String("DESIGNABLE"))
2350 spec->setDesignable(l.at(pos+1));
2350 spec->setDesignable(l.at(pos+1));
2351 else if (l.at(pos) == QLatin1String("RESET"))
2351 else if (l.at(pos) == QLatin1String("RESET"))
2352 spec->setReset(l.at(pos+1));
2352 spec->setReset(l.at(pos+1));
2353 }
2353 }
2354
2354
2355 meta_class->addPropertySpec(spec);
2355 meta_class->addPropertySpec(spec);
2356 delete type;
2356 delete type;
2357 }
2357 }
2358 }
2358 }
2359
2359
2360 static void hide_functions(const AbstractMetaFunctionList &l) {
2360 static void hide_functions(const AbstractMetaFunctionList &l) {
2361 foreach (AbstractMetaFunction *f, l) {
2361 foreach (AbstractMetaFunction *f, l) {
2362 FunctionModification mod;
2362 FunctionModification mod;
2363 mod.signature = f->minimalSignature();
2363 mod.signature = f->minimalSignature();
2364 mod.modifiers = FunctionModification::Private;
2364 mod.modifiers = FunctionModification::Private;
2365 ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
2365 ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
2366 }
2366 }
2367 }
2367 }
2368
2368
2369 static void remove_function(AbstractMetaFunction *f) {
2369 static void remove_function(AbstractMetaFunction *f) {
2370 FunctionModification mod;
2370 FunctionModification mod;
2371 mod.removal = TypeSystem::All;
2371 mod.removal = TypeSystem::All;
2372 mod.signature = f->minimalSignature();
2372 mod.signature = f->minimalSignature();
2373 ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
2373 ((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
2374 }
2374 }
2375
2375
2376 static AbstractMetaFunctionList filter_functions(const AbstractMetaFunctionList &lst, QSet<QString> *signatures)
2376 static AbstractMetaFunctionList filter_functions(const AbstractMetaFunctionList &lst, QSet<QString> *signatures)
2377 {
2377 {
2378 AbstractMetaFunctionList functions;
2378 AbstractMetaFunctionList functions;
2379 foreach (AbstractMetaFunction *f, lst) {
2379 foreach (AbstractMetaFunction *f, lst) {
2380 QString signature = f->minimalSignature();
2380 QString signature = f->minimalSignature();
2381 int start = signature.indexOf(QLatin1Char('(')) + 1;
2381 int start = signature.indexOf(QLatin1Char('(')) + 1;
2382 int end = signature.lastIndexOf(QLatin1Char(')'));
2382 int end = signature.lastIndexOf(QLatin1Char(')'));
2383 signature = signature.mid(start, end - start);
2383 signature = signature.mid(start, end - start);
2384 if (signatures->contains(signature)) {
2384 if (signatures->contains(signature)) {
2385 remove_function(f);
2385 remove_function(f);
2386 continue;
2386 continue;
2387 }
2387 }
2388 (*signatures) << signature;
2388 (*signatures) << signature;
2389 functions << f;
2389 functions << f;
2390 }
2390 }
2391 return functions;
2391 return functions;
2392 }
2392 }
2393
2393
2394 void AbstractMetaBuilder::setupEquals(AbstractMetaClass *cls)
2394 void AbstractMetaBuilder::setupEquals(AbstractMetaClass *cls)
2395 {
2395 {
2396 AbstractMetaFunctionList equals;
2396 AbstractMetaFunctionList equals;
2397 AbstractMetaFunctionList nequals;
2397 AbstractMetaFunctionList nequals;
2398
2398
2399 QString op_equals = QLatin1String("operator_equal");
2399 QString op_equals = QLatin1String("operator_equal");
2400 QString op_nequals = QLatin1String("operator_not_equal");
2400 QString op_nequals = QLatin1String("operator_not_equal");
2401
2401
2402 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
2402 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
2403 | AbstractMetaClass::NotRemovedFromTargetLang);
2403 | AbstractMetaClass::NotRemovedFromTargetLang);
2404 foreach (AbstractMetaFunction *f, functions) {
2404 foreach (AbstractMetaFunction *f, functions) {
2405 if (f->name() == op_equals)
2405 if (f->name() == op_equals)
2406 equals << f;
2406 equals << f;
2407 else if (f->name() == op_nequals)
2407 else if (f->name() == op_nequals)
2408 nequals << f;
2408 nequals << f;
2409 }
2409 }
2410
2410
2411 if (equals.size() || nequals.size()) {
2411 if (equals.size() || nequals.size()) {
2412 if (!cls->hasHashFunction()) {
2412 if (!cls->hasHashFunction()) {
2413 ReportHandler::warning(QString::fromLatin1("Class '%1' has equals operators but no qHash() function")
2413 ReportHandler::warning(QString::fromLatin1("Class '%1' has equals operators but no qHash() function")
2414 .arg(cls->name()));
2414 .arg(cls->name()));
2415 }
2415 }
2416
2416
2417 hide_functions(equals);
2417 hide_functions(equals);
2418 hide_functions(nequals);
2418 hide_functions(nequals);
2419
2419
2420 // We only need == if we have both == and !=, and one == for
2420 // We only need == if we have both == and !=, and one == for
2421 // each signature type, like QDateTime::==(QDate) and (QTime)
2421 // each signature type, like QDateTime::==(QDate) and (QTime)
2422 // if such a thing exists...
2422 // if such a thing exists...
2423 QSet<QString> func_signatures;
2423 QSet<QString> func_signatures;
2424 cls->setEqualsFunctions(filter_functions(equals, &func_signatures));
2424 cls->setEqualsFunctions(filter_functions(equals, &func_signatures));
2425 cls->setNotEqualsFunctions(filter_functions(nequals, &func_signatures));
2425 cls->setNotEqualsFunctions(filter_functions(nequals, &func_signatures));
2426 }
2426 }
2427 }
2427 }
2428
2428
2429 void AbstractMetaBuilder::setupComparable(AbstractMetaClass *cls)
2429 void AbstractMetaBuilder::setupComparable(AbstractMetaClass *cls)
2430 {
2430 {
2431 AbstractMetaFunctionList greater;
2431 AbstractMetaFunctionList greater;
2432 AbstractMetaFunctionList greaterEquals;
2432 AbstractMetaFunctionList greaterEquals;
2433 AbstractMetaFunctionList less;
2433 AbstractMetaFunctionList less;
2434 AbstractMetaFunctionList lessEquals;
2434 AbstractMetaFunctionList lessEquals;
2435
2435
2436 QString op_greater = QLatin1String("operator_greater");
2436 QString op_greater = QLatin1String("operator_greater");
2437 QString op_greater_eq = QLatin1String("operator_greater_or_equal");
2437 QString op_greater_eq = QLatin1String("operator_greater_or_equal");
2438 QString op_less = QLatin1String("operator_less");
2438 QString op_less = QLatin1String("operator_less");
2439 QString op_less_eq = QLatin1String("operator_less_or_equal");
2439 QString op_less_eq = QLatin1String("operator_less_or_equal");
2440
2440
2441 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
2441 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
2442 | AbstractMetaClass::NotRemovedFromTargetLang);
2442 | AbstractMetaClass::NotRemovedFromTargetLang);
2443 foreach (AbstractMetaFunction *f, functions) {
2443 foreach (AbstractMetaFunction *f, functions) {
2444 if (f->name() == op_greater)
2444 if (f->name() == op_greater)
2445 greater << f;
2445 greater << f;
2446 else if (f->name() == op_greater_eq)
2446 else if (f->name() == op_greater_eq)
2447 greaterEquals << f;
2447 greaterEquals << f;
2448 else if (f->name() == op_less)
2448 else if (f->name() == op_less)
2449 less << f;
2449 less << f;
2450 else if (f->name() == op_less_eq)
2450 else if (f->name() == op_less_eq)
2451 lessEquals << f;
2451 lessEquals << f;
2452 }
2452 }
2453
2453
2454 bool hasEquals = cls->equalsFunctions().size() || cls->notEqualsFunctions().size();
2454 bool hasEquals = cls->equalsFunctions().size() || cls->notEqualsFunctions().size();
2455
2455
2456 // Conditions for comparable is:
2456 // Conditions for comparable is:
2457 // >, ==, < - The basic case
2457 // >, ==, < - The basic case
2458 // >, == - Less than becomes else case
2458 // >, == - Less than becomes else case
2459 // <, == - Greater than becomes else case
2459 // <, == - Greater than becomes else case
2460 // >=, <= - if (<= && >=) -> equal
2460 // >=, <= - if (<= && >=) -> equal
2461 bool mightBeComparable = greater.size() || greaterEquals.size() || less.size() || lessEquals.size()
2461 bool mightBeComparable = greater.size() || greaterEquals.size() || less.size() || lessEquals.size()
2462 || greaterEquals.size() == 1 || lessEquals.size() == 1;
2462 || greaterEquals.size() == 1 || lessEquals.size() == 1;
2463
2463
2464 if (mightBeComparable) {
2464 if (mightBeComparable) {
2465 QSet<QString> signatures;
2465 QSet<QString> signatures;
2466
2466
2467 // We only hide the original functions if we are able to make a compareTo() method
2467 // We only hide the original functions if we are able to make a compareTo() method
2468 bool wasComparable = false;
2468 bool wasComparable = false;
2469
2469
2470 // The three upper cases, prefer the <, == approach
2470 // The three upper cases, prefer the <, == approach
2471 if (hasEquals && (greater.size() || less.size())) {
2471 if (hasEquals && (greater.size() || less.size())) {
2472 cls->setLessThanFunctions(filter_functions(less, &signatures));
2472 cls->setLessThanFunctions(filter_functions(less, &signatures));
2473 cls->setGreaterThanFunctions(filter_functions(greater, &signatures));
2473 cls->setGreaterThanFunctions(filter_functions(greater, &signatures));
2474 filter_functions(greaterEquals, &signatures);
2474 filter_functions(greaterEquals, &signatures);
2475 filter_functions(lessEquals, &signatures);
2475 filter_functions(lessEquals, &signatures);
2476 wasComparable = true;
2476 wasComparable = true;
2477 } else if (hasEquals && (greaterEquals.size() || lessEquals.size())) {
2477 } else if (hasEquals && (greaterEquals.size() || lessEquals.size())) {
2478 cls->setLessThanEqFunctions(filter_functions(lessEquals, &signatures));
2478 cls->setLessThanEqFunctions(filter_functions(lessEquals, &signatures));
2479 cls->setGreaterThanEqFunctions(filter_functions(greaterEquals, &signatures));
2479 cls->setGreaterThanEqFunctions(filter_functions(greaterEquals, &signatures));
2480 wasComparable = true;
2480 wasComparable = true;
2481 } else if (greaterEquals.size() == 1 || lessEquals.size() == 1) {
2481 } else if (greaterEquals.size() == 1 || lessEquals.size() == 1) {
2482 cls->setGreaterThanEqFunctions(greaterEquals);
2482 cls->setGreaterThanEqFunctions(greaterEquals);
2483 cls->setLessThanEqFunctions(lessEquals);
2483 cls->setLessThanEqFunctions(lessEquals);
2484 filter_functions(less, &signatures);
2484 filter_functions(less, &signatures);
2485 filter_functions(greater, &signatures);
2485 filter_functions(greater, &signatures);
2486 wasComparable = true;
2486 wasComparable = true;
2487 }
2487 }
2488
2488
2489 if (wasComparable) {
2489 if (wasComparable) {
2490 hide_functions(greater);
2490 hide_functions(greater);
2491 hide_functions(greaterEquals);
2491 hide_functions(greaterEquals);
2492 hide_functions(less);
2492 hide_functions(less);
2493 hide_functions(lessEquals);
2493 hide_functions(lessEquals);
2494 }
2494 }
2495 }
2495 }
2496
2496
2497 }
2497 }
2498
2498
2499 void AbstractMetaBuilder::setupClonable(AbstractMetaClass *cls)
2499 void AbstractMetaBuilder::setupClonable(AbstractMetaClass *cls)
2500 {
2500 {
2501 QString op_assign = QLatin1String("operator_assign");
2501 QString op_assign = QLatin1String("operator_assign");
2502
2502
2503 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements);
2503 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements);
2504 foreach (AbstractMetaFunction *f, functions) {
2504 foreach (AbstractMetaFunction *f, functions) {
2505 if ((f->name() == op_assign || f->isConstructor()) && f->isPublic()) {
2505 if ((f->name() == op_assign || f->isConstructor()) && f->isPublic()) {
2506 AbstractMetaArgumentList arguments = f->arguments();
2506 AbstractMetaArgumentList arguments = f->arguments();
2507 if (arguments.size() == 1) {
2507 if (arguments.size() == 1) {
2508 if (cls->typeEntry()->qualifiedCppName() == arguments.at(0)->type()->typeEntry()->qualifiedCppName()) {
2508 if (cls->typeEntry()->qualifiedCppName() == arguments.at(0)->type()->typeEntry()->qualifiedCppName()) {
2509 if (cls->typeEntry()->isValue()) {
2509 if (cls->typeEntry()->isValue()) {
2510 cls->setHasCloneOperator(true);
2510 cls->setHasCloneOperator(true);
2511 return;
2511 return;
2512 }
2512 }
2513 }
2513 }
2514 }
2514 }
2515 }
2515 }
2516 }
2516 }
2517 }
2517 }
2518
2518
2519 static void write_reject_log_file(const QString &name,
2519 static void write_reject_log_file(const QString &name,
2520 const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
2520 const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
2521 {
2521 {
2522 QFile f(name);
2522 QFile f(name);
2523 if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
2523 if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
2524 ReportHandler::warning(QString("failed to write log file: '%1'")
2524 ReportHandler::warning(QString("failed to write log file: '%1'")
2525 .arg(f.fileName()));
2525 .arg(f.fileName()));
2526 return;
2526 return;
2527 }
2527 }
2528
2528
2529 QTextStream s(&f);
2529 QTextStream s(&f);
2530
2530
2531
2531
2532 for (int reason=0; reason<AbstractMetaBuilder::NoReason; ++reason) {
2532 for (int reason=0; reason<AbstractMetaBuilder::NoReason; ++reason) {
2533 s << QString(72, '*') << endl;
2533 s << QString(72, '*') << endl;
2534 switch (reason) {
2534 switch (reason) {
2535 case AbstractMetaBuilder::NotInTypeSystem:
2535 case AbstractMetaBuilder::NotInTypeSystem:
2536 s << "Not in type system";
2536 s << "Not in type system";
2537 break;
2537 break;
2538 case AbstractMetaBuilder::GenerationDisabled:
2538 case AbstractMetaBuilder::GenerationDisabled:
2539 s << "Generation disabled by type system";
2539 s << "Generation disabled by type system";
2540 break;
2540 break;
2541 case AbstractMetaBuilder::RedefinedToNotClass:
2541 case AbstractMetaBuilder::RedefinedToNotClass:
2542 s << "Type redefined to not be a class";
2542 s << "Type redefined to not be a class";
2543 break;
2543 break;
2544
2544
2545 case AbstractMetaBuilder::UnmatchedReturnType:
2545 case AbstractMetaBuilder::UnmatchedReturnType:
2546 s << "Unmatched return type";
2546 s << "Unmatched return type";
2547 break;
2547 break;
2548
2548
2549 case AbstractMetaBuilder::UnmatchedArgumentType:
2549 case AbstractMetaBuilder::UnmatchedArgumentType:
2550 s << "Unmatched argument type";
2550 s << "Unmatched argument type";
2551 break;
2551 break;
2552
2552
2553 default:
2553 default:
2554 s << "unknown reason";
2554 s << "unknown reason";
2555 break;
2555 break;
2556 }
2556 }
2557
2557
2558 s << endl;
2558 s << endl;
2559
2559
2560 for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
2560 for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
2561 it != rejects.constEnd(); ++it) {
2561 it != rejects.constEnd(); ++it) {
2562 if (it.value() != reason)
2562 if (it.value() != reason)
2563 continue;
2563 continue;
2564 s << " - " << it.key() << endl;
2564 s << " - " << it.key() << endl;
2565 }
2565 }
2566
2566
2567 s << QString(72, '*') << endl << endl;
2567 s << QString(72, '*') << endl << endl;
2568 }
2568 }
2569
2569
2570 }
2570 }
2571
2571
2572
2572
2573 void AbstractMetaBuilder::dumpLog()
2573 void AbstractMetaBuilder::dumpLog()
2574 {
2574 {
2575 write_reject_log_file("mjb_rejected_classes.log", m_rejected_classes);
2575 write_reject_log_file("mjb_rejected_classes.log", m_rejected_classes);
2576 write_reject_log_file("mjb_rejected_enums.log", m_rejected_enums);
2576 write_reject_log_file("mjb_rejected_enums.log", m_rejected_enums);
2577 write_reject_log_file("mjb_rejected_functions.log", m_rejected_functions);
2577 write_reject_log_file("mjb_rejected_functions.log", m_rejected_functions);
2578 write_reject_log_file("mjb_rejected_fields.log", m_rejected_fields);
2578 write_reject_log_file("mjb_rejected_fields.log", m_rejected_fields);
2579 }
2579 }
2580
2580
2581 AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted() const
2581 AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted() const
2582 {
2582 {
2583 AbstractMetaClassList res;
2583 AbstractMetaClassList res;
2584
2584
2585 AbstractMetaClassList classes = m_meta_classes;
2585 AbstractMetaClassList classes = m_meta_classes;
2586 qSort(classes);
2586 qSort(classes);
2587
2587
2588 QSet<AbstractMetaClass*> noDependency;
2588 QSet<AbstractMetaClass*> noDependency;
2589 QHash<AbstractMetaClass*, QSet<AbstractMetaClass* >* > hash;
2589 QHash<AbstractMetaClass*, QSet<AbstractMetaClass* >* > hash;
2590 foreach (AbstractMetaClass *cls, classes) {
2590 foreach (AbstractMetaClass *cls, classes) {
2591 QSet<AbstractMetaClass* > *depends = new QSet<AbstractMetaClass* >();
2591 QSet<AbstractMetaClass* > *depends = new QSet<AbstractMetaClass* >();
2592
2592
2593 if (cls->baseClass())
2593 if (cls->baseClass())
2594 depends->insert(cls->baseClass());
2594 depends->insert(cls->baseClass());
2595
2595
2596 foreach (AbstractMetaClass *interface, cls->interfaces()) {
2596 foreach (AbstractMetaClass *interface, cls->interfaces()) {
2597 AbstractMetaClass *impl = interface->primaryInterfaceImplementor();
2597 AbstractMetaClass *impl = interface->primaryInterfaceImplementor();
2598 if (impl == cls)
2598 if (impl == cls)
2599 continue;
2599 continue;
2600 depends->insert(impl);
2600 depends->insert(impl);
2601 }
2601 }
2602
2602
2603 if (depends->empty()) {
2603 if (depends->empty()) {
2604 noDependency.insert(cls);
2604 noDependency.insert(cls);
2605 } else {
2605 } else {
2606 hash.insert(cls, depends);
2606 hash.insert(cls, depends);
2607 }
2607 }
2608 }
2608 }
2609
2609
2610 while (!noDependency.empty()) {
2610 while (!noDependency.empty()) {
2611 foreach (AbstractMetaClass *cls, noDependency.values()) {
2611 foreach (AbstractMetaClass *cls, noDependency.values()) {
2612 if(!cls->isInterface())
2612 if(!cls->isInterface())
2613 res.append(cls);
2613 res.append(cls);
2614 noDependency.remove(cls);
2614 noDependency.remove(cls);
2615 QHashIterator<AbstractMetaClass*, QSet<AbstractMetaClass* >* > i(hash);
2615 QHashIterator<AbstractMetaClass*, QSet<AbstractMetaClass* >* > i(hash);
2616 while (i.hasNext()) {
2616 while (i.hasNext()) {
2617 i.next();
2617 i.next();
2618 i.value()->remove(cls);
2618 i.value()->remove(cls);
2619 if (i.value()->empty()) {
2619 if (i.value()->empty()) {
2620 AbstractMetaClass *key = i.key();
2620 AbstractMetaClass *key = i.key();
2621 noDependency.insert(key);
2621 noDependency.insert(key);
2622 hash.remove(key);
2622 hash.remove(key);
2623 delete(i.value());
2623 delete(i.value());
2624 }
2624 }
2625 }
2625 }
2626 }
2626 }
2627 }
2627 }
2628
2628
2629 if (!noDependency.empty() || !hash.empty()) {
2629 if (!noDependency.empty() || !hash.empty()) {
2630 qWarning("dependency graph was cyclic.");
2630 qWarning("dependency graph was cyclic.");
2631 }
2631 }
2632
2632
2633 return res;
2633 return res;
2634 }
2634 }
@@ -1,1976 +1,1986
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 "abstractmetalang.h"
42 #include "abstractmetalang.h"
43 #include "reporthandler.h"
43 #include "reporthandler.h"
44
44
45 /*******************************************************************************
45 /*******************************************************************************
46 * AbstractMetaType
46 * AbstractMetaType
47 */
47 */
48 AbstractMetaType *AbstractMetaType::copy() const
48 AbstractMetaType *AbstractMetaType::copy() const
49 {
49 {
50 AbstractMetaType *cpy = new AbstractMetaType;
50 AbstractMetaType *cpy = new AbstractMetaType;
51
51
52 cpy->setTypeUsagePattern(typeUsagePattern());
52 cpy->setTypeUsagePattern(typeUsagePattern());
53 cpy->setConstant(isConstant());
53 cpy->setConstant(isConstant());
54 cpy->setReference(isReference());
54 cpy->setReference(isReference());
55 cpy->setIndirections(indirections());
55 cpy->setIndirections(indirections());
56 cpy->setInstantiations(instantiations());
56 cpy->setInstantiations(instantiations());
57 cpy->setArrayElementCount(arrayElementCount());
57 cpy->setArrayElementCount(arrayElementCount());
58 cpy->setOriginalTypeDescription(originalTypeDescription());
58 cpy->setOriginalTypeDescription(originalTypeDescription());
59 cpy->setOriginalTemplateType(originalTemplateType() ? originalTemplateType()->copy() : 0);
59 cpy->setOriginalTemplateType(originalTemplateType() ? originalTemplateType()->copy() : 0);
60
60
61 cpy->setArrayElementType(arrayElementType() ? arrayElementType()->copy() : 0);
61 cpy->setArrayElementType(arrayElementType() ? arrayElementType()->copy() : 0);
62
62
63 cpy->setTypeEntry(typeEntry());
63 cpy->setTypeEntry(typeEntry());
64
64
65 return cpy;
65 return cpy;
66 }
66 }
67
67
68 QString AbstractMetaType::cppSignature() const
68 QString AbstractMetaType::cppSignature() const
69 {
69 {
70 QString s;
70 QString s;
71
71
72 if (isConstant())
72 if (isConstant())
73 s += "const ";
73 s += "const ";
74
74
75 s += typeEntry()->qualifiedCppName();
75 s += typeEntry()->qualifiedCppName();
76
76
77 if (hasInstantiationInCpp()) {
77 if (hasInstantiationInCpp()) {
78 QList<AbstractMetaType *> types = instantiations();
78 QList<AbstractMetaType *> types = instantiations();
79 s += "<";
79 s += "<";
80 for (int i=0; i<types.count(); ++i) {
80 for (int i=0; i<types.count(); ++i) {
81 if (i > 0)
81 if (i > 0)
82 s += ", ";
82 s += ", ";
83 s += types.at(i)->cppSignature();
83 s += types.at(i)->cppSignature();
84 }
84 }
85 s += " >";
85 s += " >";
86 }
86 }
87
87
88 if (actualIndirections()) {
88 if (actualIndirections()) {
89 s += ' ';
89 s += ' ';
90 if (indirections())
90 if (indirections())
91 s += QString(indirections(), '*');
91 s += QString(indirections(), '*');
92 if (isReference())
92 if (isReference())
93 s += '&';
93 s += '&';
94 }
94 }
95 return s;
95 return s;
96 }
96 }
97
97
98 /*******************************************************************************
98 /*******************************************************************************
99 * AbstractMetaArgument
99 * AbstractMetaArgument
100 */
100 */
101 AbstractMetaArgument *AbstractMetaArgument::copy() const
101 AbstractMetaArgument *AbstractMetaArgument::copy() const
102 {
102 {
103 AbstractMetaArgument *cpy = new AbstractMetaArgument;
103 AbstractMetaArgument *cpy = new AbstractMetaArgument;
104 cpy->setName(AbstractMetaVariable::name());
104 cpy->setName(AbstractMetaVariable::name());
105 cpy->setDefaultValueExpression(defaultValueExpression());
105 cpy->setDefaultValueExpression(defaultValueExpression());
106 cpy->setType(type()->copy());
106 cpy->setType(type()->copy());
107 cpy->setArgumentIndex(argumentIndex());
107 cpy->setArgumentIndex(argumentIndex());
108
108
109 return cpy;
109 return cpy;
110 }
110 }
111
111
112
112
113 QString AbstractMetaArgument::argumentName() const
113 QString AbstractMetaArgument::argumentName() const
114 {
114 {
115 QString n = AbstractMetaVariable::name();
115 QString n = AbstractMetaVariable::name();
116 if (n.isEmpty()) {
116 if (n.isEmpty()) {
117 return QString("arg__%2").arg(m_argument_index + 1);
117 return QString("arg__%2").arg(m_argument_index + 1);
118 }
118 }
119 return n;
119 return n;
120 }
120 }
121
121
122
122
123 QString AbstractMetaArgument::indexedName() const
123 QString AbstractMetaArgument::indexedName() const
124 {
124 {
125 QString n = AbstractMetaVariable::name();
125 QString n = AbstractMetaVariable::name();
126 if (n.isEmpty())
126 if (n.isEmpty())
127 return argumentName();
127 return argumentName();
128 return QString("%1%2").arg(n).arg(m_argument_index);
128 return QString("%1%2").arg(n).arg(m_argument_index);
129 }
129 }
130
130
131 QString AbstractMetaArgument::name() const
131 QString AbstractMetaArgument::name() const
132 {
132 {
133 Q_ASSERT_X(0, "AbstractMetaArgument::name()", "use argumentName() or indexedName() instead");
133 Q_ASSERT_X(0, "AbstractMetaArgument::name()", "use argumentName() or indexedName() instead");
134 return QString();
134 return QString();
135 }
135 }
136
136
137
137
138 /*******************************************************************************
138 /*******************************************************************************
139 * AbstractMetaFunction
139 * AbstractMetaFunction
140 */
140 */
141 AbstractMetaFunction::~AbstractMetaFunction()
141 AbstractMetaFunction::~AbstractMetaFunction()
142 {
142 {
143 qDeleteAll(m_arguments);
143 qDeleteAll(m_arguments);
144 delete m_type;
144 delete m_type;
145 }
145 }
146
146
147 /*******************************************************************************
147 /*******************************************************************************
148 * Indicates that this function has a modification that removes it
148 * Indicates that this function has a modification that removes it
149 */
149 */
150 bool AbstractMetaFunction::isModifiedRemoved(int types) const
150 bool AbstractMetaFunction::isModifiedRemoved(int types) const
151 {
151 {
152 FunctionModificationList mods = modifications(implementingClass());
152 FunctionModificationList mods = modifications(implementingClass());
153 foreach (FunctionModification mod, mods) {
153 foreach (FunctionModification mod, mods) {
154 if (!mod.isRemoveModifier())
154 if (!mod.isRemoveModifier())
155 continue;
155 continue;
156
156
157 if ((mod.removal & types) == types)
157 if ((mod.removal & types) == types)
158 return true;
158 return true;
159 }
159 }
160
160
161 return false;
161 return false;
162 }
162 }
163
163
164 bool AbstractMetaFunction::needsCallThrough() const
164 bool AbstractMetaFunction::needsCallThrough() const
165 {
165 {
166 if (ownerClass()->isInterface())
166 if (ownerClass()->isInterface())
167 return false;
167 return false;
168 if (referenceCounts(implementingClass()).size() > 0)
168 if (referenceCounts(implementingClass()).size() > 0)
169 return true;
169 return true;
170 if (argumentsHaveNativeId() || !isStatic())
170 if (argumentsHaveNativeId() || !isStatic())
171 return true;
171 return true;
172
172
173 foreach (const AbstractMetaArgument *arg, arguments()) {
173 foreach (const AbstractMetaArgument *arg, arguments()) {
174 if (arg->type()->isArray() || arg->type()->isTargetLangEnum() || arg->type()->isTargetLangFlags())
174 if (arg->type()->isArray() || arg->type()->isTargetLangEnum() || arg->type()->isTargetLangFlags())
175 return true;
175 return true;
176 }
176 }
177
177
178 if (type() && (type()->isArray() || type()->isTargetLangEnum() || type()->isTargetLangFlags()))
178 if (type() && (type()->isArray() || type()->isTargetLangEnum() || type()->isTargetLangFlags()))
179 return true;
179 return true;
180
180
181 for (int i=-1; i<=arguments().size(); ++i) {
181 for (int i=-1; i<=arguments().size(); ++i) {
182 TypeSystem::Ownership owner = this->ownership(implementingClass(), TypeSystem::TargetLangCode, i);
182 TypeSystem::Ownership owner = this->ownership(implementingClass(), TypeSystem::TargetLangCode, i);
183 if (owner != TypeSystem::InvalidOwnership)
183 if (owner != TypeSystem::InvalidOwnership)
184 return true;
184 return true;
185 }
185 }
186
186
187 return false;
187 return false;
188 }
188 }
189
189
190 bool AbstractMetaFunction::needsSuppressUncheckedWarning() const
190 bool AbstractMetaFunction::needsSuppressUncheckedWarning() const
191 {
191 {
192 for (int i=-1; i<=arguments().size(); ++i) {
192 for (int i=-1; i<=arguments().size(); ++i) {
193 QList<ReferenceCount> referenceCounts = this->referenceCounts(implementingClass(), i);
193 QList<ReferenceCount> referenceCounts = this->referenceCounts(implementingClass(), i);
194 foreach (ReferenceCount referenceCount, referenceCounts) {
194 foreach (ReferenceCount referenceCount, referenceCounts) {
195 if (referenceCount.action != ReferenceCount::Set)
195 if (referenceCount.action != ReferenceCount::Set)
196 return true;
196 return true;
197 }
197 }
198 }
198 }
199 return false;
199 return false;
200 }
200 }
201
201
202 QString AbstractMetaFunction::marshalledName() const
202 QString AbstractMetaFunction::marshalledName() const
203 {
203 {
204 QString returned = "__qt_" + name();
204 QString returned = "__qt_" + name();
205 AbstractMetaArgumentList arguments = this->arguments();
205 AbstractMetaArgumentList arguments = this->arguments();
206 foreach (const AbstractMetaArgument *arg, arguments) {
206 foreach (const AbstractMetaArgument *arg, arguments) {
207 returned += "_";
207 returned += "_";
208 if (arg->type()->isNativePointer()) {
208 if (arg->type()->isNativePointer()) {
209 returned += "nativepointer";
209 returned += "nativepointer";
210 } else if (arg->type()->isIntegerEnum() || arg->type()->isIntegerFlags()) {
210 } else if (arg->type()->isIntegerEnum() || arg->type()->isIntegerFlags()) {
211 returned += "int";
211 returned += "int";
212 } else {
212 } else {
213 returned += arg->type()->name().replace("[]", "_3").replace(".", "_");
213 returned += arg->type()->name().replace("[]", "_3").replace(".", "_");
214 }
214 }
215 }
215 }
216 return returned;
216 return returned;
217 }
217 }
218
218
219 bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const
219 bool AbstractMetaFunction::operator<(const AbstractMetaFunction &other) const
220 {
220 {
221 uint result = compareTo(&other);
221 uint result = compareTo(&other);
222 return result & NameLessThan;
222 return result & NameLessThan;
223 }
223 }
224
224
225
225
226 /*!
226 /*!
227 Returns a mask of CompareResult describing how this function is
227 Returns a mask of CompareResult describing how this function is
228 compares to another function
228 compares to another function
229 */
229 */
230 uint AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const
230 uint AbstractMetaFunction::compareTo(const AbstractMetaFunction *other) const
231 {
231 {
232 uint result = 0;
232 uint result = 0;
233
233
234 // Enclosing class...
234 // Enclosing class...
235 if (ownerClass() == other->ownerClass()) {
235 if (ownerClass() == other->ownerClass()) {
236 result |= EqualImplementor;
236 result |= EqualImplementor;
237 }
237 }
238
238
239 // Attributes
239 // Attributes
240 if (attributes() == other->attributes()) {
240 if (attributes() == other->attributes()) {
241 result |= EqualAttributes;
241 result |= EqualAttributes;
242 }
242 }
243
243
244 // Compare types
244 // Compare types
245 AbstractMetaType *t = type();
245 AbstractMetaType *t = type();
246 AbstractMetaType *ot = other->type();
246 AbstractMetaType *ot = other->type();
247 if ((!t && !ot) || ((t && ot && t->name() == ot->name()))) {
247 if ((!t && !ot) || ((t && ot && t->name() == ot->name()))) {
248 result |= EqualReturnType;
248 result |= EqualReturnType;
249 }
249 }
250
250
251 // Compare names
251 // Compare names
252 int cmp = originalName().compare(other->originalName());
252 int cmp = originalName().compare(other->originalName());
253
253
254 if (cmp < 0) {
254 if (cmp < 0) {
255 result |= NameLessThan;
255 result |= NameLessThan;
256 } else if (cmp == 0) {
256 } else if (cmp == 0) {
257 result |= EqualName;
257 result |= EqualName;
258 }
258 }
259
259
260 // compare name after modification...
260 // compare name after modification...
261 cmp = modifiedName().compare(other->modifiedName());
261 cmp = modifiedName().compare(other->modifiedName());
262 if (cmp == 0)
262 if (cmp == 0)
263 result |= EqualModifiedName;
263 result |= EqualModifiedName;
264
264
265 // Compare arguments...
265 // Compare arguments...
266 AbstractMetaArgumentList min_arguments;
266 AbstractMetaArgumentList min_arguments;
267 AbstractMetaArgumentList max_arguments;
267 AbstractMetaArgumentList max_arguments;
268 if (arguments().size() < other->arguments().size()) {
268 if (arguments().size() < other->arguments().size()) {
269 min_arguments = arguments();
269 min_arguments = arguments();
270 max_arguments = other->arguments();
270 max_arguments = other->arguments();
271 } else {
271 } else {
272 min_arguments = other->arguments();
272 min_arguments = other->arguments();
273 max_arguments = arguments();
273 max_arguments = arguments();
274 }
274 }
275
275
276 int min_count = min_arguments.size();
276 int min_count = min_arguments.size();
277 int max_count = max_arguments.size();
277 int max_count = max_arguments.size();
278 bool same = true;
278 bool same = true;
279 for (int i=0; i<max_count; ++i) {
279 for (int i=0; i<max_count; ++i) {
280 if (i < min_count) {
280 if (i < min_count) {
281 const AbstractMetaArgument *min_arg = min_arguments.at(i);
281 const AbstractMetaArgument *min_arg = min_arguments.at(i);
282 const AbstractMetaArgument *max_arg = max_arguments.at(i);
282 const AbstractMetaArgument *max_arg = max_arguments.at(i);
283 if (min_arg->type()->name() != max_arg->type()->name()
283 if (min_arg->type()->name() != max_arg->type()->name()
284 && (min_arg->defaultValueExpression().isEmpty() || max_arg->defaultValueExpression().isEmpty())) {
284 && (min_arg->defaultValueExpression().isEmpty() || max_arg->defaultValueExpression().isEmpty())) {
285 same = false;
285 same = false;
286 break;
286 break;
287 }
287 }
288 } else {
288 } else {
289 if (max_arguments.at(i)->defaultValueExpression().isEmpty()) {
289 if (max_arguments.at(i)->defaultValueExpression().isEmpty()) {
290 same = false;
290 same = false;
291 break;
291 break;
292 }
292 }
293 }
293 }
294 }
294 }
295
295
296 if (same)
296 if (same)
297 result |= min_count == max_count ? EqualArguments : EqualDefaultValueOverload;
297 result |= min_count == max_count ? EqualArguments : EqualDefaultValueOverload;
298
298
299 return result;
299 return result;
300 }
300 }
301
301
302 AbstractMetaFunction *AbstractMetaFunction::copy() const
302 AbstractMetaFunction *AbstractMetaFunction::copy() const
303 {
303 {
304 AbstractMetaFunction *cpy = new AbstractMetaFunction;
304 AbstractMetaFunction *cpy = new AbstractMetaFunction;
305 cpy->setName(name());
305 cpy->setName(name());
306 cpy->setOriginalName(originalName());
306 cpy->setOriginalName(originalName());
307 cpy->setOwnerClass(ownerClass());
307 cpy->setOwnerClass(ownerClass());
308 cpy->setImplementingClass(implementingClass());
308 cpy->setImplementingClass(implementingClass());
309 cpy->setInterfaceClass(interfaceClass());
309 cpy->setInterfaceClass(interfaceClass());
310 cpy->setFunctionType(functionType());
310 cpy->setFunctionType(functionType());
311 cpy->setAttributes(attributes());
311 cpy->setAttributes(attributes());
312 cpy->setDeclaringClass(declaringClass());
312 cpy->setDeclaringClass(declaringClass());
313 if (type())
313 if (type())
314 cpy->setType(type()->copy());
314 cpy->setType(type()->copy());
315 cpy->setConstant(isConstant());
315 cpy->setConstant(isConstant());
316 cpy->setOriginalAttributes(originalAttributes());
316 cpy->setOriginalAttributes(originalAttributes());
317
317
318 foreach (AbstractMetaArgument *arg, arguments())
318 foreach (AbstractMetaArgument *arg, arguments())
319 cpy->addArgument(arg->copy());
319 cpy->addArgument(arg->copy());
320
320
321 Q_ASSERT((!type() && !cpy->type())
321 Q_ASSERT((!type() && !cpy->type())
322 || (type()->instantiations() == cpy->type()->instantiations()));
322 || (type()->instantiations() == cpy->type()->instantiations()));
323
323
324 return cpy;
324 return cpy;
325 }
325 }
326
326
327 QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStringList &resolvedArguments) const
327 QStringList AbstractMetaFunction::introspectionCompatibleSignatures(const QStringList &resolvedArguments) const
328 {
328 {
329 AbstractMetaArgumentList arguments = this->arguments();
329 AbstractMetaArgumentList arguments = this->arguments();
330 if (arguments.size() == resolvedArguments.size()) {
330 if (arguments.size() == resolvedArguments.size()) {
331 return (QStringList() << QMetaObject::normalizedSignature((name() + "(" + resolvedArguments.join(",") + ")").toUtf8().constData()));
331 return (QStringList() << QMetaObject::normalizedSignature((name() + "(" + resolvedArguments.join(",") + ")").toUtf8().constData()));
332 } else {
332 } else {
333 QStringList returned;
333 QStringList returned;
334
334
335 AbstractMetaArgument *argument = arguments.at(resolvedArguments.size());
335 AbstractMetaArgument *argument = arguments.at(resolvedArguments.size());
336 QStringList minimalTypeSignature = argument->type()->minimalSignature().split("::");
336 QStringList minimalTypeSignature = argument->type()->minimalSignature().split("::");
337 for (int i=0; i<minimalTypeSignature.size(); ++i) {
337 for (int i=0; i<minimalTypeSignature.size(); ++i) {
338 returned += introspectionCompatibleSignatures(QStringList(resolvedArguments)
338 returned += introspectionCompatibleSignatures(QStringList(resolvedArguments)
339 << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join("::"));
339 << QStringList(minimalTypeSignature.mid(minimalTypeSignature.size() - i - 1)).join("::"));
340 }
340 }
341
341
342 return returned;
342 return returned;
343 }
343 }
344 }
344 }
345
345
346 QString AbstractMetaFunction::signature() const
346 QString AbstractMetaFunction::signature() const
347 {
347 {
348 QString s(m_original_name);
348 QString s(m_original_name);
349
349
350 s += "(";
350 s += "(";
351
351
352 for (int i=0; i<m_arguments.count(); ++i) {
352 for (int i=0; i<m_arguments.count(); ++i) {
353 if (i > 0)
353 if (i > 0)
354 s += ", ";
354 s += ", ";
355 AbstractMetaArgument *a = m_arguments.at(i);
355 AbstractMetaArgument *a = m_arguments.at(i);
356 s += a->type()->cppSignature();
356 s += a->type()->cppSignature();
357
357
358 // We need to have the argument names in the qdoc files
358 // We need to have the argument names in the qdoc files
359 s += " ";
359 s += " ";
360 s += a->argumentName();
360 s += a->argumentName();
361 }
361 }
362 s += ")";
362 s += ")";
363
363
364 if (isConstant())
364 if (isConstant())
365 s += " const";
365 s += " const";
366
366
367 return s;
367 return s;
368 }
368 }
369
369
370 int AbstractMetaFunction::actualMinimumArgumentCount() const
370 int AbstractMetaFunction::actualMinimumArgumentCount() const
371 {
371 {
372 AbstractMetaArgumentList arguments = this->arguments();
372 AbstractMetaArgumentList arguments = this->arguments();
373
373
374 int count = 0;
374 int count = 0;
375 for (int i=0; i<arguments.size(); ++i && ++count) {
375 for (int i=0; i<arguments.size(); ++i && ++count) {
376 if (argumentRemoved(i + 1)) --count;
376 if (argumentRemoved(i + 1)) --count;
377 else if (!arguments.at(i)->defaultValueExpression().isEmpty()) break;
377 else if (!arguments.at(i)->defaultValueExpression().isEmpty()) break;
378 }
378 }
379
379
380 return count;
380 return count;
381 }
381 }
382
382
383 // Returns reference counts for argument at idx, or all arguments if idx == -2
383 // Returns reference counts for argument at idx, or all arguments if idx == -2
384 QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const
384 QList<ReferenceCount> AbstractMetaFunction::referenceCounts(const AbstractMetaClass *cls, int idx) const
385 {
385 {
386 QList<ReferenceCount> returned;
386 QList<ReferenceCount> returned;
387
387
388 FunctionModificationList mods = this->modifications(cls);
388 FunctionModificationList mods = this->modifications(cls);
389 foreach (FunctionModification mod, mods) {
389 foreach (FunctionModification mod, mods) {
390 QList<ArgumentModification> argument_mods = mod.argument_mods;
390 QList<ArgumentModification> argument_mods = mod.argument_mods;
391 foreach (ArgumentModification argument_mod, argument_mods) {
391 foreach (ArgumentModification argument_mod, argument_mods) {
392 if (argument_mod.index != idx && idx != -2)
392 if (argument_mod.index != idx && idx != -2)
393 continue;
393 continue;
394 returned += argument_mod.referenceCounts;
394 returned += argument_mod.referenceCounts;
395 }
395 }
396 }
396 }
397
397
398 return returned;
398 return returned;
399 }
399 }
400
400
401 QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass *cls, int key) const
401 QString AbstractMetaFunction::replacedDefaultExpression(const AbstractMetaClass *cls, int key) const
402 {
402 {
403 FunctionModificationList modifications = this->modifications(cls);
403 FunctionModificationList modifications = this->modifications(cls);
404 foreach (FunctionModification modification, modifications) {
404 foreach (FunctionModification modification, modifications) {
405 QList<ArgumentModification> argument_modifications = modification.argument_mods;
405 QList<ArgumentModification> argument_modifications = modification.argument_mods;
406 foreach (ArgumentModification argument_modification, argument_modifications) {
406 foreach (ArgumentModification argument_modification, argument_modifications) {
407 if (argument_modification.index == key
407 if (argument_modification.index == key
408 && !argument_modification.replaced_default_expression.isEmpty()) {
408 && !argument_modification.replaced_default_expression.isEmpty()) {
409 return argument_modification.replaced_default_expression;
409 return argument_modification.replaced_default_expression;
410 }
410 }
411 }
411 }
412 }
412 }
413
413
414 return QString();
414 return QString();
415 }
415 }
416
416
417 bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls, int key) const
417 bool AbstractMetaFunction::removedDefaultExpression(const AbstractMetaClass *cls, int key) const
418 {
418 {
419 FunctionModificationList modifications = this->modifications(cls);
419 FunctionModificationList modifications = this->modifications(cls);
420 foreach (FunctionModification modification, modifications) {
420 foreach (FunctionModification modification, modifications) {
421 QList<ArgumentModification> argument_modifications = modification.argument_mods;
421 QList<ArgumentModification> argument_modifications = modification.argument_mods;
422 foreach (ArgumentModification argument_modification, argument_modifications) {
422 foreach (ArgumentModification argument_modification, argument_modifications) {
423 if (argument_modification.index == key
423 if (argument_modification.index == key
424 && argument_modification.removed_default_expression) {
424 && argument_modification.removed_default_expression) {
425 return true;
425 return true;
426 }
426 }
427 }
427 }
428 }
428 }
429
429
430 return false;
430 return false;
431 }
431 }
432
432
433 bool AbstractMetaFunction::resetObjectAfterUse(int argument_idx) const
433 bool AbstractMetaFunction::resetObjectAfterUse(int argument_idx) const
434 {
434 {
435 const AbstractMetaClass *cls = declaringClass();
435 const AbstractMetaClass *cls = declaringClass();
436 FunctionModificationList modifications = this->modifications(cls);
436 FunctionModificationList modifications = this->modifications(cls);
437 foreach (FunctionModification modification, modifications) {
437 foreach (FunctionModification modification, modifications) {
438 QList<ArgumentModification> argumentModifications = modification.argument_mods;
438 QList<ArgumentModification> argumentModifications = modification.argument_mods;
439 foreach (ArgumentModification argumentModification, argumentModifications) {
439 foreach (ArgumentModification argumentModification, argumentModifications) {
440 if (argumentModification.index == argument_idx && argumentModification.reset_after_use)
440 if (argumentModification.index == argument_idx && argumentModification.reset_after_use)
441 return true;
441 return true;
442 }
442 }
443 }
443 }
444
444
445 return false;
445 return false;
446 }
446 }
447
447
448 QString AbstractMetaFunction::nullPointerDefaultValue(const AbstractMetaClass *mainClass, int argument_idx) const
448 QString AbstractMetaFunction::nullPointerDefaultValue(const AbstractMetaClass *mainClass, int argument_idx) const
449 {
449 {
450 Q_ASSERT(nullPointersDisabled(mainClass, argument_idx));
450 Q_ASSERT(nullPointersDisabled(mainClass, argument_idx));
451
451
452 const AbstractMetaClass *cls = mainClass;
452 const AbstractMetaClass *cls = mainClass;
453 if (cls == 0)
453 if (cls == 0)
454 cls = implementingClass();
454 cls = implementingClass();
455
455
456 do {
456 do {
457 FunctionModificationList modifications = this->modifications(cls);
457 FunctionModificationList modifications = this->modifications(cls);
458 foreach (FunctionModification modification, modifications) {
458 foreach (FunctionModification modification, modifications) {
459 QList<ArgumentModification> argument_modifications = modification.argument_mods;
459 QList<ArgumentModification> argument_modifications = modification.argument_mods;
460 foreach (ArgumentModification argument_modification, argument_modifications) {
460 foreach (ArgumentModification argument_modification, argument_modifications) {
461 if (argument_modification.index == argument_idx
461 if (argument_modification.index == argument_idx
462 && argument_modification.no_null_pointers) {
462 && argument_modification.no_null_pointers) {
463 return argument_modification.null_pointer_default_value;
463 return argument_modification.null_pointer_default_value;
464 }
464 }
465 }
465 }
466 }
466 }
467
467
468 cls = cls->baseClass();
468 cls = cls->baseClass();
469 } while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class
469 } while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class
470
470
471 return QString();
471 return QString();
472
472
473 }
473 }
474
474
475 bool AbstractMetaFunction::nullPointersDisabled(const AbstractMetaClass *mainClass, int argument_idx) const
475 bool AbstractMetaFunction::nullPointersDisabled(const AbstractMetaClass *mainClass, int argument_idx) const
476 {
476 {
477 const AbstractMetaClass *cls = mainClass;
477 const AbstractMetaClass *cls = mainClass;
478 if (cls == 0)
478 if (cls == 0)
479 cls = implementingClass();
479 cls = implementingClass();
480
480
481 do {
481 do {
482 FunctionModificationList modifications = this->modifications(cls);
482 FunctionModificationList modifications = this->modifications(cls);
483 foreach (FunctionModification modification, modifications) {
483 foreach (FunctionModification modification, modifications) {
484 QList<ArgumentModification> argument_modifications = modification.argument_mods;
484 QList<ArgumentModification> argument_modifications = modification.argument_mods;
485 foreach (ArgumentModification argument_modification, argument_modifications) {
485 foreach (ArgumentModification argument_modification, argument_modifications) {
486 if (argument_modification.index == argument_idx
486 if (argument_modification.index == argument_idx
487 && argument_modification.no_null_pointers) {
487 && argument_modification.no_null_pointers) {
488 return true;
488 return true;
489 }
489 }
490 }
490 }
491 }
491 }
492
492
493 cls = cls->baseClass();
493 cls = cls->baseClass();
494 } while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class
494 } while (cls != 0 && mainClass == 0); // Once when mainClass != 0, or once for all base classes of implementing class
495
495
496 return false;
496 return false;
497 }
497 }
498
498
499 QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const
499 QString AbstractMetaFunction::conversionRule(TypeSystem::Language language, int key) const
500 {
500 {
501 FunctionModificationList modifications = this->modifications(declaringClass());
501 FunctionModificationList modifications = this->modifications(declaringClass());
502 foreach (FunctionModification modification, modifications) {
502 foreach (FunctionModification modification, modifications) {
503 QList<ArgumentModification> argument_modifications = modification.argument_mods;
503 QList<ArgumentModification> argument_modifications = modification.argument_mods;
504 foreach (ArgumentModification argument_modification, argument_modifications) {
504 foreach (ArgumentModification argument_modification, argument_modifications) {
505 if (argument_modification.index != key)
505 if (argument_modification.index != key)
506 continue;
506 continue;
507
507
508 foreach (CodeSnip snip, argument_modification.conversion_rules) {
508 foreach (CodeSnip snip, argument_modification.conversion_rules) {
509 if (snip.language == language && !snip.code().isEmpty())
509 if (snip.language == language && !snip.code().isEmpty())
510 return snip.code();
510 return snip.code();
511 }
511 }
512 }
512 }
513 }
513 }
514
514
515 return QString();
515 return QString();
516 }
516 }
517
517
518 QString AbstractMetaFunction::argumentReplaced(int key) const
518 QString AbstractMetaFunction::argumentReplaced(int key) const
519 {
519 {
520 FunctionModificationList modifications = this->modifications(declaringClass());
520 FunctionModificationList modifications = this->modifications(declaringClass());
521 foreach (FunctionModification modification, modifications) {
521 foreach (FunctionModification modification, modifications) {
522 QList<ArgumentModification> argument_modifications = modification.argument_mods;
522 QList<ArgumentModification> argument_modifications = modification.argument_mods;
523 foreach (ArgumentModification argument_modification, argument_modifications) {
523 foreach (ArgumentModification argument_modification, argument_modifications) {
524 if (argument_modification.index == key && !argument_modification.replace_value.isEmpty()) {
524 if (argument_modification.index == key && !argument_modification.replace_value.isEmpty()) {
525 return argument_modification.replace_value;
525 return argument_modification.replace_value;
526 }
526 }
527 }
527 }
528 }
528 }
529
529
530 return "";
530 return "";
531 }
531 }
532
532
533 bool AbstractMetaFunction::argumentRemoved(int key) const
533 bool AbstractMetaFunction::argumentRemoved(int key) const
534 {
534 {
535 FunctionModificationList modifications = this->modifications(declaringClass());
535 FunctionModificationList modifications = this->modifications(declaringClass());
536 foreach (FunctionModification modification, modifications) {
536 foreach (FunctionModification modification, modifications) {
537 QList<ArgumentModification> argument_modifications = modification.argument_mods;
537 QList<ArgumentModification> argument_modifications = modification.argument_mods;
538 foreach (ArgumentModification argument_modification, argument_modifications) {
538 foreach (ArgumentModification argument_modification, argument_modifications) {
539 if (argument_modification.index == key) {
539 if (argument_modification.index == key) {
540 if (argument_modification.removed) {
540 if (argument_modification.removed) {
541 return true;
541 return true;
542 }
542 }
543 }
543 }
544 }
544 }
545 }
545 }
546
546
547 return false;
547 return false;
548 }
548 }
549
549
550 bool AbstractMetaFunction::isVirtualSlot() const
550 bool AbstractMetaFunction::isVirtualSlot() const
551 {
551 {
552 FunctionModificationList modifications = this->modifications(declaringClass());
552 FunctionModificationList modifications = this->modifications(declaringClass());
553 foreach (FunctionModification modification, modifications) {
553 foreach (FunctionModification modification, modifications) {
554 if (modification.isVirtualSlot())
554 if (modification.isVirtualSlot())
555 return true;
555 return true;
556 }
556 }
557
557
558 return false;
558 return false;
559 }
559 }
560
560
561 bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const
561 bool AbstractMetaFunction::disabledGarbageCollection(const AbstractMetaClass *cls, int key) const
562 {
562 {
563 FunctionModificationList modifications = this->modifications(cls);
563 FunctionModificationList modifications = this->modifications(cls);
564 foreach (FunctionModification modification, modifications) {
564 foreach (FunctionModification modification, modifications) {
565 QList<ArgumentModification> argument_modifications = modification.argument_mods;
565 QList<ArgumentModification> argument_modifications = modification.argument_mods;
566 foreach (ArgumentModification argument_modification, argument_modifications) {
566 foreach (ArgumentModification argument_modification, argument_modifications) {
567 if (argument_modification.index != key)
567 if (argument_modification.index != key)
568 continue;
568 continue;
569
569
570 foreach (TypeSystem::Ownership ownership, argument_modification.ownerships.values()) {
570 foreach (TypeSystem::Ownership ownership, argument_modification.ownerships.values()) {
571 if (ownership == TypeSystem::CppOwnership)
571 if (ownership == TypeSystem::CppOwnership)
572 return true;
572 return true;
573 }
573 }
574
574
575 }
575 }
576 }
576 }
577
577
578 return false;
578 return false;
579 }
579 }
580
580
581 bool AbstractMetaFunction::isDeprecated() const
581 bool AbstractMetaFunction::isDeprecated() const
582 {
582 {
583 FunctionModificationList modifications = this->modifications(declaringClass());
583 FunctionModificationList modifications = this->modifications(declaringClass());
584 foreach (FunctionModification modification, modifications) {
584 foreach (FunctionModification modification, modifications) {
585 if (modification.isDeprecated())
585 if (modification.isDeprecated())
586 return true;
586 return true;
587 }
587 }
588 return false;
588 return false;
589 }
589 }
590
590
591 TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const
591 TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const
592 {
592 {
593 FunctionModificationList modifications = this->modifications(cls);
593 FunctionModificationList modifications = this->modifications(cls);
594 foreach (FunctionModification modification, modifications) {
594 foreach (FunctionModification modification, modifications) {
595 QList<ArgumentModification> argument_modifications = modification.argument_mods;
595 QList<ArgumentModification> argument_modifications = modification.argument_mods;
596 foreach (ArgumentModification argument_modification, argument_modifications) {
596 foreach (ArgumentModification argument_modification, argument_modifications) {
597 if (argument_modification.index == key)
597 if (argument_modification.index == key)
598 return argument_modification.ownerships.value(language, TypeSystem::InvalidOwnership);
598 return argument_modification.ownerships.value(language, TypeSystem::InvalidOwnership);
599 }
599 }
600 }
600 }
601
601
602 return TypeSystem::InvalidOwnership;
602 return TypeSystem::InvalidOwnership;
603 }
603 }
604
604
605 bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cls) const
605 bool AbstractMetaFunction::isRemovedFromAllLanguages(const AbstractMetaClass *cls) const
606 {
606 {
607 return isRemovedFrom(cls, TypeSystem::All);
607 return isRemovedFrom(cls, TypeSystem::All);
608 }
608 }
609
609
610 bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const
610 bool AbstractMetaFunction::isRemovedFrom(const AbstractMetaClass *cls, TypeSystem::Language language) const
611 {
611 {
612 FunctionModificationList modifications = this->modifications(cls);
612 FunctionModificationList modifications = this->modifications(cls);
613 foreach (FunctionModification modification, modifications) {
613 foreach (FunctionModification modification, modifications) {
614 if ((modification.removal & language) == language)
614 if ((modification.removal & language) == language)
615 return true;
615 return true;
616 }
616 }
617
617
618 return false;
618 return false;
619
619
620 }
620 }
621
621
622 QString AbstractMetaFunction::typeReplaced(int key) const
622 QString AbstractMetaFunction::typeReplaced(int key) const
623 {
623 {
624 FunctionModificationList modifications = this->modifications(declaringClass());
624 FunctionModificationList modifications = this->modifications(declaringClass());
625 foreach (FunctionModification modification, modifications) {
625 foreach (FunctionModification modification, modifications) {
626 QList<ArgumentModification> argument_modifications = modification.argument_mods;
626 QList<ArgumentModification> argument_modifications = modification.argument_mods;
627 foreach (ArgumentModification argument_modification, argument_modifications) {
627 foreach (ArgumentModification argument_modification, argument_modifications) {
628 if (argument_modification.index == key
628 if (argument_modification.index == key
629 && !argument_modification.modified_type.isEmpty()) {
629 && !argument_modification.modified_type.isEmpty()) {
630 return argument_modification.modified_type;
630 return argument_modification.modified_type;
631 }
631 }
632 }
632 }
633 }
633 }
634
634
635 return QString();
635 return QString();
636 }
636 }
637
637
638 QString AbstractMetaFunction::minimalSignature() const
638 QString AbstractMetaFunction::minimalSignature() const
639 {
639 {
640 if (!m_cached_minimal_signature.isEmpty())
640 if (!m_cached_minimal_signature.isEmpty())
641 return m_cached_minimal_signature;
641 return m_cached_minimal_signature;
642
642
643 QString minimalSignature = originalName() + "(";
643 QString minimalSignature = originalName() + "(";
644 AbstractMetaArgumentList arguments = this->arguments();
644 AbstractMetaArgumentList arguments = this->arguments();
645
645
646 for (int i=0; i<arguments.count(); ++i) {
646 for (int i=0; i<arguments.count(); ++i) {
647 AbstractMetaType *t = arguments.at(i)->type();
647 AbstractMetaType *t = arguments.at(i)->type();
648
648
649 if (i > 0)
649 if (i > 0)
650 minimalSignature += ",";
650 minimalSignature += ",";
651
651
652 minimalSignature += t->minimalSignature();
652 minimalSignature += t->minimalSignature();
653 }
653 }
654 minimalSignature += ")";
654 minimalSignature += ")";
655 if (isConstant())
655 if (isConstant())
656 minimalSignature += "const";
656 minimalSignature += "const";
657
657
658 minimalSignature = QMetaObject::normalizedSignature(minimalSignature.toLocal8Bit().constData());
658 minimalSignature = QMetaObject::normalizedSignature(minimalSignature.toLocal8Bit().constData());
659 m_cached_minimal_signature = minimalSignature;
659 m_cached_minimal_signature = minimalSignature;
660
660
661 return minimalSignature;
661 return minimalSignature;
662 }
662 }
663
663
664 FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const
664 FunctionModificationList AbstractMetaFunction::modifications(const AbstractMetaClass *implementor) const
665 {
665 {
666 Q_ASSERT(implementor);
666 Q_ASSERT(implementor);
667 return implementor->typeEntry()->functionModifications(minimalSignature());
667 return implementor->typeEntry()->functionModifications(minimalSignature());
668 }
668 }
669
669
670 bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const
670 bool AbstractMetaFunction::hasModifications(const AbstractMetaClass *implementor) const
671 {
671 {
672 FunctionModificationList mods = modifications(implementor);
672 FunctionModificationList mods = modifications(implementor);
673 return mods.count() > 0;
673 return mods.count() > 0;
674 }
674 }
675
675
676 QString AbstractMetaFunction::modifiedName() const
676 QString AbstractMetaFunction::modifiedName() const
677 {
677 {
678 if (m_cached_modified_name.isEmpty()) {
678 if (m_cached_modified_name.isEmpty()) {
679 FunctionModificationList mods = modifications(implementingClass());
679 FunctionModificationList mods = modifications(implementingClass());
680 foreach (FunctionModification mod, mods) {
680 foreach (FunctionModification mod, mods) {
681 if (mod.isRenameModifier()) {
681 if (mod.isRenameModifier()) {
682 m_cached_modified_name = mod.renamedToName;
682 m_cached_modified_name = mod.renamedToName;
683 break;
683 break;
684 }
684 }
685 }
685 }
686 if (m_cached_modified_name.isEmpty())
686 if (m_cached_modified_name.isEmpty())
687 m_cached_modified_name = name();
687 m_cached_modified_name = name();
688 }
688 }
689 return m_cached_modified_name;
689 return m_cached_modified_name;
690 }
690 }
691
691
692 QString AbstractMetaFunction::targetLangSignature(bool minimal) const
692 QString AbstractMetaFunction::targetLangSignature(bool minimal) const
693 {
693 {
694 QString s;
694 QString s;
695
695
696 // Attributes...
696 // Attributes...
697 if (!minimal) {
697 if (!minimal) {
698 #if 0 // jambi
698 #if 0 // jambi
699 if (isPublic()) s += "public ";
699 if (isPublic()) s += "public ";
700 else if (isProtected()) s += "protected ";
700 else if (isProtected()) s += "protected ";
701 else if (isPrivate()) s += "private ";
701 else if (isPrivate()) s += "private ";
702
702
703 // if (isNative()) s += "native ";
703 // if (isNative()) s += "native ";
704 // else
704 // else
705 if (isFinalInTargetLang()) s += "final ";
705 if (isFinalInTargetLang()) s += "final ";
706 else if (isAbstract()) s += "abstract ";
706 else if (isAbstract()) s += "abstract ";
707
707
708 if (isStatic()) s += "static ";
708 if (isStatic()) s += "static ";
709 #endif
709 #endif
710 // Return type
710 // Return type
711 if (type())
711 if (type())
712 s += type()->name() + " ";
712 s += type()->name() + " ";
713 else
713 else
714 s += "void ";
714 s += "void ";
715 }
715 }
716
716
717 s += modifiedName();
717 s += modifiedName();
718 s += "(";
718 s += "(";
719
719
720 int j = 0;
720 int j = 0;
721 for (int i=0; i<m_arguments.size(); ++i) {
721 for (int i=0; i<m_arguments.size(); ++i) {
722 if (argumentRemoved(i+1))
722 if (argumentRemoved(i+1))
723 continue;
723 continue;
724 if (j != 0) {
724 if (j != 0) {
725 s += ",";
725 s += ",";
726 if (!minimal)
726 if (!minimal)
727 s += QLatin1Char(' ');
727 s += QLatin1Char(' ');
728 }
728 }
729 s += m_arguments.at(i)->type()->name();
729 s += m_arguments.at(i)->type()->name();
730
730
731 if (!minimal) {
731 if (!minimal) {
732 s += " ";
732 s += " ";
733 s += m_arguments.at(i)->argumentName();
733 s += m_arguments.at(i)->argumentName();
734 }
734 }
735 ++j;
735 ++j;
736 }
736 }
737
737
738 s += ")";
738 s += ")";
739
739
740 return s;
740 return s;
741 }
741 }
742
742
743
743
744 bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b)
744 bool function_sorter(AbstractMetaFunction *a, AbstractMetaFunction *b)
745 {
745 {
746 return a->signature() < b->signature();
746 return a->signature() < b->signature();
747 }
747 }
748
748
749 /*******************************************************************************
749 /*******************************************************************************
750 * AbstractMetaClass
750 * AbstractMetaClass
751 */
751 */
752 AbstractMetaClass::~AbstractMetaClass()
752 AbstractMetaClass::~AbstractMetaClass()
753 {
753 {
754 qDeleteAll(m_functions);
754 qDeleteAll(m_functions);
755 qDeleteAll(m_fields);
755 qDeleteAll(m_fields);
756 }
756 }
757
757
758 /*AbstractMetaClass *AbstractMetaClass::copy() const
758 /*AbstractMetaClass *AbstractMetaClass::copy() const
759 {
759 {
760 AbstractMetaClass *cls = new AbstractMetaClass;
760 AbstractMetaClass *cls = new AbstractMetaClass;
761 cls->setAttributes(attributes());
761 cls->setAttributes(attributes());
762 cls->setBaseClass(baseClass());
762 cls->setBaseClass(baseClass());
763 cls->setTypeEntry(typeEntry());
763 cls->setTypeEntry(typeEntry());
764 foreach (AbstractMetaFunction *function, functions()) {
764 foreach (AbstractMetaFunction *function, functions()) {
765 AbstractMetaFunction *copy = function->copy();
765 AbstractMetaFunction *copy = function->copy();
766 function->setImplementingClass(cls);
766 function->setImplementingClass(cls);
767 cls->addFunction(copy);
767 cls->addFunction(copy);
768 }
768 }
769 cls->setEnums(enums());
769 cls->setEnums(enums());
770 foreach (const AbstractMetaField *field, fields()) {
770 foreach (const AbstractMetaField *field, fields()) {
771 AbstractMetaField *copy = field->copy();
771 AbstractMetaField *copy = field->copy();
772 copy->setEnclosingClass(cls);
772 copy->setEnclosingClass(cls);
773 cls->addField(copy);
773 cls->addField(copy);
774 }
774 }
775 cls->setInterfaces(interfaces());
775 cls->setInterfaces(interfaces());
776
776
777 return cls;
777 return cls;
778 }*/
778 }*/
779
779
780 /*******************************************************************************
780 /*******************************************************************************
781 * Returns true if this class is a subclass of the given class
781 * Returns true if this class is a subclass of the given class
782 */
782 */
783 bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const
783 bool AbstractMetaClass::inheritsFrom(const AbstractMetaClass *cls) const
784 {
784 {
785 Q_ASSERT(cls != 0);
785 Q_ASSERT(cls != 0);
786
786
787 const AbstractMetaClass *clazz = this;
787 const AbstractMetaClass *clazz = this;
788 while (clazz != 0) {
788 while (clazz != 0) {
789 if (clazz == cls)
789 if (clazz == cls)
790 return true;
790 return true;
791
791
792 clazz = clazz->baseClass();
792 clazz = clazz->baseClass();
793 }
793 }
794
794
795 return false;
795 return false;
796 }
796 }
797
797
798 /*******************************************************************************
798 /*******************************************************************************
799 * Constructs an interface based on the functions and enums in this
799 * Constructs an interface based on the functions and enums in this
800 * class and returns it...
800 * class and returns it...
801 */
801 */
802 AbstractMetaClass *AbstractMetaClass::extractInterface()
802 AbstractMetaClass *AbstractMetaClass::extractInterface()
803 {
803 {
804 Q_ASSERT(typeEntry()->designatedInterface());
804 Q_ASSERT(typeEntry()->designatedInterface());
805
805
806 if (m_extracted_interface == 0) {
806 if (m_extracted_interface == 0) {
807 AbstractMetaClass *iface = new AbstractMetaClass;
807 AbstractMetaClass *iface = new AbstractMetaClass;
808 iface->setAttributes(attributes());
808 iface->setAttributes(attributes());
809 iface->setBaseClass(0);
809 iface->setBaseClass(0);
810 iface->setPrimaryInterfaceImplementor(this);
810 iface->setPrimaryInterfaceImplementor(this);
811
811
812 iface->setTypeEntry(typeEntry()->designatedInterface());
812 iface->setTypeEntry(typeEntry()->designatedInterface());
813
813
814 foreach (AbstractMetaFunction *function, functions()) {
814 foreach (AbstractMetaFunction *function, functions()) {
815 if (!function->isConstructor())
815 if (!function->isConstructor())
816 iface->addFunction(function->copy());
816 iface->addFunction(function->copy());
817 }
817 }
818
818
819 // iface->setEnums(enums());
819 // iface->setEnums(enums());
820 // setEnums(AbstractMetaEnumList());
820 // setEnums(AbstractMetaEnumList());
821
821
822 foreach (const AbstractMetaField *field, fields()) {
822 foreach (const AbstractMetaField *field, fields()) {
823 if (field->isPublic()) {
823 if (field->isPublic()) {
824 AbstractMetaField *new_field = field->copy();
824 AbstractMetaField *new_field = field->copy();
825 new_field->setEnclosingClass(iface);
825 new_field->setEnclosingClass(iface);
826 iface->addField(new_field);
826 iface->addField(new_field);
827 }
827 }
828 }
828 }
829
829
830 m_extracted_interface = iface;
830 m_extracted_interface = iface;
831 addInterface(iface);
831 addInterface(iface);
832 }
832 }
833
833
834 return m_extracted_interface;
834 return m_extracted_interface;
835 }
835 }
836
836
837 /*******************************************************************************
837 /*******************************************************************************
838 * Returns a list of all the functions with a given name
838 * Returns a list of all the functions with a given name
839 */
839 */
840 AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const
840 AbstractMetaFunctionList AbstractMetaClass::queryFunctionsByName(const QString &name) const
841 {
841 {
842 AbstractMetaFunctionList returned;
842 AbstractMetaFunctionList returned;
843 AbstractMetaFunctionList functions = this->functions();
843 AbstractMetaFunctionList functions = this->functions();
844 foreach (AbstractMetaFunction *function, functions) {
844 foreach (AbstractMetaFunction *function, functions) {
845 if (function->name() == name)
845 if (function->name() == name)
846 returned.append(function);
846 returned.append(function);
847 }
847 }
848
848
849 return returned;
849 return returned;
850 }
850 }
851
851
852 bool AbstractMetaClass::hasDefaultIsNull() const
853 {
854 foreach(const AbstractMetaFunction* fun, queryFunctionsByName("isNull")) {
855 if (fun->actualMinimumArgumentCount()==0) {
856 return true;
857 }
858 }
859 return false;
860 }
861
852 /*******************************************************************************
862 /*******************************************************************************
853 * Returns all reference count modifications for any function in the class
863 * Returns all reference count modifications for any function in the class
854 */
864 */
855 QList<ReferenceCount> AbstractMetaClass::referenceCounts() const
865 QList<ReferenceCount> AbstractMetaClass::referenceCounts() const
856 {
866 {
857 QList<ReferenceCount> returned;
867 QList<ReferenceCount> returned;
858
868
859 AbstractMetaFunctionList functions = this->functions();
869 AbstractMetaFunctionList functions = this->functions();
860 foreach (AbstractMetaFunction *function, functions) {
870 foreach (AbstractMetaFunction *function, functions) {
861 returned += function->referenceCounts(this);
871 returned += function->referenceCounts(this);
862 }
872 }
863
873
864 return returned;
874 return returned;
865 }
875 }
866
876
867 /*******************************************************************************
877 /*******************************************************************************
868 * Returns a list of all the functions retrieved during parsing which should
878 * Returns a list of all the functions retrieved during parsing which should
869 * be added to the Java API.
879 * be added to the Java API.
870 */
880 */
871 AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const
881 AbstractMetaFunctionList AbstractMetaClass::functionsInTargetLang() const
872 {
882 {
873 int default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang;
883 int default_flags = NormalFunctions | Visible | NotRemovedFromTargetLang;
874
884
875 // Interfaces don't implement functions
885 // Interfaces don't implement functions
876 default_flags |= isInterface() ? 0 : ClassImplements;
886 default_flags |= isInterface() ? 0 : ClassImplements;
877
887
878 // Only public functions in final classes
888 // Only public functions in final classes
879 // default_flags |= isFinal() ? WasPublic : 0;
889 // default_flags |= isFinal() ? WasPublic : 0;
880 int public_flags = isFinal() ? WasPublic : 0;
890 int public_flags = isFinal() ? WasPublic : 0;
881
891
882 // Constructors
892 // Constructors
883 AbstractMetaFunctionList returned = queryFunctions(Constructors | default_flags | public_flags);
893 AbstractMetaFunctionList returned = queryFunctions(Constructors | default_flags | public_flags);
884
894
885 // Final functions
895 // Final functions
886 returned += queryFunctions(FinalInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
896 returned += queryFunctions(FinalInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
887
897
888 // Virtual functions
898 // Virtual functions
889 returned += queryFunctions(VirtualInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
899 returned += queryFunctions(VirtualInTargetLangFunctions | NonStaticFunctions | default_flags | public_flags);
890
900
891 // Static functions
901 // Static functions
892 returned += queryFunctions(StaticFunctions | default_flags | public_flags);
902 returned += queryFunctions(StaticFunctions | default_flags | public_flags);
893
903
894 // Empty, private functions, since they aren't caught by the other ones
904 // Empty, private functions, since they aren't caught by the other ones
895 returned += queryFunctions(Empty | Invisible);
905 returned += queryFunctions(Empty | Invisible);
896
906
897 return returned;
907 return returned;
898 }
908 }
899
909
900 AbstractMetaFunctionList AbstractMetaClass::virtualFunctions() const
910 AbstractMetaFunctionList AbstractMetaClass::virtualFunctions() const
901 {
911 {
902 AbstractMetaFunctionList list = functionsInShellClass();
912 AbstractMetaFunctionList list = functionsInShellClass();
903
913
904 AbstractMetaFunctionList returned;
914 AbstractMetaFunctionList returned;
905 foreach (AbstractMetaFunction *f, list) {
915 foreach (AbstractMetaFunction *f, list) {
906 if (!f->isFinalInCpp() || f->isVirtualSlot())
916 if (!f->isFinalInCpp() || f->isVirtualSlot())
907 returned += f;
917 returned += f;
908 }
918 }
909
919
910 return returned;
920 return returned;
911 }
921 }
912
922
913 AbstractMetaFunctionList AbstractMetaClass::nonVirtualShellFunctions() const
923 AbstractMetaFunctionList AbstractMetaClass::nonVirtualShellFunctions() const
914 {
924 {
915 AbstractMetaFunctionList list = functionsInShellClass();
925 AbstractMetaFunctionList list = functionsInShellClass();
916 AbstractMetaFunctionList returned;
926 AbstractMetaFunctionList returned;
917 foreach (AbstractMetaFunction *f, list) {
927 foreach (AbstractMetaFunction *f, list) {
918 if (f->isFinalInCpp() && !f->isVirtualSlot())
928 if (f->isFinalInCpp() && !f->isVirtualSlot())
919 returned += f;
929 returned += f;
920 }
930 }
921
931
922 return returned;
932 return returned;
923 }
933 }
924
934
925 /*******************************************************************************
935 /*******************************************************************************
926 * Returns a list of all functions that should be declared and implemented in
936 * Returns a list of all functions that should be declared and implemented in
927 * the shell class which is generated as a wrapper on top of the actual C++ class
937 * the shell class which is generated as a wrapper on top of the actual C++ class
928 */
938 */
929 AbstractMetaFunctionList AbstractMetaClass::functionsInShellClass() const
939 AbstractMetaFunctionList AbstractMetaClass::functionsInShellClass() const
930 {
940 {
931 // Only functions and only protected and public functions
941 // Only functions and only protected and public functions
932 int default_flags = NormalFunctions | Visible | WasVisible | NotRemovedFromShell;
942 int default_flags = NormalFunctions | Visible | WasVisible | NotRemovedFromShell;
933
943
934 // All virtual functions
944 // All virtual functions
935 AbstractMetaFunctionList returned = queryFunctions(VirtualFunctions | default_flags);
945 AbstractMetaFunctionList returned = queryFunctions(VirtualFunctions | default_flags);
936
946
937 // All functions explicitly set to be implemented by the shell class
947 // All functions explicitly set to be implemented by the shell class
938 // (mainly superclass functions that are hidden by other declarations)
948 // (mainly superclass functions that are hidden by other declarations)
939 returned += queryFunctions(ForcedShellFunctions | default_flags);
949 returned += queryFunctions(ForcedShellFunctions | default_flags);
940
950
941 // All functions explicitly set to be virtual slots
951 // All functions explicitly set to be virtual slots
942 returned += queryFunctions(VirtualSlots | default_flags);
952 returned += queryFunctions(VirtualSlots | default_flags);
943
953
944 return returned;
954 return returned;
945 }
955 }
946
956
947 /*******************************************************************************
957 /*******************************************************************************
948 * Returns a list of all functions that require a public override function to
958 * Returns a list of all functions that require a public override function to
949 * be generated in the shell class. This includes all functions that were originally
959 * be generated in the shell class. This includes all functions that were originally
950 * protected in the superclass.
960 * protected in the superclass.
951 */
961 */
952 AbstractMetaFunctionList AbstractMetaClass::publicOverrideFunctions() const
962 AbstractMetaFunctionList AbstractMetaClass::publicOverrideFunctions() const
953 {
963 {
954 return queryFunctions(NormalFunctions | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang)
964 return queryFunctions(NormalFunctions | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang)
955 + queryFunctions(Signals | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang);
965 + queryFunctions(Signals | WasProtected | FinalInCppFunctions | NotRemovedFromTargetLang);
956 }
966 }
957
967
958 AbstractMetaFunctionList AbstractMetaClass::virtualOverrideFunctions() const
968 AbstractMetaFunctionList AbstractMetaClass::virtualOverrideFunctions() const
959 {
969 {
960 return queryFunctions(NormalFunctions | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell) +
970 return queryFunctions(NormalFunctions | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell) +
961 queryFunctions(Signals | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell);
971 queryFunctions(Signals | NonEmptyFunctions | Visible | VirtualInCppFunctions | NotRemovedFromShell);
962 }
972 }
963
973
964 void AbstractMetaClass::sortFunctions()
974 void AbstractMetaClass::sortFunctions()
965 {
975 {
966 qSort(m_functions.begin(), m_functions.end(), function_sorter);
976 qSort(m_functions.begin(), m_functions.end(), function_sorter);
967 }
977 }
968
978
969 void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions)
979 void AbstractMetaClass::setFunctions(const AbstractMetaFunctionList &functions)
970 {
980 {
971 m_functions = functions;
981 m_functions = functions;
972
982
973 // Functions must be sorted by name before next loop
983 // Functions must be sorted by name before next loop
974 sortFunctions();
984 sortFunctions();
975
985
976 QString currentName;
986 QString currentName;
977 bool hasVirtuals = false;
987 bool hasVirtuals = false;
978 AbstractMetaFunctionList final_functions;
988 AbstractMetaFunctionList final_functions;
979 foreach (AbstractMetaFunction *f, m_functions) {
989 foreach (AbstractMetaFunction *f, m_functions) {
980 f->setOwnerClass(this);
990 f->setOwnerClass(this);
981
991
982 m_has_virtual_slots |= f->isVirtualSlot();
992 m_has_virtual_slots |= f->isVirtualSlot();
983 m_has_virtuals |= !f->isFinal() || f->isVirtualSlot();
993 m_has_virtuals |= !f->isFinal() || f->isVirtualSlot();
984 m_has_nonpublic |= !f->isPublic();
994 m_has_nonpublic |= !f->isPublic();
985
995
986 // If we have non-virtual overloads of a virtual function, we have to implement
996 // If we have non-virtual overloads of a virtual function, we have to implement
987 // all the overloads in the shell class to override the hiding rule
997 // all the overloads in the shell class to override the hiding rule
988 if (currentName == f->name()) {
998 if (currentName == f->name()) {
989 hasVirtuals = hasVirtuals || !f->isFinal();
999 hasVirtuals = hasVirtuals || !f->isFinal();
990 if (f->isFinal())
1000 if (f->isFinal())
991 final_functions += f;
1001 final_functions += f;
992 } else {
1002 } else {
993 if (hasVirtuals && final_functions.size() > 0) {
1003 if (hasVirtuals && final_functions.size() > 0) {
994 foreach (AbstractMetaFunction *final_function, final_functions) {
1004 foreach (AbstractMetaFunction *final_function, final_functions) {
995 *final_function += AbstractMetaAttributes::ForceShellImplementation;
1005 *final_function += AbstractMetaAttributes::ForceShellImplementation;
996
1006
997 QString warn = QString("hiding of function '%1' in class '%2'")
1007 QString warn = QString("hiding of function '%1' in class '%2'")
998 .arg(final_function->name()).arg(name());
1008 .arg(final_function->name()).arg(name());
999 ReportHandler::warning(warn);
1009 ReportHandler::warning(warn);
1000 }
1010 }
1001 }
1011 }
1002
1012
1003 hasVirtuals = !f->isFinal();
1013 hasVirtuals = !f->isFinal();
1004 final_functions.clear();
1014 final_functions.clear();
1005 if (f->isFinal())
1015 if (f->isFinal())
1006 final_functions += f;
1016 final_functions += f;
1007 currentName = f->name();
1017 currentName = f->name();
1008 }
1018 }
1009 }
1019 }
1010
1020
1011 #ifndef QT_NO_DEBUG
1021 #ifndef QT_NO_DEBUG
1012 bool duplicate_function = false;
1022 bool duplicate_function = false;
1013 for (int j=0; j<m_functions.size(); ++j) {
1023 for (int j=0; j<m_functions.size(); ++j) {
1014 FunctionModificationList mods = m_functions.at(j)->modifications(m_functions.at(j)->implementingClass());
1024 FunctionModificationList mods = m_functions.at(j)->modifications(m_functions.at(j)->implementingClass());
1015
1025
1016 bool removed = false;
1026 bool removed = false;
1017 foreach (const FunctionModification &mod, mods) {
1027 foreach (const FunctionModification &mod, mods) {
1018 if (mod.isRemoveModifier()) {
1028 if (mod.isRemoveModifier()) {
1019 removed = true;
1029 removed = true;
1020 break ;
1030 break ;
1021 }
1031 }
1022 }
1032 }
1023 if (removed)
1033 if (removed)
1024 continue ;
1034 continue ;
1025
1035
1026 for (int i=0; i<m_functions.size() - 1; ++i) {
1036 for (int i=0; i<m_functions.size() - 1; ++i) {
1027 if (j == i)
1037 if (j == i)
1028 continue;
1038 continue;
1029
1039
1030 mods = m_functions.at(i)->modifications(m_functions.at(i)->implementingClass());
1040 mods = m_functions.at(i)->modifications(m_functions.at(i)->implementingClass());
1031 bool removed = false;
1041 bool removed = false;
1032 foreach (const FunctionModification &mod, mods) {
1042 foreach (const FunctionModification &mod, mods) {
1033 if (mod.isRemoveModifier()) {
1043 if (mod.isRemoveModifier()) {
1034 removed = true;
1044 removed = true;
1035 break ;
1045 break ;
1036 }
1046 }
1037 }
1047 }
1038 if (removed)
1048 if (removed)
1039 continue ;
1049 continue ;
1040
1050
1041 uint cmp = m_functions.at(i)->compareTo(m_functions.at(j));
1051 uint cmp = m_functions.at(i)->compareTo(m_functions.at(j));
1042 if ((cmp & AbstractMetaFunction::EqualName) && (cmp & AbstractMetaFunction::EqualArguments)) {
1052 if ((cmp & AbstractMetaFunction::EqualName) && (cmp & AbstractMetaFunction::EqualArguments)) {
1043 printf("%s.%s mostly equal to %s.%s\n",
1053 printf("%s.%s mostly equal to %s.%s\n",
1044 qPrintable(m_functions.at(i)->implementingClass()->typeEntry()->qualifiedCppName()),
1054 qPrintable(m_functions.at(i)->implementingClass()->typeEntry()->qualifiedCppName()),
1045 qPrintable(m_functions.at(i)->signature()),
1055 qPrintable(m_functions.at(i)->signature()),
1046 qPrintable(m_functions.at(j)->implementingClass()->typeEntry()->qualifiedCppName()),
1056 qPrintable(m_functions.at(j)->implementingClass()->typeEntry()->qualifiedCppName()),
1047 qPrintable(m_functions.at(j)->signature()));
1057 qPrintable(m_functions.at(j)->signature()));
1048 duplicate_function = true;
1058 duplicate_function = true;
1049 }
1059 }
1050 }
1060 }
1051 }
1061 }
1052 //Q_ASSERT(!duplicate_function);
1062 //Q_ASSERT(!duplicate_function);
1053 #endif
1063 #endif
1054 }
1064 }
1055
1065
1056 bool AbstractMetaClass::hasFieldAccessors() const
1066 bool AbstractMetaClass::hasFieldAccessors() const
1057 {
1067 {
1058 foreach (const AbstractMetaField *field, fields()) {
1068 foreach (const AbstractMetaField *field, fields()) {
1059 if (field->getter() || field->setter())
1069 if (field->getter() || field->setter())
1060 return true;
1070 return true;
1061 }
1071 }
1062
1072
1063 return false;
1073 return false;
1064 }
1074 }
1065
1075
1066 bool AbstractMetaClass::hasDefaultToStringFunction() const
1076 bool AbstractMetaClass::hasDefaultToStringFunction() const
1067 {
1077 {
1068 foreach (AbstractMetaFunction *f, queryFunctionsByName("toString")) {
1078 foreach (AbstractMetaFunction *f, queryFunctionsByName("toString")) {
1069 if (f->actualMinimumArgumentCount() == 0) {
1079 if (f->actualMinimumArgumentCount() == 0) {
1070 return true;
1080 return true;
1071 }
1081 }
1072
1082
1073 }
1083 }
1074 return false;
1084 return false;
1075 }
1085 }
1076
1086
1077 void AbstractMetaClass::addFunction(AbstractMetaFunction *function)
1087 void AbstractMetaClass::addFunction(AbstractMetaFunction *function)
1078 {
1088 {
1079 function->setOwnerClass(this);
1089 function->setOwnerClass(this);
1080
1090
1081 if (!function->isDestructor()) {
1091 if (!function->isDestructor()) {
1082 m_functions << function;
1092 m_functions << function;
1083 qSort(m_functions.begin(), m_functions.end(), function_sorter);
1093 qSort(m_functions.begin(), m_functions.end(), function_sorter);
1084 }
1094 }
1085
1095
1086
1096
1087 m_has_virtual_slots |= function->isVirtualSlot();
1097 m_has_virtual_slots |= function->isVirtualSlot();
1088 m_has_virtuals |= !function->isFinal() || function->isVirtualSlot();
1098 m_has_virtuals |= !function->isFinal() || function->isVirtualSlot();
1089 m_has_nonpublic |= !function->isPublic();
1099 m_has_nonpublic |= !function->isPublic();
1090 }
1100 }
1091
1101
1092 bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const
1102 bool AbstractMetaClass::hasSignal(const AbstractMetaFunction *other) const
1093 {
1103 {
1094 if (!other->isSignal())
1104 if (!other->isSignal())
1095 return false;
1105 return false;
1096
1106
1097 foreach (const AbstractMetaFunction *f, functions()) {
1107 foreach (const AbstractMetaFunction *f, functions()) {
1098 if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName)
1108 if (f->isSignal() && f->compareTo(other) & AbstractMetaFunction::EqualName)
1099 return other->modifiedName() == f->modifiedName();
1109 return other->modifiedName() == f->modifiedName();
1100 }
1110 }
1101
1111
1102 return false;
1112 return false;
1103 }
1113 }
1104
1114
1105
1115
1106 QString AbstractMetaClass::name() const
1116 QString AbstractMetaClass::name() const
1107 {
1117 {
1108 return QString(m_type_entry->targetLangName()).replace("::", "_");
1118 return QString(m_type_entry->targetLangName()).replace("::", "_");
1109 }
1119 }
1110
1120
1111 bool AbstractMetaClass::hasFunction(const QString &str) const
1121 bool AbstractMetaClass::hasFunction(const QString &str) const
1112 {
1122 {
1113 foreach (const AbstractMetaFunction *f, functions())
1123 foreach (const AbstractMetaFunction *f, functions())
1114 if (f->name() == str)
1124 if (f->name() == str)
1115 return true;
1125 return true;
1116 return false;
1126 return false;
1117 }
1127 }
1118
1128
1119 /* Returns true if this class has one or more functions that are
1129 /* Returns true if this class has one or more functions that are
1120 protected. If a class has protected members we need to generate a
1130 protected. If a class has protected members we need to generate a
1121 shell class with public accessors to the protected functions, so
1131 shell class with public accessors to the protected functions, so
1122 they can be called from the native functions.
1132 they can be called from the native functions.
1123 */
1133 */
1124 bool AbstractMetaClass::hasProtectedFunctions() const {
1134 bool AbstractMetaClass::hasProtectedFunctions() const {
1125 foreach (AbstractMetaFunction *func, m_functions) {
1135 foreach (AbstractMetaFunction *func, m_functions) {
1126 if (func->isProtected())
1136 if (func->isProtected())
1127 return true;
1137 return true;
1128 }
1138 }
1129 return false;
1139 return false;
1130 }
1140 }
1131
1141
1132 bool AbstractMetaClass::generateShellClass() const
1142 bool AbstractMetaClass::generateShellClass() const
1133 {
1143 {
1134 return m_force_shell_class ||
1144 return m_force_shell_class ||
1135 (!isFinal()
1145 (!isFinal()
1136 && (hasVirtualFunctions()
1146 && (hasVirtualFunctions()
1137 || hasProtectedFunctions()
1147 || hasProtectedFunctions()
1138 || hasFieldAccessors()));
1148 || hasFieldAccessors()));
1139 }
1149 }
1140
1150
1141 QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const
1151 QPropertySpec *AbstractMetaClass::propertySpecForRead(const QString &name) const
1142 {
1152 {
1143 for (int i=0; i<m_property_specs.size(); ++i)
1153 for (int i=0; i<m_property_specs.size(); ++i)
1144 if (name == m_property_specs.at(i)->read())
1154 if (name == m_property_specs.at(i)->read())
1145 return m_property_specs.at(i);
1155 return m_property_specs.at(i);
1146 return 0;
1156 return 0;
1147 }
1157 }
1148
1158
1149 QPropertySpec *AbstractMetaClass::propertySpecForWrite(const QString &name) const
1159 QPropertySpec *AbstractMetaClass::propertySpecForWrite(const QString &name) const
1150 {
1160 {
1151 for (int i=0; i<m_property_specs.size(); ++i)
1161 for (int i=0; i<m_property_specs.size(); ++i)
1152 if (name == m_property_specs.at(i)->write())
1162 if (name == m_property_specs.at(i)->write())
1153 return m_property_specs.at(i);
1163 return m_property_specs.at(i);
1154 return 0;
1164 return 0;
1155 }
1165 }
1156
1166
1157 QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) const
1167 QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) const
1158 {
1168 {
1159 for (int i=0; i<m_property_specs.size(); ++i) {
1169 for (int i=0; i<m_property_specs.size(); ++i) {
1160 if (name == m_property_specs.at(i)->reset())
1170 if (name == m_property_specs.at(i)->reset())
1161 return m_property_specs.at(i);
1171 return m_property_specs.at(i);
1162 }
1172 }
1163 return 0;
1173 return 0;
1164 }
1174 }
1165
1175
1166
1176
1167
1177
1168 static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func)
1178 static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func)
1169 {
1179 {
1170 foreach (const AbstractMetaFunction *f, l) {
1180 foreach (const AbstractMetaFunction *f, l) {
1171 if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar)
1181 if ((f->compareTo(func) & AbstractMetaFunction::PrettySimilar) == AbstractMetaFunction::PrettySimilar)
1172 return true;
1182 return true;
1173 }
1183 }
1174 return false;
1184 return false;
1175 }
1185 }
1176
1186
1177 AbstractMetaField::AbstractMetaField() : m_getter(0), m_setter(0), m_class(0)
1187 AbstractMetaField::AbstractMetaField() : m_getter(0), m_setter(0), m_class(0)
1178 {
1188 {
1179 }
1189 }
1180
1190
1181 AbstractMetaField::~AbstractMetaField()
1191 AbstractMetaField::~AbstractMetaField()
1182 {
1192 {
1183 delete m_setter;
1193 delete m_setter;
1184 delete m_getter;
1194 delete m_getter;
1185 }
1195 }
1186 ushort painters; // refcount
1196 ushort painters; // refcount
1187 AbstractMetaField *AbstractMetaField::copy() const
1197 AbstractMetaField *AbstractMetaField::copy() const
1188 {
1198 {
1189 AbstractMetaField *returned = new AbstractMetaField;
1199 AbstractMetaField *returned = new AbstractMetaField;
1190 returned->setEnclosingClass(0);
1200 returned->setEnclosingClass(0);
1191 returned->setAttributes(attributes());
1201 returned->setAttributes(attributes());
1192 returned->setName(name());
1202 returned->setName(name());
1193 returned->setType(type()->copy());
1203 returned->setType(type()->copy());
1194 returned->setOriginalAttributes(originalAttributes());
1204 returned->setOriginalAttributes(originalAttributes());
1195
1205
1196 return returned;
1206 return returned;
1197 }
1207 }
1198
1208
1199 static QString upCaseFirst(const QString &str) {
1209 static QString upCaseFirst(const QString &str) {
1200 Q_ASSERT(!str.isEmpty());
1210 Q_ASSERT(!str.isEmpty());
1201 QString s = str;
1211 QString s = str;
1202 s[0] = s.at(0).toUpper();
1212 s[0] = s.at(0).toUpper();
1203 return s;
1213 return s;
1204 }
1214 }
1205
1215
1206 static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name, uint type) {
1216 static AbstractMetaFunction *createXetter(const AbstractMetaField *g, const QString &name, uint type) {
1207 AbstractMetaFunction *f = new AbstractMetaFunction;
1217 AbstractMetaFunction *f = new AbstractMetaFunction;
1208
1218
1209
1219
1210
1220
1211 f->setName(name);
1221 f->setName(name);
1212 f->setOriginalName(name);
1222 f->setOriginalName(name);
1213 f->setOwnerClass(g->enclosingClass());
1223 f->setOwnerClass(g->enclosingClass());
1214 f->setImplementingClass(g->enclosingClass());
1224 f->setImplementingClass(g->enclosingClass());
1215 f->setDeclaringClass(g->enclosingClass());
1225 f->setDeclaringClass(g->enclosingClass());
1216
1226
1217 uint attr = AbstractMetaAttributes::Native
1227 uint attr = AbstractMetaAttributes::Native
1218 | AbstractMetaAttributes::Final
1228 | AbstractMetaAttributes::Final
1219 | type;
1229 | type;
1220 if (g->isStatic())
1230 if (g->isStatic())
1221 attr |= AbstractMetaAttributes::Static;
1231 attr |= AbstractMetaAttributes::Static;
1222 if (g->isPublic())
1232 if (g->isPublic())
1223 attr |= AbstractMetaAttributes::Public;
1233 attr |= AbstractMetaAttributes::Public;
1224 else if (g->isProtected())
1234 else if (g->isProtected())
1225 attr |= AbstractMetaAttributes::Protected;
1235 attr |= AbstractMetaAttributes::Protected;
1226 else
1236 else
1227 attr |= AbstractMetaAttributes::Private;
1237 attr |= AbstractMetaAttributes::Private;
1228 f->setAttributes(attr);
1238 f->setAttributes(attr);
1229 f->setOriginalAttributes(attr);
1239 f->setOriginalAttributes(attr);
1230
1240
1231 FieldModificationList mods = g->modifications();
1241 FieldModificationList mods = g->modifications();
1232 foreach (FieldModification mod, mods) {
1242 foreach (FieldModification mod, mods) {
1233 if (mod.isRenameModifier())
1243 if (mod.isRenameModifier())
1234 f->setName(mod.renamedTo());
1244 f->setName(mod.renamedTo());
1235 if (mod.isAccessModifier()) {
1245 if (mod.isAccessModifier()) {
1236 if (mod.isPrivate())
1246 if (mod.isPrivate())
1237 f->setVisibility(AbstractMetaAttributes::Private);
1247 f->setVisibility(AbstractMetaAttributes::Private);
1238 else if (mod.isProtected())
1248 else if (mod.isProtected())
1239 f->setVisibility(AbstractMetaAttributes::Protected);
1249 f->setVisibility(AbstractMetaAttributes::Protected);
1240 else if (mod.isPublic())
1250 else if (mod.isPublic())
1241 f->setVisibility(AbstractMetaAttributes::Public);
1251 f->setVisibility(AbstractMetaAttributes::Public);
1242 else if (mod.isFriendly())
1252 else if (mod.isFriendly())
1243 f->setVisibility(AbstractMetaAttributes::Friendly);
1253 f->setVisibility(AbstractMetaAttributes::Friendly);
1244 }
1254 }
1245
1255
1246 }
1256 }
1247 return f;
1257 return f;
1248 }
1258 }
1249
1259
1250 FieldModificationList AbstractMetaField::modifications() const
1260 FieldModificationList AbstractMetaField::modifications() const
1251 {
1261 {
1252 FieldModificationList mods = enclosingClass()->typeEntry()->fieldModifications();
1262 FieldModificationList mods = enclosingClass()->typeEntry()->fieldModifications();
1253 FieldModificationList returned;
1263 FieldModificationList returned;
1254
1264
1255 foreach (FieldModification mod, mods) {
1265 foreach (FieldModification mod, mods) {
1256 if (mod.name == name())
1266 if (mod.name == name())
1257 returned += mod;
1267 returned += mod;
1258 }
1268 }
1259
1269
1260 return returned;
1270 return returned;
1261 }
1271 }
1262
1272
1263 const AbstractMetaFunction *AbstractMetaField::setter() const
1273 const AbstractMetaFunction *AbstractMetaField::setter() const
1264 {
1274 {
1265 if (m_setter == 0) {
1275 if (m_setter == 0) {
1266 m_setter = createXetter(this,
1276 m_setter = createXetter(this,
1267 name(),
1277 name(),
1268 AbstractMetaAttributes::SetterFunction);
1278 AbstractMetaAttributes::SetterFunction);
1269 AbstractMetaArgumentList arguments;
1279 AbstractMetaArgumentList arguments;
1270 AbstractMetaArgument *argument = new AbstractMetaArgument;
1280 AbstractMetaArgument *argument = new AbstractMetaArgument;
1271 argument->setType(type()->copy());
1281 argument->setType(type()->copy());
1272 argument->setName(name());
1282 argument->setName(name());
1273 arguments.append(argument);
1283 arguments.append(argument);
1274 m_setter->setArguments(arguments);
1284 m_setter->setArguments(arguments);
1275 }
1285 }
1276 return m_setter;
1286 return m_setter;
1277 }
1287 }
1278
1288
1279 const AbstractMetaFunction *AbstractMetaField::getter() const
1289 const AbstractMetaFunction *AbstractMetaField::getter() const
1280 {
1290 {
1281 if (m_getter == 0) {
1291 if (m_getter == 0) {
1282 m_getter = createXetter(this,
1292 m_getter = createXetter(this,
1283 name(),
1293 name(),
1284 AbstractMetaAttributes::GetterFunction);
1294 AbstractMetaAttributes::GetterFunction);
1285 m_getter->setType(type());
1295 m_getter->setType(type());
1286 }
1296 }
1287
1297
1288 return m_getter;
1298 return m_getter;
1289 }
1299 }
1290
1300
1291
1301
1292 bool AbstractMetaClass::hasConstructors() const
1302 bool AbstractMetaClass::hasConstructors() const
1293 {
1303 {
1294 return queryFunctions(Constructors).size() != 0;
1304 return queryFunctions(Constructors).size() != 0;
1295 }
1305 }
1296
1306
1297 void AbstractMetaClass::addDefaultConstructor()
1307 void AbstractMetaClass::addDefaultConstructor()
1298 {
1308 {
1299 AbstractMetaFunction *f = new AbstractMetaFunction;
1309 AbstractMetaFunction *f = new AbstractMetaFunction;
1300 f->setName(name());
1310 f->setName(name());
1301 f->setOwnerClass(this);
1311 f->setOwnerClass(this);
1302 f->setFunctionType(AbstractMetaFunction::ConstructorFunction);
1312 f->setFunctionType(AbstractMetaFunction::ConstructorFunction);
1303 f->setArguments(AbstractMetaArgumentList());
1313 f->setArguments(AbstractMetaArgumentList());
1304 f->setDeclaringClass(this);
1314 f->setDeclaringClass(this);
1305
1315
1306 uint attr = AbstractMetaAttributes::Native;
1316 uint attr = AbstractMetaAttributes::Native;
1307 attr |= AbstractMetaAttributes::Public;
1317 attr |= AbstractMetaAttributes::Public;
1308 f->setAttributes(attr);
1318 f->setAttributes(attr);
1309 f->setImplementingClass(this);
1319 f->setImplementingClass(this);
1310 f->setOriginalAttributes(f->attributes());
1320 f->setOriginalAttributes(f->attributes());
1311
1321
1312 addFunction(f);
1322 addFunction(f);
1313 }
1323 }
1314
1324
1315 bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const
1325 bool AbstractMetaClass::hasFunction(const AbstractMetaFunction *f) const
1316 {
1326 {
1317 return functions_contains(m_functions, f);
1327 return functions_contains(m_functions, f);
1318 }
1328 }
1319
1329
1320 /* Goes through the list of functions and returns a list of all
1330 /* Goes through the list of functions and returns a list of all
1321 functions matching all of the criteria in \a query.
1331 functions matching all of the criteria in \a query.
1322 */
1332 */
1323
1333
1324 AbstractMetaFunctionList AbstractMetaClass::queryFunctions(uint query) const
1334 AbstractMetaFunctionList AbstractMetaClass::queryFunctions(uint query) const
1325 {
1335 {
1326 AbstractMetaFunctionList functions;
1336 AbstractMetaFunctionList functions;
1327
1337
1328 foreach (AbstractMetaFunction *f, m_functions) {
1338 foreach (AbstractMetaFunction *f, m_functions) {
1329
1339
1330 if ((query & VirtualSlots) && !f->isVirtualSlot())
1340 if ((query & VirtualSlots) && !f->isVirtualSlot())
1331 continue;
1341 continue;
1332
1342
1333 if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) {
1343 if ((query & NotRemovedFromTargetLang) && f->isRemovedFrom(f->implementingClass(), TypeSystem::TargetLangCode)) {
1334 continue;
1344 continue;
1335 }
1345 }
1336
1346
1337 if ((query & NotRemovedFromTargetLang) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) {
1347 if ((query & NotRemovedFromTargetLang) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::TargetLangCode)) {
1338 continue;
1348 continue;
1339 }
1349 }
1340
1350
1341 if ((query & NotRemovedFromShell) && f->isRemovedFrom(f->implementingClass(), TypeSystem::ShellCode)) {
1351 if ((query & NotRemovedFromShell) && f->isRemovedFrom(f->implementingClass(), TypeSystem::ShellCode)) {
1342 continue;
1352 continue;
1343 }
1353 }
1344
1354
1345 if ((query & NotRemovedFromShell) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::ShellCode)) {
1355 if ((query & NotRemovedFromShell) && !f->isFinal() && f->isRemovedFrom(f->declaringClass(), TypeSystem::ShellCode)) {
1346 continue;
1356 continue;
1347 }
1357 }
1348
1358
1349 if ((query & Visible) && f->isPrivate()) {
1359 if ((query & Visible) && f->isPrivate()) {
1350 continue;
1360 continue;
1351 }
1361 }
1352
1362
1353 if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) {
1363 if ((query & VirtualInTargetLangFunctions) && f->isFinalInTargetLang()) {
1354 continue;
1364 continue;
1355 }
1365 }
1356
1366
1357 if ((query & Invisible) && !f->isPrivate()) {
1367 if ((query & Invisible) && !f->isPrivate()) {
1358 continue;
1368 continue;
1359 }
1369 }
1360
1370
1361 if ((query & Empty) && !f->isEmptyFunction()) {
1371 if ((query & Empty) && !f->isEmptyFunction()) {
1362 continue;
1372 continue;
1363 }
1373 }
1364
1374
1365 if ((query & WasPublic) && !f->wasPublic()) {
1375 if ((query & WasPublic) && !f->wasPublic()) {
1366 continue;
1376 continue;
1367 }
1377 }
1368
1378
1369 if ((query & WasVisible) && f->wasPrivate()) {
1379 if ((query & WasVisible) && f->wasPrivate()) {
1370 continue;
1380 continue;
1371 }
1381 }
1372
1382
1373 if ((query & WasProtected) && !f->wasProtected()) {
1383 if ((query & WasProtected) && !f->wasProtected()) {
1374 continue;
1384 continue;
1375 }
1385 }
1376
1386
1377 if ((query & ClassImplements) && f->ownerClass() != f->implementingClass()) {
1387 if ((query & ClassImplements) && f->ownerClass() != f->implementingClass()) {
1378 continue;
1388 continue;
1379 }
1389 }
1380
1390
1381 if ((query & Inconsistent) && (f->isFinalInTargetLang() || !f->isFinalInCpp() || f->isStatic())) {
1391 if ((query & Inconsistent) && (f->isFinalInTargetLang() || !f->isFinalInCpp() || f->isStatic())) {
1382 continue;
1392 continue;
1383 }
1393 }
1384
1394
1385 if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) {
1395 if ((query & FinalInTargetLangFunctions) && !f->isFinalInTargetLang()) {
1386 continue;
1396 continue;
1387 }
1397 }
1388
1398
1389 if ((query & FinalInCppFunctions) && !f->isFinalInCpp()) {
1399 if ((query & FinalInCppFunctions) && !f->isFinalInCpp()) {
1390 continue;
1400 continue;
1391 }
1401 }
1392
1402
1393 if ((query & VirtualInCppFunctions) && f->isFinalInCpp()) {
1403 if ((query & VirtualInCppFunctions) && f->isFinalInCpp()) {
1394 continue;
1404 continue;
1395 }
1405 }
1396
1406
1397 if ((query & Signals) && (!f->isSignal())) {
1407 if ((query & Signals) && (!f->isSignal())) {
1398 continue;
1408 continue;
1399 }
1409 }
1400
1410
1401 if ((query & ForcedShellFunctions)
1411 if ((query & ForcedShellFunctions)
1402 && (!f->isForcedShellImplementation()
1412 && (!f->isForcedShellImplementation()
1403 || !f->isFinal())) {
1413 || !f->isFinal())) {
1404 continue;
1414 continue;
1405 }
1415 }
1406
1416
1407 if (((query & Constructors) && (!f->isConstructor()
1417 if (((query & Constructors) && (!f->isConstructor()
1408 || f->ownerClass() != f->implementingClass()))
1418 || f->ownerClass() != f->implementingClass()))
1409 || (f->isConstructor() && (query & Constructors) == 0)) {
1419 || (f->isConstructor() && (query & Constructors) == 0)) {
1410 continue;
1420 continue;
1411 }
1421 }
1412
1422
1413 // Destructors are never included in the functions of a class currently
1423 // Destructors are never included in the functions of a class currently
1414 /*
1424 /*
1415 if ((query & Destructors) && (!f->isDestructor()
1425 if ((query & Destructors) && (!f->isDestructor()
1416 || f->ownerClass() != f->implementingClass())
1426 || f->ownerClass() != f->implementingClass())
1417 || f->isDestructor() && (query & Destructors) == 0) {
1427 || f->isDestructor() && (query & Destructors) == 0) {
1418 continue;
1428 continue;
1419 }*/
1429 }*/
1420
1430
1421 if ((query & VirtualFunctions) && (f->isFinal() || f->isSignal() || f->isStatic())) {
1431 if ((query & VirtualFunctions) && (f->isFinal() || f->isSignal() || f->isStatic())) {
1422 continue;
1432 continue;
1423 }
1433 }
1424
1434
1425 if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal())) {
1435 if ((query & StaticFunctions) && (!f->isStatic() || f->isSignal())) {
1426 continue;
1436 continue;
1427 }
1437 }
1428
1438
1429 if ((query & NonStaticFunctions) && (f->isStatic())) {
1439 if ((query & NonStaticFunctions) && (f->isStatic())) {
1430 continue;
1440 continue;
1431 }
1441 }
1432
1442
1433 if ((query & NonEmptyFunctions) && (f->isEmptyFunction())) {
1443 if ((query & NonEmptyFunctions) && (f->isEmptyFunction())) {
1434 continue;
1444 continue;
1435 }
1445 }
1436
1446
1437 if ((query & NormalFunctions) && (f->isSignal())) {
1447 if ((query & NormalFunctions) && (f->isSignal())) {
1438 continue;
1448 continue;
1439 }
1449 }
1440
1450
1441 if ((query & AbstractFunctions) && !f->isAbstract()) {
1451 if ((query & AbstractFunctions) && !f->isAbstract()) {
1442 continue;
1452 continue;
1443 }
1453 }
1444
1454
1445 functions << f;
1455 functions << f;
1446 }
1456 }
1447
1457
1448 // qDebug() << "queried" << m_type_entry->qualifiedCppName() << "got" << functions.size() << "out of" << m_functions.size();
1458 // qDebug() << "queried" << m_type_entry->qualifiedCppName() << "got" << functions.size() << "out of" << m_functions.size();
1449
1459
1450 return functions;
1460 return functions;
1451 }
1461 }
1452
1462
1453
1463
1454 bool AbstractMetaClass::hasInconsistentFunctions() const
1464 bool AbstractMetaClass::hasInconsistentFunctions() const
1455 {
1465 {
1456 return cppInconsistentFunctions().size() > 0;
1466 return cppInconsistentFunctions().size() > 0;
1457 }
1467 }
1458
1468
1459 bool AbstractMetaClass::hasSignals() const
1469 bool AbstractMetaClass::hasSignals() const
1460 {
1470 {
1461 return cppSignalFunctions().size() > 0;
1471 return cppSignalFunctions().size() > 0;
1462 }
1472 }
1463
1473
1464
1474
1465 /**
1475 /**
1466 * Adds the specified interface to this class by adding all the
1476 * Adds the specified interface to this class by adding all the
1467 * functions in the interface to this class.
1477 * functions in the interface to this class.
1468 */
1478 */
1469 void AbstractMetaClass::addInterface(AbstractMetaClass *interface)
1479 void AbstractMetaClass::addInterface(AbstractMetaClass *interface)
1470 {
1480 {
1471 Q_ASSERT(!m_interfaces.contains(interface));
1481 Q_ASSERT(!m_interfaces.contains(interface));
1472 m_interfaces << interface;
1482 m_interfaces << interface;
1473
1483
1474 if (m_extracted_interface != 0 && m_extracted_interface != interface)
1484 if (m_extracted_interface != 0 && m_extracted_interface != interface)
1475 m_extracted_interface->addInterface(interface);
1485 m_extracted_interface->addInterface(interface);
1476
1486
1477 foreach (AbstractMetaFunction *function, interface->functions())
1487 foreach (AbstractMetaFunction *function, interface->functions())
1478 if (!hasFunction(function) && !function->isConstructor()) {
1488 if (!hasFunction(function) && !function->isConstructor()) {
1479 AbstractMetaFunction *cpy = function->copy();
1489 AbstractMetaFunction *cpy = function->copy();
1480 // We do not want this in PythonQt:
1490 // We do not want this in PythonQt:
1481 //cpy->setImplementingClass(this);
1491 //cpy->setImplementingClass(this);
1482
1492
1483 // Setup that this function is an interface class.
1493 // Setup that this function is an interface class.
1484 cpy->setInterfaceClass(interface);
1494 cpy->setInterfaceClass(interface);
1485 *cpy += AbstractMetaAttributes::InterfaceFunction;
1495 *cpy += AbstractMetaAttributes::InterfaceFunction;
1486
1496
1487 // Copy the modifications in interface into the implementing classes.
1497 // Copy the modifications in interface into the implementing classes.
1488 FunctionModificationList mods = function->modifications(interface);
1498 FunctionModificationList mods = function->modifications(interface);
1489 foreach (const FunctionModification &mod, mods) {
1499 foreach (const FunctionModification &mod, mods) {
1490 m_type_entry->addFunctionModification(mod);
1500 m_type_entry->addFunctionModification(mod);
1491 }
1501 }
1492
1502
1493 // It should be mostly safe to assume that when we implement an interface
1503 // It should be mostly safe to assume that when we implement an interface
1494 // we don't "pass on" pure virtual functions to our sublcasses...
1504 // we don't "pass on" pure virtual functions to our sublcasses...
1495 // *cpy -= AbstractMetaAttributes::Abstract;
1505 // *cpy -= AbstractMetaAttributes::Abstract;
1496
1506
1497 addFunction(cpy);
1507 addFunction(cpy);
1498 }
1508 }
1499 }
1509 }
1500
1510
1501
1511
1502 void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces)
1512 void AbstractMetaClass::setInterfaces(const AbstractMetaClassList &interfaces)
1503 {
1513 {
1504 m_interfaces = interfaces;
1514 m_interfaces = interfaces;
1505 }
1515 }
1506
1516
1507
1517
1508 AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName)
1518 AbstractMetaEnum *AbstractMetaClass::findEnum(const QString &enumName)
1509 {
1519 {
1510 foreach (AbstractMetaEnum *e, m_enums) {
1520 foreach (AbstractMetaEnum *e, m_enums) {
1511 if (e->name() == enumName)
1521 if (e->name() == enumName)
1512 return e;
1522 return e;
1513 }
1523 }
1514
1524
1515 if (typeEntry()->designatedInterface())
1525 if (typeEntry()->designatedInterface())
1516 return extractInterface()->findEnum(enumName);
1526 return extractInterface()->findEnum(enumName);
1517
1527
1518 return 0;
1528 return 0;
1519 }
1529 }
1520
1530
1521
1531
1522
1532
1523
1533
1524 /*! Recursivly searches for the enum value named \a enumValueName in
1534 /*! Recursivly searches for the enum value named \a enumValueName in
1525 this class and its superclasses and interfaces. Values belonging to
1535 this class and its superclasses and interfaces. Values belonging to
1526 \a meta_enum are excluded from the search.
1536 \a meta_enum are excluded from the search.
1527 */
1537 */
1528 AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName, AbstractMetaEnum *meta_enum)
1538 AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValueName, AbstractMetaEnum *meta_enum)
1529 {
1539 {
1530 foreach (AbstractMetaEnum *e, m_enums) {
1540 foreach (AbstractMetaEnum *e, m_enums) {
1531 if (e == meta_enum)
1541 if (e == meta_enum)
1532 continue;
1542 continue;
1533 foreach (AbstractMetaEnumValue *v, e->values()) {
1543 foreach (AbstractMetaEnumValue *v, e->values()) {
1534 if (v->name() == enumValueName)
1544 if (v->name() == enumValueName)
1535 return v;
1545 return v;
1536 }
1546 }
1537 }
1547 }
1538
1548
1539 if (typeEntry()->designatedInterface())
1549 if (typeEntry()->designatedInterface())
1540 return extractInterface()->findEnumValue(enumValueName, meta_enum);
1550 return extractInterface()->findEnumValue(enumValueName, meta_enum);
1541
1551
1542 if (baseClass() != 0)
1552 if (baseClass() != 0)
1543 return baseClass()->findEnumValue(enumValueName, meta_enum);
1553 return baseClass()->findEnumValue(enumValueName, meta_enum);
1544
1554
1545 return 0;
1555 return 0;
1546 }
1556 }
1547
1557
1548
1558
1549 /*!
1559 /*!
1550 * Searches through all of this class' enums for a value matching the
1560 * Searches through all of this class' enums for a value matching the
1551 * name \a enumValueName. The name is excluding the class/namespace
1561 * name \a enumValueName. The name is excluding the class/namespace
1552 * prefix. The function recursivly searches interfaces and baseclasses
1562 * prefix. The function recursivly searches interfaces and baseclasses
1553 * of this class.
1563 * of this class.
1554 */
1564 */
1555 AbstractMetaEnum *AbstractMetaClass::findEnumForValue(const QString &enumValueName)
1565 AbstractMetaEnum *AbstractMetaClass::findEnumForValue(const QString &enumValueName)
1556 {
1566 {
1557 foreach (AbstractMetaEnum *e, m_enums) {
1567 foreach (AbstractMetaEnum *e, m_enums) {
1558 foreach (AbstractMetaEnumValue *v, e->values()) {
1568 foreach (AbstractMetaEnumValue *v, e->values()) {
1559 if (v->name() == enumValueName)
1569 if (v->name() == enumValueName)
1560 return e;
1570 return e;
1561 }
1571 }
1562 }
1572 }
1563
1573
1564 if (typeEntry()->designatedInterface())
1574 if (typeEntry()->designatedInterface())
1565 return extractInterface()->findEnumForValue(enumValueName);
1575 return extractInterface()->findEnumForValue(enumValueName);
1566
1576
1567 if (baseClass() != 0)
1577 if (baseClass() != 0)
1568 return baseClass()->findEnumForValue(enumValueName);
1578 return baseClass()->findEnumForValue(enumValueName);
1569
1579
1570 return 0;
1580 return 0;
1571 }
1581 }
1572
1582
1573
1583
1574 static void add_extra_include_for_type(AbstractMetaClass *meta_class, const AbstractMetaType *type)
1584 static void add_extra_include_for_type(AbstractMetaClass *meta_class, const AbstractMetaType *type)
1575 {
1585 {
1576
1586
1577 if (type == 0)
1587 if (type == 0)
1578 return;
1588 return;
1579
1589
1580 Q_ASSERT(meta_class != 0);
1590 Q_ASSERT(meta_class != 0);
1581 const TypeEntry *entry = (type ? type->typeEntry() : 0);
1591 const TypeEntry *entry = (type ? type->typeEntry() : 0);
1582 if (entry != 0 && entry->isComplex()) {
1592 if (entry != 0 && entry->isComplex()) {
1583 const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(entry);
1593 const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(entry);
1584 ComplexTypeEntry *class_entry = meta_class->typeEntry();
1594 ComplexTypeEntry *class_entry = meta_class->typeEntry();
1585 if (class_entry != 0 && centry->include().isValid())
1595 if (class_entry != 0 && centry->include().isValid())
1586 class_entry->addExtraInclude(centry->include());
1596 class_entry->addExtraInclude(centry->include());
1587 }
1597 }
1588
1598
1589 if (type->hasInstantiations()) {
1599 if (type->hasInstantiations()) {
1590 QList<AbstractMetaType *> instantiations = type->instantiations();
1600 QList<AbstractMetaType *> instantiations = type->instantiations();
1591 foreach (AbstractMetaType *instantiation, instantiations)
1601 foreach (AbstractMetaType *instantiation, instantiations)
1592 add_extra_include_for_type(meta_class, instantiation);
1602 add_extra_include_for_type(meta_class, instantiation);
1593 }
1603 }
1594 }
1604 }
1595
1605
1596 static void add_extra_includes_for_function(AbstractMetaClass *meta_class, const AbstractMetaFunction *meta_function)
1606 static void add_extra_includes_for_function(AbstractMetaClass *meta_class, const AbstractMetaFunction *meta_function)
1597 {
1607 {
1598 Q_ASSERT(meta_class != 0);
1608 Q_ASSERT(meta_class != 0);
1599 Q_ASSERT(meta_function != 0);
1609 Q_ASSERT(meta_function != 0);
1600 add_extra_include_for_type(meta_class, meta_function->type());
1610 add_extra_include_for_type(meta_class, meta_function->type());
1601
1611
1602 AbstractMetaArgumentList arguments = meta_function->arguments();
1612 AbstractMetaArgumentList arguments = meta_function->arguments();
1603 foreach (AbstractMetaArgument *argument, arguments)
1613 foreach (AbstractMetaArgument *argument, arguments)
1604 add_extra_include_for_type(meta_class, argument->type());
1614 add_extra_include_for_type(meta_class, argument->type());
1605 }
1615 }
1606
1616
1607 void AbstractMetaClass::fixFunctions()
1617 void AbstractMetaClass::fixFunctions()
1608 {
1618 {
1609 if (m_functions_fixed)
1619 if (m_functions_fixed)
1610 return;
1620 return;
1611 else
1621 else
1612 m_functions_fixed = true;
1622 m_functions_fixed = true;
1613
1623
1614 AbstractMetaClass *super_class = baseClass();
1624 AbstractMetaClass *super_class = baseClass();
1615 AbstractMetaFunctionList funcs = functions();
1625 AbstractMetaFunctionList funcs = functions();
1616
1626
1617 // printf("fix functions for %s\n", qPrintable(name()));
1627 // printf("fix functions for %s\n", qPrintable(name()));
1618
1628
1619 if (super_class != 0)
1629 if (super_class != 0)
1620 super_class->fixFunctions();
1630 super_class->fixFunctions();
1621 int iface_idx = 0;
1631 int iface_idx = 0;
1622 while (super_class || iface_idx < interfaces().size()) {
1632 while (super_class || iface_idx < interfaces().size()) {
1623 // printf(" - base: %s\n", qPrintable(super_class->name()));
1633 // printf(" - base: %s\n", qPrintable(super_class->name()));
1624
1634
1625 // Since we always traverse the complete hierarchy we are only
1635 // Since we always traverse the complete hierarchy we are only
1626 // interrested in what each super class implements, not what
1636 // interrested in what each super class implements, not what
1627 // we may have propagated from their base classes again.
1637 // we may have propagated from their base classes again.
1628 AbstractMetaFunctionList super_funcs;
1638 AbstractMetaFunctionList super_funcs;
1629 if (super_class) {
1639 if (super_class) {
1630
1640
1631 // Super classes can never be final
1641 // Super classes can never be final
1632 if (super_class->isFinalInTargetLang()) {
1642 if (super_class->isFinalInTargetLang()) {
1633 ReportHandler::warning("Final class '" + super_class->name() + "' set to non-final, as it is extended by other classes");
1643 ReportHandler::warning("Final class '" + super_class->name() + "' set to non-final, as it is extended by other classes");
1634 *super_class -= AbstractMetaAttributes::FinalInTargetLang;
1644 *super_class -= AbstractMetaAttributes::FinalInTargetLang;
1635 }
1645 }
1636 super_funcs = super_class->queryFunctions(AbstractMetaClass::ClassImplements);
1646 super_funcs = super_class->queryFunctions(AbstractMetaClass::ClassImplements);
1637 } else {
1647 } else {
1638 super_funcs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions);
1648 super_funcs = interfaces().at(iface_idx)->queryFunctions(AbstractMetaClass::NormalFunctions);
1639 }
1649 }
1640
1650
1641 QSet<AbstractMetaFunction *> funcs_to_add;
1651 QSet<AbstractMetaFunction *> funcs_to_add;
1642 for (int sfi=0; sfi<super_funcs.size(); ++sfi) {
1652 for (int sfi=0; sfi<super_funcs.size(); ++sfi) {
1643 AbstractMetaFunction *sf = super_funcs.at(sfi);
1653 AbstractMetaFunction *sf = super_funcs.at(sfi);
1644
1654
1645 if (sf->isRemovedFromAllLanguages(sf->implementingClass()))
1655 if (sf->isRemovedFromAllLanguages(sf->implementingClass()))
1646 continue;
1656 continue;
1647
1657
1648 // we generally don't care about private functions, but we have to get the ones that are
1658 // we generally don't care about private functions, but we have to get the ones that are
1649 // virtual in case they override abstract functions.
1659 // virtual in case they override abstract functions.
1650 bool add = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction());
1660 bool add = (sf->isNormal() || sf->isSignal() || sf->isEmptyFunction());
1651 for (int fi=0; fi<funcs.size(); ++fi) {
1661 for (int fi=0; fi<funcs.size(); ++fi) {
1652 AbstractMetaFunction *f = funcs.at(fi);
1662 AbstractMetaFunction *f = funcs.at(fi);
1653 if (f->isRemovedFromAllLanguages(f->implementingClass()))
1663 if (f->isRemovedFromAllLanguages(f->implementingClass()))
1654 continue;
1664 continue;
1655
1665
1656 uint cmp = f->compareTo(sf);
1666 uint cmp = f->compareTo(sf);
1657
1667
1658 if (cmp & AbstractMetaFunction::EqualModifiedName) {
1668 if (cmp & AbstractMetaFunction::EqualModifiedName) {
1659 // printf(" - %s::%s similar to %s::%s %x vs %x\n",
1669 // printf(" - %s::%s similar to %s::%s %x vs %x\n",
1660 // qPrintable(sf->implementingClass()->typeEntry()->qualifiedCppName()),
1670 // qPrintable(sf->implementingClass()->typeEntry()->qualifiedCppName()),
1661 // qPrintable(sf->name()),
1671 // qPrintable(sf->name()),
1662 // qPrintable(f->implementingClass()->typeEntry()->qualifiedCppName()),
1672 // qPrintable(f->implementingClass()->typeEntry()->qualifiedCppName()),
1663 // qPrintable(f->name()),
1673 // qPrintable(f->name()),
1664 // sf->attributes(),
1674 // sf->attributes(),
1665 // f->attributes());
1675 // f->attributes());
1666
1676
1667 add = false;
1677 add = false;
1668 if (cmp & AbstractMetaFunction::EqualArguments) {
1678 if (cmp & AbstractMetaFunction::EqualArguments) {
1669
1679
1670 // if (!(cmp & AbstractMetaFunction::EqualReturnType)) {
1680 // if (!(cmp & AbstractMetaFunction::EqualReturnType)) {
1671 // ReportHandler::warning(QString("%1::%2 and %3::%4 differ in retur type")
1681 // ReportHandler::warning(QString("%1::%2 and %3::%4 differ in retur type")
1672 // .arg(sf->implementingClass()->name())
1682 // .arg(sf->implementingClass()->name())
1673 // .arg(sf->name())
1683 // .arg(sf->name())
1674 // .arg(f->implementingClass()->name())
1684 // .arg(f->implementingClass()->name())
1675 // .arg(f->name()));
1685 // .arg(f->name()));
1676 // }
1686 // }
1677
1687
1678 // Same function, propegate virtual...
1688 // Same function, propegate virtual...
1679 if (!(cmp & AbstractMetaFunction::EqualAttributes)) {
1689 if (!(cmp & AbstractMetaFunction::EqualAttributes)) {
1680 if (!f->isEmptyFunction()) {
1690 if (!f->isEmptyFunction()) {
1681 if (!sf->isFinalInCpp() && f->isFinalInCpp()) {
1691 if (!sf->isFinalInCpp() && f->isFinalInCpp()) {
1682 *f -= AbstractMetaAttributes::FinalInCpp;
1692 *f -= AbstractMetaAttributes::FinalInCpp;
1683 // printf(" --- inherit virtual\n");
1693 // printf(" --- inherit virtual\n");
1684 }
1694 }
1685 if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) {
1695 if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) {
1686 *f -= AbstractMetaAttributes::FinalInTargetLang;
1696 *f -= AbstractMetaAttributes::FinalInTargetLang;
1687 // printf(" --- inherit virtual\n");
1697 // printf(" --- inherit virtual\n");
1688 }
1698 }
1689 if (!f->isFinalInTargetLang() && f->isPrivate()) {
1699 if (!f->isFinalInTargetLang() && f->isPrivate()) {
1690 f->setFunctionType(AbstractMetaFunction::EmptyFunction);
1700 f->setFunctionType(AbstractMetaFunction::EmptyFunction);
1691 f->setVisibility(AbstractMetaAttributes::Protected);
1701 f->setVisibility(AbstractMetaAttributes::Protected);
1692 *f += AbstractMetaAttributes::FinalInTargetLang;
1702 *f += AbstractMetaAttributes::FinalInTargetLang;
1693 ReportHandler::warning(QString("private virtual function '%1' in '%2'")
1703 ReportHandler::warning(QString("private virtual function '%1' in '%2'")
1694 .arg(f->signature())
1704 .arg(f->signature())
1695 .arg(f->implementingClass()->name()));
1705 .arg(f->implementingClass()->name()));
1696 }
1706 }
1697 }
1707 }
1698 }
1708 }
1699
1709
1700 if (f->visibility() != sf->visibility()) {
1710 if (f->visibility() != sf->visibility()) {
1701 QString warn = QString("visibility of function '%1' modified in class '%2'")
1711 QString warn = QString("visibility of function '%1' modified in class '%2'")
1702 .arg(f->name()).arg(name());
1712 .arg(f->name()).arg(name());
1703 ReportHandler::warning(warn);
1713 ReportHandler::warning(warn);
1704
1714
1705 // If new visibility is private, we can't
1715 // If new visibility is private, we can't
1706 // do anything. If it isn't, then we
1716 // do anything. If it isn't, then we
1707 // prefer the parent class's visibility
1717 // prefer the parent class's visibility
1708 // setting for the function.
1718 // setting for the function.
1709 if (!f->isPrivate() && !sf->isPrivate())
1719 if (!f->isPrivate() && !sf->isPrivate())
1710 f->setVisibility(sf->visibility());
1720 f->setVisibility(sf->visibility());
1711
1721
1712 // Private overrides of abstract functions have to go into the class or
1722 // Private overrides of abstract functions have to go into the class or
1713 // the subclasses will not compile as non-abstract classes.
1723 // the subclasses will not compile as non-abstract classes.
1714 // But they don't need to be implemented, since they can never be called.
1724 // But they don't need to be implemented, since they can never be called.
1715 if (f->isPrivate() && sf->isAbstract()) {
1725 if (f->isPrivate() && sf->isAbstract()) {
1716 f->setFunctionType(AbstractMetaFunction::EmptyFunction);
1726 f->setFunctionType(AbstractMetaFunction::EmptyFunction);
1717 f->setVisibility(sf->visibility());
1727 f->setVisibility(sf->visibility());
1718 *f += AbstractMetaAttributes::FinalInTargetLang;
1728 *f += AbstractMetaAttributes::FinalInTargetLang;
1719 *f += AbstractMetaAttributes::FinalInCpp;
1729 *f += AbstractMetaAttributes::FinalInCpp;
1720 }
1730 }
1721 }
1731 }
1722
1732
1723 // Set the class which first declares this function, afawk
1733 // Set the class which first declares this function, afawk
1724 f->setDeclaringClass(sf->declaringClass());
1734 f->setDeclaringClass(sf->declaringClass());
1725
1735
1726 if (sf->isFinalInTargetLang() && !sf->isPrivate() && !f->isPrivate() && !sf->isStatic() && !f->isStatic()) {
1736 if (sf->isFinalInTargetLang() && !sf->isPrivate() && !f->isPrivate() && !sf->isStatic() && !f->isStatic()) {
1727 // Shadowed funcion, need to make base class
1737 // Shadowed funcion, need to make base class
1728 // function non-virtual
1738 // function non-virtual
1729 if (f->implementingClass() != sf->implementingClass() && f->implementingClass()->inheritsFrom(sf->implementingClass())) {
1739 if (f->implementingClass() != sf->implementingClass() && f->implementingClass()->inheritsFrom(sf->implementingClass())) {
1730
1740
1731 // Check whether the superclass method has been redefined to non-final
1741 // Check whether the superclass method has been redefined to non-final
1732
1742
1733 bool hasNonFinalModifier = false;
1743 bool hasNonFinalModifier = false;
1734 bool isBaseImplPrivate = false;
1744 bool isBaseImplPrivate = false;
1735 FunctionModificationList mods = sf->modifications(sf->implementingClass());
1745 FunctionModificationList mods = sf->modifications(sf->implementingClass());
1736 foreach (FunctionModification mod, mods) {
1746 foreach (FunctionModification mod, mods) {
1737 if (mod.isNonFinal()) {
1747 if (mod.isNonFinal()) {
1738 hasNonFinalModifier = true;
1748 hasNonFinalModifier = true;
1739 break;
1749 break;
1740 } else if (mod.isPrivate()) {
1750 } else if (mod.isPrivate()) {
1741 isBaseImplPrivate = true;
1751 isBaseImplPrivate = true;
1742 break;
1752 break;
1743 }
1753 }
1744 }
1754 }
1745
1755
1746 if (!hasNonFinalModifier && !isBaseImplPrivate) {
1756 if (!hasNonFinalModifier && !isBaseImplPrivate) {
1747 ReportHandler::warning(QString::fromLatin1("Shadowing: %1::%2 and %3::%4; Java code will not compile")
1757 ReportHandler::warning(QString::fromLatin1("Shadowing: %1::%2 and %3::%4; Java code will not compile")
1748 .arg(sf->implementingClass()->name())
1758 .arg(sf->implementingClass()->name())
1749 .arg(sf->signature())
1759 .arg(sf->signature())
1750 .arg(f->implementingClass()->name())
1760 .arg(f->implementingClass()->name())
1751 .arg(f->signature()));
1761 .arg(f->signature()));
1752 }
1762 }
1753 }
1763 }
1754 }
1764 }
1755
1765
1756 }
1766 }
1757
1767
1758 if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) {
1768 if (cmp & AbstractMetaFunction::EqualDefaultValueOverload) {
1759 AbstractMetaArgumentList arguments;
1769 AbstractMetaArgumentList arguments;
1760 if (f->arguments().size() < sf->arguments().size())
1770 if (f->arguments().size() < sf->arguments().size())
1761 arguments = sf->arguments();
1771 arguments = sf->arguments();
1762 else
1772 else
1763 arguments = f->arguments();
1773 arguments = f->arguments();
1764
1774
1765 for (int i=0; i<arguments.size(); ++i)
1775 for (int i=0; i<arguments.size(); ++i)
1766 arguments[i]->setDefaultValueExpression(QString());
1776 arguments[i]->setDefaultValueExpression(QString());
1767 }
1777 }
1768
1778
1769
1779
1770 // Otherwise we have function shadowing and we can
1780 // Otherwise we have function shadowing and we can
1771 // skip the thing...
1781 // skip the thing...
1772 } else if (cmp & AbstractMetaFunction::EqualName && !sf->isSignal()) {
1782 } else if (cmp & AbstractMetaFunction::EqualName && !sf->isSignal()) {
1773
1783
1774 // In the case of function shadowing where the function name has been altered to
1784 // In the case of function shadowing where the function name has been altered to
1775 // avoid conflict, we don't copy in the original.
1785 // avoid conflict, we don't copy in the original.
1776 add = false;
1786 add = false;
1777 }
1787 }
1778
1788
1779 }
1789 }
1780
1790
1781 if (add)
1791 if (add)
1782 funcs_to_add << sf;
1792 funcs_to_add << sf;
1783 }
1793 }
1784
1794
1785 foreach (AbstractMetaFunction *f, funcs_to_add)
1795 foreach (AbstractMetaFunction *f, funcs_to_add)
1786 funcs << f->copy();
1796 funcs << f->copy();
1787
1797
1788 if (super_class)
1798 if (super_class)
1789 super_class = super_class->baseClass();
1799 super_class = super_class->baseClass();
1790 else
1800 else
1791 iface_idx++;
1801 iface_idx++;
1792 }
1802 }
1793
1803
1794 bool hasPrivateConstructors = false;
1804 bool hasPrivateConstructors = false;
1795 bool hasPublicConstructors = false;
1805 bool hasPublicConstructors = false;
1796 foreach (AbstractMetaFunction *func, funcs) {
1806 foreach (AbstractMetaFunction *func, funcs) {
1797 FunctionModificationList mods = func->modifications(this);
1807 FunctionModificationList mods = func->modifications(this);
1798 foreach (const FunctionModification &mod, mods) {
1808 foreach (const FunctionModification &mod, mods) {
1799 if (mod.isRenameModifier()) {
1809 if (mod.isRenameModifier()) {
1800 // qDebug() << name() << func->originalName() << func << " from "
1810 // qDebug() << name() << func->originalName() << func << " from "
1801 // << func->implementingClass()->name() << "renamed to" << mod.renamedTo();
1811 // << func->implementingClass()->name() << "renamed to" << mod.renamedTo();
1802 func->setName(mod.renamedTo());
1812 func->setName(mod.renamedTo());
1803 }
1813 }
1804 }
1814 }
1805
1815
1806 // Make sure class is abstract if one of the functions is
1816 // Make sure class is abstract if one of the functions is
1807 if (func->isAbstract()) {
1817 if (func->isAbstract()) {
1808 (*this) += AbstractMetaAttributes::Abstract;
1818 (*this) += AbstractMetaAttributes::Abstract;
1809 (*this) -= AbstractMetaAttributes::Final;
1819 (*this) -= AbstractMetaAttributes::Final;
1810 }
1820 }
1811
1821
1812 if (func->isConstructor()) {
1822 if (func->isConstructor()) {
1813 if (func->isPrivate())
1823 if (func->isPrivate())
1814 hasPrivateConstructors = true;
1824 hasPrivateConstructors = true;
1815 else
1825 else
1816 hasPublicConstructors = true;
1826 hasPublicConstructors = true;
1817 }
1827 }
1818
1828
1819
1829
1820
1830
1821 // Make sure that we include files for all classes that are in use
1831 // Make sure that we include files for all classes that are in use
1822
1832
1823 if (!func->isRemovedFrom(this, TypeSystem::ShellCode))
1833 if (!func->isRemovedFrom(this, TypeSystem::ShellCode))
1824 add_extra_includes_for_function(this, func);
1834 add_extra_includes_for_function(this, func);
1825 }
1835 }
1826
1836
1827 if (hasPrivateConstructors && !hasPublicConstructors) {
1837 if (hasPrivateConstructors && !hasPublicConstructors) {
1828 (*this) += AbstractMetaAttributes::Abstract;
1838 (*this) += AbstractMetaAttributes::Abstract;
1829 (*this) -= AbstractMetaAttributes::Final;
1839 (*this) -= AbstractMetaAttributes::Final;
1830 }
1840 }
1831
1841
1832 foreach (AbstractMetaFunction *f1, funcs) {
1842 foreach (AbstractMetaFunction *f1, funcs) {
1833 foreach (AbstractMetaFunction *f2, funcs) {
1843 foreach (AbstractMetaFunction *f2, funcs) {
1834 if (f1 != f2) {
1844 if (f1 != f2) {
1835 uint cmp = f1->compareTo(f2);
1845 uint cmp = f1->compareTo(f2);
1836 if ((cmp & AbstractMetaFunction::EqualName)
1846 if ((cmp & AbstractMetaFunction::EqualName)
1837 && !f1->isFinalInCpp()
1847 && !f1->isFinalInCpp()
1838 && f2->isFinalInCpp()) {
1848 && f2->isFinalInCpp()) {
1839 *f2 += AbstractMetaAttributes::FinalOverload;
1849 *f2 += AbstractMetaAttributes::FinalOverload;
1840 // qDebug() << f2 << f2->implementingClass()->name() << "::" << f2->name() << f2->arguments().size() << " vs " << f1 << f1->implementingClass()->name() << "::" << f1->name() << f1->arguments().size();
1850 // qDebug() << f2 << f2->implementingClass()->name() << "::" << f2->name() << f2->arguments().size() << " vs " << f1 << f1->implementingClass()->name() << "::" << f1->name() << f1->arguments().size();
1841 // qDebug() << " " << f2;
1851 // qDebug() << " " << f2;
1842 // AbstractMetaArgumentList f2Args = f2->arguments();
1852 // AbstractMetaArgumentList f2Args = f2->arguments();
1843 // foreach (AbstractMetaArgument *a, f2Args)
1853 // foreach (AbstractMetaArgument *a, f2Args)
1844 // qDebug() << " " << a->type()->name() << a->name();
1854 // qDebug() << " " << a->type()->name() << a->name();
1845 // qDebug() << " " << f1;
1855 // qDebug() << " " << f1;
1846 // AbstractMetaArgumentList f1Args = f1->arguments();
1856 // AbstractMetaArgumentList f1Args = f1->arguments();
1847 // foreach (AbstractMetaArgument *a, f1Args)
1857 // foreach (AbstractMetaArgument *a, f1Args)
1848 // qDebug() << " " << a->type()->name() << a->name();
1858 // qDebug() << " " << a->type()->name() << a->name();
1849
1859
1850 }
1860 }
1851 }
1861 }
1852 }
1862 }
1853 }
1863 }
1854
1864
1855 setFunctions(funcs);
1865 setFunctions(funcs);
1856 }
1866 }
1857
1867
1858
1868
1859 QString AbstractMetaType::minimalSignature() const
1869 QString AbstractMetaType::minimalSignature() const
1860 {
1870 {
1861 QString minimalSignature;
1871 QString minimalSignature;
1862 if (isConstant())
1872 if (isConstant())
1863 minimalSignature += "const ";
1873 minimalSignature += "const ";
1864 minimalSignature += typeEntry()->qualifiedCppName();
1874 minimalSignature += typeEntry()->qualifiedCppName();
1865 if (hasInstantiations()) {
1875 if (hasInstantiations()) {
1866 QList<AbstractMetaType *> instantiations = this->instantiations();
1876 QList<AbstractMetaType *> instantiations = this->instantiations();
1867 minimalSignature += "<";
1877 minimalSignature += "<";
1868 for (int i=0;i<instantiations.size();++i) {
1878 for (int i=0;i<instantiations.size();++i) {
1869 if (i > 0)
1879 if (i > 0)
1870 minimalSignature += ",";
1880 minimalSignature += ",";
1871 minimalSignature += instantiations.at(i)->minimalSignature();
1881 minimalSignature += instantiations.at(i)->minimalSignature();
1872 }
1882 }
1873 minimalSignature += ">";
1883 minimalSignature += ">";
1874 }
1884 }
1875
1885
1876 if (isReference())
1886 if (isReference())
1877 minimalSignature += "&";
1887 minimalSignature += "&";
1878 for (int j=0; j<indirections(); ++j)
1888 for (int j=0; j<indirections(); ++j)
1879 minimalSignature += "*";
1889 minimalSignature += "*";
1880
1890
1881 return minimalSignature;
1891 return minimalSignature;
1882 }
1892 }
1883
1893
1884 bool AbstractMetaType::hasNativeId() const
1894 bool AbstractMetaType::hasNativeId() const
1885 {
1895 {
1886 return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased();
1896 return (isQObject() || isValue() || isObject()) && typeEntry()->isNativeIdBased();
1887 }
1897 }
1888
1898
1889
1899
1890 /*******************************************************************************
1900 /*******************************************************************************
1891 * Other stuff...
1901 * Other stuff...
1892 */
1902 */
1893
1903
1894
1904
1895 AbstractMetaEnum *AbstractMetaClassList::findEnum(const EnumTypeEntry *entry) const
1905 AbstractMetaEnum *AbstractMetaClassList::findEnum(const EnumTypeEntry *entry) const
1896 {
1906 {
1897 Q_ASSERT(entry->isEnum());
1907 Q_ASSERT(entry->isEnum());
1898
1908
1899 QString qualified_name = entry->qualifiedCppName();
1909 QString qualified_name = entry->qualifiedCppName();
1900 int pos = qualified_name.lastIndexOf("::");
1910 int pos = qualified_name.lastIndexOf("::");
1901
1911
1902 QString enum_name;
1912 QString enum_name;
1903 QString class_name;
1913 QString class_name;
1904
1914
1905 if (pos > 0) {
1915 if (pos > 0) {
1906 enum_name = qualified_name.mid(pos + 2);
1916 enum_name = qualified_name.mid(pos + 2);
1907 class_name = qualified_name.mid(0, pos);
1917 class_name = qualified_name.mid(0, pos);
1908 } else {
1918 } else {
1909 enum_name = qualified_name;
1919 enum_name = qualified_name;
1910 class_name = TypeDatabase::globalNamespaceClassName(entry);
1920 class_name = TypeDatabase::globalNamespaceClassName(entry);
1911 }
1921 }
1912
1922
1913 AbstractMetaClass *meta_class = findClass(class_name);
1923 AbstractMetaClass *meta_class = findClass(class_name);
1914 if (!meta_class) {
1924 if (!meta_class) {
1915 ReportHandler::warning(QString("AbstractMeta::findEnum(), unknown class '%1' in '%2'")
1925 ReportHandler::warning(QString("AbstractMeta::findEnum(), unknown class '%1' in '%2'")
1916 .arg(class_name).arg(entry->qualifiedCppName()));
1926 .arg(class_name).arg(entry->qualifiedCppName()));
1917 return 0;
1927 return 0;
1918 }
1928 }
1919
1929
1920 return meta_class->findEnum(enum_name);
1930 return meta_class->findEnum(enum_name);
1921 }
1931 }
1922
1932
1923 AbstractMetaEnumValue *AbstractMetaEnumValueList::find(const QString &name) const
1933 AbstractMetaEnumValue *AbstractMetaEnumValueList::find(const QString &name) const
1924 {
1934 {
1925 for (int i=0; i<size(); ++i) {
1935 for (int i=0; i<size(); ++i) {
1926 if (name == at(i)->name())
1936 if (name == at(i)->name())
1927 return at(i);
1937 return at(i);
1928 }
1938 }
1929 return 0;
1939 return 0;
1930 }
1940 }
1931
1941
1932 AbstractMetaEnumValue *AbstractMetaClassList::findEnumValue(const QString &name) const
1942 AbstractMetaEnumValue *AbstractMetaClassList::findEnumValue(const QString &name) const
1933 {
1943 {
1934 QStringList lst = name.split(QLatin1String("::"));
1944 QStringList lst = name.split(QLatin1String("::"));
1935
1945
1936 Q_ASSERT_X(lst.size() == 2, "AbstractMetaClassList::findEnumValue()", "Expected qualified enum");
1946 Q_ASSERT_X(lst.size() == 2, "AbstractMetaClassList::findEnumValue()", "Expected qualified enum");
1937
1947
1938
1948
1939 QString prefixName = lst.at(0);
1949 QString prefixName = lst.at(0);
1940 QString enumName = lst.at(1);
1950 QString enumName = lst.at(1);
1941
1951
1942 AbstractMetaClass *cl = findClass(prefixName);
1952 AbstractMetaClass *cl = findClass(prefixName);
1943 if (cl)
1953 if (cl)
1944 return cl->findEnumValue(enumName, 0);
1954 return cl->findEnumValue(enumName, 0);
1945
1955
1946 ReportHandler::warning(QString("no matching enum '%1'").arg(name));
1956 ReportHandler::warning(QString("no matching enum '%1'").arg(name));
1947 return 0;
1957 return 0;
1948 }
1958 }
1949
1959
1950 /*!
1960 /*!
1951 * Searches the list after a class that mathces \a name; either as
1961 * Searches the list after a class that mathces \a name; either as
1952 * C++, Java base name or complete Java package.class name.
1962 * C++, Java base name or complete Java package.class name.
1953 */
1963 */
1954
1964
1955 AbstractMetaClass *AbstractMetaClassList::findClass(const QString &name) const
1965 AbstractMetaClass *AbstractMetaClassList::findClass(const QString &name) const
1956 {
1966 {
1957 if (name.isEmpty())
1967 if (name.isEmpty())
1958 return 0;
1968 return 0;
1959
1969
1960 foreach (AbstractMetaClass *c, *this) {
1970 foreach (AbstractMetaClass *c, *this) {
1961 if (c->qualifiedCppName() == name)
1971 if (c->qualifiedCppName() == name)
1962 return c;
1972 return c;
1963 }
1973 }
1964
1974
1965 foreach (AbstractMetaClass *c, *this) {
1975 foreach (AbstractMetaClass *c, *this) {
1966 if (c->fullName() == name)
1976 if (c->fullName() == name)
1967 return c;
1977 return c;
1968 }
1978 }
1969
1979
1970 foreach (AbstractMetaClass *c, *this) {
1980 foreach (AbstractMetaClass *c, *this) {
1971 if (c->name() == name)
1981 if (c->name() == name)
1972 return c;
1982 return c;
1973 }
1983 }
1974
1984
1975 return 0;
1985 return 0;
1976 }
1986 }
@@ -1,944 +1,946
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 ABSTRACTMETALANG_H
42 #ifndef ABSTRACTMETALANG_H
43 #define ABSTRACTMETALANG_H
43 #define ABSTRACTMETALANG_H
44
44
45 #include "codemodel.h"
45 #include "codemodel.h"
46
46
47 #include "typesystem.h"
47 #include "typesystem.h"
48
48
49 #include <QSet>
49 #include <QSet>
50 #include <QStringList>
50 #include <QStringList>
51 #include <QTextStream>
51 #include <QTextStream>
52
52
53
53
54 class AbstractMeta;
54 class AbstractMeta;
55 class AbstractMetaClass;
55 class AbstractMetaClass;
56 class AbstractMetaField;
56 class AbstractMetaField;
57 class AbstractMetaFunction;
57 class AbstractMetaFunction;
58 class AbstractMetaType;
58 class AbstractMetaType;
59 class AbstractMetaVariable;
59 class AbstractMetaVariable;
60 class AbstractMetaArgument;
60 class AbstractMetaArgument;
61 class AbstractMetaEnumValue;
61 class AbstractMetaEnumValue;
62 class AbstractMetaEnum;
62 class AbstractMetaEnum;
63 class QPropertySpec;
63 class QPropertySpec;
64
64
65 typedef QList<AbstractMetaField *> AbstractMetaFieldList;
65 typedef QList<AbstractMetaField *> AbstractMetaFieldList;
66 typedef QList<AbstractMetaArgument *> AbstractMetaArgumentList;
66 typedef QList<AbstractMetaArgument *> AbstractMetaArgumentList;
67 typedef QList<AbstractMetaFunction *> AbstractMetaFunctionList;
67 typedef QList<AbstractMetaFunction *> AbstractMetaFunctionList;
68 class AbstractMetaClassList : public QList<AbstractMetaClass *>
68 class AbstractMetaClassList : public QList<AbstractMetaClass *>
69 {
69 {
70 public:
70 public:
71 AbstractMetaClass *findClass(const QString &name) const;
71 AbstractMetaClass *findClass(const QString &name) const;
72 AbstractMetaEnumValue *findEnumValue(const QString &string) const;
72 AbstractMetaEnumValue *findEnumValue(const QString &string) const;
73 AbstractMetaEnum *findEnum(const EnumTypeEntry *entry) const;
73 AbstractMetaEnum *findEnum(const EnumTypeEntry *entry) const;
74
74
75 };
75 };
76
76
77
77
78
78
79 class AbstractMetaAttributes
79 class AbstractMetaAttributes
80 {
80 {
81 public:
81 public:
82 AbstractMetaAttributes() : m_attributes(0) { };
82 AbstractMetaAttributes() : m_attributes(0) { };
83
83
84 enum Attribute {
84 enum Attribute {
85 None = 0x00000000,
85 None = 0x00000000,
86
86
87 Private = 0x00000001,
87 Private = 0x00000001,
88 Protected = 0x00000002,
88 Protected = 0x00000002,
89 Public = 0x00000004,
89 Public = 0x00000004,
90 Friendly = 0x00000008,
90 Friendly = 0x00000008,
91 Visibility = 0x0000000f,
91 Visibility = 0x0000000f,
92
92
93 Native = 0x00000010,
93 Native = 0x00000010,
94 Abstract = 0x00000020,
94 Abstract = 0x00000020,
95 Static = 0x00000040,
95 Static = 0x00000040,
96
96
97 FinalInTargetLang = 0x00000080,
97 FinalInTargetLang = 0x00000080,
98 FinalInCpp = 0x00000100,
98 FinalInCpp = 0x00000100,
99 ForceShellImplementation = 0x00000200,
99 ForceShellImplementation = 0x00000200,
100
100
101 GetterFunction = 0x00000400,
101 GetterFunction = 0x00000400,
102 SetterFunction = 0x00000800,
102 SetterFunction = 0x00000800,
103
103
104 FinalOverload = 0x00001000,
104 FinalOverload = 0x00001000,
105 InterfaceFunction = 0x00002000,
105 InterfaceFunction = 0x00002000,
106
106
107 PropertyReader = 0x00004000,
107 PropertyReader = 0x00004000,
108 PropertyWriter = 0x00008000,
108 PropertyWriter = 0x00008000,
109 PropertyResetter = 0x00010000,
109 PropertyResetter = 0x00010000,
110
110
111 Fake = 0x00020000,
111 Fake = 0x00020000,
112
112
113 Invokable = 0x00040000,
113 Invokable = 0x00040000,
114
114
115 Final = FinalInTargetLang | FinalInCpp
115 Final = FinalInTargetLang | FinalInCpp
116 };
116 };
117
117
118 uint attributes() const { return m_attributes; }
118 uint attributes() const { return m_attributes; }
119 void setAttributes(uint attributes) { m_attributes = attributes; }
119 void setAttributes(uint attributes) { m_attributes = attributes; }
120
120
121 uint originalAttributes() const { return m_originalAttributes; }
121 uint originalAttributes() const { return m_originalAttributes; }
122 void setOriginalAttributes(uint attributes) { m_originalAttributes = attributes; }
122 void setOriginalAttributes(uint attributes) { m_originalAttributes = attributes; }
123
123
124 uint visibility() const { return m_attributes & Visibility; }
124 uint visibility() const { return m_attributes & Visibility; }
125 void setVisibility(uint visi) { m_attributes = (m_attributes & ~Visibility) | visi; }
125 void setVisibility(uint visi) { m_attributes = (m_attributes & ~Visibility) | visi; }
126
126
127 void operator+=(Attribute attribute) { m_attributes |= attribute; }
127 void operator+=(Attribute attribute) { m_attributes |= attribute; }
128 void operator-=(Attribute attribute) { m_attributes &= ~attribute; }
128 void operator-=(Attribute attribute) { m_attributes &= ~attribute; }
129
129
130 bool isNative() const { return m_attributes & Native; }
130 bool isNative() const { return m_attributes & Native; }
131 bool isFinal() const { return (m_attributes & Final) == Final; }
131 bool isFinal() const { return (m_attributes & Final) == Final; }
132 bool isFinalInTargetLang() const { return m_attributes & FinalInTargetLang; }
132 bool isFinalInTargetLang() const { return m_attributes & FinalInTargetLang; }
133 bool isFinalInCpp() const { return m_attributes & FinalInCpp; }
133 bool isFinalInCpp() const { return m_attributes & FinalInCpp; }
134 bool isAbstract() const { return m_attributes & Abstract; }
134 bool isAbstract() const { return m_attributes & Abstract; }
135 bool isStatic() const { return m_attributes & Static; }
135 bool isStatic() const { return m_attributes & Static; }
136 bool isForcedShellImplementation() const { return m_attributes & ForceShellImplementation; }
136 bool isForcedShellImplementation() const { return m_attributes & ForceShellImplementation; }
137 bool isInterfaceFunction() const { return m_attributes & InterfaceFunction; }
137 bool isInterfaceFunction() const { return m_attributes & InterfaceFunction; }
138 bool isFinalOverload() const { return m_attributes & FinalOverload; }
138 bool isFinalOverload() const { return m_attributes & FinalOverload; }
139 bool isInvokable() const { return m_attributes & Invokable; }
139 bool isInvokable() const { return m_attributes & Invokable; }
140
140
141 bool isPropertyReader() const { return m_attributes & PropertyReader; }
141 bool isPropertyReader() const { return m_attributes & PropertyReader; }
142 bool isPropertyWriter() const { return m_attributes & PropertyWriter; }
142 bool isPropertyWriter() const { return m_attributes & PropertyWriter; }
143 bool isPropertyResetter() const { return m_attributes & PropertyResetter; }
143 bool isPropertyResetter() const { return m_attributes & PropertyResetter; }
144
144
145 bool isPrivate() const { return m_attributes & Private; }
145 bool isPrivate() const { return m_attributes & Private; }
146 bool isProtected() const { return m_attributes & Protected; }
146 bool isProtected() const { return m_attributes & Protected; }
147 bool isPublic() const { return m_attributes & Public; }
147 bool isPublic() const { return m_attributes & Public; }
148 bool isFriendly() const { return m_attributes & Friendly; }
148 bool isFriendly() const { return m_attributes & Friendly; }
149
149
150 bool wasPrivate() const { return m_originalAttributes & Private; }
150 bool wasPrivate() const { return m_originalAttributes & Private; }
151 bool wasProtected() const { return m_originalAttributes & Protected; }
151 bool wasProtected() const { return m_originalAttributes & Protected; }
152 bool wasPublic() const { return m_originalAttributes & Public; }
152 bool wasPublic() const { return m_originalAttributes & Public; }
153 bool wasFriendly() const { return m_originalAttributes & Friendly; }
153 bool wasFriendly() const { return m_originalAttributes & Friendly; }
154
154
155 private:
155 private:
156 uint m_attributes;
156 uint m_attributes;
157 uint m_originalAttributes;
157 uint m_originalAttributes;
158 };
158 };
159
159
160
160
161 class AbstractMetaType
161 class AbstractMetaType
162 {
162 {
163 public:
163 public:
164 enum TypeUsagePattern {
164 enum TypeUsagePattern {
165 InvalidPattern,
165 InvalidPattern,
166 PrimitivePattern,
166 PrimitivePattern,
167 FlagsPattern,
167 FlagsPattern,
168 EnumPattern,
168 EnumPattern,
169 ValuePattern,
169 ValuePattern,
170 StringPattern,
170 StringPattern,
171 CharPattern,
171 CharPattern,
172 ObjectPattern,
172 ObjectPattern,
173 QObjectPattern,
173 QObjectPattern,
174 NativePointerPattern,
174 NativePointerPattern,
175 ContainerPattern,
175 ContainerPattern,
176 VariantPattern,
176 VariantPattern,
177 JObjectWrapperPattern,
177 JObjectWrapperPattern,
178 ArrayPattern,
178 ArrayPattern,
179 ThreadPattern
179 ThreadPattern
180 };
180 };
181
181
182 AbstractMetaType() :
182 AbstractMetaType() :
183 m_type_entry(0),
183 m_type_entry(0),
184 m_array_element_count(0),
184 m_array_element_count(0),
185 m_array_element_type(0),
185 m_array_element_type(0),
186 m_original_template_type(0),
186 m_original_template_type(0),
187 m_pattern(InvalidPattern),
187 m_pattern(InvalidPattern),
188 m_constant(false),
188 m_constant(false),
189 m_reference(false),
189 m_reference(false),
190 m_cpp_instantiation(true),
190 m_cpp_instantiation(true),
191 m_indirections(0),
191 m_indirections(0),
192 m_reserved(0)
192 m_reserved(0)
193 {
193 {
194 }
194 }
195
195
196 QString package() const { return m_type_entry->javaPackage(); }
196 QString package() const { return m_type_entry->javaPackage(); }
197 QString name() const { return m_type_entry->targetLangName(); }
197 QString name() const { return m_type_entry->targetLangName(); }
198 QString fullName() const { return m_type_entry->qualifiedTargetLangName(); }
198 QString fullName() const { return m_type_entry->qualifiedTargetLangName(); }
199
199
200 void setTypeUsagePattern(TypeUsagePattern pattern) { m_pattern = pattern; }
200 void setTypeUsagePattern(TypeUsagePattern pattern) { m_pattern = pattern; }
201 TypeUsagePattern typeUsagePattern() const { return m_pattern; }
201 TypeUsagePattern typeUsagePattern() const { return m_pattern; }
202
202
203 // true when use pattern is container
203 // true when use pattern is container
204 bool hasInstantiations() const { return !m_instantiations.isEmpty(); }
204 bool hasInstantiations() const { return !m_instantiations.isEmpty(); }
205 void addInstantiation(AbstractMetaType *inst) { m_instantiations << inst; }
205 void addInstantiation(AbstractMetaType *inst) { m_instantiations << inst; }
206 void setInstantiations(const QList<AbstractMetaType *> &insts) { m_instantiations = insts; }
206 void setInstantiations(const QList<AbstractMetaType *> &insts) { m_instantiations = insts; }
207 QList<AbstractMetaType *> instantiations() const { return m_instantiations; }
207 QList<AbstractMetaType *> instantiations() const { return m_instantiations; }
208 void setInstantiationInCpp(bool incpp) { m_cpp_instantiation = incpp; }
208 void setInstantiationInCpp(bool incpp) { m_cpp_instantiation = incpp; }
209 bool hasInstantiationInCpp() const { return hasInstantiations() && m_cpp_instantiation; }
209 bool hasInstantiationInCpp() const { return hasInstantiations() && m_cpp_instantiation; }
210
210
211 QString minimalSignature() const;
211 QString minimalSignature() const;
212
212
213 // true when the type is a QtJambiObject subclass
213 // true when the type is a QtJambiObject subclass
214 bool hasNativeId() const;
214 bool hasNativeId() const;
215
215
216 // returns true if the typs is used as a non complex primitive, no & or *'s
216 // returns true if the typs is used as a non complex primitive, no & or *'s
217 bool isPrimitive() const { return m_pattern == PrimitivePattern; }
217 bool isPrimitive() const { return m_pattern == PrimitivePattern; }
218
218
219 // returns true if the type is used as an enum
219 // returns true if the type is used as an enum
220 bool isEnum() const { return m_pattern == EnumPattern; }
220 bool isEnum() const { return m_pattern == EnumPattern; }
221
221
222 // returns true if the type is used as a QObject *
222 // returns true if the type is used as a QObject *
223 bool isQObject() const { return m_pattern == QObjectPattern; }
223 bool isQObject() const { return m_pattern == QObjectPattern; }
224
224
225 // returns true if the type is used as an object, e.g. Xxx *
225 // returns true if the type is used as an object, e.g. Xxx *
226 bool isObject() const { return m_pattern == ObjectPattern; }
226 bool isObject() const { return m_pattern == ObjectPattern; }
227
227
228 // returns true if the type is used as an array, e.g. Xxx[42]
228 // returns true if the type is used as an array, e.g. Xxx[42]
229 bool isArray() const { return m_pattern == ArrayPattern; }
229 bool isArray() const { return m_pattern == ArrayPattern; }
230
230
231 // returns true if the type is used as a value type (X or const X &)
231 // returns true if the type is used as a value type (X or const X &)
232 bool isValue() const { return m_pattern == ValuePattern; }
232 bool isValue() const { return m_pattern == ValuePattern; }
233
233
234 // returns true for more complex types...
234 // returns true for more complex types...
235 bool isNativePointer() const { return m_pattern == NativePointerPattern; }
235 bool isNativePointer() const { return m_pattern == NativePointerPattern; }
236
236
237 // returns true if the type was originally a QString or const QString & or equivalent for QLatin1String
237 // returns true if the type was originally a QString or const QString & or equivalent for QLatin1String
238 bool isTargetLangString() const { return m_pattern == StringPattern; }
238 bool isTargetLangString() const { return m_pattern == StringPattern; }
239
239
240 // returns true if the type was originally a QChar or const QChar &
240 // returns true if the type was originally a QChar or const QChar &
241 bool isTargetLangChar() const { return m_pattern == CharPattern; }
241 bool isTargetLangChar() const { return m_pattern == CharPattern; }
242
242
243 // return true if the type was originally a QVariant or const QVariant &
243 // return true if the type was originally a QVariant or const QVariant &
244 bool isVariant() const { return m_pattern == VariantPattern; }
244 bool isVariant() const { return m_pattern == VariantPattern; }
245
245
246 // return true if the type was originally a JObjectWrapper or const JObjectWrapper &
246 // return true if the type was originally a JObjectWrapper or const JObjectWrapper &
247 bool isJObjectWrapper() const { return m_pattern == JObjectWrapperPattern; }
247 bool isJObjectWrapper() const { return m_pattern == JObjectWrapperPattern; }
248
248
249 // returns true if the type was used as a container
249 // returns true if the type was used as a container
250 bool isContainer() const { return m_pattern == ContainerPattern; }
250 bool isContainer() const { return m_pattern == ContainerPattern; }
251
251
252 // returns true if the type was used as a flag
252 // returns true if the type was used as a flag
253 bool isFlags() const { return m_pattern == FlagsPattern; }
253 bool isFlags() const { return m_pattern == FlagsPattern; }
254
254
255 // returns true if the type was used as a thread
255 // returns true if the type was used as a thread
256 bool isThread() const { return m_pattern == ThreadPattern; }
256 bool isThread() const { return m_pattern == ThreadPattern; }
257
257
258 bool isConstant() const { return m_constant; }
258 bool isConstant() const { return m_constant; }
259 void setConstant(bool constant) { m_constant = constant; }
259 void setConstant(bool constant) { m_constant = constant; }
260
260
261 bool isReference() const { return m_reference; }
261 bool isReference() const { return m_reference; }
262 void setReference(bool ref) { m_reference = ref; }
262 void setReference(bool ref) { m_reference = ref; }
263
263
264 // Returns true if the type is to be implemented using Java enums, e.g. not plain ints.
264 // Returns true if the type is to be implemented using Java enums, e.g. not plain ints.
265 bool isTargetLangEnum() const { return isEnum() && !((EnumTypeEntry *) typeEntry())->forceInteger(); }
265 bool isTargetLangEnum() const { return isEnum() && !((EnumTypeEntry *) typeEntry())->forceInteger(); }
266 bool isIntegerEnum() const { return isEnum() && !isTargetLangEnum(); }
266 bool isIntegerEnum() const { return isEnum() && !isTargetLangEnum(); }
267
267
268 // Returns true if the type is to be implemented using Java QFlags, e.g. not plain ints.
268 // Returns true if the type is to be implemented using Java QFlags, e.g. not plain ints.
269 bool isTargetLangFlags() const {
269 bool isTargetLangFlags() const {
270 return isFlags() && !((FlagsTypeEntry *) typeEntry())->forceInteger(); }
270 return isFlags() && !((FlagsTypeEntry *) typeEntry())->forceInteger(); }
271 bool isIntegerFlags() const { return isFlags() && !isTargetLangFlags(); }
271 bool isIntegerFlags() const { return isFlags() && !isTargetLangFlags(); }
272
272
273 int actualIndirections() const { return m_indirections + (isReference() ? 1 : 0); }
273 int actualIndirections() const { return m_indirections + (isReference() ? 1 : 0); }
274 int indirections() const { return m_indirections; }
274 int indirections() const { return m_indirections; }
275 void setIndirections(int indirections) { m_indirections = indirections; }
275 void setIndirections(int indirections) { m_indirections = indirections; }
276
276
277 void setArrayElementCount(int n) { m_array_element_count = n; }
277 void setArrayElementCount(int n) { m_array_element_count = n; }
278 int arrayElementCount() const { return m_array_element_count; }
278 int arrayElementCount() const { return m_array_element_count; }
279
279
280 AbstractMetaType *arrayElementType() const { return m_array_element_type; }
280 AbstractMetaType *arrayElementType() const { return m_array_element_type; }
281 void setArrayElementType(AbstractMetaType *t) { m_array_element_type = t; }
281 void setArrayElementType(AbstractMetaType *t) { m_array_element_type = t; }
282
282
283 QString cppSignature() const;
283 QString cppSignature() const;
284
284
285 AbstractMetaType *copy() const;
285 AbstractMetaType *copy() const;
286
286
287 const TypeEntry *typeEntry() const { return m_type_entry; }
287 const TypeEntry *typeEntry() const { return m_type_entry; }
288 void setTypeEntry(const TypeEntry *type) { m_type_entry = type; }
288 void setTypeEntry(const TypeEntry *type) { m_type_entry = type; }
289
289
290 void setOriginalTypeDescription(const QString &otd) { m_original_type_description = otd; }
290 void setOriginalTypeDescription(const QString &otd) { m_original_type_description = otd; }
291 QString originalTypeDescription() const { return m_original_type_description; }
291 QString originalTypeDescription() const { return m_original_type_description; }
292
292
293 void setOriginalTemplateType(const AbstractMetaType *type) { m_original_template_type = type; }
293 void setOriginalTemplateType(const AbstractMetaType *type) { m_original_template_type = type; }
294 const AbstractMetaType *originalTemplateType() const { return m_original_template_type; }
294 const AbstractMetaType *originalTemplateType() const { return m_original_template_type; }
295
295
296 private:
296 private:
297 const TypeEntry *m_type_entry;
297 const TypeEntry *m_type_entry;
298 QList <AbstractMetaType *> m_instantiations;
298 QList <AbstractMetaType *> m_instantiations;
299 QString m_package;
299 QString m_package;
300 QString m_original_type_description;
300 QString m_original_type_description;
301
301
302 int m_array_element_count;
302 int m_array_element_count;
303 AbstractMetaType *m_array_element_type;
303 AbstractMetaType *m_array_element_type;
304 const AbstractMetaType *m_original_template_type;
304 const AbstractMetaType *m_original_template_type;
305
305
306 TypeUsagePattern m_pattern;
306 TypeUsagePattern m_pattern;
307 uint m_constant : 1;
307 uint m_constant : 1;
308 uint m_reference : 1;
308 uint m_reference : 1;
309 uint m_cpp_instantiation : 1;
309 uint m_cpp_instantiation : 1;
310 int m_indirections : 4;
310 int m_indirections : 4;
311 uint m_reserved : 25; // unused
311 uint m_reserved : 25; // unused
312 };
312 };
313
313
314 class AbstractMetaVariable
314 class AbstractMetaVariable
315 {
315 {
316 public:
316 public:
317 AbstractMetaVariable() : m_type(0) { }
317 AbstractMetaVariable() : m_type(0) { }
318
318
319 AbstractMetaType *type() const { return m_type; }
319 AbstractMetaType *type() const { return m_type; }
320 void setType(AbstractMetaType *type) { m_type = type; }
320 void setType(AbstractMetaType *type) { m_type = type; }
321
321
322 QString name() const { return m_name; }
322 QString name() const { return m_name; }
323 void setName(const QString &name) { m_name = name; }
323 void setName(const QString &name) { m_name = name; }
324
324
325 private:
325 private:
326 QString m_name;
326 QString m_name;
327 AbstractMetaType *m_type;
327 AbstractMetaType *m_type;
328 };
328 };
329
329
330
330
331
331
332 class AbstractMetaArgument : public AbstractMetaVariable
332 class AbstractMetaArgument : public AbstractMetaVariable
333 {
333 {
334 public:
334 public:
335 AbstractMetaArgument() : m_argument_index(0) { };
335 AbstractMetaArgument() : m_argument_index(0) { };
336
336
337 QString defaultValueExpression() const { return m_expression; }
337 QString defaultValueExpression() const { return m_expression; }
338 void setDefaultValueExpression(const QString &expr) { m_expression = expr; }
338 void setDefaultValueExpression(const QString &expr) { m_expression = expr; }
339
339
340 QString originalDefaultValueExpression() const { return m_original_expression; }
340 QString originalDefaultValueExpression() const { return m_original_expression; }
341 void setOriginalDefaultValueExpression(const QString &expr) { m_original_expression = expr; }
341 void setOriginalDefaultValueExpression(const QString &expr) { m_original_expression = expr; }
342
342
343 QString toString() const { return type()->name() + " " + AbstractMetaVariable::name() +
343 QString toString() const { return type()->name() + " " + AbstractMetaVariable::name() +
344 (m_expression.isEmpty() ? "" : " = " + m_expression); }
344 (m_expression.isEmpty() ? "" : " = " + m_expression); }
345
345
346 int argumentIndex() const { return m_argument_index; }
346 int argumentIndex() const { return m_argument_index; }
347 void setArgumentIndex(int argIndex) { m_argument_index = argIndex; }
347 void setArgumentIndex(int argIndex) { m_argument_index = argIndex; }
348
348
349 QString argumentName() const;
349 QString argumentName() const;
350 QString indexedName() const;
350 QString indexedName() const;
351
351
352 AbstractMetaArgument *copy() const;
352 AbstractMetaArgument *copy() const;
353
353
354 private:
354 private:
355 // Just to force people to call argumentName() And indexedName();
355 // Just to force people to call argumentName() And indexedName();
356 QString name() const;
356 QString name() const;
357
357
358 QString m_expression;
358 QString m_expression;
359 QString m_original_expression;
359 QString m_original_expression;
360 int m_argument_index;
360 int m_argument_index;
361 };
361 };
362
362
363
363
364 class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes
364 class AbstractMetaField : public AbstractMetaVariable, public AbstractMetaAttributes
365 {
365 {
366 public:
366 public:
367 AbstractMetaField();
367 AbstractMetaField();
368 ~AbstractMetaField();
368 ~AbstractMetaField();
369
369
370 const AbstractMetaClass *enclosingClass() const { return m_class; }
370 const AbstractMetaClass *enclosingClass() const { return m_class; }
371 void setEnclosingClass(const AbstractMetaClass *cls) { m_class = cls; }
371 void setEnclosingClass(const AbstractMetaClass *cls) { m_class = cls; }
372
372
373 const AbstractMetaFunction *getter() const;
373 const AbstractMetaFunction *getter() const;
374 const AbstractMetaFunction *setter() const;
374 const AbstractMetaFunction *setter() const;
375
375
376 FieldModificationList modifications() const;
376 FieldModificationList modifications() const;
377
377
378 AbstractMetaField *copy() const;
378 AbstractMetaField *copy() const;
379
379
380 private:
380 private:
381 mutable AbstractMetaFunction *m_getter;
381 mutable AbstractMetaFunction *m_getter;
382 mutable AbstractMetaFunction *m_setter;
382 mutable AbstractMetaFunction *m_setter;
383 const AbstractMetaClass *m_class;
383 const AbstractMetaClass *m_class;
384 };
384 };
385
385
386
386
387 class AbstractMetaFunction : public AbstractMetaAttributes
387 class AbstractMetaFunction : public AbstractMetaAttributes
388 {
388 {
389 public:
389 public:
390 enum FunctionType {
390 enum FunctionType {
391 ConstructorFunction,
391 ConstructorFunction,
392 DestructorFunction,
392 DestructorFunction,
393 NormalFunction,
393 NormalFunction,
394 SignalFunction,
394 SignalFunction,
395 EmptyFunction,
395 EmptyFunction,
396 SlotFunction,
396 SlotFunction,
397 GlobalScopeFunction
397 GlobalScopeFunction
398 };
398 };
399
399
400 enum CompareResult {
400 enum CompareResult {
401 EqualName = 0x00000001,
401 EqualName = 0x00000001,
402 EqualArguments = 0x00000002,
402 EqualArguments = 0x00000002,
403 EqualAttributes = 0x00000004,
403 EqualAttributes = 0x00000004,
404 EqualImplementor = 0x00000008,
404 EqualImplementor = 0x00000008,
405 EqualReturnType = 0x00000010,
405 EqualReturnType = 0x00000010,
406 EqualDefaultValueOverload = 0x00000020,
406 EqualDefaultValueOverload = 0x00000020,
407 EqualModifiedName = 0x00000040,
407 EqualModifiedName = 0x00000040,
408
408
409 NameLessThan = 0x00001000,
409 NameLessThan = 0x00001000,
410
410
411 PrettySimilar = EqualName | EqualArguments,
411 PrettySimilar = EqualName | EqualArguments,
412 Equal = 0x0000001f,
412 Equal = 0x0000001f,
413 NotEqual = 0x00001000
413 NotEqual = 0x00001000
414 };
414 };
415
415
416 AbstractMetaFunction()
416 AbstractMetaFunction()
417 : m_function_type(NormalFunction),
417 : m_function_type(NormalFunction),
418 m_type(0),
418 m_type(0),
419 m_class(0),
419 m_class(0),
420 m_implementing_class(0),
420 m_implementing_class(0),
421 m_declaring_class(0),
421 m_declaring_class(0),
422 m_interface_class(0),
422 m_interface_class(0),
423 m_property_spec(0),
423 m_property_spec(0),
424 m_constant(false),
424 m_constant(false),
425 m_invalid(false)
425 m_invalid(false)
426 {
426 {
427 }
427 }
428
428
429 ~AbstractMetaFunction();
429 ~AbstractMetaFunction();
430
430
431 QString name() const { return m_name; }
431 QString name() const { return m_name; }
432 void setName(const QString &name) { m_name = name; }
432 void setName(const QString &name) { m_name = name; }
433
433
434 QString originalName() const { return m_original_name.isEmpty() ? name() : m_original_name; }
434 QString originalName() const { return m_original_name.isEmpty() ? name() : m_original_name; }
435 void setOriginalName(const QString &name) { m_original_name = name; }
435 void setOriginalName(const QString &name) { m_original_name = name; }
436
436
437 QString modifiedName() const;
437 QString modifiedName() const;
438
438
439 QString minimalSignature() const;
439 QString minimalSignature() const;
440 QStringList possibleIntrospectionCompatibleSignatures() const;
440 QStringList possibleIntrospectionCompatibleSignatures() const;
441
441
442 QString marshalledName() const;
442 QString marshalledName() const;
443
443
444 // true if one or more of the arguments are of QtJambiObject subclasses
444 // true if one or more of the arguments are of QtJambiObject subclasses
445 bool argumentsHaveNativeId() const
445 bool argumentsHaveNativeId() const
446 {
446 {
447 foreach (const AbstractMetaArgument *arg, m_arguments) {
447 foreach (const AbstractMetaArgument *arg, m_arguments) {
448 if (arg->type()->hasNativeId())
448 if (arg->type()->hasNativeId())
449 return true;
449 return true;
450 }
450 }
451
451
452 return false;
452 return false;
453 }
453 }
454
454
455 bool isModifiedRemoved(int types = TypeSystem::All) const;
455 bool isModifiedRemoved(int types = TypeSystem::All) const;
456
456
457 AbstractMetaType *type() const { return m_type; }
457 AbstractMetaType *type() const { return m_type; }
458 void setType(AbstractMetaType *type) { m_type = type; }
458 void setType(AbstractMetaType *type) { m_type = type; }
459
459
460 // The class that has this function as a member.
460 // The class that has this function as a member.
461 const AbstractMetaClass *ownerClass() const { return m_class; }
461 const AbstractMetaClass *ownerClass() const { return m_class; }
462 void setOwnerClass(const AbstractMetaClass *cls) { m_class = cls; }
462 void setOwnerClass(const AbstractMetaClass *cls) { m_class = cls; }
463
463
464 // The first class in a hierarchy that declares the function
464 // The first class in a hierarchy that declares the function
465 const AbstractMetaClass *declaringClass() const { return m_declaring_class; }
465 const AbstractMetaClass *declaringClass() const { return m_declaring_class; }
466 void setDeclaringClass(const AbstractMetaClass *cls) { m_declaring_class = cls; }
466 void setDeclaringClass(const AbstractMetaClass *cls) { m_declaring_class = cls; }
467
467
468 // The class that actually implements this function
468 // The class that actually implements this function
469 const AbstractMetaClass *implementingClass() const { return m_implementing_class; }
469 const AbstractMetaClass *implementingClass() const { return m_implementing_class; }
470 void setImplementingClass(const AbstractMetaClass *cls) { m_implementing_class = cls; }
470 void setImplementingClass(const AbstractMetaClass *cls) { m_implementing_class = cls; }
471
471
472 bool needsCallThrough() const;
472 bool needsCallThrough() const;
473
473
474 AbstractMetaArgumentList arguments() const { return m_arguments; }
474 AbstractMetaArgumentList arguments() const { return m_arguments; }
475 void setArguments(const AbstractMetaArgumentList &arguments) { m_arguments = arguments; }
475 void setArguments(const AbstractMetaArgumentList &arguments) { m_arguments = arguments; }
476 void addArgument(AbstractMetaArgument *argument) { m_arguments << argument; }
476 void addArgument(AbstractMetaArgument *argument) { m_arguments << argument; }
477 int actualMinimumArgumentCount() const;
477 int actualMinimumArgumentCount() const;
478
478
479 void setInvalid(bool on) { m_invalid = on; }
479 void setInvalid(bool on) { m_invalid = on; }
480 bool isInvalid() const { return m_invalid; }
480 bool isInvalid() const { return m_invalid; }
481 bool isDeprecated() const;
481 bool isDeprecated() const;
482 bool isDestructor() const { return functionType() == DestructorFunction; }
482 bool isDestructor() const { return functionType() == DestructorFunction; }
483 bool isConstructor() const { return functionType() == ConstructorFunction; }
483 bool isConstructor() const { return functionType() == ConstructorFunction; }
484 bool isNormal() const { return functionType() == NormalFunction || isSlot() || isInGlobalScope(); }
484 bool isNormal() const { return functionType() == NormalFunction || isSlot() || isInGlobalScope(); }
485 bool isInGlobalScope() const { return functionType() == GlobalScopeFunction; }
485 bool isInGlobalScope() const { return functionType() == GlobalScopeFunction; }
486 bool isSignal() const { return functionType() == SignalFunction; }
486 bool isSignal() const { return functionType() == SignalFunction; }
487 bool isSlot() const { return functionType() == SlotFunction; }
487 bool isSlot() const { return functionType() == SlotFunction; }
488 bool isEmptyFunction() const { return functionType() == EmptyFunction; }
488 bool isEmptyFunction() const { return functionType() == EmptyFunction; }
489 FunctionType functionType() const { return m_function_type; }
489 FunctionType functionType() const { return m_function_type; }
490 void setFunctionType(FunctionType type) { m_function_type = type; }
490 void setFunctionType(FunctionType type) { m_function_type = type; }
491
491
492 bool isVirtual() { return !(isFinal() || isSignal() || isStatic()); }
492 bool isVirtual() { return !(isFinal() || isSignal() || isStatic()); }
493
493
494 QStringList introspectionCompatibleSignatures(const QStringList &resolvedArguments = QStringList()) const;
494 QStringList introspectionCompatibleSignatures(const QStringList &resolvedArguments = QStringList()) const;
495 QString signature() const;
495 QString signature() const;
496 QString targetLangSignature(bool minimal = false) const;
496 QString targetLangSignature(bool minimal = false) const;
497 bool shouldReturnThisObject() const { return QLatin1String("this") == argumentReplaced(0); }
497 bool shouldReturnThisObject() const { return QLatin1String("this") == argumentReplaced(0); }
498 bool shouldIgnoreReturnValue() const { return QLatin1String("void") == argumentReplaced(0); }
498 bool shouldIgnoreReturnValue() const { return QLatin1String("void") == argumentReplaced(0); }
499
499
500 bool isConstant() const { return m_constant; }
500 bool isConstant() const { return m_constant; }
501 void setConstant(bool constant) { m_constant = constant; }
501 void setConstant(bool constant) { m_constant = constant; }
502
502
503 QString toString() const { return m_name; }
503 QString toString() const { return m_name; }
504
504
505 uint compareTo(const AbstractMetaFunction *other) const;
505 uint compareTo(const AbstractMetaFunction *other) const;
506
506
507 bool operator <(const AbstractMetaFunction &a) const;
507 bool operator <(const AbstractMetaFunction &a) const;
508
508
509 AbstractMetaFunction *copy() const;
509 AbstractMetaFunction *copy() const;
510
510
511 QString replacedDefaultExpression(const AbstractMetaClass *cls, int idx) const;
511 QString replacedDefaultExpression(const AbstractMetaClass *cls, int idx) const;
512 bool removedDefaultExpression(const AbstractMetaClass *cls, int idx) const;
512 bool removedDefaultExpression(const AbstractMetaClass *cls, int idx) const;
513 QString conversionRule(TypeSystem::Language language, int idx) const;
513 QString conversionRule(TypeSystem::Language language, int idx) const;
514 QList<ReferenceCount> referenceCounts(const AbstractMetaClass *cls, int idx = -2) const;
514 QList<ReferenceCount> referenceCounts(const AbstractMetaClass *cls, int idx = -2) const;
515
515
516 bool nullPointersDisabled(const AbstractMetaClass *cls = 0, int argument_idx = 0) const;
516 bool nullPointersDisabled(const AbstractMetaClass *cls = 0, int argument_idx = 0) const;
517 QString nullPointerDefaultValue(const AbstractMetaClass *cls = 0, int argument_idx = 0) const;
517 QString nullPointerDefaultValue(const AbstractMetaClass *cls = 0, int argument_idx = 0) const;
518
518
519 bool resetObjectAfterUse(int argument_idx) const;
519 bool resetObjectAfterUse(int argument_idx) const;
520
520
521 // Returns whether garbage collection is disabled for the argument in any context
521 // Returns whether garbage collection is disabled for the argument in any context
522 bool disabledGarbageCollection(const AbstractMetaClass *cls, int key) const;
522 bool disabledGarbageCollection(const AbstractMetaClass *cls, int key) const;
523
523
524 // Returns the ownership rules for the given argument in the given context
524 // Returns the ownership rules for the given argument in the given context
525 TypeSystem::Ownership ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int idx) const;
525 TypeSystem::Ownership ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int idx) const;
526
526
527 bool isVirtualSlot() const;
527 bool isVirtualSlot() const;
528
528
529 QString typeReplaced(int argument_index) const;
529 QString typeReplaced(int argument_index) const;
530 bool isRemovedFromAllLanguages(const AbstractMetaClass *) const;
530 bool isRemovedFromAllLanguages(const AbstractMetaClass *) const;
531 bool isRemovedFrom(const AbstractMetaClass *, TypeSystem::Language language) const;
531 bool isRemovedFrom(const AbstractMetaClass *, TypeSystem::Language language) const;
532 bool argumentRemoved(int) const;
532 bool argumentRemoved(int) const;
533
533
534 QString argumentReplaced(int key) const;
534 QString argumentReplaced(int key) const;
535 bool needsSuppressUncheckedWarning() const;
535 bool needsSuppressUncheckedWarning() const;
536
536
537 bool hasModifications(const AbstractMetaClass *implementor) const;
537 bool hasModifications(const AbstractMetaClass *implementor) const;
538 FunctionModificationList modifications(const AbstractMetaClass *implementor) const;
538 FunctionModificationList modifications(const AbstractMetaClass *implementor) const;
539
539
540 // If this function stems from an interface, this returns the
540 // If this function stems from an interface, this returns the
541 // interface that declares it.
541 // interface that declares it.
542 const AbstractMetaClass *interfaceClass() const { return m_interface_class; }
542 const AbstractMetaClass *interfaceClass() const { return m_interface_class; }
543 void setInterfaceClass(const AbstractMetaClass *cl) { m_interface_class = cl; }
543 void setInterfaceClass(const AbstractMetaClass *cl) { m_interface_class = cl; }
544
544
545 void setPropertySpec(QPropertySpec *spec) { m_property_spec = spec; }
545 void setPropertySpec(QPropertySpec *spec) { m_property_spec = spec; }
546 QPropertySpec *propertySpec() const { return m_property_spec; }
546 QPropertySpec *propertySpec() const { return m_property_spec; }
547
547
548 private:
548 private:
549 QString m_name;
549 QString m_name;
550 QString m_original_name;
550 QString m_original_name;
551 mutable QString m_cached_minimal_signature;
551 mutable QString m_cached_minimal_signature;
552 mutable QString m_cached_modified_name;
552 mutable QString m_cached_modified_name;
553
553
554 FunctionType m_function_type;
554 FunctionType m_function_type;
555 AbstractMetaType *m_type;
555 AbstractMetaType *m_type;
556 const AbstractMetaClass *m_class;
556 const AbstractMetaClass *m_class;
557 const AbstractMetaClass *m_implementing_class;
557 const AbstractMetaClass *m_implementing_class;
558 const AbstractMetaClass *m_declaring_class;
558 const AbstractMetaClass *m_declaring_class;
559 const AbstractMetaClass *m_interface_class;
559 const AbstractMetaClass *m_interface_class;
560 QPropertySpec *m_property_spec;
560 QPropertySpec *m_property_spec;
561 AbstractMetaArgumentList m_arguments;
561 AbstractMetaArgumentList m_arguments;
562 uint m_constant : 1;
562 uint m_constant : 1;
563 uint m_invalid : 1;
563 uint m_invalid : 1;
564 };
564 };
565
565
566
566
567 class AbstractMetaEnumValue
567 class AbstractMetaEnumValue
568 {
568 {
569 public:
569 public:
570 AbstractMetaEnumValue()
570 AbstractMetaEnumValue()
571 : m_value_set(false), m_value(0)
571 : m_value_set(false), m_value(0)
572 {
572 {
573 }
573 }
574
574
575 int value() const { return m_value; }
575 int value() const { return m_value; }
576 void setValue(int value) { m_value_set = true; m_value = value; }
576 void setValue(int value) { m_value_set = true; m_value = value; }
577
577
578 QString stringValue() const { return m_string_value; }
578 QString stringValue() const { return m_string_value; }
579 void setStringValue(const QString &v) { m_string_value = v; }
579 void setStringValue(const QString &v) { m_string_value = v; }
580
580
581 QString name() const { return m_name; }
581 QString name() const { return m_name; }
582 void setName(const QString &name) { m_name = name; }
582 void setName(const QString &name) { m_name = name; }
583
583
584 bool isValueSet() const { return m_value_set; }
584 bool isValueSet() const { return m_value_set; }
585
585
586 private:
586 private:
587 QString m_name;
587 QString m_name;
588 QString m_string_value;
588 QString m_string_value;
589
589
590 bool m_value_set;
590 bool m_value_set;
591 int m_value;
591 int m_value;
592 };
592 };
593
593
594
594
595 class AbstractMetaEnumValueList : public QList<AbstractMetaEnumValue *>
595 class AbstractMetaEnumValueList : public QList<AbstractMetaEnumValue *>
596 {
596 {
597 public:
597 public:
598 AbstractMetaEnumValue *find(const QString &name) const;
598 AbstractMetaEnumValue *find(const QString &name) const;
599 };
599 };
600
600
601 class AbstractMetaEnum : public AbstractMetaAttributes
601 class AbstractMetaEnum : public AbstractMetaAttributes
602 {
602 {
603 public:
603 public:
604 AbstractMetaEnum() : m_type_entry(0), m_class(0), m_has_qenums_declaration(false) {}
604 AbstractMetaEnum() : m_type_entry(0), m_class(0), m_has_qenums_declaration(false) {}
605
605
606 AbstractMetaEnumValueList values() const { return m_enum_values; }
606 AbstractMetaEnumValueList values() const { return m_enum_values; }
607 void addEnumValue(AbstractMetaEnumValue *enumValue) { m_enum_values << enumValue; }
607 void addEnumValue(AbstractMetaEnumValue *enumValue) { m_enum_values << enumValue; }
608
608
609 QString name() const { return m_type_entry->targetLangName(); }
609 QString name() const { return m_type_entry->targetLangName(); }
610 QString qualifier() const { return m_type_entry->javaQualifier(); }
610 QString qualifier() const { return m_type_entry->javaQualifier(); }
611 QString package() const { return m_type_entry->javaPackage(); }
611 QString package() const { return m_type_entry->javaPackage(); }
612 QString fullName() const { return package() + "." + qualifier() + "." + name(); }
612 QString fullName() const { return package() + "." + qualifier() + "." + name(); }
613
613
614 // Has the enum been declared inside a Q_ENUMS() macro in its enclosing class?
614 // Has the enum been declared inside a Q_ENUMS() macro in its enclosing class?
615 void setHasQEnumsDeclaration(bool on) { m_has_qenums_declaration = on; }
615 void setHasQEnumsDeclaration(bool on) { m_has_qenums_declaration = on; }
616 bool hasQEnumsDeclaration() const { return m_has_qenums_declaration; }
616 bool hasQEnumsDeclaration() const { return m_has_qenums_declaration; }
617
617
618 EnumTypeEntry *typeEntry() const { return m_type_entry; }
618 EnumTypeEntry *typeEntry() const { return m_type_entry; }
619 void setTypeEntry(EnumTypeEntry *entry) { m_type_entry = entry; }
619 void setTypeEntry(EnumTypeEntry *entry) { m_type_entry = entry; }
620
620
621 AbstractMetaClass *enclosingClass() const { return m_class; }
621 AbstractMetaClass *enclosingClass() const { return m_class; }
622 void setEnclosingClass(AbstractMetaClass *c) { m_class = c; }
622 void setEnclosingClass(AbstractMetaClass *c) { m_class = c; }
623
623
624 private:
624 private:
625 AbstractMetaEnumValueList m_enum_values;
625 AbstractMetaEnumValueList m_enum_values;
626 EnumTypeEntry *m_type_entry;
626 EnumTypeEntry *m_type_entry;
627 AbstractMetaClass *m_class;
627 AbstractMetaClass *m_class;
628
628
629 uint m_has_qenums_declaration : 1;
629 uint m_has_qenums_declaration : 1;
630 uint m_reserved : 31;
630 uint m_reserved : 31;
631 };
631 };
632
632
633 typedef QList<AbstractMetaEnum *> AbstractMetaEnumList;
633 typedef QList<AbstractMetaEnum *> AbstractMetaEnumList;
634
634
635 class AbstractMetaClass : public AbstractMetaAttributes
635 class AbstractMetaClass : public AbstractMetaAttributes
636 {
636 {
637 public:
637 public:
638 enum FunctionQueryOption {
638 enum FunctionQueryOption {
639 Constructors = 0x000001, // Only constructors
639 Constructors = 0x000001, // Only constructors
640 //Destructors = 0x000002, // Only destructors. Not included in class.
640 //Destructors = 0x000002, // Only destructors. Not included in class.
641 VirtualFunctions = 0x000004, // Only virtual functions (virtual in both TargetLang and C++)
641 VirtualFunctions = 0x000004, // Only virtual functions (virtual in both TargetLang and C++)
642 FinalInTargetLangFunctions = 0x000008, // Only functions that are non-virtual in TargetLang
642 FinalInTargetLangFunctions = 0x000008, // Only functions that are non-virtual in TargetLang
643 FinalInCppFunctions = 0x000010, // Only functions that are non-virtual in C++
643 FinalInCppFunctions = 0x000010, // Only functions that are non-virtual in C++
644 ClassImplements = 0x000020, // Only functions implemented by the current class
644 ClassImplements = 0x000020, // Only functions implemented by the current class
645 Inconsistent = 0x000040, // Only inconsistent functions (inconsistent virtualness in TargetLang/C++)
645 Inconsistent = 0x000040, // Only inconsistent functions (inconsistent virtualness in TargetLang/C++)
646 StaticFunctions = 0x000080, // Only static functions
646 StaticFunctions = 0x000080, // Only static functions
647 Signals = 0x000100, // Only signals
647 Signals = 0x000100, // Only signals
648 NormalFunctions = 0x000200, // Only functions that aren't signals
648 NormalFunctions = 0x000200, // Only functions that aren't signals
649 Visible = 0x000400, // Only public and protected functions
649 Visible = 0x000400, // Only public and protected functions
650 ForcedShellFunctions = 0x000800, // Only functions that are overridden to be implemented in the shell class
650 ForcedShellFunctions = 0x000800, // Only functions that are overridden to be implemented in the shell class
651 WasPublic = 0x001000, // Only functions that were originally public
651 WasPublic = 0x001000, // Only functions that were originally public
652 WasProtected = 0x002000, // Only functions that were originally protected
652 WasProtected = 0x002000, // Only functions that were originally protected
653 NonStaticFunctions = 0x004000, // No static functions
653 NonStaticFunctions = 0x004000, // No static functions
654 Empty = 0x008000, // Empty overrides of abstract functions
654 Empty = 0x008000, // Empty overrides of abstract functions
655 Invisible = 0x010000, // Only private functions
655 Invisible = 0x010000, // Only private functions
656 VirtualInCppFunctions = 0x020000, // Only functions that are virtual in C++
656 VirtualInCppFunctions = 0x020000, // Only functions that are virtual in C++
657 NonEmptyFunctions = 0x040000, // Only functions with JNI implementations
657 NonEmptyFunctions = 0x040000, // Only functions with JNI implementations
658 VirtualInTargetLangFunctions = 0x080000, // Only functions which are virtual in TargetLang
658 VirtualInTargetLangFunctions = 0x080000, // Only functions which are virtual in TargetLang
659 AbstractFunctions = 0x100000, // Only abstract functions
659 AbstractFunctions = 0x100000, // Only abstract functions
660 WasVisible = 0x200000, // Only functions that were public or protected in the original code
660 WasVisible = 0x200000, // Only functions that were public or protected in the original code
661 NotRemovedFromTargetLang = 0x400000, // Only functions that have not been removed from TargetLang
661 NotRemovedFromTargetLang = 0x400000, // Only functions that have not been removed from TargetLang
662 NotRemovedFromShell = 0x800000, // Only functions that have not been removed from the shell class
662 NotRemovedFromShell = 0x800000, // Only functions that have not been removed from the shell class
663 VirtualSlots = 0x1000000 // Only functions that are set as virtual slots in the type system
663 VirtualSlots = 0x1000000 // Only functions that are set as virtual slots in the type system
664 };
664 };
665
665
666 AbstractMetaClass()
666 AbstractMetaClass()
667 : m_namespace(false),
667 : m_namespace(false),
668 m_qobject(false),
668 m_qobject(false),
669 m_has_virtuals(false),
669 m_has_virtuals(false),
670 m_has_nonpublic(false),
670 m_has_nonpublic(false),
671 m_has_virtual_slots(false),
671 m_has_virtual_slots(false),
672 m_has_nonprivateconstructor(false),
672 m_has_nonprivateconstructor(false),
673 m_functions_fixed(false),
673 m_functions_fixed(false),
674 m_has_public_destructor(true),
674 m_has_public_destructor(true),
675 m_force_shell_class(false),
675 m_force_shell_class(false),
676 m_has_hash_function(false),
676 m_has_hash_function(false),
677 m_has_equals_operator(false),
677 m_has_equals_operator(false),
678 m_has_clone_operator(false),
678 m_has_clone_operator(false),
679 m_is_type_alias(false),
679 m_is_type_alias(false),
680 m_enclosing_class(0),
680 m_enclosing_class(0),
681 m_base_class(0),
681 m_base_class(0),
682 m_template_base_class(0),
682 m_template_base_class(0),
683 m_extracted_interface(0),
683 m_extracted_interface(0),
684 m_primary_interface_implementor(0),
684 m_primary_interface_implementor(0),
685 m_type_entry(0),
685 m_type_entry(0),
686 m_qDebug_stream_function(0)
686 m_qDebug_stream_function(0)
687 {
687 {
688 }
688 }
689
689
690 virtual ~AbstractMetaClass();
690 virtual ~AbstractMetaClass();
691
691
692 AbstractMetaClass *extractInterface();
692 AbstractMetaClass *extractInterface();
693 void fixFunctions();
693 void fixFunctions();
694
694
695 AbstractMetaFunctionList functions() const { return m_functions; }
695 AbstractMetaFunctionList functions() const { return m_functions; }
696 void setFunctions(const AbstractMetaFunctionList &functions);
696 void setFunctions(const AbstractMetaFunctionList &functions);
697 void addFunction(AbstractMetaFunction *function);
697 void addFunction(AbstractMetaFunction *function);
698 bool hasFunction(const AbstractMetaFunction *f) const;
698 bool hasFunction(const AbstractMetaFunction *f) const;
699 bool hasFunction(const QString &str) const;
699 bool hasFunction(const QString &str) const;
700 bool hasSignal(const AbstractMetaFunction *f) const;
700 bool hasSignal(const AbstractMetaFunction *f) const;
701
701
702 bool hasConstructors() const;
702 bool hasConstructors() const;
703
703
704 void addDefaultConstructor();
704 void addDefaultConstructor();
705
705
706 bool hasNonPrivateConstructor() const { return m_has_nonprivateconstructor; }
706 bool hasNonPrivateConstructor() const { return m_has_nonprivateconstructor; }
707 void setHasNonPrivateConstructor(bool on) { m_has_nonprivateconstructor = on; }
707 void setHasNonPrivateConstructor(bool on) { m_has_nonprivateconstructor = on; }
708 bool hasPublicDestructor() const { return m_has_public_destructor; }
708 bool hasPublicDestructor() const { return m_has_public_destructor; }
709 void setHasPublicDestructor(bool on) { m_has_public_destructor = on; }
709 void setHasPublicDestructor(bool on) { m_has_public_destructor = on; }
710
710
711 AbstractMetaFunctionList queryFunctionsByName(const QString &name) const;
711 AbstractMetaFunctionList queryFunctionsByName(const QString &name) const;
712 AbstractMetaFunctionList queryFunctions(uint query) const;
712 AbstractMetaFunctionList queryFunctions(uint query) const;
713 inline AbstractMetaFunctionList allVirtualFunctions() const;
713 inline AbstractMetaFunctionList allVirtualFunctions() const;
714 inline AbstractMetaFunctionList allFinalFunctions() const;
714 inline AbstractMetaFunctionList allFinalFunctions() const;
715 AbstractMetaFunctionList functionsInTargetLang() const;
715 AbstractMetaFunctionList functionsInTargetLang() const;
716 AbstractMetaFunctionList functionsInShellClass() const;
716 AbstractMetaFunctionList functionsInShellClass() const;
717 inline AbstractMetaFunctionList cppInconsistentFunctions() const;
717 inline AbstractMetaFunctionList cppInconsistentFunctions() const;
718 inline AbstractMetaFunctionList cppSignalFunctions() const;
718 inline AbstractMetaFunctionList cppSignalFunctions() const;
719 AbstractMetaFunctionList publicOverrideFunctions() const;
719 AbstractMetaFunctionList publicOverrideFunctions() const;
720 AbstractMetaFunctionList virtualOverrideFunctions() const;
720 AbstractMetaFunctionList virtualOverrideFunctions() const;
721 AbstractMetaFunctionList virtualFunctions() const;
721 AbstractMetaFunctionList virtualFunctions() const;
722 AbstractMetaFunctionList nonVirtualShellFunctions() const;
722 AbstractMetaFunctionList nonVirtualShellFunctions() const;
723
723
724 AbstractMetaFieldList fields() const { return m_fields; }
724 AbstractMetaFieldList fields() const { return m_fields; }
725 void setFields(const AbstractMetaFieldList &fields) { m_fields = fields; }
725 void setFields(const AbstractMetaFieldList &fields) { m_fields = fields; }
726 void addField(AbstractMetaField *field) { m_fields << field; }
726 void addField(AbstractMetaField *field) { m_fields << field; }
727
727
728 AbstractMetaEnumList enums() const { return m_enums; }
728 AbstractMetaEnumList enums() const { return m_enums; }
729 void setEnums(const AbstractMetaEnumList &enums) { m_enums = enums; }
729 void setEnums(const AbstractMetaEnumList &enums) { m_enums = enums; }
730 void addEnum(AbstractMetaEnum *e) { m_enums << e; }
730 void addEnum(AbstractMetaEnum *e) { m_enums << e; }
731
731
732 AbstractMetaEnum *findEnum(const QString &enumName);
732 AbstractMetaEnum *findEnum(const QString &enumName);
733 AbstractMetaEnum *findEnumForValue(const QString &enumName);
733 AbstractMetaEnum *findEnumForValue(const QString &enumName);
734 AbstractMetaEnumValue *findEnumValue(const QString &enumName, AbstractMetaEnum *meta_enum);
734 AbstractMetaEnumValue *findEnumValue(const QString &enumName, AbstractMetaEnum *meta_enum);
735
735
736 AbstractMetaClassList interfaces() const { return m_interfaces; }
736 AbstractMetaClassList interfaces() const { return m_interfaces; }
737 void addInterface(AbstractMetaClass *interface);
737 void addInterface(AbstractMetaClass *interface);
738 void setInterfaces(const AbstractMetaClassList &interface);
738 void setInterfaces(const AbstractMetaClassList &interface);
739
739
740 QString fullName() const { return package() + "." + name(); }
740 QString fullName() const { return package() + "." + name(); }
741 QString name() const;
741 QString name() const;
742
742
743 QString baseClassName() const { return m_base_class ? m_base_class->name() : QString(); }
743 QString baseClassName() const { return m_base_class ? m_base_class->name() : QString(); }
744
744
745 AbstractMetaClass *baseClass() const { return m_base_class; }
745 AbstractMetaClass *baseClass() const { return m_base_class; }
746 void setBaseClass(AbstractMetaClass *base_class) { m_base_class = base_class; }
746 void setBaseClass(AbstractMetaClass *base_class) { m_base_class = base_class; }
747
747
748 const AbstractMetaClass *enclosingClass() const { return m_enclosing_class; }
748 const AbstractMetaClass *enclosingClass() const { return m_enclosing_class; }
749 void setEnclosingClass(AbstractMetaClass *cl) { m_enclosing_class = cl; }
749 void setEnclosingClass(AbstractMetaClass *cl) { m_enclosing_class = cl; }
750
750
751 QString package() const { return m_type_entry->javaPackage(); }
751 QString package() const { return m_type_entry->javaPackage(); }
752 bool isInterface() const { return m_type_entry->isInterface(); }
752 bool isInterface() const { return m_type_entry->isInterface(); }
753 bool isNamespace() const { return m_type_entry->isNamespace(); }
753 bool isNamespace() const { return m_type_entry->isNamespace(); }
754 bool isQObject() const { return m_type_entry->isQObject(); }
754 bool isQObject() const { return m_type_entry->isQObject(); }
755 bool isQtNamespace() const { return isNamespace() && name() == "Qt"; }
755 bool isQtNamespace() const { return isNamespace() && name() == "Qt"; }
756 QString qualifiedCppName() const { return m_type_entry->qualifiedCppName(); }
756 QString qualifiedCppName() const { return m_type_entry->qualifiedCppName(); }
757
757
758 bool hasInconsistentFunctions() const;
758 bool hasInconsistentFunctions() const;
759 bool hasSignals() const;
759 bool hasSignals() const;
760 bool inheritsFrom(const AbstractMetaClass *other) const;
760 bool inheritsFrom(const AbstractMetaClass *other) const;
761
761
762 void setForceShellClass(bool on) { m_force_shell_class = on; }
762 void setForceShellClass(bool on) { m_force_shell_class = on; }
763 bool generateShellClass() const;
763 bool generateShellClass() const;
764
764
765 bool hasVirtualSlots() const { return m_has_virtual_slots; }
765 bool hasVirtualSlots() const { return m_has_virtual_slots; }
766 bool hasVirtualFunctions() const { return !isFinal() && m_has_virtuals; }
766 bool hasVirtualFunctions() const { return !isFinal() && m_has_virtuals; }
767 bool hasProtectedFunctions() const;
767 bool hasProtectedFunctions() const;
768
768
769 QList<TypeEntry *> templateArguments() const { return m_template_args; }
769 QList<TypeEntry *> templateArguments() const { return m_template_args; }
770 void setTemplateArguments(const QList<TypeEntry *> &args) { m_template_args = args; }
770 void setTemplateArguments(const QList<TypeEntry *> &args) { m_template_args = args; }
771
771
772 bool hasFieldAccessors() const;
772 bool hasFieldAccessors() const;
773
773
774 // only valid during metajavabuilder's run
774 // only valid during metajavabuilder's run
775 QStringList baseClassNames() const { return m_base_class_names; }
775 QStringList baseClassNames() const { return m_base_class_names; }
776 void setBaseClassNames(const QStringList &names) { m_base_class_names = names; }
776 void setBaseClassNames(const QStringList &names) { m_base_class_names = names; }
777
777
778 AbstractMetaClass *primaryInterfaceImplementor() const { return m_primary_interface_implementor; }
778 AbstractMetaClass *primaryInterfaceImplementor() const { return m_primary_interface_implementor; }
779 void setPrimaryInterfaceImplementor(AbstractMetaClass *cl) { m_primary_interface_implementor = cl; }
779 void setPrimaryInterfaceImplementor(AbstractMetaClass *cl) { m_primary_interface_implementor = cl; }
780
780
781 const ComplexTypeEntry *typeEntry() const { return m_type_entry; }
781 const ComplexTypeEntry *typeEntry() const { return m_type_entry; }
782 ComplexTypeEntry *typeEntry() { return m_type_entry; }
782 ComplexTypeEntry *typeEntry() { return m_type_entry; }
783 void setTypeEntry(ComplexTypeEntry *type) { m_type_entry = type; }
783 void setTypeEntry(ComplexTypeEntry *type) { m_type_entry = type; }
784
784
785 void setHasHashFunction(bool on) { m_has_hash_function = on; }
785 void setHasHashFunction(bool on) { m_has_hash_function = on; }
786 bool hasHashFunction() const { return m_has_hash_function; }
786 bool hasHashFunction() const { return m_has_hash_function; }
787
787
788 void setToStringCapability(FunctionModelItem fun) { m_qDebug_stream_function= fun; }
788 void setToStringCapability(FunctionModelItem fun) { m_qDebug_stream_function= fun; }
789 FunctionModelItem hasToStringCapability() const { return m_qDebug_stream_function; }
789 FunctionModelItem hasToStringCapability() const { return m_qDebug_stream_function; }
790
790
791 virtual bool hasDefaultToStringFunction() const;
791 virtual bool hasDefaultToStringFunction() const;
792
792
793 void setHasEqualsOperator(bool on) { m_has_equals_operator = on; }
793 void setHasEqualsOperator(bool on) { m_has_equals_operator = on; }
794 bool hasEqualsOperator() const { return m_has_equals_operator; }
794 bool hasEqualsOperator() const { return m_has_equals_operator; }
795
795
796 void setHasCloneOperator(bool on) { m_has_clone_operator = on; }
796 void setHasCloneOperator(bool on) { m_has_clone_operator = on; }
797 bool hasCloneOperator() const { return m_has_clone_operator; }
797 bool hasCloneOperator() const { return m_has_clone_operator; }
798
798
799 bool hasDefaultIsNull() const;
800
799 void addPropertySpec(QPropertySpec *spec) { m_property_specs << spec; }
801 void addPropertySpec(QPropertySpec *spec) { m_property_specs << spec; }
800 QList<QPropertySpec *> propertySpecs() const { return m_property_specs; }
802 QList<QPropertySpec *> propertySpecs() const { return m_property_specs; }
801
803
802 QPropertySpec *propertySpecForRead(const QString &name) const;
804 QPropertySpec *propertySpecForRead(const QString &name) const;
803 QPropertySpec *propertySpecForWrite(const QString &name) const;
805 QPropertySpec *propertySpecForWrite(const QString &name) const;
804 QPropertySpec *propertySpecForReset(const QString &name) const;
806 QPropertySpec *propertySpecForReset(const QString &name) const;
805
807
806 QList<ReferenceCount> referenceCounts() const;
808 QList<ReferenceCount> referenceCounts() const;
807
809
808 void setEqualsFunctions(const AbstractMetaFunctionList &lst) { m_equals_functions = lst; }
810 void setEqualsFunctions(const AbstractMetaFunctionList &lst) { m_equals_functions = lst; }
809 AbstractMetaFunctionList equalsFunctions() const { return m_equals_functions; }
811 AbstractMetaFunctionList equalsFunctions() const { return m_equals_functions; }
810
812
811 void setNotEqualsFunctions(const AbstractMetaFunctionList &lst) { m_nequals_functions = lst; }
813 void setNotEqualsFunctions(const AbstractMetaFunctionList &lst) { m_nequals_functions = lst; }
812 AbstractMetaFunctionList notEqualsFunctions() const { return m_nequals_functions; }
814 AbstractMetaFunctionList notEqualsFunctions() const { return m_nequals_functions; }
813
815
814 void setLessThanFunctions(const AbstractMetaFunctionList &lst) { m_less_than_functions = lst; }
816 void setLessThanFunctions(const AbstractMetaFunctionList &lst) { m_less_than_functions = lst; }
815 AbstractMetaFunctionList lessThanFunctions() const { return m_less_than_functions; }
817 AbstractMetaFunctionList lessThanFunctions() const { return m_less_than_functions; }
816
818
817 void setGreaterThanFunctions(const AbstractMetaFunctionList &lst) { m_greater_than_functions = lst; }
819 void setGreaterThanFunctions(const AbstractMetaFunctionList &lst) { m_greater_than_functions = lst; }
818 AbstractMetaFunctionList greaterThanFunctions() const { return m_greater_than_functions; }
820 AbstractMetaFunctionList greaterThanFunctions() const { return m_greater_than_functions; }
819
821
820 void setLessThanEqFunctions(const AbstractMetaFunctionList &lst) { m_less_than_eq_functions = lst; }
822 void setLessThanEqFunctions(const AbstractMetaFunctionList &lst) { m_less_than_eq_functions = lst; }
821 AbstractMetaFunctionList lessThanEqFunctions() const { return m_less_than_eq_functions; }
823 AbstractMetaFunctionList lessThanEqFunctions() const { return m_less_than_eq_functions; }
822
824
823 void setGreaterThanEqFunctions(const AbstractMetaFunctionList &lst) { m_greater_than_eq_functions = lst; }
825 void setGreaterThanEqFunctions(const AbstractMetaFunctionList &lst) { m_greater_than_eq_functions = lst; }
824 AbstractMetaFunctionList greaterThanEqFunctions() const { return m_greater_than_eq_functions; }
826 AbstractMetaFunctionList greaterThanEqFunctions() const { return m_greater_than_eq_functions; }
825
827
826 void sortFunctions();
828 void sortFunctions();
827
829
828 const AbstractMetaClass *templateBaseClass() const { return m_template_base_class; }
830 const AbstractMetaClass *templateBaseClass() const { return m_template_base_class; }
829 void setTemplateBaseClass(const AbstractMetaClass *cls) { m_template_base_class = cls; }
831 void setTemplateBaseClass(const AbstractMetaClass *cls) { m_template_base_class = cls; }
830
832
831 void setTypeAlias(bool typeAlias) { m_is_type_alias = typeAlias; }
833 void setTypeAlias(bool typeAlias) { m_is_type_alias = typeAlias; }
832 bool isTypeAlias() const { return m_is_type_alias; }
834 bool isTypeAlias() const { return m_is_type_alias; }
833
835
834 bool operator <(const AbstractMetaClass &a) const {
836 bool operator <(const AbstractMetaClass &a) const {
835 return qualifiedCppName() < a.qualifiedCppName();
837 return qualifiedCppName() < a.qualifiedCppName();
836 }
838 }
837
839
838 private:
840 private:
839 uint m_namespace : 1;
841 uint m_namespace : 1;
840 uint m_qobject : 1;
842 uint m_qobject : 1;
841 uint m_has_virtuals : 1;
843 uint m_has_virtuals : 1;
842 uint m_has_nonpublic : 1;
844 uint m_has_nonpublic : 1;
843 uint m_has_virtual_slots : 1;
845 uint m_has_virtual_slots : 1;
844 uint m_has_nonprivateconstructor : 1;
846 uint m_has_nonprivateconstructor : 1;
845 uint m_functions_fixed : 1;
847 uint m_functions_fixed : 1;
846 uint m_has_public_destructor : 1;
848 uint m_has_public_destructor : 1;
847 uint m_force_shell_class : 1;
849 uint m_force_shell_class : 1;
848 uint m_has_hash_function : 1;
850 uint m_has_hash_function : 1;
849 uint m_has_equals_operator : 1;
851 uint m_has_equals_operator : 1;
850 uint m_has_clone_operator :1;
852 uint m_has_clone_operator :1;
851 uint m_is_type_alias : 1;
853 uint m_is_type_alias : 1;
852 uint m_reserved : 19;
854 uint m_reserved : 19;
853
855
854 const AbstractMetaClass *m_enclosing_class;
856 const AbstractMetaClass *m_enclosing_class;
855 AbstractMetaClass *m_base_class;
857 AbstractMetaClass *m_base_class;
856 const AbstractMetaClass *m_template_base_class;
858 const AbstractMetaClass *m_template_base_class;
857 AbstractMetaFunctionList m_functions;
859 AbstractMetaFunctionList m_functions;
858 AbstractMetaFieldList m_fields;
860 AbstractMetaFieldList m_fields;
859 AbstractMetaEnumList m_enums;
861 AbstractMetaEnumList m_enums;
860 AbstractMetaClassList m_interfaces;
862 AbstractMetaClassList m_interfaces;
861 AbstractMetaClass *m_extracted_interface;
863 AbstractMetaClass *m_extracted_interface;
862 AbstractMetaClass *m_primary_interface_implementor;
864 AbstractMetaClass *m_primary_interface_implementor;
863 QList<QPropertySpec *> m_property_specs;
865 QList<QPropertySpec *> m_property_specs;
864 AbstractMetaFunctionList m_equals_functions;
866 AbstractMetaFunctionList m_equals_functions;
865 AbstractMetaFunctionList m_nequals_functions;
867 AbstractMetaFunctionList m_nequals_functions;
866
868
867 AbstractMetaFunctionList m_less_than_functions;
869 AbstractMetaFunctionList m_less_than_functions;
868 AbstractMetaFunctionList m_greater_than_functions;
870 AbstractMetaFunctionList m_greater_than_functions;
869 AbstractMetaFunctionList m_less_than_eq_functions;
871 AbstractMetaFunctionList m_less_than_eq_functions;
870 AbstractMetaFunctionList m_greater_than_eq_functions;
872 AbstractMetaFunctionList m_greater_than_eq_functions;
871
873
872 QStringList m_base_class_names;
874 QStringList m_base_class_names;
873 QList<TypeEntry *> m_template_args;
875 QList<TypeEntry *> m_template_args;
874 ComplexTypeEntry *m_type_entry;
876 ComplexTypeEntry *m_type_entry;
875 FunctionModelItem m_qDebug_stream_function;
877 FunctionModelItem m_qDebug_stream_function;
876 };
878 };
877
879
878 class QPropertySpec {
880 class QPropertySpec {
879 public:
881 public:
880 QPropertySpec(const TypeEntry *type)
882 QPropertySpec(const TypeEntry *type)
881 : m_type(type),
883 : m_type(type),
882 m_index(-1)
884 m_index(-1)
883 {
885 {
884 }
886 }
885
887
886 const TypeEntry *type() const { return m_type; }
888 const TypeEntry *type() const { return m_type; }
887
889
888 QString name() const { return m_name; }
890 QString name() const { return m_name; }
889 void setName(const QString &name) { m_name = name; }
891 void setName(const QString &name) { m_name = name; }
890
892
891 QString read() const { return m_read; }
893 QString read() const { return m_read; }
892 void setRead(const QString &read) { m_read = read; }
894 void setRead(const QString &read) { m_read = read; }
893
895
894 QString write() const { return m_write; }
896 QString write() const { return m_write; }
895 void setWrite(const QString &write) { m_write = write; }
897 void setWrite(const QString &write) { m_write = write; }
896
898
897 QString designable() const { return m_designable; }
899 QString designable() const { return m_designable; }
898 void setDesignable(const QString &designable) { m_designable = designable; }
900 void setDesignable(const QString &designable) { m_designable = designable; }
899
901
900 QString reset() const { return m_reset; }
902 QString reset() const { return m_reset; }
901 void setReset(const QString &reset) { m_reset = reset; }
903 void setReset(const QString &reset) { m_reset = reset; }
902
904
903 int index() const { return m_index; }
905 int index() const { return m_index; }
904 void setIndex(int index) { m_index = index; }
906 void setIndex(int index) { m_index = index; }
905
907
906 private:
908 private:
907 QString m_name;
909 QString m_name;
908 QString m_read;
910 QString m_read;
909 QString m_write;
911 QString m_write;
910 QString m_designable;
912 QString m_designable;
911 QString m_reset;
913 QString m_reset;
912 const TypeEntry *m_type;
914 const TypeEntry *m_type;
913 int m_index;
915 int m_index;
914 };
916 };
915
917
916 inline AbstractMetaFunctionList AbstractMetaClass::allVirtualFunctions() const
918 inline AbstractMetaFunctionList AbstractMetaClass::allVirtualFunctions() const
917 {
919 {
918 return queryFunctions(VirtualFunctions
920 return queryFunctions(VirtualFunctions
919 | NotRemovedFromTargetLang);
921 | NotRemovedFromTargetLang);
920 }
922 }
921
923
922 inline AbstractMetaFunctionList AbstractMetaClass::allFinalFunctions() const
924 inline AbstractMetaFunctionList AbstractMetaClass::allFinalFunctions() const
923 {
925 {
924 return queryFunctions(FinalInTargetLangFunctions
926 return queryFunctions(FinalInTargetLangFunctions
925 | FinalInCppFunctions
927 | FinalInCppFunctions
926 | NotRemovedFromTargetLang);
928 | NotRemovedFromTargetLang);
927 }
929 }
928
930
929 inline AbstractMetaFunctionList AbstractMetaClass::cppInconsistentFunctions() const
931 inline AbstractMetaFunctionList AbstractMetaClass::cppInconsistentFunctions() const
930 {
932 {
931 return queryFunctions(Inconsistent
933 return queryFunctions(Inconsistent
932 | NormalFunctions
934 | NormalFunctions
933 | Visible
935 | Visible
934 | NotRemovedFromTargetLang);
936 | NotRemovedFromTargetLang);
935 }
937 }
936
938
937 inline AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const
939 inline AbstractMetaFunctionList AbstractMetaClass::cppSignalFunctions() const
938 {
940 {
939 return queryFunctions(Signals
941 return queryFunctions(Signals
940 | Visible
942 | Visible
941 | NotRemovedFromTargetLang);
943 | NotRemovedFromTargetLang);
942 }
944 }
943
945
944 #endif // ABSTRACTMETALANG_H
946 #endif // ABSTRACTMETALANG_H
@@ -1,235 +1,297
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 QString& package, const AbstractMetaClass *cls)
49 void SetupGenerator::addClass(const QString& package, const AbstractMetaClass *cls)
50 {
50 {
51 packHash[package].append(cls);
51 packHash[package].append(cls);
52 }
52 }
53
53
54 void maybeDeclareMetaType(QTextStream &stream, const QString &typeName,
54 void maybeDeclareMetaType(QTextStream &stream, const QString &typeName,
55 QSet<QString> &registeredTypeNames);
55 QSet<QString> &registeredTypeNames);
56 bool hasDefaultConstructor(const AbstractMetaClass *meta_class);
56 bool hasDefaultConstructor(const AbstractMetaClass *meta_class);
57
57
58 static QStringList getOperatorCodes(const AbstractMetaClass* cls) {
59 QSet<QString> operatorCodes;
60 AbstractMetaFunctionList returned;
61 AbstractMetaFunctionList functions = cls->functions();
62 foreach (AbstractMetaFunction *function, functions) {
63 if (function->originalName().startsWith("operator")) {
64 QString op = function->originalName().mid(8);
65 operatorCodes.insert(op);
66 }
67 }
68 QSet<QString> r;
69 foreach(QString op, operatorCodes.toList()) {
70 if (op == ">" || op == "<" || op == ">=" || op == "<=" || op == "==" || op == "!=") {
71 r.insert("PythonQt::Type_RichCompare");
72 } else if (op == "+") {
73 r.insert("PythonQt::Type_Add");
74 } else if (op == "-") {
75 r.insert("PythonQt::Type_Subtract");
76 } else if (op == "/") {
77 r.insert("PythonQt::Type_Divide");
78 } else if (op == "*") {
79 r.insert("PythonQt::Type_Multiply");
80 } else if (op == "%") {
81 r.insert("PythonQt::Type_Mod");
82 } else if (op == "&") {
83 r.insert("PythonQt::Type_And");
84 } else if (op == "|") {
85 r.insert("PythonQt::Type_Or");
86 } else if (op == "^") {
87 r.insert("PythonQt::Type_Xor");
88 } else if (op == "~") {
89 r.insert("PythonQt::Type_Invert");
90
91 } else if (op == "+=") {
92 r.insert("PythonQt::Type_InplaceAdd");
93 } else if (op == "-=") {
94 r.insert("PythonQt::Type_InplaceSubtract");
95 } else if (op == "/=") {
96 r.insert("PythonQt::Type_InplaceDivide");
97 } else if (op == "*=") {
98 r.insert("PythonQt::Type_InplaceMultiply");
99 } else if (op == "%=") {
100 r.insert("PythonQt::Type_InplaceMod");
101 } else if (op == "&=") {
102 r.insert("PythonQt::Type_InplaceAnd");
103 } else if (op == "|=") {
104 r.insert("PythonQt::Type_InplaceOr");
105 } else if (op == "^=") {
106 r.insert("PythonQt::Type_InplaceXor");
107 }
108 }
109 if (cls->hasDefaultIsNull()) {
110 r.insert("PythonQt::Type_NonZero");
111 }
112 QStringList result = r.toList();
113 return result;
114 }
115
58 void SetupGenerator::generate()
116 void SetupGenerator::generate()
59 {
117 {
60 AbstractMetaClassList classes_with_polymorphic_id;
118 AbstractMetaClassList classes_with_polymorphic_id;
61 {
119 {
62 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
120 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
63 while (pack.hasNext()) {
121 while (pack.hasNext()) {
64 pack.next();
122 pack.next();
65 QList<const AbstractMetaClass*> list = pack.value();
123 QList<const AbstractMetaClass*> list = pack.value();
66 foreach (const AbstractMetaClass *cls, list) {
124 foreach (const AbstractMetaClass *cls, list) {
67 if (cls->typeEntry()->isPolymorphicBase()) {
125 if (cls->typeEntry()->isPolymorphicBase()) {
68 classes_with_polymorphic_id.append((AbstractMetaClass*)cls);
126 classes_with_polymorphic_id.append((AbstractMetaClass*)cls);
69 }
127 }
70 }
128 }
71 }
129 }
72 }
130 }
73
131
74 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
132 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
75 while (pack.hasNext()) {
133 while (pack.hasNext()) {
76 pack.next();
134 pack.next();
77 QList<const AbstractMetaClass*> list = pack.value();
135 QList<const AbstractMetaClass*> list = pack.value();
78 if (list.isEmpty())
136 if (list.isEmpty())
79 continue;
137 continue;
80
138
81 QString packKey = pack.key();
139 QString packKey = pack.key();
82 QString packName = pack.key();
140 QString packName = pack.key();
83 QStringList components = packName.split("_");
141 QStringList components = packName.split("_");
84 if ((components.size() > 2) && (components.at(0) == "com")
142 if ((components.size() > 2) && (components.at(0) == "com")
85 && (components.at(1) == "trolltech")) {
143 && (components.at(1) == "trolltech")) {
86 // kill com.trolltech in key
144 // kill com.trolltech in key
87 components.removeAt(0);
145 components.removeAt(0);
88 components.removeAt(0);
146 components.removeAt(0);
89 }
147 }
90
148
91 QString shortPackName;
149 QString shortPackName;
92 foreach (QString comp, components) {
150 foreach (QString comp, components) {
93 comp[0] = comp[0].toUpper();
151 comp[0] = comp[0].toUpper();
94 shortPackName += comp;
152 shortPackName += comp;
95 }
153 }
96 // add missing camel case (workaround..)
154 // add missing camel case (workaround..)
97 if (shortPackName == "QtWebkit") {
155 if (shortPackName == "QtWebkit") {
98 shortPackName = "QtWebKit";
156 shortPackName = "QtWebKit";
99 } else if (shortPackName == "QtXmlpatterns") {
157 } else if (shortPackName == "QtXmlpatterns") {
100 shortPackName = "QtXmlPatterns";
158 shortPackName = "QtXmlPatterns";
101 } else if (shortPackName == "QtOpengl") {
159 } else if (shortPackName == "QtOpengl") {
102 shortPackName = "QtOpenGL";
160 shortPackName = "QtOpenGL";
103 } else if (shortPackName == "QtUitools") {
161 } else if (shortPackName == "QtUitools") {
104 shortPackName = "QtUiTools";
162 shortPackName = "QtUiTools";
105 }
163 }
106
164
107
165
108 {
166 {
109 FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp");
167 FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp");
110 QTextStream &s = initFile.stream;
168 QTextStream &s = initFile.stream;
111
169
112 s << "#include <PythonQt.h>" << endl;
170 s << "#include <PythonQt.h>" << endl;
113
171
114 for (int i=0; i<(list.count()+MAX_CLASSES_PER_FILE-1) / MAX_CLASSES_PER_FILE; i++) {
172 for (int i=0; i<(list.count()+MAX_CLASSES_PER_FILE-1) / MAX_CLASSES_PER_FILE; i++) {
115 s << "#include \"" << packKey << QString::number(i) << ".h\"" << endl;
173 s << "#include \"" << packKey << QString::number(i) << ".h\"" << endl;
116 }
174 }
117 s << endl;
175 s << endl;
118
176
119 QStringList polymorphicHandlers;
177 QStringList polymorphicHandlers;
120 if (!packName.endsWith("_builtin")) {
178 if (!packName.endsWith("_builtin")) {
121 polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id);
179 polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id);
122 s << endl;
180 s << endl;
123 }
181 }
124
182
125 // declare individual class creation functions
183 // declare individual class creation functions
126 s << "void PythonQt_init_" << shortPackName << "(PyObject* module) {" << endl;
184 s << "void PythonQt_init_" << shortPackName << "(PyObject* module) {" << endl;
127
185
128 if (shortPackName.endsWith("Builtin")) {
186 if (shortPackName.endsWith("Builtin")) {
129 shortPackName = shortPackName.mid(0, shortPackName.length()-strlen("builtin"));
187 shortPackName = shortPackName.mid(0, shortPackName.length()-strlen("builtin"));
130 }
188 }
131
189
132 QStringList cppClassNames;
190 QStringList cppClassNames;
133 foreach (const AbstractMetaClass *cls, list) {
191 foreach (const AbstractMetaClass *cls, list) {
134
192
135 QString shellCreator;
193 QString shellCreator;
136 if (cls->generateShellClass()) {
194 if (cls->generateShellClass()) {
137 shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">";
195 shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">";
138 } else {
196 } else {
139 shellCreator = ", NULL";
197 shellCreator = ", NULL";
140 }
198 }
199 QString operatorCodes = getOperatorCodes(cls).join("|");
200 if (operatorCodes.isEmpty()) {
201 operatorCodes = "0";
202 }
141 if (cls->isQObject()) {
203 if (cls->isQObject()) {
142 s << "PythonQt::priv()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module);" << endl;
204 s << "PythonQt::priv()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl;
143 } else {
205 } else {
144 QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():"";
206 QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():"";
145 s << "PythonQt::priv()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module);" << endl;
207 s << "PythonQt::priv()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl;
146 }
208 }
147 foreach(AbstractMetaClass* interface, cls->interfaces()) {
209 foreach(AbstractMetaClass* interface, cls->interfaces()) {
148 // the interface might be our own class... (e.g. QPaintDevice)
210 // the interface might be our own class... (e.g. QPaintDevice)
149 if (interface->qualifiedCppName() != cls->qualifiedCppName()) {
211 if (interface->qualifiedCppName() != cls->qualifiedCppName()) {
150 s << "PythonQt::self()->addParentClass(\""<< cls->qualifiedCppName() << "\", \"" << interface->qualifiedCppName() << "\",PythonQtUpcastingOffset<" << cls->qualifiedCppName() <<","<<interface->qualifiedCppName()<<">());" << endl;
212 s << "PythonQt::self()->addParentClass(\""<< cls->qualifiedCppName() << "\", \"" << interface->qualifiedCppName() << "\",PythonQtUpcastingOffset<" << cls->qualifiedCppName() <<","<<interface->qualifiedCppName()<<">());" << endl;
151 }
213 }
152 }
214 }
153 }
215 }
154 s << endl;
216 s << endl;
155 foreach (QString handler, polymorphicHandlers) {
217 foreach (QString handler, polymorphicHandlers) {
156 s << "PythonQt::self()->addPolymorphicHandler(\""<< handler << "\", polymorphichandler_" << handler << ");" << endl;
218 s << "PythonQt::self()->addPolymorphicHandler(\""<< handler << "\", polymorphichandler_" << handler << ");" << endl;
157 }
219 }
158
220
159 s << "}";
221 s << "}";
160 s << endl;
222 s << endl;
161 }
223 }
162 }
224 }
163 }
225 }
164
226
165 QStringList SetupGenerator::writePolymorphicHandler(QTextStream &s, const QString &package,
227 QStringList SetupGenerator::writePolymorphicHandler(QTextStream &s, const QString &package,
166 const AbstractMetaClassList &classes)
228 const AbstractMetaClassList &classes)
167 {
229 {
168 QStringList handlers;
230 QStringList handlers;
169 foreach (AbstractMetaClass *cls, classes) {
231 foreach (AbstractMetaClass *cls, classes) {
170 const ComplexTypeEntry *centry = cls->typeEntry();
232 const ComplexTypeEntry *centry = cls->typeEntry();
171 if (!centry->isPolymorphicBase())
233 if (!centry->isPolymorphicBase())
172 continue;
234 continue;
173 bool isGraphicsItem = (cls->qualifiedCppName()=="QGraphicsItem");
235 bool isGraphicsItem = (cls->qualifiedCppName()=="QGraphicsItem");
174
236
175 AbstractMetaClassList classList = this->classes();
237 AbstractMetaClassList classList = this->classes();
176 bool first = true;
238 bool first = true;
177 foreach (AbstractMetaClass *clazz, classList) {
239 foreach (AbstractMetaClass *clazz, classList) {
178 bool inherits = false;
240 bool inherits = false;
179 if (isGraphicsItem) {
241 if (isGraphicsItem) {
180 foreach(AbstractMetaClass* interfaze, clazz->interfaces()) {
242 foreach(AbstractMetaClass* interfaze, clazz->interfaces()) {
181 if (interfaze->qualifiedCppName()=="QGraphicsItem") {
243 if (interfaze->qualifiedCppName()=="QGraphicsItem") {
182 inherits = true;
244 inherits = true;
183 break;
245 break;
184 }
246 }
185 }
247 }
186 } else {
248 } else {
187 inherits = clazz->inheritsFrom(cls);
249 inherits = clazz->inheritsFrom(cls);
188 }
250 }
189 if (clazz->package() == package && inherits) {
251 if (clazz->package() == package && inherits) {
190 if (!clazz->typeEntry()->polymorphicIdValue().isEmpty() || isGraphicsItem) {
252 if (!clazz->typeEntry()->polymorphicIdValue().isEmpty() || isGraphicsItem) {
191 // On first find, open the function
253 // On first find, open the function
192 if (first) {
254 if (first) {
193 first = false;
255 first = false;
194
256
195 QString handler = cls->name();
257 QString handler = cls->name();
196 handlers.append(handler);
258 handlers.append(handler);
197
259
198 s << "static void* polymorphichandler_" << handler
260 s << "static void* polymorphichandler_" << handler
199 << "(const void *ptr, char **class_name)" << endl
261 << "(const void *ptr, char **class_name)" << endl
200 << "{" << endl
262 << "{" << endl
201 << " Q_ASSERT(ptr != 0);" << endl
263 << " Q_ASSERT(ptr != 0);" << endl
202 << " " << cls->qualifiedCppName() << " *object = ("
264 << " " << cls->qualifiedCppName() << " *object = ("
203 << cls->qualifiedCppName() << " *)ptr;" << endl;
265 << cls->qualifiedCppName() << " *)ptr;" << endl;
204 }
266 }
205
267
206 // For each, add case label
268 // For each, add case label
207 QString polyId = clazz->typeEntry()->polymorphicIdValue();
269 QString polyId = clazz->typeEntry()->polymorphicIdValue();
208 if (isGraphicsItem) {
270 if (isGraphicsItem) {
209 polyId = "%1->type() == " + clazz->qualifiedCppName() + "::Type";
271 polyId = "%1->type() == " + clazz->qualifiedCppName() + "::Type";
210 }
272 }
211 s << " if ("
273 s << " if ("
212 << polyId.replace("%1", "object")
274 << polyId.replace("%1", "object")
213 << ") {" << endl
275 << ") {" << endl
214 << " *class_name = \"" << clazz->name() << "\";" << endl
276 << " *class_name = \"" << clazz->name() << "\";" << endl
215 << " return (" << clazz->qualifiedCppName() << "*)object;" << endl
277 << " return (" << clazz->qualifiedCppName() << "*)object;" << endl
216 << " }" << endl;
278 << " }" << endl;
217 } else {
279 } else {
218 QString warning = QString("class '%1' inherits from polymorphic class '%2', but has no polymorphic id set")
280 QString warning = QString("class '%1' inherits from polymorphic class '%2', but has no polymorphic id set")
219 .arg(clazz->name())
281 .arg(clazz->name())
220 .arg(cls->name());
282 .arg(cls->name());
221
283
222 ReportHandler::warning(warning);
284 ReportHandler::warning(warning);
223 }
285 }
224 }
286 }
225 }
287 }
226
288
227 // Close the function if it has been opened
289 // Close the function if it has been opened
228 if (!first) {
290 if (!first) {
229 s << " return NULL;" << endl
291 s << " return NULL;" << endl
230 << "}" << endl;
292 << "}" << endl;
231 }
293 }
232 }
294 }
233
295
234 return handlers;
296 return handlers;
235 }
297 }
@@ -1,310 +1,313
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
54
55 void ShellHeaderGenerator::writeFieldAccessors(QTextStream &s, const AbstractMetaField *field)
55 void ShellHeaderGenerator::writeFieldAccessors(QTextStream &s, const AbstractMetaField *field)
56 {
56 {
57 const AbstractMetaFunction *setter = field->setter();
57 const AbstractMetaFunction *setter = field->setter();
58 const AbstractMetaFunction *getter = field->getter();
58 const AbstractMetaFunction *getter = field->getter();
59
59
60 // static fields are not supported (yet?)
60 // static fields are not supported (yet?)
61 if (setter->isStatic()) return;
61 if (setter->isStatic()) return;
62
62
63 // Uuid data4 did not work (TODO: move to typesystem...(
63 // Uuid data4 did not work (TODO: move to typesystem...(
64 if (field->enclosingClass()->name()=="QUuid" && setter->name()=="data4") return;
64 if (field->enclosingClass()->name()=="QUuid" && setter->name()=="data4") return;
65 if (field->enclosingClass()->name()=="QIPv6Address") return;
65 if (field->enclosingClass()->name()=="QIPv6Address") return;
66
66
67 if (!field->type()->isConstant()) {
67 if (!field->type()->isConstant()) {
68 writeFunctionSignature(s, setter, 0, QString(),
68 writeFunctionSignature(s, setter, 0, QString(),
69 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | ShowStatic | UnderscoreSpaces));
69 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | ShowStatic | UnderscoreSpaces));
70 s << "{ theWrappedObject->" << field->name() << " = " << setter->arguments()[0]->argumentName() << "; }\n";
70 s << "{ theWrappedObject->" << field->name() << " = " << setter->arguments()[0]->argumentName() << "; }\n";
71 }
71 }
72
72
73 writeFunctionSignature(s, getter, 0, QString(),
73 writeFunctionSignature(s, getter, 0, QString(),
74 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
74 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
75 s << "{ return theWrappedObject->" << field->name() << "; }\n";
75 s << "{ return theWrappedObject->" << field->name() << "; }\n";
76 }
76 }
77
77
78 void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
78 void ShellHeaderGenerator::write(QTextStream &s, const AbstractMetaClass *meta_class)
79 {
79 {
80 QString builtIn = ShellGenerator::isBuiltIn(meta_class->name())?"_builtin":"";
80 QString builtIn = ShellGenerator::isBuiltIn(meta_class->name())?"_builtin":"";
81 QString pro_file_name = meta_class->package().replace(".", "_") + builtIn + "/" + meta_class->package().replace(".", "_") + builtIn + ".pri";
81 QString pro_file_name = meta_class->package().replace(".", "_") + builtIn + "/" + meta_class->package().replace(".", "_") + builtIn + ".pri";
82 priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
82 priGenerator->addHeader(pro_file_name, fileNameForClass(meta_class));
83 setupGenerator->addClass(meta_class->package().replace(".", "_") + builtIn, meta_class);
83 setupGenerator->addClass(meta_class->package().replace(".", "_") + builtIn, meta_class);
84
84
85 QString include_block = "PYTHONQTWRAPPER_" + meta_class->name().toUpper() + "_H";
85 QString include_block = "PYTHONQTWRAPPER_" + meta_class->name().toUpper() + "_H";
86
86
87 s << "#ifndef " << include_block << endl
87 s << "#ifndef " << include_block << endl
88 << "#define " << include_block << endl << endl;
88 << "#define " << include_block << endl << endl;
89
89
90 Include inc = meta_class->typeEntry()->include();
90 Include inc = meta_class->typeEntry()->include();
91 ShellGenerator::writeInclude(s, inc);
91 ShellGenerator::writeInclude(s, inc);
92
92
93 s << "#include <QObject>" << endl << endl;
93 s << "#include <QObject>" << endl << endl;
94 s << "#include <PythonQt.h>" << endl << endl;
94 s << "#include <PythonQt.h>" << endl << endl;
95
95
96 IncludeList list = meta_class->typeEntry()->extraIncludes();
96 IncludeList list = meta_class->typeEntry()->extraIncludes();
97 qSort(list.begin(), list.end());
97 qSort(list.begin(), list.end());
98 foreach (const Include &inc, list) {
98 foreach (const Include &inc, list) {
99 ShellGenerator::writeInclude(s, inc);
99 ShellGenerator::writeInclude(s, inc);
100 }
100 }
101 s << endl;
101 s << endl;
102
102
103 AbstractMetaFunctionList ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
103 AbstractMetaFunctionList ctors = meta_class->queryFunctions(AbstractMetaClass::Constructors
104 | AbstractMetaClass::WasVisible
104 | AbstractMetaClass::WasVisible
105 | AbstractMetaClass::NotRemovedFromTargetLang);
105 | AbstractMetaClass::NotRemovedFromTargetLang);
106
106
107 // Shell-------------------------------------------------------------------
107 // Shell-------------------------------------------------------------------
108 if (meta_class->generateShellClass()) {
108 if (meta_class->generateShellClass()) {
109
109
110 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
110 AbstractMetaFunctionList virtualsForShell = getVirtualFunctionsForShell(meta_class);
111
111
112 s << "class " << shellClassName(meta_class)
112 s << "class " << shellClassName(meta_class)
113 << " : public " << meta_class->qualifiedCppName() << endl << "{" << endl;
113 << " : public " << meta_class->qualifiedCppName() << endl << "{" << endl;
114 s << "public:" << endl;
114 s << "public:" << endl;
115 foreach(AbstractMetaFunction* fun, ctors) {
115 foreach(AbstractMetaFunction* fun, ctors) {
116 s << " ";
116 s << " ";
117 writeFunctionSignature(s, fun, 0,"PythonQtShell_",
117 writeFunctionSignature(s, fun, 0,"PythonQtShell_",
118 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
118 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
119 s << ":" << meta_class->qualifiedCppName() << "(";
119 s << ":" << meta_class->qualifiedCppName() << "(";
120 QString scriptFunctionName = fun->originalName();
120 QString scriptFunctionName = fun->originalName();
121 AbstractMetaArgumentList args = fun->arguments();
121 AbstractMetaArgumentList args = fun->arguments();
122 for (int i = 0; i < args.size(); ++i) {
122 for (int i = 0; i < args.size(); ++i) {
123 if (i > 0)
123 if (i > 0)
124 s << ", ";
124 s << ", ";
125 s << args.at(i)->argumentName();
125 s << args.at(i)->argumentName();
126 }
126 }
127 s << "),_wrapper(NULL) {};" << endl;
127 s << "),_wrapper(NULL) {};" << endl;
128 }
128 }
129 s << endl;
129 s << endl;
130
130
131 foreach(AbstractMetaFunction* fun, virtualsForShell) {
131 foreach(AbstractMetaFunction* fun, virtualsForShell) {
132 s << "virtual ";
132 s << "virtual ";
133 writeFunctionSignature(s, fun, 0, QString(),
133 writeFunctionSignature(s, fun, 0, QString(),
134 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
134 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
135 s << ";" << endl;
135 s << ";" << endl;
136 }
136 }
137 s << endl;
137 s << endl;
138 s << " PythonQtInstanceWrapper* _wrapper; " << endl;
138 s << " PythonQtInstanceWrapper* _wrapper; " << endl;
139
139
140 s << "};" << endl << endl;
140 s << "};" << endl << endl;
141 }
141 }
142
142
143 // Promoter-------------------------------------------------------------------
143 // Promoter-------------------------------------------------------------------
144 AbstractMetaFunctionList promoteFunctions = getProtectedFunctionsThatNeedPromotion(meta_class);
144 AbstractMetaFunctionList promoteFunctions = getProtectedFunctionsThatNeedPromotion(meta_class);
145 if (!promoteFunctions.isEmpty()) {
145 if (!promoteFunctions.isEmpty()) {
146 s << "class " << promoterClassName(meta_class)
146 s << "class " << promoterClassName(meta_class)
147 << " : public " << meta_class->qualifiedCppName() << endl << "{ public:" << endl;
147 << " : public " << meta_class->qualifiedCppName() << endl << "{ public:" << endl;
148
148
149 foreach(AbstractMetaFunction* fun, promoteFunctions) {
149 foreach(AbstractMetaFunction* fun, promoteFunctions) {
150 s << "inline ";
150 s << "inline ";
151 writeFunctionSignature(s, fun, 0, "promoted_",
151 writeFunctionSignature(s, fun, 0, "promoted_",
152 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
152 Option(IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
153 s << " { ";
153 s << " { ";
154 QString scriptFunctionName = fun->originalName();
154 QString scriptFunctionName = fun->originalName();
155 AbstractMetaArgumentList args = fun->arguments();
155 AbstractMetaArgumentList args = fun->arguments();
156 if (fun->type())
156 if (fun->type())
157 s << "return ";
157 s << "return ";
158 s << meta_class->qualifiedCppName() << "::";
158 s << meta_class->qualifiedCppName() << "::";
159 s << fun->originalName() << "(";
159 s << fun->originalName() << "(";
160 for (int i = 0; i < args.size(); ++i) {
160 for (int i = 0; i < args.size(); ++i) {
161 if (i > 0)
161 if (i > 0)
162 s << ", ";
162 s << ", ";
163 s << args.at(i)->argumentName();
163 s << args.at(i)->argumentName();
164 }
164 }
165 s << "); }" << endl;
165 s << "); }" << endl;
166 }
166 }
167
167
168 s << "};" << endl << endl;
168 s << "};" << endl << endl;
169 }
169 }
170
170
171 // Wrapper-------------------------------------------------------------------
171 // Wrapper-------------------------------------------------------------------
172
172
173 s << "class " << wrapperClassName(meta_class)
173 s << "class " << wrapperClassName(meta_class)
174 << " : public QObject" << endl
174 << " : public QObject" << endl
175 << "{ Q_OBJECT" << endl;
175 << "{ Q_OBJECT" << endl;
176
176
177 s << "public:" << endl;
177 s << "public:" << endl;
178
178
179 AbstractMetaEnumList enums1 = meta_class->enums();
179 AbstractMetaEnumList enums1 = meta_class->enums();
180 AbstractMetaEnumList enums;
180 AbstractMetaEnumList enums;
181 QList<FlagsTypeEntry*> flags;
181 QList<FlagsTypeEntry*> flags;
182 foreach(AbstractMetaEnum* enum1, enums1) {
182 foreach(AbstractMetaEnum* enum1, enums1) {
183 // catch gadgets and enums that are not exported on QObjects...
183 // catch gadgets and enums that are not exported on QObjects...
184 if (enum1->wasPublic() && (!meta_class->isQObject() || !enum1->hasQEnumsDeclaration())) {
184 if (enum1->wasPublic() && (!meta_class->isQObject() || !enum1->hasQEnumsDeclaration())) {
185 enums << enum1;
185 enums << enum1;
186 if (enum1->typeEntry()->flags()) {
186 if (enum1->typeEntry()->flags()) {
187 flags << enum1->typeEntry()->flags();
187 flags << enum1->typeEntry()->flags();
188 }
188 }
189 }
189 }
190 }
190 }
191 if (enums.count()) {
191 if (enums.count()) {
192 s << "Q_ENUMS(";
192 s << "Q_ENUMS(";
193 foreach(AbstractMetaEnum* enum1, enums) {
193 foreach(AbstractMetaEnum* enum1, enums) {
194 s << enum1->name() << " ";
194 s << enum1->name() << " ";
195 }
195 }
196 s << ")" << endl;
196 s << ")" << endl;
197
197
198 if (flags.count()) {
198 if (flags.count()) {
199 s << "Q_FLAGS(";
199 s << "Q_FLAGS(";
200 foreach(FlagsTypeEntry* flag1, flags) {
200 foreach(FlagsTypeEntry* flag1, flags) {
201 QString origName = flag1->originalName();
201 QString origName = flag1->originalName();
202 int idx = origName.lastIndexOf("::");
202 int idx = origName.lastIndexOf("::");
203 if (idx!= -1) {
203 if (idx!= -1) {
204 origName = origName.mid(idx+2);
204 origName = origName.mid(idx+2);
205 }
205 }
206 s << origName << " ";
206 s << origName << " ";
207 }
207 }
208 s << ")" << endl;
208 s << ")" << endl;
209 }
209 }
210
210
211 foreach(AbstractMetaEnum* enum1, enums) {
211 foreach(AbstractMetaEnum* enum1, enums) {
212 s << "enum " << enum1->name() << "{" << endl;
212 s << "enum " << enum1->name() << "{" << endl;
213 bool first = true;
213 bool first = true;
214 foreach(AbstractMetaEnumValue* value, enum1->values()) {
214 foreach(AbstractMetaEnumValue* value, enum1->values()) {
215 if (first) { first = false; }
215 if (first) { first = false; }
216 else { s << ", "; }
216 else { s << ", "; }
217 s << " " << value->name() << " = " << meta_class->qualifiedCppName() << "::" << value->name();
217 s << " " << value->name() << " = " << meta_class->qualifiedCppName() << "::" << value->name();
218 }
218 }
219 s << "};" << endl;
219 s << "};" << endl;
220 }
220 }
221 if (flags.count()) {
221 if (flags.count()) {
222 foreach(AbstractMetaEnum* enum1, enums) {
222 foreach(AbstractMetaEnum* enum1, enums) {
223 if (enum1->typeEntry()->flags()) {
223 if (enum1->typeEntry()->flags()) {
224 QString origName = enum1->typeEntry()->flags()->originalName();
224 QString origName = enum1->typeEntry()->flags()->originalName();
225 int idx = origName.lastIndexOf("::");
225 int idx = origName.lastIndexOf("::");
226 if (idx!= -1) {
226 if (idx!= -1) {
227 origName = origName.mid(idx+2);
227 origName = origName.mid(idx+2);
228 }
228 }
229 s << "Q_DECLARE_FLAGS("<< origName << ", " << enum1->name() <<")"<<endl;
229 s << "Q_DECLARE_FLAGS("<< origName << ", " << enum1->name() <<")"<<endl;
230 }
230 }
231 }
231 }
232 }
232 }
233 }
233 }
234 s << "public slots:" << endl;
234 s << "public slots:" << endl;
235 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
235 if (meta_class->generateShellClass() || !meta_class->isAbstract()) {
236
236
237 bool copyConstructorSeen = false;
237 bool copyConstructorSeen = false;
238 bool defaultConstructorSeen = false;
238 bool defaultConstructorSeen = false;
239 foreach (const AbstractMetaFunction *fun, ctors) {
239 foreach (const AbstractMetaFunction *fun, ctors) {
240 if (!fun->isPublic() || fun->isAbstract()) { continue; }
240 if (!fun->isPublic() || fun->isAbstract()) { continue; }
241 s << meta_class->qualifiedCppName() << "* ";
241 s << meta_class->qualifiedCppName() << "* ";
242 writeFunctionSignature(s, fun, 0, "new_",
242 writeFunctionSignature(s, fun, 0, "new_",
243 Option(IncludeDefaultExpression | OriginalName | ShowStatic));
243 Option(IncludeDefaultExpression | OriginalName | ShowStatic));
244 s << ";" << endl;
244 s << ";" << endl;
245 if (fun->arguments().size()==1 && meta_class->qualifiedCppName() == fun->arguments().at(0)->type()->typeEntry()->qualifiedCppName()) {
245 if (fun->arguments().size()==1 && meta_class->qualifiedCppName() == fun->arguments().at(0)->type()->typeEntry()->qualifiedCppName()) {
246 copyConstructorSeen = true;
246 copyConstructorSeen = true;
247 }
247 }
248 if (fun->arguments().size()==0) {
248 if (fun->arguments().size()==0) {
249 defaultConstructorSeen = true;
249 defaultConstructorSeen = true;
250 }
250 }
251 }
251 }
252
252
253 if (meta_class->typeEntry()->isValue()
253 if (meta_class->typeEntry()->isValue()
254 && !copyConstructorSeen && defaultConstructorSeen) {
254 && !copyConstructorSeen && defaultConstructorSeen) {
255 QString className = meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName();
255 QString className = meta_class->generateShellClass()?shellClassName(meta_class):meta_class->qualifiedCppName();
256 s << meta_class->qualifiedCppName() << "* new_" << meta_class->name() << "(const " << meta_class->qualifiedCppName() << "& other) {" << endl;
256 s << meta_class->qualifiedCppName() << "* new_" << meta_class->name() << "(const " << meta_class->qualifiedCppName() << "& other) {" << endl;
257 s << className << "* a = new " << className << "();" << endl;
257 s << className << "* a = new " << className << "();" << endl;
258 s << "*((" << meta_class->qualifiedCppName() << "*)a) = other;" << endl;
258 s << "*((" << meta_class->qualifiedCppName() << "*)a) = other;" << endl;
259 s << "return a; }" << endl;
259 s << "return a; }" << endl;
260 }
260 }
261 }
261 }
262 if (meta_class->hasPublicDestructor() && !meta_class->isNamespace()) {
262 if (meta_class->hasPublicDestructor() && !meta_class->isNamespace()) {
263 s << "void delete_" << meta_class->name() << "(" << meta_class->qualifiedCppName() << "* obj) { delete obj; } ";
263 s << "void delete_" << meta_class->name() << "(" << meta_class->qualifiedCppName() << "* obj) { delete obj; } ";
264 s << endl;
264 s << endl;
265 }
265 }
266 if (meta_class->name()=="QTreeWidgetItem") {
266 if (meta_class->name()=="QTreeWidgetItem") {
267 s << "bool py_hasOwner(QTreeWidgetItem* theWrappedObject) { return theWrappedObject->treeWidget()!=NULL || theWrappedObject->parent()!=NULL; }" << endl;
267 s << "bool py_hasOwner(QTreeWidgetItem* theWrappedObject) { return theWrappedObject->treeWidget()!=NULL || theWrappedObject->parent()!=NULL; }" << endl;
268 } else if (meta_class->name()=="QGraphicsItem") {
268 } else if (meta_class->name()=="QGraphicsItem") {
269 s << "bool py_hasOwner(QGraphicsItem* theWrappedObject) { return theWrappedObject->scene()!=NULL || theWrappedObject->parentItem()!=NULL; }" << endl;
269 s << "bool py_hasOwner(QGraphicsItem* theWrappedObject) { return theWrappedObject->scene()!=NULL || theWrappedObject->parentItem()!=NULL; }" << endl;
270 }
270 }
271
271
272 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
272 AbstractMetaFunctionList functions = getFunctionsToWrap(meta_class);
273
273
274 foreach (const AbstractMetaFunction *function, functions) {
274 foreach (const AbstractMetaFunction *function, functions) {
275 if (!function->isSlot()) {
275 if (!function->isSlot()) {
276 s << " ";
276 s << " ";
277 writeFunctionSignature(s, function, 0, QString(),
277 writeFunctionSignature(s, function, 0, QString(),
278 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
278 Option(ConvertReferenceToPtr | FirstArgIsWrappedObject| IncludeDefaultExpression | OriginalName | ShowStatic | UnderscoreSpaces));
279 s << ";" << endl;
279 s << ";" << endl;
280 }
280 }
281 }
281 }
282 if (meta_class->hasDefaultToStringFunction() || meta_class->hasToStringCapability()) {
282 if (meta_class->hasDefaultToStringFunction() || meta_class->hasToStringCapability()) {
283 s << " QString py_toString(" << meta_class->qualifiedCppName() << "*);" << endl;
283 s << " QString py_toString(" << meta_class->qualifiedCppName() << "*);" << endl;
284 }
284 }
285 if (meta_class->hasDefaultIsNull()) {
286 s << " bool __nonzero__(" << meta_class->qualifiedCppName() << "* obj) { return !obj->isNull(); }" << endl;
287 }
285
288
286 // Field accessors
289 // Field accessors
287 foreach (const AbstractMetaField *field, meta_class->fields()) {
290 foreach (const AbstractMetaField *field, meta_class->fields()) {
288 if (field->isPublic()) {
291 if (field->isPublic()) {
289 writeFieldAccessors(s, field);
292 writeFieldAccessors(s, field);
290 }
293 }
291 }
294 }
292
295
293 // writeInjectedCode(s, meta_class);
296 // writeInjectedCode(s, meta_class);
294
297
295 // s << endl << " QScriptValue __qtscript_self;" << endl;
298 // s << endl << " QScriptValue __qtscript_self;" << endl;
296
299
297 s << "};" << endl << endl
300 s << "};" << endl << endl
298 << "#endif // " << include_block << endl;
301 << "#endif // " << include_block << endl;
299
302
300 }
303 }
301
304
302 void ShellHeaderGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
305 void ShellHeaderGenerator::writeInjectedCode(QTextStream &s, const AbstractMetaClass *meta_class)
303 {
306 {
304 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
307 CodeSnipList code_snips = meta_class->typeEntry()->codeSnips();
305 foreach (const CodeSnip &cs, code_snips) {
308 foreach (const CodeSnip &cs, code_snips) {
306 if (cs.language == TypeSystem::ShellDeclaration) {
309 if (cs.language == TypeSystem::ShellDeclaration) {
307 s << cs.code() << endl;
310 s << cs.code() << endl;
308 }
311 }
309 }
312 }
310 }
313 }
@@ -1,1217 +1,1219
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQt.h"
42 #include "PythonQt.h"
43 #include "PythonQtImporter.h"
43 #include "PythonQtImporter.h"
44 #include "PythonQtClassInfo.h"
44 #include "PythonQtClassInfo.h"
45 #include "PythonQtMethodInfo.h"
45 #include "PythonQtMethodInfo.h"
46 #include "PythonQtSignalReceiver.h"
46 #include "PythonQtSignalReceiver.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtStdOut.h"
48 #include "PythonQtStdOut.h"
49 #include "PythonQtCppWrapperFactory.h"
49 #include "PythonQtCppWrapperFactory.h"
50 #include "PythonQtVariants.h"
50 #include "PythonQtVariants.h"
51 #include "PythonQtStdDecorators.h"
51 #include "PythonQtStdDecorators.h"
52 #include "PythonQtQFileImporter.h"
52 #include "PythonQtQFileImporter.h"
53 #include <pydebug.h>
53 #include <pydebug.h>
54 #include <vector>
54 #include <vector>
55
55
56 PythonQt* PythonQt::_self = NULL;
56 PythonQt* PythonQt::_self = NULL;
57 int PythonQt::_uniqueModuleCount = 0;
57 int PythonQt::_uniqueModuleCount = 0;
58
58
59 void PythonQt_init_QtGuiBuiltin(PyObject*);
59 void PythonQt_init_QtGuiBuiltin(PyObject*);
60 void PythonQt_init_QtCoreBuiltin(PyObject*);
60 void PythonQt_init_QtCoreBuiltin(PyObject*);
61
61
62 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
62 void PythonQt::init(int flags, const QByteArray& pythonQtModuleName)
63 {
63 {
64 if (!_self) {
64 if (!_self) {
65 _self = new PythonQt(flags, pythonQtModuleName);
65 _self = new PythonQt(flags, pythonQtModuleName);
66
66
67 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
67 PythonQtMethodInfo::addParameterTypeAlias("QObjectList", "QList<QObject*>");
68 qRegisterMetaType<QList<QObject*> >("QList<void*>");
68 qRegisterMetaType<QList<QObject*> >("QList<void*>");
69
69
70 PythonQtRegisterToolClassesTemplateConverter(int);
70 PythonQtRegisterToolClassesTemplateConverter(int);
71 PythonQtRegisterToolClassesTemplateConverter(float);
71 PythonQtRegisterToolClassesTemplateConverter(float);
72 PythonQtRegisterToolClassesTemplateConverter(double);
72 PythonQtRegisterToolClassesTemplateConverter(double);
73 PythonQtRegisterToolClassesTemplateConverter(qint32);
73 PythonQtRegisterToolClassesTemplateConverter(qint32);
74 PythonQtRegisterToolClassesTemplateConverter(quint32);
74 PythonQtRegisterToolClassesTemplateConverter(quint32);
75 PythonQtRegisterToolClassesTemplateConverter(qint64);
75 PythonQtRegisterToolClassesTemplateConverter(qint64);
76 PythonQtRegisterToolClassesTemplateConverter(quint64);
76 PythonQtRegisterToolClassesTemplateConverter(quint64);
77 // TODO: which other POD types should be available for QList etc.
77 // TODO: which other POD types should be available for QList etc.
78
78
79 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
79 PythonQt::self()->addDecorators(new PythonQtStdDecorators());
80
80
81 PythonQt_init_QtCoreBuiltin(NULL);
81 PythonQt_init_QtCoreBuiltin(NULL);
82 PythonQt_init_QtGuiBuiltin(NULL);
82 PythonQt_init_QtGuiBuiltin(NULL);
83
83
84 PythonQtRegisterToolClassesTemplateConverter(QDate);
84 PythonQtRegisterToolClassesTemplateConverter(QDate);
85 PythonQtRegisterToolClassesTemplateConverter(QTime);
85 PythonQtRegisterToolClassesTemplateConverter(QTime);
86 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
86 PythonQtRegisterToolClassesTemplateConverter(QDateTime);
87 PythonQtRegisterToolClassesTemplateConverter(QUrl);
87 PythonQtRegisterToolClassesTemplateConverter(QUrl);
88 PythonQtRegisterToolClassesTemplateConverter(QLocale);
88 PythonQtRegisterToolClassesTemplateConverter(QLocale);
89 PythonQtRegisterToolClassesTemplateConverter(QRect);
89 PythonQtRegisterToolClassesTemplateConverter(QRect);
90 PythonQtRegisterToolClassesTemplateConverter(QRectF);
90 PythonQtRegisterToolClassesTemplateConverter(QRectF);
91 PythonQtRegisterToolClassesTemplateConverter(QSize);
91 PythonQtRegisterToolClassesTemplateConverter(QSize);
92 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
92 PythonQtRegisterToolClassesTemplateConverter(QSizeF);
93 PythonQtRegisterToolClassesTemplateConverter(QLine);
93 PythonQtRegisterToolClassesTemplateConverter(QLine);
94 PythonQtRegisterToolClassesTemplateConverter(QLineF);
94 PythonQtRegisterToolClassesTemplateConverter(QLineF);
95 PythonQtRegisterToolClassesTemplateConverter(QPoint);
95 PythonQtRegisterToolClassesTemplateConverter(QPoint);
96 PythonQtRegisterToolClassesTemplateConverter(QPointF);
96 PythonQtRegisterToolClassesTemplateConverter(QPointF);
97 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
97 PythonQtRegisterToolClassesTemplateConverter(QRegExp);
98
98
99 PythonQtRegisterToolClassesTemplateConverter(QFont);
99 PythonQtRegisterToolClassesTemplateConverter(QFont);
100 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
100 PythonQtRegisterToolClassesTemplateConverter(QPixmap);
101 PythonQtRegisterToolClassesTemplateConverter(QBrush);
101 PythonQtRegisterToolClassesTemplateConverter(QBrush);
102 PythonQtRegisterToolClassesTemplateConverter(QColor);
102 PythonQtRegisterToolClassesTemplateConverter(QColor);
103 PythonQtRegisterToolClassesTemplateConverter(QPalette);
103 PythonQtRegisterToolClassesTemplateConverter(QPalette);
104 PythonQtRegisterToolClassesTemplateConverter(QIcon);
104 PythonQtRegisterToolClassesTemplateConverter(QIcon);
105 PythonQtRegisterToolClassesTemplateConverter(QImage);
105 PythonQtRegisterToolClassesTemplateConverter(QImage);
106 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
106 PythonQtRegisterToolClassesTemplateConverter(QPolygon);
107 PythonQtRegisterToolClassesTemplateConverter(QRegion);
107 PythonQtRegisterToolClassesTemplateConverter(QRegion);
108 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
108 PythonQtRegisterToolClassesTemplateConverter(QBitmap);
109 PythonQtRegisterToolClassesTemplateConverter(QCursor);
109 PythonQtRegisterToolClassesTemplateConverter(QCursor);
110 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
110 PythonQtRegisterToolClassesTemplateConverter(QSizePolicy);
111 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
111 PythonQtRegisterToolClassesTemplateConverter(QKeySequence);
112 PythonQtRegisterToolClassesTemplateConverter(QPen);
112 PythonQtRegisterToolClassesTemplateConverter(QPen);
113 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
113 PythonQtRegisterToolClassesTemplateConverter(QTextLength);
114 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
114 PythonQtRegisterToolClassesTemplateConverter(QTextFormat);
115 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
115 PythonQtRegisterToolClassesTemplateConverter(QMatrix);
116
116
117
117
118 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
118 PyObject* pack = PythonQt::priv()->packageByName("QtCore");
119 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
119 PyObject* pack2 = PythonQt::priv()->packageByName("Qt");
120 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
120 PyObject* qtNamespace = PythonQt::priv()->getClassInfo("Qt")->pythonQtClassWrapper();
121 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
121 const char* names[16] = {"SIGNAL", "SLOT", "qAbs", "qBound","qDebug","qWarning","qCritical","qFatal"
122 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
122 ,"qFuzzyCompare", "qMax","qMin","qRound","qRound64","qVersion","qrand","qsrand"};
123 for (unsigned int i = 0;i<16; i++) {
123 for (unsigned int i = 0;i<16; i++) {
124 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
124 PyObject* obj = PyObject_GetAttrString(qtNamespace, names[i]);
125 if (obj) {
125 if (obj) {
126 PyModule_AddObject(pack, names[i], obj);
126 PyModule_AddObject(pack, names[i], obj);
127 Py_INCREF(obj);
127 Py_INCREF(obj);
128 PyModule_AddObject(pack2, names[i], obj);
128 PyModule_AddObject(pack2, names[i], obj);
129 } else {
129 } else {
130 std::cerr << "method not found " << names[i];
130 std::cerr << "method not found " << names[i];
131 }
131 }
132 }
132 }
133 }
133 }
134 }
134 }
135
135
136 void PythonQt::cleanup()
136 void PythonQt::cleanup()
137 {
137 {
138 if (_self) {
138 if (_self) {
139 delete _self;
139 delete _self;
140 _self = NULL;
140 _self = NULL;
141 }
141 }
142 }
142 }
143
143
144 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
144 PythonQt::PythonQt(int flags, const QByteArray& pythonQtModuleName)
145 {
145 {
146 _p = new PythonQtPrivate;
146 _p = new PythonQtPrivate;
147 _p->_initFlags = flags;
147 _p->_initFlags = flags;
148
148
149 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
149 _p->_PythonQtObjectPtr_metaId = qRegisterMetaType<PythonQtObjectPtr>("PythonQtObjectPtr");
150
150
151 Py_SetProgramName("PythonQt");
151 Py_SetProgramName("PythonQt");
152 if (flags & IgnoreSiteModule) {
152 if (flags & IgnoreSiteModule) {
153 // this prevents the automatic importing of Python site files
153 // this prevents the automatic importing of Python site files
154 Py_NoSiteFlag = 1;
154 Py_NoSiteFlag = 1;
155 }
155 }
156 Py_Initialize();
156 Py_Initialize();
157
157
158 // add our own python object types for qt object slots
158 // add our own python object types for qt object slots
159 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
159 if (PyType_Ready(&PythonQtSlotFunction_Type) < 0) {
160 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
160 std::cerr << "could not initialize PythonQtSlotFunction_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
161 }
161 }
162 Py_INCREF(&PythonQtSlotFunction_Type);
162 Py_INCREF(&PythonQtSlotFunction_Type);
163
163
164 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
164 // according to Python docs, set the type late here, since it can not safely be stored in the struct when declaring it
165 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
165 PythonQtClassWrapper_Type.tp_base = &PyType_Type;
166 // add our own python object types for classes
166 // add our own python object types for classes
167 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
167 if (PyType_Ready(&PythonQtClassWrapper_Type) < 0) {
168 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
168 std::cerr << "could not initialize PythonQtClassWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
169 }
169 }
170 Py_INCREF(&PythonQtClassWrapper_Type);
170 Py_INCREF(&PythonQtClassWrapper_Type);
171
171
172 // add our own python object types for CPP instances
172 // add our own python object types for CPP instances
173 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
173 if (PyType_Ready(&PythonQtInstanceWrapper_Type) < 0) {
174 PythonQt::handleError();
174 PythonQt::handleError();
175 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
175 std::cerr << "could not initialize PythonQtInstanceWrapper_Type" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
176 }
176 }
177 Py_INCREF(&PythonQtInstanceWrapper_Type);
177 Py_INCREF(&PythonQtInstanceWrapper_Type);
178
178
179 // add our own python object types for redirection of stdout
179 // add our own python object types for redirection of stdout
180 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
180 if (PyType_Ready(&PythonQtStdOutRedirectType) < 0) {
181 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
181 std::cerr << "could not initialize PythonQtStdOutRedirectType" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
182 }
182 }
183 Py_INCREF(&PythonQtStdOutRedirectType);
183 Py_INCREF(&PythonQtStdOutRedirectType);
184
184
185 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
185 initPythonQtModule(flags & RedirectStdOut, pythonQtModuleName);
186
186
187 _p->setupSharedLibrarySuffixes();
187 _p->setupSharedLibrarySuffixes();
188
188
189 }
189 }
190
190
191 PythonQt::~PythonQt() {
191 PythonQt::~PythonQt() {
192 delete _p;
192 delete _p;
193 _p = NULL;
193 _p = NULL;
194 }
194 }
195
195
196 PythonQtPrivate::~PythonQtPrivate() {
196 PythonQtPrivate::~PythonQtPrivate() {
197 delete _defaultImporter;
197 delete _defaultImporter;
198 _defaultImporter = NULL;
198 _defaultImporter = NULL;
199
199
200 {
200 {
201 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
201 QHashIterator<QByteArray, PythonQtClassInfo *> i(_knownClassInfos);
202 while (i.hasNext()) {
202 while (i.hasNext()) {
203 delete i.next().value();
203 delete i.next().value();
204 }
204 }
205 }
205 }
206 PythonQtConv::global_valueStorage.clear();
206 PythonQtConv::global_valueStorage.clear();
207 PythonQtConv::global_ptrStorage.clear();
207 PythonQtConv::global_ptrStorage.clear();
208 PythonQtConv::global_variantStorage.clear();
208 PythonQtConv::global_variantStorage.clear();
209
209
210 PythonQtMethodInfo::cleanupCachedMethodInfos();
210 PythonQtMethodInfo::cleanupCachedMethodInfos();
211 }
211 }
212
212
213 PythonQtImportFileInterface* PythonQt::importInterface()
213 PythonQtImportFileInterface* PythonQt::importInterface()
214 {
214 {
215 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
215 return _self->_p->_importInterface?_self->_p->_importInterface:_self->_p->_defaultImporter;
216 }
216 }
217
217
218 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
218 void PythonQt::qObjectNoLongerWrappedCB(QObject* o)
219 {
219 {
220 if (_self->_p->_noLongerWrappedCB) {
220 if (_self->_p->_noLongerWrappedCB) {
221 (*_self->_p->_noLongerWrappedCB)(o);
221 (*_self->_p->_noLongerWrappedCB)(o);
222 };
222 };
223 }
223 }
224
224
225 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
225 void PythonQt::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
226 {
226 {
227 _p->registerClass(metaobject, package, wrapperCreator, shell);
227 _p->registerClass(metaobject, package, wrapperCreator, shell);
228 }
228 }
229
229
230 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module)
230 void PythonQtPrivate::registerClass(const QMetaObject* metaobject, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
231 {
231 {
232 // we register all classes in the hierarchy
232 // we register all classes in the hierarchy
233 const QMetaObject* m = metaobject;
233 const QMetaObject* m = metaobject;
234 bool first = true;
234 bool first = true;
235 while (m) {
235 while (m) {
236 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
236 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(m->className());
237 if (!info->pythonQtClassWrapper()) {
237 if (!info->pythonQtClassWrapper()) {
238 info->setTypeSlots(typeSlots);
238 info->setupQObject(m);
239 info->setupQObject(m);
239 createPythonQtClassWrapper(info, package, module);
240 createPythonQtClassWrapper(info, package, module);
240 if (m->superClass()) {
241 if (m->superClass()) {
241 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
242 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(m->superClass()->className());
242 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
243 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo));
243 }
244 }
244 }
245 }
245 if (first) {
246 if (first) {
246 first = false;
247 first = false;
247 if (wrapperCreator) {
248 if (wrapperCreator) {
248 info->setDecoratorProvider(wrapperCreator);
249 info->setDecoratorProvider(wrapperCreator);
249 }
250 }
250 if (shell) {
251 if (shell) {
251 info->setShellSetInstanceWrapperCB(shell);
252 info->setShellSetInstanceWrapperCB(shell);
252 }
253 }
253 }
254 }
254 m = m->superClass();
255 m = m->superClass();
255 }
256 }
256 }
257 }
257
258
258 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
259 void PythonQtPrivate::createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module)
259 {
260 {
260 PyObject* pack = module?module:packageByName(package);
261 PyObject* pack = module?module:packageByName(package);
261 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
262 PyObject* pyobj = (PyObject*)createNewPythonQtClassWrapper(info, pack);
262 PyModule_AddObject(pack, info->className(), pyobj);
263 PyModule_AddObject(pack, info->className(), pyobj);
263 if (!module && package && strncmp(package,"Qt",2)==0) {
264 if (!module && package && strncmp(package,"Qt",2)==0) {
264 // since PyModule_AddObject steals the reference, we need a incref once more...
265 // since PyModule_AddObject steals the reference, we need a incref once more...
265 Py_INCREF(pyobj);
266 Py_INCREF(pyobj);
266 // put all qt objects into Qt as well
267 // put all qt objects into Qt as well
267 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
268 PyModule_AddObject(packageByName("Qt"), info->className(), pyobj);
268 }
269 }
269 info->setPythonQtClassWrapper(pyobj);
270 info->setPythonQtClassWrapper(pyobj);
270 }
271 }
271
272
272 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
273 PyObject* PythonQtPrivate::wrapQObject(QObject* obj)
273 {
274 {
274 if (!obj) {
275 if (!obj) {
275 Py_INCREF(Py_None);
276 Py_INCREF(Py_None);
276 return Py_None;
277 return Py_None;
277 }
278 }
278 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
279 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(obj);
279 if (!wrap) {
280 if (!wrap) {
280 // smuggling it in...
281 // smuggling it in...
281 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
282 PythonQtClassInfo* classInfo = _knownClassInfos.value(obj->metaObject()->className());
282 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
283 if (!classInfo || classInfo->pythonQtClassWrapper()==NULL) {
283 registerClass(obj->metaObject());
284 registerClass(obj->metaObject());
284 classInfo = _knownClassInfos.value(obj->metaObject()->className());
285 classInfo = _knownClassInfos.value(obj->metaObject()->className());
285 }
286 }
286 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
287 wrap = createNewPythonQtInstanceWrapper(obj, classInfo);
287 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
288 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
288 } else {
289 } else {
289 Py_INCREF(wrap);
290 Py_INCREF(wrap);
290 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
291 // mlabDebugConst("MLABPython","qobject wrapper reused " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
291 }
292 }
292 return (PyObject*)wrap;
293 return (PyObject*)wrap;
293 }
294 }
294
295
295 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
296 PyObject* PythonQtPrivate::wrapPtr(void* ptr, const QByteArray& name)
296 {
297 {
297 if (!ptr) {
298 if (!ptr) {
298 Py_INCREF(Py_None);
299 Py_INCREF(Py_None);
299 return Py_None;
300 return Py_None;
300 }
301 }
301
302
302 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
303 PythonQtInstanceWrapper* wrap = findWrapperAndRemoveUnused(ptr);
303 if (!wrap) {
304 if (!wrap) {
304 PythonQtClassInfo* info = _knownClassInfos.value(name);
305 PythonQtClassInfo* info = _knownClassInfos.value(name);
305 if (!info) {
306 if (!info) {
306 // maybe it is a PyObject, which we can return directly
307 // maybe it is a PyObject, which we can return directly
307 if (name == "PyObject") {
308 if (name == "PyObject") {
308 PyObject* p = (PyObject*)ptr;
309 PyObject* p = (PyObject*)ptr;
309 Py_INCREF(p);
310 Py_INCREF(p);
310 return p;
311 return p;
311 }
312 }
312
313
313 // we do not know the metaobject yet, but we might know it by it's name:
314 // we do not know the metaobject yet, but we might know it by it's name:
314 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
315 if (_knownQObjectClassNames.find(name)!=_knownQObjectClassNames.end()) {
315 // yes, we know it, so we can convert to QObject
316 // yes, we know it, so we can convert to QObject
316 QObject* qptr = (QObject*)ptr;
317 QObject* qptr = (QObject*)ptr;
317 registerClass(qptr->metaObject());
318 registerClass(qptr->metaObject());
318 info = _knownClassInfos.value(qptr->metaObject()->className());
319 info = _knownClassInfos.value(qptr->metaObject()->className());
319 }
320 }
320 }
321 }
321 if (info && info->isQObject()) {
322 if (info && info->isQObject()) {
322 QObject* qptr = (QObject*)ptr;
323 QObject* qptr = (QObject*)ptr;
323 // if the object is a derived object, we want to switch the class info to the one of the derived class:
324 // if the object is a derived object, we want to switch the class info to the one of the derived class:
324 if (name!=(qptr->metaObject()->className())) {
325 if (name!=(qptr->metaObject()->className())) {
325 registerClass(qptr->metaObject());
326 registerClass(qptr->metaObject());
326 info = _knownClassInfos.value(qptr->metaObject()->className());
327 info = _knownClassInfos.value(qptr->metaObject()->className());
327 }
328 }
328 wrap = createNewPythonQtInstanceWrapper(qptr, info);
329 wrap = createNewPythonQtInstanceWrapper(qptr, info);
329 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
330 // mlabDebugConst("MLABPython","new qobject wrapper added " << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
330 return (PyObject*)wrap;
331 return (PyObject*)wrap;
331 }
332 }
332
333
333 // not a known QObject, so try our wrapper factory:
334 // not a known QObject, so try our wrapper factory:
334 QObject* wrapper = NULL;
335 QObject* wrapper = NULL;
335 for (int i=0; i<_cppWrapperFactories.size(); i++) {
336 for (int i=0; i<_cppWrapperFactories.size(); i++) {
336 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
337 wrapper = _cppWrapperFactories.at(i)->create(name, ptr);
337 if (wrapper) {
338 if (wrapper) {
338 break;
339 break;
339 }
340 }
340 }
341 }
341
342
342 if (info) {
343 if (info) {
343 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
344 // try to downcast in the class hierarchy, which will modify info and ptr if it is successfull
344 ptr = info->castDownIfPossible(ptr, &info);
345 ptr = info->castDownIfPossible(ptr, &info);
345 }
346 }
346
347
347 if (!info || info->pythonQtClassWrapper()==NULL) {
348 if (!info || info->pythonQtClassWrapper()==NULL) {
348 // still unknown, register as CPP class
349 // still unknown, register as CPP class
349 registerCPPClass(name.constData());
350 registerCPPClass(name.constData());
350 info = _knownClassInfos.value(name);
351 info = _knownClassInfos.value(name);
351 }
352 }
352 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
353 if (wrapper && (info->metaObject() != wrapper->metaObject())) {
353 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
354 // if we a have a QObject wrapper and the metaobjects do not match, set the metaobject again!
354 info->setMetaObject(wrapper->metaObject());
355 info->setMetaObject(wrapper->metaObject());
355 }
356 }
356 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
357 wrap = createNewPythonQtInstanceWrapper(wrapper, info, ptr);
357 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
358 // mlabDebugConst("MLABPython","new c++ wrapper added " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
358 } else {
359 } else {
359 Py_INCREF(wrap);
360 Py_INCREF(wrap);
360 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
361 //mlabDebugConst("MLABPython","c++ wrapper reused " << wrap->_wrappedPtr << " " << wrap->_obj->className() << " " << wrap->classInfo()->wrappedClassName().latin1());
361 }
362 }
362 return (PyObject*)wrap;
363 return (PyObject*)wrap;
363 }
364 }
364
365
365 PyObject* PythonQtPrivate::dummyTuple() {
366 PyObject* PythonQtPrivate::dummyTuple() {
366 static PyObject* dummyTuple = NULL;
367 static PyObject* dummyTuple = NULL;
367 if (dummyTuple==NULL) {
368 if (dummyTuple==NULL) {
368 dummyTuple = PyTuple_New(1);
369 dummyTuple = PyTuple_New(1);
369 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
370 PyTuple_SET_ITEM(dummyTuple, 0 , PyString_FromString("dummy"));
370 }
371 }
371 return dummyTuple;
372 return dummyTuple;
372 }
373 }
373
374
374
375
375 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
376 PythonQtInstanceWrapper* PythonQtPrivate::createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr) {
376 // call the associated class type to create a new instance...
377 // call the associated class type to create a new instance...
377 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
378 PythonQtInstanceWrapper* result = (PythonQtInstanceWrapper*)PyObject_Call(info->pythonQtClassWrapper(), dummyTuple(), NULL);
378
379
379 result->setQObject(obj);
380 result->setQObject(obj);
380 result->_wrappedPtr = wrappedPtr;
381 result->_wrappedPtr = wrappedPtr;
381 result->_ownedByPythonQt = false;
382 result->_ownedByPythonQt = false;
382 result->_useQMetaTypeDestroy = false;
383 result->_useQMetaTypeDestroy = false;
383
384
384 if (wrappedPtr) {
385 if (wrappedPtr) {
385 _wrappedObjects.insert(wrappedPtr, result);
386 _wrappedObjects.insert(wrappedPtr, result);
386 } else {
387 } else {
387 _wrappedObjects.insert(obj, result);
388 _wrappedObjects.insert(obj, result);
388 if (obj->parent()== NULL && _wrappedCB) {
389 if (obj->parent()== NULL && _wrappedCB) {
389 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
390 // tell someone who is interested that the qobject is wrapped the first time, if it has no parent
390 (*_wrappedCB)(obj);
391 (*_wrappedCB)(obj);
391 }
392 }
392 }
393 }
393 return result;
394 return result;
394 }
395 }
395
396
396 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
397 PythonQtClassWrapper* PythonQtPrivate::createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* parentModule) {
397 PythonQtClassWrapper* result;
398 PythonQtClassWrapper* result;
398
399
399 PyObject* className = PyString_FromString(info->className());
400 PyObject* className = PyString_FromString(info->className());
400
401
401 PyObject* baseClasses = PyTuple_New(1);
402 PyObject* baseClasses = PyTuple_New(1);
402 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
403 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PythonQtInstanceWrapper_Type);
403
404
404 PyObject* typeDict = PyDict_New();
405 PyObject* typeDict = PyDict_New();
405 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
406 PyObject* moduleName = PyObject_GetAttrString(parentModule, "__name__");
406 PyDict_SetItemString(typeDict, "__module__", moduleName);
407 PyDict_SetItemString(typeDict, "__module__", moduleName);
407
408
408 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
409 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
409
410
410 // set the class info so that PythonQtClassWrapper_new can read it
411 // set the class info so that PythonQtClassWrapper_new can read it
411 _currentClassInfoForClassWrapperCreation = info;
412 _currentClassInfoForClassWrapperCreation = info;
412 // create the new type object by calling the type
413 // create the new type object by calling the type
413 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
414 result = (PythonQtClassWrapper *)PyObject_Call((PyObject *)&PythonQtClassWrapper_Type, args, NULL);
414
415
415 Py_DECREF(baseClasses);
416 Py_DECREF(baseClasses);
416 Py_DECREF(typeDict);
417 Py_DECREF(typeDict);
417 Py_DECREF(args);
418 Py_DECREF(args);
418 Py_DECREF(className);
419 Py_DECREF(className);
419
420
420 return result;
421 return result;
421 }
422 }
422
423
423 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
424 PyObject* PythonQtPrivate::createEnumValueInstance(PyObject* enumType, unsigned int enumValue)
424 {
425 {
425 PyObject* args = Py_BuildValue("(i)", enumValue);
426 PyObject* args = Py_BuildValue("(i)", enumValue);
426 PyObject* result = PyObject_Call(enumType, args, NULL);
427 PyObject* result = PyObject_Call(enumType, args, NULL);
427 Py_DECREF(args);
428 Py_DECREF(args);
428 return result;
429 return result;
429 }
430 }
430
431
431 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
432 PyObject* PythonQtPrivate::createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject) {
432 PyObject* result;
433 PyObject* result;
433
434
434 PyObject* className = PyString_FromString(enumName);
435 PyObject* className = PyString_FromString(enumName);
435
436
436 PyObject* baseClasses = PyTuple_New(1);
437 PyObject* baseClasses = PyTuple_New(1);
437 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
438 PyTuple_SET_ITEM(baseClasses, 0, (PyObject*)&PyInt_Type);
438
439
439 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
440 PyObject* module = PyObject_GetAttrString(parentObject, "__module__");
440 PyObject* typeDict = PyDict_New();
441 PyObject* typeDict = PyDict_New();
441 PyDict_SetItemString(typeDict, "__module__", module);
442 PyDict_SetItemString(typeDict, "__module__", module);
442
443
443 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
444 PyObject* args = Py_BuildValue("OOO", className, baseClasses, typeDict);
444
445
445 // create the new int derived type object by calling the core type
446 // create the new int derived type object by calling the core type
446 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
447 result = PyObject_Call((PyObject *)&PyType_Type, args, NULL);
447
448
448 Py_DECREF(baseClasses);
449 Py_DECREF(baseClasses);
449 Py_DECREF(typeDict);
450 Py_DECREF(typeDict);
450 Py_DECREF(args);
451 Py_DECREF(args);
451 Py_DECREF(className);
452 Py_DECREF(className);
452
453
453 return result;
454 return result;
454 }
455 }
455
456
456 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
457 PythonQtSignalReceiver* PythonQt::getSignalReceiver(QObject* obj)
457 {
458 {
458 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
459 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
459 if (!r) {
460 if (!r) {
460 r = new PythonQtSignalReceiver(obj);
461 r = new PythonQtSignalReceiver(obj);
461 _p->_signalReceivers.insert(obj, r);
462 _p->_signalReceivers.insert(obj, r);
462 }
463 }
463 return r;
464 return r;
464 }
465 }
465
466
466 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
467 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
467 {
468 {
468 bool flag = false;
469 bool flag = false;
469 PythonQtObjectPtr callable = lookupCallable(module, objectname);
470 PythonQtObjectPtr callable = lookupCallable(module, objectname);
470 if (callable) {
471 if (callable) {
471 PythonQtSignalReceiver* r = getSignalReceiver(obj);
472 PythonQtSignalReceiver* r = getSignalReceiver(obj);
472 flag = r->addSignalHandler(signal, callable);
473 flag = r->addSignalHandler(signal, callable);
473 if (!flag) {
474 if (!flag) {
474 // signal not found
475 // signal not found
475 }
476 }
476 } else {
477 } else {
477 // callable not found
478 // callable not found
478 }
479 }
479 return flag;
480 return flag;
480 }
481 }
481
482
482 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
483 bool PythonQt::addSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
483 {
484 {
484 bool flag = false;
485 bool flag = false;
485 PythonQtSignalReceiver* r = getSignalReceiver(obj);
486 PythonQtSignalReceiver* r = getSignalReceiver(obj);
486 if (r) {
487 if (r) {
487 flag = r->addSignalHandler(signal, receiver);
488 flag = r->addSignalHandler(signal, receiver);
488 }
489 }
489 return flag;
490 return flag;
490 }
491 }
491
492
492 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
493 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname)
493 {
494 {
494 bool flag = false;
495 bool flag = false;
495 PythonQtObjectPtr callable = lookupCallable(module, objectname);
496 PythonQtObjectPtr callable = lookupCallable(module, objectname);
496 if (callable) {
497 if (callable) {
497 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
498 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
498 if (r) {
499 if (r) {
499 flag = r->removeSignalHandler(signal, callable);
500 flag = r->removeSignalHandler(signal, callable);
500 }
501 }
501 } else {
502 } else {
502 // callable not found
503 // callable not found
503 }
504 }
504 return flag;
505 return flag;
505 }
506 }
506
507
507 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
508 bool PythonQt::removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver)
508 {
509 {
509 bool flag = false;
510 bool flag = false;
510 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
511 PythonQtSignalReceiver* r = _p->_signalReceivers[obj];
511 if (r) {
512 if (r) {
512 flag = r->removeSignalHandler(signal, receiver);
513 flag = r->removeSignalHandler(signal, receiver);
513 }
514 }
514 return flag;
515 return flag;
515 }
516 }
516
517
517 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
518 PythonQtObjectPtr PythonQt::lookupCallable(PyObject* module, const QString& name)
518 {
519 {
519 PythonQtObjectPtr p = lookupObject(module, name);
520 PythonQtObjectPtr p = lookupObject(module, name);
520 if (p) {
521 if (p) {
521 if (PyCallable_Check(p)) {
522 if (PyCallable_Check(p)) {
522 return p;
523 return p;
523 }
524 }
524 }
525 }
525 PyErr_Clear();
526 PyErr_Clear();
526 return NULL;
527 return NULL;
527 }
528 }
528
529
529 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
530 PythonQtObjectPtr PythonQt::lookupObject(PyObject* module, const QString& name)
530 {
531 {
531 QStringList l = name.split('.');
532 QStringList l = name.split('.');
532 PythonQtObjectPtr p = module;
533 PythonQtObjectPtr p = module;
533 PythonQtObjectPtr prev;
534 PythonQtObjectPtr prev;
534 QString s;
535 QString s;
535 QByteArray b;
536 QByteArray b;
536 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
537 for (QStringList::ConstIterator i = l.begin(); i!=l.end() && p; ++i) {
537 prev = p;
538 prev = p;
538 b = (*i).toLatin1();
539 b = (*i).toLatin1();
539 if (PyDict_Check(p)) {
540 if (PyDict_Check(p)) {
540 p = PyDict_GetItemString(p, b.data());
541 p = PyDict_GetItemString(p, b.data());
541 } else {
542 } else {
542 p.setNewRef(PyObject_GetAttrString(p, b.data()));
543 p.setNewRef(PyObject_GetAttrString(p, b.data()));
543 }
544 }
544 }
545 }
545 PyErr_Clear();
546 PyErr_Clear();
546 return p;
547 return p;
547 }
548 }
548
549
549 PythonQtObjectPtr PythonQt::getMainModule() {
550 PythonQtObjectPtr PythonQt::getMainModule() {
550 //both borrowed
551 //both borrowed
551 PythonQtObjectPtr dict = PyImport_GetModuleDict();
552 PythonQtObjectPtr dict = PyImport_GetModuleDict();
552 return PyDict_GetItemString(dict, "__main__");
553 return PyDict_GetItemString(dict, "__main__");
553 }
554 }
554
555
555 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
556 QVariant PythonQt::evalCode(PyObject* object, PyObject* pycode) {
556 QVariant result;
557 QVariant result;
557 if (pycode) {
558 if (pycode) {
558 PyObject* dict = NULL;
559 PyObject* dict = NULL;
559 if (PyModule_Check(object)) {
560 if (PyModule_Check(object)) {
560 dict = PyModule_GetDict(object);
561 dict = PyModule_GetDict(object);
561 } else if (PyDict_Check(object)) {
562 } else if (PyDict_Check(object)) {
562 dict = object;
563 dict = object;
563 }
564 }
564 PyObject* r = NULL;
565 PyObject* r = NULL;
565 if (dict) {
566 if (dict) {
566 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
567 r = PyEval_EvalCode((PyCodeObject*)pycode, dict , dict);
567 }
568 }
568 if (r) {
569 if (r) {
569 result = PythonQtConv::PyObjToQVariant(r);
570 result = PythonQtConv::PyObjToQVariant(r);
570 Py_DECREF(r);
571 Py_DECREF(r);
571 } else {
572 } else {
572 handleError();
573 handleError();
573 }
574 }
574 } else {
575 } else {
575 handleError();
576 handleError();
576 }
577 }
577 return result;
578 return result;
578 }
579 }
579
580
580 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
581 QVariant PythonQt::evalScript(PyObject* object, const QString& script, int start)
581 {
582 {
582 QVariant result;
583 QVariant result;
583 PythonQtObjectPtr p;
584 PythonQtObjectPtr p;
584 PyObject* dict = NULL;
585 PyObject* dict = NULL;
585 if (PyModule_Check(object)) {
586 if (PyModule_Check(object)) {
586 dict = PyModule_GetDict(object);
587 dict = PyModule_GetDict(object);
587 } else if (PyDict_Check(object)) {
588 } else if (PyDict_Check(object)) {
588 dict = object;
589 dict = object;
589 }
590 }
590 if (dict) {
591 if (dict) {
591 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
592 p.setNewRef(PyRun_String(script.toLatin1().data(), start, dict, dict));
592 }
593 }
593 if (p) {
594 if (p) {
594 result = PythonQtConv::PyObjToQVariant(p);
595 result = PythonQtConv::PyObjToQVariant(p);
595 } else {
596 } else {
596 handleError();
597 handleError();
597 }
598 }
598 return result;
599 return result;
599 }
600 }
600
601
601 void PythonQt::evalFile(PyObject* module, const QString& filename)
602 void PythonQt::evalFile(PyObject* module, const QString& filename)
602 {
603 {
603 PythonQtObjectPtr code = parseFile(filename);
604 PythonQtObjectPtr code = parseFile(filename);
604 if (code) {
605 if (code) {
605 evalCode(module, code);
606 evalCode(module, code);
606 } else {
607 } else {
607 handleError();
608 handleError();
608 }
609 }
609 }
610 }
610
611
611 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
612 PythonQtObjectPtr PythonQt::parseFile(const QString& filename)
612 {
613 {
613 PythonQtObjectPtr p;
614 PythonQtObjectPtr p;
614 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
615 p.setNewRef(PythonQtImport::getCodeFromPyc(filename));
615 if (!p) {
616 if (!p) {
616 handleError();
617 handleError();
617 }
618 }
618 return p;
619 return p;
619 }
620 }
620
621
621 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
622 PythonQtObjectPtr PythonQt::createModuleFromFile(const QString& name, const QString& filename)
622 {
623 {
623 PythonQtObjectPtr code = parseFile(filename);
624 PythonQtObjectPtr code = parseFile(filename);
624 PythonQtObjectPtr module = _p->createModule(name, code);
625 PythonQtObjectPtr module = _p->createModule(name, code);
625 return module;
626 return module;
626 }
627 }
627
628
628 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
629 PythonQtObjectPtr PythonQt::createModuleFromScript(const QString& name, const QString& script)
629 {
630 {
630 PyErr_Clear();
631 PyErr_Clear();
631 QString scriptCode = script;
632 QString scriptCode = script;
632 if (scriptCode.isEmpty()) {
633 if (scriptCode.isEmpty()) {
633 // we always need at least a linefeed
634 // we always need at least a linefeed
634 scriptCode = "\n";
635 scriptCode = "\n";
635 }
636 }
636 PythonQtObjectPtr pycode;
637 PythonQtObjectPtr pycode;
637 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
638 pycode.setNewRef(Py_CompileString((char*)scriptCode.toLatin1().data(), "", Py_file_input));
638 PythonQtObjectPtr module = _p->createModule(name, pycode);
639 PythonQtObjectPtr module = _p->createModule(name, pycode);
639 return module;
640 return module;
640 }
641 }
641
642
642 PythonQtObjectPtr PythonQt::createUniqueModule()
643 PythonQtObjectPtr PythonQt::createUniqueModule()
643 {
644 {
644 static QString pyQtStr("PythonQt_module");
645 static QString pyQtStr("PythonQt_module");
645 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
646 QString moduleName = pyQtStr+QString::number(_uniqueModuleCount++);
646 return createModuleFromScript(moduleName);
647 return createModuleFromScript(moduleName);
647 }
648 }
648
649
649 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
650 void PythonQt::addObject(PyObject* object, const QString& name, QObject* qObject)
650 {
651 {
651 if (PyModule_Check(object)) {
652 if (PyModule_Check(object)) {
652 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
653 PyModule_AddObject(object, name.toLatin1().data(), _p->wrapQObject(qObject));
653 } else if (PyDict_Check(object)) {
654 } else if (PyDict_Check(object)) {
654 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
655 PyDict_SetItemString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
655 } else {
656 } else {
656 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
657 PyObject_SetAttrString(object, name.toLatin1().data(), _p->wrapQObject(qObject));
657 }
658 }
658 }
659 }
659
660
660 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
661 void PythonQt::addVariable(PyObject* object, const QString& name, const QVariant& v)
661 {
662 {
662 if (PyModule_Check(object)) {
663 if (PyModule_Check(object)) {
663 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
664 PyModule_AddObject(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
664 } else if (PyDict_Check(object)) {
665 } else if (PyDict_Check(object)) {
665 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
666 PyDict_SetItemString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
666 } else {
667 } else {
667 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
668 PyObject_SetAttrString(object, name.toLatin1().data(), PythonQtConv::QVariantToPyObject(v));
668 }
669 }
669 }
670 }
670
671
671 void PythonQt::removeVariable(PyObject* object, const QString& name)
672 void PythonQt::removeVariable(PyObject* object, const QString& name)
672 {
673 {
673 if (PyDict_Check(object)) {
674 if (PyDict_Check(object)) {
674 PyDict_DelItemString(object, name.toLatin1().data());
675 PyDict_DelItemString(object, name.toLatin1().data());
675 } else {
676 } else {
676 PyObject_DelAttrString(object, name.toLatin1().data());
677 PyObject_DelAttrString(object, name.toLatin1().data());
677 }
678 }
678 }
679 }
679
680
680 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
681 QVariant PythonQt::getVariable(PyObject* object, const QString& objectname)
681 {
682 {
682 QVariant result;
683 QVariant result;
683 PythonQtObjectPtr obj = lookupObject(object, objectname);
684 PythonQtObjectPtr obj = lookupObject(object, objectname);
684 if (obj) {
685 if (obj) {
685 result = PythonQtConv::PyObjToQVariant(obj);
686 result = PythonQtConv::PyObjToQVariant(obj);
686 }
687 }
687 return result;
688 return result;
688 }
689 }
689
690
690 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
691 QStringList PythonQt::introspection(PyObject* module, const QString& objectname, PythonQt::ObjectType type)
691 {
692 {
692 QStringList results;
693 QStringList results;
693
694
694 PythonQtObjectPtr object;
695 PythonQtObjectPtr object;
695 if (objectname.isEmpty()) {
696 if (objectname.isEmpty()) {
696 object = module;
697 object = module;
697 } else {
698 } else {
698 object = lookupObject(module, objectname);
699 object = lookupObject(module, objectname);
699 if (!object && type == CallOverloads) {
700 if (!object && type == CallOverloads) {
700 PyObject* dict = lookupObject(module, "__builtins__");
701 PyObject* dict = lookupObject(module, "__builtins__");
701 if (dict) {
702 if (dict) {
702 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
703 object = PyDict_GetItemString(dict, objectname.toLatin1().constData());
703 }
704 }
704 }
705 }
705 }
706 }
706
707
707 if (object) {
708 if (object) {
708 if (type == CallOverloads) {
709 if (type == CallOverloads) {
709 if (PythonQtSlotFunction_Check(object)) {
710 if (PythonQtSlotFunction_Check(object)) {
710 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
711 PythonQtSlotFunctionObject* o = (PythonQtSlotFunctionObject*)object.object();
711 PythonQtSlotInfo* info = o->m_ml;
712 PythonQtSlotInfo* info = o->m_ml;
712
713
713 while (info) {
714 while (info) {
714 results << info->fullSignature();
715 results << info->fullSignature();
715 info = info->nextInfo();
716 info = info->nextInfo();
716 }
717 }
717 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
718 } else if (object->ob_type == &PythonQtClassWrapper_Type) {
718 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
719 PythonQtClassWrapper* o = (PythonQtClassWrapper*)object.object();
719 PythonQtSlotInfo* info = o->classInfo()->constructors();
720 PythonQtSlotInfo* info = o->classInfo()->constructors();
720
721
721 while (info) {
722 while (info) {
722 results << info->fullSignature();
723 results << info->fullSignature();
723 info = info->nextInfo();
724 info = info->nextInfo();
724 }
725 }
725 } else {
726 } else {
726 //TODO: use pydoc!
727 //TODO: use pydoc!
727 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
728 PyObject* doc = PyObject_GetAttrString(object, "__doc__");
728 if (doc) {
729 if (doc) {
729 results << PyString_AsString(doc);
730 results << PyString_AsString(doc);
730 Py_DECREF(doc);
731 Py_DECREF(doc);
731 }
732 }
732 }
733 }
733 } else {
734 } else {
734 PyObject* keys = NULL;
735 PyObject* keys = NULL;
735 bool isDict = false;
736 bool isDict = false;
736 if (PyDict_Check(object)) {
737 if (PyDict_Check(object)) {
737 keys = PyDict_Keys(object);
738 keys = PyDict_Keys(object);
738 isDict = true;
739 isDict = true;
739 } else {
740 } else {
740 keys = PyObject_Dir(object);
741 keys = PyObject_Dir(object);
741 }
742 }
742 if (keys) {
743 if (keys) {
743 int count = PyList_Size(keys);
744 int count = PyList_Size(keys);
744 PyObject* key;
745 PyObject* key;
745 PyObject* value;
746 PyObject* value;
746 QString keystr;
747 QString keystr;
747 for (int i = 0;i<count;i++) {
748 for (int i = 0;i<count;i++) {
748 key = PyList_GetItem(keys,i);
749 key = PyList_GetItem(keys,i);
749 if (isDict) {
750 if (isDict) {
750 value = PyDict_GetItem(object, key);
751 value = PyDict_GetItem(object, key);
751 Py_INCREF(value);
752 Py_INCREF(value);
752 } else {
753 } else {
753 value = PyObject_GetAttr(object, key);
754 value = PyObject_GetAttr(object, key);
754 }
755 }
755 if (!value) continue;
756 if (!value) continue;
756 keystr = PyString_AsString(key);
757 keystr = PyString_AsString(key);
757 static const QString underscoreStr("__tmp");
758 static const QString underscoreStr("__tmp");
758 if (!keystr.startsWith(underscoreStr)) {
759 if (!keystr.startsWith(underscoreStr)) {
759 switch (type) {
760 switch (type) {
760 case Anything:
761 case Anything:
761 results << keystr;
762 results << keystr;
762 break;
763 break;
763 case Class:
764 case Class:
764 if (value->ob_type == &PyClass_Type) {
765 if (value->ob_type == &PyClass_Type) {
765 results << keystr;
766 results << keystr;
766 }
767 }
767 break;
768 break;
768 case Variable:
769 case Variable:
769 if (value->ob_type != &PyClass_Type
770 if (value->ob_type != &PyClass_Type
770 && value->ob_type != &PyCFunction_Type
771 && value->ob_type != &PyCFunction_Type
771 && value->ob_type != &PyFunction_Type
772 && value->ob_type != &PyFunction_Type
772 && value->ob_type != &PyModule_Type
773 && value->ob_type != &PyModule_Type
773 ) {
774 ) {
774 results << keystr;
775 results << keystr;
775 }
776 }
776 break;
777 break;
777 case Function:
778 case Function:
778 if (value->ob_type == &PyFunction_Type ||
779 if (value->ob_type == &PyFunction_Type ||
779 value->ob_type == &PyMethod_Type
780 value->ob_type == &PyMethod_Type
780 ) {
781 ) {
781 results << keystr;
782 results << keystr;
782 }
783 }
783 break;
784 break;
784 case Module:
785 case Module:
785 if (value->ob_type == &PyModule_Type) {
786 if (value->ob_type == &PyModule_Type) {
786 results << keystr;
787 results << keystr;
787 }
788 }
788 break;
789 break;
789 default:
790 default:
790 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
791 std::cerr << "PythonQt: introspection: unknown case" << ", in " << __FILE__ << ":" << __LINE__ << std::endl;
791 }
792 }
792 }
793 }
793 Py_DECREF(value);
794 Py_DECREF(value);
794 }
795 }
795 Py_DECREF(keys);
796 Py_DECREF(keys);
796 }
797 }
797 }
798 }
798 }
799 }
799 return results;
800 return results;
800 }
801 }
801
802
802 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
803 QVariant PythonQt::call(PyObject* object, const QString& name, const QVariantList& args)
803 {
804 {
804 PythonQtObjectPtr callable = lookupCallable(object, name);
805 PythonQtObjectPtr callable = lookupCallable(object, name);
805 if (callable) {
806 if (callable) {
806 return call(callable, args);
807 return call(callable, args);
807 } else {
808 } else {
808 return QVariant();
809 return QVariant();
809 }
810 }
810 }
811 }
811
812
812 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
813 QVariant PythonQt::call(PyObject* callable, const QVariantList& args)
813 {
814 {
814 QVariant r;
815 QVariant r;
815 PythonQtObjectPtr result;
816 PythonQtObjectPtr result;
816 result.setNewRef(callAndReturnPyObject(callable, args));
817 result.setNewRef(callAndReturnPyObject(callable, args));
817 if (result) {
818 if (result) {
818 r = PythonQtConv::PyObjToQVariant(result);
819 r = PythonQtConv::PyObjToQVariant(result);
819 } else {
820 } else {
820 PythonQt::self()->handleError();
821 PythonQt::self()->handleError();
821 }
822 }
822 return r;
823 return r;
823 }
824 }
824
825
825 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
826 PyObject* PythonQt::callAndReturnPyObject(PyObject* callable, const QVariantList& args)
826 {
827 {
827 PyObject* result = NULL;
828 PyObject* result = NULL;
828 if (callable) {
829 if (callable) {
829 PythonQtObjectPtr pargs;
830 PythonQtObjectPtr pargs;
830 int count = args.size();
831 int count = args.size();
831 if (count>0) {
832 if (count>0) {
832 pargs.setNewRef(PyTuple_New(count));
833 pargs.setNewRef(PyTuple_New(count));
833 }
834 }
834 bool err = false;
835 bool err = false;
835 // transform QVariants to Python
836 // transform QVariants to Python
836 for (int i = 0; i < count; i++) {
837 for (int i = 0; i < count; i++) {
837 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
838 PyObject* arg = PythonQtConv::QVariantToPyObject(args.at(i));
838 if (arg) {
839 if (arg) {
839 // steals reference, no unref
840 // steals reference, no unref
840 PyTuple_SetItem(pargs, i,arg);
841 PyTuple_SetItem(pargs, i,arg);
841 } else {
842 } else {
842 err = true;
843 err = true;
843 break;
844 break;
844 }
845 }
845 }
846 }
846
847
847 if (!err) {
848 if (!err) {
848 PyErr_Clear();
849 PyErr_Clear();
849 result = PyObject_CallObject(callable, pargs);
850 result = PyObject_CallObject(callable, pargs);
850 }
851 }
851 }
852 }
852 return result;
853 return result;
853 }
854 }
854
855
855 void PythonQt::addInstanceDecorators(QObject* o)
856 void PythonQt::addInstanceDecorators(QObject* o)
856 {
857 {
857 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
858 _p->addDecorators(o, PythonQtPrivate::InstanceDecorator);
858 }
859 }
859
860
860 void PythonQt::addClassDecorators(QObject* o)
861 void PythonQt::addClassDecorators(QObject* o)
861 {
862 {
862 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
863 _p->addDecorators(o, PythonQtPrivate::StaticDecorator | PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
863 }
864 }
864
865
865 void PythonQt::addDecorators(QObject* o)
866 void PythonQt::addDecorators(QObject* o)
866 {
867 {
867 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
868 _p->addDecorators(o, PythonQtPrivate::AllDecorators);
868 }
869 }
869
870
870 void PythonQt::registerQObjectClassNames(const QStringList& names)
871 void PythonQt::registerQObjectClassNames(const QStringList& names)
871 {
872 {
872 _p->registerQObjectClassNames(names);
873 _p->registerQObjectClassNames(names);
873 }
874 }
874
875
875 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
876 void PythonQt::setImporter(PythonQtImportFileInterface* importInterface)
876 {
877 {
877 _p->_importInterface = importInterface;
878 _p->_importInterface = importInterface;
878 PythonQtImport::init();
879 PythonQtImport::init();
879 }
880 }
880
881
881 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
882 void PythonQt::setImporterIgnorePaths(const QStringList& paths)
882 {
883 {
883 _p->_importIgnorePaths = paths;
884 _p->_importIgnorePaths = paths;
884 }
885 }
885
886
886 const QStringList& PythonQt::getImporterIgnorePaths()
887 const QStringList& PythonQt::getImporterIgnorePaths()
887 {
888 {
888 return _p->_importIgnorePaths;
889 return _p->_importIgnorePaths;
889 }
890 }
890
891
891 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
892 void PythonQt::addWrapperFactory(PythonQtCppWrapperFactory* factory)
892 {
893 {
893 _p->_cppWrapperFactories.append(factory);
894 _p->_cppWrapperFactories.append(factory);
894 }
895 }
895
896
896 //---------------------------------------------------------------------------------------------------
897 //---------------------------------------------------------------------------------------------------
897 PythonQtPrivate::PythonQtPrivate()
898 PythonQtPrivate::PythonQtPrivate()
898 {
899 {
899 _importInterface = NULL;
900 _importInterface = NULL;
900 _defaultImporter = new PythonQtQFileImporter;
901 _defaultImporter = new PythonQtQFileImporter;
901 _noLongerWrappedCB = NULL;
902 _noLongerWrappedCB = NULL;
902 _wrappedCB = NULL;
903 _wrappedCB = NULL;
903 _currentClassInfoForClassWrapperCreation = NULL;
904 _currentClassInfoForClassWrapperCreation = NULL;
904 }
905 }
905
906
906 void PythonQtPrivate::setupSharedLibrarySuffixes()
907 void PythonQtPrivate::setupSharedLibrarySuffixes()
907 {
908 {
908 _sharedLibrarySuffixes.clear();
909 _sharedLibrarySuffixes.clear();
909 PythonQtObjectPtr imp;
910 PythonQtObjectPtr imp;
910 imp.setNewRef(PyImport_ImportModule("imp"));
911 imp.setNewRef(PyImport_ImportModule("imp"));
911 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
912 int cExtensionCode = imp.getVariable("C_EXTENSION").toInt();
912 QVariant result = imp.call("get_suffixes");
913 QVariant result = imp.call("get_suffixes");
913 foreach (QVariant entry, result.toList()) {
914 foreach (QVariant entry, result.toList()) {
914 QVariantList suffixEntry = entry.toList();
915 QVariantList suffixEntry = entry.toList();
915 if (suffixEntry.count()==3) {
916 if (suffixEntry.count()==3) {
916 int code = suffixEntry.at(2).toInt();
917 int code = suffixEntry.at(2).toInt();
917 if (code == cExtensionCode) {
918 if (code == cExtensionCode) {
918 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
919 _sharedLibrarySuffixes << suffixEntry.at(0).toString();
919 }
920 }
920 }
921 }
921 }
922 }
922 }
923 }
923
924
924 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
925 PythonQtClassInfo* PythonQtPrivate::currentClassInfoForClassWrapperCreation()
925 {
926 {
926 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
927 PythonQtClassInfo* info = _currentClassInfoForClassWrapperCreation;
927 _currentClassInfoForClassWrapperCreation = NULL;
928 _currentClassInfoForClassWrapperCreation = NULL;
928 return info;
929 return info;
929 }
930 }
930
931
931 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
932 void PythonQtPrivate::addDecorators(QObject* o, int decoTypes)
932 {
933 {
933 o->setParent(this);
934 o->setParent(this);
934 int numMethods = o->metaObject()->methodCount();
935 int numMethods = o->metaObject()->methodCount();
935 for (int i = 0; i < numMethods; i++) {
936 for (int i = 0; i < numMethods; i++) {
936 QMetaMethod m = o->metaObject()->method(i);
937 QMetaMethod m = o->metaObject()->method(i);
937 if ((m.methodType() == QMetaMethod::Method ||
938 if ((m.methodType() == QMetaMethod::Method ||
938 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
939 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
939 if (qstrncmp(m.signature(), "new_", 4)==0) {
940 if (qstrncmp(m.signature(), "new_", 4)==0) {
940 if ((decoTypes & ConstructorDecorator) == 0) continue;
941 if ((decoTypes & ConstructorDecorator) == 0) continue;
941 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
942 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
942 if (info->parameters().at(0).isPointer) {
943 if (info->parameters().at(0).isPointer) {
943 QByteArray signature = m.signature();
944 QByteArray signature = m.signature();
944 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
945 QByteArray nameOfClass = signature.mid(4, signature.indexOf('(')-4);
945 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
946 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
946 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
947 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
947 classInfo->addConstructor(newSlot);
948 classInfo->addConstructor(newSlot);
948 }
949 }
949 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
950 } else if (qstrncmp(m.signature(), "delete_", 7)==0) {
950 if ((decoTypes & DestructorDecorator) == 0) continue;
951 if ((decoTypes & DestructorDecorator) == 0) continue;
951 QByteArray signature = m.signature();
952 QByteArray signature = m.signature();
952 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
953 QByteArray nameOfClass = signature.mid(7, signature.indexOf('(')-7);
953 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
954 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
954 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
955 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
955 classInfo->setDestructor(newSlot);
956 classInfo->setDestructor(newSlot);
956 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
957 } else if (qstrncmp(m.signature(), "static_", 7)==0) {
957 if ((decoTypes & StaticDecorator) == 0) continue;
958 if ((decoTypes & StaticDecorator) == 0) continue;
958 QByteArray signature = m.signature();
959 QByteArray signature = m.signature();
959 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
960 QByteArray nameOfClass = signature.mid(signature.indexOf('_')+1);
960 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
961 nameOfClass = nameOfClass.mid(0, nameOfClass.indexOf('_'));
961 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
962 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(nameOfClass);
962 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
963 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::ClassDecorator);
963 classInfo->addDecoratorSlot(newSlot);
964 classInfo->addDecoratorSlot(newSlot);
964 } else {
965 } else {
965 if ((decoTypes & InstanceDecorator) == 0) continue;
966 if ((decoTypes & InstanceDecorator) == 0) continue;
966 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
967 const PythonQtMethodInfo* info = PythonQtMethodInfo::getCachedMethodInfo(m, NULL);
967 if (info->parameters().count()>1) {
968 if (info->parameters().count()>1) {
968 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
969 PythonQtMethodInfo::ParameterInfo p = info->parameters().at(1);
969 if (p.isPointer) {
970 if (p.isPointer) {
970 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
971 PythonQtClassInfo* classInfo = lookupClassInfoAndCreateIfNotPresent(p.name);
971 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
972 PythonQtSlotInfo* newSlot = new PythonQtSlotInfo(NULL, m, i, o, PythonQtSlotInfo::InstanceDecorator);
972 classInfo->addDecoratorSlot(newSlot);
973 classInfo->addDecoratorSlot(newSlot);
973 }
974 }
974 }
975 }
975 }
976 }
976 }
977 }
977 }
978 }
978 }
979 }
979
980
980 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
981 void PythonQtPrivate::registerQObjectClassNames(const QStringList& names)
981 {
982 {
982 foreach(QString name, names) {
983 foreach(QString name, names) {
983 _knownQObjectClassNames.insert(name.toLatin1(), true);
984 _knownQObjectClassNames.insert(name.toLatin1(), true);
984 }
985 }
985 }
986 }
986
987
987 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
988 void PythonQtPrivate::removeSignalEmitter(QObject* obj)
988 {
989 {
989 _signalReceivers.remove(obj);
990 _signalReceivers.remove(obj);
990 }
991 }
991
992
992 bool PythonQt::handleError()
993 bool PythonQt::handleError()
993 {
994 {
994 bool flag = false;
995 bool flag = false;
995 if (PyErr_Occurred()) {
996 if (PyErr_Occurred()) {
996
997
997 // currently we just print the error and the stderr handler parses the errors
998 // currently we just print the error and the stderr handler parses the errors
998 PyErr_Print();
999 PyErr_Print();
999
1000
1000 /*
1001 /*
1001 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1002 // EXTRA: the format of the ptype and ptraceback is not really documented, so I use PyErr_Print() above
1002 PyObject *ptype;
1003 PyObject *ptype;
1003 PyObject *pvalue;
1004 PyObject *pvalue;
1004 PyObject *ptraceback;
1005 PyObject *ptraceback;
1005 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1006 PyErr_Fetch( &ptype, &pvalue, &ptraceback);
1006
1007
1007 Py_XDECREF(ptype);
1008 Py_XDECREF(ptype);
1008 Py_XDECREF(pvalue);
1009 Py_XDECREF(pvalue);
1009 Py_XDECREF(ptraceback);
1010 Py_XDECREF(ptraceback);
1010 */
1011 */
1011 PyErr_Clear();
1012 PyErr_Clear();
1012 flag = true;
1013 flag = true;
1013 }
1014 }
1014 return flag;
1015 return flag;
1015 }
1016 }
1016
1017
1017 void PythonQt::addSysPath(const QString& path)
1018 void PythonQt::addSysPath(const QString& path)
1018 {
1019 {
1019 PythonQtObjectPtr sys;
1020 PythonQtObjectPtr sys;
1020 sys.setNewRef(PyImport_ImportModule("sys"));
1021 sys.setNewRef(PyImport_ImportModule("sys"));
1021 PythonQtObjectPtr obj = lookupObject(sys, "path");
1022 PythonQtObjectPtr obj = lookupObject(sys, "path");
1022 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1023 PyList_Insert(obj, 0, PythonQtConv::QStringToPyObject(path));
1023 }
1024 }
1024
1025
1025 void PythonQt::overwriteSysPath(const QStringList& paths)
1026 void PythonQt::overwriteSysPath(const QStringList& paths)
1026 {
1027 {
1027 PythonQtObjectPtr sys;
1028 PythonQtObjectPtr sys;
1028 sys.setNewRef(PyImport_ImportModule("sys"));
1029 sys.setNewRef(PyImport_ImportModule("sys"));
1029 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1030 PyModule_AddObject(sys, "path", PythonQtConv::QStringListToPyList(paths));
1030 }
1031 }
1031
1032
1032 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1033 void PythonQt::setModuleImportPath(PyObject* module, const QStringList& paths)
1033 {
1034 {
1034 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1035 PyModule_AddObject(module, "__path__", PythonQtConv::QStringListToPyList(paths));
1035 }
1036 }
1036
1037
1037 void PythonQt::stdOutRedirectCB(const QString& str)
1038 void PythonQt::stdOutRedirectCB(const QString& str)
1038 {
1039 {
1039 emit PythonQt::self()->pythonStdOut(str);
1040 emit PythonQt::self()->pythonStdOut(str);
1040 }
1041 }
1041
1042
1042 void PythonQt::stdErrRedirectCB(const QString& str)
1043 void PythonQt::stdErrRedirectCB(const QString& str)
1043 {
1044 {
1044 emit PythonQt::self()->pythonStdErr(str);
1045 emit PythonQt::self()->pythonStdErr(str);
1045 }
1046 }
1046
1047
1047 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1048 void PythonQt::setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb)
1048 {
1049 {
1049 _p->_wrappedCB = cb;
1050 _p->_wrappedCB = cb;
1050 }
1051 }
1051
1052
1052 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1053 void PythonQt::setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb)
1053 {
1054 {
1054 _p->_noLongerWrappedCB = cb;
1055 _p->_noLongerWrappedCB = cb;
1055 }
1056 }
1056
1057
1057
1058
1058
1059
1059 static PyMethodDef PythonQtMethods[] = {
1060 static PyMethodDef PythonQtMethods[] = {
1060 {NULL, NULL, 0, NULL}
1061 {NULL, NULL, 0, NULL}
1061 };
1062 };
1062
1063
1063 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1064 void PythonQt::initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName)
1064 {
1065 {
1065 QByteArray name = "PythonQt";
1066 QByteArray name = "PythonQt";
1066 if (!pythonQtModuleName.isEmpty()) {
1067 if (!pythonQtModuleName.isEmpty()) {
1067 name = pythonQtModuleName;
1068 name = pythonQtModuleName;
1068 }
1069 }
1069 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1070 _p->_pythonQtModule = Py_InitModule(name.constData(), PythonQtMethods);
1070 _p->_pythonQtModuleName = name;
1071 _p->_pythonQtModuleName = name;
1071
1072
1072 if (redirectStdOut) {
1073 if (redirectStdOut) {
1073 PythonQtObjectPtr sys;
1074 PythonQtObjectPtr sys;
1074 PythonQtObjectPtr out;
1075 PythonQtObjectPtr out;
1075 PythonQtObjectPtr err;
1076 PythonQtObjectPtr err;
1076 sys.setNewRef(PyImport_ImportModule("sys"));
1077 sys.setNewRef(PyImport_ImportModule("sys"));
1077 // create a redirection object for stdout and stderr
1078 // create a redirection object for stdout and stderr
1078 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1079 out = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1079 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1080 ((PythonQtStdOutRedirect*)out.object())->_cb = stdOutRedirectCB;
1080 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1081 err = PythonQtStdOutRedirectType.tp_new(&PythonQtStdOutRedirectType,NULL, NULL);
1081 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1082 ((PythonQtStdOutRedirect*)err.object())->_cb = stdErrRedirectCB;
1082 // replace the built in file objects with our own objects
1083 // replace the built in file objects with our own objects
1083 PyModule_AddObject(sys, "stdout", out);
1084 PyModule_AddObject(sys, "stdout", out);
1084 PyModule_AddObject(sys, "stderr", err);
1085 PyModule_AddObject(sys, "stderr", err);
1085 }
1086 }
1086 }
1087 }
1087
1088
1088 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1089 void PythonQt::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell)
1089 {
1090 {
1090 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1091 _p->registerCPPClass(typeName, parentTypeName, package, wrapperCreator, shell);
1091 }
1092 }
1092
1093
1093
1094
1094 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1095 PythonQtClassInfo* PythonQtPrivate::lookupClassInfoAndCreateIfNotPresent(const char* typeName)
1095 {
1096 {
1096 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1097 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1097 if (!info) {
1098 if (!info) {
1098 info = new PythonQtClassInfo();
1099 info = new PythonQtClassInfo();
1099 info->setupCPPObject(typeName);
1100 info->setupCPPObject(typeName);
1100 _knownClassInfos.insert(typeName, info);
1101 _knownClassInfos.insert(typeName, info);
1101 }
1102 }
1102 return info;
1103 return info;
1103 }
1104 }
1104
1105
1105 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1106 void PythonQt::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1106 {
1107 {
1107 _p->addPolymorphicHandler(typeName, cb);
1108 _p->addPolymorphicHandler(typeName, cb);
1108 }
1109 }
1109
1110
1110 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1111 void PythonQtPrivate::addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb)
1111 {
1112 {
1112 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1113 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1113 info->addPolymorphicHandler(cb);
1114 info->addPolymorphicHandler(cb);
1114 }
1115 }
1115
1116
1116 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1117 bool PythonQt::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1117 {
1118 {
1118 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1119 return _p->addParentClass(typeName, parentTypeName, upcastingOffset);
1119 }
1120 }
1120
1121
1121 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1122 bool PythonQtPrivate::addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset)
1122 {
1123 {
1123 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1124 PythonQtClassInfo* info = _knownClassInfos.value(typeName);
1124 if (info) {
1125 if (info) {
1125 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1126 PythonQtClassInfo* parentInfo = lookupClassInfoAndCreateIfNotPresent(parentTypeName);
1126 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1127 info->addParentClass(PythonQtClassInfo::ParentClassInfo(parentInfo, upcastingOffset));
1127 return true;
1128 return true;
1128 } else {
1129 } else {
1129 return false;
1130 return false;
1130 }
1131 }
1131 }
1132 }
1132
1133
1133 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module)
1134 void PythonQtPrivate::registerCPPClass(const char* typeName, const char* parentTypeName, const char* package, PythonQtQObjectCreatorFunctionCB* wrapperCreator, PythonQtShellSetInstanceWrapperCB* shell, PyObject* module, int typeSlots)
1134 {
1135 {
1135 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1136 PythonQtClassInfo* info = lookupClassInfoAndCreateIfNotPresent(typeName);
1136 if (!info->pythonQtClassWrapper()) {
1137 if (!info->pythonQtClassWrapper()) {
1138 info->setTypeSlots(typeSlots);
1137 info->setupCPPObject(typeName);
1139 info->setupCPPObject(typeName);
1138 createPythonQtClassWrapper(info, package, module);
1140 createPythonQtClassWrapper(info, package, module);
1139 }
1141 }
1140 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1142 if (parentTypeName && strcmp(parentTypeName,"")!=0) {
1141 addParentClass(typeName, parentTypeName, 0);
1143 addParentClass(typeName, parentTypeName, 0);
1142 }
1144 }
1143 if (wrapperCreator) {
1145 if (wrapperCreator) {
1144 info->setDecoratorProvider(wrapperCreator);
1146 info->setDecoratorProvider(wrapperCreator);
1145 }
1147 }
1146 if (shell) {
1148 if (shell) {
1147 info->setShellSetInstanceWrapperCB(shell);
1149 info->setShellSetInstanceWrapperCB(shell);
1148 }
1150 }
1149 }
1151 }
1150
1152
1151 PyObject* PythonQtPrivate::packageByName(const char* name)
1153 PyObject* PythonQtPrivate::packageByName(const char* name)
1152 {
1154 {
1153 if (name==NULL || name[0]==0) {
1155 if (name==NULL || name[0]==0) {
1154 name = "private";
1156 name = "private";
1155 }
1157 }
1156 PyObject* v = _packages.value(name);
1158 PyObject* v = _packages.value(name);
1157 if (!v) {
1159 if (!v) {
1158 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1160 v = PyImport_AddModule((_pythonQtModuleName + "." + name).constData());
1159 _packages.insert(name, v);
1161 _packages.insert(name, v);
1160 // AddObject steals the reference, so increment it!
1162 // AddObject steals the reference, so increment it!
1161 Py_INCREF(v);
1163 Py_INCREF(v);
1162 PyModule_AddObject(_pythonQtModule, name, v);
1164 PyModule_AddObject(_pythonQtModule, name, v);
1163 }
1165 }
1164 return v;
1166 return v;
1165 }
1167 }
1166
1168
1167 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1169 void PythonQtPrivate::handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result)
1168 {
1170 {
1169 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1171 QString error = "Return value '" + PythonQtConv::PyObjGetString(result) + "' can not be converted to expected C++ type '" + methodInfo->parameters().at(0).name + "' as return value of virtual method " + signature;
1170 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1172 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
1171 PythonQt::self()->handleError();
1173 PythonQt::self()->handleError();
1172 }
1174 }
1173
1175
1174 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1176 PyObject* PythonQt::helpCalled(PythonQtClassInfo* info)
1175 {
1177 {
1176 if (_p->_initFlags & ExternalHelp) {
1178 if (_p->_initFlags & ExternalHelp) {
1177 emit pythonHelpRequest(QByteArray(info->className()));
1179 emit pythonHelpRequest(QByteArray(info->className()));
1178 return Py_BuildValue("");
1180 return Py_BuildValue("");
1179 } else {
1181 } else {
1180 return PyString_FromString(info->help().toLatin1().data());
1182 return PyString_FromString(info->help().toLatin1().data());
1181 }
1183 }
1182 }
1184 }
1183
1185
1184 void PythonQtPrivate::removeWrapperPointer(void* obj)
1186 void PythonQtPrivate::removeWrapperPointer(void* obj)
1185 {
1187 {
1186 _wrappedObjects.remove(obj);
1188 _wrappedObjects.remove(obj);
1187 }
1189 }
1188
1190
1189 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1191 void PythonQtPrivate::addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper)
1190 {
1192 {
1191 _wrappedObjects.insert(obj, wrapper);
1193 _wrappedObjects.insert(obj, wrapper);
1192 }
1194 }
1193
1195
1194 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1196 PythonQtInstanceWrapper* PythonQtPrivate::findWrapperAndRemoveUnused(void* obj)
1195 {
1197 {
1196 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1198 PythonQtInstanceWrapper* wrap = _wrappedObjects.value(obj);
1197 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1199 if (wrap && !wrap->_wrappedPtr && wrap->_obj == NULL) {
1198 // this is a wrapper whose QObject was already removed due to destruction
1200 // this is a wrapper whose QObject was already removed due to destruction
1199 // so the obj pointer has to be a new QObject with the same address...
1201 // so the obj pointer has to be a new QObject with the same address...
1200 // we remove the old one and set the copy to NULL
1202 // we remove the old one and set the copy to NULL
1201 wrap->_objPointerCopy = NULL;
1203 wrap->_objPointerCopy = NULL;
1202 removeWrapperPointer(obj);
1204 removeWrapperPointer(obj);
1203 wrap = NULL;
1205 wrap = NULL;
1204 }
1206 }
1205 return wrap;
1207 return wrap;
1206 }
1208 }
1207
1209
1208 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1210 PythonQtObjectPtr PythonQtPrivate::createModule(const QString& name, PyObject* pycode)
1209 {
1211 {
1210 PythonQtObjectPtr result;
1212 PythonQtObjectPtr result;
1211 if (pycode) {
1213 if (pycode) {
1212 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1214 result.setNewRef(PyImport_ExecCodeModule((char*)name.toLatin1().data(), pycode));
1213 } else {
1215 } else {
1214 PythonQt::self()->handleError();
1216 PythonQt::self()->handleError();
1215 }
1217 }
1216 return result;
1218 return result;
1217 }
1219 }
@@ -1,543 +1,579
1 #ifndef _PYTHONQT_H
1 #ifndef _PYTHONQT_H
2 #define _PYTHONQT_H
2 #define _PYTHONQT_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 //----------------------------------------------------------------------------------
36 //----------------------------------------------------------------------------------
37 /*!
37 /*!
38 // \file PythonQt.h
38 // \file PythonQt.h
39 // \author Florian Link
39 // \author Florian Link
40 // \author Last changed by $Author: florian $
40 // \author Last changed by $Author: florian $
41 // \date 2006-05
41 // \date 2006-05
42 */
42 */
43 //----------------------------------------------------------------------------------
43 //----------------------------------------------------------------------------------
44
44
45 #include "PythonQtSystem.h"
45 #include "PythonQtSystem.h"
46 #include "PythonQtInstanceWrapper.h"
46 #include "PythonQtInstanceWrapper.h"
47 #include "PythonQtClassWrapper.h"
47 #include "PythonQtClassWrapper.h"
48 #include "PythonQtSlot.h"
48 #include "PythonQtSlot.h"
49 #include "PythonQtObjectPtr.h"
49 #include "PythonQtObjectPtr.h"
50 #include <QObject>
50 #include <QObject>
51 #include <QVariant>
51 #include <QVariant>
52 #include <QList>
52 #include <QList>
53 #include <QHash>
53 #include <QHash>
54 #include <QByteArray>
54 #include <QByteArray>
55 #include <QStringList>
55 #include <QStringList>
56 #include <QtDebug>
56 #include <QtDebug>
57 #include <iostream>
57 #include <iostream>
58
58
59
59
60 class PythonQtClassInfo;
60 class PythonQtClassInfo;
61 class PythonQtPrivate;
61 class PythonQtPrivate;
62 class PythonQtMethodInfo;
62 class PythonQtMethodInfo;
63 class PythonQtSignalReceiver;
63 class PythonQtSignalReceiver;
64 class PythonQtImportFileInterface;
64 class PythonQtImportFileInterface;
65 class PythonQtCppWrapperFactory;
65 class PythonQtCppWrapperFactory;
66 class PythonQtQFileImporter;
66 class PythonQtQFileImporter;
67
67
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
68 typedef void PythonQtQObjectWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
69 typedef void PythonQtQObjectNoLongerWrappedCB(QObject* object);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
70 typedef void* PythonQtPolymorphicHandlerCB(const void *ptr, char **class_name);
71
71
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
72 typedef void PythonQtShellSetInstanceWrapperCB(void* object, PythonQtInstanceWrapper* wrapper);
73
73
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
74 template<class T> void PythonQtSetInstanceWrapperOnShell(void* object, PythonQtInstanceWrapper* wrapper) { ((T*)object)->_wrapper = wrapper; };
75
75
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
76 //! returns the offset that needs to be added to upcast an object of type T1 to T2
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
77 template<class T1, class T2> int PythonQtUpcastingOffset() {
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
78 return (((char*)(static_cast<T2*>(reinterpret_cast<T1*>(0x100)))) - ((char*)reinterpret_cast<T1*>(0x100)));
79 }
79 }
80
80
81 //! callback to create a QObject lazily
81 //! callback to create a QObject lazily
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
82 typedef QObject* PythonQtQObjectCreatorFunctionCB();
83
83
84 //! helper template to create a derived QObject class
84 //! helper template to create a derived QObject class
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
85 template<class T> QObject* PythonQtCreateObject() { return new T(); };
86
86
87 //! the main interface to the Python Qt binding, realized as a singleton
87 //! the main interface to the Python Qt binding, realized as a singleton
88 class PYTHONQT_EXPORT PythonQt : public QObject {
88 class PYTHONQT_EXPORT PythonQt : public QObject {
89
89
90 Q_OBJECT
90 Q_OBJECT
91
91
92 public:
92 public:
93 enum InitFlags {
93 enum InitFlags {
94 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
94 RedirectStdOut = 1, //!<< sets if the std out/err is redirected to pythonStdOut() and pythonStdErr() signals
95 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
95 IgnoreSiteModule = 2, //!<< sets if Python should ignore the site module
96 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
96 ExternalHelp = 4 //!<< sets if help() calls on PythonQt modules are forwarded to the pythonHelpRequest() signal
97 };
97 };
98
98
99 //! flags that tell PythonQt which operators to expect on the registered type
100 enum TypeSlots {
101 Type_Add = 1,
102 Type_Subtract = 1 << 1,
103 Type_Multiply = 1 << 2,
104 Type_Divide = 1 << 3,
105 Type_Mod = 1 << 4,
106 Type_And = 1 << 5,
107 Type_Or = 1 << 6,
108 Type_Xor = 1 << 7,
109 Type_LShift = 1 << 8,
110 Type_RShift = 1 << 9,
111
112 Type_InplaceAdd = 1 << 10,
113 Type_InplaceSubtract = 1 << 11,
114 Type_InplaceMultiply = 1 << 12,
115 Type_InplaceDivide = 1 << 13,
116 Type_InplaceMod = 1 << 14,
117 Type_InplaceAnd = 1 << 15,
118 Type_InplaceOr = 1 << 16,
119 Type_InplaceXor = 1 << 17,
120 Type_InplaceLShift = 1 << 18,
121 Type_InplaceRShift = 1 << 19,
122
123 // Not yet needed/nicely mappable/generated...
124 //Type_Positive = 1 << 29,
125 //Type_Negative = 1 << 29,
126 //Type_Abs = 1 << 29,
127 //Type_Hash = 1 << 29,
128
129 Type_Invert = 1 << 29,
130 Type_RichCompare = 1 << 30,
131 Type_NonZero = 1 << 31,
132
133 };
134
99 //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given
135 //! initialize the python qt binding (flags are a or combination of InitFlags), if \c pythonQtModuleName is given
100 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
136 //! it defines the name of the python module that PythonQt will add, otherwise "PythonQt" is used.
101 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
137 //! This can be used to e.g. pass in PySide or PyQt4 to make it more compatible.
102 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
138 static void init(int flags = IgnoreSiteModule | RedirectStdOut, const QByteArray& pythonQtModuleName = QByteArray());
103
139
104 //! cleanup
140 //! cleanup
105 static void cleanup();
141 static void cleanup();
106
142
107 //! get the singleton instance
143 //! get the singleton instance
108 static PythonQt* self() { return _self; }
144 static PythonQt* self() { return _self; }
109
145
110 //-----------------------------------------------------------------------------
146 //-----------------------------------------------------------------------------
111 // Public API:
147 // Public API:
112
148
113 //! defines the object types for introspection
149 //! defines the object types for introspection
114 enum ObjectType {
150 enum ObjectType {
115 Class,
151 Class,
116 Function,
152 Function,
117 Variable,
153 Variable,
118 Module,
154 Module,
119 Anything,
155 Anything,
120 CallOverloads
156 CallOverloads
121 };
157 };
122
158
123 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
159 //! overwrite the python sys path (call this directly after PythonQt::init() if you want to change the std python sys path)
124 void overwriteSysPath(const QStringList& paths);
160 void overwriteSysPath(const QStringList& paths);
125
161
126 //! prepend a path to sys.path to allow importing from it
162 //! prepend a path to sys.path to allow importing from it
127 void addSysPath(const QString& path);
163 void addSysPath(const QString& path);
128
164
129 //! sets the __path__ list of a module to the given list (important for local imports)
165 //! sets the __path__ list of a module to the given list (important for local imports)
130 void setModuleImportPath(PyObject* module, const QStringList& paths);
166 void setModuleImportPath(PyObject* module, const QStringList& paths);
131
167
132 //! get the __main__ module of python
168 //! get the __main__ module of python
133 PythonQtObjectPtr getMainModule();
169 PythonQtObjectPtr getMainModule();
134
170
135 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
171 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
136 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
172 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
137 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
173 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
138 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
174 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
139
175
140 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
176 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
141 //! (ownership of wrapper is passed to PythonQt)
177 //! (ownership of wrapper is passed to PythonQt)
142 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
178 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
143
179
144 This will add a wrapper object that is used to make calls to the given classname \c typeName.
180 This will add a wrapper object that is used to make calls to the given classname \c typeName.
145 All slots that take a pointer to typeName as the first argument will be callable from Python on
181 All slots that take a pointer to typeName as the first argument will be callable from Python on
146 a variant object that contains such a type.
182 a variant object that contains such a type.
147 */
183 */
148 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
184 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL);
149
185
150 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
186 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
151 //! and it will register the classes when it first sees a pointer to such a derived class
187 //! and it will register the classes when it first sees a pointer to such a derived class
152 void registerQObjectClassNames(const QStringList& names);
188 void registerQObjectClassNames(const QStringList& names);
153
189
154 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
190 //! add a parent class relation to the \c given typeName, the upcastingOffset is needed for multiple inheritance
155 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
191 //! and can be calculated using PythonQtUpcastingOffset<type,parentType>(), which also verifies that
156 //! type is really derived from parentType.
192 //! type is really derived from parentType.
157 //! Returns false if the typeName was not yet registered.
193 //! Returns false if the typeName was not yet registered.
158 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
194 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset=0);
159
195
160 //! add a handler for polymorphic downcasting
196 //! add a handler for polymorphic downcasting
161 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
197 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
162
198
163 //! parses the given file and returns the python code object, this can then be used to call evalCode()
199 //! parses the given file and returns the python code object, this can then be used to call evalCode()
164 PythonQtObjectPtr parseFile(const QString& filename);
200 PythonQtObjectPtr parseFile(const QString& filename);
165
201
166 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
202 //! evaluates the given code and returns the result value (use Py_Compile etc. to create pycode from string)
167 //! If pycode is NULL, a python error is printed.
203 //! If pycode is NULL, a python error is printed.
168 QVariant evalCode(PyObject* object, PyObject* pycode);
204 QVariant evalCode(PyObject* object, PyObject* pycode);
169
205
170 //! evaluates the given script code and returns the result value
206 //! evaluates the given script code and returns the result value
171 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
207 QVariant evalScript(PyObject* object, const QString& script, int start = Py_file_input);
172
208
173 //! evaluates the given script code from file
209 //! evaluates the given script code from file
174 void evalFile(PyObject* object, const QString& filename);
210 void evalFile(PyObject* object, const QString& filename);
175
211
176 //! creates the new module \c name and evaluates the given file in the context of that module
212 //! creates the new module \c name and evaluates the given file in the context of that module
177 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
213 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
178 //! to a module later on.
214 //! to a module later on.
179 //! The user needs to make sure that the \c name is unique in the python module dictionary.
215 //! The user needs to make sure that the \c name is unique in the python module dictionary.
180 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
216 PythonQtObjectPtr createModuleFromFile(const QString& name, const QString& filename);
181
217
182 //! creates the new module \c name and evaluates the given script in the context of that module.
218 //! creates the new module \c name and evaluates the given script in the context of that module.
183 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
219 //! If the \c script is empty, the module contains no initial code. You can use evalScript/evalCode to add code
184 //! to a module later on.
220 //! to a module later on.
185 //! The user needs to make sure that the \c name is unique in the python module dictionary.
221 //! The user needs to make sure that the \c name is unique in the python module dictionary.
186 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
222 PythonQtObjectPtr createModuleFromScript(const QString& name, const QString& script = QString());
187
223
188 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
224 //! create a uniquely named module, you can use evalFile or evalScript to populate the module with
189 //! script code
225 //! script code
190 PythonQtObjectPtr createUniqueModule();
226 PythonQtObjectPtr createUniqueModule();
191
227
192 //@{ Signal handlers
228 //@{ Signal handlers
193
229
194 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
230 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c objectname in module
195 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
231 bool addSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
196
232
197 //! remove a signal handler from the given \c signal of \c obj
233 //! remove a signal handler from the given \c signal of \c obj
198 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
234 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* module, const QString& objectname);
199
235
200 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
236 //! add a signal handler to the given \c signal of \c obj and connect it to a callable \c receiver
201 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
237 bool addSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
202
238
203 //! remove a signal handler from the given \c signal of \c obj
239 //! remove a signal handler from the given \c signal of \c obj
204 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
240 bool removeSignalHandler(QObject* obj, const char* signal, PyObject* receiver);
205
241
206 //@}
242 //@}
207
243
208 //@{ Variable access
244 //@{ Variable access
209
245
210 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
246 //! add the given \c qObject to the python \c object as a variable with \c name (it can be removed via clearVariable)
211 void addObject(PyObject* object, const QString& name, QObject* qObject);
247 void addObject(PyObject* object, const QString& name, QObject* qObject);
212
248
213 //! add the given variable to the object
249 //! add the given variable to the object
214 void addVariable(PyObject* object, const QString& name, const QVariant& v);
250 void addVariable(PyObject* object, const QString& name, const QVariant& v);
215
251
216 //! remove the given variable
252 //! remove the given variable
217 void removeVariable(PyObject* module, const QString& name);
253 void removeVariable(PyObject* module, const QString& name);
218
254
219 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
255 //! get the variable with the \c name of the \c object, returns an invalid QVariant on error
220 QVariant getVariable(PyObject* object, const QString& name);
256 QVariant getVariable(PyObject* object, const QString& name);
221
257
222 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
258 //! read vars etc. in scope of an \c object, optional looking inside of an object \c objectname
223 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
259 QStringList introspection(PyObject* object, const QString& objectname, ObjectType type);
224
260
225 //! returns the found callable object or NULL
261 //! returns the found callable object or NULL
226 //! @return new reference
262 //! @return new reference
227 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
263 PythonQtObjectPtr lookupCallable(PyObject* object, const QString& name);
228
264
229 //@}
265 //@}
230
266
231 //@{ Calling of python callables
267 //@{ Calling of python callables
232
268
233 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
269 //! call the given python \c callable in the scope of object, returns the result converted to a QVariant
234 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
270 QVariant call(PyObject* object, const QString& callable, const QVariantList& args = QVariantList());
235
271
236 //! call the given python object, returns the result converted to a QVariant
272 //! call the given python object, returns the result converted to a QVariant
237 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
273 QVariant call(PyObject* callable, const QVariantList& args = QVariantList());
238
274
239 //! call the given python object, returns the result as new PyObject
275 //! call the given python object, returns the result as new PyObject
240 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
276 PyObject* callAndReturnPyObject(PyObject* callable, const QVariantList& args = QVariantList());
241
277
242 //@}
278 //@}
243
279
244 //@{ Decorations, constructors, wrappers...
280 //@{ Decorations, constructors, wrappers...
245
281
246
282
247 //! add an object whose slots will be used as decorator slots for
283 //! add an object whose slots will be used as decorator slots for
248 //! other QObjects or CPP classes. The slots need to follow the
284 //! other QObjects or CPP classes. The slots need to follow the
249 //! convention that the first argument is a pointer to the wrapped object.
285 //! convention that the first argument is a pointer to the wrapped object.
250 //! (ownership is passed to PythonQt)
286 //! (ownership is passed to PythonQt)
251 /*!
287 /*!
252 Example:
288 Example:
253
289
254 A slot with the signature
290 A slot with the signature
255
291
256 \code
292 \code
257 bool doSomething(QWidget* w, int a)
293 bool doSomething(QWidget* w, int a)
258 \endcode
294 \endcode
259
295
260 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
296 will extend QWidget instances (and derived classes) with a "bool doSomething(int a)" slot
261 that will be called with the concrete instance as first argument.
297 that will be called with the concrete instance as first argument.
262 So in Python you can now e.g. call
298 So in Python you can now e.g. call
263
299
264 \code
300 \code
265 someWidget.doSomething(12)
301 someWidget.doSomething(12)
266 \endcode
302 \endcode
267
303
268 without QWidget really having this method. This allows to easily make normal methods
304 without QWidget really having this method. This allows to easily make normal methods
269 of Qt classes callable by forwarding them with such decorator slots
305 of Qt classes callable by forwarding them with such decorator slots
270 or to make CPP classes (which are not derived from QObject) callable from Python.
306 or to make CPP classes (which are not derived from QObject) callable from Python.
271 */
307 */
272 void addInstanceDecorators(QObject* o);
308 void addInstanceDecorators(QObject* o);
273
309
274 //! add an object whose slots will be used as decorator slots for
310 //! add an object whose slots will be used as decorator slots for
275 //! class objects (ownership is passed to PythonQt)
311 //! class objects (ownership is passed to PythonQt)
276 /*!
312 /*!
277 The slots need to follow the following convention:
313 The slots need to follow the following convention:
278 - SomeClass* new_SomeClass(...)
314 - SomeClass* new_SomeClass(...)
279 - QVariant new_SomeClass(...)
315 - QVariant new_SomeClass(...)
280 - void delete_SomeClass(SomeClass*)
316 - void delete_SomeClass(SomeClass*)
281 - ... static_SomeClass_someName(...)
317 - ... static_SomeClass_someName(...)
282
318
283 This will add:
319 This will add:
284 - a constructor
320 - a constructor
285 - a constructor which generates a QVariant
321 - a constructor which generates a QVariant
286 - a destructor (only useful for CPP objects)
322 - a destructor (only useful for CPP objects)
287 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
323 - a static decorator slot which will be available on the MetaObject (visible in PythonQt module)
288
324
289 */
325 */
290 void addClassDecorators(QObject* o);
326 void addClassDecorators(QObject* o);
291
327
292 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
328 //! this will add the object both as class and instance decorator (ownership is passed to PythonQt)
293 void addDecorators(QObject* o);
329 void addDecorators(QObject* o);
294
330
295 //! add the given factory to PythonQt (ownership stays with caller)
331 //! add the given factory to PythonQt (ownership stays with caller)
296 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
332 void addWrapperFactory(PythonQtCppWrapperFactory* factory);
297
333
298 //@}
334 //@}
299
335
300 //@{ Custom importer (to replace internal import implementation of python)
336 //@{ Custom importer (to replace internal import implementation of python)
301
337
302 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
338 //! replace the internal import implementation and use the supplied interface to load files (both py and pyc files)
303 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
339 //! (this method should be called directly after initialization of init() and before calling overwriteSysPath().
304 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
340 //! On the first call to this method, it will install a generic PythonQt importer in Pythons "path_hooks".
305 //! This is not reversible, so even setting setImporter(NULL) afterwards will
341 //! This is not reversible, so even setting setImporter(NULL) afterwards will
306 //! keep the custom PythonQt importer with a QFile default import interface.
342 //! keep the custom PythonQt importer with a QFile default import interface.
307 //! Subsequent python import calls will make use of the passed importInterface
343 //! Subsequent python import calls will make use of the passed importInterface
308 //! which forwards all import calls to the given \c importInterface.
344 //! which forwards all import calls to the given \c importInterface.
309 //! Passing NULL will install a default QFile importer.
345 //! Passing NULL will install a default QFile importer.
310 //! (\c importInterface ownership stays with caller)
346 //! (\c importInterface ownership stays with caller)
311 void setImporter(PythonQtImportFileInterface* importInterface);
347 void setImporter(PythonQtImportFileInterface* importInterface);
312
348
313 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
349 //! this installs the default QFile importer (which effectively does a setImporter(NULL))
314 //! (without calling setImporter or installDefaultImporter at least once, the default python import
350 //! (without calling setImporter or installDefaultImporter at least once, the default python import
315 //! mechanism is in place)
351 //! mechanism is in place)
316 //! the default importer allows to import files from anywhere QFile can read from,
352 //! the default importer allows to import files from anywhere QFile can read from,
317 //! including the Qt resource system using ":". Keep in mind that you need to extend
353 //! including the Qt resource system using ":". Keep in mind that you need to extend
318 //! "sys.path" with ":" to be able to import from the Qt resources.
354 //! "sys.path" with ":" to be able to import from the Qt resources.
319 void installDefaultImporter() { setImporter(NULL); }
355 void installDefaultImporter() { setImporter(NULL); }
320
356
321 //! set paths that the importer should ignore
357 //! set paths that the importer should ignore
322 void setImporterIgnorePaths(const QStringList& paths);
358 void setImporterIgnorePaths(const QStringList& paths);
323
359
324 //! get paths that the importer should ignore
360 //! get paths that the importer should ignore
325 const QStringList& getImporterIgnorePaths();
361 const QStringList& getImporterIgnorePaths();
326
362
327 //@}
363 //@}
328
364
329 //! get access to internal data (should not be used on the public API, but is used by some C functions)
365 //! get access to internal data (should not be used on the public API, but is used by some C functions)
330 static PythonQtPrivate* priv() { return _self->_p; }
366 static PythonQtPrivate* priv() { return _self->_p; }
331
367
332 //! get access to the file importer (if set)
368 //! get access to the file importer (if set)
333 static PythonQtImportFileInterface* importInterface();
369 static PythonQtImportFileInterface* importInterface();
334
370
335 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
371 //! handle a python error, call this when a python function fails. If no error occurred, it returns false.
336 //! The error is currently just output to the python stderr, future version might implement better trace printing
372 //! The error is currently just output to the python stderr, future version might implement better trace printing
337 bool handleError();
373 bool handleError();
338
374
339 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
375 //! set a callback that is called when a QObject with parent == NULL is wrapped by pythonqt
340 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
376 void setQObjectWrappedCallback(PythonQtQObjectWrappedCB* cb);
341 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
377 //! set a callback that is called when a QObject with parent == NULL is no longer wrapped by pythonqt
342 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
378 void setQObjectNoLongerWrappedCallback(PythonQtQObjectNoLongerWrappedCB* cb);
343
379
344 //! call the callback if it is set
380 //! call the callback if it is set
345 static void qObjectNoLongerWrappedCB(QObject* o);
381 static void qObjectNoLongerWrappedCB(QObject* o);
346
382
347 signals:
383 signals:
348 //! emitted when python outputs something to stdout (and redirection is turned on)
384 //! emitted when python outputs something to stdout (and redirection is turned on)
349 void pythonStdOut(const QString& str);
385 void pythonStdOut(const QString& str);
350 //! emitted when python outputs something to stderr (and redirection is turned on)
386 //! emitted when python outputs something to stderr (and redirection is turned on)
351 void pythonStdErr(const QString& str);
387 void pythonStdErr(const QString& str);
352
388
353 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
389 //! emitted when help() is called on a PythonQt object and \c ExternalHelp is enabled
354 void pythonHelpRequest(const QByteArray& cppClassName);
390 void pythonHelpRequest(const QByteArray& cppClassName);
355
391
356
392
357 public:
393 public:
358 //! called by internal help methods
394 //! called by internal help methods
359 PyObject* helpCalled(PythonQtClassInfo* info);
395 PyObject* helpCalled(PythonQtClassInfo* info);
360
396
361 //! returns the found object or NULL
397 //! returns the found object or NULL
362 //! @return new reference
398 //! @return new reference
363 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
399 PythonQtObjectPtr lookupObject(PyObject* module, const QString& name);
364
400
365 private:
401 private:
366 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
402 void initPythonQtModule(bool redirectStdOut, const QByteArray& pythonQtModuleName);
367
403
368 //! callback for stdout redirection, emits pythonStdOut signal
404 //! callback for stdout redirection, emits pythonStdOut signal
369 static void stdOutRedirectCB(const QString& str);
405 static void stdOutRedirectCB(const QString& str);
370 //! callback for stderr redirection, emits pythonStdErr signal
406 //! callback for stderr redirection, emits pythonStdErr signal
371 static void stdErrRedirectCB(const QString& str);
407 static void stdErrRedirectCB(const QString& str);
372
408
373 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
409 //! get (and create if not available) the signal receiver of that QObject, signal receiver is made child of the passed \c obj
374 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
410 PythonQtSignalReceiver* getSignalReceiver(QObject* obj);
375
411
376 PythonQt(int flags, const QByteArray& pythonQtModuleName);
412 PythonQt(int flags, const QByteArray& pythonQtModuleName);
377 ~PythonQt();
413 ~PythonQt();
378
414
379 static PythonQt* _self;
415 static PythonQt* _self;
380 static int _uniqueModuleCount;
416 static int _uniqueModuleCount;
381
417
382 PythonQtPrivate* _p;
418 PythonQtPrivate* _p;
383
419
384 };
420 };
385
421
386 //! internal PythonQt details
422 //! internal PythonQt details
387 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
423 class PYTHONQT_EXPORT PythonQtPrivate : public QObject {
388
424
389 Q_OBJECT
425 Q_OBJECT
390
426
391 public:
427 public:
392 PythonQtPrivate();
428 PythonQtPrivate();
393 ~PythonQtPrivate();
429 ~PythonQtPrivate();
394
430
395 enum DecoratorTypes {
431 enum DecoratorTypes {
396 StaticDecorator = 1,
432 StaticDecorator = 1,
397 ConstructorDecorator = 2,
433 ConstructorDecorator = 2,
398 DestructorDecorator = 4,
434 DestructorDecorator = 4,
399 InstanceDecorator = 8,
435 InstanceDecorator = 8,
400 AllDecorators = 0xffff
436 AllDecorators = 0xffff
401 };
437 };
402
438
403 //! get the suffixes that are used for shared libraries
439 //! get the suffixes that are used for shared libraries
404 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
440 const QStringList& sharedLibrarySuffixes() { return _sharedLibrarySuffixes; }
405
441
406 //! returns if the id is the id for PythonQtObjectPtr
442 //! returns if the id is the id for PythonQtObjectPtr
407 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
443 bool isPythonQtObjectPtrMetaId(int id) { return _PythonQtObjectPtr_metaId == id; }
408
444
409 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
445 //! add the wrapper pointer (for reuse if the same obj appears while wrapper still exists)
410 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
446 void addWrapperPointer(void* obj, PythonQtInstanceWrapper* wrapper);
411 //! remove the wrapper ptr again
447 //! remove the wrapper ptr again
412 void removeWrapperPointer(void* obj);
448 void removeWrapperPointer(void* obj);
413
449
414 //! add parent class relation
450 //! add parent class relation
415 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
451 bool addParentClass(const char* typeName, const char* parentTypeName, int upcastingOffset);
416
452
417 //! add a handler for polymorphic downcasting
453 //! add a handler for polymorphic downcasting
418 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
454 void addPolymorphicHandler(const char* typeName, PythonQtPolymorphicHandlerCB* cb);
419
455
420 //! lookup existing classinfo and return new if not yet present
456 //! lookup existing classinfo and return new if not yet present
421 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
457 PythonQtClassInfo* lookupClassInfoAndCreateIfNotPresent(const char* typeName);
422
458
423 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
459 //! called when a signal emitting QObject is destroyed to remove the signal handler from the hash map
424 void removeSignalEmitter(QObject* obj);
460 void removeSignalEmitter(QObject* obj);
425
461
426 //! wrap the given QObject into a Python object (or return existing wrapper!)
462 //! wrap the given QObject into a Python object (or return existing wrapper!)
427 PyObject* wrapQObject(QObject* obj);
463 PyObject* wrapQObject(QObject* obj);
428
464
429 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
465 //! wrap the given ptr into a Python object (or return existing wrapper!) if there is a known QObject of that name or a known wrapper in the factory
430 PyObject* wrapPtr(void* ptr, const QByteArray& name);
466 PyObject* wrapPtr(void* ptr, const QByteArray& name);
431
467
432 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
468 //! registers a QObject derived class to PythonQt (this is implicitly called by addObject as well)
433 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
469 /* Since Qt4 does not offer a way to detect if a given classname is derived from QObject and thus has a QMetaObject,
434 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
470 you MUST register all your QObject derived classes here when you want them to be detected in signal and slot calls */
435 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL);
471 void registerClass(const QMetaObject* metaobject, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
436
472
437 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
473 //! add a wrapper object for the given QMetaType typeName, also does an addClassDecorators() to add constructors for variants
438 //! (ownership of wrapper is passed to PythonQt)
474 //! (ownership of wrapper is passed to PythonQt)
439 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
475 /*! Make sure that you have done a qRegisterMetaType first, if typeName is a user type!
440
476
441 This will add a wrapper object that is used to make calls to the given classname \c typeName.
477 This will add a wrapper object that is used to make calls to the given classname \c typeName.
442 All slots that take a pointer to typeName as the first argument will be callable from Python on
478 All slots that take a pointer to typeName as the first argument will be callable from Python on
443 a variant object that contains such a type.
479 a variant object that contains such a type.
444 */
480 */
445 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL);
481 void registerCPPClass(const char* typeName, const char* parentTypeName = NULL, const char* package = NULL, PythonQtQObjectCreatorFunctionCB* wrapperCreator = NULL, PythonQtShellSetInstanceWrapperCB* shell = NULL, PyObject* module = NULL, int typeSlots = 0);
446
482
447 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
483 //! as an alternative to registerClass, you can tell PythonQt the names of QObject derived classes
448 //! and it will register the classes when it first sees a pointer to such a derived class
484 //! and it will register the classes when it first sees a pointer to such a derived class
449 void registerQObjectClassNames(const QStringList& names);
485 void registerQObjectClassNames(const QStringList& names);
450
486
451 //! add a decorator object
487 //! add a decorator object
452 void addDecorators(QObject* o, int decoTypes);
488 void addDecorators(QObject* o, int decoTypes);
453
489
454 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
490 //! helper method that creates a PythonQtClassWrapper object (returns a new reference)
455 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
491 PythonQtClassWrapper* createNewPythonQtClassWrapper(PythonQtClassInfo* info, PyObject* module);
456
492
457 //! create a new instance of the given enum type with given value (returns a new reference)
493 //! create a new instance of the given enum type with given value (returns a new reference)
458 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
494 static PyObject* createEnumValueInstance(PyObject* enumType, unsigned int enumValue);
459
495
460 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
496 //! helper that creates a new int derived class that represents the enum of the given name (returns a new reference)
461 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
497 static PyObject* createNewPythonQtEnumWrapper(const char* enumName, PyObject* parentObject);
462
498
463 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
499 //! helper method that creates a PythonQtInstanceWrapper object and registers it in the object map
464 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
500 PythonQtInstanceWrapper* createNewPythonQtInstanceWrapper(QObject* obj, PythonQtClassInfo* info, void* wrappedPtr = NULL);
465
501
466 //! get the class info for a meta object (if available)
502 //! get the class info for a meta object (if available)
467 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
503 PythonQtClassInfo* getClassInfo(const QMetaObject* meta) { return _knownClassInfos.value(meta->className()); }
468
504
469 //! get the class info for a meta object (if available)
505 //! get the class info for a meta object (if available)
470 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
506 PythonQtClassInfo* getClassInfo(const QByteArray& className) { return _knownClassInfos.value(className); }
471
507
472 //! creates the new module from the given pycode
508 //! creates the new module from the given pycode
473 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
509 PythonQtObjectPtr createModule(const QString& name, PyObject* pycode);
474
510
475 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
511 //! get the current class info (for the next PythonQtClassWrapper that is created) and reset it to NULL again
476 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
512 PythonQtClassInfo* currentClassInfoForClassWrapperCreation();
477
513
478 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
514 //! the dummy tuple (which is empty and may be used to detected that a wrapper is called from internal wrapper creation
479 static PyObject* dummyTuple();
515 static PyObject* dummyTuple();
480
516
481 //! called by virtual overloads when a python return value can not be converted to the required Qt type
517 //! called by virtual overloads when a python return value can not be converted to the required Qt type
482 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
518 void handleVirtualOverloadReturnError(const char* signature, const PythonQtMethodInfo* methodInfo, PyObject* result);
483
519
484 //! get access to the PythonQt module
520 //! get access to the PythonQt module
485 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
521 PythonQtObjectPtr pythonQtModule() const { return _pythonQtModule; }
486
522
487 private:
523 private:
488 //! Setup the shared library suffixes by getting them from the "imp" module.
524 //! Setup the shared library suffixes by getting them from the "imp" module.
489 void setupSharedLibrarySuffixes();
525 void setupSharedLibrarySuffixes();
490
526
491 //! create a new pythonqt class wrapper and place it in the pythonqt module
527 //! create a new pythonqt class wrapper and place it in the pythonqt module
492 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
528 void createPythonQtClassWrapper(PythonQtClassInfo* info, const char* package, PyObject* module = NULL);
493
529
494 //! get/create new package module (the returned object is a borrowed reference)
530 //! get/create new package module (the returned object is a borrowed reference)
495 PyObject* packageByName(const char* name);
531 PyObject* packageByName(const char* name);
496
532
497 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
533 //! get the wrapper for a given pointer (and remove a wrapper of an already destroyed qobject)
498 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
534 PythonQtInstanceWrapper* findWrapperAndRemoveUnused(void* obj);
499
535
500 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
536 //! stores pointer to PyObject mapping of wrapped QObjects AND C++ objects
501 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
537 QHash<void* , PythonQtInstanceWrapper *> _wrappedObjects;
502
538
503 //! stores the meta info of known Qt classes
539 //! stores the meta info of known Qt classes
504 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
540 QHash<QByteArray, PythonQtClassInfo *> _knownClassInfos;
505
541
506 //! names of qobject derived classes that can be casted to qobject savely
542 //! names of qobject derived classes that can be casted to qobject savely
507 QHash<QByteArray, bool> _knownQObjectClassNames;
543 QHash<QByteArray, bool> _knownQObjectClassNames;
508
544
509 //! stores signal receivers for QObjects
545 //! stores signal receivers for QObjects
510 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
546 QHash<QObject* , PythonQtSignalReceiver *> _signalReceivers;
511
547
512 //! the PythonQt python module
548 //! the PythonQt python module
513 PythonQtObjectPtr _pythonQtModule;
549 PythonQtObjectPtr _pythonQtModule;
514
550
515 //! the name of the PythonQt python module
551 //! the name of the PythonQt python module
516 QByteArray _pythonQtModuleName;
552 QByteArray _pythonQtModuleName;
517
553
518 //! the importer interface (if set)
554 //! the importer interface (if set)
519 PythonQtImportFileInterface* _importInterface;
555 PythonQtImportFileInterface* _importInterface;
520
556
521 //! the default importer
557 //! the default importer
522 PythonQtQFileImporter* _defaultImporter;
558 PythonQtQFileImporter* _defaultImporter;
523
559
524 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
560 PythonQtQObjectNoLongerWrappedCB* _noLongerWrappedCB;
525 PythonQtQObjectWrappedCB* _wrappedCB;
561 PythonQtQObjectWrappedCB* _wrappedCB;
526
562
527 QStringList _importIgnorePaths;
563 QStringList _importIgnorePaths;
528 QStringList _sharedLibrarySuffixes;
564 QStringList _sharedLibrarySuffixes;
529
565
530 //! the cpp object wrapper factories
566 //! the cpp object wrapper factories
531 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
567 QList<PythonQtCppWrapperFactory*> _cppWrapperFactories;
532
568
533 QHash<QByteArray, PyObject*> _packages;
569 QHash<QByteArray, PyObject*> _packages;
534
570
535 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
571 PythonQtClassInfo* _currentClassInfoForClassWrapperCreation;
536
572
537 int _initFlags;
573 int _initFlags;
538 int _PythonQtObjectPtr_metaId;
574 int _PythonQtObjectPtr_metaId;
539
575
540 friend class PythonQt;
576 friend class PythonQt;
541 };
577 };
542
578
543 #endif
579 #endif
@@ -1,848 +1,849
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQt.cpp
35 // \file PythonQt.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassInfo.h"
42 #include "PythonQtClassInfo.h"
43 #include "PythonQtMethodInfo.h"
43 #include "PythonQtMethodInfo.h"
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include <QMetaMethod>
45 #include <QMetaMethod>
46 #include <QMetaObject>
46 #include <QMetaObject>
47 #include <QMetaEnum>
47 #include <QMetaEnum>
48
48
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
49 QHash<QByteArray, int> PythonQtMethodInfo::_parameterTypeDict;
50
50
51 PythonQtClassInfo::PythonQtClassInfo() {
51 PythonQtClassInfo::PythonQtClassInfo() {
52 _meta = NULL;
52 _meta = NULL;
53 _constructors = NULL;
53 _constructors = NULL;
54 _destructor = NULL;
54 _destructor = NULL;
55 _decoratorProvider = NULL;
55 _decoratorProvider = NULL;
56 _decoratorProviderCB = NULL;
56 _decoratorProviderCB = NULL;
57 _pythonQtClassWrapper = NULL;
57 _pythonQtClassWrapper = NULL;
58 _shellSetInstanceWrapperCB = NULL;
58 _shellSetInstanceWrapperCB = NULL;
59 _metaTypeId = -1;
59 _metaTypeId = -1;
60 _typeSlots = 0;
60 _isQObject = false;
61 _isQObject = false;
61 _enumsCreated = false;
62 _enumsCreated = false;
62 }
63 }
63
64
64 PythonQtClassInfo::~PythonQtClassInfo()
65 PythonQtClassInfo::~PythonQtClassInfo()
65 {
66 {
66 clearCachedMembers();
67 clearCachedMembers();
67
68
68 if (_constructors) {
69 if (_constructors) {
69 _constructors->deleteOverloadsAndThis();
70 _constructors->deleteOverloadsAndThis();
70 }
71 }
71 if (_destructor) {
72 if (_destructor) {
72 _destructor->deleteOverloadsAndThis();
73 _destructor->deleteOverloadsAndThis();
73 }
74 }
74 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 foreach(PythonQtSlotInfo* info, _decoratorSlots) {
75 info->deleteOverloadsAndThis();
76 info->deleteOverloadsAndThis();
76 }
77 }
77 }
78 }
78
79
79 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 void PythonQtClassInfo::setupQObject(const QMetaObject* meta)
80 {
81 {
81 // _wrappedClassName is already set earlier in the class setup
82 // _wrappedClassName is already set earlier in the class setup
82 _isQObject = true;
83 _isQObject = true;
83 _meta = meta;
84 _meta = meta;
84 }
85 }
85
86
86 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 void PythonQtClassInfo::setupCPPObject(const QByteArray& classname)
87 {
88 {
88 _isQObject = false;
89 _isQObject = false;
89 _wrappedClassName = classname;
90 _wrappedClassName = classname;
90 _metaTypeId = QMetaType::type(classname);
91 _metaTypeId = QMetaType::type(classname);
91 }
92 }
92
93
93 void PythonQtClassInfo::clearCachedMembers()
94 void PythonQtClassInfo::clearCachedMembers()
94 {
95 {
95 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 QHashIterator<QByteArray, PythonQtMemberInfo> i(_cachedMembers);
96 while (i.hasNext()) {
97 while (i.hasNext()) {
97 PythonQtMemberInfo member = i.next().value();
98 PythonQtMemberInfo member = i.next().value();
98 if (member._type== PythonQtMemberInfo::Slot) {
99 if (member._type== PythonQtMemberInfo::Slot) {
99 PythonQtSlotInfo* info = member._slot;
100 PythonQtSlotInfo* info = member._slot;
100 while (info) {
101 while (info) {
101 PythonQtSlotInfo* next = info->nextInfo();
102 PythonQtSlotInfo* next = info->nextInfo();
102 delete info;
103 delete info;
103 info = next;
104 info = next;
104 }
105 }
105 }
106 }
106 }
107 }
107 }
108 }
108
109
109 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 int PythonQtClassInfo::findCharOffset(const char* sigStart, char someChar)
110 {
111 {
111 const char* sigEnd = sigStart;
112 const char* sigEnd = sigStart;
112 char c;
113 char c;
113 do {
114 do {
114 c = *sigEnd++;
115 c = *sigEnd++;
115 } while (c!=someChar && c!=0);
116 } while (c!=someChar && c!=0);
116 return sigEnd-sigStart-1;
117 return sigEnd-sigStart-1;
117 }
118 }
118
119
119 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 bool PythonQtClassInfo::lookForPropertyAndCache(const char* memberName)
120 {
121 {
121 if (!_meta) return false;
122 if (!_meta) return false;
122
123
123 bool found = false;
124 bool found = false;
124 bool nameMapped = false;
125 bool nameMapped = false;
125 const char* attributeName = memberName;
126 const char* attributeName = memberName;
126 // look for properties
127 // look for properties
127 int i = _meta->indexOfProperty(attributeName);
128 int i = _meta->indexOfProperty(attributeName);
128 if (i==-1) {
129 if (i==-1) {
129 // try to map name to objectName
130 // try to map name to objectName
130 if (qstrcmp(attributeName, "name")==0) {
131 if (qstrcmp(attributeName, "name")==0) {
131 attributeName = "objectName";
132 attributeName = "objectName";
132 nameMapped = true;
133 nameMapped = true;
133 i = _meta->indexOfProperty(attributeName);
134 i = _meta->indexOfProperty(attributeName);
134 }
135 }
135 }
136 }
136 if (i!=-1) {
137 if (i!=-1) {
137 PythonQtMemberInfo newInfo(_meta->property(i));
138 PythonQtMemberInfo newInfo(_meta->property(i));
138 _cachedMembers.insert(attributeName, newInfo);
139 _cachedMembers.insert(attributeName, newInfo);
139 if (nameMapped) {
140 if (nameMapped) {
140 _cachedMembers.insert(memberName, newInfo);
141 _cachedMembers.insert(memberName, newInfo);
141 }
142 }
142 #ifdef PYTHONQT_DEBUG
143 #ifdef PYTHONQT_DEBUG
143 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
144 std::cout << "caching property " << memberName << " on " << _meta->className() << std::endl;
144 #endif
145 #endif
145 found = true;
146 found = true;
146 }
147 }
147 return found;
148 return found;
148 }
149 }
149
150
150 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
151 PythonQtSlotInfo* PythonQtClassInfo::recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
151 {
152 {
152 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
153 inputInfo = findDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset);
153 foreach(const ParentClassInfo& info, _parentClasses) {
154 foreach(const ParentClassInfo& info, _parentClasses) {
154 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
155 inputInfo = info._parent->recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, inputInfo, found, memberCache, upcastingOffset+info._upcastingOffset);
155 }
156 }
156 return inputInfo;
157 return inputInfo;
157 }
158 }
158
159
159 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
160 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset) {
160 QObject* decoratorProvider = decorator();
161 QObject* decoratorProvider = decorator();
161 int memberNameLen = strlen(memberName);
162 int memberNameLen = strlen(memberName);
162 if (decoratorProvider) {
163 if (decoratorProvider) {
163 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
164 //qDebug()<< "looking " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
164 const QMetaObject* meta = decoratorProvider->metaObject();
165 const QMetaObject* meta = decoratorProvider->metaObject();
165 int numMethods = meta->methodCount();
166 int numMethods = meta->methodCount();
166 int startFrom = QObject::staticMetaObject.methodCount();
167 int startFrom = QObject::staticMetaObject.methodCount();
167 for (int i = startFrom; i < numMethods; i++) {
168 for (int i = startFrom; i < numMethods; i++) {
168 QMetaMethod m = meta->method(i);
169 QMetaMethod m = meta->method(i);
169 if ((m.methodType() == QMetaMethod::Method ||
170 if ((m.methodType() == QMetaMethod::Method ||
170 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
171 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
171
172
172 const char* sigStart = m.signature();
173 const char* sigStart = m.signature();
173 bool isClassDeco = false;
174 bool isClassDeco = false;
174 if (qstrncmp(sigStart, "static_", 7)==0) {
175 if (qstrncmp(sigStart, "static_", 7)==0) {
175 // skip the static_classname_ part of the string
176 // skip the static_classname_ part of the string
176 sigStart += 7 + 1 + strlen(className());
177 sigStart += 7 + 1 + strlen(className());
177 isClassDeco = true;
178 isClassDeco = true;
178 } else if (qstrncmp(sigStart, "new_", 4)==0) {
179 } else if (qstrncmp(sigStart, "new_", 4)==0) {
179 isClassDeco = true;
180 isClassDeco = true;
180 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
181 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
181 isClassDeco = true;
182 isClassDeco = true;
182 }
183 }
183 // find the first '('
184 // find the first '('
184 int offset = findCharOffset(sigStart, '(');
185 int offset = findCharOffset(sigStart, '(');
185
186
186 // XXX no checking is currently done if the slots have correct first argument or not...
187 // XXX no checking is currently done if the slots have correct first argument or not...
187
188
188 // check if same length and same name
189 // check if same length and same name
189 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
190 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
190 found = true;
191 found = true;
191 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
192 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i, decoratorProvider, isClassDeco?PythonQtSlotInfo::ClassDecorator:PythonQtSlotInfo::InstanceDecorator);
192 info->setUpcastingOffset(upcastingOffset);
193 info->setUpcastingOffset(upcastingOffset);
193 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
194 //qDebug()<< "adding " << decoratorProvider->metaObject()->className() << " " << memberName << " " << upcastingOffset;
194 if (tail) {
195 if (tail) {
195 tail->setNextInfo(info);
196 tail->setNextInfo(info);
196 } else {
197 } else {
197 PythonQtMemberInfo newInfo(info);
198 PythonQtMemberInfo newInfo(info);
198 memberCache.insert(memberName, newInfo);
199 memberCache.insert(memberName, newInfo);
199 }
200 }
200 tail = info;
201 tail = info;
201 }
202 }
202 }
203 }
203 }
204 }
204 }
205 }
205
206
206 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
207 tail = findDecoratorSlots(memberName, memberNameLen, tail, found, memberCache, upcastingOffset);
207
208
208 return tail;
209 return tail;
209 }
210 }
210
211
211 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
212 bool PythonQtClassInfo::lookForMethodAndCache(const char* memberName)
212 {
213 {
213 bool found = false;
214 bool found = false;
214 int memberNameLen = strlen(memberName);
215 int memberNameLen = strlen(memberName);
215 PythonQtSlotInfo* tail = NULL;
216 PythonQtSlotInfo* tail = NULL;
216 if (_meta) {
217 if (_meta) {
217 int numMethods = _meta->methodCount();
218 int numMethods = _meta->methodCount();
218 for (int i = 0; i < numMethods; i++) {
219 for (int i = 0; i < numMethods; i++) {
219 QMetaMethod m = _meta->method(i);
220 QMetaMethod m = _meta->method(i);
220 if (((m.methodType() == QMetaMethod::Method ||
221 if (((m.methodType() == QMetaMethod::Method ||
221 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
222 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
222 || m.methodType()==QMetaMethod::Signal) {
223 || m.methodType()==QMetaMethod::Signal) {
223
224
224 const char* sigStart = m.signature();
225 const char* sigStart = m.signature();
225 // find the first '('
226 // find the first '('
226 int offset = findCharOffset(sigStart, '(');
227 int offset = findCharOffset(sigStart, '(');
227
228
228 // check if same length and same name
229 // check if same length and same name
229 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
230 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
230 found = true;
231 found = true;
231 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
232 PythonQtSlotInfo* info = new PythonQtSlotInfo(this, m, i);
232 if (tail) {
233 if (tail) {
233 tail->setNextInfo(info);
234 tail->setNextInfo(info);
234 } else {
235 } else {
235 PythonQtMemberInfo newInfo(info);
236 PythonQtMemberInfo newInfo(info);
236 _cachedMembers.insert(memberName, newInfo);
237 _cachedMembers.insert(memberName, newInfo);
237 }
238 }
238 tail = info;
239 tail = info;
239 }
240 }
240 }
241 }
241 }
242 }
242 }
243 }
243
244
244 // look for dynamic decorators in this class and in derived classes
245 // look for dynamic decorators in this class and in derived classes
245 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
246 tail = recursiveFindDecoratorSlotsFromDecoratorProvider(memberName, tail, found, _cachedMembers, 0);
246
247
247 return found;
248 return found;
248 }
249 }
249
250
250 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
251 bool PythonQtClassInfo::lookForEnumAndCache(const QMetaObject* meta, const char* memberName)
251 {
252 {
252 bool found = false;
253 bool found = false;
253 // look for enum values
254 // look for enum values
254 int enumCount = meta->enumeratorCount();
255 int enumCount = meta->enumeratorCount();
255 for (int i=0;i<enumCount; i++) {
256 for (int i=0;i<enumCount; i++) {
256 QMetaEnum e = meta->enumerator(i);
257 QMetaEnum e = meta->enumerator(i);
257 // we do not want flags, they will cause our values to appear two times
258 // we do not want flags, they will cause our values to appear two times
258 if (e.isFlag()) continue;
259 if (e.isFlag()) continue;
259
260
260 for (int j=0; j < e.keyCount(); j++) {
261 for (int j=0; j < e.keyCount(); j++) {
261 if (qstrcmp(e.key(j), memberName)==0) {
262 if (qstrcmp(e.key(j), memberName)==0) {
262 PyObject* enumType = findEnumWrapper(e.name());
263 PyObject* enumType = findEnumWrapper(e.name());
263 if (enumType) {
264 if (enumType) {
264 PythonQtObjectPtr enumValuePtr;
265 PythonQtObjectPtr enumValuePtr;
265 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
266 enumValuePtr.setNewRef(PythonQtPrivate::createEnumValueInstance(enumType, e.value(j)));
266 PythonQtMemberInfo newInfo(enumValuePtr);
267 PythonQtMemberInfo newInfo(enumValuePtr);
267 _cachedMembers.insert(memberName, newInfo);
268 _cachedMembers.insert(memberName, newInfo);
268 #ifdef PYTHONQT_DEBUG
269 #ifdef PYTHONQT_DEBUG
269 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
270 std::cout << "caching enum " << memberName << " on " << meta->className() << std::endl;
270 #endif
271 #endif
271 found = true;
272 found = true;
272 break;
273 break;
273 } else {
274 } else {
274 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
275 std::cout << "enum " << e.name() << " not found on " << className() << std::endl;
275 }
276 }
276 }
277 }
277 }
278 }
278 }
279 }
279 return found;
280 return found;
280 }
281 }
281
282
282 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
283 PythonQtMemberInfo PythonQtClassInfo::member(const char* memberName)
283 {
284 {
284 PythonQtMemberInfo info = _cachedMembers.value(memberName);
285 PythonQtMemberInfo info = _cachedMembers.value(memberName);
285 if (info._type != PythonQtMemberInfo::Invalid) {
286 if (info._type != PythonQtMemberInfo::Invalid) {
286 return info;
287 return info;
287 } else {
288 } else {
288 bool found = false;
289 bool found = false;
289
290
290 found = lookForPropertyAndCache(memberName);
291 found = lookForPropertyAndCache(memberName);
291 if (!found) {
292 if (!found) {
292 found = lookForMethodAndCache(memberName);
293 found = lookForMethodAndCache(memberName);
293 }
294 }
294 if (!found) {
295 if (!found) {
295 if (_meta) {
296 if (_meta) {
296 // check enums in our meta object directly
297 // check enums in our meta object directly
297 found = lookForEnumAndCache(_meta, memberName);
298 found = lookForEnumAndCache(_meta, memberName);
298 }
299 }
299 if (!found) {
300 if (!found) {
300 // check enums in the class hierachy of CPP classes
301 // check enums in the class hierachy of CPP classes
301 // look for dynamic decorators in this class and in derived classes
302 // look for dynamic decorators in this class and in derived classes
302 QList<QObject*> decoObjects;
303 QList<QObject*> decoObjects;
303 recursiveCollectDecoratorObjects(decoObjects);
304 recursiveCollectDecoratorObjects(decoObjects);
304 foreach(QObject* deco, decoObjects) {
305 foreach(QObject* deco, decoObjects) {
305 // call on ourself for caching, but with different metaObject():
306 // call on ourself for caching, but with different metaObject():
306 found = lookForEnumAndCache(deco->metaObject(), memberName);
307 found = lookForEnumAndCache(deco->metaObject(), memberName);
307 if (found) {
308 if (found) {
308 break;
309 break;
309 }
310 }
310 }
311 }
311 }
312 }
312 }
313 }
313 if (!found) {
314 if (!found) {
314 // maybe it is an enum wrapper?
315 // maybe it is an enum wrapper?
315 PyObject* p = findEnumWrapper(memberName);
316 PyObject* p = findEnumWrapper(memberName);
316 if (p) {
317 if (p) {
317 info._type = PythonQtMemberInfo::EnumWrapper;
318 info._type = PythonQtMemberInfo::EnumWrapper;
318 info._enumWrapper = p;
319 info._enumWrapper = p;
319 _cachedMembers.insert(memberName, info);
320 _cachedMembers.insert(memberName, info);
320 found = true;
321 found = true;
321 }
322 }
322 }
323 }
323 if (!found) {
324 if (!found) {
324 // since python keywords can not be looked up, we check if the name contains a single trailing _
325 // since python keywords can not be looked up, we check if the name contains a single trailing _
325 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
326 // and remove that and look again, so that we e.g. find exec on an exec_ lookup
326 QByteArray mbrName(memberName);
327 QByteArray mbrName(memberName);
327 if ((mbrName.length()>2) &&
328 if ((mbrName.length()>2) &&
328 (mbrName.at(mbrName.length()-1) == '_') &&
329 (mbrName.at(mbrName.length()-1) == '_') &&
329 (mbrName.at(mbrName.length()-2) != '_')) {
330 (mbrName.at(mbrName.length()-2) != '_')) {
330 mbrName = mbrName.mid(0,mbrName.length()-1);
331 mbrName = mbrName.mid(0,mbrName.length()-1);
331 found = lookForMethodAndCache(mbrName.constData());
332 found = lookForMethodAndCache(mbrName.constData());
332 if (found) {
333 if (found) {
333 return _cachedMembers.value(mbrName);
334 return _cachedMembers.value(mbrName);
334 }
335 }
335 }
336 }
336 }
337 }
337 if (!found) {
338 if (!found) {
338 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
339 // we store a NotFound member, so that we get a quick result for non existing members (e.g. operator_equal lookup)
339 info._type = PythonQtMemberInfo::NotFound;
340 info._type = PythonQtMemberInfo::NotFound;
340 _cachedMembers.insert(memberName, info);
341 _cachedMembers.insert(memberName, info);
341 }
342 }
342 }
343 }
343
344
344 return _cachedMembers.value(memberName);
345 return _cachedMembers.value(memberName);
345 }
346 }
346
347
347 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
348 void PythonQtClassInfo::recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects) {
348 QObject* deco = decorator();
349 QObject* deco = decorator();
349 if (deco) {
350 if (deco) {
350 decoratorObjects.append(deco);
351 decoratorObjects.append(deco);
351 }
352 }
352 foreach(const ParentClassInfo& info, _parentClasses) {
353 foreach(const ParentClassInfo& info, _parentClasses) {
353 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
354 info._parent->recursiveCollectDecoratorObjects(decoratorObjects);
354 }
355 }
355 }
356 }
356
357
357 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
358 void PythonQtClassInfo::recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects) {
358 classInfoObjects.append(this);
359 classInfoObjects.append(this);
359 foreach(const ParentClassInfo& info, _parentClasses) {
360 foreach(const ParentClassInfo& info, _parentClasses) {
360 info._parent->recursiveCollectClassInfos(classInfoObjects);
361 info._parent->recursiveCollectClassInfos(classInfoObjects);
361 }
362 }
362 }
363 }
363
364
364 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
365 PythonQtSlotInfo* PythonQtClassInfo::findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset)
365 {
366 {
366 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
367 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
367 while (it.hasNext()) {
368 while (it.hasNext()) {
368
369
369 PythonQtSlotInfo* infoOrig = it.next();
370 PythonQtSlotInfo* infoOrig = it.next();
370
371
371 const char* sigStart = infoOrig->metaMethod()->signature();
372 const char* sigStart = infoOrig->metaMethod()->signature();
372 if (qstrncmp("static_", sigStart, 7)==0) {
373 if (qstrncmp("static_", sigStart, 7)==0) {
373 sigStart += 7;
374 sigStart += 7;
374 sigStart += findCharOffset(sigStart, '_')+1;
375 sigStart += findCharOffset(sigStart, '_')+1;
375 }
376 }
376 int offset = findCharOffset(sigStart, '(');
377 int offset = findCharOffset(sigStart, '(');
377 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
378 if (memberNameLen == offset && qstrncmp(memberName, sigStart, offset)==0) {
378 //make a copy, otherwise we will have trouble on overloads!
379 //make a copy, otherwise we will have trouble on overloads!
379 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
380 PythonQtSlotInfo* info = new PythonQtSlotInfo(*infoOrig);
380 info->setUpcastingOffset(upcastingOffset);
381 info->setUpcastingOffset(upcastingOffset);
381 found = true;
382 found = true;
382 if (tail) {
383 if (tail) {
383 tail->setNextInfo(info);
384 tail->setNextInfo(info);
384 } else {
385 } else {
385 PythonQtMemberInfo newInfo(info);
386 PythonQtMemberInfo newInfo(info);
386 memberCache.insert(memberName, newInfo);
387 memberCache.insert(memberName, newInfo);
387 }
388 }
388 tail = info;
389 tail = info;
389 }
390 }
390 }
391 }
391 return tail;
392 return tail;
392 }
393 }
393
394
394 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
395 void PythonQtClassInfo::listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly) {
395 QObject* decoratorProvider = decorator();
396 QObject* decoratorProvider = decorator();
396 if (decoratorProvider) {
397 if (decoratorProvider) {
397 const QMetaObject* meta = decoratorProvider->metaObject();
398 const QMetaObject* meta = decoratorProvider->metaObject();
398 int numMethods = meta->methodCount();
399 int numMethods = meta->methodCount();
399 int startFrom = QObject::staticMetaObject.methodCount();
400 int startFrom = QObject::staticMetaObject.methodCount();
400 for (int i = startFrom; i < numMethods; i++) {
401 for (int i = startFrom; i < numMethods; i++) {
401 QMetaMethod m = meta->method(i);
402 QMetaMethod m = meta->method(i);
402 if ((m.methodType() == QMetaMethod::Method ||
403 if ((m.methodType() == QMetaMethod::Method ||
403 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
404 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
404
405
405 const char* sigStart = m.signature();
406 const char* sigStart = m.signature();
406 bool isClassDeco = false;
407 bool isClassDeco = false;
407 if (qstrncmp(sigStart, "static_", 7)==0) {
408 if (qstrncmp(sigStart, "static_", 7)==0) {
408 // skip the static_classname_ part of the string
409 // skip the static_classname_ part of the string
409 sigStart += 7 + 1 + strlen(className());
410 sigStart += 7 + 1 + strlen(className());
410 isClassDeco = true;
411 isClassDeco = true;
411 } else if (qstrncmp(sigStart, "new_", 4)==0) {
412 } else if (qstrncmp(sigStart, "new_", 4)==0) {
412 continue;
413 continue;
413 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
414 } else if (qstrncmp(sigStart, "delete_", 7)==0) {
414 continue;
415 continue;
415 } else if (qstrncmp(sigStart, "py_", 3)==0) {
416 } else if (qstrncmp(sigStart, "py_", 3)==0) {
416 // hide everything that starts with py_
417 // hide everything that starts with py_
417 continue;
418 continue;
418 }
419 }
419 // find the first '('
420 // find the first '('
420 int offset = findCharOffset(sigStart, '(');
421 int offset = findCharOffset(sigStart, '(');
421
422
422 // XXX no checking is currently done if the slots have correct first argument or not...
423 // XXX no checking is currently done if the slots have correct first argument or not...
423 if (!metaOnly || isClassDeco) {
424 if (!metaOnly || isClassDeco) {
424 list << QString::fromLatin1(sigStart, offset);
425 list << QString::fromLatin1(sigStart, offset);
425 }
426 }
426 }
427 }
427 }
428 }
428 }
429 }
429
430
430 // look for global decorator slots
431 // look for global decorator slots
431 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
432 QListIterator<PythonQtSlotInfo*> it(_decoratorSlots);
432 while (it.hasNext()) {
433 while (it.hasNext()) {
433 PythonQtSlotInfo* slot = it.next();
434 PythonQtSlotInfo* slot = it.next();
434 if (metaOnly) {
435 if (metaOnly) {
435 if (slot->isClassDecorator()) {
436 if (slot->isClassDecorator()) {
436 QByteArray first = slot->slotName();
437 QByteArray first = slot->slotName();
437 if (first.startsWith("static_")) {
438 if (first.startsWith("static_")) {
438 int idx = first.indexOf('_');
439 int idx = first.indexOf('_');
439 idx = first.indexOf('_', idx+1);
440 idx = first.indexOf('_', idx+1);
440 first = first.mid(idx+1);
441 first = first.mid(idx+1);
441 }
442 }
442 list << first;
443 list << first;
443 }
444 }
444 } else {
445 } else {
445 list << slot->slotName();
446 list << slot->slotName();
446 }
447 }
447 }
448 }
448 }
449 }
449
450
450 QStringList PythonQtClassInfo::propertyList()
451 QStringList PythonQtClassInfo::propertyList()
451 {
452 {
452 QStringList l;
453 QStringList l;
453 if (_isQObject && _meta) {
454 if (_isQObject && _meta) {
454 int i;
455 int i;
455 int numProperties = _meta->propertyCount();
456 int numProperties = _meta->propertyCount();
456 for (i = 0; i < numProperties; i++) {
457 for (i = 0; i < numProperties; i++) {
457 QMetaProperty p = _meta->property(i);
458 QMetaProperty p = _meta->property(i);
458 l << QString(p.name());
459 l << QString(p.name());
459 }
460 }
460 }
461 }
461 return l;
462 return l;
462 }
463 }
463
464
464 QStringList PythonQtClassInfo::memberList(bool metaOnly)
465 QStringList PythonQtClassInfo::memberList(bool metaOnly)
465 {
466 {
466 decorator();
467 decorator();
467
468
468 QStringList l;
469 QStringList l;
469 QString h;
470 QString h;
470 if (_isQObject && _meta && !metaOnly) {
471 if (_isQObject && _meta && !metaOnly) {
471 l = propertyList();
472 l = propertyList();
472 }
473 }
473
474
474 // normal slots of QObject (or wrapper QObject)
475 // normal slots of QObject (or wrapper QObject)
475 if (!metaOnly && _meta) {
476 if (!metaOnly && _meta) {
476 int numMethods = _meta->methodCount();
477 int numMethods = _meta->methodCount();
477 bool skipQObj = !_isQObject;
478 bool skipQObj = !_isQObject;
478 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
479 for (int i = skipQObj?QObject::staticMetaObject.methodCount():0; i < numMethods; i++) {
479 QMetaMethod m = _meta->method(i);
480 QMetaMethod m = _meta->method(i);
480 if (((m.methodType() == QMetaMethod::Method ||
481 if (((m.methodType() == QMetaMethod::Method ||
481 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
482 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public)
482 || m.methodType()==QMetaMethod::Signal) {
483 || m.methodType()==QMetaMethod::Signal) {
483 QByteArray signa(m.signature());
484 QByteArray signa(m.signature());
484 signa = signa.left(signa.indexOf('('));
485 signa = signa.left(signa.indexOf('('));
485 l << signa;
486 l << signa;
486 }
487 }
487 }
488 }
488 }
489 }
489
490
490 {
491 {
491 // look for dynamic decorators in this class and in derived classes
492 // look for dynamic decorators in this class and in derived classes
492 QList<PythonQtClassInfo*> infos;
493 QList<PythonQtClassInfo*> infos;
493 recursiveCollectClassInfos(infos);
494 recursiveCollectClassInfos(infos);
494 foreach(PythonQtClassInfo* info, infos) {
495 foreach(PythonQtClassInfo* info, infos) {
495 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
496 info->listDecoratorSlotsFromDecoratorProvider(l, metaOnly);
496 }
497 }
497 }
498 }
498
499
499 // List enumerator keys...
500 // List enumerator keys...
500 QList<const QMetaObject*> enumMetaObjects;
501 QList<const QMetaObject*> enumMetaObjects;
501 if (_meta) {
502 if (_meta) {
502 enumMetaObjects << _meta;
503 enumMetaObjects << _meta;
503 }
504 }
504 // check enums in the class hierachy of CPP classes
505 // check enums in the class hierachy of CPP classes
505 QList<QObject*> decoObjects;
506 QList<QObject*> decoObjects;
506 recursiveCollectDecoratorObjects(decoObjects);
507 recursiveCollectDecoratorObjects(decoObjects);
507 foreach(QObject* deco, decoObjects) {
508 foreach(QObject* deco, decoObjects) {
508 enumMetaObjects << deco->metaObject();
509 enumMetaObjects << deco->metaObject();
509 }
510 }
510
511
511 foreach(const QMetaObject* meta, enumMetaObjects) {
512 foreach(const QMetaObject* meta, enumMetaObjects) {
512 for (int i = 0; i<meta->enumeratorCount(); i++) {
513 for (int i = 0; i<meta->enumeratorCount(); i++) {
513 QMetaEnum e = meta->enumerator(i);
514 QMetaEnum e = meta->enumerator(i);
514 l << e.name();
515 l << e.name();
515 // we do not want flags, they will cause our values to appear two times
516 // we do not want flags, they will cause our values to appear two times
516 if (e.isFlag()) continue;
517 if (e.isFlag()) continue;
517
518
518 for (int j=0; j < e.keyCount(); j++) {
519 for (int j=0; j < e.keyCount(); j++) {
519 l << QString(e.key(j));
520 l << QString(e.key(j));
520 }
521 }
521 }
522 }
522 }
523 }
523
524
524 return QSet<QString>::fromList(l).toList();
525 return QSet<QString>::fromList(l).toList();
525 }
526 }
526
527
527 const char* PythonQtClassInfo::className()
528 const char* PythonQtClassInfo::className()
528 {
529 {
529 return _wrappedClassName.constData();
530 return _wrappedClassName.constData();
530 }
531 }
531
532
532 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
533 void* PythonQtClassInfo::castTo(void* ptr, const char* classname)
533 {
534 {
534 if (ptr==NULL) {
535 if (ptr==NULL) {
535 return NULL;
536 return NULL;
536 }
537 }
537 if (_wrappedClassName == classname) {
538 if (_wrappedClassName == classname) {
538 return ptr;
539 return ptr;
539 }
540 }
540 foreach(const ParentClassInfo& info, _parentClasses) {
541 foreach(const ParentClassInfo& info, _parentClasses) {
541 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
542 void* result = info._parent->castTo((char*)ptr + info._upcastingOffset, classname);
542 if (result) {
543 if (result) {
543 return result;
544 return result;
544 }
545 }
545 }
546 }
546 return NULL;
547 return NULL;
547 }
548 }
548
549
549 bool PythonQtClassInfo::inherits(const char* name)
550 bool PythonQtClassInfo::inherits(const char* name)
550 {
551 {
551 if (_wrappedClassName == name) {
552 if (_wrappedClassName == name) {
552 return true;
553 return true;
553 }
554 }
554 foreach(const ParentClassInfo& info, _parentClasses) {
555 foreach(const ParentClassInfo& info, _parentClasses) {
555 if (info._parent->inherits(name)) {
556 if (info._parent->inherits(name)) {
556 return true;
557 return true;
557 }
558 }
558 }
559 }
559 return false;
560 return false;
560 }
561 }
561
562
562 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
563 bool PythonQtClassInfo::inherits(PythonQtClassInfo* classInfo)
563 {
564 {
564 if (classInfo == this) {
565 if (classInfo == this) {
565 return true;
566 return true;
566 }
567 }
567 foreach(const ParentClassInfo& info, _parentClasses) {
568 foreach(const ParentClassInfo& info, _parentClasses) {
568 if (info._parent->inherits(classInfo)) {
569 if (info._parent->inherits(classInfo)) {
569 return true;
570 return true;
570 }
571 }
571 }
572 }
572 return false;
573 return false;
573 }
574 }
574
575
575 QString PythonQtClassInfo::help()
576 QString PythonQtClassInfo::help()
576 {
577 {
577 decorator();
578 decorator();
578 QString h;
579 QString h;
579 h += QString("--- ") + QString(className()) + QString(" ---\n");
580 h += QString("--- ") + QString(className()) + QString(" ---\n");
580
581
581 if (_isQObject) {
582 if (_isQObject) {
582 h += "Properties:\n";
583 h += "Properties:\n";
583
584
584 int i;
585 int i;
585 int numProperties = _meta->propertyCount();
586 int numProperties = _meta->propertyCount();
586 for (i = 0; i < numProperties; i++) {
587 for (i = 0; i < numProperties; i++) {
587 QMetaProperty p = _meta->property(i);
588 QMetaProperty p = _meta->property(i);
588 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
589 h += QString(p.name()) + " (" + QString(p.typeName()) + " )\n";
589 }
590 }
590 }
591 }
591
592
592 if (constructors()) {
593 if (constructors()) {
593 h += "Constructors:\n";
594 h += "Constructors:\n";
594 PythonQtSlotInfo* constr = constructors();
595 PythonQtSlotInfo* constr = constructors();
595 while (constr) {
596 while (constr) {
596 h += constr->fullSignature() + "\n";
597 h += constr->fullSignature() + "\n";
597 constr = constr->nextInfo();
598 constr = constr->nextInfo();
598 }
599 }
599 }
600 }
600
601
601 h += "Slots:\n";
602 h += "Slots:\n";
602 h += "QString help()\n";
603 h += "QString help()\n";
603 h += "QString className()\n";
604 h += "QString className()\n";
604
605
605 if (_meta) {
606 if (_meta) {
606 int numMethods = _meta->methodCount();
607 int numMethods = _meta->methodCount();
607 for (int i = 0; i < numMethods; i++) {
608 for (int i = 0; i < numMethods; i++) {
608 QMetaMethod m = _meta->method(i);
609 QMetaMethod m = _meta->method(i);
609 if ((m.methodType() == QMetaMethod::Method ||
610 if ((m.methodType() == QMetaMethod::Method ||
610 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
611 m.methodType() == QMetaMethod::Slot) && m.access() == QMetaMethod::Public) {
611 PythonQtSlotInfo slot(this, m, i);
612 PythonQtSlotInfo slot(this, m, i);
612 h += slot.fullSignature()+ "\n";
613 h += slot.fullSignature()+ "\n";
613 }
614 }
614 }
615 }
615 }
616 }
616
617
617 // TODO xxx : decorators and enums from decorator() are missing...
618 // TODO xxx : decorators and enums from decorator() are missing...
618 // maybe we can reuse memberlist()?
619 // maybe we can reuse memberlist()?
619
620
620 if (_meta && _meta->enumeratorCount()) {
621 if (_meta && _meta->enumeratorCount()) {
621 h += "Enums:\n";
622 h += "Enums:\n";
622 for (int i = 0; i<_meta->enumeratorCount(); i++) {
623 for (int i = 0; i<_meta->enumeratorCount(); i++) {
623 QMetaEnum e = _meta->enumerator(i);
624 QMetaEnum e = _meta->enumerator(i);
624 h += QString(e.name()) + " {";
625 h += QString(e.name()) + " {";
625 for (int j=0; j < e.keyCount(); j++) {
626 for (int j=0; j < e.keyCount(); j++) {
626 if (j) { h+= ", "; }
627 if (j) { h+= ", "; }
627 h += e.key(j);
628 h += e.key(j);
628 }
629 }
629 h += " }\n";
630 h += " }\n";
630 }
631 }
631 }
632 }
632
633
633 if (_isQObject && _meta) {
634 if (_isQObject && _meta) {
634 int numMethods = _meta->methodCount();
635 int numMethods = _meta->methodCount();
635 if (numMethods>0) {
636 if (numMethods>0) {
636 h += "Signals:\n";
637 h += "Signals:\n";
637 for (int i = 0; i < numMethods; i++) {
638 for (int i = 0; i < numMethods; i++) {
638 QMetaMethod m = _meta->method(i);
639 QMetaMethod m = _meta->method(i);
639 if (m.methodType() == QMetaMethod::Signal) {
640 if (m.methodType() == QMetaMethod::Signal) {
640 h += QString(m.signature()) + "\n";
641 h += QString(m.signature()) + "\n";
641 }
642 }
642 }
643 }
643 }
644 }
644 }
645 }
645 return h;
646 return h;
646 }
647 }
647
648
648 PythonQtSlotInfo* PythonQtClassInfo::constructors()
649 PythonQtSlotInfo* PythonQtClassInfo::constructors()
649 {
650 {
650 if (!_constructors) {
651 if (!_constructors) {
651 // force creation of lazy decorator, which will register the decorators
652 // force creation of lazy decorator, which will register the decorators
652 decorator();
653 decorator();
653 }
654 }
654 return _constructors;
655 return _constructors;
655 }
656 }
656
657
657 PythonQtSlotInfo* PythonQtClassInfo::destructor()
658 PythonQtSlotInfo* PythonQtClassInfo::destructor()
658 {
659 {
659 if (!_destructor) {
660 if (!_destructor) {
660 // force creation of lazy decorator, which will register the decorators
661 // force creation of lazy decorator, which will register the decorators
661 decorator();
662 decorator();
662 }
663 }
663 return _destructor;
664 return _destructor;
664 }
665 }
665
666
666 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
667 void PythonQtClassInfo::addConstructor(PythonQtSlotInfo* info)
667 {
668 {
668 PythonQtSlotInfo* prev = constructors();
669 PythonQtSlotInfo* prev = constructors();
669 if (prev) {
670 if (prev) {
670 info->setNextInfo(prev->nextInfo());
671 info->setNextInfo(prev->nextInfo());
671 prev->setNextInfo(info);
672 prev->setNextInfo(info);
672 } else {
673 } else {
673 _constructors = info;
674 _constructors = info;
674 }
675 }
675 }
676 }
676
677
677 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
678 void PythonQtClassInfo::addDecoratorSlot(PythonQtSlotInfo* info)
678 {
679 {
679 _decoratorSlots.append(info);
680 _decoratorSlots.append(info);
680 }
681 }
681
682
682 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
683 void PythonQtClassInfo::setDestructor(PythonQtSlotInfo* info)
683 {
684 {
684 if (_destructor) {
685 if (_destructor) {
685 _destructor->deleteOverloadsAndThis();
686 _destructor->deleteOverloadsAndThis();
686 }
687 }
687 _destructor = info;
688 _destructor = info;
688 }
689 }
689
690
690 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
691 void PythonQtClassInfo::setMetaObject(const QMetaObject* meta)
691 {
692 {
692 _meta = meta;
693 _meta = meta;
693 clearCachedMembers();
694 clearCachedMembers();
694 }
695 }
695
696
696 QObject* PythonQtClassInfo::decorator()
697 QObject* PythonQtClassInfo::decorator()
697 {
698 {
698 if (!_decoratorProvider && _decoratorProviderCB) {
699 if (!_decoratorProvider && _decoratorProviderCB) {
699 _decoratorProvider = (*_decoratorProviderCB)();
700 _decoratorProvider = (*_decoratorProviderCB)();
700 if (_decoratorProvider) {
701 if (_decoratorProvider) {
701 _decoratorProvider->setParent(PythonQt::priv());
702 _decoratorProvider->setParent(PythonQt::priv());
702 // setup enums early, since they might be needed by the constructor decorators:
703 // setup enums early, since they might be needed by the constructor decorators:
703 if (!_enumsCreated) {
704 if (!_enumsCreated) {
704 createEnumWrappers();
705 createEnumWrappers();
705 }
706 }
706 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
707 PythonQt::priv()->addDecorators(_decoratorProvider, PythonQtPrivate::ConstructorDecorator | PythonQtPrivate::DestructorDecorator);
707 }
708 }
708 }
709 }
709 // check if enums need to be created and create them if they are not yet created
710 // check if enums need to be created and create them if they are not yet created
710 if (!_enumsCreated) {
711 if (!_enumsCreated) {
711 createEnumWrappers();
712 createEnumWrappers();
712 }
713 }
713 return _decoratorProvider;
714 return _decoratorProvider;
714 }
715 }
715
716
716 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
717 bool PythonQtClassInfo::hasOwnerMethodButNoOwner(void* object)
717 {
718 {
718 PythonQtMemberInfo info = member("py_hasOwner");
719 PythonQtMemberInfo info = member("py_hasOwner");
719 if (info._type == PythonQtMemberInfo::Slot) {
720 if (info._type == PythonQtMemberInfo::Slot) {
720 void* obj = object;
721 void* obj = object;
721 bool result = false;
722 bool result = false;
722 void* args[2];
723 void* args[2];
723 args[0] = &result;
724 args[0] = &result;
724 args[1] = &obj;
725 args[1] = &obj;
725 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
726 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
726 return !result;
727 return !result;
727 } else {
728 } else {
728 return false;
729 return false;
729 }
730 }
730 }
731 }
731
732
732 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
733 void* PythonQtClassInfo::recursiveCastDownIfPossible(void* ptr, char** resultClassName)
733 {
734 {
734 if (!_polymorphicHandlers.isEmpty()) {
735 if (!_polymorphicHandlers.isEmpty()) {
735 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
736 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
736 void* resultPtr = (*cb)(ptr, resultClassName);
737 void* resultPtr = (*cb)(ptr, resultClassName);
737 if (resultPtr) {
738 if (resultPtr) {
738 return resultPtr;
739 return resultPtr;
739 }
740 }
740 }
741 }
741 }
742 }
742 foreach(const ParentClassInfo& info, _parentClasses) {
743 foreach(const ParentClassInfo& info, _parentClasses) {
743 if (!info._parent->isQObject()) {
744 if (!info._parent->isQObject()) {
744 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
745 void* resultPtr = info._parent->recursiveCastDownIfPossible((char*)ptr + info._upcastingOffset, resultClassName);
745 if (resultPtr) {
746 if (resultPtr) {
746 return resultPtr;
747 return resultPtr;
747 }
748 }
748 }
749 }
749 }
750 }
750 return NULL;
751 return NULL;
751 }
752 }
752
753
753 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
754 void* PythonQtClassInfo::castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo)
754 {
755 {
755 char* className;
756 char* className;
756 // this would do downcasting recursively...
757 // this would do downcasting recursively...
757 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
758 // void* resultPtr = recursiveCastDownIfPossible(ptr, &className);
758
759
759 // we only do downcasting on the base object, not on the whole inheritance tree...
760 // we only do downcasting on the base object, not on the whole inheritance tree...
760 void* resultPtr = NULL;
761 void* resultPtr = NULL;
761 if (!_polymorphicHandlers.isEmpty()) {
762 if (!_polymorphicHandlers.isEmpty()) {
762 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
763 foreach(PythonQtPolymorphicHandlerCB* cb, _polymorphicHandlers) {
763 resultPtr = (*cb)(ptr, &className);
764 resultPtr = (*cb)(ptr, &className);
764 if (resultPtr) {
765 if (resultPtr) {
765 break;
766 break;
766 }
767 }
767 }
768 }
768 }
769 }
769 if (resultPtr) {
770 if (resultPtr) {
770 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
771 *resultClassInfo = PythonQt::priv()->getClassInfo(className);
771 } else {
772 } else {
772 *resultClassInfo = this;
773 *resultClassInfo = this;
773 resultPtr = ptr;
774 resultPtr = ptr;
774 }
775 }
775 return resultPtr;
776 return resultPtr;
776 }
777 }
777
778
778 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
779 PyObject* PythonQtClassInfo::findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum)
779 {
780 {
780 if (isLocalEnum) {
781 if (isLocalEnum) {
781 *isLocalEnum = true;
782 *isLocalEnum = true;
782 }
783 }
783 int scopePos = name.lastIndexOf("::");
784 int scopePos = name.lastIndexOf("::");
784 if (scopePos != -1) {
785 if (scopePos != -1) {
785 if (isLocalEnum) {
786 if (isLocalEnum) {
786 *isLocalEnum = false;
787 *isLocalEnum = false;
787 }
788 }
788 // split into scope and enum name
789 // split into scope and enum name
789 QByteArray enumScope = name.mid(0,scopePos);
790 QByteArray enumScope = name.mid(0,scopePos);
790 QByteArray enumName = name.mid(scopePos+2);
791 QByteArray enumName = name.mid(scopePos+2);
791 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
792 PythonQtClassInfo* info = PythonQt::priv()->getClassInfo(enumScope);
792 if (info) {
793 if (info) {
793 return info->findEnumWrapper(enumName);
794 return info->findEnumWrapper(enumName);
794 } else{
795 } else{
795 return NULL;
796 return NULL;
796 }
797 }
797 }
798 }
798 if (localScope) {
799 if (localScope) {
799 return localScope->findEnumWrapper(name);
800 return localScope->findEnumWrapper(name);
800 } else {
801 } else {
801 return NULL;
802 return NULL;
802 }
803 }
803 }
804 }
804
805
805 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
806 void PythonQtClassInfo::createEnumWrappers(const QMetaObject* meta)
806 {
807 {
807 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
808 for (int i = meta->enumeratorOffset();i<meta->enumeratorCount();i++) {
808 QMetaEnum e = meta->enumerator(i);
809 QMetaEnum e = meta->enumerator(i);
809 PythonQtObjectPtr p;
810 PythonQtObjectPtr p;
810 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
811 p.setNewRef(PythonQtPrivate::createNewPythonQtEnumWrapper(e.name(), _pythonQtClassWrapper));
811 _enumWrappers.append(p);
812 _enumWrappers.append(p);
812 }
813 }
813 }
814 }
814
815
815 void PythonQtClassInfo::createEnumWrappers()
816 void PythonQtClassInfo::createEnumWrappers()
816 {
817 {
817 if (!_enumsCreated) {
818 if (!_enumsCreated) {
818 _enumsCreated = true;
819 _enumsCreated = true;
819 if (_meta) {
820 if (_meta) {
820 createEnumWrappers(_meta);
821 createEnumWrappers(_meta);
821 }
822 }
822 if (decorator()) {
823 if (decorator()) {
823 createEnumWrappers(decorator()->metaObject());
824 createEnumWrappers(decorator()->metaObject());
824 }
825 }
825 foreach(const ParentClassInfo& info, _parentClasses) {
826 foreach(const ParentClassInfo& info, _parentClasses) {
826 info._parent->createEnumWrappers();
827 info._parent->createEnumWrappers();
827 }
828 }
828 }
829 }
829 }
830 }
830
831
831 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
832 PyObject* PythonQtClassInfo::findEnumWrapper(const char* name) {
832 // force enum creation
833 // force enum creation
833 if (!_enumsCreated) {
834 if (!_enumsCreated) {
834 createEnumWrappers();
835 createEnumWrappers();
835 }
836 }
836 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
837 foreach(const PythonQtObjectPtr& p, _enumWrappers) {
837 const char* className = ((PyTypeObject*)p.object())->tp_name;
838 const char* className = ((PyTypeObject*)p.object())->tp_name;
838 if (qstrcmp(className, name)==0) {
839 if (qstrcmp(className, name)==0) {
839 return p.object();
840 return p.object();
840 }
841 }
841 }
842 }
842 foreach(const ParentClassInfo& info, _parentClasses) {
843 foreach(const ParentClassInfo& info, _parentClasses) {
843 PyObject* p = info._parent->findEnumWrapper(name);
844 PyObject* p = info._parent->findEnumWrapper(name);
844 if (p) return p;
845 if (p) return p;
845 }
846 }
846 return NULL;
847 return NULL;
847 }
848 }
848
849
@@ -1,256 +1,262
1 #ifndef _PYTHONQTCLASSINFO_H
1 #ifndef _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
2 #define _PYTHONQTCLASSINFO_H
3
3
4 /*
4 /*
5 *
5 *
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
6 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
7 *
7 *
8 * This library is free software; you can redistribute it and/or
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
11 * version 2.1 of the License, or (at your option) any later version.
12 *
12 *
13 * This library is distributed in the hope that it will be useful,
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
16 * Lesser General Public License for more details.
17 *
17 *
18 * Further, this software is distributed without any warranty that it is
18 * Further, this software is distributed without any warranty that it is
19 * free of the rightful claim of any third person regarding infringement
19 * free of the rightful claim of any third person regarding infringement
20 * or the like. Any license provided herein, whether implied or
20 * or the like. Any license provided herein, whether implied or
21 * otherwise, applies only to this software file. Patent licenses, if
21 * otherwise, applies only to this software file. Patent licenses, if
22 * any, provided herein do not apply to combinations of this program with
22 * any, provided herein do not apply to combinations of this program with
23 * other software, or any other product whatsoever.
23 * other software, or any other product whatsoever.
24 *
24 *
25 * You should have received a copy of the GNU Lesser General Public
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 *
28 *
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
29 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
30 * 28359 Bremen, Germany or:
30 * 28359 Bremen, Germany or:
31 *
31 *
32 * http://www.mevis.de
32 * http://www.mevis.de
33 *
33 *
34 */
34 */
35
35
36 #include <QMetaObject>
36 #include <QMetaObject>
37 #include <QMetaMethod>
37 #include <QMetaMethod>
38 #include <QHash>
38 #include <QHash>
39 #include <QByteArray>
39 #include <QByteArray>
40 #include <QList>
40 #include <QList>
41 #include "PythonQt.h"
41 #include "PythonQt.h"
42
42
43 class PythonQtSlotInfo;
43 class PythonQtSlotInfo;
44
44
45 struct PythonQtMemberInfo {
45 struct PythonQtMemberInfo {
46 enum Type {
46 enum Type {
47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
47 Invalid, Slot, EnumValue, EnumWrapper, Property, NotFound
48 };
48 };
49
49
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
50 PythonQtMemberInfo():_type(Invalid),_slot(NULL),_enumWrapper(NULL),_enumValue(0) { }
51
51
52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
52 PythonQtMemberInfo(PythonQtSlotInfo* info) {
53 _type = Slot;
53 _type = Slot;
54 _slot = info;
54 _slot = info;
55 _enumValue = NULL;
55 _enumValue = NULL;
56 }
56 }
57
57
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
58 PythonQtMemberInfo(const PythonQtObjectPtr& enumValue) {
59 _type = EnumValue;
59 _type = EnumValue;
60 _slot = NULL;
60 _slot = NULL;
61 _enumValue = enumValue;
61 _enumValue = enumValue;
62 _enumWrapper = NULL;
62 _enumWrapper = NULL;
63 }
63 }
64
64
65 PythonQtMemberInfo(const QMetaProperty& prop) {
65 PythonQtMemberInfo(const QMetaProperty& prop) {
66 _type = Property;
66 _type = Property;
67 _slot = NULL;
67 _slot = NULL;
68 _enumValue = NULL;
68 _enumValue = NULL;
69 _property = prop;
69 _property = prop;
70 _enumWrapper = NULL;
70 _enumWrapper = NULL;
71 }
71 }
72
72
73 Type _type;
73 Type _type;
74
74
75 // TODO: this could be a union...
75 // TODO: this could be a union...
76 PythonQtSlotInfo* _slot;
76 PythonQtSlotInfo* _slot;
77 PyObject* _enumWrapper;
77 PyObject* _enumWrapper;
78 PythonQtObjectPtr _enumValue;
78 PythonQtObjectPtr _enumValue;
79 QMetaProperty _property;
79 QMetaProperty _property;
80 };
80 };
81
81
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
82 //! a class that stores all required information about a Qt object (and an optional associated C++ class name)
83 /*! for fast lookup of slots when calling the object from Python
83 /*! for fast lookup of slots when calling the object from Python
84 */
84 */
85 class PythonQtClassInfo {
85 class PythonQtClassInfo {
86
86
87 public:
87 public:
88 PythonQtClassInfo();
88 PythonQtClassInfo();
89 ~PythonQtClassInfo();
89 ~PythonQtClassInfo();
90
90
91 //! store information about parent classes
91 //! store information about parent classes
92 struct ParentClassInfo {
92 struct ParentClassInfo {
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
93 ParentClassInfo(PythonQtClassInfo* parent, int upcastingOffset=0):_parent(parent),_upcastingOffset(upcastingOffset)
94 {};
94 {};
95
95
96 PythonQtClassInfo* _parent;
96 PythonQtClassInfo* _parent;
97 int _upcastingOffset;
97 int _upcastingOffset;
98 };
98 };
99
99
100
100
101 //! setup as a QObject, taking the meta object as meta information about the QObject
101 //! setup as a QObject, taking the meta object as meta information about the QObject
102 void setupQObject(const QMetaObject* meta);
102 void setupQObject(const QMetaObject* meta);
103
103
104 //! setup as a CPP (non-QObject), taking the classname
104 //! setup as a CPP (non-QObject), taking the classname
105 void setupCPPObject(const QByteArray& classname);
105 void setupCPPObject(const QByteArray& classname);
106
106
107 //! set the type capabilities
108 void setTypeSlots(int typeSlots) { _typeSlots = typeSlots; }
109 //! get the type capabilities
110 int typeSlots() const { return _typeSlots; }
111
107 //! get the Python method definition for a given slot name (without return type and signature)
112 //! get the Python method definition for a given slot name (without return type and signature)
108 PythonQtMemberInfo member(const char* member);
113 PythonQtMemberInfo member(const char* member);
109
114
110 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
115 //! get access to the constructor slot (which may be overloaded if there are multiple constructors)
111 PythonQtSlotInfo* constructors();
116 PythonQtSlotInfo* constructors();
112
117
113 //! get access to the destructor slot
118 //! get access to the destructor slot
114 PythonQtSlotInfo* destructor();
119 PythonQtSlotInfo* destructor();
115
120
116 //! add a constructor, ownership is passed to classinfo
121 //! add a constructor, ownership is passed to classinfo
117 void addConstructor(PythonQtSlotInfo* info);
122 void addConstructor(PythonQtSlotInfo* info);
118
123
119 //! set a destructor, ownership is passed to classinfo
124 //! set a destructor, ownership is passed to classinfo
120 void setDestructor(PythonQtSlotInfo* info);
125 void setDestructor(PythonQtSlotInfo* info);
121
126
122 //! add a decorator slot, ownership is passed to classinfo
127 //! add a decorator slot, ownership is passed to classinfo
123 void addDecoratorSlot(PythonQtSlotInfo* info);
128 void addDecoratorSlot(PythonQtSlotInfo* info);
124
129
125 //! get the classname (either of the QObject or of the wrapped CPP object)
130 //! get the classname (either of the QObject or of the wrapped CPP object)
126 const char* className();
131 const char* className();
127
132
128 //! returns if the QObject
133 //! returns if the QObject
129 bool isQObject() { return _isQObject; }
134 bool isQObject() { return _isQObject; }
130
135
131 //! returns if the class is a CPP wrapper
136 //! returns if the class is a CPP wrapper
132 bool isCPPWrapper() { return !_isQObject; }
137 bool isCPPWrapper() { return !_isQObject; }
133
138
134 //! get the meta object
139 //! get the meta object
135 const QMetaObject* metaObject() { return _meta; }
140 const QMetaObject* metaObject() { return _meta; }
136
141
137 //! set the meta object, this will reset the caching
142 //! set the meta object, this will reset the caching
138 void setMetaObject(const QMetaObject* meta);
143 void setMetaObject(const QMetaObject* meta);
139
144
140 //! returns if this class inherits from the given classname
145 //! returns if this class inherits from the given classname
141 bool inherits(const char* classname);
146 bool inherits(const char* classname);
142
147
143 //! returns if this class inherits from the given classinfo
148 //! returns if this class inherits from the given classinfo
144 bool inherits(PythonQtClassInfo* info);
149 bool inherits(PythonQtClassInfo* info);
145
150
146 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
151 //! casts the given \c ptr to an object of type \c classname, returns the new pointer
147 //! which might be different to \c ptr due to C++ multiple inheritance
152 //! which might be different to \c ptr due to C++ multiple inheritance
148 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
153 //! (if the cast is not possible or if ptr is NULL, NULL is returned)
149 void* castTo(void* ptr, const char* classname);
154 void* castTo(void* ptr, const char* classname);
150
155
151 //! get help string for the metaobject
156 //! get help string for the metaobject
152 QString help();
157 QString help();
153
158
154 //! get list of all properties (on QObjects only, otherwise the list is empty)
159 //! get list of all properties (on QObjects only, otherwise the list is empty)
155 QStringList propertyList();
160 QStringList propertyList();
156
161
157 //! get list of all members
162 //! get list of all members
158 QStringList memberList(bool metaOnly = false);
163 QStringList memberList(bool metaOnly = false);
159
164
160 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
165 //! get the meta type id of this class (only valid for isCPPWrapper() == true)
161 int metaTypeId() { return _metaTypeId; }
166 int metaTypeId() { return _metaTypeId; }
162
167
163 //! set an additional decorator provider that offers additional decorator slots for this class
168 //! set an additional decorator provider that offers additional decorator slots for this class
164 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
169 void setDecoratorProvider(PythonQtQObjectCreatorFunctionCB* cb) { _decoratorProviderCB = cb; _decoratorProvider = NULL; }
165
170
166 //! get the decorator qobject instance
171 //! get the decorator qobject instance
167 QObject* decorator();
172 QObject* decorator();
168
173
169 //! add the parent class info of a CPP object
174 //! add the parent class info of a CPP object
170 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
175 void addParentClass(const ParentClassInfo& info) { _parentClasses.append(info); }
171
176
172 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
177 //! check if the special method "py_hasOwner" is implemented and if it returns false, which means that the object may be destroyed
173 bool hasOwnerMethodButNoOwner(void* object);
178 bool hasOwnerMethodButNoOwner(void* object);
174
179
175 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
180 //! set the associated PythonQtClassWrapper (which handles instance creation of this type)
176 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
181 void setPythonQtClassWrapper(PyObject* obj) { _pythonQtClassWrapper = obj; }
177
182
178 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
183 //! get the associated PythonQtClassWrapper (which handles instance creation of this type)
179 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
184 PyObject* pythonQtClassWrapper() { return _pythonQtClassWrapper; }
180
185
181 //! set the shell set instance wrapper cb
186 //! set the shell set instance wrapper cb
182 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
187 void setShellSetInstanceWrapperCB(PythonQtShellSetInstanceWrapperCB* cb) {
183 _shellSetInstanceWrapperCB = cb;
188 _shellSetInstanceWrapperCB = cb;
184 }
189 }
185
190
186 //! get the shell set instance wrapper cb
191 //! get the shell set instance wrapper cb
187 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
192 PythonQtShellSetInstanceWrapperCB* shellSetInstanceWrapperCB() {
188 return _shellSetInstanceWrapperCB;
193 return _shellSetInstanceWrapperCB;
189 }
194 }
190
195
191 //! add a handler for polymorphic downcasting
196 //! add a handler for polymorphic downcasting
192 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
197 void addPolymorphicHandler(PythonQtPolymorphicHandlerCB* cb) { _polymorphicHandlers.append(cb); }
193
198
194 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
199 //! cast the pointer down in the class hierarchy if a polymorphic handler allows to do that
195 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
200 void* castDownIfPossible(void* ptr, PythonQtClassInfo** resultClassInfo);
196
201
197 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
202 //! returns if the localScope has an enum of that type name or if the enum contains a :: scope, if that class contails the enum
198 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
203 static PyObject* findEnumWrapper(const QByteArray& name, PythonQtClassInfo* localScope, bool* isLocalEnum = NULL);
199
204
200 private:
205 private:
201 void createEnumWrappers();
206 void createEnumWrappers();
202 void createEnumWrappers(const QMetaObject* meta);
207 void createEnumWrappers(const QMetaObject* meta);
203 PyObject* findEnumWrapper(const char* name);
208 PyObject* findEnumWrapper(const char* name);
204
209
205 //! clear all cached members
210 //! clear all cached members
206 void clearCachedMembers();
211 void clearCachedMembers();
207
212
208 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
213 void* recursiveCastDownIfPossible(void* ptr, char** resultClassName);
209
214
210 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
215 PythonQtSlotInfo* findDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
211 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
216 void listDecoratorSlotsFromDecoratorProvider(QStringList& list, bool metaOnly);
212 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
217 PythonQtSlotInfo* recursiveFindDecoratorSlotsFromDecoratorProvider(const char* memberName, PythonQtSlotInfo* inputInfo, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
213
218
214 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
219 void recursiveCollectClassInfos(QList<PythonQtClassInfo*>& classInfoObjects);
215 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
220 void recursiveCollectDecoratorObjects(QList<QObject*>& decoratorObjects);
216
221
217 bool lookForPropertyAndCache(const char* memberName);
222 bool lookForPropertyAndCache(const char* memberName);
218 bool lookForMethodAndCache(const char* memberName);
223 bool lookForMethodAndCache(const char* memberName);
219 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
224 bool lookForEnumAndCache(const QMetaObject* m, const char* memberName);
220
225
221 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
226 PythonQtSlotInfo* findDecoratorSlots(const char* memberName, int memberNameLen, PythonQtSlotInfo* tail, bool &found, QHash<QByteArray, PythonQtMemberInfo>& memberCache, int upcastingOffset);
222 int findCharOffset(const char* sigStart, char someChar);
227 int findCharOffset(const char* sigStart, char someChar);
223
228
224 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
229 QHash<QByteArray, PythonQtMemberInfo> _cachedMembers;
225
230
226 PythonQtSlotInfo* _constructors;
231 PythonQtSlotInfo* _constructors;
227 PythonQtSlotInfo* _destructor;
232 PythonQtSlotInfo* _destructor;
228 QList<PythonQtSlotInfo*> _decoratorSlots;
233 QList<PythonQtSlotInfo*> _decoratorSlots;
229
234
230 QList<PythonQtObjectPtr> _enumWrappers;
235 QList<PythonQtObjectPtr> _enumWrappers;
231
236
232 const QMetaObject* _meta;
237 const QMetaObject* _meta;
233
238
234 QByteArray _wrappedClassName;
239 QByteArray _wrappedClassName;
235 QList<ParentClassInfo> _parentClasses;
240 QList<ParentClassInfo> _parentClasses;
236
241
237 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
242 QList<PythonQtPolymorphicHandlerCB*> _polymorphicHandlers;
238
243
239 QObject* _decoratorProvider;
244 QObject* _decoratorProvider;
240 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
245 PythonQtQObjectCreatorFunctionCB* _decoratorProviderCB;
241
246
242 PyObject* _pythonQtClassWrapper;
247 PyObject* _pythonQtClassWrapper;
243
248
244 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
249 PythonQtShellSetInstanceWrapperCB* _shellSetInstanceWrapperCB;
245
250
246 int _metaTypeId;
251 int _metaTypeId;
252 int _typeSlots;
247
253
248 bool _isQObject;
254 bool _isQObject;
249 bool _enumsCreated;
255 bool _enumsCreated;
250
256
251 };
257 };
252
258
253 //---------------------------------------------------------------
259 //---------------------------------------------------------------
254
260
255
261
256 #endif
262 #endif
@@ -1,290 +1,452
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtClassWrapper.cpp
35 // \file PythonQtClassWrapper.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtClassWrapper.h"
42 #include "PythonQtClassWrapper.h"
43 #include <QObject>
43 #include <QObject>
44
44
45 #include "PythonQt.h"
45 #include "PythonQt.h"
46 #include "PythonQtSlot.h"
46 #include "PythonQtSlot.h"
47 #include "PythonQtClassInfo.h"
47 #include "PythonQtClassInfo.h"
48 #include "PythonQtConversion.h"
48 #include "PythonQtConversion.h"
49 #include "PythonQtInstanceWrapper.h"
49 #include "PythonQtInstanceWrapper.h"
50
50
51 static PyObject* PythonQtInstanceWrapper_invert(PythonQtInstanceWrapper* wrapper)
52 {
53 PyObject* result = NULL;
54 static QByteArray memberName = "__invert__";
55 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
56 if (opSlot._type == PythonQtMemberInfo::Slot) {
57 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
58 }
59 return result;
60 }
61
62 static int PythonQtInstanceWrapper_nonzero(PythonQtInstanceWrapper* wrapper)
63 {
64 int result = (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
65 if (result) {
66 static QByteArray memberName = "__nonzero__";
67 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
68 if (opSlot._type == PythonQtMemberInfo::Slot) {
69 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, NULL, NULL, wrapper->_wrappedPtr);
70 if (resultObj == Py_False) {
71 result = 0;
72 }
73 Py_XDECREF(resultObj);
74 }
75 }
76 return result;
77 }
78
79
80 static PyObject* PythonQtInstanceWrapper_binaryfunc(PythonQtInstanceWrapper* wrapper, PyObject* other, const QByteArray& opName, const QByteArray& fallbackOpName = QByteArray())
81 {
82 PyObject* result = NULL;
83 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(opName);
84 if (opSlot._type == PythonQtMemberInfo::Slot) {
85 // TODO get rid of tuple
86 PyObject* args = PyTuple_New(1);
87 Py_INCREF(other);
88 PyTuple_SET_ITEM(args, 0, other);
89 result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
90 Py_DECREF(args);
91 if (!result && !fallbackOpName.isEmpty()) {
92 // try fallback if we did not get a result
93 result = PythonQtInstanceWrapper_binaryfunc(wrapper, other, fallbackOpName);
94 }
95 }
96 return result;
97 }
98
99 #define BINARY_OP(NAME) \
100 static PyObject* PythonQtInstanceWrapper_ ## NAME(PythonQtInstanceWrapper* wrapper, PyObject* other) \
101 { \
102 static const QByteArray opName("__" #NAME "__"); \
103 return PythonQtInstanceWrapper_binaryfunc(wrapper, other, opName); \
104 }
105
106 #define BINARY_OP_INPLACE(NAME) \
107 static PyObject* PythonQtInstanceWrapper_i ## NAME(PythonQtInstanceWrapper* wrapper, PyObject* other) \
108 { \
109 static const QByteArray opName("__i" #NAME "__"); \
110 static const QByteArray fallbackName("__" #NAME "__"); \
111 return PythonQtInstanceWrapper_binaryfunc(wrapper, other, opName, fallbackName); \
112 }
113
114 BINARY_OP(add)
115 BINARY_OP(sub)
116 BINARY_OP(mul)
117 BINARY_OP(div)
118 BINARY_OP(and)
119 BINARY_OP(or)
120 BINARY_OP(xor)
121 BINARY_OP(mod)
122 BINARY_OP(lshift)
123 BINARY_OP(rshift)
124
125 BINARY_OP_INPLACE(add)
126 BINARY_OP_INPLACE(sub)
127 BINARY_OP_INPLACE(mul)
128 BINARY_OP_INPLACE(div)
129 BINARY_OP_INPLACE(and)
130 BINARY_OP_INPLACE(or)
131 BINARY_OP_INPLACE(xor)
132 BINARY_OP_INPLACE(mod)
133 BINARY_OP_INPLACE(lshift)
134 BINARY_OP_INPLACE(rshift)
135
136 static void initializeSlots(PythonQtClassWrapper* wrap)
137 {
138 int typeSlots = wrap->classInfo()->typeSlots();
139 if (typeSlots) {
140 if (typeSlots & PythonQt::Type_Add) {
141 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_add;
142 }
143 if (typeSlots & PythonQt::Type_Subtract) {
144 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_sub;
145 }
146 if (typeSlots & PythonQt::Type_Multiply) {
147 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_mul;
148 }
149 if (typeSlots & PythonQt::Type_Divide) {
150 wrap->_base.as_number.nb_divide = (binaryfunc)PythonQtInstanceWrapper_div;
151 wrap->_base.as_number.nb_true_divide = (binaryfunc)PythonQtInstanceWrapper_div;
152 }
153 if (typeSlots & PythonQt::Type_And) {
154 wrap->_base.as_number.nb_and = (binaryfunc)PythonQtInstanceWrapper_and;
155 }
156 if (typeSlots & PythonQt::Type_Or) {
157 wrap->_base.as_number.nb_or = (binaryfunc)PythonQtInstanceWrapper_or;
158 }
159 if (typeSlots & PythonQt::Type_Xor) {
160 wrap->_base.as_number.nb_xor = (binaryfunc)PythonQtInstanceWrapper_xor;
161 }
162 if (typeSlots & PythonQt::Type_Mod) {
163 wrap->_base.as_number.nb_remainder = (binaryfunc)PythonQtInstanceWrapper_mod;
164 }
165 if (typeSlots & PythonQt::Type_LShift) {
166 wrap->_base.as_number.nb_lshift = (binaryfunc)PythonQtInstanceWrapper_lshift;
167 }
168 if (typeSlots & PythonQt::Type_RShift) {
169 wrap->_base.as_number.nb_rshift = (binaryfunc)PythonQtInstanceWrapper_rshift;
170 }
171
172 if (typeSlots & PythonQt::Type_InplaceAdd) {
173 wrap->_base.as_number.nb_add = (binaryfunc)PythonQtInstanceWrapper_iadd;
174 }
175 if (typeSlots & PythonQt::Type_InplaceSubtract) {
176 wrap->_base.as_number.nb_subtract = (binaryfunc)PythonQtInstanceWrapper_isub;
177 }
178 if (typeSlots & PythonQt::Type_InplaceMultiply) {
179 wrap->_base.as_number.nb_multiply = (binaryfunc)PythonQtInstanceWrapper_imul;
180 }
181 if (typeSlots & PythonQt::Type_InplaceDivide) {
182 wrap->_base.as_number.nb_inplace_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
183 wrap->_base.as_number.nb_inplace_true_divide = (binaryfunc)PythonQtInstanceWrapper_idiv;
184 }
185 if (typeSlots & PythonQt::Type_InplaceAnd) {
186 wrap->_base.as_number.nb_inplace_and = (binaryfunc)PythonQtInstanceWrapper_iand;
187 }
188 if (typeSlots & PythonQt::Type_InplaceOr) {
189 wrap->_base.as_number.nb_inplace_or = (binaryfunc)PythonQtInstanceWrapper_ior;
190 }
191 if (typeSlots & PythonQt::Type_InplaceXor) {
192 wrap->_base.as_number.nb_inplace_xor = (binaryfunc)PythonQtInstanceWrapper_ixor;
193 }
194 if (typeSlots & PythonQt::Type_InplaceMod) {
195 wrap->_base.as_number.nb_inplace_remainder = (binaryfunc)PythonQtInstanceWrapper_imod;
196 }
197 if (typeSlots & PythonQt::Type_InplaceLShift) {
198 wrap->_base.as_number.nb_inplace_lshift = (binaryfunc)PythonQtInstanceWrapper_ilshift;
199 }
200 if (typeSlots & PythonQt::Type_InplaceRShift) {
201 wrap->_base.as_number.nb_inplace_rshift = (binaryfunc)PythonQtInstanceWrapper_irshift;
202 }
203 if (typeSlots & PythonQt::Type_Invert) {
204 wrap->_base.as_number.nb_invert = (unaryfunc)PythonQtInstanceWrapper_invert;
205 }
206 if (typeSlots & PythonQt::Type_NonZero) {
207 wrap->_base.as_number.nb_nonzero = (inquiry)PythonQtInstanceWrapper_nonzero;
208 }
209 }
210 }
211
51 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
212 static PyObject* PythonQtClassWrapper_alloc(PyTypeObject *self, Py_ssize_t nitems)
52 {
213 {
53 // call the default type alloc
214 // call the default type alloc
54 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
215 PyObject* obj = PyType_Type.tp_alloc(self, nitems);
55
216
56 // take current class type, if we are called via newPythonQtClassWrapper()
217 // take current class type, if we are called via newPythonQtClassWrapper()
57 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
218 PythonQtClassWrapper* wrap = (PythonQtClassWrapper*)obj;
58 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
219 wrap->_classInfo = PythonQt::priv()->currentClassInfoForClassWrapperCreation();
220 initializeSlots(wrap);
59
221
60 return obj;
222 return obj;
61 }
223 }
62
224
63
225
64 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
226 static int PythonQtClassWrapper_init(PythonQtClassWrapper* self, PyObject* args, PyObject* kwds)
65 {
227 {
66 // call the default type init
228 // call the default type init
67 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
229 if (PyType_Type.tp_init((PyObject *)self, args, kwds) < 0) {
68 return -1;
230 return -1;
69 }
231 }
70
232
71 // if we have no CPP class information, try our base class
233 // if we have no CPP class information, try our base class
72 if (!self->classInfo()) {
234 if (!self->classInfo()) {
73 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
235 PyTypeObject* superType = ((PyTypeObject *)self)->tp_base;
74
236
75 if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) {
237 if (!superType || (superType->ob_type != &PythonQtClassWrapper_Type)) {
76 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
238 PyErr_Format(PyExc_TypeError, "type %s is not derived from PythonQtClassWrapper", ((PyTypeObject*)self)->tp_name);
77 return -1;
239 return -1;
78 }
240 }
79
241
80 // take the class info from the superType
242 // take the class info from the superType
81 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
243 self->_classInfo = ((PythonQtClassWrapper*)superType)->classInfo();
82 }
244 }
83
245
84 return 0;
246 return 0;
85 }
247 }
86
248
87 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
249 static PyObject *PythonQtClassWrapper_classname(PythonQtClassWrapper* type)
88 {
250 {
89 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
251 return PyString_FromString((QString("Class_") + type->classInfo()->className()).toLatin1().data());
90 }
252 }
91
253
92 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
254 static PyObject *PythonQtClassWrapper_help(PythonQtClassWrapper* type)
93 {
255 {
94 return PythonQt::self()->helpCalled(type->classInfo());
256 return PythonQt::self()->helpCalled(type->classInfo());
95 }
257 }
96
258
97 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args)
259 PyObject *PythonQtClassWrapper__init__(PythonQtClassWrapper *type, PyObject *args)
98 {
260 {
99 Py_ssize_t argc = PyTuple_Size(args);
261 Py_ssize_t argc = PyTuple_Size(args);
100 if (argc>0) {
262 if (argc>0) {
101 // we need to call __init__ of the instance
263 // we need to call __init__ of the instance
102 PyObject* self = PyTuple_GET_ITEM(args, 0);
264 PyObject* self = PyTuple_GET_ITEM(args, 0);
103 if (PyObject_TypeCheck(self, (PyTypeObject*)type->classInfo()->pythonQtClassWrapper())) {
265 if (PyObject_TypeCheck(self, (PyTypeObject*)type->classInfo()->pythonQtClassWrapper())) {
104 PyObject* newargs = PyTuple_New(argc-1);
266 PyObject* newargs = PyTuple_New(argc-1);
105 for (int i = 0;i<argc-1; i++) {
267 for (int i = 0;i<argc-1; i++) {
106 PyTuple_SET_ITEM(newargs, i,PyTuple_GET_ITEM(args, i+1));
268 PyTuple_SET_ITEM(newargs, i,PyTuple_GET_ITEM(args, i+1));
107 }
269 }
108 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
270 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)self;
109 int result = PythonQtInstanceWrapper_init(wrapper, newargs, NULL);
271 int result = PythonQtInstanceWrapper_init(wrapper, newargs, NULL);
110 Py_DECREF(newargs);
272 Py_DECREF(newargs);
111 if (result==0) {
273 if (result==0) {
112 Py_INCREF(Py_None);
274 Py_INCREF(Py_None);
113 return Py_None;
275 return Py_None;
114 } else {
276 } else {
115 // init failed!
277 // init failed!
116 }
278 }
117 } else {
279 } else {
118 // self not of correct type!
280 // self not of correct type!
119 }
281 }
120 } else {
282 } else {
121 // wrong number of args
283 // wrong number of args
122 }
284 }
123 return NULL;
285 return NULL;
124 }
286 }
125
287
126 static PyMethodDef PythonQtClassWrapper_methods[] = {
288 static PyMethodDef PythonQtClassWrapper_methods[] = {
127 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
289 {"__init__", (PyCFunction)PythonQtClassWrapper__init__, METH_VARARGS,
128 "Return the classname of the object"
290 "Return the classname of the object"
129 },
291 },
130 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
292 {"className", (PyCFunction)PythonQtClassWrapper_classname, METH_NOARGS,
131 "Return the classname of the object"
293 "Return the classname of the object"
132 },
294 },
133 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
295 {"help", (PyCFunction)PythonQtClassWrapper_help, METH_NOARGS,
134 "Shows the help of available methods for this class"
296 "Shows the help of available methods for this class"
135 },
297 },
136 {NULL, NULL, 0 , NULL} /* Sentinel */
298 {NULL, NULL, 0 , NULL} /* Sentinel */
137 };
299 };
138
300
139
301
140 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
302 static PyObject *PythonQtClassWrapper_getattro(PyObject *obj, PyObject *name)
141 {
303 {
142 const char *attributeName;
304 const char *attributeName;
143 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
305 PythonQtClassWrapper *wrapper = (PythonQtClassWrapper *)obj;
144
306
145 if ((attributeName = PyString_AsString(name)) == NULL) {
307 if ((attributeName = PyString_AsString(name)) == NULL) {
146 return NULL;
308 return NULL;
147 }
309 }
148 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
310 if (obj == (PyObject*)&PythonQtInstanceWrapper_Type) {
149 return NULL;
311 return NULL;
150 }
312 }
151
313
152 if (qstrcmp(attributeName, "__dict__")==0) {
314 if (qstrcmp(attributeName, "__dict__")==0) {
153 PyObject* dict = ((PyTypeObject *)wrapper)->tp_dict;
315 PyObject* dict = ((PyTypeObject *)wrapper)->tp_dict;
154 if (!wrapper->classInfo()) {
316 if (!wrapper->classInfo()) {
155 Py_INCREF(dict);
317 Py_INCREF(dict);
156 return dict;
318 return dict;
157 }
319 }
158 dict = PyDict_Copy(dict);
320 dict = PyDict_Copy(dict);
159
321
160 QStringList l = wrapper->classInfo()->memberList(false);
322 QStringList l = wrapper->classInfo()->memberList(false);
161 foreach (QString name, l) {
323 foreach (QString name, l) {
162 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
324 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
163 if (o) {
325 if (o) {
164 PyDict_SetItemString(dict, name.toLatin1().data(), o);
326 PyDict_SetItemString(dict, name.toLatin1().data(), o);
165 Py_DECREF(o);
327 Py_DECREF(o);
166 } else {
328 } else {
167 // it must have been a property or child, which we do not know as a class object...
329 // it must have been a property or child, which we do not know as a class object...
168 }
330 }
169 }
331 }
170 if (wrapper->classInfo()->constructors()) {
332 if (wrapper->classInfo()->constructors()) {
171 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[0], obj);
333 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[0], obj);
172 PyDict_SetItemString(dict, "__init__", func);
334 PyDict_SetItemString(dict, "__init__", func);
173 Py_DECREF(func);
335 Py_DECREF(func);
174 }
336 }
175 for (int i = 1;i<3;i++) {
337 for (int i = 1;i<3;i++) {
176 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
338 PyObject* func = PyCFunction_New(&PythonQtClassWrapper_methods[i], obj);
177 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
339 PyDict_SetItemString(dict, PythonQtClassWrapper_methods[i].ml_name, func);
178 Py_DECREF(func);
340 Py_DECREF(func);
179 }
341 }
180 return dict;
342 return dict;
181 }
343 }
182
344
183 if (wrapper->classInfo()) {
345 if (wrapper->classInfo()) {
184 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
346 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
185 if (member._type == PythonQtMemberInfo::EnumValue) {
347 if (member._type == PythonQtMemberInfo::EnumValue) {
186 PyObject* enumValue = member._enumValue;
348 PyObject* enumValue = member._enumValue;
187 Py_INCREF(enumValue);
349 Py_INCREF(enumValue);
188 return enumValue;
350 return enumValue;
189 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
351 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
190 PyObject* enumWrapper = member._enumWrapper;
352 PyObject* enumWrapper = member._enumWrapper;
191 Py_INCREF(enumWrapper);
353 Py_INCREF(enumWrapper);
192 return enumWrapper;
354 return enumWrapper;
193 } else if (member._type == PythonQtMemberInfo::Slot) {
355 } else if (member._type == PythonQtMemberInfo::Slot) {
194 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
356 // we return all slots, even the instance slots, since they are callable as unbound slots with self argument
195 return PythonQtSlotFunction_New(member._slot, obj, NULL);
357 return PythonQtSlotFunction_New(member._slot, obj, NULL);
196 }
358 }
197 }
359 }
198
360
199 // look for the interal methods (className(), help())
361 // look for the interal methods (className(), help())
200 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
362 PyObject* internalMethod = Py_FindMethod( PythonQtClassWrapper_methods, obj, (char*)attributeName);
201 if (internalMethod) {
363 if (internalMethod) {
202 return internalMethod;
364 return internalMethod;
203 }
365 }
204 PyErr_Clear();
366 PyErr_Clear();
205
367
206 // look in super
368 // look in super
207 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
369 PyObject* superAttr = PyType_Type.tp_getattro(obj, name);
208 if (superAttr) {
370 if (superAttr) {
209 return superAttr;
371 return superAttr;
210 }
372 }
211
373
212 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
374 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
213 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
375 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
214 return NULL;
376 return NULL;
215 }
377 }
216
378
217 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
379 static int PythonQtClassWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
218 {
380 {
219 return PyType_Type.tp_setattro(obj,name,value);
381 return PyType_Type.tp_setattro(obj,name,value);
220 }
382 }
221
383
222 /*
384 /*
223 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
385 static PyObject * PythonQtClassWrapper_repr(PyObject * obj)
224 {
386 {
225 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
387 PythonQtClassWrapper* wrapper = (PythonQtClassWrapper*)obj;
226 if (wrapper->classInfo()->isCPPWrapper()) {
388 if (wrapper->classInfo()->isCPPWrapper()) {
227 const QMetaObject* meta = wrapper->classInfo()->metaObject();
389 const QMetaObject* meta = wrapper->classInfo()->metaObject();
228 if (!meta) {
390 if (!meta) {
229 QObject* decorator = wrapper->classInfo()->decorator();
391 QObject* decorator = wrapper->classInfo()->decorator();
230 if (decorator) {
392 if (decorator) {
231 meta = decorator->metaObject();
393 meta = decorator->metaObject();
232 }
394 }
233 }
395 }
234 if (meta) {
396 if (meta) {
235 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
397 return PyString_FromFormat("%s Class (C++ wrapped by %s)", wrapper->classInfo()->className(), meta->className());
236 } else {
398 } else {
237 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
399 return PyString_FromFormat("%s Class (C++ unwrapped)", wrapper->classInfo()->className());
238 }
400 }
239 } else {
401 } else {
240 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
402 return PyString_FromFormat("%s Class", wrapper->classInfo()->className());
241 }
403 }
242 }
404 }
243
405
244 */
406 */
245
407
246 PyTypeObject PythonQtClassWrapper_Type = {
408 PyTypeObject PythonQtClassWrapper_Type = {
247 PyObject_HEAD_INIT(NULL)
409 PyObject_HEAD_INIT(NULL)
248 0, /*ob_size*/
410 0, /*ob_size*/
249 "PythonQt.PythonQtClassWrapper", /*tp_name*/
411 "PythonQt.PythonQtClassWrapper", /*tp_name*/
250 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
412 sizeof(PythonQtClassWrapper), /*tp_basicsize*/
251 0, /*tp_itemsize*/
413 0, /*tp_itemsize*/
252 0, /*tp_dealloc*/
414 0, /*tp_dealloc*/
253 0, /*tp_print*/
415 0, /*tp_print*/
254 0, /*tp_getattr*/
416 0, /*tp_getattr*/
255 0, /*tp_setattr*/
417 0, /*tp_setattr*/
256 0, /*tp_compare*/
418 0, /*tp_compare*/
257 0, //PythonQtClassWrapper_repr, /*tp_repr*/
419 0, //PythonQtClassWrapper_repr, /*tp_repr*/
258 0, /*tp_as_number*/
420 0, /*tp_as_number*/
259 0, /*tp_as_sequence*/
421 0, /*tp_as_sequence*/
260 0, /*tp_as_mapping*/
422 0, /*tp_as_mapping*/
261 0, /*tp_hash */
423 0, /*tp_hash */
262 0, /*tp_call*/
424 0, /*tp_call*/
263 0, /*tp_str*/
425 0, /*tp_str*/
264 PythonQtClassWrapper_getattro, /*tp_getattro*/
426 PythonQtClassWrapper_getattro, /*tp_getattro*/
265 PythonQtClassWrapper_setattro, /*tp_setattro*/
427 PythonQtClassWrapper_setattro, /*tp_setattro*/
266 0, /*tp_as_buffer*/
428 0, /*tp_as_buffer*/
267 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
429 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
268 0, /* tp_doc */
430 0, /* tp_doc */
269 0, /* tp_traverse */
431 0, /* tp_traverse */
270 0, /* tp_clear */
432 0, /* tp_clear */
271 0, /* tp_richcompare */
433 0, /* tp_richcompare */
272 0, /* tp_weaklistoffset */
434 0, /* tp_weaklistoffset */
273 0, /* tp_iter */
435 0, /* tp_iter */
274 0, /* tp_iternext */
436 0, /* tp_iternext */
275 0, /* tp_methods */
437 0, /* tp_methods */
276 0, /* tp_members */
438 0, /* tp_members */
277 0, /* tp_getset */
439 0, /* tp_getset */
278 0, /* tp_base */
440 0, /* tp_base */
279 0, /* tp_dict */
441 0, /* tp_dict */
280 0, /* tp_descr_get */
442 0, /* tp_descr_get */
281 0, /* tp_descr_set */
443 0, /* tp_descr_set */
282 0, /* tp_dictoffset */
444 0, /* tp_dictoffset */
283 (initproc)PythonQtClassWrapper_init, /* tp_init */
445 (initproc)PythonQtClassWrapper_init, /* tp_init */
284 PythonQtClassWrapper_alloc, /* tp_alloc */
446 PythonQtClassWrapper_alloc, /* tp_alloc */
285 0, /* tp_new */
447 0, /* tp_new */
286 0, /* tp_free */
448 0, /* tp_free */
287 };
449 };
288
450
289 //-------------------------------------------------------
451 //-------------------------------------------------------
290
452
@@ -1,671 +1,715
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtInstanceWrapper.cpp
35 // \file PythonQtInstanceWrapper.cpp
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 //----------------------------------------------------------------------------------
40 //----------------------------------------------------------------------------------
41
41
42 #include "PythonQtInstanceWrapper.h"
42 #include "PythonQtInstanceWrapper.h"
43 #include <QObject>
43 #include <QObject>
44 #include "PythonQt.h"
44 #include "PythonQt.h"
45 #include "PythonQtSlot.h"
45 #include "PythonQtSlot.h"
46 #include "PythonQtClassInfo.h"
46 #include "PythonQtClassInfo.h"
47 #include "PythonQtConversion.h"
47 #include "PythonQtConversion.h"
48 #include "PythonQtClassWrapper.h"
48 #include "PythonQtClassWrapper.h"
49
49
50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
50 PythonQtClassInfo* PythonQtInstanceWrapperStruct::classInfo()
51 {
51 {
52 // take the class info from our type object
52 // take the class info from our type object
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
53 return ((PythonQtClassWrapper*)ob_type)->_classInfo;
54 }
54 }
55
55
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
56 static void PythonQtInstanceWrapper_deleteObject(PythonQtInstanceWrapper* self, bool force = false) {
57
57
58 // is this a C++ wrapper?
58 // is this a C++ wrapper?
59 if (self->_wrappedPtr) {
59 if (self->_wrappedPtr) {
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
60 //mlabDebugConst("Python","c++ wrapper removed " << self->_wrappedPtr << " " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
61
61
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
62 PythonQt::priv()->removeWrapperPointer(self->_wrappedPtr);
63 // we own our qobject, so we delete it now:
63 // we own our qobject, so we delete it now:
64 delete self->_obj;
64 delete self->_obj;
65 self->_obj = NULL;
65 self->_obj = NULL;
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
66 if (force || self->classInfo()->hasOwnerMethodButNoOwner(self->_wrappedPtr) || self->_ownedByPythonQt) {
67 int type = self->classInfo()->metaTypeId();
67 int type = self->classInfo()->metaTypeId();
68 if (self->_useQMetaTypeDestroy && type>=0) {
68 if (self->_useQMetaTypeDestroy && type>=0) {
69 // use QMetaType to destroy the object
69 // use QMetaType to destroy the object
70 QMetaType::destroy(type, self->_wrappedPtr);
70 QMetaType::destroy(type, self->_wrappedPtr);
71 } else {
71 } else {
72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
72 PythonQtSlotInfo* slot = self->classInfo()->destructor();
73 if (slot) {
73 if (slot) {
74 void* args[2];
74 void* args[2];
75 args[0] = NULL;
75 args[0] = NULL;
76 args[1] = &self->_wrappedPtr;
76 args[1] = &self->_wrappedPtr;
77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
77 slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, slot->slotIndex(), args);
78 self->_wrappedPtr = NULL;
78 self->_wrappedPtr = NULL;
79 } else {
79 } else {
80 if (type>=0) {
80 if (type>=0) {
81 // use QMetaType to destroy the object
81 // use QMetaType to destroy the object
82 QMetaType::destroy(type, self->_wrappedPtr);
82 QMetaType::destroy(type, self->_wrappedPtr);
83 } else {
83 } else {
84 // TODO: warn about not being able to destroy the object?
84 // TODO: warn about not being able to destroy the object?
85 }
85 }
86 }
86 }
87 }
87 }
88 }
88 }
89 } else {
89 } else {
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
90 //mlabDebugConst("Python","qobject wrapper removed " << self->_obj->className() << " " << self->classInfo()->wrappedClassName().latin1());
91 if (self->_objPointerCopy) {
91 if (self->_objPointerCopy) {
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
92 PythonQt::priv()->removeWrapperPointer(self->_objPointerCopy);
93 }
93 }
94 if (self->_obj) {
94 if (self->_obj) {
95 if (force || self->_ownedByPythonQt) {
95 if (force || self->_ownedByPythonQt) {
96 if (force || !self->_obj->parent()) {
96 if (force || !self->_obj->parent()) {
97 delete self->_obj;
97 delete self->_obj;
98 }
98 }
99 } else {
99 } else {
100 if (self->_obj->parent()==NULL) {
100 if (self->_obj->parent()==NULL) {
101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
101 // tell someone who is interested that the qobject is no longer wrapped, if it has no parent
102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
102 PythonQt::qObjectNoLongerWrappedCB(self->_obj);
103 }
103 }
104 }
104 }
105 }
105 }
106 }
106 }
107 self->_obj = NULL;
107 self->_obj = NULL;
108 }
108 }
109
109
110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
110 static void PythonQtInstanceWrapper_dealloc(PythonQtInstanceWrapper* self)
111 {
111 {
112 PythonQtInstanceWrapper_deleteObject(self);
112 PythonQtInstanceWrapper_deleteObject(self);
113 self->_obj.~QPointer<QObject>();
113 self->_obj.~QPointer<QObject>();
114 self->ob_type->tp_free((PyObject*)self);
114 self->ob_type->tp_free((PyObject*)self);
115 }
115 }
116
116
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
117 static PyObject* PythonQtInstanceWrapper_new(PyTypeObject *type, PyObject * /*args*/, PyObject * /*kwds*/)
118 {
118 {
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
119 //PythonQtClassWrapper *classType = (PythonQtClassWrapper*)type;
120 PythonQtInstanceWrapper *self;
120 PythonQtInstanceWrapper *self;
121 static PyObject* emptyTuple = NULL;
121 static PyObject* emptyTuple = NULL;
122 if (emptyTuple==NULL) {
122 if (emptyTuple==NULL) {
123 emptyTuple = PyTuple_New(0);
123 emptyTuple = PyTuple_New(0);
124 }
124 }
125
125
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
126 self = (PythonQtInstanceWrapper*)PyBaseObject_Type.tp_new(type, emptyTuple, NULL);
127
127
128 if (self != NULL) {
128 if (self != NULL) {
129 new (&self->_obj) QPointer<QObject>();
129 new (&self->_obj) QPointer<QObject>();
130 self->_wrappedPtr = NULL;
130 self->_wrappedPtr = NULL;
131 self->_ownedByPythonQt = false;
131 self->_ownedByPythonQt = false;
132 self->_useQMetaTypeDestroy = false;
132 self->_useQMetaTypeDestroy = false;
133 self->_isShellInstance = false;
133 self->_isShellInstance = false;
134 }
134 }
135 return (PyObject *)self;
135 return (PyObject *)self;
136 }
136 }
137
137
138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
138 int PythonQtInstanceWrapper_init(PythonQtInstanceWrapper * self, PyObject * args, PyObject * kwds)
139 {
139 {
140 if (args == PythonQtPrivate::dummyTuple()) {
140 if (args == PythonQtPrivate::dummyTuple()) {
141 // we are called from the internal PythonQt API, so our data will be filled later on...
141 // we are called from the internal PythonQt API, so our data will be filled later on...
142 return 0;
142 return 0;
143 }
143 }
144
144
145 // we are called from python, try to construct our object
145 // we are called from python, try to construct our object
146 if (self->classInfo()->constructors()) {
146 if (self->classInfo()->constructors()) {
147 void* directCPPPointer = NULL;
147 void* directCPPPointer = NULL;
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
148 PythonQtSlotFunction_CallImpl(self->classInfo(), NULL, self->classInfo()->constructors(), args, kwds, NULL, &directCPPPointer);
149 if (PyErr_Occurred()) {
149 if (PyErr_Occurred()) {
150 return -1;
150 return -1;
151 }
151 }
152 if (directCPPPointer) {
152 if (directCPPPointer) {
153 // change ownershipflag to be owned by PythonQt
153 // change ownershipflag to be owned by PythonQt
154 self->_ownedByPythonQt = true;
154 self->_ownedByPythonQt = true;
155 self->_useQMetaTypeDestroy = false;
155 self->_useQMetaTypeDestroy = false;
156 if (self->classInfo()->isCPPWrapper()) {
156 if (self->classInfo()->isCPPWrapper()) {
157 self->_wrappedPtr = directCPPPointer;
157 self->_wrappedPtr = directCPPPointer;
158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
158 // TODO xxx: if there is a wrapper factory, we might want to generate a wrapper for our class?!
159 } else {
159 } else {
160 self->setQObject((QObject*)directCPPPointer);
160 self->setQObject((QObject*)directCPPPointer);
161 }
161 }
162 // register with PythonQt
162 // register with PythonQt
163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
163 PythonQt::priv()->addWrapperPointer(directCPPPointer, self);
164
164
165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
165 PythonQtShellSetInstanceWrapperCB* cb = self->classInfo()->shellSetInstanceWrapperCB();
166 if (cb) {
166 if (cb) {
167 // if we are a derived python class, we set the wrapper
167 // if we are a derived python class, we set the wrapper
168 // to activate the shell class, otherwise we just ignore that it is a shell...
168 // to activate the shell class, otherwise we just ignore that it is a shell...
169 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
169 // we detect it be checking if the type does not have PythonQtInstanceWrapper_Type as direct base class,
170 // which is the case for all non-python derived types
170 // which is the case for all non-python derived types
171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
171 if (((PyObject*)self)->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
172 // set the wrapper and remember that we have a shell instance!
172 // set the wrapper and remember that we have a shell instance!
173 (*cb)(directCPPPointer, self);
173 (*cb)(directCPPPointer, self);
174 self->_isShellInstance = true;
174 self->_isShellInstance = true;
175 }
175 }
176 }
176 }
177 }
177 }
178 } else {
178 } else {
179 QString error = QString("No constructors available for ") + self->classInfo()->className();
179 QString error = QString("No constructors available for ") + self->classInfo()->className();
180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
180 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
181 return -1;
181 return -1;
182 }
182 }
183 return 0;
183 return 0;
184 }
184 }
185
185
186 static PyObject *PythonQtInstanceWrapper_richcompare(PythonQtInstanceWrapper* wrapper, PyObject* other, int code)
187 {
188 bool validPtrs = false;
189 bool areSamePtrs = false;
190 if (PyObject_TypeCheck((PyObject*)wrapper, &PythonQtInstanceWrapper_Type)) {
191 if (PyObject_TypeCheck(other, &PythonQtInstanceWrapper_Type)) {
192 validPtrs = true;
193 PythonQtInstanceWrapper* w1 = wrapper;
194 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)other;
195 // check pointers directly
196 if (w1->_wrappedPtr != NULL) {
197 if (w1->_wrappedPtr == w2->_wrappedPtr) {
198 areSamePtrs = true;
199 }
200 } else if (w1->_obj == w2->_obj) {
201 areSamePtrs = true;
202 }
203 } else if (other == Py_None) {
204 validPtrs = true;
205 if (wrapper->_obj || wrapper->_wrappedPtr) {
206 areSamePtrs = false;
207 } else {
208 areSamePtrs = true;
209 }
210 }
211 }
212
213 if ((wrapper->classInfo()->typeSlots() & PythonQt::Type_RichCompare) == 0) {
214 // shortcut if richcompare is not supported:
215 if (validPtrs && code == Py_EQ) {
216 return PythonQtConv::GetPyBool(areSamePtrs);
217 } else if (validPtrs && code == Py_NE) {
218 return PythonQtConv::GetPyBool(!areSamePtrs);
219 }
220 Py_INCREF(Py_NotImplemented);
221 return Py_NotImplemented;
222 }
223
224 QByteArray memberName;
225 switch (code) {
226 case Py_LT:
227 {
228 static QByteArray name = "__lt__";
229 memberName = name;
230 }
231 break;
232
233 case Py_LE:
234 {
235 static QByteArray name = "__le__";
236 memberName = name;
237 }
238 break;
239
240 case Py_EQ:
241 {
242 static QByteArray name = "__eq__";
243 memberName = name;
244 }
245 break;
246
247 case Py_NE:
248 {
249 static QByteArray name = "__ne__";
250 memberName = name;
251 }
252 break;
253
254 case Py_GT:
255 {
256 static QByteArray name = "__gt__";
257 memberName = name;
258 }
259 break;
260
261 case Py_GE:
262 {
263 static QByteArray name = "__ge__";
264 memberName = name;
265 }
266 break;
267 }
268
269 PythonQtMemberInfo opSlot = wrapper->classInfo()->member(memberName);
270 if (opSlot._type == PythonQtMemberInfo::Slot) {
271 // TODO get rid of tuple
272 PyObject* args = PyTuple_New(1);
273 Py_INCREF(other);
274 PyTuple_SET_ITEM(args, 0, other);
275 PyObject* result = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, opSlot._slot, args, NULL, wrapper->_wrappedPtr);
276 Py_DECREF(args);
277 return result;
278 } else {
279 // not implemented, let python try something else!
280 Py_INCREF(Py_NotImplemented);
281 return Py_NotImplemented;
282 }
283 }
284
285
186 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
286 static PyObject *PythonQtInstanceWrapper_classname(PythonQtInstanceWrapper* obj)
187 {
287 {
188 return PyString_FromString(obj->ob_type->tp_name);
288 return PyString_FromString(obj->ob_type->tp_name);
189 }
289 }
190
290
191 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
291 static PyObject *PythonQtInstanceWrapper_help(PythonQtInstanceWrapper* obj)
192 {
292 {
193 return PythonQt::self()->helpCalled(obj->classInfo());
293 return PythonQt::self()->helpCalled(obj->classInfo());
194 }
294 }
195
295
196 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
296 static PyObject *PythonQtInstanceWrapper_delete(PythonQtInstanceWrapper * self)
197 {
297 {
198 PythonQtInstanceWrapper_deleteObject(self, true);
298 PythonQtInstanceWrapper_deleteObject(self, true);
199 Py_INCREF(Py_None);
299 Py_INCREF(Py_None);
200 return Py_None;
300 return Py_None;
201 }
301 }
202
302
203
303
204 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
304 static PyMethodDef PythonQtInstanceWrapper_methods[] = {
205 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
305 {"className", (PyCFunction)PythonQtInstanceWrapper_classname, METH_NOARGS,
206 "Return the classname of the object"
306 "Return the classname of the object"
207 },
307 },
208 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
308 {"help", (PyCFunction)PythonQtInstanceWrapper_help, METH_NOARGS,
209 "Shows the help of available methods for this class"
309 "Shows the help of available methods for this class"
210 },
310 },
211 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
311 {"delete", (PyCFunction)PythonQtInstanceWrapper_delete, METH_NOARGS,
212 "Deletes the C++ object (at your own risk, my friend!)"
312 "Deletes the C++ object (at your own risk, my friend!)"
213 },
313 },
214 {NULL, NULL, 0, NULL} /* Sentinel */
314 {NULL, NULL, 0, NULL} /* Sentinel */
215 };
315 };
216
316
217
317
218 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
318 static PyObject *PythonQtInstanceWrapper_getattro(PyObject *obj,PyObject *name)
219 {
319 {
220 const char *attributeName;
320 const char *attributeName;
221 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
321 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
222
322
223 if ((attributeName = PyString_AsString(name)) == NULL) {
323 if ((attributeName = PyString_AsString(name)) == NULL) {
224 return NULL;
324 return NULL;
225 }
325 }
226
326
227 if (qstrcmp(attributeName, "__dict__")==0) {
327 if (qstrcmp(attributeName, "__dict__")==0) {
228 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
328 PyObject* dict = PyBaseObject_Type.tp_getattro(obj, name);
229 dict = PyDict_Copy(dict);
329 dict = PyDict_Copy(dict);
230
330
231 if (wrapper->_obj) {
331 if (wrapper->_obj) {
232 // only the properties are missing, the rest is already available from
332 // only the properties are missing, the rest is already available from
233 // PythonQtClassWrapper...
333 // PythonQtClassWrapper...
234 QStringList l = wrapper->classInfo()->propertyList();
334 QStringList l = wrapper->classInfo()->propertyList();
235 foreach (QString name, l) {
335 foreach (QString name, l) {
236 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
336 PyObject* o = PyObject_GetAttrString(obj, name.toLatin1().data());
237 if (o) {
337 if (o) {
238 PyDict_SetItemString(dict, name.toLatin1().data(), o);
338 PyDict_SetItemString(dict, name.toLatin1().data(), o);
239 Py_DECREF(o);
339 Py_DECREF(o);
240 } else {
340 } else {
241 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
341 std::cerr << "PythonQtInstanceWrapper: something is wrong, could not get attribute " << name.toLatin1().data();
242 }
342 }
243 }
343 }
244
344
245 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
345 QList<QByteArray> dynamicProps = wrapper->_obj->dynamicPropertyNames();
246 foreach (QByteArray name, dynamicProps) {
346 foreach (QByteArray name, dynamicProps) {
247 PyObject* o = PyObject_GetAttrString(obj, name.data());
347 PyObject* o = PyObject_GetAttrString(obj, name.data());
248 if (o) {
348 if (o) {
249 PyDict_SetItemString(dict, name.data(), o);
349 PyDict_SetItemString(dict, name.data(), o);
250 Py_DECREF(o);
350 Py_DECREF(o);
251 } else {
351 } else {
252 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
352 std::cerr << "PythonQtInstanceWrapper: dynamic property could not be read " << name.data();
253 }
353 }
254 }
354 }
255 }
355 }
256 // Note: we do not put children into the dict, is would look confusing?!
356 // Note: we do not put children into the dict, is would look confusing?!
257 return dict;
357 return dict;
258 }
358 }
259
359
260 // first look in super, to return derived methods from base object first
360 // first look in super, to return derived methods from base object first
261 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
361 PyObject* superAttr = PyBaseObject_Type.tp_getattro(obj, name);
262 if (superAttr) {
362 if (superAttr) {
263 return superAttr;
363 return superAttr;
264 }
364 }
265 PyErr_Clear();
365 PyErr_Clear();
266
366
267 // mlabDebugConst("Python","get " << attributeName);
367 // mlabDebugConst("Python","get " << attributeName);
268
368
269 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
369 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
270 switch (member._type) {
370 switch (member._type) {
271 case PythonQtMemberInfo::Property:
371 case PythonQtMemberInfo::Property:
272 if (wrapper->_obj) {
372 if (wrapper->_obj) {
273 if (member._property.userType() != QVariant::Invalid) {
373 if (member._property.userType() != QVariant::Invalid) {
274 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
374 return PythonQtConv::QVariantToPyObject(member._property.read(wrapper->_obj));
275 } else {
375 } else {
276 Py_INCREF(Py_None);
376 Py_INCREF(Py_None);
277 return Py_None;
377 return Py_None;
278 }
378 }
279 } else {
379 } else {
280 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
380 QString error = QString("Trying to read property '") + attributeName + "' from a destroyed " + wrapper->classInfo()->className() + " object";
281 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
381 PyErr_SetString(PyExc_ValueError, error.toLatin1().data());
282 return NULL;
382 return NULL;
283 }
383 }
284 break;
384 break;
285 case PythonQtMemberInfo::Slot:
385 case PythonQtMemberInfo::Slot:
286 return PythonQtSlotFunction_New(member._slot, obj, NULL);
386 return PythonQtSlotFunction_New(member._slot, obj, NULL);
287 break;
387 break;
288 case PythonQtMemberInfo::EnumValue:
388 case PythonQtMemberInfo::EnumValue:
289 {
389 {
290 PyObject* enumValue = member._enumValue;
390 PyObject* enumValue = member._enumValue;
291 Py_INCREF(enumValue);
391 Py_INCREF(enumValue);
292 return enumValue;
392 return enumValue;
293 }
393 }
294 break;
394 break;
295 case PythonQtMemberInfo::EnumWrapper:
395 case PythonQtMemberInfo::EnumWrapper:
296 {
396 {
297 PyObject* enumWrapper = member._enumWrapper;
397 PyObject* enumWrapper = member._enumWrapper;
298 Py_INCREF(enumWrapper);
398 Py_INCREF(enumWrapper);
299 return enumWrapper;
399 return enumWrapper;
300 }
400 }
301 break;
401 break;
302 case PythonQtMemberInfo::NotFound:
402 case PythonQtMemberInfo::NotFound:
303 {
403 {
304 static const QByteArray getterString("py_get_");
404 static const QByteArray getterString("py_get_");
305 // check for a getter slot
405 // check for a getter slot
306 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
406 PythonQtMemberInfo member = wrapper->classInfo()->member(getterString + attributeName);
307 if (member._type == PythonQtMemberInfo::Slot) {
407 if (member._type == PythonQtMemberInfo::Slot) {
308 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
408 return PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, member._slot, NULL, NULL, wrapper->_wrappedPtr);
309 }
409 }
310
410
311 // handle dynamic properties
411 // handle dynamic properties
312 if (wrapper->_obj) {
412 if (wrapper->_obj) {
313 QVariant v = wrapper->_obj->property(attributeName);
413 QVariant v = wrapper->_obj->property(attributeName);
314 if (v.isValid()) {
414 if (v.isValid()) {
315 return PythonQtConv::QVariantToPyObject(v);
415 return PythonQtConv::QVariantToPyObject(v);
316 }
416 }
317 }
417 }
318 }
418 }
319 break;
419 break;
320 default:
420 default:
321 // is an invalid type, go on
421 // is an invalid type, go on
322 break;
422 break;
323 }
423 }
324
424
325 // look for the internal methods (className(), help())
425 // look for the internal methods (className(), help())
326 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
426 PyObject* internalMethod = Py_FindMethod( PythonQtInstanceWrapper_methods, obj, (char*)attributeName);
327 if (internalMethod) {
427 if (internalMethod) {
328 return internalMethod;
428 return internalMethod;
329 }
429 }
330 PyErr_Clear();
430 PyErr_Clear();
331
431
332 if (wrapper->_obj) {
432 if (wrapper->_obj) {
333 // look for a child
433 // look for a child
334 QObjectList children = wrapper->_obj->children();
434 QObjectList children = wrapper->_obj->children();
335 for (int i = 0; i < children.count(); i++) {
435 for (int i = 0; i < children.count(); i++) {
336 QObject *child = children.at(i);
436 QObject *child = children.at(i);
337 if (child->objectName() == attributeName) {
437 if (child->objectName() == attributeName) {
338 return PythonQt::priv()->wrapQObject(child);
438 return PythonQt::priv()->wrapQObject(child);
339 }
439 }
340 }
440 }
341 }
441 }
342
442
343 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
443 QString error = QString(wrapper->classInfo()->className()) + " has no attribute named '" + QString(attributeName) + "'";
344 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
444 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
345 return NULL;
445 return NULL;
346 }
446 }
347
447
348 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
448 static int PythonQtInstanceWrapper_setattro(PyObject *obj,PyObject *name,PyObject *value)
349 {
449 {
350 QString error;
450 QString error;
351 const char *attributeName;
451 const char *attributeName;
352 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
452 PythonQtInstanceWrapper *wrapper = (PythonQtInstanceWrapper *)obj;
353
453
354 if ((attributeName = PyString_AsString(name)) == NULL)
454 if ((attributeName = PyString_AsString(name)) == NULL)
355 return -1;
455 return -1;
356
456
357 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
457 PythonQtMemberInfo member = wrapper->classInfo()->member(attributeName);
358 if (member._type == PythonQtMemberInfo::Property) {
458 if (member._type == PythonQtMemberInfo::Property) {
359
459
360 if (!wrapper->_obj) {
460 if (!wrapper->_obj) {
361 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
461 error = QString("Trying to set property '") + attributeName + "' on a destroyed " + wrapper->classInfo()->className() + " object";
362 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
462 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
363 return -1;
463 return -1;
364 }
464 }
365
465
366 QMetaProperty prop = member._property;
466 QMetaProperty prop = member._property;
367 if (prop.isWritable()) {
467 if (prop.isWritable()) {
368 QVariant v;
468 QVariant v;
369 if (prop.isEnumType()) {
469 if (prop.isEnumType()) {
370 // this will give us either a string or an int, everything else will probably be an error
470 // this will give us either a string or an int, everything else will probably be an error
371 v = PythonQtConv::PyObjToQVariant(value);
471 v = PythonQtConv::PyObjToQVariant(value);
372 } else {
472 } else {
373 int t = prop.userType();
473 int t = prop.userType();
374 v = PythonQtConv::PyObjToQVariant(value, t);
474 v = PythonQtConv::PyObjToQVariant(value, t);
375 }
475 }
376 bool success = false;
476 bool success = false;
377 if (v.isValid()) {
477 if (v.isValid()) {
378 success = prop.write(wrapper->_obj, v);
478 success = prop.write(wrapper->_obj, v);
379 }
479 }
380 if (success) {
480 if (success) {
381 return 0;
481 return 0;
382 } else {
482 } else {
383 error = QString("Property '") + attributeName + "' of type '" +
483 error = QString("Property '") + attributeName + "' of type '" +
384 prop.typeName() + "' does not accept an object of type "
484 prop.typeName() + "' does not accept an object of type "
385 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
485 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
386 }
486 }
387 } else {
487 } else {
388 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
488 error = QString("Property '") + attributeName + "' of " + obj->ob_type->tp_name + " object is not writable";
389 }
489 }
390 } else if (member._type == PythonQtMemberInfo::Slot) {
490 } else if (member._type == PythonQtMemberInfo::Slot) {
391 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
491 error = QString("Slot '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
392 } else if (member._type == PythonQtMemberInfo::EnumValue) {
492 } else if (member._type == PythonQtMemberInfo::EnumValue) {
393 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
493 error = QString("EnumValue '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
394 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
494 } else if (member._type == PythonQtMemberInfo::EnumWrapper) {
395 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
495 error = QString("Enum '") + attributeName + "' can not be overwritten on " + obj->ob_type->tp_name + " object";
396 } else if (member._type == PythonQtMemberInfo::NotFound) {
496 } else if (member._type == PythonQtMemberInfo::NotFound) {
397 // check for a setter slot
497 // check for a setter slot
398 static const QByteArray setterString("py_set_");
498 static const QByteArray setterString("py_set_");
399 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
499 PythonQtMemberInfo setter = wrapper->classInfo()->member(setterString + attributeName);
400 if (setter._type == PythonQtMemberInfo::Slot) {
500 if (setter._type == PythonQtMemberInfo::Slot) {
401 // call the setter and ignore the result value
501 // call the setter and ignore the result value
402 void* result;
502 void* result;
403 PyObject* args = PyTuple_New(1);
503 PyObject* args = PyTuple_New(1);
404 Py_INCREF(value);
504 Py_INCREF(value);
405 PyTuple_SET_ITEM(args, 0, value);
505 PyTuple_SET_ITEM(args, 0, value);
406 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
506 PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, setter._slot, args, NULL, wrapper->_wrappedPtr, &result);
407 Py_DECREF(args);
507 Py_DECREF(args);
408 return 0;
508 return 0;
409 }
509 }
410
510
411 // handle dynamic properties
511 // handle dynamic properties
412 if (wrapper->_obj) {
512 if (wrapper->_obj) {
413 QVariant prop = wrapper->_obj->property(attributeName);
513 QVariant prop = wrapper->_obj->property(attributeName);
414 if (prop.isValid()) {
514 if (prop.isValid()) {
415 QVariant v = PythonQtConv::PyObjToQVariant(value);
515 QVariant v = PythonQtConv::PyObjToQVariant(value);
416 if (v.isValid()) {
516 if (v.isValid()) {
417 wrapper->_obj->setProperty(attributeName, v);
517 wrapper->_obj->setProperty(attributeName, v);
418 return 0;
518 return 0;
419 } else {
519 } else {
420 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
520 error = QString("Dynamic property '") + attributeName + "' does not accept an object of type "
421 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
521 + QString(value->ob_type->tp_name) + " (" + PythonQtConv::PyObjGetRepresentation(value) + ")";
422 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
522 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
423 return -1;
523 return -1;
424 }
524 }
425 }
525 }
426 }
526 }
427
527
428 // if we are a derived python class, we allow setting attributes.
528 // if we are a derived python class, we allow setting attributes.
429 // if we are a direct CPP wrapper, we do NOT allow it, since
529 // if we are a direct CPP wrapper, we do NOT allow it, since
430 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
530 // it would be confusing to allow it because a wrapper will go away when it is not seen by python anymore
431 // and when it is recreated from a CPP pointer the attributes are gone...
531 // and when it is recreated from a CPP pointer the attributes are gone...
432 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
532 if (obj->ob_type->tp_base != &PythonQtInstanceWrapper_Type) {
433 return PyBaseObject_Type.tp_setattro(obj,name,value);
533 return PyBaseObject_Type.tp_setattro(obj,name,value);
434 } else {
534 } else {
435 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
535 error = QString("'") + attributeName + "' does not exist on " + obj->ob_type->tp_name + " and creating new attributes on C++ objects is not allowed";
436 }
536 }
437 }
537 }
438
538
439 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
539 PyErr_SetString(PyExc_AttributeError, error.toLatin1().data());
440 return -1;
540 return -1;
441 }
541 }
442
542
443 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
543 static QString getStringFromObject(PythonQtInstanceWrapper* wrapper) {
444 QString result;
544 QString result;
445 if (wrapper->_wrappedPtr) {
545 if (wrapper->_wrappedPtr) {
446 // first try some manually string conversions for some variants
546 // first try some manually string conversions for some variants
447 int metaid = wrapper->classInfo()->metaTypeId();
547 int metaid = wrapper->classInfo()->metaTypeId();
448 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
548 result = PythonQtConv::CPPObjectToString(metaid, wrapper->_wrappedPtr);
449 if (!result.isEmpty()) {
549 if (!result.isEmpty()) {
450 return result;
550 return result;
451 }
551 }
452 }
552 }
453 // next, try to call py_toString
553 // next, try to call py_toString
454 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
554 PythonQtMemberInfo info = wrapper->classInfo()->member("py_toString");
455 if (info._type == PythonQtMemberInfo::Slot) {
555 if (info._type == PythonQtMemberInfo::Slot) {
456 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
556 PyObject* resultObj = PythonQtSlotFunction_CallImpl(wrapper->classInfo(), wrapper->_obj, info._slot, NULL, NULL, wrapper->_wrappedPtr);
457 if (resultObj) {
557 if (resultObj) {
458 // TODO this is one conversion too much, would be nicer to call the slot directly...
558 // TODO this is one conversion too much, would be nicer to call the slot directly...
459 result = PythonQtConv::PyObjGetString(resultObj);
559 result = PythonQtConv::PyObjGetString(resultObj);
460 Py_DECREF(resultObj);
560 Py_DECREF(resultObj);
461 }
561 }
462 }
562 }
463 return result;
563 return result;
464 }
564 }
465
565
466 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
566 static PyObject * PythonQtInstanceWrapper_str(PyObject * obj)
467 {
567 {
468 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
568 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
469 const char* typeName = obj->ob_type->tp_name;
569 const char* typeName = obj->ob_type->tp_name;
470 QObject *qobj = wrapper->_obj;
570 QObject *qobj = wrapper->_obj;
471 QString str = getStringFromObject(wrapper);
571 QString str = getStringFromObject(wrapper);
472 if (!str.isEmpty()) {
572 if (!str.isEmpty()) {
473 return PyString_FromFormat("%s", str.toLatin1().constData());
573 return PyString_FromFormat("%s", str.toLatin1().constData());
474 }
574 }
475 if (wrapper->_wrappedPtr) {
575 if (wrapper->_wrappedPtr) {
476 if (wrapper->_obj) {
576 if (wrapper->_obj) {
477 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
577 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
478 } else {
578 } else {
479 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
579 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
480 }
580 }
481 } else {
581 } else {
482 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
582 return PyString_FromFormat("%s (QObject %p)", typeName, qobj);
483 }
583 }
484 }
584 }
485
585
486 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
586 static PyObject * PythonQtInstanceWrapper_repr(PyObject * obj)
487 {
587 {
488 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
588 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
489 const char* typeName = obj->ob_type->tp_name;
589 const char* typeName = obj->ob_type->tp_name;
490
590
491 QObject *qobj = wrapper->_obj;
591 QObject *qobj = wrapper->_obj;
492 QString str = getStringFromObject(wrapper);
592 QString str = getStringFromObject(wrapper);
493 if (!str.isEmpty()) {
593 if (!str.isEmpty()) {
494 if (str.startsWith(typeName)) {
594 if (str.startsWith(typeName)) {
495 return PyString_FromFormat("%s", str.toLatin1().constData());
595 return PyString_FromFormat("%s", str.toLatin1().constData());
496 } else {
596 } else {
497 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
597 return PyString_FromFormat("%s(%s, %p)", typeName, str.toLatin1().constData(), wrapper->_wrappedPtr);
498 }
598 }
499 }
599 }
500 if (wrapper->_wrappedPtr) {
600 if (wrapper->_wrappedPtr) {
501 if (wrapper->_obj) {
601 if (wrapper->_obj) {
502 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
602 return PyString_FromFormat("%s (C++ Object %p wrapped by %s %p))", typeName, wrapper->_wrappedPtr, wrapper->_obj->metaObject()->className(), qobj);
503 } else {
603 } else {
504 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
604 return PyString_FromFormat("%s (C++ Object %p)", typeName, wrapper->_wrappedPtr);
505 }
605 }
506 } else {
606 } else {
507 return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj);
607 return PyString_FromFormat("%s (%s %p)", typeName, wrapper->classInfo()->className(), qobj);
508 }
608 }
509 }
609 }
510
610
511 static int PythonQtInstanceWrapper_compare(PyObject * obj1, PyObject * obj2)
611 static int PythonQtInstanceWrapper_builtin_nonzero(PyObject *obj)
512 {
513 if (PyObject_TypeCheck(obj1, &PythonQtInstanceWrapper_Type) &&
514 PyObject_TypeCheck(obj2, &PythonQtInstanceWrapper_Type)) {
515
516 PythonQtInstanceWrapper* w1 = (PythonQtInstanceWrapper*)obj1;
517 PythonQtInstanceWrapper* w2 = (PythonQtInstanceWrapper*)obj2;
518 // check pointers directly first:
519 if (w1->_wrappedPtr != NULL) {
520 if (w1->_wrappedPtr == w2->_wrappedPtr) {
521 return 0;
522 }
523 } else if (w1->_obj == w2->_obj) {
524 return 0;
525 }
526 const char* class1 = w1->classInfo()->className();
527 const char* class2 = w2->classInfo()->className();
528 if (strcmp(class1, class2) == 0) {
529 // same class names, so we can try the operator_equal
530 PythonQtMemberInfo info = w1->classInfo()->member("operator_equal");
531 if (info._type == PythonQtMemberInfo::Slot) {
532 bool result = false;
533 void* obj1 = w1->_wrappedPtr;
534 if (!obj1) {
535 obj1 = w1->_obj;
536 }
537 if (!obj1) { return -1; }
538 void* obj2 = w2->_wrappedPtr;
539 if (!obj2) {
540 obj2 = w2->_obj;
541 }
542 if (!obj2) { return -1; }
543 if (info._slot->isInstanceDecorator()) {
544 // call on decorator QObject
545 void* args[3];
546 args[0] = &result;
547 args[1] = &obj1; // this is a pointer, so it needs a pointer to a pointer
548 args[2] = obj2; // this is a reference, so it needs the direct pointer
549 info._slot->decorator()->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
550 return result?0:-1;
551 } else {
552 // call directly on QObject
553 if (w1->_obj && w2->_obj) {
554 void* args[2];
555 args[0] = &result;
556 args[1] = obj2; // this is a reference, so it needs the direct pointer
557 w1->_obj->qt_metacall(QMetaObject::InvokeMetaMethod, info._slot->slotIndex(), args);
558 return result?0:-1;
559 }
560 }
561 }
562 }
563 }
564 return -1;
565 }
566
567 static int PythonQtInstanceWrapper_nonzero(PyObject *obj)
568 {
612 {
569 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
613 PythonQtInstanceWrapper* wrapper = (PythonQtInstanceWrapper*)obj;
570 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
614 return (wrapper->_wrappedPtr == NULL && wrapper->_obj == NULL)?0:1;
571 }
615 }
572
616
573
617
574 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
618 static long PythonQtInstanceWrapper_hash(PythonQtInstanceWrapper *obj)
575 {
619 {
576 if (obj->_wrappedPtr != NULL) {
620 if (obj->_wrappedPtr != NULL) {
577 return reinterpret_cast<long>(obj->_wrappedPtr);
621 return reinterpret_cast<long>(obj->_wrappedPtr);
578 } else {
622 } else {
579 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
623 QObject* qobj = obj->_obj; // get pointer from QPointer wrapper
580 return reinterpret_cast<long>(qobj);
624 return reinterpret_cast<long>(qobj);
581 }
625 }
582 }
626 }
583
627
584
628
585
629
586 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
630 // we override nb_nonzero, so that one can do 'if' expressions to test for a NULL ptr
587 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
631 static PyNumberMethods PythonQtInstanceWrapper_as_number = {
588 0, /* nb_add */
632 0, /* nb_add */
589 0, /* nb_subtract */
633 0, /* nb_subtract */
590 0, /* nb_multiply */
634 0, /* nb_multiply */
591 0, /* nb_divide */
635 0, /* nb_divide */
592 0, /* nb_remainder */
636 0, /* nb_remainder */
593 0, /* nb_divmod */
637 0, /* nb_divmod */
594 0, /* nb_power */
638 0, /* nb_power */
595 0, /* nb_negative */
639 0, /* nb_negative */
596 0, /* nb_positive */
640 0, /* nb_positive */
597 0, /* nb_absolute */
641 0, /* nb_absolute */
598 PythonQtInstanceWrapper_nonzero, /* nb_nonzero */
642 PythonQtInstanceWrapper_builtin_nonzero, /* nb_nonzero */
599 0, /* nb_invert */
643 0, /* nb_invert */
600 0, /* nb_lshift */
644 0, /* nb_lshift */
601 0, /* nb_rshift */
645 0, /* nb_rshift */
602 0, /* nb_and */
646 0, /* nb_and */
603 0, /* nb_xor */
647 0, /* nb_xor */
604 0, /* nb_or */
648 0, /* nb_or */
605 0, /* nb_coerce */
649 0, /* nb_coerce */
606 0, /* nb_int */
650 0, /* nb_int */
607 0, /* nb_long */
651 0, /* nb_long */
608 0, /* nb_float */
652 0, /* nb_float */
609 0, /* nb_oct */
653 0, /* nb_oct */
610 0, /* nb_hex */
654 0, /* nb_hex */
611 0, /* nb_inplace_add */
655 0, /* nb_inplace_add */
612 0, /* nb_inplace_subtract */
656 0, /* nb_inplace_subtract */
613 0, /* nb_inplace_multiply */
657 0, /* nb_inplace_multiply */
614 0, /* nb_inplace_divide */
658 0, /* nb_inplace_divide */
615 0, /* nb_inplace_remainder */
659 0, /* nb_inplace_remainder */
616 0, /* nb_inplace_power */
660 0, /* nb_inplace_power */
617 0, /* nb_inplace_lshift */
661 0, /* nb_inplace_lshift */
618 0, /* nb_inplace_rshift */
662 0, /* nb_inplace_rshift */
619 0, /* nb_inplace_and */
663 0, /* nb_inplace_and */
620 0, /* nb_inplace_xor */
664 0, /* nb_inplace_xor */
621 0, /* nb_inplace_or */
665 0, /* nb_inplace_or */
622 0, /* nb_floor_divide */
666 0, /* nb_floor_divide */
623 0, /* nb_true_divide */
667 0, /* nb_true_divide */
624 0, /* nb_inplace_floor_divide */
668 0, /* nb_inplace_floor_divide */
625 0, /* nb_inplace_true_divide */
669 0, /* nb_inplace_true_divide */
626 };
670 };
627
671
628 PyTypeObject PythonQtInstanceWrapper_Type = {
672 PyTypeObject PythonQtInstanceWrapper_Type = {
629 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
673 PyObject_HEAD_INIT(&PythonQtClassWrapper_Type)
630 0, /*ob_size*/
674 0, /*ob_size*/
631 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
675 "PythonQt.PythonQtInstanceWrapper", /*tp_name*/
632 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
676 sizeof(PythonQtInstanceWrapper), /*tp_basicsize*/
633 0, /*tp_itemsize*/
677 0, /*tp_itemsize*/
634 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
678 (destructor)PythonQtInstanceWrapper_dealloc, /*tp_dealloc*/
635 0, /*tp_print*/
679 0, /*tp_print*/
636 0, /*tp_getattr*/
680 0, /*tp_getattr*/
637 0, /*tp_setattr*/
681 0, /*tp_setattr*/
638 PythonQtInstanceWrapper_compare, /*tp_compare*/
682 0, /*tp_compare*/
639 PythonQtInstanceWrapper_repr, /*tp_repr*/
683 PythonQtInstanceWrapper_repr, /*tp_repr*/
640 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
684 &PythonQtInstanceWrapper_as_number, /*tp_as_number*/
641 0, /*tp_as_sequence*/
685 0, /*tp_as_sequence*/
642 0, /*tp_as_mapping*/
686 0, /*tp_as_mapping*/
643 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
687 (hashfunc)PythonQtInstanceWrapper_hash, /*tp_hash */
644 0, /*tp_call*/
688 0, /*tp_call*/
645 PythonQtInstanceWrapper_str, /*tp_str*/
689 PythonQtInstanceWrapper_str, /*tp_str*/
646 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
690 PythonQtInstanceWrapper_getattro, /*tp_getattro*/
647 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
691 PythonQtInstanceWrapper_setattro, /*tp_setattro*/
648 0, /*tp_as_buffer*/
692 0, /*tp_as_buffer*/
649 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
693 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES, /*tp_flags*/
650 "PythonQtInstanceWrapper object", /* tp_doc */
694 "PythonQtInstanceWrapper object", /* tp_doc */
651 0, /* tp_traverse */
695 0, /* tp_traverse */
652 0, /* tp_clear */
696 0, /* tp_clear */
653 0, /* tp_richcompare */
697 (richcmpfunc)PythonQtInstanceWrapper_richcompare, /* tp_richcompare */
654 0, /* tp_weaklistoffset */
698 0, /* tp_weaklistoffset */
655 0, /* tp_iter */
699 0, /* tp_iter */
656 0, /* tp_iternext */
700 0, /* tp_iternext */
657 0, /* tp_methods */
701 0, /* tp_methods */
658 0, /* tp_members */
702 0, /* tp_members */
659 0, /* tp_getset */
703 0, /* tp_getset */
660 0, /* tp_base */
704 0, /* tp_base */
661 0, /* tp_dict */
705 0, /* tp_dict */
662 0, /* tp_descr_get */
706 0, /* tp_descr_get */
663 0, /* tp_descr_set */
707 0, /* tp_descr_set */
664 0, /* tp_dictoffset */
708 0, /* tp_dictoffset */
665 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
709 (initproc)PythonQtInstanceWrapper_init, /* tp_init */
666 0, /* tp_alloc */
710 0, /* tp_alloc */
667 PythonQtInstanceWrapper_new, /* tp_new */
711 PythonQtInstanceWrapper_new, /* tp_new */
668 };
712 };
669
713
670 //-------------------------------------------------------
714 //-------------------------------------------------------
671
715
General Comments 0
You need to be logged in to leave comments. Login now