|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the tools applications of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
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 |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
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 |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
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. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
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. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "ui3reader.h" |
|
43 #include "parser.h" |
|
44 #include "domtool.h" |
|
45 #include "globaldefs.h" |
|
46 |
|
47 // uic4 |
|
48 #include "uic.h" |
|
49 #include "ui4.h" |
|
50 #include "driver.h" |
|
51 #include "option.h" |
|
52 |
|
53 #include <QStringList> |
|
54 #include <QFile> |
|
55 #include <QFileInfo> |
|
56 #include <QDir> |
|
57 #include <QRegExp> |
|
58 #include <QtDebug> |
|
59 |
|
60 QT_BEGIN_NAMESPACE |
|
61 |
|
62 QByteArray combinePath(const char *infile, const char *outfile) |
|
63 { |
|
64 QFileInfo inFileInfo(QDir::current(), QFile::decodeName(infile)); |
|
65 QFileInfo outFileInfo(QDir::current(), QFile::decodeName(outfile)); |
|
66 int numCommonComponents = 0; |
|
67 |
|
68 QStringList inSplitted = inFileInfo.dir().canonicalPath().split(QLatin1Char('/')); |
|
69 QStringList outSplitted = outFileInfo.dir().canonicalPath().split(QLatin1Char('/')); |
|
70 |
|
71 while (!inSplitted.isEmpty() && !outSplitted.isEmpty() && |
|
72 inSplitted.first() == outSplitted.first()) { |
|
73 inSplitted.erase(inSplitted.begin()); |
|
74 outSplitted.erase(outSplitted.begin()); |
|
75 numCommonComponents++; |
|
76 } |
|
77 |
|
78 if (numCommonComponents < 2) { |
|
79 /* |
|
80 The paths don't have the same drive, or they don't have the |
|
81 same root directory. Use an absolute path. |
|
82 */ |
|
83 return QFile::encodeName(inFileInfo.absoluteFilePath()); |
|
84 } else { |
|
85 /* |
|
86 The paths have something in common. Use a path relative to |
|
87 the output file. |
|
88 */ |
|
89 while (!outSplitted.isEmpty()) { |
|
90 outSplitted.erase(outSplitted.begin()); |
|
91 inSplitted.prepend(QLatin1String("..")); |
|
92 } |
|
93 inSplitted.append(inFileInfo.fileName()); |
|
94 return QFile::encodeName(inSplitted.join(QLatin1String("/"))); |
|
95 } |
|
96 } |
|
97 |
|
98 /*! |
|
99 Creates a declaration (header file) for the form given in \a e |
|
100 |
|
101 \sa createFormImpl() |
|
102 */ |
|
103 void Ui3Reader::createFormDecl(const QDomElement &e, bool implicitIncludes) |
|
104 { |
|
105 QDomElement body = e; |
|
106 |
|
107 QDomElement n; |
|
108 QDomNodeList nl; |
|
109 int i; |
|
110 QString objClass = getClassName(e); |
|
111 if (objClass.isEmpty()) |
|
112 return; |
|
113 QString objName = getObjectName(e); |
|
114 |
|
115 QStringList typeDefs; |
|
116 |
|
117 QMap<QString, CustomInclude> customWidgetIncludes; |
|
118 |
|
119 /* |
|
120 We are generating a few QImage members that are not strictly |
|
121 necessary in some cases. Ideally, we would use requiredImage, |
|
122 which is computed elsewhere, to keep the generated .h and .cpp |
|
123 files synchronized. |
|
124 */ |
|
125 |
|
126 // at first the images |
|
127 QMap<QString, int> customWidgets; |
|
128 QStringList forwardDecl; |
|
129 QStringList forwardDecl2; |
|
130 for (n = e; !n.isNull(); n = n.nextSibling().toElement()) { |
|
131 if (n.tagName().toLower() == QLatin1String("customwidgets")) { |
|
132 QDomElement n2 = n.firstChild().toElement(); |
|
133 while (!n2.isNull()) { |
|
134 if (n2.tagName().toLower() == QLatin1String("customwidget")) { |
|
135 QDomElement n3 = n2.firstChild().toElement(); |
|
136 QString cl; |
|
137 while (!n3.isNull()) { |
|
138 QString tagName = n3.tagName().toLower(); |
|
139 if (tagName == QLatin1String("class")) { |
|
140 cl = n3.firstChild().toText().data(); |
|
141 if (!nofwd) |
|
142 forwardDecl << cl; |
|
143 customWidgets.insert(cl, 0); |
|
144 } else if (tagName == QLatin1String("header")) { |
|
145 CustomInclude ci; |
|
146 ci.header = n3.firstChild().toText().data(); |
|
147 ci.location = n3.attribute(QLatin1String("location"), QLatin1String("global")); |
|
148 if (!ci.header.isEmpty()) |
|
149 forwardDecl.removeAll(cl); |
|
150 customWidgetIncludes.insert(cl, ci); |
|
151 } |
|
152 n3 = n3.nextSibling().toElement(); |
|
153 } |
|
154 } |
|
155 n2 = n2.nextSibling().toElement(); |
|
156 } |
|
157 } |
|
158 } |
|
159 |
|
160 // register the object and unify its name |
|
161 objName = registerObject(objName); |
|
162 QString protector = objName.toUpper() + QLatin1String("_H"); |
|
163 protector.replace(QLatin1String("::"), QLatin1String("_")); |
|
164 out << "#ifndef " << protector << endl; |
|
165 out << "#define " << protector << endl; |
|
166 out << endl; |
|
167 |
|
168 out << "#include <qvariant.h>" << endl; // for broken HP-UX compilers |
|
169 |
|
170 QStringList globalIncludes, localIncludes; |
|
171 |
|
172 { |
|
173 QMap<QString, CustomInclude>::Iterator it = customWidgetIncludes.find(objClass); |
|
174 if (it != customWidgetIncludes.end()) { |
|
175 if ((*it).location == QLatin1String("global")) |
|
176 globalIncludes += (*it).header; |
|
177 else |
|
178 localIncludes += (*it).header; |
|
179 } |
|
180 } |
|
181 |
|
182 QStringList::ConstIterator it; |
|
183 |
|
184 globalIncludes = unique(globalIncludes); |
|
185 for (it = globalIncludes.constBegin(); it != globalIncludes.constEnd(); ++it) { |
|
186 if (!(*it).isEmpty()) { |
|
187 QString header = fixHeaderName(*it); |
|
188 out << "#include <" << header << '>' << endl; |
|
189 } |
|
190 } |
|
191 localIncludes = unique(localIncludes); |
|
192 for (it = localIncludes.constBegin(); it != localIncludes.constEnd(); ++it) { |
|
193 if (!(*it).isEmpty()) { |
|
194 QString header = fixHeaderName(*it); |
|
195 out << "#include \"" << header << '\"' << endl; |
|
196 } |
|
197 } |
|
198 out << endl; |
|
199 |
|
200 bool dbForm = false; |
|
201 registerDatabases(e); |
|
202 dbConnections = unique(dbConnections); |
|
203 if (dbForms[QLatin1String("(default)")].count()) |
|
204 dbForm = true; |
|
205 bool subDbForms = false; |
|
206 for (it = dbConnections.constBegin(); it != dbConnections.constEnd(); ++it) { |
|
207 if (!(*it).isEmpty() && (*it) != QLatin1String("(default)")) { |
|
208 if (dbForms[(*it)].count()) { |
|
209 subDbForms = true; |
|
210 break; |
|
211 } |
|
212 } |
|
213 } |
|
214 |
|
215 // some typedefs, maybe |
|
216 typeDefs = unique(typeDefs); |
|
217 for (it = typeDefs.constBegin(); it != typeDefs.constEnd(); ++it) { |
|
218 if (!(*it).isEmpty()) |
|
219 out << "typedef " << *it << ';' << endl; |
|
220 } |
|
221 |
|
222 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("forward")); |
|
223 for (i = 0; i < (int) nl.length(); i++) |
|
224 forwardDecl2 << fixDeclaration(nl.item(i).toElement().firstChild().toText().data()); |
|
225 |
|
226 forwardDecl = unique(forwardDecl); |
|
227 for (it = forwardDecl.constBegin(); it != forwardDecl.constEnd(); ++it) { |
|
228 if (!(*it).isEmpty() && (*it) != objClass) { |
|
229 QString forwardName = *it; |
|
230 QStringList forwardNamespaces = forwardName.split(QLatin1String("::")); |
|
231 forwardName = forwardNamespaces.last(); |
|
232 forwardNamespaces.removeAt(forwardNamespaces.size()-1); |
|
233 |
|
234 QStringList::ConstIterator ns = forwardNamespaces.constBegin(); |
|
235 while (ns != forwardNamespaces.constEnd()) { |
|
236 out << "namespace " << *ns << " {" << endl; |
|
237 ++ns; |
|
238 } |
|
239 out << "class " << forwardName << ';' << endl; |
|
240 for (int i = 0; i < (int) forwardNamespaces.count(); i++) |
|
241 out << '}' << endl; |
|
242 } |
|
243 } |
|
244 |
|
245 for (it = forwardDecl2.constBegin(); it != forwardDecl2.constEnd(); ++it) { |
|
246 QString fd = *it; |
|
247 fd = fd.trimmed(); |
|
248 if (!fd.endsWith(QLatin1Char(';'))) |
|
249 fd += QLatin1Char(';'); |
|
250 out << fd << endl; |
|
251 } |
|
252 |
|
253 out << endl; |
|
254 |
|
255 Driver d; |
|
256 d.option().headerProtection = false; |
|
257 d.option().copyrightHeader = false; |
|
258 d.option().extractImages = m_extractImages; |
|
259 d.option().qrcOutputFile = m_qrcOutputFile; |
|
260 d.option().implicitIncludes = implicitIncludes; |
|
261 if (trmacro.size()) |
|
262 d.option().translateFunction = trmacro; |
|
263 DomUI *ui = generateUi4(e, implicitIncludes); |
|
264 d.uic(fileName, ui, &out); |
|
265 delete ui; |
|
266 |
|
267 createWrapperDeclContents(e); |
|
268 |
|
269 out << "#endif // " << protector << endl; |
|
270 } |
|
271 |
|
272 void Ui3Reader::createWrapperDecl(const QDomElement &e, const QString &convertedUiFile) |
|
273 { |
|
274 QString objName = getObjectName(e); |
|
275 |
|
276 objName = registerObject(objName); |
|
277 QString protector = objName.toUpper() + QLatin1String("_H"); |
|
278 protector.replace(QLatin1String("::"), QLatin1String("_")); |
|
279 out << "#ifndef " << protector << endl; |
|
280 out << "#define " << protector << endl; |
|
281 out << endl; |
|
282 out << "#include \"" << convertedUiFile << '\"' << endl; |
|
283 |
|
284 createWrapperDeclContents(e); |
|
285 out << endl; |
|
286 out << "#endif // " << protector << endl; |
|
287 } |
|
288 |
|
289 void Ui3Reader::createWrapperDeclContents(const QDomElement &e) |
|
290 { |
|
291 QString objClass = getClassName(e); |
|
292 if (objClass.isEmpty()) |
|
293 return; |
|
294 |
|
295 QDomNodeList nl; |
|
296 QString exportMacro; |
|
297 int i; |
|
298 QDomElement n; |
|
299 QStringList::ConstIterator it; |
|
300 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("exportmacro")); |
|
301 if (nl.length() == 1) |
|
302 exportMacro = nl.item(0).firstChild().toText().data(); |
|
303 |
|
304 QStringList::ConstIterator ns = namespaces.constBegin(); |
|
305 while (ns != namespaces.constEnd()) { |
|
306 out << "namespace " << *ns << " {" << endl; |
|
307 ++ns; |
|
308 } |
|
309 |
|
310 out << "class "; |
|
311 if (!exportMacro.isEmpty()) |
|
312 out << exportMacro << ' '; |
|
313 out << bareNameOfClass << " : public " << objClass << ", public Ui::" << bareNameOfClass << endl << '{' << endl; |
|
314 |
|
315 /* qmake ignore Q_OBJECT */ |
|
316 out << " Q_OBJECT" << endl; |
|
317 out << endl; |
|
318 out << "public:" << endl; |
|
319 |
|
320 // constructor |
|
321 if (objClass == QLatin1String("QDialog") || objClass == QLatin1String("QWizard")) { |
|
322 out << " " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0, bool modal = false, Qt::WindowFlags fl = 0);" << endl; |
|
323 } else if (objClass == QLatin1String("QWidget")) { |
|
324 out << " " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = 0);" << endl; |
|
325 } else if (objClass == QLatin1String("QMainWindow") || objClass == QLatin1String("Q3MainWindow")) { |
|
326 out << " " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0, Qt::WindowFlags fl = Qt::WType_TopLevel);" << endl; |
|
327 isMainWindow = true; |
|
328 } else { |
|
329 out << " " << bareNameOfClass << "(QWidget* parent = 0, const char* name = 0);" << endl; |
|
330 } |
|
331 |
|
332 // destructor |
|
333 out << " ~" << bareNameOfClass << "();" << endl; |
|
334 out << endl; |
|
335 |
|
336 // database connections |
|
337 dbConnections = unique(dbConnections); |
|
338 bool hadOutput = false; |
|
339 for (it = dbConnections.constBegin(); it != dbConnections.constEnd(); ++it) { |
|
340 if (!(*it).isEmpty()) { |
|
341 // only need pointers to non-default connections |
|
342 if ((*it) != QLatin1String("(default)") && !(*it).isEmpty()) { |
|
343 out << indent << "QSqlDatabase* " << *it << "Connection;" << endl; |
|
344 hadOutput = true; |
|
345 } |
|
346 } |
|
347 } |
|
348 if (hadOutput) |
|
349 out << endl; |
|
350 |
|
351 QStringList publicSlots, protectedSlots, privateSlots; |
|
352 QStringList publicSlotTypes, protectedSlotTypes, privateSlotTypes; |
|
353 QStringList publicSlotSpecifier, protectedSlotSpecifier, privateSlotSpecifier; |
|
354 |
|
355 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("slot")); |
|
356 for (i = 0; i < (int) nl.length(); i++) { |
|
357 n = nl.item(i).toElement(); |
|
358 if (n.parentNode().toElement().tagName() != QLatin1String("slots") |
|
359 && n.parentNode().toElement().tagName() != QLatin1String("connections")) |
|
360 continue; |
|
361 if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) |
|
362 continue; |
|
363 QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void")); |
|
364 QString functionName = n.firstChild().toText().data().trimmed(); |
|
365 if (functionName.endsWith(QLatin1Char(';'))) |
|
366 functionName.chop(1); |
|
367 QString specifier = n.attribute(QLatin1String("specifier")); |
|
368 QString access = n.attribute(QLatin1String("access")); |
|
369 if (access == QLatin1String(QLatin1String("protected"))) { |
|
370 protectedSlots += functionName; |
|
371 protectedSlotTypes += returnType; |
|
372 protectedSlotSpecifier += specifier; |
|
373 } else if (access == QLatin1String("private")) { |
|
374 privateSlots += functionName; |
|
375 privateSlotTypes += returnType; |
|
376 privateSlotSpecifier += specifier; |
|
377 } else { |
|
378 publicSlots += functionName; |
|
379 publicSlotTypes += returnType; |
|
380 publicSlotSpecifier += specifier; |
|
381 } |
|
382 } |
|
383 |
|
384 QStringList publicFuncts, protectedFuncts, privateFuncts; |
|
385 QStringList publicFunctRetTyp, protectedFunctRetTyp, privateFunctRetTyp; |
|
386 QStringList publicFunctSpec, protectedFunctSpec, privateFunctSpec; |
|
387 |
|
388 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("function")); |
|
389 for (i = 0; i < (int) nl.length(); i++) { |
|
390 n = nl.item(i).toElement(); |
|
391 if (n.parentNode().toElement().tagName() != QLatin1String("functions")) |
|
392 continue; |
|
393 if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) |
|
394 continue; |
|
395 QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void")); |
|
396 QString functionName = n.firstChild().toText().data().trimmed(); |
|
397 if (functionName.endsWith(QLatin1Char(';'))) |
|
398 functionName.chop(1); |
|
399 QString specifier = n.attribute(QLatin1String("specifier")); |
|
400 QString access = n.attribute(QLatin1String("access")); |
|
401 if (access == QLatin1String("protected")) { |
|
402 protectedFuncts += functionName; |
|
403 protectedFunctRetTyp += returnType; |
|
404 protectedFunctSpec += specifier; |
|
405 } else if (access == QLatin1String("private")) { |
|
406 privateFuncts += functionName; |
|
407 privateFunctRetTyp += returnType; |
|
408 privateFunctSpec += specifier; |
|
409 } else { |
|
410 publicFuncts += functionName; |
|
411 publicFunctRetTyp += returnType; |
|
412 publicFunctSpec += specifier; |
|
413 } |
|
414 } |
|
415 |
|
416 QStringList publicVars, protectedVars, privateVars; |
|
417 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("variable")); |
|
418 for (i = 0; i < (int)nl.length(); i++) { |
|
419 n = nl.item(i).toElement(); |
|
420 // Because of compatibility the next lines have to be commented out. |
|
421 // Someday it should be uncommented. |
|
422 //if (n.parentNode().toElement().tagName() != QLatin1String("variables")) |
|
423 // continue; |
|
424 QString access = n.attribute(QLatin1String("access"), QLatin1String("protected")); |
|
425 QString var = fixDeclaration(n.firstChild().toText().data().trimmed()); |
|
426 if (!var.endsWith(QLatin1Char(';'))) |
|
427 var += QLatin1Char(';'); |
|
428 if (access == QLatin1String("public")) |
|
429 publicVars += var; |
|
430 else if (access == QLatin1String("private")) |
|
431 privateVars += var; |
|
432 else |
|
433 protectedVars += var; |
|
434 } |
|
435 |
|
436 if (!publicVars.isEmpty()) { |
|
437 for (it = publicVars.constBegin(); it != publicVars.constEnd(); ++it) |
|
438 out << indent << *it << endl; |
|
439 out << endl; |
|
440 } |
|
441 if (!publicFuncts.isEmpty()) |
|
442 writeFunctionsDecl(publicFuncts, publicFunctRetTyp, publicFunctSpec); |
|
443 |
|
444 if (!publicSlots.isEmpty()) { |
|
445 out << "public slots:" << endl; |
|
446 if (!publicSlots.isEmpty()) |
|
447 writeFunctionsDecl(publicSlots, publicSlotTypes, publicSlotSpecifier); |
|
448 } |
|
449 |
|
450 // find signals |
|
451 QStringList extraSignals; |
|
452 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("signal")); |
|
453 for (i = 0; i < (int) nl.length(); i++) { |
|
454 n = nl.item(i).toElement(); |
|
455 if (n.parentNode().toElement().tagName() != QLatin1String("signals") |
|
456 && n.parentNode().toElement().tagName() != QLatin1String("connections")) |
|
457 continue; |
|
458 if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) |
|
459 continue; |
|
460 QString sigName = n.firstChild().toText().data().trimmed(); |
|
461 if (sigName.endsWith(QLatin1Char(';'))) |
|
462 sigName = sigName.left(sigName.length() - 1); |
|
463 extraSignals += fixDeclaration(sigName); |
|
464 } |
|
465 |
|
466 // create signals |
|
467 if (!extraSignals.isEmpty()) { |
|
468 out << "signals:" << endl; |
|
469 for (it = extraSignals.constBegin(); it != extraSignals.constEnd(); ++it) |
|
470 out << " void " << (*it) << ';' << endl; |
|
471 out << endl; |
|
472 } |
|
473 |
|
474 if (!protectedVars.isEmpty()) { |
|
475 out << "protected:" << endl; |
|
476 for (it = protectedVars.constBegin(); it != protectedVars.constEnd(); ++it) |
|
477 out << indent << *it << endl; |
|
478 out << endl; |
|
479 } |
|
480 |
|
481 if (!protectedFuncts.isEmpty()) { |
|
482 if (protectedVars.isEmpty()) |
|
483 out << "protected:" << endl; |
|
484 |
|
485 writeFunctionsDecl(protectedFuncts, protectedFunctRetTyp, protectedFunctSpec); |
|
486 } |
|
487 |
|
488 out << "protected slots:" << endl; |
|
489 out << " virtual void languageChange();" << endl; |
|
490 |
|
491 if (!protectedSlots.isEmpty()) { |
|
492 out << endl; |
|
493 writeFunctionsDecl(protectedSlots, protectedSlotTypes, protectedSlotSpecifier); |
|
494 } |
|
495 out << endl; |
|
496 |
|
497 // create all private stuff |
|
498 if (!privateFuncts.isEmpty() || !privateVars.isEmpty()) { |
|
499 out << "private:" << endl; |
|
500 if (!privateVars.isEmpty()) { |
|
501 for (it = privateVars.constBegin(); it != privateVars.constEnd(); ++it) |
|
502 out << indent << *it << endl; |
|
503 out << endl; |
|
504 } |
|
505 if (!privateFuncts.isEmpty()) |
|
506 writeFunctionsDecl(privateFuncts, privateFunctRetTyp, privateFunctSpec); |
|
507 } |
|
508 |
|
509 if (!privateSlots.isEmpty()) { |
|
510 out << "private slots:" << endl; |
|
511 writeFunctionsDecl(privateSlots, privateSlotTypes, privateSlotSpecifier); |
|
512 } |
|
513 |
|
514 out << "};" << endl; |
|
515 for (i = 0; i < (int) namespaces.count(); i++) |
|
516 out << '}' << endl; |
|
517 |
|
518 out << endl; |
|
519 } |
|
520 |
|
521 void Ui3Reader::writeFunctionsDecl(const QStringList &fuLst, const QStringList &typLst, const QStringList &specLst) |
|
522 { |
|
523 QStringList::ConstIterator it, it2, it3; |
|
524 for (it = fuLst.begin(), it2 = typLst.begin(), it3 = specLst.begin(); |
|
525 it != fuLst.end(); ++it, ++it2, ++it3) { |
|
526 QString signature = *it; |
|
527 QString specifier; |
|
528 QString pure; |
|
529 QString type = *it2; |
|
530 if (type.isEmpty()) |
|
531 type = QLatin1String("void"); |
|
532 if (*it3 == QLatin1String("static")) { |
|
533 specifier = QLatin1String("static "); |
|
534 } else { |
|
535 if (*it3 != QLatin1String("non virtual") && *it3 != QLatin1String("nonVirtual")) |
|
536 specifier = QLatin1String("virtual "); |
|
537 if (*it3 == QLatin1String("pure virtual") || *it3 == QLatin1String("pureVirtual")) |
|
538 pure = QLatin1String(" = 0"); |
|
539 } |
|
540 type.replace(QLatin1String(">>"), QLatin1String("> >")); |
|
541 if (!signature.contains(QLatin1String("operator"))) |
|
542 signature.replace(QLatin1String(">>"), QLatin1String("> >")); |
|
543 |
|
544 signature = fixDeclaration(signature); |
|
545 type = fixType(type); |
|
546 out << " " << specifier << type << ' ' << signature << pure << ';' << endl; |
|
547 } |
|
548 out << endl; |
|
549 } |
|
550 |
|
551 /*! |
|
552 Creates an implementation (cpp-file) for the form given in \a e. |
|
553 |
|
554 \sa createFormDecl(), createObjectImpl() |
|
555 */ |
|
556 void Ui3Reader::createFormImpl(const QDomElement &e) |
|
557 { |
|
558 QDomElement n; |
|
559 QDomNodeList nl; |
|
560 int i; |
|
561 QString objClass = getClassName(e); |
|
562 if (objClass.isEmpty()) |
|
563 return; |
|
564 QString objName = getObjectName(e); |
|
565 |
|
566 // generate local and local includes required |
|
567 QStringList globalIncludes, localIncludes; |
|
568 QStringList::Iterator it; |
|
569 |
|
570 QMap<QString, CustomInclude> customWidgetIncludes; |
|
571 |
|
572 // find additional slots and functions |
|
573 QStringList extraFuncts; |
|
574 QStringList extraFunctTyp; |
|
575 QStringList extraFunctSpecifier; |
|
576 |
|
577 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("slot")); |
|
578 for (i = 0; i < (int) nl.length(); i++) { |
|
579 n = nl.item(i).toElement(); |
|
580 if (n.parentNode().toElement().tagName() != QLatin1String("slots") |
|
581 && n.parentNode().toElement().tagName() != QLatin1String("connections")) |
|
582 continue; |
|
583 if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) |
|
584 continue; |
|
585 QString functionName = n.firstChild().toText().data().trimmed(); |
|
586 if (functionName.endsWith(QLatin1Char(';'))) |
|
587 functionName.chop(1); |
|
588 extraFuncts += functionName; |
|
589 extraFunctTyp += n.attribute(QLatin1String("returnType"), QLatin1String("void")); |
|
590 extraFunctSpecifier += n.attribute(QLatin1String("specifier"), QLatin1String("virtual")); |
|
591 } |
|
592 |
|
593 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("function")); |
|
594 for (i = 0; i < (int) nl.length(); i++) { |
|
595 n = nl.item(i).toElement(); |
|
596 if (n.parentNode().toElement().tagName() != QLatin1String("functions")) |
|
597 continue; |
|
598 if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++")) |
|
599 continue; |
|
600 QString functionName = n.firstChild().toText().data().trimmed(); |
|
601 if (functionName.endsWith(QLatin1Char(';'))) |
|
602 functionName.chop(1); |
|
603 extraFuncts += functionName; |
|
604 extraFunctTyp += n.attribute(QLatin1String("returnType"), QLatin1String("void")); |
|
605 extraFunctSpecifier += n.attribute(QLatin1String("specifier"), QLatin1String("virtual")); |
|
606 } |
|
607 |
|
608 // additional includes (local or global) and forward declaractions |
|
609 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("include")); |
|
610 for (i = 0; i < (int) nl.length(); i++) { |
|
611 QDomElement n2 = nl.item(i).toElement(); |
|
612 QString s = n2.firstChild().toText().data(); |
|
613 if (n2.attribute(QLatin1String("location")) != QLatin1String("local")) { |
|
614 if (s.right(5) == QLatin1String(".ui.h") && !QFile::exists(s)) |
|
615 continue; |
|
616 if (n2.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) != QLatin1String("in implementation")) |
|
617 continue; |
|
618 globalIncludes += s; |
|
619 } |
|
620 } |
|
621 |
|
622 registerDatabases(e); |
|
623 dbConnections = unique(dbConnections); |
|
624 bool dbForm = false; |
|
625 if (dbForms[QLatin1String("(default)")].count()) |
|
626 dbForm = true; |
|
627 bool subDbForms = false; |
|
628 for (it = dbConnections.begin(); it != dbConnections.end(); ++it) { |
|
629 if (!(*it).isEmpty() && (*it) != QLatin1String("(default)")) { |
|
630 if (dbForms[(*it)].count()) { |
|
631 subDbForms = true; |
|
632 break; |
|
633 } |
|
634 } |
|
635 } |
|
636 |
|
637 // do the local includes afterwards, since global includes have priority on clashes |
|
638 for (i = 0; i < (int) nl.length(); i++) { |
|
639 QDomElement n2 = nl.item(i).toElement(); |
|
640 QString s = n2.firstChild().toText().data(); |
|
641 if (n2.attribute(QLatin1String("location")) == QLatin1String("local") && !globalIncludes.contains(s)) { |
|
642 if (s.right(5) == QLatin1String(".ui.h") && !QFile::exists(s)) |
|
643 continue; |
|
644 if (n2.attribute(QLatin1String("impldecl"), QLatin1String("in implementation")) != QLatin1String("in implementation")) |
|
645 continue; |
|
646 localIncludes += s; |
|
647 } |
|
648 } |
|
649 |
|
650 // additional custom widget headers |
|
651 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("header")); |
|
652 for (i = 0; i < (int) nl.length(); i++) { |
|
653 QDomElement n2 = nl.item(i).toElement(); |
|
654 QString s = n2.firstChild().toText().data(); |
|
655 if (n2.attribute(QLatin1String("location")) != QLatin1String("local")) |
|
656 globalIncludes += s; |
|
657 else |
|
658 localIncludes += s; |
|
659 } |
|
660 |
|
661 out << "#include <qvariant.h>" << endl; // first for gcc 2.7.2 |
|
662 |
|
663 globalIncludes = unique(globalIncludes); |
|
664 for (it = globalIncludes.begin(); it != globalIncludes.end(); ++it) { |
|
665 if (!(*it).isEmpty()) |
|
666 out << "#include <" << fixHeaderName(*it) << '>' << endl; |
|
667 } |
|
668 |
|
669 if (externPixmaps) { |
|
670 out << "#include <qimage.h>" << endl; |
|
671 out << "#include <qpixmap.h>" << endl << endl; |
|
672 } |
|
673 |
|
674 /* |
|
675 Put local includes after all global includes |
|
676 */ |
|
677 localIncludes = unique(localIncludes); |
|
678 for (it = localIncludes.begin(); it != localIncludes.end(); ++it) { |
|
679 if (!(*it).isEmpty() && *it != QFileInfo(fileName + QLatin1String(".h")).fileName()) |
|
680 out << "#include \"" << fixHeaderName(*it) << '\"' << endl; |
|
681 } |
|
682 |
|
683 QString uiDotH = fileName + QLatin1String(".h"); |
|
684 if (QFile::exists(uiDotH)) { |
|
685 if (!outputFileName.isEmpty()) |
|
686 uiDotH = QString::fromUtf8(combinePath(uiDotH.ascii(), outputFileName.ascii())); |
|
687 out << "#include \"" << uiDotH << '\"' << endl; |
|
688 writeFunctImpl = false; |
|
689 } |
|
690 |
|
691 // register the object and unify its name |
|
692 objName = registerObject(objName); |
|
693 |
|
694 if (externPixmaps) { |
|
695 pixmapLoaderFunction = QLatin1String("QPixmap::fromMimeSource"); |
|
696 } |
|
697 |
|
698 // constructor |
|
699 if (objClass == QLatin1String("QDialog") || objClass == QLatin1String("QWizard")) { |
|
700 out << "/*" << endl; |
|
701 out << " * Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl; |
|
702 out << " * name 'name' and widget flags set to 'f'." << endl; |
|
703 out << " *" << endl; |
|
704 out << " * The " << objClass.mid(1).toLower() << " will by default be modeless, unless you set 'modal' to" << endl; |
|
705 out << " * true to construct a modal " << objClass.mid(1).toLower() << '.' << endl; |
|
706 out << " */" << endl; |
|
707 out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl)" << endl; |
|
708 out << " : " << objClass << "(parent, name, modal, fl)"; |
|
709 } else if (objClass == QLatin1String("QWidget")) { |
|
710 out << "/*" << endl; |
|
711 out << " * Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl; |
|
712 out << " * name 'name' and widget flags set to 'f'." << endl; |
|
713 out << " */" << endl; |
|
714 out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, Qt::WindowFlags fl)" << endl; |
|
715 out << " : " << objClass << "(parent, name, fl)"; |
|
716 } else if (objClass == QLatin1String("QMainWindow") || objClass == QLatin1String("Q3MainWindow")) { |
|
717 out << "/*" << endl; |
|
718 out << " * Constructs a " << nameOfClass << " as a child of 'parent', with the" << endl; |
|
719 out << " * name 'name' and widget flags set to 'f'." << endl; |
|
720 out << " *" << endl; |
|
721 out << " */" << endl; |
|
722 out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, Qt::WindowFlags fl)" << endl; |
|
723 out << " : " << objClass << "(parent, name, fl)"; |
|
724 isMainWindow = true; |
|
725 } else { |
|
726 out << "/*" << endl; |
|
727 out << " * Constructs a " << nameOfClass << " which is a child of 'parent', with the" << endl; |
|
728 out << " * name 'name'.' " << endl; |
|
729 out << " */" << endl; |
|
730 out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name)" << endl; |
|
731 out << " : " << objClass << "(parent, name)"; |
|
732 } |
|
733 |
|
734 out << endl; |
|
735 |
|
736 out << '{' << endl; |
|
737 |
|
738 // |
|
739 // setup the gui |
|
740 // |
|
741 out << indent << "setupUi(this);" << endl << endl; |
|
742 |
|
743 |
|
744 if (isMainWindow) |
|
745 out << indent << "(void)statusBar();" << endl; |
|
746 |
|
747 // database support |
|
748 dbConnections = unique(dbConnections); |
|
749 if (dbConnections.count()) |
|
750 out << endl; |
|
751 for (it = dbConnections.begin(); it != dbConnections.end(); ++it) { |
|
752 if (!(*it).isEmpty() && (*it) != QLatin1String("(default)")) { |
|
753 out << indent << (*it) << "Connection = QSqlDatabase::database(\"" <<(*it) << "\");" << endl; |
|
754 } |
|
755 } |
|
756 |
|
757 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("widget")); |
|
758 for (i = 1; i < (int) nl.length(); i++) { // start at 1, 0 is the toplevel widget |
|
759 n = nl.item(i).toElement(); |
|
760 QString s = getClassName(n); |
|
761 if ((dbForm || subDbForms) && (s == QLatin1String("QDataBrowser") || s == QLatin1String("QDataView"))) { |
|
762 QString objName = getObjectName(n); |
|
763 QString tab = getDatabaseInfo(n, QLatin1String("table")); |
|
764 QString con = getDatabaseInfo(n, QLatin1String("connection")); |
|
765 out << indent << "QSqlForm* " << objName << "Form = new QSqlForm(this);" << endl; |
|
766 out << indent << objName << "Form->setObjectName(\"" << objName << "Form\");" << endl; |
|
767 QDomElement n2; |
|
768 for (n2 = n.firstChild().toElement(); !n2.isNull(); n2 = n2.nextSibling().toElement()) |
|
769 createFormImpl(n2, objName, con, tab); |
|
770 out << indent << objName << "->setForm(" << objName << "Form);" << endl; |
|
771 } |
|
772 } |
|
773 |
|
774 if (extraFuncts.contains(QLatin1String("init()"))) |
|
775 out << indent << "init();" << endl; |
|
776 |
|
777 // end of constructor |
|
778 out << '}' << endl; |
|
779 out << endl; |
|
780 |
|
781 // destructor |
|
782 out << "/*" << endl; |
|
783 out << " * Destroys the object and frees any allocated resources" << endl; |
|
784 out << " */" << endl; |
|
785 out << nameOfClass << "::~" << bareNameOfClass << "()" << endl; |
|
786 out << '{' << endl; |
|
787 if (extraFuncts.contains(QLatin1String("destroy()"))) |
|
788 out << indent << "destroy();" << endl; |
|
789 out << indent << "// no need to delete child widgets, Qt does it all for us" << endl; |
|
790 out << '}' << endl; |
|
791 out << endl; |
|
792 |
|
793 // handle application events if required |
|
794 bool needFontEventHandler = false; |
|
795 bool needSqlTableEventHandler = false; |
|
796 bool needSqlDataBrowserEventHandler = false; |
|
797 nl = e.elementsByTagName(QLatin1String("widget")); |
|
798 for (i = 0; i < (int) nl.length(); i++) { |
|
799 if (!DomTool::propertiesOfType(nl.item(i).toElement() , QLatin1String("font")).isEmpty()) |
|
800 needFontEventHandler = true; |
|
801 QString s = getClassName(nl.item(i).toElement()); |
|
802 if (s == QLatin1String("QDataTable") || s == QLatin1String("QDataBrowser")) { |
|
803 if (!isFrameworkCodeGenerated(nl.item(i).toElement())) |
|
804 continue; |
|
805 if (s == QLatin1String("QDataTable")) |
|
806 needSqlTableEventHandler = true; |
|
807 if (s == QLatin1String("QDataBrowser")) |
|
808 needSqlDataBrowserEventHandler = true; |
|
809 } |
|
810 if (needFontEventHandler && needSqlTableEventHandler && needSqlDataBrowserEventHandler) |
|
811 break; |
|
812 } |
|
813 |
|
814 out << "/*" << endl; |
|
815 out << " * Sets the strings of the subwidgets using the current" << endl; |
|
816 out << " * language." << endl; |
|
817 out << " */" << endl; |
|
818 out << "void " << nameOfClass << "::languageChange()" << endl; |
|
819 out << '{' << endl; |
|
820 out << " retranslateUi(this);" << endl; |
|
821 out << '}' << endl; |
|
822 out << endl; |
|
823 |
|
824 // create stubs for additional slots if necessary |
|
825 if (!extraFuncts.isEmpty() && writeFunctImpl) { |
|
826 it = extraFuncts.begin(); |
|
827 QStringList::Iterator it2 = extraFunctTyp.begin(); |
|
828 QStringList::Iterator it3 = extraFunctSpecifier.begin(); |
|
829 while (it != extraFuncts.end()) { |
|
830 QString type = fixDeclaration(*it2); |
|
831 if (type.isEmpty()) |
|
832 type = QLatin1String("void"); |
|
833 type = type.simplified(); |
|
834 QString fname = fixDeclaration(Parser::cleanArgs(*it)); |
|
835 if (!(*it3).startsWith(QLatin1String("pure"))) { // "pure virtual" or "pureVirtual" |
|
836 out << type << ' ' << nameOfClass << "::" << fname << endl; |
|
837 out << '{' << endl; |
|
838 if (*it != QLatin1String("init()") && *it != QLatin1String("destroy()")) { |
|
839 QRegExp numeric(QLatin1String("^(?:signed|unsigned|u?char|u?short|u?int" |
|
840 "|u?long|Q_U?INT(?:8|16|32)|Q_U?LONG|float" |
|
841 "|double)$")); |
|
842 QString retVal; |
|
843 |
|
844 /* |
|
845 We return some kind of dummy value to shut the |
|
846 compiler up. |
|
847 |
|
848 1. If the type is 'void', we return nothing. |
|
849 |
|
850 2. If the type is 'bool', we return 'false'. |
|
851 |
|
852 3. If the type is 'unsigned long' or |
|
853 'quint16' or 'double' or similar, we |
|
854 return '0'. |
|
855 |
|
856 4. If the type is 'Foo *', we return '0'. |
|
857 |
|
858 5. If the type is 'Foo &', we create a static |
|
859 variable of type 'Foo' and return it. |
|
860 |
|
861 6. If the type is 'Foo', we assume there's a |
|
862 default constructor and use it. |
|
863 */ |
|
864 if (type != QLatin1String("void")) { |
|
865 QStringList toks = type.split(QLatin1String(" ")); |
|
866 bool isBasicNumericType = |
|
867 (toks.filter(numeric).count() == toks.count()); |
|
868 |
|
869 if (type == QLatin1String("bool")) { |
|
870 retVal = QLatin1String("false"); |
|
871 } else if (isBasicNumericType || type.endsWith(QLatin1Char('*'))) { |
|
872 retVal = QLatin1String("0"); |
|
873 } else if (type.endsWith(QLatin1Char('&'))) { |
|
874 do { |
|
875 type.chop(1); |
|
876 } while (type.endsWith(QLatin1Char(' '))); |
|
877 retVal = QLatin1String("uic_temp_var"); |
|
878 out << indent << "static " << type << ' ' << retVal << ';' << endl; |
|
879 } else { |
|
880 retVal = type + QLatin1String("()"); |
|
881 } |
|
882 } |
|
883 |
|
884 out << indent << "qWarning(\"" << nameOfClass << "::" << fname << ": Not implemented yet\");" << endl; |
|
885 if (!retVal.isEmpty()) |
|
886 out << indent << "return " << retVal << ';' << endl; |
|
887 } |
|
888 out << '}' << endl; |
|
889 out << endl; |
|
890 } |
|
891 ++it; |
|
892 ++it2; |
|
893 ++it3; |
|
894 } |
|
895 } |
|
896 } |
|
897 |
|
898 |
|
899 /*! Creates form support implementation code for the widgets given |
|
900 in \a e. |
|
901 |
|
902 Traverses recursively over all children. |
|
903 */ |
|
904 |
|
905 void Ui3Reader::createFormImpl(const QDomElement& e, const QString& form, const QString& connection, const QString& table) |
|
906 { |
|
907 if (e.tagName() == QLatin1String("widget") |
|
908 && e.attribute(QLatin1String("class")) != QLatin1String("QDataTable")) { |
|
909 QString field = getDatabaseInfo(e, QLatin1String("field")); |
|
910 if (!field.isEmpty()) { |
|
911 if (isWidgetInTable(e, connection, table)) |
|
912 out << indent << form << "Form->insert(" << getObjectName(e) << ", " << fixString(field) << ");" << endl; |
|
913 } |
|
914 } |
|
915 QDomElement n; |
|
916 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) { |
|
917 createFormImpl(n, form, connection, table); |
|
918 } |
|
919 } |
|
920 |
|
921 QT_END_NAMESPACE |