@@ -1,297 +1,303 | |||
|
1 | 1 | /**************************************************************************** |
|
2 | 2 | ** |
|
3 | 3 | ** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 | 4 | ** All rights reserved. |
|
5 | 5 | ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 | 6 | ** |
|
7 | 7 | ** This file is part of the Qt Script Generator project on Qt Labs. |
|
8 | 8 | ** |
|
9 | 9 | ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 | 10 | ** No Commercial Usage |
|
11 | 11 | ** This file contains pre-release code and may not be distributed. |
|
12 | 12 | ** You may use this file in accordance with the terms and conditions |
|
13 | 13 | ** contained in the Technology Preview License Agreement accompanying |
|
14 | 14 | ** this package. |
|
15 | 15 | ** |
|
16 | 16 | ** GNU Lesser General Public License Usage |
|
17 | 17 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 | 18 | ** General Public License version 2.1 as published by the Free Software |
|
19 | 19 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 | 20 | ** packaging of this file. Please review the following information to |
|
21 | 21 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 | 22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 | 23 | ** |
|
24 | 24 | ** In addition, as a special exception, Nokia gives you certain additional |
|
25 | 25 | ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 | 26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 | 27 | ** |
|
28 | 28 | ** If you have questions regarding the use of this file, please contact |
|
29 | 29 | ** Nokia at qt-info@nokia.com. |
|
30 | 30 | ** |
|
31 | 31 | ** |
|
32 | 32 | ** |
|
33 | 33 | ** |
|
34 | 34 | ** |
|
35 | 35 | ** |
|
36 | 36 | ** |
|
37 | 37 | ** |
|
38 | 38 | ** $QT_END_LICENSE$ |
|
39 | 39 | ** |
|
40 | 40 | ****************************************************************************/ |
|
41 | 41 | |
|
42 | 42 | #include "setupgenerator.h" |
|
43 | 43 | #include "shellgenerator.h" |
|
44 | 44 | #include "reporthandler.h" |
|
45 | 45 | #include "fileout.h" |
|
46 | 46 | |
|
47 | 47 | //#define Q_SCRIPT_LAZY_GENERATOR |
|
48 | 48 | |
|
49 | 49 | void SetupGenerator::addClass(const QString& package, const AbstractMetaClass *cls) |
|
50 | 50 | { |
|
51 | 51 | packHash[package].append(cls); |
|
52 | 52 | } |
|
53 | 53 | |
|
54 | 54 | void maybeDeclareMetaType(QTextStream &stream, const QString &typeName, |
|
55 | 55 | QSet<QString> ®isteredTypeNames); |
|
56 | 56 | bool hasDefaultConstructor(const AbstractMetaClass *meta_class); |
|
57 | 57 | |
|
58 | 58 | static QStringList getOperatorCodes(const AbstractMetaClass* cls) { |
|
59 | 59 | QSet<QString> operatorCodes; |
|
60 | 60 | AbstractMetaFunctionList returned; |
|
61 | 61 | AbstractMetaFunctionList functions = cls->functions(); |
|
62 | 62 | foreach (AbstractMetaFunction *function, functions) { |
|
63 | 63 | if (function->originalName().startsWith("operator")) { |
|
64 | 64 | QString op = function->originalName().mid(8); |
|
65 | 65 | operatorCodes.insert(op); |
|
66 | 66 | } |
|
67 | 67 | } |
|
68 | 68 | QSet<QString> r; |
|
69 | 69 | foreach(QString op, operatorCodes.toList()) { |
|
70 | 70 | if (op == ">" || op == "<" || op == ">=" || op == "<=" || op == "==" || op == "!=") { |
|
71 | 71 | r.insert("PythonQt::Type_RichCompare"); |
|
72 | 72 | } else if (op == "+") { |
|
73 | 73 | r.insert("PythonQt::Type_Add"); |
|
74 | 74 | } else if (op == "-") { |
|
75 | 75 | r.insert("PythonQt::Type_Subtract"); |
|
76 | 76 | } else if (op == "/") { |
|
77 | 77 | r.insert("PythonQt::Type_Divide"); |
|
78 | 78 | } else if (op == "*") { |
|
79 | 79 | r.insert("PythonQt::Type_Multiply"); |
|
80 | 80 | } else if (op == "%") { |
|
81 | 81 | r.insert("PythonQt::Type_Mod"); |
|
82 | 82 | } else if (op == "&") { |
|
83 | 83 | r.insert("PythonQt::Type_And"); |
|
84 | 84 | } else if (op == "|") { |
|
85 | 85 | r.insert("PythonQt::Type_Or"); |
|
86 | 86 | } else if (op == "^") { |
|
87 | 87 | r.insert("PythonQt::Type_Xor"); |
|
88 | 88 | } else if (op == "~") { |
|
89 | 89 | r.insert("PythonQt::Type_Invert"); |
|
90 | 90 | |
|
91 | 91 | } else if (op == "+=") { |
|
92 | 92 | r.insert("PythonQt::Type_InplaceAdd"); |
|
93 | 93 | } else if (op == "-=") { |
|
94 | 94 | r.insert("PythonQt::Type_InplaceSubtract"); |
|
95 | 95 | } else if (op == "/=") { |
|
96 | 96 | r.insert("PythonQt::Type_InplaceDivide"); |
|
97 | 97 | } else if (op == "*=") { |
|
98 | 98 | r.insert("PythonQt::Type_InplaceMultiply"); |
|
99 | 99 | } else if (op == "%=") { |
|
100 | 100 | r.insert("PythonQt::Type_InplaceMod"); |
|
101 | 101 | } else if (op == "&=") { |
|
102 | 102 | r.insert("PythonQt::Type_InplaceAnd"); |
|
103 | 103 | } else if (op == "|=") { |
|
104 | 104 | r.insert("PythonQt::Type_InplaceOr"); |
|
105 | 105 | } else if (op == "^=") { |
|
106 | 106 | r.insert("PythonQt::Type_InplaceXor"); |
|
107 | 107 | } |
|
108 | 108 | } |
|
109 | 109 | if (cls->hasDefaultIsNull()) { |
|
110 | 110 | r.insert("PythonQt::Type_NonZero"); |
|
111 | 111 | } |
|
112 | 112 | QStringList result = r.toList(); |
|
113 | 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 | 121 | void SetupGenerator::generate() |
|
117 | 122 | { |
|
118 | 123 | AbstractMetaClassList classes_with_polymorphic_id; |
|
119 | 124 | { |
|
120 | 125 | QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash); |
|
121 | 126 | while (pack.hasNext()) { |
|
122 | 127 | pack.next(); |
|
123 | 128 | QList<const AbstractMetaClass*> list = pack.value(); |
|
124 | 129 | foreach (const AbstractMetaClass *cls, list) { |
|
125 | 130 | if (cls->typeEntry()->isPolymorphicBase()) { |
|
126 | 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 | 138 | QHashIterator<QString, QList<const AbstractMetaClass*> > pack(packHash); |
|
133 | 139 | while (pack.hasNext()) { |
|
134 | 140 | pack.next(); |
|
135 | 141 | QList<const AbstractMetaClass*> list = pack.value(); |
|
136 | 142 | if (list.isEmpty()) |
|
137 | 143 | continue; |
|
144 | qSort(list.begin(), list.end(), class_less_than); | |
|
138 | 145 | |
|
139 | 146 | QString packKey = pack.key(); |
|
140 | 147 | QString packName = pack.key(); |
|
141 | 148 | QStringList components = packName.split("_"); |
|
142 | 149 | if ((components.size() > 2) && (components.at(0) == "com") |
|
143 | 150 | && (components.at(1) == "trolltech")) { |
|
144 | 151 | // kill com.trolltech in key |
|
145 | 152 | components.removeAt(0); |
|
146 | 153 | components.removeAt(0); |
|
147 | 154 | } |
|
148 | 155 | |
|
149 | 156 | QString shortPackName; |
|
150 | 157 | foreach (QString comp, components) { |
|
151 | 158 | comp[0] = comp[0].toUpper(); |
|
152 | 159 | shortPackName += comp; |
|
153 | 160 | } |
|
154 | 161 | // add missing camel case (workaround..) |
|
155 | 162 | if (shortPackName == "QtWebkit") { |
|
156 | 163 | shortPackName = "QtWebKit"; |
|
157 | 164 | } else if (shortPackName == "QtXmlpatterns") { |
|
158 | 165 | shortPackName = "QtXmlPatterns"; |
|
159 | 166 | } else if (shortPackName == "QtOpengl") { |
|
160 | 167 | shortPackName = "QtOpenGL"; |
|
161 | 168 | } else if (shortPackName == "QtUitools") { |
|
162 | 169 | shortPackName = "QtUiTools"; |
|
163 | 170 | } |
|
164 | 171 | |
|
165 | 172 | |
|
166 | 173 | { |
|
167 | 174 | FileOut initFile(m_out_dir + "/generated_cpp/" + packName + "/" + packKey + "_init.cpp"); |
|
168 | 175 | QTextStream &s = initFile.stream; |
|
169 | 176 | |
|
170 | 177 | s << "#include <PythonQt.h>" << endl; |
|
171 | 178 | |
|
172 | 179 | for (int i=0; i<(list.count()+MAX_CLASSES_PER_FILE-1) / MAX_CLASSES_PER_FILE; i++) { |
|
173 | 180 | s << "#include \"" << packKey << QString::number(i) << ".h\"" << endl; |
|
174 | 181 | } |
|
175 | 182 | s << endl; |
|
176 | 183 | |
|
177 | 184 | QStringList polymorphicHandlers; |
|
178 | 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 | 187 | s << endl; |
|
181 | 188 | } |
|
182 | 189 | |
|
183 | 190 | // declare individual class creation functions |
|
184 | 191 | s << "void PythonQt_init_" << shortPackName << "(PyObject* module) {" << endl; |
|
185 | 192 | |
|
186 | 193 | if (shortPackName.endsWith("Builtin")) { |
|
187 | 194 | shortPackName = shortPackName.mid(0, shortPackName.length()-strlen("builtin")); |
|
188 | 195 | } |
|
189 | 196 | |
|
190 | 197 | QStringList cppClassNames; |
|
191 | 198 | foreach (const AbstractMetaClass *cls, list) { |
|
192 | 199 | |
|
193 | 200 | QString shellCreator; |
|
194 | 201 | if (cls->generateShellClass()) { |
|
195 | 202 | shellCreator = ", PythonQtSetInstanceWrapperOnShell<" + ShellGenerator::shellClassName(cls) + ">"; |
|
196 | 203 | } else { |
|
197 | 204 | shellCreator = ", NULL"; |
|
198 | 205 | } |
|
199 | 206 | QString operatorCodes = getOperatorCodes(cls).join("|"); |
|
200 | 207 | if (operatorCodes.isEmpty()) { |
|
201 | 208 | operatorCodes = "0"; |
|
202 | 209 | } |
|
203 | 210 | if (cls->isQObject()) { |
|
204 | 211 | s << "PythonQt::priv()->registerClass(&" << cls->qualifiedCppName() << "::staticMetaObject, \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl; |
|
205 | 212 | } else { |
|
206 | 213 | QString baseName = cls->baseClass()?cls->baseClass()->qualifiedCppName():""; |
|
207 | 214 | s << "PythonQt::priv()->registerCPPClass(\""<< cls->qualifiedCppName() << "\", \"" << baseName << "\", \"" << shortPackName <<"\", PythonQtCreateObject<PythonQtWrapper_" << cls->name() << ">" << shellCreator << ", module, " << operatorCodes <<");" << endl; |
|
208 | 215 | } |
|
209 | 216 | foreach(AbstractMetaClass* interface, cls->interfaces()) { |
|
210 | 217 | // the interface might be our own class... (e.g. QPaintDevice) |
|
211 | 218 | if (interface->qualifiedCppName() != cls->qualifiedCppName()) { |
|
212 | 219 | s << "PythonQt::self()->addParentClass(\""<< cls->qualifiedCppName() << "\", \"" << interface->qualifiedCppName() << "\",PythonQtUpcastingOffset<" << cls->qualifiedCppName() <<","<<interface->qualifiedCppName()<<">());" << endl; |
|
213 | 220 | } |
|
214 | 221 | } |
|
215 | 222 | } |
|
216 | 223 | s << endl; |
|
217 | 224 | foreach (QString handler, polymorphicHandlers) { |
|
218 | 225 | s << "PythonQt::self()->addPolymorphicHandler(\""<< handler << "\", polymorphichandler_" << handler << ");" << endl; |
|
219 | 226 | } |
|
220 | 227 | |
|
221 | 228 | s << "}"; |
|
222 | 229 | s << endl; |
|
223 | 230 | } |
|
224 | 231 | } |
|
225 | 232 | } |
|
226 | 233 | |
|
227 | 234 | QStringList SetupGenerator::writePolymorphicHandler(QTextStream &s, const QString &package, |
|
228 | const AbstractMetaClassList &classes) | |
|
235 | const AbstractMetaClassList &polybase, QList<const AbstractMetaClass*>& allClasses) | |
|
229 | 236 | { |
|
230 | 237 | QStringList handlers; |
|
231 |
foreach (AbstractMetaClass *cls, |
|
|
238 | foreach (AbstractMetaClass *cls, polybase) { | |
|
232 | 239 | const ComplexTypeEntry *centry = cls->typeEntry(); |
|
233 | 240 | if (!centry->isPolymorphicBase()) |
|
234 | 241 | continue; |
|
235 | 242 | bool isGraphicsItem = (cls->qualifiedCppName()=="QGraphicsItem"); |
|
236 | 243 | |
|
237 | AbstractMetaClassList classList = this->classes(); | |
|
238 | 244 | bool first = true; |
|
239 |
foreach (AbstractMetaClass *clazz, |
|
|
245 | foreach (const AbstractMetaClass *clazz, allClasses) { | |
|
240 | 246 | bool inherits = false; |
|
241 | 247 | if (isGraphicsItem) { |
|
242 | 248 | foreach(AbstractMetaClass* interfaze, clazz->interfaces()) { |
|
243 | 249 | if (interfaze->qualifiedCppName()=="QGraphicsItem") { |
|
244 | 250 | inherits = true; |
|
245 | 251 | break; |
|
246 | 252 | } |
|
247 | 253 | } |
|
248 | 254 | } else { |
|
249 | 255 | inherits = clazz->inheritsFrom(cls); |
|
250 | 256 | } |
|
251 | 257 | if (clazz->package() == package && inherits) { |
|
252 | 258 | if (!clazz->typeEntry()->polymorphicIdValue().isEmpty() || isGraphicsItem) { |
|
253 | 259 | // On first find, open the function |
|
254 | 260 | if (first) { |
|
255 | 261 | first = false; |
|
256 | 262 | |
|
257 | 263 | QString handler = cls->name(); |
|
258 | 264 | handlers.append(handler); |
|
259 | 265 | |
|
260 | 266 | s << "static void* polymorphichandler_" << handler |
|
261 | 267 | << "(const void *ptr, char **class_name)" << endl |
|
262 | 268 | << "{" << endl |
|
263 | 269 | << " Q_ASSERT(ptr != 0);" << endl |
|
264 | 270 | << " " << cls->qualifiedCppName() << " *object = (" |
|
265 | 271 | << cls->qualifiedCppName() << " *)ptr;" << endl; |
|
266 | 272 | } |
|
267 | 273 | |
|
268 | 274 | // For each, add case label |
|
269 | 275 | QString polyId = clazz->typeEntry()->polymorphicIdValue(); |
|
270 | 276 | if (isGraphicsItem) { |
|
271 | 277 | polyId = "%1->type() == " + clazz->qualifiedCppName() + "::Type"; |
|
272 | 278 | } |
|
273 | 279 | s << " if (" |
|
274 | 280 | << polyId.replace("%1", "object") |
|
275 | 281 | << ") {" << endl |
|
276 | 282 | << " *class_name = \"" << clazz->name() << "\";" << endl |
|
277 | 283 | << " return (" << clazz->qualifiedCppName() << "*)object;" << endl |
|
278 | 284 | << " }" << endl; |
|
279 | 285 | } else { |
|
280 | 286 | QString warning = QString("class '%1' inherits from polymorphic class '%2', but has no polymorphic id set") |
|
281 | 287 | .arg(clazz->name()) |
|
282 | 288 | .arg(cls->name()); |
|
283 | 289 | |
|
284 | 290 | ReportHandler::warning(warning); |
|
285 | 291 | } |
|
286 | 292 | } |
|
287 | 293 | } |
|
288 | 294 | |
|
289 | 295 | // Close the function if it has been opened |
|
290 | 296 | if (!first) { |
|
291 | 297 | s << " return NULL;" << endl |
|
292 | 298 | << "}" << endl; |
|
293 | 299 | } |
|
294 | 300 | } |
|
295 | 301 | |
|
296 | 302 | return handlers; |
|
297 | 303 | } |
General Comments 0
You need to be logged in to leave comments.
Login now