/src/tools/uic3/ui3reader.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 631 lines · 461 code · 80 blank · 90 comment · 116 complexity · 2c952695ee9f0557386da9531ee2f9b5 MD5 · raw file

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