##// END OF EJS Templates
added sorting of polymorphic id classes to avoid changes on each code generation...
florianlink -
r131:ed1c6f151a2c
parent child
Show More
@@ -1,297 +1,303
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) {
58 static QStringList getOperatorCodes(const AbstractMetaClass* cls) {
59 QSet<QString> operatorCodes;
59 QSet<QString> operatorCodes;
60 AbstractMetaFunctionList returned;
60 AbstractMetaFunctionList returned;
61 AbstractMetaFunctionList functions = cls->functions();
61 AbstractMetaFunctionList functions = cls->functions();
62 foreach (AbstractMetaFunction *function, functions) {
62 foreach (AbstractMetaFunction *function, functions) {
63 if (function->originalName().startsWith("operator")) {
63 if (function->originalName().startsWith("operator")) {
64 QString op = function->originalName().mid(8);
64 QString op = function->originalName().mid(8);
65 operatorCodes.insert(op);
65 operatorCodes.insert(op);
66 }
66 }
67 }
67 }
68 QSet<QString> r;
68 QSet<QString> r;
69 foreach(QString op, operatorCodes.toList()) {
69 foreach(QString op, operatorCodes.toList()) {
70 if (op == ">" || op == "<" || op == ">=" || op == "<=" || op == "==" || op == "!=") {
70 if (op == ">" || op == "<" || op == ">=" || op == "<=" || op == "==" || op == "!=") {
71 r.insert("PythonQt::Type_RichCompare");
71 r.insert("PythonQt::Type_RichCompare");
72 } else if (op == "+") {
72 } else if (op == "+") {
73 r.insert("PythonQt::Type_Add");
73 r.insert("PythonQt::Type_Add");
74 } else if (op == "-") {
74 } else if (op == "-") {
75 r.insert("PythonQt::Type_Subtract");
75 r.insert("PythonQt::Type_Subtract");
76 } else if (op == "/") {
76 } else if (op == "/") {
77 r.insert("PythonQt::Type_Divide");
77 r.insert("PythonQt::Type_Divide");
78 } else if (op == "*") {
78 } else if (op == "*") {
79 r.insert("PythonQt::Type_Multiply");
79 r.insert("PythonQt::Type_Multiply");
80 } else if (op == "%") {
80 } else if (op == "%") {
81 r.insert("PythonQt::Type_Mod");
81 r.insert("PythonQt::Type_Mod");
82 } else if (op == "&") {
82 } else if (op == "&") {
83 r.insert("PythonQt::Type_And");
83 r.insert("PythonQt::Type_And");
84 } else if (op == "|") {
84 } else if (op == "|") {
85 r.insert("PythonQt::Type_Or");
85 r.insert("PythonQt::Type_Or");
86 } else if (op == "^") {
86 } else if (op == "^") {
87 r.insert("PythonQt::Type_Xor");
87 r.insert("PythonQt::Type_Xor");
88 } else if (op == "~") {
88 } else if (op == "~") {
89 r.insert("PythonQt::Type_Invert");
89 r.insert("PythonQt::Type_Invert");
90
90
91 } else if (op == "+=") {
91 } else if (op == "+=") {
92 r.insert("PythonQt::Type_InplaceAdd");
92 r.insert("PythonQt::Type_InplaceAdd");
93 } else if (op == "-=") {
93 } else if (op == "-=") {
94 r.insert("PythonQt::Type_InplaceSubtract");
94 r.insert("PythonQt::Type_InplaceSubtract");
95 } else if (op == "/=") {
95 } else if (op == "/=") {
96 r.insert("PythonQt::Type_InplaceDivide");
96 r.insert("PythonQt::Type_InplaceDivide");
97 } else if (op == "*=") {
97 } else if (op == "*=") {
98 r.insert("PythonQt::Type_InplaceMultiply");
98 r.insert("PythonQt::Type_InplaceMultiply");
99 } else if (op == "%=") {
99 } else if (op == "%=") {
100 r.insert("PythonQt::Type_InplaceMod");
100 r.insert("PythonQt::Type_InplaceMod");
101 } else if (op == "&=") {
101 } else if (op == "&=") {
102 r.insert("PythonQt::Type_InplaceAnd");
102 r.insert("PythonQt::Type_InplaceAnd");
103 } else if (op == "|=") {
103 } else if (op == "|=") {
104 r.insert("PythonQt::Type_InplaceOr");
104 r.insert("PythonQt::Type_InplaceOr");
105 } else if (op == "^=") {
105 } else if (op == "^=") {
106 r.insert("PythonQt::Type_InplaceXor");
106 r.insert("PythonQt::Type_InplaceXor");
107 }
107 }
108 }
108 }
109 if (cls->hasDefaultIsNull()) {
109 if (cls->hasDefaultIsNull()) {
110 r.insert("PythonQt::Type_NonZero");
110 r.insert("PythonQt::Type_NonZero");
111 }
111 }
112 QStringList result = r.toList();
112 QStringList result = r.toList();
113 return result;
113 return result;
114 }
114 }
115
115
116 static bool class_less_than(const AbstractMetaClass *a, const AbstractMetaClass *b)
117 {
118 return a->name() < b->name();
119 }
120
116 void SetupGenerator::generate()
121 void SetupGenerator::generate()
117 {
122 {
118 AbstractMetaClassList classes_with_polymorphic_id;
123 AbstractMetaClassList classes_with_polymorphic_id;
119 {
124 {
120 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
125 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
121 while (pack.hasNext()) {
126 while (pack.hasNext()) {
122 pack.next();
127 pack.next();
123 QList<const AbstractMetaClass*> list = pack.value();
128 QList<const AbstractMetaClass*> list = pack.value();
124 foreach (const AbstractMetaClass *cls, list) {
129 foreach (const AbstractMetaClass *cls, list) {
125 if (cls->typeEntry()->isPolymorphicBase()) {
130 if (cls->typeEntry()->isPolymorphicBase()) {
126 classes_with_polymorphic_id.append((AbstractMetaClass*)cls);
131 classes_with_polymorphic_id.append((AbstractMetaClass*)cls);
127 }
132 }
128 }
133 }
129 }
134 }
130 }
135 }
136 qSort(classes_with_polymorphic_id.begin(), classes_with_polymorphic_id.end(), class_less_than);
131
137
132 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
138 QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash);
133 while (pack.hasNext()) {
139 while (pack.hasNext()) {
134 pack.next();
140 pack.next();
135 QList<const AbstractMetaClass*> list = pack.value();
141 QList<const AbstractMetaClass*> list = pack.value();
136 if (list.isEmpty())
142 if (list.isEmpty())
137 continue;
143 continue;
144 qSort(list.begin(), list.end(), class_less_than);
138
145
139 QString packKey = pack.key();
146 QString packKey = pack.key();
140 QString packName = pack.key();
147 QString packName = pack.key();
141 QStringList components = packName.split("_");
148 QStringList components = packName.split("_");
142 if ((components.size() > 2) && (components.at(0) == "com")
149 if ((components.size() > 2) && (components.at(0) == "com")
143 && (components.at(1) == "trolltech")) {
150 && (components.at(1) == "trolltech")) {
144 // kill com.trolltech in key
151 // kill com.trolltech in key
145 components.removeAt(0);
152 components.removeAt(0);
146 components.removeAt(0);
153 components.removeAt(0);
147 }
154 }
148
155
149 QString shortPackName;
156 QString shortPackName;
150 foreach (QString comp, components) {
157 foreach (QString comp, components) {
151 comp[0] = comp[0].toUpper();
158 comp[0] = comp[0].toUpper();
152 shortPackName += comp;
159 shortPackName += comp;
153 }
160 }
154 // add missing camel case (workaround..)
161 // add missing camel case (workaround..)
155 if (shortPackName == "QtWebkit") {
162 if (shortPackName == "QtWebkit") {
156 shortPackName = "QtWebKit";
163 shortPackName = "QtWebKit";
157 } else if (shortPackName == "QtXmlpatterns") {
164 } else if (shortPackName == "QtXmlpatterns") {
158 shortPackName = "QtXmlPatterns";
165 shortPackName = "QtXmlPatterns";
159 } else if (shortPackName == "QtOpengl") {
166 } else if (shortPackName == "QtOpengl") {
160 shortPackName = "QtOpenGL";
167 shortPackName = "QtOpenGL";
161 } else if (shortPackName == "QtUitools") {
168 } else if (shortPackName == "QtUitools") {
162 shortPackName = "QtUiTools";
169 shortPackName = "QtUiTools";
163 }
170 }
164
171
165
172
166 {
173 {
167 FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp");
174 FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp");
168 QTextStream &s = initFile.stream;
175 QTextStream &s = initFile.stream;
169
176
170 s << "#include <PythonQt.h>" << endl;
177 s << "#include <PythonQt.h>" << endl;
171
178
172 for (int i=0; i<(list.count()+MAX_CLASSES_PER_FILE-1) / MAX_CLASSES_PER_FILE; i++) {
179 for (int i=0; i<(list.count()+MAX_CLASSES_PER_FILE-1) / MAX_CLASSES_PER_FILE; i++) {
173 s << "#include \"" << packKey << QString::number(i) << ".h\"" << endl;
180 s << "#include \"" << packKey << QString::number(i) << ".h\"" << endl;
174 }
181 }
175 s << endl;
182 s << endl;
176
183
177 QStringList polymorphicHandlers;
184 QStringList polymorphicHandlers;
178 if (!packName.endsWith("_builtin")) {
185 if (!packName.endsWith("_builtin")) {
179 polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id);
186 polymorphicHandlers = writePolymorphicHandler(s, list.at(0)->package(), classes_with_polymorphic_id, list);
180 s << endl;
187 s << endl;
181 }
188 }
182
189
183 // declare individual class creation functions
190 // declare individual class creation functions
184 s << "void PythonQt_init_" << shortPackName << "(PyObject* module) {" << endl;
191 s << "void PythonQt_init_" << shortPackName << "(PyObject* module) {" << endl;
185
192
186 if (shortPackName.endsWith("Builtin")) {
193 if (shortPackName.endsWith("Builtin")) {
187 shortPackName = shortPackName.mid(0, shortPackName.length()-strlen("builtin"));
194 shortPackName = shortPackName.mid(0, shortPackName.length()-strlen("builtin"));
188 }
195 }
189
196
190 QStringList cppClassNames;
197 QStringList cppClassNames;
191 foreach (const AbstractMetaClass *cls, list) {
198 foreach (const AbstractMetaClass *cls, list) {
192
199
193 QString shellCreator;
200 QString shellCreator;
194 if (cls->generateShellClass()) {
201 if (cls->generateShellClass()) {
195 shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">";
202 shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">";
196 } else {
203 } else {
197 shellCreator = ", NULL";
204 shellCreator = ", NULL";
198 }
205 }
199 QString operatorCodes = getOperatorCodes(cls).join("|");
206 QString operatorCodes = getOperatorCodes(cls).join("|");
200 if (operatorCodes.isEmpty()) {
207 if (operatorCodes.isEmpty()) {
201 operatorCodes = "0";
208 operatorCodes = "0";
202 }
209 }
203 if (cls->isQObject()) {
210 if (cls->isQObject()) {
204 s << "PythonQt::priv()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl;
211 s << "PythonQt::priv()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl;
205 } else {
212 } else {
206 QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():"";
213 QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():"";
207 s << "PythonQt::priv()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl;
214 s << "PythonQt::priv()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl;
208 }
215 }
209 foreach(AbstractMetaClass* interface, cls->interfaces()) {
216 foreach(AbstractMetaClass* interface, cls->interfaces()) {
210 // the interface might be our own class... (e.g. QPaintDevice)
217 // the interface might be our own class... (e.g. QPaintDevice)
211 if (interface->qualifiedCppName() != cls->qualifiedCppName()) {
218 if (interface->qualifiedCppName() != cls->qualifiedCppName()) {
212 s << "PythonQt::self()->addParentClass(\""<< cls->qualifiedCppName() << "\", \"" << interface->qualifiedCppName() << "\",PythonQtUpcastingOffset<" << cls->qualifiedCppName() <<","<<interface->qualifiedCppName()<<">());" << endl;
219 s << "PythonQt::self()->addParentClass(\""<< cls->qualifiedCppName() << "\", \"" << interface->qualifiedCppName() << "\",PythonQtUpcastingOffset<" << cls->qualifiedCppName() <<","<<interface->qualifiedCppName()<<">());" << endl;
213 }
220 }
214 }
221 }
215 }
222 }
216 s << endl;
223 s << endl;
217 foreach (QString handler, polymorphicHandlers) {
224 foreach (QString handler, polymorphicHandlers) {
218 s << "PythonQt::self()->addPolymorphicHandler(\""<< handler << "\", polymorphichandler_" << handler << ");" << endl;
225 s << "PythonQt::self()->addPolymorphicHandler(\""<< handler << "\", polymorphichandler_" << handler << ");" << endl;
219 }
226 }
220
227
221 s << "}";
228 s << "}";
222 s << endl;
229 s << endl;
223 }
230 }
224 }
231 }
225 }
232 }
226
233
227 QStringList SetupGenerator::writePolymorphicHandler(QTextStream &s, const QString &package,
234 QStringList SetupGenerator::writePolymorphicHandler(QTextStream &s, const QString &package,
228 const AbstractMetaClassList &classes)
235 const AbstractMetaClassList &polybase, QList<const AbstractMetaClass*>& allClasses)
229 {
236 {
230 QStringList handlers;
237 QStringList handlers;
231 foreach (AbstractMetaClass *cls, classes) {
238 foreach (AbstractMetaClass *cls, polybase) {
232 const ComplexTypeEntry *centry = cls->typeEntry();
239 const ComplexTypeEntry *centry = cls->typeEntry();
233 if (!centry->isPolymorphicBase())
240 if (!centry->isPolymorphicBase())
234 continue;
241 continue;
235 bool isGraphicsItem = (cls->qualifiedCppName()=="QGraphicsItem");
242 bool isGraphicsItem = (cls->qualifiedCppName()=="QGraphicsItem");
236
243
237 AbstractMetaClassList classList = this->classes();
238 bool first = true;
244 bool first = true;
239 foreach (AbstractMetaClass *clazz, classList) {
245 foreach (const AbstractMetaClass *clazz, allClasses) {
240 bool inherits = false;
246 bool inherits = false;
241 if (isGraphicsItem) {
247 if (isGraphicsItem) {
242 foreach(AbstractMetaClass* interfaze, clazz->interfaces()) {
248 foreach(AbstractMetaClass* interfaze, clazz->interfaces()) {
243 if (interfaze->qualifiedCppName()=="QGraphicsItem") {
249 if (interfaze->qualifiedCppName()=="QGraphicsItem") {
244 inherits = true;
250 inherits = true;
245 break;
251 break;
246 }
252 }
247 }
253 }
248 } else {
254 } else {
249 inherits = clazz->inheritsFrom(cls);
255 inherits = clazz->inheritsFrom(cls);
250 }
256 }
251 if (clazz->package() == package && inherits) {
257 if (clazz->package() == package && inherits) {
252 if (!clazz->typeEntry()->polymorphicIdValue().isEmpty() || isGraphicsItem) {
258 if (!clazz->typeEntry()->polymorphicIdValue().isEmpty() || isGraphicsItem) {
253 // On first find, open the function
259 // On first find, open the function
254 if (first) {
260 if (first) {
255 first = false;
261 first = false;
256
262
257 QString handler = cls->name();
263 QString handler = cls->name();
258 handlers.append(handler);
264 handlers.append(handler);
259
265
260 s << "static void* polymorphichandler_" << handler
266 s << "static void* polymorphichandler_" << handler
261 << "(const void *ptr, char **class_name)" << endl
267 << "(const void *ptr, char **class_name)" << endl
262 << "{" << endl
268 << "{" << endl
263 << " Q_ASSERT(ptr != 0);" << endl
269 << " Q_ASSERT(ptr != 0);" << endl
264 << " " << cls->qualifiedCppName() << " *object = ("
270 << " " << cls->qualifiedCppName() << " *object = ("
265 << cls->qualifiedCppName() << " *)ptr;" << endl;
271 << cls->qualifiedCppName() << " *)ptr;" << endl;
266 }
272 }
267
273
268 // For each, add case label
274 // For each, add case label
269 QString polyId = clazz->typeEntry()->polymorphicIdValue();
275 QString polyId = clazz->typeEntry()->polymorphicIdValue();
270 if (isGraphicsItem) {
276 if (isGraphicsItem) {
271 polyId = "%1->type() == " + clazz->qualifiedCppName() + "::Type";
277 polyId = "%1->type() == " + clazz->qualifiedCppName() + "::Type";
272 }
278 }
273 s << " if ("
279 s << " if ("
274 << polyId.replace("%1", "object")
280 << polyId.replace("%1", "object")
275 << ") {" << endl
281 << ") {" << endl
276 << " *class_name = \"" << clazz->name() << "\";" << endl
282 << " *class_name = \"" << clazz->name() << "\";" << endl
277 << " return (" << clazz->qualifiedCppName() << "*)object;" << endl
283 << " return (" << clazz->qualifiedCppName() << "*)object;" << endl
278 << " }" << endl;
284 << " }" << endl;
279 } else {
285 } else {
280 QString warning = QString("class '%1' inherits from polymorphic class '%2', but has no polymorphic id set")
286 QString warning = QString("class '%1' inherits from polymorphic class '%2', but has no polymorphic id set")
281 .arg(clazz->name())
287 .arg(clazz->name())
282 .arg(cls->name());
288 .arg(cls->name());
283
289
284 ReportHandler::warning(warning);
290 ReportHandler::warning(warning);
285 }
291 }
286 }
292 }
287 }
293 }
288
294
289 // Close the function if it has been opened
295 // Close the function if it has been opened
290 if (!first) {
296 if (!first) {
291 s << " return NULL;" << endl
297 s << " return NULL;" << endl
292 << "}" << endl;
298 << "}" << endl;
293 }
299 }
294 }
300 }
295
301
296 return handlers;
302 return handlers;
297 }
303 }
General Comments 0
You need to be logged in to leave comments. Login now