source: trunk/src/tools/uic3/ui3reader.cpp@ 240

Last change on this file since 240 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 19.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the tools applications of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "ui3reader.h"
43#include "parser.h"
44#include "domtool.h"
45#include "ui4.h"
46#include "widgetinfo.h"
47#include "globaldefs.h"
48#include "qt3to4.h"
49
50#include <QFile>
51#include <QDateTime>
52#include <QRegExp>
53#include <QXmlStreamWriter>
54#include <QtDebug>
55#include <stdio.h>
56#include <stdlib.h>
57
58QT_BEGIN_NAMESPACE
59
60bool Ui3Reader::isMainWindow = false;
61
62static QString lineColDebug(int line, int col)
63{
64 if (line >= 0) {
65 const QString ret = QString::fromLatin1("Line: %1%2");
66 return ret.arg(line).arg(col >= 0 ? QString::fromLatin1(" Column: %1").arg(col) : QString());
67 }
68 return QString();
69}
70
71void Ui3Reader::errorInvalidProperty(const QString &propertyName, const QString &widgetName, const QString &widgetClass, int line, int col)
72{
73 fprintf(stderr, "uic3: property `%s' for widget `%s' of type `%s' is not supported. %s\n",
74 propertyName.toLatin1().constData(),
75 widgetName.toLatin1().constData(),
76 widgetClass.toLatin1().constData(),
77 lineColDebug(line, col).toLocal8Bit().constData());
78}
79
80void Ui3Reader::errorInvalidSignal(const QString &signal, const QString &widgetName, const QString &widgetClass, int line, int col)
81{
82 fprintf(stderr, "uic3: signal `%s' for widget `%s' of type `%s' is not supported; connection may fail. %s\n",
83 signal.toLatin1().constData(), widgetName.toLatin1().constData(),
84 widgetClass.toLatin1().constData(),
85 lineColDebug(line, col).toLocal8Bit().constData());
86}
87
88void Ui3Reader::errorInvalidSlot(const QString &slot, const QString &widgetName, const QString &widgetClass, int line, int col)
89{
90 fprintf(stderr, "uic3: slot `%s' for widget `%s' of type `%s' is not supported; connection may fail. %s\n",
91 slot.toLatin1().constData(),
92 widgetName.toLatin1().constData(),
93 widgetClass.toLatin1().constData(),
94 lineColDebug(line, col).toLocal8Bit().constData());
95}
96
97QString Ui3Reader::getComment(const QDomNode& n)
98{
99 QDomNode child = n.firstChild();
100 while (!child.isNull()) {
101 if (child.toElement().tagName() == QLatin1String("comment"))
102 return child.toElement().firstChild().toText().data();
103 child = child.nextSibling();
104 }
105 return QString();
106}
107
108QString Ui3Reader::mkBool(bool b)
109{
110 return b ? QLatin1String("true") : QLatin1String("false");
111}
112
113QString Ui3Reader::mkBool(const QString& s)
114{
115 return mkBool(s == QLatin1String("true") || s == QLatin1String("1"));
116}
117
118bool Ui3Reader::toBool(const QString& s)
119{
120 return s == QLatin1String("true") || s.toInt() != 0;
121}
122
123QString Ui3Reader::fixString(const QString &str, bool encode)
124{
125 QString s;
126 if (!encode) {
127 s = str;
128 s.replace(QLatin1String("\\"), QLatin1String("\\\\"));
129 s.replace(QLatin1String("\""), QLatin1String("\\\""));
130 s.replace(QLatin1String("\r"), QLatin1String(""));
131 s.replace(QLatin1String("\n"), QLatin1String("\\n\"\n\""));
132 } else {
133 QByteArray utf8 = str.utf8();
134 const int l = utf8.length();
135 for (int i = 0; i < l; ++i)
136 s += QLatin1String("\\x") + QString::number((uchar)utf8[i], 16);
137 }
138
139 return QLatin1String("\"") + s + QLatin1String("\"");
140}
141
142QString Ui3Reader::trcall(const QString& sourceText, const QString& comment)
143{
144 if (sourceText.isEmpty() && comment.isEmpty())
145 return QLatin1String("QString()");
146
147 QString t = trmacro;
148 bool encode = false;
149 if (t.isNull()) {
150 t = QLatin1String("tr");
151 for (int i = 0; i < (int) sourceText.length(); i++) {
152 if (sourceText[i].unicode() >= 0x80) {
153 t = QLatin1String("trUtf8");
154 encode = true;
155 break;
156 }
157 }
158 }
159
160 if (comment.isEmpty()) {
161 return t + QLatin1String("(") + fixString(sourceText, encode) + QLatin1String(")");
162 } else {
163 return t + QLatin1String("(")
164 + fixString(sourceText, encode)
165 + QLatin1String(", ")
166 + fixString(comment, encode) + QLatin1String(")");
167 }
168}
169
170QString Ui3Reader::mkStdSet(const QString& prop)
171{
172 return QLatin1String("set") + prop[0].toUpper() + prop.mid(1);
173}
174
175void Ui3Reader::init()
176{
177 outputFileName.clear();
178 trmacro.clear();
179 nofwd = false;
180
181 fileName.clear();
182 writeFunctImpl = true;
183 defMargin = BOXLAYOUT_DEFAULT_MARGIN;
184 defSpacing = BOXLAYOUT_DEFAULT_SPACING;
185 externPixmaps = false;
186 indent = QLatin1String(" "); // default indent
187
188 item_used = cg_used = pal_used = 0;
189
190 layouts.clear();
191 layouts << QLatin1String("hbox") << QLatin1String("vbox") << QLatin1String("grid");
192 tags = layouts;
193 tags << QLatin1String("widget");
194
195 nameOfClass.clear();
196 namespaces.clear();
197 bareNameOfClass.clear();
198}
199
200QDomElement Ui3Reader::parse(const QDomDocument &doc)
201{
202 root = doc.firstChild().toElement();
203 widget = QDomElement();
204
205 pixmapLoaderFunction = getPixmapLoaderFunction(doc.firstChild().toElement());
206 nameOfClass = getFormClassName(doc.firstChild().toElement());
207
208 uiFileVersion = doc.firstChild().toElement().attribute(QLatin1String("version"));
209 stdsetdef = toBool(doc.firstChild().toElement().attribute(QLatin1String("stdsetdef")));
210
211 if (doc.firstChild().isNull() || doc.firstChild().firstChild().isNull())
212 return widget;
213
214 QDomElement e = doc.firstChild().firstChild().toElement();
215 while (!e.isNull()) {
216 if (e.tagName() == QLatin1String("widget")) {
217 widget = e;
218 } else if (e.tagName() == QLatin1String("pixmapinproject")) {
219 externPixmaps = true;
220 } else if (e.tagName() == QLatin1String("layoutdefaults")) {
221 defSpacing = e.attribute(QLatin1String("spacing"), defSpacing.toString());
222 defMargin = e.attribute(QLatin1String("margin"), defMargin.toString());
223 } else if (e.tagName() == QLatin1String("layoutfunctions")) {
224 defSpacing = e.attribute(QLatin1String("spacing"), defSpacing.toString());
225 bool ok;
226 defSpacing.toInt(&ok);
227 if (!ok) {
228 QString buf = defSpacing.toString();
229 defSpacing = buf.append(QLatin1String("()"));
230 }
231 defMargin = e.attribute(QLatin1String("margin"), defMargin.toString());
232 defMargin.toInt(&ok);
233 if (!ok) {
234 QString buf = defMargin.toString();
235 defMargin = buf.append(QLatin1String("()"));
236 }
237 }
238 e = e.nextSibling().toElement();
239 }
240
241 return widget;
242}
243
244Ui3Reader::Ui3Reader(QTextStream &outStream)
245 : out(outStream), trout(&languageChangeBody)
246{
247 m_porting = new Porting();
248 m_extractImages = false;
249}
250
251Ui3Reader::~Ui3Reader()
252{
253 delete m_porting;
254}
255
256void Ui3Reader::generate(const QString &fn, const QString &outputFn,
257 QDomDocument doc, bool decl, bool subcl, const QString &trm,
258 const QString& subClass, bool omitForwardDecls, bool implicitIncludes, const QString &convertedUiFile)
259{
260 init();
261
262 fileName = fn;
263 outputFileName = outputFn;
264 trmacro = trm;
265 nofwd = omitForwardDecls;
266
267 QDomElement e = parse(doc);
268
269 if (nameOfClass.isEmpty())
270 nameOfClass = getObjectName(e);
271 namespaces = nameOfClass.split(QLatin1String("::"));
272 bareNameOfClass = namespaces.last();
273 namespaces.removeLast();
274
275 if (!convertedUiFile.isEmpty()) {
276 createWrapperDecl(e, convertedUiFile);
277 } else if (subcl) {
278 if (decl)
279 createSubDecl(e, subClass);
280 else
281 createSubImpl(e, subClass);
282 } else {
283 if (decl)
284 createFormDecl(e, implicitIncludes);
285 else
286 createFormImpl(e);
287 }
288
289}
290
291void Ui3Reader::generateUi4(const QString &fn, const QString &outputFn, QDomDocument doc, bool implicitIncludes)
292{
293 init();
294
295 fileName = fn;
296 outputFileName = outputFn;
297
298 DomUI *ui = generateUi4(parse(doc), implicitIncludes);
299 if (!ui)
300 return;
301
302 if (pixmapLoaderFunction.size())
303 ui->setElementPixmapFunction(pixmapLoaderFunction);
304
305 QXmlStreamWriter writer(out.device());
306 writer.setAutoFormatting(true);
307 writer.setAutoFormattingIndent(2);
308 writer.writeStartDocument();
309 ui->write(writer);
310 writer.writeEndDocument();
311
312 delete ui;
313}
314
315void Ui3Reader::setTrMacro(const QString &trmacro)
316{
317 this->trmacro = trmacro;
318}
319
320void Ui3Reader::setForwardDeclarationsEnabled(bool b)
321{
322 nofwd = !b;
323}
324
325void Ui3Reader::setOutputFileName(const QString &fileName)
326{
327 outputFileName = fileName;
328}
329
330/*! Extracts a pixmap loader function from \a e
331 */
332QString Ui3Reader::getPixmapLoaderFunction(const QDomElement& e)
333{
334 QDomElement n;
335 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
336 if (n.tagName() == QLatin1String("pixmapfunction"))
337 return n.firstChild().toText().data();
338 }
339 return QString();
340}
341
342
343/*! Extracts the forms class name from \a e
344 */
345QString Ui3Reader::getFormClassName(const QDomElement& e)
346{
347 QDomElement n;
348 QString cn;
349 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
350 if (n.tagName() == QLatin1String("class")) {
351 QString s = n.firstChild().toText().data();
352 int i;
353 while ((i = s.indexOf(QLatin1Char(' '))) != -1)
354 s[i] = QLatin1Char('_');
355 cn = s;
356 }
357 }
358 return cn;
359}
360
361/*! Extracts a class name from \a e.
362 */
363QString Ui3Reader::getClassName(const QDomElement& e)
364{
365 QString s = e.attribute(QLatin1String("class"));
366 if (s.isEmpty() && e.tagName() == QLatin1String("toolbar"))
367 s = QLatin1String(QLatin1String("QToolBar"));
368 else if (s.isEmpty() && e.tagName() == QLatin1String("menubar"))
369 s = QLatin1String("QMenuBar");
370
371 return fixClassName(s);
372}
373
374/*! Returns true if database framework code is generated, else false.
375*/
376
377bool Ui3Reader::isFrameworkCodeGenerated(const QDomElement& e)
378{
379 QDomElement n = getObjectProperty(e, QLatin1String("frameworkCode"));
380 if (n.attribute(QLatin1String("name")) == QLatin1String("frameworkCode") &&
381 !DomTool::elementToVariant(n.firstChild().toElement(), QVariant(true)).toBool())
382 return false;
383 return true;
384}
385
386/*! Extracts an object name from \a e. It's stored in the 'name'
387 property.
388 */
389QString Ui3Reader::getObjectName(const QDomElement& e)
390{
391 QDomElement n = getObjectProperty(e, QLatin1String("name"));
392 if (n.firstChild().toElement().tagName() == QLatin1String("cstring"))
393 return n.firstChild().toElement().firstChild().toText().data();
394 return QString();
395}
396
397/*! Extracts an layout name from \a e. It's stored in the 'name'
398 property of the preceding sibling (the first child of a QLayoutWidget).
399 */
400QString Ui3Reader::getLayoutName(const QDomElement& e)
401{
402 QDomElement p = e.parentNode().toElement();
403 QString name;
404
405 if (getClassName(p) != QLatin1String("QLayoutWidget"))
406 name = QLatin1String("Layout");
407
408 QDomElement n = getObjectProperty(p, QLatin1String("name"));
409 if (n.firstChild().toElement().tagName() == QLatin1String("cstring")) {
410 name.prepend(n.firstChild().toElement().firstChild().toText().data());
411 return name.split(QLatin1String("::")).last();
412 }
413 return e.tagName();
414}
415
416
417QString Ui3Reader::getDatabaseInfo(const QDomElement& e, const QString& tag)
418{
419 QDomElement n;
420 QDomElement n1;
421 int child = 0;
422 // database info is a stringlist stored in this order
423 if (tag == QLatin1String("connection"))
424 child = 0;
425 else if (tag == QLatin1String("table"))
426 child = 1;
427 else if (tag == QLatin1String("field"))
428 child = 2;
429 else
430 return QString();
431 n = getObjectProperty(e, QLatin1String("database"));
432 if (n.firstChild().toElement().tagName() == QLatin1String("stringlist")) {
433 // find correct stringlist entry
434 QDomElement n1 = n.firstChild().firstChild().toElement();
435 for (int i = 0; i < child && !n1.isNull(); ++i)
436 n1 = n1.nextSibling().toElement();
437 if (n1.isNull())
438 return QString();
439 return n1.firstChild().toText().data();
440 }
441 return QString();
442}
443
444static const char* const ColorRole[] = {
445 "Foreground", "Button", "Light", "Midlight", "Dark", "Mid",
446 "Text", "BrightText", "ButtonText", "Base", "Background", "Shadow",
447 "Highlight", "HighlightedText", "Link", "LinkVisited", 0
448};
449
450
451/*!
452 Creates a colorgroup with name \a name from the color group \a cg
453 */
454void Ui3Reader::createColorGroupImpl(const QString& name, const QDomElement& e)
455{
456 int r = -1;
457 QDomElement n = e.firstChild().toElement();
458 QString color;
459
460 Color white;
461 white.init(255, 255, 255);
462
463 Color black;
464 black.init(0, 0, 0);
465
466 while (!n.isNull()) {
467 if (n.tagName() == QLatin1String("color")) {
468 r++;
469 Color col = DomTool::readColor(n);
470 color = QLatin1String("QColor(%1, %2, %3)");
471 color = color.arg(col.red).arg(col.green).arg(col.blue);
472 if (col == white)
473 color = QLatin1String("white");
474 else if (col == black)
475 color = QLatin1String("black");
476 if (n.nextSibling().toElement().tagName() != QLatin1String("pixmap")) {
477 out << indent << name << ".setColor(QColorGroup::" << ColorRole[r] << ", " << color << ");" << endl;
478 }
479 } else if (n.tagName() == QLatin1String("pixmap")) {
480 QString pixmap = n.firstChild().toText().data();
481 if (!pixmapLoaderFunction.isEmpty()) {
482 pixmap.prepend(pixmapLoaderFunction
483 + QLatin1String("(")
484 + QLatin1String(externPixmaps ? "\"" : ""));
485
486 pixmap.append(QLatin1String(externPixmaps ? "\"" : "") + QLatin1String(")"));
487 }
488 out << indent << name << ".setBrush(QColorGroup::"
489 << ColorRole[r] << ", QBrush(" << color << ", " << pixmap << "));" << endl;
490 }
491 n = n.nextSibling().toElement();
492 }
493}
494
495/*!
496 Auxiliary function to load a color group. The colorgroup must not
497 contain pixmaps.
498 */
499ColorGroup Ui3Reader::loadColorGroup(const QDomElement &e)
500{
501 ColorGroup cg;
502 int r = -1;
503 QDomElement n = e.firstChild().toElement();
504 Color col;
505 while (!n.isNull()) {
506 if (n.tagName() == QLatin1String("color")) {
507 r++;
508 col = DomTool::readColor(n);
509 cg.append(qMakePair(r, col));
510 }
511 n = n.nextSibling().toElement();
512 }
513 return cg;
514}
515
516/*! Returns true if the widget properties specify that it belongs to
517 the database \a connection and \a table.
518*/
519
520bool Ui3Reader::isWidgetInTable(const QDomElement& e, const QString& connection, const QString& table)
521{
522 QString conn = getDatabaseInfo(e, QLatin1String("connection"));
523 QString tab = getDatabaseInfo(e, QLatin1String("table"));
524 if (conn == connection && tab == table)
525 return true;
526 return false;
527}
528
529/*!
530 Registers all database connections, cursors and forms.
531*/
532
533void Ui3Reader::registerDatabases(const QDomElement& e)
534{
535 QDomElement n;
536 QDomNodeList nl;
537 int i;
538 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("widget"));
539 for (i = 0; i < (int) nl.length(); ++i) {
540 n = nl.item(i).toElement();
541 QString conn = getDatabaseInfo(n, QLatin1String("connection"));
542 QString tab = getDatabaseInfo(n, QLatin1String("table"));
543 QString fld = getDatabaseInfo(n, QLatin1String("field"));
544 if (!conn.isNull()) {
545 dbConnections += conn;
546 if (!tab.isNull()) {
547 dbCursors[conn] += tab;
548 if (!fld.isNull())
549 dbForms[conn] += tab;
550 }
551 }
552 }
553}
554
555/*!
556 Registers an object with name \a name.
557
558 The returned name is a valid variable identifier, as similar to \a
559 name as possible and guaranteed to be unique within the form.
560
561 \sa registeredName(), isObjectRegistered()
562 */
563QString Ui3Reader::registerObject(const QString& name)
564{
565 if (objectNames.isEmpty()) {
566 // some temporary variables we need
567 objectNames += QLatin1String("img");
568 objectNames += QLatin1String("item");
569 objectNames += QLatin1String("cg");
570 objectNames += QLatin1String("pal");
571 }
572
573 QString result = name;
574 int i;
575 while ((i = result.indexOf(QLatin1Char(' '))) != -1 ) {
576 result[i] = QLatin1Char('_');
577 }
578
579 if (objectNames.contains(result)) {
580 int i = 2;
581 while (objectNames.contains(result + QLatin1String("_") + QString::number(i)))
582 i++;
583 result += QLatin1String("_");
584 result += QString::number(i);
585 }
586 objectNames += result;
587 objectMapper.insert(name, result);
588 return result;
589}
590
591/*!
592 Returns the registered name for the original name \a name
593 or \a name if \a name wasn't registered.
594
595 \sa registerObject(), isObjectRegistered()
596 */
597QString Ui3Reader::registeredName(const QString& name)
598{
599 if (!objectMapper.contains(name))
600 return name;
601 return objectMapper[name];
602}
603
604/*!
605 Returns whether the object \a name was registered yet or not.
606 */
607bool Ui3Reader::isObjectRegistered(const QString& name)
608{
609 return objectMapper.contains(name);
610}
611
612/*!
613 Unifies the entries in stringlist \a list. Should really be a QStringList feature.
614 */
615QStringList Ui3Reader::unique(const QStringList& list)
616{
617 if (list.isEmpty())
618 return list;
619
620 QStringList result;
621 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) {
622 if (!result.contains(*it))
623 result += *it;
624 }
625 return result;
626}
627
628bool Ui3Reader::isLayout(const QString& name) const
629{
630 return layoutObjects.contains(name);
631}
632
633void Ui3Reader::setExtractImages(bool extract, const QString &qrcOutputFile)
634{
635 m_extractImages = extract;
636 m_qrcOutputFile = qrcOutputFile;
637}
638
639QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.