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

Last change on this file since 1056 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 19.3 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the tools applications of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
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** 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 have questions regarding the use of this file, please contact
37** Nokia 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(QLatin1Char('\\'), QLatin1String("\\\\"));
129 s.replace(QLatin1Char('\"'), QLatin1String("\\\""));
130 s.remove(QLatin1Char('\r'));
131 s.replace(QLatin1Char('\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 QLatin1Char('\"') + s + QLatin1Char('\"');
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 + QLatin1Char('(') + fixString(sourceText, encode) + QLatin1Char(')');
162 } else {
163 return t + QLatin1Char('(')
164 + fixString(sourceText, encode)
165 + QLatin1String(", ")
166 + fixString(comment, encode) + QLatin1Char(')');
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
180 fileName.clear();
181 writeFunctImpl = true;
182 defMargin = BOXLAYOUT_DEFAULT_MARGIN;
183 defSpacing = BOXLAYOUT_DEFAULT_SPACING;
184 externPixmaps = false;
185 indent = QLatin1String(" "); // default indent
186
187 item_used = cg_used = pal_used = 0;
188
189 layouts.clear();
190 layouts << QLatin1String("hbox") << QLatin1String("vbox") << QLatin1String("grid");
191 tags = layouts;
192 tags << QLatin1String("widget");
193
194 nameOfClass.clear();
195 namespaces.clear();
196 bareNameOfClass.clear();
197}
198
199QDomElement Ui3Reader::parse(const QDomDocument &doc)
200{
201 root = doc.firstChild().toElement();
202 widget = QDomElement();
203
204 pixmapLoaderFunction = getPixmapLoaderFunction(doc.firstChild().toElement());
205 nameOfClass = getFormClassName(doc.firstChild().toElement());
206
207 uiFileVersion = doc.firstChild().toElement().attribute(QLatin1String("version"));
208 stdsetdef = toBool(doc.firstChild().toElement().attribute(QLatin1String("stdsetdef")));
209
210 if (doc.firstChild().isNull() || doc.firstChild().firstChild().isNull())
211 return widget;
212
213 QDomElement e = doc.firstChild().firstChild().toElement();
214 while (!e.isNull()) {
215 if (e.tagName() == QLatin1String("widget")) {
216 widget = e;
217 } else if (e.tagName() == QLatin1String("pixmapinproject")) {
218 externPixmaps = true;
219 } else if (e.tagName() == QLatin1String("layoutdefaults")) {
220 defSpacing = e.attribute(QLatin1String("spacing"), defSpacing.toString());
221 defMargin = e.attribute(QLatin1String("margin"), defMargin.toString());
222 } else if (e.tagName() == QLatin1String("layoutfunctions")) {
223 defSpacing = e.attribute(QLatin1String("spacing"), defSpacing.toString());
224 bool ok;
225 defSpacing.toInt(&ok);
226 if (!ok) {
227 QString buf = defSpacing.toString();
228 defSpacing = buf.append(QLatin1String("()"));
229 }
230 defMargin = e.attribute(QLatin1String("margin"), defMargin.toString());
231 defMargin.toInt(&ok);
232 if (!ok) {
233 QString buf = defMargin.toString();
234 defMargin = buf.append(QLatin1String("()"));
235 }
236 }
237 e = e.nextSibling().toElement();
238 }
239
240 return widget;
241}
242
243Ui3Reader::Ui3Reader(QTextStream &outStream, unsigned options) :
244 m_options(options), out(outStream), trout(&languageChangeBody),
245 m_porting(new Porting), m_extractImages(false)
246{
247}
248
249Ui3Reader::~Ui3Reader()
250{
251 delete m_porting;
252}
253
254void Ui3Reader::generate(const QString &fn, const QString &outputFn,
255 QDomDocument doc, bool decl, bool subcl, const QString &trm,
256 const QString& subClass, const QString &convertedUiFile)
257{
258 init();
259
260 fileName = fn;
261 outputFileName = outputFn;
262 trmacro = trm;
263
264 QDomElement e = parse(doc);
265
266 if (nameOfClass.isEmpty())
267 nameOfClass = getObjectName(e);
268 namespaces = nameOfClass.split(QLatin1String("::"));
269 bareNameOfClass = namespaces.last();
270 namespaces.removeLast();
271
272 if (!convertedUiFile.isEmpty()) {
273 createWrapperDecl(e, convertedUiFile);
274 } else if (subcl) {
275 if (decl)
276 createSubDecl(e, subClass);
277 else
278 createSubImpl(e, subClass);
279 } else {
280 if (decl)
281 createFormDecl(e);
282 else
283 createFormImpl(e);
284 }
285
286}
287
288void Ui3Reader::generateUi4(const QString &fn, const QString &outputFn, QDomDocument doc)
289{
290 init();
291
292 fileName = fn;
293 outputFileName = outputFn;
294
295 DomUI *ui = generateUi4(parse(doc));
296 if (!ui)
297 return;
298
299 if (pixmapLoaderFunction.size())
300 ui->setElementPixmapFunction(pixmapLoaderFunction);
301
302 QXmlStreamWriter writer(out.device());
303 writer.setAutoFormatting(true);
304 writer.setAutoFormattingIndent(2);
305 writer.writeStartDocument();
306 ui->write(writer);
307 writer.writeEndDocument();
308
309 delete ui;
310}
311
312void Ui3Reader::setTrMacro(const QString &trmacro)
313{
314 this->trmacro = trmacro;
315}
316
317void Ui3Reader::setOutputFileName(const QString &fileName)
318{
319 outputFileName = fileName;
320}
321
322/*! Extracts a pixmap loader function from \a e
323 */
324QString Ui3Reader::getPixmapLoaderFunction(const QDomElement& e)
325{
326 QDomElement n;
327 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
328 if (n.tagName() == QLatin1String("pixmapfunction"))
329 return n.firstChild().toText().data();
330 }
331 return QString();
332}
333
334
335/*! Extracts the forms class name from \a e
336 */
337QString Ui3Reader::getFormClassName(const QDomElement& e)
338{
339 QDomElement n;
340 QString cn;
341 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
342 if (n.tagName() == QLatin1String("class")) {
343 QString s = n.firstChild().toText().data();
344 int i;
345 while ((i = s.indexOf(QLatin1Char(' '))) != -1)
346 s[i] = QLatin1Char('_');
347 cn = s;
348 }
349 }
350 return cn;
351}
352
353/*! Extracts a class name from \a e.
354 */
355QString Ui3Reader::getClassName(const QDomElement& e)
356{
357 QString s = e.attribute(QLatin1String("class"));
358 if (s.isEmpty() && e.tagName() == QLatin1String("toolbar"))
359 s = QLatin1String(QLatin1String("QToolBar"));
360 else if (s.isEmpty() && e.tagName() == QLatin1String("menubar"))
361 s = QLatin1String("QMenuBar");
362
363 return fixClassName(s);
364}
365
366/*! Returns true if database framework code is generated, else false.
367*/
368
369bool Ui3Reader::isFrameworkCodeGenerated(const QDomElement& e)
370{
371 QDomElement n = getObjectProperty(e, QLatin1String("frameworkCode"));
372 if (n.attribute(QLatin1String("name")) == QLatin1String("frameworkCode") &&
373 !DomTool::elementToVariant(n.firstChild().toElement(), QVariant(true)).toBool())
374 return false;
375 return true;
376}
377
378/*! Extracts an object name from \a e. It's stored in the 'name'
379 property.
380 */
381QString Ui3Reader::getObjectName(const QDomElement& e)
382{
383 QDomElement n = getObjectProperty(e, QLatin1String("name"));
384 if (n.firstChild().toElement().tagName() == QLatin1String("cstring"))
385 return n.firstChild().toElement().firstChild().toText().data();
386 return QString();
387}
388
389/*! Extracts an layout name from \a e. It's stored in the 'name'
390 property of the preceding sibling (the first child of a QLayoutWidget).
391 */
392QString Ui3Reader::getLayoutName(const QDomElement& e)
393{
394 QDomElement p = e.parentNode().toElement();
395 QString name;
396
397 if (getClassName(p) != QLatin1String("QLayoutWidget"))
398 name = QLatin1String("Layout");
399
400 QDomElement n = getObjectProperty(p, QLatin1String("name"));
401 if (n.firstChild().toElement().tagName() == QLatin1String("cstring")) {
402 name.prepend(n.firstChild().toElement().firstChild().toText().data());
403 return name.split(QLatin1String("::")).last();
404 }
405 return e.tagName();
406}
407
408
409QString Ui3Reader::getDatabaseInfo(const QDomElement& e, const QString& tag)
410{
411 QDomElement n;
412 QDomElement n1;
413 int child = 0;
414 // database info is a stringlist stored in this order
415 if (tag == QLatin1String("connection"))
416 child = 0;
417 else if (tag == QLatin1String("table"))
418 child = 1;
419 else if (tag == QLatin1String("field"))
420 child = 2;
421 else
422 return QString();
423 n = getObjectProperty(e, QLatin1String("database"));
424 if (n.firstChild().toElement().tagName() == QLatin1String("stringlist")) {
425 // find correct stringlist entry
426 QDomElement n1 = n.firstChild().firstChild().toElement();
427 for (int i = 0; i < child && !n1.isNull(); ++i)
428 n1 = n1.nextSibling().toElement();
429 if (n1.isNull())
430 return QString();
431 return n1.firstChild().toText().data();
432 }
433 return QString();
434}
435
436static const char* const ColorRole[] = {
437 "Foreground", "Button", "Light", "Midlight", "Dark", "Mid",
438 "Text", "BrightText", "ButtonText", "Base", "Background", "Shadow",
439 "Highlight", "HighlightedText", "Link", "LinkVisited", 0
440};
441
442
443/*!
444 Creates a colorgroup with name \a name from the color group \a cg
445 */
446void Ui3Reader::createColorGroupImpl(const QString& name, const QDomElement& e)
447{
448 int r = -1;
449 QDomElement n = e.firstChild().toElement();
450 QString color;
451
452 Color white;
453 white.init(255, 255, 255);
454
455 Color black;
456 black.init(0, 0, 0);
457
458 while (!n.isNull()) {
459 if (n.tagName() == QLatin1String("color")) {
460 r++;
461 Color col = DomTool::readColor(n);
462 color = QLatin1String("QColor(%1, %2, %3)");
463 color = color.arg(col.red).arg(col.green).arg(col.blue);
464 if (col == white)
465 color = QLatin1String("white");
466 else if (col == black)
467 color = QLatin1String("black");
468 if (n.nextSibling().toElement().tagName() != QLatin1String("pixmap")) {
469 out << indent << name << ".setColor(QColorGroup::" << ColorRole[r] << ", " << color << ");" << endl;
470 }
471 } else if (n.tagName() == QLatin1String("pixmap")) {
472 QString pixmap = n.firstChild().toText().data();
473 if (!pixmapLoaderFunction.isEmpty()) {
474 pixmap.prepend(pixmapLoaderFunction
475 + QLatin1Char('(')
476 + QLatin1String(externPixmaps ? "\"" : ""));
477
478 pixmap.append(QLatin1String(externPixmaps ? "\"" : "") + QLatin1Char(')'));
479 }
480 out << indent << name << ".setBrush(QColorGroup::"
481 << ColorRole[r] << ", QBrush(" << color << ", " << pixmap << "));" << endl;
482 }
483 n = n.nextSibling().toElement();
484 }
485}
486
487/*!
488 Auxiliary function to load a color group. The colorgroup must not
489 contain pixmaps.
490 */
491ColorGroup Ui3Reader::loadColorGroup(const QDomElement &e)
492{
493 ColorGroup cg;
494 int r = -1;
495 QDomElement n = e.firstChild().toElement();
496 Color col;
497 while (!n.isNull()) {
498 if (n.tagName() == QLatin1String("color")) {
499 r++;
500 col = DomTool::readColor(n);
501 cg.append(qMakePair(r, col));
502 }
503 n = n.nextSibling().toElement();
504 }
505 return cg;
506}
507
508/*! Returns true if the widget properties specify that it belongs to
509 the database \a connection and \a table.
510*/
511
512bool Ui3Reader::isWidgetInTable(const QDomElement& e, const QString& connection, const QString& table)
513{
514 QString conn = getDatabaseInfo(e, QLatin1String("connection"));
515 QString tab = getDatabaseInfo(e, QLatin1String("table"));
516 if (conn == connection && tab == table)
517 return true;
518 return false;
519}
520
521/*!
522 Registers all database connections, cursors and forms.
523*/
524
525void Ui3Reader::registerDatabases(const QDomElement& e)
526{
527 QDomElement n;
528 QDomNodeList nl;
529 int i;
530 nl = e.parentNode().toElement().elementsByTagName(QLatin1String("widget"));
531 for (i = 0; i < (int) nl.length(); ++i) {
532 n = nl.item(i).toElement();
533 QString conn = getDatabaseInfo(n, QLatin1String("connection"));
534 QString tab = getDatabaseInfo(n, QLatin1String("table"));
535 QString fld = getDatabaseInfo(n, QLatin1String("field"));
536 if (!conn.isNull()) {
537 dbConnections += conn;
538 if (!tab.isNull()) {
539 dbCursors[conn] += tab;
540 if (!fld.isNull())
541 dbForms[conn] += tab;
542 }
543 }
544 }
545}
546
547/*!
548 Registers an object with name \a name.
549
550 The returned name is a valid variable identifier, as similar to \a
551 name as possible and guaranteed to be unique within the form.
552
553 \sa registeredName(), isObjectRegistered()
554 */
555QString Ui3Reader::registerObject(const QString& name)
556{
557 if (objectNames.isEmpty()) {
558 // some temporary variables we need
559 objectNames += QLatin1String("img");
560 objectNames += QLatin1String("item");
561 objectNames += QLatin1String("cg");
562 objectNames += QLatin1String("pal");
563 }
564
565 QString result = name;
566 int i;
567 while ((i = result.indexOf(QLatin1Char(' '))) != -1 ) {
568 result[i] = QLatin1Char('_');
569 }
570
571 if (objectNames.contains(result)) {
572 int i = 2;
573 while (objectNames.contains(result + QLatin1Char('_') + QString::number(i)))
574 i++;
575 result += QLatin1Char('_');
576 result += QString::number(i);
577 }
578 objectNames += result;
579 objectMapper.insert(name, result);
580 return result;
581}
582
583/*!
584 Returns the registered name for the original name \a name
585 or \a name if \a name wasn't registered.
586
587 \sa registerObject(), isObjectRegistered()
588 */
589QString Ui3Reader::registeredName(const QString& name)
590{
591 if (!objectMapper.contains(name))
592 return name;
593 return objectMapper[name];
594}
595
596/*!
597 Returns whether the object \a name was registered yet or not.
598 */
599bool Ui3Reader::isObjectRegistered(const QString& name)
600{
601 return objectMapper.contains(name);
602}
603
604/*!
605 Unifies the entries in stringlist \a list. Should really be a QStringList feature.
606 */
607QStringList Ui3Reader::unique(const QStringList& list)
608{
609 if (list.isEmpty())
610 return list;
611
612 QStringList result;
613 for (QStringList::ConstIterator it = list.begin(); it != list.end(); ++it) {
614 if (!result.contains(*it))
615 result += *it;
616 }
617 return result;
618}
619
620bool Ui3Reader::isLayout(const QString& name) const
621{
622 return layoutObjects.contains(name);
623}
624
625void Ui3Reader::setExtractImages(bool extract, const QString &qrcOutputFile)
626{
627 m_extractImages = extract;
628 m_qrcOutputFile = qrcOutputFile;
629}
630
631QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.