source: trunk/src/tools/uic3/domtool.cpp@ 900

Last change on this file since 900 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: 20.5 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 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** 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 qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "domtool.h"
43
44#include <QSizePolicy>
45#include <QColor>
46#include <QCursor>
47#include <QDateTime>
48#include <QRect>
49#include <QSize>
50#include <QFont>
51#include <QDomElement>
52#include <QByteArray>
53#include <QtDebug>
54
55QT_BEGIN_NAMESPACE
56
57/*
58 \class DomTool
59 \brief The DomTool class provides static functions for Qt Designer
60 and uic.
61
62 A collection of static functions used by Resource (part of the
63 designer) and Uic.
64
65*/
66
67/*
68 Returns the contents of property \a name of object \a e as
69 a variant or the variant passed as \a defValue if the property does
70 not exist. The \a comment is passed on to the elementToVariant()
71 function.
72
73 \sa hasProperty()
74*/
75QVariant DomTool::readProperty(const QDomElement& e, const QString& name, const QVariant& defValue, QString& comment)
76{
77 QDomElement n;
78 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
79 if (n.tagName() == QLatin1String("property")) {
80 if (n.attribute(QLatin1String("name")) != name)
81 continue;
82 return elementToVariant(n.firstChild().toElement(), defValue, comment);
83 }
84 }
85 return defValue;
86}
87
88
89/*
90 \overload
91 */
92QVariant DomTool::readProperty(const QDomElement& e, const QString& name, const QVariant& defValue)
93{
94 QString comment;
95 return readProperty(e, name, defValue, comment);
96}
97
98/*
99 Returns whether object \a e defines property \a name or not.
100
101 \sa readProperty()
102 */
103bool DomTool::hasProperty(const QDomElement& e, const QString& name)
104{
105 QDomElement n;
106 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
107 if (n.tagName() == QLatin1String("property")) {
108 if (n.attribute(QLatin1String("name")) != name)
109 continue;
110 return true;
111 }
112 }
113 return false;
114}
115
116/*
117 Returns a list of the names of the properties of the given \a type
118 found in the element \a e.
119*/
120QStringList DomTool::propertiesOfType(const QDomElement& e, const QString& type)
121{
122 QStringList result;
123 QDomElement n;
124 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
125 if (n.tagName() == QLatin1String("property")) {
126 QDomElement n2 = n.firstChild().toElement();
127 if (n2.tagName() == type)
128 result += n.attribute(QLatin1String("name"));
129 }
130 }
131 return result;
132}
133
134
135/*
136 \overload
137*/
138QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValue)
139{
140 QString dummy;
141 return elementToVariant(e, defValue, dummy);
142}
143
144/*
145 Interprets element \a e as a variant and returns the result of the
146 interpretation, extracting the data as a text element is the \a
147 comment matches the tag name. If the interpretation fails the \a
148 defValue is returned instead.
149 */
150QVariant DomTool::elementToVariant(const QDomElement& e, const QVariant& defValue, QString &comment)
151{
152 Q_UNUSED(defValue);
153
154 QVariant v;
155 Variant var;
156
157 if (e.tagName() == QLatin1String("rect")) {
158 QDomElement n3 = e.firstChild().toElement();
159 int x = 0, y = 0, w = 0, h = 0;
160 while (!n3.isNull()) {
161 if (n3.tagName() == QLatin1String("x"))
162 x = n3.firstChild().toText().data().toInt();
163 else if (n3.tagName() == QLatin1String("y"))
164 y = n3.firstChild().toText().data().toInt();
165 else if (n3.tagName() == QLatin1String("width"))
166 w = n3.firstChild().toText().data().toInt();
167 else if (n3.tagName() == QLatin1String("height"))
168 h = n3.firstChild().toText().data().toInt();
169 n3 = n3.nextSibling().toElement();
170 }
171 var.createRect(x, y, w, h);
172 qVariantSetValue(v, var);
173 } else if (e.tagName() == QLatin1String("point")) {
174 QDomElement n3 = e.firstChild().toElement();
175 int x = 0, y = 0;
176 while (!n3.isNull()) {
177 if (n3.tagName() == QLatin1String("x"))
178 x = n3.firstChild().toText().data().toInt();
179 else if (n3.tagName() == QLatin1String("y"))
180 y = n3.firstChild().toText().data().toInt();
181 n3 = n3.nextSibling().toElement();
182 }
183 var.createPoint(x,y);
184 qVariantSetValue(v, var);
185 } else if (e.tagName() == QLatin1String("size")) {
186 QDomElement n3 = e.firstChild().toElement();
187 int w = 0, h = 0;
188 while (!n3.isNull()) {
189 if (n3.tagName() == QLatin1String("width"))
190 w = n3.firstChild().toText().data().toInt();
191 else if (n3.tagName() == QLatin1String("height"))
192 h = n3.firstChild().toText().data().toInt();
193 n3 = n3.nextSibling().toElement();
194 }
195 var.createSize(w, h);
196 qVariantSetValue(v, var);
197 } else if (e.tagName() == QLatin1String("color")) {
198 var.color = readColor(e);
199 qVariantSetValue(v, var);
200 } else if (e.tagName() == QLatin1String("font")) {
201 QDomElement n3 = e.firstChild().toElement();
202 Font f;
203 f.init();
204 while (!n3.isNull()) {
205 if (n3.tagName() == QLatin1String("family"))
206 f.family = qstrdup(n3.firstChild().toText().data().toLatin1());
207 else if (n3.tagName() == QLatin1String("pointsize"))
208 f.pointsize = n3.firstChild().toText().data().toInt();
209 else if (n3.tagName() == QLatin1String("bold"))
210 f.bold = n3.firstChild().toText().data().toInt();
211 else if (n3.tagName() == QLatin1String("italic"))
212 f.italic = n3.firstChild().toText().data().toInt();
213 else if (n3.tagName() == QLatin1String("underline"))
214 f.underline = n3.firstChild().toText().data().toInt();
215 else if (n3.tagName() == QLatin1String("strikeout"))
216 f.strikeout = n3.firstChild().toText().data().toInt();
217 n3 = n3.nextSibling().toElement();
218 }
219 var.font = f;
220 qVariantSetValue(v, var);
221 } else if (e.tagName() == QLatin1String("string")) {
222 v = QVariant(e.firstChild().toText().data());
223 QDomElement n = e;
224 n = n.nextSibling().toElement();
225 if (n.tagName() == QLatin1String("comment"))
226 comment = n.firstChild().toText().data();
227 } else if (e.tagName() == QLatin1String("cstring")) {
228 v = QVariant(e.firstChild().toText().data().toAscii());
229 } else if (e.tagName() == QLatin1String("number")) {
230 bool ok = true;
231 v = QVariant(e.firstChild().toText().data().toInt(&ok));
232 if (!ok)
233 v = QVariant(e.firstChild().toText().data().toDouble());
234 } else if (e.tagName() == QLatin1String("bool")) {
235 QString t = e.firstChild().toText().data();
236 v = QVariant(t == QLatin1String("true") || t == QLatin1String("1"));
237 } else if (e.tagName() == QLatin1String("pixmap")) {
238 v = QVariant(e.firstChild().toText().data());
239 } else if (e.tagName() == QLatin1String("iconset")) {
240 v = QVariant(e.firstChild().toText().data());
241 } else if (e.tagName() == QLatin1String("image")) {
242 v = QVariant(e.firstChild().toText().data());
243 } else if (e.tagName() == QLatin1String("enum")) {
244 v = QVariant(e.firstChild().toText().data());
245 } else if (e.tagName() == QLatin1String("set")) {
246 v = QVariant(e.firstChild().toText().data());
247 } else if (e.tagName() == QLatin1String("sizepolicy")) {
248 QDomElement n3 = e.firstChild().toElement();
249 var.createSizePolicy();
250 while (!n3.isNull()) {
251 if (n3.tagName() == QLatin1String("hsizetype"))
252 var.sizePolicy.hsizetype = n3.firstChild().toText().data().toInt();
253 else if (n3.tagName() == QLatin1String("vsizetype"))
254 var.sizePolicy.vsizetype = n3.firstChild().toText().data().toInt();
255 else if (n3.tagName() == QLatin1String("horstretch"))
256 var.sizePolicy.horstretch = n3.firstChild().toText().data().toInt();
257 else if (n3.tagName() == QLatin1String("verstretch"))
258 var.sizePolicy.verstretch = n3.firstChild().toText().data().toInt();
259 n3 = n3.nextSibling().toElement();
260 }
261 qVariantSetValue(v, var);
262 } else if (e.tagName() == QLatin1String("cursor")) {
263 var.createCursor(e.firstChild().toText().data().toInt());
264 qVariantSetValue(v, var);
265 } else if (e.tagName() == QLatin1String("stringlist")) {
266 QStringList lst;
267 QDomElement n;
268 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement())
269 lst << n.firstChild().toText().data();
270 v = QVariant(lst);
271 } else if (e.tagName() == QLatin1String("date")) {
272 QDomElement n3 = e.firstChild().toElement();
273 int y, m, d;
274 y = m = d = 0;
275 while (!n3.isNull()) {
276 if (n3.tagName() == QLatin1String("year"))
277 y = n3.firstChild().toText().data().toInt();
278 else if (n3.tagName() == QLatin1String("month"))
279 m = n3.firstChild().toText().data().toInt();
280 else if (n3.tagName() == QLatin1String("day"))
281 d = n3.firstChild().toText().data().toInt();
282 n3 = n3.nextSibling().toElement();
283 }
284 v = QVariant(QDate(y, m, d));
285 } else if (e.tagName() == QLatin1String("time")) {
286 QDomElement n3 = e.firstChild().toElement();
287 int h, m, s;
288 h = m = s = 0;
289 while (!n3.isNull()) {
290 if (n3.tagName() == QLatin1String("hour"))
291 h = n3.firstChild().toText().data().toInt();
292 else if (n3.tagName() == QLatin1String("minute"))
293 m = n3.firstChild().toText().data().toInt();
294 else if (n3.tagName() == QLatin1String("second"))
295 s = n3.firstChild().toText().data().toInt();
296 n3 = n3.nextSibling().toElement();
297 }
298 v = QVariant(QTime(h, m, s));
299 } else if (e.tagName() == QLatin1String("datetime")) {
300 QDomElement n3 = e.firstChild().toElement();
301 int h, mi, s, y, mo, d ;
302 h = mi = s = y = mo = d = 0;
303 while (!n3.isNull()) {
304 if (n3.tagName() == QLatin1String("hour"))
305 h = n3.firstChild().toText().data().toInt();
306 else if (n3.tagName() == QLatin1String("minute"))
307 mi = n3.firstChild().toText().data().toInt();
308 else if (n3.tagName() == QLatin1String("second"))
309 s = n3.firstChild().toText().data().toInt();
310 else if (n3.tagName() == QLatin1String("year"))
311 y = n3.firstChild().toText().data().toInt();
312 else if (n3.tagName() == QLatin1String("month"))
313 mo = n3.firstChild().toText().data().toInt();
314 else if (n3.tagName() == QLatin1String("day"))
315 d = n3.firstChild().toText().data().toInt();
316 n3 = n3.nextSibling().toElement();
317 }
318 v = QVariant(QDateTime(QDate(y, mo, d), QTime(h, mi, s)));
319 }
320
321 return v;
322}
323
324
325/* Returns the color which is returned in the dom element \a e.
326 */
327
328Color DomTool::readColor(const QDomElement &e)
329{
330 QDomElement n = e.firstChild().toElement();
331 int r= 0, g = 0, b = 0;
332 while (!n.isNull()) {
333 if (n.tagName() == QLatin1String("red"))
334 r = n.firstChild().toText().data().toInt();
335 else if (n.tagName() == QLatin1String("green"))
336 g = n.firstChild().toText().data().toInt();
337 else if (n.tagName() == QLatin1String("blue"))
338 b = n.firstChild().toText().data().toInt();
339 n = n.nextSibling().toElement();
340 }
341
342 Color c;
343 c.init(r, g, b);
344 return c;
345}
346
347/*
348 Returns the contents of attribute \a name of object \a e as
349 a variant or the variant passed as \a defValue if the attribute does
350 not exist. The \a comment is passed to the elementToVariant()
351 function.
352
353 \sa hasAttribute()
354 */
355QVariant DomTool::readAttribute(const QDomElement& e, const QString& name, const QVariant& defValue, QString& comment)
356{
357 QDomElement n;
358 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
359 if (n.tagName() == QLatin1String("attribute")) {
360 if (n.attribute(QLatin1String("name")) != name)
361 continue;
362 return elementToVariant(n.firstChild().toElement(), defValue, comment);
363 }
364 }
365 return defValue;
366}
367
368/*
369 \overload
370*/
371QVariant DomTool::readAttribute(const QDomElement& e, const QString& name, const QVariant& defValue)
372{
373 QString comment;
374 return readAttribute(e, name, defValue, comment);
375}
376
377/*
378 Returns whether object \a e defines attribute \a name or not.
379
380 \sa readAttribute()
381 */
382bool DomTool::hasAttribute(const QDomElement& e, const QString& name)
383{
384 QDomElement n;
385 for (n = e.firstChild().toElement(); !n.isNull(); n = n.nextSibling().toElement()) {
386 if (n.tagName() == QLatin1String("attribute")) {
387 if (n.attribute(QLatin1String("name")) != name)
388 continue;
389 return true;
390 }
391 }
392 return false;
393}
394
395static bool toBool(const QString& s)
396{
397 return s == QLatin1String("true") || s.toInt() != 0;
398}
399
400static double versionToDouble(QString version)
401{
402 version = version.trimmed();
403
404 if (version.isEmpty())
405 return 0.0;
406
407 bool decpt = false;
408 QString num_str;
409 for (int i = 0; i < version.size(); ++i) {
410 char c = version.at(i).toAscii();
411 if ((c < '0' || c > '9') && c != '.')
412 break;
413 if (c == '.') {
414 if (decpt)
415 break;
416 decpt = true;
417 }
418 num_str.append(QLatin1Char(c));
419 }
420
421 return num_str.toDouble();
422}
423
424/*
425 \internal
426
427 Convert Qt 2.x format to Qt 3.x format if necessary.
428*/
429void DomTool::fixDocument(QDomDocument& doc)
430{
431 QDomElement e;
432 QDomNode n;
433 QDomNodeList nl;
434 int i = 0;
435
436 e = doc.firstChild().toElement();
437 if (e.tagName() != QLatin1String("UI"))
438 return;
439
440 // rename classes and properties
441 double version = versionToDouble(e.attribute(QLatin1String("version")));
442
443 nl = e.childNodes();
444 fixAttributes(nl, version);
445
446 // 3.x don't do anything more
447 if (version >= 3.0)
448 return;
449
450 // in versions smaller than 3.0 we need to change more
451
452 e.setAttribute(QLatin1String("version"), 3.0);
453 e.setAttribute(QLatin1String("stdsetdef"), 1);
454 nl = e.elementsByTagName(QLatin1String("property"));
455 for (i = 0; i < (int) nl.length(); i++) {
456 e = nl.item(i).toElement();
457 QString name;
458 QDomElement n2 = e.firstChild().toElement();
459 if (n2.tagName() == QLatin1String("name")) {
460 name = n2.firstChild().toText().data();
461 if (name == QLatin1String("resizeable"))
462 e.setAttribute(QLatin1String("name"), QLatin1String("resizable"));
463 else
464 e.setAttribute(QLatin1String("name"), name);
465 e.removeChild(n2);
466 }
467 bool stdset = toBool(e.attribute(QLatin1String("stdset")));
468 if (stdset || name == QLatin1String("toolTip") || name == QLatin1String("whatsThis") ||
469 name == QLatin1String("buddy") ||
470 e.parentNode().toElement().tagName() == QLatin1String("item") ||
471 e.parentNode().toElement().tagName() == QLatin1String("spacer") ||
472 e.parentNode().toElement().tagName() == QLatin1String("column")
473 )
474 e.removeAttribute(QLatin1String("stdset"));
475 else
476 e.setAttribute(QLatin1String("stdset"), 0);
477 }
478
479 nl = doc.elementsByTagName(QLatin1String("attribute"));
480 for (i = 0; i < (int) nl.length(); i++) {
481 e = nl.item(i).toElement();
482 QString name;
483 QDomElement n2 = e.firstChild().toElement();
484 if (n2.tagName() == QLatin1String("name")) {
485 name = n2.firstChild().toText().data();
486 e.setAttribute(QLatin1String("name"), name);
487 e.removeChild(n2);
488 }
489 }
490
491 nl = doc.elementsByTagName(QLatin1String("image"));
492 for (i = 0; i < (int) nl.length(); i++) {
493 e = nl.item(i).toElement();
494 QString name;
495 QDomElement n2 = e.firstChild().toElement();
496 if (n2.tagName() == QLatin1String("name")) {
497 name = n2.firstChild().toText().data();
498 e.setAttribute(QLatin1String("name"), name);
499 e.removeChild(n2);
500 }
501 }
502
503 nl = doc.elementsByTagName(QLatin1String("widget"));
504 for (i = 0; i < (int) nl.length(); i++) {
505 e = nl.item(i).toElement();
506 QString name;
507 QDomElement n2 = e.firstChild().toElement();
508 if (n2.tagName() == QLatin1String("class")) {
509 name = n2.firstChild().toText().data();
510 e.setAttribute(QLatin1String("class"), name);
511 e.removeChild(n2);
512 }
513 }
514
515}
516
517struct widgetName {
518 widgetName(double v, QString b, QString a)
519 : version(v), before(b), after(a) {}
520 double version;
521 QString before;
522 QString after;
523};
524
525struct propertyName : public widgetName {
526 propertyName(double v, QString b, QString a, QString c = QString())
527 : widgetName(v, b, a), clss(c) {}
528 QString clss;
529};
530
531const int widgs = 1;
532widgetName widgetTable[1] = {
533 widgetName(3.3, QLatin1String("before"), QLatin1String("after")),
534};
535
536const int props = 1;
537propertyName propertyTable[1] = {
538 propertyName(3.0, QLatin1String("resizeable"), QLatin1String("resizable")), // we need to fix a spelling error in 3.0
539};
540
541/*
542 \internal
543*/
544void DomTool::fixAttributes(QDomNodeList &nodes, double version)
545{
546 QDomNode n;
547 QDomNodeList nl;
548 for (int i = 0; i < (int) nodes.count(); ++i) {
549 n = nodes.item(i);
550 fixAttribute(n, version);
551 nl = n.childNodes();
552 fixAttributes(nl, version);
553 }
554}
555
556/*
557 \internal
558*/
559void DomTool::fixAttribute(QDomNode &node, double version)
560{
561 QString tagName = node.toElement().tagName();
562 if (tagName == QLatin1String("widget")) {
563 QString clss = node.toElement().attribute(QLatin1String("class"));
564 for (int i = 0; i < widgs; ++i)
565 if ((version < widgetTable[i].version)
566 && (clss == widgetTable[i].before)) {
567 node.toElement().setAttribute(QLatin1String("class"), propertyTable[i].after);
568 return;
569 }
570 return;
571 }
572 if (tagName == QLatin1String("property")) {
573 QDomElement e = node.parentNode().toElement();
574 QString clss = e.attribute(QLatin1String("class"));
575 QString name = node.toElement().attribute(QLatin1String("name"), QLatin1String(""));
576 for (int i = 0; i < props; ++i)
577 if ((version < propertyTable[i].version)
578 && (clss == propertyTable[i].clss)
579 && (propertyTable[i].before.isNull()
580 || name == propertyTable[i].before)) {
581 node.toElement().setAttribute(QLatin1String("name"), propertyTable[i].after);
582 return;
583 }
584 }
585}
586
587QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.